[PATCH] Support direct tuple access operators "tuple.N"
[Thread Prev] | [Thread Next]
- Subject: [PATCH] Support direct tuple access operators "tuple.N"
- From: Quentin Carbonneaux <quentin@xxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Wed, 11 Jul 2018 14:58:56 +0000
- To: myrddin-dev@xxxxxxxxxxxxxx
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
Re: [PATCH] Support direct tuple access operators "tuple.N" | Andrew Chambers <andrewchamberss@xxxxxxxxx> |
Re: [PATCH] Support direct tuple access operators "tuple.N" | Ori Bernstein <ori@xxxxxxxxxxxxxx> |
- Prev by Date: Re: [PATCH] Typo fix in libregex.
- Next by Date: Re: [PATCH] Support direct tuple access operators "tuple.N"
- Previous by thread: Re: [PATCH] Typo fix in libregex.
- Next by thread: Re: [PATCH] Support direct tuple access operators "tuple.N"
- Index(es):