Skip to content

Instantly share code, notes, and snippets.

@moriyoshi
Created November 30, 2014 07:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moriyoshi/c0e2b2f9be6883e33251 to your computer and use it in GitHub Desktop.
Save moriyoshi/c0e2b2f9be6883e33251 to your computer and use it in GitHub Desktop.
indexoperatoroverload.patch.diff
diff -r ffe33f1f1f17 src/cmd/gc/esc.c
--- a/src/cmd/gc/esc.c Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/esc.c Sun Nov 30 15:58:50 2014 +0900
@@ -756,6 +756,12 @@
escassign(e, &e->theSink, dst->right);
dst = &e->theSink;
break;
+ case OINDEXINTER:
+ // lose track of key and value
+ esc(e, dst->left, dst);
+ esc(e, dst->right, dst);
+ dst = &e->theSink;
+ break;
}
lno = setlineno(src);
@@ -1223,6 +1229,7 @@
// fall through
case ODOTPTR:
case OINDEXMAP:
+ case OINDEXINTER:
case OIND:
newlevel = level;
if(level > MinLevel)
diff -r ffe33f1f1f17 src/cmd/gc/go.h
--- a/src/cmd/gc/go.h Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/go.h Sun Nov 30 15:58:50 2014 +0900
@@ -505,6 +505,7 @@
OIND, // *p
OINDEX, // a[i]
OINDEXMAP, // m[s]
+ OINDEXINTER, // m[s] where m is an opaque receiver
OKEY, // The x:3 in t{x:3, y:4}, the 1:2 in a[1:2], the 2:20 in [3]int{2:20}, etc.
OPARAM, // The on-stack copy of a parameter or return value that escapes.
OLEN, // len
diff -r ffe33f1f1f17 src/cmd/gc/order.c
--- a/src/cmd/gc/order.c Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/order.c Sun Nov 30 15:58:50 2014 +0900
@@ -169,6 +169,7 @@
case OINDEX:
case OINDEXMAP:
+ case OINDEXINTER:
if(isfixedarray(n->left->type))
l = ordersafeexpr(n->left, order);
else
@@ -455,7 +456,7 @@
case OAS:
order->out = list(order->out, n);
// We call writebarrierfat only for values > 4 pointers long. See walk.c.
- if((n->left->op == OINDEXMAP || (needwritebarrier(n->left, n->right) && n->left->type->width > 4*widthptr)) && !isaddrokay(n->right)) {
+ if(n->left->op != OINDEXINTER && (n->left->op == OINDEXMAP || (needwritebarrier(n->left, n->right) && n->left->type->width > 4*widthptr)) && !isaddrokay(n->right)) {
m = n->left;
n->left = ordertemp(m->type, order, 0);
a = nod(OAS, m, n->left);
diff -r ffe33f1f1f17 src/cmd/gc/subr.c
--- a/src/cmd/gc/subr.c Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/subr.c Sun Nov 30 15:58:50 2014 +0900
@@ -2051,6 +2051,7 @@
case OINDEX:
case OINDEXMAP:
+ case OINDEXINTER:
l = safeexpr(n->left, init);
r = safeexpr(n->right, init);
if(l == n->left && r == n->right)
diff -r ffe33f1f1f17 src/cmd/gc/typecheck.c
--- a/src/cmd/gc/typecheck.c Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/typecheck.c Sun Nov 30 15:58:50 2014 +0900
@@ -916,6 +916,14 @@
n->type = t->type;
n->op = OINDEXMAP;
break;
+
+ case TPTR32:
+ case TPTR64:
+ case TSTRUCT:
+ case TINTER:
+ n->etype = 0;
+ n->op = OINDEXINTER;
+ break;
}
goto ret;
@@ -2798,7 +2806,7 @@
{
if(islvalue(n))
return;
- if(n->op == OINDEXMAP) {
+ if(n->op == OINDEXMAP || n->op == OINDEXINTER) {
n->etype = 1;
return;
}
@@ -2885,7 +2893,7 @@
// Recognize slices being updated in place, for better code generation later.
// Don't rewrite if using race detector, to avoid needing to teach race detector
// about this optimization.
- if(n->left && n->left->op != OINDEXMAP && n->right && !flag_race) {
+ if(n->left && n->left->op != OINDEXMAP && n->left->op != OINDEXINTER && n->right && !flag_race) {
switch(n->right->op) {
case OSLICE:
case OSLICE3:
@@ -2958,13 +2966,18 @@
r = n->rlist->n;
// m[i] = x, ok
- if(cl == 1 && cr == 2 && l->op == OINDEXMAP) {
+ if(cl == 1 && cr == 2 && (l->op == OINDEXMAP || l->op == OINDEXINTER)) {
if(l->type == T)
goto out;
yyerror("assignment count mismatch: %d = %d (use delete)", cl, cr);
goto out;
}
+ if(cl == 2 && cr == 1 && r->op == OINDEXINTER) {
+ // We need to assert this later
+ goto out;
+ }
+
// x,y,z = f()
if(cr == 1) {
if(r->type == T)
@@ -3420,7 +3433,7 @@
defaultlit(&n, types[TINT]);
return 0;
default:
- break;
+ break;
}
}
diff -r ffe33f1f1f17 src/cmd/gc/walk.c
--- a/src/cmd/gc/walk.c Tue Nov 25 15:41:33 2014 +1100
+++ b/src/cmd/gc/walk.c Sun Nov 30 15:58:50 2014 +0900
@@ -362,6 +362,53 @@
}
}
+
+static
+void
+walkindexinter(Node **np, int as2, NodeList **init)
+{
+ Node *nn, *nr;
+ nr = nod(ONAME, N, N);
+ nr->sym = lookup("__getindex");
+ nn = nod(OCALL, nod(ODOT, (*np)->left, N), N);
+ nn->left->right = nr;
+ nn->list = list1((*np)->right);
+ if(!as2) {
+ Node *ntr, *nt1, *nt2, *nif, *nas;
+ Type *t, *t2;
+ Iter s;
+ NodeList *l;
+ typecheck(&nn, Etop);
+ if(nn->type->etype != TSTRUCT || nn->type->funarg == 0 || structcount(nn->type) != 2) {
+ yyerror("assignment count mismatch");
+ return;
+ }
+ t = structfirst(&s, &nn->type);
+ t2 = structnext(&s);
+ if(t2->type->etype != TBOOL) {
+ yyerror("function does not return a boolean value as the second value (%T)", t2);
+ return;
+ }
+ ntr = temp(t->type);
+ nt1 = temp(t->type);
+ nt2 = temp(types[TBOOL]);
+ nas = nod(OAS2, N, N);
+ nas->list = list(list1(nt1), nt2);
+ nas->rlist = list1(nn);
+ nif = nod(OIF, N, N);
+ nif->ntest = nt2;
+ nif->ninit = list1(nas);
+ nif->nbody = list1(nod(OAS, ntr, nt1));
+ nif->nelse = list1(nod(OAS, ntr, N));
+ l = list1(nif);
+ typechecklist(l, Etop);
+ walkstmtlist(l);
+ *init = concat(*init, l);
+ nn = ntr;
+ }
+ *np = nn;
+}
+
void
walkexpr(Node **np, NodeList **init)
{
@@ -607,6 +654,19 @@
*init = concat(*init, n->ninit);
n->ninit = nil;
+ if(n->left->op == OINDEXINTER) {
+ Node *nn, *nr;
+ nr = nod(ONAME, N, N);
+ nr->sym = lookup("__setindex");
+ nn = nod(OCALL, nod(ODOT, n->left->left, N), N);
+ nn->left->right = nr;
+ nn->list = list(list1(n->left->right), n->right);
+ typecheck(&nn, Etop);
+ walkexpr(&nn, init);
+ n = nn;
+ goto ret;
+ }
+
walkexpr(&n->left, init);
n->left = safeexpr(n->left, init);
@@ -644,14 +704,23 @@
case OAS2:
*init = concat(*init, n->ninit);
n->ninit = nil;
- walkexprlistsafe(n->list, init);
- walkexprlistsafe(n->rlist, init);
- ll = ascompatee(OAS, n->list, n->rlist, init);
- ll = reorder3(ll);
- for(lr = ll; lr != nil; lr = lr->next)
- lr->n = applywritebarrier(lr->n, init);
- n = liststmt(ll);
- goto ret;
+ if(n->rlist->n->op == OINDEXINTER) {
+ walkindexinter(&n->rlist->n, 1, init);
+ n->typecheck = 0;
+ typecheck(&n, Etop);
+ if(n->op != OAS2FUNC)
+ goto ret;
+ // fall-through
+ } else {
+ walkexprlistsafe(n->list, init);
+ walkexprlistsafe(n->rlist, init);
+ ll = ascompatee(OAS, n->list, n->rlist, init);
+ ll = reorder3(ll);
+ for(lr = ll; lr != nil; lr = lr->next)
+ lr->n = applywritebarrier(lr->n, init);
+ n = liststmt(ll);
+ goto ret;
+ }
case OAS2FUNC:
// a,b,... = fn()
@@ -1124,6 +1193,14 @@
zerosize = t->type->width;
goto ret;
+ case OINDEXINTER:
+ if(n->etype == 1)
+ goto ret;
+ walkindexinter(&n, 0, init);
+ typecheck(&n, Erv);
+ walkexpr(&n, init);
+ goto ret;
+
case ORECV:
fatal("walkexpr ORECV"); // should see inside OAS only
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment