diff --git a/TODO.md b/TODO.md index 8afd260..e695e00 100644 --- a/TODO.md +++ b/TODO.md @@ -31,14 +31,14 @@ After some additional development: - [x] Print stack - [x] Assembler - [ ] VM execution - - [ ] Stack operations (nil, integer, float, string, function) + - [x] Stack operations (nil, integer, float, string, function) - [x] Integer - [x] Float - [x] String - - [ ] Expressions + - [x] Expressions - [x] Integer - [x] Float - - [ ] String + - [x] String - [ ] Local/global variables - [ ] Functions - [ ] Constants diff --git a/src/vm/expr.cc b/src/vm/expr.cc index 11c7796..67123ea 100644 --- a/src/vm/expr.cc +++ b/src/vm/expr.cc @@ -10,12 +10,24 @@ namespace tyche::vm { std::function binary_ops[(size_t) BinaryOperationType::COUNT][(size_t) Type::COUNT][(size_t) Type::COUNT]; static int init_ = []() { - for (size_t i = 0; i < (size_t) BinaryOperationType::COUNT; ++i) - for (size_t j = 0; j < (size_t) Type::COUNT; ++j) - for (size_t k = 0; k < (size_t) Type::COUNT; ++k) + // every combination, except when explicit, return type error + for (size_t i = 0; i < (size_t) BinaryOperationType::COUNT; ++i) { + for (size_t j = 0; j < (size_t) Type::COUNT; ++j) { + for (size_t k = 0; k < (size_t) Type::COUNT; ++k) { binary_ops[i][j][k] = [&i](Value const& a, Value const& b) -> Value { throw VMInvalidOperation((BinaryOperationType) i, a.type(), b.type()); }; + } + } + } + + // every equality/inequality, by default, return inequal + for (size_t j = 0; j < (size_t) Type::COUNT; ++j) { + for (size_t k = 0; k < (size_t) Type::COUNT; ++k) { + binary_ops[(size_t) BinaryOperationType::Equality][j][k] = [](Value const&, Value const&) { return Value::createFalse(); }; + binary_ops[(size_t) BinaryOperationType::Inequality][j][k] = [](Value const&, Value const&) { return Value::createTrue(); }; + } + } #define BIN_OP(op, t1, t2) binary_ops[(size_t) BinaryOperationType::op][(size_t) Type::t1][(size_t) Type::t2] = [](Value const& b, Value const& a) @@ -23,6 +35,7 @@ static int init_ = []() { BIN_OP(Sum, Integer, Float) { return Value::createFloat((float) a.as_integer() + b.as_float()); }; BIN_OP(Sum, Float, Integer) { return Value::createFloat(a.as_float() + (float) b.as_integer()); }; BIN_OP(Sum, Float, Float) { return Value::createFloat(a.as_float() + b.as_float()); }; + BIN_OP(Sum, String, String) { return Value::createString(a.as_string() + b.as_string()); }; BIN_OP(Subtraction, Integer, Integer) { return Value::createInteger(a.as_integer() - b.as_integer()); }; BIN_OP(Subtraction, Integer, Float) { return Value::createFloat((float) a.as_integer() - b.as_float()); }; @@ -48,11 +61,13 @@ static int init_ = []() { BIN_OP(Equality, Integer, Float) { return Value::createIntegerFromBool(std::abs((float) a.as_integer() - b.as_float()) < FLOAT_EPSILON); }; BIN_OP(Equality, Float, Integer) { return Value::createIntegerFromBool(std::abs(a.as_float() - (float) b.as_integer()) < FLOAT_EPSILON); }; BIN_OP(Equality, Float, Float) { return Value::createIntegerFromBool(std::abs(a.as_float() - b.as_float()) < FLOAT_EPSILON); }; + BIN_OP(Equality, String, String) { return Value::createIntegerFromBool(a.as_string() == b.as_string()); }; BIN_OP(Inequality, Integer, Integer) { return Value::createIntegerFromBool(a.as_integer() != b.as_integer()); }; BIN_OP(Inequality, Integer, Float) { return Value::createIntegerFromBool(std::abs((float) a.as_integer() - b.as_float()) >= FLOAT_EPSILON); }; BIN_OP(Inequality, Float, Integer) { return Value::createIntegerFromBool(std::abs(a.as_float() - (float) b.as_integer()) >= FLOAT_EPSILON); }; BIN_OP(Inequality, Float, Float) { return Value::createIntegerFromBool(std::abs(a.as_float() - b.as_float()) >= FLOAT_EPSILON); }; + BIN_OP(Inequality, String, String) { return Value::createIntegerFromBool(a.as_string() != b.as_string()); }; BIN_OP(LessThan, Integer, Integer) { return Value::createIntegerFromBool(a.as_integer() < b.as_integer()); }; BIN_OP(LessThan, Integer, Float) { return Value::createIntegerFromBool((float) a.as_integer() < b.as_float()); }; diff --git a/src/vm/tests.cc b/src/vm/tests.cc index 102c447..b147cc7 100644 --- a/src/vm/tests.cc +++ b/src/vm/tests.cc @@ -222,6 +222,52 @@ TEST(VM, FloatFloatOperations) ASSERT_FLOAT_EQ(test_op("3.2", "3.2", "eq").to_integer(-1), 1); } +TEST(VM, StringString) +{ + ASSERT_EQ(run(R"( + .const + 0: "Hello" + 1: "World" + .func 0 + pushc 0 + pushc 1 + sum + ret + )").to_string(-1), "HelloWorld"); + + ASSERT_EQ(run(R"( + .const + 0: "Hello" + 1: "World" + .func 0 + pushc 0 + pushc 1 + eq + ret + )").to_integer(-1), 0); + + ASSERT_EQ(run(R"( + .const + 0: "Hello" + 1: "Hello" + .func 0 + pushc 0 + pushc 1 + eq + ret + )").to_integer(-1), 1); + + ASSERT_EQ(run(R"( + .const + 0: "Hello" + .func 0 + pushc 0 + pushi 1 + eq + ret + )").to_integer(-1), 0); +} + int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); diff --git a/src/vm/value.hh b/src/vm/value.hh index 0318ecd..65c98ce 100644 --- a/src/vm/value.hh +++ b/src/vm/value.hh @@ -28,6 +28,8 @@ public: static Value createString(std::string const& str) { return Value(str); } static Value createFunctionId(FunctionId f_id) { return Value(Function { f_id }); } + static Value createFalse() { return createInteger(0); } + static Value createTrue() { return createInteger(1); } static Value createIntegerFromBool(bool b) { return createInteger(b ? 1 : 0); } [[nodiscard]] Type type() const;