diff --git a/.gitignore b/.gitignore index 64b023b..59544c6 100644 --- a/.gitignore +++ b/.gitignore @@ -77,5 +77,6 @@ __pycache__/ .DS_Store # Test artifacts (generated in build directory, but ignore strays) +tests/baselines/**/*.bytecode tests/reports/*.json tests/outputs/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e06367..430a062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,10 +206,10 @@ if(PROJECT_IS_TOP_LEVEL) ) # Custom target: Generate/update baselines - add_custom_target(test-baselines + add_custom_target(update-test-baselines COMMAND ${TEST_RUNNER_CMD} --update-baselines WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Generating test baselines" + COMMENT "Updating test baselines" DEPENDS gs2test ) @@ -243,7 +243,7 @@ if(PROJECT_IS_TOP_LEVEL) message(STATUS " Reports in: ${CMAKE_BINARY_DIR}/tests/reports") message(STATUS " Available targets:") message(STATUS " run-tests - Run test suite with verbose output") - message(STATUS " test-baselines - Generate/update baseline bytecode") + message(STATUS " update-test-baselines - Generate/update baseline bytecode") message(STATUS " test-clean - Clean test artifacts") message(STATUS " test or ctest - Run tests (quiet, for CI/CD)") diff --git a/src/ast/ast.h b/src/ast/ast.h index 9d539af..a23242d 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -253,7 +253,6 @@ class ExpressionArrayIndexNode : public ExpressionNode if (list) { exprList = std::move(*list); - delete list; } for (const auto& expr : exprList) @@ -499,17 +498,17 @@ class ExpressionUnaryOpNode : public ExpressionNode return expr->toString() + std::string(ExpressionOpToString(op)); } - virtual ExpressionType expressionType() const + ExpressionType expressionType() const override { switch (op) { case ExpressionOp::UnaryMinus: case ExpressionOp::UnaryNot: return ExpressionType::EXPR_NUMBER; + default: + return expr->expressionType(); } - - return expr->expressionType(); - } + } }; class ExpressionFnCallNode : public ExpressionNode @@ -523,7 +522,6 @@ class ExpressionFnCallNode : public ExpressionNode if (argList) { args = std::move(*argList); - delete argList; } takeOwnership(funcExpr, objExpr); @@ -566,7 +564,6 @@ class ExpressionNewArrayNode : public ExpressionNode if (dim) { dimensions = std::move(*dim); - delete dim; } } @@ -596,7 +593,6 @@ class ExpressionNewObjectNode : public ExpressionNode if (argList) { args = std::move(*argList); - delete argList; } takeOwnership(newExpr); @@ -628,7 +624,6 @@ class ExpressionListNode : public ExpressionNode if (argList) { args = std::move(*argList); - delete argList; } for (const auto& node : args) @@ -701,7 +696,6 @@ class StatementFnDeclNode : public StatementNode if (argList) { args = std::move(*argList); - delete argList; } takeOwnership(stmtBlock); @@ -731,7 +725,6 @@ class StatementNewNode : public StatementNode if (argList) { args = std::move(*argList); - delete argList; } takeOwnership(stmtBlock); @@ -899,7 +892,6 @@ class StatementSwitchNode : public StatementNode if (caseNodes) { cases = std::move(*caseNodes); - delete caseNodes; } takeOwnership(expr); @@ -943,11 +935,7 @@ class EnumList addMember(member); } - ~EnumList() - { - for (const auto& n : members) - delete n; - } + ~EnumList() = default; void addMember(EnumMember *member); diff --git a/src/codegen/GS2Bytecode.cpp b/src/codegen/GS2Bytecode.cpp index 471b4ca..b530e0d 100644 --- a/src/codegen/GS2Bytecode.cpp +++ b/src/codegen/GS2Bytecode.cpp @@ -28,15 +28,6 @@ int32_t GS2Bytecode::getStringConst(const std::string& str) Buffer GS2Bytecode::getByteCode() { - // This fixes a weird bug in which the last function was uncallable, - // i am unsure if this is a bug with our specific client or something - // weird is happening during compilation that is causing the issue. - // I've used identical bytecode as per the decompiler, and still - // ran into this issue so I believe its a client issue. - // Either way, emitting this op seems to fix it. *shrugs* - // - joey - emit(opcode::OP_RET); - Buffer byteCode; // GS1EventFlags @@ -93,12 +84,6 @@ Buffer GS2Bytecode::getByteCode() functionTableBuffer.Write(func.opIndex); functionTableBuffer.write(func.functionName.c_str(), func.functionName.length()); functionTableBuffer.write('\0'); - - // emit a jump before the function declaration to the last op index - if (func.jmpLoc != 0) - { - emit(short(opIndex), func.jmpLoc - 2); - } } } @@ -130,7 +115,7 @@ Buffer GS2Bytecode::getByteCode() return byteCode; } -void GS2Bytecode::addFunction(std::string functionName, uint32_t opIdx, size_t jmpLoc) +void GS2Bytecode::addFunction(std::string functionName, uint32_t opIdx) { auto ret = functionSet.insert(functionName); @@ -138,8 +123,7 @@ void GS2Bytecode::addFunction(std::string functionName, uint32_t opIdx, size_t j { functionTable.push_back(FunctionEntry{ std::move(functionName), - opIdx, - jmpLoc + opIdx }); } else diff --git a/src/codegen/GS2Bytecode.h b/src/codegen/GS2Bytecode.h index 5caad07..447cf15 100644 --- a/src/codegen/GS2Bytecode.h +++ b/src/codegen/GS2Bytecode.h @@ -17,12 +17,12 @@ struct FunctionEntry { std::string functionName; uint32_t opIndex; - size_t jmpLoc; }; class GS2Bytecode { friend class GS2CompilerVisitor; + friend class JumpTarget; private: GS2Bytecode() : opIndex(0), lastOp(opcode::Opcode::OP_NONE) {} @@ -30,7 +30,7 @@ class GS2Bytecode Buffer getByteCode(); int32_t getStringConst(const std::string& str); - void addFunction(std::string functionName, uint32_t opIdx, size_t jmpLoc); + void addFunction(std::string functionName, uint32_t opIdx); /* * Functions to emit bytecode into the underlying buffer diff --git a/src/compiler/GS2BuiltInFunctions.cpp b/src/compiler/GS2BuiltInFunctions.cpp index e80ec26..3179b38 100644 --- a/src/compiler/GS2BuiltInFunctions.cpp +++ b/src/compiler/GS2BuiltInFunctions.cpp @@ -1,3 +1,5 @@ +#include +#include #include "GS2BuiltInFunctions.h" // Signature characters: [return][...params] @@ -7,294 +9,298 @@ // o -> OP_CONV_TO_OBJECT // s -> OP_CONV_TO_STRING -const BuiltInCmd builtInCmds[] = { - { +template +consteval std::array sortByName(std::array arr) +{ + std::ranges::sort(arr, [](const BuiltInCmd& a, const BuiltInCmd& b) { + return a.name < b.name; + }); + return arr; +} + +static constexpr auto builtInCmds = sortByName(std::array{ + BuiltInCmd{ .name = "sleep", .op = opcode::OP_SLEEP, .flags = CMD_NOOPT, .sig = "-f", }, - { + BuiltInCmd{ .name = "sin", .op = opcode::OP_SIN, .sig = "ff" }, - { + BuiltInCmd{ .name = "char", .op = opcode::OP_CHAR, .sig = "ff" }, - { + BuiltInCmd{ .name = "cos", .op = opcode::OP_COS, .sig = "ff" }, - { + BuiltInCmd{ .name = "arctan", .op = opcode::OP_ARCTAN, .sig = "ff" }, - { + BuiltInCmd{ .name = "vecx", .op = opcode::OP_VECX, .sig = "ff" }, - { + BuiltInCmd{ .name = "vecy", .op = opcode::OP_VECY, .sig = "ff" }, - { + BuiltInCmd{ .name = "abs", .op = opcode::OP_ABS, .sig = "ff" }, - { + BuiltInCmd{ .name = "exp", .op = opcode::OP_EXP, .sig = "ff" }, - { + BuiltInCmd{ .name = "log", .op = opcode::OP_LOG, .sig = "fff" }, - { + BuiltInCmd{ .name = "min", .op = opcode::OP_MIN, .sig = "fff" }, - { + BuiltInCmd{ .name = "max", .op = opcode::OP_MAX, .sig = "fff" }, - { + BuiltInCmd{ .name = "pow", .op = opcode::OP_POW, .flags = CMD_RETURN_VALUE, .sig = "fff" }, - { + BuiltInCmd{ .name = "random", .op = opcode::OP_RANDOM, .sig = "fff" }, - { + BuiltInCmd{ .name = "arraylen", .op = opcode::OP_OBJ_SIZE, .sig = "fo" }, - { + BuiltInCmd{ .name = "sarraylen", .op = opcode::OP_OBJ_SIZE, .sig = "fo" }, - { + BuiltInCmd{ .name = "setarray", .op = opcode::OP_SETARRAY, .flags = CmdFlags::CMD_NOOPT, .sig = "-of" }, - { + BuiltInCmd{ .name = "getangle", .op = opcode::OP_GETANGLE, .flags = CMD_RETURN_VALUE, .sig = "fff" }, - { + BuiltInCmd{ .name = "getdir", .op = opcode::OP_GETDIR, .flags = CMD_RETURN_VALUE, .sig = "fff" }, - { + BuiltInCmd{ .name = "waitfor", .op = opcode::OP_WAITFOR, .flags = CMD_RETURN_VALUE, .sig = "xssf" }, - { + BuiltInCmd{ .name = "format", .op = opcode::OP_FORMAT, .flags = CMD_USE_ARRAY | CMD_REVERSE_ARGS | CMD_RETURN_VALUE, .sig = "xs" }, - { + BuiltInCmd{ .name = "makevar", .op = opcode::OP_MAKEVAR, .convert_object_op = opcode::OP_CONV_TO_STRING, .sig = "s" } -}; +}); -const BuiltInCmd builtInObjCmds[] = { - { +static constexpr auto builtInObjCmds = sortByName(std::array{ + BuiltInCmd{ .name = "index", .op = opcode::OP_OBJ_INDEX, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, .sig = "fx" }, - - { + BuiltInCmd{ .name = "type", .op = opcode::OP_OBJ_TYPE, .convert_object_op = opcode::OP_CONV_TO_OBJECT }, - - { + BuiltInCmd{ .name = "indices", .op = opcode::OP_OBJ_INDICES }, - - { + BuiltInCmd{ .name = "link", .op = opcode::OP_OBJ_LINK }, - - { + BuiltInCmd{ .name = "trim", .op = opcode::OP_OBJ_TRIM, .convert_object_op = opcode::OP_CONV_TO_STRING }, - - { + BuiltInCmd{ .name = "length", .op = opcode::OP_OBJ_LENGTH, .convert_object_op = opcode::OP_CONV_TO_STRING }, - - { + BuiltInCmd{ .name = "pos", .op = opcode::OP_OBJ_POS, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, .sig = "fs" }, - - { + BuiltInCmd{ .name = "charat", .op = opcode::OP_OBJ_CHARAT, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, .sig = "sf" }, - - { + BuiltInCmd{ .name = "substring", .op = opcode::OP_OBJ_SUBSTR, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, .sig = "sff" }, - - { + BuiltInCmd{ .name = "starts", .op = opcode::OP_OBJ_STARTS, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, }, - - { + BuiltInCmd{ .name = "ends", .op = opcode::OP_OBJ_ENDS, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, }, - - { + BuiltInCmd{ .name = "tokenize", .op = opcode::OP_OBJ_TOKENIZE, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, }, - - { + BuiltInCmd{ .name = "positions", .op = opcode::OP_OBJ_POSITIONS, .convert_object_op = opcode::OP_CONV_TO_STRING, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_RETURN_VALUE, .sig = "os" }, - - { + BuiltInCmd{ .name = "size", .op = opcode::OP_OBJ_SIZE, .convert_object_op = opcode::OP_CONV_TO_OBJECT }, - { + BuiltInCmd{ .name = "subarray", .op = opcode::OP_OBJ_SUBARRAY }, - { + BuiltInCmd{ .name = "clear", .op = opcode::OP_OBJ_CLEAR, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_NOOPT, }, - { + BuiltInCmd{ .name = "add", .op = opcode::OP_OBJ_ADDSTRING, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST, }, - { + BuiltInCmd{ .name = "delete", .op = opcode::OP_OBJ_DELETESTRING, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST, }, - { + BuiltInCmd{ .name = "insert", .op = opcode::OP_OBJ_INSERTSTRING, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_REVERSE_ARGS, }, - { + BuiltInCmd{ .name = "remove", .op = opcode::OP_OBJ_REMOVESTRING, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_REVERSE_ARGS, }, - { + BuiltInCmd{ .name = "replace", .op = opcode::OP_OBJ_REPLACESTRING, .convert_object_op = opcode::OP_CONV_TO_OBJECT, .flags = CmdFlags::CMD_OBJECT_FIRST | CmdFlags::CMD_REVERSE_ARGS, }, -}; +}); -GS2BuiltInFunctions GS2BuiltInFunctions::getBuiltIn() +template +constexpr const BuiltInCmd* findIn(const std::array& table, std::string_view name) { - GS2BuiltInFunctions functions; + auto it = std::ranges::lower_bound(table, name, std::less<>{}, &BuiltInCmd::name); - for (const auto& cmd : builtInCmds) - functions.builtInCmdMap.insert({ cmd.name, cmd }); + if (it != table.end() && it->name == name) + return &*it; - for (const auto& cmd : builtInObjCmds) - functions.builtInObjMap.insert({ cmd.name, cmd }); + return nullptr; +} - return functions; +const BuiltInCmd* findBuiltInCmd(std::string_view name) +{ + return findIn(builtInCmds, name); +} + +const BuiltInCmd* findBuiltInObjCmd(std::string_view name) +{ + return findIn(builtInObjCmds, name); } diff --git a/src/compiler/GS2BuiltInFunctions.h b/src/compiler/GS2BuiltInFunctions.h index 02fdee8..7d17aa1 100644 --- a/src/compiler/GS2BuiltInFunctions.h +++ b/src/compiler/GS2BuiltInFunctions.h @@ -3,9 +3,8 @@ #ifndef GS2BUILTINFUNCTIONS_H #define GS2BUILTINFUNCTIONS_H -#include +#include #include -#include #include "opcodes.h" enum CmdFlags @@ -17,62 +16,33 @@ enum CmdFlags CMD_OBJECT_FIRST = uint8_t(1 << 3) // Visit the object before you visit arguments (needed for setarray) }; -const uint8_t DEFAULT_CMD_FLAGS = CMD_USE_ARRAY | CMD_REVERSE_ARGS | CMD_RETURN_VALUE; -const uint8_t DEFAULT_OBJ_CMD_FLAGS = CMD_USE_ARRAY | CMD_REVERSE_ARGS | CMD_RETURN_VALUE; +constexpr uint8_t DEFAULT_CMD_FLAGS = CMD_USE_ARRAY | CMD_REVERSE_ARGS | CMD_RETURN_VALUE; +constexpr uint8_t DEFAULT_OBJ_CMD_FLAGS = CMD_USE_ARRAY | CMD_REVERSE_ARGS | CMD_RETURN_VALUE; struct BuiltInCmd { - std::string name; // Function Name + std::string_view name; // Function Name opcode::Opcode op; // Op-code for built in command, or OP_CALL opcode::Opcode convert_object_op{ opcode::OP_NONE }; // Convert object to this type [used for object.call() functions] uint8_t flags = (CMD_REVERSE_ARGS | CMD_RETURN_VALUE); // See above for cmd options - std::string sig; + std::string_view sig; }; -const BuiltInCmd defaultCall = { +constexpr BuiltInCmd defaultCall = { "", opcode::OP_CALL, opcode::OP_NONE, DEFAULT_CMD_FLAGS }; -const BuiltInCmd defaultObjCall = { +constexpr BuiltInCmd defaultObjCall = { "", opcode::OP_CALL, opcode::OP_CONV_TO_OBJECT, DEFAULT_OBJ_CMD_FLAGS }; -struct GS2BuiltInFunctions -{ - std::unordered_map builtInCmdMap; - std::unordered_map builtInObjMap; - - GS2BuiltInFunctions() { } - - GS2BuiltInFunctions(GS2BuiltInFunctions&& o) noexcept; - GS2BuiltInFunctions(const GS2BuiltInFunctions&) = delete; - - GS2BuiltInFunctions& operator= (GS2BuiltInFunctions&& o) noexcept; - GS2BuiltInFunctions& operator= (const GS2BuiltInFunctions&) = delete; - - static GS2BuiltInFunctions getBuiltIn(); -}; - -inline GS2BuiltInFunctions& GS2BuiltInFunctions::operator=(GS2BuiltInFunctions&& o) noexcept -{ - if (this != &o) - { - builtInCmdMap = std::move(o.builtInCmdMap); - builtInObjMap = std::move(o.builtInObjMap); - } - - return *this; -} - -inline GS2BuiltInFunctions::GS2BuiltInFunctions(GS2BuiltInFunctions&& o) noexcept -{ - *this = std::move(o); -} +const BuiltInCmd* findBuiltInCmd(std::string_view name); +const BuiltInCmd* findBuiltInObjCmd(std::string_view name); #endif diff --git a/src/compiler/GS2CompilerVisitor.cpp b/src/compiler/GS2CompilerVisitor.cpp index 8e5436b..1ddf19e 100644 --- a/src/compiler/GS2CompilerVisitor.cpp +++ b/src/compiler/GS2CompilerVisitor.cpp @@ -1,10 +1,10 @@ #include #include -#include #include "ast/ast.h" #include "visitors/FunctionInspectVisitor.h" #include "compiler/GS2CompilerVisitor.h" +#include "compiler/GS2BuiltInFunctions.h" #include "parser/Parser.h" opcode::Opcode getExpressionOpCode(ExpressionOp op) @@ -49,39 +49,9 @@ opcode::Opcode getExpressionOpCode(ExpressionOp op) } } -GS2CompilerVisitor::GS2CompilerVisitor(ParserContext & context, GS2BuiltInFunctions & builtin) - : parserContext(context), builtIn(builtin), - _isCopyAssignment(false), _isInlineConditional(true), _isInsideExpression(false), _newObjectCount(0) +GS2CompilerVisitor::GS2CompilerVisitor(ParserContext & context) + : parserContext(context) { - fail_label = success_label = exit_label = createLabel(); - break_label = continue_label = 0; -} - -GS2CompilerVisitor::label_id GS2CompilerVisitor::createLabel() -{ - static label_id counter = 0; - auto id = ++counter; - return id; -} - -void GS2CompilerVisitor::writeLabels() -{ - for (const auto& [label, locs] : label_locs) - { - if (label == exit_label) - continue; - - auto label_iter = label_addr.find(label); - if (label_iter != label_addr.end()) - { - auto write_addr = label_iter->second; - - for (const auto& loc : locs) - { - byteCode.emit(short(write_addr), loc); - } - } - } } void GS2CompilerVisitor::Visit(Node *node) @@ -101,11 +71,48 @@ void GS2CompilerVisitor::Visit(Node *node) void GS2CompilerVisitor::Visit(StatementBlock *node) { - for (const auto& n : node->statements) + if (!_isRootBlock) + { + for (const auto& n : node->statements) + { + assert(n != nullptr); + n->visit(this); + } + return; + } + + _isRootBlock = false; + JumpTarget fnSkip(byteCode); + fn_skip_target = &fnSkip; + + for (const auto& n : node->statements) { assert(n != nullptr); + + size_t pendingBefore = fnSkip.pendingCount(); + auto opIndexBefore = byteCode.getOpIndex(); + n->visit(this); + + bool addedPrejump = (fnSkip.pendingCount() > pendingBefore); + + if (!addedPrejump && fnSkip.pendingCount() > 0) + { + fnSkip.resolve(opIndexBefore); + fnSkip.reset(); + } } + + // Trailing OP_RET fixes a weird bug in which the last function was + // uncallable on certain clients. Emitted here (before resolving the + // final function-skip group) so that the pre-jump lands after it, + // matching the legacy target address. - joey + byteCode.emit(opcode::OP_RET); + + if (fnSkip.pendingCount() > 0) + fnSkip.resolveHere(); + + fn_skip_target = nullptr; } void GS2CompilerVisitor::Visit(StatementFnDeclNode *node) @@ -114,14 +121,9 @@ void GS2CompilerVisitor::Visit(StatementFnDeclNode *node) printf("Declare function: %s\n", node->ident->c_str()); #endif - size_t jmpLoc = 0; - - if (node->emit_prejump) + if (node->emit_prejump && fn_skip_target) { - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); // replaced with jump index to last opcode - jmpLoc = byteCode.getBytecodePos(); + fn_skip_target->emitJump(opcode::OP_SET_INDEX); } bool is_universe = false; @@ -148,7 +150,7 @@ void GS2CompilerVisitor::Visit(StatementFnDeclNode *node) std::swap(funcName, funcNameUni); } - byteCode.addFunction(funcName, byteCode.getOpIndex(), jmpLoc); + byteCode.addFunction(funcName, byteCode.getOpIndex()); { byteCode.emit(opcode::OP_TYPE_ARRAY); @@ -191,51 +193,43 @@ void GS2CompilerVisitor::Visit(ExpressionTernaryOpNode *node) { node->condition->visit(this); - label_id save_labels[] = { success_label, fail_label }; + ScopeGuard guard(*this); - auto new_fail_label = createLabel(); - auto new_success_label = createLabel(); + JumpTarget falseBranch(byteCode); + JumpTarget end(byteCode); { - fail_label = new_fail_label; - success_label = new_success_label; + fail_target = &falseBranch; + success_target = &end; // Convert the result of the expression to a number since this // value will be used for the following if () stmt if (!IsBooleanReturningOp(byteCode.getLastOp())) byteCode.emitConversionOp(node->condition->expressionType(), ExpressionType::EXPR_NUMBER); - byteCode.emit(opcode::OP_IF); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(new_fail_label, byteCode.getBytecodePos() - 2); + falseBranch.emitJump(opcode::OP_IF); node->leftExpr->visit(this); // set the continue position to the right-hand expression, skipping // over the jump on the left-hand expression - setLocation(new_fail_label, byteCode.getOpIndex() + 1); + falseBranch.resolve(byteCode.getOpIndex() + 1); } // emit a jump to the end of this else block for the previous if-block - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(new_success_label, byteCode.getBytecodePos() - 2); + end.emitJump(opcode::OP_SET_INDEX); node->rightExpr->visit(this); - setLocation(new_success_label, byteCode.getOpIndex()); - - success_label = save_labels[0]; - fail_label = save_labels[1]; + end.resolveHere(); } void GS2CompilerVisitor::Visit(ExpressionBinaryOpNode *node) { if (node->op == ExpressionOp::LogicalAnd || node->op == ExpressionOp::LogicalOr) { - label_id save_labels[] = { fail_label, success_label }; + ScopeGuard guard(*this); + JumpTarget inlineTarget(byteCode); bool isFirstBinaryExpr = !_isInsideExpression; if (isFirstBinaryExpr) { @@ -244,60 +238,49 @@ void GS2CompilerVisitor::Visit(ExpressionBinaryOpNode *node) // If its a conditional expression we need to create new jump labels which leads // to OP_INLINE_CONDITIONAL emitted at the end of the first binary expression if (_isInlineConditional) - success_label = fail_label = createLabel(); + { + success_target = &inlineTarget; + fail_target = &inlineTarget; + } } - auto tmp_success_label = success_label; - auto tmp_fail_label = fail_label; + auto* tmp_success = success_target; + auto* tmp_fail = fail_target; bool is_inline_cond = _isInlineConditional; if (node->op == ExpressionOp::LogicalAnd) { - auto new_success_label = createLabel(); - success_label = new_success_label; + JumpTarget afterLhs(byteCode); + success_target = &afterLhs; node->left->visit(this); byteCode.emitConversionOp(node->left->expressionType(), ExpressionType::EXPR_NUMBER); - setLocation(new_success_label, byteCode.getOpIndex()); - success_label = tmp_success_label; - fail_label = tmp_fail_label; + afterLhs.resolveHere(); + success_target = tmp_success; + fail_target = tmp_fail; if (is_inline_cond) - { - byteCode.emit(opcode::OP_AND); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(fail_label, byteCode.getBytecodePos() - 2); - } + fail_target->emitJump(opcode::OP_AND); else - { - byteCode.emit(opcode::OP_IF); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(fail_label, byteCode.getBytecodePos() - 2); - } + fail_target->emitJump(opcode::OP_IF); node->right->visit(this); byteCode.emitConversionOp(node->right->expressionType(), ExpressionType::EXPR_NUMBER); } else if (node->op == ExpressionOp::LogicalOr) { - auto new_fail_label = createLabel(); - fail_label = new_fail_label; + JumpTarget afterLhs(byteCode); + fail_target = &afterLhs; node->left->visit(this); byteCode.emitConversionOp(node->left->expressionType(), ExpressionType::EXPR_NUMBER); - byteCode.emit(opcode::OP_OR); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(success_label, byteCode.getBytecodePos() - 2); + success_target->emitJump(opcode::OP_OR); - setLocation(new_fail_label, byteCode.getOpIndex()); - auto success_label_copy = success_label; - success_label = tmp_success_label; - fail_label = tmp_fail_label; + afterLhs.resolveHere(); + success_target = tmp_success; + fail_target = tmp_fail; node->right->visit(this); byteCode.emitConversionOp(node->right->expressionType(), ExpressionType::EXPR_NUMBER); @@ -305,19 +288,13 @@ void GS2CompilerVisitor::Visit(ExpressionBinaryOpNode *node) if (isFirstBinaryExpr) { - setLocation(tmp_success_label, byteCode.getOpIndex()); - - fail_label = save_labels[0]; - success_label = save_labels[1]; _isInsideExpression = false; if (is_inline_cond) + { + inlineTarget.resolveHere(); byteCode.emit(opcode::Opcode::OP_INLINE_CONDITIONAL); - } - else - { - success_label = tmp_success_label; - fail_label = tmp_fail_label; + } } return; @@ -498,16 +475,17 @@ void GS2CompilerVisitor::Visit(ExpressionUnaryOpNode* node) } auto temp_inlinecond = _isInlineConditional; - label_id save_labels[] = { success_label, fail_label, 0 }; + ScopeGuard guard(*this); + JumpTarget inlineTarget(byteCode); bool isFirstBinaryExpr = !_isInsideExpression; if (isFirstBinaryExpr) { _isInsideExpression = true; _isInlineConditional = true; - save_labels[2] = createLabel(); - success_label = fail_label = save_labels[2]; + success_target = &inlineTarget; + fail_target = &inlineTarget; } node->expr->visit(this); @@ -517,10 +495,7 @@ void GS2CompilerVisitor::Visit(ExpressionUnaryOpNode* node) _isInsideExpression = false; _isInlineConditional = temp_inlinecond; - success_label = save_labels[0]; - fail_label = save_labels[1]; - - setLocation(save_labels[2], byteCode.getOpIndex()); + inlineTarget.resolveHere(); } if (node->opFirst) @@ -576,31 +551,35 @@ void GS2CompilerVisitor::Visit(ExpressionUnaryOpNode* node) return; } + + default: + return; } } - else + + switch (node->op) { - switch (node->op) + case ExpressionOp::Increment: + case ExpressionOp::Decrement: { - case ExpressionOp::Increment: - case ExpressionOp::Decrement: - { - auto opCode = getExpressionOpCode(node->op); - assert(opCode != opcode::Opcode::OP_NONE); + auto opCode = getExpressionOpCode(node->op); + assert(opCode != opcode::Opcode::OP_NONE); - // TODO(joey): need to fix - byteCode.emit(opcode::OP_COPY_LAST_OP); - byteCode.emit(opcode::OP_CONV_TO_FLOAT); - byteCode.emit(opcode::OP_SWAP_LAST_OPS); - byteCode.emit(opCode); - byteCode.emit(opcode::OP_INDEX_DEC); - return; - } + // TODO(joey): need to fix + byteCode.emit(opcode::OP_COPY_LAST_OP); + byteCode.emit(opcode::OP_CONV_TO_FLOAT); + byteCode.emit(opcode::OP_SWAP_LAST_OPS); + byteCode.emit(opCode); + byteCode.emit(opcode::OP_INDEX_DEC); + return; + } + default: + { + std::string errorMsg = std::format("Undefined opcode in UnaryExpression {}: {}", static_cast(node->op), ExpressionOpToString(node->op)); + parserContext.addError({ ErrorLevel::E_ERROR, GS2CompilerError::ErrorCategory::Compiler, std::move(errorMsg) }); + return; } } - - std::string errorMsg = std::format("Undefined opcode in UnaryExpression {}: {}", static_cast(node->op), ExpressionOpToString(node->op)); - parserContext.addError({ ErrorLevel::E_ERROR, GS2CompilerError::ErrorCategory::Compiler, std::move(errorMsg) }); } void GS2CompilerVisitor::Visit(ExpressionStrConcatNode *node) @@ -832,16 +811,15 @@ void GS2CompilerVisitor::Visit(ExpressionFnCallNode *node) { auto isObjectCall = (node->objExpr != nullptr); - // Build-in commands - auto& cmdList = (isObjectCall ? builtIn.builtInObjMap : builtIn.builtInCmdMap); + // Built-in commands std::string funcName = node->funcExpr->toString(); #ifdef DBGEMITTERS printf("Call Function: %s (obj call: %d)\n", funcName.c_str(), isObjectCall ? 1 : 0); #endif - auto iter = cmdList.find(funcName); - BuiltInCmd cmd = (iter != cmdList.end() ? iter->second : (isObjectCall ? defaultObjCall : defaultCall)); + const BuiltInCmd* found = isObjectCall ? findBuiltInObjCmd(funcName) : findBuiltInCmd(funcName); + BuiltInCmd cmd = found ? *found : (isObjectCall ? defaultObjCall : defaultCall); { auto argumentVisitFn = [&](auto arg_iter, auto arg_iter_end, auto sig_iter, auto sig_iter_end) { @@ -998,15 +976,14 @@ void GS2CompilerVisitor::Visit(StatementReturnNode *node) { if (node->expr) { - label_id save_labels[] = { success_label, fail_label }; - - fail_label = success_label = createLabel(); + ScopeGuard guard(*this); + JumpTarget exprEnd(byteCode); + success_target = &exprEnd; + fail_target = &exprEnd; node->expr->visit(this); - setLocation(success_label, byteCode.getOpIndex()); - success_label = save_labels[0]; - fail_label = save_labels[1]; + exprEnd.resolveHere(); } else { @@ -1019,14 +996,14 @@ void GS2CompilerVisitor::Visit(StatementReturnNode *node) void GS2CompilerVisitor::Visit(StatementIfNode* node) { - label_id save_labels[] = { success_label, fail_label }; + ScopeGuard guard(*this); - auto new_success_label = createLabel(); - auto new_fail_label = createLabel(); + JumpTarget condEnd(byteCode); + JumpTarget falseBranch(byteCode); { - success_label = new_success_label; - fail_label = new_fail_label; + success_target = &condEnd; + fail_target = &falseBranch; { _isInlineConditional = false; @@ -1040,12 +1017,9 @@ void GS2CompilerVisitor::Visit(StatementIfNode* node) byteCode.emitConversionOp(node->expr->expressionType(), ExpressionType::EXPR_NUMBER); // set the break point to the start of the OP_IF instruction - setLocation(new_success_label, byteCode.getOpIndex()); + condEnd.resolveHere(); - byteCode.emit(opcode::OP_IF); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(new_fail_label, byteCode.getBytecodePos() - 2); + falseBranch.emitJump(opcode::OP_IF); node->thenBlock->visit(this); @@ -1053,12 +1027,9 @@ void GS2CompilerVisitor::Visit(StatementIfNode* node) // continue to the next instruction, but if their is an else-block we must // skip the next instruction since its a jmp to the end of the if-else chain auto nextOpcode = byteCode.getOpIndex() + (node->elseBlock ? 1 : 0); - setLocation(new_fail_label, nextOpcode); + falseBranch.resolve(nextOpcode); } - success_label = save_labels[0]; - fail_label = save_labels[1]; - if (node->elseBlock) { // emit a jump to the end of this else block for the previous if-block @@ -1070,9 +1041,6 @@ void GS2CompilerVisitor::Visit(StatementIfNode* node) node->elseBlock->visit(this); byteCode.emit(short(byteCode.getOpIndex()), elseLoc); - - success_label = save_labels[0]; - fail_label = save_labels[1]; } } @@ -1121,56 +1089,42 @@ void GS2CompilerVisitor::Visit(ExpressionNewObjectNode *node) void GS2CompilerVisitor::Visit(StatementWhileNode *node) { - label_id save_labels[] = {success_label, fail_label, continue_label, break_label}; - - { - auto new_break_label = createLabel(); - auto new_continue_label = createLabel(); + ScopeGuard guard(*this); - break_label = new_break_label; - continue_label = new_continue_label; + JumpTarget breakJmp(byteCode); + JumpTarget continueJmp(byteCode); - // Set the continue breakpoint to the start of the loop - setLocation(continue_label, byteCode.getOpIndex()); + break_target = &breakJmp; + continue_target = &continueJmp; - { - _isInlineConditional = false; - node->expr->visit(this); - _isInlineConditional = true; - } + // Set the continue breakpoint to the start of the loop + continueJmp.resolveHere(); - byteCode.emitConversionOp(node->expr->expressionType(), ExpressionType::EXPR_NUMBER); + { + _isInlineConditional = false; + node->expr->visit(this); + _isInlineConditional = true; + } - byteCode.emit(opcode::OP_IF); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(new_break_label, byteCode.getBytecodePos() - 2); + byteCode.emitConversionOp(node->expr->expressionType(), ExpressionType::EXPR_NUMBER); - // Increment loop count - byteCode.emit(opcode::OP_CMD_CALL); + breakJmp.emitJump(opcode::OP_IF); - node->block->visit(this); + // Increment loop count + byteCode.emit(opcode::OP_CMD_CALL); - // Jump back to condition - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(new_continue_label, byteCode.getBytecodePos() - 2); + node->block->visit(this); - // Set the fail breakpoint to after the while-statement - setLocation(new_break_label, byteCode.getOpIndex()); - } + // Jump back to condition + continueJmp.emitJump(opcode::OP_SET_INDEX); - // restore labels - success_label = save_labels[0]; - fail_label = save_labels[1]; - continue_label = save_labels[2]; - break_label = save_labels[3]; + // Set the fail breakpoint to after the while-statement + breakJmp.resolveHere(); } void GS2CompilerVisitor::Visit(StatementBreakNode* node) { - if (break_label <= 0) + if (!break_target) { std::string errorMsg = std::format("`break` outside loop detected"); parserContext.addError({ ErrorLevel::E_WARNING, GS2CompilerError::ErrorCategory::Compiler, std::move(errorMsg) }); @@ -1178,15 +1132,12 @@ void GS2CompilerVisitor::Visit(StatementBreakNode* node) } // Emit jump out of loop - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(break_label, byteCode.getBytecodePos() - 2); + break_target->emitJump(opcode::OP_SET_INDEX); } void GS2CompilerVisitor::Visit(StatementContinueNode* node) { - if (continue_label <= 0) + if (!continue_target) { std::string errorMsg = std::format("`continue` outside loop detected"); parserContext.addError({ ErrorLevel::E_WARNING, GS2CompilerError::ErrorCategory::Compiler, std::move(errorMsg) }); @@ -1194,10 +1145,7 @@ void GS2CompilerVisitor::Visit(StatementContinueNode* node) } // Emit jump back to the loop-condition - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - addLocation(continue_label, byteCode.getBytecodePos() - 2); + continue_target->emitJump(opcode::OP_SET_INDEX); } void GS2CompilerVisitor::Visit(StatementForNode *node) @@ -1222,53 +1170,40 @@ void GS2CompilerVisitor::Visit(StatementForNode *node) byteCode.emit(opcode::OP_TYPE_TRUE); } - label_id save_labels[] = {success_label, fail_label, continue_label, break_label}; - - { - auto new_break_label = createLabel(); - auto new_continue_label = createLabel(); - - break_label = new_break_label; - continue_label = new_continue_label; + ScopeGuard guard(*this); - // Emit if-loop on conditional expression, with a failed jump to the end-block - byteCode.emit(opcode::OP_IF); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - - // Add break location for the jump out of the loop - addLocation(new_break_label, byteCode.getBytecodePos() - 2); + JumpTarget breakJmp(byteCode); + JumpTarget continueJmp(byteCode); - // Increment loop count - byteCode.emit(opcode::OP_CMD_CALL); + break_target = &breakJmp; + continue_target = &continueJmp; - // Emit block - if (node->block) - node->block->visit(this); + // Emit if-loop on conditional expression, with a failed jump to the end-block + breakJmp.emitJump(opcode::OP_IF); - // Set the continue location before the post-op - setLocation(new_continue_label, byteCode.getOpIndex()); + // Increment loop count + byteCode.emit(opcode::OP_CMD_CALL); - // Emit post-op - if (node->postop) - { - // TODO(joey): discard return - node->postop->visit(this); - } + // Emit block + if (node->block) + node->block->visit(this); - // Emit jump back to condition - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emitDynamicNumber(startLoopOp); + // Set the continue location before the post-op + continueJmp.resolveHere(); - // Write out the breakpoint jumps - setLocation(new_break_label, byteCode.getOpIndex()); + // Emit post-op + if (node->postop) + { + // TODO(joey): discard return + node->postop->visit(this); } - // restore labels - success_label = save_labels[0]; - fail_label = save_labels[1]; - continue_label = save_labels[2]; - break_label = save_labels[3]; + // Emit jump back to condition + byteCode.emit(opcode::OP_SET_INDEX); + byteCode.emitDynamicNumber(startLoopOp); + + // Write out the breakpoint jumps + breakJmp.resolveHere(); } void GS2CompilerVisitor::Visit(StatementNewNode* node) @@ -1370,45 +1305,32 @@ void GS2CompilerVisitor::Visit(StatementForEachNode *node) byteCode.emit(opcode::OP_TYPE_NUMBER); byteCode.emitDynamicNumber(0); - label_id save_labels[] = { success_label, fail_label, continue_label, break_label }; - - { - auto new_break_label = createLabel(); - auto new_continue_label = createLabel(); + ScopeGuard guard(*this); - break_label = new_break_label; - continue_label = new_continue_label; - - auto startLoopOp = byteCode.getOpIndex(); - byteCode.emit(opcode::OP_FOREACH); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); + JumpTarget breakJmp(byteCode); + JumpTarget continueJmp(byteCode); - // Add break location for the jump out of the loop - addLocation(new_break_label, byteCode.getBytecodePos() - 2); + break_target = &breakJmp; + continue_target = &continueJmp; - byteCode.emit(opcode::OP_CMD_CALL); - node->block->visit(this); + auto startLoopOp = byteCode.getOpIndex(); + breakJmp.emitJump(opcode::OP_FOREACH); - // Set the continue location before we increment the idx - setLocation(new_continue_label, byteCode.getOpIndex()); - byteCode.emit(opcode::OP_INC); + byteCode.emit(opcode::OP_CMD_CALL); + node->block->visit(this); - // jump to beginning of the for-each loop - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emitDynamicNumber(startLoopOp); + // Set the continue location before we increment the idx + continueJmp.resolveHere(); + byteCode.emit(opcode::OP_INC); - // Write out the breakpoint jumps - setLocation(new_break_label, byteCode.getOpIndex()); - } + // jump to beginning of the for-each loop + byteCode.emit(opcode::OP_SET_INDEX); + byteCode.emitDynamicNumber(startLoopOp); - // restore labels - success_label = save_labels[0]; - fail_label = save_labels[1]; - continue_label = save_labels[2]; - break_label = save_labels[3]; + // Write out the breakpoint jumps + breakJmp.resolveHere(); - // pop the idx variable + // pop the idx variable (after guard restores targets) byteCode.emit(opcode::OP_INDEX_DEC); } @@ -1431,69 +1353,64 @@ void GS2CompilerVisitor::Visit(StatementSwitchNode* node) // endloc: // .... - // save labels - label_id save_labels[] = { break_label, continue_label, success_label, fail_label }; + ScopeGuard guard(*this); - { - auto new_break_label = createLabel(); + JumpTarget breakJmp(byteCode); - std::vector caseStartOp; + std::vector caseAddrs; - // jump to case-test - byteCode.emit(opcode::OP_SET_INDEX); - byteCode.emit(char(0xF4)); - byteCode.emit(short(0)); - size_t caseTestLoc = byteCode.getBytecodePos() - 2; + // jump to case-test + byteCode.emit(opcode::OP_SET_INDEX); + byteCode.emit(char(0xF4)); + byteCode.emit(short(0)); + size_t caseTestLoc = byteCode.getBytecodePos() - 2; - // case-list: - for (const auto& caseNode : node->cases) - { - auto new_case_label = createLabel(); - setLocation(new_case_label, byteCode.getOpIndex()); + // case-list: + for (const auto& caseNode : node->cases) + { + auto caseAddr = byteCode.getOpIndex(); - for (const auto& caseExpr : caseNode.exprList) - caseStartOp.push_back(new_case_label); + for (const auto& caseExpr : caseNode.exprList) + caseAddrs.push_back(caseAddr); - break_label = new_break_label; - continue_label = new_case_label; - caseNode.block->visit(this); - } + break_target = &breakJmp; - // case-test: - byteCode.emit(short(byteCode.getOpIndex()), caseTestLoc); - node->expr->visit(this); + // continue inside switch case jumps to current case start + JumpTarget caseStart(byteCode); + caseStart.resolve(caseAddr); + continue_target = &caseStart; + + caseNode.block->visit(this); + continue_target = nullptr; + } - size_t i = 0; - for (const auto& caseNode : node->cases) + // case-test: + byteCode.emit(short(byteCode.getOpIndex()), caseTestLoc); + node->expr->visit(this); + + size_t i = 0; + for (const auto& caseNode : node->cases) + { + for (const auto& caseExpr : caseNode.exprList) { - for (const auto& caseExpr : caseNode.exprList) + if (caseExpr) { - if (caseExpr) - { - byteCode.emit(opcode::OP_COPY_LAST_OP); - caseExpr->visit(this); - byteCode.emit(opcode::OP_EQ); - byteCode.emit(opcode::OP_SET_INDEX_TRUE); - } - else byteCode.emit(opcode::OP_SET_INDEX); - - byteCode.emitDynamicNumber(label_addr[caseStartOp[i++]]); + byteCode.emit(opcode::OP_COPY_LAST_OP); + caseExpr->visit(this); + byteCode.emit(opcode::OP_EQ); + byteCode.emit(opcode::OP_SET_INDEX_TRUE); } - } + else byteCode.emit(opcode::OP_SET_INDEX); - setLocation(new_break_label, byteCode.getOpIndex()); - - // Since we are consuming a copy for each case-test, we need to pop - // the original value off the top of the stack. - //if (node->expr->expressionType() == ExpressionType::EXPR_FUNCTION) // note: no idea why this was here - byteCode.emit(opcode::OP_INDEX_DEC); + byteCode.emitDynamicNumber(caseAddrs[i++]); + } } - // restore labels - break_label = save_labels[0]; - continue_label = save_labels[1]; - success_label = save_labels[2]; - fail_label = save_labels[3]; + breakJmp.resolveHere(); + + // Since we are consuming a copy for each case-test, we need to pop + // the original value off the top of the stack. + byteCode.emit(opcode::OP_INDEX_DEC); } // not implemented: should never occur diff --git a/src/compiler/GS2CompilerVisitor.h b/src/compiler/GS2CompilerVisitor.h index 504db0f..c3404a0 100644 --- a/src/compiler/GS2CompilerVisitor.h +++ b/src/compiler/GS2CompilerVisitor.h @@ -3,23 +3,80 @@ #ifndef GS2COMPILER_H #define GS2COMPILER_H +#include +#include #include #include #include -#include #include "ast/NodeVisitor.h" #include "GS2Bytecode.h" -#include "GS2BuiltInFunctions.h" class ParserContext; +class JumpTarget +{ + using jmp_address = uint32_t; + + GS2Bytecode& byteCode; + std::vector pending; + std::optional addr; + +public: + explicit JumpTarget(GS2Bytecode& bc) : byteCode(bc) {} + + ~JumpTarget() + { + assert(pending.empty() && "unresolved forward references — missing resolve() call"); + } + + JumpTarget(const JumpTarget&) = delete; + JumpTarget& operator=(const JumpTarget&) = delete; + JumpTarget(JumpTarget&&) = delete; + JumpTarget& operator=(JumpTarget&&) = delete; + + void addRef(size_t pos) + { + if (addr) + byteCode.emit(short(*addr), pos); + else + pending.push_back(pos); + } + + void resolve(jmp_address target) + { + addr = target; + for (auto pos : pending) + byteCode.emit(short(*addr), pos); + pending.clear(); + } + + void resolveHere() { resolve(byteCode.getOpIndex()); } + + jmp_address address() const { return *addr; } + + size_t pendingCount() const { return pending.size(); } + + void reset() + { + assert(pending.empty()); + addr.reset(); + } + + void emitJump(opcode::Opcode jumpOp) + { + byteCode.emit(jumpOp); + byteCode.emit(char(0xF4)); + byteCode.emit(short(0)); + addRef(byteCode.getBytecodePos() - 2); + } +}; + class GS2CompilerVisitor : public NodeVisitor { - using label_id = uint32_t; using jmp_address = uint32_t; public: - GS2CompilerVisitor(ParserContext& context, GS2BuiltInFunctions& builtin); + GS2CompilerVisitor(ParserContext& context); Buffer getByteCode(); const std::set& getJoinedClasses() const; @@ -59,34 +116,54 @@ class GS2CompilerVisitor : public NodeVisitor virtual void Visit(ExpressionConstantNode *node); virtual void Visit(ExpressionFnObject* node); - private: + private: GS2Bytecode byteCode; ParserContext& parserContext; - GS2BuiltInFunctions& builtIn; std::set joinedClasses; - bool _isCopyAssignment; - bool _isInlineConditional; - bool _isInsideExpression; - int _newObjectCount; - - // Jump-labels - label_id success_label, fail_label, exit_label; - label_id break_label, continue_label; - std::unordered_map> label_locs; - std::unordered_map label_addr; - - // Jump-label functions - label_id createLabel(); - void addLocation(label_id label, size_t loc); - void setLocation(label_id label, jmp_address addr); - void writeLabels(); + bool _isCopyAssignment = false; + bool _isInlineConditional = true; + bool _isInsideExpression = false; + int _newObjectCount = 0; + + // Jump targets + JumpTarget* success_target = nullptr; + JumpTarget* fail_target = nullptr; + JumpTarget* break_target = nullptr; + JumpTarget* continue_target = nullptr; + JumpTarget* fn_skip_target = nullptr; + bool _isRootBlock = true; + + struct ScopeGuard + { + GS2CompilerVisitor& self; + JumpTarget* saved_success; + JumpTarget* saved_fail; + JumpTarget* saved_break; + JumpTarget* saved_continue; + + explicit ScopeGuard(GS2CompilerVisitor& s) + : self(s), + saved_success(s.success_target), + saved_fail(s.fail_target), + saved_break(s.break_target), + saved_continue(s.continue_target) {} + + ~ScopeGuard() + { + self.success_target = saved_success; + self.fail_target = saved_fail; + self.break_target = saved_break; + self.continue_target = saved_continue; + } + + ScopeGuard(const ScopeGuard&) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; + }; }; inline Buffer GS2CompilerVisitor::getByteCode() { - setLocation(exit_label, byteCode.getOpIndex()); - writeLabels(); return byteCode.getByteCode(); } @@ -95,14 +172,4 @@ inline const std::set& GS2CompilerVisitor::getJoinedClasses() const return joinedClasses; } -inline void GS2CompilerVisitor::addLocation(label_id label, size_t loc) -{ - label_locs[label].push_back(loc); -} - -inline void GS2CompilerVisitor::setLocation(label_id label, jmp_address addr) -{ - label_addr[label] = addr; -} - #endif diff --git a/src/compiler/GS2Context.cpp b/src/compiler/GS2Context.cpp index 464a14b..475633e 100644 --- a/src/compiler/GS2Context.cpp +++ b/src/compiler/GS2Context.cpp @@ -8,7 +8,6 @@ GS2Context::GS2Context() : errorService([this](auto && PH1) { handleError(std::forward(PH1)); }) { - builtIn = GS2BuiltInFunctions::getBuiltIn(); } void GS2Context::handleError(GS2CompilerError& error) @@ -33,7 +32,7 @@ CompilerResponse GS2Context::compile(const std::string& script) if (stmtBlock) { // Walk the AST tree to produce bytecode - GS2CompilerVisitor compilerVisitor(parserContext, builtIn); + GS2CompilerVisitor compilerVisitor(parserContext); compilerVisitor.Visit(stmtBlock); return CompilerResponse{ diff --git a/src/compiler/GS2Context.h b/src/compiler/GS2Context.h index 8fb0699..31a6418 100644 --- a/src/compiler/GS2Context.h +++ b/src/compiler/GS2Context.h @@ -8,7 +8,6 @@ #include "gs2compiler_export.h" #include "encoding/buffer.h" #include "exceptions/GS2CompilerError.h" -#include "GS2BuiltInFunctions.h" struct CompilerResponse { @@ -32,7 +31,6 @@ class GS2COMPILER_EXPORT GS2Context static CompilerResponse Compile(const std::string& script, const std::string& scriptType, const std::string& scriptName, bool saveToDisk); private: - GS2BuiltInFunctions builtIn; GS2ErrorService errorService; std::vector errors; diff --git a/src/memory/ArenaAllocator.h b/src/memory/ArenaAllocator.h index c7ff882..7a354c0 100644 --- a/src/memory/ArenaAllocator.h +++ b/src/memory/ArenaAllocator.h @@ -5,8 +5,10 @@ #include #include +#include #include #include +#include template class ArenaAllocator { @@ -19,20 +21,25 @@ class ArenaAllocator { ArenaAllocator(ArenaAllocator&& other) noexcept : chunks_(std::move(other.chunks_)), + dtors_(std::move(other.dtors_)), current_(std::exchange(other.current_, nullptr)), remaining_(std::exchange(other.remaining_, 0)) { } ArenaAllocator& operator=(ArenaAllocator&& other) noexcept { if (this != &other) { + reset(); chunks_ = std::move(other.chunks_); + dtors_ = std::move(other.dtors_); current_ = std::exchange(other.current_, nullptr); remaining_ = std::exchange(other.remaining_, 0); } return *this; } - ~ArenaAllocator() = default; + ~ArenaAllocator() { + reset(); + } /** * Allocate and construct an object of type T @@ -45,13 +52,26 @@ class ArenaAllocator { template [[nodiscard]] T* allocate(Args&&... args) { void* ptr = allocate_raw(sizeof(T), alignof(T)); - return std::construct_at(static_cast(ptr), std::forward(args)...); + T* obj = std::construct_at(static_cast(ptr), std::forward(args)...); + + if constexpr (!std::is_trivially_destructible_v) { + dtors_.push_back(DtorRecord{ + obj, + [](void* p) noexcept { std::destroy_at(static_cast(p)); } + }); + } + + return obj; } /** * Reset the arena, freeing all allocated memory */ void reset() noexcept { + for (const auto& dtor : std::ranges::reverse_view(dtors_)) { + dtor.destroy(dtor.ptr); + } + dtors_.clear(); chunks_.clear(); current_ = nullptr; remaining_ = 0; @@ -76,6 +96,11 @@ class ArenaAllocator { } private: + struct DtorRecord { + void* ptr{}; + void (*destroy)(void*) noexcept = nullptr; + }; + /** * Represents a memory chunk */ @@ -113,6 +138,7 @@ class ArenaAllocator { } std::vector chunks_; + std::vector dtors_; std::byte* current_; size_t remaining_; }; diff --git a/src/parser/Parser.cpp b/src/parser/Parser.cpp index 413fa1a..8ca14db 100644 --- a/src/parser/Parser.cpp +++ b/src/parser/Parser.cpp @@ -156,7 +156,6 @@ void ParserContext::addEnum(EnumList *enumList, std::string prefix) } } - delete enumList; } void ParserContext::addConstant(const std::string& ident, ExpressionIdentifierNode *node) diff --git a/src/parser/gs2parser.y b/src/parser/gs2parser.y index 28d2149..af066da 100644 --- a/src/parser/gs2parser.y +++ b/src/parser/gs2parser.y @@ -129,14 +129,6 @@ typedef void* yyscan_t; %type array_idx %type array_idx_list - - // Destructors for allocated std vectors incase an error happens - // during parsing before ownership is moved to the node -%destructor { delete $$; } -%destructor { delete $$; } -%destructor { delete $$; } - - %start program %% @@ -168,15 +160,15 @@ decl_enum: ; enum_list: - enum_item { $$ = new EnumList($1); } + enum_item { $$ = parser->alloc($1); } | enum_list ',' enum_item { $$ = $1; $1->addMember($3); } | enum_list error ',' { $$ = $1; parser->addParserError("missing comma in enum list"); } ; enum_item: - T_IDENTIFIER { $$ = new EnumMember($1); } - | T_IDENTIFIER '=' T_INT { $$ = new EnumMember($1, $3); } - | T_IDENTIFIER '=' '-' T_INT { $$ = new EnumMember($1, -$4); } + T_IDENTIFIER { $$ = parser->alloc($1); } + | T_IDENTIFIER '=' T_INT { $$ = parser->alloc($1, $3); } + | T_IDENTIFIER '=' '-' T_INT { $$ = parser->alloc($1, -$4); } ; stmt_list: @@ -261,7 +253,7 @@ stmt_switch: stmt_caseblock_list: stmt_caseblock_list stmt_caseblock { $$ = $1; $$->push_back(parser->popCaseExpr()); } - | stmt_caseblock { $$ = new std::vector(); $$->push_back(parser->popCaseExpr()); } + | stmt_caseblock { $$ = parser->alloc>(); $$->push_back(parser->popCaseExpr()); } ; stmt_case_options: @@ -290,8 +282,8 @@ expr_list_with_empty: expr_list: expr_list ',' expr { $1->push_back($3); } | expr_list ',' expr_functionobj { $1->push_back($3); } - | expr { $$ = new std::vector(); $$->reserve(12); $$->push_back($1); } - | expr_functionobj { $$ = new std::vector(); $$->reserve(12); $$->push_back($1); } + | expr { $$ = parser->alloc>(); $$->reserve(12); $$->push_back($1); } + | expr_functionobj { $$ = parser->alloc>(); $$->reserve(12); $$->push_back($1); } ; constant: @@ -443,7 +435,7 @@ array_idx: array_idx_list: array_idx_list array_idx { $$ = $1; $$->push_back($2); } - | array_idx { $$ = new std::vector(); $$->push_back($1); } + | array_idx { $$ = parser->alloc>(); $$->push_back($1); } ; expr_new: diff --git a/tests/baselines/advanced/g2k1/weapon-Day-Night.bytecode b/tests/baselines/advanced/g2k1/weapon-Day-Night.bytecode deleted file mode 100644 index 8fd5518..0000000 Binary files a/tests/baselines/advanced/g2k1/weapon-Day-Night.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weapon-Staff_Boots.bytecode b/tests/baselines/advanced/g2k1/weapon-Staff_Boots.bytecode deleted file mode 100644 index 5490613..0000000 Binary files a/tests/baselines/advanced/g2k1/weapon-Staff_Boots.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weapon-Systems_Main.bytecode b/tests/baselines/advanced/g2k1/weapon-Systems_Main.bytecode deleted file mode 100644 index 147cb3b..0000000 Binary files a/tests/baselines/advanced/g2k1/weapon-Systems_Main.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponApple Seeds.bytecode b/tests/baselines/advanced/g2k1/weaponApple Seeds.bytecode deleted file mode 100644 index 5cade81..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponApple Seeds.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponBasket.bytecode b/tests/baselines/advanced/g2k1/weaponBasket.bytecode deleted file mode 100644 index 3f0c225..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponBasket.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponBread Stack.bytecode b/tests/baselines/advanced/g2k1/weaponBread Stack.bytecode deleted file mode 100644 index 8ee26e7..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponBread Stack.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponCandies.bytecode b/tests/baselines/advanced/g2k1/weaponCandies.bytecode deleted file mode 100644 index 22b78cf..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponCandies.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponCatch Net.bytecode b/tests/baselines/advanced/g2k1/weaponCatch Net.bytecode deleted file mode 100644 index c4e0556..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponCatch Net.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponDiamond Axe.bytecode b/tests/baselines/advanced/g2k1/weaponDiamond Axe.bytecode deleted file mode 100644 index 5139551..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponDiamond Axe.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponDiving.bytecode b/tests/baselines/advanced/g2k1/weaponDiving.bytecode deleted file mode 100644 index 5032965..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponDiving.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponDraisine.bytecode b/tests/baselines/advanced/g2k1/weaponDraisine.bytecode deleted file mode 100644 index e1ae069..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponDraisine.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponGold Axe.bytecode b/tests/baselines/advanced/g2k1/weaponGold Axe.bytecode deleted file mode 100644 index aabd819..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponGold Axe.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponGold Hammer.bytecode b/tests/baselines/advanced/g2k1/weaponGold Hammer.bytecode deleted file mode 100644 index 726bd19..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponGold Hammer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponHat-Trading-GS2.bytecode b/tests/baselines/advanced/g2k1/weaponHat-Trading-GS2.bytecode deleted file mode 100644 index e41b8c7..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponHat-Trading-GS2.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponHat-Trading.bytecode b/tests/baselines/advanced/g2k1/weaponHat-Trading.bytecode deleted file mode 100644 index 61f9525..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponHat-Trading.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponMemeCentral.bytecode b/tests/baselines/advanced/g2k1/weaponMemeCentral.bytecode deleted file mode 100644 index b53994a..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponMemeCentral.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponMetal Axe.bytecode b/tests/baselines/advanced/g2k1/weaponMetal Axe.bytecode deleted file mode 100644 index 2b3f1df..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponMetal Axe.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponMetal Hammer.bytecode b/tests/baselines/advanced/g2k1/weaponMetal Hammer.bytecode deleted file mode 100644 index 76ab038..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponMetal Hammer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponMining Bomb.bytecode b/tests/baselines/advanced/g2k1/weaponMining Bomb.bytecode deleted file mode 100644 index ab32fb9..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponMining Bomb.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponParticleEditor.bytecode b/tests/baselines/advanced/g2k1/weaponParticleEditor.bytecode deleted file mode 100644 index d8908a7..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponParticleEditor.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponRailroad Destroyer.bytecode b/tests/baselines/advanced/g2k1/weaponRailroad Destroyer.bytecode deleted file mode 100644 index 4dfc4dd..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponRailroad Destroyer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponRoller.bytecode b/tests/baselines/advanced/g2k1/weaponRoller.bytecode deleted file mode 100644 index c0f4c5d..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponRoller.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponRope.bytecode b/tests/baselines/advanced/g2k1/weaponRope.bytecode deleted file mode 100644 index 5985628..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponRope.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponShovel.bytecode b/tests/baselines/advanced/g2k1/weaponShovel.bytecode deleted file mode 100644 index 4f7aa25..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponShovel.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponSkip.bytecode b/tests/baselines/advanced/g2k1/weaponSkip.bytecode deleted file mode 100644 index 5985628..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponSkip.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponSpin.bytecode b/tests/baselines/advanced/g2k1/weaponSpin.bytecode deleted file mode 100644 index 9cab2f3..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponSpin.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponTestGS2.bytecode b/tests/baselines/advanced/g2k1/weaponTestGS2.bytecode deleted file mode 100644 index c5279c0..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponTestGS2.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponTorch.bytecode b/tests/baselines/advanced/g2k1/weaponTorch.bytecode deleted file mode 100644 index 4329599..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponTorch.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponTrading Item.bytecode b/tests/baselines/advanced/g2k1/weaponTrading Item.bytecode deleted file mode 100644 index b1fb752..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponTrading Item.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponViolin.bytecode b/tests/baselines/advanced/g2k1/weaponViolin.bytecode deleted file mode 100644 index bb4bc31..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponViolin.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponWater Can.bytecode b/tests/baselines/advanced/g2k1/weaponWater Can.bytecode deleted file mode 100644 index 72ede4b..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponWater Can.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponWooden Hammer.bytecode b/tests/baselines/advanced/g2k1/weaponWooden Hammer.bytecode deleted file mode 100644 index 0be25c3..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponWooden Hammer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weapongxtest.bytecode b/tests/baselines/advanced/g2k1/weapongxtest.bytecode deleted file mode 100644 index ce68da7..0000000 Binary files a/tests/baselines/advanced/g2k1/weapongxtest.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/g2k1/weaponjoey_test.bytecode b/tests/baselines/advanced/g2k1/weaponjoey_test.bytecode deleted file mode 100644 index d771c15..0000000 Binary files a/tests/baselines/advanced/g2k1/weaponjoey_test.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon%045CarSystem.bytecode b/tests/baselines/advanced/graalx/weapon%045CarSystem.bytecode deleted file mode 100644 index d0ac5c0..0000000 Binary files a/tests/baselines/advanced/graalx/weapon%045CarSystem.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon%045CarSystem.json b/tests/baselines/advanced/graalx/weapon%045CarSystem.json index 4a1717a..423e373 100644 --- a/tests/baselines/advanced/graalx/weapon%045CarSystem.json +++ b/tests/baselines/advanced/graalx/weapon%045CarSystem.json @@ -1,12 +1,12 @@ { - "bytecode_hash": "c537528f746fccd7ad8da9319ec365b7f031bd4b2bf8bc3d5462929d3381d3fb", + "bytecode_hash": "8a0a716b615c93b4c193b313671e4151593cf0097c348dd32f77e68275edfd94", "bytecode_size": 5908, "compilation_success": true, "expected_failure": false, "error_message": "", "metadata": { "script_path": "advanced/graalx/weapon%045CarSystem.gs2", - "generated_at": "2026-01-04 18:39:05", - "compiler_version": "modified_1767569912" + "generated_at": "2026-02-23 11:42:04", + "compiler_version": "modified_1771863608" } } \ No newline at end of file diff --git a/tests/baselines/advanced/graalx/weapon%045Movement.bytecode b/tests/baselines/advanced/graalx/weapon%045Movement.bytecode deleted file mode 100644 index d537e27..0000000 Binary files a/tests/baselines/advanced/graalx/weapon%045Movement.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon%045System.bytecode b/tests/baselines/advanced/graalx/weapon%045System.bytecode deleted file mode 100644 index 6dea293..0000000 Binary files a/tests/baselines/advanced/graalx/weapon%045System.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Ammo.bytecode b/tests/baselines/advanced/graalx/weapon+Ammo.bytecode deleted file mode 100644 index 8447ad2..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Ammo.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+DogTag.bytecode b/tests/baselines/advanced/graalx/weapon+DogTag.bytecode deleted file mode 100644 index cff2da9..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+DogTag.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Food.bytecode b/tests/baselines/advanced/graalx/weapon+Food.bytecode deleted file mode 100644 index d0d403b..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Food.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Guns.bytecode b/tests/baselines/advanced/graalx/weapon+Guns.bytecode deleted file mode 100644 index 98a8b4f..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Guns.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Guns_Debug.bytecode b/tests/baselines/advanced/graalx/weapon+Guns_Debug.bytecode deleted file mode 100644 index 87ad8ba..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Guns_Debug.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Guns_Debug.json b/tests/baselines/advanced/graalx/weapon+Guns_Debug.json index 43ef501..6f79ff9 100644 --- a/tests/baselines/advanced/graalx/weapon+Guns_Debug.json +++ b/tests/baselines/advanced/graalx/weapon+Guns_Debug.json @@ -1,12 +1,12 @@ { - "bytecode_hash": "dc6caf0ba55337145209df40ca85a1d6787bbcaf4ce16cf563ab00ff897d6038", + "bytecode_hash": "cfa207eda5302a846807a9f41f1ea371e4e7295ec091e08ae644e343ae42230d", "bytecode_size": 5953, "compilation_success": true, "expected_failure": false, "error_message": "", "metadata": { "script_path": "advanced/graalx/weapon+Guns_Debug.gs2", - "generated_at": "2026-01-04 18:39:05", - "compiler_version": "modified_1767569912" + "generated_at": "2026-02-23 11:42:04", + "compiler_version": "modified_1771863608" } } \ No newline at end of file diff --git a/tests/baselines/advanced/graalx/weapon+Guns_KuJi.bytecode b/tests/baselines/advanced/graalx/weapon+Guns_KuJi.bytecode deleted file mode 100644 index 0f8f6e8..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Guns_KuJi.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Guns_M4.bytecode b/tests/baselines/advanced/graalx/weapon+Guns_M4.bytecode deleted file mode 100644 index db1efca..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Guns_M4.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Guns_Shotgun.bytecode b/tests/baselines/advanced/graalx/weapon+Guns_Shotgun.bytecode deleted file mode 100644 index 8219f9b..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Guns_Shotgun.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Hats.bytecode b/tests/baselines/advanced/graalx/weapon+Hats.bytecode deleted file mode 100644 index 435cd16..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Hats.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Melee.bytecode b/tests/baselines/advanced/graalx/weapon+Melee.bytecode deleted file mode 100644 index a7b695c..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Melee.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Presents.bytecode b/tests/baselines/advanced/graalx/weapon+Presents.bytecode deleted file mode 100644 index 7fdb1c1..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Presents.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon+Seeds.bytecode b/tests/baselines/advanced/graalx/weapon+Seeds.bytecode deleted file mode 100644 index 130754f..0000000 Binary files a/tests/baselines/advanced/graalx/weapon+Seeds.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-BizSystem.bytecode b/tests/baselines/advanced/graalx/weapon-BizSystem.bytecode deleted file mode 100644 index f98056f..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-BizSystem.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-BuySys.bytecode b/tests/baselines/advanced/graalx/weapon-BuySys.bytecode deleted file mode 100644 index e8416be..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-BuySys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-DRescript.bytecode b/tests/baselines/advanced/graalx/weapon-DRescript.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-DRescript.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Death.bytecode b/tests/baselines/advanced/graalx/weapon-Death.bytecode deleted file mode 100644 index 3898b67..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Death.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-EraThingyForKinetaro.bytecode b/tests/baselines/advanced/graalx/weapon-EraThingyForKinetaro.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-EraThingyForKinetaro.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Events.bytecode b/tests/baselines/advanced/graalx/weapon-Events.bytecode deleted file mode 100644 index b6bc2d7..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Events.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-FoodSys.bytecode b/tests/baselines/advanced/graalx/weapon-FoodSys.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-FoodSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Functions.bytecode b/tests/baselines/advanced/graalx/weapon-Functions.bytecode deleted file mode 100644 index a5dd8c0..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Functions.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Gang Control.bytecode b/tests/baselines/advanced/graalx/weapon-Gang Control.bytecode deleted file mode 100644 index 4f80a30..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Gang Control.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-GangSys.bytecode b/tests/baselines/advanced/graalx/weapon-GangSys.bytecode deleted file mode 100644 index aff1001..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-GangSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-GraalDB.bytecode b/tests/baselines/advanced/graalx/weapon-GraalDB.bytecode deleted file mode 100644 index 2b3e226..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-GraalDB.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Gravity.bytecode b/tests/baselines/advanced/graalx/weapon-Gravity.bytecode deleted file mode 100644 index f1db79b..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Gravity.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Gui.bytecode b/tests/baselines/advanced/graalx/weapon-Gui.bytecode deleted file mode 100644 index c238289..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Gui.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-HotelSys.bytecode b/tests/baselines/advanced/graalx/weapon-HotelSys.bytecode deleted file mode 100644 index dd70eaa..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-HotelSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Job Quests.bytecode b/tests/baselines/advanced/graalx/weapon-Job Quests.bytecode deleted file mode 100644 index 3178dfb..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Job Quests.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Map.bytecode b/tests/baselines/advanced/graalx/weapon-Map.bytecode deleted file mode 100644 index 7616234..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Map.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Minimap.bytecode b/tests/baselines/advanced/graalx/weapon-Minimap.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Minimap.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Movement.bytecode b/tests/baselines/advanced/graalx/weapon-Movement.bytecode deleted file mode 100644 index 7761a2a..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Movement.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Movement2.bytecode b/tests/baselines/advanced/graalx/weapon-Movement2.bytecode deleted file mode 100644 index bb27fa9..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Movement2.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-NBuySys.bytecode b/tests/baselines/advanced/graalx/weapon-NBuySys.bytecode deleted file mode 100644 index e8416be..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-NBuySys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-NewGangSys.bytecode b/tests/baselines/advanced/graalx/weapon-NewGangSys.bytecode deleted file mode 100644 index 1eb36aa..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-NewGangSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-NewMovement.bytecode b/tests/baselines/advanced/graalx/weapon-NewMovement.bytecode deleted file mode 100644 index 473ef3d..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-NewMovement.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-NewWeather.bytecode b/tests/baselines/advanced/graalx/weapon-NewWeather.bytecode deleted file mode 100644 index 57043df..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-NewWeather.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-News.bytecode b/tests/baselines/advanced/graalx/weapon-News.bytecode deleted file mode 100644 index 4c1672d..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-News.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Profile.bytecode b/tests/baselines/advanced/graalx/weapon-Profile.bytecode deleted file mode 100644 index 3447da1..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Profile.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-QMenu.bytecode b/tests/baselines/advanced/graalx/weapon-QMenu.bytecode deleted file mode 100644 index 814219b..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-QMenu.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Shake.bytecode b/tests/baselines/advanced/graalx/weapon-Shake.bytecode deleted file mode 100644 index 7dae52b..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Shake.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Staff.bytecode b/tests/baselines/advanced/graalx/weapon-Staff.bytecode deleted file mode 100644 index be8aa62..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Staff.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Staff.json b/tests/baselines/advanced/graalx/weapon-Staff.json index 74f1edc..7224267 100644 --- a/tests/baselines/advanced/graalx/weapon-Staff.json +++ b/tests/baselines/advanced/graalx/weapon-Staff.json @@ -1,12 +1,12 @@ { - "bytecode_hash": "8d9de00d12d7c11ed6eec85528a4939471dc64f8b5e6d76fe9c40aaf6603f817", + "bytecode_hash": "d912c4267dc566d2862eb3fb34dc12091e7c963fbc5285a53aae79d316f04d09", "bytecode_size": 1086, "compilation_success": true, "expected_failure": false, "error_message": "", "metadata": { "script_path": "advanced/graalx/weapon-Staff.gs2", - "generated_at": "2026-01-04 18:39:05", - "compiler_version": "modified_1767569912" + "generated_at": "2026-02-23 11:42:03", + "compiler_version": "modified_1771863608" } } \ No newline at end of file diff --git a/tests/baselines/advanced/graalx/weapon-StaffTool.bytecode b/tests/baselines/advanced/graalx/weapon-StaffTool.bytecode deleted file mode 100644 index 4cc87ce..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-StaffTool.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-System.bytecode b/tests/baselines/advanced/graalx/weapon-System.bytecode deleted file mode 100644 index 9961802..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-System.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Vault.bytecode b/tests/baselines/advanced/graalx/weapon-Vault.bytecode deleted file mode 100644 index cec1170..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Vault.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Virus.bytecode b/tests/baselines/advanced/graalx/weapon-Virus.bytecode deleted file mode 100644 index 4c28328..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Virus.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weapon-Weather.bytecode b/tests/baselines/advanced/graalx/weapon-Weather.bytecode deleted file mode 100644 index be3a740..0000000 Binary files a/tests/baselines/advanced/graalx/weapon-Weather.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponBackups_Radio.bytecode b/tests/baselines/advanced/graalx/weaponBackups_Radio.bytecode deleted file mode 100644 index db8f074..0000000 Binary files a/tests/baselines/advanced/graalx/weaponBackups_Radio.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponBrasas.bytecode b/tests/baselines/advanced/graalx/weaponBrasas.bytecode deleted file mode 100644 index 36e6930..0000000 Binary files a/tests/baselines/advanced/graalx/weaponBrasas.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponEvents_Lazer.bytecode b/tests/baselines/advanced/graalx/weaponEvents_Lazer.bytecode deleted file mode 100644 index 43f22cb..0000000 Binary files a/tests/baselines/advanced/graalx/weaponEvents_Lazer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponEvents_Zombie.bytecode b/tests/baselines/advanced/graalx/weaponEvents_Zombie.bytecode deleted file mode 100644 index 8d33c63..0000000 Binary files a/tests/baselines/advanced/graalx/weaponEvents_Zombie.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponFileEditor.bytecode b/tests/baselines/advanced/graalx/weaponFileEditor.bytecode deleted file mode 100644 index e9861bd..0000000 Binary files a/tests/baselines/advanced/graalx/weaponFileEditor.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponFrankie_Test.bytecode b/tests/baselines/advanced/graalx/weaponFrankie_Test.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponFrankie_Test.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_ATM Card.bytecode b/tests/baselines/advanced/graalx/weaponItems_ATM Card.bytecode deleted file mode 100644 index 5be12c3..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_ATM Card.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Body Armor.bytecode b/tests/baselines/advanced/graalx/weaponItems_Body Armor.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Body Armor.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Boots.bytecode b/tests/baselines/advanced/graalx/weaponItems_Boots.bytecode deleted file mode 100644 index 31125fd..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Boots.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Chemicals.bytecode b/tests/baselines/advanced/graalx/weaponItems_Chemicals.bytecode deleted file mode 100644 index 339c139..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Chemicals.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Cure Virus.bytecode b/tests/baselines/advanced/graalx/weaponItems_Cure Virus.bytecode deleted file mode 100644 index c96bb5c..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Cure Virus.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Land Mine.bytecode b/tests/baselines/advanced/graalx/weaponItems_Land Mine.bytecode deleted file mode 100644 index 16c9fbd..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Land Mine.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Medkit.bytecode b/tests/baselines/advanced/graalx/weaponItems_Medkit.bytecode deleted file mode 100644 index e536960..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Medkit.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponItems_Suit Saver.bytecode b/tests/baselines/advanced/graalx/weaponItems_Suit Saver.bytecode deleted file mode 100644 index 651690a..0000000 Binary files a/tests/baselines/advanced/graalx/weaponItems_Suit Saver.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Fishing Rod.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Fishing Rod.bytecode deleted file mode 100644 index d8bdd21..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Fishing Rod.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Mining Axe.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Mining Axe.bytecode deleted file mode 100644 index 8583cc5..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Mining Axe.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Mining TNT.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Mining TNT.bytecode deleted file mode 100644 index bfbd492..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Mining TNT.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Roller.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Roller.bytecode deleted file mode 100644 index 3eef17e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Roller.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Seeds.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Seeds.bytecode deleted file mode 100644 index ef653a2..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Seeds.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Shovel.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Shovel.bytecode deleted file mode 100644 index fe6b1ee..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Shovel.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Stack.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Stack.bytecode deleted file mode 100644 index 278ce02..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Stack.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponJobs_Water Can.bytecode b/tests/baselines/advanced/graalx/weaponJobs_Water Can.bytecode deleted file mode 100644 index 0ff27da..0000000 Binary files a/tests/baselines/advanced/graalx/weaponJobs_Water Can.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponKinetaro.bytecode b/tests/baselines/advanced/graalx/weaponKinetaro.bytecode deleted file mode 100644 index 68e2a5b..0000000 Binary files a/tests/baselines/advanced/graalx/weaponKinetaro.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponKuJi_Items.bytecode b/tests/baselines/advanced/graalx/weaponKuJi_Items.bytecode deleted file mode 100644 index 503467f..0000000 Binary files a/tests/baselines/advanced/graalx/weaponKuJi_Items.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponKuJi_Staff.bytecode b/tests/baselines/advanced/graalx/weaponKuJi_Staff.bytecode deleted file mode 100644 index 45bbe42..0000000 Binary files a/tests/baselines/advanced/graalx/weaponKuJi_Staff.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponKuJi_Tool.bytecode b/tests/baselines/advanced/graalx/weaponKuJi_Tool.bytecode deleted file mode 100644 index df1b39a..0000000 Binary files a/tests/baselines/advanced/graalx/weaponKuJi_Tool.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponKuJi_Tool.json b/tests/baselines/advanced/graalx/weaponKuJi_Tool.json index 9843350..6358548 100644 --- a/tests/baselines/advanced/graalx/weaponKuJi_Tool.json +++ b/tests/baselines/advanced/graalx/weaponKuJi_Tool.json @@ -1,12 +1,12 @@ { - "bytecode_hash": "64a4f297366dc3e6a2dd3bc2b6d5604ef571a9ec44a66e49f8f779cfeca63188", + "bytecode_hash": "c46a46e4c913c4a39fcdd6f728553d7c94da6d89c79f3be87dfebf6278fbc322", "bytecode_size": 1374, "compilation_success": true, "expected_failure": false, "error_message": "", "metadata": { "script_path": "advanced/graalx/weaponKuJi_Tool.gs2", - "generated_at": "2026-01-04 18:39:04", - "compiler_version": "modified_1767569912" + "generated_at": "2026-02-23 11:42:03", + "compiler_version": "modified_1771863608" } } \ No newline at end of file diff --git a/tests/baselines/advanced/graalx/weaponLevelEditor.bytecode b/tests/baselines/advanced/graalx/weaponLevelEditor.bytecode deleted file mode 100644 index 5139412..0000000 Binary files a/tests/baselines/advanced/graalx/weaponLevelEditor.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponLevelGen.bytecode b/tests/baselines/advanced/graalx/weaponLevelGen.bytecode deleted file mode 100644 index 1aa5c9f..0000000 Binary files a/tests/baselines/advanced/graalx/weaponLevelGen.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponNotepad.bytecode b/tests/baselines/advanced/graalx/weaponNotepad.bytecode deleted file mode 100644 index 732a322..0000000 Binary files a/tests/baselines/advanced/graalx/weaponNotepad.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRC_AttributesWindow.bytecode b/tests/baselines/advanced/graalx/weaponRC_AttributesWindow.bytecode deleted file mode 100644 index 6c8fd6e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRC_AttributesWindow.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRC_NCControl.bytecode b/tests/baselines/advanced/graalx/weaponRC_NCControl.bytecode deleted file mode 100644 index 9a348bc..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRC_NCControl.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRC_RightsWindow.bytecode b/tests/baselines/advanced/graalx/weaponRC_RightsWindow.bytecode deleted file mode 100644 index 6afa025..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRC_RightsWindow.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRWA_Plane.bytecode b/tests/baselines/advanced/graalx/weaponRWA_Plane.bytecode deleted file mode 100644 index 6ed02af..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRWA_Plane.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRadio.bytecode b/tests/baselines/advanced/graalx/weaponRadio.bytecode deleted file mode 100644 index 64ac3a8..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRadio.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRemoteControl.bytecode b/tests/baselines/advanced/graalx/weaponRemoteControl.bytecode deleted file mode 100644 index 5f4a583..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRemoteControl.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponRock Throw.bytecode b/tests/baselines/advanced/graalx/weaponRock Throw.bytecode deleted file mode 100644 index 4674ccc..0000000 Binary files a/tests/baselines/advanced/graalx/weaponRock Throw.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponStaff_Axe.bytecode b/tests/baselines/advanced/graalx/weaponStaff_Axe.bytecode deleted file mode 100644 index 6daae06..0000000 Binary files a/tests/baselines/advanced/graalx/weaponStaff_Axe.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_ArchetypeEditor.bytecode b/tests/baselines/advanced/graalx/weaponSystems_ArchetypeEditor.bytecode deleted file mode 100644 index 1aa5c9f..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_ArchetypeEditor.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_B2.bytecode b/tests/baselines/advanced/graalx/weaponSystems_B2.bytecode deleted file mode 100644 index e7336f4..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_B2.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_BackupSys.bytecode b/tests/baselines/advanced/graalx/weaponSystems_BackupSys.bytecode deleted file mode 100644 index f9ce161..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_BackupSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_FoodSys.bytecode b/tests/baselines/advanced/graalx/weaponSystems_FoodSys.bytecode deleted file mode 100644 index 9094f77..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_FoodSys.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_Free.bytecode b/tests/baselines/advanced/graalx/weaponSystems_Free.bytecode deleted file mode 100644 index a18a2ae..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_Free.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_IRC.bytecode b/tests/baselines/advanced/graalx/weaponSystems_IRC.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_IRC.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_Mail.bytecode b/tests/baselines/advanced/graalx/weaponSystems_Mail.bytecode deleted file mode 100644 index 0aa0001..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_Mail.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_Party.bytecode b/tests/baselines/advanced/graalx/weaponSystems_Party.bytecode deleted file mode 100644 index acbfc12..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_Party.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.bytecode b/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.bytecode deleted file mode 100644 index 39742bb..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.json b/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.json index 8a3bf6e..966ecbf 100644 --- a/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.json +++ b/tests/baselines/advanced/graalx/weaponSystems_TradeMenu.json @@ -1,12 +1,12 @@ { - "bytecode_hash": "245b71c36dc7914792d724dbd4230cb4f3e9b2e7aacf1efcdfb9edbf4f0f795d", + "bytecode_hash": "c3c690e34dabeddc94837e2aee7421803781603f085c3789fa1476afe2aacfff", "bytecode_size": 684, "compilation_success": true, "expected_failure": false, "error_message": "", "metadata": { "script_path": "advanced/graalx/weaponSystems_TradeMenu.gs2", - "generated_at": "2026-01-04 18:39:04", - "compiler_version": "modified_1767569912" + "generated_at": "2026-02-23 11:42:03", + "compiler_version": "modified_1771863608" } } \ No newline at end of file diff --git a/tests/baselines/advanced/graalx/weaponSystems_Vote.bytecode b/tests/baselines/advanced/graalx/weaponSystems_Vote.bytecode deleted file mode 100644 index 487fe62..0000000 Binary files a/tests/baselines/advanced/graalx/weaponSystems_Vote.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponTig_NPC.bytecode b/tests/baselines/advanced/graalx/weaponTig_NPC.bytecode deleted file mode 100644 index aa1250a..0000000 Binary files a/tests/baselines/advanced/graalx/weaponTig_NPC.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponToys_CDPlayer.bytecode b/tests/baselines/advanced/graalx/weaponToys_CDPlayer.bytecode deleted file mode 100644 index 7bd3f08..0000000 Binary files a/tests/baselines/advanced/graalx/weaponToys_CDPlayer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponToys_GameEngine.bytecode b/tests/baselines/advanced/graalx/weaponToys_GameEngine.bytecode deleted file mode 100644 index 0040385..0000000 Binary files a/tests/baselines/advanced/graalx/weaponToys_GameEngine.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponToys_gPod.bytecode b/tests/baselines/advanced/graalx/weaponToys_gPod.bytecode deleted file mode 100644 index f7bc65f..0000000 Binary files a/tests/baselines/advanced/graalx/weaponToys_gPod.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponTwinny_Tool.bytecode b/tests/baselines/advanced/graalx/weaponTwinny_Tool.bytecode deleted file mode 100644 index c063385..0000000 Binary files a/tests/baselines/advanced/graalx/weaponTwinny_Tool.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponVote.bytecode b/tests/baselines/advanced/graalx/weaponVote.bytecode deleted file mode 100644 index 26b8c2c..0000000 Binary files a/tests/baselines/advanced/graalx/weaponVote.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponVulcan.bytecode b/tests/baselines/advanced/graalx/weaponVulcan.bytecode deleted file mode 100644 index 43d1453..0000000 Binary files a/tests/baselines/advanced/graalx/weaponVulcan.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponWeapons_Grenade.bytecode b/tests/baselines/advanced/graalx/weaponWeapons_Grenade.bytecode deleted file mode 100644 index 9fc8a5e..0000000 Binary files a/tests/baselines/advanced/graalx/weaponWeapons_Grenade.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/graalx/weaponWeapons_Hand Cuffs.bytecode b/tests/baselines/advanced/graalx/weaponWeapons_Hand Cuffs.bytecode deleted file mode 100644 index 6c06217..0000000 Binary files a/tests/baselines/advanced/graalx/weaponWeapons_Hand Cuffs.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Adventure.bytecode b/tests/baselines/advanced/loginserver/weapon-Adventure.bytecode deleted file mode 100644 index 22b3039..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Adventure.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-IRC_Installer.bytecode b/tests/baselines/advanced/loginserver/weapon-IRC_Installer.bytecode deleted file mode 100644 index f39ee19..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-IRC_Installer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-IRC_Login4.bytecode b/tests/baselines/advanced/loginserver/weapon-IRC_Login4.bytecode deleted file mode 100644 index b977575..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-IRC_Login4.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-LoginScreen.bytecode b/tests/baselines/advanced/loginserver/weapon-LoginScreen.bytecode deleted file mode 100644 index e657018..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-LoginScreen.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-ReShared.bytecode b/tests/baselines/advanced/loginserver/weapon-ReShared.bytecode deleted file mode 100644 index c3028b6..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-ReShared.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_-F2LogWindow.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_-F2LogWindow.bytecode deleted file mode 100644 index 1154c99..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_-F2LogWindow.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2.bytecode deleted file mode 100644 index fa9515b..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2001.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2001.bytecode deleted file mode 100644 index 731056c..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login2001.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login3.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login3.bytecode deleted file mode 100644 index 6dc6017..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login3.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login4.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login4.bytecode deleted file mode 100644 index 8dc813c..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_IRC_Login4.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Rescripted_Serverlist.bytecode b/tests/baselines/advanced/loginserver/weapon-Rescripted_Serverlist.bytecode deleted file mode 100644 index 00b96fc..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Rescripted_Serverlist.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-ServerListScreen.bytecode b/tests/baselines/advanced/loginserver/weapon-ServerListScreen.bytecode deleted file mode 100644 index 7054855..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-ServerListScreen.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Serverlist_Patches.bytecode b/tests/baselines/advanced/loginserver/weapon-Serverlist_Patches.bytecode deleted file mode 100644 index c72c7d3..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Serverlist_Patches.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Staff_GUIExplorer.bytecode b/tests/baselines/advanced/loginserver/weapon-Staff_GUIExplorer.bytecode deleted file mode 100644 index 74a4190..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Staff_GUIExplorer.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-Staff_GraalShop.bytecode b/tests/baselines/advanced/loginserver/weapon-Staff_GraalShop.bytecode deleted file mode 100644 index f467cc1..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-Staff_GraalShop.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weapon-StartConnectMessage.bytecode b/tests/baselines/advanced/loginserver/weapon-StartConnectMessage.bytecode deleted file mode 100644 index dddcfc1..0000000 Binary files a/tests/baselines/advanced/loginserver/weapon-StartConnectMessage.bytecode and /dev/null differ diff --git a/tests/baselines/advanced/loginserver/weaponTestScript.bytecode b/tests/baselines/advanced/loginserver/weaponTestScript.bytecode deleted file mode 100644 index e7fd8aa..0000000 Binary files a/tests/baselines/advanced/loginserver/weaponTestScript.bytecode and /dev/null differ diff --git a/tests/baselines/basic/01_variables.bytecode b/tests/baselines/basic/01_variables.bytecode deleted file mode 100644 index 8d06b75..0000000 Binary files a/tests/baselines/basic/01_variables.bytecode and /dev/null differ diff --git a/tests/baselines/basic/02_constants.bytecode b/tests/baselines/basic/02_constants.bytecode deleted file mode 100644 index 56700b0..0000000 Binary files a/tests/baselines/basic/02_constants.bytecode and /dev/null differ diff --git a/tests/baselines/basic/03_data_types.bytecode b/tests/baselines/basic/03_data_types.bytecode deleted file mode 100644 index ca306be..0000000 Binary files a/tests/baselines/basic/03_data_types.bytecode and /dev/null differ diff --git a/tests/baselines/classes/01_objects.bytecode b/tests/baselines/classes/01_objects.bytecode deleted file mode 100644 index 6f0c209..0000000 Binary files a/tests/baselines/classes/01_objects.bytecode and /dev/null differ diff --git a/tests/baselines/classes/02_arrays.bytecode b/tests/baselines/classes/02_arrays.bytecode deleted file mode 100644 index 67bec6a..0000000 Binary files a/tests/baselines/classes/02_arrays.bytecode and /dev/null differ diff --git a/tests/baselines/edge_cases/01_large_numbers.bytecode b/tests/baselines/edge_cases/01_large_numbers.bytecode deleted file mode 100644 index 3441041..0000000 Binary files a/tests/baselines/edge_cases/01_large_numbers.bytecode and /dev/null differ diff --git a/tests/baselines/edge_cases/02_long_strings.bytecode b/tests/baselines/edge_cases/02_long_strings.bytecode deleted file mode 100644 index 623226a..0000000 Binary files a/tests/baselines/edge_cases/02_long_strings.bytecode and /dev/null differ diff --git a/tests/baselines/edge_cases/03_deep_nesting.bytecode b/tests/baselines/edge_cases/03_deep_nesting.bytecode deleted file mode 100644 index 88812d7..0000000 Binary files a/tests/baselines/edge_cases/03_deep_nesting.bytecode and /dev/null differ diff --git a/tests/baselines/expressions/01_arithmetic.bytecode b/tests/baselines/expressions/01_arithmetic.bytecode deleted file mode 100644 index 88b84eb..0000000 Binary files a/tests/baselines/expressions/01_arithmetic.bytecode and /dev/null differ diff --git a/tests/baselines/expressions/02_comparison.bytecode b/tests/baselines/expressions/02_comparison.bytecode deleted file mode 100644 index 152e2d9..0000000 Binary files a/tests/baselines/expressions/02_comparison.bytecode and /dev/null differ diff --git a/tests/baselines/expressions/03_logical.bytecode b/tests/baselines/expressions/03_logical.bytecode deleted file mode 100644 index 98d43a4..0000000 Binary files a/tests/baselines/expressions/03_logical.bytecode and /dev/null differ diff --git a/tests/baselines/expressions/04_bitwise.bytecode b/tests/baselines/expressions/04_bitwise.bytecode deleted file mode 100644 index 63e32d2..0000000 Binary files a/tests/baselines/expressions/04_bitwise.bytecode and /dev/null differ diff --git a/tests/baselines/expressions/05_assignment.bytecode b/tests/baselines/expressions/05_assignment.bytecode deleted file mode 100644 index 1ab5928..0000000 Binary files a/tests/baselines/expressions/05_assignment.bytecode and /dev/null differ diff --git a/tests/baselines/functions/01_basic_functions.bytecode b/tests/baselines/functions/01_basic_functions.bytecode deleted file mode 100644 index 3645f37..0000000 Binary files a/tests/baselines/functions/01_basic_functions.bytecode and /dev/null differ diff --git a/tests/baselines/functions/02_recursion.bytecode b/tests/baselines/functions/02_recursion.bytecode deleted file mode 100644 index f3ca061..0000000 Binary files a/tests/baselines/functions/02_recursion.bytecode and /dev/null differ diff --git a/tests/baselines/functions/03_lambdas.bytecode b/tests/baselines/functions/03_lambdas.bytecode deleted file mode 100644 index b4fb787..0000000 Binary files a/tests/baselines/functions/03_lambdas.bytecode and /dev/null differ diff --git a/tests/baselines/functions/04_prejump_grouping.json b/tests/baselines/functions/04_prejump_grouping.json new file mode 100644 index 0000000..3a733d3 --- /dev/null +++ b/tests/baselines/functions/04_prejump_grouping.json @@ -0,0 +1,12 @@ +{ + "bytecode_hash": "d9621d9a021b2e3ef1e6db3ae2f413183afb9f3f2f34ac8cb79c475cd575d2d8", + "bytecode_size": 250, + "compilation_success": true, + "expected_failure": false, + "error_message": "", + "metadata": { + "script_path": "functions/04_prejump_grouping.gs2", + "generated_at": "2026-02-23 11:55:54", + "compiler_version": "modified_1771863608" + } +} \ No newline at end of file diff --git a/tests/baselines/statements/01_conditionals.bytecode b/tests/baselines/statements/01_conditionals.bytecode deleted file mode 100644 index 49672dd..0000000 Binary files a/tests/baselines/statements/01_conditionals.bytecode and /dev/null differ diff --git a/tests/baselines/statements/02_loops.bytecode b/tests/baselines/statements/02_loops.bytecode deleted file mode 100644 index 97d86ea..0000000 Binary files a/tests/baselines/statements/02_loops.bytecode and /dev/null differ diff --git a/tests/baselines/statements/03_switch.bytecode b/tests/baselines/statements/03_switch.bytecode deleted file mode 100644 index 41a77d6..0000000 Binary files a/tests/baselines/statements/03_switch.bytecode and /dev/null differ diff --git a/tests/baselines/statements/04_with.bytecode b/tests/baselines/statements/04_with.bytecode deleted file mode 100644 index f7f192d..0000000 Binary files a/tests/baselines/statements/04_with.bytecode and /dev/null differ diff --git a/tests/scripts/functions/04_prejump_grouping.gs2 b/tests/scripts/functions/04_prejump_grouping.gs2 new file mode 100644 index 0000000..7755a87 --- /dev/null +++ b/tests/scripts/functions/04_prejump_grouping.gs2 @@ -0,0 +1,18 @@ +function onCreated() { + temp.x = 1; +} + +function onTimeout() { + temp.y = 2; +} + +temp.startup = "initialized"; +echo("between groups"); + +function onPlayerEnters() { + temp.z = 3; +} + +function onPlayerLeaves() { + temp.w = 4; +} diff --git a/tests/tools/run_tests.py b/tests/tools/run_tests.py index b6e3afc..c517864 100755 --- a/tests/tools/run_tests.py +++ b/tests/tools/run_tests.py @@ -177,7 +177,7 @@ def _save_baseline(self, script_path: Path, success: bool, bytecode: bytes, erro bytecode_size=len(bytecode), compilation_success=success, expected_failure=expected_failure, - error_message=error_message, + error_message=error_message if not success else "", metadata={ "script_path": str(script_path.relative_to(self.scripts_dir)), "generated_at": time.strftime("%Y-%m-%d %H:%M:%S"), @@ -194,6 +194,17 @@ def _save_baseline(self, script_path: Path, success: bool, bytecode: bytes, erro with open(bytecode_path, 'wb') as f: f.write(bytecode) + def _baseline_matches_result(self, baseline: BaselineData, success: bool, bytecode: bytes, + error_message: str, expected_failure: bool) -> bool: + """Check whether baseline data already matches a compilation result.""" + bytecode_hash = hashlib.sha256(bytecode).hexdigest() if bytecode else "" + return ( + baseline.bytecode_hash == bytecode_hash + and baseline.bytecode_size == len(bytecode) + and baseline.compilation_success == success + and baseline.expected_failure == expected_failure + ) + def _load_baseline(self, script_path: Path) -> Optional[BaselineData]: """Load baseline data for a script""" baseline_path = self._get_baseline_path(script_path) @@ -291,7 +302,8 @@ def run_all_tests(self, category: Optional[str] = None, update_baselines: bool = "total_tests": len(script_files), "passed": 0, "failed": 0, - "expected_failures": 0 + "expected_failures": 0, + "changed": 0 }, "tests": [], "regressions": [], @@ -333,12 +345,18 @@ def run_all_tests(self, category: Optional[str] = None, update_baselines: bool = should_save_baseline = success or expected_failure if should_save_baseline: - self._save_baseline(script_path, success, bytecode, error_message) - if baseline is None: - results["new_tests"].append(test_info) - print(f" -> Created new baseline") + if baseline is not None and self._baseline_matches_result( + baseline, success, bytecode, error_message, expected_failure + ): + print(f" -> Baseline unchanged") else: - print(f" -> Updated baseline") + self._save_baseline(script_path, success, bytecode, error_message) + if baseline is None: + results["new_tests"].append(test_info) + print(f" -> Created new baseline") + else: + results["summary"]["changed"] += 1 + print(f" -> Updated baseline") elif baseline is None: print(f" -> Skipping baseline creation (test failed)") elif baseline: @@ -445,6 +463,7 @@ def main(): print(f" Expected Failures: {summary['expected_failures']}") print(f" Regressions: {len(results['regressions'])}") print(f" New Tests: {len(results['new_tests'])}") + print(f" Changed Tests: {summary['changed']}") print(f" Execution Time: {results['execution_time']:.2f}s") print(f" Report saved to: {report_file}") @@ -485,4 +504,4 @@ def main(): sys.exit(3) if __name__ == "__main__": - main() \ No newline at end of file + main()