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