blob: de54f1fe382dc349ea9b8eac3c28d87dd6319e63 [file] [log] [blame]
// 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);
}