more progress

master
Daniel Kolesa 2015-08-06 23:02:56 +01:00
parent a2091bdbbd
commit 27c0f1922b
2 changed files with 111 additions and 105 deletions

View File

@ -215,84 +215,90 @@ void debug_alias(CsState &cs) {
} }
} }
void Ident::push_arg(const TaggedValue &v, IdentStack &st) {
st.val = val;
st.valtype = valtype;
st.next = stack;
stack = &st;
setval(v);
clean_code();
}
void Ident::pop_arg() {
if (!stack) return;
IdentStack *st = stack;
if (valtype == VAL_STR) delete[] val.s;
setval(*stack);
clean_code();
stack = st->next;
}
void Ident::undo_arg(IdentStack &st) {
IdentStack *prev = stack;
st.val = val;
st.valtype = valtype;
st.next = prev;
stack = prev->next;
setval(*prev);
clean_code();
}
void Ident::redo_arg(const IdentStack &st) {
IdentStack *prev = st.next;
prev->val = val;
prev->valtype = valtype;
stack = prev;
setval(st);
clean_code();
}
template<typename F>
static void cs_do_args(CsState &cs, F body) {
IdentStack argstack[MAX_ARGUMENTS];
int argmask1 = cs.stack->usedargs;
for (int i = 0; argmask1; argmask1 >>= 1, ++i) if(argmask1 & 1)
cs.identmap[i]->undo_arg(argstack[i]);
IdentLink *prevstack = cs.stack->next;
IdentLink aliaslink = {
cs.stack->id, cs.stack, prevstack->usedargs, prevstack->argstack
};
cs.stack = &aliaslink;
body();
prevstack->usedargs = aliaslink.usedargs;
cs.stack = aliaslink.next;
int argmask2 = cs.stack->usedargs;
for(int i = 0; argmask2; argmask2 >>= 1, ++i) if(argmask2 & 1)
cs.identmap[i]->redo_arg(argstack[i]);
}
void init_lib_base(CsState &cs) { void init_lib_base(CsState &cs) {
cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) { cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) {
++cs.nodebug; ++cs.nodebug;
executeret(body, *cs.result); executeret(body, *cs.result);
--cs.nodebug; --cs.nodebug;
}); });
cs.add_command("push", "rTe", [](CsState &cs, Ident *id,
TaggedValue *v, ostd::uint *code) {
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
IdentStack stack;
id->push_arg(*v, stack);
v->type = VAL_NULL;
id->flags &= ~IDF_UNKNOWN;
executeret(code, *cs.result);
id->pop_arg();
});
} }
void pusharg(Ident &id, const TaggedValue &v, IdentStack &stack) {
stack.val = id.val;
stack.valtype = id.valtype;
stack.next = id.stack;
id.stack = &stack;
id.setval(v);
id.clean_code();
}
void poparg(Ident &id) {
if (!id.stack) return;
IdentStack *stack = id.stack;
if (id.valtype == VAL_STR) delete[] id.val.s;
id.setval(*stack);
id.clean_code();
id.stack = stack->next;
}
static inline void undoarg(Ident &id, IdentStack &stack) {
IdentStack *prev = id.stack;
stack.val = id.val;
stack.valtype = id.valtype;
stack.next = prev;
id.stack = prev->next;
id.setval(*prev);
id.clean_code();
}
#define UNDOARGS \
IdentStack argstack[MAX_ARGUMENTS]; \
for(int argmask = cstate.stack->usedargs, i = 0; argmask; argmask >>= 1, i++) if(argmask&1) \
undoarg(*cstate.identmap[i], argstack[i]); \
IdentLink *prevstack = cstate.stack->next; \
IdentLink aliaslink = { cstate.stack->id, cstate.stack, prevstack->usedargs, prevstack->argstack }; \
cstate.stack = &aliaslink;
static inline void redoarg(Ident &id, const IdentStack &stack) {
IdentStack *prev = stack.next;
prev->val = id.val;
prev->valtype = id.valtype;
id.stack = prev;
id.setval(stack);
id.clean_code();
}
#define REDOARGS \
prevstack->usedargs = aliaslink.usedargs; \
cstate.stack = aliaslink.next; \
for(int argmask = cstate.stack->usedargs, i = 0; argmask; argmask >>= 1, i++) if(argmask&1) \
redoarg(*cstate.identmap[i], argstack[i]);
ICOMMAND(push, "rTe", (CsState &cs, Ident *id, TaggedValue *v, ostd::uint *code), {
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
IdentStack stack;
pusharg(*id, *v, stack);
v->type = VAL_NULL;
id->flags &= ~IDF_UNKNOWN;
executeret(code, *cs.result);
poparg(*id);
});
static inline void pushalias(Ident &id, IdentStack &stack) { static inline void pushalias(Ident &id, IdentStack &stack) {
if (id.type == ID_ALIAS && id.index >= MAX_ARGUMENTS) { if (id.type == ID_ALIAS && id.index >= MAX_ARGUMENTS) {
pusharg(id, null_value, stack); id.push_arg(null_value, stack);
id.flags &= ~IDF_UNKNOWN; id.flags &= ~IDF_UNKNOWN;
} }
} }
static inline void popalias(Ident &id) { static inline void popalias(Ident &id) {
if (id.type == ID_ALIAS && id.index >= MAX_ARGUMENTS) poparg(id); if (id.type == ID_ALIAS && id.index >= MAX_ARGUMENTS) id.pop_arg();
} }
KEYWORD(local, ID_LOCAL); KEYWORD(local, ID_LOCAL);
@ -374,7 +380,7 @@ static inline void setarg(Ident &id, TaggedValue &v) {
id.setval(v); id.setval(v);
id.clean_code(); id.clean_code();
} else { } else {
pusharg(id, v, cstate.stack->argstack[id.index]); id.push_arg(v, cstate.stack->argstack[id.index]);
cstate.stack->usedargs |= 1 << id.index; cstate.stack->usedargs |= 1 << id.index;
} }
} }
@ -2341,12 +2347,12 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
case CODE_DOARGS|RET_INT: case CODE_DOARGS|RET_INT:
case CODE_DOARGS|RET_FLOAT: case CODE_DOARGS|RET_FLOAT:
if (cstate.stack != &cstate.noalias) { if (cstate.stack != &cstate.noalias) {
UNDOARGS cs_do_args(cstate, [&]() {
result.cleanup(); result.cleanup();
runcode(args[--numargs].code, result); runcode(args[--numargs].code, result);
args[numargs].cleanup(); args[numargs].cleanup();
result.force(op & CODE_RET_MASK); result.force(op & CODE_RET_MASK);
REDOARGS });
continue; continue;
} }
/* fallthrough */ /* fallthrough */
@ -2552,7 +2558,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
case CODE_IDENTARG: { case CODE_IDENTARG: {
Ident *id = cstate.identmap[op >> 8]; Ident *id = cstate.identmap[op >> 8];
if (!(cstate.stack->usedargs & (1 << id->index))) { if (!(cstate.stack->usedargs & (1 << id->index))) {
pusharg(*id, null_value, cstate.stack->argstack[id->index]); id->push_arg(null_value, cstate.stack->argstack[id->index]);
cstate.stack->usedargs |= 1 << id->index; cstate.stack->usedargs |= 1 << id->index;
} }
args[numargs++].set_ident(id); args[numargs++].set_ident(id);
@ -2562,7 +2568,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
TaggedValue &arg = args[numargs - 1]; TaggedValue &arg = args[numargs - 1];
Ident *id = arg.type == VAL_STR || arg.type == VAL_MACRO || arg.type == VAL_CSTR ? cstate.new_ident(arg.cstr, IDF_UNKNOWN) : cstate.dummy; Ident *id = arg.type == VAL_STR || arg.type == VAL_MACRO || arg.type == VAL_CSTR ? cstate.new_ident(arg.cstr, IDF_UNKNOWN) : cstate.dummy;
if (id->index < MAX_ARGUMENTS && !(cstate.stack->usedargs & (1 << id->index))) { if (id->index < MAX_ARGUMENTS && !(cstate.stack->usedargs & (1 << id->index))) {
pusharg(*id, null_value, cstate.stack->argstack[id->index]); id->push_arg(null_value, cstate.stack->argstack[id->index]);
cstate.stack->usedargs |= 1 << id->index; cstate.stack->usedargs |= 1 << id->index;
} }
arg.cleanup(); arg.cleanup();
@ -2829,7 +2835,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
#define CALLALIAS { \ #define CALLALIAS { \
IdentStack argstack[MAX_ARGUMENTS]; \ IdentStack argstack[MAX_ARGUMENTS]; \
for(int i = 0; i < callargs; i++) \ for(int i = 0; i < callargs; i++) \
pusharg(*cstate.identmap[i], args[offset + i], argstack[i]); \ cstate.identmap[i]->push_arg(args[offset + i], argstack[i]); \
int oldargs = _numargs; \ int oldargs = _numargs; \
_numargs = callargs; \ _numargs = callargs; \
int oldflags = cstate.identflags; \ int oldflags = cstate.identflags; \
@ -2845,9 +2851,9 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) {
cstate.stack = aliaslink.next; \ cstate.stack = aliaslink.next; \
cstate.identflags = oldflags; \ cstate.identflags = oldflags; \
for(int i = 0; i < callargs; i++) \ for(int i = 0; i < callargs; i++) \
poparg(*cstate.identmap[i]); \ cstate.identmap[i]->pop_arg(); \
for(int argmask = aliaslink.usedargs&(~0<<callargs), i = callargs; argmask; i++) \ for(int argmask = aliaslink.usedargs&(~0<<callargs), i = callargs; argmask; i++) \
if(argmask&(1<<i)) { poparg(*cstate.identmap[i]); argmask &= ~(1<<i); } \ if(argmask&(1<<i)) { cstate.identmap[i]->pop_arg(); argmask &= ~(1<<i); } \
result.force(op&CODE_RET_MASK); \ result.force(op&CODE_RET_MASK); \
_numargs = oldargs; \ _numargs = oldargs; \
numargs = SKIPARGS(offset); \ numargs = SKIPARGS(offset); \
@ -3253,9 +3259,7 @@ ICOMMANDK(do, ID_DO, "e", (CsState &cs, ostd::uint *body), executeret(body, *cs.
static void doargs(CsState &cs, ostd::uint *body) { static void doargs(CsState &cs, ostd::uint *body) {
if (cstate.stack != &cstate.noalias) { if (cstate.stack != &cstate.noalias) {
UNDOARGS cs_do_args(cs, [&]() { executeret(body, *cs.result); });
executeret(body, *cs.result);
REDOARGS
} else executeret(body, *cs.result); } else executeret(body, *cs.result);
} }
COMMANDK(doargs, ID_DOARGS, "e"); COMMANDK(doargs, ID_DOARGS, "e");
@ -3267,17 +3271,17 @@ ICOMMAND(pushif, "rTe", (CsState &cs, Ident *id, TaggedValue *v, ostd::uint *cod
if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return; if (id->type != ID_ALIAS || id->index < MAX_ARGUMENTS) return;
if (getbool(*v)) { if (getbool(*v)) {
IdentStack stack; IdentStack stack;
pusharg(*id, *v, stack); id->push_arg(*v, stack);
v->type = VAL_NULL; v->type = VAL_NULL;
id->flags &= ~IDF_UNKNOWN; id->flags &= ~IDF_UNKNOWN;
executeret(code, *cs.result); executeret(code, *cs.result);
poparg(*id); id->pop_arg();
} }
}); });
void loopiter(Ident *id, IdentStack &stack, const TaggedValue &v) { void loopiter(Ident *id, IdentStack &stack, const TaggedValue &v) {
if (id->stack != &stack) { if (id->stack != &stack) {
pusharg(*id, v, stack); id->push_arg(v, stack);
id->flags &= ~IDF_UNKNOWN; id->flags &= ~IDF_UNKNOWN;
} else { } else {
if (id->valtype == VAL_STR) delete[] id->val.s; if (id->valtype == VAL_STR) delete[] id->val.s;
@ -3287,7 +3291,7 @@ void loopiter(Ident *id, IdentStack &stack, const TaggedValue &v) {
} }
void loopend(Ident *id, IdentStack &stack) { void loopend(Ident *id, IdentStack &stack) {
if (id->stack == &stack) poparg(*id); if (id->stack == &stack) id->pop_arg();
} }
static inline void setiter(Ident &id, int i, IdentStack &stack) { static inline void setiter(Ident &id, int i, IdentStack &stack) {
@ -3301,7 +3305,7 @@ static inline void setiter(Ident &id, int i, IdentStack &stack) {
} else { } else {
TaggedValue t; TaggedValue t;
t.set_int(i); t.set_int(i);
pusharg(id, t, stack); id.push_arg(t, stack);
id.flags &= ~IDF_UNKNOWN; id.flags &= ~IDF_UNKNOWN;
} }
} }
@ -3313,7 +3317,7 @@ static inline void doloop(CsState &cs, Ident &id, int offset, int n, int step, o
setiter(id, offset + i * step, stack); setiter(id, offset + i * step, stack);
cs.run_int(body); cs.run_int(body);
} }
poparg(id); id.pop_arg();
} }
ICOMMAND(loop, "rie", (CsState &cs, Ident *id, int *n, ostd::uint *body), doloop(cs, *id, 0, *n, 1, body)); 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 *offset, int *n, ostd::uint *body), doloop(cs, *id, *offset, *n, 1, body));
@ -3328,7 +3332,7 @@ static inline void loopwhile(CsState &cs, Ident &id, int offset, int n, int step
if (!cs.run_bool(cond)) break; if (!cs.run_bool(cond)) break;
cs.run_int(body); cs.run_int(body);
} }
poparg(id); 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, "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 *offset, int *n, ostd::uint *cond, ostd::uint *body), loopwhile(cs, *id, *offset, *n, 1, cond, body));
@ -3351,7 +3355,7 @@ static inline void loopconc(Ident &id, int offset, int n, int step, ostd::uint *
s.push_n(vstr, len); s.push_n(vstr, len);
v.cleanup(); v.cleanup();
} }
if (n > 0) poparg(id); if (n > 0) id.pop_arg();
s.push('\0'); s.push('\0');
cstate.result->set_str(s.disown()); cstate.result->set_str(s.disown());
} }
@ -3557,7 +3561,7 @@ static inline void setiter(Ident &id, char *val, IdentStack &stack) {
} else { } else {
TaggedValue t; TaggedValue t;
t.set_str(val); t.set_str(val);
pusharg(id, t, stack); id.push_arg(t, stack);
id.flags &= ~IDF_UNKNOWN; id.flags &= ~IDF_UNKNOWN;
} }
} }
@ -3579,7 +3583,7 @@ void listfind(CsState &cs, Ident *id, const char *list, const ostd::uint *body)
} }
cs.result->set_int(-1); cs.result->set_int(-1);
found: found:
if (n >= 0) poparg(*id); if (n >= 0) id->pop_arg();
} }
COMMAND(listfind, "rse"); COMMAND(listfind, "rse");
@ -3596,7 +3600,7 @@ void listassoc(CsState &cs, Ident *id, const char *list, const ostd::uint *body)
} }
if (!parselist(s)) break; if (!parselist(s)) break;
} }
if (n >= 0) poparg(*id); if (n >= 0) id->pop_arg();
} }
COMMAND(listassoc, "rse"); COMMAND(listassoc, "rse");
@ -3639,7 +3643,7 @@ void looplist(CsState &cs, Ident *id, const char *list, const ostd::uint *body)
setiter(*id, listelem(start, end, qstart), stack); setiter(*id, listelem(start, end, qstart), stack);
cs.run_int(body); cs.run_int(body);
} }
if (n) poparg(*id); if (n) id->pop_arg();
} }
COMMAND(looplist, "rse"); COMMAND(looplist, "rse");
@ -3653,8 +3657,8 @@ void looplist2(CsState &cs, Ident *id, Ident *id2, const char *list, const ostd:
cs.run_int(body); cs.run_int(body);
} }
if (n) { if (n) {
poparg(*id); id->pop_arg();
poparg(*id2); id2->pop_arg();
} }
} }
COMMAND(looplist2, "rrse"); COMMAND(looplist2, "rrse");
@ -3670,9 +3674,9 @@ void looplist3(CsState &cs, Ident *id, Ident *id2, Ident *id3, const char *list,
cs.run_int(body); cs.run_int(body);
} }
if (n) { if (n) {
poparg(*id); id->pop_arg();
poparg(*id2); id2->pop_arg();
poparg(*id3); id3->pop_arg();
} }
} }
COMMAND(looplist3, "rrrse"); COMMAND(looplist3, "rrrse");
@ -3695,7 +3699,7 @@ void looplistconc(CsState &cs, Ident *id, const char *list, const ostd::uint *bo
r.push_n(vstr, len); r.push_n(vstr, len);
v.cleanup(); v.cleanup();
} }
if (n) poparg(*id); if (n) id->pop_arg();
r.push('\0'); r.push('\0');
cs.result->set_str(r.disown()); cs.result->set_str(r.disown());
} }
@ -3716,7 +3720,7 @@ void listfilter(CsState &cs, Ident *id, const char *list, const ostd::uint *body
r.push_n(qstart, qend - qstart); r.push_n(qstart, qend - qstart);
} }
} }
if (n) poparg(*id); if (n) id->pop_arg();
r.push('\0'); r.push('\0');
cs.result->set_str(r.disown()); cs.result->set_str(r.disown());
} }
@ -3731,7 +3735,7 @@ void listcount(CsState &cs, Ident *id, const char *list, const ostd::uint *body)
setiter(*id, val, stack); setiter(*id, val, stack);
if (cs.run_bool(body)) r++; if (cs.run_bool(body)) r++;
} }
if (n) poparg(*id); if (n) id->pop_arg();
cs.result->set_int(r); cs.result->set_int(r);
} }
COMMAND(listcount, "rse"); COMMAND(listcount, "rse");
@ -3862,9 +3866,9 @@ void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body, ost
} }
IdentStack xstack, ystack; IdentStack xstack, ystack;
pusharg(*x, null_value, xstack); x->push_arg(null_value, xstack);
x->flags &= ~IDF_UNKNOWN; x->flags &= ~IDF_UNKNOWN;
pusharg(*y, null_value, ystack); y->push_arg(null_value, ystack);
y->flags &= ~IDF_UNKNOWN; y->flags &= ~IDF_UNKNOWN;
int totalunique = total, numunique = items.size(); int totalunique = total, numunique = items.size();
@ -3904,8 +3908,8 @@ void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body, ost
} }
} }
poparg(*x); x->pop_arg();
poparg(*y); y->pop_arg();
char *sorted = cstr; char *sorted = cstr;
int sortedlen = totalunique + ostd::max(numunique - 1, 0); int sortedlen = totalunique + ostd::max(numunique - 1, 0);

View File

@ -277,6 +277,11 @@ struct Ident {
} }
void clean_code(); void clean_code();
void push_arg(const TaggedValue &v, IdentStack &st);
void pop_arg();
void undo_arg(IdentStack &st);
void redo_arg(const IdentStack &st);
}; };
struct IdentLink { struct IdentLink {
@ -576,9 +581,6 @@ static inline void loopiter(Ident *id, IdentStack &stack, const char *s) {
loopiter(id, stack, v); loopiter(id, stack, v);
} }
void pusharg(Ident &id, const TaggedValue &v, IdentStack &stack);
void poparg(Ident &id);
#define KEYWORD(name, type) static bool __dummy_##type = addcommand(#name, (IdentFunc)nullptr, nullptr, type) #define KEYWORD(name, type) static bool __dummy_##type = addcommand(#name, (IdentFunc)nullptr, nullptr, type)
#define COMMANDKN(name, type, fun, nargs) static bool __dummy_##fun = addcommand(#name, (IdentFunc)fun, nargs, type) #define COMMANDKN(name, type, fun, nargs) static bool __dummy_##fun = addcommand(#name, (IdentFunc)fun, nargs, type)
#define COMMANDK(name, type, nargs) COMMANDKN(name, type, name, nargs) #define COMMANDK(name, type, nargs) COMMANDKN(name, type, name, nargs)