diff options
| author | Bobby <[email protected]> | 2024-02-17 23:50:45 -0500 |
|---|---|---|
| committer | Bobby <[email protected]> | 2024-02-17 23:50:45 -0500 |
| commit | a18137bab2c53655168be9856e28de8c29232994 (patch) | |
| tree | 9dc1ebbe8e49e97846f944a2e04e017f5dc267e6 | |
| parent | b3d5ef5c6c3dcb6d1bf707b82e5350168d66d6c5 (diff) | |
| download | mana-a18137bab2c53655168be9856e28de8c29232994.tar.xz mana-a18137bab2c53655168be9856e28de8c29232994.zip | |
Added Evaulator and Object Model
| -rw-r--r-- | evaluator/evaluator.go | 34 | ||||
| -rw-r--r-- | evaluator/evaluator_test.go | 44 | ||||
| -rw-r--r-- | object/object.go | 52 | ||||
| -rw-r--r-- | repl/repl.go | 14 |
4 files changed, 139 insertions, 5 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go new file mode 100644 index 0000000..8d1b26d --- /dev/null +++ b/evaluator/evaluator.go @@ -0,0 +1,34 @@ +package evaluator + +import ( + "mana/ast" + "mana/object" +) + +// Eval evaluates the given ast.Node and returns an object.Object. +func Eval(node ast.Node) object.Object { + switch node := node.(type) { + // Statements + case *ast.Program: + return evalStatements(node.Statements) + + case *ast.ExpressionStatement: + return Eval(node.Expression) + + // Expressions + case *ast.IntegerLiteral: + return &object.Integer{Value: node.Value} + } + + return nil +} + +func evalStatements(stmts []ast.Statement) object.Object { + var result object.Object + + for _, statement := range stmts { + result = Eval(statement) + } + + return result +} diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go new file mode 100644 index 0000000..cd1edb1 --- /dev/null +++ b/evaluator/evaluator_test.go @@ -0,0 +1,44 @@ +package evaluator + +import ( + "mana/lexer" + "mana/object" + "mana/parser" + + "testing" +) + +func TestEvalIntegerExpression(t *testing.T) { + tests := []struct { + input string + expected int64 + }{ + {"5", 5}, + {"10", 10}, + } + + for _, tt := range tests { + evalated := testEval(tt.input) + testIntegerObject(t, evalated, tt.expected) + } +} + +func testEval(input string) object.Object { + l := lexer.New(input) + p := parser.New(l) + program := p.ParseProgram() + return Eval(program) +} + +func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool { + result, ok := obj.(*object.Integer) + if !ok { + t.Errorf("object is not Integer. got=%T (%+v)", obj, obj) + return false + } + if result.Value != expected { + t.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..cac36ac --- /dev/null +++ b/object/object.go @@ -0,0 +1,52 @@ +package object + +import "fmt" + +type ObjectType string + +const ( + INTEGER_OBJ = "INTEGER" + BOOLEAN_OBJ = "BOOLEAN" + NULL_OBJ = "NULL" +) + +type Object interface { + Type() ObjectType + Inspect() string +} + +type Integer struct { + Value int64 +} + +type Boolean struct { + Value bool +} + +type Null struct{} + +func (i *Integer) Type() ObjectType { + return INTEGER_OBJ +} + +func (i *Integer) Inspect() string { + return fmt.Sprintf("%d", i.Value) +} + +func (b *Boolean) Type() ObjectType { + return BOOLEAN_OBJ +} + +func (b *Boolean) Inspect() string { + return fmt.Sprintf("%t", b.Value) +} + +func (n *Null) Type() ObjectType { + return NULL_OBJ +} + +func (n *Null) Inspect() string { + return "null" +} + + diff --git a/repl/repl.go b/repl/repl.go index 9db9683..9a43119 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -6,11 +6,12 @@ import ( "io" "mana/lexer" "mana/parser" + "mana/evaluator" ) // PROMPT is the prompt for the REPL. const PROMPT = ">>> " -const MANA_ICON = ` +const MANA_START = ` ███╗░░░███╗░█████╗░███╗░░██╗░█████╗░ ████╗░████║██╔══██╗████╗░██║██╔══██╗ ██╔████╔██║███████║██╔██╗██║███████║ @@ -21,7 +22,7 @@ const MANA_ICON = ` func Start(in io.Reader, out io.Writer) { var scanner *bufio.Scanner = bufio.NewScanner(in) - io.WriteString(out, MANA_ICON + "\n") + io.WriteString(out, MANA_START + "\n") for { fmt.Fprint(out, PROMPT) @@ -42,13 +43,16 @@ func Start(in io.Reader, out io.Writer) { continue } - io.WriteString(out, program.String()) - io.WriteString(out, "\n") + evaluated := evaluator.Eval(program) + if evaluated != nil { + io.WriteString(out, evaluated.Inspect()) + io.WriteString(out, "\n") + } } } func printParserErrors(out io.Writer, errors []string) { - io.WriteString(out, "Mana Encountered Parser Errors:\n") + io.WriteString(out, "ParseError:\n") for _, msg := range errors { io.WriteString(out, "\t" + msg + "\n") } |
