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):