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 @@
1+Arg: 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+
12+Arg.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+
19+Arg.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+
39+Arg.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 @@
1+asmentry(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+
8+asmmod(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+
26+asmpath()
27+{
28+ bout.puts("\tsource\t\"" + srcpath() + "\"\n");
29+}
30+
31+asmdesc(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+
43+asmvar(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+
52+asmldt(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+
61+asminitializer(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+
198+asmexc(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+
230+asmstring(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+
250+asminst(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+
3+breaks: array of ref Inst;
4+conts: array of ref Inst;
5+labels: array of ref Decl;
6+bcscps: array of ref Node;
7+labdep: int;
8+nocont: ref Inst;
9+nlabel: int;
10+
11+scp: int;
12+scps:= array[MaxScope] of ref Node;
13+
14+curfn: ref Decl;
15+
16+pushscp(n : ref Node)
17+{
18+ if (scp >= MaxScope)
19+ fatal("scope too deep");
20+ scps[scp++] = n;
21+}
22+
23+popscp()
24+{
25+ scp--;
26+}
27+
28+curscp() : ref Node
29+{
30+ if (scp == 0)
31+ return nil;
32+ return scps[scp-1];
33+}
34+
35+zeroscopes(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+
48+zeroallscopes(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+
87+excs: ref Except;
88+
89+installexc(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+
110+inlist(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+
118+excdesc()
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+
148+reve(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+
161+ckinline0(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+
178+ckinline(d: ref Decl)
179+{
180+ d.inline = byte ckinline0(d.init.right, d);
181+}
182+
183+modcom(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+
348+fncom(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+#
439+scom(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+#
657+bccom(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+
679+dogoto(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+
719+fillrange(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+
737+nconstqual(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+
748+casecom(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+
888+altcom(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+
1088+excom(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+#
1136+rewritecomm(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+#
1176+declmerge(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+#
1221+recdeclsort(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+#
1245+declsort(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+
1254+nilsrc : Src;
1255+
1256+zcom1(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+
1306+zcom0(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+
1314+zcom(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+
1343+ret(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+
1352+trcom(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+
1358+return 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+
2+storename := 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+
18+storeart := 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+
34+storespace := 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+
50+impdecl: ref Decl;
51+impdecls: ref Dlist;
52+scopes := array[MaxScope] of ref Decl;
53+tails := array[MaxScope] of ref Decl;
54+scopekind := array[MaxScope] of byte;
55+scopenode := array[MaxScope] of ref Node;
56+iota: ref Decl;
57+zdecl: Decl;
58+
59+popscopes()
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+
88+declstart()
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+
109+redecl(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+
118+checkrefs(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+
181+vardecl(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+
189+vardecled(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+
208+condecl(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+
215+condecled(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+
226+exdecl(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+
239+exdecled(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+
254+importdecl(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+
261+importdecled(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+
272+mkscope(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+
280+fndecl(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+
287+fndecled(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+#
320+fnchk(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+
384+globalas(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+
417+needsstore(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+#
431+vars(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+#
449+recdasdecl(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+
483+recmark(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+
496+dasdecl(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+#
516+gdasdecl(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+
530+undefed(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+
546+nested() : 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+
554+decltozero(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+
564+pushscope(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+
575+curscope(): 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+#
587+popscope(): 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+#
615+repushids(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+#
645+popids(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+
656+installids(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+
684+lookup(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+
698+mkids(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+
710+mkdecl(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+
720+dupdecl(old: ref Decl): ref Decl
721+{
722+ d := ref *old;
723+ d.next = nil;
724+ return d;
725+}
726+
727+dupdecls(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+
743+appdecls(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+
753+revids(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+
765+idoffsets(id: ref Decl, offset: int, al: int): int
766+{
767+ algn := 1;
768+ for(; id != nil; id = id.next){
769+ if(storespace[id.store]){
770+usedty(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+
793+idindices(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+
805+declconv(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+
812+storeconv(d: ref Decl): string
813+{
814+ return storeart[d.store] + storename[d.store];
815+}
816+
817+dotconv(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+#
835+namemerge(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+#
858+recnamesort(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+#
875+namesort(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+
883+printdecls(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+
889+mergepolydecs(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+
928+adjfnptrs(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+
958+addptrs(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+
980+addfnptrs(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+
1003+rmfnptrs(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+
1031+local(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+
1039+lmodule(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+
1047+outerpolys(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+
1062+encpolys(d: ref Decl): ref Decl
1063+{
1064+ if((d = d.dot) == nil)
1065+ return nil;
1066+ return d.ty.polys;
1067+}
1068+
1069+fnlookup(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+
1104+isimpmod(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+
1114+dequal(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+
1124+tzero(t: ref Type): int
1125+{
1126+ return t.kind == Texception || tmustzero(t);
1127+}
1128+
1129+isptr(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 ?
1135+shareloc(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+
1173+freeloc(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+
2+NAMELEN: con 28;
3+
4+cache: array of byte;
5+ncached: int;
6+ndatum: int;
7+startoff: int;
8+lastoff: int;
9+lastkind: int;
10+
11+discon(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+
31+disword(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+
39+disdata(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+
49+dismod(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+
84+dispath()
85+{
86+ sp := array of byte srcpath();
87+ bout.write(sp, len sp);
88+ bout.putb(byte 0);
89+}
90+
91+disentry(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+
102+disdesc(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+
115+disvar(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+
134+disldt(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+
170+disdatum(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+
328+disexc(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+
366+disbyte(off: int, v: byte)
367+{
368+ disflush(DEFB, off, 1);
369+ cache[ncached++] = v;
370+ ndatum++;
371+}
372+
373+disbytes(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+
382+disint(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+
392+disbig(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+
408+disreal(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+
416+disstring(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+
425+disflush(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+
446+dismode := 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+
462+disregmode := 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+
478+MAXCON: con 4;
479+MAXADDR: con 2*MAXCON;
480+MAXINST: con 3*MAXADDR+2;
481+NIBUF: con 1024;
482+
483+ibuf: array of byte;
484+nibuf: int;
485+
486+disinst(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+
518+disaddr(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+
542+disbcon(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 @@
1+movetab:= 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+
80+chantab := 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+
104+opind := 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+
116+disoptab := 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+
156+isbyteinst := 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+
178+instname := 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 @@
1+maxstack: int; # max size of a stack frame called
2+
3+precasttab := array[Tend] of array of ref Type;
4+
5+optabinit()
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+#
70+vcom(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+
80+simplify(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+
92+isfix(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+#
106+rewrite(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+#
492+sumark(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+
619+mktn(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+#
636+tupblk0(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+#
667+tupblk(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
686+esrc(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+#
699+ecom(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+#
1296+eacom(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+#
1355+slicelcom(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+#
1392+indsascom(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+
1455+callcom(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+#
1611+arraycom(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+#
1708+arraydefault(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+
1750+tupcom(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+
1790+tuplcom(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+
1847+tuplrcom(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+#
1874+bcom(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+
1952+andand(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+
1961+oror(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+#
1975+recvacom(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+#
2056+pickdupcom(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+#
2153+tupaliased(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+#
2170+tupsaliased(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+#
2187+globalconst(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+
2200+globalBconst(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+
2213+globalbconst(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+
2226+globalfconst(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+
2246+globalsconst(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+#
2265+globalztup(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+
2282+subst(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+
2298+inline(n: ref Node): ref Node
2299+{
2300+ e, tn: ref Node;
2301+ t: ref Type;
2302+ d: ref Decl;
2303+
2304+if(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()");
2326+if(debug['z']) sys->print("inline2: %s\n", nodeconv(e));
2327+ return e;
2328+}
2329+
2330+fpcall(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+
6+include "disoptab.m";
7+
8+addrmode := 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+
24+wtemp: ref Decl;
25+bigtemp: ref Decl;
26+ntemp: int;
27+retnode: ref Node;
28+nilnode: ref Node;
29+
30+blockstack: array of int;
31+blockdep: int;
32+nblocks: int;
33+ntoz: ref Node;
34+
35+#znode: Node;
36+
37+genstart()
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+#
71+pushblock(): 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+
82+repushblock(b: int)
83+{
84+ blockstack[blockdep++] = blocks;
85+ blocks = b;
86+}
87+
88+popblock()
89+{
90+ blocks = blockstack[blockdep -= 1];
91+}
92+
93+tinit()
94+{
95+ wtemp = nil;
96+ bigtemp = nil;
97+}
98+
99+tdecls(): 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+
114+talloc(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+
180+tfree(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+
218+tfreelater(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+
237+tfreenow()
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+#
255+tacquire(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+
268+trelease(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+
280+mkinst(): 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+
294+nextinst(): 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+#
307+retalloc(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+
319+genrawop(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+
341+genop(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+
368+genbra(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+
392+genchan(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+
435+genmove(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+
483+patch(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+
493+getpc(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+#
509+reach(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+
522+foldbranch(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+#
582+genaddr(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+
632+sameaddr(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+
641+resolvedesc(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+
671+resolvemod(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+#
704+resolveldts(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+#
736+resolvepcs(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+#
838+rewritesrcreg(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+#
866+rewritedestreg(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+
887+instconv(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+
932+addrconv(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+
962+genstore(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+
976+genfixop(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+
997+genfixcastop(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+
182+XMAGIC: con 819248; # Normal magic
183+SMAGIC: con 923426; # Signed module
184+
185+AMP: con 16r00; # Src/Dst op addressing
186+AFP: con 16r01;
187+AIMM: con 16r2;
188+AXXX: con 16r03;
189+AIND: con 16r04;
190+AMASK: con 16r07;
191+AOFF: con 16r08;
192+AVAL: con 16r10;
193+
194+ARM: con 16rC0; # Middle op addressing
195+AXNON: con 16r00;
196+AXIMM: con 16r40;
197+AXINF: con 16r80;
198+AXINM: con 16rC0;
199+
200+DEFZ: con 0;
201+DEFB: con 1; # Byte
202+DEFW: con 2; # Word
203+DEFS: con 3; # Utf-string
204+DEFF: con 4; # Real value
205+DEFA: con 5; # Array
206+DIND: con 6; # Set index
207+DAPOP: con 7; # Restore address register
208+DEFL: con 8; # BIG
209+
210+DADEPTH: con 4; # Array address stack size
211+
212+REGLINK: con 0;
213+REGFRAME: con 1;
214+REGMOD: con 2;
215+REGTYP: con 3;
216+REGRET: con 4;
217+NREG: con 5;
218+
219+IBY2WD: con 4;
220+IBY2FT: con 8;
221+IBY2LG: con 8;
222+
223+MUSTCOMPILE: con 1<<0;
224+DONTCOMPILE: con 1<<1;
225+SHAREMP: con 1<<2;
226+DYNMOD: con 1<<3;
227+HASLDT0: con 1<<4;
228+HASEXCEPT: con 1<<5;
229+HASLDT: con 1<<6;
230+
231+DMAX: 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+
238+DBYTE: con 4;
239+SRC: con 3;
240+DST: 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 @@
1+Leof: con -1;
2+Linestart: con 0;
3+
4+Mlower,
5+Mupper,
6+Munder,
7+Mdigit,
8+Msign,
9+Mexp,
10+Mhex,
11+Mradix: con byte 1 << iota;
12+Malpha: con Mupper|Mlower|Munder;
13+
14+HashSize: con 1024;
15+
16+Keywd: adt
17+{
18+ name: string;
19+ token: int;
20+};
21+
22+#
23+# internals
24+#
25+savec: int;
26+files: array of ref File; # files making up the module, sorted by absolute line
27+nfiles: int;
28+lastfile := 0; # index of last file looked up
29+incpath := array[MaxIncPath] of string;
30+symbols := array[HashSize] of ref Sym;
31+strings := array[HashSize] of ref Sym;
32+map := array[256] of byte;
33+bins := array [MaxInclude] of ref Iobuf;
34+bin: ref Iobuf;
35+linestack := array[MaxInclude] of (int, int);
36+lineno: int;
37+linepos: int;
38+bstack: int;
39+lasttok: int;
40+lastyylval: YYSTYPE;
41+dowarn: int;
42+maxerr: int;
43+dosym: int;
44+toterrors: int;
45+fabort: int;
46+srcdir: string;
47+outfile: string;
48+stderr: ref Sys->FD;
49+dontinline: int;
50+
51+escmap := 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+};
67+unescmap := 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+
84+keywords := 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+
134+tokwords := 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+
166+lexinit()
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+
192+cmap(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+
201+lexstart(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+
214+getc(): 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+#
235+ungetc(c: int)
236+{
237+ if(c > 0)
238+ linepos--;
239+ savec = c;
240+}
241+
242+addinclude(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+
253+addfile(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+#
269+includef(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+#
299+popinclude()
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+#
314+fline(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+#
337+lexcom(): 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+
380+curline(): Line
381+{
382+ return (lineno << PosBits) | (linepos & PosMask);
383+}
384+
385+lineconv(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+
400+posconv(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+
410+srcconv(src: Src): string
411+{
412+ s := posconv(src.start);
413+ s[len s] = ',';
414+ s += posconv(src.stop);
415+ return s;
416+}
417+
418+lexid(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+
439+maxfast := 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+
450+strtoi(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+
495+digit(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+
520+strtodb(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+#
586+lexnum(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+
598+done: 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+
702+escchar(): 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+
735+lexstring()
736+{
737+ s := "";
738+ i := 0;
739+Loop:
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+
763+lexrawstring()
764+{
765+ s := "";
766+ i := 0;
767+ startlno := lineno;
768+Loop:
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+
790+lex(): 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+
979+YYLEX.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+
988+toksp(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+
1013+enterstring(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+
1041+stringcat(s, t: ref Sym): ref Sym
1042+{
1043+ return enterstring(s.name+t.name);
1044+}
1045+
1046+enter(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+
1075+stringpr(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+
1105+warn(line: Line, msg: string)
1106+{
1107+ if(errors || !dowarn)
1108+ return;
1109+ fprint(stderr, "%s: warning: %s\n", lineconv(line), msg);
1110+}
1111+
1112+nwarn(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+
1119+error(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+
1129+nerror(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+
1139+YYLEX.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+
1152+yyerror(msg: string)
1153+{
1154+ yyctxt.error(msg);
1155+}
1156+
1157+fatal(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+
1170+hex(v, n: int): string
1171+{
1172+ return sprint("%.*ux", n, v);
1173+}
1174+
1175+bhex(v: big, n: int): string
1176+{
1177+ return sprint("%.*bux", n, v);
1178+}
limbo/compiler/limbo.b+3104−0
@@ -0,0 +1,3104 @@
1+implement Limbo;
2+
3+#line 2 "limbo.y"
4+include "limbo.m";
5+include "draw.m";
6+
7+Limbo: 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+ };
24+Landeq: con 57346;
25+Loreq: con 57347;
26+Lxoreq: con 57348;
27+Llsheq: con 57349;
28+Lrsheq: con 57350;
29+Laddeq: con 57351;
30+Lsubeq: con 57352;
31+Lmuleq: con 57353;
32+Ldiveq: con 57354;
33+Lmodeq: con 57355;
34+Lexpeq: con 57356;
35+Ldeclas: con 57357;
36+Lload: con 57358;
37+Loror: con 57359;
38+Landand: con 57360;
39+Lcons: con 57361;
40+Leq: con 57362;
41+Lneq: con 57363;
42+Lleq: con 57364;
43+Lgeq: con 57365;
44+Llsh: con 57366;
45+Lrsh: con 57367;
46+Lexp: con 57368;
47+Lcomm: con 57369;
48+Linc: con 57370;
49+Ldec: con 57371;
50+Lof: con 57372;
51+Lref: con 57373;
52+Lif: con 57374;
53+Lelse: con 57375;
54+Lfn: con 57376;
55+Lexcept: con 57377;
56+Lraises: con 57378;
57+Lmdot: con 57379;
58+Lto: con 57380;
59+Lor: con 57381;
60+Lrconst: con 57382;
61+Lconst: con 57383;
62+Lid: con 57384;
63+Ltid: con 57385;
64+Lsconst: con 57386;
65+Llabs: con 57387;
66+Lnil: con 57388;
67+Llen: con 57389;
68+Lhd: con 57390;
69+Ltl: con 57391;
70+Ltagof: con 57392;
71+Limplement: con 57393;
72+Limport: con 57394;
73+Linclude: con 57395;
74+Lcon: con 57396;
75+Ltype: con 57397;
76+Lmodule: con 57398;
77+Lcyclic: con 57399;
78+Ladt: con 57400;
79+Larray: con 57401;
80+Llist: con 57402;
81+Lchan: con 57403;
82+Lself: con 57404;
83+Ldo: con 57405;
84+Lwhile: con 57406;
85+Lfor: con 57407;
86+Lbreak: con 57408;
87+Lalt: con 57409;
88+Lcase: con 57410;
89+Lpick: con 57411;
90+Lcont: con 57412;
91+Lreturn: con 57413;
92+Lexit: con 57414;
93+Lspawn: con 57415;
94+Lraise: con 57416;
95+Lfix: con 57417;
96+Ldynamic: 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
172+YYEOFCODE: con 1;
173+YYERRCODE: con 2;
174+YYMAXDEPTH: con 200;
175+
176+#line 1632 "limbo.y"
177+
178+
179+include "ipints.m";
180+include "crypt.m";
181+
182+sys: Sys;
183+ print, fprint, sprint: import sys;
184+
185+bufio: Bufio;
186+ Iobuf: import bufio;
187+
188+str: String;
189+
190+crypt:Crypt;
191+ md5: import crypt;
192+
193+math: Math;
194+ import_real, export_real, isnan: import math;
195+
196+yyctxt: ref YYLEX;
197+
198+canonnan: real;
199+
200+debug = array[256] of {* => 0};
201+
202+noline = -1;
203+nosrc = Src(-1, -1);
204+
205+infile: string;
206+
207+# front end
208+include "arg.m";
209+include "lex.b";
210+include "types.b";
211+include "nodes.b";
212+include "decls.b";
213+
214+include "typecheck.b";
215+
216+# back end
217+include "gen.b";
218+include "ecom.b";
219+include "asm.b";
220+include "dis.b";
221+include "sbl.b";
222+include "stubs.b";
223+include "com.b";
224+include "optim.b";
225+
226+init(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+
398+usage()
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+
404+mkfileext(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+
413+translate(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+
476+pwd(): 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+
487+cleanname(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+
518+srcpath(): string
519+{
520+ srcp := cleanname(infile);
521+ # sys->print("srcpath: %s\n", srcp);
522+ return srcp;
523+}
524+yyexca := 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+};
726+YYNPROD: con 284;
727+YYPRIVATE: con 57344;
728+yytoknames: array of string;
729+yystates: array of string;
730+yydebug: con 0;
731+YYLAST: con 2727;
732+yyact := 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+};
1007+yypact := 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,
1011+1507, 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,
1014+1548,1548,1548,1548,1548, 530, 520, 523,1548, 376,
1015+1548,-1000,1507, 583,-1000,-1000,-1000, 594,2217,2162,
1016+2107, 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,
1021+1507,1507,1507,1507,1507, 635,1507,1507,1507,1507,
1022+1507,1507,1507,1507,1507,1507,1507,1507,1507,1507,
1023+1507,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,
1032+2667,2667,2667,1507,2667, 581, 581, 581, 581, 591,
1033+ 591, 545, 545, 669, 669, 669, 669, 866, 866,1624,
1034+1848,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,
1039+1121,-1000,-1000, 5, 191,-1000, 299, 562,-1000, 424,
1040+-1000,2277, 424,-1000,-1000,-1000,2667,-1000,-1000,1507,
1041+1396,2273, 678, 424, 494, 216,-1000, 189, -41, 492,
1042+2667,-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,
1048+1507, 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,
1069+1548,-1000,-1000,-1000,-1000,
1070+};
1071+yypgo := 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+};
1081+yyr1 := 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+};
1112+yyr2 := 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+};
1143+yychk := 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+};
1207+yydef := 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+};
1271+yytok1 := 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+};
1286+yytok2 := 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+};
1296+yytok3 := array[] of {
1297+ 0
1298+};
1299+
1300+YYSys: 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+
1310+yysys: YYSys;
1311+yystderr: ref YYSys->FD;
1312+
1313+YYFLAG: con -1000;
1314+
1315+# parser for yacc output
1316+
1317+yytokname(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+
1324+yystatname(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+
1331+yylex1(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+
1358+YYS: adt
1359+{
1360+ yyv: YYSTYPE;
1361+ yys: int;
1362+};
1363+
1364+yyparse(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+
1381+yystack:
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+
1505+1=>
1506+#line 153 "limbo.y"
1507+{
1508+ impmods = yys[yypt-1].yyv.ids;
1509+ }
1510+2=>
1511+#line 156 "limbo.y"
1512+{
1513+ tree = rotater(yys[yypt-0].yyv.node);
1514+ }
1515+3=>
1516+#line 160 "limbo.y"
1517+{
1518+ impmods = nil;
1519+ tree = rotater(yys[yypt-0].yyv.node);
1520+ }
1521+4=>
1522+yyval.node = yys[yyp+1].yyv.node;
1523+5=>
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+ }
1533+6=>
1534+#line 179 "limbo.y"
1535+{
1536+ yyval.node = nil;
1537+ }
1538+7=>
1539+yyval.node = yys[yyp+1].yyv.node;
1540+8=>
1541+yyval.node = yys[yyp+1].yyv.node;
1542+9=>
1543+yyval.node = yys[yyp+1].yyv.node;
1544+10=>
1545+yyval.node = yys[yyp+1].yyv.node;
1546+11=>
1547+#line 187 "limbo.y"
1548+{
1549+ yyval.node = mkbin(Oas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1550+ }
1551+12=>
1552+#line 191 "limbo.y"
1553+{
1554+ yyval.node = mkbin(Oas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1555+ }
1556+13=>
1557+#line 195 "limbo.y"
1558+{
1559+ yyval.node = mkbin(Odas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1560+ }
1561+14=>
1562+#line 199 "limbo.y"
1563+{
1564+ yyval.node = mkbin(Odas, yys[yypt-3].yyv.node, yys[yypt-1].yyv.node);
1565+ }
1566+15=>
1567+#line 203 "limbo.y"
1568+{
1569+ yyerror("illegal declaration");
1570+ yyval.node = nil;
1571+ }
1572+16=>
1573+#line 208 "limbo.y"
1574+{
1575+ yyerror("illegal declaration");
1576+ yyval.node = nil;
1577+ }
1578+17=>
1579+yyval.node = yys[yyp+1].yyv.node;
1580+18=>
1581+#line 216 "limbo.y"
1582+{
1583+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
1584+ }
1585+19=>
1586+#line 222 "limbo.y"
1587+{
1588+ includef(yys[yypt-1].yyv.tok.v.idval);
1589+ yyval.node = nil;
1590+ }
1591+20=>
1592+#line 227 "limbo.y"
1593+{
1594+ yyval.node = typedecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.ty);
1595+ }
1596+21=>
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+ }
1603+22=>
1604+#line 237 "limbo.y"
1605+{
1606+ yyval.node = vardecl(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty);
1607+ }
1608+23=>
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+ }
1613+24=>
1614+#line 245 "limbo.y"
1615+{
1616+ yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1617+ }
1618+25=>
1619+yyval.node = yys[yyp+1].yyv.node;
1620+26=>
1621+#line 252 "limbo.y"
1622+{
1623+ yyval.node = exdecl(yys[yypt-3].yyv.ids, nil);
1624+ }
1625+27=>
1626+#line 256 "limbo.y"
1627+{
1628+ yyval.node = exdecl(yys[yypt-6].yyv.ids, revids(yys[yypt-2].yyv.ids));
1629+ }
1630+28=>
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+ }
1636+29=>
1637+#line 269 "limbo.y"
1638+{
1639+ yyval.node = nil;
1640+ }
1641+30=>
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+ }
1651+31=>
1652+#line 282 "limbo.y"
1653+{
1654+ yyval.node = nil;
1655+ }
1656+32=>
1657+#line 288 "limbo.y"
1658+{
1659+ yyval.node = fielddecl(Dglobal, typeids(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty));
1660+ }
1661+33=>
1662+yyval.node = yys[yyp+1].yyv.node;
1663+34=>
1664+#line 293 "limbo.y"
1665+{
1666+ yyval.node = typedecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.ty);
1667+ }
1668+35=>
1669+#line 297 "limbo.y"
1670+{
1671+ yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1672+ }
1673+36=>
1674+yyval.node = yys[yyp+1].yyv.node;
1675+37=>
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+ }
1683+38=>
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+ }
1691+39=>
1692+#line 320 "limbo.y"
1693+{
1694+ yyval.node = nil;
1695+ }
1696+40=>
1697+#line 324 "limbo.y"
1698+{
1699+ yyval.node = yys[yypt-1].yyv.node;
1700+ }
1701+41=>
1702+#line 330 "limbo.y"
1703+{
1704+ yyval.node = nil;
1705+ }
1706+42=>
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+ }
1716+43=>
1717+#line 343 "limbo.y"
1718+{
1719+ yyval.node = nil;
1720+ }
1721+44=>
1722+yyval.node = yys[yyp+1].yyv.node;
1723+45=>
1724+yyval.node = yys[yyp+1].yyv.node;
1725+46=>
1726+#line 351 "limbo.y"
1727+{
1728+ yyval.node = condecl(yys[yypt-4].yyv.ids, yys[yypt-1].yyv.node);
1729+ }
1730+47=>
1731+#line 357 "limbo.y"
1732+{
1733+ yyval.node = nil;
1734+ }
1735+48=>
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+ }
1745+49=>
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+ }
1752+50=>
1753+#line 378 "limbo.y"
1754+{
1755+ yyval.node = fielddecl(Dfield, typeids(yys[yypt-3].yyv.ids, yys[yypt-1].yyv.ty));
1756+ }
1757+51=>
1758+#line 384 "limbo.y"
1759+{
1760+ yyval.node = yys[yypt-1].yyv.node;
1761+ }
1762+52=>
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+ }
1768+53=>
1769+#line 395 "limbo.y"
1770+{
1771+ yyval.node = nil;
1772+ }
1773+54=>
1774+#line 399 "limbo.y"
1775+{
1776+ yyval.node = nil;
1777+ }
1778+55=>
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+ }
1784+56=>
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+ }
1791+57=>
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+ }
1797+58=>
1798+#line 423 "limbo.y"
1799+{
1800+ yyval.ids = revids(yys[yypt-0].yyv.ids);
1801+ }
1802+59=>
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+ }
1807+60=>
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+ }
1812+61=>
1813+#line 439 "limbo.y"
1814+{
1815+ yyval.ids = revids(yys[yypt-0].yyv.ids);
1816+ }
1817+62=>
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+ }
1822+63=>
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+ }
1827+64=>
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+ }
1833+65=>
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+ }
1839+66=>
1840+#line 467 "limbo.y"
1841+{
1842+ yyval.types = addtype(yys[yypt-0].yyv.ty, nil);
1843+ }
1844+67=>
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+ }
1850+68=>
1851+#line 476 "limbo.y"
1852+{
1853+ yyval.types = addtype(yys[yypt-0].yyv.ty, yys[yypt-2].yyv.types);
1854+ }
1855+69=>
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+ }
1861+70=>
1862+#line 487 "limbo.y"
1863+{
1864+ yyval.ty = mkidtype(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
1865+ }
1866+71=>
1867+#line 491 "limbo.y"
1868+{
1869+ yyval.ty = yys[yypt-0].yyv.ty;
1870+ }
1871+72=>
1872+#line 495 "limbo.y"
1873+{
1874+ yyval.ty = yys[yypt-0].yyv.ty;
1875+ }
1876+73=>
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+ }
1881+74=>
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+ }
1887+75=>
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+ }
1892+76=>
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+ }
1897+77=>
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+ }
1905+78=>
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+ }
1910+79=>
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+ }
1915+80=>
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+ }
1923+81=>
1924+yyval.ty = yys[yyp+1].yyv.ty;
1925+82=>
1926+#line 551 "limbo.y"
1927+{
1928+ yyval.ty = mkidtype(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
1929+ }
1930+83=>
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+ }
1935+84=>
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+ }
1940+85=>
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+ }
1946+86=>
1947+#line 572 "limbo.y"
1948+{
1949+ yyval.ids = mkids(yys[yypt-0].yyv.ty.src, nil, yys[yypt-0].yyv.ty, nil);
1950+ }
1951+87=>
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+ }
1956+88=>
1957+#line 582 "limbo.y"
1958+{
1959+ yyval.ids = nil;
1960+ }
1961+89=>
1962+#line 586 "limbo.y"
1963+{
1964+ yyval.ids = polydecl(yys[yypt-1].yyv.ids);
1965+ }
1966+90=>
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+ }
1971+91=>
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+ }
1977+92=>
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+ }
1983+93=>
1984+#line 608 "limbo.y"
1985+{
1986+ yyval.ty = yys[yypt-0].yyv.ty;
1987+ }
1988+94=>
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+ }
1995+95=>
1996+#line 620 "limbo.y"
1997+{
1998+ yyval.ty = yys[yypt-0].yyv.ty;
1999+ }
2000+96=>
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+ }
2006+97=>
2007+#line 631 "limbo.y"
2008+{
2009+ yyval.ids = nil;
2010+ }
2011+98=>
2012+yyval.ids = yys[yyp+1].yyv.ids;
2013+99=>
2014+yyval.ids = yys[yyp+1].yyv.ids;
2015+100=>
2016+#line 639 "limbo.y"
2017+{
2018+ yyval.ids = appdecls(yys[yypt-2].yyv.ids, yys[yypt-0].yyv.ids);
2019+ }
2020+101=>
2021+#line 645 "limbo.y"
2022+{
2023+ yyval.ids = typeids(yys[yypt-2].yyv.ids, yys[yypt-0].yyv.ty);
2024+ }
2025+102=>
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+ }
2032+103=>
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+ }
2039+104=>
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+ }
2046+105=>
2047+#line 669 "limbo.y"
2048+{
2049+ yyval.ids = revids(yys[yypt-0].yyv.ids);
2050+ }
2051+106=>
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+ }
2057+107=>
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+ }
2063+108=>
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+ }
2069+109=>
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+ }
2075+110=>
2076+#line 697 "limbo.y"
2077+{
2078+ yyval.ty = yys[yypt-0].yyv.ty;
2079+ }
2080+111=>
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+ }
2085+112=>
2086+#line 705 "limbo.y"
2087+{
2088+ yyval.ty = yys[yypt-0].yyv.ty;
2089+ }
2090+113=>
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+ }
2095+114=>
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+ }
2120+115=>
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+ }
2127+116=>
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+ }
2134+117=>
2135+#line 753 "limbo.y"
2136+{
2137+ yyval.node = nil;
2138+ }
2139+118=>
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+ }
2151+119=>
2152+#line 770 "limbo.y"
2153+{
2154+ yyval.node = mkn(Onothing, nil, nil);
2155+ }
2156+120=>
2157+#line 774 "limbo.y"
2158+{
2159+ yyval.node = mkn(Onothing, nil, nil);
2160+ }
2161+121=>
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+ }
2170+122=>
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+ }
2179+123=>
2180+#line 798 "limbo.y"
2181+{
2182+ yyval.node = nil;
2183+ }
2184+124=>
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+ }
2194+125=>
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+ }
2202+128=>
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+ }
2209+129=>
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+ }
2216+130=>
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+ }
2223+131=>
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+ }
2233+132=>
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+ }
2241+133=>
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+ }
2249+134=>
2250+#line 865 "limbo.y"
2251+{
2252+ yyval.node = yys[yypt-1].yyv.node;
2253+ }
2254+135=>
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+ }
2261+136=>
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+ }
2268+137=>
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+ }
2279+138=>
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+ }
2287+139=>
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+ }
2295+140=>
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+ }
2302+141=>
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+ }
2309+142=>
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+ }
2319+143=>
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+ }
2326+144=>
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+ }
2333+145=>
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+ }
2340+146=>
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+ }
2347+147=>
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+ }
2355+148=>
2356+#line 957 "limbo.y"
2357+{
2358+ yyval.node = mkn(Oexit, nil, nil);
2359+ yyval.node.src = yys[yypt-1].yyv.tok.src;
2360+ }
2361+149=>
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+ }
2371+150=>
2372+#line 977 "limbo.y"
2373+{
2374+ yyval.ids = nil;
2375+ }
2376+151=>
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+ }
2383+152=>
2384+#line 989 "limbo.y"
2385+{
2386+ yyval.ids = nil;
2387+ }
2388+153=>
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+ }
2393+154=>
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+ }
2399+155=>
2400+#line 1006 "limbo.y"
2401+{
2402+ yyval.node = mkunary(Oseq, mkscope(mkunary(Olabel, rotater(yys[yypt-1].yyv.node))));
2403+ }
2404+156=>
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+ }
2410+157=>
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+ }
2416+158=>
2417+#line 1024 "limbo.y"
2418+{
2419+ yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2420+ }
2421+159=>
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+ }
2427+160=>
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+ }
2433+161=>
2434+#line 1042 "limbo.y"
2435+{
2436+ yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2437+ }
2438+162=>
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+ }
2444+163=>
2445+yyval.node = yys[yyp+1].yyv.node;
2446+164=>
2447+#line 1054 "limbo.y"
2448+{
2449+ yyval.node = mkbin(Orange, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2450+ }
2451+165=>
2452+#line 1058 "limbo.y"
2453+{
2454+ yyval.node = mkn(Owild, nil, nil);
2455+ yyval.node.src = yys[yypt-0].yyv.tok.src;
2456+ }
2457+166=>
2458+#line 1063 "limbo.y"
2459+{
2460+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2461+ }
2462+167=>
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+ }
2469+168=>
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+ }
2475+169=>
2476+#line 1082 "limbo.y"
2477+{
2478+ yyval.node = mkunary(Oseq, mkunary(Olabel, rotater(yys[yypt-1].yyv.node)));
2479+ }
2480+170=>
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+ }
2486+171=>
2487+#line 1093 "limbo.y"
2488+{
2489+ yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2490+ }
2491+172=>
2492+#line 1097 "limbo.y"
2493+{
2494+ yyval.node = mkn(Owild, nil, nil);
2495+ yyval.node.src = yys[yypt-0].yyv.tok.src;
2496+ }
2497+173=>
2498+#line 1102 "limbo.y"
2499+{
2500+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2501+ }
2502+174=>
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+ }
2509+175=>
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+ }
2516+176=>
2517+yyval.node = yys[yyp+1].yyv.node;
2518+177=>
2519+yyval.node = yys[yyp+1].yyv.node;
2520+178=>
2521+#line 1124 "limbo.y"
2522+{
2523+ yyval.node = mkbin(Oas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2524+ }
2525+179=>
2526+#line 1128 "limbo.y"
2527+{
2528+ yyval.node = mkbin(Oandas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2529+ }
2530+180=>
2531+#line 1132 "limbo.y"
2532+{
2533+ yyval.node = mkbin(Ooras, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2534+ }
2535+181=>
2536+#line 1136 "limbo.y"
2537+{
2538+ yyval.node = mkbin(Oxoras, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2539+ }
2540+182=>
2541+#line 1140 "limbo.y"
2542+{
2543+ yyval.node = mkbin(Olshas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2544+ }
2545+183=>
2546+#line 1144 "limbo.y"
2547+{
2548+ yyval.node = mkbin(Orshas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2549+ }
2550+184=>
2551+#line 1148 "limbo.y"
2552+{
2553+ yyval.node = mkbin(Oaddas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2554+ }
2555+185=>
2556+#line 1152 "limbo.y"
2557+{
2558+ yyval.node = mkbin(Osubas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2559+ }
2560+186=>
2561+#line 1156 "limbo.y"
2562+{
2563+ yyval.node = mkbin(Omulas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2564+ }
2565+187=>
2566+#line 1160 "limbo.y"
2567+{
2568+ yyval.node = mkbin(Odivas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2569+ }
2570+188=>
2571+#line 1164 "limbo.y"
2572+{
2573+ yyval.node = mkbin(Omodas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2574+ }
2575+189=>
2576+#line 1168 "limbo.y"
2577+{
2578+ yyval.node = mkbin(Oexpas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2579+ }
2580+190=>
2581+#line 1172 "limbo.y"
2582+{
2583+ yyval.node = mkbin(Osnd, yys[yypt-3].yyv.node, yys[yypt-0].yyv.node);
2584+ }
2585+191=>
2586+#line 1176 "limbo.y"
2587+{
2588+ yyval.node = mkbin(Odas, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2589+ }
2590+192=>
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+ }
2598+193=>
2599+#line 1187 "limbo.y"
2600+{
2601+ yyval.node = yyval.node = mkbin(Oexp, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2602+ }
2603+194=>
2604+#line 1191 "limbo.y"
2605+{
2606+ yyval.node = mkbin(Omul, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2607+ }
2608+195=>
2609+#line 1195 "limbo.y"
2610+{
2611+ yyval.node = mkbin(Odiv, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2612+ }
2613+196=>
2614+#line 1199 "limbo.y"
2615+{
2616+ yyval.node = mkbin(Omod, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2617+ }
2618+197=>
2619+#line 1203 "limbo.y"
2620+{
2621+ yyval.node = mkbin(Oadd, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2622+ }
2623+198=>
2624+#line 1207 "limbo.y"
2625+{
2626+ yyval.node = mkbin(Osub, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2627+ }
2628+199=>
2629+#line 1211 "limbo.y"
2630+{
2631+ yyval.node = mkbin(Orsh, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2632+ }
2633+200=>
2634+#line 1215 "limbo.y"
2635+{
2636+ yyval.node = mkbin(Olsh, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2637+ }
2638+201=>
2639+#line 1219 "limbo.y"
2640+{
2641+ yyval.node = mkbin(Olt, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2642+ }
2643+202=>
2644+#line 1223 "limbo.y"
2645+{
2646+ yyval.node = mkbin(Ogt, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2647+ }
2648+203=>
2649+#line 1227 "limbo.y"
2650+{
2651+ yyval.node = mkbin(Oleq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2652+ }
2653+204=>
2654+#line 1231 "limbo.y"
2655+{
2656+ yyval.node = mkbin(Ogeq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2657+ }
2658+205=>
2659+#line 1235 "limbo.y"
2660+{
2661+ yyval.node = mkbin(Oeq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2662+ }
2663+206=>
2664+#line 1239 "limbo.y"
2665+{
2666+ yyval.node = mkbin(Oneq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2667+ }
2668+207=>
2669+#line 1243 "limbo.y"
2670+{
2671+ yyval.node = mkbin(Oand, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2672+ }
2673+208=>
2674+#line 1247 "limbo.y"
2675+{
2676+ yyval.node = mkbin(Oxor, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2677+ }
2678+209=>
2679+#line 1251 "limbo.y"
2680+{
2681+ yyval.node = mkbin(Oor, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2682+ }
2683+210=>
2684+#line 1255 "limbo.y"
2685+{
2686+ yyval.node = mkbin(Ocons, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2687+ }
2688+211=>
2689+#line 1259 "limbo.y"
2690+{
2691+ yyval.node = mkbin(Oandand, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2692+ }
2693+212=>
2694+#line 1263 "limbo.y"
2695+{
2696+ yyval.node = mkbin(Ooror, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2697+ }
2698+213=>
2699+yyval.node = yys[yyp+1].yyv.node;
2700+214=>
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+ }
2706+215=>
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+ }
2712+216=>
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+ }
2718+217=>
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+ }
2724+218=>
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+ }
2730+219=>
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+ }
2736+220=>
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+ }
2742+221=>
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+ }
2748+222=>
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+ }
2754+223=>
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+ }
2760+224=>
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+ }
2766+225=>
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+ }
2772+226=>
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+ }
2778+227=>
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+ }
2785+228=>
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+ }
2792+229=>
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+ }
2802+230=>
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+ }
2809+231=>
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+ }
2816+232=>
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+ }
2823+233=>
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+ }
2830+234=>
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+ }
2837+235=>
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+ }
2844+236=>
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+ }
2851+237=>
2852+yyval.node = yys[yyp+1].yyv.node;
2853+238=>
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+ }
2860+239=>
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+ }
2871+240=>
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+ }
2878+241=>
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+ }
2886+242=>
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+ }
2891+243=>
2892+#line 1433 "limbo.y"
2893+{
2894+ yyval.node = mkbin(Omdot, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2895+ }
2896+244=>
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+ }
2902+245=>
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+ }
2912+246=>
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+ }
2918+247=>
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+ }
2924+248=>
2925+#line 1461 "limbo.y"
2926+{
2927+ yyval.node = mksconst(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2928+ }
2929+249=>
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+ }
2936+250=>
2937+#line 1471 "limbo.y"
2938+{
2939+ yyval.node = mkrconst(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.rval);
2940+ }
2941+251=>
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+ }
2947+252=>
2948+#line 1482 "limbo.y"
2949+{
2950+ yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
2951+ }
2952+253=>
2953+#line 1486 "limbo.y"
2954+{
2955+ yyval.node = mknil(yys[yypt-0].yyv.tok.src);
2956+ }
2957+254=>
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+ }
2964+255=>
2965+yyval.node = yys[yyp+1].yyv.node;
2966+256=>
2967+#line 1501 "limbo.y"
2968+{
2969+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
2970+ }
2971+257=>
2972+yyval.node = yys[yyp+1].yyv.node;
2973+258=>
2974+yyval.node = yys[yyp+1].yyv.node;
2975+259=>
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+ }
2982+260=>
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+ }
2989+261=>
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+ }
2996+262=>
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+ }
3004+263=>
3005+#line 1538 "limbo.y"
3006+{
3007+ yyval.node = mkname(yys[yypt-0].yyv.tok.src, yys[yypt-0].yyv.tok.v.idval);
3008+ }
3009+264=>
3010+#line 1542 "limbo.y"
3011+{
3012+ yyval.node = nil;
3013+ }
3014+265=>
3015+yyval.node = yys[yyp+1].yyv.node;
3016+266=>
3017+yyval.node = yys[yyp+1].yyv.node;
3018+267=>
3019+#line 1550 "limbo.y"
3020+{
3021+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3022+ }
3023+268=>
3024+#line 1554 "limbo.y"
3025+{
3026+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3027+ }
3028+269=>
3029+#line 1560 "limbo.y"
3030+{
3031+ yyval.node = nil;
3032+ }
3033+270=>
3034+#line 1564 "limbo.y"
3035+{
3036+ yyval.node = rotater(yys[yypt-0].yyv.node);
3037+ }
3038+271=>
3039+yyval.node = yys[yyp+1].yyv.node;
3040+272=>
3041+yyval.node = yys[yyp+1].yyv.node;
3042+273=>
3043+yyval.node = yys[yyp+1].yyv.node;
3044+274=>
3045+#line 1575 "limbo.y"
3046+{
3047+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3048+ }
3049+275=>
3050+#line 1581 "limbo.y"
3051+{
3052+ yyval.node = rotater(yys[yypt-0].yyv.node);
3053+ }
3054+276=>
3055+#line 1585 "limbo.y"
3056+{
3057+ yyval.node = rotater(yys[yypt-1].yyv.node);
3058+ }
3059+277=>
3060+yyval.node = yys[yyp+1].yyv.node;
3061+278=>
3062+#line 1592 "limbo.y"
3063+{
3064+ yyval.node = mkbin(Oseq, yys[yypt-2].yyv.node, yys[yypt-0].yyv.node);
3065+ }
3066+279=>
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+ }
3072+280=>
3073+#line 1603 "limbo.y"
3074+{
3075+ yyval.node = mkbin(Oelem, rotater(yys[yypt-2].yyv.node), yys[yypt-0].yyv.node);
3076+ }
3077+281=>
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+ }
3086+282=>
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+ }
3091+283=>
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 @@
1+include "sys.m";
2+include "math.m";
3+include "string.m";
4+include "bufio.m";
5+include "isa.m";
6+include "workdir.m";
7+
8+# internal dis ops
9+IEXC: con MAXDIS;
10+IEXC0: con (MAXDIS+1);
11+INOOP: con (MAXDIS+2);
12+
13+# temporary
14+LDT: con 1;
15+
16+STemp: con NREG * IBY2WD;
17+RTemp: con STemp + IBY2WD;
18+DTemp: con RTemp + IBY2WD;
19+MaxTemp: con DTemp + IBY2WD;
20+MaxReg: con 1 << 16;
21+MaxAlign: con IBY2LG;
22+StrSize: con 256;
23+MaxIncPath: con 32; # max directories in include path
24+MaxScope: con 64; # max nested {}
25+MaxInclude: con 32; # max nested include ""
26+ScopeBuiltin,
27+ScopeNils,
28+ScopeGlobal: con iota;
29+
30+Line: type int;
31+PosBits: con 10;
32+PosMask: con (1 << PosBits) - 1;
33+
34+Src: adt
35+{
36+ start: Line;
37+ stop: Line;
38+};
39+
40+File: 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+
51+Val: adt
52+{
53+ idval: ref Sym;
54+ ival: big;
55+ rval: real;
56+};
57+
58+Tok: 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+
81+Addr: adt
82+{
83+ reg: int;
84+ offset: int;
85+ decl: cyclic ref Decl;
86+};
87+
88+Inst: 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+
105+Case: 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+
115+Label: 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+
142+Decl: 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+
183+Desc: 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+
193+Dlist: adt
194+{
195+ d: ref Decl;
196+ next: cyclic ref Dlist;
197+};
198+
199+Except: 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+
211+Sym: 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+
364+Const: adt
365+{
366+ val: big;
367+ rval: real;
368+};
369+
370+PARENS: con 1;
371+TEMP: con 2;
372+FNPTRA: con 4; # argument
373+FNPTR2: con 8; # 2nd parameter
374+FNPTRN: con 16; # use -ve offset
375+FNPTR: con FNPTRA|FNPTR2|FNPTRN;
376+
377+Node: 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
458+FULLARGS: con byte 1; # all hidden args added
459+INST: con byte 2; # instantiated adt
460+CYCLIC: con byte 4; # cyclic type
461+POLY: con byte 8; # polymorphic types inside
462+NOPOLY: con byte 16; # no polymorphic types inside
463+
464+# must put some picks in here
465+Type: 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+#
498+Teq: 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+
505+Tattr: adt
506+{
507+ isptr: int;
508+ refable: int;
509+ conable: int;
510+ isbig: int;
511+ vis: int; # type visible to users
512+};
513+
514+Tpair: adt
515+{
516+ t1: cyclic ref Type;
517+ t2: cyclic ref Type;
518+ nxt: cyclic ref Tpair;
519+};
520+
521+Typelist: adt
522+{
523+ t: cyclic ref Type;
524+ nxt: cyclic ref Typelist;
525+};
526+
527+Sother, Sloop, Sscope : con iota;
limbo/compiler/limbo.y+1978−0
@@ -0,0 +1,1978 @@
1+%{
2+include "limbo.m";
3+include "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+%%
152+prog : 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+
166+topdecls: 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+
178+topdecl : 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+
214+idterms : idterm
215+ | idterms ',' idterm
216+ {
217+ $$ = mkbin(Oseq, $1, $3);
218+ }
219+ ;
220+
221+decl : 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+
251+edecl : ids ':' Lexcept ';'
252+ {
253+ $$ = exdecl($1, nil);
254+ }
255+ | ids ':' Lexcept '(' tuplist ')' ';'
256+ {
257+ $$ = exdecl($1, revids($5));
258+ }
259+ ;
260+
261+mdecl : ids ':' Lmodule '{' mfields '}'
262+ {
263+ $1.src.stop = $6.stop;
264+ $$ = moddecl($1, rotater($5));
265+ }
266+ ;
267+
268+mfields :
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+
287+mfield : 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+
303+adtdecl : 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+
319+forpoly :
320+ {
321+ $$ = nil;
322+ }
323+ | Lfor '{' tpolys '}'
324+ {
325+ $$ = $3;
326+ }
327+ ;
328+
329+fields :
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+
348+field : dfield
349+ | pdecl
350+ | ids ':' Lcon exp ';'
351+ {
352+ $$ = condecl($1, $4);
353+ }
354+ ;
355+
356+dfields :
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+
371+dfield : 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+
383+pdecl : Lpick '{' pfields '}'
384+ {
385+ $$ = $3;
386+ }
387+ ;
388+
389+pfields : 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+
404+pfbody : 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+
422+ptags : rptags
423+ {
424+ $$ = revids($1);
425+ }
426+ ;
427+
428+rptags : 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+
438+ids : rids
439+ {
440+ $$ = revids($1);
441+ }
442+ ;
443+
444+rids : 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+
454+fixtype : 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+
466+types : 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+
486+type : 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+
550+iditype : 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+
560+dotiditype : 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+
571+tuplist : type
572+ {
573+ $$ = mkids($1.src, nil, $1, nil);
574+ }
575+ | tuplist ',' type
576+ {
577+ $$ = mkids($1.src, nil, $3, $1);
578+ }
579+ ;
580+
581+polydec :
582+ {
583+ $$ = nil;
584+ }
585+ | '[' ids ']'
586+ {
587+ $$ = polydecl($2);
588+ }
589+ ;
590+
591+fnarg : '(' 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+
607+fnargret: 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+
619+fnargretp: fnargret %prec '='
620+ {
621+ $$ = $1;
622+ }
623+ | fnargret Lfor '{' tpolys '}'
624+ {
625+ $$ = $1;
626+ $$.val = rotater($4);
627+ }
628+ ;
629+
630+forms :
631+ {
632+ $$ = nil;
633+ }
634+ | ftypes
635+ ;
636+
637+ftypes : ftype
638+ | ftypes ',' ftype
639+ {
640+ $$ = appdecls($1, $3);
641+ }
642+ ;
643+
644+ftype : 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+
668+nids : nrids
669+ {
670+ $$ = revids($1);
671+ }
672+ ;
673+
674+nrids : 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+
696+adtk : 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+
714+fndef : 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+
740+raises : 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+
758+fbody : '{' 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+
779+fnname : 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+
797+stmts :
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+
819+elists : '(' elist ')'
820+ | elists ',' '(' elist ')'
821+ ;
822+
823+stmt : 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+
976+bclab :
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+
988+bctarg :
989+ {
990+ $$ = nil;
991+ }
992+ | Lid
993+ {
994+ $$ = mkids($<tok.src>1, $1, nil, nil);
995+ }
996+ ;
997+
998+qstmts : qbodies stmts
999+ {
1000+ $1.left.right.right = $2;
1001+ $$ = $1;
1002+ }
1003+ ;
1004+
1005+qbodies : 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+
1016+cqstmts : cqbodies stmts
1017+ {
1018+ $1.left.right = mkscope($2);
1019+ $$ = $1;
1020+ }
1021+ ;
1022+
1023+cqbodies : 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+
1034+eqstmts : eqbodies stmts
1035+ {
1036+ $1.left.right = mkscope($2);
1037+ $$ = $1;
1038+ }
1039+ ;
1040+
1041+eqbodies : 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+
1052+qual : 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+
1074+pstmts : pbodies stmts
1075+ {
1076+ $1.left.right = mkscope($2);
1077+ $$ = $1;
1078+ }
1079+ ;
1080+
1081+pbodies : 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+
1092+pqual : 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+
1113+zexp :
1114+ {
1115+ $$ = mkn(Onothing, nil, nil);
1116+ $$.src.start = curline();
1117+ $$.src.stop = $$.src.start;
1118+ }
1119+ | exp
1120+ ;
1121+
1122+exp : 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+
1268+monexp : 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+
1399+term : 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+
1481+idatom : Lid
1482+ {
1483+ $$ = mkname($<tok.src>1, $1);
1484+ }
1485+ | Lnil
1486+ {
1487+ $$ = mknil($<tok.src>1);
1488+ }
1489+ ;
1490+
1491+idterm : '(' idlist ')'
1492+ {
1493+ $$ = mkn(Otuple, rotater($2), nil);
1494+ $$.src.start = $1.start;
1495+ $$.src.stop = $3.stop;
1496+ }
1497+ ;
1498+
1499+exportlist : export
1500+ | exportlist ',' export
1501+ {
1502+ $$ = mkbin(Oseq, $1, $3);
1503+ }
1504+ ;
1505+
1506+export : exp
1507+ | texp
1508+ ;
1509+
1510+texp : 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+
1537+idexc : Lid
1538+ {
1539+ $$ = mkname($<tok.src>1, $1);
1540+ }
1541+ | # empty
1542+ {
1543+ $$ = nil;
1544+ }
1545+ ;
1546+
1547+idlist : 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+
1559+zelist :
1560+ {
1561+ $$ = nil;
1562+ }
1563+ | elist
1564+ {
1565+ $$ = rotater($1);
1566+ }
1567+ ;
1568+
1569+celist : elist
1570+ | elist ','
1571+ ;
1572+
1573+elist : exp
1574+ | elist ',' exp
1575+ {
1576+ $$ = mkbin(Oseq, $1, $3);
1577+ }
1578+ ;
1579+
1580+initlist : elemlist
1581+ {
1582+ $$ = rotater($1);
1583+ }
1584+ | elemlist ','
1585+ {
1586+ $$ = rotater($1);
1587+ }
1588+ ;
1589+
1590+elemlist : elem
1591+ | elemlist ',' elem
1592+ {
1593+ $$ = mkbin(Oseq, $1, $3);
1594+ }
1595+ ;
1596+
1597+elem : 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+
1608+tpolys : 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+
1618+tpoly : 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+
1634+include "ipints.m";
1635+include "crypt.m";
1636+
1637+sys: Sys;
1638+ print, fprint, sprint: import sys;
1639+
1640+bufio: Bufio;
1641+ Iobuf: import bufio;
1642+
1643+str: String;
1644+
1645+crypt:Crypt;
1646+ md5: import crypt;
1647+
1648+math: Math;
1649+ import_real, export_real, isnan: import math;
1650+
1651+yyctxt: ref YYLEX;
1652+
1653+canonnan: real;
1654+
1655+debug = array[256] of {* => 0};
1656+
1657+noline = -1;
1658+nosrc = Src(-1, -1);
1659+
1660+infile: string;
1661+
1662+# front end
1663+include "arg.m";
1664+include "lex.b";
1665+include "types.b";
1666+include "nodes.b";
1667+include "decls.b";
1668+
1669+include "typecheck.b";
1670+
1671+# back end
1672+include "gen.b";
1673+include "ecom.b";
1674+include "asm.b";
1675+include "dis.b";
1676+include "sbl.b";
1677+include "stubs.b";
1678+include "com.b";
1679+include "optim.b";
1680+
1681+init(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+
1853+usage()
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+
1859+mkfileext(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+
1868+translate(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+
1931+pwd(): 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+
1942+cleanname(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+
1973+srcpath(): 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 @@
1+include "opname.m";
2+
3+znode: Node;
4+
5+isused = 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+
34+sideeffect := 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+
78+opcommute = 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+
95+oprelinvert = 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+
108+isrelop := 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+
124+ipow(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+
147+rpow(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+
170+real2fix(v: real, t: ref Type): big
171+{
172+ return big(v/scale(t));
173+}
174+
175+fix2fix(v: big, f: ref Type, t: ref Type): big
176+{
177+ return big(real v * (scale(f)/scale(t)));
178+}
179+
180+fix2real(v: big, f: ref Type): real
181+{
182+ return real v * scale(f);
183+}
184+
185+istuple(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+
203+tuplemem(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+
221+varcom(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+
239+initable(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+#
305+elemmerge(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+#
328+recelemsort(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+#
345+elemsort(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+
356+sametree(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+
382+occurs(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+#
397+folds(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+#
430+fold(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+
442+efold(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+#
660+hasside(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+
671+hascall(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+
682+hasasgns(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+
691+nodes(n: ref Node): int
692+{
693+ if(n == nil)
694+ return 0;
695+ return 1+nodes(n.left)+nodes(n.right);
696+}
697+
698+foldcast(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+#
764+foldcasti(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+#
790+foldvc(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+#
855+foldc(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+#
954+foldr(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+
1008+varinit(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+#
1021+rotater(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+#
1040+caselist(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+#
1052+etolist(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+
1072+dupn(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+
1084+mkn(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+
1094+mkunary(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+
1104+mkbin(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+
1116+mkdeclname(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+
1128+mknil(src: Src): ref Node
1129+{
1130+ return mkdeclname(src, nildecl);
1131+}
1132+
1133+mkname(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+
1147+mkconst(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+
1158+mkrconst(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+
1169+mksconst(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+
1181+opconv(op: int): string
1182+{
1183+ if(op < 0 || op > Oend)
1184+ return "op "+string op;
1185+ return opname[op];
1186+}
1187+
1188+etconv(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+
1198+expconv(n: ref Node): string
1199+{
1200+ return "'" + subexpconv(n) + "'";
1201+}
1202+
1203+subexpconv(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+
1351+eprintlist(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+
1369+nodeconv(n: ref Node): string
1370+{
1371+ return nprint(n, 0);
1372+}
1373+
1374+nprint(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 @@
1+opname := 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 @@
1+optim(nil: ref Inst, nil: ref Decl)
2+{
3+}
limbo/compiler/sbl.b+397−0
@@ -0,0 +1,397 @@
1+
2+sbltname := 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+};
38+sbltadtpick: con byte 'p';
39+
40+sfiles: ref Sym;
41+ftail: ref Sym;
42+nsfiles: int;
43+blockid: int;
44+lastf: int;
45+lastline: int;
46+
47+MAXSBLINT: con 12;
48+MAXSBLSRC: con 6*(MAXSBLINT+1);
49+
50+sblmod(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+
63+sblfile(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+
83+filename(s: string): string
84+{
85+ (nil, file) := str->splitr(s, "/ \\");
86+ return file;
87+}
88+
89+sblfiles()
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+
101+sblint(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+
122+sblsrcconvb(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+
151+sblsrcconv(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+
181+isnilsrc(s: Src): int
182+{
183+ return s.start == 0 && s.stop == 0;
184+}
185+
186+isnilstopsrc(s: Src): int
187+{
188+ return s.stop == 0;
189+}
190+
191+sblinst(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+
228+sblty(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+
242+sblfn(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+
264+sblvar(vars: ref Decl)
265+{
266+ sbldecl(vars, Dglobal);
267+}
268+
269+isvis(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+
283+sbldecl(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+
306+sbltype(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+#
4+emit(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+
34+modsbl(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+
72+lowercase(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+
80+modcode(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+
183+modtab(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+#
214+modstub(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+
263+chanstub(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+#
274+adtstub(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
351+if(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+#
363+stubalign(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+
379+constub(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+
397+mapconv(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+
408+dotprint(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+
420+ckindname := 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+
457+ctypeconv(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+
511+pickadtstub(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 @@
1+fndecls: ref Decl;
2+labstack: array of ref Node;
3+maxlabdep: int;
4+inexcept: ref Node;
5+nexc: int;
6+fndec: ref Decl;
7+
8+increfs(id: ref Decl)
9+{
10+ for( ; id != nil; id = id.link)
11+ id.refs++;
12+}
13+
14+fninline(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+
64+rewind(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+
80+ckmod(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+
127+addref(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+
140+fnref(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+
151+typecheck(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+#
253+gdecl(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+#
302+gbind(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+#
364+gcheck(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+#
440+checkused(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+
483+fncheck(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+
520+scheck(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+
686+pushlabel(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+
706+varcheck(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+
719+concheck(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+
759+exname(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+
773+excheck(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+
788+importcheck(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+
821+rewcall(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+
840+isfnrefty(t: ref Type): int
841+{
842+ return t.kind == Tref && t.tof.kind == Tfn;
843+}
844+
845+isfnref(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+
858+tagopt: int;
859+
860+#
861+# annotate the expression with types
862+#
863+echeck(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+ }
974+if(n.ty.tof.decl.refs != 0)
975+n.ty.tof.decl.refs++;
976+n.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;
1538+usedty(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;
1677+usedty(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+ }
1691+usedty(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+#
1699+callcast(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+
1760+tagcast(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+
1780+valistype(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+
1792+islval(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+#
1807+marklval(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+#
1870+circlval(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+
1914+mathchk(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+
1947+shiftchk(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+#
1969+specific(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+#
2011+declasinfer(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+#
2058+declaserr(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+
2073+argcompat(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+
2095+argncompat(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+#
2116+passimplicit(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+
2136+mem(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+
2144+memp(t: ref Type, f: ref Decl): int
2145+{
2146+ return mem(t, f.ty.polys) || mem(t, encpolys(f));
2147+}
2148+
2149+passfns0(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+
2210+passfns(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+#
2239+mkvarargs(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+#
2287+fmtcheck(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+
2428+tuplefields(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+#
2448+assignindices(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+#
2555+casecheck(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+#
2624+pickcheck(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+
2716+exccheck(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+#
2795+checklabels(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+
2860+symcmp(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+
2869+matchcmp(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+
2906+casecmp(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+
2920+casesort(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+#
2951+findlab(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+
2972+altcheck(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+
3022+hascomm(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+
3034+raisescheck(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+
3046+Elist: adt{
3047+ d: ref Decl;
3048+ nxt: cyclic ref Elist;
3049+};
3050+
3051+emerge(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+
3073+equals(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+
3091+caught(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+
3109+raisecheck(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+
3177+checkraises(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+#
3209+gsort(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+
2+kindname := 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+
39+tattr = 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.