| // 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" | |
| #include "y.tab.h" | |
| void | |
| markexport(Node *n) | |
| { | |
| Sym *s; | |
| Dcl *d, *r; | |
| loop: | |
| if(n == N) | |
| return; | |
| if(n->op == OLIST) { | |
| markexport(n->left); | |
| n = n->right; | |
| goto loop; | |
| } | |
| if(n->op != OEXPORT) | |
| fatal("markexport: op no OEXPORT: %O", n->op); | |
| s = n->sym; | |
| if(n->psym != S) | |
| s = pkglookup(n->sym->name, n->psym->name); | |
| if(s->export != 0) | |
| return; | |
| s->export = 1; | |
| d = mal(sizeof(*d)); | |
| d->dsym = s; | |
| d->dnode = N; | |
| d->lineno = curio.lineno; | |
| r = exportlist; | |
| d->back = r->back; | |
| r->back->forw = d; | |
| r->back = d; | |
| } | |
| void | |
| reexport(Node *t) | |
| { | |
| Sym *s; | |
| if(t == N) | |
| fatal("reexport: type nil\n"); | |
| s = t->sym; | |
| if(s == S/* || s->name[0] == '_'*/) { | |
| exportgen++; | |
| snprint(namebuf, sizeof(namebuf), "_e%.3ld", exportgen); | |
| s = lookup(namebuf); | |
| s->lexical = LATYPE; | |
| s->otype = t; | |
| t->sym = s; | |
| } | |
| dumpexporttype(s); | |
| } | |
| void | |
| dumpexportconst(Sym *s) | |
| { | |
| Node *n, *t; | |
| if(s->exported != 0) | |
| return; | |
| s->exported = 1; | |
| n = s->oconst; | |
| if(n == N || n->op != OLITERAL) | |
| fatal("dumpexportconst: oconst nil: %S\n", s); | |
| t = n->type; // may or may not be specified | |
| if(t != N) | |
| reexport(t); | |
| Bprint(bout, "\tconst "); | |
| if(s->export != 0) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS ", s); | |
| if(t != N) | |
| Bprint(bout, "%lS ", t->sym); | |
| switch(n->val.ctype) { | |
| default: | |
| fatal("dumpexportconst: unknown ctype: %S\n", s); | |
| case CTINT: | |
| case CTSINT: | |
| case CTUINT: | |
| case CTBOOL: | |
| Bprint(bout, "0x%llux\n", n->val.vval); | |
| break; | |
| case CTFLT: | |
| Bprint(bout, "%.17e\n", n->val.dval); | |
| break; | |
| case CTSTR: | |
| Bprint(bout, "\"%Z\"\n", n->val.sval); | |
| break; | |
| } | |
| } | |
| void | |
| dumpexportvar(Sym *s) | |
| { | |
| Node *n, *t; | |
| if(s->exported != 0) | |
| return; | |
| s->exported = 1; | |
| n = s->oname; | |
| if(n == N || n->type == N) | |
| fatal("dumpexportvar: oname nil: %S\n", s); | |
| t = n->type; | |
| reexport(t); | |
| Bprint(bout, "\tvar "); | |
| if(s->export != 0) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS %lS\n", s, t->sym); | |
| } | |
| void | |
| dumpexporttype(Sym *s) | |
| { | |
| Node *t, *f; | |
| Sym *ts; | |
| int et; | |
| if(s->exported != 0) | |
| return; | |
| s->exported = 1; | |
| t = s->otype; | |
| if(t == N || t->op != OTYPE) | |
| fatal("dumpexporttype: otype nil: %S\n", s); | |
| if(t->sym != s) | |
| fatal("dumpexporttype: cross reference: %S\n", s); | |
| et = t->etype; | |
| switch(et) { | |
| default: | |
| if(et < 0 || et >= nelem(types) || types[et] == N) | |
| fatal("dumpexporttype: basic type: %E\n", et); | |
| /* type 5 */ | |
| Bprint(bout, "\ttype %lS %d\n", s, et); | |
| break; | |
| case TARRAY: | |
| reexport(t->type); | |
| /* type 2 */ | |
| Bprint(bout, "\ttype "); | |
| if(s->export != 0) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS [%lud] %lS\n", s, t->bound, t->type->sym); | |
| break; | |
| case TPTR: | |
| reexport(t->type); | |
| /* type 6 */ | |
| Bprint(bout, "\ttype "); | |
| if(s->export != 0) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS *%lS\n", s, t->type->sym); | |
| break; | |
| case TFUNC: | |
| for(f=t->type; f!=N; f=f->down) { | |
| if(f->op != OTYPE || f->etype != TSTRUCT) | |
| fatal("dumpexporttype: funct not field: %O/%E\n", | |
| f->op, f->etype); | |
| reexport(f); | |
| } | |
| /* type 3 */ | |
| Bprint(bout, "\ttype "); | |
| if(s->export != 0) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS (", s); | |
| for(f=t->type; f!=N; f=f->down) { | |
| if(f != t->type) | |
| Bprint(bout, " "); | |
| Bprint(bout, "%lS", f->sym); | |
| } | |
| Bprint(bout, ")\n"); | |
| break; | |
| case TSTRUCT: | |
| case TINTER: | |
| for(f=t->type; f!=N; f=f->down) { | |
| if(f->op != OTYPE || f->etype != TFIELD) | |
| fatal("dumpexporttype: funct not field: %O/%E\n", | |
| f->op, f->etype); | |
| reexport(f->type); | |
| } | |
| /* type 4 */ | |
| Bprint(bout, "\ttype "); | |
| if(s->export) | |
| Bprint(bout, "!"); | |
| Bprint(bout, "%lS %c", s, (et==TSTRUCT)? '{': '<'); | |
| for(f=t->type; f!=N; f=f->down) { | |
| ts = f->type->sym; | |
| if(f != t->type) | |
| Bprint(bout, " "); | |
| Bprint(bout, "%s %lS", f->sym->name, ts); | |
| } | |
| Bprint(bout, "%c\n", (et==TSTRUCT)? '}': '>'); | |
| break; | |
| } | |
| } | |
| void | |
| dumpe(Sym *s) | |
| { | |
| switch(s->lexical) { | |
| default: | |
| yyerror("unknown export symbol: %S\n", s, s->lexical); | |
| break; | |
| case LPACK: | |
| yyerror("package export symbol: %S\n", s); | |
| break; | |
| case LATYPE: | |
| case LBASETYPE: | |
| dumpexporttype(s); | |
| break; | |
| case LNAME: | |
| dumpexportvar(s); | |
| break; | |
| case LACONST: | |
| dumpexportconst(s); | |
| break; | |
| } | |
| } | |
| void | |
| dumpexport(void) | |
| { | |
| Dcl *d; | |
| long lno; | |
| lno = dynlineno; | |
| Bprint(bout, " import\n"); | |
| Bprint(bout, " ((\n"); | |
| // print it depth first | |
| for(d=exportlist->forw; d!=D; d=d->forw) { | |
| dynlineno = d->lineno; | |
| dumpe(d->dsym); | |
| } | |
| Bprint(bout, " ))\n"); | |
| dynlineno = lno; | |
| } | |
| /* | |
| * ******* import ******* | |
| */ | |
| Node* | |
| importlooktype(Node *n) | |
| { | |
| Sym *s; | |
| if(n->op != OIMPORT) | |
| fatal("importlooktype: oops1 %N\n", n); | |
| s = pkglookup(n->sym->name, n->psym->name); | |
| if(s->otype == N) | |
| fatal("importlooktype: oops2 %S\n", s); | |
| return s->otype; | |
| } | |
| Node** | |
| importstotype(Node *n, Node **t, Node *uber) | |
| { | |
| Node *f; | |
| Iter save; | |
| n = listfirst(&save, &n); | |
| loop: | |
| if(n == N) { | |
| *t = N; | |
| return t; | |
| } | |
| f = nod(OTYPE, N, N); | |
| f->etype = TFIELD; | |
| f->type = importlooktype(n); | |
| f->uberstruct = uber; | |
| if(n->fsym != S) { | |
| f->nname = newname(n->fsym); | |
| } else { | |
| vargen++; | |
| snprint(namebuf, sizeof(namebuf), "_m%.3ld", vargen); | |
| f->nname = newname(lookup(namebuf)); | |
| } | |
| f->sym = f->nname->sym; | |
| f->nname->uberstruct = uber; | |
| *t = f; | |
| t = &f->down; | |
| n = listnext(&save); | |
| goto loop; | |
| } | |
| int | |
| importcount(Node *t) | |
| { | |
| int i; | |
| Node *f; | |
| if(t == N || t->op != OTYPE || t->etype != TSTRUCT) | |
| fatal("importcount: not a struct: %N", t); | |
| i = 0; | |
| for(f=t->type; f!=N; f=f->down) | |
| i = i+1; | |
| return i; | |
| } | |
| void | |
| importfuncnam(Node *t) | |
| { | |
| Node *n, *n1; | |
| if(t->etype != TFUNC) | |
| fatal("importfuncnam: not func %T\n", t); | |
| if(t->thistuple > 0) { | |
| n1 = t->type; | |
| if(n1->sym == S) | |
| fatal("importfuncnam: no this"); | |
| n = newname(n1->sym); | |
| vargen++; | |
| n->vargen = vargen; | |
| n1->nname = n; | |
| } | |
| if(t->outtuple > 0) { | |
| n1 = t->type->down; | |
| if(n1->sym == S) | |
| fatal("importfuncnam: no output"); | |
| n = newname(n1->sym); | |
| vargen++; | |
| n->vargen = vargen; | |
| n1->nname = n; | |
| } | |
| if(t->intuple > 0) { | |
| n1 = t->type->down->down; | |
| if(n1->sym == S) | |
| fatal("importfuncnam: no input"); | |
| n = newname(n1->sym); | |
| vargen++; | |
| n->vargen = vargen; | |
| n1->nname = n; | |
| } | |
| } | |
| Sym* | |
| getimportsym(Node *ss) | |
| { | |
| char *pkg; | |
| Sym *s; | |
| pkg = ss->psym->name; | |
| if(ss->kaka) { | |
| pkg = package; | |
| if(pkgmyname != S) | |
| pkg = pkgmyname->name; | |
| } | |
| s = pkglookup(ss->sym->name, pkg); | |
| /* botch - need some diagnostic checking for the following assignment */ | |
| s->opackage = ss->osym->name; | |
| return s; | |
| } | |
| void | |
| importaddtyp(Node *ss, Node *t) | |
| { | |
| Sym *s; | |
| s = getimportsym(ss); | |
| if(s->otype == N || !eqtype(t, s->otype, 0)) { | |
| addtyp(newtype(s), t, PEXTERN); | |
| } | |
| } | |
| /* | |
| * LCONST importsym LITERAL | |
| * untyped constant | |
| */ | |
| void | |
| doimportc1(Node *ss, Val *v) | |
| { | |
| Node *n; | |
| Sym *s; | |
| n = nod(OLITERAL, N, N); | |
| n->val = *v; | |
| s = getimportsym(ss); | |
| if(s->oconst == N) { | |
| // botch sould ask if already declared the same | |
| dodclconst(newname(s), n); | |
| } | |
| } | |
| /* | |
| * LCONST importsym importsym LITERAL | |
| * typed constant | |
| */ | |
| void | |
| doimportc2(Node *ss, Node *st, Val *v) | |
| { | |
| Node *n, *t; | |
| Sym *s; | |
| n = nod(OLITERAL, N, N); | |
| n->val = *v; | |
| t = importlooktype(st); | |
| n->type = t; | |
| s = getimportsym(ss); | |
| if(s->oconst == N) { | |
| // botch sould ask if already declared the same | |
| dodclconst(newname(s), n); | |
| } | |
| } | |
| /* | |
| * LVAR importsym importsym | |
| * variable | |
| */ | |
| void | |
| doimportv1(Node *ss, Node *st) | |
| { | |
| Node *t; | |
| Sym *s; | |
| t = importlooktype(st); | |
| s = getimportsym(ss); | |
| if(s->oname == N || !eqtype(t, s->oname->type, 0)) { | |
| addvar(newname(s), t, dclcontext); | |
| } | |
| } | |
| /* | |
| * LTYPE importsym [ importsym ] importsym | |
| * array type | |
| */ | |
| void | |
| doimport1(Node *ss, Node *ss1, Node *s) | |
| { | |
| fatal("doimport1"); | |
| } | |
| /* | |
| * LTYPE importsym [ LLITERAL ] importsym | |
| * array type | |
| */ | |
| void | |
| doimport2(Node *ss, Val *b, Node *st) | |
| { | |
| Node *t; | |
| Sym *s; | |
| t = nod(OTYPE, N, N); | |
| t->etype = TARRAY; | |
| t->bound = b->vval; | |
| s = pkglookup(st->sym->name, st->psym->name); | |
| t->type = s->otype; | |
| importaddtyp(ss, t); | |
| } | |
| /* | |
| * LTYPE importsym '(' importsym_list ')' | |
| * function/method type | |
| */ | |
| void | |
| doimport3(Node *ss, Node *n) | |
| { | |
| Node *t; | |
| t = nod(OTYPE, N, N); | |
| t->etype = TFUNC; | |
| t->type = importlooktype(n->left); | |
| t->type->down = importlooktype(n->right->left); | |
| t->type->down->down = importlooktype(n->right->right); | |
| t->thistuple = importcount(t->type); | |
| t->outtuple = importcount(t->type->down); | |
| t->intuple = importcount(t->type->down->down); | |
| importfuncnam(t); | |
| importaddtyp(ss, t); | |
| } | |
| /* | |
| * LTYPE importsym '{' importsym_list '}' | |
| * structure type | |
| */ | |
| void | |
| doimport4(Node *ss, Node *n) | |
| { | |
| Node *t; | |
| t = nod(OTYPE, N, N); | |
| t->etype = TSTRUCT; | |
| importstotype(n, &t->type, t); | |
| importaddtyp(ss, t); | |
| } | |
| /* | |
| * LTYPE importsym LLITERAL | |
| * basic type | |
| */ | |
| void | |
| doimport5(Node *ss, Val *v) | |
| { | |
| int et; | |
| Node *t; | |
| et = v->vval; | |
| if(et <= 0 || et >= nelem(types) || types[et] == N) | |
| fatal("doimport5: bad type index: %E\n", et); | |
| t = nod(OTYPE, 0, 0); | |
| t->etype = et; | |
| t->sym = S; | |
| importaddtyp(ss, t); | |
| } | |
| /* | |
| * LTYPE importsym * importsym | |
| * pointer type | |
| */ | |
| void | |
| doimport6(Node *ss, Node *st) | |
| { | |
| Node *t; | |
| Sym *s; | |
| s = pkglookup(st->sym->name, st->psym->name); | |
| t = s->otype; | |
| if(t == N) | |
| t = forwdcl(s); | |
| else | |
| t = ptrto(t); | |
| importaddtyp(ss, t); | |
| } | |
| /* | |
| * LTYPE importsym '<' importsym '>' | |
| * interface type | |
| */ | |
| void | |
| doimport7(Node *ss, Node *n) | |
| { | |
| Node *t; | |
| t = nod(OTYPE, N, N); | |
| t->etype = TINTER; | |
| importstotype(n, &t->type, t); | |
| importaddtyp(ss, t); | |
| } |