Unified · Split
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +}; | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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)) | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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; | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +}; | |
| @@ -0,0 +1,3 @@ | ||
| 1 | +optim(nil: ref Inst, nil: ref Decl) | |
| 2 | +{ | |
| 3 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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.