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