evaluator.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. default:
  62. return NULL
  63. }
  64. }
  65. func evalIntegerInfixExpression(operator string,
  66. left object.Object, right object.Object) object.Object {
  67. leftVal := left.(*object.Integer).Value
  68. rightVal := right.(*object.Integer).Value
  69. switch operator {
  70. case "+":
  71. return &object.Integer{Value: leftVal + rightVal}
  72. case "-":
  73. return &object.Integer{Value: leftVal - rightVal}
  74. case "*":
  75. return &object.Integer{Value: leftVal * rightVal}
  76. case "/":
  77. return &object.Integer{Value: leftVal / rightVal}
  78. case "<":
  79. return nativeBooleanObject(leftVal < rightVal)
  80. case ">":
  81. return nativeBooleanObject(leftVal > rightVal)
  82. case "==":
  83. return nativeBooleanObject(leftVal == rightVal)
  84. case "!=":
  85. return nativeBooleanObject(leftVal != rightVal)
  86. default:
  87. return NULL
  88. }
  89. }
  90. func evalMinusPreOperatorExpression(right object.Object) object.Object {
  91. if right.Type() != object.IntegerObj {
  92. return NULL
  93. }
  94. value := right.(*object.Integer).Value
  95. return &object.Integer{Value: -value}
  96. }
  97. func evalBangOperatorExpression(right object.Object) object.Object {
  98. switch right {
  99. case TRUE:
  100. return FALSE
  101. case FALSE:
  102. return TRUE
  103. default:
  104. return FALSE
  105. }
  106. }