support string equality in the interpreter

This commit is contained in:
Luke Boswell 2025-08-20 18:22:26 +10:00
parent 91f72a3242
commit f2321d8769
No known key found for this signature in database
GPG key ID: 54A7324B1B975757
6 changed files with 171 additions and 1 deletions

View file

@ -97,6 +97,7 @@ pub const EvalError = error{
StringInterpolationFailed,
StringSegmentEvaluationFailed,
StringConversionFailed,
StringOrderingNotSupported,
UnsupportedWorkItem,
UnexpectedWorkItem,
RuntimeCrash,
@ -1526,8 +1527,32 @@ pub const Interpreter = struct {
self.traceError("comparison operations on fractional types only support Dec precision", .{});
return error.TypeMismatch;
}
}
// Check if both operands are strings
else if (lhs_scalar.tag == .str and rhs_scalar.tag == .str) {
const lhs_ptr = @as(*const RocStr, @ptrCast(@alignCast(lhs.ptr.?)));
const rhs_ptr = @as(*const RocStr, @ptrCast(@alignCast(rhs.ptr.?)));
const lhs_str = lhs_ptr.*;
const rhs_str = rhs_ptr.*;
const result_layout = Layout.boolType();
var result_value = try self.pushStackValue(result_layout);
const bool_result: u8 = switch (kind) {
.w_binop_eq => if (lhs_str.eq(rhs_str)) 1 else 0,
.w_binop_ne => if (!lhs_str.eq(rhs_str)) 1 else 0,
// String ordering comparisons are not implemented yet
.w_binop_gt, .w_binop_lt, .w_binop_ge, .w_binop_le => {
self.traceError("string ordering comparisons (>, <, >=, <=) are not supported", .{});
return error.StringOrderingNotSupported;
},
else => unreachable,
};
result_value.setBool(bool_result);
self.traceInfo("String comparison: \"{s}\" {s} \"{s}\" = {}", .{ lhs_str.asSlice(), @tagName(kind), rhs_str.asSlice(), bool_result });
} else {
self.traceError("comparison operations require operands of the same type (both integers or both decimals)", .{});
self.traceError("comparison operations require operands of the same type (both integers, both decimals, or both strings)", .{});
return error.TypeMismatch;
}
},

View file

@ -0,0 +1,43 @@
# META
~~~ini
description=String comparison edge cases and longer strings
type=repl
~~~
# SOURCE
~~~roc
» longStr1 = "This is a very long string that should test the comparison of larger strings that might not fit in small string optimization"
» longStr2 = "This is a very long string that should test the comparison of larger strings that might not fit in small string optimization"
» longStr3 = "This is a very long string that should test the comparison of larger strings that might not fit in small string optimizatioN"
» longStr1 == longStr2
» longStr1 == longStr3
» whitespace1 = "hello "
» whitespace2 = "hello"
» whitespace1 == whitespace2
» specialChars1 = "hello\nworld"
» specialChars2 = "hello\nworld"
» specialChars1 == specialChars2
~~~
# OUTPUT
assigned `longStr1`
---
assigned `longStr2`
---
assigned `longStr3`
---
True
---
False
---
assigned `whitespace1`
---
assigned `whitespace2`
---
False
---
assigned `specialChars1`
---
assigned `specialChars2`
---
True
# PROBLEMS
NIL

View file

@ -0,0 +1,31 @@
# META
~~~ini
description=Basic string equality comparisons
type=repl
~~~
# SOURCE
~~~roc
» "hello" == "hello"
» "hello" == "world"
» "hello" != "world"
» "hello" != "hello"
» "" == ""
» "" == "not empty"
» "same length" == "different.."
~~~
# OUTPUT
True
---
False
---
True
---
False
---
True
---
False
---
False
# PROBLEMS
NIL

View file

@ -0,0 +1,31 @@
# META
~~~ini
description=String interpolation and concatenation comparisons
type=repl
~~~
# SOURCE
~~~roc
» name = "World"
» "Hello, ${name}!" == "Hello, World!"
» "Hello, ${name}!" == "Hello, Earth!"
» prefix = "Got: "
» suffix = "test"
» "${prefix}${suffix}" == "Got: test"
» "${prefix}${suffix}" != "Got: different"
~~~
# OUTPUT
assigned `name`
---
True
---
False
---
assigned `prefix`
---
assigned `suffix`
---
True
---
True
# PROBLEMS
NIL

View file

@ -0,0 +1,18 @@
# META
~~~ini
description=Simple multiline string comparison
type=repl
~~~
# SOURCE
~~~roc
» foo =
"""first line
"""second line
» foo == "first line\nsecond line"
~~~
# OUTPUT
assigned `foo`
---
True
# PROBLEMS
NIL

View file

@ -0,0 +1,22 @@
# META
~~~ini
description=String ordering operations should fail gracefully (not supported)
type=repl
~~~
# SOURCE
~~~roc
» "apple" > "banana"
» "zoo" < "aardvark"
» "equal" >= "equal"
» "first" <= "second"
~~~
# OUTPUT
Evaluation error: error.StringOrderingNotSupported
---
Evaluation error: error.StringOrderingNotSupported
---
Evaluation error: error.StringOrderingNotSupported
---
Evaluation error: error.StringOrderingNotSupported
# PROBLEMS
NIL