| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- package evaluator
- import (
- "github/runnignwater/monkey/ast"
- "github/runnignwater/monkey/object"
- )
- var (
- NULL = &object.Null{}
- TRUE = &object.Boolean{Value: true}
- FALSE = &object.Boolean{Value: false}
- )
- func Eval(node ast.Node) object.Object {
- switch node := node.(type) {
- // Statements
- case *ast.Program:
- return evalProgram(node)
- case *ast.ExpressionStatement:
- return Eval(node.Expression)
- // Expression
- case *ast.IntegerLiteral:
- return &object.Integer{Value: node.Value}
- case *ast.Boolean:
- return nativeBooleanObject(node.Value)
- case *ast.PrefixExpression:
- right := Eval(node.Right)
- return evalPrefixExpression(node.Operator, right)
- case *ast.InfixExpression:
- left := Eval(node.Left)
- right := Eval(node.Right)
- return evalInfixExpression(node.Operator, left, right)
- case *ast.BlockStatement:
- return evalBlockStatements(node)
- case *ast.IfExpression:
- return evalIfExpression(node)
- case *ast.ReturnStatement:
- val := Eval(node.ReturnValue)
- return &object.ReturnValue{Value: val}
- }
- return nil
- }
- func evalProgram(node *ast.Program) object.Object {
- var result object.Object
- for _, stmt := range node.Statements {
- result = Eval(stmt)
- // skip return 后面的语句
- if rVal, ok := result.(*object.ReturnValue); ok {
- return rVal.Value
- }
- }
- return result
- }
- func nativeBooleanObject(input bool) *object.Boolean {
- if input {
- return TRUE
- } else {
- return FALSE
- }
- }
- func evalPrefixExpression(operator string, right object.Object) object.Object {
- switch operator {
- case "!":
- return evalBangOperatorExpression(right)
- case "-":
- return evalMinusPreOperatorExpression(right)
- default:
- return NULL
- }
- }
- func evalInfixExpression(operator string, left object.Object, right object.Object) object.Object {
- switch {
- case left.Type() == object.IntegerObj && right.Type() == object.IntegerObj:
- return evalIntegerInfixExpression(operator, left, right)
- case operator == "==":
- return nativeBooleanObject(left == right)
- case operator == "!=":
- return nativeBooleanObject(left != right)
- default:
- return NULL
- }
- }
- func evalIfExpression(node *ast.IfExpression) object.Object {
- condition := Eval(node.Condition)
- if isTruthy(condition) {
- return Eval(node.Consequence)
- } else if node.Alternative != nil {
- return Eval(node.Alternative)
- } else {
- return NULL
- }
- }
- func evalBlockStatements(node *ast.BlockStatement) object.Object {
- var result object.Object
- for _, stmt := range node.Statements {
- result = Eval(stmt)
- if result != nil && result.Type() == object.ReturnValueObj {
- return result
- }
- }
- return result
- }
- func evalIntegerInfixExpression(operator string,
- left object.Object, right object.Object) object.Object {
- leftVal := left.(*object.Integer).Value
- rightVal := right.(*object.Integer).Value
- switch operator {
- case "+":
- return &object.Integer{Value: leftVal + rightVal}
- case "-":
- return &object.Integer{Value: leftVal - rightVal}
- case "*":
- return &object.Integer{Value: leftVal * rightVal}
- case "/":
- return &object.Integer{Value: leftVal / rightVal}
- case "<":
- return nativeBooleanObject(leftVal < rightVal)
- case ">":
- return nativeBooleanObject(leftVal > rightVal)
- case "==":
- return nativeBooleanObject(leftVal == rightVal)
- case "!=":
- return nativeBooleanObject(leftVal != rightVal)
- default:
- return NULL
- }
- }
- func evalMinusPreOperatorExpression(right object.Object) object.Object {
- if right.Type() != object.IntegerObj {
- return NULL
- }
- value := right.(*object.Integer).Value
- return &object.Integer{Value: -value}
- }
- func evalBangOperatorExpression(right object.Object) object.Object {
- switch right {
- case TRUE:
- return FALSE
- case FALSE:
- return TRUE
- default:
- return FALSE
- }
- }
- func isTruthy(obj object.Object) bool {
- switch obj {
- case NULL:
- return false
- case TRUE:
- return true
- case FALSE:
- return false
- default:
- return true
- }
- }
|