From c818591f792975a1f49199e5ad3dadaa7ffd9229 Mon Sep 17 00:00:00 2001 From: Chuck Smith Date: Fri, 15 Mar 2024 14:20:04 -0400 Subject: [PATCH] add string comparison --- evaluator/evaluator.go | 19 ++++++++++++++----- evaluator/evaluator_test.go | 3 +++ vm/vm.go | 20 ++++++++++++++++++++ vm/vm_test.go | 3 +++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 04a9db0..b1b75d5 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -242,14 +242,23 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje } func evalStringInfixExpression(operator string, left object.Object, right object.Object) object.Object { - if operator != "+" { - return newError("unknown operator: %s %s %s", left.Type(), operator, right.Type()) - } - leftVal := left.(*object.String).Value rightVal := right.(*object.String).Value - return &object.String{Value: leftVal + rightVal} + switch operator { + case "+": + return &object.String{Value: leftVal + rightVal} + case "<": + return nativeBoolToBooleanObject(leftVal < rightVal) + case ">": + return nativeBoolToBooleanObject(leftVal > rightVal) + case "==": + return nativeBoolToBooleanObject(leftVal == rightVal) + case "!=": + return nativeBoolToBooleanObject(leftVal != rightVal) + default: + return newError("unknown operator: %s %s %s", left.Type(), operator, right.Type()) + } } func evalIntegerInfixExpression(operator string, left, right object.Object) object.Object { diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index 342b157..d26aee4 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -62,6 +62,9 @@ func TestEvalBooleanExpression(t *testing.T) { {"(1 < 2) == false", false}, {"(1 > 2) == true", false}, {"(1 > 2) == false", true}, + {`"a" == "a"`, true}, + {`"a" < "b"`, true}, + {`"abc" == "abc"`, true}, } for _, tt := range tests { diff --git a/vm/vm.go b/vm/vm.go index 7bf2549..59fe46e 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -455,6 +455,10 @@ func (vm *VM) executeComparison(op code.Opcode) error { return vm.executeIntegerComparison(op, left, right) } + if left.Type() == object.STRING_OBJ && right.Type() == object.STRING_OBJ { + return vm.executeStringComparison(op, left, right) + } + switch op { case code.OpEqual: return vm.push(nativeBoolToBooleanObject(right == left)) @@ -581,6 +585,22 @@ func (vm *VM) executeStringIndex(str, index object.Object) error { return vm.push(&object.String{Value: string(stringObject.Value[i])}) } +func (vm *VM) executeStringComparison(op code.Opcode, left, right object.Object) error { + leftValue := left.(*object.String).Value + rightValue := right.(*object.String).Value + + switch op { + case code.OpEqual: + return vm.push(nativeBoolToBooleanObject(rightValue == leftValue)) + case code.OpNotEqual: + return vm.push(nativeBoolToBooleanObject(rightValue != leftValue)) + case code.OpGreaterThan: + return vm.push(nativeBoolToBooleanObject(leftValue > rightValue)) + default: + return fmt.Errorf("unknown operator: %d", op) + } +} + func nativeBoolToBooleanObject(input bool) *object.Boolean { if input { return True diff --git a/vm/vm_test.go b/vm/vm_test.go index c39fbe4..6708c6c 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -229,6 +229,9 @@ func TestBooleanExpressions(t *testing.T) { {"!!false", false}, {"!!5", true}, {"!(if (false) { 5; })", true}, + {`"a" == "a"`, true}, + {`"a" < "b"`, true}, + {`"abc" == "abc"`, true}, } runVmTests(t, tests)