- 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
This commit is contained in:
Tijani Lawal 2022-11-03 15:01:40 +00:00
parent 2c2c936b29
commit b028741d75
3 changed files with 44 additions and 10 deletions

View File

@ -87,7 +87,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
return apply_function(function, args) return apply_function(function, args)
case *ast.StringLiteral: case *ast.StringLiteral:
return &object.String{Value: node.Value } return &object.String{Value: node.Value}
} }
return nil return nil
@ -175,13 +175,6 @@ func eval_block_statement(block *ast.BlockStatement, env *object.Environment) ob
return result 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 { func eval_prefix_expression(operator string, right object.Object) object.Object {
switch operator { switch operator {
case "!": case "!":
@ -231,6 +224,9 @@ func eval_infix_expression(operator string, left object.Object, right object.Obj
case left.Type() != right.Type(): case left.Type() != right.Type():
return new_error("type mismatch: %s %s %s", left.Type(), operator, 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: default:
return new_error("unknown operator: %s %s %s", left.Type(), operator, right.Type()) 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 { func eval_if_expression(ie *ast.IfExpression, env *object.Environment) object.Object {
condition := Eval(ie.Condition, env) 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 { func is_truthy(object object.Object) bool {
switch object { switch object {
case NULL: case NULL:

View File

@ -56,6 +56,9 @@ func TestErrorHandling(l_test *testing.T) {
} }
`, "unknown operator: BOOLEAN + BOOLEAN"}, `, "unknown operator: BOOLEAN + BOOLEAN"},
{"foobar", "identifier not found: foobar"}, {"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 { for _, tt := range tests {
@ -237,7 +240,7 @@ func TestClosures(l_test *testing.T) {
test_integer_object(l_test, test_eval(input), 4) test_integer_object(l_test, test_eval(input), 4)
} }
func TestStringLiteral(l_test *testing.T){ func TestStringLiteral(l_test *testing.T) {
input := `"Hello, world!"` input := `"Hello, world!"`
evaluated := test_eval(input) 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 // Helpers
func test_eval(input string) object.Object { func test_eval(input string) object.Object {
l_lexer := lexer.New(input) 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 { if !ok {
l_test.Errorf("object is not integer, got=%T (%+v)", l_object, l_object) l_test.Errorf("object is not integer, got=%T (%+v)", l_object, l_object)
return false return false
} }
if result.Value != expected { if result.Value != expected {
l_test.Errorf("object has wrong value, got=%d, want=%d", result.Value, expected) l_test.Errorf("object has wrong value, got=%d, want=%d", result.Value, expected)

View File

@ -109,4 +109,4 @@ type String struct {
} }
func (s *String) Type() ObjectType { return STRING_OBJECT } func (s *String) Type() ObjectType { return STRING_OBJECT }
func (s *String) Inspect() string { return s.Value } func (s *String) Inspect() string { return s.Value }