From 3dc6ad866f2747944fe54a306f02393abdf32930 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Tue, 30 Mar 2021 02:08:25 +0200 Subject: [PATCH] make command argcount unlimited, remove maxargs checks from codegen also adjust the bytecode appropriately, now you can call commands with an unlimited number of args and aliases with max 32 args, extra args will be ignored --- src/cs_bcode.hh | 14 ++++---- src/cs_gen.cc | 90 ++++++++++++++----------------------------------- src/cs_ident.hh | 2 +- src/cs_state.cc | 20 +++++------ src/cs_vm.cc | 16 +++++---- 5 files changed, 51 insertions(+), 91 deletions(-) diff --git a/src/cs_bcode.hh b/src/cs_bcode.hh index 457e413..44a1f7c 100644 --- a/src/cs_bcode.hh +++ b/src/cs_bcode.hh @@ -163,9 +163,9 @@ enum { BC_INST_ALIAS, /* pop 2 values off the stack; top is value to set, below is alias name */ BC_INST_ALIAS_U, - /* call alias with index D[5..] and arg count D[0..5], pop the arguments - * off the stack (top being last); if unknown, raise error, store result - * in R according to M + /* call alias with index D and arg count following the instruction, pop + * the arguments off the stack (top being last); if unknown, raise error, + * store result in R according to M */ BC_INST_CALL, /* given argument count D, pop the arguments off the stack (top being last) @@ -178,12 +178,12 @@ enum { * last argument being topmost; result of the call goes in R according to M */ BC_INST_COM, - /* call builtin command with index D[5..] and number of arguments D[0..5] - * arguments are popped off the stack and passed as is + /* call builtin command with index D and arg count following the + * instruction, arguments are popped off the stack and passed as is */ BC_INST_COM_V, - /* call builtin command with index D[5..] and number of arguments D[0..5] - * arguments are popped off the stack and concatenated together + /* call builtin command with index D and arg count following the + * instruction, arguments are popped off the stack and concatenated */ BC_INST_COM_C, diff --git a/src/cs_gen.cc b/src/cs_gen.cc index ddde6f3..8b4ce1f 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -308,7 +308,7 @@ lookupid: } goto done; case ident_type::COMMAND: { - int comtype = BC_INST_COM, numargs = 0; + std::uint32_t comtype = BC_INST_COM, numargs = 0; auto fmt = static_cast(id)->get_args(); for (char c: fmt) { switch (c) { @@ -375,9 +375,9 @@ lookupid: goto done; compilecomv: gs.code.push_back( - comtype | ret_code(ltype) | (numargs << 8) | - (id->get_index() << 13) + comtype | ret_code(ltype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); gs.code.push_back( BC_INST_RESULT_ARG | ret_code(ltype) ); @@ -802,7 +802,7 @@ static bool compilearg( static void compile_cmd( codegen_state &gs, command_impl *id, bool &more, int rettype ) { - int comtype = BC_INST_COM, numargs = 0, fakeargs = 0; + std::uint32_t comtype = BC_INST_COM, numargs = 0, fakeargs = 0; bool rep = false; auto fmt = id->get_args(); for (auto it = fmt.begin(); it != fmt.end(); ++it) { @@ -819,11 +819,7 @@ static void compile_cmd( fakeargs++; } else if ((it + 1) == fmt.end()) { int numconc = 1; - while ((numargs + numconc) < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_STRING); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_STRING))) { numconc++; } if (numconc > 1) { @@ -947,11 +943,7 @@ static void compile_cmd( case 'C': /* concatenated string */ comtype = BC_INST_COM_C; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_ANY))) { numargs++; } } @@ -959,11 +951,7 @@ static void compile_cmd( case 'V': /* varargs */ comtype = BC_INST_COM_V; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_ANY))) { numargs++; } } @@ -972,15 +960,10 @@ static void compile_cmd( case '2': case '3': case '4': - if (more && (numargs < MAX_ARGUMENTS)) { + if (more) { int numrep = *it - '0' + 1; it -= numrep; rep = true; - } else { - while (numargs > MAX_ARGUMENTS) { - gs.code.push_back(BC_INST_POP); - --numargs; - } } break; } @@ -989,38 +972,29 @@ static void compile_cmd( return; compilecomv: gs.code.push_back( - comtype | ret_code(rettype) | (numargs << 8) | (id->get_index() << 13) + comtype | ret_code(rettype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); } static void compile_alias(codegen_state &gs, alias *id, bool &more) { - int numargs = 0; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + std::uint32_t numargs = 0; + while ((more = compilearg(gs, VAL_ANY))) { ++numargs; } gs.code.push_back( - BC_INST_CALL | (numargs << 8) | (id->get_index() << 13) + BC_INST_CALL | (id->get_index() << 8) ); + gs.code.push_back(numargs); } static void compile_local(codegen_state &gs, bool &more) { - int numargs = 0; + std::uint32_t numargs = 0; if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_IDENT); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_IDENT))) { numargs++; } } - if (more) { - while ((more = compilearg(gs, VAL_POP))); - } gs.code.push_back(BC_INST_LOCAL | (numargs << 8)); } @@ -1100,7 +1074,7 @@ static void compile_if( static void compile_and_or( codegen_state &gs, ident *id, bool &more, int rettype ) { - int numargs = 0; + std::uint32_t numargs = 0; if (more) { more = compilearg(gs, VAL_COND); } @@ -1112,11 +1086,7 @@ static void compile_and_or( } else { numargs++; int start = gs.code.size(), end = start; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_COND); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_COND))) { numargs++; if ((gs.code[end] & ~BC_INST_RET_MASK) != ( BC_INST_BLOCK | (uint32_t(gs.code.size() - (end + 1)) << 8) @@ -1126,17 +1096,13 @@ static void compile_and_or( end = gs.code.size(); } if (more) { - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_COND); - if (!more) { - break; - } + while ((more = compilearg(gs, VAL_COND))) { numargs++; } gs.code.push_back( - BC_INST_COM_V | ret_code(rettype) | - (numargs << 8) | (id->get_index() << 13) + BC_INST_COM_V | ret_code(rettype) | (id->get_index() << 8) ); + gs.code.push_back(numargs); } else { uint32_t op = (id->get_raw_type() == ID_AND) ? (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE) @@ -1240,12 +1206,8 @@ static void compilestatements(codegen_state &gs, int rettype, int brak) { } if (idname.empty()) { noid: - int numargs = 0; - while (numargs < MAX_ARGUMENTS) { - more = compilearg(gs, VAL_ANY); - if (!more) { - break; - } + std::uint32_t numargs = 0; + while ((more = compilearg(gs, VAL_ANY))) { ++numargs; } gs.code.push_back(BC_INST_CALL_U | (numargs << 8)); @@ -1351,12 +1313,10 @@ noid: if (!(more = compilearg(gs, VAL_STRING))) { gs.code.push_back(BC_INST_PRINT | (id->get_index() << 8)); } else { - int numargs = 0; + std::uint32_t numargs = 0; do { ++numargs; - } while (numargs < MAX_ARGUMENTS && ( - more = compilearg(gs, VAL_ANY) - )); + } while ((more = compilearg(gs, VAL_ANY))); if (numargs > 1) { gs.code.push_back( BC_INST_CONC | BC_RET_STRING | (numargs << 8) diff --git a/src/cs_ident.hh b/src/cs_ident.hh index 27b7555..259e91f 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -7,7 +7,7 @@ namespace cubescript { -static constexpr int MAX_ARGUMENTS = 32; +static constexpr std::size_t MAX_ARGUMENTS = 32; using argset = std::bitset; enum { diff --git a/src/cs_state.cc b/src/cs_state.cc index a01e8c3..c60f9df 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -73,9 +73,9 @@ state::state(alloc_func func, void *data) { p_tstate->istate = statep; p_tstate->owner = true; - for (int i = 0; i < MAX_ARGUMENTS; ++i) { - char buf[32]; - snprintf(buf, sizeof(buf), "arg%d", i + 1); + for (std::size_t i = 0; i < MAX_ARGUMENTS; ++i) { + char buf[16]; + snprintf(buf, sizeof(buf), "arg%zu", i + 1); new_ident(static_cast(buf), IDENT_FLAG_ARG); } @@ -419,15 +419,14 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( case 'e': case 'r': case '$': - if (nargs < MAX_ARGUMENTS) { - ++nargs; - } + ++nargs; break; case '1': case '2': case '3': - case '4': - if (nargs < (*fmt - '0')) { + case '4': { + int nrep = (*fmt - '0'); + if (nargs < nrep) { return nullptr; } if ((args.end() - fmt) != 2) { @@ -436,10 +435,9 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( if ((fmt[1] != 'C') && (fmt[1] != 'V')) { return nullptr; } - if (nargs < MAX_ARGUMENTS) { - fmt -= *fmt - '0' + 1; - } + nargs -= nrep; break; + } case 'C': case 'V': if ((fmt + 1) != args.end()) { diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 4bd2f19..e148ac4 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -202,6 +202,8 @@ void exec_alias( std::size_t callargs, std::size_t &nargs, std::size_t offset, std::size_t skip, std::uint32_t op ) { + /* excess arguments get ignored (make error maybe?) */ + callargs = std::min(callargs, MAX_ARGUMENTS); integer_var *anargs = static_cast( ts.istate->identmap[ID_IDX_NUMARGS] ); @@ -1062,8 +1064,8 @@ std::uint32_t *vm_exec( case BC_INST_CALL | BC_RET_FLOAT: case BC_INST_CALL | BC_RET_INT: { result.force_none(); - ident *id = ts.istate->identmap[op >> 13]; - std::size_t callargs = (op >> 8) & 0x1F; + ident *id = ts.istate->identmap[op >> 8]; + std::size_t callargs = *code++; std::size_t nnargs = args.size(); std::size_t offset = nnargs - callargs; auto flags = id->get_flags(); @@ -1232,9 +1234,9 @@ noid: case BC_INST_COM_V | BC_RET_FLOAT: case BC_INST_COM_V | BC_RET_INT: { command_impl *id = static_cast( - ts.istate->identmap[op >> 13] + ts.istate->identmap[op >> 8] ); - std::size_t callargs = (op >> 8) & 0x1F; + std::size_t callargs = *code++; std::size_t offset = args.size() - callargs; result.force_none(); id->call(cs, std::span{&args[offset], callargs}, result); @@ -1247,10 +1249,10 @@ noid: case BC_INST_COM_C | BC_RET_FLOAT: case BC_INST_COM_C | BC_RET_INT: { command_impl *id = static_cast( - ts.istate->identmap[op >> 13] + ts.istate->identmap[op >> 8] ); - std::size_t callargs = (op >> 8) & 0x1F, - offset = args.size() - callargs; + std::size_t callargs = *code++; + std::size_t offset = args.size() - callargs; result.force_none(); { any_value tv{cs};