static Nodes * circbreak1(ASTNode *n) { ASTNode *idx; BitSet *visit; ASTNode *m; int r; if(n->t == ASTASS && n->n2 != nil && n->n2->t == ASTISUB) { idx = n->n2->n1; assert(idx != nil && idx->t == ASTIDX); if(n->n1->t == ASTSSA && idx->n1->t == ASTSSA && idx->n1->semv == idx->n1->semv->sym->semc[1]) { visit = bsnew(nvars); r = findcircles(idx->n1->semv, n->n1->semv, visit); bsfree(visit); if(r) { m = nodedup(n); m->n2 = nodedup(m->n2); m->n2->n1 = nodedup(m->n2->n1); m->n2->n1->n1 = node(ASTSSA, idx->n1->semv->sym->semc[0]); circbroken++; return nl(m); } } } return nl(n); }
struct node* sortedMerge(struct node *a,struct node *b) { struct node dummy={-1,NULL}; // careful set dummy.next=NULL struct node* prev = &dummy; while(a!=NULL || b!= NULL) { if(a==NULL) { prev->next = nodedup(b); b = b->next; } else if(b==NULL) { prev->next = nodedup(a); a=a->next; } else if(a->data < b->data) { prev->next = nodedup(a); a=a->next; } else { prev->next = nodedup(b); b=b->next; } prev = prev->next; } return dummy.next; }
static ASTNode * lvalfix(ASTNode *n, int ctxt, int *ours) { if(n == nil) return nil; switch(n->t){ case ASTSYMB: if(n->sym->pipeidx >= 0){ n = nodedup(n); n->sym = stcur->outvars[n->sym->pipeidx]; if((ctxt & PRIME) == 0) bsadd(killed, n->sym->pipeidx); (*ours)++; } return n; case ASTPRIME: n = nodedup(n); n->n1 = lvalfix(n->n1, ctxt | PRIME, ours); if(*ours) return n->n1; return n; default: error(n, "lvalfix: unknown %A", n->t); return n; } }
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; } }