From b028741d7570ed3479d5c5873efe885e695b55fc Mon Sep 17 00:00:00 2001 From: tijani Date: Thu, 3 Nov 2022 15:01:40 +0000 Subject: [PATCH] - String Concatenation is now possible. - Added test to ensure only '+' will work for concatenating strings - Likkle reformatting. git-svn-id: https://svn.tlawal.org/svn/monkey@58 f6afcba9-9ef1-4bdd-9b72-7484f5705bac --- evaluator/evaluator.go | 32 ++++++++++++++++++++++++-------- evaluator/evaluator_test.go | 20 +++++++++++++++++++- object/object.go | 2 +- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index bb68d7e..1ff45b3 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -87,7 +87,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object { return apply_function(function, args) case *ast.StringLiteral: - return &object.String{Value: node.Value } + return &object.String{Value: node.Value} } return nil @@ -175,13 +175,6 @@ func eval_block_statement(block *ast.BlockStatement, env *object.Environment) ob return result } -func native_bool_to_boolean_object(input bool) *object.Boolean { - if input { - return TRUE - } - return FALSE -} - func eval_prefix_expression(operator string, right object.Object) object.Object { switch operator { case "!": @@ -231,6 +224,9 @@ func eval_infix_expression(operator string, left object.Object, right object.Obj case left.Type() != right.Type(): return new_error("type mismatch: %s %s %s", left.Type(), operator, right.Type()) + + case left.Type() == object.STRING_OBJECT && right.Type() == object.STRING_OBJECT: + return eval_string_infix_expression(operator, left, right) default: return new_error("unknown operator: %s %s %s", left.Type(), operator, right.Type()) } @@ -270,6 +266,19 @@ func eval_integer_infix_expression(operator string, left object.Object, right ob } } +/* + FEATURES TODO: + - Add support for string comparision '==' and '!='. +*/ +func eval_string_infix_expression(operator string, left object.Object, right object.Object) object.Object { + if operator != "+" { + return new_error("unknown operator: %s %s %s", left.Type(), operator, right.Type()) + } + left_value := left.(*object.String).Value + right_value := right.(*object.String).Value + return &object.String{Value: left_value + right_value} +} + func eval_if_expression(ie *ast.IfExpression, env *object.Environment) object.Object { condition := Eval(ie.Condition, env) @@ -286,6 +295,13 @@ func eval_if_expression(ie *ast.IfExpression, env *object.Environment) object.Ob } } +func native_bool_to_boolean_object(input bool) *object.Boolean { + if input { + return TRUE + } + return FALSE +} + func is_truthy(object object.Object) bool { switch object { case NULL: diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index e42de38..6147690 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -56,6 +56,9 @@ func TestErrorHandling(l_test *testing.T) { } `, "unknown operator: BOOLEAN + BOOLEAN"}, {"foobar", "identifier not found: foobar"}, + + // Test to only make sure there is only support for + operator in string concatenation, anything else would be wrong. + {`"Hello" - "World"`, "unknown operator: STRING - STRING"}, } for _, tt := range tests { @@ -237,7 +240,7 @@ func TestClosures(l_test *testing.T) { test_integer_object(l_test, test_eval(input), 4) } -func TestStringLiteral(l_test *testing.T){ +func TestStringLiteral(l_test *testing.T) { input := `"Hello, world!"` evaluated := test_eval(input) @@ -251,6 +254,20 @@ func TestStringLiteral(l_test *testing.T){ } } +func TestStringConcatenation(l_test *testing.T) { + input := `"Hello" + " " + "World!"` + + evaluated := test_eval(input) + string, ok := evaluated.(*object.String) + if !ok { + l_test.Fatalf("object is not String, got=%T (%+v)", evaluated, evaluated) + } + + if string.Value != "Hello World!" { + l_test.Errorf("String has wrong value, got=%q", string.Value) + } +} + // Helpers func test_eval(input string) object.Object { l_lexer := lexer.New(input) @@ -266,6 +283,7 @@ func test_integer_object(l_test *testing.T, l_object object.Object, expected int 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) diff --git a/object/object.go b/object/object.go index 7c61ea6..a4a8f88 100644 --- a/object/object.go +++ b/object/object.go @@ -109,4 +109,4 @@ type String struct { } func (s *String) Type() ObjectType { return STRING_OBJECT } -func (s *String) Inspect() string { return s.Value } +func (s *String) Inspect() string { return s.Value }