From e5ed6e13a4adbbe61317194af36c33c82b33c90f Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 25 Mar 2018 01:50:10 +0100 Subject: lost chapter --- evaluator/quote_unquote.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 evaluator/quote_unquote.go (limited to 'evaluator/quote_unquote.go') diff --git a/evaluator/quote_unquote.go b/evaluator/quote_unquote.go new file mode 100644 index 0000000..d3521f9 --- /dev/null +++ b/evaluator/quote_unquote.go @@ -0,0 +1,68 @@ +package evaluator + +import ( + "fmt" + "monkey/ast" + "monkey/object" + "monkey/token" +) + +func quote(node ast.Node, env *object.Environment) object.Object { + node = evalUnquoteCalls(node, env) + return &object.Quote{Node: node} +} + +func evalUnquoteCalls(quoted ast.Node, env *object.Environment) ast.Node { + return ast.Modify(quoted, func(node ast.Node) ast.Node { + if !isUnquoteCall(node) { + return node + } + + call, ok := node.(*ast.CallExpression) + if !ok { + return node + } + + if len(call.Arguments) != 1 { + return node + } + + unquoted := Eval(call.Arguments[0], env) + return convertObjectToASTNode(unquoted) + }) +} + +func isUnquoteCall(node ast.Node) bool { + callExpression, ok := node.(*ast.CallExpression) + if !ok { + return false + } + + return callExpression.Function.TokenLiteral() == "unquote" +} + +func convertObjectToASTNode(obj object.Object) ast.Node { + switch obj := obj.(type) { + case *object.Integer: + t := token.Token{ + Type: token.INT, + Literal: fmt.Sprintf("%d", obj.Value), + } + return &ast.IntegerLiteral{Token: t, Value: obj.Value} + + case *object.Boolean: + var t token.Token + if obj.Value { + t = token.Token{Type: token.TRUE, Literal: "true"} + } else { + t = token.Token{Type: token.FALSE, Literal: "false"} + } + return &ast.Boolean{Token: t, Value: obj.Value} + + case *object.Quote: + return obj.Node + + default: + return nil + } +} -- cgit v1.2.3