2008-06-04 15:37:38 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "go.h"
|
|
|
|
|
|
|
|
static Type* sw1(Node*, Type*);
|
|
|
|
static Type* sw2(Node*, Type*);
|
|
|
|
static Type* sw3(Node*, Type*);
|
|
|
|
static Node* curfn;
|
2008-09-02 17:21:30 -06:00
|
|
|
static Node* addtop;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
Inone,
|
|
|
|
I2T,
|
2008-11-05 15:27:07 -07:00
|
|
|
I2T2,
|
2008-09-22 13:16:19 -06:00
|
|
|
I2I,
|
2008-11-05 15:27:07 -07:00
|
|
|
I2I2,
|
|
|
|
T2I,
|
2008-09-22 13:16:19 -06:00
|
|
|
};
|
|
|
|
|
2008-09-11 16:23:01 -06:00
|
|
|
// can this code branch reach the end
|
|
|
|
// without an undcontitional RETURN
|
|
|
|
// this is hard, so it is conservative
|
|
|
|
int
|
|
|
|
walkret(Node *n)
|
|
|
|
{
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if(n != N)
|
|
|
|
switch(n->op) {
|
|
|
|
case OLIST:
|
|
|
|
if(n->right == N) {
|
|
|
|
n = n->left;
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
n = n->right;
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
// at this point, we have the last
|
|
|
|
// statement of the function
|
|
|
|
|
|
|
|
case OGOTO:
|
|
|
|
case OPANIC:
|
|
|
|
case ORETURN:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all other statements
|
|
|
|
// will flow to the end
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
void
|
|
|
|
walk(Node *fn)
|
|
|
|
{
|
2008-09-09 16:47:31 -06:00
|
|
|
char s[50];
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
curfn = fn;
|
2008-09-09 16:47:31 -06:00
|
|
|
if(debug['W']) {
|
|
|
|
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
|
2008-09-11 16:23:01 -06:00
|
|
|
dump(s, curfn->nbody);
|
2008-09-09 16:47:31 -06:00
|
|
|
}
|
2008-09-11 16:23:01 -06:00
|
|
|
if(curfn->type->outtuple)
|
|
|
|
if(walkret(curfn->nbody))
|
2008-09-11 16:44:45 -06:00
|
|
|
yyerror("function ends without a return statement");
|
2008-09-11 16:23:01 -06:00
|
|
|
walkstate(curfn->nbody);
|
2008-09-09 16:47:31 -06:00
|
|
|
if(debug['W']) {
|
|
|
|
snprint(s, sizeof(s), "after %S", curfn->nname->sym);
|
2008-09-11 16:23:01 -06:00
|
|
|
dump(s, curfn->nbody);
|
2008-09-09 16:47:31 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
addtotop(Node *n)
|
|
|
|
{
|
|
|
|
Node *l;
|
|
|
|
|
|
|
|
while(addtop != N) {
|
|
|
|
l = addtop;
|
|
|
|
addtop = N;
|
|
|
|
walktype(l, Etop);
|
|
|
|
n->ninit = list(n->ninit, l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-14 18:29:50 -06:00
|
|
|
gettype(Node *n, Node *a)
|
2008-09-09 16:47:31 -06:00
|
|
|
{
|
|
|
|
if(debug['W'])
|
|
|
|
dump("\nbefore gettype", n);
|
|
|
|
walktype(n, Erv);
|
2008-09-14 18:29:50 -06:00
|
|
|
if(a == N && addtop != N)
|
|
|
|
fatal("gettype: addtop");
|
|
|
|
addtotop(a);
|
2008-06-17 23:33:32 -06:00
|
|
|
if(debug['W'])
|
2008-09-09 16:47:31 -06:00
|
|
|
dump("after gettype", n);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(Node *n)
|
|
|
|
{
|
2008-09-09 16:47:31 -06:00
|
|
|
Node *more;
|
2008-09-04 13:21:10 -06:00
|
|
|
|
|
|
|
loop:
|
|
|
|
if(n == N)
|
|
|
|
return;
|
|
|
|
|
|
|
|
more = N;
|
|
|
|
switch(n->op) {
|
|
|
|
|
|
|
|
case OLIST:
|
|
|
|
walkstate(n->left);
|
|
|
|
more = n->right;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
yyerror("walkstate: %O not a top level statement", n->op);
|
|
|
|
|
|
|
|
case OASOP:
|
|
|
|
case OAS:
|
|
|
|
case OCALLMETH:
|
|
|
|
case OCALLINTER:
|
|
|
|
case OCALL:
|
|
|
|
case OSEND:
|
|
|
|
case ORECV:
|
|
|
|
case OPRINT:
|
2008-10-02 15:38:07 -06:00
|
|
|
case OPRINTN:
|
2008-09-04 13:21:10 -06:00
|
|
|
case OPANIC:
|
2008-10-02 15:38:07 -06:00
|
|
|
case OPANICN:
|
2008-09-04 13:21:10 -06:00
|
|
|
case OFOR:
|
|
|
|
case OIF:
|
|
|
|
case OSWITCH:
|
|
|
|
case OSELECT:
|
|
|
|
case OEMPTY:
|
|
|
|
case OBREAK:
|
|
|
|
case OCONTINUE:
|
|
|
|
case OGOTO:
|
|
|
|
case OLABEL:
|
|
|
|
case OFALL:
|
|
|
|
case OXCASE:
|
|
|
|
case OCASE:
|
|
|
|
case OXFALL:
|
|
|
|
case ORETURN:
|
|
|
|
case OPROC:
|
|
|
|
walktype(n, Etop);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-09-09 16:47:31 -06:00
|
|
|
addtotop(n);
|
2008-09-04 13:21:10 -06:00
|
|
|
|
|
|
|
if(more != N) {
|
|
|
|
n = more;
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-04 18:15:15 -06:00
|
|
|
void
|
|
|
|
indir(Node *nl, Node *nr)
|
|
|
|
{
|
|
|
|
if(nr != N)
|
|
|
|
*nl = *nr;
|
|
|
|
}
|
|
|
|
|
2008-09-04 13:21:10 -06:00
|
|
|
void
|
|
|
|
walktype(Node *n, int top)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
Node *r, *l;
|
|
|
|
Type *t;
|
|
|
|
Sym *s;
|
2008-06-22 22:02:06 -06:00
|
|
|
int et, cl, cr;
|
2008-08-03 18:25:15 -06:00
|
|
|
int32 lno;
|
2008-06-28 18:27:39 -06:00
|
|
|
|
2008-10-29 21:25:34 -06:00
|
|
|
if(n == N)
|
|
|
|
return;
|
2008-06-28 18:27:39 -06:00
|
|
|
lno = setlineno(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* walk the whole tree of the body of a function.
|
|
|
|
* the types expressions are calculated.
|
|
|
|
* compile-time constants are evaluated.
|
|
|
|
*/
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if(n == N)
|
|
|
|
goto ret;
|
2008-06-28 18:27:39 -06:00
|
|
|
|
2008-06-26 18:54:44 -06:00
|
|
|
setlineno(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-17 19:07:40 -06:00
|
|
|
if(debug['w'] > 1 && top == Etop && n->op != OLIST)
|
|
|
|
dump("walk-before", n);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
t = T;
|
|
|
|
et = Txxx;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
fatal("walktype: switch 1 unknown op %N", n);
|
|
|
|
goto ret;
|
|
|
|
|
2008-09-02 17:21:30 -06:00
|
|
|
case OLIST:
|
2008-09-03 15:40:22 -06:00
|
|
|
case OKEY:
|
2008-09-02 17:21:30 -06:00
|
|
|
walktype(n->left, top);
|
|
|
|
n = n->right;
|
|
|
|
goto loop;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OPRINT:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-10-02 15:38:07 -06:00
|
|
|
indir(n, prcompat(n->left, 0));
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OPRINTN:
|
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
|
|
|
indir(n, prcompat(n->left, 1));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OPANIC:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-10-02 15:38:07 -06:00
|
|
|
indir(n, list(prcompat(n->left, 0), nodpanic(n->lineno)));
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OPANICN:
|
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
|
|
|
indir(n, list(prcompat(n->left, 1), nodpanic(n->lineno)));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OLITERAL:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
n->addable = 1;
|
|
|
|
goto ret;
|
|
|
|
|
2008-06-21 16:11:29 -06:00
|
|
|
case ONONAME:
|
|
|
|
s = n->sym;
|
|
|
|
if(s->undef == 0) {
|
|
|
|
s->undef = 1;
|
|
|
|
yyerror("%S: undefined", s);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
|
|
|
goto ret;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case ONAME:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
n->addable = 1;
|
|
|
|
if(n->type == T) {
|
|
|
|
s = n->sym;
|
|
|
|
if(s->undef == 0) {
|
2008-10-06 17:44:17 -06:00
|
|
|
yyerror("walktype: %S undeclared", s);
|
2008-06-04 15:37:38 -06:00
|
|
|
s->undef = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OFOR:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto nottop;
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->ninit);
|
2008-07-05 13:49:25 -06:00
|
|
|
walkbool(n->ntest);
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->nincr);
|
|
|
|
walkstate(n->nbody);
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
case OSWITCH:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto nottop;
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
if(!casebody(n->nbody))
|
|
|
|
yyerror("switch statement must have case labels");
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->ntest == N)
|
|
|
|
n->ntest = booltrue;
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->ninit);
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->ntest, Erv);
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->nbody);
|
2008-06-18 12:43:50 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
// find common type
|
|
|
|
if(n->ntest->type == T)
|
2008-06-15 21:24:30 -06:00
|
|
|
n->ntest->type = walkswitch(n, sw1);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
// if that fails pick a type
|
|
|
|
if(n->ntest->type == T)
|
2008-06-15 21:24:30 -06:00
|
|
|
n->ntest->type = walkswitch(n, sw2);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
// set the type on all literals
|
|
|
|
if(n->ntest->type != T)
|
2008-06-15 21:24:30 -06:00
|
|
|
walkswitch(n, sw3);
|
2008-06-18 12:43:50 -06:00
|
|
|
walktype(n->ntest, Erv); // BOTCH is this right
|
|
|
|
walktype(n->nincr, Erv);
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
case OSELECT:
|
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
|
|
|
|
walkselect(n);
|
|
|
|
goto ret;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OIF:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto nottop;
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->ninit);
|
2008-07-05 13:49:25 -06:00
|
|
|
walkbool(n->ntest);
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->nbody);
|
2008-09-09 16:47:31 -06:00
|
|
|
walkstate(n->nelse);
|
2008-09-04 13:21:10 -06:00
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-07-07 13:29:26 -06:00
|
|
|
case OPROC:
|
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->left);
|
2008-07-07 13:29:26 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OCALLMETH:
|
|
|
|
case OCALLINTER:
|
|
|
|
case OCALL:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Elv)
|
|
|
|
goto nottop;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->type != T)
|
|
|
|
goto ret;
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N)
|
|
|
|
goto ret;
|
|
|
|
t = n->left->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
if(n->left->op == ODOTMETH)
|
|
|
|
n->op = OCALLMETH;
|
|
|
|
if(n->left->op == ODOTINTER)
|
|
|
|
n->op = OCALLINTER;
|
|
|
|
|
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
|
|
|
|
if(t->etype != TFUNC) {
|
|
|
|
yyerror("call of a non-function %T", t);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2008-10-06 17:44:17 -06:00
|
|
|
dowidth(t);
|
2008-06-04 15:37:38 -06:00
|
|
|
n->type = *getoutarg(t);
|
2008-09-20 15:59:15 -06:00
|
|
|
switch(t->outtuple) {
|
|
|
|
case 0:
|
|
|
|
if(top == Erv) {
|
|
|
|
yyerror("function requires a return type");
|
2008-10-29 13:46:44 -06:00
|
|
|
n->type = types[TINT];
|
2008-09-20 15:59:15 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2008-06-04 15:37:38 -06:00
|
|
|
n->type = n->type->type->type;
|
2008-09-20 15:59:15 -06:00
|
|
|
break;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->right, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
fatal("walk: op: %O", n->op);
|
|
|
|
|
|
|
|
case OCALLINTER:
|
|
|
|
l = ascompatte(n->op, getinarg(t), &n->right, 0);
|
2008-06-10 22:29:57 -06:00
|
|
|
n->right = reorder1(l);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALL:
|
|
|
|
l = ascompatte(n->op, getinarg(t), &n->right, 0);
|
2008-06-10 22:29:57 -06:00
|
|
|
n->right = reorder1(l);
|
2008-07-25 18:03:27 -06:00
|
|
|
if(isselect(n)) {
|
|
|
|
// clear output bool - special prob with selectsend
|
|
|
|
r = ascompatte(n->op, getoutarg(t), &boolfalse, 0);
|
|
|
|
n->right = list(n->right, r);
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OCALLMETH:
|
|
|
|
l = ascompatte(n->op, getinarg(t), &n->right, 0);
|
|
|
|
r = ascompatte(n->op, getthis(t), &n->left->left, 0);
|
2008-07-25 18:03:27 -06:00
|
|
|
l = list(r, l);
|
2008-06-24 11:30:33 -06:00
|
|
|
n->left->left = N;
|
|
|
|
ullmancalc(n->left);
|
2008-07-25 18:03:27 -06:00
|
|
|
n->right = reorder1(l);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OAS:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto nottop;
|
|
|
|
|
2008-09-09 16:47:31 -06:00
|
|
|
addtop = list(addtop, n->ninit);
|
|
|
|
n->ninit = N;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
l = n->left;
|
2008-06-15 21:24:30 -06:00
|
|
|
r = n->right;
|
|
|
|
walktype(l, Elv);
|
2008-06-22 22:02:06 -06:00
|
|
|
if(l == N || r == N)
|
2008-06-15 21:24:30 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-06-22 22:02:06 -06:00
|
|
|
cl = listcount(l);
|
|
|
|
cr = listcount(r);
|
|
|
|
|
|
|
|
if(cl == cr) {
|
|
|
|
walktype(r, Erv);
|
|
|
|
l = ascompatee(n->op, &n->left, &n->right);
|
|
|
|
if(l != N)
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, reorder3(l));
|
2008-06-22 22:02:06 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(r->op) {
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2008-06-22 22:02:06 -06:00
|
|
|
case OCALLMETH:
|
|
|
|
case OCALLINTER:
|
|
|
|
case OCALL:
|
2008-06-24 15:11:20 -06:00
|
|
|
if(cr == 1) {
|
|
|
|
// a,b,... = fn()
|
|
|
|
walktype(r, Erv);
|
|
|
|
l = ascompatet(n->op, &n->left, &r->type, 0);
|
2008-09-04 18:15:15 -06:00
|
|
|
if(l != N)
|
|
|
|
indir(n, list(r, reorder2(l)));
|
2008-06-24 15:11:20 -06:00
|
|
|
goto ret;
|
2008-06-10 22:29:57 -06:00
|
|
|
}
|
2008-06-22 22:02:06 -06:00
|
|
|
break;
|
2008-06-17 19:07:40 -06:00
|
|
|
|
2008-06-22 22:02:06 -06:00
|
|
|
case OINDEX:
|
|
|
|
case OINDEXPTR:
|
2008-06-24 15:11:20 -06:00
|
|
|
if(cl == 2 && cr == 1) {
|
|
|
|
// a,b = map[] - mapaccess2
|
2008-09-11 20:09:25 -06:00
|
|
|
walktype(r->left, Erv);
|
2008-06-24 15:11:20 -06:00
|
|
|
if(!isptrto(r->left->type, TMAP))
|
|
|
|
break;
|
|
|
|
l = mapop(n, top);
|
|
|
|
if(l == N)
|
|
|
|
break;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, l);
|
2008-06-24 15:11:20 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
break;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
|
|
|
case ORECV:
|
|
|
|
if(cl == 2 && cr == 1) {
|
|
|
|
// a,b = <chan - chanrecv2
|
2008-07-15 22:07:59 -06:00
|
|
|
walktype(r->left, Erv);
|
2008-07-13 15:29:46 -06:00
|
|
|
if(!isptrto(r->left->type, TCHAN))
|
|
|
|
break;
|
|
|
|
l = chanop(n, top);
|
|
|
|
if(l == N)
|
|
|
|
break;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, l);
|
2008-07-13 15:29:46 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
break;
|
2008-11-05 15:27:07 -07:00
|
|
|
|
|
|
|
case OCONV:
|
|
|
|
if(cl == 2 && cr == 1) {
|
|
|
|
// a,b = i.(T)
|
|
|
|
if(r->left == N)
|
|
|
|
break;
|
|
|
|
et = isandss(r->type, r->left);
|
|
|
|
switch(et) {
|
|
|
|
case I2T:
|
|
|
|
et = I2T2;
|
|
|
|
break;
|
|
|
|
case I2I:
|
|
|
|
et = I2I2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
et = Inone;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(et == Inone)
|
|
|
|
break;
|
|
|
|
r = ifaceop(r->type, r->left, et);
|
|
|
|
l = ascompatet(n->op, &n->left, &r->type, 0);
|
|
|
|
if(l != N)
|
|
|
|
indir(n, list(r, reorder2(l)));
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
break;
|
2008-06-24 15:11:20 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(l->op) {
|
|
|
|
case OINDEX:
|
|
|
|
case OINDEXPTR:
|
|
|
|
if(cl == 1 && cr == 2) {
|
|
|
|
// map[] = a,b - mapassign2
|
|
|
|
if(!isptrto(l->left->type, TMAP))
|
|
|
|
break;
|
|
|
|
l = mapop(n, top);
|
|
|
|
if(l == N)
|
|
|
|
break;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, l);
|
2008-06-24 15:11:20 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
2008-06-22 22:02:06 -06:00
|
|
|
break;
|
|
|
|
}
|
2008-06-24 15:11:20 -06:00
|
|
|
|
|
|
|
yyerror("bad shape across assignment - cr=%d cl=%d\n", cr, cl);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OBREAK:
|
|
|
|
case OCONTINUE:
|
|
|
|
case OGOTO:
|
|
|
|
case OLABEL:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OXCASE:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
yyerror("case statement out of place");
|
|
|
|
n->op = OCASE;
|
|
|
|
|
|
|
|
case OCASE:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(n->right);
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
case OXFALL:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
yyerror("fallthrough statement out of place");
|
|
|
|
n->op = OFALL;
|
|
|
|
|
|
|
|
case OFALL:
|
|
|
|
case OINDREG:
|
2008-09-29 21:33:51 -06:00
|
|
|
case OEMPTY:
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OCONV:
|
2008-09-03 15:40:22 -06:00
|
|
|
if(top == Etop)
|
2008-06-15 21:24:30 -06:00
|
|
|
goto nottop;
|
2008-08-12 20:13:09 -06:00
|
|
|
|
|
|
|
l = n->left;
|
|
|
|
if(l == N)
|
|
|
|
goto ret;
|
2008-10-16 16:59:31 -06:00
|
|
|
|
2008-09-29 21:33:51 -06:00
|
|
|
walktype(l, Erv);
|
|
|
|
|
2008-08-12 20:13:09 -06:00
|
|
|
t = n->type;
|
|
|
|
if(t == T)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-10-16 16:59:31 -06:00
|
|
|
if(!iscomposite(t))
|
|
|
|
convlit(l, t);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
// nil conversion
|
2008-08-12 20:13:09 -06:00
|
|
|
if(eqtype(t, l->type, 0)) {
|
|
|
|
if(l->op != ONAME)
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, l);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// simple fix-float
|
2008-08-12 20:13:09 -06:00
|
|
|
if(l->type != T)
|
|
|
|
if(isint[l->type->etype] || isfloat[l->type->etype])
|
|
|
|
if(isint[t->etype] || isfloat[t->etype]) {
|
2008-06-04 15:37:38 -06:00
|
|
|
evconst(n);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// to string
|
2008-09-02 20:11:25 -06:00
|
|
|
if(l->type != T)
|
2008-08-12 20:13:09 -06:00
|
|
|
if(isptrto(t, TSTRING)) {
|
|
|
|
if(isint[l->type->etype]) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, stringop(n, top));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
2008-09-02 17:21:30 -06:00
|
|
|
if(bytearraysz(l->type) != -2) {
|
2008-06-04 15:37:38 -06:00
|
|
|
n->op = OARRAY;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, stringop(n, top));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
// convert dynamic to static generated by ONEW
|
2008-08-28 16:17:37 -06:00
|
|
|
if(isptrarray(t) && isptrdarray(l->type))
|
2008-08-12 20:13:09 -06:00
|
|
|
goto ret;
|
2008-08-27 18:28:30 -06:00
|
|
|
|
2008-09-02 17:21:30 -06:00
|
|
|
// interface and structure
|
2008-09-22 13:16:19 -06:00
|
|
|
et = isandss(n->type, l);
|
|
|
|
if(et != Inone) {
|
|
|
|
indir(n, ifaceop(n->type, l, et));
|
2008-06-08 13:48:37 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
2008-09-02 17:21:30 -06:00
|
|
|
|
|
|
|
// structure literal
|
|
|
|
if(t->etype == TSTRUCT) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, structlit(n));
|
2008-09-02 17:21:30 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2008-09-20 20:56:40 -06:00
|
|
|
// array literal
|
2008-09-03 15:09:29 -06:00
|
|
|
if(t->etype == TARRAY) {
|
|
|
|
r = arraylit(n);
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, r);
|
2008-09-03 15:09:29 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2008-09-03 15:40:22 -06:00
|
|
|
// map literal
|
|
|
|
if(t->etype == TMAP) {
|
|
|
|
r = maplit(n);
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, r);
|
2008-09-03 15:40:22 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2008-10-16 16:59:31 -06:00
|
|
|
if(l->type != T)
|
|
|
|
yyerror("cannot convert %T to %T", l->type, t);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ORETURN:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-07-05 13:49:25 -06:00
|
|
|
if(curfn->type->outnamed && n->left == N) {
|
|
|
|
// print("special return\n");
|
|
|
|
goto ret;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1);
|
|
|
|
if(l != N)
|
2008-06-10 22:29:57 -06:00
|
|
|
n->left = reorder4(l);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ONOT:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N || n->left->type == T)
|
|
|
|
goto ret;
|
|
|
|
et = n->left->type->etype;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OASOP:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
goto nottop;
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->left, Elv);
|
2008-08-10 17:49:01 -06:00
|
|
|
l = n->left;
|
2008-08-28 20:59:42 -06:00
|
|
|
if(l->op != OINDEX) {
|
|
|
|
if(n->etype == OLSH || n->etype == ORSH)
|
|
|
|
goto shft;
|
2008-08-10 17:49:01 -06:00
|
|
|
goto com;
|
2008-08-28 20:59:42 -06:00
|
|
|
}
|
2008-08-10 17:49:01 -06:00
|
|
|
if(!isptrto(l->left->type, TMAP))
|
|
|
|
goto com;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, mapop(n, top));
|
2008-09-04 13:21:10 -06:00
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
2008-08-28 20:59:42 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
|
|
|
|
|
|
|
shft:
|
|
|
|
walktype(n->right, Erv);
|
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
goto ret;
|
|
|
|
evconst(n);
|
|
|
|
if(n->op == OLITERAL)
|
|
|
|
goto ret;
|
2008-10-29 21:25:34 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
convlit(n->left, types[TINT]);
|
|
|
|
if(n->right->type == T)
|
|
|
|
convlit(n->right, types[TUINT]);
|
2008-08-28 20:59:42 -06:00
|
|
|
if(n->left->type == T || n->right->type == T)
|
|
|
|
goto ret;
|
|
|
|
if(issigned[n->right->type->etype])
|
|
|
|
goto badt;
|
|
|
|
break;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OMOD:
|
|
|
|
case OAND:
|
|
|
|
case OOR:
|
|
|
|
case OXOR:
|
|
|
|
case OANDAND:
|
|
|
|
case OOROR:
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OLT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
case OGT:
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
case ODIV:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
|
|
|
|
|
|
|
com:
|
|
|
|
walktype(n->right, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
goto ret;
|
|
|
|
evconst(n);
|
|
|
|
if(n->op == OLITERAL)
|
|
|
|
goto ret;
|
2008-07-05 18:43:25 -06:00
|
|
|
convlit(n->left, n->right->type);
|
|
|
|
convlit(n->right, n->left->type);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left->type == T || n->right->type == T)
|
|
|
|
goto ret;
|
2008-10-14 16:08:23 -06:00
|
|
|
if(!eqtype(n->left->type, n->right->type, 0))
|
2008-06-04 15:37:38 -06:00
|
|
|
goto badt;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OLT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
case OGT:
|
|
|
|
case OADD:
|
|
|
|
case OASOP:
|
|
|
|
if(isptrto(n->left->type, TSTRING)) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, stringop(n, top));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMINUS:
|
|
|
|
case OPLUS:
|
|
|
|
case OCOM:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N)
|
|
|
|
goto ret;
|
|
|
|
evconst(n);
|
|
|
|
if(n->op == OLITERAL)
|
|
|
|
goto ret;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLEN:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
evconst(n);
|
|
|
|
t = n->left->type;
|
|
|
|
if(t != T && isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
switch(t->etype) {
|
|
|
|
default:
|
|
|
|
goto badt;
|
|
|
|
case TSTRING:
|
2008-06-24 15:11:20 -06:00
|
|
|
case TMAP:
|
2008-07-18 12:59:35 -06:00
|
|
|
break;
|
|
|
|
case TARRAY:
|
2008-08-28 16:17:37 -06:00
|
|
|
if(t->bound >= 0)
|
2008-10-29 13:46:44 -06:00
|
|
|
nodconst(n, types[TINT], t->bound);
|
2008-06-24 15:11:20 -06:00
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-29 13:46:44 -06:00
|
|
|
n->type = types[TINT];
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
case OCAP:
|
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
walktype(n->left, Erv);
|
|
|
|
evconst(n);
|
|
|
|
t = n->left->type;
|
|
|
|
if(t != T && isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
switch(t->etype) {
|
|
|
|
default:
|
|
|
|
goto badt;
|
|
|
|
case TARRAY:
|
2008-08-28 16:17:37 -06:00
|
|
|
if(t->bound >= 0)
|
2008-10-29 13:46:44 -06:00
|
|
|
nodconst(n, types[TINT], t->bound);
|
2008-08-27 18:28:30 -06:00
|
|
|
break;
|
|
|
|
}
|
2008-10-29 13:46:44 -06:00
|
|
|
n->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OINDEX:
|
|
|
|
case OINDEXPTR:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
|
|
|
|
2008-06-27 17:30:20 -06:00
|
|
|
walktype(n->left, Erv);
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->right, Erv);
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
goto ret;
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
|
|
defaultlit(n->left);
|
2008-06-04 15:37:38 -06:00
|
|
|
t = n->left->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
|
2008-07-05 18:43:25 -06:00
|
|
|
// BOTCH - convert each index opcode
|
|
|
|
// to look like this and get rid of OINDEXPTR
|
|
|
|
if(isptr[t->etype])
|
|
|
|
if(isptrto(t, TSTRING) || isptrto(t->type, TSTRING)) {
|
|
|
|
// right side must be an int
|
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
if(n->right->type == T) {
|
2008-10-29 13:46:44 -06:00
|
|
|
convlit(n->right, types[TINT]);
|
2008-07-05 18:43:25 -06:00
|
|
|
if(n->right->type == T)
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
if(!isint[n->right->type->etype])
|
|
|
|
goto badt;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, stringop(n, top));
|
2008-07-05 18:43:25 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
// left side is indirect
|
|
|
|
if(isptr[t->etype]) {
|
|
|
|
t = t->type;
|
|
|
|
n->op = OINDEXPTR;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
switch(t->etype) {
|
|
|
|
default:
|
2008-06-04 15:37:38 -06:00
|
|
|
goto badt;
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
case TMAP:
|
2008-07-13 15:29:46 -06:00
|
|
|
// right side must be map type
|
2008-06-16 23:34:50 -06:00
|
|
|
if(n->right->type == T) {
|
|
|
|
convlit(n->right, t->down);
|
|
|
|
if(n->right->type == T)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(!eqtype(n->right->type, t->down, 0))
|
|
|
|
goto badt;
|
|
|
|
if(n->op != OINDEXPTR)
|
|
|
|
goto badt;
|
|
|
|
n->op = OINDEX;
|
|
|
|
n->type = t->type;
|
2008-06-17 23:33:32 -06:00
|
|
|
if(top == Erv)
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, mapop(n, top));
|
2008-06-16 23:34:50 -06:00
|
|
|
break;
|
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
case TARRAY:
|
2008-06-16 23:34:50 -06:00
|
|
|
// right side must be an int
|
|
|
|
if(n->right->type == T) {
|
2008-10-29 13:46:44 -06:00
|
|
|
convlit(n->right, types[TINT]);
|
2008-06-16 23:34:50 -06:00
|
|
|
if(n->right->type == T)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(!isint[n->right->type->etype])
|
|
|
|
goto badt;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
n->type = t->type;
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
goto ret;
|
|
|
|
|
2008-07-13 15:29:46 -06:00
|
|
|
case OSEND:
|
2008-07-15 22:07:59 -06:00
|
|
|
if(top == Elv)
|
2008-07-13 15:29:46 -06:00
|
|
|
goto nottop;
|
2008-07-24 16:57:30 -06:00
|
|
|
walktype(n->left, Erv); // chan
|
|
|
|
walktype(n->right, Erv); // e
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, chanop(n, top));
|
2008-07-13 15:29:46 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ORECV:
|
2008-07-15 22:07:59 -06:00
|
|
|
if(top == Elv)
|
2008-07-13 15:29:46 -06:00
|
|
|
goto nottop;
|
2008-07-15 22:07:59 -06:00
|
|
|
if(n->right == N) {
|
2008-09-04 18:15:15 -06:00
|
|
|
walktype(n->left, Erv); // chan
|
|
|
|
indir(n, chanop(n, top)); // returns e blocking
|
2008-07-15 22:07:59 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
walktype(n->left, Elv); // e
|
|
|
|
walktype(n->right, Erv); // chan
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, chanop(n, top)); // returns bool non-blocking
|
2008-07-13 15:29:46 -06:00
|
|
|
goto ret;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case OSLICE:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
|
|
|
|
|
|
|
walktype(n->left, top);
|
|
|
|
walktype(n->right, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
goto ret;
|
2008-09-04 18:15:15 -06:00
|
|
|
convlit(n->left, types[TSTRING]);
|
2008-08-27 18:28:30 -06:00
|
|
|
t = n->left->type;
|
2008-09-04 18:15:15 -06:00
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
2008-08-27 18:28:30 -06:00
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if(t->etype == TSTRING) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, stringop(n, top));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
2008-08-28 16:17:37 -06:00
|
|
|
if(t->etype == TARRAY) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, arrayop(n, top));
|
2008-08-27 18:28:30 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
badtype(OSLICE, n->left->type, T);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ODOT:
|
|
|
|
case ODOTPTR:
|
|
|
|
case ODOTMETH:
|
|
|
|
case ODOTINTER:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
2008-09-14 17:57:55 -06:00
|
|
|
walkdot(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OADDR:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
2008-10-21 17:53:54 -06:00
|
|
|
if(n->left->op == OCONV && iscomposite(n->left->type)) {
|
|
|
|
// turn &Point{1, 2} into allocation.
|
|
|
|
// initialize with
|
|
|
|
// nvar := new(Point);
|
|
|
|
// *nvar = Point{1, 2};
|
|
|
|
// and replace expression with nvar
|
|
|
|
|
|
|
|
// TODO(rsc): might do a better job (fewer copies) later
|
|
|
|
Node *nnew, *nvar, *nas;
|
|
|
|
|
|
|
|
walktype(n->left, Elv);
|
|
|
|
if(n->left == N)
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
nvar = nod(0, N, N);
|
|
|
|
tempname(nvar, ptrto(n->left->type));
|
|
|
|
|
|
|
|
nnew = nod(ONEW, N, N);
|
|
|
|
nnew->type = nvar->type;
|
|
|
|
nnew = newcompat(nnew);
|
2008-11-05 12:27:50 -07:00
|
|
|
|
2008-10-21 17:53:54 -06:00
|
|
|
nas = nod(OAS, nvar, nnew);
|
|
|
|
addtop = list(addtop, nas);
|
2008-11-05 12:27:50 -07:00
|
|
|
|
2008-10-21 17:53:54 -06:00
|
|
|
nas = nod(OAS, nod(OIND, nvar, N), n->left);
|
|
|
|
addtop = list(addtop, nas);
|
|
|
|
|
|
|
|
indir(n, nvar);
|
|
|
|
goto ret;
|
|
|
|
}
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->left, Elv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N)
|
|
|
|
goto ret;
|
|
|
|
t = n->left->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
n->type = ptrto(t);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OIND:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top == Etop)
|
|
|
|
goto nottop;
|
2008-10-22 14:13:01 -06:00
|
|
|
if(top == Elv) // even if n is lvalue, n->left is rvalue
|
|
|
|
top = Erv;
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->left, top);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->left == N)
|
|
|
|
goto ret;
|
|
|
|
t = n->left->type;
|
|
|
|
if(t == T)
|
|
|
|
goto ret;
|
|
|
|
if(!isptr[t->etype])
|
|
|
|
goto badt;
|
|
|
|
n->type = t->type;
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case ONEW:
|
2008-06-15 21:24:30 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, newcompat(n));
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ======== second switch ========
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
fatal("walktype: switch 2 unknown op %N", n);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OASOP:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ONOT:
|
|
|
|
case OANDAND:
|
|
|
|
case OOROR:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(et != TBOOL)
|
|
|
|
goto badt;
|
|
|
|
t = types[TBOOL];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(!okforeq[et])
|
|
|
|
goto badt;
|
2008-10-14 16:08:23 -06:00
|
|
|
if(isinter(n->left->type)) {
|
|
|
|
indir(n, ifaceop(T, n, n->op));
|
|
|
|
goto ret;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
t = types[TBOOL];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLT:
|
|
|
|
case OLE:
|
|
|
|
case OGE:
|
|
|
|
case OGT:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(!okforadd[et])
|
|
|
|
if(!isptrto(n->left->type, TSTRING))
|
|
|
|
goto badt;
|
|
|
|
t = types[TBOOL];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
case ODIV:
|
|
|
|
case OPLUS:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(!okforadd[et])
|
|
|
|
goto badt;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMINUS:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(!okforadd[et])
|
|
|
|
goto badt;
|
|
|
|
if(!isfloat[et])
|
|
|
|
break;
|
|
|
|
|
|
|
|
l = nod(OLITERAL, N, N);
|
2008-08-08 18:13:31 -06:00
|
|
|
l->val.u.fval = mal(sizeof(*l->val.u.fval));
|
2008-06-04 15:37:38 -06:00
|
|
|
l->val.ctype = CTFLT;
|
2008-08-08 18:13:31 -06:00
|
|
|
mpmovecflt(l->val.u.fval, 0.0);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
l = nod(OSUB, l, n->left);
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, l);
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
goto ret;
|
|
|
|
|
|
|
|
case OLSH:
|
|
|
|
case ORSH:
|
|
|
|
case OAND:
|
|
|
|
case OOR:
|
|
|
|
case OXOR:
|
|
|
|
case OMOD:
|
|
|
|
case OCOM:
|
2008-09-19 10:39:09 -06:00
|
|
|
if(n->left->type == T)
|
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
et = n->left->type->etype;
|
|
|
|
if(!okforand[et])
|
|
|
|
goto badt;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t == T)
|
|
|
|
t = n->left->type;
|
|
|
|
n->type = t;
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
nottop:
|
2008-06-15 21:24:30 -06:00
|
|
|
dump("bad top", n);
|
|
|
|
fatal("walktype: top=%d %O", top, n->op);
|
2008-06-10 22:29:57 -06:00
|
|
|
goto ret;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
badt:
|
|
|
|
if(n->right == N) {
|
|
|
|
if(n->left == N) {
|
|
|
|
badtype(n->op, T, T);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
badtype(n->op, n->left->type, T);
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
badtype(n->op, n->left->type, n->right->type);
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
ret:
|
2008-06-17 19:07:40 -06:00
|
|
|
if(debug['w'] && top == Etop && n != N)
|
|
|
|
dump("walk", n);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
ullmancalc(n);
|
2008-06-26 18:54:44 -06:00
|
|
|
lineno = lno;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-07-05 13:49:25 -06:00
|
|
|
void
|
|
|
|
walkbool(Node *n)
|
|
|
|
{
|
|
|
|
walktype(n, Erv);
|
2008-09-09 16:47:31 -06:00
|
|
|
addtotop(n);
|
2008-07-05 13:49:25 -06:00
|
|
|
if(n != N && n->type != T)
|
|
|
|
if(!eqtype(n->type, types[TBOOL], 0))
|
|
|
|
yyerror("IF and FOR require a boolean type");
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
|
|
|
* return the first type
|
|
|
|
*/
|
|
|
|
Type*
|
|
|
|
sw1(Node *c, Type *place)
|
|
|
|
{
|
|
|
|
if(place == T)
|
|
|
|
return c->type;
|
|
|
|
return place;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* return a suitable type
|
|
|
|
*/
|
|
|
|
Type*
|
|
|
|
sw2(Node *c, Type *place)
|
|
|
|
{
|
2008-10-29 13:46:44 -06:00
|
|
|
return types[TINT]; // botch
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-07-24 16:57:30 -06:00
|
|
|
* check that switch type
|
2008-06-04 15:37:38 -06:00
|
|
|
* is compat with all the cases
|
|
|
|
*/
|
|
|
|
Type*
|
|
|
|
sw3(Node *c, Type *place)
|
|
|
|
{
|
|
|
|
if(place == T)
|
|
|
|
return c->type;
|
|
|
|
if(c->type == T)
|
|
|
|
c->type = place;
|
|
|
|
convlit(c, place);
|
|
|
|
if(!ascompat(place, c->type))
|
|
|
|
badtype(OSWITCH, place, c->type);
|
|
|
|
return place;
|
|
|
|
}
|
|
|
|
|
|
|
|
Type*
|
2008-06-15 21:24:30 -06:00
|
|
|
walkswitch(Node *sw, Type*(*call)(Node*, Type*))
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
Node *n, *c;
|
|
|
|
Type *place;
|
2008-06-15 21:24:30 -06:00
|
|
|
place = call(sw->ntest, T);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-28 18:27:39 -06:00
|
|
|
setlineno(sw);
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
n = sw->nbody;
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->op == OLIST)
|
|
|
|
n = n->left;
|
2008-06-15 21:24:30 -06:00
|
|
|
if(n->op == OEMPTY)
|
2008-10-02 12:34:04 -06:00
|
|
|
return T;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
for(; n!=N; n=n->right) {
|
|
|
|
if(n->op != OCASE)
|
|
|
|
fatal("walkswitch: not case %O\n", n->op);
|
|
|
|
for(c=n->left; c!=N; c=c->right) {
|
|
|
|
if(c->op != OLIST) {
|
2008-06-28 18:27:39 -06:00
|
|
|
setlineno(c);
|
2008-06-04 15:37:38 -06:00
|
|
|
place = call(c, place);
|
|
|
|
break;
|
|
|
|
}
|
2008-06-28 18:27:39 -06:00
|
|
|
setlineno(c);
|
2008-06-04 15:37:38 -06:00
|
|
|
place = call(c->left, place);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return place;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
casebody(Node *n)
|
|
|
|
{
|
|
|
|
Node *oc, *ot, *t;
|
|
|
|
Iter save;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* look to see if statements at top level have
|
|
|
|
* case labels attached to them. convert the illegal
|
|
|
|
* ops XFALL and XCASE into legal ops FALL and CASE.
|
|
|
|
* all unconverted ops will thus be caught as illegal
|
|
|
|
*/
|
|
|
|
|
|
|
|
oc = N; // last case statement
|
|
|
|
ot = N; // last statement (look for XFALL)
|
|
|
|
t = listfirst(&save, &n);
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if(t == N) {
|
2008-06-15 21:24:30 -06:00
|
|
|
/* empty switch */
|
2008-06-04 15:37:38 -06:00
|
|
|
if(oc == N)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(t->op == OXCASE) {
|
|
|
|
/* rewrite and link top level cases */
|
|
|
|
t->op = OCASE;
|
|
|
|
if(oc != N)
|
|
|
|
oc->right = t;
|
|
|
|
oc = t;
|
|
|
|
|
|
|
|
/* rewrite top fall that preceed case */
|
|
|
|
if(ot != N && ot->op == OXFALL)
|
|
|
|
ot->op = OFALL;
|
|
|
|
}
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
/* if first statement is not case */
|
2008-06-04 15:37:38 -06:00
|
|
|
if(oc == N)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ot = t;
|
|
|
|
t = listnext(&save);
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
Node*
|
2008-07-25 12:58:26 -06:00
|
|
|
selcase(Node *n, Node *var)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2008-07-25 12:58:26 -06:00
|
|
|
Node *a, *r, *on, *c;
|
2008-07-24 16:57:30 -06:00
|
|
|
Type *t;
|
|
|
|
|
2008-07-25 12:58:26 -06:00
|
|
|
c = n->left;
|
|
|
|
if(c->op == ORECV)
|
|
|
|
goto recv;
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
walktype(c->left, Erv); // chan
|
|
|
|
walktype(c->right, Erv); // elem
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
t = fixchan(c->left->type);
|
|
|
|
if(t == T)
|
2008-10-02 12:34:04 -06:00
|
|
|
return N;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
|
|
|
convlit(c->right, t->type);
|
|
|
|
if(!ascompat(t->type, c->right->type)) {
|
|
|
|
badtype(c->op, t->type, c->right->type);
|
2008-10-02 12:34:04 -06:00
|
|
|
return N;
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
|
|
|
|
on = syslook("selectsend", 1);
|
|
|
|
argtype(on, t->type);
|
|
|
|
argtype(on, t->type);
|
|
|
|
|
2008-07-25 12:58:26 -06:00
|
|
|
a = c->right; // elem
|
2008-07-24 16:57:30 -06:00
|
|
|
r = a;
|
2008-07-25 12:58:26 -06:00
|
|
|
a = c->left; // chan
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-07-25 12:58:26 -06:00
|
|
|
a = var; // sel-var
|
|
|
|
r = list(a, r);
|
|
|
|
|
2008-07-25 18:03:27 -06:00
|
|
|
goto out;
|
2008-07-25 12:58:26 -06:00
|
|
|
|
|
|
|
recv:
|
2008-07-27 12:42:52 -06:00
|
|
|
if(c->right != N)
|
|
|
|
goto recv2;
|
|
|
|
|
|
|
|
walktype(c->left, Erv); // chan
|
|
|
|
|
|
|
|
t = fixchan(c->left->type);
|
|
|
|
if(t == T)
|
2008-10-02 12:34:04 -06:00
|
|
|
return N;
|
2008-07-27 12:42:52 -06:00
|
|
|
|
|
|
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
|
|
|
on = syslook("selectrecv", 1);
|
|
|
|
argtype(on, t->type);
|
|
|
|
argtype(on, t->type);
|
|
|
|
|
|
|
|
a = c->left; // nil elem
|
|
|
|
a = nod(OLITERAL, N, N);
|
|
|
|
a->val.ctype = CTNIL;
|
|
|
|
|
|
|
|
r = a;
|
|
|
|
a = c->left; // chan
|
|
|
|
r = list(a, r);
|
|
|
|
a = var; // sel-var
|
|
|
|
r = list(a, r);
|
|
|
|
goto out;
|
|
|
|
|
2008-10-04 03:51:03 -06:00
|
|
|
recv2:
|
2008-07-25 12:58:26 -06:00
|
|
|
walktype(c->right, Erv); // chan
|
|
|
|
|
|
|
|
t = fixchan(c->right->type);
|
|
|
|
if(t == T)
|
2008-10-02 12:34:04 -06:00
|
|
|
return N;
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2008-07-27 12:42:52 -06:00
|
|
|
walktype(c->left, Elv); // elem
|
2008-07-25 12:58:26 -06:00
|
|
|
convlit(c->left, t->type);
|
|
|
|
if(!ascompat(t->type, c->left->type)) {
|
|
|
|
badtype(c->op, t->type, c->left->type);
|
2008-10-02 12:34:04 -06:00
|
|
|
return N;
|
2008-07-25 12:58:26 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
|
|
|
on = syslook("selectrecv", 1);
|
|
|
|
argtype(on, t->type);
|
|
|
|
argtype(on, t->type);
|
|
|
|
|
|
|
|
a = c->left; // elem
|
|
|
|
a = nod(OADDR, a, N);
|
|
|
|
r = a;
|
|
|
|
a = c->right; // chan
|
|
|
|
r = list(a, r);
|
|
|
|
a = var; // sel-var
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
2008-07-25 18:03:27 -06:00
|
|
|
out:
|
2008-07-24 16:57:30 -06:00
|
|
|
a = nod(OCALL, on, r);
|
|
|
|
r = nod(OIF, N, N);
|
|
|
|
r->ntest = a;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-09-16 21:51:50 -06:00
|
|
|
Node*
|
|
|
|
selectas(Node *name, Node *expr)
|
|
|
|
{
|
|
|
|
Node *a;
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
if(expr == N || expr->op != ORECV)
|
|
|
|
goto bad;
|
|
|
|
t = expr->left->type;
|
|
|
|
if(t == T)
|
|
|
|
goto bad;
|
|
|
|
if(isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if(t == T)
|
|
|
|
goto bad;
|
|
|
|
if(t->etype != TCHAN)
|
|
|
|
goto bad;
|
|
|
|
a = old2new(name, t->type);
|
|
|
|
return a;
|
|
|
|
|
|
|
|
bad:
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
|
|
|
walkselect(Node *sel)
|
|
|
|
{
|
|
|
|
Iter iter;
|
|
|
|
Node *n, *oc, *on, *r;
|
|
|
|
Node *var, *bod, *res;
|
|
|
|
int count;
|
2008-08-03 18:25:15 -06:00
|
|
|
int32 lno;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
|
|
|
lno = setlineno(sel);
|
|
|
|
|
|
|
|
// generate sel-struct
|
|
|
|
var = nod(OXXX, N, N);
|
|
|
|
tempname(var, ptrto(types[TUINT8]));
|
|
|
|
|
|
|
|
n = listfirst(&iter, &sel->left);
|
|
|
|
if(n == N || n->op != OXCASE)
|
|
|
|
yyerror("first select statement must be a case");
|
|
|
|
|
|
|
|
count = 0; // number of cases
|
|
|
|
res = N; // entire select body
|
|
|
|
bod = N; // body of each case
|
|
|
|
oc = N; // last case
|
|
|
|
|
|
|
|
for(count=0; n!=N; n=listnext(&iter)) {
|
|
|
|
setlineno(n);
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
bod = list(bod, n);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OXCASE:
|
|
|
|
switch(n->left->op) {
|
|
|
|
default:
|
|
|
|
yyerror("select cases must be send or recv");
|
|
|
|
break;
|
|
|
|
|
2008-09-16 21:51:50 -06:00
|
|
|
case OAS:
|
|
|
|
// convert new syntax (a=recv(chan)) to (recv(a,chan))
|
|
|
|
if(n->left->right == N || n->left->right->op != ORECV) {
|
|
|
|
yyerror("select cases must be send or recv");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
n->left->right->right = n->left->right->left;
|
|
|
|
n->left->right->left = n->left->left;
|
|
|
|
n->left = n->left->right;
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
case OSEND:
|
2008-07-25 12:58:26 -06:00
|
|
|
case ORECV:
|
2008-07-24 16:57:30 -06:00
|
|
|
if(oc != N) {
|
|
|
|
bod = list(bod, nod(OBREAK, N, N));
|
|
|
|
oc->nbody = rev(bod);
|
|
|
|
}
|
2008-07-25 12:58:26 -06:00
|
|
|
oc = selcase(n, var);
|
2008-07-24 16:57:30 -06:00
|
|
|
res = list(res, oc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
bod = N;
|
|
|
|
count++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(oc != N) {
|
|
|
|
bod = list(bod, nod(OBREAK, N, N));
|
|
|
|
oc->nbody = rev(bod);
|
|
|
|
}
|
|
|
|
setlineno(sel);
|
|
|
|
|
|
|
|
// selectgo(sel *byte);
|
|
|
|
on = syslook("selectgo", 0);
|
|
|
|
r = nod(OCALL, on, var); // sel-var
|
|
|
|
res = list(res, r);
|
|
|
|
|
|
|
|
// newselect(size uint32) (sel *byte);
|
|
|
|
on = syslook("newselect", 0);
|
|
|
|
|
|
|
|
r = nod(OXXX, N, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
nodconst(r, types[TINT], count); // count
|
2008-07-24 16:57:30 -06:00
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
r = nod(OAS, var, r);
|
|
|
|
|
|
|
|
sel->ninit = r;
|
|
|
|
sel->nbody = rev(res);
|
|
|
|
sel->left = N;
|
|
|
|
|
2008-09-04 13:21:10 -06:00
|
|
|
walkstate(sel->ninit);
|
|
|
|
walkstate(sel->nbody);
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2008-07-25 16:55:12 -06:00
|
|
|
//dump("sel", sel);
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
lineno = lno;
|
|
|
|
}
|
|
|
|
|
2008-10-21 16:04:10 -06:00
|
|
|
Type*
|
|
|
|
lookdot1(Node *n, Type *f)
|
|
|
|
{
|
|
|
|
Type *r;
|
|
|
|
Sym *s;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
r = T;
|
|
|
|
s = n->sym;
|
|
|
|
|
2008-09-14 17:57:55 -06:00
|
|
|
for(; f!=T; f=f->down) {
|
2008-10-21 16:04:10 -06:00
|
|
|
if(f->sym == S)
|
2008-06-04 15:37:38 -06:00
|
|
|
continue;
|
2008-10-21 16:04:10 -06:00
|
|
|
if(f->sym != s)
|
|
|
|
continue;
|
|
|
|
if(r != T) {
|
|
|
|
yyerror("ambiguous DOT reference %S", s);
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-21 16:04:10 -06:00
|
|
|
r = f;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
return r;
|
2008-10-21 16:04:10 -06:00
|
|
|
}
|
2008-10-19 21:13:37 -06:00
|
|
|
|
2008-10-21 16:04:10 -06:00
|
|
|
int
|
|
|
|
lookdot(Node *n, Type *t)
|
|
|
|
{
|
|
|
|
Type *f1, *f2;
|
|
|
|
|
|
|
|
f1 = T;
|
|
|
|
if(t->etype == TSTRUCT || t->etype == TINTER)
|
|
|
|
f1 = lookdot1(n->right, t->type);
|
|
|
|
|
|
|
|
f2 = methtype(n->left->type);
|
|
|
|
if(f2 != T)
|
|
|
|
f2 = lookdot1(n->right, f2->method);
|
|
|
|
|
|
|
|
if(f1 != T) {
|
|
|
|
if(f2 != T)
|
|
|
|
yyerror("ambiguous DOT reference %S as both field and method",
|
|
|
|
n->right->sym);
|
|
|
|
n->right = f1->nname; // substitute real name
|
|
|
|
n->xoffset = f1->width;
|
|
|
|
n->type = f1->type;
|
|
|
|
if(t->etype == TINTER)
|
|
|
|
n->op = ODOTINTER;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(f2 != T) {
|
2008-10-22 19:18:08 -06:00
|
|
|
if(needaddr(n->left->type)) {
|
|
|
|
n->left = nod(OADDR, n->left, N);
|
|
|
|
n->left->type = ptrto(n->left->left->type);
|
|
|
|
}
|
2008-10-21 16:04:10 -06:00
|
|
|
n->right = methodname(n->right, ismethod(n->left->type));
|
|
|
|
n->xoffset = f2->width;
|
|
|
|
n->type = f2->type;
|
|
|
|
n->op = ODOTMETH;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-14 17:57:55 -06:00
|
|
|
walkdot(Node *n)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-11-03 14:09:30 -07:00
|
|
|
Type *t;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
return;
|
2008-10-21 16:04:10 -06:00
|
|
|
switch(n->op) {
|
|
|
|
case ODOTINTER:
|
|
|
|
case ODOTMETH:
|
2008-09-14 17:57:55 -06:00
|
|
|
return; // already done
|
2008-10-21 16:04:10 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(n->right->op != ONAME) {
|
|
|
|
yyerror("rhs of . must be a name");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = n->left->type;
|
|
|
|
if(t == T)
|
|
|
|
return;
|
|
|
|
|
2008-10-04 03:51:03 -06:00
|
|
|
// as a structure field or pointer to structure field
|
2008-06-04 15:37:38 -06:00
|
|
|
if(isptr[t->etype]) {
|
|
|
|
t = t->type;
|
|
|
|
if(t == T)
|
|
|
|
return;
|
|
|
|
n->op = ODOTPTR;
|
|
|
|
}
|
|
|
|
|
2008-10-21 16:04:10 -06:00
|
|
|
if(!lookdot(n, t))
|
2008-10-04 03:51:03 -06:00
|
|
|
yyerror("undefined DOT %S on %T", n->right->sym, n->left->type);
|
2008-10-21 16:04:10 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
Node*
|
|
|
|
ascompatee(int op, Node **nl, Node **nr)
|
|
|
|
{
|
|
|
|
Node *l, *r, *nn, *a;
|
|
|
|
Iter savel, saver;
|
|
|
|
|
2008-06-10 22:29:57 -06:00
|
|
|
/*
|
|
|
|
* check assign expression list to
|
|
|
|
* a expression list. called in
|
|
|
|
* expr-list = expr-list
|
|
|
|
*/
|
2008-06-04 15:37:38 -06:00
|
|
|
l = listfirst(&savel, nl);
|
|
|
|
r = listfirst(&saver, nr);
|
|
|
|
nn = N;
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if(l == N || r == N) {
|
|
|
|
if(l != r)
|
2008-07-05 18:43:25 -06:00
|
|
|
yyerror("error in shape across %O", op);
|
2008-06-10 22:29:57 -06:00
|
|
|
return rev(nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
convlit(r, l->type);
|
|
|
|
if(!ascompat(l->type, r->type)) {
|
|
|
|
badtype(op, l->type, r->type);
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = nod(OAS, l, r);
|
|
|
|
a = convas(a);
|
2008-11-01 17:36:46 -06:00
|
|
|
nn = list(a, nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
l = listnext(&savel);
|
|
|
|
r = listnext(&saver);
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
ascompatet(int op, Node **nl, Type **nr, int fp)
|
|
|
|
{
|
|
|
|
Node *l, *nn, *a;
|
|
|
|
Type *r;
|
|
|
|
Iter savel, saver;
|
|
|
|
|
2008-06-10 22:29:57 -06:00
|
|
|
/*
|
|
|
|
* check assign type list to
|
|
|
|
* a expression list. called in
|
|
|
|
* expr-list = func()
|
|
|
|
*/
|
2008-06-04 15:37:38 -06:00
|
|
|
l = listfirst(&savel, nl);
|
|
|
|
r = structfirst(&saver, nr);
|
|
|
|
nn = N;
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if(l == N || r == T) {
|
|
|
|
if(l != N || r != T)
|
2008-07-05 18:43:25 -06:00
|
|
|
yyerror("error in shape across %O", op);
|
2008-06-10 22:29:57 -06:00
|
|
|
return rev(nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!ascompat(l->type, r->type)) {
|
|
|
|
badtype(op, l->type, r->type);
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = nod(OAS, l, nodarg(r, fp));
|
|
|
|
a = convas(a);
|
2008-11-01 17:36:46 -06:00
|
|
|
nn = list(a, nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
l = listnext(&savel);
|
|
|
|
r = structnext(&saver);
|
|
|
|
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
2008-11-01 17:36:46 -06:00
|
|
|
/*
|
|
|
|
* make a tsig for the structure
|
|
|
|
* carrying the ... arguments
|
|
|
|
*/
|
|
|
|
Type*
|
|
|
|
sigtype(Type *st)
|
|
|
|
{
|
|
|
|
Dcl *x;
|
|
|
|
Sym *s;
|
|
|
|
Type *t;
|
|
|
|
static int sigdddgen;
|
|
|
|
|
|
|
|
dowidth(st);
|
|
|
|
|
|
|
|
sigdddgen++;
|
|
|
|
snprint(namebuf, sizeof(namebuf), "dsigddd_%d", sigdddgen);
|
|
|
|
s = lookup(namebuf);
|
|
|
|
t = newtype(s);
|
|
|
|
t = dodcltype(t);
|
|
|
|
updatetype(t, st);
|
|
|
|
|
|
|
|
// record internal type for signature generation
|
|
|
|
x = mal(sizeof(*x));
|
|
|
|
x->op = OTYPE;
|
|
|
|
x->dsym = s;
|
|
|
|
x->dtype = s->otype;
|
|
|
|
x->forw = signatlist;
|
|
|
|
x->block = block;
|
|
|
|
signatlist = x;
|
|
|
|
|
|
|
|
return s->otype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* package all the arguments that
|
|
|
|
* match a ... parameter into an
|
|
|
|
* automatic structure.
|
|
|
|
* then call the ... arg (interface)
|
|
|
|
* with a pointer to the structure
|
|
|
|
*/
|
|
|
|
Node*
|
2008-11-03 16:32:49 -07:00
|
|
|
mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp)
|
2008-11-01 17:36:46 -06:00
|
|
|
{
|
|
|
|
Type *t, *st, *ft;
|
|
|
|
Node *a, *n, *var;
|
|
|
|
Iter saven;
|
|
|
|
|
|
|
|
n = N; // list of assignments
|
|
|
|
|
|
|
|
st = typ(TSTRUCT); // generated structure
|
|
|
|
ft = T; // last field
|
|
|
|
while(r != N) {
|
|
|
|
defaultlit(r);
|
|
|
|
|
|
|
|
// generate the next structure field
|
|
|
|
t = typ(TFIELD);
|
|
|
|
t->type = r->type;
|
|
|
|
if(ft == T)
|
|
|
|
st->type = t;
|
|
|
|
else
|
|
|
|
ft->down = t;
|
|
|
|
ft = t;
|
|
|
|
|
|
|
|
a = nod(OAS, N, r);
|
|
|
|
n = list(n, a);
|
2008-11-03 16:32:49 -07:00
|
|
|
if(rr != N) {
|
|
|
|
r = rr;
|
|
|
|
rr = N;
|
|
|
|
} else
|
|
|
|
r = listnext(saver);
|
2008-11-01 17:36:46 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// make a named type for the struct
|
|
|
|
st = sigtype(st);
|
|
|
|
|
|
|
|
// now we have the size, make the struct
|
|
|
|
var = nod(OXXX, N, N);
|
|
|
|
tempname(var, st);
|
|
|
|
|
|
|
|
// assign the fields to the struct
|
|
|
|
n = rev(n);
|
|
|
|
r = listfirst(&saven, &n);
|
|
|
|
t = st->type;
|
|
|
|
while(r != N) {
|
|
|
|
r->left = nod(OXXX, N, N);
|
|
|
|
*r->left = *var;
|
|
|
|
r->left->type = r->right->type;
|
|
|
|
r->left->xoffset += t->width;
|
|
|
|
nn = list(r, nn);
|
|
|
|
r = listnext(&saven);
|
|
|
|
t = t->down;
|
|
|
|
}
|
|
|
|
|
|
|
|
// last thing is to put assignment
|
|
|
|
// of a pointer to the structure to
|
|
|
|
// the DDD parameter
|
|
|
|
|
|
|
|
a = nod(OADDR, var, N);
|
|
|
|
a->type = ptrto(st);
|
|
|
|
a = nod(OAS, nodarg(l, fp), a);
|
|
|
|
a = convas(a);
|
|
|
|
|
|
|
|
nn = list(a, nn);
|
|
|
|
|
|
|
|
return nn;
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
Node*
|
|
|
|
ascompatte(int op, Type **nl, Node **nr, int fp)
|
|
|
|
{
|
2008-11-03 16:32:49 -07:00
|
|
|
Type *l, *ll;
|
|
|
|
Node *r, *rr, *nn, *a;
|
2008-06-04 15:37:38 -06:00
|
|
|
Iter savel, saver;
|
|
|
|
|
2008-06-10 22:29:57 -06:00
|
|
|
/*
|
|
|
|
* check assign expression list to
|
|
|
|
* a type list. called in
|
|
|
|
* return expr-list
|
|
|
|
* func(expr-list)
|
|
|
|
*/
|
2008-06-04 15:37:38 -06:00
|
|
|
l = structfirst(&savel, nl);
|
|
|
|
r = listfirst(&saver, nr);
|
|
|
|
nn = N;
|
2008-11-01 17:36:46 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
loop:
|
2008-11-01 17:36:46 -06:00
|
|
|
if(l != T && isddd(l->type)) {
|
2008-11-03 16:32:49 -07:00
|
|
|
// the ddd parameter must be last
|
|
|
|
ll = structnext(&savel);
|
|
|
|
if(ll != T)
|
|
|
|
yyerror("... must be last argument");
|
|
|
|
|
|
|
|
// special case --
|
|
|
|
// only if we are assigning a single ddd
|
|
|
|
// argument to a ddd parameter then it is
|
|
|
|
// passed thru unencapsulated
|
|
|
|
rr = listnext(&saver);
|
|
|
|
if(r != N && rr == N && isddd(r->type)) {
|
|
|
|
a = nod(OAS, nodarg(l, fp), r);
|
|
|
|
a = convas(a);
|
|
|
|
nn = list(a, nn);
|
|
|
|
return rev(nn);
|
2008-11-01 17:36:46 -06:00
|
|
|
}
|
|
|
|
|
2008-11-03 16:32:49 -07:00
|
|
|
// normal case -- make a structure of all
|
|
|
|
// remaining arguments and pass a pointer to
|
|
|
|
// it to the ddd parameter (empty interface)
|
|
|
|
nn = mkdotargs(r, rr, &saver, nn, l, fp);
|
2008-11-01 17:36:46 -06:00
|
|
|
|
|
|
|
return rev(nn);
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(l == T || r == N) {
|
|
|
|
if(l != T || r != N)
|
2008-07-05 18:43:25 -06:00
|
|
|
yyerror("error in shape across %O", op);
|
2008-06-10 22:29:57 -06:00
|
|
|
return rev(nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
convlit(r, l->type);
|
|
|
|
if(!ascompat(l->type, r->type)) {
|
|
|
|
badtype(op, l->type, r->type);
|
|
|
|
return N;
|
|
|
|
}
|
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
a = nod(OAS, nodarg(l, fp), r);
|
|
|
|
a = convas(a);
|
2008-11-01 17:36:46 -06:00
|
|
|
nn = list(a, nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
l = structnext(&savel);
|
|
|
|
r = listnext(&saver);
|
|
|
|
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* can we assign var of type t2 to var of type t1
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ascompat(Type *t1, Type *t2)
|
|
|
|
{
|
|
|
|
if(eqtype(t1, t2, 0))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
// if(eqtype(t1, nilptr, 0))
|
|
|
|
// return 1;
|
|
|
|
// if(eqtype(t2, nilptr, 0))
|
|
|
|
// return 1;
|
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
if(isnilinter(t1))
|
|
|
|
return 1;
|
2008-10-02 21:51:10 -06:00
|
|
|
if(isinter(t1)) {
|
|
|
|
if(isinter(t2))
|
2008-06-04 15:37:38 -06:00
|
|
|
return 1;
|
2008-10-02 21:51:10 -06:00
|
|
|
if(ismethod(t2))
|
|
|
|
return 1;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
if(isnilinter(t2))
|
|
|
|
return 1;
|
2008-06-04 15:37:38 -06:00
|
|
|
if(isinter(t2))
|
2008-09-20 15:59:15 -06:00
|
|
|
if(ismethod(t1))
|
2008-06-04 15:37:38 -06:00
|
|
|
return 1;
|
|
|
|
|
2008-08-28 16:17:37 -06:00
|
|
|
if(isptrdarray(t1))
|
|
|
|
if(isptrarray(t2))
|
2008-08-27 18:28:30 -06:00
|
|
|
return 1;
|
2008-08-29 14:24:53 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
2008-10-02 15:38:07 -06:00
|
|
|
prcompat(Node *n, int fmt)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
Node *l, *r;
|
2008-08-12 15:04:03 -06:00
|
|
|
Node *on;
|
2008-06-04 15:37:38 -06:00
|
|
|
Type *t;
|
|
|
|
Iter save;
|
2008-10-02 15:38:07 -06:00
|
|
|
int w, notfirst;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
r = N;
|
|
|
|
l = listfirst(&save, &n);
|
2008-10-02 15:38:07 -06:00
|
|
|
notfirst = 0;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
loop:
|
|
|
|
if(l == N) {
|
2008-10-02 15:38:07 -06:00
|
|
|
if(fmt) {
|
|
|
|
on = syslook("printnl", 0);
|
|
|
|
r = list(r, nod(OCALL, on, N));
|
|
|
|
}
|
2008-09-20 15:59:15 -06:00
|
|
|
walktype(r, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-10-02 15:38:07 -06:00
|
|
|
if(notfirst) {
|
|
|
|
on = syslook("printsp", 0);
|
|
|
|
r = list(r, nod(OCALL, on, N));
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
w = whatis(l);
|
|
|
|
switch(w) {
|
|
|
|
default:
|
2008-09-09 16:47:31 -06:00
|
|
|
if(l->type == T)
|
|
|
|
goto out;
|
2008-09-22 17:58:30 -06:00
|
|
|
if(isinter(l->type)) {
|
|
|
|
on = syslook("printinter", 1);
|
|
|
|
argtype(on, l->type); // any-1
|
|
|
|
break;
|
2008-07-16 13:44:21 -06:00
|
|
|
}
|
2008-09-22 17:58:30 -06:00
|
|
|
if(isptr[l->type->etype]) {
|
|
|
|
on = syslook("printpointer", 1);
|
|
|
|
argtype(on, l->type->type); // any-1
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
badtype(n->op, l->type, T);
|
|
|
|
l = listnext(&save);
|
|
|
|
goto loop;
|
2008-07-16 13:44:21 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
case Wlitint:
|
|
|
|
case Wtint:
|
2008-07-16 13:44:21 -06:00
|
|
|
on = syslook("printint", 0);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
case Wlitfloat:
|
|
|
|
case Wtfloat:
|
2008-07-16 13:44:21 -06:00
|
|
|
on = syslook("printfloat", 0);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
case Wlitbool:
|
|
|
|
case Wtbool:
|
2008-07-16 13:44:21 -06:00
|
|
|
on = syslook("printbool", 0);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
case Wlitstr:
|
|
|
|
case Wtstr:
|
2008-07-16 13:44:21 -06:00
|
|
|
on = syslook("printstring", 0);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
t = *getinarg(on->type);
|
2008-06-04 15:37:38 -06:00
|
|
|
if(t != nil)
|
|
|
|
t = t->type;
|
|
|
|
if(t != nil)
|
|
|
|
t = t->type;
|
|
|
|
|
|
|
|
if(!eqtype(t, l->type, 0)) {
|
|
|
|
l = nod(OCONV, l, N);
|
|
|
|
l->type = t;
|
|
|
|
}
|
|
|
|
|
2008-10-02 15:38:07 -06:00
|
|
|
r = list(r, nod(OCALL, on, l));
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-09-09 16:47:31 -06:00
|
|
|
out:
|
2008-10-02 15:38:07 -06:00
|
|
|
notfirst = fmt;
|
2008-06-04 15:37:38 -06:00
|
|
|
l = listnext(&save);
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
2008-08-03 18:25:15 -06:00
|
|
|
nodpanic(int32 lineno)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-06-15 21:24:30 -06:00
|
|
|
Node *n, *on;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("panicl", 0);
|
2008-06-04 15:37:38 -06:00
|
|
|
n = nodintconst(lineno);
|
2008-06-15 21:24:30 -06:00
|
|
|
n = nod(OCALL, on, n);
|
2008-09-20 15:59:15 -06:00
|
|
|
walktype(n, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
newcompat(Node *n)
|
|
|
|
{
|
2008-06-15 21:24:30 -06:00
|
|
|
Node *r, *on;
|
2008-06-04 15:37:38 -06:00
|
|
|
Type *t;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
t = n->type;
|
|
|
|
if(t == T || !isptr[t->etype] || t->type == T)
|
|
|
|
fatal("newcompat: type should be pointer %lT", t);
|
|
|
|
|
|
|
|
t = t->type;
|
2008-08-27 18:28:30 -06:00
|
|
|
switch(t->etype) {
|
2008-10-21 19:03:25 -06:00
|
|
|
case TFUNC:
|
|
|
|
yyerror("cannot make new %T", t);
|
|
|
|
break;
|
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
case TMAP:
|
2008-06-15 21:24:30 -06:00
|
|
|
r = mapop(n, Erv);
|
|
|
|
return r;
|
2008-08-27 18:28:30 -06:00
|
|
|
|
|
|
|
case TCHAN:
|
2008-07-12 14:08:53 -06:00
|
|
|
r = chanop(n, Erv);
|
|
|
|
return r;
|
2008-08-27 18:28:30 -06:00
|
|
|
|
|
|
|
case TARRAY:
|
|
|
|
r = arrayop(n, Erv);
|
|
|
|
return r;
|
2008-07-12 14:08:53 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
if(n->left != N)
|
|
|
|
yyerror("dont know what new(,e) means");
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
dowidth(t);
|
|
|
|
|
|
|
|
on = syslook("mal", 1);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
argtype(on, t);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
r = nodintconst(t->width);
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
// r = nod(OCONV, r, N);
|
2008-06-15 21:24:30 -06:00
|
|
|
r->type = n->type;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
2008-06-15 21:24:30 -06:00
|
|
|
stringop(Node *n, int top)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-06-15 21:24:30 -06:00
|
|
|
Node *r, *c, *on;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
2008-07-13 15:29:46 -06:00
|
|
|
fatal("stringop: unknown op %O", n->op);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
case OGE:
|
|
|
|
case OGT:
|
|
|
|
case OLE:
|
|
|
|
case OLT:
|
|
|
|
// sys_cmpstring(s1, s2) :: 0
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("cmpstring", 0);
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(n->left, n->right);
|
2008-06-15 21:24:30 -06:00
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
c = nodintconst(0);
|
|
|
|
r = nod(n->op, r, c);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OADD:
|
|
|
|
// sys_catstring(s1, s2)
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("catstring", 0);
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(n->left, n->right);
|
2008-06-15 21:24:30 -06:00
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OASOP:
|
|
|
|
// sys_catstring(s1, s2)
|
|
|
|
switch(n->etype) {
|
|
|
|
default:
|
2008-07-13 15:29:46 -06:00
|
|
|
fatal("stringop: unknown op %O-%O", n->op, n->etype);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
case OADD:
|
|
|
|
// s1 = sys_catstring(s1, s2)
|
2008-06-15 21:24:30 -06:00
|
|
|
if(n->etype != OADD)
|
|
|
|
fatal("stringop: not cat");
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(n->left, n->right);
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("catstring", 0);
|
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
r = nod(OAS, n->left, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OSLICE:
|
|
|
|
// sys_slicestring(s, lb, hb)
|
|
|
|
r = nod(OCONV, n->right->left, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
r->type = types[TINT];
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
c = nod(OCONV, n->right->right, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
c->type = types[TINT];
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(r, c);
|
|
|
|
r = list(n->left, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("slicestring", 0);
|
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2008-07-05 18:43:25 -06:00
|
|
|
case OINDEX:
|
2008-06-04 15:37:38 -06:00
|
|
|
// sys_indexstring(s, i)
|
2008-07-05 18:43:25 -06:00
|
|
|
c = n->left;
|
|
|
|
if(isptrto(c->type->type, TSTRING)) {
|
|
|
|
// lhs is string or *string
|
|
|
|
c = nod(OIND, c, N);
|
|
|
|
c->type = c->left->type->type;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
r = nod(OCONV, n->right, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
r->type = types[TINT];
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(c, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("indexstring", 0);
|
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OCONV:
|
|
|
|
// sys_intstring(v)
|
|
|
|
r = nod(OCONV, n->left, N);
|
|
|
|
r->type = types[TINT64];
|
2008-06-15 21:24:30 -06:00
|
|
|
on = syslook("intstring", 0);
|
|
|
|
r = nod(OCALL, on, r);
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OARRAY:
|
2008-09-22 21:12:15 -06:00
|
|
|
// arraystring(*[]byte) string;
|
|
|
|
r = n->left;
|
|
|
|
if(!isptr[r->type->etype])
|
|
|
|
r = nod(OADDR, r, N);
|
|
|
|
on = syslook("arraystring", 0);
|
2008-06-15 21:24:30 -06:00
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
walktype(r, top);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
Type*
|
|
|
|
fixmap(Type *tm)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
t = tm->type;
|
2008-09-14 17:57:55 -06:00
|
|
|
if(t == T)
|
|
|
|
goto bad;
|
|
|
|
if(t->etype != TMAP)
|
|
|
|
goto bad;
|
|
|
|
if(t->down == T || t->type == T)
|
|
|
|
goto bad;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
dowidth(t->down);
|
|
|
|
dowidth(t->type);
|
|
|
|
|
|
|
|
return t;
|
2008-09-14 17:57:55 -06:00
|
|
|
|
|
|
|
bad:
|
|
|
|
yyerror("not a map: %lT", tm);
|
|
|
|
return T;
|
2008-06-15 21:24:30 -06:00
|
|
|
}
|
|
|
|
|
2008-07-12 14:08:53 -06:00
|
|
|
Type*
|
|
|
|
fixchan(Type *tm)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
|
2008-10-04 03:51:03 -06:00
|
|
|
if(tm == T)
|
2008-09-14 17:57:55 -06:00
|
|
|
goto bad;
|
2008-07-12 14:08:53 -06:00
|
|
|
t = tm->type;
|
2008-09-14 17:57:55 -06:00
|
|
|
if(t == T)
|
|
|
|
goto bad;
|
|
|
|
if(t->etype != TCHAN)
|
|
|
|
goto bad;
|
|
|
|
if(t->type == T)
|
|
|
|
goto bad;
|
2008-07-12 14:08:53 -06:00
|
|
|
|
|
|
|
dowidth(t->type);
|
|
|
|
|
|
|
|
return t;
|
2008-09-14 17:57:55 -06:00
|
|
|
|
|
|
|
bad:
|
|
|
|
yyerror("not a channel: %lT", tm);
|
|
|
|
return T;
|
2008-07-12 14:08:53 -06:00
|
|
|
}
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
Node*
|
|
|
|
mapop(Node *n, int top)
|
|
|
|
{
|
|
|
|
Node *r, *a;
|
|
|
|
Type *t;
|
|
|
|
Node *on;
|
2008-10-02 12:34:04 -06:00
|
|
|
int cl, cr;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
//dump("mapop", n);
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
r = n;
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
2008-07-13 15:29:46 -06:00
|
|
|
fatal("mapop: unknown op %O", n->op);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
case ONEW:
|
2008-06-16 23:34:50 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
|
|
|
|
2008-10-29 13:46:44 -06:00
|
|
|
// newmap(keysize int, valsize int,
|
|
|
|
// keyalg int, valalg int,
|
|
|
|
// hint int) (hmap *map[any-1]any-2);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
t = fixmap(n->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
|
|
|
a = n->left; // hint
|
|
|
|
if(n->left == N)
|
|
|
|
a = nodintconst(0);
|
|
|
|
r = a;
|
|
|
|
a = nodintconst(algtype(t->type)); // val algorithm
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
a = nodintconst(algtype(t->down)); // key algorithm
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
a = nodintconst(t->type->width); // val width
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
a = nodintconst(t->down->width); // key width
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
on = syslook("newmap", 1);
|
|
|
|
|
|
|
|
argtype(on, t->down); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, top);
|
|
|
|
r->type = n->type;
|
|
|
|
break;
|
|
|
|
|
2008-06-17 23:33:32 -06:00
|
|
|
case OINDEX:
|
2008-06-16 23:34:50 -06:00
|
|
|
if(top != Erv)
|
|
|
|
goto nottop;
|
2008-06-15 21:24:30 -06:00
|
|
|
// mapaccess1(hmap *map[any]any, key any) (val any);
|
|
|
|
|
|
|
|
t = fixmap(n->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
|
|
|
convlit(n->right, t->down);
|
|
|
|
|
|
|
|
if(!eqtype(n->right->type, t->down, 0)) {
|
|
|
|
badtype(n->op, n->right->type, t->down);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = n->right; // key
|
2008-06-24 12:10:47 -06:00
|
|
|
// if(!isptr[t->down->etype]) {
|
|
|
|
// a = nod(OADDR, a, N);
|
|
|
|
// a->type = ptrto(t);
|
|
|
|
// }
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
r = a;
|
|
|
|
a = n->left; // map
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2008-06-24 12:10:47 -06:00
|
|
|
on = syslook("mapaccess1", 1);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
argtype(on, t->down); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
argtype(on, t->down); // any-3
|
|
|
|
argtype(on, t->type); // any-4
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, Erv);
|
|
|
|
r->type = t->type;
|
2008-06-04 15:37:38 -06:00
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
case OAS:
|
|
|
|
cl = listcount(n->left);
|
|
|
|
cr = listcount(n->right);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
if(cl == 1 && cr == 2)
|
|
|
|
goto assign2;
|
|
|
|
if(cl == 2 && cr == 1)
|
|
|
|
goto access2;
|
|
|
|
if(cl != 1 || cr != 1)
|
|
|
|
goto shape;
|
|
|
|
|
|
|
|
// mapassign1(hmap *map[any-1]any-2, key any-3, val any-4);
|
|
|
|
if(n->left->op != OINDEX)
|
|
|
|
goto shape;
|
|
|
|
|
|
|
|
t = fixmap(n->left->left->type);
|
2008-06-16 23:34:50 -06:00
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->right; // val
|
2008-06-16 23:34:50 -06:00
|
|
|
r = a;
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->left->right; // key
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->left->left; // map
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
on = syslook("mapassign1", 1);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
|
|
argtype(on, t->down); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
argtype(on, t->down); // any-3
|
|
|
|
argtype(on, t->type); // any-4
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
r = nod(OCALL, on, r);
|
2008-09-20 15:59:15 -06:00
|
|
|
walktype(r, Etop);
|
2008-06-16 23:34:50 -06:00
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
assign2:
|
|
|
|
// mapassign2(hmap *map[any]any, key any, val any, pres bool);
|
|
|
|
if(n->left->op != OINDEX)
|
|
|
|
goto shape;
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
|
|
t = fixmap(n->left->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->right->right; // pres
|
2008-06-16 23:34:50 -06:00
|
|
|
r = a;
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->right->left; // val
|
2008-07-24 16:57:30 -06:00
|
|
|
r =list(a, r);
|
2008-06-16 23:34:50 -06:00
|
|
|
a = n->left->right; // key
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-16 23:34:50 -06:00
|
|
|
a = n->left->left; // map
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
on = syslook("mapassign2", 1);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
|
|
argtype(on, t->down); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
argtype(on, t->down); // any-3
|
|
|
|
argtype(on, t->type); // any-4
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
2008-09-20 15:59:15 -06:00
|
|
|
walktype(r, Etop);
|
2008-06-16 23:34:50 -06:00
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
access2:
|
|
|
|
// mapaccess2(hmap *map[any-1]any-2, key any-3) (val-4 any, pres bool);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
//dump("access2", n);
|
|
|
|
if(n->right->op != OINDEX)
|
|
|
|
goto shape;
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
t = fixmap(n->right->left->type);
|
2008-06-16 23:34:50 -06:00
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->right->right; // key
|
2008-06-16 23:34:50 -06:00
|
|
|
r = a;
|
2008-06-24 15:11:20 -06:00
|
|
|
a = n->right->left; // map
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
on = syslook("mapaccess2", 1);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
|
|
argtype(on, t->down); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
argtype(on, t->down); // any-3
|
|
|
|
argtype(on, t->type); // any-4
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
n->right = nod(OCALL, on, r);
|
|
|
|
walktype(n, Etop);
|
|
|
|
r = n;
|
2008-06-16 23:34:50 -06:00
|
|
|
break;
|
|
|
|
|
2008-08-10 17:49:01 -06:00
|
|
|
case OASOP:
|
|
|
|
// rewrite map[index] op= right
|
|
|
|
// into tmpi := index; map[tmpi] = map[tmpi] op right
|
|
|
|
|
|
|
|
t = n->left->left->type->type;
|
|
|
|
a = nod(OXXX, N, N);
|
|
|
|
tempname(a, t->down); // tmpi
|
|
|
|
r = nod(OAS, a, n->left->right); // tmpi := index
|
|
|
|
n->left->right = a; // m[tmpi]
|
|
|
|
|
|
|
|
a = nod(OXXX, N, N);
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(a, n->left); // copy of map[tmpi]
|
2008-08-10 17:49:01 -06:00
|
|
|
a = nod(n->etype, a, n->right); // m[tmpi] op right
|
|
|
|
a = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right
|
|
|
|
r = nod(OLIST, r, a);
|
2008-10-04 18:11:01 -06:00
|
|
|
walktype(r, Etop);
|
|
|
|
break;
|
2008-06-16 23:34:50 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
return r;
|
2008-06-16 23:34:50 -06:00
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
shape:
|
|
|
|
dump("shape", n);
|
|
|
|
fatal("mapop: cl=%d cr=%d, %O", top, n->op);
|
|
|
|
return N;
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
nottop:
|
|
|
|
dump("bad top", n);
|
|
|
|
fatal("mapop: top=%d %O", top, n->op);
|
|
|
|
return N;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-07-12 14:08:53 -06:00
|
|
|
Node*
|
|
|
|
chanop(Node *n, int top)
|
|
|
|
{
|
|
|
|
Node *r, *a;
|
|
|
|
Type *t;
|
|
|
|
Node *on;
|
2008-10-02 12:34:04 -06:00
|
|
|
int cl, cr;
|
2008-07-12 14:08:53 -06:00
|
|
|
|
|
|
|
//dump("chanop", n);
|
|
|
|
|
|
|
|
r = n;
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
2008-07-13 15:29:46 -06:00
|
|
|
fatal("chanop: unknown op %O", n->op);
|
2008-07-12 14:08:53 -06:00
|
|
|
|
|
|
|
case ONEW:
|
2008-10-29 13:46:44 -06:00
|
|
|
// newchan(elemsize int, elemalg int,
|
|
|
|
// hint int) (hmap *chan[any-1]);
|
2008-07-12 14:08:53 -06:00
|
|
|
|
|
|
|
t = fixchan(n->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-09-20 20:56:40 -06:00
|
|
|
if(n->left != N) {
|
|
|
|
// async buf size
|
|
|
|
a = nod(OCONV, n->left, N);
|
2008-10-29 14:18:21 -06:00
|
|
|
a->type = types[TINT];
|
2008-09-20 20:56:40 -06:00
|
|
|
} else
|
2008-07-12 14:08:53 -06:00
|
|
|
a = nodintconst(0);
|
2008-09-20 20:56:40 -06:00
|
|
|
|
2008-07-12 14:08:53 -06:00
|
|
|
r = a;
|
|
|
|
a = nodintconst(algtype(t->type)); // elem algorithm
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-07-12 14:08:53 -06:00
|
|
|
a = nodintconst(t->type->width); // elem width
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-07-12 14:08:53 -06:00
|
|
|
|
|
|
|
on = syslook("newchan", 1);
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, top);
|
|
|
|
r->type = n->type;
|
|
|
|
break;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
|
|
|
case OAS:
|
2008-07-13 17:20:27 -06:00
|
|
|
cl = listcount(n->left);
|
|
|
|
cr = listcount(n->right);
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2008-07-15 22:07:59 -06:00
|
|
|
if(cl != 2 || cr != 1 || n->right->op != ORECV)
|
2008-07-13 15:29:46 -06:00
|
|
|
goto shape;
|
|
|
|
|
2008-07-15 22:07:59 -06:00
|
|
|
// chanrecv2(hchan *chan any) (elem any, pres bool);
|
|
|
|
t = fixchan(n->right->left->type);
|
2008-07-13 15:29:46 -06:00
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-07-15 22:07:59 -06:00
|
|
|
a = n->right->left; // chan
|
2008-07-13 15:29:46 -06:00
|
|
|
r = a;
|
|
|
|
|
2008-07-15 22:07:59 -06:00
|
|
|
on = syslook("chanrecv2", 1);
|
|
|
|
|
2008-07-13 15:29:46 -06:00
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
2008-07-15 22:07:59 -06:00
|
|
|
n->right = r;
|
|
|
|
r = n;
|
|
|
|
walktype(r, Etop);
|
2008-07-13 15:29:46 -06:00
|
|
|
break;
|
|
|
|
|
2008-07-13 17:20:27 -06:00
|
|
|
case ORECV:
|
2008-07-15 22:07:59 -06:00
|
|
|
if(n->right != N)
|
|
|
|
goto recv2;
|
|
|
|
|
2008-07-13 17:20:27 -06:00
|
|
|
// chanrecv1(hchan *chan any) (elem any);
|
|
|
|
|
|
|
|
t = fixchan(n->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
|
|
|
a = n->left; // chan
|
|
|
|
r = a;
|
|
|
|
|
|
|
|
on = syslook("chanrecv1", 1);
|
|
|
|
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, Erv);
|
|
|
|
break;
|
|
|
|
|
|
|
|
recv2:
|
2008-07-26 15:21:21 -06:00
|
|
|
// chanrecv3(hchan *chan any, *elem any) (pres bool);
|
2008-07-15 22:07:59 -06:00
|
|
|
t = fixchan(n->right->type);
|
2008-07-13 17:20:27 -06:00
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
2008-07-15 22:07:59 -06:00
|
|
|
a = n->right; // chan
|
2008-07-13 17:20:27 -06:00
|
|
|
r = a;
|
2008-07-26 15:21:21 -06:00
|
|
|
a = n->left; // elem
|
|
|
|
if(a == N) {
|
|
|
|
a = nod(OLITERAL, N, N);
|
|
|
|
a->val.ctype = CTNIL;
|
|
|
|
} else
|
|
|
|
a = nod(OADDR, a, N);
|
2008-07-13 17:20:27 -06:00
|
|
|
|
2008-07-26 15:21:21 -06:00
|
|
|
on = syslook("chanrecv3", 1);
|
2008-07-13 17:20:27 -06:00
|
|
|
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2008-07-13 17:20:27 -06:00
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
n->right = r;
|
|
|
|
r = n;
|
|
|
|
walktype(r, Etop);
|
|
|
|
break;
|
2008-07-15 22:07:59 -06:00
|
|
|
|
|
|
|
case OSEND:
|
|
|
|
t = fixchan(n->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
if(top != Etop)
|
|
|
|
goto send2;
|
|
|
|
|
|
|
|
// chansend1(hchan *chan any, elem any);
|
|
|
|
t = fixchan(n->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
|
|
|
a = n->right; // e
|
|
|
|
r = a;
|
|
|
|
a = n->left; // chan
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-07-15 22:07:59 -06:00
|
|
|
|
|
|
|
on = syslook("chansend1", 1);
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
2008-09-04 13:21:10 -06:00
|
|
|
walktype(r, Etop);
|
2008-07-15 22:07:59 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
send2:
|
|
|
|
// chansend2(hchan *chan any, val any) (pres bool);
|
|
|
|
t = fixchan(n->left->type);
|
|
|
|
if(t == T)
|
|
|
|
break;
|
|
|
|
|
|
|
|
a = n->right; // e
|
|
|
|
r = a;
|
|
|
|
a = n->left; // chan
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(a, r);
|
2008-07-15 22:07:59 -06:00
|
|
|
|
|
|
|
on = syslook("chansend2", 1);
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
2008-09-04 13:21:10 -06:00
|
|
|
walktype(r, Etop);
|
2008-07-15 22:07:59 -06:00
|
|
|
break;
|
2008-07-12 14:08:53 -06:00
|
|
|
}
|
|
|
|
return r;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
|
|
|
shape:
|
|
|
|
fatal("chanop: %O", n->op);
|
|
|
|
return N;
|
2008-07-12 14:08:53 -06:00
|
|
|
}
|
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
Type*
|
|
|
|
fixarray(Type *tm)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
t = tm->type;
|
2008-09-14 17:57:55 -06:00
|
|
|
if(t == T)
|
|
|
|
goto bad;
|
|
|
|
if(t->etype != TARRAY)
|
|
|
|
goto bad;
|
|
|
|
if(t->type == T)
|
|
|
|
goto bad;
|
2008-08-27 18:28:30 -06:00
|
|
|
|
|
|
|
dowidth(t->type);
|
|
|
|
|
|
|
|
return t;
|
2008-09-14 17:57:55 -06:00
|
|
|
|
|
|
|
bad:
|
|
|
|
yyerror("not an array: %lT", tm);
|
|
|
|
return T;
|
2008-10-04 03:51:03 -06:00
|
|
|
|
2008-08-27 18:28:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
arrayop(Node *n, int top)
|
|
|
|
{
|
|
|
|
Node *r, *a;
|
|
|
|
Type *t;
|
|
|
|
Node *on;
|
|
|
|
Iter save;
|
|
|
|
|
|
|
|
r = n;
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
fatal("darrayop: unknown op %O", n->op);
|
|
|
|
|
|
|
|
case ONEW:
|
2008-10-29 13:46:44 -06:00
|
|
|
// newarray(nel int, max int, width int) (ary *[]any)
|
2008-08-27 18:28:30 -06:00
|
|
|
t = fixarray(n->type);
|
|
|
|
|
|
|
|
a = nodintconst(t->type->width); // width
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = a;
|
|
|
|
|
|
|
|
a = listfirst(&save, &n->left); // max
|
2008-08-28 16:17:37 -06:00
|
|
|
a = listnext(&save);
|
2008-08-27 18:28:30 -06:00
|
|
|
if(a == N)
|
|
|
|
a = nodintconst(0);
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
2008-08-28 16:17:37 -06:00
|
|
|
a = listfirst(&save, &n->left); // nel
|
|
|
|
if(a == N) {
|
|
|
|
if(t->bound < 0)
|
|
|
|
yyerror("new open array must have size");
|
2008-08-27 18:28:30 -06:00
|
|
|
a = nodintconst(t->bound);
|
2008-08-28 16:17:37 -06:00
|
|
|
}
|
2008-08-27 18:28:30 -06:00
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("newarray", 1);
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
|
|
|
|
walktype(r, top);
|
|
|
|
if(t->etype == TARRAY) {
|
|
|
|
// single case when we can convert a dynamic
|
|
|
|
// array pointer to a static array pointer
|
|
|
|
// saves making a sys function to alloc a static
|
|
|
|
r = nod(OCONV, r, N);
|
|
|
|
r->type = ptrto(t);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OAS:
|
2008-10-29 13:46:44 -06:00
|
|
|
// arrays2d(old *any, nel int) (ary *[]any)
|
2008-08-27 18:28:30 -06:00
|
|
|
t = fixarray(n->right->type);
|
|
|
|
|
|
|
|
a = nodintconst(t->bound); // nel
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = a;
|
|
|
|
|
|
|
|
a = n->right; // old
|
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("arrays2d", 1);
|
|
|
|
argtype(on, n->right->type->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
|
|
|
|
walktype(r, top);
|
|
|
|
n->right = r;
|
|
|
|
return n;
|
|
|
|
|
|
|
|
case OSLICE:
|
2008-08-28 16:17:37 -06:00
|
|
|
if(isptrarray(n->left->type))
|
2008-08-27 18:28:30 -06:00
|
|
|
goto slicestatic;
|
|
|
|
|
2008-10-29 13:46:44 -06:00
|
|
|
// arrayslices(old *[]any, lb int, hb int, width int) (ary *[]any)
|
2008-08-27 18:28:30 -06:00
|
|
|
t = fixarray(n->left->type);
|
|
|
|
|
|
|
|
a = nodintconst(t->type->width); // width
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = a;
|
|
|
|
|
|
|
|
a = nod(OCONV, n->right->right, N); // hb
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
a = nod(OCONV, n->right->left, N); // lb
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
a = n->left; // old
|
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("arraysliced", 1);
|
|
|
|
argtype(on, t->type); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, top);
|
|
|
|
break;
|
|
|
|
|
|
|
|
slicestatic:
|
2008-10-29 13:46:44 -06:00
|
|
|
// arrayslices(old *any, nel int, lb int, hb int, width int) (ary *[]any)
|
2008-08-27 18:28:30 -06:00
|
|
|
t = fixarray(n->left->type);
|
|
|
|
|
|
|
|
a = nodintconst(t->type->width); // width
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = a;
|
|
|
|
|
|
|
|
a = nod(OCONV, n->right->right, N); // hb
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
a = nod(OCONV, n->right->left, N); // lb
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
a = nodintconst(t->bound); // nel
|
|
|
|
a = nod(OCONV, a, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
a->type = types[TINT];
|
2008-08-27 18:28:30 -06:00
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
a = n->left; // old
|
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("arrayslices", 1);
|
|
|
|
argtype(on, t); // any-1
|
|
|
|
argtype(on, t->type); // any-2
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, top);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
int
|
2008-08-12 20:13:09 -06:00
|
|
|
isandss(Type *lt, Node *r)
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-08-12 20:13:09 -06:00
|
|
|
Type *rt;
|
|
|
|
|
|
|
|
rt = r->type;
|
|
|
|
if(isinter(lt)) {
|
2008-10-02 21:51:10 -06:00
|
|
|
if(isinter(rt)) {
|
2008-11-01 17:36:46 -06:00
|
|
|
if(isnilinter(lt) && isnilinter(rt))
|
|
|
|
return Inone;
|
2008-10-02 21:51:10 -06:00
|
|
|
if(!eqtype(rt, lt, 0))
|
|
|
|
return I2I;
|
|
|
|
return Inone;
|
|
|
|
}
|
2008-11-05 12:27:50 -07:00
|
|
|
if(isnilinter(lt) || ismethod(rt) != T)
|
2008-09-22 13:16:19 -06:00
|
|
|
return T2I;
|
2008-10-02 21:51:10 -06:00
|
|
|
return Inone;
|
2008-08-12 20:13:09 -06:00
|
|
|
}
|
|
|
|
|
2008-10-02 21:51:10 -06:00
|
|
|
if(isinter(rt)) {
|
2008-11-05 12:27:50 -07:00
|
|
|
if(isnilinter(rt) || ismethod(lt) != T)
|
2008-09-22 13:16:19 -06:00
|
|
|
return I2T;
|
2008-10-02 21:51:10 -06:00
|
|
|
return Inone;
|
2008-08-12 20:13:09 -06:00
|
|
|
}
|
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
return Inone;
|
|
|
|
}
|
2008-08-12 20:13:09 -06:00
|
|
|
|
2008-11-05 15:27:07 -07:00
|
|
|
static char*
|
|
|
|
ifacename[] =
|
|
|
|
{
|
|
|
|
[I2T] = "ifaceI2T",
|
|
|
|
[I2T2] = "ifaceI2T2",
|
|
|
|
[I2I] = "ifaceI2I",
|
|
|
|
[I2I2] = "ifaceI2I2",
|
|
|
|
};
|
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
Node*
|
|
|
|
ifaceop(Type *tl, Node *n, int op)
|
|
|
|
{
|
|
|
|
Type *tr;
|
|
|
|
Node *r, *a, *on;
|
|
|
|
Sym *s;
|
2008-08-12 20:13:09 -06:00
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
tr = n->type;
|
|
|
|
|
|
|
|
switch(op) {
|
|
|
|
default:
|
2008-11-05 15:27:07 -07:00
|
|
|
fatal("ifaceop: unknown op %O\n", op);
|
2008-09-22 13:16:19 -06:00
|
|
|
|
|
|
|
case T2I:
|
2008-09-22 17:58:30 -06:00
|
|
|
// ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any);
|
2008-09-22 13:16:19 -06:00
|
|
|
|
|
|
|
a = n; // elem
|
|
|
|
r = a;
|
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
s = signame(tr); // sigt
|
2008-09-22 13:16:19 -06:00
|
|
|
if(s == S)
|
|
|
|
fatal("ifaceop: signame-1 T2I: %lT", tr);
|
|
|
|
a = s->oname;
|
|
|
|
a = nod(OADDR, a, N);
|
|
|
|
r = list(a, r);
|
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
s = signame(tl); // sigi
|
2008-09-22 13:16:19 -06:00
|
|
|
if(s == S) {
|
|
|
|
fatal("ifaceop: signame-2 T2I: %lT", tl);
|
|
|
|
}
|
|
|
|
a = s->oname;
|
|
|
|
a = nod(OADDR, a, N);
|
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("ifaceT2I", 1);
|
|
|
|
argtype(on, tr);
|
2008-09-22 17:58:30 -06:00
|
|
|
argtype(on, tl);
|
2008-09-22 13:16:19 -06:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
2008-11-05 15:27:07 -07:00
|
|
|
case I2T:
|
|
|
|
case I2T2:
|
2008-09-22 13:16:19 -06:00
|
|
|
case I2I:
|
2008-11-05 15:27:07 -07:00
|
|
|
case I2I2:
|
|
|
|
// iface[IT]2[IT][2](sigt *byte, iface any) (ret any[, ok bool]);
|
2008-09-22 13:16:19 -06:00
|
|
|
|
|
|
|
a = n; // interface
|
|
|
|
r = a;
|
2008-09-22 17:58:30 -06:00
|
|
|
|
2008-11-05 12:27:50 -07:00
|
|
|
s = signame(tl); // sigi
|
2008-09-22 13:16:19 -06:00
|
|
|
if(s == S)
|
2008-11-05 15:27:07 -07:00
|
|
|
fatal("ifaceop: signame %d", op);
|
2008-09-22 13:16:19 -06:00
|
|
|
a = s->oname;
|
|
|
|
a = nod(OADDR, a, N);
|
|
|
|
r = list(a, r);
|
2008-09-22 17:58:30 -06:00
|
|
|
|
2008-11-05 15:27:07 -07:00
|
|
|
on = syslook(ifacename[op], 1);
|
2008-09-22 13:16:19 -06:00
|
|
|
argtype(on, tr);
|
2008-09-22 17:58:30 -06:00
|
|
|
argtype(on, tl);
|
2008-11-05 15:27:07 -07:00
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
break;
|
2008-10-14 16:08:23 -06:00
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
case ONE:
|
|
|
|
// ifaceeq(i1 any-1, i2 any-2) (ret bool);
|
|
|
|
a = n->right; // i2
|
|
|
|
r = a;
|
|
|
|
|
|
|
|
a = n->left; // i1
|
|
|
|
r = list(a, r);
|
|
|
|
|
|
|
|
on = syslook("ifaceeq", 1);
|
|
|
|
argtype(on, n->right->type);
|
|
|
|
argtype(on, n->left->type);
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
if(op == ONE)
|
|
|
|
r = nod(ONOT, r, N);
|
|
|
|
|
|
|
|
walktype(r, Erv);
|
|
|
|
return r;
|
2008-09-22 13:16:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
walktype(r, Erv);
|
|
|
|
return r;
|
2008-08-12 20:13:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
convas(Node *n)
|
|
|
|
{
|
2008-06-04 15:37:38 -06:00
|
|
|
Node *l, *r;
|
|
|
|
Type *lt, *rt;
|
2008-09-22 13:16:19 -06:00
|
|
|
int et;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
if(n->op != OAS)
|
2008-06-21 16:11:29 -06:00
|
|
|
fatal("convas: not OAS %O", n->op);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-11-01 17:36:46 -06:00
|
|
|
lt = T;
|
|
|
|
rt = T;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
l = n->left;
|
|
|
|
r = n->right;
|
|
|
|
if(l == N || r == N)
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
lt = l->type;
|
|
|
|
rt = r->type;
|
|
|
|
if(lt == T || rt == T)
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
if(n->left->op == OINDEX)
|
|
|
|
if(isptrto(n->left->left->type, TMAP)) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, mapop(n, Elv));
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-16 23:34:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if(n->left->op == OINDEXPTR)
|
|
|
|
if(n->left->left->type->etype == TMAP) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, mapop(n, Elv));
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-16 23:34:50 -06:00
|
|
|
}
|
|
|
|
|
2008-07-13 15:29:46 -06:00
|
|
|
if(n->left->op == OSEND)
|
|
|
|
if(n->left->type != T) {
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, chanop(n, Elv));
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-07-13 15:29:46 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(eqtype(lt, rt, 0))
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-09-22 13:16:19 -06:00
|
|
|
et = isandss(lt, r);
|
|
|
|
if(et != Inone) {
|
|
|
|
n->right = ifaceop(lt, r, et);
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-08-28 16:17:37 -06:00
|
|
|
if(isptrdarray(lt) && isptrarray(rt)) {
|
2008-08-27 18:28:30 -06:00
|
|
|
if(!eqtype(lt->type->type, rt->type->type, 0))
|
|
|
|
goto bad;
|
2008-09-04 18:15:15 -06:00
|
|
|
indir(n, arrayop(n, Etop));
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-08-27 18:28:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ascompat(lt, rt))
|
2008-09-02 18:12:32 -06:00
|
|
|
goto out;
|
2008-08-27 18:28:30 -06:00
|
|
|
|
|
|
|
bad:
|
2008-06-04 15:37:38 -06:00
|
|
|
badtype(n->op, lt, rt);
|
2008-09-02 18:12:32 -06:00
|
|
|
|
|
|
|
out:
|
|
|
|
ullmancalc(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2008-06-21 16:11:29 -06:00
|
|
|
Node*
|
|
|
|
old2new(Node *n, Type *t)
|
|
|
|
{
|
|
|
|
Node *l;
|
|
|
|
|
|
|
|
if(n->op != ONAME && n->op != ONONAME) {
|
|
|
|
yyerror("left side of := must be a name");
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
l = newname(n->sym);
|
|
|
|
dodclvar(l, t);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
colas(Node *nl, Node *nr)
|
|
|
|
{
|
|
|
|
Iter savel, saver;
|
|
|
|
Node *l, *r, *a, *n;
|
|
|
|
Type *t;
|
|
|
|
int cl, cr;
|
|
|
|
|
|
|
|
/* nl is an expression list.
|
|
|
|
* nr is an expression list.
|
|
|
|
* return a newname-list from
|
2008-06-22 22:02:06 -06:00
|
|
|
* types derived from the rhs.
|
2008-06-21 16:11:29 -06:00
|
|
|
*/
|
|
|
|
n = N;
|
|
|
|
cr = listcount(nr);
|
|
|
|
cl = listcount(nl);
|
|
|
|
if(cl != cr) {
|
|
|
|
if(cr == 1)
|
|
|
|
goto multi;
|
|
|
|
goto badt;
|
|
|
|
}
|
|
|
|
|
|
|
|
l = listfirst(&savel, &nl);
|
|
|
|
r = listfirst(&saver, &nr);
|
|
|
|
|
2008-06-22 22:02:06 -06:00
|
|
|
while(l != N) {
|
|
|
|
walktype(r, Erv);
|
|
|
|
defaultlit(r);
|
|
|
|
a = old2new(l, r->type);
|
2008-11-01 17:36:46 -06:00
|
|
|
n = list(n, a);
|
2008-06-22 22:02:06 -06:00
|
|
|
|
|
|
|
l = listnext(&savel);
|
|
|
|
r = listnext(&saver);
|
|
|
|
}
|
2008-07-07 18:59:32 -06:00
|
|
|
n = rev(n);
|
2008-06-22 22:02:06 -06:00
|
|
|
return n;
|
2008-06-21 16:11:29 -06:00
|
|
|
|
|
|
|
multi:
|
|
|
|
/*
|
|
|
|
* there is a list on the left
|
|
|
|
* and a mono on the right.
|
|
|
|
* go into the right to get
|
|
|
|
* individual types for the left.
|
|
|
|
*/
|
|
|
|
switch(nr->op) {
|
|
|
|
default:
|
|
|
|
goto badt;
|
|
|
|
|
|
|
|
case OCALLMETH:
|
|
|
|
case OCALLINTER:
|
|
|
|
case OCALL:
|
|
|
|
walktype(nr->left, Erv);
|
|
|
|
t = nr->left->type;
|
2008-09-22 13:45:01 -06:00
|
|
|
if(t != T && t->etype == tptr)
|
|
|
|
t = t->type;
|
2008-06-21 16:11:29 -06:00
|
|
|
if(t == T || t->etype != TFUNC)
|
|
|
|
goto badt;
|
|
|
|
if(t->outtuple != cl)
|
|
|
|
goto badt;
|
|
|
|
|
|
|
|
l = listfirst(&savel, &nl);
|
|
|
|
t = structfirst(&saver, getoutarg(t));
|
|
|
|
while(l != N) {
|
2008-07-03 18:41:05 -06:00
|
|
|
a = old2new(l, t->type);
|
2008-11-01 17:36:46 -06:00
|
|
|
n = list(n, a);
|
2008-06-21 16:11:29 -06:00
|
|
|
l = listnext(&savel);
|
|
|
|
t = structnext(&saver);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OINDEX:
|
|
|
|
case OINDEXPTR:
|
|
|
|
// check if rhs is a map index.
|
|
|
|
// if so, types are bool,maptype
|
|
|
|
if(cl != 2)
|
|
|
|
goto badt;
|
|
|
|
walktype(nr->left, Elv);
|
|
|
|
t = nr->left->type;
|
|
|
|
if(t != T && isptr[t->etype])
|
|
|
|
t = t->type;
|
|
|
|
if(t == T || t->etype != TMAP)
|
|
|
|
goto badt;
|
|
|
|
|
2008-06-22 22:02:06 -06:00
|
|
|
a = old2new(nl->left, t->type);
|
2008-06-21 16:11:29 -06:00
|
|
|
n = a;
|
2008-06-22 22:02:06 -06:00
|
|
|
a = old2new(nl->right, types[TBOOL]);
|
2008-07-24 16:57:30 -06:00
|
|
|
n = list(n, a);
|
2008-06-21 16:11:29 -06:00
|
|
|
break;
|
2008-07-13 17:20:27 -06:00
|
|
|
|
|
|
|
case ORECV:
|
|
|
|
if(cl != 2)
|
|
|
|
goto badt;
|
|
|
|
walktype(nr->left, Erv);
|
|
|
|
t = nr->left->type;
|
|
|
|
if(!isptrto(t, TCHAN))
|
|
|
|
goto badt;
|
|
|
|
a = old2new(nl->left, t->type->type);
|
|
|
|
n = a;
|
|
|
|
a = old2new(nl->right, types[TBOOL]);
|
2008-07-24 16:57:30 -06:00
|
|
|
n = list(n, a);
|
2008-06-21 16:11:29 -06:00
|
|
|
}
|
2008-07-07 18:59:32 -06:00
|
|
|
n = rev(n);
|
2008-06-21 16:11:29 -06:00
|
|
|
return n;
|
|
|
|
|
|
|
|
badt:
|
|
|
|
yyerror("shape error across :=");
|
|
|
|
return nl;
|
|
|
|
}
|
|
|
|
|
2008-06-24 18:16:06 -06:00
|
|
|
/*
|
|
|
|
* from ascompat[te]
|
|
|
|
* evaluating actual function arguments.
|
|
|
|
* f(a,b)
|
|
|
|
* if there is exactly one function expr,
|
|
|
|
* then it is done first. otherwise must
|
|
|
|
* make temp variables
|
|
|
|
*/
|
2008-06-10 22:29:57 -06:00
|
|
|
Node*
|
|
|
|
reorder1(Node *n)
|
|
|
|
{
|
|
|
|
Iter save;
|
2008-06-11 22:06:26 -06:00
|
|
|
Node *l, *r, *f, *a, *g;
|
2008-06-10 22:29:57 -06:00
|
|
|
int c, t;
|
|
|
|
|
|
|
|
l = listfirst(&save, &n);
|
|
|
|
c = 0; // function calls
|
|
|
|
t = 0; // total parameters
|
|
|
|
|
|
|
|
loop1:
|
|
|
|
if(l == N) {
|
|
|
|
if(c == 0 || t == 1)
|
|
|
|
return n;
|
|
|
|
goto pass2;
|
|
|
|
}
|
|
|
|
if(l->op == OLIST)
|
|
|
|
fatal("reorder1 OLIST");
|
|
|
|
|
|
|
|
t++;
|
|
|
|
if(l->ullman >= UINF)
|
|
|
|
c++;
|
|
|
|
l = listnext(&save);
|
|
|
|
goto loop1;
|
|
|
|
|
|
|
|
pass2:
|
|
|
|
l = listfirst(&save, &n);
|
2008-06-11 22:06:26 -06:00
|
|
|
g = N; // fncalls assigned to tempnames
|
|
|
|
f = N; // one fncall assigned to stack
|
|
|
|
r = N; // non fncalls and tempnames assigned to stack
|
2008-06-10 22:29:57 -06:00
|
|
|
|
|
|
|
loop2:
|
|
|
|
if(l == N) {
|
2008-06-11 13:25:44 -06:00
|
|
|
r = rev(r);
|
2008-06-11 22:06:26 -06:00
|
|
|
g = rev(g);
|
2008-11-01 17:36:46 -06:00
|
|
|
f = list(g, f);
|
2008-07-24 16:57:30 -06:00
|
|
|
r = list(f, r);
|
2008-06-11 13:25:44 -06:00
|
|
|
return r;
|
2008-06-10 22:29:57 -06:00
|
|
|
}
|
2008-06-11 22:06:26 -06:00
|
|
|
if(l->ullman < UINF) {
|
2008-11-01 17:36:46 -06:00
|
|
|
r = list(l, r);
|
2008-06-11 22:06:26 -06:00
|
|
|
goto more;
|
|
|
|
}
|
|
|
|
if(f == N) {
|
2008-06-10 22:29:57 -06:00
|
|
|
f = l;
|
2008-06-11 22:06:26 -06:00
|
|
|
goto more;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make assignment of fncall to tempname
|
|
|
|
a = nod(OXXX, N, N);
|
|
|
|
tempname(a, l->right->type);
|
|
|
|
a = nod(OAS, a, l->right);
|
2008-11-01 17:36:46 -06:00
|
|
|
g = list(a, g);
|
2008-06-11 22:06:26 -06:00
|
|
|
|
|
|
|
// put normal arg assignment on list
|
|
|
|
// with fncall replaced by tempname
|
|
|
|
l->right = a->left;
|
2008-11-01 17:36:46 -06:00
|
|
|
r = list(l, r);
|
2008-06-10 22:29:57 -06:00
|
|
|
|
2008-06-11 22:06:26 -06:00
|
|
|
more:
|
2008-06-10 22:29:57 -06:00
|
|
|
l = listnext(&save);
|
|
|
|
goto loop2;
|
|
|
|
}
|
|
|
|
|
2008-06-24 18:16:06 -06:00
|
|
|
/*
|
|
|
|
* from ascompat[et]
|
|
|
|
* a,b = f()
|
|
|
|
* return of a multi.
|
|
|
|
* there can be no function calls at all,
|
|
|
|
* or they will over-write the return values.
|
|
|
|
*/
|
2008-06-10 22:29:57 -06:00
|
|
|
Node*
|
|
|
|
reorder2(Node *n)
|
|
|
|
{
|
|
|
|
Iter save;
|
|
|
|
Node *l;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
l = listfirst(&save, &n);
|
|
|
|
c = 0;
|
|
|
|
|
|
|
|
loop1:
|
|
|
|
if(l == N) {
|
|
|
|
if(c > 0)
|
|
|
|
yyerror("reorder2: too many funcation calls evaluating parameters");
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
if(l->op == OLIST)
|
|
|
|
fatal("reorder2 OLIST");
|
|
|
|
|
|
|
|
if(l->ullman >= UINF)
|
|
|
|
c++;
|
|
|
|
l = listnext(&save);
|
|
|
|
goto loop1;
|
|
|
|
}
|
|
|
|
|
2008-06-24 18:16:06 -06:00
|
|
|
/*
|
|
|
|
* from ascompat[ee]
|
|
|
|
* a,b = c,d
|
2008-06-25 12:35:06 -06:00
|
|
|
* simultaneous assignment. there cannot
|
|
|
|
* be later use of an earlier lvalue.
|
2008-06-24 18:16:06 -06:00
|
|
|
*/
|
|
|
|
int
|
2008-06-25 12:35:06 -06:00
|
|
|
vmatch2(Node *l, Node *r)
|
2008-06-24 18:16:06 -06:00
|
|
|
{
|
2008-06-25 12:35:06 -06:00
|
|
|
|
|
|
|
loop:
|
|
|
|
/*
|
|
|
|
* isolate all right sides
|
|
|
|
*/
|
|
|
|
if(r == N)
|
|
|
|
return 0;
|
|
|
|
switch(r->op) {
|
|
|
|
case ONAME:
|
|
|
|
// match each right given left
|
|
|
|
if(l == r)
|
|
|
|
return 1;
|
|
|
|
case OLITERAL:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(vmatch2(l, r->right))
|
|
|
|
return 1;
|
|
|
|
r = r->left;
|
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
vmatch1(Node *l, Node *r)
|
|
|
|
{
|
|
|
|
|
|
|
|
loop:
|
|
|
|
/*
|
|
|
|
* isolate all left sides
|
|
|
|
*/
|
|
|
|
if(l == N)
|
|
|
|
return 0;
|
|
|
|
switch(l->op) {
|
|
|
|
case ONAME:
|
|
|
|
// match each left with all rights
|
|
|
|
return vmatch2(l, r);
|
|
|
|
case OLITERAL:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(vmatch1(l->right, r))
|
|
|
|
return 1;
|
|
|
|
l = l->left;
|
|
|
|
goto loop;
|
2008-06-24 18:16:06 -06:00
|
|
|
}
|
|
|
|
|
2008-06-10 22:29:57 -06:00
|
|
|
Node*
|
|
|
|
reorder3(Node *n)
|
|
|
|
{
|
2008-06-24 18:16:06 -06:00
|
|
|
Iter save1, save2;
|
2008-06-25 12:35:06 -06:00
|
|
|
Node *l1, *l2, *q, *r;
|
2008-06-24 18:16:06 -06:00
|
|
|
int c1, c2;
|
|
|
|
|
2008-06-25 12:35:06 -06:00
|
|
|
r = N;
|
|
|
|
|
2008-06-24 18:16:06 -06:00
|
|
|
l1 = listfirst(&save1, &n);
|
|
|
|
c1 = 0;
|
|
|
|
|
|
|
|
while(l1 != N) {
|
2008-06-25 12:35:06 -06:00
|
|
|
l2 = listfirst(&save2, &n);
|
2008-06-24 18:16:06 -06:00
|
|
|
c2 = 0;
|
|
|
|
while(l2 != N) {
|
|
|
|
if(c2 > c1) {
|
2008-06-25 12:35:06 -06:00
|
|
|
if(vmatch1(l1->left, l2->right)) {
|
|
|
|
q = nod(OXXX, N, N);
|
2008-09-27 18:46:40 -06:00
|
|
|
tempname(q, l1->right->type);
|
2008-06-25 12:35:06 -06:00
|
|
|
q = nod(OAS, l1->left, q);
|
|
|
|
l1->left = q->right;
|
2008-09-27 18:46:40 -06:00
|
|
|
r = list(r, q);
|
2008-06-25 12:35:06 -06:00
|
|
|
break;
|
2008-06-24 18:16:06 -06:00
|
|
|
}
|
|
|
|
}
|
2008-06-25 12:35:06 -06:00
|
|
|
l2 = listnext(&save2);
|
2008-06-24 18:16:06 -06:00
|
|
|
c2++;
|
|
|
|
}
|
|
|
|
l1 = listnext(&save1);
|
|
|
|
c1++;
|
|
|
|
}
|
2008-06-25 12:35:06 -06:00
|
|
|
if(r == N)
|
|
|
|
return n;
|
|
|
|
|
|
|
|
q = N;
|
|
|
|
l1 = listfirst(&save1, &n);
|
|
|
|
while(l1 != N) {
|
2008-11-01 17:36:46 -06:00
|
|
|
q = list(q, l1);
|
2008-06-25 12:35:06 -06:00
|
|
|
l1 = listnext(&save1);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = rev(r);
|
|
|
|
l1 = listfirst(&save1, &r);
|
|
|
|
while(l1 != N) {
|
2008-11-01 17:36:46 -06:00
|
|
|
q = list(q, l1);
|
2008-06-25 12:35:06 -06:00
|
|
|
l1 = listnext(&save1);
|
|
|
|
}
|
|
|
|
|
|
|
|
q = rev(q);
|
|
|
|
//dump("res", q);
|
|
|
|
return q;
|
2008-06-10 22:29:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Node*
|
|
|
|
reorder4(Node *n)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* from ascompat[te]
|
|
|
|
* return c,d
|
|
|
|
* return expression assigned to output
|
|
|
|
* parameters. there may be no problems.
|
|
|
|
*/
|
|
|
|
return n;
|
|
|
|
}
|
2008-09-02 17:21:30 -06:00
|
|
|
|
|
|
|
Node*
|
|
|
|
structlit(Node *n)
|
|
|
|
{
|
|
|
|
Iter savel, saver;
|
|
|
|
Type *l, *t;
|
|
|
|
Node *var, *r, *a;
|
|
|
|
|
|
|
|
t = n->type;
|
|
|
|
if(t->etype != TSTRUCT)
|
|
|
|
fatal("structlit: not struct");
|
|
|
|
|
|
|
|
var = nod(OXXX, N, N);
|
|
|
|
tempname(var, t);
|
|
|
|
|
|
|
|
l = structfirst(&savel, &n->type);
|
|
|
|
r = listfirst(&saver, &n->left);
|
2008-09-29 21:33:51 -06:00
|
|
|
if(r != N && r->op == OEMPTY)
|
|
|
|
r = N;
|
2008-09-02 17:21:30 -06:00
|
|
|
|
|
|
|
loop:
|
|
|
|
if(l == T || r == N) {
|
2008-09-08 14:10:11 -06:00
|
|
|
if(l != T)
|
|
|
|
yyerror("struct literal expect expr of type %T", l);
|
|
|
|
if(r != N)
|
|
|
|
yyerror("struct literal too many expressions");
|
2008-09-02 17:21:30 -06:00
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
|
|
|
// build list of var.field = expr
|
|
|
|
|
|
|
|
a = nod(ODOT, var, newname(l->sym));
|
|
|
|
a = nod(OAS, a, r);
|
|
|
|
addtop = list(addtop, a);
|
|
|
|
|
|
|
|
l = structnext(&savel);
|
|
|
|
r = listnext(&saver);
|
|
|
|
goto loop;
|
|
|
|
}
|
2008-09-03 15:09:29 -06:00
|
|
|
|
|
|
|
Node*
|
|
|
|
arraylit(Node *n)
|
|
|
|
{
|
|
|
|
Iter saver;
|
|
|
|
Type *t;
|
|
|
|
Node *var, *r, *a;
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
t = n->type;
|
|
|
|
if(t->etype != TARRAY)
|
|
|
|
fatal("arraylit: not array");
|
|
|
|
|
|
|
|
if(t->bound < 0) {
|
2008-09-22 13:16:19 -06:00
|
|
|
// make a shallow copy
|
|
|
|
t = typ(0);
|
|
|
|
*t = *n->type;
|
|
|
|
n->type = t;
|
|
|
|
|
2008-09-03 15:09:29 -06:00
|
|
|
// make it a closed array
|
|
|
|
r = listfirst(&saver, &n->left);
|
2008-09-29 21:33:51 -06:00
|
|
|
if(r != N && r->op == OEMPTY)
|
|
|
|
r = N;
|
2008-09-03 15:09:29 -06:00
|
|
|
for(idx=0; r!=N; idx++)
|
|
|
|
r = listnext(&saver);
|
|
|
|
t->bound = idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
var = nod(OXXX, N, N);
|
|
|
|
tempname(var, t);
|
|
|
|
|
|
|
|
idx = 0;
|
|
|
|
r = listfirst(&saver, &n->left);
|
2008-09-29 21:33:51 -06:00
|
|
|
if(r != N && r->op == OEMPTY)
|
|
|
|
r = N;
|
2008-09-03 15:09:29 -06:00
|
|
|
|
|
|
|
loop:
|
2008-09-03 15:40:22 -06:00
|
|
|
if(r == N)
|
2008-09-03 15:09:29 -06:00
|
|
|
return var;
|
|
|
|
|
|
|
|
// build list of var[c] = expr
|
|
|
|
|
|
|
|
a = nodintconst(idx);
|
|
|
|
a = nod(OINDEX, var, a);
|
|
|
|
a = nod(OAS, a, r);
|
|
|
|
addtop = list(addtop, a);
|
|
|
|
idx++;
|
|
|
|
|
|
|
|
r = listnext(&saver);
|
|
|
|
goto loop;
|
|
|
|
}
|
2008-09-03 15:40:22 -06:00
|
|
|
|
|
|
|
Node*
|
|
|
|
maplit(Node *n)
|
|
|
|
{
|
|
|
|
Iter saver;
|
|
|
|
Type *t;
|
|
|
|
Node *var, *r, *a;
|
|
|
|
|
|
|
|
t = n->type;
|
|
|
|
if(t->etype != TMAP)
|
|
|
|
fatal("maplit: not array");
|
|
|
|
t = ptrto(t);
|
|
|
|
|
|
|
|
var = nod(OXXX, N, N);
|
|
|
|
tempname(var, t);
|
|
|
|
|
|
|
|
a = nod(ONEW, N, N);
|
|
|
|
a->type = t;
|
|
|
|
a = nod(OAS, var, a);
|
|
|
|
addtop = list(addtop, a);
|
|
|
|
|
|
|
|
r = listfirst(&saver, &n->left);
|
2008-09-29 21:33:51 -06:00
|
|
|
if(r != N && r->op == OEMPTY)
|
|
|
|
r = N;
|
2008-09-03 15:40:22 -06:00
|
|
|
|
|
|
|
loop:
|
|
|
|
if(r == N) {
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r->op != OKEY) {
|
|
|
|
yyerror("map literal must have key:value pairs");
|
|
|
|
return var;
|
|
|
|
}
|
|
|
|
|
|
|
|
// build list of var[c] = expr
|
|
|
|
|
|
|
|
a = nod(OINDEX, var, r->left);
|
|
|
|
a = nod(OAS, a, r->right);
|
|
|
|
addtop = list(addtop, a);
|
|
|
|
|
|
|
|
r = listnext(&saver);
|
|
|
|
goto loop;
|
|
|
|
}
|