evaluator.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. case *ast.BlockStatement:
  31. return evalStatements(node.Statements)
  32. case *ast.IfExpression:
  33. return evalIfExpression(node)
  34. }
  35. return nil
  36. }
  37. func evalStatements(stmts []ast.Statement) object.Object {
  38. var result object.Object
  39. for _, statement := range stmts {
  40. result = Eval(statement)
  41. }
  42. return result
  43. }
  44. func nativeBooleanObject(input bool) *object.Boolean {
  45. if input {
  46. return TRUE
  47. } else {
  48. return FALSE
  49. }
  50. }
  51. func evalPrefixExpression(operator string, right object.Object) object.Object {
  52. switch operator {
  53. case "!":
  54. return evalBangOperatorExpression(right)
  55. case "-":
  56. return evalMinusPreOperatorExpression(right)
  57. default:
  58. return NULL
  59. }
  60. }
  61. func evalInfixExpression(operator string, left object.Object, right object.Object) object.Object {
  62. switch {
  63. case left.Type() == object.IntegerObj && right.Type() == object.IntegerObj:
  64. return evalIntegerInfixExpression(operator, left, right)
  65. case operator == "==":
  66. return nativeBooleanObject(left == right)
  67. case operator == "!=":
  68. return nativeBooleanObject(left != right)
  69. default:
  70. return NULL
  71. }
  72. }
  73. func evalIfExpression(node *ast.IfExpression) object.Object {
  74. condition := Eval(node.Condition)
  75. if isTruthy(condition) {
  76. return Eval(node.Consequence)
  77. } else if node.Alternative != nil {
  78. return Eval(node.Alternative)
  79. } else {
  80. return NULL
  81. }
  82. }
  83. func evalIntegerInfixExpression(operator string,
  84. left object.Object, right object.Object) object.Object {
  85. leftVal := left.(*object.Integer).Value
  86. rightVal := right.(*object.Integer).Value
  87. switch operator {
  88. case "+":
  89. return &object.Integer{Value: leftVal + rightVal}
  90. case "-":
  91. return &object.Integer{Value: leftVal - rightVal}
  92. case "*":
  93. return &object.Integer{Value: leftVal * rightVal}
  94. case "/":
  95. return &object.Integer{Value: leftVal / rightVal}
  96. case "<":
  97. return nativeBooleanObject(leftVal < rightVal)
  98. case ">":
  99. return nativeBooleanObject(leftVal > rightVal)
  100. case "==":
  101. return nativeBooleanObject(leftVal == rightVal)
  102. case "!=":
  103. return nativeBooleanObject(leftVal != rightVal)
  104. default:
  105. return NULL
  106. }
  107. }
  108. func evalMinusPreOperatorExpression(right object.Object) object.Object {
  109. if right.Type() != object.IntegerObj {
  110. return NULL
  111. }
  112. value := right.(*object.Integer).Value
  113. return &object.Integer{Value: -value}
  114. }
  115. func evalBangOperatorExpression(right object.Object) object.Object {
  116. switch right {
  117. case TRUE:
  118. return FALSE
  119. case FALSE:
  120. return TRUE
  121. default:
  122. return FALSE
  123. }
  124. }
  125. func isTruthy(obj object.Object) bool {
  126. switch obj {
  127. case NULL:
  128. return false
  129. case TRUE:
  130. return true
  131. case FALSE:
  132. return false
  133. default:
  134. return true
  135. }
  136. }