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();
|
return code.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::uint32_t gen_state::peek(std::size_t idx) const {
|
||||||
|
return code[idx];
|
||||||
|
}
|
||||||
|
|
||||||
bcode_ref gen_state::steal_ref() {
|
bcode_ref gen_state::steal_ref() {
|
||||||
auto *cp = bcode_alloc(ts.istate, code.size());
|
auto *cp = bcode_alloc(ts.istate, code.size());
|
||||||
std::memcpy(cp, code.data(), code.size() * sizeof(std::uint32_t));
|
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));
|
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() {
|
void gen_state::gen_val_null() {
|
||||||
code.push_back(BC_INST_VAL_INT | BC_RET_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);
|
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() {
|
void gen_state::gen_block() {
|
||||||
code.push_back(BC_INST_EMPTY);
|
code.push_back(BC_INST_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ namespace cubescript {
|
||||||
|
|
||||||
struct gen_state {
|
struct gen_state {
|
||||||
thread_state &ts;
|
thread_state &ts;
|
||||||
valbuf<std::uint32_t> code;
|
|
||||||
|
|
||||||
gen_state() = delete;
|
gen_state() = delete;
|
||||||
gen_state(thread_state &tsr):
|
gen_state(thread_state &tsr):
|
||||||
|
@ -23,6 +22,7 @@ struct gen_state {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::size_t count() const;
|
std::size_t count() const;
|
||||||
|
std::uint32_t peek(std::size_t idx) const;
|
||||||
|
|
||||||
bcode_ref steal_ref();
|
bcode_ref steal_ref();
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ struct gen_state {
|
||||||
void gen_force(int ltype);
|
void gen_force(int ltype);
|
||||||
|
|
||||||
void gen_not(int ltype = 0);
|
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_val_null();
|
||||||
void gen_result_null(int ltype = 0);
|
void gen_result_null(int ltype = 0);
|
||||||
|
@ -92,11 +94,16 @@ struct gen_state {
|
||||||
void gen_main_integer(integer_type v);
|
void gen_main_integer(integer_type v);
|
||||||
void gen_main_float(float_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();
|
void gen_block();
|
||||||
std::pair<std::size_t, std::string_view> gen_block(
|
std::pair<std::size_t, std::string_view> gen_block(
|
||||||
std::string_view v, std::size_t line,
|
std::string_view v, std::size_t line,
|
||||||
int ret_type = BC_RET_NULL, int term = '\0'
|
int ret_type = BC_RET_NULL, int term = '\0'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
valbuf<std::uint32_t> code;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
|
@ -1137,62 +1137,28 @@ static void compile_if(
|
||||||
parser_state &gs, ident *id, bool &more, int rettype
|
parser_state &gs, ident *id, bool &more, int rettype
|
||||||
) {
|
) {
|
||||||
if (more) {
|
if (more) {
|
||||||
|
/* condition */
|
||||||
more = compilearg(gs, VAL_ANY);
|
more = compilearg(gs, VAL_ANY);
|
||||||
}
|
}
|
||||||
if (!more) {
|
if (!more) {
|
||||||
|
/* no condition: expr is nothing */
|
||||||
gs.gs.gen_result_null(rettype);
|
gs.gs.gen_result_null(rettype);
|
||||||
} else {
|
} else {
|
||||||
std::size_t start1 = gs.gs.code.size();
|
auto tpos = gs.gs.count();
|
||||||
|
/* true block */
|
||||||
more = compilearg(gs, VAL_CODE);
|
more = compilearg(gs, VAL_CODE);
|
||||||
if (!more) {
|
if (!more) {
|
||||||
|
/* we only had condition: expr is nothing */
|
||||||
gs.gs.gen_pop();
|
gs.gs.gen_pop();
|
||||||
gs.gs.gen_result_null(rettype);
|
gs.gs.gen_result_null(rettype);
|
||||||
} else {
|
} else {
|
||||||
std::size_t start2 = gs.gs.code.size();
|
auto fpos = gs.gs.count();
|
||||||
|
/* false block */
|
||||||
more = compilearg(gs, VAL_CODE);
|
more = compilearg(gs, VAL_CODE);
|
||||||
std::uint32_t inst1 = gs.gs.code[start1];
|
if (!gs.gs.gen_if(tpos, more ? fpos : 0)) {
|
||||||
std::uint32_t op1 = inst1 & ~BC_INST_RET_MASK;
|
/* can't fully compile: use a call */
|
||||||
auto len1 = std::uint32_t(start2 - (start1 + 1));
|
gs.gs.gen_command_call(*id, BC_INST_COM, rettype);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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;
|
std::uint32_t numargs = 0;
|
||||||
if (more) {
|
if (more) {
|
||||||
|
/* first */
|
||||||
more = compilearg(gs, VAL_COND);
|
more = compilearg(gs, VAL_COND);
|
||||||
}
|
}
|
||||||
if (!more) {
|
if (!more) {
|
||||||
|
/* no first: generate true or false */
|
||||||
if (ident_p{*id}.impl().p_type == ID_AND) {
|
if (ident_p{*id}.impl().p_type == ID_AND) {
|
||||||
gs.gs.gen_result_true(rettype);
|
gs.gs.gen_result_true(rettype);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1212,47 +1180,33 @@ static void compile_and_or(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
numargs++;
|
numargs++;
|
||||||
std::size_t start = gs.gs.code.size(), end = start;
|
std::size_t start = gs.gs.count(), end = start;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
/* keep going as long as we only get blocks */
|
||||||
more = compilearg(gs, VAL_COND);
|
more = compilearg(gs, VAL_COND);
|
||||||
if (!more) {
|
if (!more) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
numargs++;
|
numargs++;
|
||||||
if ((gs.gs.code[end] & ~BC_INST_RET_MASK) != (
|
if (!gs.gs.is_block(end)) {
|
||||||
BC_INST_BLOCK | (uint32_t(gs.gs.code.size() - (end + 1)) << 8)
|
|
||||||
)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
end = gs.gs.code.size();
|
end = gs.gs.count();
|
||||||
}
|
}
|
||||||
if (more) {
|
if (more) {
|
||||||
|
/* last parsed thing was not a block, fall back to call */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
/* but first, parse out the remainder of values */
|
||||||
more = compilearg(gs, VAL_COND);
|
more = compilearg(gs, VAL_COND);
|
||||||
if (!more) {
|
if (!more) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
numargs++;
|
numargs++;
|
||||||
}
|
}
|
||||||
gs.gs.code.push_back(
|
gs.gs.gen_command_call(*id, BC_INST_COM_V, rettype, numargs);
|
||||||
BC_INST_COM_V | ret_code(rettype) | (id->get_index() << 8)
|
|
||||||
);
|
|
||||||
gs.gs.code.push_back(numargs);
|
|
||||||
} else {
|
} else {
|
||||||
std::uint32_t op = (ident_p{*id}.impl().p_type == ID_AND)
|
/* all blocks and nothing left */
|
||||||
? (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE)
|
gs.gs.gen_and_or((ident_p{*id}.impl().p_type != ID_AND), start);
|
||||||
: (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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue