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 static void dumpsym(Sym*);
9 static void dumpexporttype(Sym*);
10 static void dumpexportvar(Sym*);
11 static void dumpexportconst(Sym*);
12
13 void
14 exportsym(Node *n)
15 {
16 if(n == N || n->sym == S)
17 return;
18 if(n->sym->flags & (SymExport|SymPackage)) {
19 if(n->sym->flags & SymPackage)
20 yyerror("export/package mismatch: %S", n->sym);
21 return;
22 }
23 n->sym->flags |= SymExport;
24
25 exportlist = list(exportlist, n);
26 }
27
28 static void
29 packagesym(Node *n)
30 {
31 if(n == N || n->sym == S)
32 return;
33 if(n->sym->flags & (SymExport|SymPackage)) {
34 if(n->sym->flags & SymExport)
35 yyerror("export/package mismatch: %S", n->sym);
36 return;
37 }
38 n->sym->flags |= SymPackage;
39
40 exportlist = list(exportlist, n);
41 }
42
43 int
44 exportname(char *s)
45 {
46 Rune r;
47
48 if((uchar)s[0] < Runeself)
49 return 'A' <= s[0] && s[0] <= 'Z';
50 chartorune(&r, s);
51 return isupperrune(r);
52 }
53
54 static int
55 initname(char *s)
56 {
57 return strcmp(s, "init") == 0;
58 }
59
60 void
61 autoexport(Node *n, int ctxt)
62 {
63 if(n == N || n->sym == S)
64 return;
65 if((ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN)
66 return;
67 if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left) // method
68 return;
69 if(exportname(n->sym->name) || initname(n->sym->name))
70 exportsym(n);
71 else
72 packagesym(n);
73 }
74
75 static void
76 dumppkg(Pkg *p)
77 {
78 char *suffix;
79
80 if(p == nil || p == localpkg || p->exported)
81 return;
82 p->exported = 1;
83 suffix = "";
84 if(!p->direct)
85 suffix = " // indirect";
86 Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix);
87 }
88
89 static void
90 dumpprereq(Type *t)
91 {
92 if(t == T)
93 return;
94
95 if(t->printed || t == types[t->etype])
96 return;
97 t->printed = 1;
98
99 if(t->sym != S) {
100 dumppkg(t->sym->pkg);
101 if(t->etype != TFIELD)
102 dumpsym(t->sym);
103 }
104 dumpprereq(t->type);
105 dumpprereq(t->down);
106 }
107
108 static void
109 dumpexportconst(Sym *s)
110 {
111 Node *n;
112 Type *t;
113
114 n = s->def;
115 typecheck(&n, Erv);
116 if(n == N || n->op != OLITERAL)
117 fatal("dumpexportconst: oconst nil: %S", s);
118
119 t = n->type; // may or may not be specified
120 if(t != T)
121 dumpprereq(t);
122
123 Bprint(bout, "\t");
124 Bprint(bout, "const %#S", s);
125 if(t != T && !isideal(t))
126 Bprint(bout, " %#T", t);
127 Bprint(bout, " = ");
128
129 switch(n->val.ctype) {
130 default:
131 fatal("dumpexportconst: unknown ctype: %S %d", s, n->val.ctype);
132 case CTINT:
133 Bprint(bout, "%B\n", n->val.u.xval);
134 break;
135 case CTBOOL:
136 if(n->val.u.bval)
137 Bprint(bout, "true\n");
138 else
139 Bprint(bout, "false\n");
140 break;
141 case CTFLT:
142 Bprint(bout, "%F\n", n->val.u.fval);
143 break;
144 case CTCPLX:
145 Bprint(bout, "(%F+%F)\n", &n->val.u.cval->real, &n->val.u.cval->imag);
146 break;
147 case CTSTR:
148 Bprint(bout, "\"%Z\"\n", n->val.u.sval);
149 break;
150 }
151 }
152
153 static void
154 dumpexportvar(Sym *s)
155 {
156 Node *n;
157 Type *t;
158
159 n = s->def;
160 typecheck(&n, Erv);
161 if(n == N || n->type == T) {
162 yyerror("variable exported but not defined: %S", s);
163 return;
164 }
165
166 t = n->type;
167 dumpprereq(t);
168
169 Bprint(bout, "\t");
170 if(t->etype == TFUNC && n->class == PFUNC)
171 Bprint(bout, "func %#S %#hhT", s, t);
172 else
173 Bprint(bout, "var %#S %#T", s, t);
174 Bprint(bout, "\n");
175 }
176
177 static void
178 dumpexporttype(Sym *s)
179 {
180 Type *t;
181
182 t = s->def->type;
183 dumpprereq(t);
184 Bprint(bout, "\t");
185 switch (t->etype) {
186 case TFORW:
187 yyerror("export of incomplete type %T", t);
188 return;
189 }
190 if(Bprint(bout, "type %#T %l#T\n", t, t) < 0)
191 fatal("Bprint failed for %T", t);
192 }
193
194 static int
195 methcmp(const void *va, const void *vb)
196 {
197 Type *a, *b;
198
199 a = *(Type**)va;
200 b = *(Type**)vb;
201 return strcmp(a->sym->name, b->sym->name);
202 }
203
204 static void
205 dumpsym(Sym *s)
206 {
207 Type *f, *t;
208 Type **m;
209 int i, n;
210
211 if(s->flags & SymExported)
212 return;
213 s->flags |= SymExported;
214
215 if(s->def == N) {
216 yyerror("unknown export symbol: %S", s);
217 return;
218 }
219
220 dumppkg(s->pkg);
221
222 switch(s->def->op) {
223 default:
224 yyerror("unexpected export symbol: %O %S", s->def->op, s);
225 break;
226 case OLITERAL:
227 dumpexportconst(s);
228 break;
229 case OTYPE:
230 t = s->def->type;
231 n = 0;
232 for(f=t->method; f!=T; f=f->down) {
233 dumpprereq(f);
234 n++;
235 }
236 m = mal(n*sizeof m[0]);
237 i = 0;
238 for(f=t->method; f!=T; f=f->down)
239 m[i++] = f;
240 qsort(m, n, sizeof m[0], methcmp);
241
242 dumpexporttype(s);
243 for(i=0; i<n; i++) {
244 f = m[i];
245 Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
246 f->type->type->type, f->sym, f->type);
247 }
248 break;
249 case ONAME:
250 dumpexportvar(s);
251 break;
252 }
253 }
254
255 static void
256 dumptype(Type *t)
257 {
258 // no need to re-dump type if already exported
259 if(t->printed)
260 return;
261
262 // no need to dump type if it's not ours (was imported)
263 if(t->sym != S && t->sym->def == typenod(t) && !t->local)
264 return;
265
266 Bprint(bout, "type %#T %l#T\n", t, t);
267 }
268
269 void
270 dumpexport(void)
271 {
272 NodeList *l;
273 int32 i, lno;
274 Pkg *p;
275
276 lno = lineno;
277
278 packagequotes = 1;
279 Bprint(bout, "\n$$ // exports\n");
280
281 Bprint(bout, " package %s", localpkg->name);
282 if(safemode)
283 Bprint(bout, " safe");
284 Bprint(bout, "\n");
285
286 for(i=0; i<nelem(phash); i++)
287 for(p=phash[i]; p; p=p->link)
288 if(p->direct)
289 dumppkg(p);
290
291 for(l=exportlist; l; l=l->next) {
292 lineno = l->n->lineno;
293 dumpsym(l->n->sym);
294 }
295
296 Bprint(bout, "\n$$ // local types\n");
297
298 for(l=typelist; l; l=l->next) {
299 lineno = l->n->lineno;
300 dumptype(l->n->type);
301 }
302
303 Bprint(bout, "\n$$\n");
304 packagequotes = 0;
305
306 lineno = lno;
307 }
308
309 /*
310 * import
311 */
312
313 /*
314 * return the sym for ss, which should match lexical
315 */
316 Sym*
317 importsym(Sym *s, int op)
318 {
319 if(s->def != N && s->def->op != op)
320 redeclare(s, "during import");
321
322 // mark the symbol so it is not reexported
323 if(s->def == N) {
324 if(exportname(s->name) || initname(s->name))
325 s->flags |= SymExport;
326 else
327 s->flags |= SymPackage; // package scope
328 }
329 return s;
330 }
331
332 /*
333 * return the type pkg.name, forward declaring if needed
334 */
335 Type*
336 pkgtype(Sym *s)
337 {
338 Type *t;
339
340 importsym(s, OTYPE);
341 if(s->def == N || s->def->op != OTYPE) {
342 t = typ(TFORW);
343 t->sym = s;
344 s->def = typenod(t);
345 }
346 if(s->def->type == T)
347 yyerror("pkgtype %lS", s);
348 return s->def->type;
349 }
350
351 static int
352 mypackage(Sym *s)
353 {
354 // we import all definitions for runtime.
355 // lowercase ones can only be used by the compiler.
356 return s->pkg == localpkg || s->pkg == runtimepkg;
357 }
358
359 void
360 importconst(Sym *s, Type *t, Node *n)
361 {
362 Node *n1;
363
364 if(!exportname(s->name) && !mypackage(s))
365 return;
366 importsym(s, OLITERAL);
367 convlit(&n, t);
368 if(s->def != N) {
369 // TODO: check if already the same.
370 return;
371 }
372
373 if(n->op != OLITERAL) {
374 yyerror("expression must be a constant");
375 return;
376 }
377 if(n->sym != S) {
378 n1 = nod(OXXX, N, N);
379 *n1 = *n;
380 n = n1;
381 }
382 n->sym = s;
383 declare(n, PEXTERN);
384
385 if(debug['E'])
386 print("import const %S\n", s);
387 }
388
389 void
390 importvar(Sym *s, Type *t, int ctxt)
391 {
392 Node *n;
393
394 if(!exportname(s->name) && !initname(s->name) && !mypackage(s))
395 return;
396
397 importsym(s, ONAME);
398 if(s->def != N && s->def->op == ONAME) {
399 if(eqtype(t, s->def->type))
400 return;
401 yyerror("inconsistent definition for var %S during import\n\t%T\n\t%T",
402 s, s->def->type, t);
403 }
404 n = newname(s);
405 n->type = t;
406 declare(n, ctxt);
407
408 if(debug['E'])
409 print("import var %S %lT\n", s, t);
410 }
411
412 void
413 importtype(Type *pt, Type *t)
414 {
415 if(pt != T && t != T)
416 typedcl2(pt, t);
417
418 if(debug['E'])
419 print("import type %T %lT\n", pt, t);
420 }
421
422 void
423 importmethod(Sym *s, Type *t)
424 {
425 checkwidth(t);
426 addmethod(s, t, 0);
427 }
428