From 19b4509d67257d91ffc1e18af93ef93cb2af050d Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 4 Jun 2024 22:40:10 -0400 Subject: [PATCH] added string ops and coercion --- cerise-c.m | 20 +++++++++++++++----- cerise-c.rb | 3 +-- runtime.c | 4 ++-- runtime.h | 20 ++++++++++++++++++++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/cerise-c.m b/cerise-c.m index 422f2a9..9af7d03 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -6,7 +6,6 @@ TestLiterals() #assert false #assert nil assert "123" - return true } TestBoolOps() @@ -17,7 +16,6 @@ TestBoolOps() assert true && true assert true || false assert false || true - return true } TestIntOps() @@ -46,8 +44,6 @@ TestIntOps() assert (84 / 2) == 42 assert (21 * 2) == 42 assert (11 % 5) == 1 - - return true } TestRealOps() @@ -76,14 +72,28 @@ TestRealOps() assert (84 / 2) == 42 assert (21 * 2) == 42 #assert (11 % 5) == 1 # Not valid for reals +} +TestStringOps() +{ + assert "foo" == "foo" + assert "foo" != "bar" + assert ("foo" + "bar") == "foobar" + assert ("foo" + 123) == "foo123" + assert ("foo" + 123.0) == "foo123.000000" + assert ("foo" + true) == "footrue" + assert ("foo" + false) == "foofalse" +# assert length("foo") == 3 } -init() +Main() { + def foo = 123 + def bar = foo TestLiterals() TestBoolOps() TestIntOps() TestRealOps() + TestStringOps() return true } diff --git a/cerise-c.rb b/cerise-c.rb index 2030672..ac0e260 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -1147,12 +1147,11 @@ module Codegen end def self.emit_var(state, v) - pp v var = state.syms[v.name] if var.nil? raise "no such variable: #{v.name}" end - var + var.name end def self.emit_call(state, v) diff --git a/runtime.c b/runtime.c index 8b86902..10e23a9 100644 --- a/runtime.c +++ b/runtime.c @@ -109,7 +109,7 @@ int main(int argc, char** argv) val = ToString(MakeReal(42.5)); assert(!strcmp(ValueAsString(val)->bytes, "42.500000")); - extern Value init(void); - (void)init(); + extern Value Main(void); + (void)Main(); return 0; } diff --git a/runtime.h b/runtime.h index 33cf1b6..1150cb4 100644 --- a/runtime.h +++ b/runtime.h @@ -233,6 +233,22 @@ static inline Value OpAdd(Value left, Value right) { result = MakeInt(ValueAsInt(left) + ValueAsInt(right)); } else if (IsReal(left)) { result = MakeReal(ValueAsReal(left) + ValueAsReal(right)); + } else if (IsString(left)) { + right = ToString(right); + String* left_str = ValueAsString(left); + String* right_str = ValueAsString(right); + size_t sz = left_str->length + right_str->length; + String* str = calloc(sizeof(String) + sz + 1, 1); + str->length = sz; + memcpy( + str->bytes, + left_str->bytes, + left_str->length); + memcpy( + &str->bytes[left_str->length], + right_str->bytes, + right_str->length + 1); + result = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) }; } else { fprintf(stderr, "fatal error: addition operator used on invalid type\n"); exit(1); @@ -346,6 +362,8 @@ static inline Value OpEq(Value left, Value right) { result = MakeBool(ValueAsInt(left) == ValueAsInt(right)); } else if (IsReal(left)) { result = MakeBool(ValueAsReal(left) == ValueAsReal(right)); + } else if (IsString(left)) { + result = MakeBool(!strcmp(ValueAsString(left)->bytes, ValueAsString(right)->bytes)); } else { result = MakeBool(false); } @@ -360,6 +378,8 @@ static inline Value OpNeq(Value left, Value right) { result = MakeBool(ValueAsInt(left) != ValueAsInt(right)); } else if (IsReal(left)) { result = MakeBool(ValueAsReal(left) != ValueAsReal(right)); + } else if (IsString(left)) { + result = MakeBool(0 != strcmp(ValueAsString(left)->bytes, ValueAsString(right)->bytes)); } else { result = MakeBool(false); } -- 2.54.0