Commit be16caf8 authored by Russ Cox's avatar Russ Cox

step toward no function prototypes.

delay evaluation of most types (all but func)
from parse time to type check time.

R=ken
OCL=31585
CL=31585
parent a6799963
...@@ -709,88 +709,97 @@ stotype(Node *n, int et, Type **t) ...@@ -709,88 +709,97 @@ stotype(Node *n, int et, Type **t)
Iter save; Iter save;
Strlit *note; Strlit *note;
int lno; int lno;
Node *init;
init = N;
lno = lineno; lno = lineno;
n = listfirst(&save, &n); for(n = listfirst(&save, &n); n != N; n = listnext(&save)) {
note = nil;
loop:
note = nil;
if(n == N) {
*t = T;
lineno = lno;
return t;
}
lineno = n->lineno; lineno = n->lineno;
if(n->op == OLIST) { if(n->op == OLIST) {
// recursive because it can be lists of lists // recursive because it can be lists of lists
t = stotype(n, et, t); t = stotype(n, et, t);
goto next; continue;
} }
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("stotype: oops %N\n", n); fatal("stotype: oops %N\n", n);
if(n->right != N) {
walkexpr(n->right, Etype, &init);
n->type = n->right->type;
n->right = N;
if(n->embedded && n->type != T) {
t1 = n->type;
if(t1->sym == S && isptr[t1->etype])
t1 = t1->type;
if(t1 != T && isptr[t1->etype])
yyerror("embedded type cannot be a pointer");
}
}
if(n->type == T) { if(n->type == T) {
// assume error already printed // assume error already printed
goto next; continue;
} }
switch(n->val.ctype) { switch(n->val.ctype) {
case CTSTR: case CTSTR:
if(et != TSTRUCT) if(et != TSTRUCT)
yyerror("interface method cannot have annotation"); yyerror("interface method cannot have annotation");
note = n->val.u.sval; note = n->val.u.sval;
break; break;
default: default:
if(et != TSTRUCT) if(et != TSTRUCT)
yyerror("interface method cannot have annotation"); yyerror("interface method cannot have annotation");
else else
yyerror("field annotation must be string"); yyerror("field annotation must be string");
case CTxxx: case CTxxx:
note = nil; note = nil;
break; break;
} }
if(et == TINTER && n->left == N) { if(et == TINTER && n->left == N) {
// embedded interface - inline the methods // embedded interface - inline the methods
if(n->type->etype != TINTER) { if(n->type->etype != TINTER) {
yyerror("interface contains embedded non-interface %T", t); yyerror("interface contains embedded non-interface %T", t);
goto next; continue;
}
for(t1=n->type->type; t1!=T; t1=t1->down) {
// TODO(rsc): Is this really an error?
if(strcmp(t1->sym->package, package) != 0)
yyerror("embedded interface contains unexported method %S", t1->sym);
f = typ(TFIELD);
f->type = t1->type;
f->width = BADWIDTH;
f->nname = newname(t1->sym);
f->sym = t1->sym;
*t = f;
t = &f->down;
}
continue;
} }
for(t1=n->type->type; t1!=T; t1=t1->down) {
if(strcmp(t1->sym->package, package) != 0) f = typ(TFIELD);
yyerror("embedded interface contains unexported method %S", t1->sym); f->type = n->type;
f = typ(TFIELD); f->note = note;
f->type = t1->type; f->width = BADWIDTH;
f->width = BADWIDTH;
f->nname = newname(t1->sym); if(n->left != N && n->left->op == ONAME) {
f->sym = t1->sym; f->nname = n->left;
*t = f; f->embedded = n->embedded;
t = &f->down; f->sym = f->nname->sym;
if(pkgimportname != S && !exportname(f->sym->name))
f->sym = pkglookup(f->sym->name, structpkg);
} }
goto next;
}
f = typ(TFIELD); *t = f;
f->type = n->type; t = &f->down;
f->note = note;
f->width = BADWIDTH;
if(n->left != N && n->left->op == ONAME) {
f->nname = n->left;
f->embedded = n->embedded;
f->sym = f->nname->sym;
if(pkgimportname != S && !exportname(f->sym->name))
f->sym = pkglookup(f->sym->name, structpkg);
} }
*t = f; *t = T;
t = &f->down; lineno = lno;
return t;
next:
n = listnext(&save);
goto loop;
} }
Type* Type*
...@@ -1239,7 +1248,8 @@ oldtype(Sym *s) ...@@ -1239,7 +1248,8 @@ oldtype(Sym *s)
if(s == S) if(s == S)
return T; return T;
if(s->def == N || s->def->op != OTYPE) { if(s->def == N || s->def->op != OTYPE) {
yyerror("%S is not a type", s); if(!s->undef)
yyerror("%S is not a type", s);
return T; return T;
} }
t = s->def->type; t = s->def->type;
...@@ -1661,9 +1671,7 @@ embedded(Sym *s) ...@@ -1661,9 +1671,7 @@ embedded(Sym *s)
n->embedded = 1; n->embedded = 1;
if(s == S) if(s == S)
return n; return n;
n->type = oldtype(s); n->right = oldname(s);
if(n->type != T && isptr[n->type->etype])
yyerror("embedded type cannot be a pointer");
return n; return n;
} }
......
...@@ -221,6 +221,9 @@ struct Node ...@@ -221,6 +221,9 @@ struct Node
// OLITERAL/OREGISTER // OLITERAL/OREGISTER
Val val; Val val;
// OTFUNC
Node* rcvr;
// ONAME func param with PHEAP // ONAME func param with PHEAP
Node* heapaddr; // temp holding heap address of param Node* heapaddr; // temp holding heap address of param
Node* stackparam; // OPARAM node referring to stack copy of param Node* stackparam; // OPARAM node referring to stack copy of param
...@@ -334,6 +337,8 @@ enum ...@@ -334,6 +337,8 @@ enum
ODOTTYPE, OTYPESW, ODOTTYPE, OTYPESW,
OBAD, OBAD,
OTCHAN, OTMAP, OTSTRUCT, OTINTER, OTFUNC, OTARRAY,
OEXTEND, // 6g internal OEXTEND, // 6g internal
OEND, OEND,
...@@ -420,6 +425,7 @@ enum ...@@ -420,6 +425,7 @@ enum
Etop, // evaluated at statement level Etop, // evaluated at statement level
Elv, // evaluated in lvalue context Elv, // evaluated in lvalue context
Erv, // evaluated in rvalue context Erv, // evaluated in rvalue context
Etype = 1<<8,
}; };
#define BITS 5 #define BITS 5
...@@ -711,7 +717,7 @@ void errorexit(void); ...@@ -711,7 +717,7 @@ void errorexit(void);
uint32 stringhash(char*); uint32 stringhash(char*);
Sym* lookup(char*); Sym* lookup(char*);
Sym* pkglookup(char*, char*); Sym* pkglookup(char*, char*);
Sym* opkglookup(char*, char*); Sym* restrictlookup(char*, char*);
void importdot(Sym*); void importdot(Sym*);
void yyerror(char*, ...); void yyerror(char*, ...);
void warn(char*, ...); void warn(char*, ...);
...@@ -911,6 +917,7 @@ void walk(Node*); ...@@ -911,6 +917,7 @@ void walk(Node*);
void walkstmt(Node*); void walkstmt(Node*);
void walkexpr(Node*, int, Node**); void walkexpr(Node*, int, Node**);
void walkconv(Node*, Node**); void walkconv(Node*, Node**);
void walkdottype(Node*, Node**);
void walkas(Node*); void walkas(Node*);
void walkbool(Node*); void walkbool(Node*);
void walkswitch(Node*); void walkswitch(Node*);
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
%type <sym> sym packname %type <sym> sym packname
%type <val> oliteral %type <val> oliteral
%type <node> stmt %type <node> stmt ntype
%type <node> arg_type arg_type_list %type <node> arg_type arg_type_list
%type <node> arg_type_list_r braced_keyexpr_list case caseblock %type <node> arg_type_list_r braced_keyexpr_list case caseblock
%type <node> caseblock_list_r common_dcl %type <node> caseblock_list_r common_dcl
...@@ -73,10 +73,11 @@ ...@@ -73,10 +73,11 @@
%type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r %type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r
%type <node> xdcl xdcl_list_r xfndcl %type <node> xdcl xdcl_list_r xfndcl
%type <type> convtype dotdotdot %type <type> type
%type <type> fnlitdcl fntype indcl interfacetype %type <node> convtype dotdotdot
%type <type> new_type structtype type typedclname %type <node> indcl interfacetype structtype
%type <type> chantype non_chan_type othertype non_fn_type %type <type> new_type typedclname fnlitdcl fntype
%type <node> chantype non_chan_type othertype non_fn_type
%type <sym> hidden_importsym hidden_pkg_importsym %type <sym> hidden_importsym hidden_pkg_importsym
...@@ -464,6 +465,8 @@ case: ...@@ -464,6 +465,8 @@ case:
$$ = nod(OXCASE, $$, N); $$ = nod(OXCASE, $$, N);
break; break;
} }
e = nerrors;
walkexpr($2, Etype | Erv, &top);
if($2->op == OTYPE) { if($2->op == OTYPE) {
$$ = old2new(typeswvar->right, $2->type, &top); $$ = old2new(typeswvar->right, $2->type, &top);
$$ = nod(OTYPESW, $$, N); $$ = nod(OTYPESW, $$, N);
...@@ -471,11 +474,9 @@ case: ...@@ -471,11 +474,9 @@ case:
$$->ninit = top; $$->ninit = top;
break; break;
} }
e = nerrors; // maybe walkexpr found problems that keep
gettype($2, nil);
// maybe gettype found problems that keep
// e from being valid even outside a type switch. // e from being valid even outside a type switch.
// only complain if gettype didn't print new errors. // only complain if walkexpr didn't print new errors.
if(nerrors == e) if(nerrors == e)
yyerror("non-type case in type switch"); yyerror("non-type case in type switch");
$$ = nod(OXCASE, N, N); $$ = nod(OXCASE, N, N);
...@@ -791,10 +792,6 @@ uexpr: ...@@ -791,10 +792,6 @@ uexpr:
pexpr pexpr
| '*' uexpr | '*' uexpr
{ {
if($2->op == OTYPE) {
$$ = typenod(ptrto($2->type));
break;
}
$$ = nod(OIND, $2, N); $$ = nod(OIND, $2, N);
} }
| '&' uexpr | '&' uexpr
...@@ -837,20 +834,6 @@ pseudocall: ...@@ -837,20 +834,6 @@ pseudocall:
$$ = unsafenmagic($1, $3); $$ = unsafenmagic($1, $3);
if($$) if($$)
break; break;
if($1->op == OTYPE) {
// type conversion
if($3 == N)
yyerror("conversion to %T missing expr", $1->type);
else if($3->op == OLIST)
yyerror("conversion to %T has too many exprs", $1->type);
$$ = nod(OCONV, $3, N);
$$->type = $1->type;
break;
}
if($1->op == ONAME && $1->etype != 0) { // builtin OLEN, OCAP, etc
$$ = nod($1->etype, $3, N);
break;
}
$$ = nod(OCALL, $1, $3); $$ = nod(OCALL, $1, $3);
} }
...@@ -864,7 +847,7 @@ pexpr: ...@@ -864,7 +847,7 @@ pexpr:
{ {
if($1->op == OPACK) { if($1->op == OPACK) {
Sym *s; Sym *s;
s = pkglookup($3->name, $1->sym->name); s = restrictlookup($3->name, $1->sym->name);
$$ = oldname(s); $$ = oldname(s);
break; break;
} }
...@@ -877,10 +860,7 @@ pexpr: ...@@ -877,10 +860,7 @@ pexpr:
} }
| pexpr '.' '(' expr_or_type ')' | pexpr '.' '(' expr_or_type ')'
{ {
$$ = nod(ODOTTYPE, $1, N); $$ = nod(ODOTTYPE, $1, $4);
if($4->op != OTYPE)
yyerror("expected type got %O", $4->op);
$$->type = $4->type;
} }
| pexpr '.' '(' LTYPE ')' | pexpr '.' '(' LTYPE ')'
{ {
...@@ -898,8 +878,7 @@ pexpr: ...@@ -898,8 +878,7 @@ pexpr:
| convtype '(' expr ')' | convtype '(' expr ')'
{ {
// conversion // conversion
$$ = nod(OCONV, $3, N); $$ = nod(OCALL, $1, $3);
$$->type = $1;
} }
| convtype lbrace braced_keyexpr_list '}' | convtype lbrace braced_keyexpr_list '}'
{ {
...@@ -907,8 +886,7 @@ pexpr: ...@@ -907,8 +886,7 @@ pexpr:
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, N); $$ = nod(OCOMPOS, $$, $1);
$$->type = $1;
// If the opening brace was an LBODY, // If the opening brace was an LBODY,
// set up for another one now that we're done. // set up for another one now that we're done.
...@@ -922,20 +900,13 @@ pexpr: ...@@ -922,20 +900,13 @@ pexpr:
$$ = rev($3); $$ = rev($3);
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
$$ = nod(OCOMPOS, $$, N); $$ = nod(OCOMPOS, $$, $1);
if($1->op != OTYPE)
yyerror("expected type in composite literal");
else
$$->type = $1->type;
} }
| fnliteral | fnliteral
expr_or_type: expr_or_type:
expr expr
| type %prec PreferToRightParen | ntype %prec PreferToRightParen
{
$$ = typenod($1);
}
name_or_type: name_or_type:
dotname dotname
...@@ -996,21 +967,20 @@ labelname: ...@@ -996,21 +967,20 @@ labelname:
name name
convtype: convtype:
'[' oexpr ']' type '[' oexpr ']' ntype
{ {
// array literal // array literal
$$ = aindex($2, $4); $$ = nod(OTARRAY, $2, $4);
} }
| '[' LDDD ']' type | '[' dotdotdot ']' ntype
{ {
// array literal of nelem // array literal of nelem
$$ = aindex(N, $4); $$ = nod(OTARRAY, $2, $4);
$$->bound = -100;
} }
| LMAP '[' type ']' type | LMAP '[' ntype ']' ntype
{ {
// map literal // map literal
$$ = maptype($3, $5); $$ = nod(OTMAP, $3, $5);
} }
| structtype | structtype
...@@ -1026,22 +996,34 @@ convtype: ...@@ -1026,22 +996,34 @@ convtype:
dotdotdot: dotdotdot:
LDDD LDDD
{ {
$$ = typ(TDDD); $$ = typenod(typ(TDDD));
} }
type: type:
ntype
{
Node *init;
init = N;
walkexpr($1, Etype, &init);
// init can only be set if this was not a type; ignore
$$ = $1->type;
}
ntype:
chantype chantype
| fntype | fntype { $$ = typenod($1); }
| othertype | othertype
| '(' type ')' | '(' ntype ')'
{ {
$$ = $2; $$ = $2;
} }
non_chan_type: non_chan_type:
fntype fntype { $$ = typenod($1); }
| othertype | othertype
| '(' type ')' | '(' ntype ')'
{ {
$$ = $2; $$ = $2;
} }
...@@ -1056,7 +1038,7 @@ dotname: ...@@ -1056,7 +1038,7 @@ dotname:
{ {
if($1->op == OPACK) { if($1->op == OPACK) {
Sym *s; Sym *s;
s = pkglookup($3->name, $1->sym->name); s = restrictlookup($3->name, $1->sym->name);
$$ = oldname(s); $$ = oldname(s);
break; break;
} }
...@@ -1067,52 +1049,41 @@ dotname: ...@@ -1067,52 +1049,41 @@ dotname:
othertype: othertype:
'[' oexpr ']' type '[' oexpr ']' type
{ {
$$ = aindex($2, $4); $$ = typenod(aindex($2, $4));
} }
| LCOMM LCHAN type | LCOMM LCHAN ntype
{ {
$$ = typ(TCHAN); $$ = nod(OTCHAN, $3, N);
$$->type = $3; $$->etype = Crecv;
$$->chan = Crecv;
} }
| LCHAN LCOMM non_chan_type | LCHAN LCOMM non_chan_type
{ {
$$ = typ(TCHAN); $$ = nod(OTCHAN, $3, N);
$$->type = $3; $$->etype = Csend;
$$->chan = Csend;
} }
| LMAP '[' type ']' type | LMAP '[' ntype ']' ntype
{ {
$$ = maptype($3, $5); $$ = nod(OTMAP, $3, $5);
} }
| '*' type | '*' ntype
{ {
$$ = ptrto($2); $$ = nod(OIND, $2, N);
} }
| structtype | structtype
| interfacetype | interfacetype
| dotname | dotname
{
if($1->op == ODOT) {
yyerror("%S.%S is not a type", $1->left->sym, $1->right->sym);
$$ = T;
break;
}
$$ = oldtype($1->sym);
}
chantype: chantype:
LCHAN type LCHAN ntype
{ {
$$ = typ(TCHAN); $$ = nod(OTCHAN, $2, N);
$$->type = $2; $$->etype = Cboth;
$$->chan = Cboth;
} }
structtype: structtype:
LSTRUCT '{' structdcl_list_r osemi '}' LSTRUCT '{' structdcl_list_r osemi '}'
{ {
$$ = dostruct(rev($3), TSTRUCT); $$ = nod(OTSTRUCT, rev($3), N);
// Distinguish closing brace in struct from // Distinguish closing brace in struct from
// other closing braces by explicitly marking it. // other closing braces by explicitly marking it.
// Used above (yylast == LSEMIBRACE). // Used above (yylast == LSEMIBRACE).
...@@ -1120,20 +1091,19 @@ structtype: ...@@ -1120,20 +1091,19 @@ structtype:
} }
| LSTRUCT '{' '}' | LSTRUCT '{' '}'
{ {
$$ = dostruct(N, TSTRUCT); $$ = nod(OTSTRUCT, N, N);
yylast = LSEMIBRACE; yylast = LSEMIBRACE;
} }
interfacetype: interfacetype:
LINTERFACE '{' interfacedcl_list_r osemi '}' LINTERFACE '{' interfacedcl_list_r osemi '}'
{ {
$$ = dostruct(rev($3), TINTER); $$ = nod(OTINTER, rev($3), N);
$$ = sortinter($$);
yylast = LSEMIBRACE; yylast = LSEMIBRACE;
} }
| LINTERFACE '{' '}' | LINTERFACE '{' '}'
{ {
$$ = dostruct(N, TINTER); $$ = nod(OTINTER, N, N);
yylast = LSEMIBRACE; yylast = LSEMIBRACE;
} }
...@@ -1229,8 +1199,7 @@ fnres: ...@@ -1229,8 +1199,7 @@ fnres:
} }
| non_fn_type | non_fn_type
{ {
$$ = nod(ODCLFIELD, N, N); $$ = nod(ODCLFIELD, N, $1);
$$->type = $1;
$$ = cleanidlist($$); $$ = cleanidlist($$);
} }
| '(' oarg_type_list ')' | '(' oarg_type_list ')'
...@@ -1294,10 +1263,9 @@ structdcl: ...@@ -1294,10 +1263,9 @@ structdcl:
$$ = nod(ODCLFIELD, $1, N); $$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3); $$ = nod(OLIST, $$, $3);
} }
| new_field type oliteral | new_field ntype oliteral
{ {
$$ = nod(ODCLFIELD, $1, N); $$ = nod(ODCLFIELD, $1, $2);
$$->type = $2;
$$->val = $3; $$->val = $3;
} }
| embed oliteral | embed oliteral
...@@ -1308,7 +1276,7 @@ structdcl: ...@@ -1308,7 +1276,7 @@ structdcl:
| '*' embed oliteral | '*' embed oliteral
{ {
$$ = $2; $$ = $2;
$$->type = ptrto($$->type); $$->right = nod(OIND, $$->right, N);
$$->val = $3; $$->val = $3;
} }
...@@ -1323,7 +1291,7 @@ packname: ...@@ -1323,7 +1291,7 @@ packname:
pkg = $1->name; pkg = $1->name;
} else } else
pkg = $1->def->sym->name; pkg = $1->def->sym->name;
$$ = pkglookup($3->name, pkg); $$ = restrictlookup($3->name, pkg);
} }
embed: embed:
...@@ -1340,23 +1308,21 @@ interfacedcl1: ...@@ -1340,23 +1308,21 @@ interfacedcl1:
} }
| new_name indcl | new_name indcl
{ {
$$ = nod(ODCLFIELD, $1, N); $$ = nod(ODCLFIELD, $1, $2);
$$->type = $2;
} }
interfacedcl: interfacedcl:
interfacedcl1 interfacedcl1
| packname | packname
{ {
$$ = nod(ODCLFIELD, N, N); $$ = nod(ODCLFIELD, N, typenod(oldtype($1)));
$$->type = oldtype($1);
} }
indcl: indcl:
'(' oarg_type_list ')' fnres '(' oarg_type_list ')' fnres
{ {
// without func keyword // without func keyword
$$ = functype(fakethis(), $2, $4); $$ = typenod(functype(fakethis(), $2, $4));
} }
/* /*
...@@ -1380,12 +1346,9 @@ arg_type: ...@@ -1380,12 +1346,9 @@ arg_type:
$$ = nod(ONONAME, N, N); $$ = nod(ONONAME, N, N);
$$->sym = $1; $$->sym = $1;
} }
$$ = nod(OKEY, $$, typenod($2)); $$ = nod(OKEY, $$, $2);
} }
| dotdotdot | dotdotdot
{
$$ = typenod($1);
}
arg_type_list_r: arg_type_list_r:
arg_type arg_type
...@@ -1804,15 +1767,14 @@ hidden_dcl: ...@@ -1804,15 +1767,14 @@ hidden_dcl:
hidden_structdcl: hidden_structdcl:
sym hidden_type oliteral sym hidden_type oliteral
{ {
$$ = nod(ODCLFIELD, newname($1), N); $$ = nod(ODCLFIELD, newname($1), typenod($2));
$$->type = $2;
$$->val = $3; $$->val = $3;
} }
| '?' hidden_type oliteral | '?' hidden_type oliteral
{ {
if(isptr[$2->etype]) { if(isptr[$2->etype]) {
$$ = embedded($2->type->sym); $$ = embedded($2->type->sym);
$$->type = ptrto($$->type); $$->right = nod(OIND, $$->right, N);
} else } else
$$ = embedded($2->sym); $$ = embedded($2->sym);
$$->val = $3; $$->val = $3;
...@@ -1821,8 +1783,7 @@ hidden_structdcl: ...@@ -1821,8 +1783,7 @@ hidden_structdcl:
hidden_interfacedcl: hidden_interfacedcl:
sym '(' ohidden_funarg_list ')' ohidden_funres sym '(' ohidden_funarg_list ')' ohidden_funres
{ {
$$ = nod(ODCLFIELD, newname($1), N); $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
$$->type = functype(fakethis(), $3, $5);
} }
ohidden_funres: ohidden_funres:
......
...@@ -178,29 +178,29 @@ lookup(char *p) ...@@ -178,29 +178,29 @@ lookup(char *p)
} }
Sym* Sym*
pkglookup(char *p, char *k) pkglookup(char *name, char *pkg)
{ {
Sym *s; Sym *s;
uint32 h; uint32 h;
int c; int c;
h = stringhash(p) % NHASH; h = stringhash(name) % NHASH;
c = p[0]; c = name[0];
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != c) if(s->name[0] != c)
continue; continue;
if(strcmp(s->name, p) == 0) if(strcmp(s->name, name) == 0)
if(s->package && strcmp(s->package, k) == 0) if(s->package && strcmp(s->package, pkg) == 0)
return s; return s;
} }
s = mal(sizeof(*s)); s = mal(sizeof(*s));
s->name = mal(strlen(p)+1); s->name = mal(strlen(name)+1);
strcpy(s->name, p); strcpy(s->name, name);
// botch - should probably try to reuse the pkg string // botch - should probably try to reuse the pkg string
s->package = mal(strlen(k)+1); s->package = mal(strlen(pkg)+1);
strcpy(s->package, k); strcpy(s->package, pkg);
s->link = hash[h]; s->link = hash[h];
hash[h] = s; hash[h] = s;
...@@ -208,7 +208,16 @@ pkglookup(char *p, char *k) ...@@ -208,7 +208,16 @@ pkglookup(char *p, char *k)
return s; return s;
} }
// find all the symbols in package opkg Sym*
restrictlookup(char *name, char *pkg)
{
if(!exportname(name) && strcmp(pkg, package) != 0)
yyerror("cannot refer to %s.%s", pkg, name);
return pkglookup(name, pkg);
}
// find all the exported symbols in package opkg
// and make them available in the current package // and make them available in the current package
void void
importdot(Sym *opkg) importdot(Sym *opkg)
...@@ -225,6 +234,8 @@ importdot(Sym *opkg) ...@@ -225,6 +234,8 @@ importdot(Sym *opkg)
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
if(s->package[0] != c) if(s->package[0] != c)
continue; continue;
if(!exportname(s->name))
continue;
if(strcmp(s->package, opkg->name) != 0) if(strcmp(s->package, opkg->name) != 0)
continue; continue;
s1 = lookup(s->name); s1 = lookup(s->name);
...@@ -758,6 +769,12 @@ opnames[] = ...@@ -758,6 +769,12 @@ opnames[] =
[OSLICE] = "SLICE", [OSLICE] = "SLICE",
[OSUB] = "SUB", [OSUB] = "SUB",
[OSWITCH] = "SWITCH", [OSWITCH] = "SWITCH",
[OTCHAN] = "TCHAN",
[OTMAP] = "TMAP",
[OTSTRUCT] = "TSTRUCT",
[OTINTER] = "TINTER",
[OTFUNC] = "TFUNC",
[OTARRAY] = "TARRAY",
[OTYPEOF] = "TYPEOF", [OTYPEOF] = "TYPEOF",
[OTYPESW] = "TYPESW", [OTYPESW] = "TYPESW",
[OTYPE] = "TYPE", [OTYPE] = "TYPE",
...@@ -2147,18 +2164,19 @@ cleanidlist(Node *na) ...@@ -2147,18 +2164,19 @@ cleanidlist(Node *na)
{ {
Node *last, *n; Node *last, *n;
if(na->op != OLIST) if(na->op != OLIST) {
if(na->op != ODCLFIELD)
fatal("cleanidlist: %O", na->op);
if(na->right == N)
fatal("cleanidlist: no type");
return na; return na;
}
for(last=na; last->op == OLIST; last=last->right) for(last=na; last->op == OLIST; last=last->right)
; ;
if(last->op != ODCLFIELD)
fatal("cleanidlist: %O", last->op);
if(last->type == T)
fatal("cleanidlist: no type");
for(n=na; n->op == OLIST; n=n->right) { for(n=na; n->op == OLIST; n=n->right) {
n->left->type = last->type; n->left->right = last->right;
n->left->val = last->val; n->left->val = last->val;
} }
return na; return na;
......
...@@ -48,10 +48,18 @@ loop: ...@@ -48,10 +48,18 @@ loop:
// statement of the function // statement of the function
case OGOTO: case OGOTO:
case OPANIC:
case OPANICN:
case ORETURN: case ORETURN:
return 0; return 0;
case OCALL:
if(n->left->op == ONAME) {
switch(n->left->etype) {
case OPANIC:
case OPANICN:
return 0;
}
}
break;
} }
// all other statements // all other statements
...@@ -242,12 +250,14 @@ walkexpr(Node *n, int top, Node **init) ...@@ -242,12 +250,14 @@ walkexpr(Node *n, int top, Node **init)
Node *r, *l; Node *r, *l;
Type *t; Type *t;
Sym *s; Sym *s;
int et, cl, cr; int et, cl, cr, typeok;
int32 lno; int32 lno;
if(n == N) if(n == N)
return; return;
lno = setlineno(n); lno = setlineno(n);
typeok = top & Etype;
top &= ~Etype;
loop: loop:
if(n == N) if(n == N)
...@@ -258,6 +268,7 @@ loop: ...@@ -258,6 +268,7 @@ loop:
if(debug['w'] > 1 && top == Etop && n->op != OLIST) if(debug['w'] > 1 && top == Etop && n->op != OLIST)
dump("walk-before", n); dump("walk-before", n);
reswitch:
t = T; t = T;
et = Txxx; et = Txxx;
...@@ -268,15 +279,79 @@ loop: ...@@ -268,15 +279,79 @@ loop:
goto ret; goto ret;
case OTYPE: case OTYPE:
if(!n->diag) { goto ret;
n->diag = 1;
yyerror("type %T used as expression", n->type); case OTARRAY:
t = typ(TARRAY);
l = n->left;
r = n->right;
if(l == nil) {
t->bound = -1;
} else {
walkexpr(l, Erv | Etype, init);
switch(l->op) {
default:
yyerror("invalid array bound %O", l->op);
break;
case OLITERAL:
if(consttype(l) == CTINT) {
t->bound = mpgetfix(l->val.u.xval);
if(t->bound < 0) {
yyerror("array bound must be non-negative");
t->bound = 1;
}
}
break;
case OTYPE:
if(l->type == T)
break;
if(l->type->etype != TDDD)
yyerror("invalid array bound %T", l->type);
t->bound = -100;
break;
}
} }
walkexpr(r, Etype, init);
t->type = r->type;
n->op = OTYPE;
n->type = t;
goto ret;
case OTMAP:
l = n->left;
r = n->right;
walkexpr(l, Etype, init);
walkexpr(r, Etype, init);
n->op = OTYPE;
n->type = maptype(l->type, r->type);
goto ret;
case OTCHAN:
t = typ(TCHAN);
l = n->left;
walkexpr(l, Etype, init);
t->type = l->type;
t->chan = n->etype;
n->op = OTYPE;
n->type = t;
goto ret;
case OTSTRUCT:
n->op = OTYPE;
n->type = dostruct(n->left, TSTRUCT);
goto ret;
case OTINTER:
n->op = OTYPE;
n->type = dostruct(n->left, TINTER);
n->type = sortinter(n->type);
goto ret; goto ret;
case OLIST: case OLIST:
case OKEY: case OKEY:
walkexpr(n->left, top, init); walkexpr(n->left, top | typeok, init);
n = n->right; n = n->right;
goto loop; goto loop;
...@@ -318,7 +393,8 @@ loop: ...@@ -318,7 +393,8 @@ loop:
s = n->sym; s = n->sym;
if(s->undef == 0) { if(s->undef == 0) {
s->undef = 1; s->undef = 1;
yyerror("%S: undefined", s); n->diag = 1;
yyerror("undefined: %S", s);
goto ret; goto ret;
} }
if(top == Etop) if(top == Etop)
...@@ -354,7 +430,15 @@ loop: ...@@ -354,7 +430,15 @@ loop:
if(n->left == N) if(n->left == N)
goto ret; goto ret;
walkexpr(n->left, Erv, init); if(n->left->op == ONAME && n->left->etype != 0) {
// builtin OLEN, OCAP, etc.
n->op = n->left->etype;
n->left = n->right;
n->right = N;
goto reswitch;
}
walkexpr(n->left, Erv | Etype, init);
defaultlit(n->left, T); defaultlit(n->left, T);
t = n->left->type; t = n->left->type;
...@@ -365,6 +449,16 @@ loop: ...@@ -365,6 +449,16 @@ loop:
n->op = OCALLMETH; n->op = OCALLMETH;
if(n->left->op == ODOTINTER) if(n->left->op == ODOTINTER)
n->op = OCALLINTER; n->op = OCALLINTER;
if(n->left->op == OTYPE) {
n->op = OCONV;
if(top != Erv)
goto nottop;
// turn CALL(type, arg) into CONV(arg) w/ type.
n->type = n->left->type;
n->left = n->right;
n->right = N;
goto reswitch;
}
if(t->etype != TFUNC) { if(t->etype != TFUNC) {
yyerror("call of a non-function: %T", t); yyerror("call of a non-function: %T", t);
...@@ -493,9 +587,9 @@ loop: ...@@ -493,9 +587,9 @@ loop:
break; break;
case ODOTTYPE: case ODOTTYPE:
walkdottype(r, init);
if(cl == 2 && cr == 1) { if(cl == 2 && cr == 1) {
// a,b = i.(T) // a,b = i.(T)
walkexpr(r->left, Erv, init);
if(r->left == N) if(r->left == N)
break; break;
et = ifaceas1(r->type, r->left->type, 1); et = ifaceas1(r->type, r->left->type, 1);
...@@ -558,8 +652,10 @@ loop: ...@@ -558,8 +652,10 @@ loop:
case OEMPTY: case OEMPTY:
goto ret; goto ret;
case OCONV:
case ODOTTYPE: case ODOTTYPE:
walkdottype(n, init);
// fall through
case OCONV:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
walkconv(n, init); walkconv(n, init);
...@@ -573,9 +669,12 @@ loop: ...@@ -573,9 +669,12 @@ loop:
goto ret; goto ret;
case OCOMPOS: case OCOMPOS:
t = n->type; walkexpr(n->right, Etype, init);
t = n->right->type;
n->type = t;
if(t == T) if(t == T)
goto ret; goto ret;
l = n->left; l = n->left;
if(l == N) if(l == N)
goto ret; goto ret;
...@@ -911,7 +1010,12 @@ loop: ...@@ -911,7 +1010,12 @@ loop:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
defaultlit(n->left, T); defaultlit(n->left, T);
if(n->left->op == OCOMPOS && n->left->type != T) { if(n->left->op == OCOMPOS) {
walkexpr(n->left->right, Etype, init);
n->left->type = n->left->right->type;
if(n->left->type == T)
goto ret;
Node *nvar, *nas, *nstar; Node *nvar, *nas, *nstar;
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation. // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
...@@ -971,10 +1075,15 @@ loop: ...@@ -971,10 +1075,15 @@ loop:
goto nottop; goto nottop;
if(top == Elv) // even if n is lvalue, n->left is rvalue if(top == Elv) // even if n is lvalue, n->left is rvalue
top = Erv; top = Erv;
walkexpr(n->left, top, init);
defaultlit(n->left, T);
if(n->left == N) if(n->left == N)
goto ret; goto ret;
walkexpr(n->left, top | Etype, init);
defaultlit(n->left, T);
if(n->left->op == OTYPE) {
n->op = OTYPE;
n->type = ptrto(n->left->type);
goto ret;
}
t = n->left->type; t = n->left->type;
if(t == T) if(t == T)
goto ret; goto ret;
...@@ -998,12 +1107,11 @@ loop: ...@@ -998,12 +1107,11 @@ loop:
if(top != Erv) if(top != Erv)
goto nottop; goto nottop;
l = n->left; l = n->left;
walkexpr(l, Etype, init);
if(l == N) if(l == N)
yyerror("missing argument to new"); yyerror("missing argument to new");
else if(n->right != N) else if(n->right != N)
yyerror("too many arguments to new"); yyerror("too many arguments to new");
else if(l->op != OTYPE)
yyerror("argument to new must be type");
else if((t = l->type) == T) else if((t = l->type) == T)
; ;
else else
...@@ -1153,9 +1261,12 @@ nottop: ...@@ -1153,9 +1261,12 @@ nottop:
if(n->diag) if(n->diag)
goto ret; goto ret;
n->diag = 1; n->diag = 1;
switch(top) { switch(top | typeok) {
default: default:
yyerror("didn't expect %O here", n->op); yyerror("didn't expect %O here [top=%d]", n->op, top);
break;
case Etype:
yyerror("operation %O not allowed in type context", n->op);
break; break;
case Etop: case Etop:
yyerror("operation %O not allowed in statement context", n->op); yyerror("operation %O not allowed in statement context", n->op);
...@@ -1164,6 +1275,7 @@ nottop: ...@@ -1164,6 +1275,7 @@ nottop:
yyerror("operation %O not allowed in assignment context", n->op); yyerror("operation %O not allowed in assignment context", n->op);
break; break;
case Erv: case Erv:
case Erv | Etype:
yyerror("operation %O not allowed in expression context", n->op); yyerror("operation %O not allowed in expression context", n->op);
break; break;
} }
...@@ -1188,6 +1300,21 @@ ret: ...@@ -1188,6 +1300,21 @@ ret:
if(debug['w'] && top == Etop && n != N) if(debug['w'] && top == Etop && n != N)
dump("walk", n); dump("walk", n);
if(typeok && top == 0) { // must be type
if(n->op != OTYPE) {
if(n->sym) {
if(!n->sym->undef)
yyerror("%S is not a type", n->sym);
} else {
yyerror("expr %O is not type", n->op);
n->op = OTYPE; // leads to fewer errors later
n->type = T;
}
}
}
if(!typeok && n->op == OTYPE)
yyerror("cannot use type %T as expr", n->type);
ullmancalc(n); ullmancalc(n);
lineno = lno; lineno = lno;
} }
...@@ -1203,6 +1330,22 @@ walkbool(Node *n) ...@@ -1203,6 +1330,22 @@ walkbool(Node *n)
yyerror("IF and FOR require a boolean type"); yyerror("IF and FOR require a boolean type");
} }
void
walkdottype(Node *n, Node **init)
{
walkexpr(n->left, Erv, init);
if(n->left == N)
return;
defaultlit(n->left, T);
if(!isinter(n->left->type))
yyerror("type assertion requires interface on left, have %T", n->left->type);
if(n->right != N) {
walkexpr(n->right, Etype, init);
n->type = n->right->type;
n->right = N;
}
}
void void
walkconv(Node *n, Node **init) walkconv(Node *n, Node **init)
{ {
...@@ -1223,9 +1366,6 @@ walkconv(Node *n, Node **init) ...@@ -1223,9 +1366,6 @@ walkconv(Node *n, Node **init)
// if using .(T), interface assertion. // if using .(T), interface assertion.
if(n->op == ODOTTYPE) { if(n->op == ODOTTYPE) {
defaultlit(l, T);
if(!isinter(l->type))
yyerror("type assertion requires interface on left, have %T", l->type);
et = ifaceas1(t, l->type, 1); et = ifaceas1(t, l->type, 1);
if(et == I2Isame || et == E2Esame) if(et == I2Isame || et == E2Esame)
goto nop; goto nop;
...@@ -1727,7 +1867,7 @@ walkdot(Node *n, Node **init) ...@@ -1727,7 +1867,7 @@ walkdot(Node *n, Node **init)
if(!lookdot(n, t)) { if(!lookdot(n, t)) {
if(!n->diag) { if(!n->diag) {
n->diag = 1; n->diag = 1;
yyerror("undefined DOT %S on %T", n->right->sym, n->left->type); yyerror("undefined: %T field %S", n->left->type, n->right->sym);
} }
} }
} }
...@@ -2300,7 +2440,7 @@ Node* ...@@ -2300,7 +2440,7 @@ Node*
makecompat(Node *n) makecompat(Node *n)
{ {
Type *t; Type *t;
Node *l, *r; Node *l, *r, *init;
l = n->left; l = n->left;
r = N; r = N;
...@@ -2308,6 +2448,8 @@ makecompat(Node *n) ...@@ -2308,6 +2448,8 @@ makecompat(Node *n)
r = l->right; r = l->right;
l = l->left; l = l->left;
} }
init = N;
walkexpr(l, Etype, &init);
if(l->op != OTYPE) { if(l->op != OTYPE) {
yyerror("cannot make(expr)"); yyerror("cannot make(expr)");
return n; return n;
...@@ -3455,10 +3597,17 @@ colas(Node *nl, Node *nr, Node **init) ...@@ -3455,10 +3597,17 @@ colas(Node *nl, Node *nr, Node **init)
/* check calls early, to give better message for a := f() */ /* check calls early, to give better message for a := f() */
if(cr == 1) { if(cr == 1) {
switch(nr->op) { switch(nr->op) {
case OCALL:
if(nr->left->op == ONAME && nr->left->etype != 0)
break;
walkexpr(nr->left, Erv | Etype, init);
if(nr->left->op == OTYPE)
break;
goto call;
case OCALLMETH: case OCALLMETH:
case OCALLINTER: case OCALLINTER:
case OCALL:
walkexpr(nr->left, Erv, init); walkexpr(nr->left, Erv, init);
call:
convlit(nr->left, types[TFUNC]); convlit(nr->left, types[TFUNC]);
t = nr->left->type; t = nr->left->type;
if(t == T) if(t == T)
...@@ -3539,11 +3688,9 @@ multi: ...@@ -3539,11 +3688,9 @@ multi:
case ODOTTYPE: case ODOTTYPE:
// a,b := i.(T) // a,b := i.(T)
walkdottype(nr, init);
if(cl != 2) if(cl != 2)
goto badt; goto badt;
walkexpr(nr->left, Erv, init);
if(!isinter(nr->left->type))
goto badt;
// a,b = iface // a,b = iface
a = mixedoldnew(nl->left, nr->type); a = mixedoldnew(nl->left, nr->type);
n = a; n = a;
......
...@@ -130,8 +130,8 @@ fixedbugs/bug035.go:7: variable f redeclared in this block ...@@ -130,8 +130,8 @@ fixedbugs/bug035.go:7: variable f redeclared in this block
previous declaration at fixedbugs/bug035.go:5 previous declaration at fixedbugs/bug035.go:5
=========== fixedbugs/bug037.go =========== fixedbugs/bug037.go
fixedbugs/bug037.go:6: vlong: undefined fixedbugs/bug037.go:6: undefined: vlong
fixedbugs/bug037.go:6: s: undefined fixedbugs/bug037.go:6: undefined: s
=========== fixedbugs/bug039.go =========== fixedbugs/bug039.go
fixedbugs/bug039.go:6: variable x redeclared in this block fixedbugs/bug039.go:6: variable x redeclared in this block
...@@ -166,7 +166,7 @@ do break ...@@ -166,7 +166,7 @@ do break
broke broke
=========== fixedbugs/bug072.go =========== fixedbugs/bug072.go
fixedbugs/bug072.go:6: bug: undefined fixedbugs/bug072.go:6: undefined: bug
=========== fixedbugs/bug073.go =========== fixedbugs/bug073.go
fixedbugs/bug073.go:8: illegal types for operand: LSH fixedbugs/bug073.go:8: illegal types for operand: LSH
...@@ -185,16 +185,16 @@ fixedbugs/bug074.go:6: invalid type for composite literal: string ...@@ -185,16 +185,16 @@ fixedbugs/bug074.go:6: invalid type for composite literal: string
fixedbugs/bug074.go:6: invalid type for composite literal: string fixedbugs/bug074.go:6: invalid type for composite literal: string
=========== fixedbugs/bug081.go =========== fixedbugs/bug081.go
fixedbugs/bug081.go:5: x is not a type fixedbugs/bug081.go:5: undefined: x
=========== fixedbugs/bug083.go =========== fixedbugs/bug083.go
fixedbugs/bug083.dir/bug1.go:9: cannot use type bug0.t0 fixedbugs/bug083.dir/bug1.go:9: cannot refer to bug0.t0
=========== fixedbugs/bug086.go =========== fixedbugs/bug086.go
fixedbugs/bug086.go:5: function ends without a return statement fixedbugs/bug086.go:5: function ends without a return statement
=========== fixedbugs/bug091.go =========== fixedbugs/bug091.go
fixedbugs/bug091.go:15: c: undefined fixedbugs/bug091.go:15: undefined: c
fixedbugs/bug091.go:15: illegal types for operand: AS fixedbugs/bug091.go:15: illegal types for operand: AS
undefined undefined
...@@ -203,7 +203,7 @@ M ...@@ -203,7 +203,7 @@ M
=========== fixedbugs/bug103.go =========== fixedbugs/bug103.go
fixedbugs/bug103.go:8: assignment count mismatch: 1 = 0 fixedbugs/bug103.go:8: assignment count mismatch: 1 = 0
fixedbugs/bug103.go:8: x: undefined fixedbugs/bug103.go:8: undefined: x
fixedbugs/bug103.go:8: function requires a return type fixedbugs/bug103.go:8: function requires a return type
fixedbugs/bug103.go:8: illegal types for operand: AS fixedbugs/bug103.go:8: illegal types for operand: AS
int int
...@@ -228,6 +228,6 @@ fixedbugs/bug131.go:7: illegal types for operand: AS ...@@ -228,6 +228,6 @@ fixedbugs/bug131.go:7: illegal types for operand: AS
uint64 uint64
=========== fixedbugs/bug133.go =========== fixedbugs/bug133.go
fixedbugs/bug133.dir/bug2.go:11: undefined DOT i on bug0.T fixedbugs/bug133.dir/bug2.go:11: undefined: bug0.T field i
fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN
int int
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment