Evaluation - Integer evaluation now works, got basically a REPL going on.
git-svn-id: https://svn.tlawal.org/svn/monkey@44 f6afcba9-9ef1-4bdd-9b72-7484f5705bac
This commit is contained in:
parent
7a319dc03b
commit
1b97196361
32
evaluator/evaluator.go
Normal file
32
evaluator/evaluator.go
Normal file
@ -0,0 +1,32 @@
|
||||
package evaluator
|
||||
|
||||
import (
|
||||
"monkey/ast"
|
||||
"monkey/object"
|
||||
)
|
||||
|
||||
func Eval(node ast.Node) object.Object {
|
||||
switch node := node.(type) {
|
||||
// Statements
|
||||
case *ast.Program:
|
||||
return eval_statements(node.Statements)
|
||||
|
||||
case *ast.ExpressionStatement:
|
||||
return Eval(node.Expression)
|
||||
|
||||
// Expressions
|
||||
case *ast.IntegerLiteral:
|
||||
return &object.Integer{Value: node.Value}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func eval_statements(statements []ast.Statement) object.Object {
|
||||
var result object.Object
|
||||
|
||||
for _, statement := range statements {
|
||||
result = Eval(statement)
|
||||
}
|
||||
return result
|
||||
}
|
45
evaluator/evaluator_test.go
Normal file
45
evaluator/evaluator_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package evaluator
|
||||
|
||||
import (
|
||||
"monkey/lexer"
|
||||
"monkey/object"
|
||||
"monkey/parser"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEvalIntegerExpression(l_test *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected int64
|
||||
}{
|
||||
{"5", 5},
|
||||
{"10", 10},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
evaluated := test_eval(tt.input)
|
||||
test_integer_object(l_test, evaluated, tt.expected)
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
func test_eval(input string) object.Object {
|
||||
l_lexer := lexer.New(input)
|
||||
l_parser := parser.New(l_lexer)
|
||||
program := l_parser.ParseProgram()
|
||||
|
||||
return Eval(program)
|
||||
}
|
||||
|
||||
func test_integer_object(l_test *testing.T, l_object object.Object, expected int64) bool {
|
||||
result, ok := l_object.(*object.Integer)
|
||||
if !ok {
|
||||
l_test.Errorf("object is not integer, got=%T (%+v)", l_object, l_object)
|
||||
return false
|
||||
}
|
||||
if result.Value != expected {
|
||||
l_test.Errorf("object has wrong value, got=%d, want=%d", result.Value, expected)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
53
object/object.go
Normal file
53
object/object.go
Normal file
@ -0,0 +1,53 @@
|
||||
package object
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ObjectType string
|
||||
|
||||
const (
|
||||
INTEGER_OBJECT = "INTEGER"
|
||||
BOOLEAN_OBJECT = "BOOLEAN"
|
||||
NULL_OBJECT = "NULL"
|
||||
)
|
||||
|
||||
type Object interface {
|
||||
Type() ObjectType
|
||||
Inspect() string
|
||||
}
|
||||
|
||||
// Integer
|
||||
type Integer struct {
|
||||
Value int64
|
||||
}
|
||||
|
||||
func (i *Integer) Type() ObjectType {
|
||||
return INTEGER_OBJECT
|
||||
}
|
||||
|
||||
func (i *Integer) Inspect() string {
|
||||
return fmt.Sprintf("%d", i.Value)
|
||||
}
|
||||
|
||||
// Booleans
|
||||
type Boolean struct {
|
||||
Value bool
|
||||
}
|
||||
|
||||
func (b *Boolean) Type() ObjectType {
|
||||
return BOOLEAN_OBJECT
|
||||
}
|
||||
|
||||
func (b *Boolean) Inpect() string {
|
||||
return fmt.Sprintf("%t", b.Value)
|
||||
}
|
||||
|
||||
// Null
|
||||
type Null struct{}
|
||||
|
||||
func (n *Null) Type() ObjectType {
|
||||
return NULL_OBJECT
|
||||
}
|
||||
|
||||
func (n *Null) Inpect() string {
|
||||
return "null"
|
||||
}
|
Loading…
Reference in New Issue
Block a user