From 27c0f1922bc63de834ba17b62f5e8a9bf393726f Mon Sep 17 00:00:00 2001 From: q66 Date: Thu, 6 Aug 2015 23:02:56 +0100 Subject: [PATCH] more progress --- command.cc | 208 +++++++++++++++++++++++++++-------------------------- command.hh | 8 ++- 2 files changed, 111 insertions(+), 105 deletions(-) diff --git a/command.cc b/command.cc index 4b49ef37..58b44977 100644 --- a/command.cc +++ b/command.cc @@ -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 +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) { cs.add_command("nodebug", "e", [](CsState &cs, ostd::uint *body) { ++cs.nodebug; executeret(body, *cs.result); --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) { if (id.type == ID_ALIAS && id.index >= MAX_ARGUMENTS) { - pusharg(id, null_value, stack); + id.push_arg(null_value, stack); id.flags &= ~IDF_UNKNOWN; } } 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); @@ -374,7 +380,7 @@ static inline void setarg(Ident &id, TaggedValue &v) { id.setval(v); id.clean_code(); } else { - pusharg(id, v, cstate.stack->argstack[id.index]); + id.push_arg(v, cstate.stack->argstack[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_FLOAT: if (cstate.stack != &cstate.noalias) { - UNDOARGS - result.cleanup(); - runcode(args[--numargs].code, result); - args[numargs].cleanup(); - result.force(op & CODE_RET_MASK); - REDOARGS + cs_do_args(cstate, [&]() { + result.cleanup(); + runcode(args[--numargs].code, result); + args[numargs].cleanup(); + result.force(op & CODE_RET_MASK); + }); continue; } /* fallthrough */ @@ -2552,7 +2558,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) { case CODE_IDENTARG: { Ident *id = cstate.identmap[op >> 8]; 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; } 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]; 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))) { - 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; } arg.cleanup(); @@ -2829,7 +2835,7 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) { #define CALLALIAS { \ IdentStack argstack[MAX_ARGUMENTS]; \ 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; \ _numargs = callargs; \ int oldflags = cstate.identflags; \ @@ -2845,9 +2851,9 @@ static const ostd::uint *runcode(const ostd::uint *code, TaggedValue &result) { cstate.stack = aliaslink.next; \ cstate.identflags = oldflags; \ for(int i = 0; i < callargs; i++) \ - poparg(*cstate.identmap[i]); \ + cstate.identmap[i]->pop_arg(); \ for(int argmask = aliaslink.usedargs&(~0<pop_arg(); argmask &= ~(1<type != ID_ALIAS || id->index < MAX_ARGUMENTS) return; if (getbool(*v)) { IdentStack stack; - pusharg(*id, *v, stack); + id->push_arg(*v, stack); v->type = VAL_NULL; id->flags &= ~IDF_UNKNOWN; executeret(code, *cs.result); - poparg(*id); + id->pop_arg(); } }); void loopiter(Ident *id, IdentStack &stack, const TaggedValue &v) { if (id->stack != &stack) { - pusharg(*id, v, stack); + id->push_arg(v, stack); id->flags &= ~IDF_UNKNOWN; } else { 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) { - if (id->stack == &stack) poparg(*id); + if (id->stack == &stack) id->pop_arg(); } 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 { TaggedValue t; t.set_int(i); - pusharg(id, t, stack); + id.push_arg(t, stack); 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); 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+, "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; 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+, "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); v.cleanup(); } - if (n > 0) poparg(id); + if (n > 0) id.pop_arg(); s.push('\0'); cstate.result->set_str(s.disown()); } @@ -3557,7 +3561,7 @@ static inline void setiter(Ident &id, char *val, IdentStack &stack) { } else { TaggedValue t; t.set_str(val); - pusharg(id, t, stack); + id.push_arg(t, stack); 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); found: - if (n >= 0) poparg(*id); + if (n >= 0) id->pop_arg(); } 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 (n >= 0) poparg(*id); + if (n >= 0) id->pop_arg(); } 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); cs.run_int(body); } - if (n) poparg(*id); + if (n) id->pop_arg(); } COMMAND(looplist, "rse"); @@ -3653,8 +3657,8 @@ void looplist2(CsState &cs, Ident *id, Ident *id2, const char *list, const ostd: cs.run_int(body); } if (n) { - poparg(*id); - poparg(*id2); + id->pop_arg(); + id2->pop_arg(); } } COMMAND(looplist2, "rrse"); @@ -3670,9 +3674,9 @@ void looplist3(CsState &cs, Ident *id, Ident *id2, Ident *id3, const char *list, cs.run_int(body); } if (n) { - poparg(*id); - poparg(*id2); - poparg(*id3); + id->pop_arg(); + id2->pop_arg(); + id3->pop_arg(); } } 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); v.cleanup(); } - if (n) poparg(*id); + if (n) id->pop_arg(); r.push('\0'); 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); } } - if (n) poparg(*id); + if (n) id->pop_arg(); r.push('\0'); 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); if (cs.run_bool(body)) r++; } - if (n) poparg(*id); + if (n) id->pop_arg(); cs.result->set_int(r); } COMMAND(listcount, "rse"); @@ -3862,9 +3866,9 @@ void sortlist(CsState &cs, char *list, Ident *x, Ident *y, ostd::uint *body, ost } IdentStack xstack, ystack; - pusharg(*x, null_value, xstack); + x->push_arg(null_value, xstack); x->flags &= ~IDF_UNKNOWN; - pusharg(*y, null_value, ystack); + y->push_arg(null_value, ystack); y->flags &= ~IDF_UNKNOWN; 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); - poparg(*y); + x->pop_arg(); + y->pop_arg(); char *sorted = cstr; int sortedlen = totalunique + ostd::max(numunique - 1, 0); diff --git a/command.hh b/command.hh index 3b9af753..92f60baa 100644 --- a/command.hh +++ b/command.hh @@ -277,6 +277,11 @@ struct Ident { } 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 { @@ -576,9 +581,6 @@ static inline void loopiter(Ident *id, IdentStack &stack, const char *s) { 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 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)