History

Add limbo compiler written in limbo - Taken from the official Inferno repo

arr committed 9 years ago

Commit eb06d3d1 parent d773bc520 files · +24140 −0Browse files

Unified · Split

20 files
  1. limbo/compiler/arg.m +50 −0
  2. limbo/compiler/asm.b +263 −0
  3. limbo/compiler/com.b +1402 −0
  4. limbo/compiler/decls.b +1177 −0
  5. limbo/compiler/dis.b +560 −0
  6. limbo/compiler/disoptab.m +355 −0
  7. limbo/compiler/ecom.b +2345 −0
  8. limbo/compiler/gen.b +1011 −0
  9. limbo/compiler/isa.m +247 −0
  10. limbo/compiler/lex.b +1178 −0
  11. limbo/compiler/limbo.b +3104 −0
  12. limbo/compiler/limbo.m +527 −0
  13. limbo/compiler/limbo.y +1978 −0
  14. limbo/compiler/nodes.b +1402 −0
  15. limbo/compiler/opname.m +109 −0
  16. limbo/compiler/optim.b +3 −0
  17. limbo/compiler/sbl.b +397 −0
  18. limbo/compiler/stubs.b +575 −0
  19. limbo/compiler/typecheck.b +3223 −0
  20. limbo/compiler/types.b +4234 −0
limbo/compiler/arg.m+50−0
@@ -0,0 +1,50 @@
1Arg: adt
2{
3 argv: list of string;
4 c: int;
5 opts: string;
6
7 init: fn(argv: list of string): ref Arg;
8 opt: fn(arg: self ref Arg): int;
9 arg: fn(arg: self ref Arg): string;
10};
11
12Arg.init(argv: list of string): ref Arg
13{
14 if(argv != nil)
15 argv = tl argv;
16 return ref Arg(argv, 0, nil);
17}
18
19Arg.opt(arg: self ref Arg): int
20{
21 if(arg.opts != ""){
22 arg.c = arg.opts[0];
23 arg.opts = arg.opts[1:];
24 return arg.c;
25 }
26 if(arg.argv == nil)
27 return arg.c = 0;
28 arg.opts = hd arg.argv;
29 if(len arg.opts < 2 || arg.opts[0] != '-')
30 return arg.c = 0;
31 arg.argv = tl arg.argv;
32 if(arg.opts == "--")
33 return arg.c = 0;
34 arg.c = arg.opts[1];
35 arg.opts = arg.opts[2:];
36 return arg.c;
37}
38
39Arg.arg(arg: self ref Arg): string
40{
41 s := arg.opts;
42 arg.opts = "";
43 if(s != "")
44 return s;
45 if(arg.argv == nil)
46 return "";
47 s = hd arg.argv;
48 arg.argv = tl arg.argv;
49 return s;
50}
limbo/compiler/asm.b+263−0
@@ -0,0 +1,263 @@
1asmentry(e: ref Decl)
2{
3 if(e == nil)
4 return;
5 bout.puts("\tentry\t"+string e.pc.pc+", "+string e.desc.id+"\n");
6}
7
8asmmod(m: ref Decl)
9{
10 bout.puts("\tmodule\t");
11 bout.puts(m.sym.name);
12 bout.putc('\n');
13 for(m = m.ty.tof.ids; m != nil; m = m.next){
14 case m.store{
15 Dglobal =>
16 bout.puts("\tlink\t-1,-1,0x"+hex(sign(m), 0)+",\".mp\"\n");
17 Dfn =>
18 bout.puts("\tlink\t"+string m.desc.id+","+string m.pc.pc+",0x"+string hex(sign(m), 0)+",\"");
19 if(m.dot.ty.kind == Tadt)
20 bout.puts(m.dot.sym.name+".");
21 bout.puts(m.sym.name+"\"\n");
22 }
23 }
24}
25
26asmpath()
27{
28 bout.puts("\tsource\t\"" + srcpath() + "\"\n");
29}
30
31asmdesc(d: ref Desc)
32{
33 for(; d != nil; d = d.next){
34 bout.puts("\tdesc\t$"+string d.id+","+string d.size+",\"");
35 e := d.nmap;
36 m := d.map;
37 for(i := 0; i < e; i++)
38 bout.puts(hex(int m[i], 2));
39 bout.puts("\"\n");
40 }
41}
42
43asmvar(size: int, d: ref Decl)
44{
45 bout.puts("\tvar\t@mp," + string size + "\n");
46
47 for(; d != nil; d = d.next)
48 if(d.store == Dglobal && d.init != nil)
49 asminitializer(d.offset, d.init);
50}
51
52asmldt(size: int, d: ref Decl)
53{
54 bout.puts("\tldts\t@ldt," + string size + "\n");
55
56 for(; d != nil; d = d.next)
57 if(d.store == Dglobal && d.init != nil)
58 asminitializer(d.offset, d.init);
59}
60
61asminitializer(offset: int, n: ref Node)
62{
63 wild: ref Node;
64 c: ref Case;
65 lab: Label;
66 id: ref Decl;
67 i, e: int;
68
69 case n.ty.kind{
70 Tbyte =>
71 bout.puts("\tbyte\t@mp+"+string offset+","+string(int n.c.val & 16rff)+"\n");
72 Tint or
73 Tfix =>
74 bout.puts("\tword\t@mp+"+string offset+","+string(int n.c.val)+"\n");
75 Tbig =>
76 bout.puts("\tlong\t@mp+"+string offset+","+string n.c.val+" # "+string bhex(n.c.val, 16)+"\n");
77 Tstring =>
78 asmstring(offset, n.decl.sym);
79 Treal =>
80 fs := "";
81 ba := array[8] of byte;
82 export_real(ba, array[] of {n.c.rval});
83 for(i = 0; i < 8; i++)
84 fs += hex(int ba[i], 2);
85 bout.puts("\treal\t@mp+"+string offset+","+string n.c.rval+" # "+fs+"\n");
86 Tadt or
87 Tadtpick or
88 Ttuple =>
89 id = n.ty.ids;
90 for(n = n.left; n != nil; n = n.right){
91 asminitializer(offset + id.offset, n.left);
92 id = id.next;
93 }
94 Tcase =>
95 c = n.ty.cse;
96 bout.puts("\tword\t@mp+"+string offset+","+string c.nlab);
97 for(i = 0; i < c.nlab; i++){
98 lab = c.labs[i];
99 bout.puts(","+string(int lab.start.c.val)+","+string(int lab.stop.c.val+1)+","+string(lab.inst.pc));
100 }
101 if(c.iwild != nil)
102 bout.puts(","+string c.iwild.pc+"\n");
103 else
104 bout.puts(",-1\n");
105 Tcasel =>
106 c = n.ty.cse;
107 bout.puts("\tword\t@mp+"+string offset+","+string c.nlab);
108 for(i = 0; i < c.nlab; i++){
109 lab = c.labs[i];
110 bout.puts(","+string(lab.start.c.val)+","+string(lab.stop.c.val+big 1)+","+string(lab.inst.pc));
111 }
112 if(c.iwild != nil)
113 bout.puts(","+string c.iwild.pc+"\n");
114 else
115 bout.puts(",-1\n");
116 Tcasec =>
117 c = n.ty.cse;
118 bout.puts("\tword\t@mp+"+string offset+","+string c.nlab+"\n");
119 offset += IBY2WD;
120 for(i = 0; i < c.nlab; i++){
121 lab = c.labs[i];
122 asmstring(offset, lab.start.decl.sym);
123 offset += IBY2WD;
124 if(lab.stop != lab.start)
125 asmstring(offset, lab.stop.decl.sym);
126 offset += IBY2WD;
127 bout.puts("\tword\t@mp+"+string offset+","+string lab.inst.pc+"\n");
128 offset += IBY2WD;
129 }
130 if(c.iwild != nil)
131 bout.puts("\tword\t@mp+"+string offset+","+string c.iwild.pc+"\n");
132 else
133 bout.puts("\tword\t@mp+"+string offset+",-1\n");
134 Tgoto =>
135 c = n.ty.cse;
136 bout.puts("\tword\t@mp+"+string offset);
137 bout.puts(","+string(n.ty.size/IBY2WD-1));
138 for(i = 0; i < c.nlab; i++)
139 bout.puts(","+string c.labs[i].inst.pc);
140 if(c.iwild != nil)
141 bout.puts(","+string c.iwild.pc);
142 bout.puts("\n");
143 Tany =>
144 break;
145 Tarray =>
146 bout.puts("\tarray\t@mp+"+string offset+",$"+string n.ty.tof.decl.desc.id+","+string int n.left.c.val+"\n");
147 if(n.right == nil)
148 break;
149 bout.puts("\tindir\t@mp+"+string offset+",0\n");
150 c = n.right.ty.cse;
151 wild = nil;
152 if(c.wild != nil)
153 wild = c.wild.right;
154 last := 0;
155 esz := n.ty.tof.size;
156 for(i = 0; i < c.nlab; i++){
157 e = int c.labs[i].start.c.val;
158 if(wild != nil){
159 for(; last < e; last++)
160 asminitializer(esz * last, wild);
161 }
162 last = e;
163 e = int c.labs[i].stop.c.val;
164 elem := c.labs[i].node.right;
165 for(; last <= e; last++)
166 asminitializer(esz * last, elem);
167 }
168 if(wild != nil)
169 for(e = int n.left.c.val; last < e; last++)
170 asminitializer(esz * last, wild);
171 bout.puts("\tapop\n");
172 Tiface =>
173 if(LDT)
174 bout.puts("\tword\t@ldt+"+string offset+","+string int n.c.val+"\n");
175 else
176 bout.puts("\tword\t@mp+"+string offset+","+string int n.c.val+"\n");
177 offset += IBY2WD;
178 for(id = n.decl.ty.ids; id != nil; id = id.next){
179 offset = align(offset, IBY2WD);
180 if(LDT)
181 bout.puts("\text\t@ldt+"+string offset+",0x"+string hex(sign(id), 0)+",\"");
182 else
183 bout.puts("\text\t@mp+"+string offset+",0x"+string hex(sign(id), 0)+",\"");
184 dotlen := 0;
185 idlen := len array of byte id.sym.name + 1;
186 if(id.dot.ty.kind == Tadt){
187 dotlen = len array of byte id.dot.sym.name + 1;
188 bout.puts(id.dot.sym.name+".");
189 }
190 bout.puts(id.sym.name+"\"\n");
191 offset += idlen + dotlen + IBY2WD;
192 }
193 * =>
194 fatal("can't asm global "+nodeconv(n));
195 }
196}
197
198asmexc(es: ref Except)
199{
200 e: ref Except;
201
202 n := 0;
203 for(e = es; e != nil; e = e.next)
204 n++;
205 bout.puts("\texceptions\t" + string n + "\n");
206 for(e = es; e != nil; e = e.next){
207 if(!int e.p1.reach && !int e.p2.reach)
208 continue;
209 c := e.c;
210 o := e.d.offset;
211 if(e.desc != nil)
212 id := e.desc.id;
213 else
214 id = -1;
215 bout.puts("\texception\t" + string getpc(e.p1) + ", " + string getpc(e.p2) + ", " + string o + ", " + string id + ", " + string c.nlab + ", " + string e.ne + "\n");
216 for(i := 0; i < c.nlab; i++){
217 lab := c.labs[i];
218 d := lab.start.decl;
219 if(lab.start.ty.kind == Texception)
220 d = d.init.decl;
221 bout.puts("\texctab\t\"" + d.sym.name + "\", " + string lab.inst.pc + "\n");
222 }
223 if(c.iwild == nil)
224 bout.puts("\texctab\t" + "*" + ", " + string -1 + "\n");
225 else
226 bout.puts("\texctab\t" + "*" + ", " + string c.iwild.pc + "\n");
227 }
228}
229
230asmstring(offset: int, sym: ref Sym)
231{
232 bout.puts("\tstring\t@mp+"+string offset+",\"");
233 s := sym.name;
234 for(i := 0; i < len s; i++){
235 c := s[i];
236 if(c == '\n')
237 bout.puts("\\n");
238 else if(c == '\u0000')
239 bout.puts("\\z");
240 else if(c == '"')
241 bout.puts("\\\"");
242 else if(c == '\\')
243 bout.puts("\\\\");
244 else
245 bout.putc(c);
246 }
247 bout.puts("\"\n");
248}
249
250asminst(in: ref Inst)
251{
252 for(; in != nil; in = in.next){
253 if(in.op == INOOP)
254 continue;
255 if(in.pc % 10 == 0){
256 bout.putc('#');
257 bout.puts(string in.pc);
258 bout.putc('\n');
259 }
260 bout.puts(instconv(in));
261 bout.putc('\n');
262 }
263}
limbo/compiler/com.b+1402−0
@@ -0,0 +1,1402 @@
1# back end
2
3breaks: array of ref Inst;
4conts: array of ref Inst;
5labels: array of ref Decl;
6bcscps: array of ref Node;
7labdep: int;
8nocont: ref Inst;
9nlabel: int;
10
11scp: int;
12scps:= array[MaxScope] of ref Node;
13
14curfn: ref Decl;
15
16pushscp(n : ref Node)
17{
18 if (scp >= MaxScope)
19 fatal("scope too deep");
20 scps[scp++] = n;
21}
22
23popscp()
24{
25 scp--;
26}
27
28curscp() : ref Node
29{
30 if (scp == 0)
31 return nil;
32 return scps[scp-1];
33}
34
35zeroscopes(stop : ref Node)
36{
37 i : int;
38 cs : ref Node;
39
40 for (i = scp-1; i >= 0; i--) {
41 cs = scps[i];
42 if (cs == stop)
43 break;
44 zcom(cs.left, nil);
45 }
46}
47
48zeroallscopes(n: ref Node, nn: array of ref Node)
49{
50 if(n == nil)
51 return;
52 for(; n != nil; n = n.right){
53 case(n.op){
54 Oscope =>
55 zeroallscopes(n.right, nn);
56 zcom(n.left, nn);
57 return;
58 Olabel or
59 Odo =>
60 zeroallscopes(n.right, nn);
61 return;
62 Oif or
63 Ofor =>
64 zeroallscopes(n.right.left, nn);
65 zeroallscopes(n.right.right, nn);
66 return;
67 Oalt or
68 Ocase or
69 Opick or
70 Oexcept =>
71 for(n = n.right; n != nil; n = n.right)
72 zeroallscopes(n.left.right, nn);
73 return;
74 Oseq =>
75 zeroallscopes(n.left, nn);
76 break;
77 Oexstmt =>
78 zeroallscopes(n.left, nn);
79 zeroallscopes(n.right, nn);
80 return;
81 * =>
82 return;
83 }
84 }
85}
86
87excs: ref Except;
88
89installexc(en: ref Node, p1: ref Inst, p2: ref Inst, zn: ref Node)
90{
91 e := ref Except;
92 e.p1 = p1;
93 e.p2 = p2;
94 e.c = en.ty.cse;
95 e.d = en.left.decl;
96 e.zn = zn;
97 e.next = excs;
98 excs = e;
99
100 ne := 0;
101 c := e.c;
102 for(i := 0; i < c.nlab; i++){
103 lab := c.labs[i];
104 if(lab.start.ty.kind == Texception)
105 ne++;
106 }
107 e.ne = ne;
108}
109
110inlist(d: ref Decl, dd: ref Decl): int
111{
112 for( ; dd != nil; dd = dd.next)
113 if(d == dd)
114 return 1;
115 return 0;
116}
117
118excdesc()
119{
120 dd, nd: ref Decl;
121
122 for(e := excs; e != nil; e = e.next){
123 if(e.zn != nil){
124 dd = nil;
125 maxo := 0;
126 for(n := e.zn ; n != nil; n = n.right){
127 d := n.decl;
128 d.locals = d.next;
129 if(!inlist(d, dd)){
130 d.next = dd;
131 dd = d;
132 o := d.offset+d.ty.size;
133 if(o > maxo)
134 maxo = o;
135 }
136 }
137 e.desc = gendesc(e.d, align(maxo, MaxAlign), dd);
138 for(d := dd; d != nil; d = nd){
139 nd = d.next;
140 d.next = d.locals;
141 d.locals = nil;
142 }
143 e.zn = nil;
144 }
145 }
146}
147
148reve(e: ref Except): ref Except
149{
150 l, n: ref Except;
151
152 l = nil;
153 for( ; e != nil; e = n){
154 n = e.next;
155 e.next = l;
156 l = e;
157 }
158 return l;
159}
160
161ckinline0(n: ref Node, d: ref Decl): int
162{
163 dd: ref Decl;
164
165 if(n == nil)
166 return 1;
167 if(n.op == Oname){
168 dd = n.decl;
169 if(d == dd)
170 return 0;
171 if(int dd.inline == 1)
172 return ckinline0(dd.init.right, d);
173 return 1;
174 }
175 return ckinline0(n.left, d) && ckinline0(n.right, d);
176}
177
178ckinline(d: ref Decl)
179{
180 d.inline = byte ckinline0(d.init.right, d);
181}
182
183modcom(entry: ref Decl)
184{
185 d, m: ref Decl;
186
187 if(errors)
188 return;
189
190 if(emitcode != "" || emitstub || emittab != "" || emitsbl != ""){
191 emit(curscope());
192 popscope();
193 return;
194 }
195
196 #
197 # scom introduces global variables for case statements
198 # and unaddressable constants, so it must be done before
199 # popping the global scope
200 #
201 gent = sys->millisec();
202 nlabel = 0;
203 maxstack = MaxTemp;
204 nocont = ref Inst;
205 genstart();
206
207 for(i := 0; i < nfns; i++)
208 if(int fns[i].inline == 1)
209 ckinline(fns[i]);
210
211 ok := 0;
212 for(i = 0; i < nfns; i++){
213 d = fns[i];
214 if(d.refs > 1 && !(int d.inline == 1 && local(d) && d.iface == nil)){
215 fns[ok++] = d;
216 fncom(d);
217 }
218 }
219 fns = fns[:ok];
220 nfns = ok;
221 if(blocks != -1)
222 fatal("blocks not nested correctly");
223 firstinst = firstinst.next;
224 if(errors)
225 return;
226
227 globals := popscope();
228 checkrefs(globals);
229 if(errors)
230 return;
231 globals = vars(globals);
232 moddataref();
233
234 nils := popscope();
235 m = nil;
236 for(d = nils; d != nil; d = d.next){
237 if(debug['n'])
238 print("nil '%s' ref %d\n", d.sym.name, d.refs);
239 if(d.refs && m == nil)
240 m = dupdecl(d);
241 d.offset = 0;
242 }
243 globals = appdecls(m, globals);
244 globals = namesort(globals);
245 globals = modglobals(impdecls.d, globals);
246 vcom(globals);
247 narrowmods();
248 ldts: ref Decl;
249 if(LDT)
250 (globals, ldts) = resolveldts(globals);
251 offset := idoffsets(globals, 0, IBY2WD);
252 if(LDT)
253 ldtoff := idindices(ldts); # idoffsets(ldts, 0, IBY2WD);
254 for(d = nils; d != nil; d = d.next){
255 if(debug['n'])
256 print("nil '%s' ref %d\n", d.sym.name, d.refs);
257 if(d.refs)
258 d.offset = m.offset;
259 }
260
261 if(debug['g']){
262 print("globals:\n");
263 printdecls(globals);
264 }
265
266 ndata := 0;
267 for(d = globals; d != nil; d = d.next)
268 ndata++;
269 ndesc := resolvedesc(impdecls.d, offset, globals);
270 ninst := resolvepcs(firstinst);
271 modresolve();
272 if(impdecls.next != nil)
273 for(dl := impdecls; dl != nil; dl = dl.next)
274 resolvemod(dl.d);
275 nlink := resolvemod(impdecl);
276 gent = sys->millisec() - gent;
277
278 maxstack *= 10;
279 if(fixss != 0)
280 maxstack = fixss;
281
282 if(debug['s'])
283 print("%d instructions\n%d data elements\n%d type descriptors\n%d functions exported\n%d stack size\n",
284 ninst, ndata, ndesc, nlink, maxstack);
285
286 excs = reve(excs);
287
288 writet = sys->millisec();
289 if(gendis){
290 discon(XMAGIC);
291 hints := 0;
292 if(mustcompile)
293 hints |= MUSTCOMPILE;
294 if(dontcompile)
295 hints |= DONTCOMPILE;
296 if(LDT)
297 hints |= HASLDT;
298 if(excs != nil)
299 hints |= HASEXCEPT;
300 discon(hints); # runtime hints
301 discon(maxstack); # minimum stack extent size
302 discon(ninst);
303 discon(offset);
304 discon(ndesc);
305 discon(nlink);
306 disentry(entry);
307 disinst(firstinst);
308 disdesc(descriptors);
309 disvar(offset, globals);
310 dismod(impdecl);
311 if(LDT)
312 disldt(ldtoff, ldts);
313 if(excs != nil)
314 disexc(excs);
315 dispath();
316 }else{
317 asminst(firstinst);
318 asmentry(entry);
319 asmdesc(descriptors);
320 asmvar(offset, globals);
321 asmmod(impdecl);
322 if(LDT)
323 asmldt(ldtoff, ldts);
324 if(excs != nil)
325 asmexc(excs);
326 asmpath();
327 }
328 writet = sys->millisec() - writet;
329
330 symt = sys->millisec();
331 if(bsym != nil){
332 sblmod(impdecl);
333
334 sblfiles();
335 sblinst(firstinst, ninst);
336 sblty(adts, nadts);
337 sblfn(fns, nfns);
338 sblvar(globals);
339 }
340 symt = sys->millisec() - symt;
341
342 firstinst = nil;
343 lastinst = nil;
344
345 excs = nil;
346}
347
348fncom(decl: ref Decl)
349{
350 curfn = decl;
351 if(ispoly(decl))
352 addfnptrs(decl, 1);
353
354 #
355 # pick up the function body and compile it
356 # this code tries to clean up the parse nodes as fast as possible
357 # function is Ofunc(name, body)
358 #
359 decl.pc = nextinst();
360 tinit();
361 labdep = 0;
362 scp = 0;
363 breaks = array[maxlabdep] of ref Inst;
364 conts = array[maxlabdep] of ref Inst;
365 labels = array[maxlabdep] of ref Decl;
366 bcscps = array[maxlabdep] of ref Node;
367
368 n := decl.init;
369 if(int decl.inline == 1)
370 decl.init = dupn(0, nosrc, n);
371 else
372 decl.init = n.left;
373 src := n.right.src;
374 src.start = src.stop - 1;
375 for(n = n.right; n != nil; n = n.right){
376 if(n.op != Oseq){
377 if(n.op == Ocall && trcom(n, nil, 1))
378 break;
379 scom(n);
380 break;
381 }
382 if(n.left.op == Ocall && trcom(n.left, n.right, 1)){
383 n = n.right;
384 if(n == nil || n.op != Oseq)
385 break;
386 }
387 else
388 scom(n.left);
389 }
390 pushblock();
391 valued := decl.ty.tof != tnone;
392 if(valued)
393 in := genrawop(src, IRAISE, nil, nil, nil);
394 else
395 in = genrawop(src, IRET, nil, nil, nil);
396 popblock();
397 reach(decl.pc);
398 if(valued && in.reach != byte 0)
399 error(src.start, "no return at end of function " + dotconv(decl));
400 # decl.endpc = lastinst;
401 if(labdep != 0)
402 fatal("unbalanced label stack");
403 breaks = nil;
404 conts = nil;
405 labels = nil;
406 bcscps = nil;
407
408 loc := declsort(appdecls(vars(decl.locals), tdecls()));
409
410 decl.offset = idoffsets(loc, decl.offset, MaxAlign);
411 for(last := decl.ty.ids; last != nil && last.next != nil; last = last.next)
412 ;
413 if(last != nil)
414 last.next = loc;
415 else
416 decl.ty.ids = loc;
417
418 if(debug['f']){
419 print("fn: %s\n", decl.sym.name);
420 printdecls(decl.ty.ids);
421 }
422
423 decl.desc = gendesc(decl, decl.offset, decl.ty.ids);
424 decl.locals = loc;
425 excdesc();
426 if(decl.offset > maxstack)
427 maxstack = decl.offset;
428 if(optims)
429 optim(decl.pc, decl);
430 if(last != nil)
431 last.next = nil;
432 else
433 decl.ty.ids = nil;
434}
435
436#
437# statement compiler
438#
439scom(n: ref Node)
440{
441 b: int;
442 p, pp: ref Inst;
443 left: ref Node;
444
445 for(; n != nil; n = n.right){
446 case n.op{
447 Ocondecl or
448 Otypedecl or
449 Ovardecl or
450 Oimport or
451 Oexdecl =>
452 return;
453 Ovardecli =>
454 break;
455 Oscope =>
456 pushscp(n);
457 scom(n.right);
458 popscp();
459 zcom(n.left, nil);
460 return;
461 Olabel =>
462 scom(n.right);
463 return;
464 Oif =>
465 pushblock();
466 left = simplify(n.left);
467 if(left.op == Oconst && left.ty == tint){
468 if(left.c.val != big 0)
469 scom(n.right.left);
470 else
471 scom(n.right.right);
472 popblock();
473 return;
474 }
475 sumark(left);
476 pushblock();
477 p = bcom(left, 1, nil);
478 tfreenow();
479 popblock();
480 scom(n.right.left);
481 if(n.right.right != nil){
482 pp = p;
483 p = genrawop(lastinst.src, IJMP, nil, nil, nil);
484 patch(pp, nextinst());
485 scom(n.right.right);
486 }
487 patch(p, nextinst());
488 popblock();
489 return;
490 Ofor =>
491 n.left = left = simplify(n.left);
492 if(left.op == Oconst && left.ty == tint){
493 if(left.c.val == big 0)
494 return;
495 left.op = Onothing;
496 left.ty = tnone;
497 left.decl = nil;
498 }
499 pp = nextinst();
500 b = pushblock();
501 sumark(left);
502 p = bcom(left, 1, nil);
503 tfreenow();
504 popblock();
505
506 if(labdep >= maxlabdep)
507 fatal("label stack overflow");
508 breaks[labdep] = nil;
509 conts[labdep] = nil;
510 labels[labdep] = n.decl;
511 bcscps[labdep] = curscp();
512 labdep++;
513 scom(n.right.left);
514 labdep--;
515
516 patch(conts[labdep], nextinst());
517 if(n.right.right != nil){
518 pushblock();
519 scom(n.right.right);
520 popblock();
521 }
522 repushblock(lastinst.block); # was b
523 patch(genrawop(lastinst.src, IJMP, nil, nil, nil), pp); # for cprof: was left.src
524 popblock();
525 patch(p, nextinst());
526 patch(breaks[labdep], nextinst());
527 return;
528 Odo =>
529 pp = nextinst();
530
531 if(labdep >= maxlabdep)
532 fatal("label stack overflow");
533 breaks[labdep] = nil;
534 conts[labdep] = nil;
535 labels[labdep] = n.decl;
536 bcscps[labdep] = curscp();
537 labdep++;
538 scom(n.right);
539 labdep--;
540
541 patch(conts[labdep], nextinst());
542
543 left = simplify(n.left);
544 if(left.op == Onothing
545 || left.op == Oconst && left.ty == tint){
546 if(left.op == Onothing || left.c.val != big 0){
547 pushblock();
548 p = genrawop(left.src, IJMP, nil, nil, nil);
549 popblock();
550 }else
551 p = nil;
552 }else{
553 pushblock();
554 p = bcom(sumark(left), 0, nil);
555 tfreenow();
556 popblock();
557 }
558 patch(p, pp);
559 patch(breaks[labdep], nextinst());
560 return;
561 Ocase or
562 Opick or
563 Oalt or
564 Oexcept =>
565 pushblock();
566 if(labdep >= maxlabdep)
567 fatal("label stack overflow");
568 breaks[labdep] = nil;
569 conts[labdep] = nocont;
570 labels[labdep] = n.decl;
571 bcscps[labdep] = curscp();
572 labdep++;
573 case n.op{
574 Oalt =>
575 altcom(n);
576 Ocase or
577 Opick =>
578 casecom(n);
579 Oexcept =>
580 excom(n);
581 }
582 labdep--;
583 patch(breaks[labdep], nextinst());
584 popblock();
585 return;
586 Obreak =>
587 pushblock();
588 bccom(n, breaks);
589 popblock();
590 Ocont =>
591 pushblock();
592 bccom(n, conts);
593 popblock();
594 Oseq =>
595 if(n.left.op == Ocall && trcom(n.left, n.right, 0)){
596 n = n.right;
597 if(n == nil || n.op != Oseq)
598 return;
599 }
600 else
601 scom(n.left);
602 Oret =>
603 if(n.left != nil && n.left.op == Ocall && trcom(n.left, nil, 1))
604 return;
605 pushblock();
606 if(n.left != nil){
607 n.left = simplify(n.left);
608 sumark(n.left);
609 ecom(n.left.src, retalloc(ref Node, n.left), n.left);
610 tfreenow();
611 }
612 genrawop(n.src, IRET, nil, nil, nil);
613 popblock();
614 return;
615 Oexit =>
616 pushblock();
617 genrawop(n.src, IEXIT, nil, nil, nil);
618 popblock();
619 return;
620 Onothing =>
621 return;
622 Ofunc =>
623 fatal("Ofunc");
624 return;
625 Oexstmt =>
626 pushblock();
627 pp = genrawop(n.right.src, IEXC0, nil, nil, nil); # marker
628 p1 := nextinst();
629 scom(n.left);
630 p2 := nextinst();
631 p3 := genrawop(n.right.src, IJMP, nil, nil, nil);
632 p = genrawop(n.right.src, IEXC, nil, nil, nil); # marker
633 p.d.decl = mkdecl(n.src, 0, n.right.ty);
634 zn := array[1] of ref Node;
635 zeroallscopes(n.left, zn);
636 scom(n.right);
637 patch(p3, nextinst());
638 installexc(n.right, p1, p2, zn[0]);
639 patch(pp, p);
640 popblock();
641 return;
642 * =>
643 pushblock();
644 n = simplify(n);
645 sumark(n);
646 ecom(n.src, nil, n);
647 tfreenow();
648 popblock();
649 return;
650 }
651 }
652}
653
654#
655# compile a break, continue
656#
657bccom(n: ref Node, bs: array of ref Inst)
658{
659 s: ref Sym;
660
661 s = nil;
662 if(n.decl != nil)
663 s = n.decl.sym;
664 ok := -1;
665 for(i := 0; i < labdep; i++){
666 if(bs[i] == nocont)
667 continue;
668 if(s == nil || labels[i] != nil && labels[i].sym == s)
669 ok = i;
670 }
671 if(ok < 0)
672 fatal("didn't find break or continue");
673 zeroscopes(bcscps[ok]);
674 p := genrawop(n.src, IJMP, nil, nil, nil);
675 p.branch = bs[ok];
676 bs[ok] = p;
677}
678
679dogoto(c: ref Case): int
680{
681 i, j, k, n, r, q, v: int;
682 l, nl: array of Label;
683 src: Src;
684
685 l = c.labs;
686 n = c.nlab;
687 if(n == 0)
688 return 0;
689 r = int l[n-1].stop.c.val - int l[0].start.c.val+1;
690 if(r >= 3 && r <= 3*n){
691 if(r != n){
692 # remove ranges, fill in gaps
693 c.nlab = r;
694 nl = c.labs = array[r] of Label;
695 k = 0;
696 v = int l[0].start.c.val-1;
697 for(i = 0; i < n; i++){
698 # p = int l[i].start.c.val;
699 q = int l[i].stop.c.val;
700 src = l[i].start.src;
701 for(j = v+1; j <= q; j++){
702 nl[k] = l[i];
703 nl[k].start = nl[k].stop = mkconst(src, big j);
704 k++;
705 }
706 v = q;
707 }
708 if(k != r)
709 fatal("bad case expansion");
710 }
711 l = c.labs;
712 for(i = 0; i < r; i++)
713 l[i].inst = nil;
714 return 1;
715 }
716 return 0;
717}
718
719fillrange(c: ref Case, nn: ref Node, in: ref Inst)
720{
721 i, j, n, p, q: int;
722 l: array of Label;
723
724 l = c.labs;
725 n = c.nlab;
726 p = int nn.left.c.val;
727 q = int nn.right.c.val;
728 for(i = 0; i < n; i++)
729 if(int l[i].start.c.val == p)
730 break;
731 if(i == n)
732 fatal("fillrange fails");
733 for(j = p; j <= q; j++)
734 l[i++].inst = in;
735}
736
737nconstqual(s1: ref Node): int
738{
739 n := 0;
740 for(; s1 != nil; s1 = s1.right){
741 for(s2 := s1.left.left; s2 != nil; s2 = s2.right)
742 if(s2.left.op == Oconst)
743 n++;
744 }
745 return n;
746}
747
748casecom(cn: ref Node)
749{
750 d: ref Decl;
751 left, p, tmp, tmpc: ref Node;
752 jmps, wild, j1, j2: ref Inst;
753
754 c := cn.ty.cse;
755
756 needwild := cn.op != Opick || nconstqual(cn.right) != cn.left.right.ty.tof.decl.tag;
757 igoto := cn.left.ty == tint && dogoto(c);
758
759 #
760 # generate global which has case labels
761 #
762 if(igoto){
763 d = mkids(cn.src, enter(".g"+string nlabel++, 0), cn.ty, nil);
764 cn.ty.kind = Tgoto;
765 }
766 else
767 d = mkids(cn.src, enter(".c"+string nlabel++, 0), cn.ty, nil);
768 d.init = mkdeclname(cn.src, d);
769 nto := ref znode;
770 nto.addable = Rmreg;
771 nto.left = nil;
772 nto.right = nil;
773 nto.op = Oname;
774 nto.ty = d.ty;
775 nto.decl = d;
776
777 tmp = nil;
778 left = cn.left;
779 left = simplify(left);
780 cn.left = left;
781 sumark(left);
782 if(debug['c'])
783 print("case %s\n", nodeconv(left));
784 ctype := cn.left.ty;
785 if(left.addable >= Rcant){
786 if(cn.op == Opick){
787 ecom(left.src, nil, left);
788 tfreenow();
789 left = mkunary(Oind, dupn(1, left.src, left.left));
790 left.ty = tint;
791 sumark(left);
792 ctype = tint;
793 }else{
794 (left, tmp) = eacom(left, nil);
795 tfreenow();
796 }
797 }
798
799 labs := c.labs;
800 nlab := c.nlab;
801
802 if(igoto){
803 if(labs[0].start.c.val != big 0){
804 tmpc = talloc(left.ty, nil);
805 if(left.addable == Radr || left.addable == Rmadr){
806 genrawop(left.src, IMOVW, left, nil, tmpc);
807 left = tmpc;
808 }
809 genrawop(left.src, ISUBW, sumark(labs[0].start), left, tmpc);
810 left = tmpc;
811 }
812 if(needwild){
813 j1 = genrawop(left.src, IBLTW, left, sumark(mkconst(left.src, big 0)), nil);
814 j2 = genrawop(left.src, IBGTW, left, sumark(mkconst(left.src, labs[nlab-1].start.c.val-labs[0].start.c.val)), nil);
815 }
816 j := nextinst();
817 genrawop(left.src, IGOTO, left, nil, nto);
818 j.d.reg = IBY2WD;
819 }
820 else{
821 op := ICASE;
822 if(ctype == tbig)
823 op = ICASEL;
824 else if(ctype == tstring)
825 op = ICASEC;
826 genrawop(left.src, op, left, nil, nto);
827 }
828 tfree(tmp);
829 tfree(tmpc);
830
831 jmps = nil;
832 wild = nil;
833 for(n := cn.right; n != nil; n = n.right){
834 j := nextinst();
835 for(p = n.left.left; p != nil; p = p.right){
836 if(debug['c'])
837 print("case qualifier %s\n", nodeconv(p.left));
838 case p.left.op{
839 Oconst =>
840 labs[findlab(ctype, p.left, labs, nlab)].inst = j;
841 Orange =>
842 labs[findlab(ctype, p.left.left, labs, nlab)].inst = j;
843 if(igoto)
844 fillrange(c, p.left, j);
845 Owild =>
846 if(needwild)
847 wild = j;
848 # else
849 # nwarn(p.left, "default case redundant");
850 }
851 }
852
853 if(debug['c'])
854 print("case body for %s: %s\n", expconv(n.left.left), nodeconv(n.left.right));
855
856 k := nextinst();
857 scom(n.left.right);
858
859 src := lastinst.src;
860 # if(n.left.right == nil || n.left.right.op == Onothing)
861 if(k == nextinst())
862 src = n.left.left.src;
863 j = genrawop(src, IJMP, nil, nil, nil);
864 j.branch = jmps;
865 jmps = j;
866 }
867 patch(jmps, nextinst());
868 if(wild == nil && needwild)
869 wild = nextinst();
870
871 if(igoto){
872 if(needwild){
873 patch(j1, wild);
874 patch(j2, wild);
875 }
876 for(i := 0; i < nlab; i++)
877 if(labs[i].inst == nil)
878 labs[i].inst = wild;
879 }
880
881 c.iwild = wild;
882
883 d.ty.cse = c;
884 usetype(d.ty);
885 installids(Dglobal, d);
886}
887
888altcom(nalt: ref Node)
889{
890 p, op, left: ref Node;
891 jmps, wild, j: ref Inst = nil;
892
893 talt := nalt.ty;
894 c := talt.cse;
895 nlab := c.nlab;
896 nsnd := c.nsnd;
897 comm := array[nlab] of ref Node;
898 labs := array[nlab] of Label;
899 tmps := array[nlab] of ref Node;
900 c.labs = labs;
901
902 #
903 # built the type of the alt channel table
904 # note that we lie to the garbage collector
905 # if we know that another reference exists for the channel
906 #
907 is := 0;
908 ir := nsnd;
909 i := 0;
910 for(n := nalt.left; n != nil; n = n.right){
911 for(p = n.left.right.left; p != nil; p = p.right){
912 left = simplify(p.left);
913 p.left = left;
914 if(left.op == Owild)
915 continue;
916 comm[i] = hascomm(left);
917 left = comm[i].left;
918 sumark(left);
919 isptr := left.addable >= Rcant;
920 if(comm[i].op == Osnd)
921 labs[is++].isptr = isptr;
922 else
923 labs[ir++].isptr = isptr;
924 i++;
925 }
926 }
927
928 which := talloc(tint, nil);
929 tab := talloc(talt, nil);
930
931 #
932 # build the node for the address of each channel,
933 # the values to send, and the storage fro values received
934 #
935 off := ref znode;
936 adr := ref znode;
937 add := ref znode;
938 slot := ref znode;
939 off.op = Oconst;
940 off.c = ref Const(big 0, 0.0); # jrf - added initialization
941 off.ty = tint;
942 off.addable = Rconst;
943 adr.op = Oadr;
944 adr.left = tab;
945 adr.ty = tint;
946 add.op = Oadd;
947 add.left = adr;
948 add.right = off;
949 add.ty = tint;
950 slot.op = Oind;
951 slot.left = add;
952 sumark(slot);
953
954 #
955 # compile the sending and receiving channels and values
956 #
957 is = 2*IBY2WD;
958 ir = is + nsnd*2*IBY2WD;
959 i = 0;
960 for(n = nalt.left; n != nil; n = n.right){
961 for(p = n.left.right.left; p != nil; p = p.right){
962 if(p.left.op == Owild)
963 continue;
964
965 #
966 # gen channel
967 #
968 op = comm[i];
969 if(op.op == Osnd){
970 off.c.val = big is;
971 is += 2*IBY2WD;
972 }else{
973 off.c.val = big ir;
974 ir += 2*IBY2WD;
975 }
976 left = op.left;
977
978 #
979 # this sleaze is lying to the garbage collector
980 #
981 if(left.addable < Rcant)
982 genmove(left.src, Mas, tint, left, slot);
983 else{
984 slot.ty = left.ty;
985 ecom(left.src, slot, left);
986 tfreenow();
987 slot.ty = nil;
988 }
989
990 #
991 # gen value
992 #
993 off.c.val += big IBY2WD;
994 (p.left, tmps[i]) = rewritecomm(p.left, comm[i], slot);
995
996 i++;
997 }
998 }
999
1000 #
1001 # stuff the number of send & receive channels into the table
1002 #
1003 altsrc := nalt.src;
1004 altsrc.stop = (altsrc.stop & ~PosMask) | ((altsrc.stop + 3) & PosMask);
1005 off.c.val = big 0;
1006 genmove(altsrc, Mas, tint, sumark(mkconst(altsrc, big nsnd)), slot);
1007 off.c.val += big IBY2WD;
1008 genmove(altsrc, Mas, tint, sumark(mkconst(altsrc, big(nlab-nsnd))), slot);
1009 off.c.val += big IBY2WD;
1010
1011 altop := IALT;
1012 if(c.wild != nil)
1013 altop = INBALT;
1014 pp := genrawop(altsrc, altop, tab, nil, which);
1015 pp.m.offset = talt.size; # for optimizer
1016
1017 d := mkids(nalt.src, enter(".g"+string nlabel++, 0), mktype(nalt.src.start, nalt.src.stop, Tgoto, nil, nil), nil);
1018 d.ty.cse = c;
1019 d.init = mkdeclname(nalt.src, d);
1020
1021 nto := ref znode;
1022 nto.addable = Rmreg;
1023 nto.left = nil;
1024 nto.right = nil;
1025 nto.op = Oname;
1026 nto.decl = d;
1027 nto.ty = d.ty;
1028
1029 me := genrawop(altsrc, IGOTO, which, nil, nto);
1030 me.d.reg = IBY2WD; # skip the number of cases field
1031 tfree(tab);
1032 tfree(which);
1033
1034 #
1035 # compile the guard expressions and bodies
1036 #
1037 i = 0;
1038 is = 0;
1039 ir = nsnd;
1040 jmps = nil;
1041 wild = nil;
1042 for(n = nalt.left; n != nil; n = n.right){
1043 j = nil;
1044 for(p = n.left.right.left; p != nil; p = p.right){
1045 tj := nextinst();
1046 if(p.left.op == Owild){
1047 wild = nextinst();
1048 }else{
1049 if(comm[i].op == Osnd)
1050 labs[is++].inst = tj;
1051 else{
1052 labs[ir++].inst = tj;
1053 tacquire(tmps[i]);
1054 }
1055 sumark(p.left);
1056 if(debug['a'])
1057 print("alt guard %s\n", nodeconv(p.left));
1058 ecom(p.left.src, nil, p.left);
1059 tfree(tmps[i]);
1060 tfreenow();
1061 i++;
1062 }
1063 if(p.right != nil){
1064 tj = genrawop(lastinst.src, IJMP, nil, nil, nil);
1065 tj.branch = j;
1066 j = tj;
1067 }
1068 }
1069
1070 patch(j, nextinst());
1071 if(debug['a'])
1072 print("alt body %s\n", nodeconv(n.left.right));
1073 scom(n.left);
1074
1075 j = genrawop(lastinst.src, IJMP, nil, nil, nil);
1076 j.branch = jmps;
1077 jmps = j;
1078 }
1079 patch(jmps, nextinst());
1080 comm = nil;
1081
1082 c.iwild = wild;
1083
1084 usetype(d.ty);
1085 installids(Dglobal, d);
1086}
1087
1088excom(en: ref Node)
1089{
1090 ed: ref Decl;
1091 p: ref Node;
1092 jmps, wild: ref Inst;
1093
1094 ed = en.left.decl;
1095 ed.ty = rtexception;
1096 c := en.ty.cse;
1097 labs := c.labs;
1098 nlab := c.nlab;
1099 jmps = nil;
1100 wild = nil;
1101 for(n := en.right; n != nil; n = n.right){
1102 qt: ref Type = nil;
1103 j := nextinst();
1104 for(p = n.left.left; p != nil; p = p.right){
1105 case p.left.op{
1106 Oconst =>
1107 labs[findlab(texception, p.left, labs, nlab)].inst = j;
1108 Owild =>
1109 wild = j;
1110 }
1111 if(qt == nil)
1112 qt = p.left.ty;
1113 else if(!tequal(qt, p.left.ty))
1114 qt = texception;
1115 }
1116 if(qt != nil)
1117 ed.ty = qt;
1118 k := nextinst();
1119 scom(n.left.right);
1120 src := lastinst.src;
1121 if(k == nextinst())
1122 src = n.left.left.src;
1123 j = genrawop(src, IJMP, nil, nil, nil);
1124 j.branch = jmps;
1125 jmps = j;
1126 }
1127 ed.ty = rtexception;
1128 patch(jmps, nextinst());
1129 c.iwild = wild;
1130}
1131
1132#
1133# rewrite the communication operand
1134# allocate any temps needed for holding value to send or receive
1135#
1136rewritecomm(n, comm, slot: ref Node): (ref Node, ref Node)
1137{
1138 adr, tmp: ref Node;
1139
1140 if(n == nil)
1141 return (nil, nil);
1142 adr = nil;
1143 if(n == comm){
1144 if(comm.op == Osnd && sumark(n.right).addable < Rcant)
1145 adr = n.right;
1146 else{
1147 adr = tmp = talloc(n.ty, nil);
1148 tmp.src = n.src;
1149 if(comm.op == Osnd){
1150 ecom(n.right.src, tmp, n.right);
1151 tfreenow();
1152 }
1153 else
1154 trelease(tmp);
1155 }
1156 }
1157 if(n.right == comm && n.op == Oas && comm.op == Orcv
1158 && sumark(n.left).addable < Rcant && (n.left.op != Oname || n.left.decl != nildecl))
1159 adr = n.left;
1160 if(adr != nil){
1161 p := genrawop(comm.left.src, ILEA, adr, nil, slot);
1162 p.m.offset = adr.ty.size; # for optimizer
1163 if(comm.op == Osnd)
1164 p.m.reg = 1; # for optimizer
1165 return (adr, tmp);
1166 }
1167 (n.left, tmp) = rewritecomm(n.left, comm, slot);
1168 if(tmp == nil)
1169 (n.right, tmp) = rewritecomm(n.right, comm, slot);
1170 return (n, tmp);
1171}
1172
1173#
1174# merge together two sorted lists, yielding a sorted list
1175#
1176declmerge(e, f: ref Decl): ref Decl
1177{
1178 d := rock := ref Decl;
1179 while(e != nil && f != nil){
1180 fs := f.ty.size;
1181 es := e.ty.size;
1182 # v := 0;
1183 v := (e.link == nil) - (f.link == nil);
1184 if(v == 0 && (es <= IBY2WD || fs <= IBY2WD))
1185 v = fs - es;
1186 if(v == 0)
1187 v = e.refs - f.refs;
1188 if(v == 0)
1189 v = fs - es;
1190 if(v == 0 && e.sym.name > f.sym.name)
1191 v = -1;
1192 if(v >= 0){
1193 d.next = e;
1194 d = e;
1195 e = e.next;
1196 while(e != nil && e.nid == byte 0){
1197 d = e;
1198 e = e.next;
1199 }
1200 }else{
1201 d.next = f;
1202 d = f;
1203 f = f.next;
1204 while(f != nil && f.nid == byte 0){
1205 d = f;
1206 f = f.next;
1207 }
1208 }
1209 # d = d.next;
1210 }
1211 if(e != nil)
1212 d.next = e;
1213 else
1214 d.next = f;
1215 return rock.next;
1216}
1217
1218#
1219# recursively split lists and remerge them after they are sorted
1220#
1221recdeclsort(d: ref Decl, n: int): ref Decl
1222{
1223 if(n <= 1)
1224 return d;
1225 m := n / 2 - 1;
1226 dd := d;
1227 for(i := 0; i < m; i++){
1228 dd = dd.next;
1229 while(dd.nid == byte 0)
1230 dd = dd.next;
1231 }
1232 r := dd.next;
1233 while(r.nid == byte 0){
1234 dd = r;
1235 r = r.next;
1236 }
1237 dd.next = nil;
1238 return declmerge(recdeclsort(d, n / 2),
1239 recdeclsort(r, (n + 1) / 2));
1240}
1241
1242#
1243# sort the ids by size and number of references
1244#
1245declsort(d: ref Decl): ref Decl
1246{
1247 n := 0;
1248 for(dd := d; dd != nil; dd = dd.next)
1249 if(dd.nid > byte 0)
1250 n++;
1251 return recdeclsort(d, n);
1252}
1253
1254nilsrc : Src;
1255
1256zcom1(n : ref Node, nn: array of ref Node)
1257{
1258 ty : ref Type;
1259 d : ref Decl;
1260 e : ref Node;
1261
1262 ty = n.ty;
1263 if (!tmustzero(ty))
1264 return;
1265 if (n.op == Oname && n.decl.refs == 0)
1266 return;
1267 if (nn != nil) {
1268 if(n.op != Oname)
1269 error(n.src.start, "fatal: bad op in zcom1 map");
1270 n.right = nn[0];
1271 nn[0] = n;
1272 return;
1273 }
1274 if (ty.kind == Tadtpick)
1275 ty = ty.tof;
1276 if (ty.kind == Ttuple || ty.kind == Tadt) {
1277 for (d = ty.ids; d != nil; d = d.next) {
1278 if (tmustzero(d.ty)) {
1279 dn := n;
1280 if (d.next != nil)
1281 dn = dupn(0, nilsrc, n);
1282 e = mkbin(Odot, dn, mkname(nilsrc, d.sym));
1283 e.right.decl = d;
1284 e.ty = e.right.ty = d.ty;
1285 zcom1(e, nn);
1286 }
1287 }
1288 }
1289 else {
1290 src := n.src;
1291 n.src = nilsrc;
1292 e = mkbin(Oas, n, mknil(nilsrc));
1293 e.ty = e.right.ty = ty;
1294 if (debug['Z'])
1295 print("ecom %s\n", nodeconv(e));
1296 pushblock();
1297 e = simplify(e);
1298 sumark(e);
1299 ecom(e.src, nil, e);
1300 popblock();
1301 n.src = src;
1302 e = nil;
1303 }
1304}
1305
1306zcom0(id : ref Decl, nn: array of ref Node)
1307{
1308 e := mkname(nilsrc, id.sym);
1309 e.decl = id;
1310 e.ty = id.ty;
1311 zcom1(e, nn);
1312}
1313
1314zcom(n : ref Node, nn: array of ref Node)
1315{
1316 r : ref Node;
1317
1318 for ( ; n != nil; n = r) {
1319 r = n.right;
1320 n.right = nil;
1321 case (n.op) {
1322 Ovardecl =>
1323 last := n.left.decl;
1324 for (ids := n.decl; ids != last.next; ids = ids.next)
1325 zcom0(ids, nn);
1326 break;
1327 Oname =>
1328 if (n.decl != nildecl)
1329 zcom1(dupn(0, nilsrc, n), nn);
1330 break;
1331 Otuple =>
1332 for (nt := n.left; nt != nil; nt = nt.right)
1333 zcom(nt.left, nn);
1334 break;
1335 * =>
1336 fatal("bad node in zcom()");
1337 break;
1338 }
1339 n.right = r;
1340 }
1341}
1342
1343ret(n: ref Node, nilret: int): int
1344{
1345 if(n == nil)
1346 return nilret;
1347 if(n.op == Oseq)
1348 n = n.left;
1349 return n.op == Oret && n.left == nil;
1350}
1351
1352trcom(e: ref Node, ne: ref Node, nilret: int): int
1353{
1354 d, id: ref Decl;
1355 as, a, f, n: ref Node;
1356 p: ref Inst;
1357
1358return 0; # TBS
1359 if(e.op != Ocall || e.left.op != Oname)
1360 return 0;
1361 d = e.left.decl;
1362 if(d != curfn || int d.handler || ispoly(d))
1363 return 0;
1364 if(!ret(ne, nilret))
1365 return 0;
1366 pushblock();
1367 id = d.ty.ids;
1368 # evaluate args in same order as normal calls
1369 for(as = e.right; as != nil; as = as.right){
1370 a = as.left;
1371 if(!(a.op == Oname && id == a.decl)){
1372 if(occurs(id, as.right)){
1373 f = talloc(id.ty, nil);
1374 f.flags |= byte TEMP;
1375 }
1376 else
1377 f = mkdeclname(as.src, id);
1378 n = mkbin(Oas, f, a);
1379 n.ty = id.ty;
1380 scom(n);
1381 if(int f.flags&TEMP)
1382 as.left = f;
1383 }
1384 id = id.next;
1385 }
1386 id = d.ty.ids;
1387 for(as = e.right; as != nil; as = as.right){
1388 a = as.left;
1389 if(int a.flags&TEMP){
1390 f = mkdeclname(as.src, id);
1391 n = mkbin(Oas, f, a);
1392 n.ty = id.ty;
1393 scom(n);
1394 tfree(a);
1395 }
1396 id = id.next;
1397 }
1398 p = genrawop(e.src, IJMP, nil, nil, nil);
1399 patch(p, d.pc);
1400 popblock();
1401 return 1;
1402}
limbo/compiler/decls.b+1177−0
@@ -0,0 +1,1177 @@
1
2storename := array[Dend] of
3{
4 Dtype => "type",
5 Dfn => "function",
6 Dglobal => "global",
7 Darg => "argument",
8 Dlocal => "local",
9 Dconst => "con",
10 Dfield => "field",
11 Dtag => "pick tag",
12 Dimport => "import",
13 Dunbound => "unbound",
14 Dundef => "undefined",
15 Dwundef => "undefined",
16};
17
18storeart := array[Dend] of
19{
20 Dtype => "a ",
21 Dfn => "a ",
22 Dglobal => "a ",
23 Darg => "an ",
24 Dlocal => "a ",
25 Dconst => "a ",
26 Dfield => "a ",
27 Dtag => "a ",
28 Dimport => "an ",
29 Dunbound => "",
30 Dundef => "",
31 Dwundef => "",
32};
33
34storespace := array[Dend] of
35{
36 Dtype => 0,
37 Dfn => 0,
38 Dglobal => 1,
39 Darg => 1,
40 Dlocal => 1,
41 Dconst => 0,
42 Dfield => 1,
43 Dtag => 0,
44 Dimport => 0,
45 Dunbound => 0,
46 Dundef => 0,
47 Dwundef => 0,
48};
49
50impdecl: ref Decl;
51impdecls: ref Dlist;
52scopes := array[MaxScope] of ref Decl;
53tails := array[MaxScope] of ref Decl;
54scopekind := array[MaxScope] of byte;
55scopenode := array[MaxScope] of ref Node;
56iota: ref Decl;
57zdecl: Decl;
58
59popscopes()
60{
61 d: ref Decl;
62
63 #
64 # clear out any decls left in syms
65 #
66 while(scope >= ScopeBuiltin){
67 for(d = scopes[scope--]; d != nil; d = d.next){
68 if(d.sym != nil){
69 d.sym.decl = d.old;
70 d.old = nil;
71 }
72 }
73 }
74
75 for(id := impdecls; id != nil; id = id.next){
76 for(d = id.d.ty.ids; d != nil; d = d.next){
77 d.sym.decl = nil;
78 d.old = nil;
79 }
80 }
81 impdecls = nil;
82
83 scope = ScopeBuiltin;
84 scopes[ScopeBuiltin] = nil;
85 tails[ScopeBuiltin] = nil;
86}
87
88declstart()
89{
90 iota = mkids(nosrc, enter("iota", 0), tint, nil);
91 iota.init = mkconst(nosrc, big 0);
92
93 scope = ScopeNils;
94 scopes[ScopeNils] = nil;
95 tails[ScopeNils] = nil;
96
97 nildecl = mkdecl(nosrc, Dglobal, tany);
98 nildecl.sym = enter("nil", 0);
99 installids(Dglobal, nildecl);
100 d := mkdecl(nosrc, Dglobal, tstring);
101 d.sym = enterstring("");
102 installids(Dglobal, d);
103
104 scope = ScopeGlobal;
105 scopes[ScopeGlobal] = nil;
106 tails[ScopeGlobal] = nil;
107}
108
109redecl(d: ref Decl)
110{
111 old := d.sym.decl;
112 if(old.store == Dwundef)
113 return;
114 error(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "+storeconv(old)+" on line "+
115 lineconv(old.src.start));
116}
117
118checkrefs(d: ref Decl)
119{
120 id, m: ref Decl;
121 refs: int;
122
123 for(; d != nil; d = d.next){
124 if(d.das != byte 0)
125 d.refs--;
126 case d.store{
127 Dtype =>
128 refs = d.refs;
129 if(d.ty.kind == Tadt){
130 for(id = d.ty.ids; id != nil; id = id.next){
131 d.refs += id.refs;
132 if(id.store != Dfn)
133 continue;
134 if(id.init == nil && id.link == nil && d.importid == nil)
135 error(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not defined");
136 if(superwarn && !id.refs && d.importid == nil)
137 warn(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not referenced");
138 }
139 }
140 if(d.ty.kind == Tmodule){
141 for(id = d.ty.ids; id != nil; id = id.next){
142 refs += id.refs;
143 if(id.iface != nil)
144 id.iface.refs += id.refs;
145 if(id.store == Dtype){
146 for(m = id.ty.ids; m != nil; m = m.next){
147 refs += m.refs;
148 if(m.iface != nil)
149 m.iface.refs += m.refs;
150 }
151 }
152 }
153 d.refs = refs;
154 }
155 if(superwarn && !refs && d.importid == nil)
156 warn(d.src.start, declconv(d)+" not referenced");
157 Dglobal =>
158 if(superwarn && !d.refs && d.sym != nil && d.sym.name[0] != '.')
159 warn(d.src.start, declconv(d)+" not referenced");
160 Dlocal or
161 Darg =>
162 if(!d.refs && d.sym != nil && d.sym.name != nil && d.sym.name[0] != '.')
163 warn(d.src.start, declconv(d)+" not referenced");
164 Dconst =>
165 if(superwarn && !d.refs && d.sym != nil)
166 warn(d.src.start, declconv(d)+" not referenced");
167 Dfn =>
168 if(d.init == nil && d.importid == nil)
169 error(d.src.start, declconv(d)+" not defined");
170 if(superwarn && !d.refs)
171 warn(d.src.start, declconv(d)+" not referenced");
172 Dimport =>
173 if(superwarn && !d.refs)
174 warn(d.src.start, declconv(d)+" not referenced");
175 }
176 if(d.das != byte 0)
177 d.refs++;
178 }
179}
180
181vardecl(ids: ref Decl, t: ref Type): ref Node
182{
183 n := mkn(Ovardecl, mkn(Oseq, nil, nil), nil);
184 n.decl = ids;
185 n.ty = t;
186 return n;
187}
188
189vardecled(n: ref Node)
190{
191 store := Dlocal;
192 if(scope == ScopeGlobal)
193 store = Dglobal;
194 if(n.ty.kind == Texception && n.ty.cons == byte 1){
195 store = Dconst;
196 fatal("Texception in vardecled");
197 }
198 ids := n.decl;
199 installids(store, ids);
200 t := n.ty;
201 for(last := ids; ids != nil; ids = ids.next){
202 ids.ty = t;
203 last = ids;
204 }
205 n.left.decl = last;
206}
207
208condecl(ids: ref Decl, init: ref Node): ref Node
209{
210 n := mkn(Ocondecl, mkn(Oseq, nil, nil), init);
211 n.decl = ids;
212 return n;
213}
214
215condecled(n: ref Node)
216{
217 ids := n.decl;
218 installids(Dconst, ids);
219 for(last := ids; ids != nil; ids = ids.next){
220 ids.ty = tunknown;
221 last = ids;
222 }
223 n.left.decl = last;
224}
225
226exdecl(ids: ref Decl, tids: ref Decl): ref Node
227{
228 n: ref Node;
229 t: ref Type;
230
231 t = mktype(ids.src.start, ids.src.stop, Texception, nil, tids);
232 t.cons = byte 1;
233 n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil);
234 n.decl = ids;
235 n.ty = t;
236 return n;
237}
238
239exdecled(n: ref Node)
240{
241 ids, last: ref Decl;
242 t: ref Type;
243
244 ids = n.decl;
245 installids(Dconst, ids);
246 t = n.ty;
247 for(last = ids; ids != nil; ids = ids.next){
248 ids.ty = t;
249 last = ids;
250 }
251 n.left.decl = last;
252}
253
254importdecl(m: ref Node, ids: ref Decl): ref Node
255{
256 n := mkn(Oimport, mkn(Oseq, nil, nil), m);
257 n.decl = ids;
258 return n;
259}
260
261importdecled(n: ref Node)
262{
263 ids := n.decl;
264 installids(Dimport, ids);
265 for(last := ids; ids != nil; ids = ids.next){
266 ids.ty = tunknown;
267 last = ids;
268 }
269 n.left.decl = last;
270}
271
272mkscope(body: ref Node): ref Node
273{
274 n := mkn(Oscope, nil, body);
275 if(body != nil)
276 n.src = body.src;
277 return n;
278}
279
280fndecl(n: ref Node, t: ref Type, body: ref Node): ref Node
281{
282 n = mkbin(Ofunc, n, body);
283 n.ty = t;
284 return n;
285}
286
287fndecled(n: ref Node)
288{
289 left := n.left;
290 if(left.op == Oname){
291 d := left.decl.sym.decl;
292 if(d == nil || d.store == Dimport){
293 d = mkids(left.src, left.decl.sym, n.ty, nil);
294 installids(Dfn, d);
295 }
296 left.decl = d;
297 d.refs++;
298 }
299 if(left.op == Odot)
300 pushscope(nil, Sother);
301 if(n.ty.polys != nil){
302 pushscope(nil, Sother);
303 installids(Dtype, n.ty.polys);
304 }
305 pushscope(nil, Sother);
306 installids(Darg, n.ty.ids);
307 n.ty.ids = popscope();
308 if(n.ty.val != nil)
309 mergepolydecs(n.ty);
310 if(n.ty.polys != nil)
311 n.ty.polys = popscope();
312 if(left.op == Odot)
313 popscope();
314}
315
316#
317# check the function declaration only
318# the body will be type checked later by fncheck
319#
320fnchk(n: ref Node): ref Decl
321{
322 bad := 0;
323 d := n.left.decl;
324 if(n.left.op == Odot)
325 d = n.left.right.decl;
326 if(d == nil)
327 fatal("decl() fnchk nil");
328 n.left.decl = d;
329 if(d.store == Dglobal || d.store == Dfield)
330 d.store = Dfn;
331 if(d.store != Dfn || d.init != nil){
332 nerror(n, "redeclaration of function "+dotconv(d)+", previously declared as "
333 +storeconv(d)+" on line "+lineconv(d.src.start));
334 if(d.store == Dfn && d.init != nil)
335 bad = 1;
336 }
337 d.init = n;
338
339 t := n.ty;
340 inadt := d.dot;
341 if(inadt != nil && (inadt.store != Dtype || inadt.ty.kind != Tadt))
342 inadt = nil;
343 if(n.left.op == Odot){
344 pushscope(nil, Sother);
345 adtp := outerpolys(n.left);
346 if(adtp != nil)
347 installids(Dtype, adtp);
348 if(!polyequal(adtp, n.decl))
349 nerror(n, "adt polymorphic type mismatch");
350 n.decl = nil;
351 }
352 t = validtype(t, inadt);
353 if(n.left.op == Odot)
354 popscope();
355 if(debug['d'])
356 print("declare function %s ty %s newty %s\n", dotconv(d), typeconv(d.ty), typeconv(t));
357 t = usetype(t);
358
359 if(!polyequal(d.ty.polys, t.polys))
360 nerror(n, "function polymorphic type mismatch");
361 if(!tcompat(d.ty, t, 0))
362 nerror(n, "type mismatch: "+dotconv(d)+" defined as "
363 +typeconv(t)+" declared as "+typeconv(d.ty)+" on line "+lineconv(d.src.start));
364 else if(!raisescompat(d.ty.eraises, t.eraises))
365 nerror(n, "raises mismatch: " + dotconv(d));
366 if(t.varargs != byte 0)
367 nerror(n, "cannot define functions with a '*' argument, such as "+dotconv(d));
368
369 t.eraises = d.ty.eraises;
370
371 d.ty = t;
372 d.offset = idoffsets(t.ids, MaxTemp, IBY2WD);
373 d.src = n.src;
374
375 d.locals = nil;
376
377 n.ty = t;
378
379 if(bad)
380 return nil;
381 return d;
382}
383
384globalas(dst: ref Node, v: ref Node, valok: int): ref Node
385{
386 if(v == nil)
387 return nil;
388 if(v.op == Oas || v.op == Odas){
389 v = globalas(v.left, v.right, valok);
390 if(v == nil)
391 return nil;
392 }else if(valok && !initable(dst, v, 0))
393 return nil;
394 case dst.op{
395 Oname =>
396 if(dst.decl.init != nil)
397 nerror(dst, "duplicate assignment to "+expconv(dst)+", previously assigned on line "
398 +lineconv(dst.decl.init.src.start));
399 if(valok)
400 dst.decl.init = v;
401 return v;
402 Otuple =>
403 if(valok && v.op != Otuple)
404 fatal("can't deal with "+nodeconv(v)+" in tuple case of globalas");
405 tv := v.left;
406 for(dst = dst.left; dst != nil; dst = dst.right){
407 globalas(dst.left, tv.left, valok);
408 if(valok)
409 tv = tv.right;
410 }
411 return v;
412 }
413 fatal("can't deal with "+nodeconv(dst)+" in globalas");
414 return nil;
415}
416
417needsstore(d: ref Decl): int
418{
419 if(!d.refs)
420 return 0;
421 if(d.importid != nil)
422 return 0;
423 if(storespace[d.store])
424 return 1;
425 return 0;
426}
427
428#
429# return the list of all referenced storage variables
430#
431vars(d: ref Decl): ref Decl
432{
433 while(d != nil && !needsstore(d))
434 d = d.next;
435 for(v := d; v != nil; v = v.next){
436 while(v.next != nil){
437 n := v.next;
438 if(needsstore(n))
439 break;
440 v.next = n.next;
441 }
442 }
443 return d;
444}
445
446#
447# declare variables from the left side of a := statement
448#
449recdasdecl(n: ref Node, store: int, nid: int): (int, int)
450{
451 r: int;
452
453 case n.op{
454 Otuple =>
455 ok := 1;
456 for(n = n.left; n != nil; n = n.right){
457 (r, nid) = recdasdecl(n.left, store, nid);
458 ok &= r;
459 }
460 return (ok, nid);
461 Oname =>
462 if(n.decl == nildecl)
463 return (1, -1);
464 d := mkids(n.src, n.decl.sym, nil, nil);
465 installids(store, d);
466 n.decl = d;
467 old := d.old;
468 if(old != nil
469 && old.store != Dfn
470 && old.store != Dwundef
471 && old.store != Dundef)
472 warn(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "
473 +storeconv(old)+" on line "+lineconv(old.src.start));
474 d.refs++;
475 d.das = byte 1;
476 if(nid >= 0)
477 nid++;
478 return (1, nid);
479 }
480 return (0, nid);
481}
482
483recmark(n: ref Node, nid: int): int
484{
485 case(n.op){
486 Otuple =>
487 for(n = n.left; n != nil; n = n.right)
488 nid = recmark(n.left, nid);
489 Oname =>
490 n.decl.nid = byte nid;
491 nid = 0;
492 }
493 return nid;
494}
495
496dasdecl(n: ref Node): int
497{
498 ok: int;
499
500 nid := 0;
501 store := Dlocal;
502 if(scope == ScopeGlobal)
503 store = Dglobal;
504
505 (ok, nid) = recdasdecl(n, store, nid);
506 if(!ok)
507 nerror(n, "illegal declaration expression "+expconv(n));
508 if(ok && store == Dlocal && nid > 1)
509 recmark(n, nid);
510 return ok;
511}
512
513#
514# declare global variables in nested := expressions
515#
516gdasdecl(n: ref Node)
517{
518 if(n == nil)
519 return;
520
521 if(n.op == Odas){
522 gdasdecl(n.right);
523 dasdecl(n.left);
524 }else{
525 gdasdecl(n.left);
526 gdasdecl(n.right);
527 }
528}
529
530undefed(src: Src, s: ref Sym): ref Decl
531{
532 d := mkids(src, s, tnone, nil);
533 error(src.start, s.name+" is not declared");
534 installids(Dwundef, d);
535 return d;
536}
537
538# inloop() : int
539# {
540# for (i := scope; i > 0; i--)
541# if (int scopekind[i] == Sloop)
542# return 1;
543# return 0;
544# }
545
546nested() : int
547{
548 for (i := scope; i > 0; i--)
549 if (int scopekind[i] == Sscope || int scopekind[i] == Sloop)
550 return 1;
551 return 0;
552}
553
554decltozero(n : ref Node)
555{
556 if ((scop := scopenode[scope]) != nil) {
557 if (n.right != nil && errors == 0)
558 fatal("Ovardecl/Oname/Otuple has right field\n");
559 n.right = scop.left;
560 scop.left = n;
561 }
562}
563
564pushscope(scp : ref Node, kind : int)
565{
566 if(scope >= MaxScope)
567 fatal("scope too deep");
568 scope++;
569 scopes[scope] = nil;
570 tails[scope] = nil;
571 scopenode[scope] = scp;
572 scopekind[scope] = byte kind;
573}
574
575curscope(): ref Decl
576{
577 return scopes[scope];
578}
579
580#
581# revert to old declarations for each symbol in the currect scope.
582# remove the effects of any imported adt types
583# whenever the adt is imported from a module,
584# we record in the type's decl the module to use
585# when calling members. the process is reversed here.
586#
587popscope(): ref Decl
588{
589 for(id := scopes[scope]; id != nil; id = id.next){
590 if(id.sym != nil){
591 id.sym.decl = id.old;
592 id.old = nil;
593 }
594 if(id.importid != nil)
595 id.importid.refs += id.refs;
596 t := id.ty;
597 if(id.store == Dtype
598 && t.decl != nil
599 && t.decl.timport == id)
600 t.decl.timport = id.timport;
601 if(id.store == Dlocal)
602 freeloc(id);
603 }
604 return scopes[scope--];
605}
606
607#
608# make a new scope,
609# preinstalled with some previously installed identifiers
610# don't add the identifiers to the scope chain,
611# so they remain separate from any newly installed ids
612#
613# these routines assume no ids are imports
614#
615repushids(ids: ref Decl)
616{
617 if(scope >= MaxScope)
618 fatal("scope too deep");
619 scope++;
620 scopes[scope] = nil;
621 tails[scope] = nil;
622 scopenode[scope] = nil;
623 scopekind[scope] = byte Sother;
624
625 for(; ids != nil; ids = ids.next){
626 if(ids.scope != scope
627 && (ids.dot == nil || !isimpmod(ids.dot.sym)
628 || ids.scope != ScopeGlobal || scope != ScopeGlobal + 1))
629 fatal("repushids scope mismatch");
630 s := ids.sym;
631 if(s != nil && ids.store != Dtag){
632 if(s.decl != nil && s.decl.scope >= scope)
633 ids.old = s.decl.old;
634 else
635 ids.old = s.decl;
636 s.decl = ids;
637 }
638 }
639}
640
641#
642# pop a scope which was started with repushids
643# return any newly installed ids
644#
645popids(ids: ref Decl): ref Decl
646{
647 for(; ids != nil; ids = ids.next){
648 if(ids.sym != nil && ids.store != Dtag){
649 ids.sym.decl = ids.old;
650 ids.old = nil;
651 }
652 }
653 return popscope();
654}
655
656installids(store: int, ids: ref Decl)
657{
658 last : ref Decl = nil;
659 for(d := ids; d != nil; d = d.next){
660 d.scope = scope;
661 if(d.store == Dundef)
662 d.store = store;
663 s := d.sym;
664 if(s != nil){
665 if(s.decl != nil && s.decl.scope >= scope){
666 redecl(d);
667 d.old = s.decl.old;
668 }else
669 d.old = s.decl;
670 s.decl = d;
671 }
672 last = d;
673 }
674 if(ids != nil){
675 d = tails[scope];
676 if(d == nil)
677 scopes[scope] = ids;
678 else
679 d.next = ids;
680 tails[scope] = last;
681 }
682}
683
684lookup(sym: ref Sym): ref Decl
685{
686 s: int;
687 d: ref Decl;
688
689 for(s = scope; s >= ScopeBuiltin; s--){
690 for(d = scopes[s]; d != nil; d = d.next){
691 if(d.sym == sym)
692 return d;
693 }
694 }
695 return nil;
696}
697
698mkids(src: Src, s: ref Sym, t: ref Type, next: ref Decl): ref Decl
699{
700 d := ref zdecl;
701 d.src = src;
702 d.store = Dundef;
703 d.ty = t;
704 d.next = next;
705 d.sym = s;
706 d.nid = byte 1;
707 return d;
708}
709
710mkdecl(src: Src, store: int, t: ref Type): ref Decl
711{
712 d := ref zdecl;
713 d.src = src;
714 d.store = store;
715 d.ty = t;
716 d.nid = byte 1;
717 return d;
718}
719
720dupdecl(old: ref Decl): ref Decl
721{
722 d := ref *old;
723 d.next = nil;
724 return d;
725}
726
727dupdecls(old: ref Decl): ref Decl
728{
729 d, nd, first, last: ref Decl;
730
731 first = last = nil;
732 for(d = old; d != nil; d = d.next){
733 nd = dupdecl(d);
734 if(first == nil)
735 first = nd;
736 else
737 last.next = nd;
738 last = nd;
739 }
740 return first;
741}
742
743appdecls(d: ref Decl, dd: ref Decl): ref Decl
744{
745 if(d == nil)
746 return dd;
747 for(t := d; t.next != nil; t = t.next)
748 ;
749 t.next = dd;
750 return d;
751}
752
753revids(id: ref Decl): ref Decl
754{
755 next : ref Decl;
756 d : ref Decl = nil;
757 for(; id != nil; id = next){
758 next = id.next;
759 id.next = d;
760 d = id;
761 }
762 return d;
763}
764
765idoffsets(id: ref Decl, offset: int, al: int): int
766{
767 algn := 1;
768 for(; id != nil; id = id.next){
769 if(storespace[id.store]){
770usedty(id.ty);
771 if(id.store == Dlocal && id.link != nil){
772 # id.nid always 1
773 id.offset = id.link.offset;
774 continue;
775 }
776 a := id.ty.align;
777 if(id.nid > byte 1){
778 for(d := id.next; d != nil && d.nid == byte 0; d = d.next)
779 if(d.ty.align > a)
780 a = d.ty.align;
781 algn = a;
782 }
783 offset = align(offset, a);
784 id.offset = offset;
785 offset += id.ty.size;
786 if(id.nid == byte 0 && (id.next == nil || id.next.nid != byte 0))
787 offset = align(offset, algn);
788 }
789 }
790 return align(offset, al);
791}
792
793idindices(id: ref Decl): int
794{
795 i := 0;
796 for(; id != nil; id = id.next){
797 if(storespace[id.store]){
798 usedty(id.ty);
799 id.offset = i++;
800 }
801 }
802 return i;
803}
804
805declconv(d: ref Decl): string
806{
807 if(d.sym == nil)
808 return storename[d.store] + " " + "<???>";
809 return storename[d.store] + " " + d.sym.name;
810}
811
812storeconv(d: ref Decl): string
813{
814 return storeart[d.store] + storename[d.store];
815}
816
817dotconv(d: ref Decl): string
818{
819 s: string;
820
821 if(d.dot != nil && !isimpmod(d.dot.sym)){
822 s = dotconv(d.dot);
823 if(d.dot.ty != nil && d.dot.ty.kind == Tmodule)
824 s += ".";
825 else
826 s += ".";
827 }
828 s += d.sym.name;
829 return s;
830}
831
832#
833# merge together two sorted lists, yielding a sorted list
834#
835namemerge(e, f: ref Decl): ref Decl
836{
837 d := rock := ref Decl;
838 while(e != nil && f != nil){
839 if(e.sym.name <= f.sym.name){
840 d.next = e;
841 e = e.next;
842 }else{
843 d.next = f;
844 f = f.next;
845 }
846 d = d.next;
847 }
848 if(e != nil)
849 d.next = e;
850 else
851 d.next = f;
852 return rock.next;
853}
854
855#
856# recursively split lists and remerge them after they are sorted
857#
858recnamesort(d: ref Decl, n: int): ref Decl
859{
860 if(n <= 1)
861 return d;
862 m := n / 2 - 1;
863 dd := d;
864 for(i := 0; i < m; i++)
865 dd = dd.next;
866 r := dd.next;
867 dd.next = nil;
868 return namemerge(recnamesort(d, n / 2),
869 recnamesort(r, (n + 1) / 2));
870}
871
872#
873# sort the ids by name
874#
875namesort(d: ref Decl): ref Decl
876{
877 n := 0;
878 for(dd := d; dd != nil; dd = dd.next)
879 n++;
880 return recnamesort(d, n);
881}
882
883printdecls(d: ref Decl)
884{
885 for(; d != nil; d = d.next)
886 print("%d: %s %s ref %d\n", d.offset, declconv(d), typeconv(d.ty), d.refs);
887}
888
889mergepolydecs(t: ref Type)
890{
891 n, nn: ref Node;
892 id, ids, ids1: ref Decl;
893
894 for(n = t.val; n != nil; n = n.right){
895 nn = n.left;
896 for(ids = nn.decl; ids != nil; ids = ids.next){
897 id = ids.sym.decl;
898 if(id == nil){
899 undefed(ids.src, ids.sym);
900 break;
901 }
902 if(id.store != Dtype){
903 error(ids.src.start, declconv(id) + " is not a type");
904 break;
905 }
906 if(id.ty.kind != Tpoly){
907 error(ids.src.start, declconv(id) + " is not a polymorphic type");
908 break;
909 }
910 if(id.ty.ids != nil)
911 error(ids.src.start, declconv(id) + " redefined");
912 pushscope(nil, Sother);
913 fielddecled(nn.left);
914 id.ty.ids = popscope();
915 for(ids1 = id.ty.ids; ids1 != nil; ids1 = ids1.next){
916 ids1.dot = id;
917 bindtypes(ids1.ty);
918 if(ids1.ty.kind != Tfn){
919 error(ids1.src.start, "only function types expected");
920 id.ty.ids = nil;
921 }
922 }
923 }
924 }
925 t.val = nil;
926}
927
928adjfnptrs(d: ref Decl, polys1: ref Decl, polys2: ref Decl)
929{
930 n: int;
931 id, idt, idf, arg: ref Decl;
932
933 n = 0;
934 for(id = d.ty.ids; id != nil; id = id.next)
935 n++;
936 for(idt = polys1; idt != nil; idt = idt.next)
937 for(idf = idt.ty.ids; idf != nil; idf = idf.next)
938 n -= 2;
939 for(idt = polys2; idt != nil; idt = idt.next)
940 for(idf = idt.ty.ids; idf != nil; idf = idf.next)
941 n -= 2;
942 for(arg = d.ty.ids; --n >= 0; arg = arg.next)
943 ;
944 for(idt = polys1; idt != nil; idt = idt.next){
945 for(idf = idt.ty.ids; idf != nil; idf = idf.next){
946 idf.link = arg;
947 arg = arg.next.next;
948 }
949 }
950 for(idt = polys2; idt != nil; idt = idt.next){
951 for(idf = idt.ty.ids; idf != nil; idf = idf.next){
952 idf.link = arg;
953 arg = arg.next.next;
954 }
955 }
956}
957
958addptrs(polys: ref Decl, fps: ref Decl, last: ref Decl, link: int, src: Src): (ref Decl, ref Decl)
959{
960 for(idt := polys; idt != nil; idt = idt.next){
961 for(idf := idt.ty.ids; idf != nil; idf = idf.next){
962 fp := mkdecl(src, Darg, tany);
963 fp.sym = idf.sym;
964 if(link)
965 idf.link = fp;
966 if(fps == nil)
967 fps = fp;
968 else
969 last.next = fp;
970 last = fp;
971 fp = mkdecl(src, Darg, tint);
972 fp.sym = idf.sym;
973 last.next = fp;
974 last = fp;
975 }
976 }
977 return (fps, last);
978}
979
980addfnptrs(d: ref Decl, link: int)
981{
982 fps, last, polys: ref Decl;
983
984 polys = encpolys(d);
985 if(int(d.ty.flags&FULLARGS)){
986 if(link)
987 adjfnptrs(d, d.ty.polys, polys);
988 return;
989 }
990 d.ty.flags |= FULLARGS;
991 fps = last = nil;
992 (fps, last) = addptrs(d.ty.polys, fps, last, link, d.src);
993 (fps, last) = addptrs(polys, fps, last, link, d.src);
994 for(last = d.ty.ids; last != nil && last.next != nil; last = last.next)
995 ;
996 if(last != nil)
997 last.next = fps;
998 else
999 d.ty.ids = fps;
1000 d.offset = idoffsets(d.ty.ids, MaxTemp, IBY2WD);
1001}
1002
1003rmfnptrs(d: ref Decl)
1004{
1005 n: int;
1006 id, idt, idf: ref Decl;
1007
1008 if(int(d.ty.flags&FULLARGS))
1009 d.ty.flags &= ~FULLARGS;
1010 else
1011 return;
1012 n = 0;
1013 for(id = d.ty.ids; id != nil; id = id.next)
1014 n++;
1015 for(idt = d.ty.polys; idt != nil; idt = idt.next)
1016 for(idf = idt.ty.ids; idf != nil; idf = idf.next)
1017 n -= 2;
1018 for(idt = encpolys(d); idt != nil; idt = idt.next)
1019 for(idf = idt.ty.ids; idf != nil; idf = idf.next)
1020 n -= 2;
1021 if(n == 0){
1022 d.ty.ids = nil;
1023 return;
1024 }
1025 for(id = d.ty.ids; --n > 0; id = id.next)
1026 ;
1027 id.next = nil;
1028 d.offset = idoffsets(d.ty.ids, MaxTemp, IBY2WD);
1029}
1030
1031local(d: ref Decl): int
1032{
1033 for(d = d.dot; d != nil; d = d.dot)
1034 if(d.store == Dtype && d.ty.kind == Tmodule)
1035 return 0;
1036 return 1;
1037}
1038
1039lmodule(d: ref Decl): ref Decl
1040{
1041 for(d = d.dot; d != nil; d = d.dot)
1042 if(d.store == Dtype && d.ty.kind == Tmodule)
1043 return d;
1044 return nil;
1045}
1046
1047outerpolys(n: ref Node): ref Decl
1048{
1049 d: ref Decl;
1050
1051 if(n.op == Odot){
1052 d = n.right.decl;
1053 if(d == nil)
1054 fatal("decl() outeradt nil");
1055 d = d.dot;
1056 if(d != nil && d.store == Dtype && d.ty.kind == Tadt)
1057 return d.ty.polys;
1058 }
1059 return nil;
1060}
1061
1062encpolys(d: ref Decl): ref Decl
1063{
1064 if((d = d.dot) == nil)
1065 return nil;
1066 return d.ty.polys;
1067}
1068
1069fnlookup(s: ref Sym, t: ref Type): (ref Decl, ref Node)
1070{
1071 id: ref Decl;
1072 mod: ref Node;
1073
1074 id = nil;
1075 mod = nil;
1076 if(t.kind == Tpoly || t.kind == Tmodule)
1077 id = namedot(t.ids, s);
1078 else if(t.kind == Tref){
1079 t = t.tof;
1080 if(t.kind == Tadt){
1081 id = namedot(t.ids, s);
1082 if(t.decl != nil && t.decl.timport != nil)
1083 mod = t.decl.timport.eimport;
1084 }
1085 else if(t.kind == Tadtpick){
1086 id = namedot(t.ids, s);
1087 if(t.decl != nil && t.decl.timport != nil)
1088 mod = t.decl.timport.eimport;
1089 t = t.decl.dot.ty;
1090 if(id == nil)
1091 id = namedot(t.ids, s);
1092 if(t.decl != nil && t.decl.timport != nil)
1093 mod = t.decl.timport.eimport;
1094 }
1095 }
1096 if(id == nil){
1097 id = lookup(s);
1098 if(id != nil)
1099 mod = id.eimport;
1100 }
1101 return (id, mod);
1102}
1103
1104isimpmod(s: ref Sym): int
1105{
1106 d: ref Decl;
1107
1108 for(d = impmods; d != nil; d = d.next)
1109 if(d.sym == s)
1110 return 1;
1111 return 0;
1112}
1113
1114dequal(d1: ref Decl, d2: ref Decl, full: int): int
1115{
1116 return d1.sym == d2.sym &&
1117 d1.store == d2.store &&
1118 d1.implicit == d2.implicit &&
1119 d1.cyc == d2.cyc &&
1120 (!full || tequal(d1.ty, d2.ty)) &&
1121 (!full || d1.store == Dfn || sametree(d1.init, d2.init));
1122}
1123
1124tzero(t: ref Type): int
1125{
1126 return t.kind == Texception || tmustzero(t);
1127}
1128
1129isptr(t: ref Type): int
1130{
1131 return t.kind == Texception || tattr[t.kind].isptr;
1132}
1133
1134# can d share the same stack location as another local ?
1135shareloc(d: ref Decl)
1136{
1137 z: int;
1138 t, tt: ref Type;
1139 dd, res: ref Decl;
1140
1141 if(d.store != Dlocal || d.nid != byte 1)
1142 return;
1143 t = d.ty;
1144 res = nil;
1145 for(dd = fndecls; dd != nil; dd = dd.next){
1146 if(d == dd)
1147 fatal("d==dd in shareloc");
1148 if(dd.store != Dlocal || dd.nid != byte 1 || dd.link != nil || dd.tref != 0)
1149 continue;
1150 tt = dd.ty;
1151 if(t.size != tt.size || t.align != tt.align)
1152 continue;
1153 z = tzero(t)+tzero(tt);
1154 if(z > 0)
1155 continue; # for now
1156 if(t == tt || tequal(t, tt))
1157 res = dd;
1158 else{
1159 if(z == 1)
1160 continue;
1161 if(z == 0 || isptr(t) || isptr(tt) || mktdesc(t) == mktdesc(tt))
1162 res = dd;
1163 }
1164 if(res != nil){
1165 d.link = res;
1166 res.tref = 1;
1167 return;
1168 }
1169 }
1170 return;
1171}
1172
1173freeloc(d: ref Decl)
1174{
1175 if(d.link != nil)
1176 d.link.tref = 0;
1177}
limbo/compiler/dis.b+560−0
@@ -0,0 +1,560 @@
1
2NAMELEN: con 28;
3
4cache: array of byte;
5ncached: int;
6ndatum: int;
7startoff: int;
8lastoff: int;
9lastkind: int;
10
11discon(val: int)
12{
13 if(val >= -64 && val <= 63){
14 bout.putb(byte (val & ~16r80));
15 return;
16 }
17 if(val >= -8192 && val <= 8191){
18 bout.putb(byte ((val>>8) & ~16rC0 | 16r80));
19 bout.putb(byte val);
20 return;
21 }
22 if(val < 0 && ((val >> 29) & 7) != 7
23 || val > 0 && (val >> 29) != 0)
24 fatal("overflow in constant 16r"+hex(val, 0));
25 bout.putb(byte(val>>24 | 16rC0));
26 bout.putb(byte(val>>16));
27 bout.putb(byte(val>>8));
28 bout.putb(byte val);
29}
30
31disword(w: int)
32{
33 bout.putb(byte(w >> 24));
34 bout.putb(byte(w >> 16));
35 bout.putb(byte(w >> 8));
36 bout.putb(byte w);
37}
38
39disdata(kind, n: int)
40{
41 if(n < DMAX && n != 0)
42 bout.putb(byte((kind << DBYTE) | n));
43 else{
44 bout.putb(byte kind << DBYTE);
45 discon(n);
46 }
47}
48
49dismod(m: ref Decl)
50{
51 fileoff := bout.seek(big 0, 1);
52 name := array of byte m.sym.name;
53 n := len name;
54 if(n > NAMELEN-1)
55 n = NAMELEN-1;
56 bout.write(name, n);
57 bout.putb(byte 0);
58 for(m = m.ty.tof.ids; m != nil; m = m.next){
59 case m.store{
60 Dglobal =>
61 discon(-1);
62 discon(-1);
63 disword(sign(m));
64 bout.puts(".mp");
65 bout.putb(byte 0);
66 Dfn =>
67 discon(m.pc.pc);
68 discon(m.desc.id);
69 disword(sign(m));
70 if(m.dot.ty.kind == Tadt){
71 bout.puts(m.dot.sym.name);
72 bout.putb(byte '.');
73 }
74 bout.puts(m.sym.name);
75 bout.putb(byte 0);
76 * =>
77 fatal("unknown kind in dismod: "+declconv(m));
78 }
79 }
80 if(debug['s'])
81 print("%bd linkage bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
82}
83
84dispath()
85{
86 sp := array of byte srcpath();
87 bout.write(sp, len sp);
88 bout.putb(byte 0);
89}
90
91disentry(e: ref Decl)
92{
93 if(e == nil){
94 discon(-1);
95 discon(-1);
96 return;
97 }
98 discon(e.pc.pc);
99 discon(e.desc.id);
100}
101
102disdesc(d: ref Desc)
103{
104 fileoff := bout.seek(big 0, 1);
105 for(; d != nil; d = d.next){
106 discon(d.id);
107 discon(d.size);
108 discon(d.nmap);
109 bout.write(d.map, d.nmap);
110 }
111 if(debug['s'])
112 print("%bd type descriptor bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
113}
114
115disvar(nil: int, ids: ref Decl)
116{
117 fileoff := bout.seek(big 0, 1);
118 lastkind = -1;
119 ncached = 0;
120 ndatum = 0;
121
122 for(d := ids; d != nil; d = d.next)
123 if(d.store == Dglobal && d.init != nil)
124 disdatum(d.offset, d.init);
125
126 disflush(-1, -1, 0);
127
128 bout.putb(byte 0);
129
130 if(debug['s'])
131 print("%bd data bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
132}
133
134disldt(size: int, ds: ref Decl)
135{
136 if(0){
137 discon(size);
138 disvar(size, ds);
139 return;
140 }
141
142 m := 0;
143 for(d := ds; d != nil; d = d.next)
144 if(d.store == Dglobal && d.init != nil)
145 m++;
146 discon(m);
147 n: ref Node;
148 for(d = ds; d != nil; d = d.next){
149 if(d.store == Dglobal && d.init != nil){
150 n = d.init;
151 if(n.ty.kind != Tiface)
152 nerror(n, "disldt: not Tiface");
153 discon(int n.c.val);
154 for(id := n.decl.ty.ids; id != nil; id = id.next){
155 disword(sign(id));
156 if(id.dot.ty.kind == Tadt){
157 s := array of byte id.dot.sym.name;
158 bout.write(s, len s);
159 bout.putb(byte '.');
160 }
161 s := array of byte id.sym.name;
162 bout.write(s, len s);
163 bout.putb(byte 0);
164 }
165 }
166 }
167 discon(0);
168}
169
170disdatum(offset: int, n: ref Node)
171{
172 c: ref Case;
173 lab: Label;
174 id: ref Decl;
175 wild: ref Node;
176 i, e: int;
177
178 case n.ty.kind{
179 Tbyte =>
180 disbyte(offset, byte n.c.val);
181 Tint or
182 Tfix =>
183 disint(offset, int n.c.val);
184 Tbig =>
185 disbig(offset, n.c.val);
186 Tstring =>
187 disstring(offset, n.decl.sym);
188 Treal =>
189 disreal(offset, n.c.rval);
190 Tadt or
191 Tadtpick or
192 Ttuple =>
193 id = n.ty.ids;
194 for(n = n.left; n != nil; n = n.right){
195 disdatum(offset + id.offset, n.left);
196 id = id.next;
197 }
198 Tany =>
199 break;
200 Tcase =>
201 c = n.ty.cse;
202 disint(offset, c.nlab);
203 offset += IBY2WD;
204 for(i = 0; i < c.nlab; i++){
205 lab = c.labs[i];
206 disint(offset, int lab.start.c.val);
207 offset += IBY2WD;
208 disint(offset, int lab.stop.c.val+1);
209 offset += IBY2WD;
210 disint(offset, lab.inst.pc);
211 offset += IBY2WD;
212 }
213 if(c.iwild != nil)
214 disint(offset, c.iwild.pc);
215 else
216 disint(offset, -1);
217 Tcasel =>
218 c = n.ty.cse;
219 disint(offset, c.nlab);
220 offset += 2*IBY2WD;
221 for(i = 0; i < c.nlab; i++){
222 lab = c.labs[i];
223 disbig(offset, lab.start.c.val);
224 offset += IBY2LG;
225 disbig(offset, lab.stop.c.val+big 1);
226 offset += IBY2LG;
227 disint(offset, lab.inst.pc);
228 offset += 2*IBY2WD;
229 }
230 if(c.iwild != nil)
231 disint(offset, c.iwild.pc);
232 else
233 disint(offset, -1);
234 Tcasec =>
235 c = n.ty.cse;
236 disint(offset, c.nlab);
237 offset += IBY2WD;
238 for(i = 0; i < c.nlab; i++){
239 lab = c.labs[i];
240 disstring(offset, lab.start.decl.sym);
241 offset += IBY2WD;
242 if(lab.stop != lab.start)
243 disstring(offset, lab.stop.decl.sym);
244 offset += IBY2WD;
245 disint(offset, lab.inst.pc);
246 offset += IBY2WD;
247 }
248 if(c.iwild != nil)
249 disint(offset, c.iwild.pc);
250 else
251 disint(offset, -1);
252 Tgoto =>
253 c = n.ty.cse;
254 disint(offset, n.ty.size/IBY2WD-1);
255 offset += IBY2WD;
256 for(i = 0; i < c.nlab; i++){
257 disint(offset, c.labs[i].inst.pc);
258 offset += IBY2WD;
259 }
260 if(c.iwild != nil)
261 disint(offset, c.iwild.pc);
262 Tarray =>
263 disflush(-1, -1, 0);
264 disdata(DEFA, 1); # 1 is ignored
265 discon(offset);
266 disword(n.ty.tof.decl.desc.id);
267 disword(int n.left.c.val);
268
269 if(n.right == nil)
270 break;
271
272 disdata(DIND, 1); # 1 is ignored
273 discon(offset);
274 disword(0);
275
276 c = n.right.ty.cse;
277 wild = nil;
278 if(c.wild != nil)
279 wild = c.wild.right;
280 last := 0;
281 esz := n.ty.tof.size;
282 for(i = 0; i < c.nlab; i++){
283 e = int c.labs[i].start.c.val;
284 if(wild != nil){
285 for(; last < e; last++)
286 disdatum(esz * last, wild);
287 }
288 last = e;
289 e = int c.labs[i].stop.c.val;
290 elem := c.labs[i].node.right;
291 for(; last <= e; last++)
292 disdatum(esz * last, elem);
293 }
294 if(wild != nil)
295 for(e = int n.left.c.val; last < e; last++)
296 disdatum(esz * last, wild);
297
298 disflush(-1, -1, 0);
299 disdata(DAPOP, 1); # 1 is ignored
300 discon(0);
301 Tiface =>
302 disint(offset, int n.c.val);
303 offset += IBY2WD;
304 for(id = n.decl.ty.ids; id != nil; id = id.next){
305 offset = align(offset, IBY2WD);
306 disint(offset, sign(id));
307 offset += IBY2WD;
308
309 name: array of byte;
310 if(id.dot.ty.kind == Tadt){
311 name = array of byte id.dot.sym.name;
312 disbytes(offset, name);
313 offset += len name;
314 disbyte(offset, byte '.');
315 offset++;
316 }
317 name = array of byte id.sym.name;
318 disbytes(offset, name);
319 offset += len name;
320 disbyte(offset, byte 0);
321 offset++;
322 }
323 * =>
324 fatal("can't gen global "+nodeconv(n));
325 }
326}
327
328disexc(es: ref Except)
329{
330 e: ref Except;
331
332 n := 0;
333 for(e = es; e != nil; e = e.next)
334 if(int e.p1.reach || int e.p2.reach)
335 n++;
336 discon(n);
337 for(e = es; e != nil; e = e.next){
338 if(!int e.p1.reach && !int e.p2.reach)
339 continue;
340 c := e.c;
341 discon(e.d.offset);
342 discon(getpc(e.p1));
343 discon(getpc(e.p2));
344 if(e.desc != nil)
345 discon(e.desc.id);
346 else
347 discon(-1);
348 discon(c.nlab|(e.ne<<16));
349 for(i := 0; i < c.nlab; i++){
350 lab := c.labs[i];
351 d := lab.start.decl;
352 if(lab.start.ty.kind == Texception)
353 d = d.init.decl;
354 bout.puts(d.sym.name);
355 bout.putb(byte 0);
356 discon(lab.inst.pc);
357 }
358 if(c.iwild == nil)
359 discon(-1);
360 else
361 discon(c.iwild.pc);
362 }
363 discon(0);
364}
365
366disbyte(off: int, v: byte)
367{
368 disflush(DEFB, off, 1);
369 cache[ncached++] = v;
370 ndatum++;
371}
372
373disbytes(off: int, v: array of byte)
374{
375 n := len v;
376 disflush(DEFB, off, n);
377 cache[ncached:] = v;
378 ncached += n;
379 ndatum += n;
380}
381
382disint(off, v: int)
383{
384 disflush(DEFW, off, IBY2WD);
385 cache[ncached++] = byte(v >> 24);
386 cache[ncached++] = byte(v >> 16);
387 cache[ncached++] = byte(v >> 8);
388 cache[ncached++] = byte(v);
389 ndatum++;
390}
391
392disbig(off: int, v: big)
393{
394 disflush(DEFL, off, IBY2LG);
395 iv := int(v >> 32);
396 cache[ncached++] = byte(iv >> 24);
397 cache[ncached++] = byte(iv >> 16);
398 cache[ncached++] = byte(iv >> 8);
399 cache[ncached++] = byte(iv);
400 iv = int v;
401 cache[ncached++] = byte(iv >> 24);
402 cache[ncached++] = byte(iv >> 16);
403 cache[ncached++] = byte(iv >> 8);
404 cache[ncached++] = byte(iv);
405 ndatum++;
406}
407
408disreal(off: int, v: real)
409{
410 disflush(DEFF, off, IBY2LG);
411 export_real(cache[ncached:ncached+8], array[] of {v});
412 ncached += IBY2LG;
413 ndatum++;
414}
415
416disstring(offset: int, sym: ref Sym)
417{
418 disflush(-1, -1, 0);
419 d := array of byte sym.name;
420 disdata(DEFS, len d);
421 discon(offset);
422 bout.write(d, len d);
423}
424
425disflush(kind, off, size: int)
426{
427 if(kind != lastkind || off != lastoff){
428 if(lastkind != -1 && ncached){
429 disdata(lastkind, ndatum);
430 discon(startoff);
431 bout.write(cache, ncached);
432 }
433 startoff = off;
434 lastkind = kind;
435 ncached = 0;
436 ndatum = 0;
437 }
438 lastoff = off + size;
439 while(kind >= 0 && ncached + size >= len cache){
440 c := array[ncached + 1024] of byte;
441 c[0:] = cache;
442 cache = c;
443 }
444}
445
446dismode := array[int Aend] of
447{
448 int Aimm => byte AIMM,
449 int Amp => byte AMP,
450 int Ampind => byte(AMP|AIND),
451 int Afp => byte AFP,
452 int Afpind => byte(AFP|AIND),
453 int Apc => byte AIMM,
454 int Adesc => byte AIMM,
455 int Aoff => byte AIMM,
456 int Anoff => byte AIMM,
457 int Aerr => byte AXXX,
458 int Anone => byte AXXX,
459 int Aldt => byte AIMM,
460};
461
462disregmode := array[int Aend] of
463{
464 int Aimm => byte AXIMM,
465 int Amp => byte AXINM,
466 int Ampind => byte AXNON,
467 int Afp => byte AXINF,
468 int Afpind => byte AXNON,
469 int Apc => byte AXIMM,
470 int Adesc => byte AXIMM,
471 int Aoff => byte AXIMM,
472 int Anoff => byte AXIMM,
473 int Aerr => byte AXNON,
474 int Anone => byte AXNON,
475 int Aldt => byte AXIMM,
476};
477
478MAXCON: con 4;
479MAXADDR: con 2*MAXCON;
480MAXINST: con 3*MAXADDR+2;
481NIBUF: con 1024;
482
483ibuf: array of byte;
484nibuf: int;
485
486disinst(in: ref Inst)
487{
488 fileoff := bout.seek(big 0, 1);
489 ibuf = array[NIBUF] of byte;
490 nibuf = 0;
491 for(; in != nil; in = in.next){
492 if(in.op == INOOP)
493 continue;
494 if(nibuf >= NIBUF-MAXINST){
495 bout.write(ibuf, nibuf);
496 nibuf = 0;
497 }
498 ibuf[nibuf++] = byte in.op;
499 o := dismode[int in.sm] << SRC;
500 o |= dismode[int in.dm] << DST;
501 o |= disregmode[int in.mm];
502 ibuf[nibuf++] = o;
503 if(in.mm != Anone)
504 disaddr(in.mm, in.m);
505 if(in.sm != Anone)
506 disaddr(in.sm, in.s);
507 if(in.dm != Anone)
508 disaddr(in.dm, in.d);
509 }
510 if(nibuf > 0)
511 bout.write(ibuf, nibuf);
512 ibuf = nil;
513
514 if(debug['s'])
515 print("%bd instruction bytes start %bd\n", bout.seek(big 0, 1) - fileoff, fileoff);
516}
517
518disaddr(m: byte, a: Addr)
519{
520 val := 0;
521 case int m{
522 int Aimm or
523 int Apc or
524 int Adesc =>
525 val = a.offset;
526 int Aoff =>
527 val = a.decl.iface.offset;
528 int Anoff =>
529 val = -(a.decl.iface.offset+1);
530 int Afp or
531 int Amp or
532 int Aldt =>
533 val = a.reg;
534 int Afpind or
535 int Ampind =>
536 disbcon(a.reg);
537 val = a.offset;
538 }
539 disbcon(val);
540}
541
542disbcon(val: int)
543{
544 if(val >= -64 && val <= 63){
545 ibuf[nibuf++] = byte(val & ~16r80);
546 return;
547 }
548 if(val >= -8192 && val <= 8191){
549 ibuf[nibuf++] = byte(val>>8 & ~16rC0 | 16r80);
550 ibuf[nibuf++] = byte val;
551 return;
552 }
553 if(val < 0 && ((val >> 29) & 7) != 7
554 || val > 0 && (val >> 29) != 0)
555 fatal("overflow in constant 16r"+hex(val, 0));
556 ibuf[nibuf++] = byte(val>>24 | 16rC0);
557 ibuf[nibuf++] = byte(val>>16);
558 ibuf[nibuf++] = byte(val>>8);
559 ibuf[nibuf++] = byte val;
560}
limbo/compiler/disoptab.m+355−0
@@ -0,0 +1,355 @@
1movetab:= array [Mend]of
2{
3 Mas => array[Tend] of
4 {
5 Tadt => IMOVM,
6 Tadtpick => IMOVM,
7 Tarray => IMOVP,
8 Tbig => IMOVL,
9 Tbyte => IMOVB,
10 Tchan => IMOVP,
11 Treal => IMOVF,
12 Tint => IMOVW,
13 Tlist => IMOVP,
14 Tmodule => IMOVP,
15 Tref => IMOVP,
16 Tstring => IMOVP,
17 Ttuple => IMOVM,
18 Texception => IMOVM,
19 Tfix => IMOVW,
20 Tpoly => IMOVP,
21
22 Tany => IMOVP,
23
24 * => 0
25 },
26 Mcons => array[Tend] of
27 {
28 Tadt => ICONSM,
29 Tadtpick => 0,
30 Tarray => ICONSP,
31 Tbig => ICONSL,
32 Tbyte => ICONSB,
33 Tchan => ICONSP,
34 Treal => ICONSF,
35 Tint => ICONSW,
36 Tlist => ICONSP,
37 Tmodule => ICONSP,
38 Tref => ICONSP,
39 Tstring => ICONSP,
40 Ttuple => ICONSM,
41 Texception => ICONSM,
42 Tfix => ICONSW,
43 Tpoly => ICONSP,
44
45 Tany => ICONSP,
46
47 * => 0
48 },
49 Mhd => array[Tend] of
50 {
51 Tadt => IHEADM,
52 Tadtpick => 0,
53 Tarray => IHEADP,
54 Tbig => IHEADL,
55 Tbyte => IHEADB,
56 Tchan => IHEADP,
57 Treal => IHEADF,
58 Tint => IHEADW,
59 Tlist => IHEADP,
60 Tmodule => IHEADP,
61 Tref => IHEADP,
62 Tstring => IHEADP,
63 Ttuple => IHEADM,
64 Texception => IHEADM,
65 Tfix => IHEADW,
66 Tpoly => IHEADP,
67
68 Tany => IHEADP,
69
70 * => 0
71 },
72 Mtl => array[Tend] of
73 {
74 Tlist => ITAIL,
75
76 * => 0
77 },
78};
79
80chantab := array[Tend] of
81{
82 Tadt => INEWCM,
83 Tadtpick => 0,
84 Tarray => INEWCP,
85 Tbig => INEWCL,
86 Tbyte => INEWCB,
87 Tchan => INEWCP,
88 Treal => INEWCF,
89 Tint => INEWCW,
90 Tlist => INEWCP,
91 Tmodule => INEWCP,
92 Tref => INEWCP,
93 Tstring => INEWCP,
94 Ttuple => INEWCM,
95 Texception => INEWCM,
96 Tfix => INEWCW,
97 Tpoly => INEWCP,
98
99 Tany => INEWCP,
100
101 * => 0
102};
103
104opind := array[Tend] of
105{
106 Tbyte => 1,
107 Tint => 2,
108 Tbig => 3,
109 Treal => 4,
110 Tstring => 5,
111 Tfix => 6,
112
113 * => 0
114};
115
116disoptab := array[Oend+1] of
117{
118 # opcode default byte word big real string fixed
119 Oadd => array[7] of {0, IADDB, IADDW, IADDL, IADDF, IADDC, IADDW,},
120 Oaddas => array[7] of {0, IADDB, IADDW, IADDL, IADDF, IADDC, IADDW,},
121 Oand => array[7] of {0, IANDB, IANDW, IANDL, 0, 0, 0,},
122 Oandas => array[7] of {0, IANDB, IANDW, IANDL, 0, 0, 0,},
123 Odec => array[7] of {0, ISUBB, ISUBW, ISUBL, ISUBF, 0, ISUBW,},
124 Odiv => array[7] of {0, IDIVB, IDIVW, IDIVL, IDIVF, 0, IDIVX,},
125 Odivas => array[7] of {0, IDIVB, IDIVW, IDIVL, IDIVF, 0, IDIVX,},
126 Oeq => array[7] of {IBEQW, IBEQB, IBEQW, IBEQL, IBEQF, IBEQC, IBEQW,},
127 Oexp => array[7] of {0, 0, IEXPW, IEXPL, IEXPF, 0, 0,},
128 Oexpas => array[7] of {0, 0, IEXPW, IEXPL, IEXPF, 0, 0,},
129 Ogeq => array[7] of {0, IBGEB, IBGEW, IBGEL, IBGEF, IBGEC, IBGEW,},
130 Ogt => array[7] of {0, IBGTB, IBGTW, IBGTL, IBGTF, IBGTC, IBGTW,},
131 Oinc => array[7] of {0, IADDB, IADDW, IADDL, IADDF, 0, IADDW,},
132 Oinds => array[7] of {0, 0, IINDC, 0, 0, 0, 0,},
133 Oindx => array[7] of {0, 0, IINDX, 0, 0, 0, 0,},
134 Olen => array[7] of {ILENA, 0, 0, 0, 0, ILENC, 0,},
135 Oleq => array[7] of {0, IBLEB, IBLEW, IBLEL, IBLEF, IBLEC, IBLEW,},
136 Olsh => array[7] of {0, ISHLB, ISHLW, ISHLL, 0, 0, 0,},
137 Olshas => array[7] of {0, ISHLB, ISHLW, ISHLL, 0, 0, 0,},
138 Olt => array[7] of {0, IBLTB, IBLTW, IBLTL, IBLTF, IBLTC, IBLTW,},
139 Omod => array[7] of {0, IMODB, IMODW, IMODL, 0, 0, 0,},
140 Omodas => array[7] of {0, IMODB, IMODW, IMODL, 0, 0, 0,},
141 Omul => array[7] of {0, IMULB, IMULW, IMULL, IMULF, 0, IMULX,},
142 Omulas => array[7] of {0, IMULB, IMULW, IMULL, IMULF, 0, IMULX,},
143 Oneg => array[7] of {0, 0, 0, 0, INEGF, 0, 0, },
144 Oneq => array[7] of {IBNEW, IBNEB, IBNEW, IBNEL, IBNEF, IBNEC, IBNEW,},
145 Oor => array[7] of {0, IORB, IORW, IORL, 0, 0, 0,},
146 Ooras => array[7] of {0, IORB, IORW, IORL, 0, 0, 0,},
147 Orsh => array[7] of {0, ISHRB, ISHRW, ISHRL, 0, 0, 0,},
148 Orshas => array[7] of {0, ISHRB, ISHRW, ISHRL, 0, 0, 0,},
149 Oslice => array[7] of {ISLICEA,0, 0, 0, 0, ISLICEC, 0,},
150 Osub => array[7] of {0, ISUBB, ISUBW, ISUBL, ISUBF, 0, ISUBW,},
151 Osubas => array[7] of {0, ISUBB, ISUBW, ISUBL, ISUBF, 0, ISUBW,},
152 Oxor => array[7] of {0, IXORB, IXORW, IXORL, 0, 0, 0,},
153 Oxoras => array[7] of {0, IXORB, IXORW, IXORL, 0, 0, 0,},
154};
155
156isbyteinst := array [256] of
157{
158 IMULB => 1,
159 ISUBB => 1,
160 IADDB => 1,
161 IDIVB => 1,
162 IORB => 1,
163 IXORB => 1,
164 ISHLB => 1,
165 ISHRB => 1,
166 IMODB => 1,
167 IANDB => 1,
168 IBEQB => 1,
169 IBNEB => 1,
170 IBLTB => 1,
171 IBLEB => 1,
172 IBGTB => 1,
173 IBGEB => 1,
174
175 * => 0,
176};
177
178instname := array[256] of
179{
180 "nop",
181 "alt",
182 "nbalt",
183 "goto",
184 "call",
185 "frame",
186 "spawn",
187 "runt",
188 "load",
189 "mcall",
190 "mspawn",
191 "mframe",
192 "ret",
193 "jmp",
194 "case",
195 "exit",
196 "new",
197 "newa",
198 "newcb",
199 "newcw",
200 "newcf",
201 "newcp",
202 "newcm",
203 "newcmp",
204 "send",
205 "recv",
206 "consb",
207 "consw",
208 "consp",
209 "consf",
210 "consm",
211 "consmp",
212 "headb",
213 "headw",
214 "headp",
215 "headf",
216 "headm",
217 "headmp",
218 "tail",
219 "lea",
220 "indx",
221 "movp",
222 "movm",
223 "movmp",
224 "movb",
225 "movw",
226 "movf",
227 "cvtbw",
228 "cvtwb",
229 "cvtfw",
230 "cvtwf",
231 "cvtca",
232 "cvtac",
233 "cvtwc",
234 "cvtcw",
235 "cvtfc",
236 "cvtcf",
237 "addb",
238 "addw",
239 "addf",
240 "subb",
241 "subw",
242 "subf",
243 "mulb",
244 "mulw",
245 "mulf",
246 "divb",
247 "divw",
248 "divf",
249 "modw",
250 "modb",
251 "andb",
252 "andw",
253 "orb",
254 "orw",
255 "xorb",
256 "xorw",
257 "shlb",
258 "shlw",
259 "shrb",
260 "shrw",
261 "insc",
262 "indc",
263 "addc",
264 "lenc",
265 "lena",
266 "lenl",
267 "beqb",
268 "bneb",
269 "bltb",
270 "bleb",
271 "bgtb",
272 "bgeb",
273 "beqw",
274 "bnew",
275 "bltw",
276 "blew",
277 "bgtw",
278 "bgew",
279 "beqf",
280 "bnef",
281 "bltf",
282 "blef",
283 "bgtf",
284 "bgef",
285 "beqc",
286 "bnec",
287 "bltc",
288 "blec",
289 "bgtc",
290 "bgec",
291 "slicea",
292 "slicela",
293 "slicec",
294 "indw",
295 "indf",
296 "indb",
297 "negf",
298 "movl",
299 "addl",
300 "subl",
301 "divl",
302 "modl",
303 "mull",
304 "andl",
305 "orl",
306 "xorl",
307 "shll",
308 "shrl",
309 "bnel",
310 "bltl",
311 "blel",
312 "bgtl",
313 "bgel",
314 "beql",
315 "cvtlf",
316 "cvtfl",
317 "cvtlw",
318 "cvtwl",
319 "cvtlc",
320 "cvtcl",
321 "headl",
322 "consl",
323 "newcl",
324 "casec",
325 "indl",
326 "movpc",
327 "tcmp",
328 "mnewz",
329 "cvtrf",
330 "cvtfr",
331 "cvtws",
332 "cvtsw",
333 "lsrw",
334 "lsrl",
335 "eclr",
336 "newz",
337 "newaz",
338 "raise",
339 "casel",
340 "mulx",
341 "divx",
342 "cvtxx",
343 "mulx0",
344 "divx0",
345 "cvtxx0",
346 "mulx1",
347 "divx1",
348 "cvtxx1",
349 "cvtfx",
350 "cvtxf",
351 "expw",
352 "expl",
353 "expf",
354 "self",
355};
limbo/compiler/ecom.b+2345−0
@@ -0,0 +1,2345 @@
1maxstack: int; # max size of a stack frame called
2
3precasttab := array[Tend] of array of ref Type;
4
5optabinit()
6{
7 ct := array[Tend] of ref Type;
8 for(i := 0; i < Tend; i++)
9 precasttab[i] = ct;
10 precasttab[Tstring] = array[Tend] of { Tbyte => tint, Tfix => treal, };
11 precasttab[Tbig] = array[Tend] of { Tbyte => tint, Tfix => treal, };
12 precasttab[Treal] = array[Tend] of { Tbyte => tint, };
13 precasttab[Tfix] = array[Tend] of { Tbyte => tint, Tstring => treal, Tbig => treal, };
14 precasttab[Tbyte] = array[Tend] of { Tstring => tint, Tbig => tint, Treal => tint, Tfix => tint, };
15
16 casttab = array[Tend] of { * => array[Tend] of {* => 0}};
17
18 casttab[Tint][Tint] = IMOVW;
19 casttab[Tbig][Tbig] = IMOVL;
20 casttab[Treal][Treal] = IMOVF;
21 casttab[Tbyte][Tbyte] = IMOVB;
22 casttab[Tstring][Tstring] = IMOVP;
23 casttab[Tfix][Tfix] = ICVTXX; # never same type
24
25 casttab[Tint][Tbyte] = ICVTWB;
26 casttab[Tint][Treal] = ICVTWF;
27 casttab[Tint][Tstring] = ICVTWC;
28 casttab[Tint][Tfix] = ICVTXX;
29 casttab[Tbyte][Tint] = ICVTBW;
30 casttab[Treal][Tint] = ICVTFW;
31 casttab[Tstring][Tint] = ICVTCW;
32 casttab[Tfix][Tint] = ICVTXX;
33
34 casttab[Tint][Tbig] = ICVTWL;
35 casttab[Treal][Tbig] = ICVTFL;
36 casttab[Tstring][Tbig] = ICVTCL;
37 casttab[Tbig][Tint] = ICVTLW;
38 casttab[Tbig][Treal] = ICVTLF;
39 casttab[Tbig][Tstring] = ICVTLC;
40
41 casttab[Treal][Tstring] = ICVTFC;
42 casttab[Tstring][Treal] = ICVTCF;
43
44 casttab[Treal][Tfix] = ICVTFX;
45 casttab[Tfix][Treal] = ICVTXF;
46
47 casttab[Tstring][Tarray] = ICVTCA;
48 casttab[Tarray][Tstring] = ICVTAC;
49
50 #
51 # placeholders; fixed in precasttab
52 #
53 casttab[Tbyte][Tstring] = 16rff;
54 casttab[Tstring][Tbyte] = 16rff;
55 casttab[Tbyte][Treal] = 16rff;
56 casttab[Treal][Tbyte] = 16rff;
57 casttab[Tbyte][Tbig] = 16rff;
58 casttab[Tbig][Tbyte] = 16rff;
59 casttab[Tfix][Tbyte] = 16rff;
60 casttab[Tbyte][Tfix] = 16rff;
61 casttab[Tfix][Tbig] = 16rff;
62 casttab[Tbig][Tfix] = 16rff;
63 casttab[Tfix][Tstring] = 16rff;
64 casttab[Tstring][Tfix] = 16rff;
65}
66
67#
68# global variable and constant initialization checking
69#
70vcom(ids: ref Decl): int
71{
72 ok := 1;
73 for(v := ids; v != nil; v = v.next)
74 ok &= varcom(v);
75 for(v = ids; v != nil; v = v.next)
76 v.init = simplify(v.init);
77 return ok;
78}
79
80simplify(n: ref Node): ref Node
81{
82 if(n == nil)
83 return nil;
84 if(debug['F'])
85 print("simplify %s\n", nodeconv(n));
86 n = efold(rewrite(n));
87 if(debug['F'])
88 print("simplified %s\n", nodeconv(n));
89 return n;
90}
91
92isfix(n: ref Node): int
93{
94 if(n.ty.kind == Tint || n.ty.kind == Tfix){
95 if(n.op == Ocast)
96 return n.left.ty.kind == Tint || n.left.ty.kind == Tfix;
97 return 1;
98 }
99 return 0;
100}
101
102#
103# rewrite an expression to make it easiser to compile,
104# or give the correct results
105#
106rewrite(n: ref Node): ref Node
107{
108 v: big;
109 t: ref Type;
110 d: ref Decl;
111 nn: ref Node;
112
113 if(n == nil)
114 return nil;
115
116 left := n.left;
117 right := n.right;
118
119 #
120 # rewrites
121 #
122 case n.op{
123 Oname =>
124 d = n.decl;
125 if(d.importid != nil){
126 left = mkbin(Omdot, dupn(1, n.src, d.eimport), mkdeclname(n.src, d.importid));
127 left.ty = n.ty;
128 return rewrite(left);
129 }
130 if((t = n.ty).kind == Texception){
131 if(int t.cons)
132 fatal("cons in rewrite Oname");
133 n = mkbin(Oadd, n, mkconst(n.src, big(2*IBY2WD)));
134 n = mkunary(Oind, n);
135 n.ty = t;
136 n.left.ty = n.left.left.ty = tint;
137 return rewrite(n);
138 }
139 Odas =>
140 n.op = Oas;
141 return rewrite(n);
142 Oneg =>
143 n.left = rewrite(left);
144 if(n.ty == treal)
145 break;
146 left = n.left;
147 n.right = left;
148 n.left = mkconst(n.src, big 0);
149 n.left.ty = n.ty;
150 n.op = Osub;
151 Ocomp =>
152 v = big 0;
153 v = ~v;
154 n.right = mkconst(n.src, v);
155 n.right.ty = n.ty;
156 n.left = rewrite(left);
157 n.op = Oxor;
158 Oinc or
159 Odec or
160 Opreinc or
161 Opredec =>
162 n.left = rewrite(left);
163 case n.ty.kind{
164 Treal =>
165 n.right = mkrconst(n.src, 1.0);
166 Tint or
167 Tbig or
168 Tbyte or
169 Tfix =>
170 n.right = mkconst(n.src, big 1);
171 n.right.ty = n.ty;
172 * =>
173 fatal("can't rewrite inc/dec "+nodeconv(n));
174 }
175 if(n.op == Opreinc)
176 n.op = Oaddas;
177 else if(n.op == Opredec)
178 n.op = Osubas;
179 Oslice =>
180 if(right.left.op == Onothing)
181 right.left = mkconst(right.left.src, big 0);
182 n.left = rewrite(left);
183 n.right = rewrite(right);
184 Oindex =>
185 n.op = Oindx;
186 n.left = rewrite(left);
187 n.right = rewrite(right);
188 n = mkunary(Oind, n);
189 n.ty = n.left.ty;
190 n.left.ty = tint;
191 Oload =>
192 n.right = mkn(Oname, nil, nil);
193 n.right.src = n.left.src;
194 n.right.decl = n.ty.tof.decl;
195 n.right.ty = n.ty;
196 n.left = rewrite(left);
197 Ocast =>
198 if(left.ty.kind == Texception){
199 n = rewrite(left);
200 break;
201 }
202 n.op = Ocast;
203 t = precasttab[left.ty.kind][n.ty.kind];
204 if(t != nil){
205 n.left = mkunary(Ocast, left);
206 n.left.ty = t;
207 return rewrite(n);
208 }
209 n.left = rewrite(left);
210 Oraise =>
211 if(left.ty == tstring)
212 ;
213 else if(left.ty.cons == byte 0)
214 break;
215 else if(left.op != Ocall || left.left.ty.kind == Tfn){
216 left = mkunary(Ocall, left);
217 left.ty = left.left.ty;
218 }
219 n.left = rewrite(left);
220 Ocall =>
221 t = left.ty;
222 if(t.kind == Tref)
223 t = t.tof;
224 if(t.kind == Tfn){
225 if(left.ty.kind == Tref){ # call by function reference
226 n.left = mkunary(Oind, left);
227 n.left.ty = t;
228 return rewrite(n);
229 }
230 d = nil;
231 if(left.op == Oname)
232 d = left.decl;
233 else if(left.op == Omdot && left.right.op == Odot)
234 d = left.right.right.decl;
235 else if(left.op == Omdot || left.op == Odot)
236 d = left.right.decl;
237 else if(left.op != Oind)
238 fatal("cannot deal with call " + nodeconv(n) + " in rewrite");
239 if(ispoly(d))
240 addfnptrs(d, 0);
241 n.left = rewrite(left);
242 if(right != nil)
243 n.right = rewrite(right);
244 if(d != nil && int d.inline == 1)
245 n = simplify(inline(n));
246 break;
247 }
248 case n.ty.kind{
249 Tref =>
250 n = mkunary(Oref, n);
251 n.ty = n.left.ty;
252 n.left.ty = n.left.ty.tof;
253 n.left.left.ty = n.left.ty;
254 return rewrite(n);
255 Tadt =>
256 n.op = Otuple;
257 n.right = nil;
258 if(n.ty.tags != nil){
259 n.left = nn = mkunary(Oseq, mkconst(n.src, big left.right.decl.tag));
260 if(right != nil){
261 nn.right = right;
262 nn.src.stop = right.src.stop;
263 }
264 n.ty = left.right.decl.ty.tof;
265 }else
266 n.left = right;
267 return rewrite(n);
268 Tadtpick =>
269 n.op = Otuple;
270 n.right = nil;
271 n.left = nn = mkunary(Oseq, mkconst(n.src, big left.right.decl.tag));
272 if(right != nil){
273 nn.right = right;
274 nn.src.stop = right.src.stop;
275 }
276 n.ty = left.right.decl.ty.tof;
277 return rewrite(n);
278 Texception =>
279 if(n.ty.cons == byte 0)
280 return n.left;
281 if(left.op == Omdot){
282 left.right.ty = left.ty;
283 left = left.right;
284 }
285 n.op = Otuple;
286 n.right = nil;
287 n.left = nn = mkunary(Oseq, left.decl.init);
288 nn.right = mkunary(Oseq, mkconst(n.src, big 0));
289 nn.right.right = right;
290 n.ty = mkexbasetype(n.ty);
291 n = mkunary(Oref, n);
292 n.ty = internaltype(mktype(n.src.start, n.src.stop, Tref, t, nil));
293 return rewrite(n);
294 * =>
295 fatal("can't deal with "+nodeconv(n)+" in rewrite/Ocall");
296 }
297 Omdot =>
298 #
299 # what about side effects from left?
300 #
301 d = right.decl;
302 case d.store{
303 Dfn =>
304 n.left = rewrite(left);
305 if(right.op == Odot){
306 n.right = dupn(1, left.src, right.right);
307 n.right.ty = d.ty;
308 }
309 Dconst or
310 Dtag or
311 Dtype =>
312 # handled by fold
313 return n;
314 Dglobal =>
315 right.op = Oconst;
316 right.c = ref Const(big d.offset, 0.);
317 right.ty = tint;
318
319 n.left = left = mkunary(Oind, left);
320 left.ty = tint;
321 n.op = Oadd;
322 n = mkunary(Oind, n);
323 n.ty = n.left.ty;
324 n.left.ty = tint;
325 n.left = rewrite(n.left);
326 return n;
327 Darg =>
328 return n;
329 * =>
330 fatal("can't deal with "+nodeconv(n)+" in rewrite/Omdot");
331 }
332 Odot =>
333 #
334 # what about side effects from left?
335 #
336 d = right.decl;
337 case d.store{
338 Dfn =>
339 if(right.left != nil){
340 n = mkbin(Omdot, dupn(1, left.src, right.left), right);
341 right.left = nil;
342 n.ty = d.ty;
343 return rewrite(n);
344 }
345 if(left.ty.kind == Tpoly){
346 n = mkbin(Omdot, mkdeclname(left.src, d.link), mkdeclname(left.src, d.link.next));
347 n.ty = d.ty;
348 return rewrite(n);
349 }
350 n.op = Oname;
351 n.decl = d;
352 n.right = nil;
353 n.left = nil;
354 return n;
355 Dconst or
356 Dtag or
357 Dtype =>
358 # handled by fold
359 return n;
360 }
361 if(istuple(left))
362 return n; # handled by fold
363 right.op = Oconst;
364 right.c = ref Const(big d.offset, 0.);
365 right.ty = tint;
366
367 if(left.ty.kind != Tref){
368 n.left = mkunary(Oadr, left);
369 n.left.ty = tint;
370 }
371 n.op = Oadd;
372 n = mkunary(Oind, n);
373 n.ty = n.left.ty;
374 n.left.ty = tint;
375 n.left = rewrite(n.left);
376 return n;
377 Oadr =>
378 left = rewrite(left);
379 n.left = left;
380 if(left.op == Oind)
381 return left.left;
382 Otagof =>
383 if(n.decl == nil){
384 n.op = Oind;
385 return rewrite(n);
386 }
387 return n;
388 Omul or
389 Odiv =>
390 left = n.left = rewrite(left);
391 right = n.right = rewrite(right);
392 if(n.ty.kind == Tfix && isfix(left) && isfix(right)){
393 if(left.op == Ocast && tequal(left.ty, n.ty))
394 n.left = left.left;
395 if(right.op == Ocast && tequal(right.ty, n.ty))
396 n.right = right.left;
397 }
398 Oself =>
399 if(newfnptr)
400 return n;
401 if(selfdecl == nil){
402 d = selfdecl = mkids(n.src, enter(".self", 5), tany, nil);
403 installids(Dglobal, d);
404 d.refs++;
405 }
406 nn = mkn(Oload, nil, nil);
407 nn.src = n.src;
408 nn.left = mksconst(n.src, enterstring("$self"));
409 nn.ty = impdecl.ty;
410 usetype(nn.ty);
411 usetype(nn.ty.tof);
412 nn = rewrite(nn);
413 nn.op = Oself;
414 return nn;
415 Ofnptr =>
416 if(n.flags == byte 0){
417 # module
418 if(left == nil)
419 left = mkn(Oself, nil, nil);
420 return rewrite(left);
421 }
422 right.flags = n.flags;
423 n = right;
424 d = n.decl;
425 if(int n.flags == FNPTR2){
426 if(left != nil && left.op != Oname)
427 fatal("not Oname for addiface");
428 if(left == nil){
429 addiface(nil, d);
430 if(newfnptr)
431 n.flags |= byte FNPTRN;
432 }
433 else
434 addiface(left.decl, d);
435 n.ty = tint;
436 return n;
437 }
438 if(int n.flags == FNPTRA){
439 n = mkdeclname(n.src, d.link);
440 n.ty = tany;
441 return n;
442 }
443 if(int n.flags == (FNPTRA|FNPTR2)){
444 n = mkdeclname(n.src, d.link.next);
445 n.ty = tint;
446 return n;
447 }
448 Ochan =>
449 if(left == nil)
450 left = n.left = mkconst(n.src, big 0);
451 n.left = rewrite(left);
452 * =>
453 n.left = rewrite(left);
454 n.right = rewrite(right);
455 }
456
457 return n;
458}
459
460#
461# label a node with sethi-ullman numbers and addressablity
462# genaddr interprets addable to generate operands,
463# so a change here mandates a change there.
464#
465# addressable:
466# const Rconst $value may also be Roff or Rdesc or Rnoff
467# Asmall(local) Rreg value(FP)
468# Asmall(global) Rmreg value(MP)
469# ind(Rareg) Rreg value(FP)
470# ind(Ramreg) Rmreg value(MP)
471# ind(Rreg) Radr *value(FP)
472# ind(Rmreg) Rmadr *value(MP)
473# ind(Raadr) Radr value(value(FP))
474# ind(Ramadr) Rmadr value(value(MP))
475#
476# almost addressable:
477# adr(Rreg) Rareg
478# adr(Rmreg) Ramreg
479# add(const, Rareg) Rareg
480# add(const, Ramreg) Ramreg
481# add(const, Rreg) Raadr
482# add(const, Rmreg) Ramadr
483# add(const, Raadr) Raadr
484# add(const, Ramadr) Ramadr
485# adr(Radr) Raadr
486# adr(Rmadr) Ramadr
487#
488# strangely addressable:
489# fn Rpc
490# mdot(module,exp) Rmpc
491#
492sumark(n: ref Node): ref Node
493{
494 if(n == nil)
495 return nil;
496
497 n.temps = byte 0;
498 n.addable = Rcant;
499
500 left := n.left;
501 right := n.right;
502 if(left != nil){
503 sumark(left);
504 n.temps = left.temps;
505 }
506 if(right != nil){
507 sumark(right);
508 if(right.temps == n.temps)
509 n.temps++;
510 else if(right.temps > n.temps)
511 n.temps = right.temps;
512 }
513
514 case n.op{
515 Oadr =>
516 case int left.addable{
517 int Rreg =>
518 n.addable = Rareg;
519 int Rmreg =>
520 n.addable = Ramreg;
521 int Radr =>
522 n.addable = Raadr;
523 int Rmadr =>
524 n.addable = Ramadr;
525 }
526 Oind =>
527 case int left.addable{
528 int Rreg =>
529 n.addable = Radr;
530 int Rmreg =>
531 n.addable = Rmadr;
532 int Rareg =>
533 n.addable = Rreg;
534 int Ramreg =>
535 n.addable = Rmreg;
536 int Raadr =>
537 n.addable = Radr;
538 int Ramadr =>
539 n.addable = Rmadr;
540 }
541 Oname =>
542 case n.decl.store{
543 Darg or
544 Dlocal =>
545 n.addable = Rreg;
546 Dglobal =>
547 n.addable = Rmreg;
548 if(LDT && n.decl.ty.kind == Tiface)
549 n.addable = Rldt;
550 Dtype =>
551 #
552 # check for inferface to load
553 #
554 if(n.decl.ty.kind == Tmodule)
555 n.addable = Rmreg;
556 Dfn =>
557 if(int n.flags & FNPTR){
558 if(int n.flags == FNPTR2)
559 n.addable = Roff;
560 else if(int n.flags == (FNPTR2|FNPTRN))
561 n.addable = Rnoff;
562 }
563 else
564 n.addable = Rpc;
565 * =>
566 fatal("cannot deal with "+declconv(n.decl)+" in Oname in "+nodeconv(n));
567 }
568 Omdot =>
569 n.addable = Rmpc;
570 Oconst =>
571 case n.ty.kind{
572 Tint or
573 Tfix =>
574 v := int n.c.val;
575 if(v < 0 && ((v >> 29) & 7) != 7
576 || v > 0 && (v >> 29) != 0){
577 n.decl = globalconst(n);
578 n.addable = Rmreg;
579 }else
580 n.addable = Rconst;
581 Tbig =>
582 n.decl = globalBconst(n);
583 n.addable = Rmreg;
584 Tbyte =>
585 n.decl = globalbconst(n);
586 n.addable = Rmreg;
587 Treal =>
588 n.decl = globalfconst(n);
589 n.addable = Rmreg;
590 Tstring =>
591 n.decl = globalsconst(n);
592 n.addable = Rmreg;
593 * =>
594 fatal("cannot const in sumark "+typeconv(n.ty));
595 }
596 Oadd =>
597 if(right.addable == Rconst){
598 case int left.addable{
599 int Rareg =>
600 n.addable = Rareg;
601 int Ramreg =>
602 n.addable = Ramreg;
603 int Rreg or
604 int Raadr =>
605 n.addable = Raadr;
606 int Rmreg or
607 int Ramadr =>
608 n.addable = Ramadr;
609 }
610 }
611 }
612 if(n.addable < Rcant)
613 n.temps = byte 0;
614 else if(n.temps == byte 0)
615 n.temps = byte 1;
616 return n;
617}
618
619mktn(t: ref Type): ref Node
620{
621 n := mkn(Oname, nil, nil);
622 usedesc(mktdesc(t));
623 n.ty = t;
624 if(t.decl == nil)
625 fatal("mktn nil decl t "+typeconv(t));
626 n.decl = t.decl;
627 n.addable = Rdesc;
628 return n;
629}
630
631# does a tuple of the form (a, b, ...) form a contiguous block
632# of memory on the stack when offsets are assigned later
633# - only when (a, b, ...) := rhs and none of the names nil
634# can we guarantee this
635#
636tupblk0(n: ref Node, d: ref Decl): (int, ref Decl)
637{
638 ok, nid: int;
639
640 case(n.op){
641 Otuple =>
642 for(n = n.left; n != nil; n = n.right){
643 (ok, d) = tupblk0(n.left, d);
644 if(!ok)
645 return (0, nil);
646 }
647 return (1, d);
648 Oname =>
649 if(n.decl == nildecl)
650 return (0, nil);
651 if(d != nil && d.next != n.decl)
652 return (0, nil);
653 nid = int n.decl.nid;
654 if(d == nil && nid == 1)
655 return (0, nil);
656 if(d != nil && nid != 0)
657 return (0, nil);
658 return (1, n.decl);
659 }
660 return (0, nil);
661}
662
663# could force locals to be next to each other
664# - need to shuffle locals list
665# - later
666#
667tupblk(n: ref Node): ref Node
668{
669 ok: int;
670 d: ref Decl;
671
672 if(n.op != Otuple)
673 return nil;
674 d = nil;
675 (ok, d) = tupblk0(n, d);
676 if(!ok)
677 return nil;
678 while(n.op == Otuple)
679 n = n.left.left;
680 if(n.op != Oname || n.decl.nid == byte 1)
681 fatal("bad tupblk");
682 return n;
683}
684
685# for cprof
686esrc(src: Src, osrc: Src, nto: ref Node): Src
687{
688 if(nto != nil && src.start != 0 && src.stop != 0)
689 return src;
690 return osrc;
691}
692
693#
694# compile an expression with an implicit assignment
695# note: you are not allowed to use nto.src
696#
697# need to think carefully about the types used in moves
698#
699ecom(src: Src, nto, n: ref Node): ref Node
700{
701 tleft, tright, tto, ttn: ref Node;
702 t: ref Type;
703 p: ref Inst;
704
705 if(debug['e']){
706 print("ecom: %s\n", nodeconv(n));
707 if(nto != nil)
708 print("ecom nto: %s\n", nodeconv(nto));
709 }
710
711 if(n.addable < Rcant){
712 #
713 # think carefully about the type used here
714 #
715 if(nto != nil)
716 genmove(src, Mas, n.ty, n, nto);
717 return nto;
718 }
719
720 left := n.left;
721 right := n.right;
722 op := n.op;
723 case op{
724 * =>
725 fatal("can't ecom "+nodeconv(n));
726 return nto;
727 Oif =>
728 p = bcom(left, 1, nil);
729 ecom(right.left.src, nto, right.left);
730 if(right.right != nil){
731 pp := p;
732 p = genrawop(right.left.src, IJMP, nil, nil, nil);
733 patch(pp, nextinst());
734 ecom(right.right.src, nto, right.right);
735 }
736 patch(p, nextinst());
737 Ocomma =>
738 ttn = left.left;
739 ecom(left.src, nil, left);
740 ecom(right.src, nto, right);
741 tfree(ttn);
742 Oname =>
743 if(n.addable == Rpc){
744 if(nto != nil)
745 genmove(src, Mas, n.ty, n, nto);
746 return nto;
747 }
748 fatal("can't ecom "+nodeconv(n));
749 Onothing =>
750 break;
751 Oused =>
752 if(nto != nil)
753 fatal("superflous used "+nodeconv(left)+" nto "+nodeconv(nto));
754 tto = talloc(left.ty, nil);
755 ecom(left.src, tto, left);
756 tfree(tto);
757 Oas =>
758 if(right.ty == tany)
759 right.ty = n.ty;
760 if(left.op == Oname && left.decl.ty == tany){
761 if(nto == nil)
762 nto = tto = talloc(right.ty, nil);
763 left = nto;
764 nto = nil;
765 }
766 if(left.op == Oinds){
767 indsascom(src, nto, n);
768 tfree(tto);
769 break;
770 }
771 if(left.op == Oslice){
772 slicelcom(src, nto, n);
773 tfree(tto);
774 break;
775 }
776
777 if(left.op == Otuple){
778 if(!tupsaliased(right, left)){
779 if((tn := tupblk(left)) != nil){
780 tn.ty = n.ty;
781 ecom(n.right.src, tn, right);
782 if(nto != nil)
783 genmove(src, Mas, n.ty, tn, nto);
784 tfree(tto);
785 break;
786 }
787 if((tn = tupblk(right)) != nil){
788 tn.ty = n.ty;
789 tuplcom(tn, left);
790 if(nto != nil)
791 genmove(src, Mas, n.ty, tn, nto);
792 tfree(tto);
793 break;
794 }
795 if(nto == nil && right.op == Otuple && left.ty.kind != Tadtpick){
796 tuplrcom(right, left);
797 tfree(tto);
798 break;
799 }
800 }
801 if(right.addable >= Ralways
802 || right.op != Oname
803 || tupaliased(right, left)){
804 tright = talloc(n.ty, nil);
805 ecom(n.right.src, tright, right);
806 right = tright;
807 }
808 tuplcom(right, n.left);
809 if(nto != nil)
810 genmove(src, Mas, n.ty, right, nto);
811 tfree(tright);
812 tfree(tto);
813 break;
814 }
815
816 #
817 # check for left/right aliasing and build right into temporary
818 #
819 if(right.op == Otuple){
820 if(!tupsaliased(left, right) && (tn := tupblk(right)) != nil){
821 tn.ty = n.ty;
822 right = tn;
823 }
824 else if(left.op != Oname || tupaliased(left, right))
825 right = ecom(right.src, tright = talloc(right.ty, nil), right);
826 }
827
828 #
829 # think carefully about types here
830 #
831 if(left.addable >= Rcant)
832 (left, tleft) = eacom(left, nto);
833 ecom(n.src, left, right);
834 if(nto != nil)
835 genmove(src, Mas, nto.ty, left, nto);
836 tfree(tleft);
837 tfree(tright);
838 tfree(tto);
839 Ochan =>
840 if(left != nil && left.addable >= Rcant)
841 (left, tleft) = eacom(left, nto);
842 genchan(src, left, n.ty.tof, nto);
843 tfree(tleft);
844 Oinds =>
845 if(right.addable < Ralways){
846 if(left.addable >= Rcant)
847 (left, tleft) = eacom(left, nil);
848 }else if(left.temps <= right.temps){
849 right = ecom(right.src, tright = talloc(right.ty, nil), right);
850 if(left.addable >= Rcant)
851 (left, tleft) = eacom(left, nil);
852 }else{
853 (left, tleft) = eacom(left, nil);
854 right = ecom(right.src, tright = talloc(right.ty, nil), right);
855 }
856 genop(n.src, op, left, right, nto);
857 tfree(tleft);
858 tfree(tright);
859 Osnd =>
860 if(right.addable < Rcant){
861 if(left.addable >= Rcant)
862 (left, tleft) = eacom(left, nto);
863 }else if(left.temps < right.temps){
864 (right, tright) = eacom(right, nto);
865 if(left.addable >= Rcant)
866 (left, tleft) = eacom(left, nil);
867 }else{
868 (left, tleft) = eacom(left, nto);
869 (right, tright) = eacom(right, nil);
870 }
871 p = genrawop(n.src, ISEND, right, nil, left);
872 p.m.offset = n.ty.size; # for optimizer
873 if(nto != nil)
874 genmove(src, Mas, right.ty, right, nto);
875 tfree(tleft);
876 tfree(tright);
877 Orcv =>
878 if(nto == nil){
879 ecom(n.src, tto = talloc(n.ty, nil), n);
880 tfree(tto);
881 return nil;
882 }
883 if(left.addable >= Rcant)
884 (left, tleft) = eacom(left, nto);
885 if(left.ty.kind == Tchan){
886 p = genrawop(src, IRECV, left, nil, nto);
887 p.m.offset = n.ty.size; # for optimizer
888 }else{
889 recvacom(src, nto, n);
890 }
891 tfree(tleft);
892 Ocons =>
893 #
894 # another temp which can go with analysis
895 #
896 if(left.addable >= Rcant)
897 (left, tleft) = eacom(left, nil);
898 if(!sameaddr(right, nto)){
899 ecom(right.src, tto = talloc(n.ty, nto), right);
900 genmove(src, Mcons, left.ty, left, tto);
901 if(!sameaddr(tto, nto))
902 genmove(src, Mas, nto.ty, tto, nto);
903 }else
904 genmove(src, Mcons, left.ty, left, nto);
905 tfree(tleft);
906 tfree(tto);
907 Ohd =>
908 if(left.addable >= Rcant)
909 (left, tleft) = eacom(left, nto);
910 genmove(src, Mhd, nto.ty, left, nto);
911 tfree(tleft);
912 Otl =>
913 if(left.addable >= Rcant)
914 (left, tleft) = eacom(left, nto);
915 genmove(src, Mtl, left.ty, left, nto);
916 tfree(tleft);
917 Otuple =>
918 if((tn := tupblk(n)) != nil){
919 tn.ty = n.ty;
920 genmove(src, Mas, n.ty, tn, nto);
921 break;
922 }
923 tupcom(nto, n);
924 Oadd or
925 Osub or
926 Omul or
927 Odiv or
928 Omod or
929 Oand or
930 Oor or
931 Oxor or
932 Olsh or
933 Orsh or
934 Oexp =>
935 #
936 # check for 2 operand forms
937 #
938 if(sameaddr(nto, left)){
939 if(right.addable >= Rcant)
940 (right, tright) = eacom(right, nto);
941 genop(src, op, right, nil, nto);
942 tfree(tright);
943 break;
944 }
945
946 if(opcommute[op] && sameaddr(nto, right) && n.ty != tstring){
947 if(left.addable >= Rcant)
948 (left, tleft) = eacom(left, nto);
949 genop(src, opcommute[op], left, nil, nto);
950 tfree(tleft);
951 break;
952 }
953
954 if(right.addable < left.addable
955 && opcommute[op]
956 && n.ty != tstring){
957 op = opcommute[op];
958 left = right;
959 right = n.left;
960 }
961 if(left.addable < Ralways){
962 if(right.addable >= Rcant)
963 (right, tright) = eacom(right, nto);
964 }else if(right.temps <= left.temps){
965 left = ecom(left.src, tleft = talloc(left.ty, nto), left);
966 if(right.addable >= Rcant)
967 (right, tright) = eacom(right, nil);
968 }else{
969 (right, tright) = eacom(right, nto);
970 left = ecom(left.src, tleft = talloc(left.ty, nil), left);
971 }
972
973 #
974 # check for 2 operand forms
975 #
976 if(sameaddr(nto, left))
977 genop(src, op, right, nil, nto);
978 else if(opcommute[op] && sameaddr(nto, right) && n.ty != tstring)
979 genop(src, opcommute[op], left, nil, nto);
980 else
981 genop(src, op, right, left, nto);
982 tfree(tleft);
983 tfree(tright);
984 Oaddas or
985 Osubas or
986 Omulas or
987 Odivas or
988 Omodas or
989 Oexpas or
990 Oandas or
991 Ooras or
992 Oxoras or
993 Olshas or
994 Orshas =>
995 if(left.op == Oinds){
996 indsascom(src, nto, n);
997 break;
998 }
999 if(right.addable < Rcant){
1000 if(left.addable >= Rcant)
1001 (left, tleft) = eacom(left, nto);
1002 }else if(left.temps < right.temps){
1003 (right, tright) = eacom(right, nto);
1004 if(left.addable >= Rcant)
1005 (left, tleft) = eacom(left, nil);
1006 }else{
1007 (left, tleft) = eacom(left, nto);
1008 (right, tright) = eacom(right, nil);
1009 }
1010 genop(n.src, op, right, nil, left);
1011 if(nto != nil)
1012 genmove(src, Mas, left.ty, left, nto);
1013 tfree(tleft);
1014 tfree(tright);
1015 Olen =>
1016 if(left.addable >= Rcant)
1017 (left, tleft) = eacom(left, nto);
1018 op = -1;
1019 t = left.ty;
1020 if(t == tstring)
1021 op = ILENC;
1022 else if(t.kind == Tarray)
1023 op = ILENA;
1024 else if(t.kind == Tlist)
1025 op = ILENL;
1026 else
1027 fatal("can't len "+nodeconv(n));
1028 genrawop(src, op, left, nil, nto);
1029 tfree(tleft);
1030 Oneg =>
1031 if(left.addable >= Rcant)
1032 (left, tleft) = eacom(left, nto);
1033 genop(n.src, op, left, nil, nto);
1034 tfree(tleft);
1035 Oinc or
1036 Odec =>
1037 if(left.op == Oinds){
1038 indsascom(src, nto, n);
1039 break;
1040 }
1041 if(left.addable >= Rcant)
1042 (left, tleft) = eacom(left, nil);
1043 if(nto != nil)
1044 genmove(src, Mas, left.ty, left, nto);
1045 if(right.addable >= Rcant)
1046 fatal("inc/dec amount not addressable: "+nodeconv(n));
1047 genop(n.src, op, right, nil, left);
1048 tfree(tleft);
1049 Ospawn =>
1050 if(left.left.op == Oind)
1051 fpcall(n.src, op, left, nto);
1052 else
1053 callcom(n.src, op, left, nto);
1054 Oraise =>
1055 if(left.addable >= Rcant)
1056 (left, tleft) = eacom(left, nil);
1057 genrawop(n.src, IRAISE, left, nil, nil);
1058 tfree(tleft);
1059 Ocall =>
1060 if(left.op == Oind)
1061 fpcall(esrc(src, n.src, nto), op, n, nto);
1062 else
1063 callcom(esrc(src, n.src, nto), op, n, nto);
1064 Oref =>
1065 t = left.ty;
1066 if(left.op == Oname && left.decl.store == Dfn || left.op == Omdot && left.right.op == Oname && left.right.decl.store == Dfn){ # create a function reference
1067 mod, ind: ref Node;
1068
1069 d := left.decl;
1070 if(left.op == Omdot){
1071 d = left.right.decl;
1072 mod = left.left;
1073 }
1074 else if(d.eimport != nil)
1075 mod = d.eimport;
1076 else{
1077 mod = rewrite(mkn(Oself, nil, nil));
1078 addiface(nil, d);
1079 }
1080 sumark(mod);
1081 tto = talloc(n.ty, nto);
1082 genrawop(src, INEW, mktn(usetype(tfnptr)), nil, tto);
1083 tright = ref znode;
1084 tright.src = src;
1085 tright.op = Oind;
1086 tright.left = tto;
1087 tright.right = nil;
1088 tright.ty = tany;
1089 sumark(tright);
1090 ecom(src, tright, mod);
1091 ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, tto), mkconst(src, big IBY2WD)));
1092 ind.ty = ind.left.ty = ind.left.right.ty = tint;
1093 tright.op = Oas;
1094 tright.left = ind;
1095 tright.right = mkdeclname(src, d);
1096 tright.ty = tright.right.ty = tint;
1097 sumark(tright);
1098 if(mod.op == Oself && newfnptr)
1099 tright.right.addable = Rnoff;
1100 else
1101 tright.right.addable = Roff;
1102 ecom(src, nil, tright);
1103 if(!sameaddr(tto, nto))
1104 genmove(src, Mas, n.ty, tto, nto);
1105 tfree(tto);
1106 break;
1107 }
1108 if(left.op == Oname && left.decl.store == Dtype){
1109 genrawop(src, INEW, mktn(t), nil, nto);
1110 break;
1111 }
1112 if(t.kind == Tadt && t.tags != nil){
1113 pickdupcom(src, nto, left);
1114 break;
1115 }
1116
1117 tt := t;
1118 if(left.op == Oconst && left.decl.store == Dtag)
1119 t = left.decl.ty.tof;
1120
1121 #
1122 # could eliminate temp if nto does not occur
1123 # in tuple initializer
1124 #
1125 tto = talloc(n.ty, nto);
1126 genrawop(src, INEW, mktn(t), nil, tto);
1127 tright = ref znode;
1128 tright.op = Oind;
1129 tright.left = tto;
1130 tright.right = nil;
1131 tright.ty = tt;
1132 sumark(tright);
1133 ecom(src, tright, left);
1134 if(!sameaddr(tto, nto))
1135 genmove(src, Mas, n.ty, tto, nto);
1136 tfree(tto);
1137 Oload =>
1138 if(left.addable >= Rcant)
1139 (left, tleft) = eacom(left, nto);
1140 tright = talloc(tint, nil);
1141 if(LDT)
1142 genrawop(src, ILOAD, left, right, nto);
1143 else{
1144 genrawop(src, ILEA, right, nil, tright);
1145 genrawop(src, ILOAD, left, tright, nto);
1146 }
1147 tfree(tleft);
1148 tfree(tright);
1149 Ocast =>
1150 if(left.addable >= Rcant)
1151 (left, tleft) = eacom(left, nto);
1152 t = left.ty;
1153 if(t.kind == Tfix || n.ty.kind == Tfix){
1154 op = casttab[t.kind][n.ty.kind];
1155 if(op == ICVTXX)
1156 genfixcastop(src, op, left, nto);
1157 else{
1158 ttn = sumark(mkrconst(src, scale2(t, n.ty)));
1159 genrawop(src, op, left, ttn, nto);
1160 }
1161 }
1162 else
1163 genrawop(src, casttab[t.kind][n.ty.kind], left, nil, nto);
1164 tfree(tleft);
1165 Oarray =>
1166 if(left.addable >= Rcant)
1167 (left, tleft) = eacom(left, nto);
1168 if(arrayz)
1169 genrawop(esrc(src, left.src, nto), INEWAZ, left, mktn(n.ty.tof), nto);
1170 else
1171 genrawop(esrc(src, left.src, nto), INEWA, left, mktn(n.ty.tof), nto);
1172 if(right != nil)
1173 arraycom(nto, right);
1174 tfree(tleft);
1175 Oslice =>
1176 tn := right.right;
1177 right = right.left;
1178
1179 #
1180 # make the left node of the slice directly addressable
1181 # therefore, if it's len is taken (via tn),
1182 # left's tree won't be rewritten
1183 #
1184 if(left.addable >= Rcant)
1185 (left, tleft) = eacom(left, nil);
1186
1187 if(tn.op == Onothing){
1188 tn = mkn(Olen, left, nil);
1189 tn.src = src;
1190 tn.ty = tint;
1191 sumark(tn);
1192 }
1193 if(tn.addable < Ralways){
1194 if(right.addable >= Rcant)
1195 (right, tright) = eacom(right, nil);
1196 }else if(right.temps <= tn.temps){
1197 tn = ecom(tn.src, ttn = talloc(tn.ty, nil), tn);
1198 if(right.addable >= Rcant)
1199 (right, tright) = eacom(right, nil);
1200 }else{
1201 (right, tright) = eacom(right, nil);
1202 tn = ecom(tn.src, ttn = talloc(tn.ty, nil), tn);
1203 }
1204 op = ISLICEA;
1205 if(nto.ty == tstring)
1206 op = ISLICEC;
1207
1208 #
1209 # overwrite the destination last,
1210 # since it might be used in computing the slice bounds
1211 #
1212 if(!sameaddr(left, nto))
1213 ecom(left.src, nto, left);
1214
1215 genrawop(src, op, right, tn, nto);
1216 tfree(tleft);
1217 tfree(tright);
1218 tfree(ttn);
1219 Oindx =>
1220 if(right.addable < Rcant){
1221 if(left.addable >= Rcant)
1222 (left, tleft) = eacom(left, nto);
1223 }else if(left.temps < right.temps){
1224 (right, tright) = eacom(right, nto);
1225 if(left.addable >= Rcant)
1226 (left, tleft) = eacom(left, nil);
1227 }else{
1228 (left, tleft) = eacom(left, nto);
1229 (right, tright) = eacom(right, nil);
1230 }
1231 if(nto.addable >= Ralways)
1232 nto = ecom(src, tto = talloc(nto.ty, nil), nto);
1233 op = IINDX;
1234 case left.ty.tof.size{
1235 IBY2LG =>
1236 op = IINDL;
1237 if(left.ty.tof == treal)
1238 op = IINDF;
1239 IBY2WD =>
1240 op = IINDW;
1241 1 =>
1242 op = IINDB;
1243 }
1244 genrawop(src, op, left, nto, right);
1245 if(tleft != nil && tleft.decl != nil)
1246 tfreelater(tleft);
1247 else
1248 tfree(tleft);
1249 tfree(tright);
1250 tfree(tto);
1251 Oind =>
1252 (n, tleft) = eacom(n, nto);
1253 genmove(src, Mas, n.ty, n, nto);
1254 tfree(tleft);
1255 Onot or
1256 Oandand or
1257 Ooror or
1258 Oeq or
1259 Oneq or
1260 Olt or
1261 Oleq or
1262 Ogt or
1263 Ogeq =>
1264 p = bcom(n, 1, nil);
1265 genmove(src, Mas, tint, sumark(mkconst(src, big 1)), nto);
1266 pp := genrawop(src, IJMP, nil, nil, nil);
1267 patch(p, nextinst());
1268 genmove(src, Mas, tint, sumark(mkconst(src, big 0)), nto);
1269 patch(pp, nextinst());
1270 Oself =>
1271 if(newfnptr){
1272 if(nto != nil)
1273 genrawop(src, ISELF, nil, nil, nto);
1274 break;
1275 }
1276 tn := sumark(mkdeclname(src, selfdecl));
1277 p = genbra(src, Oneq, tn, sumark(mkdeclname(src, nildecl)));
1278 n.op = Oload;
1279 ecom(src, tn, n);
1280 patch(p, nextinst());
1281 genmove(src, Mas, n.ty, tn, nto);
1282 }
1283 return nto;
1284}
1285
1286#
1287# compile exp n to yield an addressable expression
1288# use reg to build a temporary; if t is a temp, it is usable
1289#
1290# note that 0adr's are strange as they are only used
1291# for calculating the addresses of fields within adt's.
1292# therefore an Oind is the parent or grandparent of the Oadr,
1293# and we pick off all of the cases where Oadr's argument is not
1294# addressable by looking from the Oind.
1295#
1296eacom(n, t: ref Node): (ref Node, ref Node)
1297{
1298 reg: ref Node;
1299
1300 if(n.op == Ocomma){
1301 tn := n.left.left;
1302 ecom(n.left.src, nil, n.left);
1303 nn := eacom(n.right, t);
1304 tfree(tn);
1305 return nn;
1306 }
1307
1308 if(debug['e'] || debug['E'])
1309 print("eacom: %s\n", nodeconv(n));
1310
1311 left := n.left;
1312 if(n.op != Oind){
1313 ecom(n.src, reg = talloc(n.ty, t), n);
1314 reg.src = n.src;
1315 return (reg, reg);
1316 }
1317
1318 if(left.op == Oadd && left.right.op == Oconst){
1319 if(left.left.op == Oadr){
1320 (left.left.left, reg) = eacom(left.left.left, t);
1321 sumark(n);
1322 if(n.addable >= Rcant)
1323 fatal("eacom can't make node addressable: "+nodeconv(n));
1324 return (n, reg);
1325 }
1326 reg = talloc(left.left.ty, t);
1327 ecom(left.left.src, reg, left.left);
1328 left.left.decl = reg.decl;
1329 left.left.addable = Rreg;
1330 left.left = reg;
1331 left.addable = Raadr;
1332 n.addable = Radr;
1333 }else if(left.op == Oadr){
1334 reg = talloc(left.left.ty, t);
1335 ecom(left.left.src, reg, left.left);
1336
1337 #
1338 # sleaze: treat the temp as the type of the field, not the enclosing structure
1339 #
1340 reg.ty = n.ty;
1341 reg.src = n.src;
1342 return (reg, reg);
1343 }else{
1344 reg = talloc(left.ty, t);
1345 ecom(left.src, reg, left);
1346 n.left = reg;
1347 n.addable = Radr;
1348 }
1349 return (n, reg);
1350}
1351
1352#
1353# compile an assignment to an array slice
1354#
1355slicelcom(src: Src, nto, n: ref Node): ref Node
1356{
1357 tleft, tright, tv: ref Node;
1358
1359 left := n.left.left;
1360 right := n.left.right.left;
1361 v := n.right;
1362 if(right.addable < Ralways){
1363 if(left.addable >= Rcant)
1364 (left, tleft) = eacom(left, nto);
1365 }else if(left.temps <= right.temps){
1366 right = ecom(right.src, tright = talloc(right.ty, nto), right);
1367 if(left.addable >= Rcant)
1368 (left, tleft) = eacom(left, nil);
1369 }else{
1370 (left, tleft) = eacom(left, nil); # dangle on right and v
1371 right = ecom(right.src, tright = talloc(right.ty, nil), right);
1372 }
1373
1374 case n.op{
1375 Oas =>
1376 if(v.addable >= Rcant)
1377 (v, tv) = eacom(v, nil);
1378 }
1379
1380 genrawop(n.src, ISLICELA, v, right, left);
1381 if(nto != nil)
1382 genmove(src, Mas, n.ty, left, nto);
1383 tfree(tleft);
1384 tfree(tv);
1385 tfree(tright);
1386 return nto;
1387}
1388
1389#
1390# compile an assignment to a string location
1391#
1392indsascom(src: Src, nto, n: ref Node): ref Node
1393{
1394 tleft, tright, tv, tu, u: ref Node;
1395
1396 left := n.left.left;
1397 right := n.left.right;
1398 v := n.right;
1399 if(right.addable < Ralways){
1400 if(left.addable >= Rcant)
1401 (left, tleft) = eacom(left, nto);
1402 }else if(left.temps <= right.temps){
1403 right = ecom(right.src, tright = talloc(right.ty, nto), right);
1404 if(left.addable >= Rcant)
1405 (left, tleft) = eacom(left, nil);
1406 }else{
1407 (left, tleft) = eacom(left, nil); # dangle on right and v
1408 right = ecom(right.src, tright = talloc(right.ty, nil), right);
1409 }
1410
1411 case n.op{
1412 Oas =>
1413 if(v.addable >= Rcant)
1414 (v, tv) = eacom(v, nil);
1415 Oinc or
1416 Odec =>
1417 if(v.addable >= Rcant)
1418 fatal("inc/dec amount not addable");
1419 u = tu = talloc(tint, nil);
1420 genop(n.left.src, Oinds, left, right, u);
1421 if(nto != nil)
1422 genmove(src, Mas, n.ty, u, nto);
1423 nto = nil;
1424 genop(n.src, n.op, v, nil, u);
1425 v = u;
1426 Oaddas or
1427 Osubas or
1428 Omulas or
1429 Odivas or
1430 Omodas or
1431 Oexpas or
1432 Oandas or
1433 Ooras or
1434 Oxoras or
1435 Olshas or
1436 Orshas =>
1437 if(v.addable >= Rcant)
1438 (v, tv) = eacom(v, nil);
1439 u = tu = talloc(tint, nil);
1440 genop(n.left.src, Oinds, left, right, u);
1441 genop(n.src, n.op, v, nil, u);
1442 v = u;
1443 }
1444
1445 genrawop(n.src, IINSC, v, right, left);
1446 tfree(tleft);
1447 tfree(tv);
1448 tfree(tright);
1449 tfree(tu);
1450 if(nto != nil)
1451 genmove(src, Mas, n.ty, v, nto);
1452 return nto;
1453}
1454
1455callcom(src: Src, op: int, n, ret: ref Node)
1456{
1457 tmod, tind: ref Node;
1458 callee: ref Decl;
1459
1460 args := n.right;
1461 nfn := n.left;
1462 case(nfn.op){
1463 Odot =>
1464 callee = nfn.right.decl;
1465 nfn.addable = Rpc;
1466 Omdot =>
1467 callee = nfn.right.decl;
1468 Oname =>
1469 callee = nfn.decl;
1470 * =>
1471 callee = nil;
1472 fatal("bad call op in callcom");
1473 }
1474 if(nfn.addable != Rpc && nfn.addable != Rmpc)
1475 fatal("can't gen call addresses");
1476 if(nfn.ty.tof != tnone && ret == nil){
1477 ecom(src, tmod = talloc(nfn.ty.tof, nil), n);
1478 tfree(tmod);
1479 return;
1480 }
1481 if(ispoly(callee))
1482 addfnptrs(callee, 0);
1483 if(nfn.ty.varargs != byte 0){
1484 d := dupdecl(nfn.right.decl);
1485 nfn.decl = d;
1486 d.desc = gendesc(d, idoffsets(nfn.ty.ids, MaxTemp, MaxAlign), nfn.ty.ids);
1487 }
1488
1489 frame := talloc(tint, nil);
1490
1491 mod := nfn.left;
1492 ind := nfn.right;
1493 if(nfn.addable == Rmpc){
1494 if(mod.addable >= Rcant)
1495 (mod, tmod) = eacom(mod, nil); # dangle always
1496 if(ind.op != Oname && ind.addable >= Ralways){
1497 tind = talloc(ind.ty, nil);
1498 ecom(ind.src, tind, ind);
1499 ind = tind;
1500 }
1501 else if(ind.decl != nil && ind.decl.store != Darg)
1502 ind.addable = Roff;
1503 }
1504
1505 #
1506 # stop nested uncalled frames
1507 # otherwise exception handling very complicated
1508 #
1509 for(a := args; a != nil; a = a.right){
1510 if(hascall(a.left)){
1511 tn := talloc(a.left.ty, nil);
1512 ecom(a.left.src, tn, a.left);
1513 a.left = tn;
1514 tn.flags |= byte TEMP;
1515 }
1516 }
1517
1518 #
1519 # allocate the frame
1520 #
1521 if(nfn.addable == Rmpc && nfn.ty.varargs == byte 0){
1522 genrawop(src, IMFRAME, mod, ind, frame);
1523 }else if(nfn.op == Odot){
1524 genrawop(src, IFRAME, nfn.left, nil, frame);
1525 }else{
1526 in := genrawop(src, IFRAME, nil, nil, frame);
1527 in.sm = Adesc;
1528 in.s.decl = nfn.decl;
1529 }
1530
1531 #
1532 # build a fake node for the argument area
1533 #
1534 toff := ref znode;
1535 tadd := ref znode;
1536 pass := ref znode;
1537 toff.op = Oconst;
1538 toff.c = ref Const(big 0, 0.0); # jrf - added initialization
1539 toff.addable = Rconst;
1540 toff.ty = tint;
1541 tadd.op = Oadd;
1542 tadd.addable = Raadr;
1543 tadd.left = frame;
1544 tadd.right = toff;
1545 tadd.ty = tint;
1546 pass.op = Oind;
1547 pass.addable = Radr;
1548 pass.left = tadd;
1549
1550 #
1551 # compile all the args
1552 #
1553 d := nfn.ty.ids;
1554 off := 0;
1555 for(a = args; a != nil; a = a.right){
1556 off = d.offset;
1557 toff.c.val = big off;
1558 if(d.ty.kind == Tpoly)
1559 pass.ty = a.left.ty;
1560 else
1561 pass.ty = d.ty;
1562 ecom(a.left.src, pass, a.left);
1563 d = d.next;
1564 if(int a.left.flags & TEMP)
1565 tfree(a.left);
1566 }
1567 if(off > maxstack)
1568 maxstack = off;
1569
1570 #
1571 # pass return value
1572 #
1573 if(ret != nil){
1574 toff.c.val = big(REGRET*IBY2WD);
1575 pass.ty = nfn.ty.tof;
1576 p := genrawop(src, ILEA, ret, nil, pass);
1577 p.m.offset = ret.ty.size; # for optimizer
1578 }
1579
1580 #
1581 # call it
1582 #
1583 iop: int;
1584 if(nfn.addable == Rmpc){
1585 iop = IMCALL;
1586 if(op == Ospawn)
1587 iop = IMSPAWN;
1588 genrawop(src, iop, frame, ind, mod);
1589 tfree(tmod);
1590 tfree(tind);
1591 }else if(nfn.op == Odot){
1592 iop = ICALL;
1593 if(op == Ospawn)
1594 iop = ISPAWN;
1595 genrawop(src, iop, frame, nil, nfn.right);
1596 }else{
1597 iop = ICALL;
1598 if(op == Ospawn)
1599 iop = ISPAWN;
1600 in := genrawop(src, iop, frame, nil, nil);
1601 in.d.decl = nfn.decl;
1602 in.dm = Apc;
1603 }
1604 tfree(frame);
1605}
1606
1607#
1608# initialization code for arrays
1609# a must be addressable (< Rcant)
1610#
1611arraycom(a, elems: ref Node)
1612{
1613 top, out: ref Inst;
1614 ri, n, wild: ref Node;
1615
1616 if(debug['A'])
1617 print("arraycom: %s %s\n", nodeconv(a), nodeconv(elems));
1618
1619 # c := elems.ty.cse;
1620 # don't use c.wild in case we've been inlined
1621 wild = nil;
1622 for(e := elems; e != nil; e = e.right)
1623 for(q := e.left.left; q != nil; q = q.right)
1624 if(q.left.op == Owild)
1625 wild = e.left;
1626 if(wild != nil)
1627 arraydefault(a, wild.right);
1628
1629 tindex := ref znode;
1630 fake := ref znode;
1631 tmp := talloc(tint, nil);
1632 tindex.op = Oindx;
1633 tindex.addable = Rcant;
1634 tindex.left = a;
1635 tindex.right = nil;
1636 tindex.ty = tint;
1637 fake.op = Oind;
1638 fake.addable = Radr;
1639 fake.left = tmp;
1640 fake.ty = a.ty.tof;
1641
1642 for(e = elems; e != nil; e = e.right){
1643 #
1644 # just duplicate the initializer for Oor
1645 #
1646 for(q = e.left.left; q != nil; q = q.right){
1647 if(q.left.op == Owild)
1648 continue;
1649
1650 body := e.left.right;
1651 if(q.right != nil)
1652 body = dupn(0, nosrc, body);
1653 top = nil;
1654 out = nil;
1655 ri = nil;
1656 if(q.left.op == Orange){
1657 #
1658 # for(i := q.left.left; i <= q.left.right; i++)
1659 #
1660 ri = talloc(tint, nil);
1661 ri.src = q.left.src;
1662 ecom(q.left.src, ri, q.left.left);
1663
1664 # i <= q.left.right;
1665 n = mkn(Oleq, ri, q.left.right);
1666 n.src = q.left.src;
1667 n.ty = tint;
1668 top = nextinst();
1669 out = bcom(n, 1, nil);
1670
1671 tindex.right = ri;
1672 }else{
1673 tindex.right = q.left;
1674 }
1675
1676 tindex.addable = Rcant;
1677 tindex.src = q.left.src;
1678 ecom(tindex.src, tmp, tindex);
1679
1680 ecom(body.src, fake, body);
1681
1682 if(q.left.op == Orange){
1683 # i++
1684 n = mkbin(Oinc, ri, sumark(mkconst(ri.src, big 1)));
1685 n.ty = tint;
1686 n.addable = Rcant;
1687 ecom(n.src, nil, n);
1688
1689 # jump to test
1690 patch(genrawop(q.left.src, IJMP, nil, nil, nil), top);
1691 patch(out, nextinst());
1692 tfree(ri);
1693 }
1694 }
1695 }
1696 tfree(tmp);
1697}
1698
1699#
1700# default initialization code for arrays.
1701# compiles to
1702# n = len a;
1703# while(n){
1704# n--;
1705# a[n] = elem;
1706# }
1707#
1708arraydefault(a, elem: ref Node)
1709{
1710 e: ref Node;
1711
1712 if(debug['A'])
1713 print("arraydefault: %s %s\n", nodeconv(a), nodeconv(elem));
1714
1715 t := mkn(Olen, a, nil);
1716 t.src = elem.src;
1717 t.ty = tint;
1718 t.addable = Rcant;
1719 n := talloc(tint, nil);
1720 n.src = elem.src;
1721 ecom(t.src, n, t);
1722
1723 top := nextinst();
1724 out := bcom(n, 1, nil);
1725
1726 t = mkbin(Odec, n, sumark(mkconst(elem.src, big 1)));
1727 t.ty = tint;
1728 t.addable = Rcant;
1729 ecom(t.src, nil, t);
1730
1731 if(elem.addable >= Rcant)
1732 (elem, e) = eacom(elem, nil);
1733
1734 t = mkn(Oindx, a, n);
1735 t.src = elem.src;
1736 t = mkbin(Oas, mkunary(Oind, t), elem);
1737 t.ty = elem.ty;
1738 t.left.ty = elem.ty;
1739 t.left.left.ty = tint;
1740 sumark(t);
1741 ecom(t.src, nil, t);
1742
1743 patch(genrawop(t.src, IJMP, nil, nil, nil), top);
1744
1745 tfree(n);
1746 tfree(e);
1747 patch(out, nextinst());
1748}
1749
1750tupcom(nto, n: ref Node)
1751{
1752 if(debug['Y'])
1753 print("tupcom %s\nto %s\n", nodeconv(n), nodeconv(nto));
1754
1755 #
1756 # build a fake node for the tuple
1757 #
1758 toff := ref znode;
1759 tadd := ref znode;
1760 fake := ref znode;
1761 tadr := ref znode;
1762 toff.op = Oconst;
1763 toff.c = ref Const(big 0, 0.0); # no val => may get fatal error below (jrf)
1764 toff.ty = tint;
1765 tadr.op = Oadr;
1766 tadr.left = nto;
1767 tadr.ty = tint;
1768 tadd.op = Oadd;
1769 tadd.left = tadr;
1770 tadd.right = toff;
1771 tadd.ty = tint;
1772 fake.op = Oind;
1773 fake.left = tadd;
1774 sumark(fake);
1775 if(fake.addable >= Rcant)
1776 fatal("tupcom: bad value exp "+nodeconv(fake));
1777
1778 #
1779 # compile all the exps
1780 #
1781 d := n.ty.ids;
1782 for(e := n.left; e != nil; e = e.right){
1783 toff.c.val = big d.offset;
1784 fake.ty = d.ty;
1785 ecom(e.left.src, fake, e.left);
1786 d = d.next;
1787 }
1788}
1789
1790tuplcom(n, nto: ref Node)
1791{
1792 if(debug['Y'])
1793 print("tuplcom %s\nto %s\n", nodeconv(n), nodeconv(nto));
1794
1795 #
1796 # build a fake node for the tuple
1797 #
1798 toff := ref znode;
1799 tadd := ref znode;
1800 fake := ref znode;
1801 tadr := ref znode;
1802 toff.op = Oconst;
1803 toff.c = ref Const(big 0, 0.0); # no val => may get fatal error below (jrf)
1804 toff.ty = tint;
1805 tadr.op = Oadr;
1806 tadr.left = n;
1807 tadr.ty = tint;
1808 tadd.op = Oadd;
1809 tadd.left = tadr;
1810 tadd.right = toff;
1811 tadd.ty = tint;
1812 fake.op = Oind;
1813 fake.left = tadd;
1814 sumark(fake);
1815 if(fake.addable >= Rcant)
1816 fatal("tuplcom: bad value exp for "+nodeconv(fake));
1817
1818 #
1819 # compile all the exps
1820 #
1821 tas := ref znode;
1822 d := nto.ty.ids;
1823 if(nto.ty.kind == Tadtpick)
1824 d = nto.ty.tof.ids.next;
1825 for(e := nto.left; e != nil; e = e.right){
1826 as := e.left;
1827 if(as.op != Oname || as.decl != nildecl){
1828 toff.c.val = big d.offset;
1829 fake.ty = d.ty;
1830 fake.src = as.src;
1831 if(as.addable < Rcant)
1832 genmove(as.src, Mas, d.ty, fake, as);
1833 else{
1834 tas.op = Oas;
1835 tas.ty = d.ty;
1836 tas.src = as.src;
1837 tas.left = as;
1838 tas.right = fake;
1839 tas.addable = Rcant;
1840 ecom(as.src, nil, tas);
1841 }
1842 }
1843 d = d.next;
1844 }
1845}
1846
1847tuplrcom(n: ref Node, nto: ref Node)
1848{
1849 s, d, tas: ref Node;
1850 de: ref Decl;
1851
1852 tas = ref znode;
1853 de = nto.ty.ids;
1854 for((s, d) = (n.left, nto.left); s != nil && d != nil; (s, d) = (s.right, d.right)){
1855 if(d.left.op != Oname || d.left.decl != nildecl){
1856 tas.op = Oas;
1857 tas.ty = de.ty;
1858 tas.src = s.left.src;
1859 tas.left = d.left;
1860 tas.right = s.left;
1861 sumark(tas);
1862 ecom(tas.src, nil, tas);
1863 }
1864 de = de.next;
1865 }
1866 if(s != nil || d != nil)
1867 fatal("tuplrcom");
1868}
1869
1870#
1871# boolean compiler
1872# fall through when condition == true
1873#
1874bcom(n: ref Node, iftrue: int, b: ref Inst): ref Inst
1875{
1876 tleft, tright: ref Node;
1877
1878 if(n.op == Ocomma){
1879 tn := n.left.left;
1880 ecom(n.left.src, nil, n.left);
1881 b = bcom(n.right, iftrue, b);
1882 tfree(tn);
1883 return b;
1884 }
1885
1886 if(debug['b'])
1887 print("bcom %s %d\n", nodeconv(n), iftrue);
1888
1889 left := n.left;
1890 right := n.right;
1891 op := n.op;
1892 case op{
1893 Onothing =>
1894 return b;
1895 Onot =>
1896 return bcom(n.left, !iftrue, b);
1897 Oandand =>
1898 if(!iftrue)
1899 return oror(n, iftrue, b);
1900 return andand(n, iftrue, b);
1901 Ooror =>
1902 if(!iftrue)
1903 return andand(n, iftrue, b);
1904 return oror(n, iftrue, b);
1905 Ogt or
1906 Ogeq or
1907 Oneq or
1908 Oeq or
1909 Olt or
1910 Oleq =>
1911 break;
1912 * =>
1913 if(n.ty.kind == Tint){
1914 right = mkconst(n.src, big 0);
1915 right.addable = Rconst;
1916 left = n;
1917 op = Oneq;
1918 break;
1919 }
1920 fatal("can't bcom "+nodeconv(n));
1921 return b;
1922 }
1923
1924 if(iftrue)
1925 op = oprelinvert[op];
1926
1927 if(left.addable < right.addable){
1928 t := left;
1929 left = right;
1930 right = t;
1931 op = opcommute[op];
1932 }
1933
1934 if(right.addable < Ralways){
1935 if(left.addable >= Rcant)
1936 (left, tleft) = eacom(left, nil);
1937 }else if(left.temps <= right.temps){
1938 right = ecom(right.src, tright = talloc(right.ty, nil), right);
1939 if(left.addable >= Rcant)
1940 (left, tleft) = eacom(left, nil);
1941 }else{
1942 (left, tleft) = eacom(left, nil);
1943 right = ecom(right.src, tright = talloc(right.ty, nil), right);
1944 }
1945 bb := genbra(n.src, op, left, right);
1946 bb.branch = b;
1947 tfree(tleft);
1948 tfree(tright);
1949 return bb;
1950}
1951
1952andand(n: ref Node, iftrue: int, b: ref Inst): ref Inst
1953{
1954 if(debug['b'])
1955 print("andand %s\n", nodeconv(n));
1956 b = bcom(n.left, iftrue, b);
1957 b = bcom(n.right, iftrue, b);
1958 return b;
1959}
1960
1961oror(n: ref Node, iftrue: int, b: ref Inst): ref Inst
1962{
1963 if(debug['b'])
1964 print("oror %s\n", nodeconv(n));
1965 bb := bcom(n.left, !iftrue, nil);
1966 b = bcom(n.right, iftrue, b);
1967 patch(bb, nextinst());
1968 return b;
1969}
1970
1971#
1972# generate code for a recva expression
1973# this is just a hacked up small alt
1974#
1975recvacom(src: Src, nto, n: ref Node)
1976{
1977 p: ref Inst;
1978
1979 left := n.left;
1980
1981 labs := array[1] of Label;
1982 labs[0].isptr = left.addable >= Rcant;
1983 c := ref Case;
1984 c.nlab = 1;
1985 c.nsnd = 0;
1986 c.offset = 0;
1987 c.labs = labs;
1988 talt := mktalt(c);
1989
1990 which := talloc(tint, nil);
1991 tab := talloc(talt, nil);
1992
1993 #
1994 # build the node for the address of each channel,
1995 # the values to send, and the storage for values received
1996 #
1997 off := ref znode;
1998 adr := ref znode;
1999 add := ref znode;
2000 slot := ref znode;
2001 off.op = Oconst;
2002 off.c = ref Const(big 0, 0.0); # jrf - added initialization
2003 off.ty = tint;
2004 off.addable = Rconst;
2005 adr.op = Oadr;
2006 adr.left = tab;
2007 adr.ty = tint;
2008 add.op = Oadd;
2009 add.left = adr;
2010 add.right = off;
2011 add.ty = tint;
2012 slot.op = Oind;
2013 slot.left = add;
2014 sumark(slot);
2015
2016 #
2017 # gen the channel
2018 # this sleaze is lying to the garbage collector
2019 #
2020 off.c.val = big(2*IBY2WD);
2021 if(left.addable < Rcant)
2022 genmove(src, Mas, tint, left, slot);
2023 else{
2024 slot.ty = left.ty;
2025 ecom(src, slot, left);
2026 slot.ty = nil;
2027 }
2028
2029 #
2030 # gen the value
2031 #
2032 off.c.val += big IBY2WD;
2033 p = genrawop(left.src, ILEA, nto, nil, slot);
2034 p.m.offset = nto.ty.size; # for optimizer
2035
2036 #
2037 # number of senders and receivers
2038 #
2039 off.c.val = big 0;
2040 genmove(src, Mas, tint, sumark(mkconst(src, big 0)), slot);
2041 off.c.val += big IBY2WD;
2042 genmove(src, Mas, tint, sumark(mkconst(src, big 1)), slot);
2043 off.c.val += big IBY2WD;
2044
2045 p = genrawop(src, IALT, tab, nil, which);
2046 p.m.offset = talt.size; # for optimizer
2047 tfree(which);
2048 tfree(tab);
2049}
2050
2051#
2052# generate code to duplicate an adt with pick fields
2053# this is just a hacked up small pick
2054# n is Oind(exp)
2055#
2056pickdupcom(src: Src, nto, n: ref Node)
2057{
2058 jmps: ref Inst;
2059
2060 if(n.op != Oind)
2061 fatal("pickdupcom not Oind: " + nodeconv(n));
2062
2063 t := n.ty;
2064 nlab := t.decl.tag;
2065
2066 #
2067 # generate global which has case labels
2068 #
2069 d := mkids(src, enter(".c"+string nlabel++, 0), mktype(src.start, src.stop, Tcase, nil, nil), nil);
2070 d.init = mkdeclname(src, d);
2071
2072 clab := ref znode;
2073 clab.addable = Rmreg;
2074 clab.left = nil;
2075 clab.right = nil;
2076 clab.op = Oname;
2077 clab.ty = d.ty;
2078 clab.decl = d;
2079
2080 #
2081 # generate a temp to hold the real value
2082 # then generate a case on the tag
2083 #
2084 orig := n.left;
2085 tmp := talloc(orig.ty, nil);
2086 ecom(src, tmp, orig);
2087 orig = mkunary(Oind, tmp);
2088 orig.ty = tint;
2089 sumark(orig);
2090
2091 dest := mkunary(Oind, nto);
2092 dest.ty = nto.ty.tof;
2093 sumark(dest);
2094
2095 genrawop(src, ICASE, orig, nil, clab);
2096
2097 labs := array[nlab] of Label;
2098
2099 i := 0;
2100 jmps = nil;
2101 for(tg := t.tags; tg != nil; tg = tg.next){
2102 stg := tg;
2103 for(; tg.next != nil; tg = tg.next)
2104 if(stg.ty != tg.next.ty)
2105 break;
2106 start := sumark(simplify(mkdeclname(src, stg)));
2107 stop := start;
2108 node := start;
2109 if(stg != tg){
2110 stop = sumark(simplify(mkdeclname(src, tg)));
2111 node = mkbin(Orange, start, stop);
2112 }
2113
2114 labs[i].start = start;
2115 labs[i].stop = stop;
2116 labs[i].node = node;
2117 labs[i++].inst = nextinst();
2118
2119 genrawop(src, INEW, mktn(tg.ty.tof), nil, nto);
2120 genmove(src, Mas, tg.ty.tof, orig, dest);
2121
2122 j := genrawop(src, IJMP, nil, nil, nil);
2123 j.branch = jmps;
2124 jmps = j;
2125 }
2126
2127 #
2128 # this should really be a runtime error
2129 #
2130 wild := genrawop(src, IJMP, nil, nil, nil);
2131 patch(wild, wild);
2132
2133 patch(jmps, nextinst());
2134 tfree(tmp);
2135
2136 if(i > nlab)
2137 fatal("overflowed label tab for pickdupcom");
2138
2139 c := ref Case;
2140 c.nlab = i;
2141 c.nsnd = 0;
2142 c.labs = labs;
2143 c.iwild = wild;
2144
2145 d.ty.cse = c;
2146 usetype(d.ty);
2147 installids(Dglobal, d);
2148}
2149
2150#
2151# see if name n occurs anywhere in e
2152#
2153tupaliased(n, e: ref Node): int
2154{
2155 for(;;){
2156 if(e == nil)
2157 return 0;
2158 if(e.op == Oname && e.decl == n.decl)
2159 return 1;
2160 if(tupaliased(n, e.left))
2161 return 1;
2162 e = e.right;
2163 }
2164 return 0;
2165}
2166
2167#
2168# see if any name in n occurs anywere in e
2169#
2170tupsaliased(n, e: ref Node): int
2171{
2172 for(;;){
2173 if(n == nil)
2174 return 0;
2175 if(n.op == Oname && tupaliased(n, e))
2176 return 1;
2177 if(tupsaliased(n.left, e))
2178 return 1;
2179 n = n.right;
2180 }
2181 return 0;
2182}
2183
2184#
2185# put unaddressable constants in the global data area
2186#
2187globalconst(n: ref Node): ref Decl
2188{
2189 s := enter(".i." + hex(int n.c.val, 8), 0);
2190 d := s.decl;
2191 if(d == nil){
2192 d = mkids(n.src, s, tint, nil);
2193 installids(Dglobal, d);
2194 d.init = n;
2195 d.refs++;
2196 }
2197 return d;
2198}
2199
2200globalBconst(n: ref Node): ref Decl
2201{
2202 s := enter(".B." + bhex(n.c.val, 16), 0);
2203 d := s.decl;
2204 if(d == nil){
2205 d = mkids(n.src, s, tbig, nil);
2206 installids(Dglobal, d);
2207 d.init = n;
2208 d.refs++;
2209 }
2210 return d;
2211}
2212
2213globalbconst(n: ref Node): ref Decl
2214{
2215 s := enter(".b." + hex(int n.c.val & 16rff, 2), 0);
2216 d := s.decl;
2217 if(d == nil){
2218 d = mkids(n.src, s, tbyte, nil);
2219 installids(Dglobal, d);
2220 d.init = n;
2221 d.refs++;
2222 }
2223 return d;
2224}
2225
2226globalfconst(n: ref Node): ref Decl
2227{
2228 ba := array[8] of byte;
2229 export_real(ba, array[] of {n.c.rval});
2230 fs := ".f.";
2231 for(i := 0; i < 8; i++)
2232 fs += hex(int ba[i], 2);
2233 if(fs != ".f." + bhex(math->realbits64(n.c.rval), 16))
2234 fatal("bad globalfconst number");
2235 s := enter(fs, 0);
2236 d := s.decl;
2237 if(d == nil){
2238 d = mkids(n.src, s, treal, nil);
2239 installids(Dglobal, d);
2240 d.init = n;
2241 d.refs++;
2242 }
2243 return d;
2244}
2245
2246globalsconst(n: ref Node): ref Decl
2247{
2248 s := n.decl.sym;
2249 n.decl = nil;
2250 d := s.decl;
2251 if(d == nil){
2252 d = mkids(n.src, s, tstring, nil);
2253 installids(Dglobal, d);
2254 d.init = n;
2255 }
2256 d.refs++;
2257 n.decl = d;
2258 return d;
2259}
2260
2261#
2262# make a global of type t
2263# used to make initialized data
2264#
2265globalztup(t: ref Type): ref Decl
2266{
2267 z := ".z." + string t.size + ".";
2268 desc := t.decl.desc;
2269 for(i := 0; i < desc.nmap; i++)
2270 z += hex(int desc.map[i], 2);
2271 s := enter(z, 0);
2272 d := s.decl;
2273 if(d == nil){
2274 d = mkids(t.src, s, t, nil);
2275 installids(Dglobal, d);
2276 d.init = nil;
2277 }
2278 d.refs++;
2279 return d;
2280}
2281
2282subst(d: ref Decl, e: ref Node, n: ref Node): ref Node
2283{
2284 if(n == nil)
2285 return nil;
2286 if(n.op == Oname){
2287 if(d == n.decl){
2288 n = dupn(0, nosrc, e);
2289 n.ty = d.ty;
2290 }
2291 return n;
2292 }
2293 n.left = subst(d, e, n.left);
2294 n.right = subst(d, e, n.right);
2295 return n;
2296}
2297
2298inline(n: ref Node): ref Node
2299{
2300 e, tn: ref Node;
2301 t: ref Type;
2302 d: ref Decl;
2303
2304if(debug['z']) sys->print("inline1: %s\n", nodeconv(n));
2305 if(n.left.op == Oname)
2306 d = n.left.decl;
2307 else
2308 d = n.left.right.decl;
2309 e = d.init;
2310 t = e.ty;
2311 e = dupn(1, n.src, e.right.left.left);
2312 n = n.right;
2313 for(d = t.ids; d != nil && n != nil; d = d.next){
2314 if(hasside(n.left, 0) && occurs(d, e) != 1){
2315 tn = talloc(d.ty, nil);
2316 e = mkbin(Ocomma, mkbin(Oas, tn, n.left), subst(d, tn, e));
2317 e.ty = e.right.ty;
2318 e.left.ty = d.ty;
2319 }
2320 else
2321 e = subst(d, n.left, e);
2322 n = n.right;
2323 }
2324 if(d != nil || n != nil)
2325 fatal("bad arg match in inline()");
2326if(debug['z']) sys->print("inline2: %s\n", nodeconv(e));
2327 return e;
2328}
2329
2330fpcall(src: Src, op: int, n: ref Node, ret: ref Node)
2331{
2332 tp, e, mod, ind: ref Node;
2333
2334 e = n.left.left;
2335 if(e.addable >= Rcant)
2336 (e, tp) = eacom(e, nil);
2337 mod = mkunary(Oind, e);
2338 ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, e), mkconst(src, big IBY2WD)));
2339 n.left = mkbin(Omdot, mod, ind);
2340 n.left.ty = e.ty.tof;
2341 mod.ty = ind.ty = ind.left.ty = ind.left.right.ty = tint;
2342 sumark(n);
2343 callcom(src, op, n, ret);
2344 tfree(tp);
2345}
limbo/compiler/gen.b+1011−0
@@ -0,0 +1,1011 @@
1 blocks: int; # nesting of blocks while generating code
2 zinst: Inst;
3 firstinst: ref Inst;
4 lastinst: ref Inst;
5
6include "disoptab.m";
7
8addrmode := array[int Rend] of
9{
10 int Rreg => Afp,
11 int Rmreg => Amp,
12 int Roff => Aoff,
13 int Rnoff => Anoff,
14 int Rdesc => Adesc,
15 int Rdescp => Adesc,
16 int Rconst => Aimm,
17 int Radr => Afpind,
18 int Rmadr => Ampind,
19 int Rpc => Apc,
20 int Rldt => Aldt,
21 * => Aerr,
22};
23
24wtemp: ref Decl;
25bigtemp: ref Decl;
26ntemp: int;
27retnode: ref Node;
28nilnode: ref Node;
29
30blockstack: array of int;
31blockdep: int;
32nblocks: int;
33ntoz: ref Node;
34
35#znode: Node;
36
37genstart()
38{
39 d := mkdecl(nosrc, Dlocal, tint);
40 d.sym = enter(".ret", 0);
41 d.offset = IBY2WD * REGRET;
42
43 retnode = ref znode;
44 retnode.op = Oname;
45 retnode.addable = Rreg;
46 retnode.decl = d;
47 retnode.ty = tint;
48
49 zinst.op = INOP;
50 zinst.sm = Anone;
51 zinst.dm = Anone;
52 zinst.mm = Anone;
53
54 firstinst = ref zinst;
55 lastinst = firstinst;
56
57 nilnode = ref znode;
58 nilnode.op = Oname;
59 nilnode.addable = Rmreg;
60 nilnode.decl = nildecl;
61 nilnode.ty = nildecl.ty;
62
63 blocks = -1;
64 blockdep = 0;
65 nblocks = 0;
66}
67
68#
69# manage nested control flow blocks
70#
71pushblock(): int
72{
73 if(blockdep >= len blockstack){
74 bs := array[blockdep + 32] of int;
75 bs[0:] = blockstack;
76 blockstack = bs;
77 }
78 blockstack[blockdep++] = blocks;
79 return blocks = nblocks++;
80}
81
82repushblock(b: int)
83{
84 blockstack[blockdep++] = blocks;
85 blocks = b;
86}
87
88popblock()
89{
90 blocks = blockstack[blockdep -= 1];
91}
92
93tinit()
94{
95 wtemp = nil;
96 bigtemp = nil;
97}
98
99tdecls(): ref Decl
100{
101 for(d := wtemp; d != nil; d = d.next){
102 if(d.tref != 1)
103 fatal("temporary "+d.sym.name+" has "+string(d.tref-1)+" references");
104 }
105
106 for(d = bigtemp; d != nil; d = d.next){
107 if(d.tref != 1)
108 fatal("temporary "+d.sym.name+" has "+string(d.tref-1)+" references");
109 }
110
111 return appdecls(wtemp, bigtemp);
112}
113
114talloc(t: ref Type, nok: ref Node): ref Node
115{
116 ok, d: ref Decl;
117
118 ok = nil;
119 if(nok != nil)
120 ok = nok.decl;
121 if(ok == nil || ok.tref == 0 || tattr[ok.ty.kind].isbig != tattr[t.kind].isbig || ok.ty.align != t.align)
122 ok = nil;
123 n := ref znode;
124 n.op = Oname;
125 n.addable = Rreg;
126 n.ty = t;
127 if(tattr[t.kind].isbig){
128 desc := mktdesc(t);
129 if(ok != nil && ok.desc == desc){
130 ok.tref++;
131 ok.refs++;
132 n.decl = ok;
133 return n;
134 }
135 for(d = bigtemp; d != nil; d = d.next){
136 if(d.tref == 1 && d.desc == desc && d.ty.align == t.align){
137 d.tref++;
138 d.refs++;
139 n.decl = d;
140 return n;
141 }
142 }
143 d = mkdecl(nosrc, Dlocal, t);
144 d.desc = desc;
145 d.tref = 2;
146 d.refs = 1;
147 d.sym = enter(".b"+string ntemp++, 0);
148 d.next = bigtemp;
149 bigtemp = d;
150 n.decl = d;
151 return n;
152 }
153 if(ok != nil
154 && tattr[ok.ty.kind].isptr == tattr[t.kind].isptr
155 && ok.ty.size == t.size){
156 ok.tref++;
157 n.decl = ok;
158 return n;
159 }
160 for(d = wtemp; d != nil; d = d.next){
161 if(d.tref == 1
162 && tattr[d.ty.kind].isptr == tattr[t.kind].isptr
163 && d.ty.size == t.size
164 && d.ty.align == t.align){
165 d.tref++;
166 n.decl = d;
167 return n;
168 }
169 }
170 d = mkdecl(nosrc, Dlocal, t);
171 d.tref = 2;
172 d.refs = 1;
173 d.sym = enter(".t"+string ntemp++, 0);
174 d.next = wtemp;
175 wtemp = d;
176 n.decl = d;
177 return n;
178}
179
180tfree(n: ref Node)
181{
182 if(n == nil || n.decl == nil)
183 return;
184 d := n.decl;
185 if(d.tref == 0)
186 return;
187
188 if(d.tref == 1)
189 fatal("double free of temporary " + d.sym.name);
190 if (--d.tref == 1)
191 zcom1(n, nil);
192
193 #
194 # nil out any pointers so we don't
195 # hang onto references
196 #
197#
198# costs ~7% in instruction count
199# if(d.tref != 1)
200# return;
201# if(!tattr[d.ty.kind].isbig){
202# if(tattr[d.ty.kind].isptr){ # or tmustzero()
203# nilnode.decl.refs++;
204# genmove(lastinst.src, Mas, d.ty, nilnode, n);
205# }
206# }else{
207# if(d.desc.nmap != 0){ # tmustzero() is better
208# zn := ref znode;
209# zn.op = Oname;
210# zn.addable = Rmreg;
211# zn.decl = globalztup(d.ty);
212# zn.ty = d.ty;
213# genmove(lastinst.src, Mas, d.ty, zn, n);
214# }
215# }
216}
217
218tfreelater(n: ref Node)
219{
220 if(n == nil || n.decl == nil)
221 return;
222 d := n.decl;
223 if(d.tref == 0)
224 return;
225
226 if(d.tref == 1)
227 fatal("double free of temporary " + d.sym.name);
228 if (--d.tref == 1){
229 nn := mkn(Oname, nil, nil);
230 *nn = *n;
231 nn.left = ntoz;
232 ntoz = nn;
233 d.tref++;
234 }
235}
236
237tfreenow()
238{
239 nn: ref Node;
240
241 for(n := ntoz; n != nil; n = nn){
242 nn = n.left;
243 n.left = nil;
244 if(n.decl.tref != 2)
245 fatal(sprint("bad free of temporary %s", n.decl.sym.name));
246 --n.decl.tref;
247 zcom1(n, nil);
248 }
249 ntoz = nil;
250}
251
252#
253# realloc a temporary after it's been released
254#
255tacquire(n: ref Node): ref Node
256{
257 if(n == nil || n.decl == nil)
258 return n;
259 d := n.decl;
260 if(d.tref == 0)
261 return n;
262 # if(d.tref != 1)
263 # fatal("tacquire ref != 1: "+string d.tref);
264 d.tref++;
265 return n;
266}
267
268trelease(n: ref Node)
269{
270 if(n == nil || n.decl == nil)
271 return;
272 d := n.decl;
273 if(d.tref == 0)
274 return;
275 if(d.tref == 1)
276 fatal("double release of temporary " + d.sym.name);
277 d.tref--;
278}
279
280mkinst(): ref Inst
281{
282 in := lastinst.next;
283 if(in == nil){
284 in = ref zinst;
285 lastinst.next = in;
286 }
287 lastinst = in;
288 in.block = blocks;
289 if(blocks < 0)
290 fatal("mkinst no block");
291 return in;
292}
293
294nextinst(): ref Inst
295{
296 in := lastinst.next;
297 if(in != nil)
298 return in;
299 in = ref zinst;
300 lastinst.next = in;
301 return in;
302}
303
304#
305# allocate a node for returning
306#
307retalloc(n, nn: ref Node): ref Node
308{
309 if(nn.ty == tnone)
310 return nil;
311 n = ref znode;
312 n.op = Oind;
313 n.addable = Radr;
314 n.left = dupn(1, n.src, retnode);
315 n.ty = nn.ty;
316 return n;
317}
318
319genrawop(src: Src, op: int, s, m, d: ref Node): ref Inst
320{
321 in := mkinst();
322 in.op = op;
323 in.src = src;
324 if(s != nil){
325 in.s = genaddr(s);
326 in.sm = addrmode[int s.addable];
327 }
328 if(m != nil){
329 in.m = genaddr(m);
330 in.mm = addrmode[int m.addable];
331 if(in.mm == Ampind || in.mm == Afpind)
332 fatal("illegal addressing mode in register "+nodeconv(m));
333 }
334 if(d != nil){
335 in.d = genaddr(d);
336 in.dm = addrmode[int d.addable];
337 }
338 return in;
339}
340
341genop(src: Src, op: int, s, m, d: ref Node): ref Inst
342{
343 iop := disoptab[op][opind[d.ty.kind]];
344 if(iop == 0)
345 fatal("can't deal with op "+opconv(op)+" on "+nodeconv(s)+" "+nodeconv(m)+" "+nodeconv(d)+" in genop");
346 if(iop == IMULX || iop == IDIVX)
347 return genfixop(src, iop, s, m, d);
348 in := mkinst();
349 in.op = iop;
350 in.src = src;
351 if(s != nil){
352 in.s = genaddr(s);
353 in.sm = addrmode[int s.addable];
354 }
355 if(m != nil){
356 in.m = genaddr(m);
357 in.mm = addrmode[int m.addable];
358 if(in.mm == Ampind || in.mm == Afpind)
359 fatal("illegal addressing mode in register "+nodeconv(m));
360 }
361 if(d != nil){
362 in.d = genaddr(d);
363 in.dm = addrmode[int d.addable];
364 }
365 return in;
366}
367
368genbra(src: Src, op: int, s, m: ref Node): ref Inst
369{
370 t := s.ty;
371 if(t == tany)
372 t = m.ty;
373 iop := disoptab[op][opind[t.kind]];
374 if(iop == 0)
375 fatal("can't deal with op "+opconv(op)+" on "+nodeconv(s)+" "+nodeconv(m)+" in genbra");
376 in := mkinst();
377 in.op = iop;
378 in.src = src;
379 if(s != nil){
380 in.s = genaddr(s);
381 in.sm = addrmode[int s.addable];
382 }
383 if(m != nil){
384 in.m = genaddr(m);
385 in.mm = addrmode[int m.addable];
386 if(in.mm == Ampind || in.mm == Afpind)
387 fatal("illegal addressing mode in register "+nodeconv(m));
388 }
389 return in;
390}
391
392genchan(src: Src, sz: ref Node, mt: ref Type, d: ref Node): ref Inst
393{
394 reg: Addr;
395
396 regm := Anone;
397 reg.decl = nil;
398 reg.reg = 0;
399 reg.offset = 0;
400 op := chantab[mt.kind];
401 if(op == 0)
402 fatal("can't deal with op "+string mt.kind+" in genchan");
403
404 case mt.kind{
405 Tadt or
406 Tadtpick or
407 Ttuple =>
408 td := mktdesc(mt);
409 if(td.nmap != 0){
410 op++; # sleazy
411 usedesc(td);
412 regm = Adesc;
413 reg.decl = mt.decl;
414 }else{
415 regm = Aimm;
416 reg.offset = mt.size;
417 }
418 }
419 in := mkinst();
420 in.op = op;
421 in.src = src;
422 in.s = reg;
423 in.sm = regm;
424 if(sz != nil){
425 in.m = genaddr(sz);
426 in.mm = addrmode[int sz.addable];
427 }
428 if(d != nil){
429 in.d = genaddr(d);
430 in.dm = addrmode[int d.addable];
431 }
432 return in;
433}
434
435genmove(src: Src, how: int, mt: ref Type, s, d: ref Node): ref Inst
436{
437 reg: Addr;
438
439 regm := Anone;
440 reg.decl = nil;
441 reg.reg = 0;
442 reg.offset = 0;
443 op := movetab[how][mt.kind];
444 if(op == 0)
445 fatal("can't deal with op "+string how+" on "+nodeconv(s)+" "+nodeconv(d)+" in genmove");
446
447 case mt.kind{
448 Tadt or
449 Tadtpick or
450 Ttuple or
451 Texception =>
452 if(mt.size == 0 && how == Mas)
453 return nil;
454 td := mktdesc(mt);
455 if(td.nmap != 0){
456 op++; # sleazy
457 usedesc(td);
458 regm = Adesc;
459 reg.decl = mt.decl;
460 }else{
461 regm = Aimm;
462 reg.offset = mt.size;
463 }
464 }
465 in := mkinst();
466 in.op = op;
467 in.src = src;
468 if(s != nil){
469 in.s = genaddr(s);
470 in.sm = addrmode[int s.addable];
471 }
472 in.m = reg;
473 in.mm = regm;
474 if(d != nil){
475 in.d = genaddr(d);
476 in.dm = addrmode[int d.addable];
477 }
478 if(s.addable == Rpc)
479 in.op = IMOVPC;
480 return in;
481}
482
483patch(b, dst: ref Inst)
484{
485 n: ref Inst;
486
487 for(; b != nil; b = n){
488 n = b.branch;
489 b.branch = dst;
490 }
491}
492
493getpc(i: ref Inst): int
494{
495 if(i.pc == 0 && i != firstinst && (firstinst.op != INOOP || i != firstinst.next)){
496 do
497 i = i.next;
498 while(i != nil && i.pc == 0);
499 if(i == nil || i.pc == 0)
500 fatal("bad instruction in getpc");
501 }
502 return i.pc;
503}
504
505#
506# follow all possible paths from n,
507# marking reached code, compressing branches, and reclaiming unreached insts
508#
509reach(in: ref Inst)
510{
511 foldbranch(in);
512 last := in;
513 for(in = in.next; in != nil; in = in.next){
514 if(in.reach == byte 0)
515 last.next = in.next;
516 else
517 last = in;
518 }
519 lastinst = last;
520}
521
522foldbranch(in: ref Inst)
523{
524 while(in != nil && in.reach != byte 1){
525 in.reach = byte 1;
526 if(in.branch != nil)
527 while(in.branch.op == IJMP){
528 if(in == in.branch || in.branch == in.branch.branch)
529 break;
530 in.branch = in.branch.branch;
531 }
532 case in.op{
533 IGOTO or
534 ICASE or
535 ICASEL or
536 ICASEC or
537 IEXC =>
538 foldbranch(in.d.decl.ty.cse.iwild);
539 lab := in.d.decl.ty.cse.labs;
540 n := in.d.decl.ty.cse.nlab;
541 for(i := 0; i < n; i++)
542 foldbranch(lab[i].inst);
543 if(in.op == IEXC)
544 in.op = INOOP;
545 return;
546 IEXC0 =>
547 foldbranch(in.branch);
548 in.op = INOOP;
549 break;
550 IRET or
551 IEXIT or
552 IRAISE =>
553 return;
554 IJMP =>
555 b := in.branch;
556 case b.op{
557 ICASE or
558 ICASEL or
559 ICASEC or
560 IRET or
561 IEXIT =>
562 next := in.next;
563 *in = *b;
564 in.next = next;
565 continue;
566 }
567 foldbranch(in.branch);
568 return;
569 * =>
570 if(in.branch != nil)
571 foldbranch(in.branch);
572 }
573
574 in = in.next;
575 }
576}
577
578#
579# convert the addressable node into an operand
580# see the comment for sumark
581#
582genaddr(n: ref Node): Addr
583{
584 a: Addr;
585
586 a.reg = 0;
587 a.offset = 0;
588 a.decl = nil;
589 case int n.addable{
590 int Rreg =>
591 if(n.decl != nil)
592 a.decl = n.decl;
593 else
594 a = genaddr(n.left);
595 int Rmreg =>
596 if(n.decl != nil)
597 a.decl = n.decl;
598 else
599 a = genaddr(n.left);
600 int Rdesc =>
601 a.decl = n.ty.decl;
602 int Roff or
603 int Rnoff =>
604 a.decl = n.decl;
605 int Rconst =>
606 a.offset = int n.c.val;
607 int Radr =>
608 a = genaddr(n.left);
609 int Rmadr =>
610 a = genaddr(n.left);
611 int Rareg or
612 int Ramreg =>
613 a = genaddr(n.left);
614 if(n.op == Oadd)
615 a.reg += int n.right.c.val;
616 int Raadr or
617 int Ramadr =>
618 a = genaddr(n.left);
619 if(n.op == Oadd)
620 a.offset += int n.right.c.val;
621 int Rldt =>
622 a.decl = n.decl;
623 int Rdescp or
624 int Rpc =>
625 a.decl = n.decl;
626 * =>
627 fatal("can't deal with "+nodeconv(n)+" in genaddr");
628 }
629 return a;
630}
631
632sameaddr(n, m: ref Node): int
633{
634 if(n.addable != m.addable)
635 return 0;
636 a := genaddr(n);
637 b := genaddr(m);
638 return a.offset == b.offset && a.reg == b.reg && a.decl == b.decl;
639}
640
641resolvedesc(mod: ref Decl, length: int, id: ref Decl): int
642{
643 last: ref Desc;
644
645 g := gendesc(mod, length, id);
646 g.used = 0;
647 last = nil;
648 for(d := descriptors; d != nil; d = d.next){
649 if(!d.used){
650 if(last != nil)
651 last.next = d.next;
652 else
653 descriptors = d.next;
654 continue;
655 }
656 last = d;
657 }
658
659 g.next = descriptors;
660 descriptors = g;
661
662 descid := 0;
663 for(d = descriptors; d != nil; d = d.next)
664 d.id = descid++;
665 if(g.id != 0)
666 fatal("bad global descriptor id");
667
668 return descid;
669}
670
671resolvemod(m: ref Decl): int
672{
673 for(id := m.ty.ids; id != nil; id = id.next){
674 case id.store{
675 Dfn =>
676 id.iface.pc = id.pc;
677 id.iface.desc = id.desc;
678 Dtype =>
679 if(id.ty.kind != Tadt)
680 break;
681 for(d := id.ty.ids; d != nil; d = d.next){
682 if(d.store == Dfn){
683 d.iface.pc = d.pc;
684 d.iface.desc = d.desc;
685 }
686 }
687 }
688 }
689 # for addiface
690 for(id = m.ty.tof.ids; id != nil; id = id.next){
691 if(id.store == Dfn){
692 if(id.pc == nil)
693 id.pc = id.iface.pc;
694 if(id.desc == nil)
695 id.desc = id.iface.desc;
696 }
697 }
698 return int m.ty.tof.decl.init.c.val;
699}
700
701#
702# place the Tiface decs in another list
703#
704resolveldts(d: ref Decl): (ref Decl, ref Decl)
705{
706 d1, ld1, d2, ld2, n: ref Decl;
707
708 d1 = d2 = nil;
709 ld1 = ld2 = nil;
710 for( ; d != nil; d = n){
711 n = d.next;
712 d.next = nil;
713 if(d.ty.kind == Tiface){
714 if(d2 == nil)
715 d2 = d;
716 else
717 ld2.next = d;
718 ld2 = d;
719 }
720 else{
721 if(d1 == nil)
722 d1 = d;
723 else
724 ld1.next = d;
725 ld1 = d;
726 }
727 }
728 return (d1, d2);
729}
730
731#
732# fix up all pc's
733# finalize all data offsets
734# fix up instructions with offsets too large
735#
736resolvepcs(inst: ref Inst): int
737{
738 d: ref Decl;
739
740 pc := 0;
741 for(in := inst; in != nil; in = in.next){
742 if(in.reach == byte 0 || in.op == INOP)
743 fatal("unreachable pc: "+instconv(in));
744 if(in.op == INOOP){
745 in.pc = pc;
746 continue;
747 }
748 d = in.s.decl;
749 if(d != nil){
750 if(in.sm == Adesc){
751 if(d.desc != nil)
752 in.s.offset = d.desc.id;
753 }else
754 in.s.reg += d.offset;
755 }
756 r := in.s.reg;
757 off := in.s.offset;
758 if((in.sm == Afpind || in.sm == Ampind)
759 && (r >= MaxReg || off >= MaxReg))
760 fatal("big offset in "+instconv(in));
761
762 d = in.m.decl;
763 if(d != nil){
764 if(in.mm == Adesc){
765 if(d.desc != nil)
766 in.m.offset = d.desc.id;
767 }else
768 in.m.reg += d.offset;
769 }
770 v := 0;
771 case int in.mm{
772 int Anone =>
773 break;
774 int Aimm or
775 int Apc or
776 int Adesc =>
777 v = in.m.offset;
778 int Aoff or
779 int Anoff =>
780 v = in.m.decl.iface.offset;
781 int Afp or
782 int Amp or
783 int Aldt =>
784 v = in.m.reg;
785 if(v < 0)
786 v = 16r8000;
787 * =>
788 fatal("can't deal with "+instconv(in)+"'s m mode");
789 }
790 if(v > 16r7fff || v < -16r8000){
791 case in.op{
792 IALT or
793 IINDX =>
794 rewritedestreg(in, IMOVW, RTemp);
795 * =>
796 op := IMOVW;
797 if(isbyteinst[in.op])
798 op = IMOVB;
799 in = rewritesrcreg(in, op, RTemp, pc++);
800 }
801 }
802
803 d = in.d.decl;
804 if(d != nil){
805 if(in.dm == Apc)
806 in.d.offset = d.pc.pc;
807 else
808 in.d.reg += d.offset;
809 }
810 r = in.d.reg;
811 off = in.d.offset;
812 if((in.dm == Afpind || in.dm == Ampind)
813 && (r >= MaxReg || off >= MaxReg))
814 fatal("big offset in "+instconv(in));
815
816 in.pc = pc;
817 pc++;
818 }
819 for(in = inst; in != nil; in = in.next){
820 d = in.s.decl;
821 if(d != nil && in.sm == Apc)
822 in.s.offset = d.pc.pc;
823 d = in.d.decl;
824 if(d != nil && in.dm == Apc)
825 in.d.offset = d.pc.pc;
826 if(in.branch != nil){
827 in.dm = Apc;
828 in.d.offset = in.branch.pc;
829 }
830 }
831 return pc;
832}
833
834#
835# fixp up a big register constant uses as a source
836# ugly: smashes the instruction
837#
838rewritesrcreg(in: ref Inst, op: int, treg: int, pc: int): ref Inst
839{
840 a := in.m;
841 am := in.mm;
842 in.mm = Afp;
843 in.m.reg = treg;
844 in.m.decl = nil;
845
846 new := ref *in;
847
848 *in = zinst;
849 in.src = new.src;
850 in.next = new;
851 in.op = op;
852 in.s = a;
853 in.sm = am;
854 in.dm = Afp;
855 in.d.reg = treg;
856 in.pc = pc;
857 in.reach = byte 1;
858 in.block = new.block;
859 return new;
860}
861
862#
863# fix up a big register constant by moving to the destination
864# after the instruction completes
865#
866rewritedestreg(in: ref Inst, op: int, treg: int): ref Inst
867{
868 n := ref zinst;
869 n.next = in.next;
870 in.next = n;
871 n.src = in.src;
872 n.op = op;
873 n.sm = Afp;
874 n.s.reg = treg;
875 n.d = in.m;
876 n.dm = in.mm;
877 n.reach = byte 1;
878 n.block = in.block;
879
880 in.mm = Afp;
881 in.m.reg = treg;
882 in.m.decl = nil;
883
884 return n;
885}
886
887instconv(in: ref Inst): string
888{
889 if(in.op == INOP)
890 return "nop";
891 op := "";
892 if(in.op >= 0 && in.op < 256)
893 op = instname[in.op];
894 if(op == nil)
895 op = "?"+string in.op+"?";
896 s := "\t" + op + "\t";
897 comma := "";
898 if(in.sm != Anone){
899 s += addrconv(in.sm, in.s);
900 comma = ",";
901 }
902 if(in.mm != Anone){
903 s += comma;
904 s += addrconv(in.mm, in.m);
905 comma = ",";
906 }
907 if(in.dm != Anone){
908 s += comma;
909 s += addrconv(in.dm, in.d);
910 }
911
912 if(!asmsym)
913 return s;
914
915 if(in.s.decl != nil && in.sm == Adesc){
916 s += "\t#";
917 s += dotconv(in.s.decl);
918 }
919 if(0 && in.m.decl != nil){
920 s += "\t#";
921 s += dotconv(in.m.decl);
922 }
923 if(in.d.decl != nil && in.dm == Apc){
924 s += "\t#";
925 s += dotconv(in.d.decl);
926 }
927 s += "\t#";
928 s += srcconv(in.src);
929 return s;
930}
931
932addrconv(am: byte, a: Addr): string
933{
934 s := "";
935 case int am{
936 int Anone =>
937 break;
938 int Aimm or
939 int Apc or
940 int Adesc =>
941 s = "$" + string a.offset;
942 int Aoff =>
943 s = "$" + string a.decl.iface.offset;
944 int Anoff =>
945 s = "-$" + string a.decl.iface.offset;
946 int Afp =>
947 s = string a.reg + "(fp)";
948 int Afpind =>
949 s = string a.offset + "(" + string a.reg + "(fp))";
950 int Amp =>
951 s = string a.reg + "(mp)";
952 int Ampind =>
953 s = string a.offset + "(" + string a.reg + "(mp))";
954 int Aldt =>
955 s = "$" + string a.reg;
956 * =>
957 s = string a.offset + "(" + string a.reg + "(?" + string am + "?))";
958 }
959 return s;
960}
961
962genstore(src: Src, n: ref Node, offset: int)
963{
964 de := mkdecl(nosrc, Dlocal, tint);
965 de.sym = nil;
966 de.offset = offset;
967
968 d := ref znode;
969 d.op = Oname;
970 d.addable = Rreg;
971 d.decl = de;
972 d.ty = tint;
973 genrawop(src, IMOVW, n, nil, d);
974}
975
976genfixop(src: Src, op: int, s, m, d: ref Node): ref Inst
977{
978 p, a: int;
979 mm: ref Node;
980
981 if(m == nil)
982 mm = d;
983 else
984 mm = m;
985 (op, p, a) = fixop(op, mm.ty, s.ty, d.ty);
986 if(op == IMOVW){ # just zero d
987 s = sumark(mkconst(src, big 0));
988 return genrawop(src, op, s, nil, d);
989 }
990 if(op != IMULX && op != IDIVX)
991 genstore(src, sumark(mkconst(src, big a)), STemp);
992 genstore(src, sumark(mkconst(src, big p)), DTemp);
993 i := genrawop(src, op, s, m, d);
994 return i;
995}
996
997genfixcastop(src: Src, op: int, s, d: ref Node): ref Inst
998{
999 p, a: int;
1000 m: ref Node;
1001
1002 (op, p, a) = fixop(op, s.ty, tint, d.ty);
1003 if(op == IMOVW){ # just zero d
1004 s = sumark(mkconst(src, big 0));
1005 return genrawop(src, op, s, nil, d);
1006 }
1007 m = sumark(mkconst(src, big p));
1008 if(op != ICVTXX)
1009 genstore(src, sumark(mkconst(src, big a)), STemp);
1010 return genrawop(src, op, s, m, d);
1011}
limbo/compiler/isa.m+247−0
@@ -0,0 +1,247 @@
1#
2# VM instruction set
3#
4 INOP,
5 IALT,
6 INBALT,
7 IGOTO,
8 ICALL,
9 IFRAME,
10 ISPAWN,
11 IRUNT,
12 ILOAD,
13 IMCALL,
14 IMSPAWN,
15 IMFRAME,
16 IRET,
17 IJMP,
18 ICASE,
19 IEXIT,
20 INEW,
21 INEWA,
22 INEWCB,
23 INEWCW,
24 INEWCF,
25 INEWCP,
26 INEWCM,
27 INEWCMP,
28 ISEND,
29 IRECV,
30 ICONSB,
31 ICONSW,
32 ICONSP,
33 ICONSF,
34 ICONSM,
35 ICONSMP,
36 IHEADB,
37 IHEADW,
38 IHEADP,
39 IHEADF,
40 IHEADM,
41 IHEADMP,
42 ITAIL,
43 ILEA,
44 IINDX,
45 IMOVP,
46 IMOVM,
47 IMOVMP,
48 IMOVB,
49 IMOVW,
50 IMOVF,
51 ICVTBW,
52 ICVTWB,
53 ICVTFW,
54 ICVTWF,
55 ICVTCA,
56 ICVTAC,
57 ICVTWC,
58 ICVTCW,
59 ICVTFC,
60 ICVTCF,
61 IADDB,
62 IADDW,
63 IADDF,
64 ISUBB,
65 ISUBW,
66 ISUBF,
67 IMULB,
68 IMULW,
69 IMULF,
70 IDIVB,
71 IDIVW,
72 IDIVF,
73 IMODW,
74 IMODB,
75 IANDB,
76 IANDW,
77 IORB,
78 IORW,
79 IXORB,
80 IXORW,
81 ISHLB,
82 ISHLW,
83 ISHRB,
84 ISHRW,
85 IINSC,
86 IINDC,
87 IADDC,
88 ILENC,
89 ILENA,
90 ILENL,
91 IBEQB,
92 IBNEB,
93 IBLTB,
94 IBLEB,
95 IBGTB,
96 IBGEB,
97 IBEQW,
98 IBNEW,
99 IBLTW,
100 IBLEW,
101 IBGTW,
102 IBGEW,
103 IBEQF,
104 IBNEF,
105 IBLTF,
106 IBLEF,
107 IBGTF,
108 IBGEF,
109 IBEQC,
110 IBNEC,
111 IBLTC,
112 IBLEC,
113 IBGTC,
114 IBGEC,
115 ISLICEA,
116 ISLICELA,
117 ISLICEC,
118 IINDW,
119 IINDF,
120 IINDB,
121 INEGF,
122 IMOVL,
123 IADDL,
124 ISUBL,
125 IDIVL,
126 IMODL,
127 IMULL,
128 IANDL,
129 IORL,
130 IXORL,
131 ISHLL,
132 ISHRL,
133 IBNEL,
134 IBLTL,
135 IBLEL,
136 IBGTL,
137 IBGEL,
138 IBEQL,
139 ICVTLF,
140 ICVTFL,
141 ICVTLW,
142 ICVTWL,
143 ICVTLC,
144 ICVTCL,
145 IHEADL,
146 ICONSL,
147 INEWCL,
148 ICASEC,
149 IINDL,
150 IMOVPC,
151 ITCMP,
152 IMNEWZ,
153 ICVTRF,
154 ICVTFR,
155 ICVTWS,
156 ICVTSW,
157 ILSRW,
158 ILSRL,
159 IECLR,
160 INEWZ,
161 INEWAZ,
162 IRAISE,
163 ICASEL,
164 IMULX,
165 IDIVX,
166 ICVTXX,
167 IMULX0,
168 IDIVX0,
169 ICVTXX0,
170 IMULX1,
171 IDIVX1,
172 ICVTXX1,
173 ICVTFX,
174 ICVTXF,
175 IEXPW,
176 IEXPL,
177 IEXPF,
178 ISELF,
179 # add new operators here
180 MAXDIS: con iota;
181
182XMAGIC: con 819248; # Normal magic
183SMAGIC: con 923426; # Signed module
184
185AMP: con 16r00; # Src/Dst op addressing
186AFP: con 16r01;
187AIMM: con 16r2;
188AXXX: con 16r03;
189AIND: con 16r04;
190AMASK: con 16r07;
191AOFF: con 16r08;
192AVAL: con 16r10;
193
194ARM: con 16rC0; # Middle op addressing
195AXNON: con 16r00;
196AXIMM: con 16r40;
197AXINF: con 16r80;
198AXINM: con 16rC0;
199
200DEFZ: con 0;
201DEFB: con 1; # Byte
202DEFW: con 2; # Word
203DEFS: con 3; # Utf-string
204DEFF: con 4; # Real value
205DEFA: con 5; # Array
206DIND: con 6; # Set index
207DAPOP: con 7; # Restore address register
208DEFL: con 8; # BIG
209
210DADEPTH: con 4; # Array address stack size
211
212REGLINK: con 0;
213REGFRAME: con 1;
214REGMOD: con 2;
215REGTYP: con 3;
216REGRET: con 4;
217NREG: con 5;
218
219IBY2WD: con 4;
220IBY2FT: con 8;
221IBY2LG: con 8;
222
223MUSTCOMPILE: con 1<<0;
224DONTCOMPILE: con 1<<1;
225SHAREMP: con 1<<2;
226DYNMOD: con 1<<3;
227HASLDT0: con 1<<4;
228HASEXCEPT: con 1<<5;
229HASLDT: con 1<<6;
230
231DMAX: con 1 << 4;
232
233#define DTYPE(x) (x>>4)
234#define DBYTE(x, l) ((x<<4)|l)
235#define DMAX (1<<4)
236#define DLEN(x) (x& (DMAX-1))
237
238DBYTE: con 4;
239SRC: con 3;
240DST: con 0;
241
242#define SRC(x) ((x)<<3)
243#define DST(x) ((x)<<0)
244#define USRC(x) (((x)>>3)&AMASK)
245#define UDST(x) ((x)&AMASK)
246#define UXSRC(x) ((x)&(AMASK<<3))
247#define UXDST(x) ((x)&(AMASK<<0))
limbo/compiler/lex.b+1178−0
@@ -0,0 +1,1178 @@
1Leof: con -1;
2Linestart: con 0;
3
4Mlower,
5Mupper,
6Munder,
7Mdigit,
8Msign,
9Mexp,
10Mhex,
11Mradix: con byte 1 << iota;
12Malpha: con Mupper|Mlower|Munder;
13
14HashSize: con 1024;
15
16Keywd: adt
17{
18 name: string;
19 token: int;
20};
21
22#
23# internals
24#
25savec: int;
26files: array of ref File; # files making up the module, sorted by absolute line
27nfiles: int;
28lastfile := 0; # index of last file looked up
29incpath := array[MaxIncPath] of string;
30symbols := array[HashSize] of ref Sym;
31strings := array[HashSize] of ref Sym;
32map := array[256] of byte;
33bins := array [MaxInclude] of ref Iobuf;
34bin: ref Iobuf;
35linestack := array[MaxInclude] of (int, int);
36lineno: int;
37linepos: int;
38bstack: int;
39lasttok: int;
40lastyylval: YYSTYPE;
41dowarn: int;
42maxerr: int;
43dosym: int;
44toterrors: int;
45fabort: int;
46srcdir: string;
47outfile: string;
48stderr: ref Sys->FD;
49dontinline: int;
50
51escmap := array[256] of
52{
53 '\'' => '\'',
54 '"' => '"',
55 '\\' => '\\',
56 'a' => '\a',
57 'b' => '\b',
58 'f' => '\f',
59 'n' => '\n',
60 'r' => '\r',
61 't' => '\t',
62 'v' => '\v',
63 '0' => '\u0000',
64
65 * => -1
66};
67unescmap := array[256] of
68{
69 '\'' => '\'',
70 '"' => '"',
71 '\\' => '\\',
72 '\a' => 'a',
73 '\b' => 'b',
74 '\f' => 'f',
75 '\n' => 'n',
76 '\r' => 'r',
77 '\t' => 't',
78 '\v' => 'v',
79 '\u0000' => '0',
80
81 * => 0
82};
83
84keywords := array [] of
85{
86 Keywd("adt", Ladt),
87 Keywd("alt", Lalt),
88 Keywd("array", Larray),
89 Keywd("big", Ltid),
90 Keywd("break", Lbreak),
91 Keywd("byte", Ltid),
92 Keywd("case", Lcase),
93 Keywd("chan", Lchan),
94 Keywd("con", Lcon),
95 Keywd("continue", Lcont),
96 Keywd("cyclic", Lcyclic),
97 Keywd("do", Ldo),
98 Keywd("dynamic", Ldynamic),
99 Keywd("else", Lelse),
100 Keywd("exception", Lexcept),
101 Keywd("exit", Lexit),
102 Keywd("fixed", Lfix),
103 Keywd("fn", Lfn),
104 Keywd("for", Lfor),
105 Keywd("hd", Lhd),
106 Keywd("if", Lif),
107 Keywd("implement", Limplement),
108 Keywd("import", Limport),
109 Keywd("include", Linclude),
110 Keywd("int", Ltid),
111 Keywd("len", Llen),
112 Keywd("list", Llist),
113 Keywd("load", Lload),
114 Keywd("module", Lmodule),
115 Keywd("nil", Lnil),
116 Keywd("of", Lof),
117 Keywd("or", Lor),
118 Keywd("pick", Lpick),
119 Keywd("raise", Lraise),
120 Keywd("raises", Lraises),
121 Keywd("real", Ltid),
122 Keywd("ref", Lref),
123 Keywd("return", Lreturn),
124 Keywd("self", Lself),
125 Keywd("spawn", Lspawn),
126 Keywd("string", Ltid),
127 Keywd("tagof", Ltagof),
128 Keywd("tl", Ltl),
129 Keywd("to", Lto),
130 Keywd("type", Ltype),
131 Keywd("while", Lwhile),
132};
133
134tokwords := array[] of
135{
136 Keywd("&=", Landeq),
137 Keywd("|=", Loreq),
138 Keywd("^=", Lxoreq),
139 Keywd("<<=", Llsheq),
140 Keywd(">>=", Lrsheq),
141 Keywd("+=", Laddeq),
142 Keywd("-=", Lsubeq),
143 Keywd("*=", Lmuleq),
144 Keywd("/=", Ldiveq),
145 Keywd("%=", Lmodeq),
146 Keywd("**=", Lexpeq),
147 Keywd(":=", Ldeclas),
148 Keywd("||", Loror),
149 Keywd("&&", Landand),
150 Keywd("::", Lcons),
151 Keywd("==", Leq),
152 Keywd("!=", Lneq),
153 Keywd("<=", Lleq),
154 Keywd(">=", Lgeq),
155 Keywd("<<", Llsh),
156 Keywd(">>", Lrsh),
157 Keywd("<-", Lcomm),
158 Keywd("++", Linc),
159 Keywd("--", Ldec),
160 Keywd("->", Lmdot),
161 Keywd("=>", Llabs),
162 Keywd("**", Lexp),
163 Keywd("EOF", Leof),
164};
165
166lexinit()
167{
168 for(i := 0; i < 256; i++){
169 map[i] = byte 0;
170 if(i == '_' || i > 16ra0)
171 map[i] |= Munder;
172 if(i >= 'A' && i <= 'Z')
173 map[i] |= Mupper;
174 if(i >= 'a' && i <= 'z')
175 map[i] |= Mlower;
176 if(i >= 'A' && i <= 'F' || i >= 'a' && i <= 'f')
177 map[i] |= Mhex;
178 if(i == 'e' || i == 'E')
179 map[i] |= Mexp;
180 if(i == 'r' || i == 'R')
181 map[i] |= Mradix;
182 if(i == '-' || i == '+')
183 map[i] |= Msign;
184 if(i >= '0' && i <= '9')
185 map[i] |= Mdigit;
186 }
187
188 for(i = 0; i < len keywords; i++)
189 enter(keywords[i].name, keywords[i].token);
190}
191
192cmap(c: int): byte
193{
194 if(c<0)
195 return byte 0;
196 if(c<256)
197 return map[c];
198 return Mlower;
199}
200
201lexstart(in: string)
202{
203 savec = 0;
204 bstack = 0;
205 nfiles = 0;
206 addfile(ref File(in, 1, 0, -1, nil, 0, -1));
207 bin = bins[bstack];
208 lineno = 1;
209 linepos = Linestart;
210
211 (srcdir, nil) = str->splitr(in, "/");
212}
213
214getc(): int
215{
216 if(c := savec){
217 if(savec >= 0){
218 linepos++;
219 savec = 0;
220 }
221 return c;
222 }
223 c = bin.getc();
224 if(c < 0){
225 savec = -1;
226 return savec;
227 }
228 linepos++;
229 return c;
230}
231
232#
233# dumps '\u0000' chararcters
234#
235ungetc(c: int)
236{
237 if(c > 0)
238 linepos--;
239 savec = c;
240}
241
242addinclude(s: string)
243{
244 for(i := 0; i < MaxIncPath; i++){
245 if(incpath[i] == nil){
246 incpath[i] = s;
247 return;
248 }
249 }
250 fatal("out of include path space");
251}
252
253addfile(f: ref File): int
254{
255 if(lastfile >= nfiles)
256 lastfile = 0;
257 if(nfiles >= len files){
258 nf := array[nfiles+32] of ref File;
259 nf[0:] = files;
260 files = nf;
261 }
262 files[nfiles] = f;
263 return nfiles++;
264}
265
266#
267# include a new file
268#
269includef(file: ref Sym)
270{
271 linestack[bstack] = (lineno, linepos);
272 bstack++;
273 if(bstack >= MaxInclude)
274 fatal(lineconv(lineno<<PosBits)+": include file depth too great");
275 buf := file.name;
276 if(buf[0] != '/')
277 buf = srcdir+buf;
278 b := bufio->open(buf, Bufio->OREAD);
279 for(i := 0; b == nil && i < MaxIncPath && incpath[i] != nil && file.name[0] != '/'; i++){
280 buf = incpath[i] + "/" + file.name;
281 b = bufio->open(buf, Bufio->OREAD);
282 }
283 bins[bstack] = b;
284 if(bins[bstack] == nil){
285 yyerror("can't include "+file.name+": "+sprint("%r"));
286 bstack--;
287 }else{
288 addfile(ref File(buf, lineno+1, -lineno, lineno, nil, 0, -1));
289 lineno++;
290 linepos = Linestart;
291 }
292 bin = bins[bstack];
293}
294
295#
296# we hit eof in the current file
297# revert to the file which included it.
298#
299popinclude()
300{
301 savec = 0;
302 bstack--;
303 bin = bins[bstack];
304 (oline, opos) := linestack[bstack];
305 (f, ln) := fline(oline);
306 lineno++;
307 linepos = opos;
308 addfile(ref File(f.name, lineno, ln-lineno, f.in, f.act, f.actoff, -1));
309}
310
311#
312# convert an absolute Line into a file and line within the file
313#
314fline(absline: int): (ref File, int)
315{
316 if(absline < files[lastfile].abs
317 || lastfile+1 < nfiles && absline >= files[lastfile+1].abs){
318 lastfile = 0;
319 l := 0;
320 r := nfiles - 1;
321 while(l <= r){
322 m := (r + l) / 2;
323 s := files[m].abs;
324 if(s <= absline){
325 l = m + 1;
326 lastfile = m;
327 }else
328 r = m - 1;
329 }
330 }
331 return (files[lastfile], absline + files[lastfile].off);
332}
333
334#
335# read a comment; process #line file renamings
336#
337lexcom(): int
338{
339 i := 0;
340 buf := "";
341 while((c := getc()) != '\n'){
342 if(c == Bufio->EOF)
343 return -1;
344 buf[i++] = c;
345 }
346
347 lineno++;
348 linepos = Linestart;
349
350 if(len buf < 6
351 || buf[len buf - 1] != '"'
352 || buf[:5] != "line " && buf[:5] != "line\t")
353 return 0;
354 for(s := 5; buf[s] == ' ' || buf[s] == '\t'; s++)
355 ;
356 if((cmap(buf[s]) & Mdigit) == byte 0)
357 return 0;
358 n := 0;
359 for(; (cmap(c = buf[s]) & Mdigit) != byte 0; s++)
360 n = n * 10 + c - '0';
361 for(; buf[s] == ' ' || buf[s] == '\t'; s++)
362 ;
363 if(buf[s++] != '"')
364 return 0;
365 buf = buf[s:len buf - 1];
366 f := files[nfiles - 1];
367 if(n == f.off+lineno && buf == f.name)
368 return 1;
369 act := f.name;
370 actline := lineno + f.off;
371 if(f.act != nil){
372 actline += f.actoff;
373 act = f.act;
374 }
375 addfile(ref File(buf, lineno, n-lineno, f.in, act, actline - n, -1));
376
377 return 1;
378}
379
380curline(): Line
381{
382 return (lineno << PosBits) | (linepos & PosMask);
383}
384
385lineconv(line: Line): string
386{
387 line >>= PosBits;
388 if(line < 0)
389 return "<noline>";
390 (f, ln) := fline(line);
391 s := "";
392 if(f.in >= 0){
393 s = ": " + lineconv(f.in << PosBits);
394 }
395 if(f.act != nil)
396 s = " [ " + f.act + ":" + string(f.actoff+ln) + " ]" + s;
397 return f.name + ":" + string ln + s;
398}
399
400posconv(s: Line): string
401{
402 if(s < 0)
403 return "nopos";
404 spos := s & PosMask;
405 s >>= PosBits;
406 (f, ln) := fline(s);
407 return f.name + ":" + string ln + "." + string spos;
408}
409
410srcconv(src: Src): string
411{
412 s := posconv(src.start);
413 s[len s] = ',';
414 s += posconv(src.stop);
415 return s;
416}
417
418lexid(c: int): int
419{
420 id := "";
421 i := 0;
422 for(;;){
423 if(i < StrSize)
424 id[i++] = c;
425 c = getc();
426 if(c == Bufio->EOF
427 || (cmap(c) & (Malpha|Mdigit)) == byte 0){
428 ungetc(c);
429 break;
430 }
431 }
432 sym := enter(id, Lid);
433 t := sym.token;
434 if(t == Lid || t == Ltid)
435 yyctxt.lval.tok.v.idval = sym;
436 return t;
437}
438
439maxfast := array[37] of
440{
441 2 => 31,
442 4 => 15,
443 8 => 10,
444 10 => 9,
445 16 => 7,
446 32 => 6,
447 * => 0,
448};
449
450strtoi(t: string, bbase: big): big
451{
452 #
453 # do the first part in ints
454 #
455 v := 0;
456 bv: big;
457 base := int bbase;
458 n := maxfast[base];
459
460 neg := 0;
461 i := 0;
462 if(i < len t && t[i] == '-'){
463 neg = 1;
464 i++;
465 }else if(i < len t && t[i] == '+')
466 i++;
467
468 for(; i < len t; i++){
469 c := t[i];
470 if(c >= '0' && c <= '9')
471 c -= '0';
472 else if(c >= 'a' && c <= 'z')
473 c -= 'a' - 10;
474 else
475 c -= 'A' - 10;
476 if(c >= base){
477 yyerror("digit '"+t[i:i+1]+"' is not radix "+string base);
478 return big -1;
479 }
480 if(i < n)
481 v = v * base + c;
482 else{
483 if(i == n)
484 bv = big v;
485 bv = bv * bbase + big c;
486 }
487 }
488 if(i <= n)
489 bv = big v;
490 if(neg)
491 return -bv;
492 return bv;
493}
494
495digit(c: int, base: int): int
496{
497 ck: byte;
498 cc: int;
499
500 cc = c;
501 ck = cmap(c);
502 if((ck & Mdigit) != byte 0)
503 c -= '0';
504 else if((ck & Mlower) != byte 0)
505 c = c - 'a' + 10;
506 else if((ck & Mupper) != byte 0)
507 c = c - 'A' + 10;
508 else if((ck & Munder) != byte 0)
509 ;
510 else
511 return -1;
512 if(c >= base){
513 s := "z";
514 s[0] = cc;
515 yyerror("digit '" + s + "' not radix " + string base);
516 }
517 return c;
518}
519
520strtodb(t: string, base: int): real
521{
522 num, dem, rbase: real;
523 neg, eneg, dig, exp, c, d: int;
524
525 t[len t] = 0;
526
527 num = 0.0;
528 rbase = real base;
529 neg = 0;
530 dig = 0;
531 exp = 0;
532 eneg = 0;
533
534 i := 0;
535 c = t[i++];
536 if(c == '-' || c == '+'){
537 if(c == '-')
538 neg = 1;
539 c = t[i++];
540 }
541 while((d = digit(c, base)) >= 0){
542 num = num*rbase + real d;
543 c = t[i++];
544 }
545 if(c == '.')
546 c = t[i++];
547 while((d = digit(c, base)) >= 0){
548 num = num*rbase + real d;
549 dig++;
550 c = t[i++];
551 }
552 if(c == 'e' || c == 'E'){
553 c = t[i++];
554 if(c == '-' || c == '+'){
555 if(c == '-'){
556 dig = -dig;
557 eneg = 1;
558 }
559 c = t[i++];
560 }
561 while((d = digit(c, base)) >= 0){
562 exp = exp*base + d;
563 c = t[i++];
564 }
565 }
566 exp -= dig;
567 if(exp < 0){
568 exp = -exp;
569 eneg = !eneg;
570 }
571 dem = rpow(rbase, exp);
572 if(eneg)
573 num /= dem;
574 else
575 num *= dem;
576 if(neg)
577 return -num;
578 return num;
579}
580
581#
582# parse a numeric identifier
583# format [0-9]+(r[0-9A-Za-z]+)?
584# or ([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)?
585#
586lexnum(c: int): int
587{
588 Int, Radix, RadixSeen, Frac, ExpSeen, ExpSignSeen, Exp, FracB: con iota;
589
590 i := 0;
591 buf := "";
592 buf[i++] = c;
593 state := Int;
594 if(c == '.')
595 state = Frac;
596 radix := "";
597
598done: for(;;){
599 c = getc();
600 if(c == Bufio->EOF){
601 yyerror("end of file in numeric constant");
602 return Leof;
603 }
604
605 ck := cmap(c);
606 case state{
607 Int =>
608 if((ck & Mdigit) != byte 0)
609 break;
610 if((ck & Mexp) != byte 0){
611 state = ExpSeen;
612 break;
613 }
614 if((ck & Mradix) != byte 0){
615 radix = buf;
616 buf = "";
617 i = 0;
618 state = RadixSeen;
619 break;
620 }
621 if(c == '.'){
622 state = Frac;
623 break;
624 }
625 break done;
626 RadixSeen or
627 Radix =>
628 if((ck & (Mdigit|Malpha)) != byte 0){
629 state = Radix;
630 break;
631 }
632 if(c == '.'){
633 state = FracB;
634 break;
635 }
636 break done;
637 Frac =>
638 if((ck & Mdigit) != byte 0)
639 break;
640 if((ck & Mexp) != byte 0)
641 state = ExpSeen;
642 else
643 break done;
644 FracB =>
645 if((ck & (Mdigit|Malpha)) != byte 0)
646 break;
647 break done;
648 ExpSeen =>
649 if((ck & Msign) != byte 0){
650 state = ExpSignSeen;
651 break;
652 }
653 if((ck & Mdigit) != byte 0){
654 state = Exp;
655 break;
656 }
657 break done;
658 ExpSignSeen or
659 Exp =>
660 if((ck & Mdigit) != byte 0){
661 state = Exp;
662 break;
663 }
664 break done;
665 }
666 buf[i++] = c;
667 }
668
669 ungetc(c);
670 v: big;
671 case state{
672 * =>
673 yyerror("malformed numerical constant '"+radix+buf+"'");
674 yyctxt.lval.tok.v.ival = big 0;
675 return Lconst;
676 Radix =>
677 v = strtoi(radix, big 10);
678 if(v < big 2 || v > big 36){
679 yyerror("radix '"+radix+"' is not between 2 and 36");
680 break;
681 }
682 v = strtoi(buf[1:], v);
683 Int =>
684 v = strtoi(buf, big 10);
685 Frac or
686 Exp =>
687 yyctxt.lval.tok.v.rval = real buf;
688 return Lrconst;
689 FracB =>
690 v = strtoi(radix, big 10);
691 if(v < big 2 || v > big 36){
692 yyerror("radix '"+radix+"' is not between 2 and 36");
693 break;
694 }
695 yyctxt.lval.tok.v.rval = strtodb(buf[1:], int v);
696 return Lrconst;
697 }
698 yyctxt.lval.tok.v.ival = v;
699 return Lconst;
700}
701
702escchar(): int
703{
704 c := getc();
705 if(c == Bufio->EOF)
706 return Bufio->EOF;
707 if(c == 'u'){
708 v := 0;
709 for(i := 0; i < 4; i++){
710 c = getc();
711 ck := cmap(c);
712 if(c == Bufio->EOF || (ck & (Mdigit|Mhex)) == byte 0){
713 yyerror("malformed \\u escape sequence");
714 ungetc(c);
715 break;
716 }
717 if((ck & Mdigit) != byte 0)
718 c -= '0';
719 else if((ck & Mlower) != byte 0)
720 c = c - 'a' + 10;
721 else if((ck & Mupper) != byte 0)
722 c = c - 'A' + 10;
723 v = v * 16 + c;
724 }
725 return v;
726 }
727 if(c < len escmap && (v := escmap[c]) >= 0)
728 return v;
729 s := "";
730 s[0] = c;
731 yyerror("unrecognized escape \\"+s);
732 return c;
733}
734
735lexstring()
736{
737 s := "";
738 i := 0;
739Loop:
740 for(;;){
741 case c := getc(){
742 '\\' =>
743 c = escchar();
744 if(c != Bufio->EOF)
745 s[i++] = c;
746 Bufio->EOF =>
747 yyerror("end of file in string constant");
748 break Loop;
749 '\n' =>
750 yyerror("newline in string constant");
751 lineno++;
752 linepos = Linestart;
753 break Loop;
754 '"' =>
755 break Loop;
756 * =>
757 s[i++] = c;
758 }
759 }
760 yyctxt.lval.tok.v.idval = enterstring(s);
761}
762
763lexrawstring()
764{
765 s := "";
766 i := 0;
767 startlno := lineno;
768Loop:
769 for(;;){
770 case c := getc(){
771 Bufio->EOF =>
772 t := lineno;
773 lineno = startlno;
774 yyerror("end of file in raw string constant");
775 lineno = t;
776 break Loop;
777 '\n' =>
778 s[i++] = c;
779 lineno++;
780 linepos = Linestart;
781 '`' =>
782 break Loop;
783 * =>
784 s[i++] = c;
785 }
786 }
787 yyctxt.lval.tok.v.idval = enterstring(s);
788}
789
790lex(): int
791{
792 for(;;){
793 yyctxt.lval.tok.src.start = (lineno << PosBits) | (linepos & PosMask);
794 case c := getc(){
795 Bufio->EOF =>
796 bin.close();
797 if(bstack == 0)
798 return Leof;
799 popinclude();
800 '#' =>
801 if(lexcom() < 0){
802 bin.close();
803 if(bstack == 0)
804 return Leof;
805 popinclude();
806 }
807 '\n' =>
808 lineno++;
809 linepos = Linestart;
810 ' ' or
811 '\t' or
812 '\r' or
813 '\v' =>
814 ;
815 '"' =>
816 lexstring();
817 return Lsconst;
818 '`' =>
819 lexrawstring();
820 return Lsconst;
821 '\'' =>
822 c = getc();
823 if(c == '\\')
824 c = escchar();
825 if(c == Bufio->EOF){
826 yyerror("end of file in character constant");
827 return Bufio->EOF;
828 }else
829 yyctxt.lval.tok.v.ival = big c;
830 c = getc();
831 if(c != '\''){
832 yyerror("missing closing '");
833 ungetc(c);
834 }
835 return Lconst;
836 '(' or
837 ')' or
838 '[' or
839 ']' or
840 '{' or
841 '}' or
842 ',' or
843 ';' or
844 '~' =>
845 return c;
846 ':' =>
847 c = getc();
848 if(c == ':')
849 return Lcons;
850 if(c == '=')
851 return Ldeclas;
852 ungetc(c);
853 return ':';
854 '.' =>
855 c = getc();
856 ungetc(c);
857 if(c != Bufio->EOF && (cmap(c) & Mdigit) != byte 0)
858 return lexnum('.');
859 return '.';
860 '|' =>
861 c = getc();
862 if(c == '=')
863 return Loreq;
864 if(c == '|')
865 return Loror;
866 ungetc(c);
867 return '|';
868 '&' =>
869 c = getc();
870 if(c == '=')
871 return Landeq;
872 if(c == '&')
873 return Landand;
874 ungetc(c);
875 return '&';
876 '^' =>
877 c = getc();
878 if(c == '=')
879 return Lxoreq;
880 ungetc(c);
881 return '^';
882 '*' =>
883 c = getc();
884 if(c == '=')
885 return Lmuleq;
886 if(c == '*'){
887 c = getc();
888 if(c == '=')
889 return Lexpeq;
890 ungetc(c);
891 return Lexp;
892 }
893 ungetc(c);
894 return '*';
895 '/' =>
896 c = getc();
897 if(c == '=')
898 return Ldiveq;
899 ungetc(c);
900 return '/';
901 '%' =>
902 c = getc();
903 if(c == '=')
904 return Lmodeq;
905 ungetc(c);
906 return '%';
907 '=' =>
908 c = getc();
909 if(c == '=')
910 return Leq;
911 if(c == '>')
912 return Llabs;
913 ungetc(c);
914 return '=';
915 '!' =>
916 c = getc();
917 if(c == '=')
918 return Lneq;
919 ungetc(c);
920 return '!';
921 '>' =>
922 c = getc();
923 if(c == '=')
924 return Lgeq;
925 if(c == '>'){
926 c = getc();
927 if(c == '=')
928 return Lrsheq;
929 ungetc(c);
930 return Lrsh;
931 }
932 ungetc(c);
933 return '>';
934 '<' =>
935 c = getc();
936 if(c == '=')
937 return Lleq;
938 if(c == '-')
939 return Lcomm;
940 if(c == '<'){
941 c = getc();
942 if(c == '=')
943 return Llsheq;
944 ungetc(c);
945 return Llsh;
946 }
947 ungetc(c);
948 return '<';
949 '+' =>
950 c = getc();
951 if(c == '=')
952 return Laddeq;
953 if(c == '+')
954 return Linc;
955 ungetc(c);
956 return '+';
957 '-' =>
958 c = getc();
959 if(c == '=')
960 return Lsubeq;
961 if(c == '-')
962 return Ldec;
963 if(c == '>')
964 return Lmdot;
965 ungetc(c);
966 return '-';
967 '0' to '9' =>
968 return lexnum(c);
969 * =>
970 if((cmap(c) & Malpha) != byte 0)
971 return lexid(c);
972 s := "";
973 s[0] = c;
974 yyerror("unknown character '"+s+"'");
975 }
976 }
977}
978
979YYLEX.lex(nil: self ref YYLEX): int
980{
981 t := lex();
982 yyctxt.lval.tok.src.stop = (lineno << PosBits) | (linepos & PosMask);
983 lasttok = t;
984 lastyylval = yyctxt.lval;
985 return t;
986}
987
988toksp(t: int): string
989{
990 case(t){
991 Lconst =>
992 return sprint("%bd", lastyylval.tok.v.ival);
993 Lrconst =>
994 return sprint("%f", lastyylval.tok.v.rval);
995 Lsconst =>
996 return sprint("\"%s\"", lastyylval.tok.v.idval.name);
997 Ltid or Lid =>
998 return lastyylval.tok.v.idval.name;
999 }
1000 for(i := 0; i < len keywords; i++)
1001 if(t == keywords[i].token)
1002 return keywords[i].name;
1003 for(i = 0; i < len tokwords; i++)
1004 if(t == tokwords[i].token)
1005 return tokwords[i].name;
1006 if(t < 0 || t > 255)
1007 fatal(sprint("bad token %d in toksp()", t));
1008 buf := "Z";
1009 buf[0] = t;
1010 return buf;
1011}
1012
1013enterstring(name: string): ref Sym
1014{
1015 h := 0;
1016 n := len name;
1017 for(i := 0; i < n; i++){
1018 c := d := name[i];
1019 c ^= c << 6;
1020 h += (c << 11) ^ (c >> 1);
1021 h ^= (d << 14) + (d << 7) + (d << 4) + d;
1022 }
1023
1024 h &= HashSize-1;
1025 for(s := strings[h]; s != nil; s = s.next){
1026 sn := s.name;
1027 if(len sn == n && sn == name)
1028 return s;
1029 }
1030
1031
1032 s = ref Sym;
1033 s.token = -1;
1034 s.name = name;
1035 s.hash = h;
1036 s.next = strings[h];
1037 strings[h] = s;
1038 return s;
1039}
1040
1041stringcat(s, t: ref Sym): ref Sym
1042{
1043 return enterstring(s.name+t.name);
1044}
1045
1046enter(name: string, token: int): ref Sym
1047{
1048 h := 0;
1049 n := len name;
1050 for(i := 0; i < n; i++){
1051 c := d := name[i];
1052 c ^= c << 6;
1053 h += (c << 11) ^ (c >> 1);
1054 h ^= (d << 14) + (d << 7) + (d << 4) + d;
1055 }
1056
1057 h &= HashSize-1;
1058 for(s := symbols[h]; s != nil; s = s.next){
1059 sn := s.name;
1060 if(len sn == n && sn == name)
1061 return s;
1062 }
1063
1064 if(token == 0)
1065 token = Lid;
1066 s = ref Sym;
1067 s.token = token;
1068 s.name = name;
1069 s.hash = h;
1070 s.next = symbols[h];
1071 symbols[h] = s;
1072 return s;
1073}
1074
1075stringpr(sym: ref Sym): string
1076{
1077 s := sym.name;
1078 n := len s;
1079 if(n > 10)
1080 n = 10;
1081 sb := "\"";
1082 for(i := 0; i < n; i++){
1083 case c := s[i]{
1084 '\\' or
1085 '"' or
1086 '\n' or
1087 '\r' or
1088 '\t' or
1089 '\b' or
1090 '\a' or
1091 '\v' or
1092 '\u0000' =>
1093 sb[len sb] = '\\';
1094 sb[len sb] = unescmap[c];
1095 * =>
1096 sb[len sb] = c;
1097 }
1098 }
1099 if(n != len s)
1100 sb += "...";
1101 sb[len sb] = '"';
1102 return sb;
1103}
1104
1105warn(line: Line, msg: string)
1106{
1107 if(errors || !dowarn)
1108 return;
1109 fprint(stderr, "%s: warning: %s\n", lineconv(line), msg);
1110}
1111
1112nwarn(n: ref Node, msg: string)
1113{
1114 if(errors || !dowarn)
1115 return;
1116 fprint(stderr, "%s: warning: %s\n", lineconv(n.src.start), msg);
1117}
1118
1119error(line: Line, msg: string)
1120{
1121 errors++;
1122 if(errors > maxerr)
1123 return;
1124 fprint(stderr, "%s: %s\n", lineconv(line), msg);
1125 if(errors == maxerr)
1126 fprint(stderr, "too many errors, stopping\n");
1127}
1128
1129nerror(n: ref Node, msg: string)
1130{
1131 errors++;
1132 if(errors > maxerr)
1133 return;
1134 fprint(stderr, "%s: %s\n", lineconv(n.src.start), msg);
1135 if(errors == maxerr)
1136 fprint(stderr, "too many errors, stopping\n");
1137}
1138
1139YYLEX.error(nil: self ref YYLEX, msg: string)
1140{
1141 errors++;
1142 if(errors > maxerr)
1143 return;
1144 if(lasttok != 0)
1145 fprint(stderr, "%s: near ` %s ` : %s\n", lineconv(lineno<<PosBits), toksp(lasttok), msg);
1146 else
1147 fprint(stderr, "%s: %s\n", lineconv(lineno<<PosBits), msg);
1148 if(errors == maxerr)
1149 fprint(stderr, "too many errors, stopping\n");
1150}
1151
1152yyerror(msg: string)
1153{
1154 yyctxt.error(msg);
1155}
1156
1157fatal(msg: string)
1158{
1159 if(errors == 0 || fabort)
1160 fprint(stderr, "fatal limbo compiler error: %s\n", msg);
1161 if(bout != nil)
1162 sys->remove(outfile);
1163 if(fabort){
1164 n: ref Node;
1165 if(n.ty == nil); # abort
1166 }
1167 raise "fail:error";
1168}
1169
1170hex(v, n: int): string
1171{
1172 return sprint("%.*ux", n, v);
1173}
1174
1175bhex(v: big, n: int): string
1176{
1177 return sprint("%.*bux", n, v);
1178}
limbo/compiler/limbo.b+3104−0
@@ -0,0 +1,3104 @@
1implement Limbo;
2
3#line 2 "limbo.y"
4include "limbo.m";
5include "draw.m";
6
7Limbo: module {
8
9 init: fn(ctxt: ref Draw->Context, argv: list of string);
10
11 YYSTYPE: adt{
12 tok: Tok;
13 ids: ref Decl;
14 node: ref Node;
15 ty: ref Type;
16 types: ref Typelist;
17 };
18
19 YYLEX: adt {
20 lval: YYSTYPE;
21 lex: fn(nil: self ref YYLEX): int;
22 error: fn(nil: self ref YYLEX, err: string);
23 };
24Landeq: con 57346;
25Loreq: con 57347;
26Lxoreq: con 57348;
27Llsheq: con 57349;
28Lrsheq: con 57350;
29Laddeq: con 57351;
30Lsubeq: con 57352;
31Lmuleq: con 57353;
32Ldiveq: con 57354;
33Lmodeq: con 57355;
34Lexpeq: con 57356;
35Ldeclas: con 57357;
36Lload: con 57358;
37Loror: con 57359;
38Landand: con 57360;
39Lcons: con 57361;
40Leq: con 57362;
41Lneq: con 57363;
42Lleq: con 57364;
43Lgeq: con 57365;
44Llsh: con 57366;
45Lrsh: con 57367;
46Lexp: con 57368;
47Lcomm: con 57369;
48Linc: con 57370;
49Ldec: con 57371;
50Lof: con 57372;
51Lref: con 57373;
52Lif: con 57374;
53Lelse: con 57375;
54Lfn: con 57376;
55Lexcept: con 57377;
56Lraises: con 57378;
57Lmdot: con 57379;
58Lto: con 57380;
59Lor: con 57381;
60Lrconst: con 57382;
61Lconst: con 57383;
62Lid: con 57384;
63Ltid: con 57385;
64Lsconst: con 57386;
65Llabs: con 57387;
66Lnil: con 57388;
67Llen: con 57389;
68Lhd: con 57390;
69Ltl: con 57391;
70Ltagof: con 57392;
71Limplement: con 57393;
72Limport: con 57394;
73Linclude: con 57395;
74Lcon: con 57396;
75Ltype: con 57397;
76Lmodule: con 57398;
77Lcyclic: con 57399;
78Ladt: con 57400;
79Larray: con 57401;
80Llist: con 57402;
81Lchan: con 57403;
82Lself: con 57404;
83Ldo: con 57405;
84Lwhile: con 57406;
85Lfor: con 57407;
86Lbreak: con 57408;
87Lalt: con 57409;
88Lcase: con 57410;
89Lpick: con 57411;
90Lcont: con 57412;
91Lreturn: con 57413;
92Lexit: con 57414;
93Lspawn: con 57415;
94Lraise: con 57416;
95Lfix: con 57417;
96Ldynamic: con 57418;
97
98};
99
100#line 27 "limbo.y"
101 #
102 # lex.b
103 #
104 signdump: string; # name of function for sig debugging
105 superwarn: int;
106 debug: array of int;
107 noline: Line;
108 nosrc: Src;
109 arrayz: int;
110 oldcycles: int;
111 emitcode: string; # emit stub routines for system module functions
112 emitdyn: int; # emit as above but for dynamic modules
113 emitsbl: string; # emit symbol file for sysm modules
114 emitstub: int; # emit type and call frames for system modules
115 emittab: string; # emit table of runtime functions for this module
116 errors: int;
117 mustcompile: int;
118 dontcompile: int;
119 asmsym: int; # generate symbols in assembly language?
120 bout: ref Bufio->Iobuf; # output file
121 bsym: ref Bufio->Iobuf; # symbol output file; nil => no sym out
122 gendis: int; # generate dis or asm?
123 fixss: int;
124 newfnptr: int; # ISELF and -ve indices
125 optims: int;
126
127 #
128 # decls.b
129 #
130 scope: int;
131 # impmod: ref Sym; # name of implementation module
132 impmods: ref Decl; # name of implementation module(s)
133 nildecl: ref Decl; # declaration for limbo's nil
134 selfdecl: ref Decl; # declaration for limbo's self
135
136 #
137 # types.b
138 #
139 tany: ref Type;
140 tbig: ref Type;
141 tbyte: ref Type;
142 terror: ref Type;
143 tint: ref Type;
144 tnone: ref Type;
145 treal: ref Type;
146 tstring: ref Type;
147 texception: ref Type;
148 tunknown: ref Type;
149 tfnptr: ref Type;
150 rtexception: ref Type;
151 descriptors: ref Desc; # list of all possible descriptors
152 tattr: array of Tattr;
153
154 #
155 # nodes.b
156 #
157 opcommute: array of int;
158 oprelinvert: array of int;
159 isused: array of int;
160 casttab: array of array of int; # instruction to cast from [1] to [2]
161
162 nfns: int; # functions defined
163 nfnexp: int;
164 fns: array of ref Decl; # decls for fns defined
165 tree: ref Node; # root of parse tree
166
167 parset: int; # time to parse
168 checkt: int; # time to typecheck
169 gent: int; # time to generate code
170 writet: int; # time to write out code
171 symt: int; # time to write out symbols
172YYEOFCODE: con 1;
173YYERRCODE: con 2;
174YYMAXDEPTH: con 200;
175
176#line 1632 "limbo.y"
177
178
179include "ipints.m";
180include "crypt.m";
181
182sys: Sys;
183 print, fprint, sprint: import sys;
184
185bufio: Bufio;
186 Iobuf: import bufio;
187
188str: String;
189
190crypt:Crypt;
191 md5: import crypt;
192
193math: Math;
194 import_real, export_real, isnan: import math;
195
196yyctxt: ref YYLEX;
197
198canonnan: real;
199
200debug = array[256] of {* => 0};
201
202noline = -1;
203nosrc = Src(-1, -1);
204
205infile: string;
206
207# front end
208include "arg.m";
209include "lex.b";
210include "types.b";
211include "nodes.b";
212include "decls.b";
213
214include "typecheck.b";
215
216# back end
217include "gen.b";
218include "ecom.b";
219include "asm.b";
220include "dis.b";
221include "sbl.b";
222include "stubs.b";
223include "com.b";
224include "optim.b";
225
226init(nil: ref Draw->Context, argv: list of string)
227{
228 s: string;
229
230 sys = load Sys Sys->PATH;
231 crypt = load Crypt Crypt->PATH;
232 math = load Math Math->PATH;
233 bufio = load Bufio Bufio->PATH;
234 if(bufio == nil){
235 sys->print("can't load %s: %r\n", Bufio->PATH);
236 raise("fail:bad module");
237 }
238 str = load String String->PATH;
239 if(str == nil){
240 sys->print("can't load %s: %r\n", String->PATH);
241 raise("fail:bad module");
242 }
243
244 stderr = sys->fildes(2);
245 yyctxt = ref YYLEX;
246
247 math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX);
248 na := array[1] of {0.};
249 import_real(array[8] of {byte 16r7f, * => byte 16rff}, na);
250 canonnan = na[0];
251 if(!isnan(canonnan))
252 fatal("bad canonical NaN");
253
254 lexinit();
255 typeinit();
256 optabinit();
257
258 gendis = 1;
259 asmsym = 0;
260 maxerr = 20;
261 ofile := "";
262 ext := "";
263
264 arg := Arg.init(argv);
265 while(c := arg.opt()){
266 case c{
267 'Y' =>
268 emitsbl = arg.arg();
269 if(emitsbl == nil)
270 usage();
271 'C' =>
272 dontcompile = 1;
273 'D' =>
274 #
275 # debug flags:
276 #
277 # a alt compilation
278 # A array constructor compilation
279 # b boolean and branch compilation
280 # c case compilation
281 # d function declaration
282 # D descriptor generation
283 # e expression compilation
284 # E addressable expression compilation
285 # f print arguments for compiled functions
286 # F constant folding
287 # g print out globals
288 # m module declaration and type checking
289 # n nil references
290 # s print sizes of output file sections
291 # S type signing
292 # t type checking function bodies
293 # T timing
294 # v global var and constant compilation
295 # x adt verification
296 # Y tuple compilation
297 # z Z bug fixes
298 #
299 s = arg.arg();
300 for(i := 0; i < len s; i++){
301 c = s[i];
302 if(c < len debug)
303 debug[c] = 1;
304 }
305 'I' =>
306 s = arg.arg();
307 if(s == "")
308 usage();
309 addinclude(s);
310 'G' =>
311 asmsym = 1;
312 'S' =>
313 gendis = 0;
314 'a' =>
315 emitstub = 1;
316 'A' =>
317 emitstub = emitdyn = 1;
318 'c' =>
319 mustcompile = 1;
320 'e' =>
321 maxerr = 1000;
322 'f' =>
323 fabort = 1;
324 'F' =>
325 newfnptr = 1;
326 'g' =>
327 dosym = 1;
328 'i' =>
329 dontinline = 1;
330 'o' =>
331 ofile = arg.arg();
332 'O' =>
333 optims = 1;
334 's' =>
335 s = arg.arg();
336 if(s != nil)
337 fixss = int s;
338 't' =>
339 emittab = arg.arg();
340 if(emittab == nil)
341 usage();
342 'T' =>
343 emitcode = arg.arg();
344 if(emitcode == nil)
345 usage();
346 'd' =>
347 emitcode = arg.arg();
348 if(emitcode == nil)
349 usage();
350 emitdyn = 1;
351 'w' =>
352 superwarn = dowarn;
353 dowarn = 1;
354 'x' =>
355 ext = arg.arg();
356 'X' =>
357 signdump = arg.arg();
358 'z' =>
359 arrayz = 1;
360 'y' =>
361 oldcycles = 1;
362 * =>
363 usage();
364 }
365 }
366
367 addinclude("/module");
368
369 argv = arg.argv;
370 arg = nil;
371
372 if(argv == nil){
373 usage();
374 }else if(ofile != nil){
375 if(len argv != 1)
376 usage();
377 translate(hd argv, ofile, mkfileext(ofile, ".dis", ".sbl"));
378 }else{
379 pr := len argv != 1;
380 if(ext == ""){
381 ext = ".s";
382 if(gendis)
383 ext = ".dis";
384 }
385 for(; argv != nil; argv = tl argv){
386 file := hd argv;
387 (nil, s) = str->splitr(file, "/");
388 if(pr)
389 print("%s:\n", s);
390 out := mkfileext(s, ".b", ext);
391 translate(file, out, mkfileext(out, ext, ".sbl"));
392 }
393 }
394 if (toterrors > 0)
395 raise("fail:errors");
396}
397
398usage()
399{
400 fprint(stderr, "usage: limbo [-GSagwe] [-I incdir] [-o outfile] [-{T|t|d} module] [-D debug] file ...\n");
401 raise("fail:usage");
402}
403
404mkfileext(file, oldext, ext: string): string
405{
406 n := len file;
407 n2 := len oldext;
408 if(n >= n2 && file[n-n2:] == oldext)
409 file = file[:n-n2];
410 return file + ext;
411}
412
413translate(in, out, dbg: string)
414{
415 infile = in;
416 outfile = out;
417 errors = 0;
418 bins[0] = bufio->open(in, Bufio->OREAD);
419 if(bins[0] == nil){
420 fprint(stderr, "can't open %s: %r\n", in);
421 toterrors++;
422 return;
423 }
424 doemit := emitcode != "" || emitstub || emittab != "" || emitsbl != "";
425 if(!doemit){
426 bout = bufio->create(out, Bufio->OWRITE, 8r666);
427 if(bout == nil){
428 fprint(stderr, "can't open %s: %r\n", out);
429 toterrors++;
430 bins[0].close();
431 return;
432 }
433 if(dosym){
434 bsym = bufio->create(dbg, Bufio->OWRITE, 8r666);
435 if(bsym == nil)
436 fprint(stderr, "can't open %s: %r\n", dbg);
437 }
438 }
439
440 lexstart(in);
441
442 popscopes();
443 typestart();
444 declstart();
445 nfnexp = 0;
446
447 parset = sys->millisec();
448 yyparse(yyctxt);
449 parset = sys->millisec() - parset;
450
451 checkt = sys->millisec();
452 entry := typecheck(!doemit);
453 checkt = sys->millisec() - checkt;
454
455 modcom(entry);
456
457 fns = nil;
458 nfns = 0;
459 descriptors = nil;
460
461 if(debug['T'])
462 print("times: parse=%d type=%d: gen=%d write=%d symbols=%d\n",
463 parset, checkt, gent, writet, symt);
464
465 if(bout != nil)
466 bout.close();
467 if(bsym != nil)
468 bsym.close();
469 toterrors += errors;
470 if(errors && bout != nil)
471 sys->remove(out);
472 if(errors && bsym != nil)
473 sys->remove(dbg);
474}
475
476pwd(): string
477{
478 workdir := load Workdir Workdir->PATH;
479 if(workdir == nil)
480 cd := "/";
481 else
482 cd = workdir->init();
483 # sys->print("pwd: %s\n", cd);
484 return cd;
485}
486
487cleanname(s: string): string
488{
489 ls, path: list of string;
490
491 if(s == nil)
492 return nil;
493 if(s[0] != '/' && s[0] != '\\')
494 (nil, ls) = sys->tokenize(pwd(), "/\\");
495 for( ; ls != nil; ls = tl ls)
496 path = hd ls :: path;
497 (nil, ls) = sys->tokenize(s, "/\\");
498 for( ; ls != nil; ls = tl ls){
499 n := hd ls;
500 if(n == ".")
501 ;
502 else if (n == ".."){
503 if(path != nil)
504 path = tl path;
505 }
506 else
507 path = n :: path;
508 }
509 p := "";
510 for( ; path != nil; path = tl path)
511 p = "/" + hd path + p;
512 if(p == nil)
513 p = "/";
514 # sys->print("cleanname: %s\n", p);
515 return p;
516}
517
518srcpath(): string
519{
520 srcp := cleanname(infile);
521 # sys->print("srcpath: %s\n", srcp);
522 return srcp;
523}
524yyexca := array[] of {-1, 1,
525 1, -1,
526 -2, 0,
527-1, 3,
528 1, 3,
529 -2, 0,
530-1, 17,
531 39, 88,
532 50, 62,
533 54, 88,
534 99, 62,
535 -2, 252,
536-1, 211,
537 59, 29,
538 71, 29,
539 -2, 0,
540-1, 230,
541 1, 2,
542 -2, 0,
543-1, 273,
544 50, 176,
545 -2, 257,
546-1, 308,
547 59, 41,
548 71, 41,
549 91, 41,
550 -2, 0,
551-1, 310,
552 72, 175,
553 85, 150,
554 86, 150,
555 87, 150,
556 89, 150,
557 90, 150,
558 91, 150,
559 -2, 0,
560-1, 380,
561 50, 62,
562 99, 62,
563 -2, 252,
564-1, 381,
565 72, 175,
566 85, 150,
567 86, 150,
568 87, 150,
569 89, 150,
570 90, 150,
571 91, 150,
572 -2, 0,
573-1, 387,
574 53, 71,
575 54, 71,
576 -2, 110,
577-1, 389,
578 53, 72,
579 54, 72,
580 -2, 112,
581-1, 421,
582 72, 175,
583 85, 150,
584 86, 150,
585 87, 150,
586 89, 150,
587 90, 150,
588 91, 150,
589 -2, 0,
590-1, 428,
591 72, 175,
592 85, 150,
593 86, 150,
594 87, 150,
595 89, 150,
596 90, 150,
597 91, 150,
598 -2, 0,
599-1, 443,
600 53, 71,
601 54, 71,
602 -2, 111,
603-1, 444,
604 53, 72,
605 54, 72,
606 -2, 113,
607-1, 452,
608 71, 279,
609 99, 279,
610 -2, 163,
611-1, 469,
612 72, 175,
613 85, 150,
614 86, 150,
615 87, 150,
616 89, 150,
617 90, 150,
618 91, 150,
619 -2, 0,
620-1, 486,
621 50, 126,
622 99, 126,
623 -2, 239,
624-1, 491,
625 71, 276,
626 -2, 0,
627-1, 503,
628 59, 47,
629 71, 47,
630 -2, 0,
631-1, 508,
632 59, 41,
633 71, 41,
634 91, 41,
635 -2, 0,
636-1, 514,
637 72, 175,
638 85, 150,
639 86, 150,
640 87, 150,
641 89, 150,
642 90, 150,
643 91, 150,
644 -2, 0,
645-1, 548,
646 72, 175,
647 85, 150,
648 86, 150,
649 87, 150,
650 89, 150,
651 90, 150,
652 91, 150,
653 -2, 0,
654-1, 554,
655 71, 154,
656 72, 175,
657 85, 150,
658 86, 150,
659 87, 150,
660 89, 150,
661 90, 150,
662 91, 150,
663 -2, 0,
664-1, 562,
665 56, 59,
666 62, 59,
667 -2, 62,
668-1, 568,
669 72, 175,
670 85, 150,
671 86, 150,
672 87, 150,
673 89, 150,
674 90, 150,
675 91, 150,
676 -2, 0,
677-1, 573,
678 71, 157,
679 72, 175,
680 85, 150,
681 86, 150,
682 87, 150,
683 89, 150,
684 90, 150,
685 91, 150,
686 -2, 0,
687-1, 577,
688 72, 176,
689 -2, 163,
690-1, 596,
691 71, 160,
692 72, 175,
693 85, 150,
694 86, 150,
695 87, 150,
696 89, 150,
697 90, 150,
698 91, 150,
699 -2, 0,
700-1, 602,
701 71, 168,
702 72, 175,
703 85, 150,
704 86, 150,
705 87, 150,
706 89, 150,
707 90, 150,
708 91, 150,
709 -2, 0,
710-1, 606,
711 72, 175,
712 85, 150,
713 86, 150,
714 87, 150,
715 89, 150,
716 90, 150,
717 91, 150,
718 -2, 0,
719-1, 609,
720 50, 62,
721 56, 171,
722 62, 171,
723 99, 62,
724 -2, 252,
725};
726YYNPROD: con 284;
727YYPRIVATE: con 57344;
728yytoknames: array of string;
729yystates: array of string;
730yydebug: con 0;
731YYLAST: con 2727;
732yyact := array[] of {
733 379, 591, 453, 364, 505, 384, 412, 310, 369, 314,
734 359, 451, 449, 185, 84, 83, 432, 298, 270, 15,
735 8, 49, 213, 102, 320, 12, 42, 110, 48, 78,
736 79, 80, 4, 35, 198, 51, 23, 544, 363, 6,
737 423, 3, 6, 486, 459, 382, 365, 14, 458, 21,
738 14, 353, 350, 293, 285, 491, 118, 225, 400, 330,
739 286, 226, 31, 223, 46, 112, 465, 11, 105, 517,
740 420, 419, 418, 186, 164, 165, 166, 167, 168, 169,
741 170, 171, 172, 173, 174, 175, 176, 43, 117, 422,
742 182, 183, 184, 599, 71, 10, 286, 205, 10, 208,
743 93, 349, 286, 601, 119, 349, 32, 114, 40, 349,
744 294, 32, 294, 286, 44, 119, 428, 427, 426, 308,
745 430, 429, 431, 585, 231, 232, 233, 234, 235, 236,
746 237, 238, 239, 240, 241, 242, 309, 244, 245, 246,
747 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
748 257, 258, 259, 260, 261, 262, 263, 264, 265, 186,
749 6, 547, 273, 230, 37, 22, 194, 195, 14, 22,
750 271, 485, 267, 210, 5, 483, 482, 565, 279, 481,
751 513, 410, 284, 87, 438, 559, 424, 228, 409, 288,
752 85, 407, 94, 90, 289, 99, 269, 415, 217, 202,
753 5, 415, 47, 92, 82, 22, 209, 26, 303, 25,
754 212, 19, 24, 218, 229, 566, 10, 354, 96, 595,
755 98, 95, 100, 572, 101, 88, 89, 86, 557, 194,
756 195, 17, 87, 312, 311, 18, 297, 19, 187, 85,
757 553, 77, 90, 313, 326, 305, 536, 13, 512, 112,
758 323, 318, 92, 82, 525, 207, 490, 17, 87, 468,
759 399, 18, 383, 23, 508, 85, 316, 215, 90, 6,
760 498, 2, 500, 13, 88, 89, 86, 14, 92, 82,
761 194, 195, 479, 186, 43, 467, 398, 340, 194, 195,
762 77, 114, 193, 361, 282, 499, 338, 182, 500, 535,
763 88, 89, 86, 336, 194, 195, 219, 530, 87, 211,
764 341, 44, 87, 324, 580, 85, 77, 325, 90, 85,
765 381, 348, 90, 206, 19, 10, 358, 357, 92, 82,
766 579, 393, 92, 82, 604, 214, 389, 387, 391, 448,
767 614, 194, 195, 402, 45, 539, 194, 195, 18, 392,
768 88, 89, 86, 356, 88, 89, 86, 321, 194, 195,
769 192, 385, 72, 403, 404, 495, 77, 33, 317, 108,
770 77, 416, 73, 19, 19, 421, 436, 301, 281, 186,
771 76, 75, 45, 435, 74, 437, 18, 216, 487, 493,
772 434, 441, 439, 115, 115, 612, 564, 116, 116, 452,
773 488, 340, 183, 444, 443, 507, 414, 45, 316, 604,
774 562, 18, 493, 543, 493, 603, 336, 493, 600, 70,
775 597, 493, 63, 588, 504, 73, 473, 574, 469, 22,
776 478, 442, 476, 76, 75, 69, 68, 74, 480, 18,
777 54, 55, 62, 60, 61, 64, 87, 433, 291, 452,
778 290, 91, 268, 85, 91, 157, 90, 65, 66, 67,
779 120, 489, 493, 104, 497, 493, 92, 82, 555, 540,
780 594, 494, 186, 77, 159, 477, 168, 194, 195, 103,
781 523, 507, 522, 515, 516, 511, 406, 510, 88, 89,
782 86, 87, 452, 527, 523, 529, 528, 487, 85, 518,
783 533, 90, 593, 526, 77, 91, 39, 91, 532, 537,
784 466, 92, 82, 417, 545, 91, 408, 568, 546, 541,
785 523, 36, 552, 329, 224, 556, 91, 592, 299, 554,
786 106, 300, 34, 88, 89, 86, 158, 401, 161, 397,
787 162, 163, 560, 563, 441, 316, 335, 332, 201, 77,
788 160, 159, 570, 200, 197, 577, 569, 575, 571, 573,
789 81, 477, 177, 97, 181, 179, 331, 523, 180, 583,
790 446, 177, 584, 445, 577, 178, 587, 141, 142, 138,
791 139, 140, 137, 135, 561, 328, 227, 346, 414, 345,
792 596, 41, 203, 606, 598, 477, 586, 577, 602, 605,
793 91, 548, 386, 327, 607, 222, 611, 221, 549, 475,
794 613, 474, 471, 425, 196, 477, 199, 91, 137, 135,
795 91, 91, 39, 91, 204, 138, 139, 140, 137, 135,
796 91, 183, 168, 188, 19, 220, 29, 27, 524, 243,
797 360, 538, 307, 287, 91, 91, 368, 121, 30, 28,
798 1, 464, 272, 477, 123, 124, 125, 126, 127, 128,
799 129, 130, 131, 132, 133, 134, 136, 274, 156, 155,
800 154, 153, 152, 151, 149, 150, 145, 146, 147, 148,
801 144, 143, 141, 142, 138, 139, 140, 137, 135, 315,
802 343, 542, 582, 581, 413, 503, 502, 590, 91, 144,
803 143, 141, 142, 138, 139, 140, 137, 135, 589, 283,
804 16, 411, 306, 355, 91, 9, 551, 87, 550, 521,
805 91, 520, 7, 450, 85, 337, 292, 90, 266, 295,
806 296, 506, 371, 109, 107, 87, 113, 92, 82, 199,
807 111, 91, 85, 20, 38, 90, 0, 99, 282, 342,
808 0, 91, 91, 319, 322, 92, 82, 0, 0, 88,
809 89, 86, 0, 0, 0, 91, 91, 0, 0, 91,
810 96, 0, 98, 95, 0, 77, 87, 88, 89, 86,
811 0, 0, 0, 85, 0, 0, 90, 0, 0, 0,
812 0, 0, 0, 77, 0, 0, 92, 82, 0, 0,
813 0, 0, 0, 0, 0, 0, 0, 333, 91, 0,
814 455, 0, 0, 0, 0, 0, 0, 91, 88, 89,
815 86, 91, 0, 347, 0, 50, 91, 0, 91, 351,
816 0, 0, 0, 0, 77, 0, 0, 91, 0, 0,
817 52, 53, 454, 91, 0, 0, 59, 72, 0, 0,
818 390, 57, 58, 0, 63, 0, 0, 73, 0, 0,
819 395, 396, 0, 0, 0, 76, 75, 69, 68, 74,
820 0, 18, 54, 55, 62, 60, 61, 64, 405, 0,
821 0, 0, 91, 0, 0, 0, 91, 0, 0, 65,
822 66, 67, 145, 146, 147, 148, 144, 143, 141, 142,
823 138, 139, 140, 137, 135, 77, 0, 91, 0, 0,
824 0, 0, 0, 366, 0, 0, 0, 196, 0, 0,
825 91, 0, 0, 0, 0, 0, 447, 0, 50, 0,
826 456, 0, 0, 0, 0, 460, 0, 461, 0, 0,
827 0, 0, 0, 52, 53, 56, 97, 0, 0, 59,
828 378, 0, 472, 0, 57, 58, 0, 63, 370, 0,
829 73, 0, 0, 0, 0, 0, 0, 0, 76, 75,
830 380, 68, 74, 0, 18, 54, 55, 62, 60, 61,
831 64, 367, 509, 366, 0, 0, 13, 0, 0, 0,
832 0, 496, 65, 66, 67, 501, 0, 0, 50, 372,
833 0, 0, 0, 373, 374, 377, 375, 376, 77, 0,
834 0, 0, 0, 52, 53, 56, 501, 0, 0, 59,
835 378, 0, 0, 0, 57, 58, 0, 63, 370, 534,
836 73, 0, 0, 0, 0, 0, 0, 0, 76, 75,
837 380, 68, 74, 0, 18, 54, 55, 62, 60, 61,
838 64, 367, 470, 366, 0, 0, 13, 0, 0, 0,
839 0, 0, 65, 66, 67, 0, 0, 0, 50, 372,
840 0, 0, 0, 373, 374, 377, 375, 376, 77, 0,
841 0, 0, 0, 52, 53, 56, 0, 0, 0, 59,
842 378, 0, 0, 0, 57, 58, 0, 63, 370, 0,
843 73, 0, 0, 0, 0, 0, 0, 0, 76, 75,
844 380, 68, 74, 0, 18, 54, 55, 62, 60, 61,
845 64, 367, 440, 366, 0, 0, 13, 0, 0, 0,
846 0, 0, 65, 66, 67, 0, 0, 0, 50, 372,
847 0, 0, 0, 373, 374, 377, 375, 376, 77, 0,
848 0, 0, 0, 52, 53, 56, 0, 0, 0, 59,
849 378, 0, 0, 0, 57, 58, 0, 63, 370, 0,
850 73, 0, 0, 0, 0, 0, 0, 0, 76, 75,
851 380, 68, 74, 0, 18, 54, 55, 62, 60, 61,
852 64, 367, 362, 608, 0, 0, 13, 0, 0, 0,
853 0, 0, 65, 66, 67, 0, 0, 0, 50, 372,
854 0, 0, 0, 373, 374, 377, 375, 376, 77, 0,
855 0, 0, 0, 52, 53, 610, 0, 0, 0, 59,
856 378, 0, 0, 0, 57, 58, 0, 63, 370, 0,
857 73, 0, 0, 0, 0, 0, 0, 0, 76, 75,
858 609, 68, 74, 0, 18, 54, 55, 62, 60, 61,
859 64, 367, 576, 0, 0, 0, 13, 0, 0, 0,
860 0, 0, 65, 66, 67, 0, 0, 50, 0, 372,
861 0, 0, 0, 373, 374, 377, 375, 376, 77, 0,
862 0, 0, 52, 53, 454, 0, 0, 0, 59, 378,
863 0, 0, 0, 57, 58, 0, 63, 370, 0, 73,
864 0, 0, 0, 0, 0, 0, 0, 76, 75, 380,
865 68, 74, 0, 18, 54, 55, 62, 60, 61, 64,
866 367, 366, 0, 0, 0, 13, 0, 0, 0, 0,
867 0, 65, 66, 67, 0, 0, 50, 0, 372, 0,
868 0, 0, 373, 374, 377, 375, 376, 77, 0, 0,
869 0, 52, 53, 56, 0, 0, 0, 59, 378, 0,
870 0, 0, 57, 58, 0, 63, 370, 0, 73, 0,
871 0, 0, 0, 0, 0, 0, 76, 75, 380, 68,
872 74, 0, 18, 54, 55, 62, 60, 61, 64, 367,
873 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
874 65, 66, 67, 50, 0, 0, 0, 372, 0, 0,
875 0, 373, 374, 377, 375, 376, 77, 0, 52, 53,
876 56, 0, 0, 0, 59, 72, 0, 0, 0, 57,
877 58, 0, 63, 0, 0, 73, 0, 0, 0, 0,
878 0, 0, 0, 76, 75, 69, 275, 74, 0, 18,
879 54, 55, 62, 60, 61, 64, 0, 0, 0, 50,
880 0, 0, 0, 0, 0, 278, 0, 276, 277, 67,
881 0, 0, 0, 0, 52, 53, 56, 0, 0, 0,
882 59, 72, 0, 77, 280, 57, 58, 0, 63, 0,
883 0, 73, 0, 0, 0, 0, 0, 0, 0, 76,
884 75, 69, 68, 74, 0, 18, 54, 55, 62, 60,
885 61, 64, 0, 0, 50, 0, 0, 0, 0, 0,
886 0, 0, 0, 65, 66, 67, 0, 0, 0, 52,
887 53, 56, 0, 0, 0, 59, 72, 0, 0, 77,
888 57, 58, 0, 63, 0, 0, 73, 0, 0, 0,
889 0, 0, 0, 0, 76, 75, 69, 68, 74, 0,
890 18, 54, 55, 62, 60, 61, 64, 0, 0, 0,
891 52, 53, 56, 0, 0, 0, 59, 72, 65, 66,
892 67, 57, 58, 0, 63, 0, 0, 73, 0, 0,
893 0, 0, 0, 0, 77, 76, 75, 69, 68, 74,
894 0, 18, 54, 55, 62, 60, 61, 64, 0, 0,
895 0, 0, 0, 0, 0, 0, 87, 0, 0, 65,
896 66, 67, 0, 85, 0, 0, 90, 0, 99, 0,
897 0, 0, 0, 0, 0, 77, 92, 82, 149, 150,
898 145, 146, 147, 148, 144, 143, 141, 142, 138, 139,
899 140, 137, 135, 463, 462, 0, 0, 101, 88, 89,
900 86, 123, 124, 125, 126, 127, 128, 129, 130, 131,
901 132, 133, 134, 136, 77, 156, 155, 154, 153, 152,
902 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
903 142, 138, 139, 140, 137, 135, 155, 154, 153, 152,
904 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
905 142, 138, 139, 140, 137, 135, 123, 124, 125, 126,
906 127, 128, 129, 130, 131, 132, 133, 134, 136, 567,
907 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
908 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
909 135, 154, 153, 152, 151, 149, 150, 145, 146, 147,
910 148, 144, 143, 141, 142, 138, 139, 140, 137, 135,
911 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
912 132, 133, 134, 136, 558, 156, 155, 154, 153, 152,
913 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
914 142, 138, 139, 140, 137, 135, 152, 151, 149, 150,
915 145, 146, 147, 148, 144, 143, 141, 142, 138, 139,
916 140, 137, 135, 0, 0, 0, 123, 124, 125, 126,
917 127, 128, 129, 130, 131, 132, 133, 134, 136, 531,
918 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
919 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
920 135, 151, 149, 150, 145, 146, 147, 148, 144, 143,
921 141, 142, 138, 139, 140, 137, 135, 0, 0, 0,
922 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
923 132, 133, 134, 136, 484, 156, 155, 154, 153, 152,
924 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
925 142, 138, 139, 140, 137, 135, 0, 0, 0, 0,
926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
927 0, 0, 0, 0, 0, 0, 123, 124, 125, 126,
928 127, 128, 129, 130, 131, 132, 133, 134, 136, 352,
929 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
930 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
931 135, 0, 0, 0, 0, 0, 0, 0, 0, 0,
932 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
933 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
934 132, 133, 134, 136, 344, 156, 155, 154, 153, 152,
935 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
936 142, 138, 139, 140, 137, 135, 0, 0, 0, 0,
937 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
938 0, 0, 0, 0, 0, 0, 123, 124, 125, 126,
939 127, 128, 129, 130, 131, 132, 133, 134, 136, 304,
940 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
941 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
942 135, 0, 0, 0, 0, 0, 0, 0, 0, 0,
943 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
944 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
945 132, 133, 134, 136, 302, 156, 155, 154, 153, 152,
946 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
947 142, 138, 139, 140, 137, 135, 0, 0, 0, 0,
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949 0, 0, 0, 0, 0, 0, 123, 124, 125, 126,
950 127, 128, 129, 130, 131, 132, 133, 134, 136, 191,
951 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
952 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
953 135, 0, 0, 0, 0, 0, 0, 0, 0, 0,
954 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
955 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
956 132, 133, 134, 136, 190, 156, 155, 154, 153, 152,
957 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
958 142, 138, 139, 140, 137, 135, 0, 0, 0, 0,
959 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
960 0, 0, 0, 0, 0, 0, 123, 124, 125, 126,
961 127, 128, 129, 130, 131, 132, 133, 134, 136, 189,
962 156, 155, 154, 153, 152, 151, 149, 150, 145, 146,
963 147, 148, 144, 143, 141, 142, 138, 139, 140, 137,
964 135, 0, 87, 0, 0, 0, 87, 0, 0, 85,
965 0, 0, 90, 388, 0, 0, 90, 0, 0, 0,
966 0, 0, 92, 394, 0, 0, 92, 82, 0, 0,
967 0, 0, 0, 0, 122, 0, 0, 0, 0, 0,
968 0, 0, 0, 0, 88, 89, 86, 0, 88, 89,
969 86, 0, 0, 0, 0, 0, 0, 0, 0, 0,
970 77, 0, 0, 0, 77, 123, 124, 125, 126, 127,
971 128, 129, 130, 131, 132, 133, 134, 136, 0, 156,
972 155, 154, 153, 152, 151, 149, 150, 145, 146, 147,
973 148, 144, 143, 141, 142, 138, 139, 140, 137, 135,
974 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
975 0, 0, 0, 0, 0, 0, 0, 0, 123, 124,
976 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
977 136, 578, 156, 155, 154, 153, 152, 151, 149, 150,
978 145, 146, 147, 148, 144, 143, 141, 142, 138, 139,
979 140, 137, 135, 0, 0, 0, 0, 0, 0, 0,
980 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
981 0, 123, 124, 125, 126, 127, 128, 129, 130, 131,
982 132, 133, 134, 136, 519, 156, 155, 154, 153, 152,
983 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
984 142, 138, 139, 140, 137, 135, 0, 0, 0, 123,
985 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
986 134, 136, 492, 156, 155, 154, 153, 152, 151, 149,
987 150, 145, 146, 147, 148, 144, 143, 141, 142, 138,
988 139, 140, 137, 135, 0, 0, 0, 339, 123, 124,
989 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
990 136, 0, 156, 155, 154, 153, 152, 151, 149, 150,
991 145, 146, 147, 148, 144, 143, 141, 142, 138, 139,
992 140, 137, 135, 0, 0, 0, 334, 123, 124, 125,
993 126, 127, 128, 129, 130, 131, 132, 133, 134, 136,
994 0, 156, 155, 154, 153, 152, 151, 149, 150, 145,
995 146, 147, 148, 144, 143, 141, 142, 138, 139, 140,
996 137, 135, 0, 514, 123, 124, 125, 126, 127, 128,
997 129, 130, 131, 132, 133, 134, 136, 0, 156, 155,
998 154, 153, 152, 151, 149, 150, 145, 146, 147, 148,
999 144, 143, 141, 142, 138, 139, 140, 137, 135, 0,
1000 457, 123, 124, 125, 126, 127, 128, 129, 130, 131,
1001 132, 133, 134, 136, 0, 156, 155, 154, 153, 152,
1002 151, 149, 150, 145, 146, 147, 148, 144, 143, 141,
1003 142, 138, 139, 140, 137, 135, 156, 155, 154, 153,
1004 152, 151, 149, 150, 145, 146, 147, 148, 144, 143,
1005 141, 142, 138, 139, 140, 137, 135,
1006};
1007yypact := array[] of {
1008 198,-1000, 370, 172,-1000, 140,-1000,-1000, 137, 135,
1009 633, 632, 12, 306, 482,-1000, 467, 550,-1000, 285,
1010 -35, 130,-1000,-1000,-1000,-1000,-1000,1507,1507,1507,
10111507, 737, 595, 120, 144, 427, 404, -19, 480, 335,
1012-1000, 370, 16,-1000,-1000,-1000, 401,-1000,2272,-1000,
1013 396, 497,1548,1548,1548,1548,1548,1548,1548,1548,
10141548,1548,1548,1548,1548, 530, 520, 523,1548, 376,
10151548,-1000,1507, 583,-1000,-1000,-1000, 594,2217,2162,
10162107, 288,-1000,-1000,-1000, 737, 509, 737, 508, 503,
1017 550,-1000, 551,-1000,-1000, 737,1507, 251,1507, 134,
1018 239, 550, 265, 348, 550, 236, 737, 567, 565, -36,
1019-1000, 474, 7, -38,-1000,-1000,-1000, 544,-1000, 285,
1020-1000, 172,-1000,1507,1507,1507,1507,1507,1507,1507,
10211507,1507,1507,1507,1507, 635,1507,1507,1507,1507,
10221507,1507,1507,1507,1507,1507,1507,1507,1507,1507,
10231507,1507,1507,1507,1507,1507,1507,1507,1507, 393,
1024 323,1396,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
1025-1000,-1000,-1000,-1000,-1000,-1000,-1000,1452, 318, 224,
1026 737,1507,-1000,-1000,-1000, 14,2667,-1000,1507,-1000,
1027-1000,-1000,-1000,1507, 391, 389, 424, 737, 13, 424,
1028 737, 737, 583, 452, 305,2052,-1000,1507,1997,-1000,
1029 737, 640, 49,-1000,-1000, 163, 285,-1000,-1000, 370,
1030 424,-1000,-1000, 334, 273, 273, 254,-1000,-1000,-1000,
1031 172,2667,2667,2667,2667,2667,2667,2667,2667,2667,
10322667,2667,2667,1507,2667, 581, 581, 581, 581, 591,
1033 591, 545, 545, 669, 669, 669, 669, 866, 866,1624,
10341848,1794,1741,1741,1687,2688, 563, -39,-1000, 420,
1035 543, 473, -40,2667,-1000,1548, 521, 502, 737,2554,
1036 501,1548,1507, 424,2515,-1000,1507, 265, 650,1942,
1037 548, 546, 424,-1000, 737, 424, 424, 427, 10, 424,
1038 737,-1000,-1000,1887,-1000, 11, 146,-1000, 638, 223,
10391121,-1000,-1000, 5, 191,-1000, 299, 562,-1000, 424,
1040-1000,2277, 424,-1000,-1000,-1000,2667,-1000,-1000,1507,
10411396,2273, 678, 424, 494, 216,-1000, 189, -41, 492,
10422667,-1000,1507,-1000,-1000, 452, 452, 424,-1000, 407,
1043-1000, 424,-1000, 119,-1000,-1000, 466, 116,-1000, 110,
1044-1000, 370,-1000,-1000,-1000, 463, 0,-1000, -10, 114,
1045 574, 31, 388, 388,1507,1507,1507, 112,1507,2667,
1046 376,1051,-1000,-1000, 370,-1000,-1000,-1000, 737,-1000,
1047 424, 531, 528,2667,1548, 424, 424, 269, 808,-1000,
10481507, 737,2630, 6, 2, 424, 737,-1000,1587,-1000,
1049 -21,-1000,-1000,-1000, 460, 215, 188, 696,-1000,-1000,
1050-1000, 981, 573, 737,-1000,1507, 572, 570,1329,1507,
1051 212, 379, 107,-1000, 104, 103,1832, 99,-1000, 3,
1052-1000,-1000, 338,-1000,-1000,-1000,-1000, 424, 808, 185,
1053 -44,-1000,2477, 409,1548,-1000, 424,-1000,-1000,-1000,
1054 424, 293, 737,1507,-1000, 200, 219, 422, 194, 911,
1055 436,1507, 176,2593,1507,1507, -17, 449,2424, 808,
1056 622,-1000,-1000,-1000,-1000,-1000,-1000, 193,-1000, 183,
1057-1000, 808,1507, 808,1507,-1000, 235,1777, 370,1507,
1058 737, 227, 175, 639,-1000, 283, 413,-1000, 638,-1000,
1059 354, -3,-1000,1507,1329, 89, 561, 569,-1000, 808,
1060 169,-1000, 406,2477,1507,-1000,-1000,2667,-1000,2667,
1061-1000,-1000, 157,1722, 113,-1000,-1000, 351, 346,-1000,
1062 337, 106, 145,-1000,-1000,1667, 469,1507,1329,1507,
1063 152,-1000, 365,-1000,1260,-1000,2371,-1000,-1000,-1000,
1064 268, 447,-1000, 252,-1000,-1000, 808,-1000,1329, 51,
1065-1000, 556,-1000,1260,-1000, 361, 0,2477, 468,-1000,
1066-1000, 148,-1000, 358,-1000,1507, 21, 356,-1000, 32,
1067-1000, 353,-1000,-1000,-1000,-1000,1260,-1000, 553,-1000,
1068-1000,-1000,1191,-1000, 468, 333,1329, 278, 0, 376,
10691548,-1000,-1000,-1000,-1000,
1070};
1071yypgo := array[] of {
1072 0, 528, 744, 164, 33, 24, 419, 15, 14, 46,
1073 743, 740, 736, 34, 734, 733, 27, 732, 16, 4,
1074 731, 108, 8, 0, 21, 35, 13, 728, 725, 94,
1075 25, 67, 26, 12, 723, 11, 2, 38, 41, 32,
1076 722, 22, 3, 7, 721, 719, 718, 716, 715, 20,
1077 713, 712, 711, 10, 710, 708, 697, 1, 696, 695,
1078 694, 6, 5, 693, 692, 691, 19, 23, 689, 9,
1079 667, 18, 652, 651, 17, 650, 647, 646, 643,
1080};
1081yyr1 := array[] of {
1082 0, 76, 75, 75, 38, 38, 39, 39, 39, 39,
1083 39, 39, 39, 39, 39, 39, 39, 30, 30, 37,
1084 37, 37, 37, 37, 37, 37, 66, 66, 48, 51,
1085 51, 51, 50, 50, 50, 50, 50, 49, 49, 73,
1086 73, 53, 53, 53, 52, 52, 52, 62, 62, 61,
1087 61, 60, 58, 58, 58, 59, 59, 59, 19, 20,
1088 20, 9, 10, 10, 6, 6, 74, 74, 74, 74,
1089 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1090 1, 1, 7, 7, 8, 8, 13, 13, 21, 21,
1091 2, 2, 2, 3, 3, 4, 4, 14, 14, 15,
1092 15, 16, 16, 16, 16, 11, 12, 12, 12, 12,
1093 5, 5, 5, 5, 40, 67, 67, 67, 41, 41,
1094 41, 54, 54, 43, 43, 43, 77, 77, 42, 42,
1095 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
1096 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
1097 17, 17, 18, 18, 44, 45, 45, 46, 47, 47,
1098 63, 64, 64, 36, 36, 36, 36, 36, 55, 56,
1099 56, 57, 57, 57, 57, 22, 22, 23, 23, 23,
1100 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
1101 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
1102 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
1103 23, 23, 23, 24, 24, 24, 24, 24, 24, 24,
1104 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
1105 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
1106 78, 25, 25, 25, 25, 25, 25, 25, 25, 25,
1107 25, 25, 29, 29, 31, 72, 72, 71, 71, 70,
1108 70, 70, 70, 65, 65, 32, 32, 32, 32, 27,
1109 27, 28, 28, 26, 26, 33, 33, 34, 34, 35,
1110 35, 69, 68, 68,
1111};
1112yyr2 := array[] of {
1113 0, 0, 5, 1, 1, 2, 2, 1, 1, 2,
1114 2, 4, 4, 4, 4, 4, 6, 1, 3, 3,
1115 5, 5, 4, 6, 5, 1, 4, 7, 6, 0,
1116 2, 1, 4, 2, 5, 5, 1, 8, 11, 0,
1117 4, 0, 2, 1, 1, 1, 5, 0, 2, 5,
1118 4, 4, 2, 2, 1, 2, 4, 4, 1, 1,
1119 3, 1, 1, 3, 6, 4, 1, 2, 3, 4,
1120 1, 1, 1, 3, 6, 2, 3, 3, 3, 3,
1121 4, 1, 1, 4, 3, 6, 1, 3, 0, 3,
1122 3, 3, 5, 1, 3, 1, 5, 0, 1, 1,
1123 3, 3, 3, 3, 3, 1, 1, 1, 3, 3,
1124 2, 3, 2, 3, 4, 4, 2, 0, 3, 2,
1125 4, 2, 4, 0, 2, 2, 3, 5, 2, 2,
1126 4, 3, 4, 6, 2, 5, 7, 10, 6, 8,
1127 3, 3, 3, 3, 3, 6, 5, 8, 2, 8,
1128 0, 2, 0, 1, 2, 2, 4, 2, 2, 4,
1129 2, 2, 4, 1, 3, 1, 3, 1, 2, 2,
1130 4, 1, 1, 3, 1, 0, 1, 1, 3, 3,
1131 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1132 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1133 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1134 3, 3, 3, 1, 2, 2, 2, 2, 2, 2,
1135 2, 2, 2, 2, 2, 2, 2, 6, 8, 7,
1136 5, 3, 6, 4, 2, 2, 2, 1, 4, 3,
1137 0, 4, 3, 3, 4, 6, 2, 2, 1, 1,
1138 1, 6, 1, 1, 3, 1, 3, 1, 1, 1,
1139 3, 3, 2, 1, 0, 1, 1, 3, 3, 0,
1140 1, 1, 2, 1, 3, 1, 2, 1, 3, 1,
1141 3, 2, 2, 4,
1142};
1143yychk := array[] of {
1144-1000, -75, 73, -38, -39, 2, -37, -40, -49, -48,
1145 -29, -31, -30, 75, -9, -66, -54, 59, 63, 39,
1146 -10, -9, 59, -39, 72, 72, 72, 4, 16, 4,
1147 16, 50, 99, 61, 50, -4, 54, -3, -2, 39,
1148 -21, 41, -32, -31, -29, 59, 99, 72, -23, -24,
1149 17, -25, 32, 33, 64, 65, 34, 43, 44, 38,
1150 67, 68, 66, 46, 69, 81, 82, 83, 60, 59,
1151 -6, -29, 39, 49, 61, 58, 57, 97, -23, -23,
1152 -23, -1, 60, -7, -8, 46, 83, 39, 81, 82,
1153 49, -6, 59, -31, 72, 77, 74, -1, 76, 51,
1154 78, 80, -67, 52, 59, 87, 50, -14, 34, -15,
1155 -16, -11, -30, -12, -31, 59, 63, -9, 40, 99,
1156 59, -76, 72, 4, 5, 6, 7, 8, 9, 10,
1157 11, 12, 13, 14, 15, 38, 16, 37, 34, 35,
1158 36, 32, 33, 31, 30, 26, 27, 28, 29, 24,
1159 25, 23, 22, 21, 20, 19, 18, 59, 39, 54,
1160 53, 41, 43, 44, -24, -24, -24, -24, -24, -24,
1161 -24, -24, -24, -24, -24, -24, -24, 41, 45, 45,
1162 45, 41, -24, -24, -24, -26, -23, -3, 39, 72,
1163 72, 72, 72, 4, 53, 54, -1, 45, -13, -1,
1164 45, 45, -21, 41, -1, -23, 72, 4, -23, 72,
1165 39, 70, -21, -41, 70, 2, 39, -29, -21, 70,
1166 -1, 40, 40, 99, 50, 50, 99, 42, -31, -29,
1167 -38, -23, -23, -23, -23, -23, -23, -23, -23, -23,
1168 -23, -23, -23, 4, -23, -23, -23, -23, -23, -23,
1169 -23, -23, -23, -23, -23, -23, -23, -23, -23, -23,
1170 -23, -23, -23, -23, -23, -23, -27, -26, 59, -25,
1171 -71, -22, -72, -23, -70, 60, 81, 82, 79, -23,
1172 42, 60, 70, -1, -23, 40, 99, -78, -23, -23,
1173 59, 59, -1, 40, 99, -1, -1, -4, -74, -1,
1174 79, 72, 72, -23, 72, -13, -51, 2, 70, 87,
1175 -43, 71, 70, -32, -69, -68, -9, 34, -16, -1,
1176 -5, 84, -1, -5, 59, 63, -23, 40, 42, 50,
1177 99, 45, 45, -1, 42, 45, -24, -28, -26, 42,
1178 -23, -41, 99, 40, 72, 41, 41, -1, -67, 99,
1179 42, -1, 72, 40, 71, -50, -9, -49, -66, -53,
1180 2, 70, 71, -37, -42, -9, 2, 70, -77, -22,
1181 47, -17, 88, 92, 93, 95, 96, 94, 39, -23,
1182 59, -43, 40, 71, -62, 62, 40, -7, 46, -8,
1183 -1, -22, -71, -23, 60, -1, -1, 45, 70, 71,
1184 99, 45, -23, -74, -74, -1, 79, 72, 50, 72,
1185 71, -52, -61, -60, -9, 91, -69, 50, 72, 71,
1186 70, -43, 99, 50, 72, 39, 87, 86, 85, 90,
1187 89, 91, -18, 59, -18, -22, -23, -22, 72, -26,
1188 71, -61, -9, -7, -8, 42, 42, -1, 70, -33,
1189 -34, -35, -23, -36, 34, 2, -1, 40, 42, 42,
1190 -1, -1, 77, 76, -73, 87, 50, 70, 71, -43,
1191 71, 39, -1, -23, 39, 39, -42, -9, -23, 70,
1192 59, 72, 72, 72, 72, 72, 40, 50, 62, -33,
1193 71, 99, 55, 56, 62, 72, -1, -23, 70, 76,
1194 79, -1, -58, -59, 2, -19, -20, 59, 70, 71,
1195 51, -26, 72, 4, 40, -22, -22, 86, 50, 70,
1196 -44, -45, -36, -23, 16, 71, -35, -23, -36, -23,
1197 72, 72, -69, -23, -1, 72, 71, -62, 2, 62,
1198 56, -53, -65, 59, 40, -23, -42, 72, 40, 39,
1199 -46, -47, -36, 71, -43, 62, -23, 71, 72, 72,
1200 -19, -9, 59, -19, 59, 71, 70, 72, 48, -22,
1201 -42, -22, 71, -43, 62, -36, 2, -23, 70, 62,
1202 62, -63, -64, -36, -42, 72, 40, -36, 62, -55,
1203 -56, -57, 59, 34, 2, 71, -43, 62, -22, 72,
1204 62, 71, -43, 62, 56, -36, 40, -57, 2, 59,
1205 34, -57, 62, -42, 62,
1206};
1207yydef := array[] of {
1208 0, -2, 0, -2, 4, 0, 7, 8, 0, 0,
1209 0, 17, 0, 0, 0, 25, 0, -2, 253, 0,
1210 61, 0, 62, 5, 6, 9, 10, 0, 0, 0,
1211 0, 0, 0, 0, 0, 117, 0, 95, 93, 97,
1212 121, 0, 0, 265, 266, 252, 0, 1, 0, 177,
1213 0, 213, 0, 0, 0, 0, 0, 0, 0, 0,
1214 0, 0, 0, 0, 0, 0, 0, 0, 0, 252,
1215 0, 237, 0, 0, 248, 249, 250, 0, 0, 0,
1216 0, 0, 70, 71, 72, 0, 0, 0, 0, 0,
1217 88, 81, 82, 18, 19, 0, 0, 0, 0, 0,
1218 0, 88, 0, 0, 88, 0, 0, 0, 0, 98,
1219 99, 0, 0, 105, 17, 106, 107, 0, 254, 0,
1220 63, 0, 11, 0, 0, 0, 0, 0, 0, 0,
1221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1223 0, 0, 0, 0, 0, 0, 0, 0, 269, 0,
1224 0, 175, 246, 247, 214, 215, 216, 217, 218, 219,
1225 220, 221, 222, 223, 224, 225, 226, 0, 0, 0,
1226 0, 0, 234, 235, 236, 0, 273, 240, 0, 13,
1227 12, 14, 15, 0, 0, 0, 75, 0, 0, 86,
1228 0, 0, 0, 0, 0, 0, 22, 0, 0, 26,
1229 0, -2, 0, 114, 123, 0, 0, 116, 122, 0,
1230 94, 90, 91, 0, 0, 0, 0, 89, 267, 268,
1231 -2, 178, 179, 180, 181, 182, 183, 184, 185, 186,
1232 187, 188, 189, 0, 191, 193, 194, 195, 196, 197,
1233 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
1234 208, 209, 210, 211, 212, 192, 0, 270, 242, 243,
1235 255, 0, 0, -2, 258, 259, 0, 0, 0, 0,
1236 0, 0, 0, 231, 0, 239, 0, 0, 0, 0,
1237 73, 84, 76, 77, 0, 78, 79, 117, 0, 66,
1238 0, 20, 21, 0, 24, 0, 0, 31, -2, 0,
1239 -2, 119, 123, 0, 0, 47, 0, 0, 100, 101,
1240 102, 0, 103, 104, 108, 109, 190, 238, 244, 175,
1241 0, 0, 0, 262, 0, 0, 233, 0, 271, 0,
1242 274, 241, 0, 65, 16, 0, 0, 87, 80, 0,
1243 83, 67, 23, 0, 28, 30, 0, 0, 36, 0,
1244 43, 0, 118, 124, 125, 0, 0, 123, 0, 0,
1245 0, 0, 152, 152, 175, 0, 175, 0, 0, 176,
1246 -2, -2, 115, 96, 281, 282, 92, -2, 0, -2,
1247 0, 0, 256, 257, 70, 260, 261, 0, 0, 230,
1248 272, 0, 0, 0, 0, 68, 0, 27, 0, 33,
1249 39, 42, 44, 45, 0, 0, 0, 151, 128, 129,
1250 123, -2, 0, 0, 134, 0, 0, 0, -2, 0,
1251 0, 0, 0, 153, 0, 0, 0, 0, 148, 0,
1252 120, 48, 0, -2, -2, 245, 251, 227, 0, 0,
1253 275, 277, -2, 0, 165, 167, 232, 64, 74, 85,
1254 69, 0, 0, 0, 37, 0, 0, 0, 0, -2,
1255 131, 0, 0, 0, 175, 175, 0, 0, 0, 0,
1256 0, 140, 141, 142, 143, 144, -2, 0, 283, 0,
1257 229, -2, 0, 0, 0, 32, 0, 0, 0, 0,
1258 0, 0, 0, -2, 54, 0, 58, 59, -2, 130,
1259 264, 0, 132, 0, -2, 0, 0, 0, 151, 0,
1260 0, 123, 0, 163, 0, 228, 278, 164, 166, 280,
1261 34, 35, 0, 0, 0, 50, 51, 52, 53, 55,
1262 0, 0, 0, 263, 127, 0, 135, 175, -2, 175,
1263 0, 123, 0, 146, -2, 155, 0, 40, 46, 49,
1264 0, 0, -2, 0, 60, 38, 0, 133, -2, 0,
1265 138, 0, 145, -2, 158, 0, 167, -2, 0, 56,
1266 57, 0, 123, 0, 136, 175, 0, 0, 156, 0,
1267 123, 0, 171, 172, 174, 149, -2, 161, 0, 139,
1268 159, 147, -2, 169, 0, 0, -2, 0, 174, -2,
1269 172, 173, 162, 137, 170,
1270};
1271yytok1 := array[] of {
1272 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1273 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1274 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1275 3, 3, 3, 64, 3, 3, 3, 36, 23, 3,
1276 39, 40, 34, 32, 99, 33, 54, 35, 3, 3,
1277 3, 3, 3, 3, 3, 3, 3, 3, 50, 72,
1278 26, 4, 27, 3, 3, 3, 3, 3, 3, 3,
1279 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1280 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1281 3, 41, 3, 42, 22, 3, 3, 3, 3, 3,
1282 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1283 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
1284 3, 3, 3, 70, 21, 71, 65,
1285};
1286yytok2 := array[] of {
1287 2, 3, 5, 6, 7, 8, 9, 10, 11, 12,
1288 13, 14, 15, 16, 17, 18, 19, 20, 24, 25,
1289 28, 29, 30, 31, 37, 38, 43, 44, 45, 46,
1290 47, 48, 49, 51, 52, 53, 55, 56, 57, 58,
1291 59, 60, 61, 62, 63, 66, 67, 68, 69, 73,
1292 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
1293 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
1294 94, 95, 96, 97, 98,
1295};
1296yytok3 := array[] of {
1297 0
1298};
1299
1300YYSys: module
1301{
1302 FD: adt
1303 {
1304 fd: int;
1305 };
1306 fildes: fn(fd: int): ref FD;
1307 fprint: fn(fd: ref FD, s: string, *): int;
1308};
1309
1310yysys: YYSys;
1311yystderr: ref YYSys->FD;
1312
1313YYFLAG: con -1000;
1314
1315# parser for yacc output
1316
1317yytokname(yyc: int): string
1318{
1319 if(yyc > 0 && yyc <= len yytoknames && yytoknames[yyc-1] != nil)
1320 return yytoknames[yyc-1];
1321 return "<"+string yyc+">";
1322}
1323
1324yystatname(yys: int): string
1325{
1326 if(yys >= 0 && yys < len yystates && yystates[yys] != nil)
1327 return yystates[yys];
1328 return "<"+string yys+">\n";
1329}
1330
1331yylex1(yylex: ref YYLEX): int
1332{
1333 c : int;
1334 yychar := yylex.lex();
1335 if(yychar <= 0)
1336 c = yytok1[0];
1337 else if(yychar < len yytok1)
1338 c = yytok1[yychar];
1339 else if(yychar >= YYPRIVATE && yychar < YYPRIVATE+len yytok2)
1340 c = yytok2[yychar-YYPRIVATE];
1341 else{
1342 n := len yytok3;
1343 c = 0;
1344 for(i := 0; i < n; i+=2) {
1345 if(yytok3[i+0] == yychar) {
1346 c = yytok3[i+1];
1347 break;
1348 }
1349 }
1350 if(c == 0)
1351 c = yytok2[1]; # unknown char
1352 }
1353 if(yydebug >= 3)
1354 yysys->fprint(yystderr, "lex %.4ux %s\n", yychar, yytokname(c));
1355 return c;
1356}
1357
1358YYS: adt
1359{
1360 yyv: YYSTYPE;
1361 yys: int;
1362};
1363
1364yyparse(yylex: ref YYLEX): int
1365{
1366 if(yydebug >= 1 && yysys == nil) {
1367 yysys = load YYSys "$Sys";
1368 yystderr = yysys->fildes(2);
1369 }
1370
1371 yys := array[YYMAXDEPTH] of YYS;
1372
1373 yyval: YYSTYPE;
1374 yystate := 0;
1375 yychar := -1;
1376 yynerrs := 0; # number of errors
1377 yyerrflag := 0; # error recovery flag
1378 yyp := -1;
1379 yyn := 0;
1380
1381yystack:
1382 for(;;){
1383 # put a state and value onto the stack
1384 if(yydebug >= 4)
1385 yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
1386
1387 yyp++;
1388 if(yyp >= len yys)
1389 yys = (array[len yys * 2] of YYS)[0:] = yys;
1390 yys[yyp].yys = yystate;
1391 yys[yyp].yyv = yyval;
1392
1393 for(;;){
1394 yyn = yypact[yystate];
1395 if(yyn > YYFLAG) { # simple state
1396 if(yychar < 0)
1397 yychar = yylex1(yylex);
1398 yyn += yychar;
1399 if(yyn >= 0 && yyn < YYLAST) {
1400 yyn = yyact[yyn];
1401 if(yychk[yyn] == yychar) { # valid shift
1402 yychar = -1;
1403 yyp++;
1404 if(yyp >= len yys)
1405 yys = (array[len yys * 2] of YYS)[0:] = yys;
1406 yystate = yyn;
1407 yys[yyp].yys = yystate;
1408 yys[yyp].yyv = yylex.lval;
1409 if(yyerrflag > 0)
1410 yyerrflag--;
1411 if(yydebug >= 4)
1412 yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
1413 continue;
1414 }
1415 }
1416 }
1417
1418 # default state action
1419 yyn = yydef[yystate];
1420 if(yyn == -2) {
1421 if(yychar < 0)
1422 yychar = yylex1(yylex);
1423
1424 # look through exception table
1425 for(yyxi:=0;; yyxi+=2)
1426 if(yyexca[yyxi] == -1 && yyexca[yyxi+1] == yystate)
1427 break;
1428 for(yyxi += 2;; yyxi += 2) {
1429 yyn = yyexca[yyxi];
1430 if(yyn < 0 || yyn == yychar)
1431 break;
1432 }
1433 yyn = yyexca[yyxi+1];
1434 if(yyn < 0){
1435 yyn = 0;
1436 break yystack;
1437 }
1438 }
1439
1440 if(yyn != 0)
1441 break;
1442
1443 # error ... attempt to resume parsing
1444 if(yyerrflag == 0) { # brand new error
1445 yylex.error("syntax error");
1446 yynerrs++;
1447 if(yydebug >= 1) {
1448 yysys->fprint(yystderr, "%s", yystatname(yystate));
1449 yysys->fprint(yystderr, "saw %s\n", yytokname(yychar));
1450 }
1451 }
1452
1453 if(yyerrflag != 3) { # incompletely recovered error ... try again
1454 yyerrflag = 3;
1455
1456 # find a state where "error" is a legal shift action
1457 while(yyp >= 0) {
1458 yyn = yypact[yys[yyp].yys] + YYERRCODE;
1459 if(yyn >= 0 && yyn < YYLAST) {
1460 yystate = yyact[yyn]; # simulate a shift of "error"
1461 if(yychk[yystate] == YYERRCODE)
1462 continue yystack;
1463 }
1464
1465 # the current yyp has no shift onn "error", pop stack
1466 if(yydebug >= 2)
1467 yysys->fprint(yystderr, "error recovery pops state %d, uncovers %d\n",
1468 yys[yyp].yys, yys[yyp-1].yys );
1469 yyp--;
1470 }
1471 # there is no state on the stack with an error shift ... abort
1472 yyn = 1;
1473 break yystack;
1474 }
1475
1476 # no shift yet; clobber input char
1477 if(yydebug >= 2)
1478 yysys->fprint(yystderr, "error recovery discards %s\n", yytokname(yychar));
1479 if(yychar == YYEOFCODE) {
1480 yyn = 1;
1481 break yystack;
1482 }
1483 yychar = -1;
1484 # try again in the same state
1485 }
1486
1487 # reduction by production yyn
1488 if(yydebug >= 2)
1489 yysys->fprint(yystderr, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
1490
1491 yypt := yyp;
1492 yyp -= yyr2[yyn];
1493# yyval = yys[yyp+1].yyv;
1494 yym := yyn;
1495
1496 # consult goto table to find next state
1497 yyn = yyr1[yyn];
1498 yyg := yypgo[yyn];
1499 yyj := yyg + yys[yyp].yys + 1;
1500
1501 if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
1502 yystate = yyact[yyg];
1503 case yym {
1504
15051=>
1506#line 153 "limbo.y"
1507{
1508 impmods = yys[yypt-1].yyv.ids;
1509 }
15102=>
1511#line 156 "limbo.y"
1512{
1513 tree = rotater(yys[yypt-0].yyv.node);
1514 }
15153=>
1516#line 160 "limbo.y"
1517{
1518 impmods = nil;
1519 tree = rotater(yys[yypt-0].yyv.node);
1520 }
15214=>
1522yyval.node = yys[yyp+1].yyv.node;
15235=>
1524#line 168 "limbo.y"
1525{
1526 if(yys[yypt-1].yyv.node == nil)
1527 yyval.node = yys[yypt-0].yyv.node;
1528 else if(yys[yypt-0].yyv.node == nil)
1529 yyval.node = yys[yypt-1].yyv.node;
1530 else
1531 yyval.node = mkbin(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
1532 }
15336=>
1534#line 179 "limbo.y"
1535{
1536 yyval.node = nil;
1537 }
15387=>
1539yyval.node = yys[yyp+1].yyv.node;
15408=>
1541yyval.node = yys[yyp+1].yyv.node;
15429=>
1543yyval.node = yys[yyp+1].yyv.node;
154410=>
1545yyval.node = yys[yyp+1].yyv.node;
154611=>
1547#line 187 "limbo.y"
1548{
1549 yyval.node = mkbin(Oas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1550 }
155112=>
1552#line 191 "limbo.y"
1553{
1554 yyval.node = mkbin(Oas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1555 }
155613=>
1557#line 195 "limbo.y"
1558{
1559 yyval.node = mkbin(Odas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1560 }
156114=>
1562#line 199 "limbo.y"
1563{
1564 yyval.node = mkbin(Odas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1565 }
156615=>
1567#line 203 "limbo.y"
1568{
1569 yyerror("illegal declaration");
1570 yyval.node = nil;
1571 }
157216=>
1573#line 208 "limbo.y"
1574{
1575 yyerror("illegal declaration");
1576 yyval.node = nil;
1577 }
157817=>
1579yyval.node = yys[yyp+1].yyv.node;
158018=>
1581#line 216 "limbo.y"
1582{
1583 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
1584 }
158519=>
1586#line 222 "limbo.y"
1587{
1588 includef(yys[yypt-1].yyv.tok.v.idval);
1589 yyval.node = nil;
1590 }
159120=>
1592#line 227 "limbo.y"
1593{
1594 yyval.node = typedecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.ty);
1595 }
159621=>
1597#line 231 "limbo.y"
1598{
1599 yyval.node = importdecl(yys[yypt-1].yyv.node, yys[yypt-4].yyv.ids);
1600 yyval.node.src.start = yys[yypt-4].yyv.ids.src.start;
1601 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
1602 }
160322=>
1604#line 237 "limbo.y"
1605{
1606 yyval.node = vardecl(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty);
1607 }
160823=>
1609#line 241 "limbo.y"
1610{
1611 yyval.node = mkbin(Ovardecli, vardecl(yys[yypt-5].yyv.ids, yys[yypt-3].yyv.ty), varinit(yys[yypt-5].yyv.ids, yys[yypt-1].yyv.node));
1612 }
161324=>
1614#line 245 "limbo.y"
1615{
1616 yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1617 }
161825=>
1619yyval.node = yys[yyp+1].yyv.node;
162026=>
1621#line 252 "limbo.y"
1622{
1623 yyval.node = exdecl(yys[yypt-3].yyv.ids, nil);
1624 }
162527=>
1626#line 256 "limbo.y"
1627{
1628 yyval.node = exdecl(yys[yypt-6].yyv.ids, revids(yys[yypt-2].yyv.ids));
1629 }
163028=>
1631#line 262 "limbo.y"
1632{
1633 yys[yypt-5].yyv.ids.src.stop = yys[yypt-0].yyv.tok.src.stop;
1634 yyval.node = moddecl(yys[yypt-5].yyv.ids, rotater(yys[yypt-1].yyv.node));
1635 }
163629=>
1637#line 269 "limbo.y"
1638{
1639 yyval.node = nil;
1640 }
164130=>
1642#line 273 "limbo.y"
1643{
1644 if(yys[yypt-1].yyv.node == nil)
1645 yyval.node = yys[yypt-0].yyv.node;
1646 else if(yys[yypt-0].yyv.node == nil)
1647 yyval.node = yys[yypt-1].yyv.node;
1648 else
1649 yyval.node = mkn(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
1650 }
165131=>
1652#line 282 "limbo.y"
1653{
1654 yyval.node = nil;
1655 }
165632=>
1657#line 288 "limbo.y"
1658{
1659 yyval.node = fielddecl(Dglobal, typeids(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty));
1660 }
166133=>
1662yyval.node = yys[yyp+1].yyv.node;
166334=>
1664#line 293 "limbo.y"
1665{
1666 yyval.node = typedecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.ty);
1667 }
166835=>
1669#line 297 "limbo.y"
1670{
1671 yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1672 }
167336=>
1674yyval.node = yys[yyp+1].yyv.node;
167537=>
1676#line 304 "limbo.y"
1677{
1678 yys[yypt-7].yyv.ids.src.stop = yys[yypt-1].yyv.tok.src.stop;
1679 yyval.node = adtdecl(yys[yypt-7].yyv.ids, rotater(yys[yypt-2].yyv.node));
1680 yyval.node.ty.polys = yys[yypt-4].yyv.ids;
1681 yyval.node.ty.val = rotater(yys[yypt-0].yyv.node);
1682 }
168338=>
1684#line 311 "limbo.y"
1685{
1686 yys[yypt-10].yyv.ids.src.stop = yys[yypt-0].yyv.tok.src.stop;
1687 yyval.node = adtdecl(yys[yypt-10].yyv.ids, rotater(yys[yypt-1].yyv.node));
1688 yyval.node.ty.polys = yys[yypt-7].yyv.ids;
1689 yyval.node.ty.val = rotater(yys[yypt-4].yyv.node);
1690 }
169139=>
1692#line 320 "limbo.y"
1693{
1694 yyval.node = nil;
1695 }
169640=>
1697#line 324 "limbo.y"
1698{
1699 yyval.node = yys[yypt-1].yyv.node;
1700 }
170141=>
1702#line 330 "limbo.y"
1703{
1704 yyval.node = nil;
1705 }
170642=>
1707#line 334 "limbo.y"
1708{
1709 if(yys[yypt-1].yyv.node == nil)
1710 yyval.node = yys[yypt-0].yyv.node;
1711 else if(yys[yypt-0].yyv.node == nil)
1712 yyval.node = yys[yypt-1].yyv.node;
1713 else
1714 yyval.node = mkn(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
1715 }
171643=>
1717#line 343 "limbo.y"
1718{
1719 yyval.node = nil;
1720 }
172144=>
1722yyval.node = yys[yyp+1].yyv.node;
172345=>
1724yyval.node = yys[yyp+1].yyv.node;
172546=>
1726#line 351 "limbo.y"
1727{
1728 yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1729 }
173047=>
1731#line 357 "limbo.y"
1732{
1733 yyval.node = nil;
1734 }
173548=>
1736#line 361 "limbo.y"
1737{
1738 if(yys[yypt-1].yyv.node == nil)
1739 yyval.node = yys[yypt-0].yyv.node;
1740 else if(yys[yypt-0].yyv.node == nil)
1741 yyval.node = yys[yypt-1].yyv.node;
1742 else
1743 yyval.node = mkn(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
1744 }
174549=>
1746#line 372 "limbo.y"
1747{
1748 for(d := yys[yypt-4].yyv.ids; d != nil; d = d.next)
1749 d.cyc = byte 1;
1750 yyval.node = fielddecl(Dfield, typeids(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.ty));
1751 }
175250=>
1753#line 378 "limbo.y"
1754{
1755 yyval.node = fielddecl(Dfield, typeids(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty));
1756 }
175751=>
1758#line 384 "limbo.y"
1759{
1760 yyval.node = yys[yypt-1].yyv.node;
1761 }
176252=>
1763#line 390 "limbo.y"
1764{
1765 yys[yypt-1].yyv.node.right.right = yys[yypt-0].yyv.node;
1766 yyval.node = yys[yypt-1].yyv.node;
1767 }
176853=>
1769#line 395 "limbo.y"
1770{
1771 yyval.node = nil;
1772 }
177354=>
1774#line 399 "limbo.y"
1775{
1776 yyval.node = nil;
1777 }
177855=>
1779#line 405 "limbo.y"
1780{
1781 yyval.node = mkn(Opickdecl, nil, mkn(Oseq, fielddecl(Dtag, yys[yypt-1].yyv.ids), nil));
1782 typeids(yys[yypt-1].yyv.ids, mktype(yys[yypt-1].yyv.ids.src.start, yys[yypt-1].yyv.ids.src.stop, Tadtpick, nil, nil));
1783 }
178456=>
1785#line 410 "limbo.y"
1786{
1787 yys[yypt-3].yyv.node.right.right = yys[yypt-2].yyv.node;
1788 yyval.node = mkn(Opickdecl, yys[yypt-3].yyv.node, mkn(Oseq, fielddecl(Dtag, yys[yypt-1].yyv.ids), nil));
1789 typeids(yys[yypt-1].yyv.ids, mktype(yys[yypt-1].yyv.ids.src.start, yys[yypt-1].yyv.ids.src.stop, Tadtpick, nil, nil));
1790 }
179157=>
1792#line 416 "limbo.y"
1793{
1794 yyval.node = mkn(Opickdecl, nil, mkn(Oseq, fielddecl(Dtag, yys[yypt-1].yyv.ids), nil));
1795 typeids(yys[yypt-1].yyv.ids, mktype(yys[yypt-1].yyv.ids.src.start, yys[yypt-1].yyv.ids.src.stop, Tadtpick, nil, nil));
1796 }
179758=>
1798#line 423 "limbo.y"
1799{
1800 yyval.ids = revids(yys[yypt-0].yyv.ids);
1801 }
180259=>
1803#line 429 "limbo.y"
1804{
1805 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, nil);
1806 }
180760=>
1808#line 433 "limbo.y"
1809{
1810 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, yys[yypt-2].yyv.ids);
1811 }
181261=>
1813#line 439 "limbo.y"
1814{
1815 yyval.ids = revids(yys[yypt-0].yyv.ids);
1816 }
181762=>
1818#line 445 "limbo.y"
1819{
1820 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, nil);
1821 }
182263=>
1823#line 449 "limbo.y"
1824{
1825 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, yys[yypt-2].yyv.ids);
1826 }
182764=>
1828#line 455 "limbo.y"
1829{
1830 yyval.ty = mktype(yys[yypt-5].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tfix, nil, nil);
1831 yyval.ty.val = mkbin(Oseq, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1832 }
183365=>
1834#line 460 "limbo.y"
1835{
1836 yyval.ty = mktype(yys[yypt-3].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tfix, nil, nil);
1837 yyval.ty.val = yys[yypt-1].yyv.node;
1838 }
183966=>
1840#line 467 "limbo.y"
1841{
1842 yyval.types = addtype(yys[yypt-0].yyv.ty, nil);
1843 }
184467=>
1845#line 471 "limbo.y"
1846{
1847 yyval.types = addtype(yys[yypt-0].yyv.ty, nil);
1848 yys[yypt-0].yyv.ty.flags |= CYCLIC;
1849 }
185068=>
1851#line 476 "limbo.y"
1852{
1853 yyval.types = addtype(yys[yypt-0].yyv.ty, yys[yypt-2].yyv.types);
1854 }
185569=>
1856#line 480 "limbo.y"
1857{
1858 yyval.types = addtype(yys[yypt-0].yyv.ty, yys[yypt-3].yyv.types);
1859 yys[yypt-0].yyv.ty.flags |= CYCLIC;
1860 }
186170=>
1862#line 487 "limbo.y"
1863{
1864 yyval.ty = mkidtype(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
1865 }
186671=>
1867#line 491 "limbo.y"
1868{
1869 yyval.ty = yys[yypt-0].yyv.ty;
1870 }
187172=>
1872#line 495 "limbo.y"
1873{
1874 yyval.ty = yys[yypt-0].yyv.ty;
1875 }
187673=>
1877#line 499 "limbo.y"
1878{
1879 yyval.ty = mkarrowtype(yys[yypt-2].yyv.ty.src.start, yys[yypt-0].yyv.tok.src.stop, yys[yypt-2].yyv.ty, yys[yypt-0].yyv.tok.v.idval);
1880 }
188174=>
1882#line 503 "limbo.y"
1883{
1884 yyval.ty = mkarrowtype(yys[yypt-5].yyv.ty.src.start, yys[yypt-3].yyv.tok.src.stop, yys[yypt-5].yyv.ty, yys[yypt-3].yyv.tok.v.idval);
1885 yyval.ty = mkinsttype(yys[yypt-5].yyv.ty.src, yyval.ty, yys[yypt-1].yyv.types);
1886 }
188775=>
1888#line 508 "limbo.y"
1889{
1890 yyval.ty = mktype(yys[yypt-1].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tref, yys[yypt-0].yyv.ty, nil);
1891 }
189276=>
1893#line 512 "limbo.y"
1894{
1895 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tchan, yys[yypt-0].yyv.ty, nil);
1896 }
189777=>
1898#line 516 "limbo.y"
1899{
1900 if(yys[yypt-1].yyv.ids.next == nil)
1901 yyval.ty = yys[yypt-1].yyv.ids.ty;
1902 else
1903 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Ttuple, nil, revids(yys[yypt-1].yyv.ids));
1904 }
190578=>
1906#line 523 "limbo.y"
1907{
1908 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tarray, yys[yypt-0].yyv.ty, nil);
1909 }
191079=>
1911#line 527 "limbo.y"
1912{
1913 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tlist, yys[yypt-0].yyv.ty, nil);
1914 }
191580=>
1916#line 531 "limbo.y"
1917{
1918 yys[yypt-1].yyv.ty.src.start = yys[yypt-3].yyv.tok.src.start;
1919 yys[yypt-1].yyv.ty.polys = yys[yypt-2].yyv.ids;
1920 yys[yypt-1].yyv.ty.eraises = yys[yypt-0].yyv.node;
1921 yyval.ty = yys[yypt-1].yyv.ty;
1922 }
192381=>
1924yyval.ty = yys[yyp+1].yyv.ty;
192582=>
1926#line 551 "limbo.y"
1927{
1928 yyval.ty = mkidtype(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
1929 }
193083=>
1931#line 555 "limbo.y"
1932{
1933 yyval.ty = mkinsttype(yys[yypt-3].yyv.tok.src, mkidtype(yys[yypt-3].yyv.tok.src, yys[yypt-3].yyv.tok.v.idval), yys[yypt-1].yyv.types);
1934 }
193584=>
1936#line 561 "limbo.y"
1937{
1938 yyval.ty = mkdottype(yys[yypt-2].yyv.ty.src.start, yys[yypt-0].yyv.tok.src.stop, yys[yypt-2].yyv.ty, yys[yypt-0].yyv.tok.v.idval);
1939 }
194085=>
1941#line 565 "limbo.y"
1942{
1943 yyval.ty = mkdottype(yys[yypt-5].yyv.ty.src.start, yys[yypt-3].yyv.tok.src.stop, yys[yypt-5].yyv.ty, yys[yypt-3].yyv.tok.v.idval);
1944 yyval.ty = mkinsttype(yys[yypt-5].yyv.ty.src, yyval.ty, yys[yypt-1].yyv.types);
1945 }
194686=>
1947#line 572 "limbo.y"
1948{
1949 yyval.ids = mkids(yys[yypt-0].yyv.ty.src, nil, yys[yypt-0].yyv.ty, nil);
1950 }
195187=>
1952#line 576 "limbo.y"
1953{
1954 yyval.ids = mkids(yys[yypt-2].yyv.ids.src, nil, yys[yypt-0].yyv.ty, yys[yypt-2].yyv.ids);
1955 }
195688=>
1957#line 582 "limbo.y"
1958{
1959 yyval.ids = nil;
1960 }
196189=>
1962#line 586 "limbo.y"
1963{
1964 yyval.ids = polydecl(yys[yypt-1].yyv.ids);
1965 }
196690=>
1967#line 592 "limbo.y"
1968{
1969 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tfn, tnone, yys[yypt-1].yyv.ids);
1970 }
197191=>
1972#line 596 "limbo.y"
1973{
1974 yyval.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tfn, tnone, nil);
1975 yyval.ty.varargs = byte 1;
1976 }
197792=>
1978#line 601 "limbo.y"
1979{
1980 yyval.ty = mktype(yys[yypt-4].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tfn, tnone, yys[yypt-3].yyv.ids);
1981 yyval.ty.varargs = byte 1;
1982 }
198393=>
1984#line 608 "limbo.y"
1985{
1986 yyval.ty = yys[yypt-0].yyv.ty;
1987 }
198894=>
1989#line 612 "limbo.y"
1990{
1991 yys[yypt-2].yyv.ty.tof = yys[yypt-0].yyv.ty;
1992 yys[yypt-2].yyv.ty.src.stop = yys[yypt-0].yyv.ty.src.stop;
1993 yyval.ty = yys[yypt-2].yyv.ty;
1994 }
199595=>
1996#line 620 "limbo.y"
1997{
1998 yyval.ty = yys[yypt-0].yyv.ty;
1999 }
200096=>
2001#line 624 "limbo.y"
2002{
2003 yyval.ty = yys[yypt-4].yyv.ty;
2004 yyval.ty.val = rotater(yys[yypt-1].yyv.node);
2005 }
200697=>
2007#line 631 "limbo.y"
2008{
2009 yyval.ids = nil;
2010 }
201198=>
2012yyval.ids = yys[yyp+1].yyv.ids;
201399=>
2014yyval.ids = yys[yyp+1].yyv.ids;
2015100=>
2016#line 639 "limbo.y"
2017{
2018 yyval.ids = appdecls(yys[yypt-2].yyv.ids, yys[yypt-0].yyv.ids);
2019 }
2020101=>
2021#line 645 "limbo.y"
2022{
2023 yyval.ids = typeids(yys[yypt-2].yyv.ids, yys[yypt-0].yyv.ty);
2024 }
2025102=>
2026#line 649 "limbo.y"
2027{
2028 yyval.ids = typeids(yys[yypt-2].yyv.ids, yys[yypt-0].yyv.ty);
2029 for(d := yyval.ids; d != nil; d = d.next)
2030 d.implicit = byte 1;
2031 }
2032103=>
2033#line 655 "limbo.y"
2034{
2035 yyval.ids = mkids(yys[yypt-2].yyv.node.src, enter("junk", 0), yys[yypt-0].yyv.ty, nil);
2036 yyval.ids.store = Darg;
2037 yyerror("illegal argument declaraion");
2038 }
2039104=>
2040#line 661 "limbo.y"
2041{
2042 yyval.ids = mkids(yys[yypt-2].yyv.node.src, enter("junk", 0), yys[yypt-0].yyv.ty, nil);
2043 yyval.ids.store = Darg;
2044 yyerror("illegal argument declaraion");
2045 }
2046105=>
2047#line 669 "limbo.y"
2048{
2049 yyval.ids = revids(yys[yypt-0].yyv.ids);
2050 }
2051106=>
2052#line 675 "limbo.y"
2053{
2054 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, nil);
2055 yyval.ids.store = Darg;
2056 }
2057107=>
2058#line 680 "limbo.y"
2059{
2060 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, nil, nil, nil);
2061 yyval.ids.store = Darg;
2062 }
2063108=>
2064#line 685 "limbo.y"
2065{
2066 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, yys[yypt-2].yyv.ids);
2067 yyval.ids.store = Darg;
2068 }
2069109=>
2070#line 690 "limbo.y"
2071{
2072 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, nil, nil, yys[yypt-2].yyv.ids);
2073 yyval.ids.store = Darg;
2074 }
2075110=>
2076#line 697 "limbo.y"
2077{
2078 yyval.ty = yys[yypt-0].yyv.ty;
2079 }
2080111=>
2081#line 701 "limbo.y"
2082{
2083 yyval.ty = mktype(yys[yypt-1].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tref, yys[yypt-0].yyv.ty, nil);
2084 }
2085112=>
2086#line 705 "limbo.y"
2087{
2088 yyval.ty = yys[yypt-0].yyv.ty;
2089 }
2090113=>
2091#line 709 "limbo.y"
2092{
2093 yyval.ty = mktype(yys[yypt-1].yyv.tok.src.start, yys[yypt-0].yyv.tok.src.stop, Tref, yys[yypt-0].yyv.ty, nil);
2094 }
2095114=>
2096#line 715 "limbo.y"
2097{
2098 yyval.node = fndecl(yys[yypt-3].yyv.node, yys[yypt-2].yyv.ty, yys[yypt-0].yyv.node);
2099 nfns++;
2100 # patch up polydecs
2101 if(yys[yypt-3].yyv.node.op == Odot){
2102 if(yys[yypt-3].yyv.node.right.left != nil){
2103 yys[yypt-2].yyv.ty.polys = yys[yypt-3].yyv.node.right.left.decl;
2104 yys[yypt-3].yyv.node.right.left = nil;
2105 }
2106 if(yys[yypt-3].yyv.node.left.op == Oname && yys[yypt-3].yyv.node.left.left != nil){
2107 yyval.node.decl = yys[yypt-3].yyv.node.left.left.decl;
2108 yys[yypt-3].yyv.node.left.left = nil;
2109 }
2110 }
2111 else{
2112 if(yys[yypt-3].yyv.node.left != nil){
2113 yys[yypt-2].yyv.ty.polys = yys[yypt-3].yyv.node.left.decl;
2114 yys[yypt-3].yyv.node.left = nil;
2115 }
2116 }
2117 yys[yypt-2].yyv.ty.eraises = yys[yypt-1].yyv.node;
2118 yyval.node.src = yys[yypt-3].yyv.node.src;
2119 }
2120115=>
2121#line 741 "limbo.y"
2122{
2123 yyval.node = mkn(Otuple, rotater(yys[yypt-1].yyv.node), nil);
2124 yyval.node.src.start = yys[yypt-3].yyv.tok.src.start;
2125 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2126 }
2127116=>
2128#line 747 "limbo.y"
2129{
2130 yyval.node = mkn(Otuple, mkunary(Oseq, yys[yypt-0].yyv.node), nil);
2131 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2132 yyval.node.src.stop = yys[yypt-0].yyv.node.src.stop;
2133 }
2134117=>
2135#line 753 "limbo.y"
2136{
2137 yyval.node = nil;
2138 }
2139118=>
2140#line 759 "limbo.y"
2141{
2142 if(yys[yypt-1].yyv.node == nil){
2143 yys[yypt-1].yyv.node = mkn(Onothing, nil, nil);
2144 yys[yypt-1].yyv.node.src.start = curline();
2145 yys[yypt-1].yyv.node.src.stop = yys[yypt-1].yyv.node.src.start;
2146 }
2147 yyval.node = rotater(yys[yypt-1].yyv.node);
2148 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2149 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2150 }
2151119=>
2152#line 770 "limbo.y"
2153{
2154 yyval.node = mkn(Onothing, nil, nil);
2155 }
2156120=>
2157#line 774 "limbo.y"
2158{
2159 yyval.node = mkn(Onothing, nil, nil);
2160 }
2161121=>
2162#line 780 "limbo.y"
2163{
2164 yyval.node = mkname(yys[yypt-1].yyv.tok.src, yys[yypt-1].yyv.tok.v.idval);
2165 if(yys[yypt-0].yyv.ids != nil){
2166 yyval.node.left = mkn(Onothing, nil ,nil);
2167 yyval.node.left.decl = yys[yypt-0].yyv.ids;
2168 }
2169 }
2170122=>
2171#line 788 "limbo.y"
2172{
2173 yyval.node = mkbin(Odot, yys[yypt-3].yyv.node, mkname(yys[yypt-1].yyv.tok.src, yys[yypt-1].yyv.tok.v.idval));
2174 if(yys[yypt-0].yyv.ids != nil){
2175 yyval.node.right.left = mkn(Onothing, nil ,nil);
2176 yyval.node.right.left.decl = yys[yypt-0].yyv.ids;
2177 }
2178 }
2179123=>
2180#line 798 "limbo.y"
2181{
2182 yyval.node = nil;
2183 }
2184124=>
2185#line 802 "limbo.y"
2186{
2187 if(yys[yypt-1].yyv.node == nil)
2188 yyval.node = yys[yypt-0].yyv.node;
2189 else if(yys[yypt-0].yyv.node == nil)
2190 yyval.node = yys[yypt-1].yyv.node;
2191 else
2192 yyval.node = mkbin(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
2193 }
2194125=>
2195#line 811 "limbo.y"
2196{
2197 if(yys[yypt-1].yyv.node == nil)
2198 yyval.node = yys[yypt-0].yyv.node;
2199 else
2200 yyval.node = mkbin(Oseq, yys[yypt-1].yyv.node, yys[yypt-0].yyv.node);
2201 }
2202128=>
2203#line 824 "limbo.y"
2204{
2205 yyval.node = mkn(Onothing, nil, nil);
2206 yyval.node.src.start = curline();
2207 yyval.node.src.stop = yyval.node.src.start;
2208 }
2209129=>
2210#line 830 "limbo.y"
2211{
2212 yyval.node = mkn(Onothing, nil, nil);
2213 yyval.node.src.start = curline();
2214 yyval.node.src.stop = yyval.node.src.start;
2215 }
2216130=>
2217#line 836 "limbo.y"
2218{
2219 yyval.node = mkn(Onothing, nil, nil);
2220 yyval.node.src.start = curline();
2221 yyval.node.src.stop = yyval.node.src.start;
2222 }
2223131=>
2224#line 842 "limbo.y"
2225{
2226 if(yys[yypt-1].yyv.node == nil){
2227 yys[yypt-1].yyv.node = mkn(Onothing, nil, nil);
2228 yys[yypt-1].yyv.node.src.start = curline();
2229 yys[yypt-1].yyv.node.src.stop = yys[yypt-1].yyv.node.src.start;
2230 }
2231 yyval.node = mkscope(rotater(yys[yypt-1].yyv.node));
2232 }
2233132=>
2234#line 851 "limbo.y"
2235{
2236 yyerror("illegal declaration");
2237 yyval.node = mkn(Onothing, nil, nil);
2238 yyval.node.src.start = curline();
2239 yyval.node.src.stop = yyval.node.src.start;
2240 }
2241133=>
2242#line 858 "limbo.y"
2243{
2244 yyerror("illegal declaration");
2245 yyval.node = mkn(Onothing, nil, nil);
2246 yyval.node.src.start = curline();
2247 yyval.node.src.stop = yyval.node.src.start;
2248 }
2249134=>
2250#line 865 "limbo.y"
2251{
2252 yyval.node = yys[yypt-1].yyv.node;
2253 }
2254135=>
2255#line 869 "limbo.y"
2256{
2257 yyval.node = mkn(Oif, yys[yypt-2].yyv.node, mkunary(Oseq, yys[yypt-0].yyv.node));
2258 yyval.node.src.start = yys[yypt-4].yyv.tok.src.start;
2259 yyval.node.src.stop = yys[yypt-0].yyv.node.src.stop;
2260 }
2261136=>
2262#line 875 "limbo.y"
2263{
2264 yyval.node = mkn(Oif, yys[yypt-4].yyv.node, mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node));
2265 yyval.node.src.start = yys[yypt-6].yyv.tok.src.start;
2266 yyval.node.src.stop = yys[yypt-0].yyv.node.src.stop;
2267 }
2268137=>
2269#line 881 "limbo.y"
2270{
2271 yyval.node = mkunary(Oseq, yys[yypt-0].yyv.node);
2272 if(yys[yypt-2].yyv.node.op != Onothing)
2273 yyval.node.right = yys[yypt-2].yyv.node;
2274 yyval.node = mkbin(Ofor, yys[yypt-4].yyv.node, yyval.node);
2275 yyval.node.decl = yys[yypt-9].yyv.ids;
2276 if(yys[yypt-6].yyv.node.op != Onothing)
2277 yyval.node = mkbin(Oseq, yys[yypt-6].yyv.node, yyval.node);
2278 }
2279138=>
2280#line 891 "limbo.y"
2281{
2282 yyval.node = mkn(Ofor, yys[yypt-2].yyv.node, mkunary(Oseq, yys[yypt-0].yyv.node));
2283 yyval.node.src.start = yys[yypt-4].yyv.tok.src.start;
2284 yyval.node.src.stop = yys[yypt-0].yyv.node.src.stop;
2285 yyval.node.decl = yys[yypt-5].yyv.ids;
2286 }
2287139=>
2288#line 898 "limbo.y"
2289{
2290 yyval.node = mkn(Odo, yys[yypt-2].yyv.node, yys[yypt-5].yyv.node);
2291 yyval.node.src.start = yys[yypt-6].yyv.tok.src.start;
2292 yyval.node.src.stop = yys[yypt-1].yyv.tok.src.stop;
2293 yyval.node.decl = yys[yypt-7].yyv.ids;
2294 }
2295140=>
2296#line 905 "limbo.y"
2297{
2298 yyval.node = mkn(Obreak, nil, nil);
2299 yyval.node.decl = yys[yypt-1].yyv.ids;
2300 yyval.node.src = yys[yypt-2].yyv.tok.src;
2301 }
2302141=>
2303#line 911 "limbo.y"
2304{
2305 yyval.node = mkn(Ocont, nil, nil);
2306 yyval.node.decl = yys[yypt-1].yyv.ids;
2307 yyval.node.src = yys[yypt-2].yyv.tok.src;
2308 }
2309142=>
2310#line 917 "limbo.y"
2311{
2312 yyval.node = mkn(Oret, yys[yypt-1].yyv.node, nil);
2313 yyval.node.src = yys[yypt-2].yyv.tok.src;
2314 if(yys[yypt-1].yyv.node.op == Onothing)
2315 yyval.node.left = nil;
2316 else
2317 yyval.node.src.stop = yys[yypt-1].yyv.node.src.stop;
2318 }
2319143=>
2320#line 926 "limbo.y"
2321{
2322 yyval.node = mkn(Ospawn, yys[yypt-1].yyv.node, nil);
2323 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2324 yyval.node.src.stop = yys[yypt-1].yyv.node.src.stop;
2325 }
2326144=>
2327#line 932 "limbo.y"
2328{
2329 yyval.node = mkn(Oraise, yys[yypt-1].yyv.node, nil);
2330 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2331 yyval.node.src.stop = yys[yypt-1].yyv.node.src.stop;
2332 }
2333145=>
2334#line 938 "limbo.y"
2335{
2336 yyval.node = mkn(Ocase, yys[yypt-3].yyv.node, caselist(yys[yypt-1].yyv.node, nil));
2337 yyval.node.src = yys[yypt-3].yyv.node.src;
2338 yyval.node.decl = yys[yypt-5].yyv.ids;
2339 }
2340146=>
2341#line 944 "limbo.y"
2342{
2343 yyval.node = mkn(Oalt, caselist(yys[yypt-1].yyv.node, nil), nil);
2344 yyval.node.src = yys[yypt-3].yyv.tok.src;
2345 yyval.node.decl = yys[yypt-4].yyv.ids;
2346 }
2347147=>
2348#line 950 "limbo.y"
2349{
2350 yyval.node = mkn(Opick, mkbin(Odas, mkname(yys[yypt-5].yyv.tok.src, yys[yypt-5].yyv.tok.v.idval), yys[yypt-3].yyv.node), caselist(yys[yypt-1].yyv.node, nil));
2351 yyval.node.src.start = yys[yypt-5].yyv.tok.src.start;
2352 yyval.node.src.stop = yys[yypt-3].yyv.node.src.stop;
2353 yyval.node.decl = yys[yypt-7].yyv.ids;
2354 }
2355148=>
2356#line 957 "limbo.y"
2357{
2358 yyval.node = mkn(Oexit, nil, nil);
2359 yyval.node.src = yys[yypt-1].yyv.tok.src;
2360 }
2361149=>
2362#line 962 "limbo.y"
2363{
2364 if(yys[yypt-6].yyv.node == nil){
2365 yys[yypt-6].yyv.node = mkn(Onothing, nil, nil);
2366 yys[yypt-6].yyv.node.src.start = yys[yypt-6].yyv.node.src.stop = curline();
2367 }
2368 yys[yypt-6].yyv.node = mkscope(rotater(yys[yypt-6].yyv.node));
2369 yyval.node = mkbin(Oexstmt, yys[yypt-6].yyv.node, mkn(Oexcept, yys[yypt-3].yyv.node, caselist(yys[yypt-1].yyv.node, nil)));
2370 }
2371150=>
2372#line 977 "limbo.y"
2373{
2374 yyval.ids = nil;
2375 }
2376151=>
2377#line 981 "limbo.y"
2378{
2379 if(yys[yypt-1].yyv.ids.next != nil)
2380 yyerror("only one identifier allowed in a label");
2381 yyval.ids = yys[yypt-1].yyv.ids;
2382 }
2383152=>
2384#line 989 "limbo.y"
2385{
2386 yyval.ids = nil;
2387 }
2388153=>
2389#line 993 "limbo.y"
2390{
2391 yyval.ids = mkids(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval, nil, nil);
2392 }
2393154=>
2394#line 999 "limbo.y"
2395{
2396 yys[yypt-1].yyv.node.left.right.right = yys[yypt-0].yyv.node;
2397 yyval.node = yys[yypt-1].yyv.node;
2398 }
2399155=>
2400#line 1006 "limbo.y"
2401{
2402 yyval.node = mkunary(Oseq, mkscope(mkunary(Olabel, rotater(yys[yypt-1].yyv.node))));
2403 }
2404156=>
2405#line 1010 "limbo.y"
2406{
2407 yys[yypt-3].yyv.node.left.right.right = yys[yypt-2].yyv.node;
2408 yyval.node = mkbin(Oseq, mkscope(mkunary(Olabel, rotater(yys[yypt-1].yyv.node))), yys[yypt-3].yyv.node);
2409 }
2410157=>
2411#line 1017 "limbo.y"
2412{
2413 yys[yypt-1].yyv.node.left.right = mkscope(yys[yypt-0].yyv.node);
2414 yyval.node = yys[yypt-1].yyv.node;
2415 }
2416158=>
2417#line 1024 "limbo.y"
2418{
2419 yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2420 }
2421159=>
2422#line 1028 "limbo.y"
2423{
2424 yys[yypt-3].yyv.node.left.right = mkscope(yys[yypt-2].yyv.node);
2425 yyval.node = mkbin(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)), yys[yypt-3].yyv.node);
2426 }
2427160=>
2428#line 1035 "limbo.y"
2429{
2430 yys[yypt-1].yyv.node.left.right = mkscope(yys[yypt-0].yyv.node);
2431 yyval.node = yys[yypt-1].yyv.node;
2432 }
2433161=>
2434#line 1042 "limbo.y"
2435{
2436 yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2437 }
2438162=>
2439#line 1046 "limbo.y"
2440{
2441 yys[yypt-3].yyv.node.left.right = mkscope(yys[yypt-2].yyv.node);
2442 yyval.node = mkbin(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)), yys[yypt-3].yyv.node);
2443 }
2444163=>
2445yyval.node = yys[yyp+1].yyv.node;
2446164=>
2447#line 1054 "limbo.y"
2448{
2449 yyval.node = mkbin(Orange, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2450 }
2451165=>
2452#line 1058 "limbo.y"
2453{
2454 yyval.node = mkn(Owild, nil, nil);
2455 yyval.node.src = yys[yypt-0].yyv.tok.src;
2456 }
2457166=>
2458#line 1063 "limbo.y"
2459{
2460 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2461 }
2462167=>
2463#line 1067 "limbo.y"
2464{
2465 yyval.node = mkn(Onothing, nil, nil);
2466 yyval.node.src.start = curline();
2467 yyval.node.src.stop = yyval.node.src.start;
2468 }
2469168=>
2470#line 1075 "limbo.y"
2471{
2472 yys[yypt-1].yyv.node.left.right = mkscope(yys[yypt-0].yyv.node);
2473 yyval.node = yys[yypt-1].yyv.node;
2474 }
2475169=>
2476#line 1082 "limbo.y"
2477{
2478 yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2479 }
2480170=>
2481#line 1086 "limbo.y"
2482{
2483 yys[yypt-3].yyv.node.left.right = mkscope(yys[yypt-2].yyv.node);
2484 yyval.node = mkbin(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)), yys[yypt-3].yyv.node);
2485 }
2486171=>
2487#line 1093 "limbo.y"
2488{
2489 yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2490 }
2491172=>
2492#line 1097 "limbo.y"
2493{
2494 yyval.node = mkn(Owild, nil, nil);
2495 yyval.node.src = yys[yypt-0].yyv.tok.src;
2496 }
2497173=>
2498#line 1102 "limbo.y"
2499{
2500 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2501 }
2502174=>
2503#line 1106 "limbo.y"
2504{
2505 yyval.node = mkn(Onothing, nil, nil);
2506 yyval.node.src.start = curline();
2507 yyval.node.src.stop = yyval.node.src.start;
2508 }
2509175=>
2510#line 1114 "limbo.y"
2511{
2512 yyval.node = mkn(Onothing, nil, nil);
2513 yyval.node.src.start = curline();
2514 yyval.node.src.stop = yyval.node.src.start;
2515 }
2516176=>
2517yyval.node = yys[yyp+1].yyv.node;
2518177=>
2519yyval.node = yys[yyp+1].yyv.node;
2520178=>
2521#line 1124 "limbo.y"
2522{
2523 yyval.node = mkbin(Oas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2524 }
2525179=>
2526#line 1128 "limbo.y"
2527{
2528 yyval.node = mkbin(Oandas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2529 }
2530180=>
2531#line 1132 "limbo.y"
2532{
2533 yyval.node = mkbin(Ooras, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2534 }
2535181=>
2536#line 1136 "limbo.y"
2537{
2538 yyval.node = mkbin(Oxoras, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2539 }
2540182=>
2541#line 1140 "limbo.y"
2542{
2543 yyval.node = mkbin(Olshas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2544 }
2545183=>
2546#line 1144 "limbo.y"
2547{
2548 yyval.node = mkbin(Orshas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2549 }
2550184=>
2551#line 1148 "limbo.y"
2552{
2553 yyval.node = mkbin(Oaddas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2554 }
2555185=>
2556#line 1152 "limbo.y"
2557{
2558 yyval.node = mkbin(Osubas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2559 }
2560186=>
2561#line 1156 "limbo.y"
2562{
2563 yyval.node = mkbin(Omulas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2564 }
2565187=>
2566#line 1160 "limbo.y"
2567{
2568 yyval.node = mkbin(Odivas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2569 }
2570188=>
2571#line 1164 "limbo.y"
2572{
2573 yyval.node = mkbin(Omodas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2574 }
2575189=>
2576#line 1168 "limbo.y"
2577{
2578 yyval.node = mkbin(Oexpas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2579 }
2580190=>
2581#line 1172 "limbo.y"
2582{
2583 yyval.node = mkbin(Osnd, yys[yypt-3].yyv.node, yys[yypt-0].yyv.node);
2584 }
2585191=>
2586#line 1176 "limbo.y"
2587{
2588 yyval.node = mkbin(Odas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2589 }
2590192=>
2591#line 1180 "limbo.y"
2592{
2593 yyval.node = mkn(Oload, yys[yypt-0].yyv.node, nil);
2594 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2595 yyval.node.src.stop = yys[yypt-0].yyv.node.src.stop;
2596 yyval.node.ty = mkidtype(yys[yypt-1].yyv.tok.src, yys[yypt-1].yyv.tok.v.idval);
2597 }
2598193=>
2599#line 1187 "limbo.y"
2600{
2601 yyval.node = yyval.node = mkbin(Oexp, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2602 }
2603194=>
2604#line 1191 "limbo.y"
2605{
2606 yyval.node = mkbin(Omul, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2607 }
2608195=>
2609#line 1195 "limbo.y"
2610{
2611 yyval.node = mkbin(Odiv, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2612 }
2613196=>
2614#line 1199 "limbo.y"
2615{
2616 yyval.node = mkbin(Omod, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2617 }
2618197=>
2619#line 1203 "limbo.y"
2620{
2621 yyval.node = mkbin(Oadd, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2622 }
2623198=>
2624#line 1207 "limbo.y"
2625{
2626 yyval.node = mkbin(Osub, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2627 }
2628199=>
2629#line 1211 "limbo.y"
2630{
2631 yyval.node = mkbin(Orsh, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2632 }
2633200=>
2634#line 1215 "limbo.y"
2635{
2636 yyval.node = mkbin(Olsh, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2637 }
2638201=>
2639#line 1219 "limbo.y"
2640{
2641 yyval.node = mkbin(Olt, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2642 }
2643202=>
2644#line 1223 "limbo.y"
2645{
2646 yyval.node = mkbin(Ogt, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2647 }
2648203=>
2649#line 1227 "limbo.y"
2650{
2651 yyval.node = mkbin(Oleq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2652 }
2653204=>
2654#line 1231 "limbo.y"
2655{
2656 yyval.node = mkbin(Ogeq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2657 }
2658205=>
2659#line 1235 "limbo.y"
2660{
2661 yyval.node = mkbin(Oeq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2662 }
2663206=>
2664#line 1239 "limbo.y"
2665{
2666 yyval.node = mkbin(Oneq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2667 }
2668207=>
2669#line 1243 "limbo.y"
2670{
2671 yyval.node = mkbin(Oand, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2672 }
2673208=>
2674#line 1247 "limbo.y"
2675{
2676 yyval.node = mkbin(Oxor, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2677 }
2678209=>
2679#line 1251 "limbo.y"
2680{
2681 yyval.node = mkbin(Oor, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2682 }
2683210=>
2684#line 1255 "limbo.y"
2685{
2686 yyval.node = mkbin(Ocons, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2687 }
2688211=>
2689#line 1259 "limbo.y"
2690{
2691 yyval.node = mkbin(Oandand, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2692 }
2693212=>
2694#line 1263 "limbo.y"
2695{
2696 yyval.node = mkbin(Ooror, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2697 }
2698213=>
2699yyval.node = yys[yyp+1].yyv.node;
2700214=>
2701#line 1270 "limbo.y"
2702{
2703 yys[yypt-0].yyv.node.src.start = yys[yypt-1].yyv.tok.src.start;
2704 yyval.node = yys[yypt-0].yyv.node;
2705 }
2706215=>
2707#line 1275 "limbo.y"
2708{
2709 yyval.node = mkunary(Oneg, yys[yypt-0].yyv.node);
2710 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2711 }
2712216=>
2713#line 1280 "limbo.y"
2714{
2715 yyval.node = mkunary(Onot, yys[yypt-0].yyv.node);
2716 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2717 }
2718217=>
2719#line 1285 "limbo.y"
2720{
2721 yyval.node = mkunary(Ocomp, yys[yypt-0].yyv.node);
2722 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2723 }
2724218=>
2725#line 1290 "limbo.y"
2726{
2727 yyval.node = mkunary(Oind, yys[yypt-0].yyv.node);
2728 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2729 }
2730219=>
2731#line 1295 "limbo.y"
2732{
2733 yyval.node = mkunary(Opreinc, yys[yypt-0].yyv.node);
2734 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2735 }
2736220=>
2737#line 1300 "limbo.y"
2738{
2739 yyval.node = mkunary(Opredec, yys[yypt-0].yyv.node);
2740 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2741 }
2742221=>
2743#line 1305 "limbo.y"
2744{
2745 yyval.node = mkunary(Orcv, yys[yypt-0].yyv.node);
2746 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2747 }
2748222=>
2749#line 1310 "limbo.y"
2750{
2751 yyval.node = mkunary(Ohd, yys[yypt-0].yyv.node);
2752 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2753 }
2754223=>
2755#line 1315 "limbo.y"
2756{
2757 yyval.node = mkunary(Otl, yys[yypt-0].yyv.node);
2758 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2759 }
2760224=>
2761#line 1320 "limbo.y"
2762{
2763 yyval.node = mkunary(Olen, yys[yypt-0].yyv.node);
2764 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2765 }
2766225=>
2767#line 1325 "limbo.y"
2768{
2769 yyval.node = mkunary(Oref, yys[yypt-0].yyv.node);
2770 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2771 }
2772226=>
2773#line 1330 "limbo.y"
2774{
2775 yyval.node = mkunary(Otagof, yys[yypt-0].yyv.node);
2776 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2777 }
2778227=>
2779#line 1335 "limbo.y"
2780{
2781 yyval.node = mkn(Oarray, yys[yypt-3].yyv.node, nil);
2782 yyval.node.ty = mktype(yys[yypt-5].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tarray, yys[yypt-0].yyv.ty, nil);
2783 yyval.node.src = yyval.node.ty.src;
2784 }
2785228=>
2786#line 1341 "limbo.y"
2787{
2788 yyval.node = mkn(Oarray, yys[yypt-5].yyv.node, yys[yypt-1].yyv.node);
2789 yyval.node.src.start = yys[yypt-7].yyv.tok.src.start;
2790 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2791 }
2792229=>
2793#line 1347 "limbo.y"
2794{
2795 yyval.node = mkn(Onothing, nil, nil);
2796 yyval.node.src.start = yys[yypt-5].yyv.tok.src.start;
2797 yyval.node.src.stop = yys[yypt-4].yyv.tok.src.stop;
2798 yyval.node = mkn(Oarray, yyval.node, yys[yypt-1].yyv.node);
2799 yyval.node.src.start = yys[yypt-6].yyv.tok.src.start;
2800 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2801 }
2802230=>
2803#line 1356 "limbo.y"
2804{
2805 yyval.node = etolist(yys[yypt-1].yyv.node);
2806 yyval.node.src.start = yys[yypt-4].yyv.tok.src.start;
2807 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2808 }
2809231=>
2810#line 1362 "limbo.y"
2811{
2812 yyval.node = mkn(Ochan, nil, nil);
2813 yyval.node.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tchan, yys[yypt-0].yyv.ty, nil);
2814 yyval.node.src = yyval.node.ty.src;
2815 }
2816232=>
2817#line 1368 "limbo.y"
2818{
2819 yyval.node = mkn(Ochan, yys[yypt-3].yyv.node, nil);
2820 yyval.node.ty = mktype(yys[yypt-5].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tchan, yys[yypt-0].yyv.ty, nil);
2821 yyval.node.src = yyval.node.ty.src;
2822 }
2823233=>
2824#line 1374 "limbo.y"
2825{
2826 yyval.node = mkunary(Ocast, yys[yypt-0].yyv.node);
2827 yyval.node.ty = mktype(yys[yypt-3].yyv.tok.src.start, yys[yypt-0].yyv.node.src.stop, Tarray, mkidtype(yys[yypt-1].yyv.tok.src, yys[yypt-1].yyv.tok.v.idval), nil);
2828 yyval.node.src = yyval.node.ty.src;
2829 }
2830234=>
2831#line 1380 "limbo.y"
2832{
2833 yyval.node = mkunary(Ocast, yys[yypt-0].yyv.node);
2834 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2835 yyval.node.ty = mkidtype(yyval.node.src, yys[yypt-1].yyv.tok.v.idval);
2836 }
2837235=>
2838#line 1386 "limbo.y"
2839{
2840 yyval.node = mkunary(Ocast, yys[yypt-0].yyv.node);
2841 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2842 yyval.node.ty = mkidtype(yyval.node.src, yys[yypt-1].yyv.tok.v.idval);
2843 }
2844236=>
2845#line 1392 "limbo.y"
2846{
2847 yyval.node = mkunary(Ocast, yys[yypt-0].yyv.node);
2848 yyval.node.src.start = yys[yypt-1].yyv.tok.src.start;
2849 yyval.node.ty = yys[yypt-1].yyv.ty;
2850 }
2851237=>
2852yyval.node = yys[yyp+1].yyv.node;
2853238=>
2854#line 1401 "limbo.y"
2855{
2856 yyval.node = mkn(Ocall, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
2857 yyval.node.src.start = yys[yypt-3].yyv.node.src.start;
2858 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2859 }
2860239=>
2861#line 1407 "limbo.y"
2862{
2863 yyval.node = yys[yypt-1].yyv.node;
2864 if(yys[yypt-1].yyv.node.op == Oseq)
2865 yyval.node = mkn(Otuple, rotater(yys[yypt-1].yyv.node), nil);
2866 else
2867 yyval.node.flags |= byte PARENS;
2868 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2869 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2870 }
2871240=>
2872#line 1417 "limbo.y"
2873{
2874# n := mkdeclname($1, mkids($1, enter(".fn"+string nfnexp++, 0), nil, nil));
2875# $<node>$ = fndef(n, $2);
2876# nfns++;
2877 }
2878241=>
2879#line 1422 "limbo.y"
2880{
2881# $$ = fnfinishdef($<node>3, $4);
2882# $$ = mkdeclname($1, $$.left.decl);
2883 yyerror("urt unk");
2884 yyval.node = nil;
2885 }
2886242=>
2887#line 1429 "limbo.y"
2888{
2889 yyval.node = mkbin(Odot, yys[yypt-2].yyv.node, mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval));
2890 }
2891243=>
2892#line 1433 "limbo.y"
2893{
2894 yyval.node = mkbin(Omdot, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2895 }
2896244=>
2897#line 1437 "limbo.y"
2898{
2899 yyval.node = mkbin(Oindex, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
2900 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2901 }
2902245=>
2903#line 1442 "limbo.y"
2904{
2905 if(yys[yypt-3].yyv.node.op == Onothing)
2906 yys[yypt-3].yyv.node.src = yys[yypt-2].yyv.tok.src;
2907 if(yys[yypt-1].yyv.node.op == Onothing)
2908 yys[yypt-1].yyv.node.src = yys[yypt-2].yyv.tok.src;
2909 yyval.node = mkbin(Oslice, yys[yypt-5].yyv.node, mkbin(Oseq, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node));
2910 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2911 }
2912246=>
2913#line 1451 "limbo.y"
2914{
2915 yyval.node = mkunary(Oinc, yys[yypt-1].yyv.node);
2916 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2917 }
2918247=>
2919#line 1456 "limbo.y"
2920{
2921 yyval.node = mkunary(Odec, yys[yypt-1].yyv.node);
2922 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2923 }
2924248=>
2925#line 1461 "limbo.y"
2926{
2927 yyval.node = mksconst(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2928 }
2929249=>
2930#line 1465 "limbo.y"
2931{
2932 yyval.node = mkconst(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.ival);
2933 if(yys[yypt-0].yyv.tok.v.ival > big 16r7fffffff || yys[yypt-0].yyv.tok.v.ival < big -16r7fffffff)
2934 yyval.node.ty = tbig;
2935 }
2936250=>
2937#line 1471 "limbo.y"
2938{
2939 yyval.node = mkrconst(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.rval);
2940 }
2941251=>
2942#line 1475 "limbo.y"
2943{
2944 yyval.node = mkbin(Oindex, yys[yypt-5].yyv.node, rotater(mkbin(Oseq, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node)));
2945 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2946 }
2947252=>
2948#line 1482 "limbo.y"
2949{
2950 yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2951 }
2952253=>
2953#line 1486 "limbo.y"
2954{
2955 yyval.node = mknil(yys[yypt-0].yyv.tok.src);
2956 }
2957254=>
2958#line 1492 "limbo.y"
2959{
2960 yyval.node = mkn(Otuple, rotater(yys[yypt-1].yyv.node), nil);
2961 yyval.node.src.start = yys[yypt-2].yyv.tok.src.start;
2962 yyval.node.src.stop = yys[yypt-0].yyv.tok.src.stop;
2963 }
2964255=>
2965yyval.node = yys[yyp+1].yyv.node;
2966256=>
2967#line 1501 "limbo.y"
2968{
2969 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2970 }
2971257=>
2972yyval.node = yys[yyp+1].yyv.node;
2973258=>
2974yyval.node = yys[yyp+1].yyv.node;
2975259=>
2976#line 1511 "limbo.y"
2977{
2978 yyval.node = mkn(Otype, nil, nil);
2979 yyval.node.ty = mkidtype(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2980 yyval.node.src = yyval.node.ty.src;
2981 }
2982260=>
2983#line 1517 "limbo.y"
2984{
2985 yyval.node = mkn(Otype, nil, nil);
2986 yyval.node.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tarray, yys[yypt-0].yyv.ty, nil);
2987 yyval.node.src = yyval.node.ty.src;
2988 }
2989261=>
2990#line 1523 "limbo.y"
2991{
2992 yyval.node = mkn(Otype, nil, nil);
2993 yyval.node.ty = mktype(yys[yypt-2].yyv.tok.src.start, yys[yypt-0].yyv.ty.src.stop, Tlist, yys[yypt-0].yyv.ty, nil);
2994 yyval.node.src = yyval.node.ty.src;
2995 }
2996262=>
2997#line 1529 "limbo.y"
2998{
2999 yyval.node = mkn(Otype, nil ,nil);
3000 yyval.node.ty = yys[yypt-0].yyv.ty;
3001 yyval.node.ty.flags |= CYCLIC;
3002 yyval.node.src = yyval.node.ty.src;
3003 }
3004263=>
3005#line 1538 "limbo.y"
3006{
3007 yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
3008 }
3009264=>
3010#line 1542 "limbo.y"
3011{
3012 yyval.node = nil;
3013 }
3014265=>
3015yyval.node = yys[yyp+1].yyv.node;
3016266=>
3017yyval.node = yys[yyp+1].yyv.node;
3018267=>
3019#line 1550 "limbo.y"
3020{
3021 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3022 }
3023268=>
3024#line 1554 "limbo.y"
3025{
3026 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3027 }
3028269=>
3029#line 1560 "limbo.y"
3030{
3031 yyval.node = nil;
3032 }
3033270=>
3034#line 1564 "limbo.y"
3035{
3036 yyval.node = rotater(yys[yypt-0].yyv.node);
3037 }
3038271=>
3039yyval.node = yys[yyp+1].yyv.node;
3040272=>
3041yyval.node = yys[yyp+1].yyv.node;
3042273=>
3043yyval.node = yys[yyp+1].yyv.node;
3044274=>
3045#line 1575 "limbo.y"
3046{
3047 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3048 }
3049275=>
3050#line 1581 "limbo.y"
3051{
3052 yyval.node = rotater(yys[yypt-0].yyv.node);
3053 }
3054276=>
3055#line 1585 "limbo.y"
3056{
3057 yyval.node = rotater(yys[yypt-1].yyv.node);
3058 }
3059277=>
3060yyval.node = yys[yyp+1].yyv.node;
3061278=>
3062#line 1592 "limbo.y"
3063{
3064 yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3065 }
3066279=>
3067#line 1598 "limbo.y"
3068{
3069 yyval.node = mkn(Oelem, nil, yys[yypt-0].yyv.node);
3070 yyval.node.src = yys[yypt-0].yyv.node.src;
3071 }
3072280=>
3073#line 1603 "limbo.y"
3074{
3075 yyval.node = mkbin(Oelem, rotater(yys[yypt-2].yyv.node), yys[yypt-0].yyv.node);
3076 }
3077281=>
3078#line 1609 "limbo.y"
3079{
3080 if(yys[yypt-1].yyv.node.op == Oseq)
3081 yys[yypt-1].yyv.node.right.left = rotater(yys[yypt-0].yyv.node);
3082 else
3083 yys[yypt-1].yyv.node.left = rotater(yys[yypt-0].yyv.node);
3084 yyval.node = yys[yypt-1].yyv.node;
3085 }
3086282=>
3087#line 1619 "limbo.y"
3088{
3089 yyval.node = typedecl(yys[yypt-1].yyv.ids, mktype(yys[yypt-1].yyv.ids.src.start, yys[yypt-0].yyv.tok.src.stop, Tpoly, nil, nil));
3090 }
3091283=>
3092#line 1623 "limbo.y"
3093{
3094 if(yys[yypt-3].yyv.node.op == Oseq)
3095 yys[yypt-3].yyv.node.right.left = rotater(yys[yypt-2].yyv.node);
3096 else
3097 yys[yypt-3].yyv.node.left = rotater(yys[yypt-2].yyv.node);
3098 yyval.node = mkbin(Oseq, yys[yypt-3].yyv.node, typedecl(yys[yypt-1].yyv.ids, mktype(yys[yypt-1].yyv.ids.src.start, yys[yypt-0].yyv.tok.src.stop, Tpoly, nil, nil)));
3099 }
3100 }
3101 }
3102
3103 return yyn;
3104}
limbo/compiler/limbo.m+527−0
@@ -0,0 +1,527 @@
1include "sys.m";
2include "math.m";
3include "string.m";
4include "bufio.m";
5include "isa.m";
6include "workdir.m";
7
8# internal dis ops
9IEXC: con MAXDIS;
10IEXC0: con (MAXDIS+1);
11INOOP: con (MAXDIS+2);
12
13# temporary
14LDT: con 1;
15
16STemp: con NREG * IBY2WD;
17RTemp: con STemp + IBY2WD;
18DTemp: con RTemp + IBY2WD;
19MaxTemp: con DTemp + IBY2WD;
20MaxReg: con 1 << 16;
21MaxAlign: con IBY2LG;
22StrSize: con 256;
23MaxIncPath: con 32; # max directories in include path
24MaxScope: con 64; # max nested {}
25MaxInclude: con 32; # max nested include ""
26ScopeBuiltin,
27ScopeNils,
28ScopeGlobal: con iota;
29
30Line: type int;
31PosBits: con 10;
32PosMask: con (1 << PosBits) - 1;
33
34Src: adt
35{
36 start: Line;
37 stop: Line;
38};
39
40File: adt
41{
42 name: string;
43 abs: int; # absolute line of start of the part of file
44 off: int; # offset to line in the file
45 in: int; # absolute line where included
46 act: string; # name of real file with #line fake file
47 actoff: int; # offset from fake line to real line
48 sbl: int; # symbol file number
49};
50
51Val: adt
52{
53 idval: ref Sym;
54 ival: big;
55 rval: real;
56};
57
58Tok: adt
59{
60 src: Src;
61 v: Val;
62};
63
64#
65# addressing modes
66#
67 Aimm, # immediate
68 Amp, # global
69 Ampind, # global indirect
70 Afp, # activation frame
71 Afpind, # frame indirect
72 Apc, # branch
73 Adesc, # type descriptor immediate
74 Aoff, # offset in module description table
75 Anoff, # above encoded as a -ve
76 Aerr, # error
77 Anone, # no operand
78 Aldt, # linkage descriptor table immediate
79 Aend: con byte iota;
80
81Addr: adt
82{
83 reg: int;
84 offset: int;
85 decl: cyclic ref Decl;
86};
87
88Inst: adt
89{
90 src: Src;
91 op: int; # could be a byte
92 pc: int;
93 reach: byte; # could a control path reach this instruction?
94 sm: byte; # operand addressing modes
95 mm: byte;
96 dm: byte;
97 s: cyclic Addr; # operands
98 m: cyclic Addr;
99 d: cyclic Addr;
100 branch: cyclic ref Inst; # branch destination
101 next: cyclic ref Inst;
102 block: int; # blocks nested inside
103};
104
105Case: adt
106{
107 nlab: int;
108 nsnd: int;
109 offset: int; # offset in mp
110 labs: cyclic array of Label;
111 wild: cyclic ref Node; # if nothing matches
112 iwild: cyclic ref Inst;
113};
114
115Label: adt
116{
117 node: cyclic ref Node;
118 isptr: int; # true if the labelled alt channel is a pointer
119 start: cyclic ref Node; # value in range [start, stop) => code
120 stop: cyclic ref Node;
121 inst: cyclic ref Inst;
122};
123
124#
125# storage classes
126#
127 Dtype,
128 Dfn,
129 Dglobal,
130 Darg,
131 Dlocal,
132 Dconst,
133 Dfield,
134 Dtag, # pick tags
135 Dimport, # imported identifier
136 Dunbound, # unbound identified
137 Dundef,
138 Dwundef, # undefined, but don't whine
139
140 Dend: con iota;
141
142Decl: adt
143{
144 src: Src; # where declaration
145 sym: cyclic ref Sym; # name
146 store: int; # storage class
147 nid: byte; # block grouping for locals
148 inline: byte; # inline function
149 handler: byte; # fn has exception handler(s)
150 das: byte; # declared with :=
151 dot: cyclic ref Decl; # parent adt or module
152 ty: cyclic ref Type;
153 refs: int; # number of references
154 offset: int;
155 tag: int; # union tag
156
157 scope: int; # in which it was declared
158 next: cyclic ref Decl; # list in same scope, field or argument list, etc.
159 old: cyclic ref Decl; # declaration of the symbol in enclosing scope
160
161 eimport: cyclic ref Node; # expr from which imported
162 importid: cyclic ref Decl; # identifier imported
163 timport: cyclic ref Decl; # stack of identifiers importing a type
164
165 init: cyclic ref Node; # data initialization
166 tref: int; # 1 => is a tmp; >=2 => tmp in use
167 cycle: byte; # can create a cycle
168 cyc: byte; # so labelled in source
169 cycerr: byte; # delivered an error message for cycle?
170 implicit: byte; # implicit first argument in an adt?
171
172 iface: cyclic ref Decl; # used external declarations in a module
173
174 locals: cyclic ref Decl; # locals for a function
175 link: cyclic ref Decl; # pointer to parent function or function argument or local share or parent type dec
176 pc: cyclic ref Inst; # start of function
177 # endpc: cyclic ref Inst; # limit of function - unused
178
179# should be able to move this to Type
180 desc: ref Desc; # heap descriptor
181};
182
183Desc: adt
184{
185 id: int; # dis type identifier
186 used: int; # actually used in output?
187 map: array of byte; # byte map of pointers
188 size: int; # length of the object
189 nmap: int; # length of good bytes in map
190 next: cyclic ref Desc;
191};
192
193Dlist: adt
194{
195 d: ref Decl;
196 next: cyclic ref Dlist;
197};
198
199Except: adt
200{
201 p1: ref Inst; # first pc covered
202 p2: ref Inst; # last pc not covered
203 c: ref Case; # exception case instructions
204 d: ref Decl; # exception definition if any
205 zn: ref Node; # list of nodes to zero in handler
206 desc: ref Desc; # descriptor map for above
207 ne: int; # number of exceptions (ie not strings) in case
208 next: cyclic ref Except;
209};
210
211Sym: adt
212{
213 token: int;
214 name: string;
215 hash: int;
216 next: cyclic ref Sym;
217 decl: cyclic ref Decl;
218 unbound: cyclic ref Decl; # place holder for unbound symbols
219};
220
221#
222# ops for nodes
223#
224 Oadd,
225 Oaddas,
226 Oadr,
227 Oadtdecl,
228 Oalt,
229 Oand,
230 Oandand,
231 Oandas,
232 Oarray,
233 Oas,
234 Obreak,
235 Ocall,
236 Ocase,
237 Ocast,
238 Ochan,
239 Ocomma,
240 Ocomp,
241 Ocondecl,
242 Ocons,
243 Oconst,
244 Ocont,
245 Odas,
246 Odec,
247 Odiv,
248 Odivas,
249 Odo,
250 Odot,
251 Oelem,
252 Oeq,
253 Oexcept,
254 Oexdecl,
255 Oexit,
256 Oexp,
257 Oexpas,
258 Oexstmt,
259 Ofielddecl,
260 Ofnptr,
261 Ofor,
262 Ofunc,
263 Ogeq,
264 Ogt,
265 Ohd,
266 Oif,
267 Oimport,
268 Oinc,
269 Oind,
270 Oindex,
271 Oinds,
272 Oindx,
273 Oinv,
274 Ojmp,
275 Olabel,
276 Olen,
277 Oleq,
278 Oload,
279 Olsh,
280 Olshas,
281 Olt,
282 Omdot,
283 Omod,
284 Omodas,
285 Omoddecl,
286 Omul,
287 Omulas,
288 Oname,
289 Oneg,
290 Oneq,
291 Onot,
292 Onothing,
293 Oor,
294 Ooras,
295 Ooror,
296 Opick,
297 Opickdecl,
298 Opredec,
299 Opreinc,
300 Oraise,
301 Orange,
302 Orcv,
303 Oref,
304 Oret,
305 Orsh,
306 Orshas,
307 Oscope,
308 Oself,
309 Oseq,
310 Oslice,
311 Osnd,
312 Ospawn,
313 Osub,
314 Osubas,
315 Otagof,
316 Otl,
317 Otuple,
318 Otype,
319 Otypedecl,
320 Oused,
321 Ovardecl,
322 Ovardecli,
323 Owild,
324 Oxor,
325 Oxoras,
326
327 Oend: con iota + 1;
328
329#
330# moves
331#
332 Mas,
333 Mcons,
334 Mhd,
335 Mtl,
336
337 Mend: con iota;
338
339#
340# addressability
341#
342 Rreg, # v(fp)
343 Rmreg, # v(mp)
344 Roff, # $v
345 Rnoff, # $v encoded as -ve
346 Rdesc, # $v
347 Rdescp, # $v
348 Rconst, # $v
349 Ralways, # preceeding are always addressable
350 Radr, # v(v(fp))
351 Rmadr, # v(v(mp))
352 Rcant, # following are not quite addressable
353 Rpc, # branch address
354 Rmpc, # cross module branch address
355 Rareg, # $v(fp)
356 Ramreg, # $v(mp)
357 Raadr, # $v(v(fp))
358 Ramadr, # $v(v(mp))
359 Rldt, # $v
360
361 Rend: con byte iota;
362
363
364Const: adt
365{
366 val: big;
367 rval: real;
368};
369
370PARENS: con 1;
371TEMP: con 2;
372FNPTRA: con 4; # argument
373FNPTR2: con 8; # 2nd parameter
374FNPTRN: con 16; # use -ve offset
375FNPTR: con FNPTRA|FNPTR2|FNPTRN;
376
377Node: adt
378{
379 src: Src;
380 op: int;
381 addable: byte;
382 flags: byte;
383 temps: byte;
384 left: cyclic ref Node;
385 right: cyclic ref Node;
386 ty: cyclic ref Type;
387 decl: cyclic ref Decl;
388 c: ref Const; # for Oconst
389};
390
391 #
392 # types visible to limbo
393 #
394 Tnone,
395 Tadt,
396 Tadtpick, # pick case of an adt
397 Tarray,
398 Tbig, # 64 bit int
399 Tbyte, # 8 bit unsigned int
400 Tchan,
401 Treal,
402 Tfn,
403 Tint, # 32 bit int
404 Tlist,
405 Tmodule,
406 Tref,
407 Tstring,
408 Ttuple,
409 Texception,
410 Tfix,
411 Tpoly,
412
413 #
414 # internal use types
415 #
416 Tainit, # array initializers
417 Talt, # alt channels
418 Tany, # type of nil
419 Tarrow, # unresolved ty->ty types
420 Tcase, # case labels
421 Tcasel, # case big labels
422 Tcasec, # case string labels
423 Tdot, # unresolved ty.id types
424 Terror,
425 Tgoto, # goto labels
426 Tid, # id with unknown type
427 Tiface, # module interface
428 Texcept, # exception handler tables
429 Tinst, # instantiated adt
430
431 Tend: con iota;
432
433 #
434 # marks for various phases of verifing types
435 #
436 OKbind, # type decls are bound
437 OKverify, # type looks ok
438 OKsized, # started figuring size
439 OKref, # recorded use of type
440 OKclass, # equivalence class found
441 OKcyc, # checked for cycles
442 OKcycsize, # checked for cycles and size
443 OKmodref: # started checking for a module handle
444
445 con byte 1 << iota;
446 OKmask: con byte 16rff;
447
448 #
449 # recursive marks
450 #
451 TReq,
452 TRcom,
453 TRcyc,
454 TRvis:
455 con byte 1 << iota;
456
457# type flags
458FULLARGS: con byte 1; # all hidden args added
459INST: con byte 2; # instantiated adt
460CYCLIC: con byte 4; # cyclic type
461POLY: con byte 8; # polymorphic types inside
462NOPOLY: con byte 16; # no polymorphic types inside
463
464# must put some picks in here
465Type: adt
466{
467 src: Src;
468 kind: int;
469 ok: byte; # set when type is verified
470 varargs: byte; # if a function, ends with vargs?
471 linkall: byte; # put all iface fns in external linkage?
472 rec: byte; # in the middle of recursive type
473 pr: byte; # in the middle of printing a recursive type
474 cons: byte; # exception constant
475 flags: byte;
476 sbl: int; # slot in .sbl adt table
477 sig: int; # signature for dynamic type check
478 size: int; # storage required, in bytes
479 align: int; # alignment in bytes
480 decl: cyclic ref Decl;
481 tof: cyclic ref Type;
482 ids: cyclic ref Decl;
483 tags: cyclic ref Decl;# tagged fields in an adt
484 polys: cyclic ref Decl;# polymorphic fields in fn or adt
485 cse: cyclic ref Case;# case or goto labels
486 teq: cyclic ref Type;# temporary equiv class for equiv checking
487 tcom: cyclic ref Type;# temporary equiv class for compat checking
488 eq: cyclic ref Teq; # real equiv class
489 eraises: cyclic ref Node; # for Tfn only
490 val: cyclic ref Node; # for Tfix, Tfn, Tadt only
491 tlist: cyclic ref Typelist; # for Tinst only
492 tmap: cyclic ref Tpair; # for Tadt only
493};
494
495#
496# type equivalence classes
497#
498Teq: adt
499{
500 id: int; # for signing
501 ty: cyclic ref Type;# an instance of the class
502 eq: cyclic ref Teq; # used to link eq sets
503};
504
505Tattr: adt
506{
507 isptr: int;
508 refable: int;
509 conable: int;
510 isbig: int;
511 vis: int; # type visible to users
512};
513
514Tpair: adt
515{
516 t1: cyclic ref Type;
517 t2: cyclic ref Type;
518 nxt: cyclic ref Tpair;
519};
520
521Typelist: adt
522{
523 t: cyclic ref Type;
524 nxt: cyclic ref Typelist;
525};
526
527Sother, Sloop, Sscope : con iota;
limbo/compiler/limbo.y+1978−0
@@ -0,0 +1,1978 @@
1%{
2include "limbo.m";
3include "draw.m";
4
5%}
6
7%module Limbo
8{
9 init: fn(ctxt: ref Draw->Context, argv: list of string);
10
11 YYSTYPE: adt{
12 tok: Tok;
13 ids: ref Decl;
14 node: ref Node;
15 ty: ref Type;
16 types: ref Typelist;
17 };
18
19 YYLEX: adt {
20 lval: YYSTYPE;
21 lex: fn(nil: self ref YYLEX): int;
22 error: fn(nil: self ref YYLEX, err: string);
23 };
24}
25
26%{
27 #
28 # lex.b
29 #
30 signdump: string; # name of function for sig debugging
31 superwarn: int;
32 debug: array of int;
33 noline: Line;
34 nosrc: Src;
35 arrayz: int;
36 oldcycles: int;
37 emitcode: string; # emit stub routines for system module functions
38 emitdyn: int; # emit as above but for dynamic modules
39 emitsbl: string; # emit symbol file for sysm modules
40 emitstub: int; # emit type and call frames for system modules
41 emittab: string; # emit table of runtime functions for this module
42 errors: int;
43 mustcompile: int;
44 dontcompile: int;
45 asmsym: int; # generate symbols in assembly language?
46 bout: ref Bufio->Iobuf; # output file
47 bsym: ref Bufio->Iobuf; # symbol output file; nil => no sym out
48 gendis: int; # generate dis or asm?
49 fixss: int;
50 newfnptr: int; # ISELF and -ve indices
51 optims: int;
52
53 #
54 # decls.b
55 #
56 scope: int;
57 # impmod: ref Sym; # name of implementation module
58 impmods: ref Decl; # name of implementation module(s)
59 nildecl: ref Decl; # declaration for limbo's nil
60 selfdecl: ref Decl; # declaration for limbo's self
61
62 #
63 # types.b
64 #
65 tany: ref Type;
66 tbig: ref Type;
67 tbyte: ref Type;
68 terror: ref Type;
69 tint: ref Type;
70 tnone: ref Type;
71 treal: ref Type;
72 tstring: ref Type;
73 texception: ref Type;
74 tunknown: ref Type;
75 tfnptr: ref Type;
76 rtexception: ref Type;
77 descriptors: ref Desc; # list of all possible descriptors
78 tattr: array of Tattr;
79
80 #
81 # nodes.b
82 #
83 opcommute: array of int;
84 oprelinvert: array of int;
85 isused: array of int;
86 casttab: array of array of int; # instruction to cast from [1] to [2]
87
88 nfns: int; # functions defined
89 nfnexp: int;
90 fns: array of ref Decl; # decls for fns defined
91 tree: ref Node; # root of parse tree
92
93 parset: int; # time to parse
94 checkt: int; # time to typecheck
95 gent: int; # time to generate code
96 writet: int; # time to write out code
97 symt: int; # time to write out symbols
98%}
99
100%type <ty> type fnarg fnargret fnargretp adtk fixtype iditype dotiditype
101%type <ids> ids rids nids nrids tuplist forms ftypes ftype
102 bclab bctarg ptags rptags polydec
103%type <node> zexp exp monexp term elist zelist celist
104 idatom idterms idterm idlist
105 initlist elemlist elem qual
106 decl topdecls topdecl fndef fbody stmt stmts qstmts qbodies cqstmts cqbodies
107 mdecl adtdecl mfield mfields field fields fnname
108 pstmts pbodies pqual pfields pfbody pdecl dfield dfields
109 eqstmts eqbodies idexc edecl raises tpoly tpolys texp export exportlist forpoly
110%type <types> types
111
112%right <tok.src> '=' Landeq Loreq Lxoreq Llsheq Lrsheq
113 Laddeq Lsubeq Lmuleq Ldiveq Lmodeq Lexpeq Ldeclas
114%left <tok.src> Lload
115%left <tok.src> Loror
116%left <tok.src> Landand
117%right <tok.src> Lcons
118%left <tok.src> '|'
119%left <tok.src> '^'
120%left <tok.src> '&'
121%left <tok.src> Leq Lneq
122%left <tok.src> '<' '>' Lleq Lgeq
123%left <tok.src> Llsh Lrsh
124%left <tok.src> '+' '-'
125%left <tok.src> '*' '/' '%'
126%right <tok.src> Lexp
127%right <tok.src> Lcomm
128
129%left <tok.src> '(' ')' '[' ']' Linc Ldec Lof Lref
130%right <tok.src> Lif Lelse Lfn ':' Lexcept Lraises
131%left <tok.src> Lmdot
132%left <tok.src> '.'
133
134%left <tok.src> Lto
135%left <tok.src> Lor
136
137
138%nonassoc <tok.v.rval> Lrconst
139%nonassoc <tok.v.ival> Lconst
140%nonassoc <tok.v.idval> Lid Ltid Lsconst
141%nonassoc <tok.src> Llabs Lnil
142 '!' '~' Llen Lhd Ltl Ltagof
143 '{' '}' ';'
144 Limplement Limport Linclude
145 Lcon Ltype Lmodule Lcyclic
146 Ladt Larray Llist Lchan Lself
147 Ldo Lwhile Lfor Lbreak
148 Lalt Lcase Lpick Lcont
149 Lreturn Lexit Lspawn Lraise Lfix
150 Ldynamic
151%%
152prog : Limplement ids ';'
153 {
154 impmods = $2;
155 } topdecls
156 {
157 tree = rotater($5);
158 }
159 | topdecls
160 {
161 impmods = nil;
162 tree = rotater($1);
163 }
164 ;
165
166topdecls: topdecl
167 | topdecls topdecl
168 {
169 if($1 == nil)
170 $$ = $2;
171 else if($2 == nil)
172 $$ = $1;
173 else
174 $$ = mkbin(Oseq, $1, $2);
175 }
176 ;
177
178topdecl : error ';'
179 {
180 $$ = nil;
181 }
182 | decl
183 | fndef
184 | adtdecl ';'
185 | mdecl ';'
186 | idatom '=' exp ';'
187 {
188 $$ = mkbin(Oas, $1, $3);
189 }
190 | idterm '=' exp ';'
191 {
192 $$ = mkbin(Oas, $1, $3);
193 }
194 | idatom Ldeclas exp ';'
195 {
196 $$ = mkbin(Odas, $1, $3);
197 }
198 | idterm Ldeclas exp ';'
199 {
200 $$ = mkbin(Odas, $1, $3);
201 }
202 | idterms ':' type ';'
203 {
204 yyerror("illegal declaration");
205 $$ = nil;
206 }
207 | idterms ':' type '=' exp ';'
208 {
209 yyerror("illegal declaration");
210 $$ = nil;
211 }
212 ;
213
214idterms : idterm
215 | idterms ',' idterm
216 {
217 $$ = mkbin(Oseq, $1, $3);
218 }
219 ;
220
221decl : Linclude Lsconst ';'
222 {
223 includef($2);
224 $$ = nil;
225 }
226 | ids ':' Ltype type ';'
227 {
228 $$ = typedecl($1, $4);
229 }
230 | ids ':' Limport exp ';'
231 {
232 $$ = importdecl($4, $1);
233 $$.src.start = $1.src.start;
234 $$.src.stop = $5.stop;
235 }
236 | ids ':' type ';'
237 {
238 $$ = vardecl($1, $3);
239 }
240 | ids ':' type '=' exp ';'
241 {
242 $$ = mkbin(Ovardecli, vardecl($1, $3), varinit($1, $5));
243 }
244 | ids ':' Lcon exp ';'
245 {
246 $$ = condecl($1, $4);
247 }
248 | edecl
249 ;
250
251edecl : ids ':' Lexcept ';'
252 {
253 $$ = exdecl($1, nil);
254 }
255 | ids ':' Lexcept '(' tuplist ')' ';'
256 {
257 $$ = exdecl($1, revids($5));
258 }
259 ;
260
261mdecl : ids ':' Lmodule '{' mfields '}'
262 {
263 $1.src.stop = $6.stop;
264 $$ = moddecl($1, rotater($5));
265 }
266 ;
267
268mfields :
269 {
270 $$ = nil;
271 }
272 | mfields mfield
273 {
274 if($1 == nil)
275 $$ = $2;
276 else if($2 == nil)
277 $$ = $1;
278 else
279 $$ = mkn(Oseq, $1, $2);
280 }
281 | error
282 {
283 $$ = nil;
284 }
285 ;
286
287mfield : ids ':' type ';'
288 {
289 $$ = fielddecl(Dglobal, typeids($1, $3));
290 }
291 | adtdecl ';'
292 | ids ':' Ltype type ';'
293 {
294 $$ = typedecl($1, $4);
295 }
296 | ids ':' Lcon exp ';'
297 {
298 $$ = condecl($1, $4);
299 }
300 | edecl
301 ;
302
303adtdecl : ids ':' Ladt polydec '{' fields '}' forpoly
304 {
305 $1.src.stop = $7.stop;
306 $$ = adtdecl($1, rotater($6));
307 $$.ty.polys = $4;
308 $$.ty.val = rotater($8);
309 }
310 | ids ':' Ladt polydec Lfor '{' tpolys '}' '{' fields '}'
311 {
312 $1.src.stop = $11.stop;
313 $$ = adtdecl($1, rotater($10));
314 $$.ty.polys = $4;
315 $$.ty.val = rotater($7);
316 }
317 ;
318
319forpoly :
320 {
321 $$ = nil;
322 }
323 | Lfor '{' tpolys '}'
324 {
325 $$ = $3;
326 }
327 ;
328
329fields :
330 {
331 $$ = nil;
332 }
333 | fields field
334 {
335 if($1 == nil)
336 $$ = $2;
337 else if($2 == nil)
338 $$ = $1;
339 else
340 $$ = mkn(Oseq, $1, $2);
341 }
342 | error
343 {
344 $$ = nil;
345 }
346 ;
347
348field : dfield
349 | pdecl
350 | ids ':' Lcon exp ';'
351 {
352 $$ = condecl($1, $4);
353 }
354 ;
355
356dfields :
357 {
358 $$ = nil;
359 }
360 | dfields dfield
361 {
362 if($1 == nil)
363 $$ = $2;
364 else if($2 == nil)
365 $$ = $1;
366 else
367 $$ = mkn(Oseq, $1, $2);
368 }
369 ;
370
371dfield : ids ':' Lcyclic type ';'
372 {
373 for(d := $1; d != nil; d = d.next)
374 d.cyc = byte 1;
375 $$ = fielddecl(Dfield, typeids($1, $4));
376 }
377 | ids ':' type ';'
378 {
379 $$ = fielddecl(Dfield, typeids($1, $3));
380 }
381 ;
382
383pdecl : Lpick '{' pfields '}'
384 {
385 $$ = $3;
386 }
387 ;
388
389pfields : pfbody dfields
390 {
391 $1.right.right = $2;
392 $$ = $1;
393 }
394 | pfbody error
395 {
396 $$ = nil;
397 }
398 | error
399 {
400 $$ = nil;
401 }
402 ;
403
404pfbody : ptags Llabs
405 {
406 $$ = mkn(Opickdecl, nil, mkn(Oseq, fielddecl(Dtag, $1), nil));
407 typeids($1, mktype($1.src.start, $1.src.stop, Tadtpick, nil, nil));
408 }
409 | pfbody dfields ptags Llabs
410 {
411 $1.right.right = $2;
412 $$ = mkn(Opickdecl, $1, mkn(Oseq, fielddecl(Dtag, $3), nil));
413 typeids($3, mktype($3.src.start, $3.src.stop, Tadtpick, nil, nil));
414 }
415 | pfbody error ptags Llabs
416 {
417 $$ = mkn(Opickdecl, nil, mkn(Oseq, fielddecl(Dtag, $3), nil));
418 typeids($3, mktype($3.src.start, $3.src.stop, Tadtpick, nil, nil));
419 }
420 ;
421
422ptags : rptags
423 {
424 $$ = revids($1);
425 }
426 ;
427
428rptags : Lid
429 {
430 $$ = mkids($<tok.src>1, $1, nil, nil);
431 }
432 | rptags Lor Lid
433 {
434 $$ = mkids($<tok.src>3, $3, nil, $1);
435 }
436 ;
437
438ids : rids
439 {
440 $$ = revids($1);
441 }
442 ;
443
444rids : Lid
445 {
446 $$ = mkids($<tok.src>1, $1, nil, nil);
447 }
448 | rids ',' Lid
449 {
450 $$ = mkids($<tok.src>3, $3, nil, $1);
451 }
452 ;
453
454fixtype : Lfix '(' exp ',' exp ')'
455 {
456 $$ = mktype($1.start, $6.stop, Tfix, nil, nil);
457 $$.val = mkbin(Oseq, $3, $5);
458 }
459 | Lfix '(' exp ')'
460 {
461 $$ = mktype($1.start, $4.stop, Tfix, nil, nil);
462 $$.val = $3;
463 }
464 ;
465
466types : type
467 {
468 $$ = addtype($1, nil);
469 }
470 | Lcyclic type
471 {
472 $$ = addtype($2, nil);
473 $2.flags |= CYCLIC;
474 }
475 | types ',' type
476 {
477 $$ = addtype($3, $1);
478 }
479 | types ',' Lcyclic type
480 {
481 $$ = addtype($4, $1);
482 $4.flags |= CYCLIC;
483 }
484 ;
485
486type : Ltid
487 {
488 $$ = mkidtype($<tok.src>1, $1);
489 }
490 | iditype
491 {
492 $$ = $1;
493 }
494 | dotiditype
495 {
496 $$ = $1;
497 }
498 | type Lmdot Lid
499 {
500 $$ = mkarrowtype($1.src.start, $<tok.src>3.stop, $1, $3);
501 }
502 | type Lmdot Lid '[' types ']'
503 {
504 $$ = mkarrowtype($1.src.start, $<tok.src>3.stop, $1, $3);
505 $$ = mkinsttype($1.src, $$, $5);
506 }
507 | Lref type
508 {
509 $$ = mktype($1.start, $2.src.stop, Tref, $2, nil);
510 }
511 | Lchan Lof type
512 {
513 $$ = mktype($1.start, $3.src.stop, Tchan, $3, nil);
514 }
515 | '(' tuplist ')'
516 {
517 if($2.next == nil)
518 $$ = $2.ty;
519 else
520 $$ = mktype($1.start, $3.stop, Ttuple, nil, revids($2));
521 }
522 | Larray Lof type
523 {
524 $$ = mktype($1.start, $3.src.stop, Tarray, $3, nil);
525 }
526 | Llist Lof type
527 {
528 $$ = mktype($1.start, $3.src.stop, Tlist, $3, nil);
529 }
530 | Lfn polydec fnargretp raises
531 {
532 $3.src.start = $1.start;
533 $3.polys = $2;
534 $3.eraises = $4;
535 $$ = $3;
536 }
537 | fixtype
538# | Lexcept
539# {
540# $$ = mktype($1.start, $1.stop, Texception, nil, nil);
541# $$.cons = byte 1;
542# }
543# | Lexcept '(' tuplist ')'
544# {
545# $$ = mktype($1.start, $4.stop, Texception, nil, revids($3));
546# $$.cons = byte 1;
547# }
548 ;
549
550iditype : Lid
551 {
552 $$ = mkidtype($<tok.src>1, $1);
553 }
554 | Lid '[' types ']'
555 {
556 $$ = mkinsttype($<tok.src>1, mkidtype($<tok.src>1, $1), $3);
557 }
558 ;
559
560dotiditype : type '.' Lid
561 {
562 $$ = mkdottype($1.src.start, $<tok.src>3.stop, $1, $3);
563 }
564 | type '.' Lid '[' types ']'
565 {
566 $$ = mkdottype($1.src.start, $<tok.src>3.stop, $1, $3);
567 $$ = mkinsttype($1.src, $$, $5);
568 }
569 ;
570
571tuplist : type
572 {
573 $$ = mkids($1.src, nil, $1, nil);
574 }
575 | tuplist ',' type
576 {
577 $$ = mkids($1.src, nil, $3, $1);
578 }
579 ;
580
581polydec :
582 {
583 $$ = nil;
584 }
585 | '[' ids ']'
586 {
587 $$ = polydecl($2);
588 }
589 ;
590
591fnarg : '(' forms ')'
592 {
593 $$ = mktype($1.start, $3.stop, Tfn, tnone, $2);
594 }
595 | '(' '*' ')'
596 {
597 $$ = mktype($1.start, $3.stop, Tfn, tnone, nil);
598 $$.varargs = byte 1;
599 }
600 | '(' ftypes ',' '*' ')'
601 {
602 $$ = mktype($1.start, $5.stop, Tfn, tnone, $2);
603 $$.varargs = byte 1;
604 }
605 ;
606
607fnargret: fnarg %prec ':'
608 {
609 $$ = $1;
610 }
611 | fnarg ':' type
612 {
613 $1.tof = $3;
614 $1.src.stop = $3.src.stop;
615 $$ = $1;
616 }
617 ;
618
619fnargretp: fnargret %prec '='
620 {
621 $$ = $1;
622 }
623 | fnargret Lfor '{' tpolys '}'
624 {
625 $$ = $1;
626 $$.val = rotater($4);
627 }
628 ;
629
630forms :
631 {
632 $$ = nil;
633 }
634 | ftypes
635 ;
636
637ftypes : ftype
638 | ftypes ',' ftype
639 {
640 $$ = appdecls($1, $3);
641 }
642 ;
643
644ftype : nids ':' type
645 {
646 $$ = typeids($1, $3);
647 }
648 | nids ':' adtk
649 {
650 $$ = typeids($1, $3);
651 for(d := $$; d != nil; d = d.next)
652 d.implicit = byte 1;
653 }
654 | idterms ':' type
655 {
656 $$ = mkids($1.src, enter("junk", 0), $3, nil);
657 $$.store = Darg;
658 yyerror("illegal argument declaraion");
659 }
660 | idterms ':' adtk
661 {
662 $$ = mkids($1.src, enter("junk", 0), $3, nil);
663 $$.store = Darg;
664 yyerror("illegal argument declaraion");
665 }
666 ;
667
668nids : nrids
669 {
670 $$ = revids($1);
671 }
672 ;
673
674nrids : Lid
675 {
676 $$ = mkids($<tok.src>1, $1, nil, nil);
677 $$.store = Darg;
678 }
679 | Lnil
680 {
681 $$ = mkids($1, nil, nil, nil);
682 $$.store = Darg;
683 }
684 | nrids ',' Lid
685 {
686 $$ = mkids($<tok.src>3, $3, nil, $1);
687 $$.store = Darg;
688 }
689 | nrids ',' Lnil
690 {
691 $$ = mkids($3, nil, nil, $1);
692 $$.store = Darg;
693 }
694 ;
695
696adtk : Lself iditype
697 {
698 $$ = $2;
699 }
700 | Lself Lref iditype
701 {
702 $$ = mktype($<tok.src>2.start, $<tok.src>3.stop, Tref, $3, nil);
703 }
704 | Lself dotiditype
705 {
706 $$ = $2;
707 }
708 | Lself Lref dotiditype
709 {
710 $$ = mktype($<tok.src>2.start, $<tok.src>3.stop, Tref, $3, nil);
711 }
712 ;
713
714fndef : fnname fnargretp raises fbody
715 {
716 $$ = fndecl($1, $2, $4);
717 nfns++;
718 # patch up polydecs
719 if($1.op == Odot){
720 if($1.right.left != nil){
721 $2.polys = $1.right.left.decl;
722 $1.right.left = nil;
723 }
724 if($1.left.op == Oname && $1.left.left != nil){
725 $$.decl = $1.left.left.decl;
726 $1.left.left = nil;
727 }
728 }
729 else{
730 if($1.left != nil){
731 $2.polys = $1.left.decl;
732 $1.left = nil;
733 }
734 }
735 $2.eraises = $3;
736 $$.src = $1.src;
737 }
738 ;
739
740raises : Lraises '(' idlist ')'
741 {
742 $$ = mkn(Otuple, rotater($3), nil);
743 $$.src.start = $1.start;
744 $$.src.stop = $4.stop;
745 }
746 | Lraises idatom
747 {
748 $$ = mkn(Otuple, mkunary(Oseq, $2), nil);
749 $$.src.start = $1.start;
750 $$.src.stop = $2.src.stop;
751 }
752 | %prec Lraises
753 {
754 $$ = nil;
755 }
756 ;
757
758fbody : '{' stmts '}'
759 {
760 if($2 == nil){
761 $2 = mkn(Onothing, nil, nil);
762 $2.src.start = curline();
763 $2.src.stop = $2.src.start;
764 }
765 $$ = rotater($2);
766 $$.src.start = $1.start;
767 $$.src.stop = $3.stop;
768 }
769 | error '}'
770 {
771 $$ = mkn(Onothing, nil, nil);
772 }
773 | error '{' stmts '}'
774 {
775 $$ = mkn(Onothing, nil, nil);
776 }
777 ;
778
779fnname : Lid polydec
780 {
781 $$ = mkname($<tok.src>1, $1);
782 if($2 != nil){
783 $$.left = mkn(Onothing, nil ,nil);
784 $$.left.decl = $2;
785 }
786 }
787 | fnname '.' Lid polydec
788 {
789 $$ = mkbin(Odot, $1, mkname($<tok.src>3, $3));
790 if($4 != nil){
791 $$.right.left = mkn(Onothing, nil ,nil);
792 $$.right.left.decl = $4;
793 }
794 }
795 ;
796
797stmts :
798 {
799 $$ = nil;
800 }
801 | stmts decl
802 {
803 if($1 == nil)
804 $$ = $2;
805 else if($2 == nil)
806 $$ = $1;
807 else
808 $$ = mkbin(Oseq, $1, $2);
809 }
810 | stmts stmt
811 {
812 if($1 == nil)
813 $$ = $2;
814 else
815 $$ = mkbin(Oseq, $1, $2);
816 }
817 ;
818
819elists : '(' elist ')'
820 | elists ',' '(' elist ')'
821 ;
822
823stmt : error ';'
824 {
825 $$ = mkn(Onothing, nil, nil);
826 $$.src.start = curline();
827 $$.src.stop = $$.src.start;
828 }
829 | error '}'
830 {
831 $$ = mkn(Onothing, nil, nil);
832 $$.src.start = curline();
833 $$.src.stop = $$.src.start;
834 }
835 | error '{' stmts '}'
836 {
837 $$ = mkn(Onothing, nil, nil);
838 $$.src.start = curline();
839 $$.src.stop = $$.src.start;
840 }
841 | '{' stmts '}'
842 {
843 if($2 == nil){
844 $2 = mkn(Onothing, nil, nil);
845 $2.src.start = curline();
846 $2.src.stop = $2.src.start;
847 }
848 $$ = mkscope(rotater($2));
849 }
850 | elists ':' type ';'
851 {
852 yyerror("illegal declaration");
853 $$ = mkn(Onothing, nil, nil);
854 $$.src.start = curline();
855 $$.src.stop = $$.src.start;
856 }
857 | elists ':' type '=' exp';'
858 {
859 yyerror("illegal declaration");
860 $$ = mkn(Onothing, nil, nil);
861 $$.src.start = curline();
862 $$.src.stop = $$.src.start;
863 }
864 | zexp ';'
865 {
866 $$ = $1;
867 }
868 | Lif '(' exp ')' stmt
869 {
870 $$ = mkn(Oif, $3, mkunary(Oseq, $5));
871 $$.src.start = $1.start;
872 $$.src.stop = $5.src.stop;
873 }
874 | Lif '(' exp ')' stmt Lelse stmt
875 {
876 $$ = mkn(Oif, $3, mkbin(Oseq, $5, $7));
877 $$.src.start = $1.start;
878 $$.src.stop = $7.src.stop;
879 }
880 | bclab Lfor '(' zexp ';' zexp ';' zexp ')' stmt
881 {
882 $$ = mkunary(Oseq, $10);
883 if($8.op != Onothing)
884 $$.right = $8;
885 $$ = mkbin(Ofor, $6, $$);
886 $$.decl = $1;
887 if($4.op != Onothing)
888 $$ = mkbin(Oseq, $4, $$);
889 }
890 | bclab Lwhile '(' zexp ')' stmt
891 {
892 $$ = mkn(Ofor, $4, mkunary(Oseq, $6));
893 $$.src.start = $2.start;
894 $$.src.stop = $6.src.stop;
895 $$.decl = $1;
896 }
897 | bclab Ldo stmt Lwhile '(' zexp ')' ';'
898 {
899 $$ = mkn(Odo, $6, $3);
900 $$.src.start = $2.start;
901 $$.src.stop = $7.stop;
902 $$.decl = $1;
903 }
904 | Lbreak bctarg ';'
905 {
906 $$ = mkn(Obreak, nil, nil);
907 $$.decl = $2;
908 $$.src = $1;
909 }
910 | Lcont bctarg ';'
911 {
912 $$ = mkn(Ocont, nil, nil);
913 $$.decl = $2;
914 $$.src = $1;
915 }
916 | Lreturn zexp ';'
917 {
918 $$ = mkn(Oret, $2, nil);
919 $$.src = $1;
920 if($2.op == Onothing)
921 $$.left = nil;
922 else
923 $$.src.stop = $2.src.stop;
924 }
925 | Lspawn exp ';'
926 {
927 $$ = mkn(Ospawn, $2, nil);
928 $$.src.start = $1.start;
929 $$.src.stop = $2.src.stop;
930 }
931 | Lraise zexp ';'
932 {
933 $$ = mkn(Oraise, $2, nil);
934 $$.src.start = $1.start;
935 $$.src.stop = $2.src.stop;
936 }
937 | bclab Lcase exp '{' cqstmts '}'
938 {
939 $$ = mkn(Ocase, $3, caselist($5, nil));
940 $$.src = $3.src;
941 $$.decl = $1;
942 }
943 | bclab Lalt '{' qstmts '}'
944 {
945 $$ = mkn(Oalt, caselist($4, nil), nil);
946 $$.src = $2;
947 $$.decl = $1;
948 }
949 | bclab Lpick Lid Ldeclas exp '{' pstmts '}'
950 {
951 $$ = mkn(Opick, mkbin(Odas, mkname($<tok.src>3, $3), $5), caselist($7, nil));
952 $$.src.start = $<tok.src>3.start;
953 $$.src.stop = $5.src.stop;
954 $$.decl = $1;
955 }
956 | Lexit ';'
957 {
958 $$ = mkn(Oexit, nil, nil);
959 $$.src = $1;
960 }
961 | '{' stmts '}' Lexcept idexc '{' eqstmts '}'
962 {
963 if($2 == nil){
964 $2 = mkn(Onothing, nil, nil);
965 $2.src.start = $2.src.stop = curline();
966 }
967 $2 = mkscope(rotater($2));
968 $$ = mkbin(Oexstmt, $2, mkn(Oexcept, $5, caselist($7, nil)));
969 }
970# | stmt Lexcept idexc '{' eqstmts '}'
971# {
972# $$ = mkbin(Oexstmt, $1, mkn(Oexcept, $3, caselist($5, nil)));
973# }
974 ;
975
976bclab :
977 {
978 $$ = nil;
979 }
980 | ids ':'
981 {
982 if($1.next != nil)
983 yyerror("only one identifier allowed in a label");
984 $$ = $1;
985 }
986 ;
987
988bctarg :
989 {
990 $$ = nil;
991 }
992 | Lid
993 {
994 $$ = mkids($<tok.src>1, $1, nil, nil);
995 }
996 ;
997
998qstmts : qbodies stmts
999 {
1000 $1.left.right.right = $2;
1001 $$ = $1;
1002 }
1003 ;
1004
1005qbodies : qual Llabs
1006 {
1007 $$ = mkunary(Oseq, mkscope(mkunary(Olabel, rotater($1))));
1008 }
1009 | qbodies stmts qual Llabs
1010 {
1011 $1.left.right.right = $2;
1012 $$ = mkbin(Oseq, mkscope(mkunary(Olabel, rotater($3))), $1);
1013 }
1014 ;
1015
1016cqstmts : cqbodies stmts
1017 {
1018 $1.left.right = mkscope($2);
1019 $$ = $1;
1020 }
1021 ;
1022
1023cqbodies : qual Llabs
1024 {
1025 $$ = mkunary(Oseq, mkunary(Olabel, rotater($1)));
1026 }
1027 | cqbodies stmts qual Llabs
1028 {
1029 $1.left.right = mkscope($2);
1030 $$ = mkbin(Oseq, mkunary(Olabel, rotater($3)), $1);
1031 }
1032 ;
1033
1034eqstmts : eqbodies stmts
1035 {
1036 $1.left.right = mkscope($2);
1037 $$ = $1;
1038 }
1039 ;
1040
1041eqbodies : qual Llabs
1042 {
1043 $$ = mkunary(Oseq, mkunary(Olabel, rotater($1)));
1044 }
1045 | eqbodies stmts qual Llabs
1046 {
1047 $1.left.right = mkscope($2);
1048 $$ = mkbin(Oseq, mkunary(Olabel, rotater($3)), $1);
1049 }
1050 ;
1051
1052qual : exp
1053 | exp Lto exp
1054 {
1055 $$ = mkbin(Orange, $1, $3);
1056 }
1057 | '*'
1058 {
1059 $$ = mkn(Owild, nil, nil);
1060 $$.src = $1;
1061 }
1062 | qual Lor qual
1063 {
1064 $$ = mkbin(Oseq, $1, $3);
1065 }
1066 | error
1067 {
1068 $$ = mkn(Onothing, nil, nil);
1069 $$.src.start = curline();
1070 $$.src.stop = $$.src.start;
1071 }
1072 ;
1073
1074pstmts : pbodies stmts
1075 {
1076 $1.left.right = mkscope($2);
1077 $$ = $1;
1078 }
1079 ;
1080
1081pbodies : pqual Llabs
1082 {
1083 $$ = mkunary(Oseq, mkunary(Olabel, rotater($1)));
1084 }
1085 | pbodies stmts pqual Llabs
1086 {
1087 $1.left.right = mkscope($2);
1088 $$ = mkbin(Oseq, mkunary(Olabel, rotater($3)), $1);
1089 }
1090 ;
1091
1092pqual : Lid
1093 {
1094 $$ = mkname($<tok>1.src, $1);
1095 }
1096 | '*'
1097 {
1098 $$ = mkn(Owild, nil, nil);
1099 $$.src = $1;
1100 }
1101 | pqual Lor pqual
1102 {
1103 $$ = mkbin(Oseq, $1, $3);
1104 }
1105 | error
1106 {
1107 $$ = mkn(Onothing, nil, nil);
1108 $$.src.start = curline();
1109 $$.src.stop = $$.src.start;
1110 }
1111 ;
1112
1113zexp :
1114 {
1115 $$ = mkn(Onothing, nil, nil);
1116 $$.src.start = curline();
1117 $$.src.stop = $$.src.start;
1118 }
1119 | exp
1120 ;
1121
1122exp : monexp
1123 | exp '=' exp
1124 {
1125 $$ = mkbin(Oas, $1, $3);
1126 }
1127 | exp Landeq exp
1128 {
1129 $$ = mkbin(Oandas, $1, $3);
1130 }
1131 | exp Loreq exp
1132 {
1133 $$ = mkbin(Ooras, $1, $3);
1134 }
1135 | exp Lxoreq exp
1136 {
1137 $$ = mkbin(Oxoras, $1, $3);
1138 }
1139 | exp Llsheq exp
1140 {
1141 $$ = mkbin(Olshas, $1, $3);
1142 }
1143 | exp Lrsheq exp
1144 {
1145 $$ = mkbin(Orshas, $1, $3);
1146 }
1147 | exp Laddeq exp
1148 {
1149 $$ = mkbin(Oaddas, $1, $3);
1150 }
1151 | exp Lsubeq exp
1152 {
1153 $$ = mkbin(Osubas, $1, $3);
1154 }
1155 | exp Lmuleq exp
1156 {
1157 $$ = mkbin(Omulas, $1, $3);
1158 }
1159 | exp Ldiveq exp
1160 {
1161 $$ = mkbin(Odivas, $1, $3);
1162 }
1163 | exp Lmodeq exp
1164 {
1165 $$ = mkbin(Omodas, $1, $3);
1166 }
1167 | exp Lexpeq exp
1168 {
1169 $$ = mkbin(Oexpas, $1, $3);
1170 }
1171 | exp Lcomm '=' exp
1172 {
1173 $$ = mkbin(Osnd, $1, $4);
1174 }
1175 | exp Ldeclas exp
1176 {
1177 $$ = mkbin(Odas, $1, $3);
1178 }
1179 | Lload Lid exp %prec Lload
1180 {
1181 $$ = mkn(Oload, $3, nil);
1182 $$.src.start = $<tok.src.start>1;
1183 $$.src.stop = $3.src.stop;
1184 $$.ty = mkidtype($<tok.src>2, $2);
1185 }
1186 | exp Lexp exp
1187 {
1188 $$ = $$ = mkbin(Oexp, $1, $3);
1189 }
1190 | exp '*' exp
1191 {
1192 $$ = mkbin(Omul, $1, $3);
1193 }
1194 | exp '/' exp
1195 {
1196 $$ = mkbin(Odiv, $1, $3);
1197 }
1198 | exp '%' exp
1199 {
1200 $$ = mkbin(Omod, $1, $3);
1201 }
1202 | exp '+' exp
1203 {
1204 $$ = mkbin(Oadd, $1, $3);
1205 }
1206 | exp '-' exp
1207 {
1208 $$ = mkbin(Osub, $1, $3);
1209 }
1210 | exp Lrsh exp
1211 {
1212 $$ = mkbin(Orsh, $1, $3);
1213 }
1214 | exp Llsh exp
1215 {
1216 $$ = mkbin(Olsh, $1, $3);
1217 }
1218 | exp '<' exp
1219 {
1220 $$ = mkbin(Olt, $1, $3);
1221 }
1222 | exp '>' exp
1223 {
1224 $$ = mkbin(Ogt, $1, $3);
1225 }
1226 | exp Lleq exp
1227 {
1228 $$ = mkbin(Oleq, $1, $3);
1229 }
1230 | exp Lgeq exp
1231 {
1232 $$ = mkbin(Ogeq, $1, $3);
1233 }
1234 | exp Leq exp
1235 {
1236 $$ = mkbin(Oeq, $1, $3);
1237 }
1238 | exp Lneq exp
1239 {
1240 $$ = mkbin(Oneq, $1, $3);
1241 }
1242 | exp '&' exp
1243 {
1244 $$ = mkbin(Oand, $1, $3);
1245 }
1246 | exp '^' exp
1247 {
1248 $$ = mkbin(Oxor, $1, $3);
1249 }
1250 | exp '|' exp
1251 {
1252 $$ = mkbin(Oor, $1, $3);
1253 }
1254 | exp Lcons exp
1255 {
1256 $$ = mkbin(Ocons, $1, $3);
1257 }
1258 | exp Landand exp
1259 {
1260 $$ = mkbin(Oandand, $1, $3);
1261 }
1262 | exp Loror exp
1263 {
1264 $$ = mkbin(Ooror, $1, $3);
1265 }
1266 ;
1267
1268monexp : term
1269 | '+' monexp
1270 {
1271 $2.src.start = $1.start;
1272 $$ = $2;
1273 }
1274 | '-' monexp
1275 {
1276 $$ = mkunary(Oneg, $2);
1277 $$.src.start = $1.start;
1278 }
1279 | '!' monexp
1280 {
1281 $$ = mkunary(Onot, $2);
1282 $$.src.start = $1.start;
1283 }
1284 | '~' monexp
1285 {
1286 $$ = mkunary(Ocomp, $2);
1287 $$.src.start = $1.start;
1288 }
1289 | '*' monexp
1290 {
1291 $$ = mkunary(Oind, $2);
1292 $$.src.start = $1.start;
1293 }
1294 | Linc monexp
1295 {
1296 $$ = mkunary(Opreinc, $2);
1297 $$.src.start = $1.start;
1298 }
1299 | Ldec monexp
1300 {
1301 $$ = mkunary(Opredec, $2);
1302 $$.src.start = $1.start;
1303 }
1304 | Lcomm monexp
1305 {
1306 $$ = mkunary(Orcv, $2);
1307 $$.src.start = $1.start;
1308 }
1309 | Lhd monexp
1310 {
1311 $$ = mkunary(Ohd, $2);
1312 $$.src.start = $1.start;
1313 }
1314 | Ltl monexp
1315 {
1316 $$ = mkunary(Otl, $2);
1317 $$.src.start = $1.start;
1318 }
1319 | Llen monexp
1320 {
1321 $$ = mkunary(Olen, $2);
1322 $$.src.start = $1.start;
1323 }
1324 | Lref monexp
1325 {
1326 $$ = mkunary(Oref, $2);
1327 $$.src.start = $1.start;
1328 }
1329 | Ltagof monexp
1330 {
1331 $$ = mkunary(Otagof, $2);
1332 $$.src.start = $1.start;
1333 }
1334 | Larray '[' exp ']' Lof type
1335 {
1336 $$ = mkn(Oarray, $3, nil);
1337 $$.ty = mktype($1.start, $6.src.stop, Tarray, $6, nil);
1338 $$.src = $$.ty.src;
1339 }
1340 | Larray '[' exp ']' Lof '{' initlist '}'
1341 {
1342 $$ = mkn(Oarray, $3, $7);
1343 $$.src.start = $1.start;
1344 $$.src.stop = $8.stop;
1345 }
1346 | Larray '[' ']' Lof '{' initlist '}'
1347 {
1348 $$ = mkn(Onothing, nil, nil);
1349 $$.src.start = $2.start;
1350 $$.src.stop = $3.stop;
1351 $$ = mkn(Oarray, $$, $6);
1352 $$.src.start = $1.start;
1353 $$.src.stop = $7.stop;
1354 }
1355 | Llist Lof '{' celist '}'
1356 {
1357 $$ = etolist($4);
1358 $$.src.start = $1.start;
1359 $$.src.stop = $5.stop;
1360 }
1361 | Lchan Lof type
1362 {
1363 $$ = mkn(Ochan, nil, nil);
1364 $$.ty = mktype($1.start, $3.src.stop, Tchan, $3, nil);
1365 $$.src = $$.ty.src;
1366 }
1367 | Lchan '[' exp ']' Lof type
1368 {
1369 $$ = mkn(Ochan, $3, nil);
1370 $$.ty = mktype($1.start, $6.src.stop, Tchan, $6, nil);
1371 $$.src = $$.ty.src;
1372 }
1373 | Larray Lof Ltid monexp
1374 {
1375 $$ = mkunary(Ocast, $4);
1376 $$.ty = mktype($1.start, $4.src.stop, Tarray, mkidtype($<tok.src>3, $3), nil);
1377 $$.src = $$.ty.src;
1378 }
1379 | Ltid monexp
1380 {
1381 $$ = mkunary(Ocast, $2);
1382 $$.src.start = $<tok.src>1.start;
1383 $$.ty = mkidtype($$.src, $1);
1384 }
1385 | Lid monexp
1386 {
1387 $$ = mkunary(Ocast, $2);
1388 $$.src.start = $<tok.src>1.start;
1389 $$.ty = mkidtype($$.src, $1);
1390 }
1391 | fixtype monexp
1392 {
1393 $$ = mkunary(Ocast, $2);
1394 $$.src.start = $<tok.src>1.start;
1395 $$.ty = $1;
1396 }
1397 ;
1398
1399term : idatom
1400 | term '(' zelist ')'
1401 {
1402 $$ = mkn(Ocall, $1, $3);
1403 $$.src.start = $1.src.start;
1404 $$.src.stop = $4.stop;
1405 }
1406 | '(' elist ')'
1407 {
1408 $$ = $2;
1409 if($2.op == Oseq)
1410 $$ = mkn(Otuple, rotater($2), nil);
1411 else
1412 $$.flags |= byte PARENS;
1413 $$.src.start = $1.start;
1414 $$.src.stop = $3.stop;
1415 }
1416 | Lfn fnargret
1417 {
1418# n := mkdeclname($1, mkids($1, enter(".fn"+string nfnexp++, 0), nil, nil));
1419# $<node>$ = fndef(n, $2);
1420# nfns++;
1421 } fbody
1422 {
1423# $$ = fnfinishdef($<node>3, $4);
1424# $$ = mkdeclname($1, $$.left.decl);
1425 yyerror("urt unk");
1426 $$ = nil;
1427 }
1428 | term '.' Lid
1429 {
1430 $$ = mkbin(Odot, $1, mkname($<tok.src>3, $3));
1431 }
1432 | term Lmdot term
1433 {
1434 $$ = mkbin(Omdot, $1, $3);
1435 }
1436 | term '[' export ']'
1437 {
1438 $$ = mkbin(Oindex, $1, $3);
1439 $$.src.stop = $4.stop;
1440 }
1441 | term '[' zexp ':' zexp ']'
1442 {
1443 if($3.op == Onothing)
1444 $3.src = $4;
1445 if($5.op == Onothing)
1446 $5.src = $4;
1447 $$ = mkbin(Oslice, $1, mkbin(Oseq, $3, $5));
1448 $$.src.stop = $6.stop;
1449 }
1450 | term Linc
1451 {
1452 $$ = mkunary(Oinc, $1);
1453 $$.src.stop = $2.stop;
1454 }
1455 | term Ldec
1456 {
1457 $$ = mkunary(Odec, $1);
1458 $$.src.stop = $2.stop;
1459 }
1460 | Lsconst
1461 {
1462 $$ = mksconst($<tok.src>1, $1);
1463 }
1464 | Lconst
1465 {
1466 $$ = mkconst($<tok.src>1, $1);
1467 if($1 > big 16r7fffffff || $1 < big -16r7fffffff)
1468 $$.ty = tbig;
1469 }
1470 | Lrconst
1471 {
1472 $$ = mkrconst($<tok.src>1, $1);
1473 }
1474 | term '[' exportlist ',' export ']'
1475 {
1476 $$ = mkbin(Oindex, $1, rotater(mkbin(Oseq, $3, $5)));
1477 $$.src.stop = $6.stop;
1478 }
1479 ;
1480
1481idatom : Lid
1482 {
1483 $$ = mkname($<tok.src>1, $1);
1484 }
1485 | Lnil
1486 {
1487 $$ = mknil($<tok.src>1);
1488 }
1489 ;
1490
1491idterm : '(' idlist ')'
1492 {
1493 $$ = mkn(Otuple, rotater($2), nil);
1494 $$.src.start = $1.start;
1495 $$.src.stop = $3.stop;
1496 }
1497 ;
1498
1499exportlist : export
1500 | exportlist ',' export
1501 {
1502 $$ = mkbin(Oseq, $1, $3);
1503 }
1504 ;
1505
1506export : exp
1507 | texp
1508 ;
1509
1510texp : Ltid
1511 {
1512 $$ = mkn(Otype, nil, nil);
1513 $$.ty = mkidtype($<tok.src>1, $1);
1514 $$.src = $$.ty.src;
1515 }
1516 | Larray Lof type
1517 {
1518 $$ = mkn(Otype, nil, nil);
1519 $$.ty = mktype($1.start, $3.src.stop, Tarray, $3, nil);
1520 $$.src = $$.ty.src;
1521 }
1522 | Llist Lof type
1523 {
1524 $$ = mkn(Otype, nil, nil);
1525 $$.ty = mktype($1.start, $3.src.stop, Tlist, $3, nil);
1526 $$.src = $$.ty.src;
1527 }
1528 | Lcyclic type
1529 {
1530 $$ = mkn(Otype, nil ,nil);
1531 $$.ty = $2;
1532 $$.ty.flags |= CYCLIC;
1533 $$.src = $$.ty.src;
1534 }
1535 ;
1536
1537idexc : Lid
1538 {
1539 $$ = mkname($<tok.src>1, $1);
1540 }
1541 | # empty
1542 {
1543 $$ = nil;
1544 }
1545 ;
1546
1547idlist : idterm
1548 | idatom
1549 | idlist ',' idterm
1550 {
1551 $$ = mkbin(Oseq, $1, $3);
1552 }
1553 | idlist ',' idatom
1554 {
1555 $$ = mkbin(Oseq, $1, $3);
1556 }
1557 ;
1558
1559zelist :
1560 {
1561 $$ = nil;
1562 }
1563 | elist
1564 {
1565 $$ = rotater($1);
1566 }
1567 ;
1568
1569celist : elist
1570 | elist ','
1571 ;
1572
1573elist : exp
1574 | elist ',' exp
1575 {
1576 $$ = mkbin(Oseq, $1, $3);
1577 }
1578 ;
1579
1580initlist : elemlist
1581 {
1582 $$ = rotater($1);
1583 }
1584 | elemlist ','
1585 {
1586 $$ = rotater($1);
1587 }
1588 ;
1589
1590elemlist : elem
1591 | elemlist ',' elem
1592 {
1593 $$ = mkbin(Oseq, $1, $3);
1594 }
1595 ;
1596
1597elem : exp
1598 {
1599 $$ = mkn(Oelem, nil, $1);
1600 $$.src = $1.src;
1601 }
1602 | qual Llabs exp
1603 {
1604 $$ = mkbin(Oelem, rotater($1), $3);
1605 }
1606 ;
1607
1608tpolys : tpoly dfields
1609 {
1610 if($1.op == Oseq)
1611 $1.right.left = rotater($2);
1612 else
1613 $1.left = rotater($2);
1614 $$ = $1;
1615 }
1616 ;
1617
1618tpoly : ids Llabs
1619 {
1620 $$ = typedecl($1, mktype($1.src.start, $2.stop, Tpoly, nil, nil));
1621 }
1622 | tpoly dfields ids Llabs
1623 {
1624 if($1.op == Oseq)
1625 $1.right.left = rotater($2);
1626 else
1627 $1.left = rotater($2);
1628 $$ = mkbin(Oseq, $1, typedecl($3, mktype($3.src.start, $4.stop, Tpoly, nil, nil)));
1629 }
1630 ;
1631
1632%%
1633
1634include "ipints.m";
1635include "crypt.m";
1636
1637sys: Sys;
1638 print, fprint, sprint: import sys;
1639
1640bufio: Bufio;
1641 Iobuf: import bufio;
1642
1643str: String;
1644
1645crypt:Crypt;
1646 md5: import crypt;
1647
1648math: Math;
1649 import_real, export_real, isnan: import math;
1650
1651yyctxt: ref YYLEX;
1652
1653canonnan: real;
1654
1655debug = array[256] of {* => 0};
1656
1657noline = -1;
1658nosrc = Src(-1, -1);
1659
1660infile: string;
1661
1662# front end
1663include "arg.m";
1664include "lex.b";
1665include "types.b";
1666include "nodes.b";
1667include "decls.b";
1668
1669include "typecheck.b";
1670
1671# back end
1672include "gen.b";
1673include "ecom.b";
1674include "asm.b";
1675include "dis.b";
1676include "sbl.b";
1677include "stubs.b";
1678include "com.b";
1679include "optim.b";
1680
1681init(nil: ref Draw->Context, argv: list of string)
1682{
1683 s: string;
1684
1685 sys = load Sys Sys->PATH;
1686 crypt = load Crypt Crypt->PATH;
1687 math = load Math Math->PATH;
1688 bufio = load Bufio Bufio->PATH;
1689 if(bufio == nil){
1690 sys->print("can't load %s: %r\n", Bufio->PATH);
1691 raise("fail:bad module");
1692 }
1693 str = load String String->PATH;
1694 if(str == nil){
1695 sys->print("can't load %s: %r\n", String->PATH);
1696 raise("fail:bad module");
1697 }
1698
1699 stderr = sys->fildes(2);
1700 yyctxt = ref YYLEX;
1701
1702 math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX);
1703 na := array[1] of {0.};
1704 import_real(array[8] of {byte 16r7f, * => byte 16rff}, na);
1705 canonnan = na[0];
1706 if(!isnan(canonnan))
1707 fatal("bad canonical NaN");
1708
1709 lexinit();
1710 typeinit();
1711 optabinit();
1712
1713 gendis = 1;
1714 asmsym = 0;
1715 maxerr = 20;
1716 ofile := "";
1717 ext := "";
1718
1719 arg := Arg.init(argv);
1720 while(c := arg.opt()){
1721 case c{
1722 'Y' =>
1723 emitsbl = arg.arg();
1724 if(emitsbl == nil)
1725 usage();
1726 'C' =>
1727 dontcompile = 1;
1728 'D' =>
1729 #
1730 # debug flags:
1731 #
1732 # a alt compilation
1733 # A array constructor compilation
1734 # b boolean and branch compilation
1735 # c case compilation
1736 # d function declaration
1737 # D descriptor generation
1738 # e expression compilation
1739 # E addressable expression compilation
1740 # f print arguments for compiled functions
1741 # F constant folding
1742 # g print out globals
1743 # m module declaration and type checking
1744 # n nil references
1745 # s print sizes of output file sections
1746 # S type signing
1747 # t type checking function bodies
1748 # T timing
1749 # v global var and constant compilation
1750 # x adt verification
1751 # Y tuple compilation
1752 # z Z bug fixes
1753 #
1754 s = arg.arg();
1755 for(i := 0; i < len s; i++){
1756 c = s[i];
1757 if(c < len debug)
1758 debug[c] = 1;
1759 }
1760 'I' =>
1761 s = arg.arg();
1762 if(s == "")
1763 usage();
1764 addinclude(s);
1765 'G' =>
1766 asmsym = 1;
1767 'S' =>
1768 gendis = 0;
1769 'a' =>
1770 emitstub = 1;
1771 'A' =>
1772 emitstub = emitdyn = 1;
1773 'c' =>
1774 mustcompile = 1;
1775 'e' =>
1776 maxerr = 1000;
1777 'f' =>
1778 fabort = 1;
1779 'F' =>
1780 newfnptr = 1;
1781 'g' =>
1782 dosym = 1;
1783 'i' =>
1784 dontinline = 1;
1785 'o' =>
1786 ofile = arg.arg();
1787 'O' =>
1788 optims = 1;
1789 's' =>
1790 s = arg.arg();
1791 if(s != nil)
1792 fixss = int s;
1793 't' =>
1794 emittab = arg.arg();
1795 if(emittab == nil)
1796 usage();
1797 'T' =>
1798 emitcode = arg.arg();
1799 if(emitcode == nil)
1800 usage();
1801 'd' =>
1802 emitcode = arg.arg();
1803 if(emitcode == nil)
1804 usage();
1805 emitdyn = 1;
1806 'w' =>
1807 superwarn = dowarn;
1808 dowarn = 1;
1809 'x' =>
1810 ext = arg.arg();
1811 'X' =>
1812 signdump = arg.arg();
1813 'z' =>
1814 arrayz = 1;
1815 'y' =>
1816 oldcycles = 1;
1817 * =>
1818 usage();
1819 }
1820 }
1821
1822 addinclude("/module");
1823
1824 argv = arg.argv;
1825 arg = nil;
1826
1827 if(argv == nil){
1828 usage();
1829 }else if(ofile != nil){
1830 if(len argv != 1)
1831 usage();
1832 translate(hd argv, ofile, mkfileext(ofile, ".dis", ".sbl"));
1833 }else{
1834 pr := len argv != 1;
1835 if(ext == ""){
1836 ext = ".s";
1837 if(gendis)
1838 ext = ".dis";
1839 }
1840 for(; argv != nil; argv = tl argv){
1841 file := hd argv;
1842 (nil, s) = str->splitr(file, "/");
1843 if(pr)
1844 print("%s:\n", s);
1845 out := mkfileext(s, ".b", ext);
1846 translate(file, out, mkfileext(out, ext, ".sbl"));
1847 }
1848 }
1849 if (toterrors > 0)
1850 raise("fail:errors");
1851}
1852
1853usage()
1854{
1855 fprint(stderr, "usage: limbo [-GSagwe] [-I incdir] [-o outfile] [-{T|t|d} module] [-D debug] file ...\n");
1856 raise("fail:usage");
1857}
1858
1859mkfileext(file, oldext, ext: string): string
1860{
1861 n := len file;
1862 n2 := len oldext;
1863 if(n >= n2 && file[n-n2:] == oldext)
1864 file = file[:n-n2];
1865 return file + ext;
1866}
1867
1868translate(in, out, dbg: string)
1869{
1870 infile = in;
1871 outfile = out;
1872 errors = 0;
1873 bins[0] = bufio->open(in, Bufio->OREAD);
1874 if(bins[0] == nil){
1875 fprint(stderr, "can't open %s: %r\n", in);
1876 toterrors++;
1877 return;
1878 }
1879 doemit := emitcode != "" || emitstub || emittab != "" || emitsbl != "";
1880 if(!doemit){
1881 bout = bufio->create(out, Bufio->OWRITE, 8r666);
1882 if(bout == nil){
1883 fprint(stderr, "can't open %s: %r\n", out);
1884 toterrors++;
1885 bins[0].close();
1886 return;
1887 }
1888 if(dosym){
1889 bsym = bufio->create(dbg, Bufio->OWRITE, 8r666);
1890 if(bsym == nil)
1891 fprint(stderr, "can't open %s: %r\n", dbg);
1892 }
1893 }
1894
1895 lexstart(in);
1896
1897 popscopes();
1898 typestart();
1899 declstart();
1900 nfnexp = 0;
1901
1902 parset = sys->millisec();
1903 yyparse(yyctxt);
1904 parset = sys->millisec() - parset;
1905
1906 checkt = sys->millisec();
1907 entry := typecheck(!doemit);
1908 checkt = sys->millisec() - checkt;
1909
1910 modcom(entry);
1911
1912 fns = nil;
1913 nfns = 0;
1914 descriptors = nil;
1915
1916 if(debug['T'])
1917 print("times: parse=%d type=%d: gen=%d write=%d symbols=%d\n",
1918 parset, checkt, gent, writet, symt);
1919
1920 if(bout != nil)
1921 bout.close();
1922 if(bsym != nil)
1923 bsym.close();
1924 toterrors += errors;
1925 if(errors && bout != nil)
1926 sys->remove(out);
1927 if(errors && bsym != nil)
1928 sys->remove(dbg);
1929}
1930
1931pwd(): string
1932{
1933 workdir := load Workdir Workdir->PATH;
1934 if(workdir == nil)
1935 cd := "/";
1936 else
1937 cd = workdir->init();
1938 # sys->print("pwd: %s\n", cd);
1939 return cd;
1940}
1941
1942cleanname(s: string): string
1943{
1944 ls, path: list of string;
1945
1946 if(s == nil)
1947 return nil;
1948 if(s[0] != '/' && s[0] != '\\')
1949 (nil, ls) = sys->tokenize(pwd(), "/\\");
1950 for( ; ls != nil; ls = tl ls)
1951 path = hd ls :: path;
1952 (nil, ls) = sys->tokenize(s, "/\\");
1953 for( ; ls != nil; ls = tl ls){
1954 n := hd ls;
1955 if(n == ".")
1956 ;
1957 else if (n == ".."){
1958 if(path != nil)
1959 path = tl path;
1960 }
1961 else
1962 path = n :: path;
1963 }
1964 p := "";
1965 for( ; path != nil; path = tl path)
1966 p = "/" + hd path + p;
1967 if(p == nil)
1968 p = "/";
1969 # sys->print("cleanname: %s\n", p);
1970 return p;
1971}
1972
1973srcpath(): string
1974{
1975 srcp := cleanname(infile);
1976 # sys->print("srcpath: %s\n", srcp);
1977 return srcp;
1978}
limbo/compiler/nodes.b+1402−0
@@ -0,0 +1,1402 @@
1include "opname.m";
2
3znode: Node;
4
5isused = array[Oend] of
6{
7 Oas => 1,
8 Odas => 1,
9 Oaddas => 1,
10 Osubas => 1,
11 Omulas => 1,
12 Odivas => 1,
13 Omodas => 1,
14 Oexpas => 1,
15 Oandas => 1,
16 Ooras => 1,
17 Oxoras => 1,
18 Olshas => 1,
19 Onothing => 1,
20 Orshas => 1,
21 Oinc => 1,
22 Odec => 1,
23 Opreinc => 1,
24 Opredec => 1,
25 Ocall => 1,
26 Oraise => 1,
27 Ospawn => 1,
28 Osnd => 1,
29 Orcv => 1,
30
31 * => 0
32};
33
34sideeffect := array[Oend] of
35{
36 Oas => 1,
37 Odas => 1,
38 Oaddas => 1,
39 Osubas => 1,
40 Omulas => 1,
41 Odivas => 1,
42 Omodas => 1,
43 Oexpas => 1,
44 Oandas => 1,
45 Ooras => 1,
46 Oxoras => 1,
47 Olshas => 1,
48 Orshas => 1,
49 Oinc => 1,
50 Odec => 1,
51 Opreinc => 1,
52 Opredec => 1,
53 Ocall => 1,
54 Oraise => 1,
55 Ospawn => 1,
56 Osnd => 1,
57 Orcv => 1,
58
59 Oadr => 1,
60 Oarray => 1,
61 Ocast => 1,
62 Ochan => 1,
63 Ocons => 1,
64 Odiv => 1,
65 Odot => 1,
66 Oind => 1,
67 Oindex => 1,
68 Oinds => 1,
69 Oindx => 1,
70 Olen => 1,
71 Oload => 1,
72 Omod => 1,
73 Oref => 1,
74
75 * => 0
76};
77
78opcommute = array[Oend] of
79{
80 Oeq => Oeq,
81 Oneq => Oneq,
82 Olt => Ogt,
83 Ogt => Olt,
84 Ogeq => Oleq,
85 Oleq => Ogeq,
86 Oadd => Oadd,
87 Omul => Omul,
88 Oxor => Oxor,
89 Oor => Oor,
90 Oand => Oand,
91
92 * => 0
93};
94
95oprelinvert = array[Oend] of
96{
97
98 Oeq => Oneq,
99 Oneq => Oeq,
100 Olt => Ogeq,
101 Ogt => Oleq,
102 Ogeq => Olt,
103 Oleq => Ogt,
104
105 * => 0
106};
107
108isrelop := array[Oend] of
109{
110
111 Oeq => 1,
112 Oneq => 1,
113 Olt => 1,
114 Oleq => 1,
115 Ogt => 1,
116 Ogeq => 1,
117 Oandand => 1,
118 Ooror => 1,
119 Onot => 1,
120
121 * => 0
122};
123
124ipow(x: big, n: int): big
125{
126 inv: int;
127 r: big;
128
129 inv = 0;
130 if(n < 0){
131 n = -n;
132 inv = 1;
133 }
134 r = big 1;
135 for(;;){
136 if(n&1)
137 r *= x;
138 if((n >>= 1) == 0)
139 break;
140 x *= x;
141 }
142 if(inv)
143 r = big 1/r;
144 return r;
145}
146
147rpow(x: real, n: int): real
148{
149 inv: int;
150 r: real;
151
152 inv = 0;
153 if(n < 0){
154 n = -n;
155 inv = 1;
156 }
157 r = 1.0;
158 for(;;){
159 if(n&1)
160 r *= x;
161 if((n >>= 1) == 0)
162 break;
163 x *= x;
164 }
165 if(inv)
166 r = 1.0/r;
167 return r;
168}
169
170real2fix(v: real, t: ref Type): big
171{
172 return big(v/scale(t));
173}
174
175fix2fix(v: big, f: ref Type, t: ref Type): big
176{
177 return big(real v * (scale(f)/scale(t)));
178}
179
180fix2real(v: big, f: ref Type): real
181{
182 return real v * scale(f);
183}
184
185istuple(n: ref Node): int
186{
187 d: ref Decl;
188
189 case(n.op){
190 Otuple =>
191 return 1;
192 Oname =>
193 d = n.decl;
194 if(d.importid != nil)
195 d = d.importid;
196 return d.store == Dconst && (n.ty.kind == Ttuple || n.ty.kind == Tadt);
197 Odot =>
198 return 0; # istuple(n.left);
199 }
200 return 0;
201}
202
203tuplemem(n: ref Node, d: ref Decl): ref Node
204{
205 ty: ref Type;
206 ids: ref Decl;
207
208 ty = n.ty;
209 n = n.left;
210 for(ids = ty.ids; ids != nil; ids = ids.next){
211 if(ids.sym == d.sym)
212 break;
213 else
214 n = n.right;
215 }
216 if(n == nil)
217 fatal("tuplemem cannot cope !\n");
218 return n.left;
219}
220
221varcom(v: ref Decl): int
222{
223 n := v.init;
224 n = fold(n);
225 v.init = n;
226 if(debug['v'])
227 print("variable '%s' val %s\n", v.sym.name, expconv(n));
228 if(n == nil)
229 return 1;
230
231 tn := ref znode;
232 tn.op = Oname;
233 tn.decl = v;
234 tn.src = v.src;
235 tn.ty = v.ty;
236 return initable(tn, n, 0);
237}
238
239initable(v, n: ref Node, allocdep: int): int
240{
241 case n.ty.kind{
242 Tiface or
243 Tgoto or
244 Tcase or
245 Tcasel or
246 Tcasec or
247 Talt or
248 Texcept =>
249 return 1;
250 Tint or
251 Tbig or
252 Tbyte or
253 Treal or
254 Tstring or
255 Tfix =>
256 if(n.op != Oconst)
257 break;
258 return 1;
259 Tadt or
260 Tadtpick or
261 Ttuple =>
262 if(n.op == Otuple)
263 n = n.left;
264 else if(n.op == Ocall)
265 n = n.right;
266 else
267 break;
268 for(; n != nil; n = n.right)
269 if(!initable(v, n.left, allocdep))
270 return 0;
271 return 1;
272 Tarray =>
273 if(n.op != Oarray)
274 break;
275 if(allocdep >= DADEPTH){
276 nerror(v, expconv(v)+"s initializer has arrays nested more than "+string allocdep+" deep");
277 return 0;
278 }
279 allocdep++;
280 usedesc(mktdesc(n.ty.tof));
281 if(n.left.op != Oconst){
282 nerror(v, expconv(v)+"s size is not a constant");
283 return 0;
284 }
285 for(e := n.right; e != nil; e = e.right)
286 if(!initable(v, e.left.right, allocdep))
287 return 0;
288 return 1;
289 Tany =>
290 return 1;
291 Tref or
292 Tlist or
293 Tpoly or
294 * =>
295 nerror(v, "can't initialize "+etconv(v));
296 return 0;
297 }
298 nerror(v, expconv(v)+"s initializer, "+expconv(n)+", is not a constant expression");
299 return 0;
300}
301
302#
303# merge together two sorted lists, yielding a sorted list
304#
305elemmerge(e, f: ref Node): ref Node
306{
307 r := rock := ref Node;
308 while(e != nil && f != nil){
309 if(e.left.left.c.val <= f.left.left.c.val){
310 r.right = e;
311 e = e.right;
312 }else{
313 r.right = f;
314 f = f.right;
315 }
316 r = r.right;
317 }
318 if(e != nil)
319 r.right = e;
320 else
321 r.right = f;
322 return rock.right;
323}
324
325#
326# recursively split lists and remerge them after they are sorted
327#
328recelemsort(e: ref Node, n: int): ref Node
329{
330 if(n <= 1)
331 return e;
332 m := n / 2 - 1;
333 ee := e;
334 for(i := 0; i < m; i++)
335 ee = ee.right;
336 r := ee.right;
337 ee.right = nil;
338 return elemmerge(recelemsort(e, n / 2),
339 recelemsort(r, (n + 1) / 2));
340}
341
342#
343# sort the elems by index; wild card is first
344#
345elemsort(e: ref Node): ref Node
346{
347 n := 0;
348 for(ee := e; ee != nil; ee = ee.right){
349 if(ee.left.left.op == Owild)
350 ee.left.left.c = ref Const(big -1, 0.);
351 n++;
352 }
353 return recelemsort(e, n);
354}
355
356sametree(n1: ref Node, n2: ref Node): int
357{
358 if(n1 == n2)
359 return 1;
360 if(n1 == nil || n2 == nil)
361 return 0;
362 if(n1.op != n2.op || n1.ty != n2.ty)
363 return 0;
364 if(n1.op == Oconst){
365 case(n1.ty.kind){
366 Tbig or
367 Tbyte or
368 Tint =>
369 return n1.c.val == n2.c.val;
370 Treal =>
371 return n1.c.rval == n2.c.rval;
372 Tfix =>
373 return n1.c.val == n2.c.val && tequal(n1.ty, n2.ty);
374 Tstring =>
375 return n1.decl.sym == n2.decl.sym;
376 }
377 return 0;
378 }
379 return n1.decl == n2.decl && sametree(n1.left, n2.left) && sametree(n1.right, n2.right);
380}
381
382occurs(d: ref Decl, n: ref Node): int
383{
384 if(n == nil)
385 return 0;
386 if(n.op == Oname){
387 if(d == n.decl)
388 return 1;
389 return 0;
390 }
391 return occurs(d, n.left) + occurs(d, n.right);
392}
393
394#
395# left and right subtrees the same
396#
397folds(n: ref Node): ref Node
398{
399 if(hasside(n, 1))
400 return n;
401 case(n.op){
402 Oeq or
403 Oleq or
404 Ogeq =>
405 n.c = ref Const(big 1, 0.0);
406 Osub =>
407 n.c = ref Const(big 0, 0.0);
408 Oxor or
409 Oneq or
410 Olt or
411 Ogt =>
412 n.c = ref Const(big 0, 0.0);
413 Oand or
414 Oor or
415 Oandand or
416 Ooror =>
417 return n.left;
418 * =>
419 return n;
420 }
421 n.op = Oconst;
422 n.left = n.right = nil;
423 n.decl = nil;
424 return n;
425}
426
427#
428# constant folding for typechecked expressions
429#
430fold(n: ref Node): ref Node
431{
432 if(n == nil)
433 return nil;
434 if(debug['F'])
435 print("fold %s\n", nodeconv(n));
436 n = efold(n);
437 if(debug['F'])
438 print("folded %s\n", nodeconv(n));
439 return n;
440}
441
442efold(n: ref Node): ref Node
443{
444 d: ref Decl;
445
446 if(n == nil)
447 return nil;
448
449 left := n.left;
450 right := n.right;
451 case n.op{
452 Oname =>
453 d = n.decl;
454 if(d.importid != nil)
455 d = d.importid;
456 if(d.store != Dconst){
457 if(d.store == Dtag){
458 n.op = Oconst;
459 n.ty = tint;
460 n.c = ref Const(big d.tag, 0.);
461 }
462 break;
463 }
464 case n.ty.kind{
465 Tbig =>
466 n.op = Oconst;
467 n.c = ref Const(d.init.c.val, 0.);
468 Tbyte =>
469 n.op = Oconst;
470 n.c = ref Const(big byte d.init.c.val, 0.);
471 Tint or
472 Tfix =>
473 n.op = Oconst;
474 n.c = ref Const(big int d.init.c.val, 0.);
475 Treal =>
476 n.op = Oconst;
477 n.c = ref Const(big 0, d.init.c.rval);
478 Tstring =>
479 n.op = Oconst;
480 n.decl = d.init.decl;
481 Ttuple =>
482 *n = *d.init;
483 Tadt =>
484 *n = *d.init;
485 n = rewrite(n); # was call
486 Texception =>
487 if(n.ty.cons == byte 0)
488 fatal("non-const exception type in efold");
489 n.op = Oconst;
490 * =>
491 fatal("unknown const type "+typeconv(n.ty)+" in efold");
492 }
493 Oadd =>
494 left = efold(left);
495 right = efold(right);
496 n.left = left;
497 n.right = right;
498 if(n.ty == tstring && right.op == Oconst){
499 if(left.op == Oconst)
500 n = mksconst(n.src, stringcat(left.decl.sym, right.decl.sym));
501 else if(left.op == Oadd && left.ty == tstring && left.right.op == Oconst){
502 left.right = mksconst(n.src, stringcat(left.right.decl.sym, right.decl.sym));
503 n = left;
504 }
505 }
506 Olen =>
507 left = efold(left);
508 n.left = left;
509 if(left.ty == tstring && left.op == Oconst)
510 n = mkconst(n.src, big len left.decl.sym.name);
511 Oslice =>
512 if(right.left.op == Onothing)
513 right.left = mkconst(right.left.src, big 0);
514 n.left = efold(left);
515 n.right = efold(right);
516 Oinds =>
517 n.left = left = efold(left);
518 n.right = right = efold(right);
519 if(right.op == Oconst && left.op == Oconst){
520 ;
521 }
522 Ocast =>
523 n.op = Ocast;
524 left = efold(left);
525 n.left = left;
526 if(n.ty == left.ty || n.ty.kind == Tfix && tequal(n.ty, left.ty))
527 return left;
528 if(left.op == Oconst)
529 return foldcast(n, left);
530 Odot or
531 Omdot =>
532 #
533 # what about side effects from left?
534 #
535 d = right.decl;
536 case d.store{
537 Dconst or
538 Dtag or
539 Dtype =>
540 #
541 # set it up as a name and let that case do the hard work
542 #
543 n.op = Oname;
544 n.decl = d;
545 n.left = nil;
546 n.right = nil;
547 return efold(n);
548 }
549 n.left = efold(left);
550 if(n.left.op == Otuple)
551 n = tuplemem(n.left, d);
552 else
553 n.right = efold(right);
554 Otagof =>
555 if(n.decl != nil){
556 n.op = Oconst;
557 n.left = nil;
558 n.right = nil;
559 n.c = ref Const(big n.decl.tag, 0.);
560 return efold(n);
561 }
562 n.left = efold(left);
563 Oif =>
564 n.left = left = efold(left);
565 n.right = right = efold(right);
566 if(left.op == Oconst){
567 if(left.c.val != big 0)
568 return right.left;
569 else
570 return right.right;
571 }
572 * =>
573 n.left = efold(left);
574 n.right = efold(right);
575 }
576
577 left = n.left;
578 right = n.right;
579 if(left == nil)
580 return n;
581
582 if(right == nil){
583 if(left.op == Oconst){
584 if(left.ty == tint || left.ty == tbyte || left.ty == tbig)
585 return foldc(n);
586 if(left.ty == treal)
587 return foldr(n);
588 }
589 return n;
590 }
591
592 if(left.op == Oconst){
593 case n.op{
594 Olsh or
595 Orsh =>
596 if(left.c.val == big 0 && !hasside(right, 1))
597 return left;
598 Ooror =>
599 if(left.ty == tint || left.ty == tbyte || left.ty == tbig){
600 if(left.c.val == big 0){
601 n = mkbin(Oneq, right, mkconst(right.src, big 0));
602 n.ty = right.ty;
603 n.left.ty = right.ty;
604 return efold(n);
605 }
606 left.c.val = big 1;
607 return left;
608 }
609 Oandand =>
610 if(left.ty == tint || left.ty == tbyte || left.ty == tbig){
611 if(left.c.val == big 0)
612 return left;
613 n = mkbin(Oneq, right, mkconst(right.src, big 0));
614 n.ty = right.ty;
615 n.left.ty = right.ty;
616 return efold(n);
617 }
618 }
619 }
620 if(left.op == Oconst && right.op != Oconst
621 && opcommute[n.op]
622 && n.ty != tstring){
623 n.op = opcommute[n.op];
624 n.left = right;
625 n.right = left;
626 left = right;
627 right = n.right;
628 }
629 if(right.op == Oconst && left.op == n.op && left.right.op == Oconst
630 && (n.op == Oadd || n.op == Omul || n.op == Oor || n.op == Oxor || n.op == Oand)
631 && n.ty != tstring){
632 n.left = left.left;
633 left.left = right;
634 right = efold(left);
635 n.right = right;
636 left = n.left;
637 }
638 if(right.op == Oconst){
639 if(n.op == Oexp && left.ty == treal){
640 if(left.op == Oconst)
641 return foldr(n);
642 return n;
643 }
644 if(right.ty == tint || right.ty == tbyte || left.ty == tbig){
645 if(left.op == Oconst)
646 return foldc(n);
647 return foldvc(n);
648 }
649 if(right.ty == treal && left.op == Oconst)
650 return foldr(n);
651 }
652 if(sametree(left, right))
653 return folds(n);
654 return n;
655}
656
657#
658# does evaluating the node have any side effects?
659#
660hasside(n: ref Node, strict: int): int
661{
662 for(; n != nil; n = n.right){
663 if(sideeffect[n.op] && (strict || n.op != Oadr && n.op != Oind))
664 return 1;
665 if(hasside(n.left, strict))
666 return 1;
667 }
668 return 0;
669}
670
671hascall(n: ref Node): int
672{
673 for(; n != nil; n = n.right){
674 if(n.op == Ocall || n.op == Ospawn)
675 return 1;
676 if(hascall(n.left))
677 return 1;
678 }
679 return 0;
680}
681
682hasasgns(n: ref Node): int
683{
684 if(n == nil)
685 return 0;
686 if(n.op != Ocall && isused[n.op] && n.op != Onothing)
687 return 1;
688 return hasasgns(n.left) || hasasgns(n.right);
689}
690
691nodes(n: ref Node): int
692{
693 if(n == nil)
694 return 0;
695 return 1+nodes(n.left)+nodes(n.right);
696}
697
698foldcast(n, left: ref Node): ref Node
699{
700 case left.ty.kind{
701 Tint =>
702 left.c.val = big int left.c.val;
703 return foldcasti(n, left);
704 Tbyte =>
705 left.c.val = big byte left.c.val;
706 return foldcasti(n, left);
707 Tbig =>
708 return foldcasti(n, left);
709 Treal =>
710 case n.ty.kind{
711 Tint or
712 Tbyte or
713 Tbig =>
714 left.c.val = big left.c.rval;
715 Tfix =>
716 left.c.val = real2fix(left.c.rval, n.ty);
717 Tstring =>
718 return mksconst(n.src, enterstring(string left.c.rval));
719 * =>
720 return n;
721 }
722 Tfix =>
723 case n.ty.kind{
724 Tint or
725 Tbyte or
726 Tbig =>
727 left.c.val = big fix2real(left.c.val, left.ty);
728 Treal =>
729 left.c.rval = fix2real(left.c.val, left.ty);
730 Tfix =>
731 if(tequal(left.ty, n.ty))
732 return left;
733 left.c.val = fix2fix(left.c.val, left.ty, n.ty);
734 Tstring =>
735 return mksconst(n.src, enterstring(string fix2real(left.c.val, left.ty)));
736 * =>
737 return n;
738 }
739 break;
740 Tstring =>
741 case n.ty.kind{
742 Tint or
743 Tbyte or
744 Tbig =>
745 left.c = ref Const(big left.decl.sym.name, 0.);
746 Treal =>
747 left.c = ref Const(big 0, real left.decl.sym.name);
748 Tfix =>
749 left.c = ref Const(real2fix(real left.decl.sym.name, n.ty), 0.);
750 * =>
751 return n;
752 }
753 * =>
754 return n;
755 }
756 left.ty = n.ty;
757 left.src = n.src;
758 return left;
759}
760
761#
762# left is some kind of int type
763#
764foldcasti(n, left: ref Node): ref Node
765{
766 case n.ty.kind{
767 Tint =>
768 left.c.val = big int left.c.val;
769 Tbyte =>
770 left.c.val = big byte left.c.val;
771 Tbig =>
772 ;
773 Treal =>
774 left.c.rval = real left.c.val;
775 Tfix =>
776 left.c.val = real2fix(real left.c.val, n.ty);
777 Tstring =>
778 return mksconst(n.src, enterstring(string left.c.val));
779 * =>
780 return n;
781 }
782 left.ty = n.ty;
783 left.src = n.src;
784 return left;
785}
786
787#
788# right is a const int
789#
790foldvc(n: ref Node): ref Node
791{
792 left := n.left;
793 right := n.right;
794 case n.op{
795 Oadd or
796 Osub or
797 Oor or
798 Oxor or
799 Olsh or
800 Orsh or
801 Ooror =>
802 if(right.c.val == big 0)
803 return left;
804 if(n.op == Ooror && !hasside(left, 1))
805 return right;
806 Oand =>
807 if(right.c.val == big 0 && !hasside(left, 1))
808 return right;
809 Omul =>
810 if(right.c.val == big 1)
811 return left;
812 if(right.c.val == big 0 && !hasside(left, 1))
813 return right;
814 Odiv =>
815 if(right.c.val == big 1)
816 return left;
817 Omod =>
818 if(right.c.val == big 1 && !hasside(left, 1)){
819 right.c.val = big 0;
820 return right;
821 }
822 Oexp =>
823 if(right.c.val == big 0){
824 right.c.val = big 1;
825 return right;
826 }
827 if(right.c.val == big 1)
828 return left;
829 Oandand =>
830 if(right.c.val != big 0)
831 return left;
832 if(!hasside(left, 1))
833 return right;
834 Oneq =>
835 if(!isrelop[left.op])
836 return n;
837 if(right.c.val == big 0)
838 return left;
839 n.op = Onot;
840 n.right = nil;
841 Oeq =>
842 if(!isrelop[left.op])
843 return n;
844 if(right.c.val != big 0)
845 return left;
846 n.op = Onot;
847 n.right = nil;
848 }
849 return n;
850}
851
852#
853# left and right are const ints
854#
855foldc(n: ref Node): ref Node
856{
857 v: big;
858 rv, nb: int;
859
860 left := n.left;
861 right := n.right;
862 case n.op{
863 Oadd =>
864 v = left.c.val + right.c.val;
865 Osub =>
866 v = left.c.val - right.c.val;
867 Omul =>
868 v = left.c.val * right.c.val;
869 Odiv =>
870 if(right.c.val == big 0){
871 nerror(n, "divide by 0 in constant expression");
872 return n;
873 }
874 v = left.c.val / right.c.val;
875 Omod =>
876 if(right.c.val == big 0){
877 nerror(n, "mod by 0 in constant expression");
878 return n;
879 }
880 v = left.c.val % right.c.val;
881 Oexp =>
882 if(left.c.val == big 0 && right.c.val < big 0){
883 nerror(n, "0 to negative power in constant expression");
884 return n;
885 }
886 v = ipow(left.c.val, int right.c.val);
887 Oand =>
888 v = left.c.val & right.c.val;
889 Oor =>
890 v = left.c.val | right.c.val;
891 Oxor =>
892 v = left.c.val ^ right.c.val;
893 Olsh =>
894 v = left.c.val;
895 rv = int right.c.val;
896 if(rv < 0 || rv >= n.ty.size * 8){
897 nwarn(n, "shift amount "+string rv+" out of range");
898 rv = 0;
899 }
900 if(rv == 0)
901 break;
902 v <<= rv;
903 Orsh =>
904 v = left.c.val;
905 rv = int right.c.val;
906 nb = n.ty.size * 8;
907 if(rv < 0 || rv >= nb){
908 nwarn(n, "shift amount "+string rv+" out of range");
909 rv = 0;
910 }
911 if(rv == 0)
912 break;
913 v >>= rv;
914 Oneg =>
915 v = -left.c.val;
916 Ocomp =>
917 v = ~left.c.val;
918 Oeq =>
919 v = big(left.c.val == right.c.val);
920 Oneq =>
921 v = big(left.c.val != right.c.val);
922 Ogt =>
923 v = big(left.c.val > right.c.val);
924 Ogeq =>
925 v = big(left.c.val >= right.c.val);
926 Olt =>
927 v = big(left.c.val < right.c.val);
928 Oleq =>
929 v = big(left.c.val <= right.c.val);
930 Oandand =>
931 v = big(int left.c.val && int right.c.val);
932 Ooror =>
933 v = big(int left.c.val || int right.c.val);
934 Onot =>
935 v = big(left.c.val == big 0);
936 * =>
937 return n;
938 }
939 if(n.ty == tint)
940 v = big int v;
941 else if(n.ty == tbyte)
942 v = big byte v;
943 n.left = nil;
944 n.right = nil;
945 n.decl = nil;
946 n.op = Oconst;
947 n.c = ref Const(v, 0.);
948 return n;
949}
950
951#
952# left and right are const reals
953#
954foldr(n: ref Node): ref Node
955{
956 rv := 0.;
957 v := big 0;
958
959 left := n.left;
960 right := n.right;
961 case n.op{
962 Ocast =>
963 return n;
964 Oadd =>
965 rv = left.c.rval + right.c.rval;
966 Osub =>
967 rv = left.c.rval - right.c.rval;
968 Omul =>
969 rv = left.c.rval * right.c.rval;
970 Odiv =>
971 rv = left.c.rval / right.c.rval;
972 Oexp =>
973 rv = rpow(left.c.rval, int right.c.val);
974 Oneg =>
975 rv = -left.c.rval;
976 Oinv =>
977 if(left.c.rval == 0.0){
978 error(n.src.start, "divide by 0 in fixed point type");
979 return n;
980 }
981 rv = 1.0/left.c.rval;
982 Oeq =>
983 v = big(left.c.rval == right.c.rval);
984 Oneq =>
985 v = big(left.c.rval != right.c.rval);
986 Ogt =>
987 v = big(left.c.rval > right.c.rval);
988 Ogeq =>
989 v = big(left.c.rval >= right.c.rval);
990 Olt =>
991 v = big(left.c.rval < right.c.rval);
992 Oleq =>
993 v = big(left.c.rval <= right.c.rval);
994 * =>
995 return n;
996 }
997 n.left = nil;
998 n.right = nil;
999 n.op = Oconst;
1000
1001 if(isnan(rv))
1002 rv = canonnan;
1003
1004 n.c = ref Const(v, rv);
1005 return n;
1006}
1007
1008varinit(d: ref Decl, e: ref Node): ref Node
1009{
1010 n := mkdeclname(e.src, d);
1011 if(d.next == nil)
1012 return mkbin(Oas, n, e);
1013 return mkbin(Oas, n, varinit(d.next, e));
1014}
1015
1016#
1017# given: an Oseq list with left == next or the last child
1018# make a list with the right == next
1019# ie: Oseq(Oseq(a, b),c) ==> Oseq(a, Oseq(b, Oseq(c, nil))))
1020#
1021rotater(e: ref Node): ref Node
1022{
1023 if(e == nil)
1024 return e;
1025 if(e.op != Oseq)
1026 return mkunary(Oseq, e);
1027 e.right = mkunary(Oseq, e.right);
1028 while(e.left.op == Oseq){
1029 left := e.left;
1030 e.left = left.right;
1031 left.right = e;
1032 e = left;
1033 }
1034 return e;
1035}
1036
1037#
1038# reverse the case labels list
1039#
1040caselist(s, nr: ref Node): ref Node
1041{
1042 r := s.right;
1043 s.right = nr;
1044 if(r == nil)
1045 return s;
1046 return caselist(r, s);
1047}
1048
1049#
1050# e is a seq of expressions; make into cons's to build a list
1051#
1052etolist(e: ref Node): ref Node
1053{
1054 if(e == nil)
1055 return nil;
1056 n := mknil(e.src);
1057 n.src.start = n.src.stop;
1058 if(e.op != Oseq)
1059 return mkbin(Ocons, e, n);
1060 e.right = mkbin(Ocons, e.right, n);
1061 while(e.left.op == Oseq){
1062 e.op = Ocons;
1063 left := e.left;
1064 e.left = left.right;
1065 left.right = e;
1066 e = left;
1067 }
1068 e.op = Ocons;
1069 return e;
1070}
1071
1072dupn(resrc: int, src: Src, n: ref Node): ref Node
1073{
1074 nn := ref *n;
1075 if(resrc)
1076 nn.src = src;
1077 if(nn.left != nil)
1078 nn.left = dupn(resrc, src, nn.left);
1079 if(nn.right != nil)
1080 nn.right = dupn(resrc, src, nn.right);
1081 return nn;
1082}
1083
1084mkn(op: int, left, right: ref Node): ref Node
1085{
1086 n := ref Node;
1087 n.op = op;
1088 n.flags = byte 0;
1089 n.left = left;
1090 n.right = right;
1091 return n;
1092}
1093
1094mkunary(op: int, left: ref Node): ref Node
1095{
1096 n := ref Node;
1097 n.src = left.src;
1098 n.op = op;
1099 n.flags = byte 0;
1100 n.left = left;
1101 return n;
1102}
1103
1104mkbin(op: int, left, right: ref Node): ref Node
1105{
1106 n := ref Node;
1107 n.src.start = left.src.start;
1108 n.src.stop = right.src.stop;
1109 n.op = op;
1110 n.flags = byte 0;
1111 n.left = left;
1112 n.right = right;
1113 return n;
1114}
1115
1116mkdeclname(src: Src, d: ref Decl): ref Node
1117{
1118 n := ref Node;
1119 n.src = src;
1120 n.op = Oname;
1121 n.flags = byte 0;
1122 n.decl = d;
1123 n.ty = d.ty;
1124 d.refs++;
1125 return n;
1126}
1127
1128mknil(src: Src): ref Node
1129{
1130 return mkdeclname(src, nildecl);
1131}
1132
1133mkname(src: Src, s: ref Sym): ref Node
1134{
1135 n := ref Node;
1136 n.src = src;
1137 n.op = Oname;
1138 n.flags = byte 0;
1139 if(s.unbound == nil){
1140 s.unbound = mkdecl(src, Dunbound, nil);
1141 s.unbound.sym = s;
1142 }
1143 n.decl = s.unbound;
1144 return n;
1145}
1146
1147mkconst(src: Src, v: big): ref Node
1148{
1149 n := ref Node;
1150 n.src = src;
1151 n.op = Oconst;
1152 n.flags = byte 0;
1153 n.ty = tint;
1154 n.c = ref Const(v, 0.);
1155 return n;
1156}
1157
1158mkrconst(src: Src, v: real): ref Node
1159{
1160 n := ref Node;
1161 n.src = src;
1162 n.op = Oconst;
1163 n.flags = byte 0;
1164 n.ty = treal;
1165 n.c = ref Const(big 0, v);
1166 return n;
1167}
1168
1169mksconst(src: Src, s: ref Sym): ref Node
1170{
1171 n := ref Node;
1172 n.src = src;
1173 n.op = Oconst;
1174 n.flags = byte 0;
1175 n.ty = tstring;
1176 n.decl = mkdecl(src, Dconst, tstring);
1177 n.decl.sym = s;
1178 return n;
1179}
1180
1181opconv(op: int): string
1182{
1183 if(op < 0 || op > Oend)
1184 return "op "+string op;
1185 return opname[op];
1186}
1187
1188etconv(n: ref Node): string
1189{
1190 s := expconv(n);
1191 if(n.ty == tany || n.ty == tnone || n.ty == terror)
1192 return s;
1193 s += " of type ";
1194 s += typeconv(n.ty);
1195 return s;
1196}
1197
1198expconv(n: ref Node): string
1199{
1200 return "'" + subexpconv(n) + "'";
1201}
1202
1203subexpconv(n: ref Node): string
1204{
1205 if(n == nil)
1206 return "";
1207 s := "";
1208 if(int n.flags & PARENS)
1209 s[len s] = '(';
1210 case n.op{
1211 Obreak or
1212 Ocont =>
1213 s += opname[n.op];
1214 if(n.decl != nil)
1215 s += " "+n.decl.sym.name;
1216 Oexit or
1217 Owild =>
1218 s += opname[n.op];
1219 Onothing =>
1220 ;
1221 Oadr or
1222 Oused =>
1223 s += subexpconv(n.left);
1224 Oseq =>
1225 s += eprintlist(n, ", ");
1226 Oname =>
1227 if(n.decl == nil)
1228 s += "<nil>";
1229 else
1230 s += n.decl.sym.name;
1231 Oconst =>
1232 if(n.ty.kind == Tstring){
1233 s += stringpr(n.decl.sym);
1234 break;
1235 }
1236 if(n.decl != nil && n.decl.sym != nil){
1237 s += n.decl.sym.name;
1238 break;
1239 }
1240 case n.ty.kind{
1241 Tbig or
1242 Tint or
1243 Tbyte =>
1244 s += string n.c.val;
1245 Treal =>
1246 s += string n.c.rval;
1247 Tfix =>
1248 s += string n.c.val + "(" + string n.ty.val.c.rval + ")";
1249 * =>
1250 s += opname[n.op];
1251 }
1252 Ocast =>
1253 s += typeconv(n.ty);
1254 s[len s] = ' ';
1255 s += subexpconv(n.left);
1256 Otuple =>
1257 if(n.ty != nil && n.ty.kind == Tadt)
1258 s += n.ty.decl.sym.name;
1259 s[len s] = '(';
1260 s += eprintlist(n.left, ", ");
1261 s[len s] = ')';
1262 Ochan =>
1263 if(n.left != nil){
1264 s += "chan [";
1265 s += subexpconv(n.left);
1266 s += "] of ";
1267 s += typeconv(n.ty.tof);
1268 }
1269 else
1270 s += "chan of "+typeconv(n.ty.tof);
1271 Oarray =>
1272 s += "array [";
1273 if(n.left != nil)
1274 s += subexpconv(n.left);
1275 s += "] of ";
1276 if(n.right != nil){
1277 s += "{";
1278 s += eprintlist(n.right, ", ");
1279 s += "}";
1280 }else{
1281 s += typeconv(n.ty.tof);
1282 }
1283 Oelem or
1284 Olabel =>
1285 if(n.left != nil){
1286 s += eprintlist(n.left, " or ");
1287 s += " =>";
1288 }
1289 s += subexpconv(n.right);
1290 Orange =>
1291 s += subexpconv(n.left);
1292 s += " to ";
1293 s += subexpconv(n.right);
1294 Ospawn =>
1295 s += "spawn ";
1296 s += subexpconv(n.left);
1297 Oraise =>
1298 s += "raise ";
1299 s += subexpconv(n.left);
1300 Ocall =>
1301 s += subexpconv(n.left);
1302 s += "(";
1303 s += eprintlist(n.right, ", ");
1304 s += ")";
1305 Oinc or
1306 Odec =>
1307 s += subexpconv(n.left);
1308 s += opname[n.op];
1309 Oindex or
1310 Oindx or
1311 Oinds =>
1312 s += subexpconv(n.left);
1313 s += "[";
1314 s += subexpconv(n.right);
1315 s += "]";
1316 Oslice =>
1317 s += subexpconv(n.left);
1318 s += "[";
1319 s += subexpconv(n.right.left);
1320 s += ":";
1321 s += subexpconv(n.right.right);
1322 s += "]";
1323 Oload =>
1324 s += "load ";
1325 s += typeconv(n.ty);
1326 s += " ";
1327 s += subexpconv(n.left);
1328 Oref or
1329 Olen or
1330 Ohd or
1331 Otl or
1332 Otagof =>
1333 s += opname[n.op];
1334 s[len s] = ' ';
1335 s += subexpconv(n.left);
1336 * =>
1337 if(n.right == nil){
1338 s += opname[n.op];
1339 s += subexpconv(n.left);
1340 }else{
1341 s += subexpconv(n.left);
1342 s += opname[n.op];
1343 s += subexpconv(n.right);
1344 }
1345 }
1346 if(int n.flags & PARENS)
1347 s[len s] = ')';
1348 return s;
1349}
1350
1351eprintlist(elist: ref Node, sep: string): string
1352{
1353 if(elist == nil)
1354 return "";
1355 s := "";
1356 for(; elist.right != nil; elist = elist.right){
1357 if(elist.op == Onothing)
1358 continue;
1359 if(elist.left.op == Ofnptr)
1360 return s;
1361 s += subexpconv(elist.left);
1362 if(elist.right.left.op != Ofnptr)
1363 s += sep;
1364 }
1365 s += subexpconv(elist.left);
1366 return s;
1367}
1368
1369nodeconv(n: ref Node): string
1370{
1371 return nprint(n, 0);
1372}
1373
1374nprint(n: ref Node, indent: int): string
1375{
1376 if(n == nil)
1377 return "";
1378 s := "\n";
1379 for(i := 0; i < indent; i++)
1380 s[len s] = ' ';
1381 case n.op{
1382 Oname =>
1383 if(n.decl == nil)
1384 s += "<nil>";
1385 else
1386 s += n.decl.sym.name;
1387 Oconst =>
1388 if(n.decl != nil && n.decl.sym != nil)
1389 s += n.decl.sym.name;
1390 else
1391 s += opconv(n.op);
1392 if(n.ty == tint || n.ty == tbyte || n.ty == tbig)
1393 s += " (" + string n.c.val + ")";
1394 * =>
1395 s += opconv(n.op);
1396 }
1397 s += " " + typeconv(n.ty) + " " + string n.addable + " " + string n.temps;
1398 indent += 2;
1399 s += nprint(n.left, indent);
1400 s += nprint(n.right, indent);
1401 return s;
1402}
limbo/compiler/opname.m+109−0
@@ -0,0 +1,109 @@
1opname := array[Oend+1] of
2{
3 "unknown",
4
5 Oadd => "+",
6 Oaddas => "+=",
7 Oadr => "adr",
8 Oadtdecl => "adtdecl",
9 Oalt => "alt",
10 Oand => "&",
11 Oandand => "&&",
12 Oandas => "&=",
13 Oarray => "array",
14 Oas => "=",
15 Obreak => "break",
16 Ocall => "call",
17 Ocase => "case",
18 Ocast => "cast",
19 Ochan => "chan",
20 Ocomma => ",",
21 Ocomp => "~",
22 Ocondecl => "condecl",
23 Ocons => "::",
24 Oconst => "const",
25 Ocont => "continue",
26 Odas => ":=",
27 Odec => "--",
28 Odiv => "/",
29 Odivas => "/=",
30 Odo => "do",
31 Odot => ".",
32 Oelem => "elem",
33 Oeq => "==",
34 Oexcept => "except",
35 Oexdecl => "exdecl",
36 Oexit => "exit",
37 Oexp => "**",
38 Oexpas => "**=",
39 Oexstmt => "exstat",
40 Ofielddecl => "fielddecl",
41 Ofnptr => "fnptr",
42 Ofor => "for",
43 Ofunc => "fn(){}",
44 Ogeq => ">=",
45 Ogt => ">",
46 Ohd => "hd",
47 Oif => "if",
48 Oimport => "import",
49 Oinc => "++",
50 Oind => "*",
51 Oindex => "index",
52 Oinds => "inds",
53 Oindx => "indx",
54 Oinv => "inv",
55 Ojmp => "jmp",
56 Olabel => "label",
57 Olen => "len",
58 Oleq => "<=",
59 Oload => "load",
60 Olsh => "<<",
61 Olshas => "<<=",
62 Olt => "<",
63 Omdot => "->",
64 Omod => "%",
65 Omodas => "%=",
66 Omoddecl => "moddecl",
67 Omul => "*",
68 Omulas => "*=",
69 Oname => "name",
70 Oneg => "-",
71 Oneq => "!=",
72 Onot => "!",
73 Onothing => "nothing",
74 Oor => "|",
75 Ooras => "|=",
76 Ooror => "||",
77 Opick => "pick",
78 Opickdecl => "pickdec",
79 Opredec => "--",
80 Opreinc => "++",
81 Oraise => "raise",
82 Orange => "range",
83 Orcv => "<-",
84 Oref => "ref",
85 Oret => "return",
86 Orsh => ">>",
87 Orshas => ">>=",
88 Oscope => "scope",
89 Oself => "self",
90 Oseq => "seq",
91 Oslice => "slice",
92 Osnd => "<-=",
93 Ospawn => "spawn",
94 Osub => "-",
95 Osubas => "-=",
96 Otagof => "tagof",
97 Otl => "tl",
98 Otuple => "tuple",
99 Otype => "type",
100 Otypedecl => "typedecl",
101 Oused => "used",
102 Ovardecl => "vardecl",
103 Ovardecli => "vardecli",
104 Owild => "*",
105 Oxor => "^",
106 Oxoras => "^=",
107
108 Oend => "unknown"
109};
limbo/compiler/optim.b+3−0
@@ -0,0 +1,3 @@
1optim(nil: ref Inst, nil: ref Decl)
2{
3}
limbo/compiler/sbl.b+397−0
@@ -0,0 +1,397 @@
1
2sbltname := array[Tend] of
3{
4 Tnone => byte 'n',
5 Tadt => byte 'a',
6 Tadtpick => byte 'a',
7 Tarray => byte 'A',
8 Tbig => byte 'B',
9 Tbyte => byte 'b',
10 Tchan => byte 'C',
11 Treal => byte 'f',
12 Tfn => byte 'F',
13 Tint => byte 'i',
14 Tlist => byte 'L',
15 Tmodule => byte 'm',
16 Tref => byte 'R',
17 Tstring => byte 's',
18 Ttuple => byte 't',
19 Texception => byte 't',
20 Tfix => byte 'i',
21 Tpoly => byte 'P',
22
23 Tainit => byte '?',
24 Talt => byte '?',
25 Tany => byte 'N',
26 Tarrow => byte '?',
27 Tcase => byte '?',
28 Tcasel => byte '?',
29 Tcasec => byte '?',
30 Tdot => byte '?',
31 Terror => byte '?',
32 Tgoto => byte '?',
33 Tid => byte '?',
34 Tiface => byte '?',
35 Texcept => byte '?',
36 Tinst => byte '?',
37};
38sbltadtpick: con byte 'p';
39
40sfiles: ref Sym;
41ftail: ref Sym;
42nsfiles: int;
43blockid: int;
44lastf: int;
45lastline: int;
46
47MAXSBLINT: con 12;
48MAXSBLSRC: con 6*(MAXSBLINT+1);
49
50sblmod(m: ref Decl)
51{
52 bsym.puts("limbo .sbl 2.1\n");
53 bsym.puts(m.sym.name);
54 bsym.putb(byte '\n');
55
56 blockid = 0;
57 nsfiles = 0;
58 sfiles = ftail = nil;
59 lastf = 0;
60 lastline = 0;
61}
62
63sblfile(name: string): int
64{
65 i := 0;
66 for(s := sfiles; s != nil; s = s.next){
67 if(s.name == name)
68 return i;
69 i++;
70 }
71 s = ref Sym;
72 s.name = name;
73 s.next = nil;
74 if(sfiles == nil)
75 sfiles = s;
76 else
77 ftail.next = s;
78 ftail = s;
79 nsfiles = i + 1;
80 return i;
81}
82
83filename(s: string): string
84{
85 (nil, file) := str->splitr(s, "/ \\");
86 return file;
87}
88
89sblfiles()
90{
91 for(i := 0; i < nfiles; i++)
92 files[i].sbl = sblfile(files[i].name);
93 bsym.puts(string nsfiles);
94 bsym.putb(byte '\n');
95 for(s := sfiles; s != nil; s = s.next){
96 bsym.puts(filename(s.name));
97 bsym.putb(byte '\n');
98 }
99}
100
101sblint(buf: array of byte, off, v: int): int
102{
103 if(v == 0){
104 buf[off++] = byte '0';
105 return off;
106 }
107 stop := off + MAXSBLINT;
108 if(v < 0){
109 buf[off++] = byte '-';
110 v = -v;
111 }
112 n := stop;
113 while(v > 0){
114 buf[n -= 1] = byte(v % 10 + '0');
115 v = v / 10;
116 }
117 while(n < stop)
118 buf[off++] = buf[n++];
119 return off;
120}
121
122sblsrcconvb(buf: array of byte, off: int, src: Src): int
123{
124 (startf, startl) := fline(src.start >> PosBits);
125 (stopf, stopl) := fline(src.stop >> PosBits);
126 if(lastf != startf.sbl){
127 off = sblint(buf, off, startf.sbl);
128 buf[off++] = byte ':';
129 }
130 if(lastline != startl){
131 off = sblint(buf, off, startl);
132 buf[off++] = byte '.';
133 }
134 off = sblint(buf, off, (src.start & PosMask));
135 buf[off++] = byte ',';
136 if(startf.sbl != stopf.sbl){
137 off = sblint(buf, off, stopf.sbl);
138 buf[off++] = byte ':';
139 }
140 if(startl != stopl){
141 off = sblint(buf, off, stopl);
142 buf[off++] = byte '.';
143 }
144 off = sblint(buf, off, (src.stop & PosMask));
145 buf[off++] = byte ' ';
146 lastf = stopf.sbl;
147 lastline = stopl;
148 return off;
149}
150
151sblsrcconv(src: Src): string
152{
153 s := "";
154 (startf, startl) := fline(src.start >> PosBits);
155 (stopf, stopl) := fline(src.stop >> PosBits);
156 if(lastf != startf.sbl){
157 s += string startf.sbl;
158 s[len s] = ':';
159 }
160 if(lastline != startl){
161 s += string startl;
162 s[len s] = '.';
163 }
164 s += string (src.start & PosMask);
165 s[len s] = ',';
166 if(startf.sbl != stopf.sbl){
167 s += string stopf.sbl;
168 s[len s] = ':';
169 }
170 if(startl != stopl){
171 s += string stopl;
172 s[len s] = '.';
173 }
174 s += string (src.stop & PosMask);
175 s[len s] = ' ';
176 lastf = stopf.sbl;
177 lastline = stopl;
178 return s;
179}
180
181isnilsrc(s: Src): int
182{
183 return s.start == 0 && s.stop == 0;
184}
185
186isnilstopsrc(s: Src): int
187{
188 return s.stop == 0;
189}
190
191sblinst(in: ref Inst, ninst: int)
192{
193 src: Src;
194
195 MAXSBL: con 8*1024;
196 buf := array[MAXSBL] of byte;
197 n := 0;
198 bsym.puts(string ninst);
199 bsym.putb(byte '\n');
200 sblblocks := array[nblocks] of {* => -1};
201 for(; in != nil; in = in.next){
202 if(in.op == INOOP)
203 continue;
204 if(in.src.start < 0)
205 fatal("no file specified for "+instconv(in));
206 if(n >= (MAXSBL - MAXSBLSRC - MAXSBLINT - 1)){
207 bsym.write(buf, n);
208 n = 0;
209 }
210 if(isnilsrc(in.src))
211 in.src = src;
212 else if(isnilstopsrc(in.src)){ # how does this happen ?
213 in.src.stop = in.src.start;
214 in.src.stop++;
215 }
216 n = sblsrcconvb(buf, n, in.src);
217 src = in.src;
218 b := sblblocks[in.block];
219 if(b < 0)
220 sblblocks[in.block] = b = blockid++;
221 n = sblint(buf, n, b);
222 buf[n++] = byte '\n';
223 }
224 if(n > 0)
225 bsym.write(buf, n);
226}
227
228sblty(tys: array of ref Decl, ntys: int)
229{
230 bsym.puts(string ntys);
231 bsym.putb(byte '\n');
232 for(i := 0; i < ntys; i++){
233 d := tys[i];
234 d.ty.sbl = i;
235 }
236 for(i = 0; i < ntys; i++){
237 d := tys[i];
238 sbltype(d.ty, 1);
239 }
240}
241
242sblfn(fns: array of ref Decl, nfns: int)
243{
244 bsym.puts(string nfns);
245 bsym.putb(byte '\n');
246 for(i := 0; i < nfns; i++){
247 f := fns[i];
248 if(ispoly(f))
249 rmfnptrs(f);
250 bsym.puts(string f.pc.pc);
251 bsym.putb(byte ':');
252 if(f.dot != nil && f.dot.ty.kind == Tadt){
253 bsym.puts(f.dot.sym.name);
254 bsym.putb(byte '.');
255 }
256 bsym.puts(f.sym.name);
257 bsym.putb(byte '\n');
258 sbldecl(f.ty.ids, Darg);
259 sbldecl(f.locals, Dlocal);
260 sbltype(f.ty.tof, 0);
261 }
262}
263
264sblvar(vars: ref Decl)
265{
266 sbldecl(vars, Dglobal);
267}
268
269isvis(id: ref Decl): int
270{
271 if(!tattr[id.ty.kind].vis
272 || id.sym == nil
273 || id.sym.name == ""
274 || id.sym.name[0] == '.')
275 return 0;
276 if(id.ty == tstring && id.init != nil && id.init.op == Oconst)
277 return 0;
278 if(id.src.start < 0 || id.src.stop < 0)
279 return 0;
280 return 1;
281}
282
283sbldecl(ids: ref Decl, store: int)
284{
285 n := 0;
286 for(id := ids; id != nil; id = id.next){
287 if(id.store != store || !isvis(id))
288 continue;
289 n++;
290 }
291 bsym.puts(string n);
292 bsym.putb(byte '\n');
293 for(id = ids; id != nil; id = id.next){
294 if(id.store != store || !isvis(id))
295 continue;
296 bsym.puts(string id.offset);
297 bsym.putb(byte ':');
298 bsym.puts(id.sym.name);
299 bsym.putb(byte ':');
300 bsym.puts(sblsrcconv(id.src));
301 sbltype(id.ty, 0);
302 bsym.putb(byte '\n');
303 }
304}
305
306sbltype(t: ref Type, force: int)
307{
308 if(t.kind == Tadtpick)
309 t = t.decl.dot.ty;
310
311 d := t.decl;
312 if(!force && d != nil && d.ty.sbl >= 0){
313 bsym.putb(byte '@');
314 bsym.puts(string d.ty.sbl);
315 bsym.putb(byte '\n');
316 return;
317 }
318
319 if(t.rec != byte 0)
320 fatal("recursive sbl type: "+typeconv(t));
321
322 t.rec = byte 1;
323 case t.kind{
324 * =>
325 fatal("bad type in sbltype: "+typeconv(t));
326 Tnone or
327 Tany or
328 Tint or
329 Tbig or
330 Tbyte or
331 Treal or
332 Tstring or
333 Tfix or
334 Tpoly =>
335 bsym.putb(sbltname[t.kind]);
336 Tfn =>
337 bsym.putb(sbltname[t.kind]);
338 sbldecl(t.ids, Darg);
339 sbltype(t.tof, 0);
340 Tarray or
341 Tlist or
342 Tchan or
343 Tref =>
344 bsym.putb(sbltname[t.kind]);
345 if(t.kind == Tref && t.tof.kind == Tfn){
346 tattr[Tany].vis = 1;
347 sbltype(tfnptr, 0);
348 tattr[Tany].vis = 0;
349 }
350 else
351 sbltype(t.tof, 0);
352 Ttuple or
353 Texception =>
354 bsym.putb(sbltname[t.kind]);
355 bsym.puts(string t.size);
356 bsym.putb(byte '.');
357 sbldecl(t.ids, Dfield);
358 Tadt =>
359 if(t.tags != nil)
360 bsym.putb(sbltadtpick);
361 else
362 bsym.putb(sbltname[t.kind]);
363 if(d.dot != nil && !isimpmod(d.dot.sym))
364 bsym.puts(d.dot.sym.name + "->");
365 bsym.puts(d.sym.name);
366 bsym.putb(byte ' ');
367 bsym.puts(sblsrcconv(d.src));
368 bsym.puts(string d.ty.size);
369 bsym.putb(byte '\n');
370 sbldecl(t.ids, Dfield);
371 if(t.tags != nil){
372 bsym.puts(string t.decl.tag);
373 bsym.putb(byte '\n');
374 lastt : ref Type = nil;
375 for(tg := t.tags; tg != nil; tg = tg.next){
376 bsym.puts(tg.sym.name);
377 bsym.putb(byte ':');
378 bsym.puts(sblsrcconv(tg.src));
379 if(lastt == tg.ty){
380 bsym.putb(byte '\n');
381 }else{
382 bsym.puts(string tg.ty.size);
383 bsym.putb(byte '\n');
384 sbldecl(tg.ty.ids, Dfield);
385 }
386 lastt = tg.ty;
387 }
388 }
389 Tmodule =>
390 bsym.putb(sbltname[t.kind]);
391 bsym.puts(d.sym.name);
392 bsym.putb(byte '\n');
393 bsym.puts(sblsrcconv(d.src));
394 sbldecl(t.ids, Dglobal);
395 }
396 t.rec = byte 0;
397}
limbo/compiler/stubs.b+575−0
@@ -0,0 +1,575 @@
1#
2# write out some stub C code for limbo modules
3#
4emit(globals: ref Decl)
5{
6 for(m := globals; m != nil; m = m.next){
7 if(m.store != Dtype || m.ty.kind != Tmodule)
8 continue;
9 m.ty = usetype(m.ty);
10 for(d := m.ty.ids; d != nil; d = d.next){
11 d.ty = usetype(d.ty);
12 if(d.store == Dglobal || d.store == Dfn)
13 modrefable(d.ty);
14 if(d.store == Dtype && d.ty.kind == Tadt){
15 for(id := d.ty.ids; id != nil; id = id.next){
16 id.ty = usetype(id.ty);
17 modrefable(d.ty);
18 }
19 }
20 }
21 }
22 if(emitstub){
23 adtstub(globals);
24 modstub(globals);
25 }
26 if(emittab != nil)
27 modtab(globals);
28 if(emitcode != nil)
29 modcode(globals);
30 if(emitsbl != nil)
31 modsbl(globals);
32}
33
34modsbl(globals: ref Decl)
35{
36 for(d := globals; d != nil; d = d.next)
37 if(d.store == Dtype && d.ty.kind == Tmodule && d.sym.name == emitsbl)
38 break;
39
40 if(d == nil)
41 return;
42 bsym = bufio->fopen(sys->fildes(1), Bufio->OWRITE);
43
44 sblmod(d);
45 sblfiles();
46 n := 0;
47 genstart();
48 for(id := d.ty.tof.ids; id != nil; id = id.next){
49 if(id.sym.name == ".mp")
50 continue;
51 pushblock();
52 id.pc = genrawop(id.src, INOP, nil, nil, nil);
53 id.pc.pc = n++;
54 popblock();
55 }
56 firstinst = firstinst.next;
57 sblinst(firstinst, n);
58# (adts, nadts) := findadts(globals);
59 sblty(adts, nadts);
60 fs := array[n] of ref Decl;
61 n = 0;
62 for(id = d.ty.tof.ids; id != nil; id = id.next){
63 if(id.sym.name == ".mp")
64 continue;
65 fs[n] = id;
66 n++;
67 }
68 sblfn(fs, n);
69 sblvar(nil);
70}
71
72lowercase(f: string): string
73{
74 for(i := 0; i < len f; i++)
75 if(f[i] >= 'A' && f[i] <= 'Z')
76 f[i] += 'a' - 'A';
77 return f;
78}
79
80modcode(globals: ref Decl)
81{
82 buf: string;
83
84 if(emitdyn){
85 buf = lowercase(emitcode);
86 print("#include \"%s.h\"\n", buf);
87 }
88 else{
89 print("#include <lib9.h>\n");
90 print("#include <isa.h>\n");
91 print("#include <interp.h>\n");
92 print("#include \"%smod.h\"\n", emitcode);
93 }
94 print("\n");
95
96 for(d := globals; d != nil; d = d.next)
97 if(d.store == Dtype && d.ty.kind == Tmodule && d.sym.name == emitcode)
98 break;
99
100 if(d == nil)
101 return;
102
103 #
104 # stub types
105 #
106 for(id := d.ty.ids; id != nil; id = id.next){
107 if(id.store == Dtype && id.ty.kind == Tadt){
108 id.ty = usetype(id.ty);
109 print("Type*\tT_%s;\n", id.sym.name);
110 }
111 }
112
113 #
114 # type maps
115 #
116 if(emitdyn){
117 for(id = d.ty.ids; id != nil; id = id.next)
118 if(id.store == Dtype && id.ty.kind == Tadt)
119 print("uchar %s_map[] = %s_%s_map;\n",
120 id.sym.name, emitcode, id.sym.name);
121 }
122
123 #
124 # heap allocation and garbage collection for a type
125 #
126 if(emitdyn){
127 for(id = d.ty.ids; id != nil; id = id.next)
128 if(id.store == Dtype && id.ty.kind == Tadt){
129 print("\n%s_%s*\n%salloc%s(void)\n{\n\tHeap *h;\n\n\th = heap(T_%s);\n\treturn H2D(%s_%s*, h);\n}\n", emitcode, id.sym.name, emitcode, id.sym.name, id.sym.name, emitcode, id.sym.name);
130 print("\nvoid\n%sfree%s(Heap *h, int swept)\n{\n\t%s_%s *d;\n\n\td = H2D(%s_%s*, h);\n\tfreeheap(h, swept);\n}\n", emitcode, id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name);
131 }
132 }
133
134 #
135 # initialization function
136 #
137 if(emitdyn)
138 print("\nvoid\n%sinit(void)\n{\n", emitcode);
139 else{
140 print("\nvoid\n%smodinit(void)\n{\n", emitcode);
141 print("\tbuiltinmod(\"$%s\", %smodtab, %smodlen);\n", emitcode, emitcode, emitcode);
142 }
143 for(id = d.ty.ids; id != nil; id = id.next)
144 if(id.store == Dtype && id.ty.kind == Tadt){
145 if(emitdyn)
146 print("\tT_%s = dtype(%sfree%s, %s_%s_size, %s_map, sizeof(%s_map));\n",
147 id.sym.name, emitcode, id.sym.name, emitcode, id.sym.name, id.sym.name, id.sym.name);
148 else
149 print("\tT_%s = dtype(freeheap, sizeof(%s), %smap, sizeof(%smap));\n",
150 id.sym.name, id.sym.name, id.sym.name, id.sym.name);
151 }
152 print("}\n");
153
154 #
155 # end function
156 #
157 if(emitdyn){
158 print("\nvoid\n%send(void)\n{\n", emitcode);
159 for(id = d.ty.ids; id != nil; id = id.next)
160 if(id.store == Dtype && id.ty.kind == Tadt)
161 print("\tfreetype(T_%s);\n", id.sym.name);
162 print("}\n");
163 }
164
165 #
166 # stub functions
167 #
168 for(id = d.ty.tof.ids; id != nil; id = id.next){
169 print("\nvoid\n%s_%s(void *fp)\n{\n\tF_%s_%s *f = fp;\n",
170 id.dot.sym.name, id.sym.name,
171 id.dot.sym.name, id.sym.name);
172 if(id.ty.tof != tnone && tattr[id.ty.tof.kind].isptr){
173 print("\tvoid *r;\n");
174 print("\n\tr = *f->ret;\n\t*f->ret = H;\n\tdestroy(r);\n");
175 }
176 print("}\n");
177 }
178
179 if(emitdyn)
180 print("\n#include \"%smod.h\"\n", buf);
181}
182
183modtab(globals: ref Decl)
184{
185 print("typedef struct{char *name; long sig; void (*fn)(void*); int size; int np; uchar map[16];} Runtab;\n");
186 for(d := globals; d != nil; d = d.next){
187 if(d.store == Dtype && d.ty.kind == Tmodule && d.sym.name == emittab){
188 n := 0;
189 print("Runtab %smodtab[]={\n", d.sym.name);
190 for(id := d.ty.tof.ids; id != nil; id = id.next){
191 n++;
192 print("\t\"");
193 if(id.dot != d)
194 print("%s.", id.dot.sym.name);
195 print("%s\",0x%ux,%s_%s,", id.sym.name, sign(id),
196 id.dot.sym.name, id.sym.name);
197 if(id.ty.varargs != byte 0)
198 print("0,0,{0},");
199 else{
200 md := mkdesc(idoffsets(id.ty.ids, MaxTemp, MaxAlign), id.ty.ids);
201 print("%d,%d,%s,", md.size, md.nmap, mapconv(md));
202 }
203 print("\n");
204 }
205 print("\t0\n};\n");
206 print("#define %smodlen %d\n", d.sym.name, n);
207 }
208 }
209}
210
211#
212# produce activation records for all the functions in modules
213#
214modstub(globals: ref Decl)
215{
216 for(d := globals; d != nil; d = d.next){
217 if(d.store != Dtype || d.ty.kind != Tmodule)
218 continue;
219 arg := 0;
220 for(id := d.ty.tof.ids; id != nil; id = id.next){
221 s := id.dot.sym.name + "_" + id.sym.name;
222 if(emitdyn && id.dot.dot != nil)
223 s = id.dot.dot.sym.name + "_" + s;
224 print("void %s(void*);\ntypedef struct F_%s F_%s;\nstruct F_%s\n{\n",
225 s, s, s, s);
226 print(" WORD regs[NREG-1];\n");
227 if(id.ty.tof != tnone)
228 print(" %s* ret;\n", ctypeconv(id.ty.tof));
229 else
230 print(" WORD noret;\n");
231 print(" uchar temps[%d];\n", MaxTemp-NREG*IBY2WD);
232 offset := MaxTemp;
233 for(m := id.ty.ids; m != nil; m = m.next){
234 p := "";
235 if(m.sym != nil)
236 p = m.sym.name;
237 else
238 p = "arg"+string arg;
239
240 #
241 # explicit pads for structure alignment
242 #
243 t := m.ty;
244 (offset, nil) = stubalign(offset, t.align, nil);
245 if(offset != m.offset)
246 yyerror("module stub must not contain data objects");
247 # fatal("modstub bad offset");
248 print(" %s %s;\n", ctypeconv(t), p);
249 arg++;
250 offset += t.size;
251#ZZZ need to align?
252 }
253 if(id.ty.varargs != byte 0)
254 print(" WORD vargs;\n");
255 print("};\n");
256 }
257 for(id = d.ty.ids; id != nil; id = id.next)
258 if(id.store == Dconst)
259 constub(id);
260 }
261}
262
263chanstub(in: string, id: ref Decl)
264{
265 print("typedef %s %s_%s;\n", ctypeconv(id.ty.tof), in, id.sym.name);
266 desc := mktdesc(id.ty.tof);
267 print("#define %s_%s_size %d\n", in, id.sym.name, desc.size);
268 print("#define %s_%s_map %s\n", in, id.sym.name, mapconv(desc));
269}
270
271#
272# produce c structs for all adts
273#
274adtstub(globals: ref Decl)
275{
276 t, tt: ref Type;
277 m, d, id: ref Decl;
278
279 for(m = globals; m != nil; m = m.next){
280 if(m.store != Dtype || m.ty.kind != Tmodule)
281 continue;
282 for(d = m.ty.ids; d != nil; d = d.next){
283 if(d.store != Dtype)
284 continue;
285 t = usetype(d.ty);
286 d.ty = t;
287 s := dotprint(d.ty.decl, '_');
288 case d.ty.kind{
289 Tadt =>
290 print("typedef struct %s %s;\n", s, s);
291 Tint or
292 Tbyte or
293 Treal or
294 Tbig or
295 Tfix =>
296 print("typedef %s %s;\n", ctypeconv(t), s);
297 }
298 }
299 }
300 for(m = globals; m != nil; m = m.next){
301 if(m.store != Dtype || m.ty.kind != Tmodule)
302 continue;
303 for(d = m.ty.ids; d != nil; d = d.next){
304 if(d.store != Dtype)
305 continue;
306 t = d.ty;
307 if(t.kind == Tadt || t.kind == Ttuple && t.decl.sym != anontupsym){
308 if(t.tags != nil){
309 pickadtstub(t);
310 continue;
311 }
312 s := dotprint(t.decl, '_');
313 print("struct %s\n{\n", s);
314
315 offset := 0;
316 for(id = t.ids; id != nil; id = id.next){
317 if(id.store == Dfield){
318 tt = id.ty;
319 (offset, nil) = stubalign(offset, tt.align, nil);
320 if(offset != id.offset)
321 fatal("adtstub bad offset");
322 print(" %s %s;\n", ctypeconv(tt), id.sym.name);
323 offset += tt.size;
324 }
325 }
326 if(t.ids == nil){
327 print(" char dummy[1];\n");
328 offset = 1;
329 }
330 (offset, nil)= stubalign(offset, t.align, nil);
331#ZZZ
332(offset, nil) = stubalign(offset, IBY2WD, nil);
333 if(offset != t.size && t.ids != nil)
334 fatal("adtstub: bad size");
335 print("};\n");
336
337 for(id = t.ids; id != nil; id = id.next)
338 if(id.store == Dconst)
339 constub(id);
340
341 for(id = t.ids; id != nil; id = id.next)
342 if(id.ty.kind == Tchan)
343 chanstub(s, id);
344
345 desc := mktdesc(t);
346 if(offset != desc.size && t.ids != nil)
347 fatal("adtstub: bad desc size");
348 print("#define %s_size %d\n", s, offset);
349 print("#define %s_map %s\n", s, mapconv(desc));
350#ZZZ
351if(0)
352 print("struct %s_check {int s[2*(sizeof(%s)==%s_size)-1];};\n", s, s, s);
353 }else if(t.kind == Tchan)
354 chanstub(m.sym.name, d);
355 }
356 }
357}
358
359#
360# emit an expicit pad field for aligning emitted c structs
361# according to limbo's definition
362#
363stubalign(offset: int, a: int, s: string): (int, string)
364{
365 x := offset & (a-1);
366 if(x == 0)
367 return (offset, s);
368 x = a - x;
369 if(s != nil)
370 s += sprint("uchar\t_pad%d[%d]; ", offset, x);
371 else
372 print("\tuchar\t_pad%d[%d];\n", offset, x);
373 offset += x;
374 if((offset & (a-1)) || x >= a)
375 fatal("compiler stub misalign");
376 return (offset, s);
377}
378
379constub(id: ref Decl)
380{
381 s := id.dot.sym.name + "_" + id.sym.name;
382 case id.ty.kind{
383 Tbyte =>
384 print("#define %s %d\n", s, int id.init.c.val & 16rff);
385 Tint or
386 Tfix =>
387 print("#define %s %d\n", s, int id.init.c.val);
388 Tbig =>
389 print("#define %s %bd\n", s, id.init.c.val);
390 Treal =>
391 print("#define %s %g\n", s, id.init.c.rval);
392 Tstring =>
393 print("#define %s \"%s\"\n", s, id.init.decl.sym.name);
394 }
395}
396
397mapconv(d: ref Desc): string
398{
399 s := "{";
400 for(i := 0; i < d.nmap; i++)
401 s += "0x" + hex(int d.map[i], 0) + ",";
402 if(i == 0)
403 s += "0";
404 s += "}";
405 return s;
406}
407
408dotprint(d: ref Decl, dot: int): string
409{
410 s : string;
411 if(d.dot != nil){
412 s = dotprint(d.dot, dot);
413 s[len s] = dot;
414 }
415 if(d.sym == nil)
416 return s;
417 return s + d.sym.name;
418}
419
420ckindname := array[Tend] of
421{
422 Tnone => "void",
423 Tadt => "struct",
424 Tadtpick => "?adtpick?",
425 Tarray => "Array*",
426 Tbig => "LONG",
427 Tbyte => "BYTE",
428 Tchan => "Channel*",
429 Treal => "REAL",
430 Tfn => "?fn?",
431 Tint => "WORD",
432 Tlist => "List*",
433 Tmodule => "Modlink*",
434 Tref => "?ref?",
435 Tstring => "String*",
436 Ttuple => "?tuple?",
437 Texception => "?exception",
438 Tfix => "WORD",
439 Tpoly => "void*",
440
441 Tainit => "?ainit?",
442 Talt => "?alt?",
443 Tany => "void*",
444 Tarrow => "?arrow?",
445 Tcase => "?case?",
446 Tcasel => "?casel?",
447 Tcasec => "?casec?",
448 Tdot => "?dot?",
449 Terror => "?error?",
450 Tgoto => "?goto?",
451 Tid => "?id?",
452 Tiface => "?iface?",
453 Texcept => "?except?",
454 Tinst => "?inst?",
455};
456
457ctypeconv(t: ref Type): string
458{
459 if(t == nil)
460 return "void";
461 s := "";
462 case t.kind{
463 Terror =>
464 return "type error";
465 Tref =>
466 s = ctypeconv(t.tof);
467 s += "*";
468 Tarray or
469 Tlist or
470 Tint or
471 Tbig or
472 Tstring or
473 Treal or
474 Tbyte or
475 Tnone or
476 Tany or
477 Tchan or
478 Tmodule or
479 Tfix or
480 Tpoly =>
481 return ckindname[t.kind];
482 Tadtpick =>
483 return ctypeconv(t.decl.dot.ty);
484 Tadt or
485 Ttuple =>
486 if(t.decl.sym != anontupsym)
487 return dotprint(t.decl, '_');
488 s += "struct{ ";
489 offset := 0;
490 for(id := t.ids; id != nil; id = id.next){
491 tt := id.ty;
492 (offset, s) = stubalign(offset, tt.align, s);
493 if(offset != id.offset)
494 fatal("ctypeconv tuple bad offset");
495 s += ctypeconv(tt);
496 s += " ";
497 s += id.sym.name;
498 s += "; ";
499 offset += tt.size;
500 }
501 (offset, s) = stubalign(offset, t.align, s);
502 if(offset != t.size)
503 fatal(sprint("ctypeconv tuple bad t=%s size=%d offset=%d", typeconv(t), t.size, offset));
504 s += "}";
505 * =>
506 fatal("no C equivalent for type " + string t.kind);
507 }
508 return s;
509}
510
511pickadtstub(t: ref Type)
512{
513 tt: ref Type;
514 desc: ref Desc;
515 id, tg: ref Decl;
516 ok: byte;
517 offset, tgoffset: int;
518
519 buf := dotprint(t.decl, '_');
520 offset = 0;
521 for(tg = t.tags; tg != nil; tg = tg.next)
522 print("#define %s_%s %d\n", buf, tg.sym.name, offset++);
523 print("struct %s\n{\n", buf);
524 print(" int pick;\n");
525 offset = IBY2WD;
526 for(id = t.ids; id != nil; id = id.next){
527 if(id.store == Dfield){
528 tt = id.ty;
529 (offset, nil) = stubalign(offset, tt.align, nil);
530 if(offset != id.offset)
531 fatal("pickadtstub bad offset");
532 print(" %s %s;\n", ctypeconv(tt), id.sym.name);
533 offset += tt.size;
534 }
535 }
536 print(" union{\n");
537 for(tg = t.tags; tg != nil; tg = tg.next){
538 tgoffset = offset;
539 print(" struct{\n");
540 for(id = tg.ty.ids; id != nil; id = id.next){
541 if(id.store == Dfield){
542 tt = id.ty;
543 (tgoffset, nil) = stubalign(tgoffset, tt.align, nil);
544 if(tgoffset != id.offset)
545 fatal("pickadtstub bad offset");
546 print(" %s %s;\n", ctypeconv(tt), id.sym.name);
547 tgoffset += tt.size;
548 }
549 }
550 if(tg.ty.ids == nil)
551 print(" char dummy[1];\n");
552 print(" } %s;\n", tg.sym.name);
553 }
554 print(" } u;\n");
555 print("};\n");
556
557 for(id = t.ids; id != nil; id = id.next)
558 if(id.store == Dconst)
559 constub(id);
560
561 for(id = t.ids; id != nil; id = id.next)
562 if(id.ty.kind == Tchan)
563 chanstub(buf, id);
564
565 for(tg = t.tags; tg != nil; tg = tg.next){
566 ok = tg.ty.tof.ok;
567 tg.ty.tof.ok = OKverify;
568 sizetype(tg.ty.tof);
569 tg.ty.tof.ok = OKmask;
570 desc = mktdesc(tg.ty.tof);
571 tg.ty.tof.ok = ok;
572 print("#define %s_%s_size %d\n", buf, tg.sym.name, tg.ty.size);
573 print("#define %s_%s_map %s\n", buf, tg.sym.name, mapconv(desc));
574 }
575}
limbo/compiler/typecheck.b+3223−0
@@ -0,0 +1,3223 @@
1fndecls: ref Decl;
2labstack: array of ref Node;
3maxlabdep: int;
4inexcept: ref Node;
5nexc: int;
6fndec: ref Decl;
7
8increfs(id: ref Decl)
9{
10 for( ; id != nil; id = id.link)
11 id.refs++;
12}
13
14fninline(d: ref Decl): int
15{
16 left, right: ref Node;
17
18 n := d.init;
19 if(dontinline || d.inline == byte -1 || d.locals != nil || ispoly(d) || n.ty.tof.kind == Tnone || nodes(n) >= 100)
20 return 0;
21 n = n.right;
22 if(n.op == Oseq && n.right == nil)
23 n = n.left;
24 #
25 # inline
26 # (a) return e;
27 # (b) if(c) return e1; else return e2;
28 # (c) if(c) return e1; return e2;
29 #
30 case(n.op){
31 Oret =>
32 break;
33 Oif =>
34 right = n.right;
35 if(right.right == nil || right.left.op != Oret || right.right.op != Oret || !tequal(right.left.left.ty, right.right.left.ty))
36 return 0;
37 break;
38 Oseq =>
39 left = n.left;
40 right = n.right;
41 if(left.op != Oif || left.right.right != nil || left.right.left.op != Oret || right.op != Oseq || right.right != nil || right.left.op != Oret || !tequal(left.right.left.left.ty, right.left.left.ty))
42 return 0;
43 break;
44 * =>
45 return 0;
46 }
47 if(occurs(d, n) || hasasgns(n))
48 return 0;
49 if(n.op == Oseq){
50 left.right.right = right.left;
51 n = left;
52 right = n.right;
53 d.init.right.right = nil;
54 }
55 if(n.op == Oif){
56 n.ty = right.ty = right.left.left.ty;
57 right.left = right.left.left;
58 right.right = right.right.left;
59 d.init.right.left = mkunary(Oret, n);
60 }
61 return 1;
62}
63
64rewind(n: ref Node)
65{
66 r, nn: ref Node;
67
68 r = n;
69 nn = n.left;
70 for(n = n.right; n != nil; n = n.right){
71 if(n.right == nil){
72 r.left = nn;
73 r.right = n.left;
74 }
75 else
76 nn = mkbin(Oindex, nn, n.left);
77 }
78}
79
80ckmod(n: ref Node, id: ref Decl)
81{
82 t: ref Type;
83 d, idc: ref Decl;
84 mod: ref Node;
85
86 if(id == nil)
87 fatal("can't find function: " + nodeconv(n));
88 idc = nil;
89 mod = nil;
90 if(n.op == Oname){
91 idc = id;
92 mod = id.eimport;
93 }
94 else if(n.op == Omdot)
95 mod = n.left;
96 else if(n.op == Odot){
97 idc = id.dot;
98 t = n.left.ty;
99 if(t.kind == Tref)
100 t = t.tof;
101 if(t.kind == Tadtpick)
102 t = t.decl.dot.ty;
103 d = t.decl;
104 while(d != nil && d.link != nil)
105 d = d.link;
106 if(d != nil && d.timport != nil)
107 mod = d.timport.eimport;
108 n.right.left = mod;
109 }
110 if(mod != nil && mod.ty.kind != Tmodule){
111 nerror(n, "cannot use " + expconv(n) + " as a function reference");
112 return;
113 }
114 if(mod != nil){
115 if(valistype(mod)){
116 nerror(n, "cannot use " + expconv(n) + " as a function reference because " + expconv(mod) + " is a module interface");
117 return;
118 }
119 }else if(idc != nil && idc.dot != nil && !isimpmod(idc.dot.sym)){
120 nerror(n, "cannot use " + expconv(n) + " without importing " + idc.sym.name + " from a variable");
121 return;
122 }
123 if(mod != nil)
124 modrefable(n.ty);
125}
126
127addref(n: ref Node)
128{
129 nn: ref Node;
130
131 nn = mkn(0, nil, nil);
132 *nn = *n;
133 n.op = Oref;
134 n.left = nn;
135 n.right = nil;
136 n.decl = nil;
137 n.ty = usetype(mktype(n.src.start, n.src.stop, Tref, nn.ty, nil));
138}
139
140fnref(n: ref Node, id: ref Decl)
141{
142 id.inline = byte -1;
143 ckmod(n, id);
144 addref(n);
145 while(id.link != nil)
146 id = id.link;
147 if(ispoly(id) && encpolys(id) != nil)
148 nerror(n, "cannot have a polymorphic adt function reference " + id.sym.name);
149}
150
151typecheck(checkimp: int): ref Decl
152{
153 entry, d, m: ref Decl;
154
155 if(errors)
156 return nil;
157
158 #
159 # generate the set of all functions
160 # compile one function at a time
161 #
162 gdecl(tree);
163 gbind(tree);
164 fns = array[nfns] of ref Decl;
165 i := gcheck(tree, fns, 0);
166 if(i != nfns)
167 fatal("wrong number of functions found in gcheck");
168
169 maxlabdep = 0;
170 for(i = 0; i < nfns; i++){
171 d = fns[i];
172 if(d != nil)
173 fndec = d;
174 if(d != nil)
175 fncheck(d);
176 fndec = nil;
177 }
178
179 if(errors)
180 return nil;
181
182 entry = nil;
183 if(checkimp){
184 im: ref Decl;
185 dm: ref Dlist;
186
187 if(impmods == nil){
188 yyerror("no implementation module");
189 return nil;
190 }
191 for(im = impmods; im != nil; im = im.next){
192 for(dm = impdecls; dm != nil; dm = dm.next)
193 if(dm.d.sym == im.sym)
194 break;
195 if(dm == nil || dm.d.ty == nil){
196 yyerror("no definition for implementation module "+im.sym.name);
197 return nil;
198 }
199 }
200
201 #
202 # can't check the module spec until all types and imports are determined,
203 # which happens in scheck
204 #
205 for(dm = impdecls; dm != nil; dm = dm.next){
206 im = dm.d;
207 im.refs++;
208 im.ty = usetype(im.ty);
209 if(im.store != Dtype || im.ty.kind != Tmodule){
210 error(im.src.start, "cannot implement "+declconv(im));
211 return nil;
212 }
213 }
214
215 # now check any multiple implementations
216 impdecl = modimp(impdecls, impmods);
217
218 s := enter("init", 0);
219 for(dm = impdecls; dm != nil; dm = dm.next){
220 im = dm.d;
221 for(m = im.ty.ids; m != nil; m = m.next){
222 m.ty = usetype(m.ty);
223 m.refs++;
224
225 if(m.sym == s && m.ty.kind == Tfn && entry == nil)
226 entry = m;
227
228 if(m.store == Dglobal || m.store == Dfn)
229 modrefable(m.ty);
230
231 if(m.store == Dtype && m.ty.kind == Tadt){
232 for(d = m.ty.ids; d != nil; d = d.next){
233 d.ty = usetype(d.ty);
234 modrefable(d.ty);
235 d.refs++;
236 }
237 }
238 }
239 checkrefs(im.ty.ids);
240 }
241 }
242 if(errors)
243 return nil;
244 gsort(tree);
245 tree = nil;
246 return entry;
247}
248#
249# introduce all global declarations
250# also adds all fields to adts and modules
251# note the complications due to nested Odas expressions
252#
253gdecl(n: ref Node)
254{
255 for(;;){
256 if(n == nil)
257 return;
258 if(n.op != Oseq)
259 break;
260 gdecl(n.left);
261 n = n.right;
262 }
263 case n.op{
264 Oimport =>
265 importdecled(n);
266 gdasdecl(n.right);
267 Oadtdecl =>
268 adtdecled(n);
269 Ocondecl =>
270 condecled(n);
271 gdasdecl(n.right);
272 Oexdecl =>
273 exdecled(n);
274 Omoddecl =>
275 moddecled(n);
276 Otypedecl =>
277 typedecled(n);
278 Ovardecl =>
279 vardecled(n);
280 Ovardecli =>
281 vardecled(n.left);
282 gdasdecl(n.right);
283 Ofunc =>
284 fndecled(n);
285 Oas or
286 Odas or
287 Onothing =>
288 gdasdecl(n);
289 * =>
290 fatal("can't deal with "+opconv(n.op)+" in gdecl");
291 }
292}
293
294#
295# bind all global type ids,
296# including those nested inside modules
297# this needs to be done, since we may use such
298# a type later in a nested scope, so if we bound
299# the type ids then, the type could get bound
300# to a nested declaration
301#
302gbind(n: ref Node)
303{
304 ids: ref Decl;
305
306 for(;;){
307 if(n == nil)
308 return;
309 if(n.op != Oseq)
310 break;
311 gbind(n.left);
312 n = n.right;
313 }
314 case n.op{
315 Oas or
316 Ocondecl or
317 Odas or
318 Oexdecl or
319 Ofunc or
320 Oimport or
321 Onothing or
322 Ovardecl or
323 Ovardecli =>
324 break;
325 Ofielddecl =>
326 bindtypes(n.decl.ty);
327 Otypedecl =>
328 bindtypes(n.decl.ty);
329 if(n.left != nil)
330 gbind(n.left);
331 Opickdecl =>
332 gbind(n.left);
333 d := n.right.left.decl;
334 bindtypes(d.ty);
335 repushids(d.ty.ids);
336 gbind(n.right.right);
337 # get new ids for undefined types; propagate outwards
338 ids = popids(d.ty.ids);
339 if(ids != nil)
340 installids(Dundef, ids);
341 Oadtdecl or
342 Omoddecl =>
343 bindtypes(n.ty);
344 if(n.ty.polys != nil)
345 repushids(n.ty.polys);
346 repushids(n.ty.ids);
347 gbind(n.left);
348 # get new ids for undefined types; propagate outwards
349 ids = popids(n.ty.ids);
350 if(ids != nil)
351 installids(Dundef, ids);
352 if(n.ty.polys != nil)
353 popids(n.ty.polys);
354 * =>
355 fatal("can't deal with "+opconv(n.op)+" in gbind");
356 }
357}
358
359#
360# check all of the global declarations
361# bind all type ids referred to within types at the global level
362# record decls for defined functions
363#
364gcheck(n: ref Node, fns: array of ref Decl, nfns: int): int
365{
366 ok, allok: int;
367
368 for(;;){
369 if(n == nil)
370 return nfns;
371 if(n.op != Oseq)
372 break;
373 nfns = gcheck(n.left, fns, nfns);
374 n = n.right;
375 }
376
377 case n.op{
378 Ofielddecl =>
379 if(n.decl.ty.eraises != nil)
380 raisescheck(n.decl.ty);
381 Onothing or
382 Opickdecl =>
383 break;
384 Otypedecl =>
385 tcycle(n.ty);
386 Oadtdecl or
387 Omoddecl =>
388 if(n.ty.polys != nil)
389 repushids(n.ty.polys);
390 repushids(n.ty.ids);
391 if(gcheck(n.left, nil, 0))
392 fatal("gcheck fn decls nested in modules or adts");
393 if(popids(n.ty.ids) != nil)
394 fatal("gcheck installs new ids in a module or adt");
395 if(n.ty.polys != nil)
396 popids(n.ty.polys);
397 Ovardecl =>
398 varcheck(n, 1);
399 Ocondecl =>
400 concheck(n, 1);
401 Oexdecl =>
402 excheck(n, 1);
403 Oimport =>
404 importcheck(n, 1);
405 Ovardecli =>
406 varcheck(n.left, 1);
407 (ok, allok) = echeck(n.right, 0, 1, nil);
408 if(ok){
409 if(allok)
410 n.right = fold(n.right);
411 globalas(n.right.left, n.right.right, allok);
412 }
413 Oas or
414 Odas =>
415 (ok, allok) = echeck(n, 0, 1, nil);
416 if(ok){
417 if(allok)
418 n = fold(n);
419 globalas(n.left, n.right, allok);
420 }
421 Ofunc =>
422 (ok, allok) = echeck(n.left, 0, 1, n);
423 if(ok && n.ty.eraises != nil)
424 raisescheck(n.ty);
425 d : ref Decl = nil;
426 if(ok)
427 d = fnchk(n);
428 fns[nfns++] = d;
429 * =>
430 fatal("can't deal with "+opconv(n.op)+" in gcheck");
431 }
432 return nfns;
433}
434
435#
436# check for unused expression results
437# make sure the any calculated expression has
438# a destination
439#
440checkused(n: ref Node): ref Node
441{
442 #
443 # only nil; and nil = nil; should have type tany
444 #
445 if(n.ty == tany){
446 if(n.op == Oname)
447 return n;
448 if(n.op == Oas)
449 return checkused(n.right);
450 fatal("line "+lineconv(n.src.start)+" checkused "+nodeconv(n));
451 }
452
453 if(n.op == Ocall && n.left.ty.kind == Tfn && n.left.ty.tof != tnone){
454 n = mkunary(Oused, n);
455 n.ty = n.left.ty;
456 return n;
457 }
458 if(n.op == Ocall && isfnrefty(n.left.ty)){
459 if(n.left.ty.tof.tof != tnone){
460 n = mkunary(Oused, n);
461 n.ty = n.left.ty;
462 }
463 return n;
464 }
465 if(isused[n.op] && (n.op != Ocall || n.left.ty.kind == Tfn))
466 return n;
467 t := n.ty;
468 if(t.kind == Tfn)
469 nerror(n, "function "+expconv(n)+" not called");
470 else if(t.kind == Tadt && t.tags != nil || t.kind == Tadtpick)
471 nerror(n, "expressions cannot have type "+typeconv(t));
472 else if(n.op == Otuple){
473 for(nn := n.left; nn != nil; nn = nn.right)
474 checkused(nn.left);
475 }
476 else
477 nwarn(n, "result of expression "+expconv(n)+" not used");
478 n = mkunary(Oused, n);
479 n.ty = n.left.ty;
480 return n;
481}
482
483fncheck(d: ref Decl)
484{
485 n := d.init;
486 if(debug['t'])
487 print("typecheck tree: %s\n", nodeconv(n));
488
489 fndecls = nil;
490 adtp := outerpolys(n.left);
491 if(n.left.op == Odot)
492 repushids(adtp);
493 if(d.ty.polys != nil)
494 repushids(d.ty.polys);
495 repushids(d.ty.ids);
496
497 labdep = 0;
498 labstack = array[maxlabdep] of ref Node;
499 n.right = scheck(n.right, d.ty.tof, Sother);
500 if(labdep != 0)
501 fatal("unbalanced label stack in fncheck");
502 labstack = nil;
503
504 d.locals = appdecls(popids(d.ty.ids), fndecls);
505 if(d.ty.polys != nil)
506 popids(d.ty.polys);
507 if(n.left.op == Odot)
508 popids(adtp);
509 fndecls = nil;
510
511 checkrefs(d.ty.ids);
512 checkrefs(d.ty.polys);
513 checkrefs(d.locals);
514
515 checkraises(n);
516
517 d.inline = byte fninline(d);
518}
519
520scheck(n: ref Node, ret: ref Type, kind : int): ref Node
521{
522 s: ref Sym;
523 rok: int;
524
525 top := n;
526 last: ref Node = nil;
527 for(; n != nil; n = n.right){
528 left := n.left;
529 right := n.right;
530 case n.op{
531 Ovardecl =>
532 vardecled(n);
533 varcheck(n, 0);
534 if (nested() && tmustzero(n.decl.ty))
535 decltozero(n);
536# else if (inloop() && tmustzero(n.decl.ty))
537# decltozero(n);
538 return top;
539 Ovardecli =>
540 vardecled(left);
541 varcheck(left, 0);
542 echeck(right, 0, 0, nil);
543 if (nested() && tmustzero(left.decl.ty))
544 decltozero(left);
545 return top;
546 Otypedecl =>
547 typedecled(n);
548 bindtypes(n.ty);
549 tcycle(n.ty);
550 return top;
551 Ocondecl =>
552 condecled(n);
553 concheck(n, 0);
554 return top;
555 Oexdecl =>
556 exdecled(n);
557 excheck(n, 0);
558 return top;
559 Oimport =>
560 importdecled(n);
561 importcheck(n, 0);
562 return top;
563 Ofunc =>
564 fatal("scheck func");
565 Oscope =>
566 if (kind == Sother)
567 kind = Sscope;
568 pushscope(n, kind);
569 if (left != nil)
570 fatal("Oscope has left field");
571 echeck(left, 0, 0, nil);
572 n.right = scheck(right, ret, Sother);
573 d := popscope();
574 fndecls = appdecls(fndecls, d);
575 return top;
576 Olabel =>
577 echeck(left, 0, 0, nil);
578 n.right = scheck(right, ret, Sother);
579 return top;
580 Oseq =>
581 n.left = scheck(left, ret, Sother);
582 # next time will check n.right
583 Oif =>
584 (rok, nil) = echeck(left, 0, 0, nil);
585 if(rok && left.op != Onothing && left.ty != tint)
586 nerror(n, "if conditional must be an int, not "+etconv(left));
587 right.left = scheck(right.left, ret, Sother);
588 # next time will check n.right.right
589 n = right;
590 Ofor =>
591 (rok, nil) = echeck(left, 0, 0, nil);
592 if(rok && left.op != Onothing && left.ty != tint)
593 nerror(n, "for conditional must be an int, not "+etconv(left));
594 #
595 # do the continue clause before the body
596 # this reflects the ordering of declarations
597 #
598 pushlabel(n);
599 right.right = scheck(right.right, ret, Sother);
600 right.left = scheck(right.left, ret, Sloop);
601 labdep--;
602 if(n.decl != nil && !n.decl.refs)
603 nwarn(n, "label "+n.decl.sym.name+" never referenced");
604 return top;
605 Odo =>
606 (rok, nil) = echeck(left, 0, 0, nil);
607 if(rok && left.op != Onothing && left.ty != tint)
608 nerror(n, "do conditional must be an int, not "+etconv(left));
609 pushlabel(n);
610 n.right = scheck(n.right, ret, Sloop);
611 labdep--;
612 if(n.decl != nil && !n.decl.refs)
613 nwarn(n, "label "+n.decl.sym.name+" never referenced");
614 return top;
615 Oalt or
616 Ocase or
617 Opick or
618 Oexcept =>
619 pushlabel(n);
620 case n.op{
621 Oalt =>
622 altcheck(n, ret);
623 Ocase =>
624 casecheck(n, ret);
625 Opick =>
626 pickcheck(n, ret);
627 Oexcept =>
628 exccheck(n, ret);
629 }
630 labdep--;
631 if(n.decl != nil && !n.decl.refs)
632 nwarn(n, "label "+n.decl.sym.name+" never referenced");
633 return top;
634 Oret =>
635 (rok, nil) = echeck(left, 0, 0, nil);
636 if(!rok)
637 return top;
638 if(left == nil){
639 if(ret != tnone)
640 nerror(n, "return of nothing from a fn of "+typeconv(ret));
641 }else if(ret == tnone){
642 if(left.ty != tnone)
643 nerror(n, "return "+etconv(left)+" from a fn with no return type");
644 }else if(!tcompat(ret, left.ty, 0))
645 nerror(n, "return "+etconv(left)+" from a fn of "+typeconv(ret));
646 return top;
647 Obreak or
648 Ocont =>
649 s = nil;
650 if(n.decl != nil)
651 s = n.decl.sym;
652 for(i := 0; i < labdep; i++){
653 if(s == nil || labstack[i].decl != nil && labstack[i].decl.sym == s){
654 if(n.op == Ocont
655 && labstack[i].op != Ofor && labstack[i].op != Odo)
656 continue;
657 if(s != nil)
658 labstack[i].decl.refs++;
659 return top;
660 }
661 }
662 nerror(n, "no appropriate target for "+expconv(n));
663 return top;
664 Oexit or
665 Onothing =>
666 return top;
667 Oexstmt =>
668 fndec.handler = byte 1;
669 n.left = scheck(left, ret, Sother);
670 n.right = scheck(right, ret, Sother);
671 return top;
672 * =>
673 (nil, rok) = echeck(n, 0, 0, nil);
674 if(rok)
675 n = checkused(n);
676 if(last == nil)
677 return n;
678 last.right = n;
679 return top;
680 }
681 last = n;
682 }
683 return top;
684}
685
686pushlabel(n: ref Node)
687{
688 s: ref Sym;
689
690 if(labdep >= maxlabdep){
691 maxlabdep += MaxScope;
692 labs := array[maxlabdep] of ref Node;
693 labs[:] = labstack;
694 labstack = labs;
695 }
696 if(n.decl != nil){
697 s = n.decl.sym;
698 n.decl.refs = 0;
699 for(i := 0; i < labdep; i++)
700 if(labstack[i].decl != nil && labstack[i].decl.sym == s)
701 nerror(n, "label " + s.name + " duplicated on line " + lineconv(labstack[i].decl.src.start));
702 }
703 labstack[labdep++] = n;
704}
705
706varcheck(n: ref Node, isglobal: int)
707{
708 t := validtype(n.ty, nil);
709 t = topvartype(t, n.decl, isglobal, 0);
710 last := n.left.decl;
711 for(ids := n.decl; ids != last.next; ids = ids.next){
712 ids.ty = t;
713 shareloc(ids);
714 }
715 if(t.eraises != nil)
716 raisescheck(t);
717}
718
719concheck(n: ref Node, isglobal: int)
720{
721 t: ref Type;
722 init: ref Node;
723
724 pushscope(nil, Sother);
725 installids(Dconst, iota);
726 (ok, allok) := echeck(n.right, 0, isglobal, nil);
727 popscope();
728
729 init = n.right;
730 if(!ok){
731 t = terror;
732 }else{
733 t = init.ty;
734 if(!tattr[t.kind].conable){
735 nerror(init, "cannot have a "+typeconv(t)+" constant");
736 allok = 0;
737 }
738 }
739
740 last := n.left.decl;
741 for(ids := n.decl; ids != last.next; ids = ids.next)
742 ids.ty = t;
743
744 if(!allok)
745 return;
746
747 i := 0;
748 for(ids = n.decl; ids != last.next; ids = ids.next){
749 if(ok){
750 iota.init.c.val = big i;
751 ids.init = dupn(0, nosrc, init);
752 if(!varcom(ids))
753 ok = 0;
754 }
755 i++;
756 }
757}
758
759exname(d: ref Decl): string
760{
761 s := "";
762 m := impmods.sym;
763 if(d.dot != nil)
764 m = d.dot.sym;
765 if(m != nil)
766 s += m.name+".";
767 if(fndec != nil)
768 s += fndec.sym.name+".";
769 s += string (scope-ScopeGlobal)+"."+d.sym.name;
770 return s;
771}
772
773excheck(n: ref Node, isglobal: int)
774{
775 t: ref Type;
776 ids, last: ref Decl;
777
778 t = validtype(n.ty, nil);
779 t = topvartype(t, n.decl, isglobal, 0);
780 last = n.left.decl;
781 for(ids = n.decl; ids != last.next; ids = ids.next){
782 ids.ty = t;
783 ids.init = mksconst(n.src, enterstring(exname(ids)));
784 # ids.init = mksconst(n.src, enterstring(ids.sym.name));
785 }
786}
787
788importcheck(n: ref Node, isglobal: int)
789{
790 (ok, nil) := echeck(n.right, 1, isglobal, nil);
791 if(!ok)
792 return;
793
794 m := n.right;
795 if(m.ty.kind != Tmodule || m.op != Oname){
796 nerror(n, "cannot import from "+etconv(m));
797 return;
798 }
799
800 last := n.left.decl;
801 for(id := n.decl; id != last.next; id = id.next){
802 v := namedot(m.ty.ids, id.sym);
803 if(v == nil){
804 error(id.src.start, id.sym.name+" is not a member of "+expconv(m));
805 id.store = Dwundef;
806 continue;
807 }
808 id.store = v.store;
809 v.ty = validtype(v.ty, nil);
810 id.ty = t := v.ty;
811 if(id.store == Dtype && t.decl != nil){
812 id.timport = t.decl.timport;
813 t.decl.timport = id;
814 }
815 id.init = v.init;
816 id.importid = v;
817 id.eimport = m;
818 }
819}
820
821rewcall(n: ref Node, d: ref Decl): ref Decl
822{
823 # put original function back now we're type checked
824 while(d.link != nil)
825 d = d.link;
826 if(n.op == Odot)
827 n.right.decl = d;
828 else if(n.op == Omdot){
829 n.right.right.decl = d;
830 n.right.right.ty = d.ty;
831 }
832 else
833 fatal("bad op in Ocall rewcall");
834 n.ty = n.right.ty = d.ty;
835 d.refs++;
836 usetype(d.ty);
837 return d;
838}
839
840isfnrefty(t: ref Type): int
841{
842 return t.kind == Tref && t.tof.kind == Tfn;
843}
844
845isfnref(d: ref Decl): int
846{
847 case(d.store){
848 Dglobal or
849 Darg or
850 Dlocal or
851 Dfield or
852 Dimport =>
853 return isfnrefty(d.ty);
854 }
855 return 0;
856}
857
858tagopt: int;
859
860#
861# annotate the expression with types
862#
863echeck(n: ref Node, typeok, isglobal: int, par: ref Node): (int, int)
864{
865 tg, id, callee: ref Decl;
866 t, tt: ref Type;
867 ok, allok, max, nocheck, kidsok: int;
868
869 ok = allok = 1;
870 if(n == nil)
871 return (1, 1);
872
873 if(n.op == Oseq){
874 for( ; n != nil && n.op == Oseq; n = n.right){
875 (okl, allokl) := echeck(n.left, typeok == 2, isglobal, n);
876 ok &= okl;
877 allok &= allokl;
878 n.ty = tnone;
879 }
880 if(n == nil)
881 return (ok, allok);
882 }
883
884 left := n.left;
885 right := n.right;
886
887 nocheck = 0;
888 if(n.op == Odot || n.op == Omdot || n.op == Ocall || n.op == Oref || n.op == Otagof || n.op == Oindex)
889 nocheck = 1;
890 if(n.op != Odas # special case
891 && n.op != Oload) # can have better error recovery
892 (ok, allok) = echeck(left, nocheck, isglobal, n);
893 if(n.op != Odas # special case
894 && n.op != Odot # special check
895 && n.op != Omdot # special check
896 && n.op != Ocall # can have better error recovery
897 && n.op != Oindex){
898 (okr, allokr) := echeck(right, 0, isglobal, n);
899 ok &= okr;
900 allok &= allokr;
901 }
902 if(!ok){
903 n.ty = terror;
904 return (0, 0);
905 }
906
907 case n.op{
908 Odas =>
909 (ok, allok) = echeck(right, 0, isglobal, n);
910 if(!ok)
911 right.ty = terror;
912 if(!isglobal && !dasdecl(left)){
913 ok = 0;
914 }else if(!specific(right.ty) || !declasinfer(left, right.ty)){
915 nerror(n, "cannot declare "+expconv(left)+" from "+etconv(right));
916 declaserr(left);
917 ok = 0;
918 }
919 if(right.ty.kind == Texception)
920 left.ty = n.ty = mkextuptype(right.ty);
921 else{
922 left.ty = n.ty = right.ty;
923 usedty(n.ty);
924 }
925 if (nested() && tmustzero(left.ty))
926 decltozero(left);
927 return (ok, allok & ok);
928 Oseq or
929 Onothing =>
930 n.ty = tnone;
931 Owild =>
932 n.ty = tint;
933 Ocast =>
934 t = usetype(n.ty);
935 n.ty = t;
936 tt = left.ty;
937 if(tcompat(t, tt, 0)){
938 left.ty = t;
939 break;
940 }
941 if(tt.kind == Tarray){
942 if(tt.tof == tbyte && t == tstring)
943 break;
944 }else if(t.kind == Tarray){
945 if(t.tof == tbyte && tt == tstring)
946 break;
947 }else if(casttab[tt.kind][t.kind]){
948 break;
949 }
950 nerror(n, "cannot make a "+typeconv(n.ty)+" from "+etconv(left));
951 return (0, 0);
952 Ochan =>
953 n.ty = usetype(n.ty);
954 if(left != nil && left.ty.kind != Tint){
955 nerror(n, "channel size "+etconv(left)+" is not an int");
956 return (0, 0);
957 }
958 Oload =>
959 n.ty = usetype(n.ty);
960 (nil, kidsok) = echeck(left, 0, isglobal, n);
961 if(n.ty.kind != Tmodule){
962 nerror(n, "cannot load a "+typeconv(n.ty));
963 return (0, 0);
964 }
965 if(!kidsok){
966 allok = 0;
967 break;
968 }
969 if(left.ty != tstring){
970 nerror(n, "cannot load a module from "+etconv(left));
971 allok = 0;
972 break;
973 }
974if(n.ty.tof.decl.refs != 0)
975n.ty.tof.decl.refs++;
976n.ty.decl.refs++;
977 usetype(n.ty.tof);
978 Oref =>
979 t = left.ty;
980 if(t.kind != Tadt && t.kind != Tadtpick && t.kind != Tfn && t.kind != Ttuple){
981 nerror(n, "cannot make a ref from "+etconv(left));
982 return (0, 0);
983 }
984 if(!tagopt && t.kind == Tadt && t.tags != nil && valistype(left)){
985 nerror(n, "instances of ref "+expconv(left)+" must be qualified with a pick tag");
986 return (0, 0);
987 }
988 if(t.kind == Tadtpick)
989 t.tof = usetype(t.tof);
990 n.ty = usetype(mktype(n.src.start, n.src.stop, Tref, t, nil));
991 Oarray =>
992 max = 0;
993 if(right != nil){
994 max = assignindices(n);
995 if(max < 0)
996 return (0, 0);
997 if(!specific(right.left.ty)){
998 nerror(n, "type for array not specific");
999 return (0, 0);
1000 }
1001 n.ty = mktype(n.src.start, n.src.stop, Tarray, right.left.ty, nil);
1002 }
1003 n.ty = usetype(n.ty);
1004
1005 if(left.op == Onothing)
1006 n.left = left = mkconst(n.left.src, big max);
1007
1008 if(left.ty.kind != Tint){
1009 nerror(n, "array size "+etconv(left)+" is not an int");
1010 return (0, 0);
1011 }
1012 Oelem =>
1013 n.ty = right.ty;
1014 Orange =>
1015 if(left.ty != right.ty
1016 || left.ty != tint && left.ty != tstring){
1017 nerror(left, "range "+etconv(left)+" to "+etconv(right)+" is not an int or string range");
1018 return (0, 0);
1019 }
1020 n.ty = left.ty;
1021 Oname =>
1022 id = n.decl;
1023 if(id == nil){
1024 nerror(n, "name with no declaration");
1025 return (0, 0);
1026 }
1027 if(id.store == Dunbound){
1028 s := id.sym;
1029 id = s.decl;
1030 if(id == nil)
1031 id = undefed(n.src, s);
1032 # save a little space
1033 s.unbound = nil;
1034 n.decl = id;
1035 id.refs++;
1036 }
1037 n.ty = id.ty = usetype(id.ty);
1038 case id.store{
1039 Dfn or
1040 Dglobal or
1041 Darg or
1042 Dlocal or
1043 Dimport or
1044 Dfield or
1045 Dtag =>
1046 break;
1047 Dunbound =>
1048 fatal("unbound symbol found in echeck");
1049 Dundef =>
1050 nerror(n, id.sym.name+" is not declared");
1051 id.store = Dwundef;
1052 return (0, 0);
1053 Dwundef =>
1054 return (0, 0);
1055 Dconst =>
1056 if(id.init == nil){
1057 nerror(n, id.sym.name+"'s value cannot be determined");
1058 id.store = Dwundef;
1059 return (0, 0);
1060 }
1061 Dtype =>
1062 if(typeok)
1063 break;
1064 nerror(n, declconv(id)+" is not a variable");
1065 return (0, 0);
1066 * =>
1067 fatal("echeck: unknown symbol storage");
1068 }
1069
1070 if(n.ty == nil){
1071 nerror(n, declconv(id)+"'s type is not fully defined");
1072 id.store = Dwundef;
1073 return (0, 0);
1074 }
1075 if(id.importid != nil && valistype(id.eimport)
1076 && id.store != Dconst && id.store != Dtype && id.store != Dfn){
1077 nerror(n, "cannot use "+expconv(n)+" because "+expconv(id.eimport)+" is a module interface");
1078 return (0, 0);
1079 }
1080 if(n.ty.kind == Texception && !int n.ty.cons && par != nil && par.op != Oraise && par.op != Odot){
1081 nn := mkn(0, nil, nil);
1082 *nn = *n;
1083 n.op = Ocast;
1084 n.left = nn;
1085 n.decl = nil;
1086 n.ty = usetype(mkextuptype(n.ty));
1087 }
1088 # function name as function reference
1089 if(id.store == Dfn && (par == nil || (par.op != Odot && par.op != Omdot && par.op != Ocall && par.op != Ofunc)))
1090 fnref(n, id);
1091 Oconst =>
1092 if(n.ty == nil){
1093 nerror(n, "no type in "+expconv(n));
1094 return (0, 0);
1095 }
1096 Oas =>
1097 t = right.ty;
1098 if(t.kind == Texception)
1099 t = mkextuptype(t);
1100 if(!tcompat(left.ty, t, 1)){
1101 nerror(n, "type clash in "+etconv(left)+" = "+etconv(right));
1102 return (0, 0);
1103 }
1104 if(t == tany)
1105 t = left.ty;
1106 n.ty = t;
1107 left.ty = t;
1108 if(t.kind == Tadt && t.tags != nil || t.kind == Tadtpick)
1109 if(left.ty.kind != Tadtpick || right.ty.kind != Tadtpick)
1110 nerror(n, "expressions cannot have type "+typeconv(t));
1111 if(left.ty.kind == Texception){
1112 nerror(n, "cannot assign to an exception");
1113 return (0, 0);
1114 }
1115 if(islval(left))
1116 break;
1117 return (0, 0);
1118 Osnd =>
1119 if(left.ty.kind != Tchan){
1120 nerror(n, "cannot send on "+etconv(left));
1121 return (0, 0);
1122 }
1123 if(!tcompat(left.ty.tof, right.ty, 0)){
1124 nerror(n, "type clash in "+etconv(left)+" <-= "+etconv(right));
1125 return (0, 0);
1126 }
1127 t = right.ty;
1128 if(t == tany)
1129 t = left.ty.tof;
1130 n.ty = t;
1131 Orcv =>
1132 t = left.ty;
1133 if(t.kind == Tarray)
1134 t = t.tof;
1135 if(t.kind != Tchan){
1136 nerror(n, "cannot receive on "+etconv(left));
1137 return (0, 0);
1138 }
1139 if(left.ty.kind == Tarray)
1140 n.ty = usetype(mktype(n.src.start, n.src.stop, Ttuple, nil,
1141 mkids(n.src, nil, tint, mkids(n.src, nil, t.tof, nil))));
1142 else
1143 n.ty = t.tof;
1144 Ocons =>
1145 if(right.ty.kind != Tlist && right.ty != tany){
1146 nerror(n, "cannot :: to "+etconv(right));
1147 return (0, 0);
1148 }
1149 n.ty = right.ty;
1150 if(right.ty == tany)
1151 n.ty = usetype(mktype(n.src.start, n.src.stop, Tlist, left.ty, nil));
1152 else if(!tcompat(right.ty.tof, left.ty, 0)){
1153 t = tparent(right.ty.tof, left.ty);
1154 if(!tcompat(t, left.ty, 0)){
1155 nerror(n, "type clash in "+etconv(left)+" :: "+etconv(right));
1156 return (0, 0);
1157 }
1158 else
1159 n.ty = usetype(mktype(n.src.start, n.src.stop, Tlist, t, nil));
1160 }
1161 Ohd or
1162 Otl =>
1163 if(left.ty.kind != Tlist || left.ty.tof == nil){
1164 nerror(n, "cannot "+opconv(n.op)+" "+etconv(left));
1165 return (0, 0);
1166 }
1167 if(n.op == Ohd)
1168 n.ty = left.ty.tof;
1169 else
1170 n.ty = left.ty;
1171 Otuple =>
1172 n.ty = usetype(mktype(n.src.start, n.src.stop, Ttuple, nil, tuplefields(left)));
1173 Ospawn =>
1174 if(left.op != Ocall || left.left.ty.kind != Tfn && !isfnrefty(left.left.ty)){
1175 nerror(left, "cannot spawn "+expconv(left));
1176 return (0, 0);
1177 }
1178 if(left.ty != tnone){
1179 nerror(left, "cannot spawn functions which return values, such as "+etconv(left));
1180 return (0, 0);
1181 }
1182 Oraise =>
1183 if(left.op == Onothing){
1184 if(inexcept == nil){
1185 nerror(n, expconv(n)+": empty raise not in exception handler");
1186 return (0, 0);
1187 }
1188 n.left = dupn(1, n.src, inexcept);
1189 break;
1190 }
1191 if(left.ty != tstring && left.ty.kind != Texception){
1192 nerror(n, expconv(n)+": raise argument "+etconv(left)+" is not a string or exception");
1193 return (0, 0);
1194 }
1195 if((left.op != Ocall || left.left.ty.kind == Tfn) && left.ty.ids != nil && int left.ty.cons){
1196 nerror(n, "too few exception arguments");
1197 return (0, 0);
1198 }
1199 Ocall =>
1200 (nil, kidsok) = echeck(right, 0, isglobal, nil);
1201 t = left.ty;
1202 usedty(t);
1203 pure := 1;
1204 if(t.kind == Tref){
1205 pure = 0;
1206 t = t.tof;
1207 }
1208 if(t.kind != Tfn)
1209 return callcast(n, kidsok, allok);
1210 n.ty = t.tof;
1211 if(!kidsok){
1212 allok = 0;
1213 break;
1214 }
1215
1216 #
1217 # get the name to call and any associated module
1218 #
1219 mod: ref Node = nil;
1220 callee = nil;
1221 id = nil;
1222 tt = nil;
1223 if(left.op == Odot){
1224 callee = left.right.decl;
1225 id = callee.dot;
1226 right = passimplicit(left, right);
1227 n.right = right;
1228 tt = left.left.ty;
1229 if(tt.kind == Tref)
1230 tt = tt.tof;
1231 ttt := tt;
1232 if(tt.kind == Tadtpick)
1233 ttt = tt.decl.dot.ty;
1234 dd := ttt.decl;
1235 while(dd != nil && dd.link != nil)
1236 dd = dd.link;
1237 if(dd != nil && dd.timport != nil)
1238 mod = dd.timport.eimport;
1239
1240 #
1241 # stash the import module under a rock,
1242 # because we won't be able to get it later
1243 # after scopes are popped
1244 #
1245 left.right.left = mod;
1246 }else if(left.op == Omdot){
1247 if(left.right.op == Odot){
1248 callee = left.right.right.decl;
1249 right = passimplicit(left.right, right);
1250 n.right = right;
1251 tt = left.right.left.ty;
1252 if(tt.kind == Tref)
1253 tt = tt.tof;
1254 }else
1255 callee = left.right.decl;
1256 mod = left.left;
1257 }else if(left.op == Oname){
1258 callee = left.decl;
1259 id = callee;
1260 mod = id.eimport;
1261 }else if(pure){
1262 nerror(left, expconv(left)+" is not a function name");
1263 allok = 0;
1264 break;
1265 }
1266 if(pure && callee == nil)
1267 fatal("can't find called function: "+nodeconv(left));
1268 if(callee != nil && callee.store != Dfn && !isfnref(callee)){
1269 nerror(left, expconv(left)+" is not a function");
1270 allok = 0;
1271 break;
1272 }
1273 if(mod != nil && mod.ty.kind != Tmodule){
1274 nerror(left, "cannot call "+expconv(left));
1275 allok = 0;
1276 break;
1277 }
1278 if(mod != nil){
1279 if(valistype(mod)){
1280 nerror(left, "cannot call "+expconv(left)+" because "+expconv(mod)+" is a module interface");
1281 allok = 0;
1282 break;
1283 }
1284 }else if(id != nil && id.dot != nil && !isimpmod(id.dot.sym)){
1285 nerror(left, "cannot call "+expconv(left)+" without importing "+id.sym.name+" from a variable");
1286 allok = 0;
1287 break;
1288 }
1289 if(mod != nil)
1290 modrefable(left.ty);
1291 if(callee != nil && callee.store != Dfn)
1292 callee = nil;
1293 if(t.varargs != byte 0){
1294 t = mkvarargs(left, right);
1295 if(left.ty.kind == Tref)
1296 left.ty = usetype(mktype(t.src.start, t.src.stop, Tref, t, nil));
1297 else
1298 left.ty = t;
1299 }
1300 else if(ispoly(callee) || isfnrefty(left.ty) && left.ty.tof.polys != nil){
1301 unifysrc = n.src;
1302 if(!argncompat(n, t.ids, right)){
1303 allok = 0;
1304 break;
1305 }
1306 (okp, tp) := tunify(left.ty, calltype(left.ty, right, n.ty));
1307 if(!okp){
1308 nerror(n, "function call type mismatch (" + typeconv(left.ty)+" vs "+typeconv(calltype(left.ty, right, n.ty))+")");
1309 allok = 0;
1310 }
1311 else{
1312 (n.ty, tp) = expandtype(n.ty, nil, nil, tp);
1313 n.ty = usetype(n.ty);
1314 if(ispoly(callee) && tt != nil && (tt.kind == Tadt || tt.kind == Tadtpick) && int (tt.flags&INST))
1315 callee = rewcall(left, callee);
1316 n.right = passfns(n.src, callee, left, right, tt, tp);
1317 }
1318 }
1319 else if(!argcompat(n, t.ids, right))
1320 allok = 0;
1321 Odot =>
1322 t = left.ty;
1323 if(t.kind == Tref)
1324 t = t.tof;
1325 case t.kind{
1326 Tadt or
1327 Tadtpick or
1328 Ttuple or
1329 Texception or
1330 Tpoly =>
1331 id = namedot(t.ids, right.decl.sym);
1332 if(id == nil){
1333 id = namedot(t.tags, right.decl.sym);
1334 if(id != nil && !valistype(left)){
1335 nerror(n, expconv(left)+" is not a type");
1336 return (0, 0);
1337 }
1338 }
1339 if(id == nil){
1340 id = namedot(t.polys, right.decl.sym);
1341 if(id != nil && !valistype(left)){
1342 nerror(n, expconv(left)+" is not a type");
1343 return (0, 0);
1344 }
1345 }
1346 if(id == nil && t.kind == Tadtpick)
1347 id = namedot(t.decl.dot.ty.ids, right.decl.sym);
1348 if(id == nil){
1349 for(tg = t.tags; tg != nil; tg = tg.next){
1350 id = namedot(tg.ty.ids, right.decl.sym);
1351 if(id != nil)
1352 break;
1353 }
1354 if(id != nil){
1355 nerror(n, "cannot yet index field "+right.decl.sym.name+" of "+etconv(left));
1356 return (0, 0);
1357 }
1358 }
1359 if(id == nil)
1360 break;
1361 if(id.store == Dfield && valistype(left)){
1362 nerror(n, expconv(left)+" is not a value");
1363 return (0, 0);
1364 }
1365 id.ty = validtype(id.ty, t.decl);
1366 id.ty = usetype(id.ty);
1367 break;
1368 * =>
1369 nerror(left, etconv(left)+" cannot be qualified with .");
1370 return (0, 0);
1371 }
1372 if(id == nil){
1373 nerror(n, expconv(right)+" is not a member of "+etconv(left));
1374 return (0, 0);
1375 }
1376 if(id.ty == tunknown){
1377 nerror(n, "illegal forward reference to "+expconv(n));
1378 return (0, 0);
1379 }
1380
1381 increfs(id);
1382 right.decl = id;
1383 n.ty = id.ty;
1384 if((id.store == Dconst || id.store == Dtag) && hasside(left, 1))
1385 nwarn(left, "result of expression "+etconv(left)+" ignored");
1386 # function name as function reference
1387 if(id.store == Dfn && (par == nil || (par.op != Omdot && par.op != Ocall && par.op != Ofunc)))
1388 fnref(n, id);
1389 Omdot =>
1390 t = left.ty;
1391 if(t.kind != Tmodule){
1392 nerror(left, etconv(left)+" cannot be qualified with ->");
1393 return (0, 0);
1394 }
1395 id = nil;
1396 if(right.op == Oname){
1397 id = namedot(t.ids, right.decl.sym);
1398 }else if(right.op == Odot){
1399 (ok, kidsok) = echeck(right, 0, isglobal, n);
1400 allok &= kidsok;
1401 if(!ok)
1402 return (0, 0);
1403 tt = right.left.ty;
1404 if(tt.kind == Tref)
1405 tt = tt.tof;
1406 if(right.ty.kind == Tfn
1407 && tt.kind == Tadt
1408 && tt.decl.dot == t.decl)
1409 id = right.right.decl;
1410 }
1411 if(id == nil){
1412 nerror(n, expconv(right)+" is not a member of "+etconv(left));
1413 return (0, 0);
1414 }
1415 if(id.store != Dconst && id.store != Dtype && id.store != Dtag){
1416 if(valistype(left)){
1417 nerror(n, expconv(left)+" is not a value");
1418 return (0, 0);
1419 }
1420 }else if(hasside(left, 1))
1421 nwarn(left, "result of expression "+etconv(left)+" ignored");
1422 if(!typeok && id.store == Dtype){
1423 nerror(n, expconv(n)+" is a type, not a value");
1424 return (0, 0);
1425 }
1426 if(id.ty == tunknown){
1427 nerror(n, "illegal forward reference to "+expconv(n));
1428 return (0, 0);
1429 }
1430 id.refs++;
1431 right.decl = id;
1432 n.ty = id.ty = usetype(id.ty);
1433 if(id.store == Dglobal)
1434 modrefable(id.ty);
1435 # function name as function reference
1436 if(id.store == Dfn && (par == nil || (par.op != Ocall && par.op != Ofunc)))
1437 fnref(n, id);
1438 Otagof =>
1439 n.ty = tint;
1440 t = left.ty;
1441 if(t.kind == Tref)
1442 t = t.tof;
1443 id = nil;
1444 case left.op{
1445 Oname =>
1446 id = left.decl;
1447 Odot =>
1448 id = left.right.decl;
1449 Omdot =>
1450 if(left.right.op == Odot)
1451 id = left.right.right.decl;
1452 }
1453 if(id != nil && id.store == Dtag
1454 || id != nil && id.store == Dtype && t.kind == Tadt && t.tags != nil)
1455 n.decl = id;
1456 else if(t.kind == Tadt && t.tags != nil || t.kind == Tadtpick)
1457 n.decl = nil;
1458 else{
1459 nerror(n, "cannot get the tag value for "+etconv(left));
1460 return (1, 0);
1461 }
1462 Oind =>
1463 t = left.ty;
1464 if(t.kind != Tref || (t.tof.kind != Tadt && t.tof.kind != Tadtpick && t.tof.kind != Ttuple)){
1465 nerror(n, "cannot * "+etconv(left));
1466 return (0, 0);
1467 }
1468 n.ty = t.tof;
1469 for(tg = t.tof.tags; tg != nil; tg = tg.next)
1470 tg.ty.tof = usetype(tg.ty.tof);
1471 Oindex =>
1472 if(valistype(left)){
1473 tagopt = 1;
1474 (nil, kidsok) = echeck(right, 2, isglobal, n);
1475 tagopt = 0;
1476 if(!kidsok)
1477 return (0, 0);
1478 if((t = exptotype(n)) == nil){
1479 nerror(n, expconv(right) + " is not a type list");
1480 return (0, 0);
1481 }
1482 if(!typeok){
1483 nerror(n, expconv(left) + " is not a variable");
1484 return (0, 0);
1485 }
1486 *n = *(n.left);
1487 n.ty = usetype(t);
1488 break;
1489 }
1490 if(0 && right.op == Oseq){ # a[e1, e2, ...]
1491 # array creation to do before we allow this
1492 rewind(n);
1493 return echeck(n, typeok, isglobal, par);
1494 }
1495 t = left.ty;
1496 (nil, kidsok) = echeck(right, 0, isglobal, n);
1497 if(t.kind != Tarray && t != tstring){
1498 nerror(n, "cannot index "+etconv(left));
1499 return (0, 0);
1500 }
1501 if(t == tstring){
1502 n.op = Oinds;
1503 n.ty = tint;
1504 }else{
1505 n.ty = t.tof;
1506 }
1507 if(!kidsok){
1508 allok = 0;
1509 break;
1510 }
1511 if(right.ty != tint){
1512 nerror(n, "cannot index "+etconv(left)+" with "+etconv(right));
1513 allok = 0;
1514 break;
1515 }
1516 Oslice =>
1517 t = n.ty = left.ty;
1518 if(t.kind != Tarray && t != tstring){
1519 nerror(n, "cannot slice "+etconv(left)+" with '"+subexpconv(right.left)+":"+subexpconv(right.right)+"'");
1520 return (0, 0);
1521 }
1522 if(right.left.ty != tint && right.left.op != Onothing
1523 || right.right.ty != tint && right.right.op != Onothing){
1524 nerror(n, "cannot slice "+etconv(left)+" with '"+subexpconv(right.left)+":"+subexpconv(right.right)+"'");
1525 return (1, 0);
1526 }
1527 Olen =>
1528 t = left.ty;
1529 n.ty = tint;
1530 if(t.kind != Tarray && t.kind != Tlist && t != tstring){
1531 nerror(n, "len requires an array, string or list in "+etconv(left));
1532 return (1, 0);
1533 }
1534 Ocomp or
1535 Onot or
1536 Oneg =>
1537 n.ty = left.ty;
1538usedty(n.ty);
1539 case left.ty.kind{
1540 Tint =>
1541 return (1, allok);
1542 Treal or
1543 Tfix =>
1544 if(n.op == Oneg)
1545 return (1, allok);
1546 Tbig or
1547 Tbyte =>
1548 if(n.op == Oneg || n.op == Ocomp)
1549 return (1, allok);
1550 }
1551 nerror(n, "cannot apply "+opconv(n.op)+" to "+etconv(left));
1552 return (0, 0);
1553 Oinc or
1554 Odec or
1555 Opreinc or
1556 Opredec =>
1557 n.ty = left.ty;
1558 case left.ty.kind{
1559 Tint or
1560 Tbig or
1561 Tbyte or
1562 Treal =>
1563 break;
1564 * =>
1565 nerror(n, "cannot apply "+opconv(n.op)+" to "+etconv(left));
1566 return (0, 0);
1567 }
1568 if(islval(left))
1569 break;
1570 return(0, 0);
1571 Oadd or
1572 Odiv or
1573 Omul or
1574 Osub =>
1575 if(mathchk(n, 1))
1576 break;
1577 return (0, 0);
1578 Oexp or
1579 Oexpas =>
1580 n.ty = left.ty;
1581 if(n.ty != tint && n.ty != tbig && n.ty != treal){
1582 nerror(n, "exponend " + etconv(left) + " is not int or real");
1583 return (0, 0);
1584 }
1585 if(right.ty != tint){
1586 nerror(n, "exponent " + etconv(right) + " is not int");
1587 return (0, 0);
1588 }
1589 if(n.op == Oexpas && !islval(left))
1590 return (0, 0);
1591 break;
1592 # if(mathchk(n, 0)){
1593 # if(n.ty != tint){
1594 # nerror(n, "exponentiation operands not int");
1595 # return (0, 0);
1596 # }
1597 # break;
1598 # }
1599 # return (0, 0);
1600 Olsh or
1601 Orsh =>
1602 if(shiftchk(n))
1603 break;
1604 return (0, 0);
1605 Oandand or
1606 Ooror =>
1607 if(left.ty != tint){
1608 nerror(n, opconv(n.op)+"'s left operand is not an int: "+etconv(left));
1609 allok = 0;
1610 }
1611 if(right.ty != tint){
1612 nerror(n, opconv(n.op)+"'s right operand is not an int: "+etconv(right));
1613 allok = 0;
1614 }
1615 n.ty = tint;
1616 Oand or
1617 Omod or
1618 Oor or
1619 Oxor =>
1620 if(mathchk(n, 0))
1621 break;
1622 return (0, 0);
1623 Oaddas or
1624 Odivas or
1625 Omulas or
1626 Osubas =>
1627 if(mathchk(n, 1) && islval(left))
1628 break;
1629 return (0, 0);
1630 Olshas or
1631 Orshas =>
1632 if(shiftchk(n) && islval(left))
1633 break;
1634 return (0, 0);
1635 Oandas or
1636 Omodas or
1637 Oxoras or
1638 Ooras =>
1639 if(mathchk(n, 0) && islval(left))
1640 break;
1641 return (0, 0);
1642 Olt or
1643 Oleq or
1644 Ogt or
1645 Ogeq =>
1646 if(!mathchk(n, 1))
1647 return (0, 0);
1648 n.ty = tint;
1649 Oeq or
1650 Oneq =>
1651 case left.ty.kind{
1652 Tint or
1653 Tbig or
1654 Tbyte or
1655 Treal or
1656 Tstring or
1657 Tref or
1658 Tlist or
1659 Tarray or
1660 Tchan or
1661 Tany or
1662 Tmodule or
1663 Tfix or
1664 Tpoly =>
1665 if(!tcompat(left.ty, right.ty, 0) && !tcompat(right.ty, left.ty, 0))
1666 break;
1667 t = left.ty;
1668 if(t == tany)
1669 t = right.ty;
1670 if(t == tany)
1671 t = tint;
1672 if(left.ty == tany)
1673 left.ty = t;
1674 if(right.ty == tany)
1675 right.ty = t;
1676 n.ty = tint;
1677usedty(n.ty);
1678 return (1, allok);
1679 }
1680 nerror(n, "cannot compare "+etconv(left)+" to "+etconv(right));
1681 return (0, 0);
1682 Otype =>
1683 if(!typeok){
1684 nerror(n, expconv(n) + " is not a variable");
1685 return (0, 0);
1686 }
1687 n.ty = usetype(n.ty);
1688 * =>
1689 fatal("unknown op in typecheck: "+opconv(n.op));
1690 }
1691usedty(n.ty);
1692 return (1, allok);
1693}
1694
1695#
1696# n is syntactically a call, but n.left is not a fn
1697# check if it's the contructor for an adt
1698#
1699callcast(n: ref Node, kidsok, allok: int): (int, int)
1700{
1701 id: ref Decl;
1702
1703 left := n.left;
1704 right := n.right;
1705 id = nil;
1706 case left.op{
1707 Oname =>
1708 id = left.decl;
1709 Omdot =>
1710 if(left.right.op == Odot)
1711 id = left.right.right.decl;
1712 else
1713 id = left.right.decl;
1714 Odot =>
1715 id = left.right.decl;
1716 }
1717 if(id == nil || (id.store != Dtype && id.store != Dtag && id.ty.kind != Texception)){
1718 nerror(left, expconv(left)+" is not a function or type name");
1719 return (0, 0);
1720 }
1721 if(id.store == Dtag)
1722 return tagcast(n, left, right, id, kidsok, allok);
1723 t := left.ty;
1724 n.ty = t;
1725 if(!kidsok)
1726 return (1, 0);
1727
1728 if(t.kind == Tref)
1729 t = t.tof;
1730 tt := mktype(n.src.start, n.src.stop, Ttuple, nil, tuplefields(right));
1731 if(t.kind == Tadt && tcompat(t, tt, 1)){
1732 if(right == nil)
1733 *n = *n.left;
1734 return (1, allok);
1735 }
1736
1737 # try an exception with args
1738 tt = mktype(n.src.start, n.src.stop, Texception, nil, tuplefields(right));
1739 tt.cons = byte 1;
1740 if(t.kind == Texception && t.cons == byte 1 && tcompat(t, tt, 1)){
1741 if(right == nil)
1742 *n = *n.left;
1743 return (1, allok);
1744 }
1745
1746 # try a cast
1747 if(t.kind != Texception && right != nil && right.right == nil){ # Oseq but single expression
1748 right = right.left;
1749 n.op = Ocast;
1750 n.left = right;
1751 n.right = nil;
1752 n.ty = mkidtype(n.src, id.sym);
1753 return echeck(n, 0, 0, nil);
1754 }
1755
1756 nerror(left, "cannot make a "+expconv(left)+" from '("+subexpconv(right)+")'");
1757 return (0, 0);
1758}
1759
1760tagcast(n, left, right: ref Node, id: ref Decl, kidsok, allok: int): (int, int)
1761{
1762 left.ty = id.ty;
1763 if(left.op == Omdot)
1764 left.right.ty = id.ty;
1765 n.ty = id.ty;
1766 if(!kidsok)
1767 return (1, 0);
1768 id.ty.tof = usetype(id.ty.tof);
1769 if(right != nil)
1770 right.ty = id.ty.tof;
1771 tt := mktype(n.src.start, n.src.stop, Ttuple, nil, mkids(nosrc, nil, tint, tuplefields(right)));
1772 tt.ids.store = Dfield;
1773 if(tcompat(id.ty.tof, tt, 1))
1774 return (1, allok);
1775
1776 nerror(left, "cannot make a "+expconv(left)+" from '("+subexpconv(right)+")'");
1777 return (0, 0);
1778}
1779
1780valistype(n: ref Node): int
1781{
1782 case n.op{
1783 Oname =>
1784 if(n.decl.store == Dtype)
1785 return 1;
1786 Omdot =>
1787 return valistype(n.right);
1788 }
1789 return 0;
1790}
1791
1792islval(n: ref Node): int
1793{
1794 s := marklval(n);
1795 if(s == 1)
1796 return 1;
1797 if(s == 0)
1798 nerror(n, "cannot assign to "+expconv(n));
1799 else
1800 circlval(n, n);
1801 return 0;
1802}
1803
1804#
1805# check to see if n is an lval
1806#
1807marklval(n: ref Node): int
1808{
1809 if(n == nil)
1810 return 0;
1811 case n.op{
1812 Oname =>
1813 return storespace[n.decl.store] && n.ty.kind != Texception; #ZZZZ && n.decl.tagged == nil;
1814 Odot =>
1815 if(n.right.decl.store != Dfield)
1816 return 0;
1817 if(n.right.decl.cycle != byte 0 && n.right.decl.cyc == byte 0)
1818 return -1;
1819 if(n.left.ty.kind != Tref && marklval(n.left) == 0)
1820 nwarn(n, "assignment to "+etconv(n)+" ignored");
1821 return 1;
1822 Omdot =>
1823 if(n.right.decl.store == Dglobal)
1824 return 1;
1825 return 0;
1826 Oind =>
1827 for(id := n.ty.ids; id != nil; id = id.next)
1828 if(id.cycle != byte 0 && id.cyc == byte 0)
1829 return -1;
1830 return 1;
1831 Oslice =>
1832 if(n.right.right.op != Onothing || n.ty == tstring)
1833 return 0;
1834 return 1;
1835 Oinds =>
1836 #
1837 # make sure we don't change a string constant
1838 #
1839 case n.left.op{
1840 Oconst =>
1841 return 0;
1842 Oname =>
1843 return storespace[n.left.decl.store];
1844 Odot or
1845 Omdot =>
1846 if(n.left.right.decl != nil)
1847 return storespace[n.left.right.decl.store];
1848 }
1849 return 1;
1850 Oindex or
1851 Oindx =>
1852 return 1;
1853 Otuple =>
1854 for(nn := n.left; nn != nil; nn = nn.right){
1855 s := marklval(nn.left);
1856 if(s != 1)
1857 return s;
1858 }
1859 return 1;
1860 * =>
1861 return 0;
1862 }
1863 return 0;
1864}
1865
1866#
1867# n has a circular field assignment.
1868# find it and print an error message.
1869#
1870circlval(n, lval: ref Node): int
1871{
1872 if(n == nil)
1873 return 0;
1874 case n.op{
1875 Oname =>
1876 break;
1877 Odot =>
1878 if(oldcycles && n.right.decl.cycle != byte 0 && n.right.decl.cyc == byte 0){
1879 nerror(lval, "cannot assign to "+expconv(lval)+" because field '"+n.right.decl.sym.name
1880 +"' of "+expconv(n.left)+" could complete a cycle to "+expconv(n.left));
1881 return -1;
1882 }
1883 return 1;
1884 Oind =>
1885 for(id := n.ty.ids; id != nil; id = id.next){
1886 if(oldcycles && id.cycle != byte 0 && id.cyc == byte 0){
1887 nerror(lval, "cannot assign to "+expconv(lval)+" because field '"+id.sym.name
1888 +"' of "+expconv(n)+" could complete a cycle to "+expconv(n));
1889 return -1;
1890 }
1891 }
1892 return 1;
1893 Oslice =>
1894 if(n.right.right.op != Onothing || n.ty == tstring)
1895 return 0;
1896 return 1;
1897 Oindex or
1898 Oinds or
1899 Oindx =>
1900 return 1;
1901 Otuple =>
1902 for(nn := n.left; nn != nil; nn = nn.right){
1903 s := circlval(nn.left, lval);
1904 if(s != 1)
1905 return s;
1906 }
1907 return 1;
1908 * =>
1909 return 0;
1910 }
1911 return 0;
1912}
1913
1914mathchk(n: ref Node, realok: int): int
1915{
1916 lt := n.left.ty;
1917 rt := n.right.ty;
1918 if(rt != lt && !tequal(lt, rt)){
1919 nerror(n, "type clash in "+etconv(n.left)+" "+opconv(n.op)+" "+etconv(n.right));
1920 return 0;
1921 }
1922 n.ty = rt;
1923 case rt.kind{
1924 Tint or
1925 Tbig or
1926 Tbyte =>
1927 return 1;
1928 Tstring =>
1929 case n.op{
1930 Oadd or
1931 Oaddas or
1932 Ogt or
1933 Ogeq or
1934 Olt or
1935 Oleq =>
1936 return 1;
1937 }
1938 Treal or
1939 Tfix =>
1940 if(realok)
1941 return 1;
1942 }
1943 nerror(n, "cannot "+opconv(n.op)+" "+etconv(n.left)+" and "+etconv(n.right));
1944 return 0;
1945}
1946
1947shiftchk(n: ref Node): int
1948{
1949 right := n.right;
1950 left := n.left;
1951 n.ty = left.ty;
1952 case n.ty.kind{
1953 Tint or
1954 Tbyte or
1955 Tbig =>
1956 if(right.ty.kind != Tint){
1957 nerror(n, "shift "+etconv(right)+" is not an int");
1958 return 0;
1959 }
1960 return 1;
1961 }
1962 nerror(n, "cannot "+opconv(n.op)+" "+etconv(left)+" by "+etconv(right));
1963 return 0;
1964}
1965
1966#
1967# check for any tany's in t
1968#
1969specific(t: ref Type): int
1970{
1971 if(t == nil)
1972 return 0;
1973 case t.kind{
1974 Terror or
1975 Tnone or
1976 Tint or
1977 Tbig or
1978 Tstring or
1979 Tbyte or
1980 Treal or
1981 Tfn or
1982 Tadt or
1983 Tadtpick or
1984 Tmodule or
1985 Tfix =>
1986 return 1;
1987 Tany =>
1988 return 0;
1989 Tpoly =>
1990 return 1;
1991 Tref or
1992 Tlist or
1993 Tarray or
1994 Tchan =>
1995 return specific(t.tof);
1996 Ttuple or
1997 Texception =>
1998 for(d := t.ids; d != nil; d = d.next)
1999 if(!specific(d.ty))
2000 return 0;
2001 return 1;
2002 }
2003 fatal("unknown type in specific: "+typeconv(t));
2004 return 0;
2005}
2006
2007#
2008# infer the type of all variable in n from t
2009# n is the left-hand exp of a := exp
2010#
2011declasinfer(n: ref Node, t: ref Type): int
2012{
2013 if(t.kind == Texception){
2014 if(int t.cons)
2015 return 0;
2016 t = mkextuptype(t);
2017 }
2018 case n.op{
2019 Otuple =>
2020 if(t.kind != Ttuple && t.kind != Tadt && t.kind != Tadtpick)
2021 return 0;
2022 ok := 1;
2023 n.ty = t;
2024 n = n.left;
2025 ids := t.ids;
2026 if(t.kind == Tadtpick)
2027 ids = t.tof.ids.next;
2028 for(; n != nil && ids != nil; ids = ids.next){
2029 if(ids.store != Dfield)
2030 continue;
2031 ok &= declasinfer(n.left, ids.ty);
2032 n = n.right;
2033 }
2034 for(; ids != nil; ids = ids.next)
2035 if(ids.store == Dfield)
2036 break;
2037 if(n != nil || ids != nil)
2038 return 0;
2039 return ok;
2040 Oname =>
2041 topvartype(t, n.decl, 0, 0);
2042 if(n.decl == nildecl)
2043 return 1;
2044 n.decl.ty = t;
2045 n.ty = t;
2046 shareloc(n.decl);
2047 return 1;
2048 }
2049 fatal("unknown op in declasinfer: "+nodeconv(n));
2050 return 0;
2051}
2052
2053#
2054# an error occured in declaring n;
2055# set all decl identifiers to Dwundef
2056# so further errors are squashed.
2057#
2058declaserr(n: ref Node)
2059{
2060 case n.op{
2061 Otuple =>
2062 for(n = n.left; n != nil; n = n.right)
2063 declaserr(n.left);
2064 return;
2065 Oname =>
2066 if(n.decl != nildecl)
2067 n.decl.store = Dwundef;
2068 return;
2069 }
2070 fatal("unknown op in declaserr: "+nodeconv(n));
2071}
2072
2073argcompat(n: ref Node, f: ref Decl, a: ref Node): int
2074{
2075 for(; a != nil; a = a.right){
2076 if(f == nil){
2077 nerror(n, expconv(n.left)+": too many function arguments");
2078 return 0;
2079 }
2080 if(!tcompat(f.ty, a.left.ty, 0)){
2081 nerror(n, expconv(n.left)+": argument type mismatch: expected "+typeconv(f.ty)+" saw "+etconv(a.left));
2082 return 0;
2083 }
2084 if(a.left.ty == tany)
2085 a.left.ty = f.ty;
2086 f = f.next;
2087 }
2088 if(f != nil){
2089 nerror(n, expconv(n.left)+": too few function arguments");
2090 return 0;
2091 }
2092 return 1;
2093}
2094
2095argncompat(n: ref Node, f: ref Decl, a: ref Node): int
2096{
2097 for(; a != nil; a = a.right){
2098 if(f == nil){
2099 nerror(n, expconv(n.left)+": too many function arguments");
2100 return 0;
2101 }
2102 f = f.next;
2103 }
2104 if(f != nil){
2105 nerror(n, expconv(n.left)+": too few function arguments");
2106 return 0;
2107 }
2108 return 1;
2109}
2110
2111#
2112# fn is Odot(adt, methid)
2113# pass adt implicitly if needed
2114# if not, any side effect of adt will be ingored
2115#
2116passimplicit(fname, args: ref Node): ref Node
2117{
2118 t := fname.ty;
2119 n := fname.left;
2120 if(t.ids == nil || t.ids.implicit == byte 0){
2121 if(!isfnrefty(t) && hasside(n, 1))
2122 nwarn(fname, "result of expression "+expconv(n)+" ignored");
2123 return args;
2124 }
2125 if(n.op == Oname && n.decl.store == Dtype){
2126 nerror(n, expconv(n)+" is a type and cannot be a self argument");
2127 n = mkn(Onothing, nil, nil);
2128 n.src = fname.src;
2129 n.ty = t.ids.ty;
2130 }
2131 args = mkn(Oseq, n, args);
2132 args.src = n.src;
2133 return args;
2134}
2135
2136mem(t: ref Type, d: ref Decl): int
2137{
2138 for( ; d != nil; d = d.next)
2139 if(d.ty == t) # was if(d.ty == t || tequal(d.ty, t))
2140 return 1;
2141 return 0;
2142}
2143
2144memp(t: ref Type, f: ref Decl): int
2145{
2146 return mem(t, f.ty.polys) || mem(t, encpolys(f));
2147}
2148
2149passfns0(src: Src, fun: ref Decl, args0: ref Node, args: ref Node, a: ref Node, tp: ref Tpair, polys: ref Decl): (ref Node, ref Node)
2150{
2151 id, idt, idf: ref Decl;
2152 sym: ref Sym;
2153 tt: ref Type;
2154 na, mod: ref Node;
2155
2156 for(idt = polys; idt != nil; idt = idt.next){
2157 tt = valtmap(idt.ty, tp);
2158 if(tt.kind == Tpoly && fndec != nil && !memp(tt, fndec))
2159 error(src.start, "cannot determine the instantiated type of " + typeconv(tt));
2160 for(idf = idt.ty.ids; idf != nil; idf = idf.next){
2161 sym = idf.sym;
2162 (id, mod) = fnlookup(sym, tt);
2163 while(id != nil && id.link != nil)
2164 id = id.link;
2165 if(id == nil) # error flagged already
2166 continue;
2167 id.refs++;
2168 id.inline = byte -1;
2169 if(tt.kind == Tmodule){ # mod an actual parameter
2170 for(;;){
2171 if(args0 != nil && tequal(tt, args0.left.ty)){
2172 mod = args0.left;
2173 break;
2174 }
2175 if(args0 != nil)
2176 args0 = args0.right;
2177 }
2178 }
2179 if(mod == nil && (dot := lmodule(id)) != nil && !isimpmod(dot.sym))
2180 error(src.start, "cannot use " + id.sym.name + " without importing " + id.dot.sym.name + " from a variable");
2181
2182 n := mkn(Ofnptr, mod, mkdeclname(src, id));
2183 n.src = src;
2184 n.decl = fun;
2185 if(tt.kind == Tpoly)
2186 n.flags = byte FNPTRA;
2187 else
2188 n.flags = byte 0;
2189 na = mkn(Oseq, n, nil);
2190 if(a == nil)
2191 args = na;
2192 else
2193 a.right = na;
2194
2195 n = mkn(Ofnptr, mod, mkdeclname(src, id));
2196 n.src = src;
2197 n.decl = fun;
2198 if(tt.kind == Tpoly)
2199 n.flags = byte (FNPTRA|FNPTR2);
2200 else
2201 n.flags = byte FNPTR2;
2202 a = na.right = mkn(Oseq, n, nil);
2203 }
2204 if(args0 != nil)
2205 args0 = args0.right;
2206 }
2207 return (args, a);
2208}
2209
2210passfns(src: Src, fun: ref Decl, left: ref Node, args: ref Node, adtt: ref Type, tp: ref Tpair): ref Node
2211{
2212 a, args0: ref Node;
2213
2214 a = nil;
2215 args0 = args;
2216 if(args != nil)
2217 for(a = args; a.right != nil; a = a.right)
2218 ;
2219 if(ispoly(fun))
2220 polys := fun.ty.polys;
2221 else
2222 polys = left.ty.tof.polys;
2223 (args, a) = passfns0(src, fun, args0, args, a, tp, polys);
2224 if(adtt != nil){
2225 if(ispoly(fun))
2226 polys = encpolys(fun);
2227 else
2228 polys = nil;
2229 (args, a) = passfns0(src, fun, args0, args, a, adtt.tmap, polys);
2230 }
2231 return args;
2232}
2233
2234#
2235# check the types for a function with a variable number of arguments
2236# last typed argument must be a constant string, and must use the
2237# print format for describing arguments.
2238#
2239mkvarargs(n, args: ref Node): ref Type
2240{
2241 last: ref Decl;
2242
2243 nt := copytypeids(n.ty);
2244 n.ty = nt;
2245 f := n.ty.ids;
2246 last = nil;
2247 if(f == nil){
2248 nerror(n, expconv(n)+"'s type is illegal");
2249 return nt;
2250 }
2251 s := args;
2252 for(a := args; a != nil; a = a.right){
2253 if(f == nil)
2254 break;
2255 if(!tcompat(f.ty, a.left.ty, 0)){
2256 nerror(n, expconv(n)+": argument type mismatch: expected "+typeconv(f.ty)+" saw "+etconv(a.left));
2257 return nt;
2258 }
2259 if(a.left.ty == tany)
2260 a.left.ty = f.ty;
2261 last = f;
2262 f = f.next;
2263 s = a;
2264 }
2265 if(f != nil){
2266 nerror(n, expconv(n)+": too few function arguments");
2267 return nt;
2268 }
2269 s.left = fold(s.left);
2270 s = s.left;
2271 if(s.ty != tstring || s.op != Oconst){
2272 nerror(args, expconv(n)+": format argument "+etconv(s)+" is not a string constant");
2273 return nt;
2274 }
2275 fmtcheck(n, s, a);
2276 va := tuplefields(a);
2277 if(last == nil)
2278 nt.ids = va;
2279 else
2280 last.next = va;
2281 return nt;
2282}
2283
2284#
2285# check that a print style format string matches it's arguments
2286#
2287fmtcheck(f, fmtarg, va: ref Node)
2288{
2289 fmt := fmtarg.decl.sym;
2290 s := fmt.name;
2291 ns := 0;
2292 while(ns < len s){
2293 c := s[ns++];
2294 if(c != '%')
2295 continue;
2296
2297 verb := -1;
2298 n1 := 0;
2299 n2 := 0;
2300 dot := 0;
2301 flag := 0;
2302 flags := "";
2303 fmtstart := ns - 1;
2304 while(ns < len s && verb < 0){
2305 c = s[ns++];
2306 case c{
2307 * =>
2308 nerror(f, expconv(f)+": invalid character "+s[ns-1:ns]+" in format '"+s[fmtstart:ns]+"'");
2309 return;
2310 '.' =>
2311 if(dot){
2312 nerror(f, expconv(f)+": invalid format '"+s[fmtstart:ns]+"'");
2313 return;
2314 }
2315 n1 = 1;
2316 dot = 1;
2317 continue;
2318 '*' =>
2319 if(!n1)
2320 n1 = 1;
2321 else if(!n2 && dot)
2322 n2 = 1;
2323 else{
2324 nerror(f, expconv(f)+": invalid format '"+s[fmtstart:ns]+"'");
2325 return;
2326 }
2327 if(va == nil){
2328 nerror(f, expconv(f)+": too few arguments for format '"+s[fmtstart:ns]+"'");
2329 return;
2330 }
2331 if(va.left.ty.kind != Tint){
2332 nerror(f, expconv(f)+": format '"+s[fmtstart:ns]+"' incompatible with argument "+etconv(va.left));
2333 return;
2334 }
2335 va = va.right;
2336 '0' to '9' =>
2337 while(ns < len s && s[ns] >= '0' && s[ns] <= '9')
2338 ns++;
2339 if(!n1)
2340 n1 = 1;
2341 else if(!n2 && dot)
2342 n2 = 1;
2343 else{
2344 nerror(f, expconv(f)+": invalid format '"+s[fmtstart:ns]+"'");
2345 return;
2346 }
2347 '+' or
2348 '-' or
2349 '#' or
2350 ',' or
2351 'b' or
2352 'u' =>
2353 for(i := 0; i < flag; i++){
2354 if(flags[i] == c){
2355 nerror(f, expconv(f)+": duplicate flag "+s[ns-1:ns]+" in format '"+s[fmtstart:ns]+"'");
2356 return;
2357 }
2358 }
2359 flags[flag++] = c;
2360 '%' or
2361 'r' =>
2362 verb = Tnone;
2363 'H' =>
2364 verb = Tany;
2365 'c' =>
2366 verb = Tint;
2367 'd' or
2368 'o' or
2369 'x' or
2370 'X' =>
2371 verb = Tint;
2372 for(i := 0; i < flag; i++){
2373 if(flags[i] == 'b'){
2374 verb = Tbig;
2375 break;
2376 }
2377 }
2378 'e' or
2379 'f' or
2380 'g' or
2381 'E' or
2382 'G' =>
2383 verb = Treal;
2384 's' or
2385 'q' =>
2386 verb = Tstring;
2387 }
2388 }
2389 if(verb != Tnone){
2390 if(verb < 0){
2391 nerror(f, expconv(f)+": incomplete format '"+s[fmtstart:ns]+"'");
2392 return;
2393 }
2394 if(va == nil){
2395 nerror(f, expconv(f)+": too few arguments for format '"+s[fmtstart:ns]+"'");
2396 return;
2397 }
2398 ty := va.left.ty;
2399 if(ty.kind == Texception)
2400 ty = mkextuptype(ty);
2401 case verb{
2402 Tint =>
2403 case ty.kind{
2404 Tstring or
2405 Tarray or
2406 Tref or
2407 Tchan or
2408 Tlist or
2409 Tmodule =>
2410 if(c == 'x' || c == 'X')
2411 verb = ty.kind;
2412 }
2413 Tany =>
2414 if(tattr[ty.kind].isptr)
2415 verb = ty.kind;
2416 }
2417 if(verb != ty.kind){
2418 nerror(f, expconv(f)+": format '"+s[fmtstart:ns]+"' incompatible with argument "+etconv(va.left));
2419 return;
2420 }
2421 va = va.right;
2422 }
2423 }
2424 if(va != nil)
2425 nerror(f, expconv(f)+": more arguments than formats");
2426}
2427
2428tuplefields(n: ref Node): ref Decl
2429{
2430 h, last: ref Decl;
2431
2432 for(; n != nil; n = n.right){
2433 d := mkdecl(n.left.src, Dfield, n.left.ty);
2434 if(h == nil)
2435 h = d;
2436 else
2437 last.next = d;
2438 last = d;
2439 }
2440 return h;
2441}
2442
2443#
2444# make explicit indices for every element in an array initializer
2445# return the maximum index
2446# sort the indices and check for duplicates
2447#
2448assignindices(ar: ref Node): int
2449{
2450 wild, off, q: ref Node;
2451
2452 amax := 16r7fffffff;
2453 size := dupn(0, nosrc, ar.left);
2454 if(size.ty == tint){
2455 size = fold(size);
2456 if(size.op == Oconst)
2457 amax = int size.c.val;
2458 }
2459
2460 inits := ar.right;
2461 max := -1;
2462 last := -1;
2463 t := inits.left.ty;
2464 wild = nil;
2465 nlab := 0;
2466 ok := 1;
2467 for(n := inits; n != nil; n = n.right){
2468 if(!tcompat(t, n.left.ty, 0)){
2469 t = tparent(t, n.left.ty);
2470 if(!tcompat(t, n.left.ty, 0)){
2471 nerror(n.left, "inconsistent types "+typeconv(t)+" and "+typeconv(n.left.ty)+" in array initializer");
2472 return -1;
2473 }
2474 else
2475 inits.left.ty = t;
2476 }
2477 if(t == tany)
2478 t = n.left.ty;
2479
2480 #
2481 # make up an index if there isn't one
2482 #
2483 if(n.left.left == nil)
2484 n.left.left = mkn(Oseq, mkconst(n.left.right.src, big(last + 1)), nil);
2485
2486 for(q = n.left.left; q != nil; q = q.right){
2487 off = q.left;
2488 if(off.ty != tint){
2489 nerror(off, "array index "+etconv(off)+" is not an int");
2490 ok = 0;
2491 continue;
2492 }
2493 off = fold(off);
2494 case off.op{
2495 Owild =>
2496 if(wild != nil)
2497 nerror(off, "array index * duplicated on line "+lineconv(wild.src.start));
2498 wild = off;
2499 continue;
2500 Orange =>
2501 if(off.left.op != Oconst || off.right.op != Oconst){
2502 nerror(off, "range "+expconv(off)+" is not constant");
2503 off = nil;
2504 }else if(off.left.c.val < big 0 || off.right.c.val >= big amax){
2505 nerror(off, "array index "+expconv(off)+" out of bounds");
2506 off = nil;
2507 }else
2508 last = int off.right.c.val;
2509 Oconst =>
2510 last = int off.c.val;
2511 if(off.c.val < big 0 || off.c.val >= big amax){
2512 nerror(off, "array index "+expconv(off)+" out of bounds");
2513 off = nil;
2514 }
2515 Onothing =>
2516 # get here from a syntax error
2517 off = nil;
2518 * =>
2519 nerror(off, "array index "+expconv(off)+" is not constant");
2520 off = nil;
2521 }
2522
2523 nlab++;
2524 if(off == nil){
2525 off = mkconst(n.left.right.src, big(last));
2526 ok = 0;
2527 }
2528 if(last > max)
2529 max = last;
2530 q.left = off;
2531 }
2532 }
2533
2534 #
2535 # fix up types of nil elements
2536 #
2537 for(n = inits; n != nil; n = n.right)
2538 if(n.left.ty == tany)
2539 n.left.ty = t;
2540
2541 if(!ok)
2542 return -1;
2543
2544 c := checklabels(inits, tint, nlab, "array index");
2545 t = mktype(inits.src.start, inits.src.stop, Tainit, nil, nil);
2546 inits.ty = t;
2547 t.cse = c;
2548
2549 return max + 1;
2550}
2551
2552#
2553# check the labels of a case statment
2554#
2555casecheck(cn: ref Node, ret: ref Type)
2556{
2557 wild: ref Node;
2558
2559 (rok, nil) := echeck(cn.left, 0, 0, nil);
2560 cn.right = scheck(cn.right, ret, Sother);
2561 if(!rok)
2562 return;
2563 arg := cn.left;
2564
2565 t := arg.ty;
2566 if(t != tint && t != tbig && t != tstring){
2567 nerror(cn, "case argument "+etconv(arg)+" is not an int or big or string");
2568 return;
2569 }
2570
2571 wild = nil;
2572 nlab := 0;
2573 ok := 1;
2574 for(n := cn.right; n != nil; n = n.right){
2575 q := n.left.left;
2576 if(n.left.right.right == nil)
2577 nwarn(q, "no body for case qualifier "+expconv(q));
2578 for(; q != nil; q = q.right){
2579 left := fold(q.left);
2580 q.left = left;
2581 case left.op{
2582 Owild =>
2583 if(wild != nil)
2584 nerror(left, "case qualifier * duplicated on line "+lineconv(wild.src.start));
2585 wild = left;
2586 Orange =>
2587 if(left.ty != t)
2588 nerror(left, "case qualifier "+etconv(left)+" clashes with "+etconv(arg));
2589 else if(left.left.op != Oconst || left.right.op != Oconst){
2590 nerror(left, "case range "+expconv(left)+" is not constant");
2591 ok = 0;
2592 }
2593 nlab++;
2594 * =>
2595 if(left.ty != t){
2596 nerror(left, "case qualifier "+etconv(left)+" clashes with "+etconv(arg));
2597 ok = 0;
2598 }else if(left.op != Oconst){
2599 nerror(left, "case qualifier "+expconv(left)+" is not constant");
2600 ok = 0;
2601 }
2602 nlab++;
2603 }
2604 }
2605 }
2606
2607 if(!ok)
2608 return;
2609
2610 c := checklabels(cn.right, t, nlab, "case qualifier");
2611 op := Tcase;
2612 if(t == tbig)
2613 op = Tcasel;
2614 else if(t == tstring)
2615 op = Tcasec;
2616 t = mktype(cn.src.start, cn.src.stop, op, nil, nil);
2617 cn.ty = t;
2618 t.cse = c;
2619}
2620
2621#
2622# check the labels and bodies of a pick statment
2623#
2624pickcheck(n: ref Node, ret: ref Type)
2625{
2626 qs, q, w: ref Node;
2627
2628 arg := n.left.right;
2629 (nil, allok) := echeck(arg, 0, 0, nil);
2630 if(!allok)
2631 return;
2632 t := arg.ty;
2633 if(t.kind == Tref)
2634 t = t.tof;
2635 if(arg.ty.kind != Tref || t.kind != Tadt || t.tags == nil){
2636 nerror(arg, "pick argument "+etconv(arg)+" is not a ref adt with pick tags");
2637 return;
2638 }
2639 argty := usetype(mktype(arg.ty.src.start, arg.ty.src.stop, Tref, t, nil));
2640
2641 arg = n.left.left;
2642 pushscope(nil, Sother);
2643 dasdecl(arg);
2644 arg.decl.ty = argty;
2645 arg.ty = argty;
2646
2647 tags := array[t.decl.tag] of ref Node;
2648 w = nil;
2649 ok := 1;
2650 nlab := 0;
2651 for(qs = n.right; qs != nil; qs = qs.right){
2652 qt : ref Node = nil;
2653 for(q = qs.left.left; q != nil; q = q.right){
2654 left := q.left;
2655 case left.op{
2656 Owild =>
2657 # left.ty = tnone;
2658 left.ty = t;
2659 if(w != nil)
2660 nerror(left, "pick qualifier * duplicated on line "+lineconv(w.src.start));
2661 w = left;
2662 Oname =>
2663 id := namedot(t.tags, left.decl.sym);
2664 if(id == nil){
2665 nerror(left, "pick qualifier "+expconv(left)+" is not a member of "+etconv(arg));
2666 ok = 0;
2667 continue;
2668 }
2669
2670 left.decl = id;
2671 left.ty = id.ty;
2672
2673 if(tags[id.tag] != nil){
2674 nerror(left, "pick qualifier "+expconv(left)+" duplicated on line "+lineconv(tags[id.tag].src.start));
2675 ok = 0;
2676 }
2677 tags[id.tag] = left;
2678 nlab++;
2679 * =>
2680 fatal("pickcheck can't handle "+nodeconv(q));
2681 }
2682
2683 if(qt == nil)
2684 qt = left;
2685 else if(!tequal(qt.ty, left.ty))
2686 nerror(left, "type clash in pick qualifiers "+etconv(qt)+" and "+etconv(left));
2687 }
2688
2689 argty.tof = t;
2690 if(qt != nil)
2691 argty.tof = qt.ty;
2692 qs.left.right = scheck(qs.left.right, ret, Sother);
2693 if(qs.left.right == nil)
2694 nwarn(qs.left.left, "no body for pick qualifier "+expconv(qs.left.left));
2695 }
2696 argty.tof = t;
2697 for(qs = n.right; qs != nil; qs = qs.right)
2698 for(q = qs.left.left; q != nil; q = q.right)
2699 q.left = fold(q.left);
2700
2701 d := popscope();
2702 d.refs++;
2703 if(d.next != nil)
2704 fatal("pickcheck: installing more than one id");
2705 fndecls = appdecls(fndecls, d);
2706
2707 if(!ok)
2708 return;
2709
2710 c := checklabels(n.right, tint, nlab, "pick qualifier");
2711 t = mktype(n.src.start, n.src.stop, Tcase, nil, nil);
2712 n.ty = t;
2713 t.cse = c;
2714}
2715
2716exccheck(en: ref Node, ret: ref Type)
2717{
2718 ed: ref Decl;
2719 wild: ref Node;
2720 qt: ref Type;
2721
2722 pushscope(nil, Sother);
2723 if(en.left == nil)
2724 en.left = mkdeclname(en.src, mkids(en.src, enter(".ex"+string nexc++, 0), texception, nil));
2725 oinexcept := inexcept;
2726 inexcept = en.left;
2727 dasdecl(en.left);
2728 en.left.ty = en.left.decl.ty = texception;
2729 ed = en.left.decl;
2730 # en.right = scheck(en.right, ret, Sother);
2731 t := tstring;
2732 wild = nil;
2733 nlab := 0;
2734 ok := 1;
2735 for(n := en.right; n != nil; n = n.right){
2736 qt = nil;
2737 for(q := n.left.left; q != nil; q = q.right){
2738 left := q.left;
2739 case left.op{
2740 Owild =>
2741 left.ty = texception;
2742 if(wild != nil)
2743 nerror(left, "exception qualifier * duplicated on line "+lineconv(wild.src.start));
2744 wild = left;
2745 Orange =>
2746 left.ty = tnone;
2747 nerror(left, "exception qualifier "+expconv(left)+" is illegal");
2748 ok = 0;
2749 * =>
2750 (rok, nil) := echeck(left, 0, 0, nil);
2751 if(!rok){
2752 ok = 0;
2753 break;
2754 }
2755 left = q.left = fold(left);
2756 if(left.ty != t && left.ty.kind != Texception){
2757 nerror(left, "exception qualifier "+etconv(left)+" is not a string or exception");
2758 ok = 0;
2759 }else if(left.op != Oconst){
2760 nerror(left, "exception qualifier "+expconv(left)+" is not constant");
2761 ok = 0;
2762 }
2763 else if(left.ty != t)
2764 left.ty = mkextype(left.ty);
2765 nlab++;
2766 }
2767
2768 if(qt == nil)
2769 qt = left.ty;
2770 else if(!tequal(qt, left.ty))
2771 qt = texception;
2772 }
2773
2774 if(qt != nil)
2775 ed.ty = qt;
2776 n.left.right = scheck(n.left.right, ret, Sother);
2777 if(n.left.right.right == nil)
2778 nwarn(n.left.left, "no body for exception qualifier " + expconv(n.left.left));
2779 }
2780 ed.ty = texception;
2781 inexcept = oinexcept;
2782 if(!ok)
2783 return;
2784 c := checklabels(en.right, texception, nlab, "exception qualifier");
2785 t = mktype(en.src.start, en.src.stop, Texcept, nil, nil);
2786 en.ty = t;
2787 t.cse = c;
2788 ed = popscope();
2789 fndecls = appdecls(fndecls, ed);
2790}
2791
2792#
2793# check array and case labels for validity
2794#
2795checklabels(inits: ref Node, ctype: ref Type, nlab: int, title: string): ref Case
2796{
2797 n, q, wild: ref Node;
2798
2799 labs := array[nlab] of Label;
2800 i := 0;
2801 wild = nil;
2802 for(n = inits; n != nil; n = n.right){
2803 for(q = n.left.left; q != nil; q = q.right){
2804 case q.left.op{
2805 Oconst =>
2806 labs[i].start = q.left;
2807 labs[i].stop = q.left;
2808 labs[i++].node = n.left;
2809 Orange =>
2810 labs[i].start = q.left.left;
2811 labs[i].stop = q.left.right;
2812 labs[i++].node = n.left;
2813 Owild =>
2814 wild = n.left;
2815 * =>
2816 fatal("bogus index in checklabels");
2817 }
2818 }
2819 }
2820
2821 if(i != nlab)
2822 fatal("bad label count: "+string nlab+" then "+string i);
2823
2824 casesort(ctype, array[nlab] of Label, labs, 0, nlab);
2825 for(i = 0; i < nlab; i++){
2826 p := labs[i].stop;
2827 if(casecmp(ctype, labs[i].start, p) > 0)
2828 nerror(labs[i].start, "unmatchable "+title+" "+expconv(labs[i].node));
2829 for(e := i + 1; e < nlab; e++){
2830 if(casecmp(ctype, labs[e].start, p) <= 0)
2831 nerror(labs[e].start, title+" '"+eprintlist(labs[e].node.left, " or ")
2832 +"' overlaps with '"+eprintlist(labs[e-1].node.left, " or ")+"' on line "
2833 +lineconv(p.src.start));
2834
2835 #
2836 # check for merging case labels
2837 #
2838 if(ctype != tint
2839 || labs[e].start.c.val != p.c.val+big 1
2840 || labs[e].node != labs[i].node)
2841 break;
2842 p = labs[e].stop;
2843 }
2844 if(e != i + 1){
2845 labs[i].stop = p;
2846 labs[i+1:] = labs[e:nlab];
2847 nlab -= e - (i + 1);
2848 }
2849 }
2850
2851 c := ref Case;
2852 c.nlab = nlab;
2853 c.nsnd = 0;
2854 c.labs = labs;
2855 c.wild = wild;
2856
2857 return c;
2858}
2859
2860symcmp(a: ref Sym, b: ref Sym): int
2861{
2862 if(a.name < b.name)
2863 return -1;
2864 if(a.name > b.name)
2865 return 1;
2866 return 0;
2867}
2868
2869matchcmp(na: ref Node, nb: ref Node): int
2870{
2871 a := na.decl.sym;
2872 b := nb.decl.sym;
2873 la := len a.name;
2874 lb := len b.name;
2875 sa := la > 0 && a.name[la-1] == '*';
2876 sb := lb > 0 && b.name[lb-1] == '*';
2877 if(sa){
2878 if(sb){
2879 if(la == lb)
2880 return symcmp(a, b);
2881 return lb-la;
2882 }
2883 else
2884 return 1;
2885 }
2886 else{
2887 if(sb)
2888 return -1;
2889 else{
2890 if(na.ty == tstring){
2891 if(nb.ty == tstring)
2892 return symcmp(a, b);
2893 else
2894 return 1;
2895 }
2896 else{
2897 if(nb.ty == tstring)
2898 return -1;
2899 else
2900 return symcmp(a, b);
2901 }
2902 }
2903 }
2904}
2905
2906casecmp(ty: ref Type, a, b: ref Node): int
2907{
2908 if(ty == tint || ty == tbig){
2909 if(a.c.val < b.c.val)
2910 return -1;
2911 if(a.c.val > b.c.val)
2912 return 1;
2913 return 0;
2914 }
2915 if(ty == texception)
2916 return matchcmp(a, b);
2917 return symcmp(a.decl.sym, b.decl.sym);
2918}
2919
2920casesort(t: ref Type, aux, labs: array of Label, start, stop: int)
2921{
2922 n := stop - start;
2923 if(n <= 1)
2924 return;
2925 top := mid := start + n / 2;
2926
2927 casesort(t, aux, labs, start, top);
2928 casesort(t, aux, labs, mid, stop);
2929
2930 #
2931 # merge together two sorted label arrays, yielding a sorted array
2932 #
2933 n = 0;
2934 base := start;
2935 while(base < top && mid < stop){
2936 if(casecmp(t, labs[base].start, labs[mid].start) <= 0)
2937 aux[n++] = labs[base++];
2938 else
2939 aux[n++] = labs[mid++];
2940 }
2941 if(base < top)
2942 aux[n:] = labs[base:top];
2943 else if(mid < stop)
2944 aux[n:] = labs[mid:stop];
2945 labs[start:] = aux[:stop-start];
2946}
2947
2948#
2949# binary search for the label corresponding to a given value
2950#
2951findlab(ty: ref Type, v: ref Node, labs: array of Label, nlab: int): int
2952{
2953 if(nlab <= 1)
2954 return 0;
2955 m : int;
2956 l := 1;
2957 r := nlab - 1;
2958 while(l <= r){
2959 m = (r + l) / 2;
2960 if(casecmp(ty, labs[m].start, v) <= 0)
2961 l = m + 1;
2962 else
2963 r = m - 1;
2964 }
2965 m = l - 1;
2966 if(casecmp(ty, labs[m].start, v) > 0
2967 || casecmp(ty, labs[m].stop, v) < 0)
2968 fatal("findlab out of range");
2969 return m;
2970}
2971
2972altcheck(an: ref Node, ret: ref Type)
2973{
2974 n, q, left, op, wild: ref Node;
2975
2976 an.left = scheck(an.left, ret, Sother);
2977
2978 ok := 1;
2979 nsnd := 0;
2980 nrcv := 0;
2981 wild = nil;
2982 for(n = an.left; n != nil; n = n.right){
2983 q = n.left.right.left;
2984 if(n.left.right.right == nil)
2985 nwarn(q, "no body for alt guard "+expconv(q));
2986 for(; q != nil; q = q.right){
2987 left = q.left;
2988 case left.op{
2989 Owild =>
2990 if(wild != nil)
2991 nerror(left, "alt guard * duplicated on line "+lineconv(wild.src.start));
2992 wild = left;
2993 Orange =>
2994 nerror(left, "alt guard "+expconv(left)+" is illegal");
2995 ok = 0;
2996 * =>
2997 op = hascomm(left);
2998 if(op == nil){
2999 nerror(left, "alt guard "+expconv(left)+" has no communication");
3000 ok = 0;
3001 break;
3002 }
3003 if(op.op == Osnd)
3004 nsnd++;
3005 else
3006 nrcv++;
3007 }
3008 }
3009 }
3010
3011 if(!ok)
3012 return;
3013
3014 c := ref Case;
3015 c.nlab = nsnd + nrcv;
3016 c.nsnd = nsnd;
3017 c.wild = wild;
3018
3019 an.ty = mktalt(c);
3020}
3021
3022hascomm(n: ref Node): ref Node
3023{
3024 if(n == nil)
3025 return nil;
3026 if(n.op == Osnd || n.op == Orcv)
3027 return n;
3028 r := hascomm(n.left);
3029 if(r != nil)
3030 return r;
3031 return hascomm(n.right);
3032}
3033
3034raisescheck(t: ref Type)
3035{
3036 if(t.kind != Tfn)
3037 return;
3038 n := t.eraises;
3039 for(nn := n.left; nn != nil; nn = nn.right){
3040 (ok, nil) := echeck(nn.left, 0, 0, nil);
3041 if(ok && nn.left.ty.kind != Texception)
3042 nerror(n, expconv(nn.left) + ": illegal raises expression");
3043 }
3044}
3045
3046Elist: adt{
3047 d: ref Decl;
3048 nxt: cyclic ref Elist;
3049};
3050
3051emerge(el1: ref Elist, el2: ref Elist): ref Elist
3052{
3053 f: int;
3054 el, nxt: ref Elist;
3055
3056 for( ; el1 != nil; el1 = nxt){
3057 f = 0;
3058 for(el = el2; el != nil; el = el.nxt){
3059 if(el1.d == el.d){
3060 f = 1;
3061 break;
3062 }
3063 }
3064 nxt = el1.nxt;
3065 if(!f){
3066 el1.nxt = el2;
3067 el2 = el1;
3068 }
3069 }
3070 return el2;
3071}
3072
3073equals(n: ref Node): ref Elist
3074{
3075 q, nn: ref Node;
3076 e, el: ref Elist;
3077
3078 el = nil;
3079 for(q = n.left.left; q != nil; q = q.right){
3080 nn = q.left;
3081 if(nn.op == Owild)
3082 return nil;
3083 if(nn.ty.kind != Texception)
3084 continue;
3085 e = ref Elist(nn.decl, el);
3086 el = e;
3087 }
3088 return el;
3089}
3090
3091caught(d: ref Decl, n: ref Node): int
3092{
3093 q, nn: ref Node;
3094
3095 for(n = n.right; n != nil; n = n.right){
3096 for(q = n.left.left; q != nil; q = q.right){
3097 nn = q.left;
3098 if(nn.op == Owild)
3099 return 1;
3100 if(nn.ty.kind != Texception)
3101 continue;
3102 if(d == nn.decl)
3103 return 1;
3104 }
3105 }
3106 return 0;
3107}
3108
3109raisecheck(n: ref Node, ql: ref Elist): ref Elist
3110{
3111 exc: int;
3112 e: ref Node;
3113 el, nel, nxt: ref Elist;
3114
3115 if(n == nil)
3116 return nil;
3117 el = nil;
3118 for(; n != nil; n = n.right){
3119 case(n.op){
3120 Oscope =>
3121 return raisecheck(n.right, ql);
3122 Olabel or
3123 Odo =>
3124 return raisecheck(n.right, ql);
3125 Oif or
3126 Ofor =>
3127 return emerge(raisecheck(n.right.left, ql),
3128 raisecheck(n.right.right, ql));
3129 Oalt or
3130 Ocase or
3131 Opick or
3132 Oexcept =>
3133 exc = n.op == Oexcept;
3134 for(n = n.right; n != nil; n = n.right){
3135 ql = nil;
3136 if(exc)
3137 ql = equals(n);
3138 el = emerge(raisecheck(n.left.right, ql), el);
3139 }
3140 return el;
3141 Oseq =>
3142 el = emerge(raisecheck(n.left, ql), el);
3143 break;
3144 Oexstmt =>
3145 el = raisecheck(n.left, ql);
3146 nel = nil;
3147 for( ; el != nil; el = nxt){
3148 nxt = el.nxt;
3149 if(!caught(el.d, n.right)){
3150 el.nxt = nel;
3151 nel = el;
3152 }
3153 }
3154 return emerge(nel, raisecheck(n.right, ql));
3155 Oraise =>
3156 e = n.left;
3157 if(e.ty != nil && e.ty.kind == Texception){
3158 if(e.ty.cons == byte 0)
3159 return ql;
3160 if(e.op == Ocall)
3161 e = e.left;
3162 if(e.op == Omdot)
3163 e = e.right;
3164 if(e.op != Oname)
3165 fatal("exception " + nodeconv(e) + " not a name");
3166 el = ref Elist(e.decl, nil);
3167 return el;
3168 }
3169 return nil;
3170 * =>
3171 return nil;
3172 }
3173 }
3174 return el;
3175}
3176
3177checkraises(n: ref Node)
3178{
3179 f: int;
3180 d: ref Decl;
3181 e, el: ref Elist;
3182 es, nn: ref Node;
3183
3184 el = raisecheck(n.right, nil);
3185 es = n.ty.eraises;
3186 if(es != nil){
3187 for(nn = es.left; nn != nil; nn = nn.right){
3188 d = nn.left.decl;
3189 f = 0;
3190 for(e = el; e != nil; e = e.nxt){
3191 if(d == e.d){
3192 f = 1;
3193 e.d = nil;
3194 break;
3195 }
3196 }
3197 if(!f)
3198 nwarn(n, "function " + expconv(n.left) + " does not raise " + d.sym.name + " but declared");
3199 }
3200 }
3201 for(e = el; e != nil; e = e.nxt)
3202 if(e.d != nil)
3203 nwarn(n, "function " + expconv(n.left) + " raises " + e.d.sym.name + " but not declared");
3204}
3205
3206# sort all globals in modules now that we've finished with 'last' pointers
3207# and before any code generation
3208#
3209gsort(n: ref Node)
3210{
3211 for(;;){
3212 if(n == nil)
3213 return;
3214 if(n.op != Oseq)
3215 break;
3216 gsort(n.left);
3217 n = n.right;
3218 }
3219 if(n.op == Omoddecl && int (n.ty.ok & OKverify)){
3220 n.ty.ids = namesort(n.ty.ids);
3221 sizeids(n.ty.ids, 0);
3222 }
3223}
limbo/compiler/types.b+4234−0
@@ -0,0 +1,4234 @@
1
2kindname := array [Tend] of
3{
4 Tnone => "no type",
5 Tadt => "adt",
6 Tadtpick => "adt",
7 Tarray => "array",
8 Tbig => "big",
9 Tbyte => "byte",
10 Tchan => "chan",
11 Treal => "real",
12 Tfn => "fn",
13 Tint => "int",
14 Tlist => "list",
15 Tmodule => "module",
16 Tref => "ref",
17 Tstring => "string",
18 Ttuple => "tuple",
19 Texception => "exception",
20 Tfix => "fixed point",
21 Tpoly => "polymorphic",
22
23 Tainit => "array initializers",
24 Talt => "alt channels",
25 Tany => "polymorphic type",
26 Tarrow => "->",
27 Tcase => "case int labels",
28 Tcasel => "case big labels",
29 Tcasec => "case string labels",
30 Tdot => ".",
31 Terror => "type error",
32 Tgoto => "goto labels",
33 Tid => "id",
34 Tiface => "module interface",
35 Texcept => "exception handler table",
36 Tinst => "instantiated type",
37};
38
39tattr = array[Tend] of
40{
41 # isptr refable conable big vis
42 Tnone => Tattr(0, 0, 0, 0, 0),
43 Tadt => Tattr(0, 1, 1, 1, 1),
44 Tadtpick => Tattr(0, 1, 0, 1, 1),
45 Tarray => Tattr(1, 0, 0, 0, 1),
46 Tbig => Tattr(0, 0, 1, 1, 1),
47 Tbyte => Tattr(0, 0, 1, 0, 1),
48 Tchan => Tattr(1, 0, 0, 0, 1),
49 Treal => Tattr(0, 0, 1, 1, 1),
50 Tfn => Tattr(0, 1, 0, 0, 1),
51 Tint => Tattr(0, 0, 1, 0, 1),
52 Tlist => Tattr(1, 0, 0, 0, 1),
53 Tmodule => Tattr(1, 0, 0, 0, 1),
54 Tref => Tattr(1, 0, 0, 0, 1),
55 Tstring => Tattr(1, 0, 1, 0, 1),
56 Ttuple => Tattr(0, 1, 1, 1, 1),
57 Texception => Tattr(0, 0, 0, 1, 1),
58 Tfix => Tattr(0, 0, 1, 0, 1),
59 Tpoly => Tattr(1, 0, 0, 0, 1),
60
61 Tainit => Tattr(0, 0, 0, 1, 0),
62 Talt => Tattr(0, 0, 0, 1, 0),
63 Tany => Tattr(1, 0, 0, 0, 0),
64 Tarrow => Tattr(0, 0, 0, 0, 1),
65 Tcase => Tattr(0, 0, 0, 1, 0),
66 Tcasel => Tattr(0, 0, 0, 1, 0),
67 Tcasec => Tattr(0, 0, 0, 1, 0),
68 Tdot => Tattr(0, 0, 0, 0, 1),
69 Terror => Tattr(0, 1, 1, 0, 0),
70 Tgoto => Tattr(0, 0, 0, 1, 0),
71 Tid => Tattr(0, 0, 0, 0, 1),
72 Tiface => Tattr(0, 0, 0, 1, 0),
73 Texcept => Tattr(0, 0, 0, 1, 0),
74 Tinst => Tattr(0, 1, 1, 1, 1),

4160 more lines aren’t shown here.