separate cs_gen.hh, various refactors

master
Daniel Kolesa 2021-03-24 02:21:27 +01:00
parent 21aec59ad3
commit d774db675a
10 changed files with 246 additions and 247 deletions

View File

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

View File

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

View File

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

165
src/cs_gen.hh 100644
View File

@ -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 */

View File

@ -1,7 +1,7 @@
#include "cs_ident.hh"
#include "cs_bcode.hh"
#include "cs_vm.hh"
#include "cs_gen.hh"
namespace cubescript {

View File

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

View File

@ -1,5 +1,5 @@
#include <cubescript/cubescript.hh>
#include "cs_vm.hh"
#include "cs_gen.hh"
#include "cs_std.hh"
#include "cs_parser.hh"

View File

@ -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 (...) {

View File

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

View File

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