umx_compiler

UMX virtual machine "Monkey" interpreter / bytecode compiler
git clone git://bsandro.tech/umx_compiler
Log | Files | Refs

commit c887ec01da2d32fb90c22dd84fe104ce5d6fa624
parent 74f2a1ec1374f47939afe92253630cacb116eec5
Author: bsandro <email@bsandro.tech>
Date:   Sun, 26 Jun 2022 23:46:50 +0300

Strings eval

Diffstat:
Mast/ast.go | 13+++++++++++++
Meval/eval.go | 2++
Meval/eval_test.go | 12++++++++++++
Mobject/object.go | 8++++++++
Mparser/parser.go | 6++++++
Mparser/parser_test.go | 16++++++++++++++++
6 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/ast/ast.go b/ast/ast.go @@ -265,3 +265,16 @@ func (ce *CallExpression) String() string { out.WriteString(")") return out.String() } + +type StringLiteral struct { + Token token.Token + Value string +} + +func (sl *StringLiteral) expressionNode() {} +func (sl *StringLiteral) TokenLiteral() string { + return sl.Token.Literal +} +func (sl *StringLiteral) String() string { + return sl.Token.Literal +} diff --git a/eval/eval.go b/eval/eval.go @@ -89,6 +89,8 @@ func Eval(node ast.Node, ctx *object.Context) object.Object { return args[0] } return applyFunction(fn, args) + case *ast.StringLiteral: + return &object.String{Value: node.Value} } return nil } diff --git a/eval/eval_test.go b/eval/eval_test.go @@ -228,3 +228,15 @@ func TestFunctionApplication(t *testing.T) { testIntegerObject(t, testEval(tt.input), tt.expected) } } + +func TestStringLiteral(t *testing.T) { + input := `"ehlo world"` + evaluated := testEval(input) + str, ok := evaluated.(*object.String) + if !ok { + t.Fatalf("object is not a string") + } + if str.Value != "ehlo world" { + t.Errorf("String has wrong value: %s", str.Value) + } +} diff --git a/object/object.go b/object/object.go @@ -16,6 +16,7 @@ const ( RETURN_VALUE_OBJ = "RETURN_VALUE" ERROR_OBJ = "ERROR" FUNCTION_OBJ = "FUNCTION" + STRING_OBJ = "STRING" ) type Object interface { @@ -76,3 +77,10 @@ func (f *Function) Inspect() string { out.WriteString("\n}") return out.String() } + +type String struct { + Value string +} + +func (s *String) Type() ObjectType { return STRING_OBJ } +func (s *String) Inspect() string { return s.Value } diff --git a/parser/parser.go b/parser/parser.go @@ -78,6 +78,8 @@ func New(l *lexer.Lexer) *Parser { p.registerPrefix(token.FUNCTION, p.parseFunctionLiteral) p.registerInfix(token.LPAREN, p.parseCallExpression) + p.registerPrefix(token.STRING, p.parseStringLiteral) + return p } @@ -368,3 +370,7 @@ func (p *Parser) parseCallArguments() []ast.Expression { } return args } + +func (p *Parser) parseStringLiteral() ast.Expression { + return &ast.StringLiteral{Token: p.curToken, Value: p.curToken.Literal} +} diff --git a/parser/parser_test.go b/parser/parser_test.go @@ -571,3 +571,19 @@ func TestCallParametersParsing(t *testing.T) { testInfixExpression(t, expr.Arguments[1], 2, "*", 3) testInfixExpression(t, expr.Arguments[2], 4, "+", 5) } + +func TestStringLiteralExpression(t *testing.T) { + input := `"ehlo world";` + l := lexer.New(input) + p := New(l) + prg := p.ParseProgram() + checkParserErrors(t, p) + statement := prg.Statements[0].(*ast.ExpressionStatement) + literal, ok := statement.Expression.(*ast.StringLiteral) + if !ok { + t.Fatalf("expression is not string literal") + } + if literal.Value != "ehlo world" { + t.Errorf("literal string value is wrong") + } +}