evaluator.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package evaluator
  2. import (
  3. "github/runnignwater/monkey/ast"
  4. "github/runnignwater/monkey/object"
  5. )
  6. var (
  7. NULL = &object.Null{}
  8. TRUE = &object.Boolean{Value: true}
  9. FALSE = &object.Boolean{Value: false}
  10. )
  11. func Eval(node ast.Node) object.Object {
  12. switch node := node.(type) {
  13. // Statements
  14. case *ast.Program:
  15. return evalStatements(node.Statements)
  16. case *ast.ExpressionStatement:
  17. return Eval(node.Expression)
  18. // Expression
  19. case *ast.IntegerLiteral:
  20. return &object.Integer{Value: node.Value}
  21. case *ast.Boolean:
  22. return nativeBooleanObject(node.Value)
  23. case *ast.PrefixExpression:
  24. right := Eval(node.Right)
  25. return evalPrefixExpression(node.Operator, right)
  26. case *ast.InfixExpression:
  27. left := Eval(node.Left)
  28. right := Eval(node.Right)
  29. return evalInfixExpression(node.Operator, left, right)
  30. }
  31. return nil
  32. }
  33. func evalStatements(stmts []ast.Statement) object.Object {
  34. var result object.Object
  35. for _, statement := range stmts {
  36. result = Eval(statement)
  37. }
  38. return result
  39. }
  40. func nativeBooleanObject(input bool) *object.Boolean {
  41. if input {
  42. return TRUE
  43. } else {
  44. return FALSE
  45. }
  46. }
  47. func evalPrefixExpression(operator string, right object.Object) object.Object {
  48. switch operator {
  49. case "!":
  50. return evalBangOperatorExpression(right)
  51. case "-":
  52. return evalMinusPreOperatorExpression(right)
  53. default:
  54. return NULL
  55. }
  56. }
  57. func evalInfixExpression(operator string, left object.Object, right object.Object) object.Object {
  58. switch {
  59. case left.Type() == object.IntegerObj && right.Type() == object.IntegerObj:
  60. return evalIntegerInfixExpression(operator, left, right)
  61. case operator == "==":
  62. return nativeBooleanObject(left == right)
  63. case operator == "!=":
  64. return nativeBooleanObject(left != right)
  65. default:
  66. return NULL
  67. }
  68. }
  69. func evalIntegerInfixExpression(operator string,
  70. left object.Object, right object.Object) object.Object {
  71. leftVal := left.(*object.Integer).Value
  72. rightVal := right.(*object.Integer).Value
  73. switch operator {
  74. case "+":
  75. return &object.Integer{Value: leftVal + rightVal}
  76. case "-":
  77. return &object.Integer{Value: leftVal - rightVal}
  78. case "*":
  79. return &object.Integer{Value: leftVal * rightVal}
  80. case "/":
  81. return &object.Integer{Value: leftVal / rightVal}
  82. case "<":
  83. return nativeBooleanObject(leftVal < rightVal)
  84. case ">":
  85. return nativeBooleanObject(leftVal > rightVal)
  86. case "==":
  87. return nativeBooleanObject(leftVal == rightVal)
  88. case "!=":
  89. return nativeBooleanObject(leftVal != rightVal)
  90. default:
  91. return NULL
  92. }
  93. }
  94. func evalMinusPreOperatorExpression(right object.Object) object.Object {
  95. if right.Type() != object.IntegerObj {
  96. return NULL
  97. }
  98. value := right.(*object.Integer).Value
  99. return &object.Integer{Value: -value}
  100. }
  101. func evalBangOperatorExpression(right object.Object) object.Object {
  102. switch right {
  103. case TRUE:
  104. return FALSE
  105. case FALSE:
  106. return TRUE
  107. default:
  108. return FALSE
  109. }
  110. }