From 536011ee797d143baed0a1c5149b98f0c5693d3f Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 17:29:46 +0100 Subject: [PATCH 1/7] feat(iroptimizer, vm): adding FUSED_MATH super instruction, able to fuse 3 math instructions (add, sub, mul, div) in a single pass --- include/Ark/Compiler/Instructions.hpp | 4 +- .../IntermediateRepresentation/Entity.hpp | 8 ++- .../IntermediateRepresentation/Word.hpp | 4 ++ src/arkreactor/Compiler/BytecodeReader.cpp | 9 ++- .../IntermediateRepresentation/Entity.cpp | 11 +++ .../IntermediateRepresentation/IRCompiler.cpp | 6 ++ .../IROptimizer.cpp | 28 ++++++++ src/arkreactor/VM/VM.cpp | 68 ++++++++++++++++++- 8 files changed, 133 insertions(+), 5 deletions(-) diff --git a/include/Ark/Compiler/Instructions.hpp b/include/Ark/Compiler/Instructions.hpp index 61aad040..66775b73 100644 --- a/include/Ark/Compiler/Instructions.hpp +++ b/include/Ark/Compiler/Instructions.hpp @@ -432,6 +432,7 @@ namespace Ark::internal MUL_BY = 0x6c, MUL_BY_INDEX = 0x6d, MUL_SET_VAL = 0x6e, + FUSED_MATH = 0x6f, InstructionsCount }; @@ -549,7 +550,8 @@ namespace Ark::internal "LT_LEN_SYM_JUMP_IF_FALSE", "MUL_BY", "MUL_BY_INDEX", - "MUL_SET_VAL" + "MUL_SET_VAL", + "FUSED_MATH" }; static_assert(InstructionNames.size() == static_cast(Instruction::InstructionsCount) && "Some instruction names appear to be missing"); diff --git a/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp b/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp index 35b28eea..8d2ae741 100644 --- a/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp +++ b/include/Ark/Compiler/IntermediateRepresentation/Entity.hpp @@ -26,7 +26,8 @@ namespace Ark::internal::IR Goto, GotoWithArg, Opcode, - Opcode2Args + Opcode2Args, + Opcode3Args }; using label_t = std::size_t; @@ -45,6 +46,8 @@ namespace Ark::internal::IR Entity(Instruction inst, uint16_t primary_arg, uint16_t secondary_arg); + Entity(Instruction inst, uint8_t inst2, uint8_t inst3, uint8_t inst4); + static Entity Label(label_t value); static Entity Goto(const Entity& label, Instruction inst = Instruction::JUMP); @@ -65,6 +68,8 @@ namespace Ark::internal::IR [[nodiscard]] inline uint16_t secondaryArg() const { return m_secondary_arg; } + [[nodiscard]] inline uint16_t tertiaryArg() const { return m_tertiary_arg; } + void setSourceLocation(const std::string& filename, std::size_t line); [[nodiscard]] inline bool hasValidSourceLocation() const { return !m_source_file.empty(); } @@ -79,6 +84,7 @@ namespace Ark::internal::IR Instruction m_inst { NOP }; uint16_t m_primary_arg { 0 }; uint16_t m_secondary_arg { 0 }; + uint16_t m_tertiary_arg { 0 }; std::string m_source_file; std::size_t m_source_line { 0 }; }; diff --git a/include/Ark/Compiler/IntermediateRepresentation/Word.hpp b/include/Ark/Compiler/IntermediateRepresentation/Word.hpp index fee745ae..a03781f4 100644 --- a/include/Ark/Compiler/IntermediateRepresentation/Word.hpp +++ b/include/Ark/Compiler/IntermediateRepresentation/Word.hpp @@ -39,6 +39,10 @@ namespace Ark::internal byte_2 = static_cast((secondary_arg & 0x00f) << 4 | (primary_arg & 0xf00) >> 8); byte_3 = static_cast(primary_arg & 0x0ff); } + + Word(const uint8_t inst, const uint8_t one, const uint8_t two, const uint8_t three) : + opcode(inst), byte_1(one), byte_2(two), byte_3(three) + {} }; } diff --git a/src/arkreactor/Compiler/BytecodeReader.cpp b/src/arkreactor/Compiler/BytecodeReader.cpp index e319e4a1..71b99e21 100644 --- a/src/arkreactor/Compiler/BytecodeReader.cpp +++ b/src/arkreactor/Compiler/BytecodeReader.cpp @@ -468,7 +468,8 @@ namespace Ark SymRaw, ///< Symbol, number RawSym, ///< Symbol index, symbol RawConst, ///< Symbol index, constant - RawRaw ///< Symbol index, symbol index + RawRaw, ///< Symbol index, symbol index + RawRawRaw }; struct Arg @@ -562,7 +563,8 @@ namespace Ark { LT_LEN_SYM_JUMP_IF_FALSE, ArgKind::SymRaw }, { MUL_BY, ArgKind::RawRaw }, { MUL_BY_INDEX, ArgKind::RawRaw }, - { MUL_SET_VAL, ArgKind::RawRaw } + { MUL_SET_VAL, ArgKind::RawRaw }, + { FUSED_MATH, ArgKind::RawRawRaw } }; const auto builtin_name = [](const uint16_t idx) { @@ -627,6 +629,9 @@ namespace Ark case ArgKind::RawRaw: fmt::print(" {}, {}\n", fmt::styled(arg->primary(), raw_color), fmt::styled(arg->secondary(), raw_color)); break; + case ArgKind::RawRawRaw: + fmt::print(" {}, {}, {}\n", fmt::styled(arg->padding, raw_color), fmt::styled((arg->arg & 0xff00) >> 8, raw_color), fmt::styled(arg->arg & 0x00ff, raw_color)); + break; } } else diff --git a/src/arkreactor/Compiler/IntermediateRepresentation/Entity.cpp b/src/arkreactor/Compiler/IntermediateRepresentation/Entity.cpp index f7ab8fbb..178877d7 100644 --- a/src/arkreactor/Compiler/IntermediateRepresentation/Entity.cpp +++ b/src/arkreactor/Compiler/IntermediateRepresentation/Entity.cpp @@ -17,6 +17,11 @@ namespace Ark::internal::IR m_inst(inst), m_primary_arg(primary_arg), m_secondary_arg(secondary_arg) {} + Entity::Entity(const Instruction inst, const uint8_t inst2, const uint8_t inst3, const uint8_t inst4) : + m_kind(Kind::Opcode3Args), + m_inst(inst), m_primary_arg(inst2), m_secondary_arg(inst3), m_tertiary_arg(inst4) + {} + Entity Entity::Label(const label_t value) { auto entity = Entity(Kind::Label); @@ -55,6 +60,12 @@ namespace Ark::internal::IR return Word(m_inst, m_primary_arg); if (m_kind == Kind::Opcode2Args) return Word(m_inst, m_primary_arg, m_secondary_arg); + if (m_kind == Kind::Opcode3Args) + return Word( + m_inst, + static_cast(m_primary_arg), + static_cast(m_secondary_arg), + static_cast(m_tertiary_arg)); return Word(0, 0); } diff --git a/src/arkreactor/Compiler/IntermediateRepresentation/IRCompiler.cpp b/src/arkreactor/Compiler/IntermediateRepresentation/IRCompiler.cpp index 93f34118..f6dbb578 100644 --- a/src/arkreactor/Compiler/IntermediateRepresentation/IRCompiler.cpp +++ b/src/arkreactor/Compiler/IntermediateRepresentation/IRCompiler.cpp @@ -94,6 +94,10 @@ namespace Ark::internal case IR::Kind::Opcode2Args: fmt::println(stream, "\t{} {}, {}", InstructionNames[entity.inst()], entity.primaryArg(), entity.secondaryArg()); break; + + case IR::Kind::Opcode3Args: + fmt::println(stream, "\t{} {}, {}, {}", InstructionNames[entity.inst()], entity.primaryArg(), entity.secondaryArg(), entity.tertiaryArg()); + break; } } @@ -158,6 +162,8 @@ namespace Ark::internal case IR::Kind::Opcode: [[fallthrough]]; case IR::Kind::Opcode2Args: + [[fallthrough]]; + case IR::Kind::Opcode3Args: pushWord(inst.bytecode()); break; diff --git a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp index 44c9c070..5b95b3fd 100644 --- a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp +++ b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp @@ -9,6 +9,16 @@ namespace Ark::internal { + IR::Entity fuseMathOps3(const std::span e) + { + return IR::Entity(FUSED_MATH, e[0].inst(), e[1].inst(), e[2].inst()); + } + + IR::Entity fuseMathOps2(const std::span e) + { + return IR::Entity(FUSED_MATH, e[0].inst(), e[1].inst(), NOP); + } + IROptimizer::IROptimizer(const unsigned debug) : m_logger("IROptimizer", debug) { @@ -234,6 +244,24 @@ namespace Ark::internal return IR::Entity::GotoWithArg(e[3], LT_LEN_SYM_JUMP_IF_FALSE, e[0].primaryArg()); } }, }; + + const auto math_ops = { ADD, SUB, MUL, DIV }; + for (const auto& one : math_ops) + { + for (const auto& two : math_ops) + { + for (const auto& three : math_ops) + m_ruleset.emplace_back(Rule { { one, two, three }, fuseMathOps3 }); + } + } + + for (const auto& one : math_ops) + { + for (const auto& two : math_ops) + m_ruleset.emplace_back(Rule { { one, two }, fuseMathOps2 }); + } + + m_logger.debug("Loaded {} rules", m_ruleset.size()); } void IROptimizer::process(const std::vector& pages, const std::vector& symbols, const std::vector& values) diff --git a/src/arkreactor/VM/VM.cpp b/src/arkreactor/VM/VM.cpp index 05264bf8..76e634e8 100644 --- a/src/arkreactor/VM/VM.cpp +++ b/src/arkreactor/VM/VM.cpp @@ -108,6 +108,24 @@ namespace Ark types::Contract { { types::Typedef("src", ValueType::String), types::Typedef("idx", ValueType::Number) } } } }, { container, index }); } + + inline double doMath(double a, double b, const Instruction op) + { + if (op == ADD) + a += b; + else if (op == SUB) + a -= b; + else if (op == MUL) + a *= b; + else if (op == DIV) + { + if (b == 0) + Ark::VM::throwVMError(ErrorKind::DivisionByZero, fmt::format("Can not compute expression (/ {} {})", a, b)); + a /= b; + } + + return a; + } } VM::VM(State& state) noexcept : @@ -647,7 +665,8 @@ namespace Ark &&TARGET_LT_LEN_SYM_JUMP_IF_FALSE, &&TARGET_MUL_BY, &&TARGET_MUL_BY_INDEX, - &&TARGET_MUL_SET_VAL + &&TARGET_MUL_SET_VAL, + &&TARGET_FUSED_MATH }; static_assert(opcode_targets.size() == static_cast(Instruction::InstructionsCount) && "Some instructions are not implemented in the VM"); @@ -2051,6 +2070,53 @@ namespace Ark } DISPATCH(); } + + TARGET(FUSED_MATH) + { + const auto op1 = static_cast(padding), + op2 = static_cast((arg & 0xff00) >> 8), + op3 = static_cast(arg & 0x00ff); + const std::size_t arg_count = (op1 != NOP) + (op2 != NOP) + (op3 != NOP); + + const Value* d = popAndResolveAsPtr(context); + const Value* c = popAndResolveAsPtr(context); + const Value* b = popAndResolveAsPtr(context); + + if (d->valueType() != ValueType::Number || c->valueType() != ValueType::Number) + throw types::TypeCheckingError( + InstructionNames[op1], + { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, + { *c, *d }); + + double temp = helper::doMath(c->number(), d->number(), op1); + if (b->valueType() != ValueType::Number) + throw types::TypeCheckingError( + InstructionNames[op2], + { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, + { *b, Value(temp) }); + temp = helper::doMath(b->number(), temp, op2); + + if (arg_count == 2) + push(Value(temp), context); + else if (arg_count == 3) + { + const Value* a = popAndResolveAsPtr(context); + if (a->valueType() != ValueType::Number) + throw types::TypeCheckingError( + InstructionNames[op3], + { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, + { *a, Value(temp) }); + + temp = helper::doMath(a->number(), temp, op3); + push(Value(temp), context); + } + else + throw Error( + fmt::format( + "FUSED_MATH got {} arguments, expected 2 or 3. Arguments: {:x}{:x}{:x}. There is a bug in the codegen!", + arg_count, static_cast(op1), static_cast(op2), static_cast(op3))); + DISPATCH(); + } #pragma endregion } #if ARK_USE_COMPUTED_GOTOS From ba2705da12acf2542ecd25d77077c12f02fa18b3 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 17:48:07 +0100 Subject: [PATCH 2/7] feat(ci): increase AFL MAP SIZE --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 943d2172..5b02c208 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -292,7 +292,7 @@ jobs: FUZZER_TIMEOUT_EXEC_MS: 500 AFL_NO_STARTUP_CALIBRATION: 1 AFL_CMPLOG_ONLY_NEW: 1 - AFL_MAP_SIZE: 223723 + AFL_MAP_SIZE: 312000 volumes: - ${{ github.workspace }}:/src options: --cpus 4 From 9058c26dc02f186de14935145278cbc64804ce3a Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 18:06:05 +0100 Subject: [PATCH 3/7] chore(tests, docs): adding tests for fused math ops and documentation the new super instructions --- CHANGELOG.md | 1 + include/Ark/Compiler/Instructions.hpp | 11 + src/arkreactor/VM/VM.cpp | 19 +- .../optimized_ir/fused_math_ops.ark | 90 ++++ .../optimized_ir/fused_math_ops.expected | 394 ++++++++++++++++++ ...fused_math_sub_add_mul_num_num_num_str.ark | 6 + ..._math_sub_add_mul_num_num_num_str.expected | 16 + .../fused_math_sub_add_num_num_str.ark | 5 + .../fused_math_sub_add_num_num_str.expected | 16 + .../fused_math_sub_add_str_str_num.ark | 5 + .../fused_math_sub_add_str_str_num.expected | 16 + 11 files changed, 576 insertions(+), 3 deletions(-) create mode 100644 tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.ark create mode 100644 tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.ark create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.expected create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.ark create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.expected create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.ark create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.expected diff --git a/CHANGELOG.md b/CHANGELOG.md index d86111d9..86d5efd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - the repl prints the output of the last expression it ran - new super instructions: `MUL_BY`, `MUL_BY_INDEX`, `MUL_SET_VAL` that can do multiplications (and optional storing in vars) in place +- new super instruction: `FUSED_MATH`, which can fuse 2 to 3 math operations in one go (ADD, SUB, MUL, DIV) ### Fixed - the REPL doesn't color `import` in two colors (red for `imp__t` and blue for `___or_`), it keeps the first color that matched (red for import here) diff --git a/include/Ark/Compiler/Instructions.hpp b/include/Ark/Compiler/Instructions.hpp index 66775b73..346feba1 100644 --- a/include/Ark/Compiler/Instructions.hpp +++ b/include/Ark/Compiler/Instructions.hpp @@ -429,9 +429,20 @@ namespace Ark::internal // @role Compute the length of a symbol (list or string), and pop TS to compare it, then jump if false LT_LEN_SYM_JUMP_IF_FALSE = 0x6b, + // @args symbol id, offset number + // @role Multiply the symbol by (offset symbol - 2048), then push it to the stack MUL_BY = 0x6c, + + // @args symbol index, offset number + // @role Multiply the symbol by (offset symbol - 2048), then push it to the stack MUL_BY_INDEX = 0x6d, + + // @args symbol id, offset number + // @role Multiply the symbol by (offset symbol - 2048), then store the result using the given symbol id MUL_SET_VAL = 0x6e, + + // @args op1, op2, op3 + // @role Pop 3 or 4 values from the stack, and apply the ops sequentially (only ADD, SUB, MUL, and DIV are supported). Push the result to the stack. Only op3 may be NOP. FUSED_MATH = 0x6f, InstructionsCount diff --git a/src/arkreactor/VM/VM.cpp b/src/arkreactor/VM/VM.cpp index 76e634e8..a7119f29 100644 --- a/src/arkreactor/VM/VM.cpp +++ b/src/arkreactor/VM/VM.cpp @@ -126,6 +126,19 @@ namespace Ark return a; } + + inline std::string mathInstToStr(const Instruction op) + { + if (op == ADD) + return "+"; + if (op == SUB) + return "-"; + if (op == MUL) + return "*"; + if (op == DIV) + return "/"; + return "???"; + } } VM::VM(State& state) noexcept : @@ -2084,14 +2097,14 @@ namespace Ark if (d->valueType() != ValueType::Number || c->valueType() != ValueType::Number) throw types::TypeCheckingError( - InstructionNames[op1], + helper::mathInstToStr(op1), { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, { *c, *d }); double temp = helper::doMath(c->number(), d->number(), op1); if (b->valueType() != ValueType::Number) throw types::TypeCheckingError( - InstructionNames[op2], + helper::mathInstToStr(op2), { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, { *b, Value(temp) }); temp = helper::doMath(b->number(), temp, op2); @@ -2103,7 +2116,7 @@ namespace Ark const Value* a = popAndResolveAsPtr(context); if (a->valueType() != ValueType::Number) throw types::TypeCheckingError( - InstructionNames[op3], + helper::mathInstToStr(op3), { { types::Contract { { types::Typedef("a", ValueType::Number), types::Typedef("b", ValueType::Number) } } } }, { *a, Value(temp) }); diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.ark b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.ark new file mode 100644 index 00000000..b288ca91 --- /dev/null +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.ark @@ -0,0 +1,90 @@ +(let a 2) +(let b 3) +(let c 4) +(let d 5) + +(print [ + (+ a (+ b c)) + (+ a (* b c)) + (+ a (- b c)) + (+ a (/ b c)) + (- a (+ b c)) + (- a (* b c)) + (- a (- b c)) + (- a (/ b c)) + (* a (+ b c)) + (* a (* b c)) + (* a (- b c)) + (* a (/ b c)) + (/ a (+ b c)) + (/ a (* b c)) + (/ a (- b c)) + (/ a (/ b c)) + + (+ a (+ b (+ c d))) + (+ a (* b (+ c d))) + (+ a (- b (+ c d))) + (+ a (/ b (+ c d))) + (- a (+ b (+ c d))) + (- a (* b (+ c d))) + (- a (- b (+ c d))) + (- a (/ b (+ c d))) + (* a (+ b (+ c d))) + (* a (* b (+ c d))) + (* a (- b (+ c d))) + (* a (/ b (+ c d))) + (/ a (+ b (+ c d))) + (/ a (* b (+ c d))) + (/ a (- b (+ c d))) + (/ a (/ b (+ c d))) + + (+ a (+ b (- c d))) + (+ a (* b (- c d))) + (+ a (- b (- c d))) + (+ a (/ b (- c d))) + (- a (+ b (- c d))) + (- a (* b (- c d))) + (- a (- b (- c d))) + (- a (/ b (- c d))) + (* a (+ b (- c d))) + (* a (* b (- c d))) + (* a (- b (- c d))) + (* a (/ b (- c d))) + (/ a (+ b (- c d))) + (/ a (* b (- c d))) + (/ a (- b (- c d))) + (/ a (/ b (- c d))) + + (+ a (+ b (* c d))) + (+ a (* b (* c d))) + (+ a (- b (* c d))) + (+ a (/ b (* c d))) + (- a (+ b (* c d))) + (- a (* b (* c d))) + (- a (- b (* c d))) + (- a (/ b (* c d))) + (* a (+ b (* c d))) + (* a (* b (* c d))) + (* a (- b (* c d))) + (* a (/ b (* c d))) + (/ a (+ b (* c d))) + (/ a (* b (* c d))) + (/ a (- b (* c d))) + (/ a (/ b (* c d))) + + (+ a (+ b (/ c d))) + (+ a (* b (/ c d))) + (+ a (- b (/ c d))) + (+ a (/ b (/ c d))) + (- a (+ b (/ c d))) + (- a (* b (/ c d))) + (- a (- b (/ c d))) + (- a (/ b (/ c d))) + (* a (+ b (/ c d))) + (* a (* b (/ c d))) + (* a (- b (/ c d))) + (* a (/ b (/ c d))) + (/ a (+ b (/ c d))) + (/ a (* b (/ c d))) + (/ a (- b (/ c d))) + (/ a (/ b (/ c d))) ]) diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected new file mode 100644 index 00000000..cb6d4141 --- /dev/null +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected @@ -0,0 +1,394 @@ +page_0 + LOAD_CONST_STORE 0, 0 + LOAD_CONST_STORE 1, 1 + LOAD_CONST_STORE 2, 2 + LOAD_CONST_STORE 3, 3 + PUSH_RETURN_ADDRESS L0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 40, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 38, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 39, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 37, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 40, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 38, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 39, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 37, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 40, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 38, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 39, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 37, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 40, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 38, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 39, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 40, 37, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 40, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 38, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 39, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 37, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 40, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 38, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 39, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 37, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 40, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 38, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 39, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 37, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 40, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 38, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 39, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 39, 37, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 40, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 38, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 39, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 37, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 40, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 38, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 39, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 37, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 40, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 38, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 39, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 37, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 40, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 38, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 39, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 38, 37, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 40, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 38, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 39, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 37, 40 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 40, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 38, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 39, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 37, 39 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 40, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 38, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 39, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 37, 38 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 40, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 38, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 39, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + LOAD_SYMBOL_BY_INDEX 0 + FUSED_MATH 37, 37, 37 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 40, 40, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 38, 40, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 39, 40, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 37, 40, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 40, 39, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 38, 39, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 39, 39, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 37, 39, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 40, 38, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 38, 38, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 39, 38, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 37, 38, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 40, 37, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 38, 37, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 39, 37, 0 + LOAD_SYMBOL_BY_INDEX 3 + LOAD_SYMBOL_BY_INDEX 2 + LOAD_SYMBOL_BY_INDEX 1 + FUSED_MATH 37, 37, 0 + LIST 80 + CALL_BUILTIN 9, 1 +.L0: + HALT 0 diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.ark new file mode 100644 index 00000000..d098ff85 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.ark @@ -0,0 +1,6 @@ +(let a "1") +(let b 2) +(let c 3) +(let d 4) + +(print (* a (+ b (- c d)))) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.expected new file mode 100644 index 00000000..7eb602ac --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.expected @@ -0,0 +1,16 @@ +Function * expected 2 arguments +Call + ↳ (* 1 1) +Signature + ↳ (* a b) +Arguments + → `a' (expected Number), got 1 (String) + → `b' (expected Number) ✓ + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_mul_num_num_num_str.ark:6 + 3 | (let c 3) + 4 | (let d 4) + 5 | + 6 | (print (* a (+ b (- c d)))) + | ^~~~~~~~~~~~~~~~~~~~~~~~~~ + 7 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.ark new file mode 100644 index 00000000..c5a0b9d2 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.ark @@ -0,0 +1,5 @@ +(let a "1") +(let b 2) +(let c 3) + +(print (+ a (- b c))) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.expected new file mode 100644 index 00000000..b00be97b --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.expected @@ -0,0 +1,16 @@ +Function + expected 2 arguments +Call + ↳ (+ 1 -1) +Signature + ↳ (+ a b) +Arguments + → `a' (expected Number), got 1 (String) + → `b' (expected Number) ✓ + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_num_num_str.ark:5 + 2 | (let b 2) + 3 | (let c 3) + 4 | + 5 | (print (+ a (- b c))) + | ^~~~~~~~~~~~~~~~~~~~ + 6 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.ark new file mode 100644 index 00000000..e4ba92aa --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.ark @@ -0,0 +1,5 @@ +(let a 1) +(let b "2") +(let c "3") + +(print (+ a (- b c))) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.expected new file mode 100644 index 00000000..4059e048 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.expected @@ -0,0 +1,16 @@ +Function - expected 2 arguments +Call + ↳ (- 2 3) +Signature + ↳ (- a b) +Arguments + → `a' (expected Number), got 2 (String) + → `b' (expected Number), got 3 (String) + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_sub_add_str_str_num.ark:5 + 2 | (let b "2") + 3 | (let c "3") + 4 | + 5 | (print (+ a (- b c))) + | ^~~~~~~~~~~~~~~~~~~~ + 6 | From 8bd0fca1a23b1accc4be66f80881e9dd0d07d3d2 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 18:19:18 +0100 Subject: [PATCH 4/7] feat(parser): preventing the user from trying to use 'ref' as a function --- src/arkreactor/Compiler/AST/Parser.cpp | 3 +++ .../resources/ParserSuite/failure/ref_as_func_call.ark | 2 ++ .../resources/ParserSuite/failure/ref_as_func_call.expected | 6 ++++++ 3 files changed, 11 insertions(+) create mode 100644 tests/unittests/resources/ParserSuite/failure/ref_as_func_call.ark create mode 100644 tests/unittests/resources/ParserSuite/failure/ref_as_func_call.expected diff --git a/src/arkreactor/Compiler/AST/Parser.cpp b/src/arkreactor/Compiler/AST/Parser.cpp index 570f4445..118f4318 100644 --- a/src/arkreactor/Compiler/AST/Parser.cpp +++ b/src/arkreactor/Compiler/AST/Parser.cpp @@ -766,6 +766,9 @@ namespace Ark::internal else return std::nullopt; + if (func.value().nodeType() == NodeType::Symbol && func.value().string() == "ref") + error("`ref' can not be used outside a function's arguments list.", func_name_pos); + std::optional leaf { NodeType::List }; leaf->push_back(positioned(func.value(), func_name_pos)); diff --git a/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.ark b/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.ark new file mode 100644 index 00000000..d4e2aede --- /dev/null +++ b/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.ark @@ -0,0 +1,2 @@ +(let a 1) +(let b (ref a)) diff --git a/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.expected b/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.expected new file mode 100644 index 00000000..18fb9079 --- /dev/null +++ b/tests/unittests/resources/ParserSuite/failure/ref_as_func_call.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/ParserSuite/failure/ref_as_func_call.ark:2 + 1 | (let a 1) + 2 | (let b (ref a)) + | ^~~ + 3 | + `ref' can not be used outside a function's arguments list. From 0937dc400ffb60e95cc33533d03bcafa406d6483 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 18:22:12 +0100 Subject: [PATCH 5/7] chore(tests): adding a small test calling 'disassemble' builtin, so that the bytecode reader is somewhat covered by tests --- tests/unittests/resources/LangSuite/builtins-tests.ark | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/unittests/resources/LangSuite/builtins-tests.ark b/tests/unittests/resources/LangSuite/builtins-tests.ark index 78189068..342f6ca0 100644 --- a/tests/unittests/resources/LangSuite/builtins-tests.ark +++ b/tests/unittests/resources/LangSuite/builtins-tests.ark @@ -1,6 +1,9 @@ (import std.Testing) (import std.List) +(let foo (fun ((mut a) (ref b) c) + (+ a (* b c)))) + (test:suite builtin { (test:case "time" { (let old (time)) @@ -18,4 +21,7 @@ "should not find any number outside the given range") (let r (random)) - (test:expect (and (<= r 2147483647) (>= r -2147483648))) })}) + (test:expect (and (<= r 2147483647) (>= r -2147483648))) }) + + (test:case "disassemble" { + (disassemble foo) }) }) From 8ee83924cf8bbd54568feaea3ef3fedcddaadc98 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 18:26:08 +0100 Subject: [PATCH 6/7] chore(tests): adding failure tests for DIV in fused math ops --- .../fused_math_add_div_num_num_0.ark | 5 +++++ .../fused_math_add_div_num_num_0.expected | 9 +++++++++ .../fused_math_add_div_num_num_str.ark | 5 +++++ .../fused_math_add_div_num_num_str.expected | 16 ++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.ark create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.expected create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.ark create mode 100644 tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.expected diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.ark new file mode 100644 index 00000000..f95d0547 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.ark @@ -0,0 +1,5 @@ +(let a 1) +(let b -3) +(let c 3) + +(print (/ a (+ b c))) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.expected new file mode 100644 index 00000000..541b495a --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.expected @@ -0,0 +1,9 @@ +DivisionByZero: Can not compute expression (/ 1 0) + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_0.ark:5 + 2 | (let b -3) + 3 | (let c 3) + 4 | + 5 | (print (/ a (+ b c))) + | ^~~~~~~~~~~~~~~~~~~~ + 6 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.ark new file mode 100644 index 00000000..a8237234 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.ark @@ -0,0 +1,5 @@ +(let a "1") +(let b 2) +(let c 3) + +(print (/ a (+ b c))) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.expected new file mode 100644 index 00000000..16c08cdd --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.expected @@ -0,0 +1,16 @@ +Function / expected 2 arguments +Call + ↳ (/ 1 5) +Signature + ↳ (/ a b) +Arguments + → `a' (expected Number), got 1 (String) + → `b' (expected Number) ✓ + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/fused_math_add_div_num_num_str.ark:5 + 2 | (let b 2) + 3 | (let c 3) + 4 | + 5 | (print (/ a (+ b c))) + | ^~~~~~~~~~~~~~~~~~~~ + 6 | From 7c2dd3487c5a63c29085c4ce8a622a0a896931aa Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Fri, 19 Dec 2025 18:32:06 +0100 Subject: [PATCH 7/7] chore: addressing cppcheck recommandations --- src/arkreactor/VM/VM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arkreactor/VM/VM.cpp b/src/arkreactor/VM/VM.cpp index a7119f29..1821bf04 100644 --- a/src/arkreactor/VM/VM.cpp +++ b/src/arkreactor/VM/VM.cpp @@ -745,7 +745,7 @@ namespace Ark { // Not resolving a potential ref is on purpose! // This instruction is only used by functions when storing arguments - Value* tmp = pop(context); + const Value* tmp = pop(context); store(arg, tmp, context); DISPATCH(); }