495#if ARK_USE_COMPUTED_GOTOS 
  496#    define TARGET(op) TARGET_##op: 
  497#    define DISPATCH_GOTO()            \ 
  498        _Pragma("GCC diagnostic push") \ 
  499            _Pragma("GCC diagnostic ignored \"-Wpedantic\"") goto* opcode_targets[inst]; 
  500        _Pragma(
"GCC diagnostic pop")
 
  501#    define GOTO_HALT() goto dispatch_end 
  503#    define TARGET(op) case op: 
  504#    define DISPATCH_GOTO() goto dispatch_opcode 
  505#    define GOTO_HALT() break 
  511        inst = m_state.inst(context.pp, context.ip);                                                                              \ 
  512        padding = m_state.inst(context.pp, context.ip + 1);                                                                       \ 
  513        arg = static_cast<uint16_t>((m_state.inst(context.pp, context.ip + 2) << 8) +                                             \ 
  514                                    m_state.inst(context.pp, context.ip + 3));                                                    \ 
  516        context.inst_exec_counter = (context.inst_exec_counter + 1) % VMOverflowBufferSize;                                       \ 
  517        if (context.inst_exec_counter < 2 && context.sp >= VMStackSize)                                                           \ 
  519            if (context.pp != 0)                                                                                                  \ 
  520                throw Error("Stack overflow. You could consider rewriting your function to make use of tail-call optimization."); \ 
  522                throw Error("Stack overflow. Are you trying to call a function with too many arguments?");                        \ 
  528#define UNPACK_ARGS()                                                                 \ 
  531        secondary_arg = static_cast<uint16_t>((padding << 4) | (arg & 0xf000) >> 12); \ 
  532        primary_arg = arg & 0x0fff;                                                   \ 
  535#if ARK_USE_COMPUTED_GOTOS 
  536#    pragma GCC diagnostic push 
  537#    pragma GCC diagnostic ignored "-Wpedantic" 
  538            constexpr std::array opcode_targets = {
 
  541                &&TARGET_LOAD_SYMBOL,
 
  542                &&TARGET_LOAD_SYMBOL_BY_INDEX,
 
  544                &&TARGET_POP_JUMP_IF_TRUE,
 
  547                &&TARGET_POP_JUMP_IF_FALSE,
 
  551                &&TARGET_PUSH_RETURN_ADDRESS,
 
  554                &&TARGET_RENAME_NEXT_CAPTURE,
 
  557                &&TARGET_MAKE_CLOSURE,
 
  563                &&TARGET_APPEND_IN_PLACE,
 
  564                &&TARGET_CONCAT_IN_PLACE,
 
  566                &&TARGET_POP_LIST_IN_PLACE,
 
  567                &&TARGET_SET_AT_INDEX,
 
  568                &&TARGET_SET_AT_2_INDEX,
 
  570                &&TARGET_SHORTCIRCUIT_AND,
 
  571                &&TARGET_SHORTCIRCUIT_OR,
 
  572                &&TARGET_CREATE_SCOPE,
 
  573                &&TARGET_RESET_SCOPE_JUMP,
 
  575                &&TARGET_GET_CURRENT_PAGE_ADDR,
 
  600                &&TARGET_LOAD_CONST_LOAD_CONST,
 
  601                &&TARGET_LOAD_CONST_STORE,
 
  602                &&TARGET_LOAD_CONST_SET_VAL,
 
  604                &&TARGET_STORE_FROM_INDEX,
 
  605                &&TARGET_SET_VAL_FROM,
 
  606                &&TARGET_SET_VAL_FROM_INDEX,
 
  608                &&TARGET_INCREMENT_BY_INDEX,
 
  609                &&TARGET_INCREMENT_STORE,
 
  611                &&TARGET_DECREMENT_BY_INDEX,
 
  612                &&TARGET_DECREMENT_STORE,
 
  614                &&TARGET_STORE_TAIL_BY_INDEX,
 
  616                &&TARGET_STORE_HEAD_BY_INDEX,
 
  618                &&TARGET_SET_VAL_TAIL,
 
  619                &&TARGET_SET_VAL_TAIL_BY_INDEX,
 
  620                &&TARGET_SET_VAL_HEAD,
 
  621                &&TARGET_SET_VAL_HEAD_BY_INDEX,
 
  622                &&TARGET_CALL_BUILTIN,
 
  623                &&TARGET_CALL_BUILTIN_WITHOUT_RETURN_ADDRESS,
 
  624                &&TARGET_LT_CONST_JUMP_IF_FALSE,
 
  625                &&TARGET_LT_CONST_JUMP_IF_TRUE,
 
  626                &&TARGET_LT_SYM_JUMP_IF_FALSE,
 
  627                &&TARGET_GT_CONST_JUMP_IF_TRUE,
 
  628                &&TARGET_GT_CONST_JUMP_IF_FALSE,
 
  629                &&TARGET_GT_SYM_JUMP_IF_FALSE,
 
  630                &&TARGET_EQ_CONST_JUMP_IF_TRUE,
 
  631                &&TARGET_EQ_SYM_INDEX_JUMP_IF_TRUE,
 
  632                &&TARGET_NEQ_CONST_JUMP_IF_TRUE,
 
  633                &&TARGET_NEQ_SYM_JUMP_IF_FALSE,
 
  634                &&TARGET_CALL_SYMBOL,
 
  635                &&TARGET_CALL_CURRENT_PAGE,
 
  636                &&TARGET_GET_FIELD_FROM_SYMBOL,
 
  637                &&TARGET_GET_FIELD_FROM_SYMBOL_INDEX,
 
  639                &&TARGET_AT_SYM_INDEX_SYM_INDEX,
 
  640                &&TARGET_AT_SYM_INDEX_CONST,
 
  641                &&TARGET_CHECK_TYPE_OF,
 
  642                &&TARGET_CHECK_TYPE_OF_BY_INDEX,
 
  643                &&TARGET_APPEND_IN_PLACE_SYM,
 
  644                &&TARGET_APPEND_IN_PLACE_SYM_INDEX,
 
  646                &&TARGET_LT_LEN_SYM_JUMP_IF_FALSE
 
  649        static_assert(opcode_targets.size() == 
static_cast<std::size_t
>(Instruction::InstructionsCount) && 
"Some instructions are not implemented in the VM");
 
  650#    pragma GCC diagnostic pop 
  658            uint16_t primary_arg = 0;
 
  659            uint16_t secondary_arg = 0;
 
  666#if !ARK_USE_COMPUTED_GOTOS 
  671#pragma region "Instructions" 
  751                                push(std::move(ip_or_val), context);
 
  754                            if (context.
fc <= untilFrameCount)
 
  820                                var->usertypeRef().del();
 
  852                            push(std::move(l), context);
 
  863                                std::vector<Value> args = { *list };
 
  864                                for (uint16_t i = 0; i < arg; ++i)
 
  872                            const auto size = 
static_cast<uint16_t
>(list->
constList().size());
 
  875                            obj.
list().reserve(size + arg);
 
  877                            for (uint16_t i = 0; i < arg; ++i)
 
  879                            push(std::move(obj), context);
 
  890                            for (uint16_t i = 0; i < arg; ++i)
 
  900                                std::ranges::copy(next->
list(), std::back_inserter(obj.list()));
 
  902                            push(std::move(obj), context);
 
  918                        for (uint16_t i = 0; i < arg; ++i)
 
  928                            std::ranges::copy(next->
list(), std::back_inserter(list->
list()));
 
  945                            long idx = 
static_cast<long>(number.
number());
 
  946                            idx = idx < 0 ? static_cast<long>(list.
list().size()) + idx : idx;
 
  947                            if (std::cmp_greater_equal(idx, list.
list().size()) || idx < 0)
 
  950                                    fmt::format(
"pop index ({}) out of range (list size: {})", idx, list.
list().size()));
 
  952                            list.
list().erase(list.
list().begin() + idx);
 
  970                            long idx = 
static_cast<long>(number.
number());
 
  971                            idx = idx < 0 ? static_cast<long>(list->
list().size()) + idx : idx;
 
  972                            if (std::cmp_greater_equal(idx, list->
list().size()) || idx < 0)
 
  975                                    fmt::format(
"pop! index ({}) out of range (list size: {})", idx, list->
list().size()));
 
  977                            list->
list().erase(list->
list().begin() + idx);
 
 1000                                    { *list, number, new_value });
 
 1003                            long idx = 
static_cast<long>(number.
number());
 
 1004                            idx = idx < 0 ? static_cast<long>(size) + idx : idx;
 
 1005                            if (std::cmp_greater_equal(idx, size) || idx < 0)
 
 1008                                    fmt::format(
"@= index ({}) out of range (indexable size: {})", idx, size));
 
 1011                                list->
list()[
static_cast<std::size_t
>(idx)] = new_value;
 
 1013                                list->
stringRef()[
static_cast<std::size_t
>(idx)] = new_value.
string()[0];
 
 1034                                    { *list, x, y, new_value });
 
 1036                            long idx_y = 
static_cast<long>(x.
number());
 
 1037                            idx_y = idx_y < 0 ? static_cast<long>(list->
list().size()) + idx_y : idx_y;
 
 1038                            if (std::cmp_greater_equal(idx_y, list->
list().size()) || idx_y < 0)
 
 1041                                    fmt::format(
"@@= index (y: {}) out of range (list size: {})", idx_y, list->
list().size()));
 
 1043                            if (!list->
list()[
static_cast<std::size_t
>(idx_y)].isIndexable() ||
 
 1057                                    { *list, x, y, new_value });
 
 1059                            const bool is_list = list->
list()[
static_cast<std::size_t
>(idx_y)].valueType() == 
ValueType::List;
 
 1060                            const std::size_t size =
 
 1062                                ? list->
list()[
static_cast<std::size_t
>(idx_y)].list().size()
 
 1063                                : list->
list()[
static_cast<std::size_t
>(idx_y)].stringRef().size();
 
 1065                            long idx_x = 
static_cast<long>(y.
number());
 
 1066                            idx_x = idx_x < 0 ? static_cast<long>(size) + idx_x : idx_x;
 
 1067                            if (std::cmp_greater_equal(idx_x, size) || idx_x < 0)
 
 1070                                    fmt::format(
"@@= index (x: {}) out of range (inner indexable size: {})", idx_x, size));
 
 1073                                list->
list()[
static_cast<std::size_t
>(idx_y)].list()[
static_cast<std::size_t
>(idx_x)] = new_value;
 
 1075                                list->
list()[
static_cast<std::size_t
>(idx_y)].stringRef()[
static_cast<std::size_t
>(idx_x)] = new_value.
string()[0];
 
 1112                        context.
locals.back().reset();
 
 1119                        context.
locals.pop_back();
 
 1132#pragma region "Operators" 
 1188                            throwVMError(ErrorKind::DivisionByZero, fmt::format(
"Can not compute expression (/ {} {})", a->toString(*
this), b->
toString(*
this)));
 
 1357                            long idx_y = 
static_cast<long>(y->
number());
 
 1358                            idx_y = idx_y < 0 ? static_cast<long>(list.
list().size()) + idx_y : idx_y;
 
 1359                            if (std::cmp_greater_equal(idx_y, list.
list().size()) || idx_y < 0)
 
 1362                                    fmt::format(
"@@ index ({}) out of range (list size: {})", idx_y, list.
list().size()));
 
 1364                            const bool is_list = list.
list()[
static_cast<std::size_t
>(idx_y)].valueType() == 
ValueType::List;
 
 1365                            const std::size_t size =
 
 1367                                ? list.
list()[
static_cast<std::size_t
>(idx_y)].list().size()
 
 1368                                : list.
list()[
static_cast<std::size_t
>(idx_y)].stringRef().size();
 
 1370                            long idx_x = 
static_cast<long>(x->
number());
 
 1371                            idx_x = idx_x < 0 ? static_cast<long>(size) + idx_x : idx_x;
 
 1372                            if (std::cmp_greater_equal(idx_x, size) || idx_x < 0)
 
 1375                                    fmt::format(
"@@ index (x: {}) out of range (inner indexable size: {})", idx_x, size));
 
 1378                                push(list.
list()[
static_cast<std::size_t
>(idx_y)].list()[
static_cast<std::size_t
>(idx_x)], context);
 
 1380                                push(
Value(std::string(1, list.
list()[
static_cast<std::size_t
>(idx_y)].stringRef()[
static_cast<std::size_t
>(idx_x)])), context);
 
 1413                                    { *closure, *field });
 
 1422                            auto id = 
static_cast<std::uint16_t
>(std::distance(
m_state.
m_symbols.begin(), it));
 
 1437#pragma region "Super Instructions" 
 1505                                    { *var, 
Value(secondary_arg) });
 
 1526                                    { *var, 
Value(secondary_arg) });
 
 1544                                setVal(primary_arg, &val, context);
 
 1550                                    { *var, 
Value(secondary_arg) });
 
 1571                                    { *var, 
Value(secondary_arg) });
 
 1592                                    { *var, 
Value(secondary_arg) });
 
 1610                                setVal(primary_arg, &val, context);
 
 1616                                    { *var, 
Value(secondary_arg) });
 
 1627                            store(secondary_arg, &tail, context);
 
 1638                            store(secondary_arg, &tail, context);
 
 1649                            store(secondary_arg, &head, context);
 
 1660                            store(secondary_arg, &head, context);
 
 1670                            store(secondary_arg, &l, context);
 
 1681                            setVal(secondary_arg, &tail, context);
 
 1692                            setVal(secondary_arg, &tail, context);
 
 1703                            setVal(secondary_arg, &head, context);
 
 1714                            setVal(secondary_arg, &head, context);
 
 1744                            jump(secondary_arg, context);
 
 1753                            jump(secondary_arg, context);
 
 1761                        if (!(*sym < *
loadSymbol(primary_arg, context)))
 
 1762                            jump(secondary_arg, context);
 
 1772                            jump(secondary_arg, context);
 
 1782                            jump(secondary_arg, context);
 
 1792                            jump(secondary_arg, context);
 
 1801                            jump(secondary_arg, context);
 
 1810                            jump(secondary_arg, context);
 
 1819                            jump(secondary_arg, context);
 
 1827                        if (*sym == *
loadSymbol(primary_arg, context))
 
 1828                            jump(secondary_arg, context);
 
 1845                        call(context, secondary_arg,  
nullptr,  
static_cast<PageAddr_t>(context.
pp));
 
 1937                                len = 
Value(
static_cast<int>(a->
string().size()));
 
 1944                            store(secondary_arg, &len, context);
 
 1959                                size = 
Value(
static_cast<int>(sym->
string().size()));
 
 1968                                jump(secondary_arg, context);
 
 1974#if ARK_USE_COMPUTED_GOTOS 
 1982        catch (
const Error& e)
 
 1984            if (fail_with_exception)
 
 1986                std::stringstream stream;
 
 1995        catch (
const std::exception& e)
 
 1997            if (fail_with_exception)
 
 1999                std::stringstream stream;
 
 2008            if (fail_with_exception)
 
 2011#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 
 2014            fmt::println(
"Unknown error");
 
 
 2141        const std::size_t saved_ip = context.
ip;
 
 2142        const std::size_t saved_pp = context.
pp;
 
 2143        const uint16_t saved_sp = context.
sp;
 
 2144        constexpr std::size_t max_consecutive_traces = 7;
 
 2154                        .filename = filename,
 
 2155                        .start = 
FilePos { .line = maybe_location->line, .column = 0 },
 
 2156                        .end = std::nullopt },
 
 2160            fmt::println(os, 
"");
 
 2168            std::string previous_trace;
 
 2169            std::size_t displayed_traces = 0;
 
 2170            std::size_t consecutive_similar_traces = 0;
 
 2172            while (context.
fc != 0 && context.
pp != 0)
 
 2175                const auto loc_as_text = maybe_call_loc ? fmt::format(
" ({}:{})", 
m_state.
m_filenames[maybe_call_loc->filename_id], maybe_call_loc->line + 1) : 
"";
 
 2182                if (func_name + loc_as_text != previous_trace)
 
 2186                        "[{:4}] In function `{}'{}",
 
 2187                        fmt::styled(context.
fc, colorize ? fmt::fg(fmt::color::cyan) : fmt::text_style()),
 
 2188                        fmt::styled(func_name, colorize ? fmt::fg(fmt::color::green) : fmt::text_style()),
 
 2190                    previous_trace = func_name + loc_as_text;
 
 2192                    consecutive_similar_traces = 0;
 
 2194                else if (consecutive_similar_traces == 0)
 
 2196                    fmt::println(os, 
"       ...");
 
 2197                    ++consecutive_similar_traces;
 
 2210                if (displayed_traces > max_consecutive_traces)
 
 2212                    fmt::println(os, 
"       ...");
 
 2217            if (context.
pp == 0)
 
 2220                const auto loc_as_text = maybe_call_loc ? fmt::format(
" ({}:{})", 
m_state.
m_filenames[maybe_call_loc->filename_id], maybe_call_loc->line + 1) : 
"";
 
 2221                fmt::println(os, 
"[{:4}] In global scope{}", fmt::styled(context.
fc, colorize ? fmt::fg(fmt::color::cyan) : fmt::text_style()), loc_as_text);
 
 2225            fmt::println(os, 
"\nCurrent scope variables values:");
 
 2226            for (std::size_t i = 0, size = old_scope.
size(); i < size; ++i)
 
 2231                    fmt::styled(
m_state.
m_symbols[old_scope.
atPos(i).first], colorize ? fmt::fg(fmt::color::cyan) : fmt::text_style()),
 
 2232                    old_scope.
atPos(i).second.toString(*
this));
 
 2238            "At IP: {}, PP: {}, SP: {}",
 
 2240            fmt::styled(saved_ip / 4, colorize ? fmt::fg(fmt::color::cyan) : fmt::text_style()),
 
 2241            fmt::styled(saved_pp, colorize ? fmt::fg(fmt::color::green) : fmt::text_style()),
 
 2242            fmt::styled(saved_sp, colorize ? fmt::fg(fmt::color::yellow) : fmt::text_style()));