diff --git a/CHANGELOG.md b/CHANGELOG.md index 22d131ad..84e33d0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - the repl prints the output of the last expression it ran - new super instructions: `MUL_BY`, `MUL_BY_INDEX`, `MUL_SET_VAL` that can do multiplications (and optional storing in vars) in place - new super instruction: `FUSED_MATH`, which can fuse 2 to 3 math operations in one go (ADD, SUB, MUL, DIV) +- new `LOAD_SYMBOL` instruction that avoids creating a reference ### Fixed - the REPL doesn't color `import` in two colors (red for `imp__t` and blue for `___or_`), it keeps the first color that matched (red for import here) @@ -16,6 +17,7 @@ - `empty?` now accepts `nil` and returns `true` for this value - the REPL adds `(repl:history)` and `(repl:save filename)` as builtins - the REPL attempts to load a file from `ARKSCRIPT_REPL_STARTUP` environment variable, to preload code +- rename LOAD_SYMBOL and LOAD_SYMBOL_BY_INDEX to LOAD_FAST and LOAD_FAST_BY_INDEX to emphasize they load refs ### Removed @@ -83,11 +85,11 @@ - new operator `@@` to get elements in list of lists / list of strings - new builtin `random`, returning a random number between INT_MIN and INT_MAX, or in a custom range - `$as-is` to paste a node inside a maro without evaluating it further ; useful to stop recursive evaluation of nodes inside function macros -- `LOAD_SYMBOL_BY_INDEX` instruction, loading a local from the current scope by an index (0 being the last element added to the scope) +- `LOAD_FAST_BY_INDEX` instruction, loading a local from the current scope by an index (0 being the last element added to the scope) - `STORE_FROM_INDEX` and `SET_VAL_FROM_INDEX` instructions for parity with the super instructions not using load by index - `INCREMENT_BY_INDEX` and `DECREMENT_BY_INDEX` instructions for parity with the super instructions not using load by index - `STORE_TAIL_BY_INDEX`, `STORE_HEAD_BY_INDEX`, `SET_VAL_TAIL_BY_INDEX`, `SET_VAL_HEAD_BY_INDEX` super instructions added for parity with the super instructions not using load by index -- `RESET_SCOPE_JUMP` instruction emitted at the end of a while loop to reset a scope so that we can create multiple variables and use `LOAD_SYMBOL_BY_INDEX` +- `RESET_SCOPE_JUMP` instruction emitted at the end of a while loop to reset a scope so that we can create multiple variables and use `LOAD_FAST_BY_INDEX` - instruction source location ; two new bytecode tables were added: one for filenames, another for (page pointer, instruction pointer, file id, line), allowing the VM to display better error messages when the source is available - show source location when a runtime error is thrown in the VM - `LT_CONST_JUMP_IF_FALSE` and `LT_SYM_JUMP_IF_FALSE` to compare a symbol to a const and a symbol to a symbol (respectively), then jump to an address if false (useful for while loops that check a simple `(< x n)` condition) @@ -185,7 +187,7 @@ - magic numbers for value types in bytecode files have been changed from 0x01, 0x02, 0x03 to 0xF1, 0xF2, 0xF3 (number, string, function) - numbers in the values table in bytecode files are no longer turned to string, but their IEEE754 representation is now encoded on 12 bytes (4 for the exponent, 8 for the mantissa) - changed how scopes are stored inside the VM to enhance performances. All scope data are now contiguous! -- when possible, accessing variables from the current scope is compiled to a new instruction `LOAD_SYMBOL_BY_INDEX`, to avoid the sometimes expansive lookup by id +- when possible, accessing variables from the current scope is compiled to a new instruction `LOAD_FAST_BY_INDEX`, to avoid the sometimes expansive lookup by id - this works inside normal scopes (introduced by while loops) and functions scopes, but not for closures - VM stack size is now 4096 instead of 8192 - `Ark::CodeError` now takes a `CodeErrorContext` to store the source (filename, line, column, expression) of an error diff --git a/include/Ark/Compiler/Instructions.hpp b/include/Ark/Compiler/Instructions.hpp index bfd426fe..94c460b7 100644 --- a/include/Ark/Compiler/Instructions.hpp +++ b/include/Ark/Compiler/Instructions.hpp @@ -37,421 +37,426 @@ namespace Ark::internal INST_LOC_TABLE_START = 0xA5, // @args symbol id - // @role Load a symbol from its ID onto the stack - LOAD_SYMBOL = 0x01, + // @role Load a symbol from its ID onto the stack, as a reference unless it's already one + LOAD_FAST = 0x01, // @args stack index - // @role Load a symbol from the locals stack by its index (starting from the end of the current scope) - LOAD_SYMBOL_BY_INDEX = 0x02, + // @role Load a symbol from the locals stack by its index (starting from the end of the current scope), as a reference unless it's already one + LOAD_FAST_BY_INDEX = 0x02, + + // @args symbol id + // @role Load a symbol from its ID onto the stack, avoiding the creation of a reference + LOAD_SYMBOL = 0x03, // @args constant id // @role Load a constant from its ID onto the stack - LOAD_CONST = 0x03, + LOAD_CONST = 0x04, // @args absolute address to jump to // @role Jump to the provided address if the last value on the stack was equal to true. Remove the value from the stack no matter what it is - POP_JUMP_IF_TRUE = 0x04, + POP_JUMP_IF_TRUE = 0x05, // @args symbol id // @role Take the value on top of the stack and create a variable in the current scope, named following the given symbol id (cf symbols table) - STORE = 0x05, + STORE = 0x06, // @args symbol id // @role Store a value in a symbol without dereferencing it (used by functions only) - STORE_REF = 0x06, + STORE_REF = 0x07, // @args symbol id // @role Take the value on top of the stack and put it inside a variable named following the symbol id (cf symbols table), in the nearest scope. Raise an error if it couldn't find a scope where the variable exists - SET_VAL = 0x07, + SET_VAL = 0x08, // @args absolute address to jump to // @role Jump to the provided address if the last value on the stack was equal to false. Remove the value from the stack no matter what it is - POP_JUMP_IF_FALSE = 0x08, + POP_JUMP_IF_FALSE = 0x09, // @args absolute address to jump to // @role Jump to the provided address - JUMP = 0x09, + JUMP = 0x0a, // @role If in a code segment other than the main one, quit it, and push the value on top of the stack to the new stack; should as well delete the current environment. Otherwise, acts as a `HALT` - RET = 0x0a, + RET = 0x0b, // @role Stop the Virtual Machine - HALT = 0x0b, + HALT = 0x0c, // @role push pp, then ip on the stack, preparing for a call instruction - PUSH_RETURN_ADDRESS = 0x0c, + PUSH_RETURN_ADDRESS = 0x0d, // @args argument count // @role Call function from its symbol id located on top of the stack. Take the given number of arguments from the top of stack and give them to the function (the first argument taken from the stack will be the last one of the function). The stack of the function is now composed of its arguments, from the first to the last one - CALL = 0x0d, + CALL = 0x0e, // @args symbol id // @role Tell the Virtual Machine to capture the variable from the current environment. Main goal is to be able to handle closures, which need to save the environment in which they were created - CAPTURE = 0x0e, + CAPTURE = 0x0f, // @args symbol id // @role Tell the VM to use the given symbol for the next capture - RENAME_NEXT_CAPTURE = 0x0f, + RENAME_NEXT_CAPTURE = 0x10, // @args builtin id // @role Push the corresponding builtin function object on the stack - BUILTIN = 0x10, + BUILTIN = 0x11, // @args symbol id // @role Remove a variable/constant named following the given symbol id (cf symbols table) - DEL = 0x11, + DEL = 0x12, // @args constant id // @role Push a Closure with the page address pointed by the constant, along with the saved scope created by CAPTURE instruction(s) - MAKE_CLOSURE = 0x12, + MAKE_CLOSURE = 0x13, // @args symbol id // @role Read the field named following the given symbol id (cf symbols table) of a `Closure` stored in TS. Pop TS and push the value of field read on the stack - GET_FIELD = 0x13, + GET_FIELD = 0x14, // @args constant id // @role Load a plugin dynamically, plugin name is stored as a string in the constants table - PLUGIN = 0x14, + PLUGIN = 0x15, // @args number of elements // @role Create a list from the N elements pushed on the stack. Follows the function calling convention - LIST = 0x15, + LIST = 0x16, // @args number of elements // @role Append N elements to a list (TS). Elements are stored in TS(1)..TS(N). Follows the function calling convention - APPEND = 0x16, + APPEND = 0x17, // @args number of elements // @role Concatenate N lists to a list (TS). Lists to concat to TS are stored in TS(1)..TS(N). Follows the function calling convention - CONCAT = 0x17, + CONCAT = 0x18, // @args number of elements // @role Append N elements to a reference to a list (TS), the list is being mutated in-place, no new object created. Elements are stored in TS(1)..TS(N). Follows the function calling convention - APPEND_IN_PLACE = 0x18, + APPEND_IN_PLACE = 0x19, // @args number of elements // @role Concatenate N lists to a reference to a list (TS), the list is being mutated in-place, no new object created. Lists to concat to TS are stored in TS(1)..TS(N). Follows the function calling convention - CONCAT_IN_PLACE = 0x19, + CONCAT_IN_PLACE = 0x1a, // @role Remove an element from a list (TS), given an index (TS1). Push a new list without the removed element to the stack - POP_LIST = 0x1a, + POP_LIST = 0x1b, // @role Remove an element from a reference to a list (TS), given an index (TS1). The list is mutated in-place, no new object created - POP_LIST_IN_PLACE = 0x1b, + POP_LIST_IN_PLACE = 0x1c, // @role Modify a reference to a list or string (TS) by replacing the element at TS1 (must be a number) by the value in TS2. The object is mutated in-place, no new object created - SET_AT_INDEX = 0x1c, + SET_AT_INDEX = 0x1d, // @role Modify a reference to a list (TS) by replacing TS[TS2][TS1] by the value in TS3. TS[TS2] can be a string (if it is, TS3 must be a string). The object is mutated in-place, no new object created - SET_AT_2_INDEX = 0x1d, + SET_AT_2_INDEX = 0x1e, // @role Remove the top of the stack - POP = 0x1e, + POP = 0x1f, // @role Pop the top of the stack, if it's false, jump to an address - SHORTCIRCUIT_AND = 0x1f, + SHORTCIRCUIT_AND = 0x20, // @role Pop the top of the stack, if it's true, jump to an address - SHORTCIRCUIT_OR = 0x20, + SHORTCIRCUIT_OR = 0x21, // @role Create a new local scope - CREATE_SCOPE = 0x21, + CREATE_SCOPE = 0x22, // @role Reset the current scope so that it is empty, and jump to a given location - RESET_SCOPE_JUMP = 0x22, + RESET_SCOPE_JUMP = 0x23, // @role Destroy the last local scope - POP_SCOPE = 0x23, + POP_SCOPE = 0x24, // @args symbol id (function name) // @role Push the current page address as a value on the stack - GET_CURRENT_PAGE_ADDR = 0x24, + GET_CURRENT_PAGE_ADDR = 0x25, - FIRST_OPERATOR = 0x25, + FIRST_OPERATOR = 0x26, // @role Push `TS1 + TS` - ADD = 0x25, + ADD = 0x26, // @role Push `TS1 - TS` - SUB = 0x26, + SUB = 0x27, // @role Push `TS1 * TS` - MUL = 0x27, + MUL = 0x28, // @role Push `TS1 / TS` - DIV = 0x28, + DIV = 0x29, // @role Push `TS1 > TS` - GT = 0x29, + GT = 0x2a, // @role Push `TS1 < TS` - LT = 0x2a, + LT = 0x2b, // @role Push `TS1 <= TS` - LE = 0x2b, + LE = 0x2c, // @role Push `TS1 >= TS` - GE = 0x2c, + GE = 0x2d, // @role Push `TS1 != TS` - NEQ = 0x2d, + NEQ = 0x2e, // @role Push `TS1 == TS` - EQ = 0x2e, + EQ = 0x2f, // @role Push `len(TS)`, TS must be a list - LEN = 0x2f, + LEN = 0x30, // @role Push `empty?(TS)`, TS must be a list or string - EMPTY = 0x30, + IS_EMPTY = 0x31, // @role Push `tail(TS)`, all the elements of TS except the first one. TS must be a list or string - TAIL = 0x31, + TAIL = 0x32, // @role Push `head(TS)`, the first element of TS or nil if empty. TS must be a list or string - HEAD = 0x32, + HEAD = 0x33, // @role Push true if TS is nil, false otherwise - ISNIL = 0x33, + IS_NIL = 0x34, // @role Throw an exception if TS1 is false, and display TS (must be a string). Do not push anything on the stack - ASSERT = 0x34, + ASSERT = 0x35, // @role Convert TS to number (must be a string) - TO_NUM = 0x35, + TO_NUM = 0x36, // @role Convert TS to string - TO_STR = 0x36, + TO_STR = 0x37, // @role Push the value at index TS (must be a number) in TS1, which must be a list or string - AT = 0x37, + AT = 0x38, // @role Push the value at index TS (must be a number), inside the list or string at index TS1 (must be a number) in the list at TS2 - AT_AT = 0x38, + AT_AT = 0x39, // @role Push `TS1 % TS` - MOD = 0x39, + MOD = 0x3a, // @role Push the type of TS as a string - TYPE = 0x3a, + TYPE = 0x3b, // @role Check if TS1 is a closure field of TS. TS must be a Closure, TS1 a String - HASFIELD = 0x3b, + HAS_FIELD = 0x3c, // @role Push `!TS` - NOT = 0x3c, + NOT = 0x3d, // @args constant id, constant id // @role Load two consts (`primary` then `secondary`) on the stack in one instruction - LOAD_CONST_LOAD_CONST = 0x3d, + LOAD_CONST_LOAD_CONST = 0x3e, // @args constant id, symbol id // @role Load const `primary` into the symbol `secondary` (create a variable) - LOAD_CONST_STORE = 0x3e, + LOAD_CONST_STORE = 0x3f, // @args constant id, symbol id // @role Load const `primary` into the symbol `secondary` (search for the variable with the given symbol id) - LOAD_CONST_SET_VAL = 0x3f, + LOAD_CONST_SET_VAL = 0x40, // @args symbol id, symbol id // @role Store the value of the symbol `primary` into a new variable `secondary` - STORE_FROM = 0x40, + STORE_FROM = 0x41, // @args symbol index, symbol id // @role Store the value of the symbol `primary` into a new variable `secondary` - STORE_FROM_INDEX = 0x41, + STORE_FROM_INDEX = 0x42, // @args symbol id, symbol id // @role Store the value of the symbol `primary` into an existing variable `secondary` - SET_VAL_FROM = 0x42, + SET_VAL_FROM = 0x43, // @args symbol index, symbol id // @role Store the value of the symbol `primary` into an existing variable `secondary` - SET_VAL_FROM_INDEX = 0x43, + SET_VAL_FROM_INDEX = 0x44, // @args symbol id, count // @role Increment the variable `primary` by `count` and push its value on the stack - INCREMENT = 0x44, + INCREMENT = 0x45, // @args symbol index, count // @role Increment the variable `primary` by `count` and push its value on the stack - INCREMENT_BY_INDEX = 0x45, + INCREMENT_BY_INDEX = 0x46, // @args symbol id, count // @role Increment the variable `primary` by `count` and store its value in the given symbol id - INCREMENT_STORE = 0x46, + INCREMENT_STORE = 0x47, // @args symbol id, count // @role Decrement the variable `primary` by `count` and push its value on the stack - DECREMENT = 0x47, + DECREMENT = 0x48, // @args symbol index, count // @role Decrement the variable `primary` by `count` and push its value on the stack - DECREMENT_BY_INDEX = 0x48, + DECREMENT_BY_INDEX = 0x49, // @args symbol id, count // @role Decrement the variable `primary` by `count` and store its value in the given symbol id - DECREMENT_STORE = 0x49, + DECREMENT_STORE = 0x4a, // @args symbol id, symbol id // @role Load the symbol `primary`, compute its tail, store it in a new variable `secondary` - STORE_TAIL = 0x4a, + STORE_TAIL = 0x4b, // @args symbol index, symbol id // @role Load the symbol `primary`, compute its tail, store it in a new variable `secondary` - STORE_TAIL_BY_INDEX = 0x4b, + STORE_TAIL_BY_INDEX = 0x4c, // @args symbol id, symbol id // @role Load the symbol `primary`, compute its head, store it in a new variable `secondary` - STORE_HEAD = 0x4c, + STORE_HEAD = 0x4d, // @args symbol index, symbol id // @role Load the symbol `primary`, compute its head, store it in a new variable `secondary` - STORE_HEAD_BY_INDEX = 0x4d, + STORE_HEAD_BY_INDEX = 0x4e, // @args number, symbol id // @role Create a list of `number` elements, and store it in a new variable `secondary` - STORE_LIST = 0x4e, + STORE_LIST = 0x4f, // @args symbol id, symbol id // @role Load the symbol `primary`, compute its tail, store it in an existing variable `secondary` - SET_VAL_TAIL = 0x4f, + SET_VAL_TAIL = 0x50, // @args symbol index, symbol id // @role Load the symbol `primary`, compute its tail, store it in an existing variable `secondary` - SET_VAL_TAIL_BY_INDEX = 0x50, + SET_VAL_TAIL_BY_INDEX = 0x51, // @args symbol id, symbol id // @role Load the symbol `primary`, compute its head, store it in an existing variable `secondary` - SET_VAL_HEAD = 0x51, + SET_VAL_HEAD = 0x52, // @args symbol index, symbol id // @role Load the symbol `primary`, compute its head, store it in an existing variable `secondary` - SET_VAL_HEAD_BY_INDEX = 0x52, + SET_VAL_HEAD_BY_INDEX = 0x53, // @args builtin id, argument count // @role Call a builtin by its id in `primary`, with `secondary` arguments. Bypass the stack size check because we do not push IP/PP since builtins calls do not alter the stack - CALL_BUILTIN = 0x53, + CALL_BUILTIN = 0x54, // @args builtin id, argument count // @role Call a builtin by its id in `primary`, with `secondary` arguments. Bypass the stack size check because we do not push IP/PP since builtins calls do not alter the stack, as well as the return address removal - CALL_BUILTIN_WITHOUT_RETURN_ADDRESS = 0x54, + CALL_BUILTIN_WITHOUT_RETURN_ADDRESS = 0x55, // @args constant id, absolute address to jump to // @role Compare `TS < constant`, if the comparison fails, jump to the given address. Otherwise, does nothing - LT_CONST_JUMP_IF_FALSE = 0x55, + LT_CONST_JUMP_IF_FALSE = 0x56, // @args constant id, absolute address to jump to // @role Compare `TS < constant`, if the comparison succeeds, jump to the given address. Otherwise, does nothing - LT_CONST_JUMP_IF_TRUE = 0x56, + LT_CONST_JUMP_IF_TRUE = 0x57, // @args symbol id, absolute address to jump to // @role Compare `TS < symbol`, if the comparison fails, jump to the given address. Otherwise, does nothing - LT_SYM_JUMP_IF_FALSE = 0x57, + LT_SYM_JUMP_IF_FALSE = 0x58, // @args constant id, absolute address to jump to // @role Compare `TS > constant`, if the comparison succeeds, jump to the given address. Otherwise, does nothing - GT_CONST_JUMP_IF_TRUE = 0x58, + GT_CONST_JUMP_IF_TRUE = 0x59, // @args constant id, absolute address to jump to // @role Compare `TS > constant`, if the comparison fails, jump to the given address. Otherwise, does nothing - GT_CONST_JUMP_IF_FALSE = 0x59, + GT_CONST_JUMP_IF_FALSE = 0x5a, // @args symbol id, absolute address to jump to // @role Compare `TS > symbol`, if the comparison fails, jump to the given address. Otherwise, does nothing - GT_SYM_JUMP_IF_FALSE = 0x5a, + GT_SYM_JUMP_IF_FALSE = 0x5b, // @args constant id, absolute address to jump to // @role Compare `TS == constant`, if the comparison succeeds, jump to the given address. Otherwise, does nothing - EQ_CONST_JUMP_IF_TRUE = 0x5b, + EQ_CONST_JUMP_IF_TRUE = 0x5c, // @args symbol index, absolute address to jump to // @role Compare `TS == symbol`, if the comparison succeeds, jump to the given address. Otherwise, does nothing - EQ_SYM_INDEX_JUMP_IF_TRUE = 0x5c, + EQ_SYM_INDEX_JUMP_IF_TRUE = 0x5d, // @args constant id, absolute address to jump to // @role Compare `TS != constant`, if the comparison succeeds, jump to the given address. Otherwise, does nothing - NEQ_CONST_JUMP_IF_TRUE = 0x5d, + NEQ_CONST_JUMP_IF_TRUE = 0x5e, // @args symbol id, absolute address to jump to // @role Compare `TS != symbol`, if the comparison fails, jump to the given address. Otherwise, does nothing - NEQ_SYM_JUMP_IF_FALSE = 0x5e, + NEQ_SYM_JUMP_IF_FALSE = 0x5f, // @args symbol id, argument count // @role Call a symbol by its id in `primary`, with `secondary` arguments - CALL_SYMBOL = 0x5f, + CALL_SYMBOL = 0x60, // @args symbol id (function name), argument count // @role Call the current page with `secondary` arguments - CALL_CURRENT_PAGE = 0x60, + CALL_CURRENT_PAGE = 0x61, // @args symbol id, field id in symbols table // @role Push the field of a given symbol (which has to be a closure) on the stack - GET_FIELD_FROM_SYMBOL = 0x61, + GET_FIELD_FROM_SYMBOL = 0x62, // @args symbol index, field id in symbols table // @role Push the field of a given symbol (which has to be a closure) on the stack - GET_FIELD_FROM_SYMBOL_INDEX = 0x62, + GET_FIELD_FROM_SYMBOL_INDEX = 0x63, // @args symbol id, symbol id2 // @role Push symbol[symbol2] - AT_SYM_SYM = 0x63, + AT_SYM_SYM = 0x64, // @args symbol index, symbol index2 // @role Push symbol[symbol2] - AT_SYM_INDEX_SYM_INDEX = 0x64, + AT_SYM_INDEX_SYM_INDEX = 0x65, // @args symbol index, constant id // @role Push symbol[constant] - AT_SYM_INDEX_CONST = 0x65, + AT_SYM_INDEX_CONST = 0x66, // @args symbol id, constant id // @role Check that the type of symbol is the given constant, push true if so, false otherwise - CHECK_TYPE_OF = 0x66, + CHECK_TYPE_OF = 0x67, // @args symbol index, constant id // @role Check that the type of symbol is the given constant, push true if so, false otherwise - CHECK_TYPE_OF_BY_INDEX = 0x67, + CHECK_TYPE_OF_BY_INDEX = 0x68, // @args symbol id, number of elements // @role Append N elements to a reference to a list (symbol id), the list is being mutated in-place, no new object created. Elements are stored in TS(1)..TS(N). Follows the function calling convention - APPEND_IN_PLACE_SYM = 0x68, + APPEND_IN_PLACE_SYM = 0x69, // @args symbol index, number of elements // @role Append N elements to a reference to a list (symbol index), the list is being mutated in-place, no new object created. Elements are stored in TS(1)..TS(N). Follows the function calling convention - APPEND_IN_PLACE_SYM_INDEX = 0x69, + APPEND_IN_PLACE_SYM_INDEX = 0x6a, // @args symbol index, symbol id // @role Compute the length of the list or string at symbol index, and store it in a variable (symbol id) - STORE_LEN = 0x6a, + STORE_LEN = 0x6b, // @args symbol id, absolute address to jump to // @role Compute the length of a symbol (list or string), and pop TS to compare it, then jump if false - LT_LEN_SYM_JUMP_IF_FALSE = 0x6b, + LT_LEN_SYM_JUMP_IF_FALSE = 0x6c, // @args symbol id, offset number // @role Multiply the symbol by (offset symbol - 2048), then push it to the stack - MUL_BY = 0x6c, + MUL_BY = 0x6d, // @args symbol index, offset number // @role Multiply the symbol by (offset symbol - 2048), then push it to the stack - MUL_BY_INDEX = 0x6d, + MUL_BY_INDEX = 0x6e, // @args symbol id, offset number // @role Multiply the symbol by (offset symbol - 2048), then store the result using the given symbol id - MUL_SET_VAL = 0x6e, + MUL_SET_VAL = 0x6f, // @args op1, op2, op3 // @role Pop 3 or 4 values from the stack, and apply the ops sequentially (only ADD, SUB, MUL, and DIV are supported). Push the result to the stack. Only op3 may be NOP. - FUSED_MATH = 0x6f, + FUSED_MATH = 0x70, InstructionsCount }; constexpr std::array InstructionNames = { "NOP", + "LOAD_FAST", + "LOAD_FAST_BY_INDEX", "LOAD_SYMBOL", - "LOAD_SYMBOL_BY_INDEX", "LOAD_CONST", "POP_JUMP_IF_TRUE", "STORE", @@ -498,10 +503,10 @@ namespace Ark::internal "NEQ", "EQ", "LEN", - "EMPTY", + "IS_EMPTY", "TAIL", "HEAD", - "ISNIL", + "IS_NIL", "ASSERT", "TO_NUM", "TO_STR", @@ -509,7 +514,7 @@ namespace Ark::internal "AT_AT", "MOD", "TYPE", - "HASFIELD", + "HAS_FIELD", "NOT", // super instructions "LOAD_CONST_LOAD_CONST", diff --git a/include/Ark/Compiler/Lowerer/ASTLowerer.hpp b/include/Ark/Compiler/Lowerer/ASTLowerer.hpp index 6cb289fb..de9971fb 100644 --- a/include/Ark/Compiler/Lowerer/ASTLowerer.hpp +++ b/include/Ark/Compiler/Lowerer/ASTLowerer.hpp @@ -180,7 +180,7 @@ namespace Ark::internal */ void compileExpression(Node& x, Page p, bool is_result_unused, bool is_terminal); - void compileSymbol(const Node& x, Page p, bool is_result_unused); + void compileSymbol(const Node& x, Page p, bool is_result_unused, bool can_use_ref); void compileListInstruction(Node& x, Page p, bool is_result_unused); void compileIf(Node& x, Page p, bool is_result_unused, bool is_terminal); void compileFunction(Node& x, Page p, bool is_result_unused); diff --git a/src/arkreactor/Compiler/BytecodeReader.cpp b/src/arkreactor/Compiler/BytecodeReader.cpp index c972594a..b51f5be0 100644 --- a/src/arkreactor/Compiler/BytecodeReader.cpp +++ b/src/arkreactor/Compiler/BytecodeReader.cpp @@ -490,8 +490,9 @@ namespace Ark }; const std::unordered_map arg_kinds = { + { LOAD_FAST, ArgKind::Symbol }, + { LOAD_FAST_BY_INDEX, ArgKind::Raw }, { LOAD_SYMBOL, ArgKind::Symbol }, - { LOAD_SYMBOL_BY_INDEX, ArgKind::Raw }, { LOAD_CONST, ArgKind::Constant }, { POP_JUMP_IF_TRUE, ArgKind::Raw }, { STORE, ArgKind::Symbol }, diff --git a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp index 5b95b3fd..7f4ac8ac 100644 --- a/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp +++ b/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp @@ -26,25 +26,25 @@ namespace Ark::internal Rule { { LOAD_CONST, LOAD_CONST }, LOAD_CONST_LOAD_CONST }, Rule { { LOAD_CONST, STORE }, LOAD_CONST_STORE }, Rule { { LOAD_CONST, SET_VAL }, LOAD_CONST_SET_VAL }, - Rule { { LOAD_SYMBOL, STORE }, STORE_FROM }, - Rule { { LOAD_SYMBOL_BY_INDEX, STORE }, STORE_FROM_INDEX }, - Rule { { LOAD_SYMBOL, SET_VAL }, SET_VAL_FROM }, - Rule { { LOAD_SYMBOL_BY_INDEX, SET_VAL }, SET_VAL_FROM_INDEX }, - Rule { { STORE, PUSH_RETURN_ADDRESS, LOAD_SYMBOL_BY_INDEX, BUILTIN, CALL }, + Rule { { LOAD_FAST, STORE }, STORE_FROM }, + Rule { { LOAD_FAST_BY_INDEX, STORE }, STORE_FROM_INDEX }, + Rule { { LOAD_FAST, SET_VAL }, SET_VAL_FROM }, + Rule { { LOAD_FAST_BY_INDEX, SET_VAL }, SET_VAL_FROM_INDEX }, + Rule { { STORE, PUSH_RETURN_ADDRESS, LOAD_FAST_BY_INDEX, BUILTIN, CALL }, [](const Entities entities, const std::size_t start_idx) { return Builtins::builtins[entities[3].primaryArg()].second.isFunction() && start_idx == 0; }, [](const Entities e) { return IR::Entity(CALL_BUILTIN_WITHOUT_RETURN_ADDRESS, e[3].primaryArg(), 1); } }, - Rule { { STORE, STORE, PUSH_RETURN_ADDRESS, LOAD_SYMBOL_BY_INDEX, LOAD_SYMBOL_BY_INDEX, BUILTIN, CALL }, + Rule { { STORE, STORE, PUSH_RETURN_ADDRESS, LOAD_FAST_BY_INDEX, LOAD_FAST_BY_INDEX, BUILTIN, CALL }, [](const Entities entities, const std::size_t start_idx) { return Builtins::builtins[entities[5].primaryArg()].second.isFunction() && start_idx == 0; }, [](const Entities e) { return IR::Entity(CALL_BUILTIN_WITHOUT_RETURN_ADDRESS, e[5].primaryArg(), 2); } }, - Rule { { STORE, STORE, STORE, PUSH_RETURN_ADDRESS, LOAD_SYMBOL_BY_INDEX, LOAD_SYMBOL_BY_INDEX, LOAD_SYMBOL_BY_INDEX, BUILTIN, CALL }, + Rule { { STORE, STORE, STORE, PUSH_RETURN_ADDRESS, LOAD_FAST_BY_INDEX, LOAD_FAST_BY_INDEX, LOAD_FAST_BY_INDEX, BUILTIN, CALL }, [](const Entities entities, const std::size_t start_idx) { return Builtins::builtins[entities[7].primaryArg()].second.isFunction() && start_idx == 0; }, @@ -54,137 +54,137 @@ namespace Ark::internal Rule { { BUILTIN, CALL }, CALL_BUILTIN, [](const Entities entities, const std::size_t) { return Builtins::builtins[entities[0].primaryArg()].second.isFunction(); } }, - Rule { { LOAD_SYMBOL, CALL }, CALL_SYMBOL }, + Rule { { LOAD_FAST, CALL }, CALL_SYMBOL }, Rule { { GET_CURRENT_PAGE_ADDR, CALL }, CALL_CURRENT_PAGE }, - Rule { { LOAD_SYMBOL, GET_FIELD }, GET_FIELD_FROM_SYMBOL }, - Rule { { LOAD_SYMBOL_BY_INDEX, GET_FIELD }, GET_FIELD_FROM_SYMBOL_INDEX }, + Rule { { LOAD_FAST, GET_FIELD }, GET_FIELD_FROM_SYMBOL }, + Rule { { LOAD_FAST_BY_INDEX, GET_FIELD }, GET_FIELD_FROM_SYMBOL_INDEX }, Rule { { LIST, STORE }, STORE_LIST }, - Rule { { LOAD_SYMBOL, APPEND_IN_PLACE }, APPEND_IN_PLACE_SYM }, - Rule { { LOAD_SYMBOL_BY_INDEX, APPEND_IN_PLACE }, APPEND_IN_PLACE_SYM_INDEX }, - // LOAD_CONST, LOAD_SYMBOL a, MUL, SET_VAL / LOAD_SYMBOL a, LOAD_CONST, MUL, SET_VAL + Rule { { LOAD_FAST, APPEND_IN_PLACE }, APPEND_IN_PLACE_SYM }, + Rule { { LOAD_FAST_BY_INDEX, APPEND_IN_PLACE }, APPEND_IN_PLACE_SYM_INDEX }, + // LOAD_CONST, LOAD_FAST a, MUL, SET_VAL / LOAD_FAST a, LOAD_CONST, MUL, SET_VAL // ---> MUL_SET_VAL a value - Rule { { LOAD_CONST, LOAD_SYMBOL, MUL, SET_VAL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST, MUL, SET_VAL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[0].primaryArg()) && e[1].primaryArg() == e[3].primaryArg(); }, [this](const Entities e) { return IR::Entity(MUL_SET_VAL, e[1].primaryArg(), smallerNumberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, MUL, SET_VAL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, MUL, SET_VAL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[1].primaryArg()) && e[0].primaryArg() == e[3].primaryArg(); }, [this](const Entities e) { return IR::Entity(MUL_SET_VAL, e[0].primaryArg(), smallerNumberAsArg(e[1].primaryArg())); } }, - // LOAD_CONST, LOAD_SYMBOL a, MUL / LOAD_SYMBOL a, LOAD_CONST, MUL + // LOAD_CONST, LOAD_FAST a, MUL / LOAD_FAST a, LOAD_CONST, MUL // ---> MUL_(BY|BY_INDEX) a value - Rule { { LOAD_CONST, LOAD_SYMBOL, MUL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST, MUL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[0].primaryArg()); }, [this](const Entities e) { return IR::Entity(MUL_BY, e[1].primaryArg(), smallerNumberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, MUL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, MUL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(MUL_BY, e[0].primaryArg(), smallerNumberAsArg(e[1].primaryArg())); } }, - Rule { { LOAD_CONST, LOAD_SYMBOL_BY_INDEX, MUL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST_BY_INDEX, MUL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[0].primaryArg()); }, [this](const Entities e) { return IR::Entity(MUL_BY_INDEX, e[1].primaryArg(), smallerNumberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, MUL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST_BY_INDEX, LOAD_CONST, MUL }, [this](const Entities e, const std::size_t) { return isSmallerNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(MUL_BY_INDEX, e[0].primaryArg(), smallerNumberAsArg(e[1].primaryArg())); } }, - // (LOAD_SYMBOL a | LOAD_SYMBOL_BY_INDEX index), LOAD_CONST n (=1), (ADD | SUB), STORE + // (LOAD_FAST a | LOAD_FAST_BY_INDEX index), LOAD_CONST n (=1), (ADD | SUB), STORE // ---> INCREMENT_STORE / DECREMENT_STORE a value - Rule { { LOAD_CONST, LOAD_SYMBOL, ADD, SET_VAL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST, ADD, SET_VAL }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[0].primaryArg()) && e[1].primaryArg() == e[3].primaryArg(); }, [this](const Entities e) { return IR::Entity(INCREMENT_STORE, e[1].primaryArg(), numberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, ADD, SET_VAL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, ADD, SET_VAL }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()) && e[0].primaryArg() == e[3].primaryArg(); }, [this](const Entities e) { return IR::Entity(INCREMENT_STORE, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, SUB, SET_VAL }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, SUB, SET_VAL }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()) && e[0].primaryArg() == e[3].primaryArg(); }, [this](const Entities e) { return IR::Entity(DECREMENT_STORE, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, // without the final store, just increment/decrement - Rule { { LOAD_CONST, LOAD_SYMBOL, ADD }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST, ADD }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[0].primaryArg()); }, [this](const Entities e) { return IR::Entity(INCREMENT, e[1].primaryArg(), numberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, ADD }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, ADD }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(INCREMENT, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, - Rule { { LOAD_SYMBOL, LOAD_CONST, SUB }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST, LOAD_CONST, SUB }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(DECREMENT, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, - Rule { { LOAD_CONST, LOAD_SYMBOL_BY_INDEX, ADD }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_CONST, LOAD_FAST_BY_INDEX, ADD }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[0].primaryArg()); }, [this](const Entities e) { return IR::Entity(INCREMENT_BY_INDEX, e[1].primaryArg(), numberAsArg(e[0].primaryArg())); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, ADD }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST_BY_INDEX, LOAD_CONST, ADD }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(INCREMENT_BY_INDEX, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, SUB }, [this](const Entities e, const std::size_t) { + Rule { { LOAD_FAST_BY_INDEX, LOAD_CONST, SUB }, [this](const Entities e, const std::size_t) { return isPositiveNumberInlinable(e[1].primaryArg()); }, [this](const Entities e) { return IR::Entity(DECREMENT_BY_INDEX, e[0].primaryArg(), numberAsArg(e[1].primaryArg())); } }, - // LOAD_SYMBOL list, (TAIL | HEAD), (STORE | SET_VAL a) + // LOAD_FAST list, (TAIL | HEAD), (STORE | SET_VAL a) // ---> STORE_TAIL list a ; STORE_HEAD ; SET_VAL_TAIL ; SET_VAL_HEAD - Rule { { LOAD_SYMBOL, TAIL, STORE }, [](const Entities e) { + Rule { { LOAD_FAST, TAIL, STORE }, [](const Entities e) { return IR::Entity(STORE_TAIL, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL, TAIL, SET_VAL }, [](const Entities e) { + Rule { { LOAD_FAST, TAIL, SET_VAL }, [](const Entities e) { return IR::Entity(SET_VAL_TAIL, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL, HEAD, STORE }, [](const Entities e) { + Rule { { LOAD_FAST, HEAD, STORE }, [](const Entities e) { return IR::Entity(STORE_HEAD, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL, HEAD, SET_VAL }, [](const Entities e) { + Rule { { LOAD_FAST, HEAD, SET_VAL }, [](const Entities e) { return IR::Entity(SET_VAL_HEAD, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, TAIL, STORE }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, TAIL, STORE }, [](const Entities e) { return IR::Entity(STORE_TAIL_BY_INDEX, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, TAIL, SET_VAL }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, TAIL, SET_VAL }, [](const Entities e) { return IR::Entity(SET_VAL_TAIL_BY_INDEX, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, HEAD, STORE }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, HEAD, STORE }, [](const Entities e) { return IR::Entity(STORE_HEAD_BY_INDEX, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, HEAD, SET_VAL }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, HEAD, SET_VAL }, [](const Entities e) { return IR::Entity(SET_VAL_HEAD_BY_INDEX, e[0].primaryArg(), e[2].primaryArg()); } }, - // (LOAD_CONST id | LOAD_SYMBOL id), , POP_JUMP_IF_(FALSE|TRUE) + // (LOAD_CONST id | LOAD_FAST id), , POP_JUMP_IF_(FALSE|TRUE) // ---> _(CONST|SYM)_JUMP_IF_(FALSE|TRUE) Rule { { LOAD_CONST, LT, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], LT_CONST_JUMP_IF_FALSE, e[0].primaryArg()); @@ -192,7 +192,7 @@ namespace Ark::internal Rule { { LOAD_CONST, LT, POP_JUMP_IF_TRUE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], LT_CONST_JUMP_IF_TRUE, e[0].primaryArg()); } }, - Rule { { LOAD_SYMBOL, LT, POP_JUMP_IF_FALSE }, [](const Entities e) { + Rule { { LOAD_FAST, LT, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], LT_SYM_JUMP_IF_FALSE, e[0].primaryArg()); } }, Rule { { LOAD_CONST, GT, POP_JUMP_IF_TRUE }, [](const Entities e) { @@ -201,46 +201,46 @@ namespace Ark::internal Rule { { LOAD_CONST, GT, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], GT_CONST_JUMP_IF_FALSE, e[0].primaryArg()); } }, - Rule { { LOAD_SYMBOL, GT, POP_JUMP_IF_FALSE }, [](const Entities e) { + Rule { { LOAD_FAST, GT, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], GT_SYM_JUMP_IF_FALSE, e[0].primaryArg()); } }, Rule { { LOAD_CONST, EQ, POP_JUMP_IF_TRUE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], EQ_CONST_JUMP_IF_TRUE, e[0].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, EQ, POP_JUMP_IF_TRUE }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, EQ, POP_JUMP_IF_TRUE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], EQ_SYM_INDEX_JUMP_IF_TRUE, e[0].primaryArg()); } }, Rule { { LOAD_CONST, NEQ, POP_JUMP_IF_TRUE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], NEQ_CONST_JUMP_IF_TRUE, e[0].primaryArg()); } }, - Rule { { LOAD_SYMBOL, NEQ, POP_JUMP_IF_FALSE }, [](const Entities e) { + Rule { { LOAD_FAST, NEQ, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[2], NEQ_SYM_JUMP_IF_FALSE, e[0].primaryArg()); } }, - // LOAD_SYMBOL id, LOAD_SYMBOL id2, AT + // LOAD_FAST id, LOAD_FAST id2, AT // ---> AT_SYM_SYM id id2 - Rule { { LOAD_SYMBOL, LOAD_SYMBOL, AT }, AT_SYM_SYM }, - Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_SYMBOL_BY_INDEX, AT }, AT_SYM_INDEX_SYM_INDEX }, - Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, AT }, AT_SYM_INDEX_CONST }, - // LOAD_SYMBOL sym, TYPE, LOAD_CONST cst, EQ + Rule { { LOAD_FAST, LOAD_FAST, AT }, AT_SYM_SYM }, + Rule { { LOAD_FAST_BY_INDEX, LOAD_FAST_BY_INDEX, AT }, AT_SYM_INDEX_SYM_INDEX }, + Rule { { LOAD_FAST_BY_INDEX, LOAD_CONST, AT }, AT_SYM_INDEX_CONST }, + // LOAD_FAST sym, TYPE, LOAD_CONST cst, EQ // ---> CHECK_TYPE_OF sym, cst - // also works with LOAD_CONST cst, LOAD_SYMBOL sym, TYPE, EQ, but args will be flipped - Rule { { LOAD_SYMBOL, TYPE, LOAD_CONST, EQ }, [](const Entities e) { + // also works with LOAD_CONST cst, LOAD_FAST sym, TYPE, EQ, but args will be flipped + Rule { { LOAD_FAST, TYPE, LOAD_CONST, EQ }, [](const Entities e) { return IR::Entity(CHECK_TYPE_OF, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_CONST, LOAD_SYMBOL, TYPE, EQ }, [](const Entities e) { + Rule { { LOAD_CONST, LOAD_FAST, TYPE, EQ }, [](const Entities e) { return IR::Entity(CHECK_TYPE_OF, e[1].primaryArg(), e[0].primaryArg()); } }, - Rule { { LOAD_SYMBOL_BY_INDEX, TYPE, LOAD_CONST, EQ }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, TYPE, LOAD_CONST, EQ }, [](const Entities e) { return IR::Entity(CHECK_TYPE_OF_BY_INDEX, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_CONST, LOAD_SYMBOL_BY_INDEX, TYPE, EQ }, [](const Entities e) { + Rule { { LOAD_CONST, LOAD_FAST_BY_INDEX, TYPE, EQ }, [](const Entities e) { return IR::Entity(CHECK_TYPE_OF_BY_INDEX, e[1].primaryArg(), e[0].primaryArg()); } }, // --- - Rule { { LOAD_SYMBOL_BY_INDEX, LEN, STORE }, [](const Entities e) { + Rule { { LOAD_FAST_BY_INDEX, LEN, STORE }, [](const Entities e) { return IR::Entity(STORE_LEN, e[0].primaryArg(), e[2].primaryArg()); } }, - Rule { { LOAD_SYMBOL, LEN, LT, POP_JUMP_IF_FALSE }, [](const Entities e) { + Rule { { LOAD_FAST, LEN, LT, POP_JUMP_IF_FALSE }, [](const Entities e) { return IR::Entity::GotoWithArg(e[3], LT_LEN_SYM_JUMP_IF_FALSE, e[0].primaryArg()); } }, }; diff --git a/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp b/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp index 4a0b2b52..6df66aa4 100644 --- a/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp +++ b/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp @@ -99,10 +99,10 @@ namespace Ark::internal { case NOT: [[fallthrough]]; case LEN: [[fallthrough]]; - case EMPTY: [[fallthrough]]; + case IS_EMPTY: [[fallthrough]]; case TAIL: [[fallthrough]]; case HEAD: [[fallthrough]]; - case ISNIL: [[fallthrough]]; + case IS_NIL: [[fallthrough]]; case TO_NUM: [[fallthrough]]; case TO_STR: [[fallthrough]]; case TYPE: @@ -139,11 +139,11 @@ namespace Ark::internal { // register symbols if (x.nodeType() == NodeType::Symbol) - compileSymbol(x, p, is_result_unused); + compileSymbol(x, p, is_result_unused, /* can_use_ref= */ true); else if (x.nodeType() == NodeType::Field) { // the parser guarantees us that there is at least 2 elements (eg: a.b) - compileSymbol(x.list()[0], p, is_result_unused); + compileSymbol(x.list()[0], p, is_result_unused, /* can_use_ref= */ true); for (auto it = x.constList().begin() + 1, end = x.constList().end(); it != end; ++it) { uint16_t i = addSymbol(*it); @@ -205,9 +205,9 @@ namespace Ark::internal compileExpression( x.list()[i], p, - // All the nodes in a begin (except for the last one) are producing a result that we want to drop. + // All the nodes in a 'begin' (except for the last one) are producing a result that we want to drop. (i != size - 1) || is_result_unused, - // If the begin is a terminal node, only its last node is terminal. + // If the 'begin' is a terminal node, only its last node is terminal. is_terminal && (i == size - 1)); break; } @@ -240,7 +240,7 @@ namespace Ark::internal x); } - void ASTLowerer::compileSymbol(const Node& x, const Page p, const bool is_result_unused) + void ASTLowerer::compileSymbol(const Node& x, const Page p, const bool is_result_unused, const bool can_use_ref) { const std::string& name = x.string(); @@ -250,9 +250,14 @@ namespace Ark::internal buildAndThrowError(fmt::format("Found a free standing operator: `{}`", name), x); else { - const std::optional maybe_local_idx = m_locals_locator.lookupLastScopeByName(name); - if (maybe_local_idx.has_value()) - page(p).emplace_back(LOAD_SYMBOL_BY_INDEX, static_cast(maybe_local_idx.value())); + if (can_use_ref) + { + const std::optional maybe_local_idx = m_locals_locator.lookupLastScopeByName(name); + if (maybe_local_idx.has_value()) + page(p).emplace_back(LOAD_FAST_BY_INDEX, static_cast(maybe_local_idx.value())); + else + page(p).emplace_back(LOAD_FAST, addSymbol(x)); + } else page(p).emplace_back(LOAD_SYMBOL, addSymbol(x)); } @@ -552,7 +557,13 @@ namespace Ark::internal for (Node& value : std::ranges::drop_view(call.list(), 1) | std::views::reverse) { if (nodeProducesOutput(value)) - compileExpression(value, p, false, false); + { + // we have to disallow usage of references in tail calls, because if we shuffle arguments around while using refs, they will end up with the same value + if (value.nodeType() == NodeType::Symbol && is_tail_call) + compileSymbol(value, p, false, /* can_use_ref= */ false); + else + compileExpression(value, p, false, false); + } else { std::string message; @@ -630,7 +641,7 @@ namespace Ark::internal if (node.nodeType() == NodeType::Symbol && !m_opened_vars.empty() && m_opened_vars.top() == node.string()) { // The function is trying to call itself, but this isn't a tail call. - // We can skip the LOAD_SYMBOL function_name and directly push the current + // We can skip the LOAD_FAST function_name and directly push the current // function page, which will be quicker than a local variable resolution. // We set its argument to the symbol id of the function we are calling, // so that the VM knows the name of the last called function. diff --git a/src/arkreactor/VM/VM.cpp b/src/arkreactor/VM/VM.cpp index df435962..d7995854 100644 --- a/src/arkreactor/VM/VM.cpp +++ b/src/arkreactor/VM/VM.cpp @@ -569,8 +569,9 @@ namespace Ark constexpr std::array opcode_targets = { // cppcheck-suppress syntaxError ; cppcheck do not know about labels addresses (GCC extension) &&TARGET_NOP, + &&TARGET_LOAD_FAST, + &&TARGET_LOAD_FAST_BY_INDEX, &&TARGET_LOAD_SYMBOL, - &&TARGET_LOAD_SYMBOL_BY_INDEX, &&TARGET_LOAD_CONST, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_STORE, @@ -616,10 +617,10 @@ namespace Ark &&TARGET_NEQ, &&TARGET_EQ, &&TARGET_LEN, - &&TARGET_EMPTY, + &&TARGET_IS_EMPTY, &&TARGET_TAIL, &&TARGET_HEAD, - &&TARGET_ISNIL, + &&TARGET_IS_NIL, &&TARGET_ASSERT, &&TARGET_TO_NUM, &&TARGET_TO_STR, @@ -627,7 +628,7 @@ namespace Ark &&TARGET_AT_AT, &&TARGET_MOD, &&TARGET_TYPE, - &&TARGET_HASFIELD, + &&TARGET_HAS_FIELD, &&TARGET_NOT, &&TARGET_LOAD_CONST_LOAD_CONST, &&TARGET_LOAD_CONST_STORE, @@ -710,18 +711,25 @@ namespace Ark DISPATCH(); } - TARGET(LOAD_SYMBOL) + TARGET(LOAD_FAST) { push(loadSymbol(arg, context), context); DISPATCH(); } - TARGET(LOAD_SYMBOL_BY_INDEX) + TARGET(LOAD_FAST_BY_INDEX) { push(loadSymbolFromIndex(arg, context), context); DISPATCH(); } + TARGET(LOAD_SYMBOL) + { + // force resolving the reference + push(*loadSymbol(arg, context), context); + DISPATCH(); + } + TARGET(LOAD_CONST) { push(loadConstAsPtr(arg), context); @@ -1295,7 +1303,7 @@ namespace Ark DISPATCH(); } - TARGET(EMPTY) + TARGET(IS_EMPTY) { const Value* a = popAndResolveAsPtr(context); @@ -1329,7 +1337,7 @@ namespace Ark DISPATCH(); } - TARGET(ISNIL) + TARGET(IS_NIL) { const Value* a = popAndResolveAsPtr(context); push((*a == Builtins::nil) ? Builtins::trueSym : Builtins::falseSym, context); @@ -1449,7 +1457,7 @@ namespace Ark DISPATCH(); } - TARGET(HASFIELD) + TARGET(HAS_FIELD) { { Value* const field = popAndResolveAsPtr(context); diff --git a/tests/unittests/resources/CompilerSuite/ir/99bottles.expected b/tests/unittests/resources/CompilerSuite/ir/99bottles.expected index b583a6e7..1ff09c92 100644 --- a/tests/unittests/resources/CompilerSuite/ir/99bottles.expected +++ b/tests/unittests/resources/CompilerSuite/ir/99bottles.expected @@ -1,7 +1,7 @@ page_0 - LOAD_SYMBOL 1 + LOAD_FAST 1 STORE 0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LEN 0 LOAD_CONST 0 GE 0 @@ -9,33 +9,33 @@ page_0 BUILTIN 2 JUMP L1 .L0: - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LOAD_CONST 1 AT 0 TO_NUM 0 .L1: STORE 2 - LOAD_SYMBOL_BY_INDEX 0 - ISNIL 0 + LOAD_FAST_BY_INDEX 0 + IS_NIL 0 POP_JUMP_IF_TRUE L2 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 JUMP L3 .L2: LOAD_CONST 2 .L3: STORE 3 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 STORE 4 CREATE_SCOPE 0 .L4: - LOAD_SYMBOL 4 + LOAD_FAST 4 LOAD_CONST 0 GT 0 POP_JUMP_IF_FALSE L5 PUSH_RETURN_ADDRESS L6 PUSH_RETURN_ADDRESS L7 - LOAD_SYMBOL 4 - LOAD_SYMBOL 4 + LOAD_FAST 4 + LOAD_FAST 4 LOAD_CONST 3 BUILTIN 26 CALL 3 @@ -44,13 +44,13 @@ page_0 CALL 1 .L6: POP 0 - LOAD_SYMBOL 4 + LOAD_FAST 4 LOAD_CONST 0 SUB 0 SET_VAL 4 PUSH_RETURN_ADDRESS L8 PUSH_RETURN_ADDRESS L9 - LOAD_SYMBOL 4 + LOAD_FAST 4 LOAD_CONST 4 BUILTIN 26 CALL 2 diff --git a/tests/unittests/resources/CompilerSuite/ir/ackermann.expected b/tests/unittests/resources/CompilerSuite/ir/ackermann.expected index 7759fc53..2fde96b7 100644 --- a/tests/unittests/resources/CompilerSuite/ir/ackermann.expected +++ b/tests/unittests/resources/CompilerSuite/ir/ackermann.expected @@ -5,7 +5,7 @@ page_0 PUSH_RETURN_ADDRESS L6 LOAD_CONST 3 LOAD_CONST 4 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 2 .L6: LOAD_CONST 5 @@ -17,35 +17,35 @@ page_0 page_1 STORE 1 STORE 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 LOAD_CONST 1 GT 0 POP_JUMP_IF_TRUE L0 LOAD_CONST 2 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 ADD 0 JUMP L1 .L0: LOAD_CONST 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 EQ 0 POP_JUMP_IF_TRUE L2 PUSH_RETURN_ADDRESS L3 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LOAD_CONST 2 SUB 0 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 GET_CURRENT_PAGE_ADDR 0 CALL 2 .L3: - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 LOAD_CONST 2 SUB 0 JUMP 0 JUMP L4 .L2: LOAD_CONST 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 LOAD_CONST 2 SUB 0 JUMP 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/args_attr.expected b/tests/unittests/resources/CompilerSuite/ir/args_attr.expected index fa58aa6d..c06f3200 100644 --- a/tests/unittests/resources/CompilerSuite/ir/args_attr.expected +++ b/tests/unittests/resources/CompilerSuite/ir/args_attr.expected @@ -8,9 +8,9 @@ page_0 STORE 3 PUSH_RETURN_ADDRESS L0 PUSH_RETURN_ADDRESS L1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LOAD_CONST 3 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 CALL 2 .L1: BUILTIN 9 @@ -21,9 +21,9 @@ page_0 page_1 STORE 1 STORE_REF 2 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LEN 0 SET_VAL 1 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/closures.expected b/tests/unittests/resources/CompilerSuite/ir/closures.expected index 0db3bce0..0bf9b580 100644 --- a/tests/unittests/resources/CompilerSuite/ir/closures.expected +++ b/tests/unittests/resources/CompilerSuite/ir/closures.expected @@ -5,7 +5,7 @@ page_0 LOAD_CONST 3 LOAD_CONST 4 LOAD_CONST 5 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 3 .L0: STORE 6 @@ -13,12 +13,12 @@ page_0 LOAD_CONST 6 LOAD_CONST 7 LOAD_CONST 8 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 CALL 3 .L1: STORE 7 PUSH_RETURN_ADDRESS L2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 GET_FIELD 2 LOAD_CONST 9 BUILTIN 9 @@ -33,13 +33,13 @@ page_0 POP 0 PUSH_RETURN_ADDRESS L4 LOAD_CONST 11 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 GET_FIELD 4 CALL 1 .L4: POP 0 PUSH_RETURN_ADDRESS L5 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 GET_FIELD 2 LOAD_CONST 12 BUILTIN 9 @@ -47,7 +47,7 @@ page_0 .L5: POP 0 PUSH_RETURN_ADDRESS L6 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 GET_FIELD 2 LOAD_CONST 13 BUILTIN 9 @@ -58,13 +58,13 @@ page_0 STORE 8 PUSH_RETURN_ADDRESS L7 LOAD_CONST 17 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 1 .L7: STORE 10 PUSH_RETURN_ADDRESS L8 PUSH_RETURN_ADDRESS L9 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L9: LOAD_CONST 18 @@ -74,7 +74,7 @@ page_0 POP 0 PUSH_RETURN_ADDRESS L10 PUSH_RETURN_ADDRESS L11 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L11: LOAD_CONST 18 @@ -84,7 +84,7 @@ page_0 POP 0 PUSH_RETURN_ADDRESS L12 PUSH_RETURN_ADDRESS L13 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L13: LOAD_CONST 18 @@ -109,7 +109,7 @@ page_1 page_2 STORE 5 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 SET_VAL 2 RET 0 HALT 0 @@ -127,10 +127,10 @@ page_4 HALT 0 page_5 - LOAD_SYMBOL 9 + LOAD_FAST 9 LOAD_CONST 16 SUB 0 SET_VAL 9 - LOAD_SYMBOL 9 + LOAD_FAST 9 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/factorial.expected b/tests/unittests/resources/CompilerSuite/ir/factorial.expected index 483d829d..948b695e 100644 --- a/tests/unittests/resources/CompilerSuite/ir/factorial.expected +++ b/tests/unittests/resources/CompilerSuite/ir/factorial.expected @@ -4,7 +4,7 @@ page_0 PUSH_RETURN_ADDRESS L2 PUSH_RETURN_ADDRESS L3 LOAD_CONST 3 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 1 .L3: LOAD_CONST 4 @@ -21,21 +21,21 @@ page_1 STORE 3 CREATE_SCOPE 0 .L0: - LOAD_SYMBOL 3 - LOAD_SYMBOL 1 + LOAD_FAST 3 + LOAD_FAST 1 LE 0 POP_JUMP_IF_FALSE L1 - LOAD_SYMBOL 2 - LOAD_SYMBOL 3 + LOAD_FAST 2 + LOAD_FAST 3 MUL 0 SET_VAL 2 LOAD_CONST 1 - LOAD_SYMBOL 3 + LOAD_FAST 3 ADD 0 SET_VAL 3 RESET_SCOPE_JUMP L0 .L1: POP_SCOPE 0 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/plugin.expected b/tests/unittests/resources/CompilerSuite/ir/plugin.expected index d1d7c6e6..abfa2f78 100644 --- a/tests/unittests/resources/CompilerSuite/ir/plugin.expected +++ b/tests/unittests/resources/CompilerSuite/ir/plugin.expected @@ -3,7 +3,7 @@ page_0 LOAD_CONST 1 PUSH_RETURN_ADDRESS L0 LOAD_CONST 2 - LOAD_SYMBOL 0 + LOAD_FAST 0 CALL 1 .L0: EQ 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/renamed_capture.expected b/tests/unittests/resources/CompilerSuite/ir/renamed_capture.expected index c534479f..17493714 100644 --- a/tests/unittests/resources/CompilerSuite/ir/renamed_capture.expected +++ b/tests/unittests/resources/CompilerSuite/ir/renamed_capture.expected @@ -6,7 +6,7 @@ page_0 MAKE_CLOSURE 1 STORE 1 PUSH_RETURN_ADDRESS L0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 BUILTIN 9 CALL 1 .L0: diff --git a/tests/unittests/resources/CompilerSuite/ir/tail_call.ark b/tests/unittests/resources/CompilerSuite/ir/tail_call.ark new file mode 100644 index 00000000..3ac929ff --- /dev/null +++ b/tests/unittests/resources/CompilerSuite/ir/tail_call.ark @@ -0,0 +1,6 @@ +(let f (fun (a b) + (if (nil? b) + (f "wrong" a) + (print b)))) + +(f "correct" nil) diff --git a/tests/unittests/resources/CompilerSuite/ir/tail_call.expected b/tests/unittests/resources/CompilerSuite/ir/tail_call.expected new file mode 100644 index 00000000..b7b9b786 --- /dev/null +++ b/tests/unittests/resources/CompilerSuite/ir/tail_call.expected @@ -0,0 +1,30 @@ +page_0 + LOAD_CONST 0 + STORE 0 + PUSH_RETURN_ADDRESS L3 + BUILTIN 2 + LOAD_CONST 2 + LOAD_FAST_BY_INDEX 0 + CALL 2 +.L3: + HALT 0 + +page_1 + STORE 1 + STORE 2 + LOAD_FAST_BY_INDEX 0 + IS_NIL 0 + POP_JUMP_IF_TRUE L0 + PUSH_RETURN_ADDRESS L1 + LOAD_FAST_BY_INDEX 0 + BUILTIN 9 + CALL 1 +.L1: + JUMP L2 +.L0: + LOAD_SYMBOL 1 + LOAD_CONST 1 + JUMP 0 +.L2: + RET 0 + HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/99bottles.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/99bottles.expected index 844c28dc..485b5b7b 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/99bottles.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/99bottles.expected @@ -6,7 +6,7 @@ page_0 STORE 6 STORE_FROM 8, 7 STORE_FROM 10, 9 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 LEN 0 LOAD_CONST 3 GE 0 @@ -18,10 +18,10 @@ page_0 TO_NUM 0 .L4: STORE 11 - LOAD_SYMBOL_BY_INDEX 0 - ISNIL 0 + LOAD_FAST_BY_INDEX 0 + IS_NIL 0 POP_JUMP_IF_TRUE L5 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 JUMP L6 .L5: LOAD_CONST 5 @@ -30,12 +30,12 @@ page_0 STORE_FROM_INDEX 0, 13 CREATE_SCOPE 0 .L7: - LOAD_SYMBOL 13 + LOAD_FAST 13 GT_CONST_JUMP_IF_FALSE L8, 3 PUSH_RETURN_ADDRESS L9 PUSH_RETURN_ADDRESS L10 - LOAD_SYMBOL 13 - LOAD_SYMBOL 13 + LOAD_FAST 13 + LOAD_FAST 13 LOAD_CONST 6 CALL_BUILTIN 26, 3 .L10: @@ -45,7 +45,7 @@ page_0 DECREMENT_STORE 13, 1 PUSH_RETURN_ADDRESS L11 PUSH_RETURN_ADDRESS L12 - LOAD_SYMBOL 13 + LOAD_FAST 13 LOAD_CONST 7 CALL_BUILTIN 26, 2 .L12: diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/ackermann.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/ackermann.expected index 1f9e6da5..cfc6e151 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/ackermann.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/ackermann.expected @@ -3,7 +3,7 @@ page_0 PUSH_RETURN_ADDRESS L5 PUSH_RETURN_ADDRESS L6 LOAD_CONST_LOAD_CONST 3, 4 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 2 .L6: LOAD_CONST 5 @@ -14,7 +14,7 @@ page_0 page_1 STORE 1 STORE 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 GT_CONST_JUMP_IF_TRUE L0, 1 INCREMENT_BY_INDEX 0, 1 JUMP L1 @@ -23,7 +23,7 @@ page_1 EQ_SYM_INDEX_JUMP_IF_TRUE L2, 0 PUSH_RETURN_ADDRESS L3 DECREMENT_BY_INDEX 0, 1 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 CALL_CURRENT_PAGE 0, 2 .L3: DECREMENT_BY_INDEX 1, 1 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/closures.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/closures.expected index 391b4eb3..176d1d18 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/closures.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/closures.expected @@ -3,14 +3,14 @@ page_0 PUSH_RETURN_ADDRESS L0 LOAD_CONST_LOAD_CONST 3, 4 LOAD_CONST 5 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 3 .L0: STORE 6 PUSH_RETURN_ADDRESS L1 LOAD_CONST_LOAD_CONST 6, 7 LOAD_CONST 8 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 CALL 3 .L1: STORE 7 @@ -46,7 +46,7 @@ page_0 LOAD_CONST_STORE 14, 8 PUSH_RETURN_ADDRESS L7 LOAD_CONST 17 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 1 .L7: STORE 10 @@ -86,7 +86,7 @@ page_4 page_5 DECREMENT_STORE 9, 1 - LOAD_SYMBOL 9 + LOAD_FAST 9 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/factorial.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/factorial.expected index de7675e0..ad4c4c66 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/factorial.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/factorial.expected @@ -3,7 +3,7 @@ page_0 PUSH_RETURN_ADDRESS L2 PUSH_RETURN_ADDRESS L3 LOAD_CONST 3 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 1 .L3: LOAD_CONST 4 @@ -17,18 +17,18 @@ page_1 LOAD_CONST_STORE 2, 3 CREATE_SCOPE 0 .L0: - LOAD_SYMBOL 3 - LOAD_SYMBOL 1 + LOAD_FAST 3 + LOAD_FAST 1 LE 0 POP_JUMP_IF_FALSE L1 - LOAD_SYMBOL 2 - LOAD_SYMBOL 3 + LOAD_FAST 2 + LOAD_FAST 3 MUL 0 SET_VAL 2 INCREMENT_STORE 3, 1 RESET_SCOPE_JUMP L0 .L1: POP_SCOPE 0 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected index cb6d4141..7d911eb0 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/fused_math_ops.expected @@ -4,390 +4,390 @@ page_0 LOAD_CONST_STORE 2, 2 LOAD_CONST_STORE 3, 3 PUSH_RETURN_ADDRESS L0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 41, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 39, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 40, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 38, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 41, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 39, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 40, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 38, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 41, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 39, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 40, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 38, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 41, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 39, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 40, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 41, 38, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 41, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 39, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 40, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 38, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 41, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 39, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 40, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 38, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 39, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 37, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 41, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 39, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 40, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 38, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 39, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 37, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 41, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 40, 39, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 40, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 40, 38, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 39, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 37, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 40, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 38, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 39, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 40, 37, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 41, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 39, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 40, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 38, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 41, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 39, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 40, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 38, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 39, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 37, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 41, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 39, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 40, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 38, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 39, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 37, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 41, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 39, 39, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 40, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 39, 38, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 39, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 37, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 40, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 38, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 39, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 39, 37, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 41, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 39, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 40, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 38, 41 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 41, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 39, 40 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 40, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 38, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 39, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 37, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 41, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 39, 39 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 40, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 38, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 39, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 37, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 41, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 + FUSED_MATH 38, 39, 38 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 40, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + LOAD_FAST_BY_INDEX 0 FUSED_MATH 38, 38, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 39, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 37, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 40, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 38, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 39, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 38, 37, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 40, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 38, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 39, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 37, 40 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 40, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 38, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 39, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 37, 39 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 40, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 38, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 39, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 37, 38 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 40, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 38, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 39, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - LOAD_SYMBOL_BY_INDEX 0 - FUSED_MATH 37, 37, 37 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 41, 41, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 39, 41, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 40, 41, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 38, 41, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 41, 40, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 39, 40, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 40, 40, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 38, 40, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 39, 40, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 37, 40, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 41, 39, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 39, 39, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 40, 39, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 38, 39, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 39, 39, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 37, 39, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 41, 38, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 + FUSED_MATH 39, 38, 0 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 40, 38, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 3 + LOAD_FAST_BY_INDEX 2 + LOAD_FAST_BY_INDEX 1 FUSED_MATH 38, 38, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 39, 38, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 37, 38, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 40, 37, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 38, 37, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 39, 37, 0 - LOAD_SYMBOL_BY_INDEX 3 - LOAD_SYMBOL_BY_INDEX 2 - LOAD_SYMBOL_BY_INDEX 1 - FUSED_MATH 37, 37, 0 LIST 80 CALL_BUILTIN 9, 1 .L0: diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/increments.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/increments.expected index c0700c67..a7401b22 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/increments.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/increments.expected @@ -6,17 +6,17 @@ page_0 SET_VAL 0 DECREMENT_BY_INDEX 0, 8 SET_VAL 0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LOAD_CONST 4 ADD 0 SET_VAL 0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 LOAD_CONST 5 ADD 0 SET_VAL 0 CREATE_SCOPE 0 .L0: - LOAD_SYMBOL 0 + LOAD_FAST 0 LT_CONST_JUMP_IF_FALSE L1, 6 INCREMENT_STORE 0, 1 INCREMENT_STORE 0, 1 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/jumps.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/jumps.expected index 08e7591e..47797cf6 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/jumps.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/jumps.expected @@ -3,10 +3,10 @@ page_0 LOAD_CONST_STORE 1, 2 CREATE_SCOPE 0 .L0: - LOAD_SYMBOL 2 + LOAD_FAST 2 LT_CONST_JUMP_IF_FALSE L1, 2 PUSH_RETURN_ADDRESS L2 - LOAD_SYMBOL 2 + LOAD_FAST 2 CALL_SYMBOL 1, 1 .L2: POP 0 @@ -14,12 +14,12 @@ page_0 RESET_SCOPE_JUMP L0 .L1: POP_SCOPE 0 - LOAD_SYMBOL 3 + LOAD_FAST 3 LT_CONST_JUMP_IF_TRUE L3, 4 JUMP L4 .L3: PUSH_RETURN_ADDRESS L5 - LOAD_SYMBOL 3 + LOAD_FAST 3 CALL_BUILTIN 9, 1 .L5: POP 0 @@ -27,10 +27,10 @@ page_0 LOAD_CONST_STORE 2, 3 CREATE_SCOPE 0 .L6: - LOAD_SYMBOL 2 + LOAD_FAST 2 LT_SYM_JUMP_IF_FALSE L7, 3 PUSH_RETURN_ADDRESS L8 - LOAD_SYMBOL 2 + LOAD_FAST 2 CALL_SYMBOL 1, 1 .L8: POP 0 @@ -38,22 +38,22 @@ page_0 RESET_SCOPE_JUMP L6 .L7: POP_SCOPE 0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 GT_CONST_JUMP_IF_TRUE L9, 4 JUMP L10 .L9: PUSH_RETURN_ADDRESS L11 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL_BUILTIN 9, 1 .L11: POP 0 .L10: CREATE_SCOPE 0 .L12: - LOAD_SYMBOL 2 + LOAD_FAST 2 GT_CONST_JUMP_IF_FALSE L13, 5 PUSH_RETURN_ADDRESS L14 - LOAD_SYMBOL 2 + LOAD_FAST 2 CALL_BUILTIN 9, 1 .L14: POP 0 @@ -62,17 +62,17 @@ page_0 POP_SCOPE 0 CREATE_SCOPE 0 .L15: - LOAD_SYMBOL 3 + LOAD_FAST 3 GT_SYM_JUMP_IF_FALSE L16, 2 PUSH_RETURN_ADDRESS L17 - LOAD_SYMBOL 3 + LOAD_FAST 3 CALL_BUILTIN 9, 1 .L17: POP 0 RESET_SCOPE_JUMP L15 .L16: POP_SCOPE 0 - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 EQ_CONST_JUMP_IF_TRUE L18, 4 JUMP L19 .L18: @@ -82,7 +82,7 @@ page_0 .L20: POP 0 .L19: - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 EQ_SYM_INDEX_JUMP_IF_TRUE L21, 0 JUMP L22 .L21: @@ -92,7 +92,7 @@ page_0 .L23: POP 0 .L22: - LOAD_SYMBOL_BY_INDEX 1 + LOAD_FAST_BY_INDEX 1 NEQ_CONST_JUMP_IF_TRUE L24, 4 JUMP L25 .L24: @@ -104,10 +104,10 @@ page_0 .L25: CREATE_SCOPE 0 .L27: - LOAD_SYMBOL 2 + LOAD_FAST 2 NEQ_SYM_JUMP_IF_FALSE L28, 3 PUSH_RETURN_ADDRESS L29 - LOAD_SYMBOL 2 + LOAD_FAST 2 CALL_BUILTIN 9, 1 .L29: POP 0 @@ -118,6 +118,6 @@ page_0 page_1 STORE 1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 RET 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/lists.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/lists.expected index 2d5b6778..7521508a 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/lists.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/lists.expected @@ -6,13 +6,13 @@ page_0 LOAD_CONST_STORE 3, 2 LOAD_CONST_STORE 4, 3 PUSH_RETURN_ADDRESS L0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L0: POP 0 STORE_HEAD_BY_INDEX 3, 7 PUSH_RETURN_ADDRESS L1 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL_BUILTIN 9, 1 .L1: POP 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/mul.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/mul.expected index a91f0621..4f7bcedc 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/mul.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/mul.expected @@ -6,7 +6,7 @@ page_0 SET_VAL 0 LOAD_CONST_STORE 2, 1 PUSH_RETURN_ADDRESS L0 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L0: HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/optimized_ir/type.expected b/tests/unittests/resources/CompilerSuite/optimized_ir/type.expected index 0942a68b..ad581087 100644 --- a/tests/unittests/resources/CompilerSuite/optimized_ir/type.expected +++ b/tests/unittests/resources/CompilerSuite/optimized_ir/type.expected @@ -22,7 +22,7 @@ page_0 .L4: LOAD_CONST_STORE 3, 1 PUSH_RETURN_ADDRESS L12 - LOAD_SYMBOL_BY_INDEX 0 + LOAD_FAST_BY_INDEX 0 CALL 0 .L12: HALT 0 diff --git a/tests/unittests/resources/LangSuite/vm-tests.ark b/tests/unittests/resources/LangSuite/vm-tests.ark index 737c963c..83882ee1 100644 --- a/tests/unittests/resources/LangSuite/vm-tests.ark +++ b/tests/unittests/resources/LangSuite/vm-tests.ark @@ -237,4 +237,15 @@ # SET_VAL_HEAD_BY_INDEX (set data (head data)) (test:eq data3 data) - (test:eq data 3) })}) + (test:eq data 3) }) + + (test:case "tail calls" { + (mut output []) + (let f (fun (a b) { + (append! output [a b]) + (if (nil? b) + (f "wrong" a) + (append! output b)) })) + + (f "correct" nil) + (test:eq output [["correct" nil] ["wrong" "correct"] "correct"]) }) })