move some more codegen into proper place

master
Daniel Kolesa 2021-04-10 00:40:57 +02:00
parent 295c905c32
commit 1bc94bf5af
4 changed files with 130 additions and 67 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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: