move all codegen stuff, make instruction vector private
parent
05661662d2
commit
d2b53b174e
|
@ -20,6 +20,10 @@ std::size_t gen_state::count() const {
|
|||
return code.size();
|
||||
}
|
||||
|
||||
std::uint32_t gen_state::peek(std::size_t idx) const {
|
||||
return code[idx];
|
||||
}
|
||||
|
||||
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));
|
||||
|
@ -50,6 +54,71 @@ void gen_state::gen_not(int ltype) {
|
|||
code.push_back(BC_INST_NOT | ret_code(ltype));
|
||||
}
|
||||
|
||||
bool gen_state::gen_if(std::size_t tpos, std::size_t fpos, int ltype) {
|
||||
auto inst1 = code[tpos];
|
||||
auto op1 = inst1 & ~BC_INST_RET_MASK;
|
||||
auto tlen = std::uint32_t(fpos - tpos - 1);
|
||||
if (!fpos) {
|
||||
if (is_block(tpos, fpos)) {
|
||||
code[tpos] = (tlen << 8) | BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
|
||||
code[tpos + 1] = BC_INST_ENTER_RESULT;
|
||||
code[tpos + tlen] = (
|
||||
code[tpos + tlen] & ~BC_INST_RET_MASK
|
||||
) | ret_code(ltype);
|
||||
return true;
|
||||
}
|
||||
gen_block();
|
||||
} else {
|
||||
auto inst2 = code[fpos];
|
||||
auto flen = std::uint32_t(count() - fpos - 1);
|
||||
if (is_block(fpos)) {
|
||||
if (is_block(tpos, fpos)) {
|
||||
code[tpos] = (std::uint32_t(fpos - tpos) << 8)
|
||||
| BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
|
||||
code[tpos + 1] = BC_INST_ENTER_RESULT;
|
||||
code[tpos + tlen] = (
|
||||
code[tpos + tlen] & ~BC_INST_RET_MASK
|
||||
) | ret_code(ltype);
|
||||
code[fpos] = (flen << 8) | BC_INST_JUMP;
|
||||
code[fpos + 1] = BC_INST_ENTER_RESULT;
|
||||
code[fpos + flen] = (
|
||||
code[fpos + flen] & ~BC_INST_RET_MASK
|
||||
) | ret_code(ltype);
|
||||
return true;
|
||||
} else if (op1 == BC_INST_EMPTY) {
|
||||
code[tpos] = BC_INST_NULL | (inst2 & BC_INST_RET_MASK);
|
||||
code[fpos] = (flen << 8) | BC_INST_JUMP_B | BC_INST_FLAG_TRUE;
|
||||
code[fpos + 1] = BC_INST_ENTER_RESULT;
|
||||
code[fpos + flen] = (
|
||||
code[fpos + flen] & ~BC_INST_RET_MASK
|
||||
) | ret_code(ltype);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void gen_state::gen_and_or(bool is_or, std::size_t start, int ltype) {
|
||||
std::uint32_t op;
|
||||
if (is_or) {
|
||||
op = (BC_INST_JUMP_RESULT | BC_INST_FLAG_TRUE);
|
||||
} else {
|
||||
op = (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE);
|
||||
}
|
||||
code.push_back(op);
|
||||
std::size_t end = count();
|
||||
while ((start + 1) < end) {
|
||||
uint32_t len = code[start] >> 8;
|
||||
code[start] = std::uint32_t((end - start - 1) << 8) | op;
|
||||
code[start + 1] = BC_INST_ENTER;
|
||||
code[start + len] = (
|
||||
code[start + len] & ~BC_INST_RET_MASK
|
||||
) | ret_code(ltype);
|
||||
start += len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void gen_state::gen_val_null() {
|
||||
code.push_back(BC_INST_VAL_INT | BC_RET_NULL);
|
||||
}
|
||||
|
@ -392,6 +461,15 @@ void gen_state::gen_main_float(float_type v) {
|
|||
code.push_back(BC_INST_EXIT);
|
||||
}
|
||||
|
||||
bool gen_state::is_block(std::size_t idx, std::size_t epos) const {
|
||||
if (!epos) {
|
||||
epos = count();
|
||||
}
|
||||
return ((code[idx] & ~BC_INST_RET_MASK) == (
|
||||
BC_INST_BLOCK | (std::uint32_t(epos - idx - 1) << 8)
|
||||
));
|
||||
}
|
||||
|
||||
void gen_state::gen_block() {
|
||||
code.push_back(BC_INST_EMPTY);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace cubescript {
|
|||
|
||||
struct gen_state {
|
||||
thread_state &ts;
|
||||
valbuf<std::uint32_t> code;
|
||||
|
||||
gen_state() = delete;
|
||||
gen_state(thread_state &tsr):
|
||||
|
@ -23,6 +22,7 @@ struct gen_state {
|
|||
{}
|
||||
|
||||
std::size_t count() const;
|
||||
std::uint32_t peek(std::size_t idx) const;
|
||||
|
||||
bcode_ref steal_ref();
|
||||
|
||||
|
@ -33,6 +33,8 @@ struct gen_state {
|
|||
void gen_force(int ltype);
|
||||
|
||||
void gen_not(int ltype = 0);
|
||||
bool gen_if(std::size_t tpos, std::size_t fpos, int ltype = 0);
|
||||
void gen_and_or(bool is_or, std::size_t start, int ltype = 0);
|
||||
|
||||
void gen_val_null();
|
||||
void gen_result_null(int ltype = 0);
|
||||
|
@ -92,11 +94,16 @@ struct gen_state {
|
|||
void gen_main_integer(integer_type v);
|
||||
void gen_main_float(float_type v);
|
||||
|
||||
bool is_block(std::size_t idx, std::size_t epos = 0) const;
|
||||
|
||||
void gen_block();
|
||||
std::pair<std::size_t, std::string_view> gen_block(
|
||||
std::string_view v, std::size_t line,
|
||||
int ret_type = BC_RET_NULL, int term = '\0'
|
||||
);
|
||||
|
||||
private:
|
||||
valbuf<std::uint32_t> code;
|
||||
};
|
||||
|
||||
} /* namespace cubescript */
|
||||
|
|
|
@ -1137,62 +1137,28 @@ static void compile_if(
|
|||
parser_state &gs, ident *id, bool &more, int rettype
|
||||
) {
|
||||
if (more) {
|
||||
/* condition */
|
||||
more = compilearg(gs, VAL_ANY);
|
||||
}
|
||||
if (!more) {
|
||||
/* no condition: expr is nothing */
|
||||
gs.gs.gen_result_null(rettype);
|
||||
} else {
|
||||
std::size_t start1 = gs.gs.code.size();
|
||||
auto tpos = gs.gs.count();
|
||||
/* true block */
|
||||
more = compilearg(gs, VAL_CODE);
|
||||
if (!more) {
|
||||
/* we only had condition: expr is nothing */
|
||||
gs.gs.gen_pop();
|
||||
gs.gs.gen_result_null(rettype);
|
||||
} else {
|
||||
std::size_t start2 = gs.gs.code.size();
|
||||
auto fpos = gs.gs.count();
|
||||
/* false block */
|
||||
more = compilearg(gs, VAL_CODE);
|
||||
std::uint32_t inst1 = gs.gs.code[start1];
|
||||
std::uint32_t op1 = inst1 & ~BC_INST_RET_MASK;
|
||||
auto len1 = std::uint32_t(start2 - (start1 + 1));
|
||||
if (!more) {
|
||||
if (op1 == (BC_INST_BLOCK | (len1 << 8))) {
|
||||
gs.gs.code[start1] = (len1 << 8) | BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
|
||||
gs.gs.code[start1 + 1] = BC_INST_ENTER_RESULT;
|
||||
gs.gs.code[start1 + len1] = (
|
||||
gs.gs.code[start1 + len1] & ~BC_INST_RET_MASK
|
||||
) | ret_code(rettype);
|
||||
return;
|
||||
}
|
||||
gs.gs.gen_block();
|
||||
} else {
|
||||
std::uint32_t inst2 = gs.gs.code[start2];
|
||||
std::uint32_t op2 = inst2 & ~BC_INST_RET_MASK;
|
||||
auto len2 = std::uint32_t(gs.gs.code.size() - (start2 + 1));
|
||||
if (op2 == (BC_INST_BLOCK | (len2 << 8))) {
|
||||
if (op1 == (BC_INST_BLOCK | (len1 << 8))) {
|
||||
gs.gs.code[start1] = (std::uint32_t(start2 - start1) << 8)
|
||||
| BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
|
||||
gs.gs.code[start1 + 1] = BC_INST_ENTER_RESULT;
|
||||
gs.gs.code[start1 + len1] = (
|
||||
gs.gs.code[start1 + len1] & ~BC_INST_RET_MASK
|
||||
) | ret_code(rettype);
|
||||
gs.gs.code[start2] = (len2 << 8) | BC_INST_JUMP;
|
||||
gs.gs.code[start2 + 1] = BC_INST_ENTER_RESULT;
|
||||
gs.gs.code[start2 + len2] = (
|
||||
gs.gs.code[start2 + len2] & ~BC_INST_RET_MASK
|
||||
) | ret_code(rettype);
|
||||
return;
|
||||
} else if (op1 == (BC_INST_EMPTY | (len1 << 8))) {
|
||||
gs.gs.code[start1] = BC_INST_NULL | (inst2 & BC_INST_RET_MASK);
|
||||
gs.gs.code[start2] = (len2 << 8) | BC_INST_JUMP_B | BC_INST_FLAG_TRUE;
|
||||
gs.gs.code[start2 + 1] = BC_INST_ENTER_RESULT;
|
||||
gs.gs.code[start2 + len2] = (
|
||||
gs.gs.code[start2 + len2] & ~BC_INST_RET_MASK
|
||||
) | ret_code(rettype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!gs.gs.gen_if(tpos, more ? fpos : 0)) {
|
||||
/* can't fully compile: use a call */
|
||||
gs.gs.gen_command_call(*id, BC_INST_COM, rettype);
|
||||
}
|
||||
gs.gs.code.push_back(BC_INST_COM | ret_code(rettype) | (id->get_index() << 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1202,9 +1168,11 @@ static void compile_and_or(
|
|||
) {
|
||||
std::uint32_t numargs = 0;
|
||||
if (more) {
|
||||
/* first */
|
||||
more = compilearg(gs, VAL_COND);
|
||||
}
|
||||
if (!more) {
|
||||
/* no first: generate true or false */
|
||||
if (ident_p{*id}.impl().p_type == ID_AND) {
|
||||
gs.gs.gen_result_true(rettype);
|
||||
} else {
|
||||
|
@ -1212,47 +1180,33 @@ static void compile_and_or(
|
|||
}
|
||||
} else {
|
||||
numargs++;
|
||||
std::size_t start = gs.gs.code.size(), end = start;
|
||||
std::size_t start = gs.gs.count(), end = start;
|
||||
for (;;) {
|
||||
/* keep going as long as we only get blocks */
|
||||
more = compilearg(gs, VAL_COND);
|
||||
if (!more) {
|
||||
break;
|
||||
}
|
||||
numargs++;
|
||||
if ((gs.gs.code[end] & ~BC_INST_RET_MASK) != (
|
||||
BC_INST_BLOCK | (uint32_t(gs.gs.code.size() - (end + 1)) << 8)
|
||||
)) {
|
||||
if (!gs.gs.is_block(end)) {
|
||||
break;
|
||||
}
|
||||
end = gs.gs.code.size();
|
||||
end = gs.gs.count();
|
||||
}
|
||||
if (more) {
|
||||
/* last parsed thing was not a block, fall back to call */
|
||||
for (;;) {
|
||||
/* but first, parse out the remainder of values */
|
||||
more = compilearg(gs, VAL_COND);
|
||||
if (!more) {
|
||||
break;
|
||||
}
|
||||
numargs++;
|
||||
}
|
||||
gs.gs.code.push_back(
|
||||
BC_INST_COM_V | ret_code(rettype) | (id->get_index() << 8)
|
||||
);
|
||||
gs.gs.code.push_back(numargs);
|
||||
gs.gs.gen_command_call(*id, BC_INST_COM_V, rettype, numargs);
|
||||
} else {
|
||||
std::uint32_t op = (ident_p{*id}.impl().p_type == ID_AND)
|
||||
? (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE)
|
||||
: (BC_INST_JUMP_RESULT | BC_INST_FLAG_TRUE);
|
||||
gs.gs.code.push_back(op);
|
||||
end = gs.gs.code.size();
|
||||
while ((start + 1) < end) {
|
||||
uint32_t len = gs.gs.code[start] >> 8;
|
||||
gs.gs.code[start] = std::uint32_t((end - (start + 1)) << 8) | op;
|
||||
gs.gs.code[start + 1] = BC_INST_ENTER;
|
||||
gs.gs.code[start + len] = (
|
||||
gs.gs.code[start + len] & ~BC_INST_RET_MASK
|
||||
) | ret_code(rettype);
|
||||
start += len + 1;
|
||||
}
|
||||
/* all blocks and nothing left */
|
||||
gs.gs.gen_and_or((ident_p{*id}.impl().p_type != ID_AND), start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue