File tree Expand file tree Collapse file tree 2 files changed +93
-0
lines changed
Expand file tree Collapse file tree 2 files changed +93
-0
lines changed Original file line number Diff line number Diff line change 1+ package evaluator
2+
3+ // Package evaluator implements the evaluator -- a tree-walker implementation
4+ // that recursively walks the parsed AST (Abstract Syntax Tree) and evaluates
5+ // the nodes according to their semantic meaning.
6+
7+ import (
8+ "github.com/cedrickchee/hou/ast"
9+ "github.com/cedrickchee/hou/object"
10+ )
11+
12+ // Eval evaluates the node and returns an object.
13+ func Eval (node ast.Node ) object.Object {
14+ // Traverse the AST by starting at the top of the tree, receiving an
15+ // *ast.Program, and then traverse every node in it.
16+
17+ switch node := node .(type ) {
18+
19+ // Statements
20+ case * ast.Program :
21+ // Traverse the tree and evaluate every statement of the *ast.Program.
22+ return evalStatements (node .Statements )
23+
24+ case * ast.ExpressionStatement :
25+ // If the statement is an *ast.ExpressionStatement we evaluate its
26+ // expression. An expression statement (not a return statement and not
27+ // a let statement).
28+ return Eval (node .Expression )
29+
30+ // Expressions
31+ case * ast.IntegerLiteral :
32+ return & object.Integer {Value : node .Value }
33+ }
34+
35+ return nil
36+ }
37+
38+ func evalStatements (stmts []ast.Statement ) object.Object {
39+ var result object.Object
40+
41+ for _ , statement := range stmts {
42+ result = Eval (statement )
43+ }
44+
45+ return result
46+ }
Original file line number Diff line number Diff line change 1+ package evaluator
2+
3+ import (
4+ "testing"
5+
6+ "github.com/cedrickchee/hou/lexer"
7+ "github.com/cedrickchee/hou/object"
8+ "github.com/cedrickchee/hou/parser"
9+ )
10+
11+ func TestEvalIntegerExpression (t * testing.T ) {
12+ tests := []struct {
13+ input string
14+ expected int64
15+ }{
16+ {"5" , 5 },
17+ {"10" , 10 },
18+ }
19+
20+ for _ , tt := range tests {
21+ evaluated := testEval (tt .input )
22+ testIntegerObject (t , evaluated , tt .expected )
23+ }
24+ }
25+
26+ func testEval (input string ) object.Object {
27+ l := lexer .New (input )
28+ p := parser .New (l )
29+ program := p .ParseProgram ()
30+
31+ // The heart of the test is the call to Eval.
32+ return Eval (program )
33+ }
34+
35+ func testIntegerObject (t * testing.T , obj object.Object , expected int64 ) bool {
36+ result , ok := obj .(* object.Integer )
37+ if ! ok {
38+ t .Errorf ("object is not Integer. got=%T (%+v)" , obj , obj )
39+ return false
40+ }
41+ if result .Value != expected {
42+ t .Errorf ("object has wrong value. got=%d, want=%d" , result .Value , expected )
43+ return false
44+ }
45+
46+ return true
47+ }
You can’t perform that action at this time.
0 commit comments