commit 5cbae63c67263f473fbfb7a5ec45e0d11a144c12
parent 70b2cc1df065a909998e5db015454daa8d591c44
Author: bsandro <email@bsandro.tech>
Date: Thu, 23 Jun 2022 04:04:42 +0300
primitive integer eval
Diffstat:
3 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/eval/eval.go b/eval/eval.go
@@ -0,0 +1,26 @@
+package eval
+
+import (
+ "interp/ast"
+ "interp/object"
+)
+
+func Eval(node ast.Node) object.Object {
+ switch node := node.(type) {
+ case *ast.Program:
+ return evalStatements(node.Statements)
+ case *ast.ExpressionStatement:
+ return Eval(node.Expression)
+ case *ast.IntegerLiteral:
+ return &object.Integer{Value: node.Value}
+ }
+ return nil
+}
+
+func evalStatements(statements []ast.Statement) object.Object {
+ var result object.Object
+ for _,statement := range statements {
+ result = Eval(statement)
+ }
+ return result
+}
diff --git a/eval/eval_test.go b/eval/eval_test.go
@@ -0,0 +1,42 @@
+package eval
+
+import (
+ "interp/lexer"
+ "interp/parser"
+ "interp/object"
+ "testing"
+)
+
+func TestEvalIntegerExpression(t *testing.T) {
+ tests := []struct{
+ input string
+ expected int64
+ }{
+ {"6", 6},
+ {"10", 10},
+ }
+ for _, tt := range tests {
+ evaluated := testEval(tt.input)
+ testIntegerObject(t, evaluated, tt.expected)
+ }
+}
+
+func testEval(input string) object.Object {
+ l := lexer.New(input)
+ p := parser.New(l)
+ prg := p.ParseProgram()
+ return Eval(prg)
+}
+
+func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
+ result, ok := obj.(*object.Integer)
+ if !ok {
+ t.Errorf("obj is not integer (%T %+v)", obj, obj)
+ return false
+ }
+ if result.Value != expected {
+ t.Errorf("obj has wrong value (%d instead of %d)", result.Value, expected)
+ return false
+ }
+ return true
+}
diff --git a/object/object.go b/object/object.go
@@ -0,0 +1,32 @@
+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
+}
+func (i *Integer) Inspect() string { return fmt.Sprintf("%d", i.Value) }
+func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
+
+type Boolean struct {
+ Value bool
+}
+func (b *Boolean) Inspect() string { return fmt.Sprintf("%t", b.Value) }
+func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
+
+type Null struct {}
+func (n *Null) Inspect() string { return "null" }
+func (n *Null) Type() ObjectType { return NULL_OBJ }