bool mul(){ if(onlyone()) return false; for(int i=1; i<=n; i++) if(abs(s[i][t[i]-1] * s[i][t[i]]) > INF) { return false; } for(int i=1; i<=n; i++) {s[i][t[i]-1] = s[i][t[i]-1] * s[i][t[i]]; t[i]--;} return true; }
static void circbreak(void) { SemBlock *b; int i; circbroken = 0; for(i = 0; i < nblocks; i++) { b = blocks[i]; b->cont = onlyone(descend(b->cont, nil, circbreak1)); } if(circbroken != 0) trackdeps(); }
static int metacond(ASTNode *c) { c = onlyone(metarun(c)); if(c == nil){ error(nil, "metacond: nil"); return -1; } if(c->t == ASTCINT) return c->i != 0; if(c->t == ASTCONST) return mpcmp(c->cons.n, mpzero) != 0; error(c, "if: unresolved %n", c); return -1; }
/* process statement in initial block with triggers tr, creating SemInit structures for all triggers. */ static void initial1(ASTNode *n, Nodes *tr, SemDefs *glob) { Nodes *r; SemVar *v; SemInit *si, **p; int t; if(n == nil) return; switch(n->t) { case ASTASS: assert(n->n1 != nil); if(n->n1->t != ASTSYMB) { error(n, "initial1: unknown lval %A", n->n1->t); return; } assert(n->n1->sym != nil); v = n->n1->sym->semc[0]; assert(v != nil); if((v->flags & SVREG) == 0) { warn(n, "'%s' initial assignment ignored", v->sym->name); break; } for(r = tr; r != nil; r = r->next) { t = inittype(r->n); if(t == SIINVAL || t == SINONE) continue; for(p = &v->init; *p != nil; p = &(*p)->vnext) if(nodeeq((*p)->trigger, r->n, nodeeq)) { error(n, "'%s' conflicting initial value", v->sym->name); break; } if(*p != nil) continue; si = emalloc(sizeof(SemInit)); si->trigger = onlyone(ssabuildbl(r->n, glob, 0)); si->type = t; si->var = v; si->val = n->n2; *p = si; } break; case ASTBLOCK: for(r = n->nl; r != nil; r = r->next) initial1(r->n, tr, glob); break; default: error(n, "initial1: unknown %A", n->t); } }
bool div(){ if(onlyone()) return false; int fh; for(int i=1; i<=n; i++) { if(s[i][t[i]]==0) { return false; } if(abs(s[i][t[i]-1]) / abs(s[i][t[i]]) > INF){ return false; } } for(int i=1; i<=n; i++) { if(s[i][t[i]-1]/s[i][t[i]]>=0) fh=1; else fh=-1; s[i][t[i]-1] = abs(s[i][t[i]-1]) / abs(s[i][t[i]]); s[i][t[i]-1]*=fh; t[i]--; } return true; }
bool add(){ if(onlyone()) return false; for(int i=1; i<=n; i++) if(abs(s[i][t[i]] + s[i][t[i]-1]) > INF)return false; for(int i=1; i<=n; i++) {s[i][t[i]-1] = s[i][t[i]] + s[i][t[i]-1]; t[i]--;} return true; }
ASTNode * pipecompile(ASTNode *n) { return onlyone(descend(n, nil, findpipe)); }
static Nodes * process(ASTNode *n) { Nodes *r, *s, *t; int ours; BitSet *ks; if(n == nil) return nil; switch(n->t){ case ASTPIPEL: t = nil; s = nil; for(r = n->nl; r != nil; r = r->next) if(r->n->t == ASTSTATE){ if(stcur == nil) stcur = stlist.next; else stcur = stcur->next; assert(stcur != nil && stcur->sym == r->n->sym); bsreset(killed); if(s != nil) t = nlcat(t, nl(node(ASTBLOCK, s))); s = nil; }else s = nlcat(s, process(r->n)); if(s != nil) t = nlcat(t, nl(node(ASTBLOCK, s))); return t; case ASTSYMB: if(stcur != nil && n->sym->pipeidx >= 0) if(bstest(killed, n->sym->pipeidx)) n->sym = stcur->outvars[n->sym->pipeidx]; else n->sym = stcur->invars[n->sym->pipeidx]; return nl(n); case ASTPRIME: ours = 0; return nl(lvalfix(n, 0, &ours)); case ASTASS: n = nodedup(n); n->n2 = onlyone(process(n->n2)); ours = 0; n->n1 = lvalfix(n->n1, LVAL, &ours); return nl(n); case ASTDECL: return nil; case ASTBLOCK: n = nodedup(n); s = nil; for(r = n->nl; r != nil; r = r->next) s = nlcat(s, process(r->n)); n->nl = s; return nl(n); case ASTCINT: case ASTCONST: return nl(n); case ASTOP: case ASTTERN: n = nodedup(n); n->n1 = onlyone(process(n->n1)); n->n2 = onlyone(process(n->n2)); n->n3 = onlyone(process(n->n3)); n->n4 = onlyone(process(n->n4)); return nl(n); case ASTIF: n = nodedup(n); n->n1 = onlyone(process(n->n1)); ks = killed; killed = bsdup(ks); n->n2 = onlyone(process(n->n2)); bsfree(killed); killed = ks; n->n3 = onlyone(process(n->n3)); return nl(n); default: warn(n, "process: unknown %A", n->t); } return nl(n); }
static Nodes * metarun(ASTNode *n) { ASTNode *m; Nodes *r, *s; if(n == nil) return nil; switch(n->t){ case ASTCINT: case ASTCONST: return nl(n); case ASTSYMB: if(n->sym == nil){ error(n, "metarun: nil symbol"); return nl(n); } switch(n->sym->t){ case SYMVAR: if((n->sym->opt & OPTMETA) == 0){ error(n, "'%s' run-time variable in compile-time expression", n->sym->name); return nl(n); } case SYMCONST: return nl(n->sym->val); case SYMFUNC: return nl(n); default: error(n, "'%s' %σ invalid in compile-time expression", n->sym->name, n->sym->t); } return nl(n); case ASTOP: m = nodedup(n); m->n1 = onlyone(metarun(n->n1)); m->n2 = onlyone(metarun(n->n2)); m->n3 = onlyone(metarun(n->n3)); return nl(constfold(m)); case ASTDECL: n->sym->opt |= OPTMETA; return nil; case ASTBLOCK: r = nil; for(s = n->nl; s != nil; s = s->next) r = nlcat(r, metarun(s->n)); return r; case ASTASS: if(n->n1 == nil || n->n1->t != ASTSYMB) error(n, "metarun: unsupported lval %n", n->n1); else if((n->n1->sym->opt & OPTMETA) == 0) error(n, "compile-time assignment to a run-time variable"); else{ m = onlyone(metarun(n->n2)); n->n1->sym->val = constfold(node(ASTCAST, n->n1->sym->type, m)); } return nil; case ASTVERBAT: r = descend(n->n1, metacopy, nil); if(r != nil && r->next == nil && r->n->t == ASTBLOCK) return r->n->nl; return r; case ASTIF: switch(metacond(n->n1)){ case 1: return metarun(n->n2); case 0: return metarun(n->n3); } return nil; case ASTFOR: r = metarun(n->n1); while(metacond(n->n2) == 1){ r = nlcat(r, metarun(n->n4)); r = nlcat(r, metarun(n->n3)); } return r; case ASTFCALL: m = nodedup(n); m->n1 = onlyone(metarun(n->n1)); m->nl = nil; for(s = n->nl; s != nil; s = s->next) m->nl = nlcat(m->nl, metarun(s->n)); return nl(constfold(m)); default: error(n, "metarun: unknown %A", n->t); return nil; } }
ASTNode * metacompile(ASTNode *n) { metatypecheck(n); return onlyone(descend(n, metacopy, nil)); }