Re: [PATCH] Support direct tuple access operators "tuple.N"
[Thread Prev] | [Thread Next]
- Subject: Re: [PATCH] Support direct tuple access operators "tuple.N"
- From: Andrew Chambers <andrewchamberss@xxxxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Thu, 12 Jul 2018 09:10:09 +1200
- To: myrddin-dev@xxxxxxxxxxxxxx
hey neat, closes https://github.com/oridb/mc/issues/104 :) On Thu, Jul 12, 2018 at 2:58 AM, Quentin Carbonneaux <quentin@xxxxxx> wrote: > Hi myrddin-dev, > > This patch adds tuple access expressions. If t is a tuple, its > N-th component can be retrieved with the syntax t.N. Of course, > the components are zero indexed. I believe the code also works > if 't' is a pointer to a tuple (but I have not checked this). > > Feel free to throw the code in a nearby incinerator, it is only > very mildly tested, and was quite hastily hacked in public > transportation. > > Best, > > --- > 6/isel.c | 2 +- > 6/simp.c | 3 +-- > 6/typeinfo.c | 35 ++++++++++++++++++++++--------- > mi/flatten.c | 3 ++- > parse/gram.y | 2 ++ > parse/infer.c | 58 +++++++++++++++++++++++++++++++++++---------------- > parse/ops.def | 1 + > 7 files changed, 72 insertions(+), 32 deletions(-) > > diff --git a/6/isel.c b/6/isel.c > index 7b30b04c..bb111adc 100644 > --- a/6/isel.c > +++ b/6/isel.c > @@ -945,7 +945,7 @@ selexpr(Isel *s, Node *n) > case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb: > case Oslbase: case Osllen: case Ocast: case Outag: case Oudata: > case Otup: case Oarr: case Ostruct: > - case Oslice: case Oidx: case Osize: case Otupget: > + case Oslice: case Oidx: case Osize: case Otupget: case Otupmemb: > case Obreak: case Ocontinue: > case Numops: > dump(n, stdout); > diff --git a/6/simp.c b/6/simp.c > index 457227eb..eb866337 100644 > --- a/6/simp.c > +++ b/6/simp.c > @@ -1137,8 +1137,7 @@ rval(Simp *s, Node *n, Node *dst) > u = idxaddr(s, t, n->expr.args[1]); > r = load(u); > break; > - /* array.len slice.len are magic 'virtual' members. > - * they need to be special cased. */ > + case Otupmemb: > case Omemb: > t = membaddr(s, n); > r = load(t); > diff --git a/6/typeinfo.c b/6/typeinfo.c > index 312aefb8..0a7045b1 100644 > --- a/6/typeinfo.c > +++ b/6/typeinfo.c > @@ -349,7 +349,7 @@ tyalign(Type *ty) > return min(align, Ptrsz); > } > > -/* gets the byte offset of 'memb' within the aggregate type 'aggr' */ > +/* gets the byte offset of 'memb' within the aggregate type 'ty' */ > ssize_t > tyoffset(Type *ty, Node *memb) > { > @@ -360,16 +360,31 @@ tyoffset(Type *ty, Node *memb) > if (ty->type == Typtr) > ty = tybase(ty->sub[0]); > > - assert(ty->type == Tystruct); > - off = 0; > - for (i = 0; i < ty->nmemb; i++) { > - off = alignto(off, decltype(ty->sdecls[i])); > - if (!strcmp(namestr(memb), declname(ty->sdecls[i]))) > - return off; > - off += size(ty->sdecls[i]); > + switch (memb->type) { > + case Nname: > + assert(ty->type == Tystruct); > + off = 0; > + for (i = 0; i < ty->nmemb; i++) { > + off = alignto(off, decltype(ty->sdecls[i])); > + if (!strcmp(namestr(memb), > declname(ty->sdecls[i]))) > + return off; > + off += size(ty->sdecls[i]); > + } > + die("bad offset"); > + return 0; > + case Nlit: > + assert(ty->type == Tytuple); > + assert(memb->lit.intval < ty->nsub); > + off = 0; > + for (i = 0; i < memb->lit.intval; i++) { > + off += tysize(ty->sub[i]); > + off = alignto(off, ty->sub[i+1]); > + } > + return off; > + default: > + die("bad offset node type"); > + return 0; > } > - die("bad offset"); > - return 0; > } > > size_t > diff --git a/mi/flatten.c b/mi/flatten.c > index 5a749962..9d7ab791 100644 > --- a/mi/flatten.c > +++ b/mi/flatten.c > @@ -560,8 +560,9 @@ rval(Flattenctx *s, Node *n) > if (ty->type == Tyslice || ty->type == Tyarray) { > r = seqlen(s, args[0], exprtype(n)); > } else { > + case Otupmemb: > t = rval(s, args[0]); > - r = mkexpr(n->loc, Omemb, t, args[1], NULL); > + r = mkexpr(n->loc, exprop(n), t, args[1], NULL); > r->expr.type = n->expr.type; > } > break; > diff --git a/parse/gram.y b/parse/gram.y > index 146c8422..cf058882 100644 > --- a/parse/gram.y > +++ b/parse/gram.y > @@ -784,6 +784,8 @@ prefixexpr > postfixexpr > : postfixexpr Tdot Tident > {$$ = mkexpr($1->loc, Omemb, $1, mkname($3->loc, $3->id), NULL);} > + | postfixexpr Tdot Tintlit > + {$$ = mkexpr($1->loc, Otupmemb, $1, mkint($3->loc, $3->intval), > NULL);} > | postfixexpr Tinc > {$$ = mkexpr($1->loc, Opostinc, $1, NULL);} > | postfixexpr Tdec > diff --git a/parse/infer.c b/parse/infer.c > index c5cad2f1..69e9f9ba 100644 > --- a/parse/infer.c > +++ b/parse/infer.c > @@ -228,6 +228,9 @@ ctxstr(Node *n) > case Omemb: > bprintf(buf, sizeof buf, "<%s>.%s", t1, > namestr(args[1])); > break; > + case Otupmemb: > + bprintf(buf, sizeof buf, "<%s>.%llu", t1, > args[1]->lit.intval); > + break; > default: > bprintf(buf, sizeof buf, "%s:%s", d, t); > break; > @@ -1764,6 +1767,7 @@ inferexpr(Node **np, Type *ret, int *sawret) > break; > > /* special cases */ > + case Otupmemb: /* @a.N -> @b, verify type(@a.N)==@b later */ > case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later > */ > infersub(n, ret, sawret, &isconst); > settype(n, mktyvar(n->loc)); > @@ -2253,27 +2257,22 @@ infercompn(Node *n, Node ***rem, size_t *nrem, > Stab ***remscope, size_t *nremsco > Type *t; > size_t i; > int found; > + int ismemb; > + uvlong idx; > > aggr = n->expr.args[0]; > memb = n->expr.args[1]; > + ismemb = n->expr.op == Omemb; > > found = 0; > t = tybase(tf(type(aggr))); > /* all array-like types have a fake "len" member that we emulate */ > - if (t->type == Tyslice || t->type == Tyarray) { > + if (ismemb && (t->type == Tyslice || t->type == Tyarray)) { > if (!strcmp(namestr(memb), "len")) { > constrain(n, type(n), traittab[Tcnum]); > constrain(n, type(n), traittab[Tcint]); > found = 1; > } > - /* > - * otherwise, we search aggregate types for the member, and unify > - * the expression with the member type; ie: > - * > - * x: aggrtype y : memb in aggrtype > - * --------------------------------------- > - * x.y : membtype > - */ > } else { > if (tybase(t)->type == Typtr) > t = tybase(tf(t->sub[0])); > @@ -2284,17 +2283,39 @@ infercompn(Node *n, Node ***rem, size_t *nrem, > Stab ***remscope, size_t *nremsco > lappend(rem, nrem, n); > lappend(remscope, nremscope, curstab()); > return; > - } else if (tybase(t)->type != Tystruct) { > - fatal(n, "type %s does not support member > operators near %s", > - tystr(t), ctxstr(n)); > } > - nl = t->sdecls; > - for (i = 0; i < t->nmemb; i++) { > - if (!strcmp(namestr(memb), declname(nl[i]))) { > - unify(n, type(n), decltype(nl[i])); > - found = 1; > - break; > + if (ismemb) { > + /* > + * aggregate types for the member, and unify the > expression with the > + * member type; ie: > + * > + * x: aggrtype y : memb in aggrtype > + * --------------------------------------- > + * x.y : membtype > + */ > + if (tybase(t)->type != Tystruct) > + fatal(n, "type %s does not support member > operators near %s", > + tystr(t), ctxstr(n)); > + nl = t->sdecls; > + for (i = 0; i < t->nmemb; i++) { > + if (!strcmp(namestr(memb), > declname(nl[i]))) { > + unify(n, type(n), decltype(nl[i])); > + found = 1; > + break; > + } > } > + } else { > + /* tuple access; similar to the logic for member > accesses */ > + if (tybase(t)->type != Tytuple) > + fatal(n, "type %s does not support tuple > access operators near %s", > + tystr(t), ctxstr(n)); > + assert(memb->type == Nlit); > + idx = memb->lit.intval; > + if (idx >= t->nsub) > + fatal(n, "cannot access element %llu of a > tuple of type %s near %s", > + idx, tystr(t), ctxstr(n)); > + unify(n, type(n), t->sub[idx]); > + found = 1; > } > } > if (!found) > @@ -2414,6 +2435,7 @@ postcheckpass(Node ***rem, size_t *nrem, Stab > ***remscope, size_t *nremscope) > pushstab(postcheckscope[i]); > if (n->type == Nexpr) { > switch (exprop(n)) { > + case Otupmemb: > case Omemb: infercompn(n, rem, nrem, remscope, > nremscope); break; > case Ocast: checkcast(n, rem, nrem, remscope, > nremscope); break; > case Ostruct: checkstruct(n, rem, nrem, > remscope, nremscope); break; > diff --git a/parse/ops.def b/parse/ops.def > index 909736ec..e2f0b508 100644 > --- a/parse/ops.def > +++ b/parse/ops.def > @@ -42,6 +42,7 @@ O(Obsreq, 1, OTbin, ">>=") > O(Oidx, 1, OTmisc, NULL) > O(Oslice, 1, OTmisc, NULL) > O(Omemb, 1, OTmisc, NULL) > +O(Otupmemb, 1, OTmisc, NULL) > O(Osize, 1, OTmisc, NULL) > O(Ocall, 0, OTmisc, NULL) > O(Ocast, 1, OTmisc, NULL) > -- > 2.18.0 > > >
[PATCH] Support direct tuple access operators "tuple.N" | Quentin Carbonneaux <quentin@xxxxxx> |
- Prev by Date: [PATCH] Support direct tuple access operators "tuple.N"
- Next by Date: [PATCH] Fix typo in generic sleq implementation
- Previous by thread: [PATCH] Support direct tuple access operators "tuple.N"
- Next by thread: Re: [PATCH] Support direct tuple access operators "tuple.N"
- Index(es):