Added stub for constant expression evaluator
This commit is contained in:
parent
034d9661b3
commit
373db2ae81
|
@ -0,0 +1,2 @@
|
|||
// Package eval provides a way to evaluate FSPL expressions.
|
||||
package eval
|
|
@ -0,0 +1,106 @@
|
|||
package eval
|
||||
|
||||
import "git.tebibyte.media/fspl/fspl/errors"
|
||||
import "git.tebibyte.media/fspl/fspl/entity"
|
||||
|
||||
type evaluator struct { }
|
||||
|
||||
func (this *evaluator) assertConstant (expression entity.Expression) error {
|
||||
if expression.IsConstant() {
|
||||
return nil
|
||||
} else {
|
||||
return errors.Errorf(expression.Position(), "%v is not constant", expression)
|
||||
}
|
||||
}
|
||||
|
||||
// EvaluateConstant evaluates a constant expression. On success, it always
|
||||
// returns a literal made of other literals. It is very important that the input
|
||||
// expression has come from the semantic analyzer.
|
||||
func EvaluateConstant (expression entity.Expression) (entity.Expression, error) {
|
||||
// evaluate
|
||||
this := new(evaluator)
|
||||
expression, err := this.evaluateConstant(expression)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
// sanity check
|
||||
if !expression.IsConstant() {
|
||||
panic("BUG: evaluation result is not constant")
|
||||
}
|
||||
|
||||
return expression, nil
|
||||
}
|
||||
|
||||
func (this *evaluator) evaluateConstant (expression entity.Expression) (entity.Expression, error) {
|
||||
// TODO expand this to include all constant expressions
|
||||
|
||||
switch expression := expression.(type) {
|
||||
case *entity.LiteralInt:
|
||||
return expression, nil
|
||||
case *entity.LiteralFloat:
|
||||
return expression, nil
|
||||
case *entity.LiteralString:
|
||||
return expression, nil
|
||||
case *entity.LiteralArray:
|
||||
return this.evaluateConstantLiteralArray(expression)
|
||||
case *entity.LiteralStruct:
|
||||
return this.evaluateConstantLiteralStruct(expression)
|
||||
case *entity.LiteralBoolean:
|
||||
return expression, nil
|
||||
case *entity.LiteralNil:
|
||||
return expression, nil
|
||||
|
||||
case *entity.Constant:
|
||||
return expression.Declaration.Value, nil
|
||||
|
||||
default:
|
||||
err := this.assertConstant(expression)
|
||||
if err != nil { return nil, err }
|
||||
return nil, errors.Errorf (
|
||||
expression.Position(),
|
||||
"%v expressions are currently unsupported by the " +
|
||||
"constant expression evaluator")
|
||||
}
|
||||
}
|
||||
|
||||
func (this *evaluator) evaluateConstantLiteralArray (array *entity.LiteralArray) (entity.Expression, error) {
|
||||
result := &entity.LiteralArray {
|
||||
Pos: array.Position(),
|
||||
Elements: make([]entity.Expression, len(array.Elements)),
|
||||
Ty: array.Type(),
|
||||
}
|
||||
|
||||
for index, element := range array.Elements {
|
||||
elementResult, err := this.evaluateConstant(element)
|
||||
if err != nil { return nil, err }
|
||||
result.Elements[index] = elementResult
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (this *evaluator) evaluateConstantLiteralStruct (struc *entity.LiteralStruct) (entity.Expression, error) {
|
||||
result := &entity.LiteralStruct {
|
||||
Pos: struc.Position(),
|
||||
Members: make([]*entity.Member, len(struc.Members)),
|
||||
MemberOrder: make([]string, len(struc.MemberOrder)),
|
||||
MemberMap: make(map[string] *entity.Member),
|
||||
Ty: struc.Type(),
|
||||
}
|
||||
|
||||
for index, member := range struc.Members {
|
||||
memberResult := &entity.Member {
|
||||
Pos: member.Position(),
|
||||
Name: member.Name,
|
||||
}
|
||||
|
||||
memberValueResult, err := this.evaluateConstant(member.Value)
|
||||
if err != nil { return nil, err }
|
||||
memberResult.Value = memberValueResult
|
||||
|
||||
result.Members[index] = memberResult
|
||||
result.MemberOrder[index] = memberResult.Name
|
||||
result.MemberMap[memberResult.Name] = memberResult
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
Loading…
Reference in New Issue