]> Cypherpunks repositories - gostls13.git/blob
7003045
[gostls13.git] /
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include        "go.h"
6 #include        "y.tab.h"
7
8 int
9 dflag(void)
10 {
11         if(!debug['d'])
12                 return 0;
13         if(debug['y'])
14                 return 1;
15         if(inimportsys)
16                 return 0;
17         return 1;
18 }
19
20 /*
21  * declaration stack & operations
22  */
23 static  Sym*    dclstack;
24
25 void
26 dcopy(Sym *a, Sym *b)
27 {
28         a->name = b->name;
29         a->def = b->def;
30         a->package = b->package;
31         a->undef = b->undef;
32         a->vargen = b->vargen;
33         a->block = b->block;
34         a->lastlineno = b->lastlineno;
35         a->offset = b->offset;
36 }
37
38 Sym*
39 push(void)
40 {
41         Sym *d;
42
43         d = mal(sizeof(*d));
44         d->link = dclstack;
45         dclstack = d;
46         return d;
47 }
48
49 Sym*
50 pushdcl(Sym *s)
51 {
52         Sym *d;
53
54         d = push();
55         dcopy(d, s);
56         return d;
57 }
58
59 void
60 popdcl(void)
61 {
62         Sym *d, *s;
63
64 //      if(dflag())
65 //              print("revert\n");
66
67         for(d=dclstack; d!=S; d=d->link) {
68                 if(d->name == nil)
69                         break;
70                 s = pkglookup(d->name, d->package);
71                 dcopy(s, d);
72                 if(dflag())
73                         print("\t%L pop %S\n", lineno, s);
74         }
75         if(d == S)
76                 fatal("popdcl: no mark");
77         dclstack = d->link;
78         block = d->block;
79 }
80
81 void
82 poptodcl(void)
83 {
84         Sym *d, *s;
85
86         for(d=dclstack; d!=S; d=d->link) {
87                 if(d->name == nil)
88                         break;
89                 s = pkglookup(d->name, d->package);
90                 dcopy(s, d);
91                 if(dflag())
92                         print("\t%L pop %S\n", lineno, s);
93         }
94         if(d == S)
95                 fatal("poptodcl: no mark");
96         dclstack = d;
97 }
98
99 void
100 markdcl(void)
101 {
102         Sym *d;
103
104         d = push();
105         d->name = nil;          // used as a mark in fifo
106         d->block = block;
107
108         blockgen++;
109         block = blockgen;
110
111 //      if(dflag())
112 //              print("markdcl\n");
113 }
114
115 void
116 dumpdcl(char *st)
117 {
118         Sym *s, *d;
119         int i;
120
121         i = 0;
122         for(d=dclstack; d!=S; d=d->link) {
123                 i++;
124                 print("    %.2d %p", i, d);
125                 if(d->name == nil) {
126                         print("\n");
127                         continue;
128                 }
129                 print(" '%s'", d->name);
130                 s = pkglookup(d->name, d->package);
131                 print(" %lS\n", s);
132         }
133 }
134
135 void
136 testdclstack(void)
137 {
138         Sym *d;
139
140         for(d=dclstack; d!=S; d=d->link) {
141                 if(d->name == nil) {
142                         yyerror("mark left on the stack");
143                         continue;
144                 }
145         }
146 }
147
148 /*
149  * declare individual names - var, typ, const
150  */
151 static void
152 redeclare(char *str, Sym *s)
153 {
154         if(s->block == block) {
155                 yyerror("%s %S redeclared in this block", str, s);
156                 print(" previous declaration at %L\n", s->lastlineno);
157         }
158         s->block = block;
159         s->lastlineno = lineno;
160 }
161
162 void
163 addvar(Node *n, Type *t, int ctxt)
164 {
165         Dcl *r, *d;
166         Sym *s;
167         int gen;
168
169         if(n==N || n->sym == S || (n->op != ONAME && n->op != ONONAME) || t == T)
170                 fatal("addvar: n=%N t=%T nil", n, t);
171
172         s = n->sym;
173
174         if(ctxt == PEXTERN || ctxt == PFUNC) {
175                 r = externdcl;
176                 gen = 0;
177         } else {
178                 r = autodcl;
179                 vargen++;
180                 gen = vargen;
181                 pushdcl(s);
182         }
183
184         redeclare("variable", s);
185         n->op = ONAME;
186         s->vargen = gen;
187         s->def = n;
188         s->offset = 0;
189
190         n->funcdepth = funcdepth;
191         n->type = t;
192         n->vargen = gen;
193         n->class = ctxt;
194
195         d = dcl();
196         d->dsym = s;
197         d->dnode = n;
198         d->op = ONAME;
199
200         r->back->forw = d;
201         r->back = d;
202
203         if(dflag()) {
204                 if(ctxt == PEXTERN)
205                         print("extern var-dcl %S G%ld %T\n", s, s->vargen, t);
206                 else if(ctxt == PFUNC)
207                         print("extern func-dcl %S G%ld %T\n", s, s->vargen, t);
208                 else
209                         print("auto   var-dcl %S G%ld %T\n", s, s->vargen, t);
210         }
211 }
212
213 void
214 addtyp(Type *n, int ctxt)
215 {
216         Dcl *r, *d;
217         Sym *s;
218         static int typgen;
219
220         if(n==T || n->sym == S)
221                 fatal("addtyp: n=%T t=%T nil", n);
222
223         s = n->sym;
224
225         if(ctxt == PEXTERN)
226                 r = externdcl;
227         else {
228                 r = autodcl;
229                 pushdcl(s);
230                 n->vargen = ++typgen;
231         }
232
233         redeclare("type", s);
234         s->def = typenod(n);
235
236         d = dcl();
237         d->dsym = s;
238         d->dtype = n;
239         d->op = OTYPE;
240
241         d->back = r->back;
242         r->back->forw = d;
243         r->back = d;
244
245         d = dcl();
246         d->dtype = n;
247         d->op = OTYPE;
248
249         r = typelist;
250         d->back = r->back;
251         r->back->forw = d;
252         r->back = d;
253
254         if(dflag()) {
255                 if(ctxt == PEXTERN)
256                         print("extern typ-dcl %S G%ld %T\n", s, s->vargen, n);
257                 else
258                         print("auto   typ-dcl %S G%ld %T\n", s, s->vargen, n);
259         }
260 }
261
262 // TODO(rsc): cut
263 void
264 addconst(Node *n, Node *e, int ctxt)
265 {
266         Sym *s;
267         Dcl *r, *d;
268
269         if(n->op != ONAME && n->op != ONONAME)
270                 fatal("addconst: not a name");
271
272         if(e->op != OLITERAL) {
273                 yyerror("expression must be a constant");
274                 return;
275         }
276
277         s = n->sym;
278
279         if(ctxt == PEXTERN)
280                 r = externdcl;
281         else {
282                 r = autodcl;
283                 pushdcl(s);
284         }
285
286         redeclare("constant", s);
287         s->def = e;
288         e->sym = s;
289
290         d = dcl();
291         d->dsym = s;
292         d->dnode = e;
293         d->op = OLITERAL;
294         d->back = r->back;
295         r->back->forw = d;
296         r->back = d;
297
298         if(dflag())
299                 print("const-dcl %S %N\n", n->sym, n->sym->def);
300 }
301
302 /*
303  * declare (possible list) n of type t.
304  * append ODCL nodes to *init
305  */
306 void
307 dodclvar(Node *n, Type *t, NodeList **init)
308 {
309         if(n == N)
310                 return;
311
312         if(t != T && (t->etype == TIDEAL || t->etype == TNIL))
313                 fatal("dodclvar %T", t);
314         dowidth(t);
315
316         // in case of type checking error,
317         // use "undefined" type for variable type,
318         // to avoid fatal in addvar.
319         if(t == T)
320                 t = typ(TFORW);
321
322         addvar(n, t, dclcontext);
323         autoexport(n->sym);
324         if(funcdepth > 0)
325                 *init = list(*init, nod(ODCL, n, N));
326 }
327
328 // TODO(rsc): cut
329 void
330 dodclconst(Node *n, Node *e)
331 {
332         if(n == N)
333                 return;
334         addconst(n, e, dclcontext);
335         autoexport(n->sym);
336 }
337
338 /*
339  * introduce a type named n
340  * but it is an unknown type for now
341  */
342 Type*
343 dodcltype(Type *n)
344 {
345         Sym *s;
346
347         // if n has been forward declared,
348         // use the Type* created then
349         s = n->sym;
350         if((funcdepth == 0 || s->block == block) && s->def != N && s->def->op == OTYPE) {
351                 switch(s->def->type->etype) {
352                 case TFORWSTRUCT:
353                 case TFORWINTER:
354                         n = s->def->type;
355                         if(s->block != block) {
356                                 // completing forward struct from other file
357                                 Dcl *d, *r;
358                                 d = dcl();
359                                 d->dsym = s;
360                                 d->dtype = n;
361                                 d->op = OTYPE;
362                                 r = externdcl;
363                                 d->back = r->back;
364                                 r->back->forw = d;
365                                 r->back = d;
366                         }
367                         goto found;
368                 }
369         }
370
371         // otherwise declare a new type
372         addtyp(n, dclcontext);
373
374 found:
375         n->local = 1;
376         autoexport(n->sym);
377         return n;
378 }
379
380 /*
381  * now we know what n is: it's t
382  */
383 void
384 updatetype(Type *n, Type *t)
385 {
386         Sym *s;
387         int local, vargen;
388         int maplineno, lno, etype;
389
390         if(t == T)
391                 return;
392         s = n->sym;
393         if(s == S || s->def == N || s->def->op != OTYPE || s->def->type != n)
394                 fatal("updatetype %T = %T", n, t);
395
396         etype = n->etype;
397         switch(n->etype) {
398         case TFORW:
399                 break;
400
401         case TFORWSTRUCT:
402                 if(t->etype != TSTRUCT) {
403                         yyerror("%T forward declared as struct", n);
404                         return;
405                 }
406                 n->local = 1;
407                 break;
408
409         case TFORWINTER:
410                 if(t->etype != TINTER) {
411                         yyerror("%T forward declared as interface", n);
412                         return;
413                 }
414                 break;
415
416         default:
417                 fatal("updatetype %T / %T", n, t);
418         }
419
420         // decl was
421         //      type n t;
422         // copy t, but then zero out state associated with t
423         // that is no longer associated with n.
424         maplineno = n->maplineno;
425         local = n->local;
426         vargen = n->vargen;
427         *n = *t;
428         n->sym = s;
429         n->local = local;
430         n->siggen = 0;
431         n->printed = 0;
432         n->method = nil;
433         n->vargen = vargen;
434         n->nod = N;
435
436         // catch declaration of incomplete type
437         switch(n->etype) {
438         case TFORWSTRUCT:
439         case TFORWINTER:
440                 break;
441         default:
442                 checkwidth(n);
443         }
444
445         // double-check use of type as map key
446         if(maplineno) {
447                 lno = lineno;
448                 lineno = maplineno;
449                 maptype(n, types[TBOOL]);
450                 lineno = lno;
451         }
452 }
453
454 /*
455  * declare variables from grammar
456  * new_name_list (type | [type] = expr_list)
457  */
458 NodeList*
459 variter(NodeList *vl, Node *t, NodeList *el)
460 {
461         int doexpr, gen;
462         Node *v, *e;
463         NodeList *init;
464         Sym *s;
465         Dcl *r, *d;
466
467         init = nil;
468         doexpr = el != nil;
469         for(; vl; vl=vl->next) {
470                 if(doexpr) {
471                         if(el == nil) {
472                                 yyerror("missing expr in var dcl");
473                                 break;
474                         }
475                         e = el->n;
476                         el = el->next;
477                 } else
478                         e = N;
479
480                 v = vl->n;              
481                 s = v->sym;
482                 if(dclcontext == PEXTERN || dclcontext == PFUNC) {
483                         r = externdcl;
484                         gen = 0;
485                 } else {
486                         r = autodcl;
487                         gen = ++vargen;
488                         pushdcl(s);
489                 }
490                         
491                 redeclare("variable", s);
492                 s->def = v;
493                 // TODO: vargen
494                 s->offset = 0;
495                 s->block = block;
496
497                 v->op = ONAME;
498                 v->class = dclcontext;
499                 v->ntype = t;
500                 v->funcdepth = funcdepth;
501                 v->vargen = gen;
502                 if(e != N || funcdepth > 0) {
503                         if(funcdepth > 0)
504                                 init = list(init, nod(ODCL, v, N));
505                         e = nod(OAS, v, e);
506                         init = list(init, e);
507                         if(e->right != N)
508                                 v->defn = e;
509                 }
510                 
511                 d = dcl();
512                 d->dsym = s;
513                 d->dnode = v;
514                 d->op = ONAME;
515                 r->back->forw = d;
516                 r->back = d;
517
518                 autoexport(s);
519         }
520         if(el != nil)
521                 yyerror("extra expr in var dcl");
522         return init;
523 }
524
525 /*
526  * declare constants from grammar
527  * new_name_list [[type] = expr_list]
528  */
529 NodeList*
530 constiter(NodeList *vl, Node *t, NodeList *cl)
531 {
532         Node *v, *c;
533         NodeList *vv;
534         Sym *s;
535
536         vv = vl;
537         if(cl == nil) {
538                 if(t != N)
539                         yyerror("constdcl cannot have type without expr");
540                 cl = lastconst;
541                 t = lasttype;
542         } else {
543                 lastconst = cl;
544                 lasttype = t;
545         }
546         cl = listtreecopy(cl);
547
548         for(; vl; vl=vl->next) {
549                 if(cl == nil) {
550                         yyerror("missing expr in const dcl");
551                         break;
552                 }
553                 c = cl->n;
554                 cl = cl->next;
555
556                 v = vl->n;
557                 s = v->sym;
558                 if(dclcontext != PEXTERN)
559                         pushdcl(s);
560                 redeclare("constant", s);
561                 s->def = v;
562
563                 v->op = OLITERAL;
564                 v->ntype = t;
565                 v->defn = c;
566                 autoexport(s);
567         }
568         if(cl != nil)
569                 yyerror("extra expr in const dcl");
570         iota += 1;
571         return vv;
572 }
573
574 /*
575  * this generates a new name that is
576  * pushed down on the declaration list.
577  * no diagnostics are produced as this
578  * name will soon be declared.
579  */
580 Node*
581 newname(Sym *s)
582 {
583         Node *n;
584
585         n = nod(ONAME, N, N);
586         n->sym = s;
587         n->type = T;
588         n->addable = 1;
589         n->ullman = 1;
590         n->xoffset = 0;
591         return n;
592 }
593
594 Node*
595 dclname(Sym *s)
596 {
597         Node *n;
598
599         // top-level name: might already have been
600         // referred to, in which case s->def is already
601         // set to an ONONAME.
602         if(dclcontext == PEXTERN && s->block == 0) {
603                 // toss predefined name like "close"
604                 // TODO(rsc): put close in at the end.
605                 if(s->def != N && s->def->etype)
606                         s->def = N;
607                 if(s->def == N)
608                         oldname(s);
609                 return s->def;
610         }
611
612         n = newname(s);
613         n->op = ONONAME;        // caller will correct it
614         return n;
615 }
616
617 Node*
618 typenod(Type *t)
619 {
620         if(t->nod == N) {
621                 t->nod = nod(OTYPE, N, N);
622                 t->nod->type = t;
623                 t->nod->sym = t->sym;
624         }
625         return t->nod;
626 }
627
628
629 /*
630  * this will return an old name
631  * that has already been pushed on the
632  * declaration list. a diagnostic is
633  * generated if no name has been defined.
634  */
635 Node*
636 oldname(Sym *s)
637 {
638         Node *n;
639         Node *c;
640
641         n = s->def;
642         if(n == N) {
643                 // maybe a top-level name will come along
644                 // to give this a definition later.
645                 n = newname(s);
646                 n->op = ONONAME;
647                 s->def = n;
648         }
649         if(n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
650                 // inner func is referring to var
651                 // in outer func.
652                 if(n->closure == N || n->closure->funcdepth != funcdepth) {
653                         typecheck(&n, Erv);
654                         // create new closure var.
655                         c = nod(ONAME, N, N);
656                         c->sym = s;
657                         c->class = PPARAMREF;
658                         c->type = n->type;
659                         c->addable = 0;
660                         c->ullman = 2;
661                         c->funcdepth = funcdepth;
662                         c->outer = n->closure;
663                         n->closure = c;
664                         c->closure = n;
665                         if(funclit != N)
666                                 funclit->cvars = list(funclit->cvars, c);
667                 }
668                 // return ref to closure var, not original
669                 return n->closure;
670         }
671         return n;
672 }
673
674 /*
675  * same for types
676  */
677 Type*
678 newtype(Sym *s)
679 {
680         Type *t;
681
682         t = typ(TFORW);
683         t->sym = s;
684         t->type = T;
685         return t;
686 }
687
688 Type*
689 oldtype(Sym *s)
690 {
691         Type *t;
692
693         if(s == S)
694                 return T;
695         if(s->def == N || s->def->op != OTYPE) {
696                 if(!s->undef)
697                         yyerror("%S is not a type", s);
698                 return T;
699         }
700         t = s->def->type;
701
702         /*
703          * If t is lowercase and not in our package
704          * and this isn't a reference during the parsing
705          * of import data, complain.
706          */
707         if(pkgimportname == S && !exportname(s->name) && strcmp(s->package, package) != 0)
708                 yyerror("cannot use type %T", t);
709         return t;
710 }
711
712 /*
713  * type check top level declarations
714  */
715 void
716 dclchecks(void)
717 {
718         Dcl *d;
719         
720         for(d=externdcl; d!=D; d=d->forw) {
721                 if(d->op != ONAME)
722                         continue;
723                 typecheck(&d->dnode, Erv);
724         }
725 }
726
727
728 /*
729  * structs, functions, and methods.
730  * they don't belong here, but where do they belong?
731  */
732
733
734 /*
735  * turn a parsed struct into a type
736  */
737 Type**
738 stotype(NodeList *l, int et, Type **t)
739 {
740         Type *f, *t1;
741         Strlit *note;
742         int lno;
743         NodeList *init;
744         Node *n;
745
746         init = nil;
747         lno = lineno;
748         for(; l; l=l->next) {
749                 n = l->n;
750                 lineno = n->lineno;
751                 note = nil;
752
753                 if(n->op != ODCLFIELD)
754                         fatal("stotype: oops %N\n", n);
755                 if(n->right != N) {
756                         typecheck(&n->right, Etype);
757                         n->type = n->right->type;
758                         n->right = N;
759                         if(n->embedded && n->type != T) {
760                                 t1 = n->type;
761                                 if(t1->sym == S && isptr[t1->etype])
762                                         t1 = t1->type;
763                                 if(t1 != T && isptr[t1->etype])
764                                         yyerror("embedded type cannot be a pointer");
765                         }
766                 }
767
768                 if(n->type == T) {
769                         // assume error already printed
770                         continue;
771                 }
772
773                 switch(n->val.ctype) {
774                 case CTSTR:
775                         if(et != TSTRUCT)
776                                 yyerror("interface method cannot have annotation");
777                         note = n->val.u.sval;
778                         break;
779                 default:
780                         if(et != TSTRUCT)
781                                 yyerror("interface method cannot have annotation");
782                         else
783                                 yyerror("field annotation must be string");
784                 case CTxxx:
785                         note = nil;
786                         break;
787                 }
788
789                 if(et == TINTER && n->left == N) {
790                         // embedded interface - inline the methods
791                         if(n->type->etype != TINTER) {
792                                 yyerror("interface contains embedded non-interface %T", t);
793                                 continue;
794                         }
795                         for(t1=n->type->type; t1!=T; t1=t1->down) {
796                                 // TODO(rsc): Is this really an error?
797                                 if(strcmp(t1->sym->package, package) != 0)
798                                         yyerror("embedded interface contains unexported method %S", t1->sym);
799                                 f = typ(TFIELD);
800                                 f->type = t1->type;
801                                 f->width = BADWIDTH;
802                                 f->nname = newname(t1->sym);
803                                 f->sym = t1->sym;
804                                 *t = f;
805                                 t = &f->down;
806                         }
807                         continue;
808                 }
809
810                 f = typ(TFIELD);
811                 f->type = n->type;
812                 f->note = note;
813                 f->width = BADWIDTH;
814
815                 if(n->left != N && n->left->op == ONAME) {
816                         f->nname = n->left;
817                         f->embedded = n->embedded;
818                         f->sym = f->nname->sym;
819                         if(pkgimportname != S && !exportname(f->sym->name))
820                                 f->sym = pkglookup(f->sym->name, structpkg);
821                 }
822
823                 *t = f;
824                 t = &f->down;
825         }
826
827         *t = T;
828         lineno = lno;
829         return t;
830 }
831
832 Type*
833 dostruct(NodeList *l, int et)
834 {
835         Type *t;
836         int funarg;
837
838         /*
839          * convert a parsed id/type list into
840          * a type for struct/interface/arglist
841          */
842
843         funarg = 0;
844         if(et == TFUNC) {
845                 funarg = 1;
846                 et = TSTRUCT;
847         }
848         t = typ(et);
849         t->funarg = funarg;
850         stotype(l, et, &t->type);
851         if(!funarg)
852                 checkwidth(t);
853         return t;
854 }
855
856
857 Node*
858 embedded(Sym *s)
859 {
860         Node *n;
861         char *name;
862
863         // Names sometimes have disambiguation junk
864         // appended after a center dot.  Discard it when
865         // making the name for the embedded struct field.
866         enum { CenterDot = 0xB7 };
867         name = s->name;
868         if(utfrune(s->name, CenterDot)) {
869                 name = strdup(s->name);
870                 *utfrune(name, CenterDot) = 0;
871         }
872
873         n = newname(lookup(name));
874         n = nod(ODCLFIELD, n, N);
875         n->embedded = 1;
876         if(s == S)
877                 return n;
878         n->right = oldname(s);
879         return n;
880 }
881
882 static Node*
883 findtype(NodeList *l)
884 {
885         for(; l; l=l->next)
886                 if(l->n->op == OKEY)
887                         return l->n->right;
888         return N;
889 }
890
891 static Node*
892 xanondcl(Node *nt)
893 {
894         Node *n;
895         Type *t;
896
897         typecheck(&nt, Etype);
898         t = nt->type;
899         if(nt->op != OTYPE) {
900                 yyerror("%S is not a type", nt->sym);
901                 t = types[TINT32];
902         }
903         n = nod(ODCLFIELD, N, N);
904         n->type = t;
905         return n;
906 }
907
908 static Node*
909 namedcl(Node *nn, Node *nt)
910 {
911         Node *n;
912         Type *t;
913
914         if(nn->op == OKEY)
915                 nn = nn->left;
916         if(nn->sym == S) {
917                 typecheck(&nn, Etype);
918                 yyerror("cannot mix anonymous %T with named arguments", nn->type);
919                 return xanondcl(nn);
920         }
921         t = types[TINT32];
922         if(nt == N)
923                 yyerror("missing type for argument %S", nn->sym);
924         else {
925                 typecheck(&nt, Etype);
926                 if(nt->op != OTYPE)
927                         yyerror("%S is not a type", nt->sym);
928                 else
929                         t = nt->type;
930         }
931         n = nod(ODCLFIELD, newname(nn->sym), N);
932         n->type = t;
933         return n;
934 }
935
936 /*
937  * check that the list of declarations is either all anonymous or all named
938  */
939 NodeList*
940 checkarglist(NodeList *all)
941 {
942         int named;
943         Node *r;
944         NodeList *l;
945
946         named = 0;
947         for(l=all; l; l=l->next) {
948                 if(l->n->op == OKEY) {
949                         named = 1;
950                         break;
951                 }
952         }
953
954         for(l=all; l; l=l->next) {
955                 if(named)
956                         l->n = namedcl(l->n, findtype(l));
957                 else
958                         l->n = xanondcl(l->n);
959                 if(l->next != nil) {
960                         r = l->n;
961                         if(r != N && r->type != T && r->type->etype == TDDD)
962                                 yyerror("only last argument can have type ...");
963                 }
964         }
965         return all;
966 }
967
968
969 Node*
970 fakethis(void)
971 {
972         Node *n;
973
974         n = nod(ODCLFIELD, N, N);
975         n->type = ptrto(typ(TSTRUCT));
976         return n;
977 }
978
979 /*
980  * Is this field a method on an interface?
981  * Those methods have an anonymous
982  * *struct{} as the receiver.
983  * (See fakethis above.)
984  */
985 int
986 isifacemethod(Type *f)
987 {
988         Type *rcvr;
989         Type *t;
990
991         rcvr = getthisx(f->type)->type;
992         if(rcvr->sym != S)
993                 return 0;
994         t = rcvr->type;
995         if(!isptr[t->etype])
996                 return 0;
997         t = t->type;
998         if(t->sym != S || t->etype != TSTRUCT || t->type != T)
999                 return 0;
1000         return 1;
1001 }
1002
1003 /*
1004  * turn a parsed function declaration
1005  * into a type
1006  */
1007 Type*
1008 functype(Node *this, NodeList *in, NodeList *out)
1009 {
1010         Type *t;
1011         NodeList *rcvr;
1012
1013         t = typ(TFUNC);
1014
1015         rcvr = nil;
1016         if(this)
1017                 rcvr = list1(this);
1018         t->type = dostruct(rcvr, TFUNC);
1019         t->type->down = dostruct(out, TFUNC);
1020         t->type->down->down = dostruct(in, TFUNC);
1021
1022         if(this)
1023                 t->thistuple = 1;
1024         t->outtuple = count(out);
1025         t->intuple = count(in);
1026
1027         checkwidth(t);
1028         return t;
1029 }
1030
1031 int
1032 methcmp(Type *t1, Type *t2)
1033 {
1034         if(t1->etype != TFUNC)
1035                 return 0;
1036         if(t2->etype != TFUNC)
1037                 return 0;
1038
1039         t1 = t1->type->down;    // skip this arg
1040         t2 = t2->type->down;    // skip this arg
1041         for(;;) {
1042                 if(t1 == t2)
1043                         break;
1044                 if(t1 == T || t2 == T)
1045                         return 0;
1046                 if(t1->etype != TSTRUCT || t2->etype != TSTRUCT)
1047                         return 0;
1048
1049                 if(!eqtype(t1->type, t2->type))
1050                         return 0;
1051
1052                 t1 = t1->down;
1053                 t2 = t2->down;
1054         }
1055         return 1;
1056 }
1057
1058 Sym*
1059 methodsym(Sym *nsym, Type *t0)
1060 {
1061         Sym *s;
1062         char buf[NSYMB];
1063         Type *t;
1064
1065         t = t0;
1066         if(t == T)
1067                 goto bad;
1068         s = t->sym;
1069         if(s == S) {
1070                 if(!isptr[t->etype])
1071                         goto bad;
1072                 t = t->type;
1073                 if(t == T)
1074                         goto bad;
1075                 s = t->sym;
1076                 if(s == S)
1077                         goto bad;
1078         }
1079
1080         // if t0 == *t and t0 has a sym,
1081         // we want to see *t, not t0, in the method name.
1082         if(t != t0 && t0->sym)
1083                 t0 = ptrto(t);
1084
1085         snprint(buf, sizeof(buf), "%#hTĀ·%s", t0, nsym->name);
1086 //print("methodname %s\n", buf);
1087         return pkglookup(buf, s->package);
1088
1089 bad:
1090         yyerror("illegal <this> type: %T", t);
1091         return S;
1092 }
1093
1094 Node*
1095 methodname(Node *n, Type *t)
1096 {
1097         Sym *s;
1098
1099         s = methodsym(n->sym, t);
1100         if(s == S)
1101                 return n;
1102         return newname(s);
1103 }
1104
1105 /*
1106  * add a method, declared as a function,
1107  * n is fieldname, pa is base type, t is function type
1108  */
1109 void
1110 addmethod(Node *n, Type *t, int local)
1111 {
1112         Type *f, *d, *pa;
1113         Sym *sf;
1114
1115         pa = nil;
1116         sf = nil;
1117
1118         // get field sym
1119         if(n == N)
1120                 goto bad;
1121         if(n->op != ONAME)
1122                 goto bad;
1123         sf = n->sym;
1124         if(sf == S)
1125                 goto bad;
1126
1127         // get parent type sym
1128         pa = *getthis(t);       // ptr to this structure
1129         if(pa == T)
1130                 goto bad;
1131         pa = pa->type;          // ptr to this field
1132         if(pa == T)
1133                 goto bad;
1134         pa = pa->type;          // ptr to this type
1135         if(pa == T)
1136                 goto bad;
1137
1138         f = methtype(pa);
1139         if(f == T)
1140                 goto bad;
1141
1142         pa = f;
1143         if(pkgimportname != S && !exportname(sf->name))
1144                 sf = pkglookup(sf->name, pkgimportname->name);
1145
1146         n = nod(ODCLFIELD, newname(sf), N);
1147         n->type = t;
1148
1149         d = T;  // last found
1150         for(f=pa->method; f!=T; f=f->down) {
1151                 d = f;
1152                 if(f->etype != TFIELD)
1153                         fatal("addmethod: not TFIELD: %N", f);
1154                 if(strcmp(sf->name, f->sym->name) != 0)
1155                         continue;
1156                 if(!eqtype(t, f->type)) {
1157                         yyerror("method redeclared: %T.%S", pa, sf);
1158                         print("\t%T\n\t%T\n", f->type, t);
1159                 }
1160                 return;
1161         }
1162
1163         if(local && !pa->local) {
1164                 // defining method on non-local type.
1165                 // method must have been forward declared
1166                 // elsewhere, i.e. where the type was.
1167                 yyerror("cannot define new methods on non-local type %T", pa);
1168                 return;
1169         }
1170
1171         if(d == T)
1172                 stotype(list1(n), 0, &pa->method);
1173         else
1174                 stotype(list1(n), 0, &d->down);
1175         return;
1176
1177 bad:
1178         yyerror("invalid receiver type %T", pa);
1179 }
1180
1181 /*
1182  * declare the function proper.
1183  * and declare the arguments
1184  * called in extern-declaration context
1185  * returns in auto-declaration context.
1186  */
1187 void
1188 funchdr(Node *n)
1189 {
1190         Node *on;
1191         Sym *s;
1192
1193         s = n->nname->sym;
1194         on = s->def;
1195         if(on != N && (on->op != ONAME || on->builtin))
1196                 on = N;
1197
1198         // check for same types
1199         if(on != N) {
1200                 if(eqtype(n->type, on->type)) {
1201                         if(!eqargs(n->type, on->type)) {
1202                                 yyerror("function arg names changed: %S", s);
1203                                 print("\t%T\n\t%T\n", on->type, n->type);
1204                         }
1205                 } else {
1206                         yyerror("function redeclared: %S", s);
1207                         print("\t%T\n\t%T\n", on->type, n->type);
1208                         on = N;
1209                 }
1210         }
1211
1212         // check for forward declaration
1213         if(on == N) {
1214                 // initial declaration or redeclaration
1215                 // declare fun name, argument types and argument names
1216                 n->nname->type = n->type;
1217                 if(n->type->thistuple == 0)
1218                         addvar(n->nname, n->type, PFUNC);
1219                 else
1220                         n->nname->class = PFUNC;
1221         } else {
1222                 // identical redeclaration
1223                 // steal previous names
1224                 n->nname = on;
1225                 n->type = on->type;
1226                 n->class = on->class;
1227                 n->sym = s;
1228         }
1229
1230         // change the declaration context from extern to auto
1231         autodcl = dcl();
1232         autodcl->back = autodcl;
1233
1234         if(funcdepth == 0 && dclcontext != PEXTERN)
1235                 fatal("funchdr: dclcontext");
1236
1237         dclcontext = PAUTO;
1238         markdcl();
1239         funcargs(n->type);
1240 }
1241
1242 void
1243 funcargs(Type *ft)
1244 {
1245         Type *t;
1246         Iter save;
1247         int all;
1248
1249         funcdepth++;
1250
1251         // declare the this/in arguments
1252         t = funcfirst(&save, ft);
1253         while(t != T) {
1254                 if(t->nname != N) {
1255                         t->nname->xoffset = t->width;
1256                         addvar(t->nname, t->type, PPARAM);
1257                 }
1258                 t = funcnext(&save);
1259         }
1260
1261         // declare the outgoing arguments
1262         all = 0;
1263         t = structfirst(&save, getoutarg(ft));
1264         while(t != T) {
1265                 if(t->nname != N)
1266                         t->nname->xoffset = t->width;
1267                 if(t->nname != N) {
1268                         addvar(t->nname, t->type, PPARAMOUT);
1269                         all |= 1;
1270                 } else
1271                         all |= 2;
1272                 t = structnext(&save);
1273         }
1274
1275         // this test is remarkedly similar to checkarglist
1276         if(all == 3)
1277                 yyerror("cannot mix anonymous and named output arguments");
1278
1279         ft->outnamed = 0;
1280         if(all == 1)
1281                 ft->outnamed = 1;
1282 }
1283
1284 /*
1285  * compile the function.
1286  * called in auto-declaration context.
1287  * returns in extern-declaration context.
1288  */
1289 void
1290 funcbody(Node *n)
1291 {
1292
1293         compile(n);
1294
1295         // change the declaration context from auto to extern
1296         if(dclcontext != PAUTO)
1297                 fatal("funcbody: dclcontext");
1298         popdcl();
1299         funcdepth--;
1300         if(funcdepth == 0)
1301                 dclcontext = PEXTERN;
1302 }
1303
1304 Node*
1305 funclit0(Node *t)
1306 {
1307         Node *n;
1308
1309         n = nod(OXXX, N, N);
1310         n->outer = funclit;
1311         n->dcl = autodcl;
1312         funclit = n;
1313
1314         // new declaration context
1315         autodcl = dcl();
1316         autodcl->back = autodcl;
1317
1318         typecheck(&t, Etype);
1319         funcargs(t->type);
1320         return t;
1321 }
1322
1323 Node*
1324 funclit1(Node *ntype, NodeList *body)
1325 {
1326         Node *func;
1327         Type *type;
1328         Node *a, *d, *f, *n, *clos;
1329         Type *ft, *t;
1330         Iter save;
1331         int narg, shift;
1332         NodeList *args, *l, *in, *out;
1333
1334         type = ntype->type;
1335         popdcl();
1336         func = funclit;
1337         funclit = func->outer;
1338
1339         // build up type of func f that we're going to compile.
1340         // as we referred to variables from the outer function,
1341         // we accumulated a list of PHEAP names in func->cvars.
1342         narg = 0;
1343         // add PHEAP versions as function arguments.
1344         in = nil;
1345         for(l=func->cvars; l; l=l->next) {
1346                 a = l->n;
1347                 d = nod(ODCLFIELD, a, N);
1348                 d->type = ptrto(a->type);
1349                 in = list(in, d);
1350
1351                 // while we're here, set up a->heapaddr for back end
1352                 n = nod(ONAME, N, N);
1353                 snprint(namebuf, sizeof namebuf, "&%s", a->sym->name);
1354                 n->sym = lookup(namebuf);
1355                 n->type = ptrto(a->type);
1356                 n->class = PPARAM;
1357                 n->xoffset = narg*types[tptr]->width;
1358                 n->addable = 1;
1359                 n->ullman = 1;
1360                 narg++;
1361                 a->heapaddr = n;
1362
1363                 a->xoffset = 0;
1364
1365                 // unlink from actual ONAME in symbol table
1366                 a->closure->closure = a->outer;
1367         }
1368
1369         // add a dummy arg for the closure's caller pc
1370         d = nod(ODCLFIELD, N, N);
1371         d->type = types[TUINTPTR];
1372         in = list(in, d);
1373
1374         // slide param offset to make room for ptrs above.
1375         // narg+1 to skip over caller pc.
1376         shift = (narg+1)*types[tptr]->width;
1377
1378         // now the original arguments.
1379         for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) {
1380                 d = nod(ODCLFIELD, t->nname, N);
1381                 d->type = t->type;
1382                 in = list(in, d);
1383
1384                 a = t->nname;
1385                 if(a != N) {
1386                         if(a->stackparam != N)
1387                                 a = a->stackparam;
1388                         a->xoffset += shift;
1389                 }
1390         }
1391
1392         // out arguments
1393         out = nil;
1394         for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) {
1395                 d = nod(ODCLFIELD, t->nname, N);
1396                 d->type = t->type;
1397                 out = list(out, d);
1398
1399                 a = t->nname;
1400                 if(a != N) {
1401                         if(a->stackparam != N)
1402                                 a = a->stackparam;
1403                         a->xoffset += shift;
1404                 }
1405         }
1406
1407         ft = functype(N, in, out);
1408         ft->outnamed = type->outnamed;
1409
1410         // declare function.
1411         vargen++;
1412         snprint(namebuf, sizeof(namebuf), "_f%.3ldĀ·%s", vargen, filename);
1413         f = newname(lookup(namebuf));
1414         addvar(f, ft, PFUNC);
1415         f->funcdepth = 0;
1416
1417         // compile function
1418         n = nod(ODCLFUNC, N, N);
1419         n->nname = f;
1420         n->type = ft;
1421         if(body == nil)
1422                 body = list1(nod(OEMPTY, N, N));
1423         n->nbody = body;
1424         compile(n);
1425         funcdepth--;
1426         autodcl = func->dcl;
1427
1428         // build up type for this instance of the closure func.
1429         in = nil;
1430         d = nod(ODCLFIELD, N, N);       // siz
1431         d->type = types[TINT];
1432         in = list(in, d);
1433         d = nod(ODCLFIELD, N, N);       // f
1434         d->type = ft;
1435         in = list(in, d);
1436         for(l=func->cvars; l; l=l->next) {
1437                 a = l->n;
1438                 d = nod(ODCLFIELD, N, N);       // arg
1439                 d->type = ptrto(a->type);
1440                 in = list(in, d);
1441         }
1442
1443         d = nod(ODCLFIELD, N, N);
1444         d->type = type;
1445         out = list1(d);
1446
1447         clos = syslook("closure", 1);
1448         clos->type = functype(N, in, out);
1449
1450         // literal expression is sys.closure(siz, f, arg0, arg1, ...)
1451         // which builds a function that calls f after filling in arg0,
1452         // arg1, ... for the PHEAP arguments above.
1453         args = nil;
1454         if(narg*widthptr > 100)
1455                 yyerror("closure needs too many variables; runtime will reject it");
1456         a = nodintconst(narg*widthptr);
1457         args = list(args, a);   // siz
1458         args = list(args, f);   // f
1459         for(l=func->cvars; l; l=l->next) {
1460                 a = l->n;
1461                 d = oldname(a->sym);
1462                 args = list(args, nod(OADDR, d, N));
1463         }
1464         typechecklist(args, Erv);
1465
1466         n = nod(OCALL, clos, N);
1467         n->list = args;
1468         return n;
1469 }