diff options
Diffstat (limited to 'evaluator/evaluator.go')
| -rw-r--r-- | evaluator/evaluator.go | 134 |
1 files changed, 83 insertions, 51 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 9cead89..f765d02 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -1,9 +1,9 @@ package evaluator import ( + "fmt" "mana/ast" "mana/object" - "fmt" ) var ( @@ -25,15 +25,15 @@ func Eval(node ast.Node, env *object.Environment) object.Object { case *ast.BlockStatement: return evalBlockStatement(node, env) - case *ast.LetStatement: - val := Eval(node.Value, env) - if isError(val) { - return val - } - env.Set(node.Name.Value, val) + case *ast.LetStatement: + val := Eval(node.Value, env) + if isError(val) { + return val + } + env.Set(node.Name.Value, val) - case *ast.Identifier: - return evalIdentifier(node, env) + case *ast.Identifier: + return evalIdentifier(node, env) // Expressions case *ast.IntegerLiteral: @@ -44,30 +44,48 @@ func Eval(node ast.Node, env *object.Environment) object.Object { case *ast.PrefixExpression: right := Eval(node.Right, env) - if isError(right) { - return right - } + if isError(right) { + return right + } return evalPrefixExpression(node.Operator, right) case *ast.InfixExpression: left := Eval(node.Left, env) - if isError(left) { - return left - } + if isError(left) { + return left + } right := Eval(node.Right, env) - if isError(right) { - return right - } + if isError(right) { + return right + } return evalInfixExpression(node.Operator, left, right) case *ast.IfExpression: return evalIfExpression(node, env) + case *ast.CallExpression: + function := Eval(node.Function, env) + + if isError(function) { + return function + } + + args := evalExpressions(node.Arguments, env) + if len(args) == 1 && isError(args[0]) { + return args[0] + } + + case *ast.FunctionLiteral: + params := node.Parameters + body := node.Body + + return &object.Function{Parameters: params, Body: body, Env: env} + case *ast.ReturnStatement: val := Eval(node.ReturnValue, env) - if isError(val) { - return val - } + if isError(val) { + return val + } return &object.ReturnValue{Value: val} } @@ -80,30 +98,44 @@ func evalProgram(program *ast.Program, env *object.Environment) object.Object { for _, statement := range program.Statements { result = Eval(statement, env) - switch result := result.(type) { - case *object.ReturnValue: - return result.Value - case *object.Error: - return result - } + switch result := result.(type) { + case *object.ReturnValue: + return result.Value + case *object.Error: + return result + } } return result } - func evalBlockStatement(block *ast.BlockStatement, env *object.Environment) object.Object { var result object.Object for _, statement := range block.Statements { result = Eval(statement, env) - if result != nil { - rt := result.Type() - if rt == object.RETURN_VALUE_OBJ || rt == object.ERROR_OBJ { - return result - } - } + if result != nil { + rt := result.Type() + if rt == object.RETURN_VALUE_OBJ || rt == object.ERROR_OBJ { + return result + } + } + } + + return result +} + +func evalExpressions(exps []ast.Expression, env *object.Environment) []object.Object { + var result []object.Object + + for _, e := range exps { + evaluated := Eval(e, env) + if isError(evaluated) { + return []object.Object{evaluated} + } + + result = append(result, evaluated) } return result @@ -123,7 +155,7 @@ func evalPrefixExpression(operator string, right object.Object) object.Object { case "-": return evalMinusPrefixOperatorExpression(right) default: - return newError("unknown operator: %s%s", operator, right.Type()) + return newError("unknown operator: %s%s", operator, right.Type()) } } @@ -135,10 +167,10 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje return nativeBoolToBooleanObject(left == right) case operator == "!=": return nativeBoolToBooleanObject(left != right) - case left.Type() != right.Type(): - return newError("type mismatch: %s %s %s", left.Type(), operator, right.Type()) + case left.Type() != right.Type(): + return newError("type mismatch: %s %s %s", left.Type(), operator, right.Type()) default: - return newError("unknown operator: %s %s %s", left.Type(), operator, right.Type()) + return newError("unknown operator: %s %s %s", left.Type(), operator, right.Type()) } } @@ -195,9 +227,9 @@ func evalIntegerInfixExpression(operator string, left, right object.Object) obje func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Object { condition := Eval(ie.Condition, env) - if isError(condition) { - return condition - } + if isError(condition) { + return condition + } if isTruthy(condition) { return Eval(ie.Consequence, env) } else if ie.Alternative != nil { @@ -208,11 +240,11 @@ func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Obje } func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object { - val, ok := env.Get(node.Value) - if !ok { - return newError("identifier not found: " + node.Value) - } - return val + val, ok := env.Get(node.Value) + if !ok { + return newError("identifier not found: " + node.Value) + } + return val } func isTruthy(obj object.Object) bool { @@ -229,12 +261,12 @@ func isTruthy(obj object.Object) bool { } func newError(format string, a ...interface{}) *object.Error { - return &object.Error{Message: fmt.Sprintf(format, a...)} + return &object.Error{Message: fmt.Sprintf(format, a...)} } func isError(obj object.Object) bool { - if obj != nil { - return obj.Type() == object.ERROR_OBJ - } - return false + if obj != nil { + return obj.Type() == object.ERROR_OBJ + } + return false } |
