From 1bc94bf5af42c58944f80d72ab3d03e1374f773e Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Sat, 10 Apr 2021 00:40:57 +0200 Subject: [PATCH] move some more codegen into proper place --- src/cs_bcode.hh | 4 +- src/cs_gen.cc | 77 +++++++++++++++++++++++++++++++++---- src/cs_gen.hh | 18 +++++++++ src/cs_parser.cc | 98 ++++++++++++++++++++---------------------------- 4 files changed, 130 insertions(+), 67 deletions(-) diff --git a/src/cs_bcode.hh b/src/cs_bcode.hh index 3ab331b..444979c 100644 --- a/src/cs_bcode.hh +++ b/src/cs_bcode.hh @@ -135,10 +135,10 @@ enum { */ BC_INST_LOOKUP_U, /* concatenate D values on top of the stack together, with topmost value - * being last; push the result according to M + * being last; delimit with spaces; push the result according to M */ BC_INST_CONC, - /* like above but delimit with spaces */ + /* like above but without delimiter */ BC_INST_CONC_W, /* push the value of svar with index D on the stack according to M */ BC_INST_SVAR, diff --git a/src/cs_gen.cc b/src/cs_gen.cc index 63fdaec..3cc3a91 100644 --- a/src/cs_gen.cc +++ b/src/cs_gen.cc @@ -9,6 +9,17 @@ namespace cubescript { +static inline int ret_code(int type, int def = 0) { + if (type >= VAL_ANY) { + return def; + } + return type << BC_INST_RET; +} + +std::size_t gen_state::count() const { + return code.size(); +} + bcode_ref gen_state::steal_ref() { auto *cp = bcode_alloc(ts.istate, code.size()); std::memcpy(cp, code.data(), code.size() * sizeof(std::uint32_t)); @@ -19,10 +30,34 @@ void gen_state::gen_pop() { code.push_back(BC_INST_POP); } +void gen_state::gen_dup(int ltype) { + code.push_back(BC_INST_DUP | ret_code(ltype)); +} + +void gen_state::gen_push_result(int ltype) { + code.push_back(BC_INST_RESULT_ARG | ret_code(ltype)); +} + +void gen_state::gen_force(int ltype) { + code.push_back(BC_INST_FORCE | ret_code(ltype, BC_RET_STRING)); +} + void gen_state::gen_val_null() { code.push_back(BC_INST_VAL_INT | BC_RET_NULL); } +void gen_state::gen_result_null(int ltype) { + code.push_back(BC_INST_NULL | ret_code(ltype)); +} + +void gen_state::gen_result_true(int ltype) { + code.push_back(BC_INST_TRUE | ret_code(ltype)); +} + +void gen_state::gen_result_false(int ltype) { + code.push_back(BC_INST_FALSE | ret_code(ltype)); +} + void gen_state::gen_val_integer(integer_type v) { if (v >= -0x800000 && v <= 0x7FFFFF) { code.push_back(BC_INST_VAL_INT | BC_RET_INT | (v << 8)); @@ -218,13 +253,6 @@ void gen_state::gen_val( } } -static inline int ret_code(int type, int def = 0) { - if (type >= VAL_ANY) { - return def; - } - return type << BC_INST_RET; -} - void gen_state::gen_lookup_ivar(ident &id, int ltype) { code.push_back( BC_INST_IVAR | ret_code(ltype, BC_RET_INT) | (id.get_index() << 8) @@ -245,7 +273,7 @@ void gen_state::gen_lookup_svar(ident &id, int ltype) { void gen_state::gen_lookup_alias(ident &id, int ltype, int dtype) { code.push_back( - BC_INST_LOOKUP | ret_code(ltype, dtype) | (id.get_index() << 8) + BC_INST_LOOKUP | ret_code(ltype, ret_code(dtype)) | (id.get_index() << 8) ); } @@ -265,6 +293,39 @@ void gen_state::gen_ident_lookup() { code.push_back(BC_INST_IDENT_U); } +void gen_state::gen_concat(std::size_t concs, bool space, int ltype) { + if (!concs) { + return; + } + if (space) { + code.push_back(BC_INST_CONC | ret_code(ltype) | (concs << 8)); + } else { + code.push_back(BC_INST_CONC_W | ret_code(ltype) | (concs << 8)); + } +} + +void gen_state::gen_command_call( + ident &id, int comt, int ltype, std::uint32_t nargs +) { + code.push_back(comt | ret_code(ltype) | (id.get_index() << 8)); + if (comt != BC_INST_COM) { + code.push_back(nargs); + } +} + +void gen_state::gen_alias_call(ident &id, std::uint32_t nargs) { + code.push_back(BC_INST_CALL | (id.get_index() << 8)); + code.push_back(nargs); +} + +void gen_state::gen_call(std::uint32_t nargs) { + code.push_back(BC_INST_CALL_U | (nargs << 8)); +} + +void gen_state::gen_local(std::uint32_t nargs) { + code.push_back(BC_INST_LOCAL | (nargs << 8)); +} + void gen_state::gen_main_null() { code.reserve(code.size() + 4); code.push_back(BC_INST_START); diff --git a/src/cs_gen.hh b/src/cs_gen.hh index 57c1847..9636b48 100644 --- a/src/cs_gen.hh +++ b/src/cs_gen.hh @@ -22,11 +22,19 @@ struct gen_state { ts{tsr}, code{tsr.istate} {} + std::size_t count() const; + bcode_ref steal_ref(); void gen_pop(); + void gen_dup(int ltype = 0); + void gen_push_result(int ltype = 0); + void gen_force(int ltype); void gen_val_null(); + void gen_result_null(int ltype = 0); + void gen_result_true(int ltype = 0); + void gen_result_false(int ltype = 0); void gen_val_integer(integer_type v = 0); void gen_val_integer(std::string_view v); @@ -57,6 +65,16 @@ struct gen_state { void gen_compile(bool cond = false); void gen_ident_lookup(); + void gen_concat(std::size_t concs, bool space, int ltype = 0); + + void gen_command_call( + ident &id, int comt, int ltype = 0, std::uint32_t nargs = 0 + ); + void gen_alias_call(ident &id, std::uint32_t nargs = 0); + void gen_call(std::uint32_t nargs = 0); + + void gen_local(std::uint32_t nargs); + void gen_main_null(); void gen_main_integer(integer_type v); void gen_main_float(float_type v); diff --git a/src/cs_parser.cc b/src/cs_parser.cc index c3931ba..f3a31db 100644 --- a/src/cs_parser.cc +++ b/src/cs_parser.cc @@ -479,7 +479,7 @@ lookupid: gs.gs.gen_lookup_alias(id); break; default: - gs.gs.gen_lookup_alias(id, ltype, BC_RET_STRING); + gs.gs.gen_lookup_alias(id, ltype, VAL_STRING); break; } goto done; @@ -505,7 +505,7 @@ lookupid: numargs++; break; case 'F': - gs.gs.code.push_back(BC_INST_DUP | BC_RET_FLOAT); + gs.gs.gen_dup(VAL_FLOAT); numargs++; break; case 'E': @@ -531,10 +531,10 @@ lookupid: break; case 'C': comtype = BC_INST_COM_C; - goto compilecomv; + break; case 'V': comtype = BC_INST_COM_V; - goto compilecomv; + break; case '1': case '2': case '3': @@ -542,21 +542,8 @@ lookupid: break; } } - gs.gs.code.push_back( - comtype | ret_code(ltype) | (id.get_index() << 8) - ); - gs.gs.code.push_back( - BC_INST_RESULT_ARG | ret_code(ltype) - ); - goto done; - compilecomv: - gs.gs.code.push_back( - comtype | ret_code(ltype) | (id.get_index() << 8) - ); - gs.gs.code.push_back(numargs); - gs.gs.code.push_back( - BC_INST_RESULT_ARG | ret_code(ltype) - ); + gs.gs.gen_command_call(id, comtype, ltype, numargs); + gs.gs.gen_push_result(ltype); goto done; } default: @@ -741,9 +728,7 @@ static void compileblockmain(parser_state &gs, int wordtype) { concs++; } } - if (concs) { - gs.gs.code.push_back(BC_INST_CONC_W | ret_code(wordtype) | (concs << 8)); - } + gs.gs.gen_concat(concs, false, wordtype); switch (wordtype) { case VAL_POP: if (concs || gs.source - 1 > start) { @@ -784,7 +769,7 @@ static void compileblockmain(parser_state &gs, int wordtype) { if (gs.source - 1 <= start) { gs.gs.gen_val(wordtype); } else { - gs.gs.code.push_back(BC_INST_FORCE | (wordtype << BC_INST_RET)); + gs.gs.gen_force(wordtype); } } break; @@ -841,10 +826,10 @@ static bool compilearg( return true; case '(': { gs.next_char(); - std::size_t start = gs.gs.code.size(); + auto start = gs.gs.count(); gs.parse_block(VAL_ANY, ')'); - if (gs.gs.code.size() > start) { - gs.gs.code.push_back(BC_INST_RESULT_ARG | ret_code(wordtype)); + if (gs.gs.count() > start) { + gs.gs.gen_push_result(wordtype); } else { gs.gs.gen_val(wordtype); return true; @@ -942,7 +927,7 @@ static void compile_cmd( numconc++; } if (numconc > 1) { - gs.gs.code.push_back(BC_INST_CONC | BC_RET_STRING | (numconc << 8)); + gs.gs.gen_concat(numconc, true, VAL_STRING); } } numargs++; @@ -998,7 +983,7 @@ static void compile_cmd( if (rep) { break; } - gs.gs.code.push_back(BC_INST_DUP | BC_RET_FLOAT); + gs.gs.gen_dup(VAL_FLOAT); fakeargs++; } numargs++; @@ -1080,7 +1065,7 @@ static void compile_cmd( numcargs++; } } - goto compilecomv; + break; case 'V': /* varargs */ comtype = BC_INST_COM_V; if (more && (!limit || (numcargs < limit))) { @@ -1093,7 +1078,7 @@ static void compile_cmd( numcargs++; } } - goto compilecomv; + break; case '1': /* vararg repetition */ case '2': case '3': @@ -1106,13 +1091,7 @@ static void compile_cmd( break; } } - gs.gs.code.push_back(comtype | ret_code(rettype) | (id->get_index() << 8)); - return; -compilecomv: - gs.gs.code.push_back( - comtype | ret_code(rettype) | (id->get_index() << 8) - ); - gs.gs.code.push_back(numargs); + gs.gs.gen_command_call(*id, comtype, rettype, numargs); } static void compile_alias(parser_state &gs, alias *id, bool &more) { @@ -1124,10 +1103,7 @@ static void compile_alias(parser_state &gs, alias *id, bool &more) { } ++numargs; } - gs.gs.code.push_back( - BC_INST_CALL | (id->get_index() << 8) - ); - gs.gs.code.push_back(numargs); + gs.gs.gen_alias_call(*id, numargs); } static void compile_local(parser_state &gs, bool &more) { @@ -1141,7 +1117,7 @@ static void compile_local(parser_state &gs, bool &more) { numargs++; } } - gs.gs.code.push_back(BC_INST_LOCAL | (numargs << 8)); + gs.gs.gen_local(numargs); } static void compile_do( @@ -1150,7 +1126,11 @@ static void compile_do( if (more) { more = compilearg(gs, VAL_CODE); } - gs.gs.code.push_back((more ? opcode : BC_INST_NULL) | ret_code(rettype)); + if (!more) { + gs.gs.gen_result_null(rettype); + } else { + gs.gs.code.push_back(opcode | ret_code(rettype)); + } } static void compile_if( @@ -1160,13 +1140,13 @@ static void compile_if( more = compilearg(gs, VAL_ANY); } if (!more) { - gs.gs.code.push_back(BC_INST_NULL | ret_code(rettype)); + gs.gs.gen_result_null(rettype); } else { std::size_t start1 = gs.gs.code.size(); more = compilearg(gs, VAL_CODE); if (!more) { gs.gs.gen_pop(); - gs.gs.code.push_back(BC_INST_NULL | ret_code(rettype)); + gs.gs.gen_result_null(rettype); } else { std::size_t start2 = gs.gs.code.size(); more = compilearg(gs, VAL_CODE); @@ -1225,10 +1205,11 @@ static void compile_and_or( more = compilearg(gs, VAL_COND); } if (!more) { - gs.gs.code.push_back( - ((ident_p{*id}.impl().p_type == ID_AND) - ? BC_INST_TRUE : BC_INST_FALSE) | ret_code(rettype) - ); + if (ident_p{*id}.impl().p_type == ID_AND) { + gs.gs.gen_result_true(rettype); + } else { + gs.gs.gen_result_false(rettype); + } } else { numargs++; std::size_t start = gs.gs.code.size(), end = start; @@ -1363,7 +1344,7 @@ noid: } ++numargs; } - gs.code.push_back(BC_INST_CALL_U | (numargs << 8)); + gs.gen_call(numargs); } else { idname.push_back('\0'); ident *id = ts.pstate->get_ident(idname.str_term()); @@ -1423,18 +1404,21 @@ noid: if (more) { more = compilearg(*this, VAL_ANY); } - gs.code.push_back( - (more ? BC_INST_RESULT : BC_INST_NULL) | - ret_code(rettype) - ); + if (!more) { + gs.gen_result_null(rettype); + } else { + gs.code.push_back(BC_INST_RESULT | ret_code(rettype)); + } break; case ID_NOT: if (more) { more = compilearg(*this, VAL_ANY); } - gs.code.push_back( - (more ? BC_INST_NOT : BC_INST_TRUE) | ret_code(rettype) - ); + if (!more) { + gs.gen_result_true(rettype); + } else { + gs.code.push_back(BC_INST_NOT | ret_code(rettype)); + } break; case ID_AND: case ID_OR: