static void simpmatch(Simp *s, Node *n) { Node *end, *cur, *next; /* labels */ Node *val, *tmp; Node *m; size_t i; end = genlbl(); val = temp(s, n->matchstmt.val); tmp = rval(s, n->matchstmt.val, val); if (val != tmp) append(s, assign(s, val, tmp)); for (i = 0; i < n->matchstmt.nmatches; i++) { m = n->matchstmt.matches[i]; /* check pattern */ cur = genlbl(); next = genlbl(); umatch(s, m->match.pat, val, val->expr.type, cur, next); /* do the action if it matches */ append(s, cur); simp(s, m->match.block); jmp(s, end); append(s, next); } append(s, end); }
/* pat; seq; * body;; * * => * .pseudo = seqinit * jmp :cond * :body * ...body... * :step * ...step... * :cond * ...cond... * cjmp (cond) :match :end * :match * ...match... * cjmp (match) :body :step * :end */ static void simpiter(Simp *s, Node *n) { Node *lbody, *lstep, *lcond, *lmatch, *lend; Node *idx, *len, *dcl, *seq, *val, *done; Node *zero; lbody = genlbl(); lstep = genlbl(); lcond = genlbl(); lmatch = genlbl(); lend = genlbl(); lappend(&s->loopstep, &s->nloopstep, lstep); lappend(&s->loopexit, &s->nloopexit, lend); zero = mkintlit(n->line, 0); zero->expr.type = tyintptr; seq = rval(s, n->iterstmt.seq, NULL); idx = gentemp(s, n, tyintptr, &dcl); declarelocal(s, dcl); /* setup */ append(s, assign(s, idx, zero)); jmp(s, lcond); simp(s, lbody); /* body */ simp(s, n->iterstmt.body); /* step */ simp(s, lstep); simp(s, assign(s, idx, addk(idx, 1))); /* condition */ simp(s, lcond); len = seqlen(s, seq, tyintptr); done = mkexpr(n->line, Olt, idx, len, NULL); cjmp(s, done, lmatch, lend); simp(s, lmatch); val = load(idxaddr(s, seq, idx)); umatch(s, n->iterstmt.elt, val, val->expr.type, lbody, lstep); simp(s, lend); s->nloopstep--; s->nloopexit--; }
static int amatch(char *s, char *p) { int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return amatch(++s, ++p); else return 0; case '-': k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; } if (scc==(lc=cc)) k++; } return 0; case '?': caseq: if(scc) return amatch(++s, ++p); return 0; case '*': return umatch(s, ++p); case 0: return !scc; } if (c==scc) goto caseq; return 0; }
static void umatch(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, Node *iffalse) { Node *v, *x, *y; Node *deeper, *next; Node **patarg; Ucon *uc; size_t i; size_t off; assert(pat->type == Nexpr); t = tybase(t); if (exprop(pat) == Ovar && !decls[pat->expr.did]->decl.isconst) { v = assign(s, pat, val); append(s, v); jmp(s, iftrue); return; } switch (t->type) { /* Never supported */ case Tyvoid: case Tybad: case Tyvalist: case Tyvar: case Typaram: case Tyunres: case Tyname: case Ntypes: /* Should never show up */ case Tyslice: die("Unsupported type for compare"); break; case Tybool: case Tychar: case Tybyte: case Tyint8: case Tyint16: case Tyint32: case Tyint: case Tyuint8: case Tyuint16: case Tyuint32: case Tyuint: case Tyint64: case Tyuint64: case Tylong: case Tyulong: case Tyfloat32: case Tyfloat64: case Typtr: case Tyfunc: v = mkexpr(pat->line, Oeq, pat, val, NULL); v->expr.type = mktype(pat->line, Tybool); cjmp(s, v, iftrue, iffalse); break; /* We got lucky. The structure of tuple, array, and struct literals * is the same, so long as we don't inspect the type, so we can * share the code*/ case Tystruct: case Tytuple: case Tyarray: patarg = pat->expr.args; off = 0; for (i = 0; i < pat->expr.nargs; i++) { off = tyalign(off, size(patarg[i])); next = genlbl(); v = load(addk(addr(s, val, exprtype(patarg[i])), off)); umatch(s, patarg[i], v, exprtype(patarg[i]), next, iffalse); append(s, next); off += size(patarg[i]); } jmp(s, iftrue); break; case Tyunion: uc = finducon(pat); if (!uc) uc = finducon(val); deeper = genlbl(); x = uconid(s, pat); y = uconid(s, val); v = mkexpr(pat->line, Oeq, x, y, NULL); v->expr.type = tyintptr; cjmp(s, v, deeper, iffalse); append(s, deeper); if (uc->etype) { pat = patval(s, pat, uc->etype); val = patval(s, val, uc->etype); umatch(s, pat, val, uc->etype, iftrue, iffalse); } break; } }