separate cs_gen.hh, various refactors
parent
21aec59ad3
commit
d774db675a
|
@ -26,6 +26,11 @@ enum {
|
|||
VAL_POP, VAL_COND
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <cubescript/cubescript.hh>
|
||||
|
||||
#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<integer_var *>(cs.p_state->identmap[DbgaliasIdx]);
|
||||
integer_var *dalias = static_cast<integer_var *>(cs.p_state->identmap[ID_IDX_DBGALIAS]);
|
||||
if (!dalias->get_value()) {
|
||||
return stack_state(cs, nullptr, !!cs.p_callstack);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <cubescript/cubescript.hh>
|
||||
#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<command_impl *>(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
|
||||
)
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
#ifndef LIBCUBESCRIPT_GEN_HH
|
||||
#define LIBCUBESCRIPT_GEN_HH
|
||||
|
||||
#include "cubescript/cubescript.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#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<uint32_t> 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<unsigned char>(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<std::uint32_t const *>(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<integer_type>] = {0};
|
||||
std::memcpy(u, &i, sizeof(i));
|
||||
code.push_back(BC_INST_VAL | BC_RET_INT);
|
||||
code.append(u, u + bc_store_size<integer_type>);
|
||||
}
|
||||
}
|
||||
|
||||
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<float_type>] = {0};
|
||||
std::memcpy(u, &f, sizeof(f));
|
||||
code.push_back(BC_INST_VAL | BC_RET_FLOAT);
|
||||
code.append(u, u + bc_store_size<float_type>);
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
|
@ -1,7 +1,7 @@
|
|||
#include "cs_ident.hh"
|
||||
|
||||
#include "cs_bcode.hh"
|
||||
#include "cs_vm.hh"
|
||||
#include "cs_gen.hh"
|
||||
|
||||
namespace cubescript {
|
||||
|
||||
|
|
|
@ -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<charbuf>(*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<char const *>(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<alias_impl *>(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();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <cubescript/cubescript.hh>
|
||||
#include "cs_vm.hh"
|
||||
#include "cs_gen.hh"
|
||||
#include "cs_std.hh"
|
||||
#include "cs_parser.hh"
|
||||
|
||||
|
|
42
src/cs_vm.cc
42
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<alias_impl *>(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<alias_impl *>(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<integer_var *>(cs.p_state->identmap[NumargsIdx]);
|
||||
valarray<ident_stack, MaxArguments> argstack{cs};
|
||||
integer_var *anargs = static_cast<integer_var *>(cs.p_state->identmap[ID_IDX_NUMARGS]);
|
||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{cs};
|
||||
for(int i = 0; i < callargs; i++) {
|
||||
static_cast<alias_impl *>(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<any_value, MaxArguments> buf{cs};
|
||||
valarray<any_value, MAX_ARGUMENTS> buf{cs};
|
||||
callcommand(
|
||||
cs, static_cast<command_impl *>(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<any_value, MaxArguments + MaxResults> args{cs};
|
||||
valarray<any_value, MAX_ARGUMENTS + MAX_RESULTS> 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<ident_stack, MaxArguments> locals{cs};
|
||||
valarray<ident_stack, MAX_ARGUMENTS> 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<integer_type const *>(code)
|
||||
);
|
||||
code += CsTypeStorageSize<integer_type>;
|
||||
code += bc_store_size<integer_type>;
|
||||
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<float_type const *>(code)
|
||||
);
|
||||
code += CsTypeStorageSize<float_type>;
|
||||
code += bc_store_size<float_type>;
|
||||
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<alias_impl *>(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<ident_stack, MaxArguments> locals{cs};
|
||||
valarray<ident_stack, MAX_ARGUMENTS> 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<alias *>(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<any_value> args, any_value &ret) {
|
|||
/* fallthrough */
|
||||
case ident_type::COMMAND:
|
||||
if (nargs < static_cast<command_impl *>(id)->get_num_args()) {
|
||||
valarray<any_value, MaxArguments> buf{*this};
|
||||
valarray<any_value, MAX_ARGUMENTS> 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<any_value> args, any_value &ret) {
|
|||
case ident_type::ALIAS: {
|
||||
alias *a = static_cast<alias *>(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 (...) {
|
||||
|
|
182
src/cs_vm.hh
182
src/cs_vm.hh
|
@ -3,188 +3,16 @@
|
|||
|
||||
#include "cubescript/cubescript.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#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<typename T>
|
||||
constexpr size_t CsTypeStorageSize =
|
||||
(sizeof(T) - 1) / sizeof(uint32_t) + 1;
|
||||
|
||||
struct codegen_state {
|
||||
state &cs;
|
||||
codegen_state *prevps;
|
||||
bool parsing = true;
|
||||
valbuf<uint32_t> 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<unsigned char>(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<uint32_t const *>(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<integer_type>];
|
||||
} c;
|
||||
c.i = i;
|
||||
code.push_back(BC_INST_VAL | BC_RET_INT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<integer_type>);
|
||||
}
|
||||
}
|
||||
|
||||
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<float_type>];
|
||||
} c;
|
||||
c.f = f;
|
||||
code.push_back(BC_INST_VAL | BC_RET_FLOAT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<float_type>);
|
||||
}
|
||||
}
|
||||
|
||||
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<typename F>
|
||||
|
@ -193,7 +21,7 @@ static void call_with_args(state &cs, F body) {
|
|||
body();
|
||||
return;
|
||||
}
|
||||
valarray<ident_stack, MaxArguments> argstack{cs};
|
||||
valarray<ident_stack, MAX_ARGUMENTS> 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;
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue