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;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
walk(Node *fn)
|
|
|
|
|
{
|
2008-06-17 23:33:32 -06:00
|
|
|
|
if(debug['W'])
|
|
|
|
|
dump("fn-before", fn->nbody);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
curfn = fn;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(fn->nbody, Etop);
|
2008-06-17 23:33:32 -06:00
|
|
|
|
if(debug['W'])
|
|
|
|
|
dump("fn", fn->nbody);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
}
|
|
|
|
|
|
2008-07-25 18:03:27 -06:00
|
|
|
|
int
|
|
|
|
|
isselect(Node *n)
|
|
|
|
|
{
|
|
|
|
|
Sym *s;
|
|
|
|
|
|
|
|
|
|
if(n == N)
|
|
|
|
|
return 0;
|
|
|
|
|
n = n->left;
|
|
|
|
|
s = pkglookup("selectsend", "sys");
|
|
|
|
|
if(s == n->sym)
|
|
|
|
|
return 1;
|
|
|
|
|
s = pkglookup("selectrecv", "sys");
|
|
|
|
|
if(s == n->sym)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
void
|
|
|
|
|
walktype(Node *n, int top)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(top == Exxx || top == Eyyy) {
|
|
|
|
|
dump("", n);
|
2008-06-21 16:11:29 -06:00
|
|
|
|
fatal("walktype: bad top=%d", top);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
case OPRINT:
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(top != Etop)
|
|
|
|
|
goto nottop;
|
|
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
*n = *prcompat(n->left);
|
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
case OPANIC:
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(top != Etop)
|
|
|
|
|
goto nottop;
|
|
|
|
|
walktype(n->left, Erv);
|
2008-07-24 16:57:30 -06:00
|
|
|
|
*n = *list(prcompat(n->left), 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) {
|
|
|
|
|
yyerror("walktype: %N undeclared", n);
|
|
|
|
|
s->undef = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
case OLIST:
|
|
|
|
|
walktype(n->left, top);
|
|
|
|
|
n = n->right;
|
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
|
|
case OFOR:
|
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->ninit, Etop);
|
2008-07-05 13:49:25 -06:00
|
|
|
|
walkbool(n->ntest);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(n->nincr, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
n = n->nbody;
|
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
|
|
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-06-15 21:24:30 -06:00
|
|
|
|
walktype(n->ninit, Etop);
|
|
|
|
|
walktype(n->ntest, Erv);
|
|
|
|
|
walktype(n->nbody, Etop);
|
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;
|
|
|
|
|
|
|
|
|
|
case OSCASE:
|
|
|
|
|
if(top != Etop)
|
|
|
|
|
goto nottop;
|
|
|
|
|
// walktype(n->left, Erv); SPECIAL
|
|
|
|
|
n = n->right;
|
|
|
|
|
goto loop;
|
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
case OEMPTY:
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(top != Etop)
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto nottop;
|
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
case OIF:
|
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->ninit, Etop);
|
2008-07-05 13:49:25 -06:00
|
|
|
|
walkbool(n->ntest);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(n->nelse, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
n = n->nbody;
|
|
|
|
|
goto loop;
|
|
|
|
|
|
2008-07-07 13:29:26 -06:00
|
|
|
|
case OPROC:
|
|
|
|
|
if(top != Etop)
|
|
|
|
|
goto nottop;
|
2008-07-07 18:59:32 -06:00
|
|
|
|
walktype(n->left, Etop);
|
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;
|
|
|
|
|
|
|
|
|
|
dowidth(t);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n->type = *getoutarg(t);
|
|
|
|
|
if(t->outtuple == 1)
|
|
|
|
|
n->type = n->type->type->type;
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
*n = *reorder3(l);
|
|
|
|
|
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);
|
|
|
|
|
if(l != N) {
|
2008-07-24 16:57:30 -06:00
|
|
|
|
*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
|
|
|
|
|
if(!isptrto(r->left->type, TMAP))
|
|
|
|
|
break;
|
|
|
|
|
l = mapop(n, top);
|
|
|
|
|
if(l == N)
|
|
|
|
|
break;
|
|
|
|
|
*n = *l;
|
|
|
|
|
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;
|
|
|
|
|
*n = *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;
|
|
|
|
|
*n = *l;
|
|
|
|
|
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);
|
|
|
|
|
n = n->right;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
case OS2I:
|
|
|
|
|
case OI2S:
|
|
|
|
|
case OI2I:
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(top != Erv)
|
|
|
|
|
goto nottop;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
n->addable = 0;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(n->left, Erv);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
case OCONV:
|
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;
|
|
|
|
|
|
|
|
|
|
convlit(n->left, n->type);
|
|
|
|
|
|
|
|
|
|
// nil conversion
|
|
|
|
|
if(eqtype(n->type, n->left->type, 0)) {
|
|
|
|
|
if(n->left->op != ONAME)
|
|
|
|
|
*n = *n->left;
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// simple fix-float
|
2008-06-08 13:48:37 -06:00
|
|
|
|
if(n->left->type != T)
|
2008-06-04 15:37:38 -06:00
|
|
|
|
if(isint[n->left->type->etype] || isfloat[n->left->type->etype])
|
|
|
|
|
if(isint[n->type->etype] || isfloat[n->type->etype]) {
|
|
|
|
|
evconst(n);
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// to string
|
|
|
|
|
if(isptrto(n->type, TSTRING)) {
|
|
|
|
|
if(isint[n->left->type->etype]) {
|
2008-06-15 21:24:30 -06:00
|
|
|
|
*n = *stringop(n, top);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
if(isbytearray(n->left->type) != 0) {
|
|
|
|
|
n->op = OARRAY;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
*n = *stringop(n, top);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 13:48:37 -06:00
|
|
|
|
if(n->type->etype == TARRAY) {
|
|
|
|
|
arrayconv(n->type, n->left);
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
badtype(n->op, n->left->type, n->type);
|
|
|
|
|
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;
|
|
|
|
|
if(l->op != OINDEX)
|
|
|
|
|
goto com;
|
|
|
|
|
if(!isptrto(l->left->type, TMAP))
|
|
|
|
|
goto com;
|
|
|
|
|
*n = *mapop(n, top);
|
|
|
|
|
goto loop;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
|
|
case OLSH:
|
|
|
|
|
case ORSH:
|
|
|
|
|
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;
|
|
|
|
|
if(!ascompat(n->left->type, n->right->type))
|
|
|
|
|
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-06-15 21:24:30 -06:00
|
|
|
|
*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
|
|
|
|
case TDARRAY:
|
|
|
|
|
break;
|
|
|
|
|
case TARRAY:
|
|
|
|
|
nodconst(n, types[TINT32], t->bound);
|
2008-06-24 15:11:20 -06:00
|
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
}
|
|
|
|
|
n->type = types[TINT32];
|
|
|
|
|
goto ret;
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
convlit(n->right, types[TINT32]);
|
|
|
|
|
if(n->right->type == T)
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
if(!isint[n->right->type->etype])
|
|
|
|
|
goto badt;
|
|
|
|
|
*n = *stringop(n, top);
|
|
|
|
|
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-06-21 16:11:29 -06:00
|
|
|
|
*n = *mapop(n, top);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case TARRAY:
|
|
|
|
|
case TDARRAY:
|
|
|
|
|
// right side must be an int
|
|
|
|
|
if(n->right->type == T) {
|
|
|
|
|
convlit(n->right, types[TINT32]);
|
|
|
|
|
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-07-15 22:07:59 -06:00
|
|
|
|
*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) {
|
|
|
|
|
walktype(n->left, Erv); // chan
|
|
|
|
|
*n = *chanop(n, top); // returns e blocking
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
walktype(n->left, Elv); // e
|
|
|
|
|
walktype(n->right, Erv); // chan
|
|
|
|
|
*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;
|
|
|
|
|
if(isptrto(n->left->type, TSTRING)) {
|
2008-06-15 21:24:30 -06:00
|
|
|
|
*n = *stringop(n, top);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
walkdot(n, top);
|
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;
|
|
|
|
|
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;
|
|
|
|
|
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-06-04 15:37:38 -06:00
|
|
|
|
*n = *newcompat(n);
|
|
|
|
|
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:
|
|
|
|
|
et = n->left->type->etype;
|
|
|
|
|
if(et != TBOOL)
|
|
|
|
|
goto badt;
|
|
|
|
|
t = types[TBOOL];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
|
case ONE:
|
|
|
|
|
et = n->left->type->etype;
|
|
|
|
|
if(!okforeq[et])
|
|
|
|
|
goto badt;
|
|
|
|
|
t = types[TBOOL];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OLT:
|
|
|
|
|
case OLE:
|
|
|
|
|
case OGE:
|
|
|
|
|
case OGT:
|
|
|
|
|
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:
|
|
|
|
|
et = n->left->type->etype;
|
|
|
|
|
if(!okforadd[et])
|
|
|
|
|
goto badt;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OMINUS:
|
|
|
|
|
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);
|
|
|
|
|
*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:
|
|
|
|
|
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);
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
return types[TINT32]; // botch
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
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)
|
|
|
|
|
return;
|
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 18:03:27 -06:00
|
|
|
|
Iter iter;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
|
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)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
convlit(c->right, t->type);
|
|
|
|
|
if(!ascompat(t->type, c->right->type)) {
|
|
|
|
|
badtype(c->op, t->type, c->right->type);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
recv2:
|
2008-07-25 12:58:26 -06:00
|
|
|
|
walktype(c->right, Erv); // chan
|
|
|
|
|
|
|
|
|
|
t = fixchan(c->right->type);
|
|
|
|
|
if(t == T)
|
|
|
|
|
return;
|
|
|
|
|
|
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);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
nodconst(r, types[TINT32], count); // count
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
|
r = nod(OAS, var, r);
|
|
|
|
|
|
|
|
|
|
sel->ninit = r;
|
|
|
|
|
sel->nbody = rev(res);
|
|
|
|
|
sel->left = N;
|
|
|
|
|
|
|
|
|
|
walktype(sel->ninit, Etop);
|
|
|
|
|
walktype(sel->nbody, Etop);
|
|
|
|
|
|
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-06-04 15:37:38 -06:00
|
|
|
|
/*
|
|
|
|
|
* allowable type combinations for
|
|
|
|
|
* normal binary operations.
|
|
|
|
|
*/
|
|
|
|
|
Type*
|
|
|
|
|
lookdot(Node *n, Type *t, int d)
|
|
|
|
|
{
|
|
|
|
|
Type *f, *r, *c;
|
|
|
|
|
Sym *s;
|
|
|
|
|
|
|
|
|
|
r = T;
|
|
|
|
|
s = n->sym;
|
|
|
|
|
if(d > 0)
|
|
|
|
|
goto deep;
|
|
|
|
|
|
|
|
|
|
for(f=t->type; f!=T; f=f->down) {
|
|
|
|
|
if(f->sym == S)
|
|
|
|
|
continue;
|
|
|
|
|
if(f->sym != s)
|
|
|
|
|
continue;
|
|
|
|
|
if(r != T) {
|
|
|
|
|
yyerror("ambiguous DOT reference %s", s->name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
r = f;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
deep:
|
|
|
|
|
/* deeper look after shallow failed */
|
|
|
|
|
for(f=t->type; f!=T; f=f->down) {
|
|
|
|
|
// only look at unnamed sub-structures
|
|
|
|
|
// BOTCH no such thing -- all are assigned temp names
|
|
|
|
|
if(f->sym != S)
|
|
|
|
|
continue;
|
|
|
|
|
c = f->type;
|
|
|
|
|
if(c->etype != TSTRUCT)
|
|
|
|
|
continue;
|
|
|
|
|
c = lookdot(n, c, d-1);
|
|
|
|
|
if(c == T)
|
|
|
|
|
continue;
|
|
|
|
|
if(r != T) {
|
|
|
|
|
yyerror("ambiguous unnamed DOT reference %s", s->name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
r = c;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walkdot(Node *n, int top)
|
2008-06-04 15:37:38 -06:00
|
|
|
|
{
|
|
|
|
|
Node *mn;
|
|
|
|
|
Type *t, *f;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if(n->left == N || n->right == N)
|
|
|
|
|
return;
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if(isptr[t->etype]) {
|
|
|
|
|
t = t->type;
|
|
|
|
|
if(t == T)
|
|
|
|
|
return;
|
|
|
|
|
n->op = ODOTPTR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(n->right->op != ONAME)
|
|
|
|
|
fatal("walkdot: not name %O", n->right->op);
|
|
|
|
|
|
|
|
|
|
switch(t->etype) {
|
|
|
|
|
default:
|
|
|
|
|
badtype(ODOT, t, T);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case TSTRUCT:
|
|
|
|
|
case TINTER:
|
|
|
|
|
for(i=0; i<5; i++) {
|
|
|
|
|
f = lookdot(n->right, t, i);
|
|
|
|
|
if(f != T)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// look up the field as TYPE_name
|
|
|
|
|
// for a mothod. botch this should
|
|
|
|
|
// be done better.
|
|
|
|
|
if(f == T && t->etype == TSTRUCT) {
|
|
|
|
|
mn = methodname(n->right, t);
|
|
|
|
|
for(i=0; i<5; i++) {
|
|
|
|
|
f = lookdot(mn, t, i);
|
|
|
|
|
if(f != T)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(f == T) {
|
|
|
|
|
yyerror("undefined DOT reference %N", n->right);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n->xoffset = f->width;
|
|
|
|
|
n->right = f->nname; // substitute real name
|
|
|
|
|
n->type = f->type;
|
|
|
|
|
if(n->type->etype == TFUNC) {
|
|
|
|
|
n->op = ODOTMETH;
|
|
|
|
|
if(t->etype == TINTER) {
|
|
|
|
|
n->op = ODOTINTER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
if(nn == N)
|
|
|
|
|
nn = a;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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);
|
|
|
|
|
if(nn == N)
|
|
|
|
|
nn = a;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -06:00
|
|
|
|
nn = list(a, nn);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
|
|
l = listnext(&savel);
|
|
|
|
|
r = structnext(&saver);
|
|
|
|
|
|
|
|
|
|
goto loop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Node*
|
|
|
|
|
ascompatte(int op, Type **nl, Node **nr, int fp)
|
|
|
|
|
{
|
|
|
|
|
Type *l;
|
|
|
|
|
Node *r, *nn, *a;
|
|
|
|
|
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;
|
|
|
|
|
loop:
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = nod(OAS, nodarg(l, fp), r);
|
|
|
|
|
a = convas(a);
|
|
|
|
|
if(nn == N)
|
|
|
|
|
nn = a;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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;
|
|
|
|
|
|
|
|
|
|
if(isinter(t1))
|
|
|
|
|
if(isptrto(t2, TSTRUCT) || isinter(t2))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
if(isinter(t2))
|
|
|
|
|
if(isptrto(t1, TSTRUCT))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Node*
|
|
|
|
|
prcompat(Node *n)
|
|
|
|
|
{
|
|
|
|
|
Node *l, *r;
|
|
|
|
|
Type *t;
|
|
|
|
|
Iter save;
|
|
|
|
|
int w;
|
|
|
|
|
char *name;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
Node *on;
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
|
|
r = N;
|
|
|
|
|
l = listfirst(&save, &n);
|
|
|
|
|
|
|
|
|
|
loop:
|
|
|
|
|
if(l == N) {
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(r, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w = whatis(l);
|
|
|
|
|
switch(w) {
|
|
|
|
|
default:
|
2008-07-16 13:44:21 -06:00
|
|
|
|
if(!isptr[l->type->etype]) {
|
|
|
|
|
badtype(n->op, l->type, T);
|
|
|
|
|
l = listnext(&save);
|
|
|
|
|
goto loop;
|
|
|
|
|
}
|
|
|
|
|
on = syslook("printpointer", 1);
|
|
|
|
|
argtype(on, l->type->type); // any-1
|
|
|
|
|
break;
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(r == N)
|
2008-06-15 21:24:30 -06:00
|
|
|
|
r = nod(OCALL, on, l);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
else
|
2008-07-24 16:57:30 -06:00
|
|
|
|
r = list(r, nod(OCALL, on, l));
|
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);
|
|
|
|
|
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;
|
|
|
|
|
if(t->etype == TMAP) {
|
|
|
|
|
r = mapop(n, Erv);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
2008-07-12 14:08:53 -06:00
|
|
|
|
if(t->etype == TCHAN) {
|
|
|
|
|
r = chanop(n, Erv);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
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-08-03 18:25:15 -06:00
|
|
|
|
int32 l;
|
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);
|
|
|
|
|
r->type = types[TINT32];
|
|
|
|
|
|
|
|
|
|
c = nod(OCONV, n->right->right, N);
|
|
|
|
|
c->type = types[TINT32];
|
|
|
|
|
|
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);
|
|
|
|
|
r->type = types[TINT32];
|
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:
|
|
|
|
|
// byteastring(a, l)
|
|
|
|
|
c = nodintconst(0);
|
|
|
|
|
r = nod(OINDEX, n->left, c);
|
|
|
|
|
r = nod(OADDR, r, N);
|
|
|
|
|
|
|
|
|
|
l = isbytearray(n->left->type);
|
|
|
|
|
c = nodintconst(l-1);
|
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
|
r = list(r, c);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
on = syslook("byteastring", 0);
|
|
|
|
|
r = nod(OCALL, on, r);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
walktype(r, top);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Type*
|
|
|
|
|
fixmap(Type *tm)
|
|
|
|
|
{
|
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
|
|
t = tm->type;
|
|
|
|
|
if(t == T) {
|
|
|
|
|
fatal("fixmap: t nil");
|
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(t->etype != TMAP) {
|
2008-07-15 22:07:59 -06:00
|
|
|
|
fatal("fixmap: %lT not map", tm);
|
2008-06-15 21:24:30 -06:00
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(t->down == T || t->type == T) {
|
|
|
|
|
fatal("fixmap: map key/value types are nil");
|
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dowidth(t->down);
|
|
|
|
|
dowidth(t->type);
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-12 14:08:53 -06:00
|
|
|
|
Type*
|
|
|
|
|
fixchan(Type *tm)
|
|
|
|
|
{
|
|
|
|
|
Type *t;
|
|
|
|
|
|
|
|
|
|
t = tm->type;
|
|
|
|
|
if(t == T) {
|
|
|
|
|
fatal("fixchan: t nil");
|
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(t->etype != TCHAN) {
|
2008-07-15 22:07:59 -06:00
|
|
|
|
fatal("fixchan: %lT not chan", tm);
|
2008-07-12 14:08:53 -06:00
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(t->type == T) {
|
|
|
|
|
fatal("fixchan: chan element type is nil");
|
|
|
|
|
return T;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dowidth(t->type);
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
|
static int
|
|
|
|
|
algtype(Type *t)
|
|
|
|
|
{
|
|
|
|
|
int a;
|
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
|
a = 100;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
if(issimple[t->etype])
|
2008-06-16 23:34:50 -06:00
|
|
|
|
a = 0; // simple mem
|
2008-06-15 21:24:30 -06:00
|
|
|
|
else
|
|
|
|
|
if(isptrto(t, TSTRING))
|
2008-06-16 23:34:50 -06:00
|
|
|
|
a = 1; // string
|
2008-06-15 21:24:30 -06:00
|
|
|
|
else
|
|
|
|
|
if(isptr[t->etype])
|
2008-06-16 23:34:50 -06:00
|
|
|
|
a = 2; // pointer
|
2008-06-15 21:24:30 -06:00
|
|
|
|
else
|
|
|
|
|
if(isinter(t))
|
2008-06-16 23:34:50 -06:00
|
|
|
|
a = 3; // interface
|
2008-06-15 21:24:30 -06:00
|
|
|
|
else
|
|
|
|
|
fatal("algtype: cant find type %T", t);
|
|
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Node*
|
|
|
|
|
mapop(Node *n, int top)
|
|
|
|
|
{
|
|
|
|
|
Node *r, *a;
|
|
|
|
|
Type *t;
|
|
|
|
|
Node *on;
|
2008-06-24 15:11:20 -06:00
|
|
|
|
int alg1, alg2, 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-06-15 21:24:30 -06:00
|
|
|
|
// newmap(keysize uint32, valsize uint32,
|
|
|
|
|
// keyalg uint32, valalg uint32,
|
2008-06-16 23:34:50 -06:00
|
|
|
|
// hint uint32) (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);
|
|
|
|
|
|
|
|
|
|
//dump("assign1", n);
|
|
|
|
|
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);
|
|
|
|
|
walktype(r, Erv);
|
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);
|
2008-06-16 23:34:50 -06:00
|
|
|
|
|
2008-06-24 15:11:20 -06:00
|
|
|
|
//dump("assign2", n);
|
|
|
|
|
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);
|
|
|
|
|
walktype(r, Erv);
|
|
|
|
|
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);
|
|
|
|
|
*a = *n->left; // copy of map[tmpi]
|
|
|
|
|
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-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;
|
|
|
|
|
int alg, cl, cr;
|
|
|
|
|
|
|
|
|
|
//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:
|
|
|
|
|
// newchan(elemsize uint32, elemalg uint32,
|
|
|
|
|
// hint uint32) (hmap *chan[any-1]);
|
|
|
|
|
|
|
|
|
|
t = fixchan(n->type);
|
|
|
|
|
if(t == T)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
a = n->left; // hint
|
|
|
|
|
if(n->left == N)
|
|
|
|
|
a = nodintconst(0);
|
|
|
|
|
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);
|
|
|
|
|
walktype(r, top);
|
|
|
|
|
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);
|
|
|
|
|
walktype(r, top);
|
|
|
|
|
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-06-04 15:37:38 -06:00
|
|
|
|
void
|
|
|
|
|
diagnamed(Type *t)
|
|
|
|
|
{
|
|
|
|
|
if(isinter(t))
|
|
|
|
|
if(t->sym == S)
|
|
|
|
|
yyerror("interface type must be named");
|
|
|
|
|
if(isptrto(t, TSTRUCT))
|
|
|
|
|
if(t->type == T || t->type->sym == S)
|
|
|
|
|
yyerror("structure type must be named");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Node*
|
|
|
|
|
convas(Node *n)
|
|
|
|
|
{
|
|
|
|
|
int o;
|
|
|
|
|
Node *l, *r;
|
|
|
|
|
Type *lt, *rt;
|
|
|
|
|
|
|
|
|
|
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-06-11 13:25:44 -06:00
|
|
|
|
ullmancalc(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
l = n->left;
|
|
|
|
|
r = n->right;
|
|
|
|
|
if(l == N || r == N)
|
|
|
|
|
return n;
|
|
|
|
|
|
|
|
|
|
lt = l->type;
|
|
|
|
|
rt = r->type;
|
|
|
|
|
if(lt == T || rt == T)
|
|
|
|
|
return n;
|
|
|
|
|
|
2008-06-16 23:34:50 -06:00
|
|
|
|
if(n->left->op == OINDEX)
|
|
|
|
|
if(isptrto(n->left->left->type, TMAP)) {
|
|
|
|
|
*n = *mapop(n, Elv);
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(n->left->op == OINDEXPTR)
|
|
|
|
|
if(n->left->left->type->etype == TMAP) {
|
|
|
|
|
*n = *mapop(n, Elv);
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-13 15:29:46 -06:00
|
|
|
|
if(n->left->op == OSEND)
|
|
|
|
|
if(n->left->type != T) {
|
|
|
|
|
*n = *chanop(n, Elv);
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
if(eqtype(lt, rt, 0))
|
|
|
|
|
return n;
|
|
|
|
|
|
|
|
|
|
if(isinter(lt)) {
|
|
|
|
|
if(isptrto(rt, TSTRUCT)) {
|
|
|
|
|
o = OS2I;
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
if(isinter(rt)) {
|
|
|
|
|
o = OI2I;
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(isptrto(lt, TSTRUCT)) {
|
|
|
|
|
if(isinter(rt)) {
|
|
|
|
|
o = OI2S;
|
|
|
|
|
goto ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
badtype(n->op, lt, rt);
|
|
|
|
|
return n;
|
|
|
|
|
|
|
|
|
|
ret:
|
|
|
|
|
diagnamed(lt);
|
|
|
|
|
diagnamed(rt);
|
|
|
|
|
|
|
|
|
|
n->right = nod(o, r, N);
|
|
|
|
|
n->right->type = l->type;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(n, Etop);
|
2008-06-04 15:37:38 -06:00
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-08 13:48:37 -06:00
|
|
|
|
void
|
|
|
|
|
arrayconv(Type *t, Node *n)
|
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
Iter save;
|
|
|
|
|
Node *l;
|
|
|
|
|
|
|
|
|
|
l = listfirst(&save, &n);
|
|
|
|
|
c = 0;
|
|
|
|
|
|
|
|
|
|
loop:
|
|
|
|
|
if(l == N) {
|
|
|
|
|
if(t->bound == 0)
|
|
|
|
|
t->bound = c;
|
|
|
|
|
if(t->bound == 0 || t->bound < c)
|
|
|
|
|
yyerror("error with array convert bounds");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c++;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
walktype(l, Erv);
|
2008-06-08 13:48:37 -06:00
|
|
|
|
convlit(l, t->type);
|
|
|
|
|
if(!ascompat(l->type, t->type))
|
|
|
|
|
badtype(OARRAY, l->type, t->type);
|
|
|
|
|
l = listnext(&save);
|
|
|
|
|
goto loop;
|
|
|
|
|
}
|
2008-06-10 22:29:57 -06:00
|
|
|
|
|
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);
|
|
|
|
|
if(n == N)
|
|
|
|
|
n = a;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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;
|
|
|
|
|
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-06-21 16:11:29 -06:00
|
|
|
|
if(n == N)
|
|
|
|
|
n = a;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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);
|
|
|
|
|
if(g != N)
|
2008-07-24 16:57:30 -06:00
|
|
|
|
f = list(g, f);
|
|
|
|
|
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) {
|
|
|
|
|
if(r == N)
|
|
|
|
|
r = l;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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);
|
|
|
|
|
|
|
|
|
|
if(g == N)
|
|
|
|
|
g = a;
|
2008-06-11 13:25:44 -06:00
|
|
|
|
else
|
2008-07-24 16:57:30 -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-06-10 22:29:57 -06:00
|
|
|
|
if(r == N)
|
|
|
|
|
r = l;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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);
|
|
|
|
|
tempname(q, l2->right->type);
|
|
|
|
|
q = nod(OAS, l1->left, q);
|
|
|
|
|
l1->left = q->right;
|
|
|
|
|
if(r == N)
|
|
|
|
|
r = q;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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) {
|
|
|
|
|
if(q == N)
|
|
|
|
|
q = l1;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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) {
|
|
|
|
|
if(q == N)
|
|
|
|
|
q = l1;
|
|
|
|
|
else
|
2008-07-24 16:57:30 -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;
|
|
|
|
|
}
|