From 1b9719636102d1e3beb0ec2bb438d7b4877103d3 Mon Sep 17 00:00:00 2001 From: tijani Date: Sun, 7 Aug 2022 14:44:11 +0000 Subject: [PATCH] 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 --- evaluator/evaluator.go | 32 ++++++++++++++++++++++ evaluator/evaluator_test.go | 45 +++++++++++++++++++++++++++++++ object/object.go | 53 +++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 evaluator/evaluator.go create mode 100644 evaluator/evaluator_test.go create mode 100644 object/object.go diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go new file mode 100644 index 0000000..dc480b9 --- /dev/null +++ b/evaluator/evaluator.go @@ -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 +} diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go new file mode 100644 index 0000000..aceb434 --- /dev/null +++ b/evaluator/evaluator_test.go @@ -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 +} diff --git a/object/object.go b/object/object.go new file mode 100644 index 0000000..e81b429 --- /dev/null +++ b/object/object.go @@ -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" +}