diff --git a/src/cs_bcode.hh b/src/cs_bcode.hh index 2aebcbe..81b86ad 100644 --- a/src/cs_bcode.hh +++ b/src/cs_bcode.hh @@ -26,6 +26,11 @@ enum { VAL_POP, VAL_COND }; +template +constexpr std::size_t bc_store_size = ( + sizeof(T) - 1 +) / sizeof(std::uint32_t) + 1; + /* instruction: uint32 [length 24][retflag 2][opcode 6] */ enum { BC_INST_START = 0, diff --git a/src/cs_error.cc b/src/cs_error.cc index 34b5fa4..86445e8 100644 --- a/src/cs_error.cc +++ b/src/cs_error.cc @@ -1,6 +1,6 @@ #include -#include "cs_vm.hh" +#include "cs_gen.hh" namespace cubescript { @@ -44,7 +44,7 @@ LIBCUBESCRIPT_EXPORT char *error::request_buf( } LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) { - integer_var *dalias = static_cast(cs.p_state->identmap[DbgaliasIdx]); + integer_var *dalias = static_cast(cs.p_state->identmap[ID_IDX_DBGALIAS]); if (!dalias->get_value()) { return stack_state(cs, nullptr, !!cs.p_callstack); } diff --git a/src/cs_gen.cc b/src/cs_gen.cc index e9f8366..9566af3 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -1,5 +1,5 @@ #include -#include "cs_vm.hh" +#include "cs_gen.hh" #include "cs_std.hh" #include "cs_parser.hh" @@ -213,11 +213,11 @@ static inline void compileunescapestr(codegen_state &gs) { } static bool compilearg( - codegen_state &gs, int wordtype, int prevargs = MaxResults, + codegen_state &gs, int wordtype, int prevargs = MAX_RESULTS, charbuf *word = nullptr ); -static void compilelookup(codegen_state &gs, int ltype, int prevargs = MaxResults) { +static void compilelookup(codegen_state &gs, int ltype, int prevargs = MAX_RESULTS) { charbuf lookup{gs.cs}; gs.next_char(); switch (gs.current()) { @@ -294,7 +294,7 @@ lookupid: return; case VAL_COND: gs.code.push_back( - (id->get_index() < MaxArguments + (id->get_index() < MAX_ARGUMENTS ? BC_INST_LOOKUP_MARG : BC_INST_LOOKUP_M ) | (id->get_index() << 8) @@ -303,7 +303,7 @@ lookupid: case VAL_CODE: case VAL_IDENT: gs.code.push_back( - (id->get_index() < MaxArguments + (id->get_index() < MAX_ARGUMENTS ? BC_INST_LOOKUP_MARG : BC_INST_LOOKUP_M ) | BC_RET_STRING | (id->get_index() << 8) @@ -311,7 +311,7 @@ lookupid: break; default: gs.code.push_back( - (id->get_index() < MaxArguments + (id->get_index() < MAX_ARGUMENTS ? BC_INST_LOOKUP_ARG : BC_INST_LOOKUP ) | ret_code(ltype, BC_RET_STRING) | @@ -322,7 +322,7 @@ lookupid: goto done; case ident_type::COMMAND: { int comtype = BC_INST_COM, numargs = 0; - if (prevargs >= MaxResults) { + if (prevargs >= MAX_RESULTS) { gs.code.push_back(BC_INST_ENTER); } auto fmt = static_cast(id)->get_args(); @@ -391,7 +391,7 @@ lookupid: comtype | ret_code(ltype) | (id->get_index() << 8) ); gs.code.push_back( - (prevargs >= MaxResults + (prevargs >= MAX_RESULTS ? BC_INST_EXIT : BC_INST_RESULT_ARG ) | ret_code(ltype) @@ -403,7 +403,7 @@ lookupid: (id->get_index() << 13) ); gs.code.push_back( - (prevargs >= MaxResults + (prevargs >= MAX_RESULTS ? BC_INST_EXIT : BC_INST_RESULT_ARG ) | ret_code(ltype) @@ -557,7 +557,7 @@ lookupid: goto done; case ident_type::ALIAS: gs.code.push_back( - (id->get_index() < MaxArguments + (id->get_index() < MAX_ARGUMENTS ? BC_INST_LOOKUP_MARG : BC_INST_LOOKUP_M ) | (id->get_index() << 8) @@ -615,10 +615,10 @@ static void compileblockmain(codegen_state &gs, int wordtype, int prevargs) { throw error(gs.cs, "too many @s"); return; } - if (!concs && prevargs >= MaxResults) { + if (!concs && prevargs >= MAX_RESULTS) { gs.code.push_back(BC_INST_ENTER); } - if (concs + 2 > MaxArguments) { + if (concs + 2 > MAX_ARGUMENTS) { gs.code.push_back(BC_INST_CONC_W | BC_RET_STRING | (concs << 8)); concs = 1; } @@ -631,7 +631,7 @@ static void compileblockmain(codegen_state &gs, int wordtype, int prevargs) { if (concs) { start = gs.source; curline = gs.current_line; - } else if (prevargs >= MaxResults) { + } else if (prevargs >= MAX_RESULTS) { gs.code.pop_back(); } break; @@ -669,7 +669,7 @@ static void compileblockmain(codegen_state &gs, int wordtype, int prevargs) { } } if (concs) { - if (prevargs >= MaxResults) { + if (prevargs >= MAX_RESULTS) { gs.code.push_back(BC_INST_CONC_M | ret_code(wordtype) | (concs << 8)); gs.code.push_back(BC_INST_EXIT | ret_code(wordtype)); } else { @@ -773,7 +773,7 @@ static bool compilearg( return true; case '(': gs.next_char(); - if (prevargs >= MaxResults) { + if (prevargs >= MAX_RESULTS) { gs.code.push_back(BC_INST_ENTER); compilestatements(gs, VAL_ANY, ')'); gs.code.push_back(BC_INST_EXIT | ret_code(wordtype)); @@ -870,7 +870,7 @@ static void compile_cmd( fakeargs++; } else if ((it + 1) == fmt.end()) { int numconc = 1; - while ((numargs + numconc) < MaxArguments) { + while ((numargs + numconc) < MAX_ARGUMENTS) { more = compilearg( gs, VAL_STRING, prevargs + numargs + numconc ); @@ -1003,7 +1003,7 @@ static void compile_cmd( case 'C': /* concatenated string */ comtype = BC_INST_COM_C; if (more) { - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_ANY, prevargs + numargs); if (!more) { break; @@ -1015,7 +1015,7 @@ static void compile_cmd( case 'V': /* varargs */ comtype = BC_INST_COM_V; if (more) { - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_ANY, prevargs + numargs); if (!more) { break; @@ -1028,12 +1028,12 @@ static void compile_cmd( case '2': case '3': case '4': - if (more && (numargs < MaxArguments)) { + if (more && (numargs < MAX_ARGUMENTS)) { int numrep = *it - '0' + 1; it -= numrep; rep = true; } else { - while (numargs > MaxArguments) { + while (numargs > MAX_ARGUMENTS) { gs.code.push_back(BC_INST_POP); --numargs; } @@ -1051,7 +1051,7 @@ compilecomv: static void compile_alias(codegen_state &gs, alias *id, bool &more, int prevargs) { int numargs = 0; - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_ANY, prevargs + numargs); if (!more) { break; @@ -1059,7 +1059,7 @@ static void compile_alias(codegen_state &gs, alias *id, bool &more, int prevargs ++numargs; } gs.code.push_back( - (id->get_index() < MaxArguments ? BC_INST_CALL_ARG : BC_INST_CALL) + (id->get_index() < MAX_ARGUMENTS ? BC_INST_CALL_ARG : BC_INST_CALL) | (numargs << 8) | (id->get_index() << 13) ); } @@ -1067,7 +1067,7 @@ static void compile_alias(codegen_state &gs, alias *id, bool &more, int prevargs static void compile_local(codegen_state &gs, bool &more, int prevargs) { int numargs = 0; if (more) { - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_IDENT, prevargs + numargs); if (!more) { break; @@ -1169,7 +1169,7 @@ static void compile_and_or( } else { numargs++; int start = gs.code.size(), end = start; - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_COND, prevargs + numargs); if (!more) { break; @@ -1183,7 +1183,7 @@ static void compile_and_or( end = gs.code.size(); } if (more) { - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_COND, prevargs + numargs); if (!more) { break; @@ -1249,7 +1249,7 @@ static void compilestatements(codegen_state &gs, int rettype, int brak, int prev gs.gen_str(); } gs.code.push_back( - (id->get_index() < MaxArguments + (id->get_index() < MAX_ARGUMENTS ? BC_INST_ALIAS_ARG : BC_INST_ALIAS ) | (id->get_index() << 8) @@ -1299,7 +1299,7 @@ static void compilestatements(codegen_state &gs, int rettype, int brak, int prev if (idname.empty()) { noid: int numargs = 0; - while (numargs < MaxArguments) { + while (numargs < MAX_ARGUMENTS) { more = compilearg(gs, VAL_ANY, prevargs + numargs); if (!more) { break; @@ -1412,7 +1412,7 @@ noid: int numargs = 0; do { ++numargs; - } while (numargs < MaxArguments && ( + } while (numargs < MAX_ARGUMENTS && ( more = compilearg( gs, VAL_ANY, prevargs + numargs ) diff --git a/src/cs_gen.hh b/src/cs_gen.hh new file mode 100644 index 0000000..00d80ce --- /dev/null +++ b/src/cs_gen.hh @@ -0,0 +1,165 @@ +#ifndef LIBCUBESCRIPT_GEN_HH +#define LIBCUBESCRIPT_GEN_HH + +#include "cubescript/cubescript.hh" + +#include +#include +#include +#include + +#include "cs_std.hh" +#include "cs_bcode.hh" +#include "cs_ident.hh" + +namespace cubescript { + +static constexpr int MAX_ARGUMENTS = 25; +static constexpr int MAX_RESULTS = 7; + +static constexpr int ID_IDX_DUMMY = MAX_ARGUMENTS; +static constexpr int ID_IDX_NUMARGS = MAX_ARGUMENTS + 1; +static constexpr int ID_IDX_DBGALIAS = MAX_ARGUMENTS + 2; + +struct codegen_state { + state &cs; + codegen_state *prevps; + bool parsing = true; + valbuf code; + char const *source, *send; + std::size_t current_line; + std::string_view src_name; + + codegen_state() = delete; + codegen_state(state &csr): + cs{csr}, prevps{csr.p_pstate}, code{cs}, + source{}, send{}, current_line{1}, src_name{} + { + csr.p_pstate = this; + } + + ~codegen_state() { + done(); + } + + void done() { + if (!parsing) { + return; + } + cs.p_pstate = prevps; + parsing = false; + } + + std::string_view get_str(); + charbuf get_str_dup(); + + std::string_view get_word(); + + void gen_str(std::string_view word) { + if (word.size() <= 3) { + std::uint32_t op = BC_INST_VAL_INT | BC_RET_STRING; + for (size_t i = 0; i < word.size(); ++i) { + op |= std::uint32_t( + static_cast(word[i]) + ) << ((i + 1) * 8); + } + code.push_back(op); + return; + } + code.push_back(BC_INST_VAL | BC_RET_STRING | (word.size() << 8)); + auto it = reinterpret_cast(word.data()); + code.append(it, it + (word.size() / sizeof(std::uint32_t))); + std::size_t esz = word.size() % sizeof(std::uint32_t); + char c[sizeof(std::uint32_t)] = {0}; + std::memcpy(c, word.data() + word.size() - esz, esz); + std::uint32_t u; + std::memcpy(&u, c, sizeof(u)); + code.push_back(u); + } + + void gen_str() { + code.push_back(BC_INST_VAL_INT | BC_RET_STRING); + } + + void gen_null() { + code.push_back(BC_INST_VAL_INT | BC_RET_NULL); + } + + void gen_int(integer_type i = 0) { + if (i >= -0x800000 && i <= 0x7FFFFF) { + code.push_back(BC_INST_VAL_INT | BC_RET_INT | (i << 8)); + } else { + std::uint32_t u[bc_store_size] = {0}; + std::memcpy(u, &i, sizeof(i)); + code.push_back(BC_INST_VAL | BC_RET_INT); + code.append(u, u + bc_store_size); + } + } + + void gen_int(std::string_view word); + + void gen_float(float_type f = 0.0f) { + if (integer_type(f) == f && f >= -0x800000 && f <= 0x7FFFFF) { + code.push_back(BC_INST_VAL_INT | BC_RET_FLOAT | (integer_type(f) << 8)); + } else { + std::uint32_t u[bc_store_size] = {0}; + std::memcpy(u, &f, sizeof(f)); + code.push_back(BC_INST_VAL | BC_RET_FLOAT); + code.append(u, u + bc_store_size); + } + } + + void gen_float(std::string_view word); + + void gen_ident(ident *id) { + code.push_back( + ((id->get_index() < MAX_ARGUMENTS) + ? BC_INST_IDENT_ARG + : BC_INST_IDENT + ) | (id->get_index() << 8) + ); + } + + void gen_ident() { + gen_ident(cs.p_state->identmap[ID_IDX_DUMMY]); + } + + void gen_ident(std::string_view word) { + gen_ident(cs.new_ident(word)); + } + + void gen_value( + int wordtype, std::string_view word = std::string_view(), + int line = 0 + ); + + void gen_main(std::string_view s, int ret_type = VAL_ANY); + + void next_char() { + if (source == send) { + return; + } + if (*source == '\n') { + ++current_line; + } + ++source; + } + + char current(size_t ahead = 0) { + if (std::size_t(send - source) <= ahead) { + return '\0'; + } + return source[ahead]; + } + + std::string_view read_macro_name(); + + char skip_until(std::string_view chars); + char skip_until(char cf); + + void skip_comments(); +}; + +} /* namespace cubescript */ + +#endif /* LIBCUBESCRIPT_GEN_HH */ diff --git a/src/cs_ident.cc b/src/cs_ident.cc index a53b9a5..659c6b6 100644 --- a/src/cs_ident.cc +++ b/src/cs_ident.cc @@ -1,7 +1,7 @@ #include "cs_ident.hh" #include "cs_bcode.hh" -#include "cs_vm.hh" +#include "cs_gen.hh" namespace cubescript { diff --git a/src/cs_state.cc b/src/cs_state.cc index 7ef3331..5a8a06a 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -3,7 +3,8 @@ #include "cs_bcode.hh" #include "cs_state.hh" #include "cs_strman.hh" -#include "cs_vm.hh" // FIXME, only Max Arguments +#include "cs_gen.hh" // FIXME, only MAX_ARGUMENTS +#include "cs_vm.hh" // break/continue, call_with_args #include "cs_parser.hh" namespace cubescript { @@ -66,24 +67,24 @@ state::state(alloc_func func, void *data): /* will be used as message storage for errors */ p_errbuf = p_state->create(*this); - for (int i = 0; i < MaxArguments; ++i) { + for (int i = 0; i < MAX_ARGUMENTS; ++i) { char buf[32]; snprintf(buf, sizeof(buf), "arg%d", i + 1); new_ident(static_cast(buf), IDENT_FLAG_ARG); } ident *id = new_ident("//dummy"); - if (id->get_index() != DummyIdx) { + if (id->get_index() != ID_IDX_DUMMY) { throw internal_error{"invalid dummy index"}; } - id = new_ivar("numargs", MaxArguments, 0, 0); - if (id->get_index() != NumargsIdx) { + id = new_ivar("numargs", MAX_ARGUMENTS, 0, 0); + if (id->get_index() != ID_IDX_NUMARGS) { throw internal_error{"invalid numargs index"}; } id = new_ivar("dbgalias", 0, 1000, 4); - if (id->get_index() != DbgaliasIdx) { + if (id->get_index() != ID_IDX_DBGALIAS) { throw internal_error{"invalid dbgalias index"}; } @@ -157,7 +158,7 @@ state::state(alloc_func func, void *data): p = new_command("break", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { - throw CsBreakException{}; + throw break_exception{}; } else { throw error{cs, "no loop to break"}; } @@ -166,7 +167,7 @@ state::state(alloc_func func, void *data): p = new_command("continue", "", [](auto &cs, auto, auto &) { if (cs.is_in_loop()) { - throw CsContinueException{}; + throw continue_exception{}; } else { throw error{cs, "no loop to continue"}; } @@ -284,8 +285,8 @@ LIBCUBESCRIPT_EXPORT ident *state::force_ident(any_value &v) { default: break; } - v.set_ident(p_state->identmap[DummyIdx]); - return p_state->identmap[DummyIdx]; + v.set_ident(p_state->identmap[ID_IDX_DUMMY]); + return p_state->identmap[ID_IDX_DUMMY]; } LIBCUBESCRIPT_EXPORT ident *state::get_ident(std::string_view name) { @@ -379,7 +380,7 @@ LIBCUBESCRIPT_EXPORT void state::set_alias( switch (id->get_type()) { case ident_type::ALIAS: { alias_impl *a = static_cast(id); - if (a->get_index() < MaxArguments) { + if (a->get_index() < MAX_ARGUMENTS) { a->set_arg(*this, v); } else { a->set_alias(*this, v); @@ -429,7 +430,7 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( case 'e': case 'r': case '$': - if (nargs < MaxArguments) { + if (nargs < MAX_ARGUMENTS) { ++nargs; } break; @@ -446,7 +447,7 @@ LIBCUBESCRIPT_EXPORT command *state::new_command( if ((fmt[1] != 'C') && (fmt[1] != 'V')) { return nullptr; } - if (nargs < MaxArguments) { + if (nargs < MAX_ARGUMENTS) { fmt -= *fmt - '0' + 1; } break; @@ -660,7 +661,7 @@ state::get_alias_val(std::string_view name) { if (!a) { return std::nullopt; } - if ((a->get_index() < MaxArguments) && !ident_is_used_arg(a, *this)) { + if ((a->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(a, *this)) { return std::nullopt; } return a->get_value().get_str(); diff --git a/src/cs_val.cc b/src/cs_val.cc index bc4560f..a943163 100644 --- a/src/cs_val.cc +++ b/src/cs_val.cc @@ -1,5 +1,5 @@ #include -#include "cs_vm.hh" +#include "cs_gen.hh" #include "cs_std.hh" #include "cs_parser.hh" diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 87c8512..6c0cf3e 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -16,14 +16,14 @@ static inline bool ident_has_cb(ident *id) { } static inline void push_alias(state &cs, ident *id, ident_stack &st) { - if (id->is_alias() && (id->get_index() >= MaxArguments)) { + if (id->is_alias() && (id->get_index() >= MAX_ARGUMENTS)) { any_value nv{cs}; static_cast(id)->push_arg(nv, st); } } static inline void pop_alias(ident *id) { - if (id->is_alias() && (id->get_index() >= MaxArguments)) { + if (id->is_alias() && (id->get_index() >= MAX_ARGUMENTS)) { static_cast(id)->pop_arg(); } } @@ -214,7 +214,7 @@ static inline void callcommand( if (rep) { break; } - args[i].set_ident(cs.p_state->identmap[DummyIdx]); + args[i].set_ident(cs.p_state->identmap[ID_IDX_DUMMY]); fakeargs++; } else { cs.force_ident(args[i]); @@ -268,8 +268,8 @@ static inline void call_alias( state &cs, alias *a, any_value *args, any_value &result, int callargs, int &nargs, int offset, int skip, uint32_t op ) { - integer_var *anargs = static_cast(cs.p_state->identmap[NumargsIdx]); - valarray argstack{cs}; + integer_var *anargs = static_cast(cs.p_state->identmap[ID_IDX_NUMARGS]); + valarray argstack{cs}; for(int i = 0; i < callargs; i++) { static_cast(cs.p_state->identmap[i])->push_arg( args[offset + i], argstack[i], false @@ -354,7 +354,7 @@ static inline int get_lookupu_type( if (id->get_flags() & IDENT_FLAG_UNKNOWN) { break; } - if ((id->get_index() < MaxArguments) && !ident_is_used_arg(id, cs)) { + if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) { return ID_UNKNOWN; } return ID_ALIAS; @@ -366,7 +366,7 @@ static inline int get_lookupu_type( return ID_FVAR; case ident_type::COMMAND: { arg.set_none(); - valarray buf{cs}; + valarray buf{cs}; callcommand( cs, static_cast(id), &buf[0], arg, 0, true @@ -385,7 +385,7 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { result.set_none(); RunDepthRef level{cs}; /* incr and decr on scope exit */ int numargs = 0; - valarray args{cs}; + valarray args{cs}; auto &chook = cs.get_call_hook(); if (chook) { chook(cs); @@ -476,7 +476,7 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { case BC_INST_LOCAL: { int numlocals = op >> 8, offset = numargs - numlocals; - valarray locals{cs}; + valarray locals{cs}; for (int i = 0; i < numlocals; ++i) { push_alias(cs, args[offset + i].get_ident(), locals[i]); } @@ -555,14 +555,14 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { } case BC_INST_BREAK | BC_INST_FLAG_FALSE: if (cs.is_in_loop()) { - throw CsBreakException(); + throw break_exception(); } else { throw error(cs, "no loop to break"); } break; case BC_INST_BREAK | BC_INST_FLAG_TRUE: if (cs.is_in_loop()) { - throw CsContinueException(); + throw continue_exception(); } else { throw error(cs, "no loop to continue"); } @@ -594,7 +594,7 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { args[numargs++].set_int( *reinterpret_cast(code) ); - code += CsTypeStorageSize; + code += bc_store_size; continue; case BC_INST_VAL_INT | BC_RET_INT: args[numargs++].set_int(integer_type(op) >> 8); @@ -603,7 +603,7 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { args[numargs++].set_float( *reinterpret_cast(code) ); - code += CsTypeStorageSize; + code += bc_store_size; continue; case BC_INST_VAL_INT | BC_RET_FLOAT: args[numargs++].set_float(float_type(integer_type(op) >> 8)); @@ -759,11 +759,11 @@ static uint32_t *runcode(state &cs, uint32_t *code, any_value &result) { } case BC_INST_IDENT_U: { any_value &arg = args[numargs - 1]; - ident *id = cs.p_state->identmap[DummyIdx]; + ident *id = cs.p_state->identmap[ID_IDX_DUMMY]; if (arg.get_type() == value_type::STRING) { id = cs.new_ident(arg.get_str()); } - if ((id->get_index() < MaxArguments) && !ident_is_used_arg(id, cs)) { + if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) { any_value nv{cs}; static_cast(id)->push_arg( nv, cs.p_callstack->argstack[id->get_index()], false @@ -1291,7 +1291,7 @@ noid: numargs = offset - 1; continue; case ID_LOCAL: { - valarray locals{cs}; + valarray locals{cs}; for (size_t j = 0; j < size_t(callargs); ++j) { push_alias(cs, cs.force_ident( args[offset + j] @@ -1345,7 +1345,7 @@ noid: case ID_ALIAS: { alias *a = static_cast(id); if ( - (a->get_index() < MaxArguments) && + (a->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(a, cs) ) { numargs = offset - 1; @@ -1411,7 +1411,7 @@ void state::run(ident *id, std::span args, any_value &ret) { /* fallthrough */ case ident_type::COMMAND: if (nargs < static_cast(id)->get_num_args()) { - valarray buf{*this}; + valarray buf{*this}; for (std::size_t i = 0; i < args.size(); ++i) { buf[i] = args[i]; } @@ -1455,7 +1455,7 @@ void state::run(ident *id, std::span args, any_value &ret) { case ident_type::ALIAS: { alias *a = static_cast(id); if ( - (a->get_index() < MaxArguments) && !ident_is_used_arg(a, *this) + (a->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(a, *this) ) { break; } @@ -1499,10 +1499,10 @@ loop_state state::run_loop(bcode *code, any_value &ret) { ++p_inloop; try { run(code, ret); - } catch (CsBreakException) { + } catch (break_exception) { --p_inloop; return loop_state::BREAK; - } catch (CsContinueException) { + } catch (continue_exception) { --p_inloop; return loop_state::CONTINUE; } catch (...) { diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 41e8bc1..9940f7a 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -3,188 +3,16 @@ #include "cubescript/cubescript.hh" -#include -#include -#include -#include - #include "cs_std.hh" -#include "cs_bcode.hh" #include "cs_ident.hh" +#include "cs_gen.hh" namespace cubescript { -static constexpr int MaxArguments = 25; -static constexpr int MaxResults = 7; - -static constexpr int DummyIdx = MaxArguments; -static constexpr int NumargsIdx = MaxArguments + 1; -static constexpr int DbgaliasIdx = MaxArguments + 2; - -static const int valtypet[] = { - VAL_NULL, VAL_INT, VAL_FLOAT, VAL_STRING, - VAL_CODE, VAL_IDENT +struct break_exception { }; -static inline int vtype_to_int(value_type v) { - return valtypet[int(v)]; -} - -struct CsBreakException { -}; - -struct CsContinueException { -}; - -template -constexpr size_t CsTypeStorageSize = - (sizeof(T) - 1) / sizeof(uint32_t) + 1; - -struct codegen_state { - state &cs; - codegen_state *prevps; - bool parsing = true; - valbuf code; - char const *source, *send; - size_t current_line; - std::string_view src_name; - - codegen_state() = delete; - codegen_state(state &csr): - cs{csr}, prevps{csr.p_pstate}, code{cs}, - source{}, send{}, current_line{1}, src_name{} - { - csr.p_pstate = this; - } - - ~codegen_state() { - done(); - } - - void done() { - if (!parsing) { - return; - } - cs.p_pstate = prevps; - parsing = false; - } - - std::string_view get_str(); - charbuf get_str_dup(); - - std::string_view get_word(); - - void gen_str(std::string_view word) { - if (word.size() <= 3) { - uint32_t op = BC_INST_VAL_INT | BC_RET_STRING; - for (size_t i = 0; i < word.size(); ++i) { - op |= uint32_t( - static_cast(word[i]) - ) << ((i + 1) * 8); - } - code.push_back(op); - return; - } - code.push_back(BC_INST_VAL | BC_RET_STRING | (word.size() << 8)); - auto it = reinterpret_cast(word.data()); - code.append(it, it + (word.size() / sizeof(uint32_t))); - size_t esz = word.size() % sizeof(uint32_t); - union { - char c[sizeof(uint32_t)]; - uint32_t u; - } end; - end.u = 0; - memcpy(end.c, word.data() + word.size() - esz, esz); - code.push_back(end.u); - } - - void gen_str() { - code.push_back(BC_INST_VAL_INT | BC_RET_STRING); - } - - void gen_null() { - code.push_back(BC_INST_VAL_INT | BC_RET_NULL); - } - - void gen_int(integer_type i = 0) { - if (i >= -0x800000 && i <= 0x7FFFFF) { - code.push_back(BC_INST_VAL_INT | BC_RET_INT | (i << 8)); - } else { - union { - integer_type i; - uint32_t u[CsTypeStorageSize]; - } c; - c.i = i; - code.push_back(BC_INST_VAL | BC_RET_INT); - code.append(c.u, c.u + CsTypeStorageSize); - } - } - - void gen_int(std::string_view word); - - void gen_float(float_type f = 0.0f) { - if (integer_type(f) == f && f >= -0x800000 && f <= 0x7FFFFF) { - code.push_back(BC_INST_VAL_INT | BC_RET_FLOAT | (integer_type(f) << 8)); - } else { - union { - float_type f; - uint32_t u[CsTypeStorageSize]; - } c; - c.f = f; - code.push_back(BC_INST_VAL | BC_RET_FLOAT); - code.append(c.u, c.u + CsTypeStorageSize); - } - } - - void gen_float(std::string_view word); - - void gen_ident(ident *id) { - code.push_back( - ((id->get_index() < MaxArguments) - ? BC_INST_IDENT_ARG - : BC_INST_IDENT - ) | (id->get_index() << 8) - ); - } - - void gen_ident() { - gen_ident(cs.p_state->identmap[DummyIdx]); - } - - void gen_ident(std::string_view word) { - gen_ident(cs.new_ident(word)); - } - - void gen_value( - int wordtype, std::string_view word = std::string_view(), - int line = 0 - ); - - void gen_main(std::string_view s, int ret_type = VAL_ANY); - - void next_char() { - if (source == send) { - return; - } - if (*source == '\n') { - ++current_line; - } - ++source; - } - - char current(size_t ahead = 0) { - if (std::size_t(send - source) <= ahead) { - return '\0'; - } - return source[ahead]; - } - - std::string_view read_macro_name(); - - char skip_until(std::string_view chars); - char skip_until(char cf); - - void skip_comments(); +struct continue_exception { }; template @@ -193,7 +21,7 @@ static void call_with_args(state &cs, F body) { body(); return; } - valarray argstack{cs}; + valarray argstack{cs}; int argmask1 = cs.p_callstack->usedargs; for (int i = 0; argmask1; argmask1 >>= 1, ++i) { if (argmask1 & 1) { @@ -205,7 +33,7 @@ static void call_with_args(state &cs, F body) { ident_link *prevstack = cs.p_callstack->next; ident_link aliaslink = { cs.p_callstack->id, cs.p_callstack, - prevstack ? prevstack->usedargs : ((1 << MaxArguments) - 1), + prevstack ? prevstack->usedargs : ((1 << MAX_ARGUMENTS) - 1), prevstack ? prevstack->argstack : nullptr }; cs.p_callstack = &aliaslink; diff --git a/src/lib_base.cc b/src/lib_base.cc index d8cce84..7af8c82 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -2,7 +2,7 @@ #include "cs_std.hh" #include "cs_ident.hh" -#include "cs_vm.hh" // FIXME, only Max Arguments +#include "cs_gen.hh" // FIXME, only MAX_ARGUMENTS namespace cubescript { @@ -154,7 +154,7 @@ void init_lib_base(state &gcs) { gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) { stacked_value idv{cs, args[0].get_ident()}; - if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { + if (!idv.has_alias() || (idv.get_alias()->get_index() < MAX_ARGUMENTS)) { return; } if (args[1].get_bool()) { @@ -298,7 +298,7 @@ end: gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) { stacked_value idv{cs, args[0].get_ident()}; - if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) { + if (!idv.has_alias() || (idv.get_alias()->get_index() < MAX_ARGUMENTS)) { return; } idv = args[1];