use Uint32 + more progress

master
Daniel Kolesa 2015-08-07 23:37:54 +01:00
parent efab3dc4e7
commit bc38bdf879
2 changed files with 301 additions and 207 deletions

View File

@ -657,7 +657,7 @@ void CsState::set_var_str_checked(Ident *id, ostd::ConstCharRange v) {
bool CsState::add_command(ostd::ConstCharRange name, ostd::ConstCharRange args,
IdentFunc func, int type) {
ostd::uint argmask = 0;
ostd::Uint32 argmask = 0;
int nargs = 0;
bool limit = true;
ostd::ConstCharRange fmt(args);
@ -711,14 +711,14 @@ bool CsState::add_command(ostd::ConstCharRange name, ostd::ConstCharRange args,
}
static void cs_init_lib_base_var(CsState &cs) {
cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) {
cs.add_command("nodebug", "e", [](CsState &cs, ostd::Uint32 *body) {
++cs.nodebug;
cs.run_ret(body);
--cs.nodebug;
});
cs.add_command("push", "rTe", [](CsState &cs, Ident *id,
TaggedValue *v, ostd::uint *code) {
TaggedValue *v, ostd::Uint32 *code) {
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
IdentStack stack;
id->push_arg(*v, stack);
@ -985,25 +985,27 @@ static void compilestatements(GenState &gs, const char *&p, int rettype, int bra
struct GenState {
CsState &cs;
ostd::Vector<ostd::uint> code;
ostd::Vector<ostd::Uint32> code;
GenState() = delete;
GenState(CsState &cs): cs(cs), code() {}
void gen_str(ostd::ConstCharRange word, bool macro = false) {
if (word.size() <= 3 && !macro) {
ostd::uint op = CODE_VALI | RET_STR;
ostd::Uint32 op = CODE_VALI | RET_STR;
for (ostd::Size i = 0; i < word.size(); ++i)
op |= ostd::uint(ostd::byte(word[i])) << ((i + 1) * 8);
op |= ostd::Uint32(ostd::byte(word[i])) << ((i + 1) * 8);
code.push(op);
return;
}
code.push((macro ? CODE_MACRO : (CODE_VAL | RET_STR)) | (word.size() << 8));
code.push_n((const ostd::uint *)word.data(), word.size() / sizeof(ostd::uint));
ostd::Size esz = word.size() % sizeof(ostd::uint);
code.push((macro ? CODE_MACRO : (CODE_VAL | RET_STR)) |
(word.size() << 8));
code.push_n((const ostd::Uint32 *)word.data(),
word.size() / sizeof(ostd::Uint32));
ostd::Size esz = word.size() % sizeof(ostd::Uint32);
union {
char c[sizeof(ostd::uint)];
ostd::uint u;
char c[sizeof(ostd::Uint32)];
ostd::Uint32 u;
} end;
end.u = 0;
memcpy(end.c, word.data() + word.size() - esz, esz);
@ -1037,7 +1039,7 @@ struct GenState {
else {
union {
float f;
ostd::uint u;
ostd::Uint32 u;
} c;
c.f = f;
code.push(CODE_VAL | RET_FLOAT);
@ -1077,7 +1079,7 @@ static inline const char *compileblock(GenState &gs, const char *p, int rettype
if (p) compilestatements(gs, p, VAL_ANY, brak);
if (gs.code.size() > start + 2) {
gs.code.push(CODE_EXIT | rettype);
gs.code[start] |= ostd::uint(gs.code.size() - (start + 1)) << 8;
gs.code[start] |= ostd::Uint32(gs.code.size() - (start + 1)) << 8;
} else {
gs.code.resize(start);
gs.code.push(CODE_EMPTY | rettype);
@ -1089,17 +1091,17 @@ static inline void compileunescapestring(GenState &gs, const char *&p, bool macr
p++;
const char *end = parsestring(p);
gs.code.push(macro ? CODE_MACRO : CODE_VAL | RET_STR);
gs.code.reserve(gs.code.size() + (end - p) / sizeof(ostd::uint) + 1);
gs.code.reserve(gs.code.size() + (end - p) / sizeof(ostd::Uint32) + 1);
char *buf = (char *)&gs.code[gs.code.size()];
int len = unescapestring(buf, p, end);
memset(&buf[len], 0, sizeof(ostd::uint) - len % sizeof(ostd::uint));
memset(&buf[len], 0, sizeof(ostd::Uint32) - len % sizeof(ostd::Uint32));
gs.code.back() |= len << 8;
gs.code.advance(len / sizeof(ostd::uint) + 1);
gs.code.advance(len / sizeof(ostd::Uint32) + 1);
p = end;
if (*p == '\"') p++;
}
static ostd::uint emptyblock[VAL_ANY][2] = {
static ostd::Uint32 emptyblock[VAL_ANY][2] = {
{ CODE_START + 0x100, CODE_EXIT | RET_NULL },
{ CODE_START + 0x100, CODE_EXIT | RET_INT },
{ CODE_START + 0x100, CODE_EXIT | RET_FLOAT },
@ -1403,7 +1405,7 @@ invalid:
static bool compileblockstr(GenState &gs, const char *str, const char *end, bool macro) {
int start = gs.code.size();
gs.code.push(macro ? CODE_MACRO : CODE_VAL | RET_STR);
gs.code.reserve(gs.code.size() + (end - str) / sizeof(ostd::uint) + 1);
gs.code.reserve(gs.code.size() + (end - str) / sizeof(ostd::Uint32) + 1);
char *buf = (char *)&gs.code[gs.code.size()];
int len = 0;
while (str < end) {
@ -1438,8 +1440,8 @@ static bool compileblockstr(GenState &gs, const char *str, const char *end, bool
}
}
done:
memset(&buf[len], '\0', sizeof(ostd::uint) - len % sizeof(ostd::uint));
gs.code.advance(len / sizeof(ostd::uint) + 1);
memset(&buf[len], '\0', sizeof(ostd::Uint32) - len % sizeof(ostd::Uint32));
gs.code.advance(len / sizeof(ostd::Uint32) + 1);
gs.code[start] |= len << 8;
return true;
}
@ -1938,7 +1940,7 @@ compilecomv:
} else {
int start2 = gs.code.size();
more = compilearg(gs, p, VAL_CODE, prevargs + 2);
ostd::uint inst1 = gs.code[start1], op1 = inst1 & ~CODE_RET_MASK, len1 = start2 - (start1 + 1);
ostd::Uint32 inst1 = gs.code[start1], op1 = inst1 & ~CODE_RET_MASK, len1 = start2 - (start1 + 1);
if (!more) {
if (op1 == (CODE_BLOCK | (len1 << 8))) {
gs.code[start1] = (len1 << 8) | CODE_JUMP_FALSE;
@ -1948,7 +1950,7 @@ compilecomv:
}
compileblock(gs);
} else {
ostd::uint inst2 = gs.code[start2], op2 = inst2 & ~CODE_RET_MASK, len2 = gs.code.size() - (start2 + 1);
ostd::Uint32 inst2 = gs.code[start2], op2 = inst2 & ~CODE_RET_MASK, len2 = gs.code.size() - (start2 + 1);
if (op2 == (CODE_BLOCK | (len2 << 8))) {
if (op1 == (CODE_BLOCK | (len1 << 8))) {
gs.code[start1] = ((start2 - start1) << 8) | CODE_JUMP_FALSE;
@ -1991,18 +1993,18 @@ compilecomv:
more = compilearg(gs, p, VAL_COND, prevargs + numargs);
if (!more) break;
numargs++;
if ((gs.code[end] & ~CODE_RET_MASK) != (CODE_BLOCK | (ostd::uint(gs.code.size() - (end + 1)) << 8))) break;
if ((gs.code[end] & ~CODE_RET_MASK) != (CODE_BLOCK | (ostd::Uint32(gs.code.size() - (end + 1)) << 8))) break;
end = gs.code.size();
}
if (more) {
while (numargs < MAX_ARGUMENTS && (more = compilearg(gs, p, VAL_COND, prevargs + numargs))) numargs++;
gs.code.push(CODE_COMV | cs_ret_code(rettype) | (numargs << 8) | (id->index << 13));
} else {
ostd::uint op = id->type == ID_AND ? CODE_JUMP_RESULT_FALSE : CODE_JUMP_RESULT_TRUE;
ostd::Uint32 op = id->type == ID_AND ? CODE_JUMP_RESULT_FALSE : CODE_JUMP_RESULT_TRUE;
gs.code.push(op);
end = gs.code.size();
while (start + 1 < end) {
ostd::uint len = gs.code[start] >> 8;
ostd::Uint32 len = gs.code[start] >> 8;
gs.code[start] = ((end - (start + 1)) << 8) | op;
gs.code[start + 1] = CODE_ENTER;
gs.code[start + len] = (gs.code[start + len] & ~CODE_RET_MASK) | cs_ret_code(rettype);
@ -2061,17 +2063,17 @@ void GenState::gen_main(const char *p, int ret_type) {
code.push(CODE_EXIT | ((ret_type < VAL_ANY) ? (ret_type << CODE_RET) : 0));
}
ostd::uint *compilecode(CsState &cs, const char *p) {
ostd::Uint32 *compilecode(CsState &cs, const char *p) {
GenState gs(cs);
gs.code.reserve(64);
gs.gen_main(p);
ostd::uint *code = new ostd::uint[gs.code.size()];
memcpy(code, gs.code.data(), gs.code.size() * sizeof(ostd::uint));
ostd::Uint32 *code = new ostd::Uint32[gs.code.size()];
memcpy(code, gs.code.data(), gs.code.size() * sizeof(ostd::Uint32));
code[0] += 0x100;
return code;
}
static inline const ostd::uint *forcecode(CsState &cs, TaggedValue &v) {
static inline const ostd::Uint32 *forcecode(CsState &cs, TaggedValue &v) {
if (v.type != VAL_CODE) {
GenState gs(cs);
gs.code.reserve(64);
@ -2093,7 +2095,7 @@ static inline void forcecond(CsState &cs, TaggedValue &v) {
}
}
void keepcode(ostd::uint *code) {
void keepcode(ostd::Uint32 *code) {
if (!code) return;
switch (*code & CODE_OP_MASK) {
case CODE_START:
@ -2111,7 +2113,7 @@ void keepcode(ostd::uint *code) {
}
}
void freecode(ostd::uint *code) {
void freecode(ostd::Uint32 *code) {
if (!code) return;
switch (*code & CODE_OP_MASK) {
case CODE_START:
@ -2147,15 +2149,15 @@ using CommandFunc11 = void (__cdecl *)(CsState &, void *, void *, void *, void *
using CommandFunc12 = void (__cdecl *)(CsState &, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *);
using CommandFuncTv = void (__cdecl *)(CsState &, TaggedValue *, int);
static const ostd::uint *skipcode(const ostd::uint *code, TaggedValue &result = no_ret) {
static const ostd::Uint32 *skipcode(const ostd::Uint32 *code, TaggedValue &result = no_ret) {
int depth = 0;
for (;;) {
ostd::uint op = *code++;
ostd::Uint32 op = *code++;
switch (op & 0xFF) {
case CODE_MACRO:
case CODE_VAL|RET_STR: {
ostd::uint len = op >> 8;
code += len / sizeof(ostd::uint) + 1;
ostd::Uint32 len = op >> 8;
code += len / sizeof(ostd::Uint32) + 1;
continue;
}
case CODE_BLOCK:
@ -2164,7 +2166,7 @@ static const ostd::uint *skipcode(const ostd::uint *code, TaggedValue &result =
case CODE_JUMP_FALSE:
case CODE_JUMP_RESULT_TRUE:
case CODE_JUMP_RESULT_FALSE: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
code += len;
continue;
}
@ -2319,7 +2321,7 @@ cleanup:
#define MAXRUNDEPTH 255
static int rundepth = 0;
static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValue &result) {
static const ostd::Uint32 *runcode(CsState &cs, const ostd::Uint32 *code, TaggedValue &result) {
result.set_null();
if (rundepth >= MAXRUNDEPTH) {
cs.debug_code("exceeded recursion limit");
@ -2330,7 +2332,7 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
TaggedValue args[MAX_ARGUMENTS + MAX_RESULTS], *prevret = cs.result;
cs.result = &result;
for (;;) {
ostd::uint op = *code++;
ostd::Uint32 op = *code++;
switch (op & 0xFF) {
case CODE_START:
case CODE_OFFSET:
@ -2430,24 +2432,24 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
continue;
case CODE_JUMP: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
code += len;
continue;
}
case CODE_JUMP_TRUE: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
if (getbool(args[--numargs])) code += len;
args[numargs].cleanup();
continue;
}
case CODE_JUMP_FALSE: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
if (!getbool(args[--numargs])) code += len;
args[numargs].cleanup();
continue;
}
case CODE_JUMP_RESULT_TRUE: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
result.cleanup();
--numargs;
if (args[numargs].type == VAL_CODE) {
@ -2458,7 +2460,7 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
continue;
}
case CODE_JUMP_RESULT_FALSE: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
result.cleanup();
--numargs;
if (args[numargs].type == VAL_CODE) {
@ -2470,16 +2472,16 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
}
case CODE_MACRO: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
args[numargs++].set_macro(code);
code += len / sizeof(ostd::uint) + 1;
code += len / sizeof(ostd::Uint32) + 1;
continue;
}
case CODE_VAL|RET_STR: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
args[numargs++].set_str(dup_ostr(ostd::ConstCharRange((const char *)code, len)));
code += len / sizeof(ostd::uint) + 1;
code += len / sizeof(ostd::Uint32) + 1;
continue;
}
case CODE_VALI|RET_STR: {
@ -2556,7 +2558,7 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
args[numargs++].set_code(emptyblock[VAL_FLOAT] + 1);
break;
case CODE_BLOCK: {
ostd::uint len = op >> 8;
ostd::Uint32 len = op >> 8;
args[numargs++].set_code(code + 1);
code += len;
continue;
@ -2906,7 +2908,7 @@ static const ostd::uint *runcode(CsState &cs, const ostd::uint *code, TaggedValu
IdentLink aliaslink = { id, (cs).stack, (1<<callargs)-1, argstack }; \
(cs).stack = &aliaslink; \
if(!id->code) id->code = compilecode((cs), id->get_str()); \
ostd::uint *code = id->code; \
ostd::Uint32 *code = id->code; \
code[0] += 0x100; \
runcode((cs), code+1, (result)); \
code[0] -= 0x100; \
@ -3015,7 +3017,7 @@ exit:
return code;
}
void CsState::run_ret(const ostd::uint *code, TaggedValue &result) {
void CsState::run_ret(const ostd::Uint32 *code, TaggedValue &result) {
runcode(*this, code, result);
}
@ -3081,7 +3083,7 @@ void CsState::run_ret(Ident *id, ostd::PointerRange<TaggedValue> args,
--rundepth;
}
ostd::String CsState::run_str(const ostd::uint *code) {
ostd::String CsState::run_str(const ostd::Uint32 *code) {
TaggedValue result;
runcode(*this, code, result);
if (result.type == VAL_NULL) return ostd::String();
@ -3112,7 +3114,7 @@ ostd::String CsState::run_str(Ident *id, ostd::PointerRange<TaggedValue> args) {
return ret;
}
int CsState::run_int(const ostd::uint *code) {
int CsState::run_int(const ostd::Uint32 *code) {
TaggedValue result;
runcode(*this, code, result);
int i = result.get_int();
@ -3140,7 +3142,7 @@ int CsState::run_int(Ident *id, ostd::PointerRange<TaggedValue> args) {
return i;
}
float CsState::run_float(const ostd::uint *code) {
float CsState::run_float(const ostd::Uint32 *code) {
TaggedValue result;
runcode(*this, code, result);
float f = result.get_float();
@ -3164,7 +3166,7 @@ float CsState::run_float(Ident *id, ostd::PointerRange<TaggedValue> args) {
return f;
}
bool CsState::run_bool(const ostd::uint *code) {
bool CsState::run_bool(const ostd::Uint32 *code) {
TaggedValue result;
runcode(*this, code, result);
bool b = getbool(result);
@ -3221,6 +3223,10 @@ void init_lib_io(CsState &cs) {
cs.add_command("exec", "sb", [](CsState &cs, char *file, int *msg) {
cs.result->set_int(cs.run_file(file, *msg != 0) ? 1 : 0);
});
cs.add_command("echo", "C", [](CsState &, char *s) {
ostd::writeln(s);
});
}
const char *escapestring(const char *s) {
@ -3303,12 +3309,14 @@ bool validateblock(const char *s) {
/* standard lib */
void cs_init_lib_base_loops(CsState &cs);
void init_lib_base(CsState &cs) {
cs.add_command("do", "e", [](CsState &cs, ostd::uint *body) {
cs.add_command("do", "e", [](CsState &cs, ostd::Uint32 *body) {
cs.run_ret(body);
}, ID_DO);
cs.add_command("doargs", "e", [](CsState &cs, ostd::uint *body) {
cs.add_command("doargs", "e", [](CsState &cs, ostd::Uint32 *body) {
if (cs.stack != &cs.noalias)
cs_do_args(cs, [&]() { cs.run_ret(body); });
else
@ -3316,7 +3324,7 @@ void init_lib_base(CsState &cs) {
}, ID_DOARGS);
cs.add_command("if", "tee", [](CsState &cs, TaggedValue *cond,
ostd::uint *t, ostd::uint *f) {
ostd::Uint32 *t, ostd::Uint32 *f) {
cs.run_ret(getbool(*cond) ? t : f);
}, ID_IF);
@ -3362,9 +3370,215 @@ void init_lib_base(CsState &cs) {
result(cs, *(getbool(*cond) ? t : f));
});
cs.add_command("cond", "ee2V", [](CsState &cs, TaggedValue *args,
int numargs) {
for (int i = 0; i < numargs; i += 2) {
if ((i + 1) < numargs) {
if (cs.run_bool(args[i].code)) {
cs.run_ret(args[i + 1].code);
break;
}
} else {
cs.run_ret(args[i].code);
break;
}
}
});
#define CS_CASE_COMMAND(name, fmt, type, acc, compare) \
cs.add_command(name, fmt "te2V", [](CsState &cs, TaggedValue *args, \
int numargs) { \
type val = acc; \
int i; \
for (i = 1; (i + 1) < numargs; i += 2) { \
if (compare) { \
cs.run_ret(args[i + 1].code); \
return; \
} \
} \
});
CS_CASE_COMMAND("case", "i", int, args[0].get_int(),
((args[i].type == VAL_NULL) ||
(args[i].get_int() == val)));
CS_CASE_COMMAND("casef", "f", float, args[0].get_float(),
((args[i].type == VAL_NULL) ||
(args[i].get_float() == val)));
CS_CASE_COMMAND("cases", "s", const char *, args[0].get_str(),
((args[i].type == VAL_NULL) ||
!strcmp(args[i].get_str(), val)));
#undef CS_CASE_COMMAND
cs.add_command("pushif", "rTe", [](CsState &cs, Ident *id,
TaggedValue *v, ostd::Uint32 *code) {
if ((id->type != ID_ALIAS) || (id->index < MAX_ARGUMENTS))
return;
if (getbool(*v)) {
IdentStack stack;
id->push_arg(*v, stack);
v->type = VAL_NULL;
id->flags &= ~IDF_UNKNOWN;
cs.run_ret(code);
id->pop_arg();
}
});
cs_init_lib_base_loops(cs);
cs_init_lib_base_var(cs);
}
static inline void cs_set_iter(Ident &id, int i, IdentStack &stack) {
if (id.stack == &stack) {
if (id.valtype != VAL_INT) {
if (id.valtype == VAL_STR) delete[] id.val.s;
id.clean_code();
id.valtype = VAL_INT;
}
id.val.i = i;
return;
}
TaggedValue v;
v.set_int(i);
id.push_arg(v, stack);
id.flags &= ~IDF_UNKNOWN;
}
static inline void cs_do_loop(CsState &cs, Ident &id, int offset, int n,
int step, ostd::Uint32 *cond, ostd::Uint32 *body) {
if (n <= 0 || (id.type != ID_ALIAS))
return;
IdentStack stack;
for (int i = 0; i < n; ++i) {
cs_set_iter(id, offset + i * step, stack);
if (cond && !cs.run_bool(cond)) break;
cs.run_int(body);
}
id.pop_arg();
}
static inline void cs_loop_conc(CsState &cs, Ident &id, int offset, int n,
int step, ostd::Uint32 *body, bool space) {
if (n <= 0 || id.type != ID_ALIAS)
return;
IdentStack stack;
ostd::Vector<char> s;
for (int i = 0; i < n; ++i) {
cs_set_iter(id, offset + i * step, stack);
TaggedValue v;
cs.run_ret(body, v);
const char *vstr = v.get_str();
if (space && i) s.push(' ');
s.push_n(vstr, strlen(vstr));
v.cleanup();
}
if (n > 0) id.pop_arg();
s.push('\0');
cs.result->set_str(s.disown());
}
void cs_init_lib_base_loops(CsState &cs) {
cs.add_command("loop", "rie", [](CsState &cs, Ident *id, int *n,
ostd::Uint32 *body) {
cs_do_loop(cs, *id, 0, *n, 1, nullptr, body);
});
cs.add_command("loop+", "riie", [](CsState &cs, Ident *id, int *offset,
int *n, ostd::Uint32 *body) {
cs_do_loop(cs, *id, *offset, *n, 1, nullptr, body);
});
cs.add_command("loop*", "riie", [](CsState &cs, Ident *id, int *step,
int *n, ostd::Uint32 *body) {
cs_do_loop(cs, *id, 0, *n, *step, nullptr, body);
});
cs.add_command("loop+*", "riiie", [](CsState &cs, Ident *id, int *offset,
int *step, int *n, ostd::Uint32 *body) {
cs_do_loop(cs, *id, *offset, *n, *step, nullptr, body);
});
cs.add_command("loopwhile", "riee", [](CsState &cs, Ident *id, int *n,
ostd::Uint32 *cond,
ostd::Uint32 *body) {
cs_do_loop(cs, *id, 0, *n, 1, cond, body);
});
cs.add_command("loopwhile+", "riiee", [](CsState &cs, Ident *id,
int *offset, int *n,
ostd::Uint32 *cond,
ostd::Uint32 *body) {
cs_do_loop(cs, *id, *offset, *n, 1, cond, body);
});
cs.add_command("loopwhile*", "riiee", [](CsState &cs, Ident *id,
int *step, int *n,
ostd::Uint32 *cond,
ostd::Uint32 *body) {
cs_do_loop(cs, *id, 0, *n, *step, cond, body);
});
cs.add_command("loopwhile+*", "riiiee", [](CsState &cs, Ident *id,
int *offset, int *step,
int *n, ostd::Uint32 *cond,
ostd::Uint32 *body) {
cs_do_loop(cs, *id, *offset, *n, *step, cond, body);
});
cs.add_command("while", "ee", [](CsState &cs, ostd::Uint32 *cond,
ostd::Uint32 *body) {
while (cs.run_bool(cond)) cs.run_int(body);
});
cs.add_command("loopconcat", "rie", [](CsState &cs, Ident *id, int *n,
ostd::Uint32 *body) {
cs_loop_conc(cs, *id, 0, *n, 1, body, true);
});
cs.add_command("loopconcat+", "riie", [](CsState &cs, Ident *id,
int *offset, int *n,
ostd::Uint32 *body) {
cs_loop_conc(cs, *id, *offset, *n, 1, body, true);
});
cs.add_command("loopconcat*", "riie", [](CsState &cs, Ident *id,
int *step, int *n,
ostd::Uint32 *body) {
cs_loop_conc(cs, *id, 0, *n, *step, body, true);
});
cs.add_command("loopconcat+*", "riiie", [](CsState &cs, Ident *id,
int *offset, int *step,
int *n, ostd::Uint32 *body) {
cs_loop_conc(cs, *id, *offset, *n, *step, body, true);
});
cs.add_command("loopconcatword", "rie", [](CsState &cs, Ident *id,
int *n, ostd::Uint32 *body) {
cs_loop_conc(cs, *id, 0, *n, 1, body, false);
});
cs.add_command("loopconcatword+", "riie", [](CsState &cs, Ident *id,
int *offset, int *n,
ostd::Uint32 *body) {
cs_loop_conc(cs, *id, *offset, *n, 1, body, false);
});
cs.add_command("loopconcatword*", "riie", [](CsState &cs, Ident *id,
int *step, int *n,
ostd::Uint32 *body) {
cs_loop_conc(cs, *id, 0, *n, *step, body, false);
});
cs.add_command("loopconcatword+*", "riiie", [](CsState &cs, Ident *id,
int *offset, int *step,
int *n, ostd::Uint32 *body) {
cs_loop_conc(cs, *id, *offset, *n, *step, body, false);
});
}
static char retbuf[4][256];
static int retidx = 0;
@ -3385,92 +3599,6 @@ const char *floatstr(float v) {
#undef ICOMMANDSNAME
#define ICOMMANDSNAME _stdcmd
ICOMMAND(pushif, "rTe", (CsState &cs, Ident *id, TaggedValue *v, ostd::uint *code), {
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
if (getbool(*v)) {
IdentStack stack;
id->push_arg(*v, stack);
v->type = VAL_NULL;
id->flags &= ~IDF_UNKNOWN;
cs.run_ret(code);
id->pop_arg();
}
});
static inline void setiter(Ident &id, int i, IdentStack &stack) {
if (id.stack == &stack) {
if (id.valtype != VAL_INT) {
if (id.valtype == VAL_STR) delete[] id.val.s;
id.clean_code();
id.valtype = VAL_INT;
}
id.val.i = i;
} else {
TaggedValue t;
t.set_int(i);
id.push_arg(t, stack);
id.flags &= ~IDF_UNKNOWN;
}
}
static inline void doloop(CsState &cs, Ident &id, int offset, int n, int step, ostd::uint *body) {
if (n <= 0 || id.type != ID_ALIAS) return;
IdentStack stack;
for (int i = 0; i < n; ++i) {
setiter(id, offset + i * step, stack);
cs.run_int(body);
}
id.pop_arg();
}
ICOMMAND(loop, "rie", (CsState &cs, Ident *id, int *n, ostd::uint *body), doloop(cs, *id, 0, *n, 1, body));
ICOMMAND(loop+, "riie", (CsState &cs, Ident *id, int *offset, int *n, ostd::uint *body), doloop(cs, *id, *offset, *n, 1, body));
ICOMMAND(loop*, "riie", (CsState &cs, Ident *id, int *step, int *n, ostd::uint *body), doloop(cs, *id, 0, *n, *step, body));
ICOMMAND(loop+*, "riiie", (CsState &cs, Ident *id, int *offset, int *step, int *n, ostd::uint *body), doloop(cs, *id, *offset, *n, *step, body));
static inline void loopwhile(CsState &cs, Ident &id, int offset, int n, int step, ostd::uint *cond, ostd::uint *body) {
if (n <= 0 || id.type != ID_ALIAS) return;
IdentStack stack;
for (int i = 0; i < n; ++i) {
setiter(id, offset + i * step, stack);
if (!cs.run_bool(cond)) break;
cs.run_int(body);
}
id.pop_arg();
}
ICOMMAND(loopwhile, "riee", (CsState &cs, Ident *id, int *n, ostd::uint *cond, ostd::uint *body), loopwhile(cs, *id, 0, *n, 1, cond, body));
ICOMMAND(loopwhile+, "riiee", (CsState &cs, Ident *id, int *offset, int *n, ostd::uint *cond, ostd::uint *body), loopwhile(cs, *id, *offset, *n, 1, cond, body));
ICOMMAND(loopwhile*, "riiee", (CsState &cs, Ident *id, int *step, int *n, ostd::uint *cond, ostd::uint *body), loopwhile(cs, *id, 0, *n, *step, cond, body));
ICOMMAND(loopwhile+*, "riiiee", (CsState &cs, Ident *id, int *offset, int *step, int *n, ostd::uint *cond, ostd::uint *body), loopwhile(cs, *id, *offset, *n, *step, cond, body));
ICOMMAND(while, "ee", (CsState &cs, ostd::uint *cond, ostd::uint *body), while (cs.run_bool(cond)) cs.run_int(body));
static inline void loopconc(CsState &cs, Ident &id, int offset, int n, int step, ostd::uint *body, bool space) {
if (n <= 0 || id.type != ID_ALIAS) return;
IdentStack stack;
ostd::Vector<char> s;
for (int i = 0; i < n; ++i) {
setiter(id, offset + i * step, stack);
TaggedValue v;
cs.run_ret(body, v);
const char *vstr = v.get_str();
int len = strlen(vstr);
if (space && i) s.push(' ');
s.push_n(vstr, len);
v.cleanup();
}
if (n > 0) id.pop_arg();
s.push('\0');
cs.result->set_str(s.disown());
}
ICOMMAND(loopconcat, "rie", (CsState &cs, Ident *id, int *n, ostd::uint *body), loopconc(cs, *id, 0, *n, 1, body, true));
ICOMMAND(loopconcat+, "riie", (CsState &cs, Ident *id, int *offset, int *n, ostd::uint *body), loopconc(cs, *id, *offset, *n, 1, body, true));
ICOMMAND(loopconcat*, "riie", (CsState &cs, Ident *id, int *step, int *n, ostd::uint *body), loopconc(cs, *id, 0, *n, *step, body, true));
ICOMMAND(loopconcat+*, "riiie", (CsState &cs, Ident *id, int *offset, int *step, int *n, ostd::uint *body), loopconc(cs, *id, *offset, *n, *step, body, true));
ICOMMAND(loopconcatword, "rie", (CsState &cs, Ident *id, int *n, ostd::uint *body), loopconc(cs, *id, 0, *n, 1, body, false));
ICOMMAND(loopconcatword+, "riie", (CsState &cs, Ident *id, int *offset, int *n, ostd::uint *body), loopconc(cs, *id, *offset, *n, 1, body, false));
ICOMMAND(loopconcatword*, "riie", (CsState &cs, Ident *id, int *step, int *n, ostd::uint *body), loopconc(cs, *id, 0, *n, *step, body, false));
ICOMMAND(loopconcatword+*, "riiie", (CsState &cs, Ident *id, int *offset, int *step, int *n, ostd::uint *body), loopconc(cs, *id, *offset, *n, *step, body, false));
void concat(CsState &cs, TaggedValue *v, int n) {
cs.result->set_str(conc(v, n, true));
}
@ -3664,7 +3792,7 @@ static inline void setiter(Ident &id, char *val, IdentStack &stack) {
}
}
void listfind(CsState &cs, Ident *id, const char *list, const ostd::uint *body) {
void listfind(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS) {
cs.result->set_int(-1);
return;
@ -3685,7 +3813,7 @@ found:
}
COMMAND(listfind, "rse");
void listassoc(CsState &cs, Ident *id, const char *list, const ostd::uint *body) {
void listassoc(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS) return;
IdentStack stack;
int n = -1;
@ -3733,7 +3861,7 @@ LISTASSOC(listassoc=, "i", int, , parseint(start) == *val);
LISTASSOC(listassoc=f, "f", float, , parsefloat(start) == *val);
LISTASSOC(listassoc=s, "s", char, int len = (int)strlen(val), int(end - start) == len && !memcmp(start, val, len));
void looplist(CsState &cs, Ident *id, const char *list, const ostd::uint *body) {
void looplist(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS) return;
IdentStack stack;
int n = 0;
@ -3745,7 +3873,7 @@ void looplist(CsState &cs, Ident *id, const char *list, const ostd::uint *body)
}
COMMAND(looplist, "rse");
void looplist2(CsState &cs, Ident *id, Ident *id2, const char *list, const ostd::uint *body) {
void looplist2(CsState &cs, Ident *id, Ident *id2, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS || id2->type != ID_ALIAS) return;
IdentStack stack, stack2;
int n = 0;
@ -3761,7 +3889,7 @@ void looplist2(CsState &cs, Ident *id, Ident *id2, const char *list, const ostd:
}
COMMAND(looplist2, "rrse");
void looplist3(CsState &cs, Ident *id, Ident *id2, Ident *id3, const char *list, const ostd::uint *body) {
void looplist3(CsState &cs, Ident *id, Ident *id2, Ident *id3, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS || id2->type != ID_ALIAS || id3->type != ID_ALIAS) return;
IdentStack stack, stack2, stack3;
int n = 0;
@ -3779,7 +3907,7 @@ void looplist3(CsState &cs, Ident *id, Ident *id2, Ident *id3, const char *list,
}
COMMAND(looplist3, "rrrse");
void looplistconc(CsState &cs, Ident *id, const char *list, const ostd::uint *body, bool space) {
void looplistconc(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body, bool space) {
if (id->type != ID_ALIAS) return;
IdentStack stack;
ostd::Vector<char> r;
@ -3801,10 +3929,10 @@ void looplistconc(CsState &cs, Ident *id, const char *list, const ostd::uint *bo
r.push('\0');
cs.result->set_str(r.disown());
}
ICOMMAND(looplistconcat, "rse", (CsState &cs, Ident *id, char *list, ostd::uint *body), looplistconc(cs, id, list, body, true));
ICOMMAND(looplistconcatword, "rse", (CsState &cs, Ident *id, char *list, ostd::uint *body), looplistconc(cs, id, list, body, false));
ICOMMAND(looplistconcat, "rse", (CsState &cs, Ident *id, char *list, ostd::Uint32 *body), looplistconc(cs, id, list, body, true));
ICOMMAND(looplistconcatword, "rse", (CsState &cs, Ident *id, char *list, ostd::Uint32 *body), looplistconc(cs, id, list, body, false));
void listfilter(CsState &cs, Ident *id, const char *list, const ostd::uint *body) {
void listfilter(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS) return;
IdentStack stack;
ostd::Vector<char> r;
@ -3824,7 +3952,7 @@ void listfilter(CsState &cs, Ident *id, const char *list, const ostd::uint *body
}
COMMAND(listfilter, "rse");
void listcount(CsState &cs, Ident *id, const char *list, const ostd::uint *body) {
void listcount(CsState &cs, Ident *id, const char *list, const ostd::Uint32 *body) {
if (id->type != ID_ALIAS) return;
IdentStack stack;
int n = 0, r = 0;
@ -3931,20 +4059,20 @@ struct sortitem {
struct sortfun {
CsState &cs;
Ident *x, *y;
ostd::uint *body;
ostd::Uint32 *body;
bool operator()(const sortitem &xval, const sortitem &yval) {
if (x->valtype != VAL_CSTR) x->valtype = VAL_CSTR;
x->clean_code();
x->val.code = (const ostd::uint *)xval.str;
x->val.code = (const ostd::Uint32 *)xval.str;
if (y->valtype != VAL_CSTR) y->valtype = VAL_CSTR;
y->clean_code();
y->val.code = (const ostd::uint *)yval.str;
y->val.code = (const ostd::Uint32 *)yval.str;
return cs.run_bool(body);
}
};
void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body, ostd::uint *unique) {
void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::Uint32 *body, ostd::Uint32 *unique) {
if (x == y || x->type != ID_ALIAS || y->type != ID_ALIAS) return;
ostd::Vector<sortitem> items;
@ -4030,7 +4158,7 @@ void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body, ost
cs.result->set_str(sorted);
}
COMMAND(sortlist, "srree");
ICOMMAND(uniquelist, "srre", (CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body), sortlist(cs, list, x, y, nullptr, body));
ICOMMAND(uniquelist, "srre", (CsState &cs, char *list, Ident *x, Ident *y, ostd::Uint32 *body), sortlist(cs, list, x, y, nullptr, body));
#define MATHCMD(name, fmt, type, op, initval, unaryop) \
ICOMMANDS(name, #fmt "1V", (CsState &cs, TaggedValue *args, int numargs), \
@ -4189,39 +4317,6 @@ ICOMMAND(round, "ff", (CsState &cs, float *n, float *k), {
cs.result->set_float(float(r));
});
ICOMMAND(cond, "ee2V", (CsState &cs, TaggedValue *args, int numargs), {
for (int i = 0; i < numargs; i += 2) {
if (i + 1 < numargs) {
if (cs.run_bool(args[i].code)) {
cs.run_ret(args[i + 1].code);
break;
}
} else {
cs.run_ret(args[i].code);
break;
}
}
});
#define CASECOMMAND(name, fmt, type, acc, compare) \
ICOMMAND(name, fmt "te2V", (CsState &cs, TaggedValue *args, int numargs), \
{ \
type val = acc; \
int i; \
for(i = 1; i+1 < numargs; i += 2) \
{ \
if(compare) \
{ \
cs.run_ret(args[i+1].code); \
return; \
} \
} \
})
CASECOMMAND(case, "i", int, args[0].get_int(), args[i].type == VAL_NULL || args[i].get_int() == val);
CASECOMMAND(casef, "f", float, args[0].get_float(), args[i].type == VAL_NULL || args[i].get_float() == val);
CASECOMMAND(cases, "s", const char *, args[0].get_str(), args[i].type == VAL_NULL || !strcmp(args[i].get_str(), val));
ICOMMAND(tohex, "ii", (CsState &cs, int *n, int *p), {
auto r = ostd::appender<ostd::Vector<char>>();
ostd::format(r, "0x%.*X", ostd::max(*p, 1), *n);
@ -4250,7 +4345,6 @@ CMPSCMD(>s, >);
CMPSCMD(<=s, <=);
CMPSCMD(>=s, >=);
ICOMMAND(echo, "C", (CsState &, char *s), ostd::writeln(s));
ICOMMAND(strstr, "ss", (CsState &cs, char *a, char *b), { char *s = strstr(a, b); cs.result->set_int(s ? s - a : -1); });
ICOMMAND(strlen, "s", (CsState &cs, char *s), cs.result->set_int(strlen(s)));
ICOMMAND(strcode, "si", (CsState &cs, char *s, int *i), cs.result->set_int(*i > 0 ? (memchr(s, 0, *i) ? 0 : ostd::byte(s[*i])) : ostd::byte(s[0])));

View File

@ -99,7 +99,7 @@ struct IdentValue {
int i; /* ID_VAR, VAL_INT */
float f; /* ID_FVAR, VAL_FLOAT */
char *s; /* ID_SVAR, VAL_STR */
const ostd::uint *code; /* VAL_CODE */
const ostd::Uint32 *code; /* VAL_CODE */
Ident *id; /* VAL_IDENT */
const char *cstr; /* VAL_CSTR */
};
@ -124,11 +124,11 @@ struct TaggedValue: IdentValue {
type = VAL_NULL;
i = 0;
}
void set_code(const ostd::uint *val) {
void set_code(const ostd::Uint32 *val) {
type = VAL_CODE;
code = val;
}
void set_macro(const ostd::uint *val) {
void set_macro(const ostd::Uint32 *val) {
type = VAL_MACRO;
code = val;
}
@ -195,13 +195,13 @@ struct Ident {
IdentValue overrideval;
};
struct { /* ID_ALIAS */
ostd::uint *code;
ostd::Uint32 *code;
IdentValue val;
IdentStack *stack;
};
struct { /* ID_COMMAND */
char *args;
ostd::uint argmask;
ostd::Uint32 argmask;
};
};
IdentFunc fun; /* ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND */
@ -243,7 +243,7 @@ struct Ident {
val = v;
}
/* ID_COMMAND */
Ident(int t, ostd::ConstCharRange n, ostd::ConstCharRange args, ostd::uint argmask, int numargs, IdentFunc f = nullptr, int flags = 0)
Ident(int t, ostd::ConstCharRange n, ostd::ConstCharRange args, ostd::Uint32 argmask, int numargs, IdentFunc f = nullptr, int flags = 0)
: type(t), numargs(numargs), flags(flags), name(n), args(!args.empty() ? dup_ostr(args) : nullptr), argmask(argmask), fun(f) {
}
@ -360,28 +360,28 @@ struct CsState {
bool add_command(ostd::ConstCharRange name, ostd::ConstCharRange args,
IdentFunc func, int type = ID_COMMAND);
ostd::String run_str(const ostd::uint *code);
ostd::String run_str(const ostd::Uint32 *code);
ostd::String run_str(ostd::ConstCharRange code);
ostd::String run_str(Ident *id, ostd::PointerRange<TaggedValue> args);
int run_int(const ostd::uint *code);
int run_int(const ostd::Uint32 *code);
int run_int(ostd::ConstCharRange code);
int run_int(Ident *id, ostd::PointerRange<TaggedValue> args);
float run_float(const ostd::uint *code);
float run_float(const ostd::Uint32 *code);
float run_float(ostd::ConstCharRange code);
float run_float(Ident *id, ostd::PointerRange<TaggedValue> args);
bool run_bool(const ostd::uint *code);
bool run_bool(const ostd::Uint32 *code);
bool run_bool(ostd::ConstCharRange code);
bool run_bool(Ident *id, ostd::PointerRange<TaggedValue> args);
void run_ret(const ostd::uint *code, TaggedValue &result);
void run_ret(const ostd::Uint32 *code, TaggedValue &result);
void run_ret(ostd::ConstCharRange code, TaggedValue &result);
void run_ret(Ident *id, ostd::PointerRange<TaggedValue> args,
TaggedValue &result);
void run_ret(const ostd::uint *code) {
void run_ret(const ostd::Uint32 *code) {
run_ret(code, *result);
}
@ -581,9 +581,9 @@ inline void Ident::getcval(TaggedValue &v) const {
}
}
extern ostd::uint *compilecode(const char *p);
extern void keepcode(ostd::uint *p);
extern void freecode(ostd::uint *p);
extern ostd::Uint32 *compilecode(const char *p);
extern void keepcode(ostd::Uint32 *p);
extern void freecode(ostd::Uint32 *p);
extern const char *getalias(const char *name);
extern const char *escapestring(const char *s);