diff options
author | David Walter Seikel | 2012-01-23 21:58:02 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-23 21:58:02 +1000 |
commit | 2d1df4714e2736dbde7855ddcd76b4c1de822fa5 (patch) | |
tree | c80e4622631c92dbe8dd6375d187702d084c2f2b /LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua | |
parent | Remove the conflict, and the comment. lol (diff) | |
download | SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.zip SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.gz SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.bz2 SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.xz |
Added a big bunch of example lua scripts for testing the speed of lua compiling.
Diffstat (limited to '')
-rw-r--r-- | LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua | 902 |
1 files changed, 902 insertions, 0 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua new file mode 100644 index 0000000..c18dc08 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/lcode.lua | |||
@@ -0,0 +1,902 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | lcode.lua | ||
4 | Lua 5 code generator in Lua | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net> | ||
8 | The COPYRIGHT file describes the conditions | ||
9 | under which this software may be distributed. | ||
10 | |||
11 | See the ChangeLog for more information. | ||
12 | |||
13 | ----------------------------------------------------------------------]] | ||
14 | |||
15 | --[[-------------------------------------------------------------------- | ||
16 | -- Notes: | ||
17 | -- * one function manipulate a pointer argument with a simple data type | ||
18 | -- (can't be emulated by a table, ambiguous), now returns that value: | ||
19 | -- luaK:concat(fs, l1, l2) | ||
20 | -- * some function parameters changed to boolean, additional code | ||
21 | -- translates boolean back to 1/0 for instruction fields | ||
22 | -- * Added: | ||
23 | -- luaK:ttisnumber(o) (from lobject.h) | ||
24 | -- luaK:nvalue(o) (from lobject.h) | ||
25 | -- luaK:setnilvalue(o) (from lobject.h) | ||
26 | -- luaK:setsvalue(o, x) (from lobject.h) | ||
27 | -- luaK:setnvalue(o, x) (from lobject.h) | ||
28 | -- luaK:sethvalue(o, x) (from lobject.h) | ||
29 | ----------------------------------------------------------------------]] | ||
30 | |||
31 | -- requires luaP, luaX, luaY | ||
32 | luaK = {} | ||
33 | |||
34 | ------------------------------------------------------------------------ | ||
35 | -- Marks the end of a patch list. It is an invalid value both as an absolute | ||
36 | -- address, and as a list link (would link an element to itself). | ||
37 | ------------------------------------------------------------------------ | ||
38 | luaK.NO_JUMP = -1 | ||
39 | |||
40 | ------------------------------------------------------------------------ | ||
41 | -- grep "ORDER OPR" if you change these enums | ||
42 | ------------------------------------------------------------------------ | ||
43 | luaK.BinOpr = { | ||
44 | OPR_ADD = 0, OPR_SUB = 1, OPR_MULT = 2, OPR_DIV = 3, OPR_POW = 4, | ||
45 | OPR_CONCAT = 5, | ||
46 | OPR_NE = 6, OPR_EQ = 7, | ||
47 | OPR_LT = 8, OPR_LE = 9, OPR_GT = 10, OPR_GE = 11, | ||
48 | OPR_AND = 12, OPR_OR = 13, | ||
49 | OPR_NOBINOPR = 14, | ||
50 | } | ||
51 | |||
52 | ------------------------------------------------------------------------ | ||
53 | -- emulation of TObject macros (these are from lobject.h) | ||
54 | -- * TObject is a table since lcode passes references around | ||
55 | -- * tt member field removed, using Lua's type() instead | ||
56 | ------------------------------------------------------------------------ | ||
57 | function luaK:ttisnumber(o) | ||
58 | if o then return type(o.value) == "number" else return false end | ||
59 | end | ||
60 | function luaK:nvalue(o) return o.value end | ||
61 | function luaK:setnilvalue(o) o.value = nil end | ||
62 | function luaK:setsvalue(o, x) o.value = x end | ||
63 | luaK.setnvalue = luaK.setsvalue | ||
64 | luaK.sethvalue = luaK.setsvalue | ||
65 | |||
66 | ------------------------------------------------------------------------ | ||
67 | -- * binopistest appears to be unused | ||
68 | -- * UnOpr is used by luaK:prefix's op argument | ||
69 | ------------------------------------------------------------------------ | ||
70 | function luaK:binopistest(op) | ||
71 | return self.BinOpr[op] >= self.BinOpr["OPR_NE"] | ||
72 | end | ||
73 | |||
74 | luaK.UnOpr = { | ||
75 | OPR_MINUS = 0, OPR_NOT = 1, OPR_NOUNOPR = 2 | ||
76 | } | ||
77 | |||
78 | ------------------------------------------------------------------------ | ||
79 | -- returns the instruction object for given e (expdesc) | ||
80 | ------------------------------------------------------------------------ | ||
81 | function luaK:getcode(fs, e) | ||
82 | return fs.f.code[e.info] | ||
83 | end | ||
84 | |||
85 | ------------------------------------------------------------------------ | ||
86 | -- codes an instruction with a signed Bx (sBx) field | ||
87 | ------------------------------------------------------------------------ | ||
88 | function luaK:codeAsBx(fs, o, A, sBx) | ||
89 | return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx) | ||
90 | end | ||
91 | |||
92 | ------------------------------------------------------------------------ | ||
93 | -- there is a jump if patch lists are not identical | ||
94 | -- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val() | ||
95 | ------------------------------------------------------------------------ | ||
96 | function luaK:hasjumps(e) | ||
97 | return e.t ~= e.f | ||
98 | end | ||
99 | |||
100 | ------------------------------------------------------------------------ | ||
101 | -- codes loading of nil, optimization done if consecutive locations | ||
102 | -- * used only in discharge2reg() | ||
103 | ------------------------------------------------------------------------ | ||
104 | function luaK:_nil(fs, from, n) | ||
105 | if fs.pc > fs.lasttarget then -- no jumps to current position? | ||
106 | local previous = fs.f.code[fs.pc - 1] | ||
107 | if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then | ||
108 | local pfrom = luaP:GETARG_A(previous) | ||
109 | local pto = luaP:GETARG_B(previous) | ||
110 | if pfrom <= from and from <= pto + 1 then -- can connect both? | ||
111 | if from + n - 1 > pto then | ||
112 | luaP:SETARG_B(previous, from + n - 1) | ||
113 | end | ||
114 | return | ||
115 | end | ||
116 | end | ||
117 | end | ||
118 | self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization | ||
119 | end | ||
120 | |||
121 | ------------------------------------------------------------------------ | ||
122 | -- | ||
123 | -- * used in multiple locations | ||
124 | ------------------------------------------------------------------------ | ||
125 | function luaK:jump(fs) | ||
126 | local jpc = fs.jpc -- save list of jumps to here | ||
127 | fs.jpc = self.NO_JUMP | ||
128 | local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP) | ||
129 | return self:concat(fs, j, jpc) -- keep them on hold | ||
130 | end | ||
131 | |||
132 | ------------------------------------------------------------------------ | ||
133 | -- | ||
134 | -- * used in luaK:jumponcond(), luaK:codebinop() | ||
135 | ------------------------------------------------------------------------ | ||
136 | function luaK:condjump(fs, op, A, B, C) | ||
137 | self:codeABC(fs, op, A, B, C) | ||
138 | return self:jump(fs) | ||
139 | end | ||
140 | |||
141 | ------------------------------------------------------------------------ | ||
142 | -- | ||
143 | -- * used in luaK:patchlistaux(), luaK:concat() | ||
144 | ------------------------------------------------------------------------ | ||
145 | function luaK:fixjump(fs, pc, dest) | ||
146 | local jmp = fs.f.code[pc] | ||
147 | local offset = dest - (pc + 1) | ||
148 | lua_assert(dest ~= self.NO_JUMP) | ||
149 | if math.abs(offset) > luaP.MAXARG_sBx then | ||
150 | luaX:syntaxerror(fs.ls, "control structure too long") | ||
151 | end | ||
152 | luaP:SETARG_sBx(jmp, offset) | ||
153 | end | ||
154 | |||
155 | ------------------------------------------------------------------------ | ||
156 | -- returns current 'pc' and marks it as a jump target (to avoid wrong | ||
157 | -- optimizations with consecutive instructions not in the same basic block). | ||
158 | -- * used in multiple locations | ||
159 | -- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL | ||
160 | ------------------------------------------------------------------------ | ||
161 | function luaK:getlabel(fs) | ||
162 | fs.lasttarget = fs.pc | ||
163 | return fs.pc | ||
164 | end | ||
165 | |||
166 | ------------------------------------------------------------------------ | ||
167 | -- | ||
168 | -- * used in luaK:need_value(), luaK:patchlistaux(), luaK:concat() | ||
169 | ------------------------------------------------------------------------ | ||
170 | function luaK:getjump(fs, pc) | ||
171 | local offset = luaP:GETARG_sBx(fs.f.code[pc]) | ||
172 | if offset == self.NO_JUMP then -- point to itself represents end of list | ||
173 | return self.NO_JUMP -- end of list | ||
174 | else | ||
175 | return (pc + 1) + offset -- turn offset into absolute position | ||
176 | end | ||
177 | end | ||
178 | |||
179 | ------------------------------------------------------------------------ | ||
180 | -- | ||
181 | -- * used in luaK:need_value(), luaK:patchlistaux(), luaK:invertjump() | ||
182 | ------------------------------------------------------------------------ | ||
183 | function luaK:getjumpcontrol(fs, pc) | ||
184 | local pi = fs.f.code[pc] | ||
185 | local ppi = fs.f.code[pc - 1] | ||
186 | if pc >= 1 and luaP:testOpMode(luaP:GET_OPCODE(ppi), "OpModeT") then | ||
187 | return ppi | ||
188 | else | ||
189 | return pi | ||
190 | end | ||
191 | end | ||
192 | |||
193 | ------------------------------------------------------------------------ | ||
194 | -- check whether list has any jump that do not produce a value | ||
195 | -- (or produce an inverted value) | ||
196 | -- * used only in luaK:exp2reg() | ||
197 | ------------------------------------------------------------------------ | ||
198 | function luaK:need_value(fs, list, cond) | ||
199 | while list ~= self.NO_JUMP do | ||
200 | local i = self:getjumpcontrol(fs, list) | ||
201 | if luaP:GET_OPCODE(i) ~= "OP_TEST" or | ||
202 | luaP:GETARG_A(i) ~= luaP.NO_REG or | ||
203 | luaP:GETARG_C(i) ~= cond then | ||
204 | return true | ||
205 | end | ||
206 | list = self:getjump(fs, list) | ||
207 | end | ||
208 | return false -- not found | ||
209 | end | ||
210 | |||
211 | ------------------------------------------------------------------------ | ||
212 | -- | ||
213 | -- * used only in luaK:patchlistaux() | ||
214 | ------------------------------------------------------------------------ | ||
215 | function luaK:patchtestreg(i, reg) | ||
216 | if reg == luaP.NO_REG then reg = luaP:GETARG_B(i) end | ||
217 | luaP:SETARG_A(i, reg) | ||
218 | end | ||
219 | |||
220 | ------------------------------------------------------------------------ | ||
221 | -- | ||
222 | -- * used only in luaK:codenot() | ||
223 | ------------------------------------------------------------------------ | ||
224 | |||
225 | function luaK:removevalues(fs, list) | ||
226 | while list ~= self.NO_JUMP do | ||
227 | local i = self:getjumpcontrol(fs, list) | ||
228 | if luaP:GET_OPCODE(i) == "OP_TEST" then | ||
229 | self:patchtestreg(i, luaP.NO_REG) | ||
230 | end | ||
231 | list = self:getjump(fs, list) | ||
232 | end | ||
233 | end | ||
234 | |||
235 | ------------------------------------------------------------------------ | ||
236 | -- | ||
237 | -- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg() | ||
238 | ------------------------------------------------------------------------ | ||
239 | function luaK:patchlistaux(fs, list, vtarget, reg, dtarget) | ||
240 | while list ~= self.NO_JUMP do | ||
241 | local _next = self:getjump(fs, list) | ||
242 | local i = self:getjumpcontrol(fs, list) | ||
243 | if luaP:GET_OPCODE(i) == "OP_TEST" and luaP:GETARG_A(i) == luaP.NO_REG then | ||
244 | self:patchtestreg(i, reg) | ||
245 | self:fixjump(fs, list, vtarget) | ||
246 | else | ||
247 | self:fixjump(fs, list, dtarget) -- jump to default target | ||
248 | end | ||
249 | list = _next | ||
250 | end | ||
251 | end | ||
252 | |||
253 | ------------------------------------------------------------------------ | ||
254 | -- | ||
255 | -- * used only in luaK:code() | ||
256 | ------------------------------------------------------------------------ | ||
257 | function luaK:dischargejpc(fs) | ||
258 | self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc) | ||
259 | fs.jpc = self.NO_JUMP | ||
260 | end | ||
261 | |||
262 | ------------------------------------------------------------------------ | ||
263 | -- | ||
264 | -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody() | ||
265 | ------------------------------------------------------------------------ | ||
266 | function luaK:patchlist(fs, list, target) | ||
267 | if target == fs.pc then | ||
268 | self:patchtohere(fs, list) | ||
269 | else | ||
270 | lua_assert(target < fs.pc) | ||
271 | self:patchlistaux(fs, list, target, luaP.NO_REG, target) | ||
272 | end | ||
273 | end | ||
274 | |||
275 | ------------------------------------------------------------------------ | ||
276 | -- | ||
277 | -- * used in multiple locations | ||
278 | ------------------------------------------------------------------------ | ||
279 | function luaK:patchtohere(fs, list) | ||
280 | self:getlabel(fs) | ||
281 | fs.jpc = self:concat(fs, fs.jpc, list) | ||
282 | end | ||
283 | |||
284 | ------------------------------------------------------------------------ | ||
285 | -- * l1 was a pointer, now l1 is returned and callee assigns the value | ||
286 | -- * used in multiple locations | ||
287 | ------------------------------------------------------------------------ | ||
288 | function luaK:concat(fs, l1, l2) | ||
289 | if l2 == self.NO_JUMP then return l1 -- unchanged | ||
290 | elseif l1 == self.NO_JUMP then | ||
291 | return l2 -- changed | ||
292 | else | ||
293 | local list = l1 | ||
294 | local _next = self:getjump(fs, list) | ||
295 | while _next ~= self.NO_JUMP do -- find last element | ||
296 | list = _next | ||
297 | _next = self:getjump(fs, list) | ||
298 | end | ||
299 | self:fixjump(fs, list, l2) | ||
300 | end | ||
301 | return l1 -- unchanged | ||
302 | end | ||
303 | |||
304 | ------------------------------------------------------------------------ | ||
305 | -- | ||
306 | -- * used in luaK:reserveregs(), (lparser) luaY:forlist() | ||
307 | ------------------------------------------------------------------------ | ||
308 | function luaK:checkstack(fs, n) | ||
309 | local newstack = fs.freereg + n | ||
310 | if newstack > fs.f.maxstacksize then | ||
311 | if newstack >= luaY.MAXSTACK then | ||
312 | luaX:syntaxerror(fs.ls, "function or expression too complex") | ||
313 | end | ||
314 | fs.f.maxstacksize = newstack | ||
315 | end | ||
316 | end | ||
317 | |||
318 | ------------------------------------------------------------------------ | ||
319 | -- | ||
320 | -- * used in multiple locations | ||
321 | ------------------------------------------------------------------------ | ||
322 | function luaK:reserveregs(fs, n) | ||
323 | self:checkstack(fs, n) | ||
324 | fs.freereg = fs.freereg + n | ||
325 | end | ||
326 | |||
327 | ------------------------------------------------------------------------ | ||
328 | -- | ||
329 | -- * used in luaK:freeexp(), luaK:dischargevars() | ||
330 | ------------------------------------------------------------------------ | ||
331 | function luaK:freereg(fs, reg) | ||
332 | if reg >= fs.nactvar and reg < luaY.MAXSTACK then | ||
333 | fs.freereg = fs.freereg - 1 | ||
334 | lua_assert(reg == fs.freereg) | ||
335 | end | ||
336 | end | ||
337 | |||
338 | ------------------------------------------------------------------------ | ||
339 | -- | ||
340 | -- * used in multiple locations | ||
341 | ------------------------------------------------------------------------ | ||
342 | function luaK:freeexp(fs, e) | ||
343 | if e.k == "VNONRELOC" then | ||
344 | self:freereg(fs, e.info) | ||
345 | end | ||
346 | end | ||
347 | |||
348 | ------------------------------------------------------------------------ | ||
349 | -- * luaH_get, luaH_set deleted; direct table access used instead | ||
350 | -- * luaO_rawequalObj deleted in first assert | ||
351 | -- * setobj2n deleted in assignment of v to f.k table | ||
352 | -- * used in luaK:stringK(), luaK:numberK(), luaK:nil_constant() | ||
353 | ------------------------------------------------------------------------ | ||
354 | function luaK:addk(fs, k, v) | ||
355 | local idx = fs.h[k.value] | ||
356 | if self:ttisnumber(idx) then | ||
357 | --TODO this assert currently FAILS, probably something wrong... | ||
358 | --lua_assert(fs.f.k[self:nvalue(idx)] == v) | ||
359 | return self:nvalue(idx) | ||
360 | else -- constant not found; create a new entry | ||
361 | local f = fs.f | ||
362 | luaY:growvector(fs.L, f.k, fs.nk, f.sizek, nil, | ||
363 | luaP.MAXARG_Bx, "constant table overflow") | ||
364 | f.k[fs.nk] = v -- setobj2n deleted | ||
365 | fs.h[k.value] = {} | ||
366 | self:setnvalue(fs.h[k.value], fs.nk) | ||
367 | local nk = fs.nk | ||
368 | fs.nk = fs.nk + 1 | ||
369 | return nk | ||
370 | end | ||
371 | end | ||
372 | |||
373 | ------------------------------------------------------------------------ | ||
374 | -- creates and sets a string object | ||
375 | -- * used in (lparser) luaY:codestring(), luaY:singlevaraux() | ||
376 | ------------------------------------------------------------------------ | ||
377 | function luaK:stringK(fs, s) | ||
378 | local o = {} -- TObject | ||
379 | self:setsvalue(o, s) | ||
380 | return self:addk(fs, o, o) | ||
381 | end | ||
382 | |||
383 | ------------------------------------------------------------------------ | ||
384 | -- creates and sets a number object | ||
385 | -- * used in luaK:prefix() for negative (or negation of) numbers | ||
386 | -- * used in (lparser) luaY:simpleexp(), luaY:fornum() | ||
387 | ------------------------------------------------------------------------ | ||
388 | function luaK:numberK(fs, r) | ||
389 | local o = {} -- TObject | ||
390 | self:setnvalue(o, r) | ||
391 | return self:addk(fs, o, o) | ||
392 | end | ||
393 | |||
394 | ------------------------------------------------------------------------ | ||
395 | -- | ||
396 | -- * used only in luaK:exp2RK() | ||
397 | ------------------------------------------------------------------------ | ||
398 | function luaK:nil_constant(fs) | ||
399 | local k, v = {}, {} -- TObject | ||
400 | self:setnilvalue(v) | ||
401 | self:sethvalue(k, fs.h) -- cannot use nil as key; instead use table itself | ||
402 | return self:addk(fs, k, v) | ||
403 | end | ||
404 | |||
405 | ------------------------------------------------------------------------ | ||
406 | -- | ||
407 | -- * used in luaK:dischargevars() | ||
408 | -- * used in (lparser) luaY:adjust_assign(), luaY:lastlistfield(), | ||
409 | -- luaY:funcargs(), luaY:assignment(), luaY:exprstat(), luaY:retstat() | ||
410 | ------------------------------------------------------------------------ | ||
411 | function luaK:setcallreturns(fs, e, nresults) | ||
412 | if e.k == "VCALL" then -- expression is an open function call? | ||
413 | luaP:SETARG_C(self:getcode(fs, e), nresults + 1) | ||
414 | if nresults == 1 then -- 'regular' expression? | ||
415 | e.k = "VNONRELOC" | ||
416 | e.info = luaP:GETARG_A(self:getcode(fs, e)) | ||
417 | end | ||
418 | end | ||
419 | end | ||
420 | |||
421 | ------------------------------------------------------------------------ | ||
422 | -- | ||
423 | -- * used in multiple locations | ||
424 | ------------------------------------------------------------------------ | ||
425 | function luaK:dischargevars(fs, e) | ||
426 | local k = e.k | ||
427 | if k == "VLOCAL" then | ||
428 | e.k = "VNONRELOC" | ||
429 | elseif k == "VUPVAL" then | ||
430 | e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0) | ||
431 | e.k = "VRELOCABLE" | ||
432 | elseif k == "VGLOBAL" then | ||
433 | e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info) | ||
434 | e.k = "VRELOCABLE" | ||
435 | elseif k == "VINDEXED" then | ||
436 | self:freereg(fs, e.aux) | ||
437 | self:freereg(fs, e.info) | ||
438 | e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux) | ||
439 | e.k = "VRELOCABLE" | ||
440 | elseif k == "VCALL" then | ||
441 | self:setcallreturns(fs, e, 1) | ||
442 | else | ||
443 | -- there is one value available (somewhere) | ||
444 | end | ||
445 | end | ||
446 | |||
447 | ------------------------------------------------------------------------ | ||
448 | -- | ||
449 | -- * used only in luaK:exp2reg() | ||
450 | ------------------------------------------------------------------------ | ||
451 | function luaK:code_label(fs, A, b, jump) | ||
452 | self:getlabel(fs) -- those instructions may be jump targets | ||
453 | return self:codeABC(fs, "OP_LOADBOOL", A, b, jump) | ||
454 | end | ||
455 | |||
456 | ------------------------------------------------------------------------ | ||
457 | -- | ||
458 | -- * used in luaK:discharge2anyreg(), luaK:exp2reg() | ||
459 | ------------------------------------------------------------------------ | ||
460 | function luaK:discharge2reg(fs, e, reg) | ||
461 | self:dischargevars(fs, e) | ||
462 | local k = e.k | ||
463 | if k == "VNIL" then | ||
464 | self:_nil(fs, reg, 1) | ||
465 | elseif k == "VFALSE" or k == "VTRUE" then | ||
466 | self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0) | ||
467 | elseif k == "VK" then | ||
468 | self:codeABx(fs, "OP_LOADK", reg, e.info) | ||
469 | elseif k == "VRELOCABLE" then | ||
470 | local pc = self:getcode(fs, e) | ||
471 | luaP:SETARG_A(pc, reg) | ||
472 | elseif k == "VNONRELOC" then | ||
473 | if reg ~= e.info then | ||
474 | self:codeABC(fs, "OP_MOVE", reg, e.info, 0) | ||
475 | end | ||
476 | else | ||
477 | lua_assert(e.k == "VVOID" or e.k == "VJMP") | ||
478 | return -- nothing to do... | ||
479 | end | ||
480 | e.info = reg | ||
481 | e.k = "VNONRELOC" | ||
482 | end | ||
483 | |||
484 | ------------------------------------------------------------------------ | ||
485 | -- | ||
486 | -- * used in luaK:jumponcond(), luaK:codenot() | ||
487 | ------------------------------------------------------------------------ | ||
488 | function luaK:discharge2anyreg(fs, e) | ||
489 | if e.k ~= "VNONRELOC" then | ||
490 | self:reserveregs(fs, 1) | ||
491 | self:discharge2reg(fs, e, fs.freereg - 1) | ||
492 | end | ||
493 | end | ||
494 | |||
495 | ------------------------------------------------------------------------ | ||
496 | -- | ||
497 | -- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar() | ||
498 | ------------------------------------------------------------------------ | ||
499 | function luaK:exp2reg(fs, e, reg) | ||
500 | self:discharge2reg(fs, e, reg) | ||
501 | if e.k == "VJMP" then | ||
502 | e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list | ||
503 | end | ||
504 | if self:hasjumps(e) then | ||
505 | local final -- position after whole expression | ||
506 | local p_f = self.NO_JUMP -- position of an eventual LOAD false | ||
507 | local p_t = self.NO_JUMP -- position of an eventual LOAD true | ||
508 | if self:need_value(fs, e.t, 1) or self:need_value(fs, e.f, 0) then | ||
509 | local fj = self.NO_JUMP -- first jump (over LOAD ops.) | ||
510 | if e.k ~= "VJMP" then | ||
511 | fj = self:jump(fs) | ||
512 | end | ||
513 | p_f = self:code_label(fs, reg, 0, 1) | ||
514 | p_t = self:code_label(fs, reg, 1, 0) | ||
515 | self:patchtohere(fs, fj) | ||
516 | end | ||
517 | final = self:getlabel(fs) | ||
518 | self:patchlistaux(fs, e.f, final, reg, p_f) | ||
519 | self:patchlistaux(fs, e.t, final, reg, p_t) | ||
520 | end | ||
521 | e.f, e.t = self.NO_JUMP, self.NO_JUMP | ||
522 | e.info = reg | ||
523 | e.k = "VNONRELOC" | ||
524 | end | ||
525 | |||
526 | ------------------------------------------------------------------------ | ||
527 | -- | ||
528 | -- * used in multiple locations | ||
529 | ------------------------------------------------------------------------ | ||
530 | function luaK:exp2nextreg(fs, e) | ||
531 | self:dischargevars(fs, e) | ||
532 | self:freeexp(fs, e) | ||
533 | self:reserveregs(fs, 1) | ||
534 | self:exp2reg(fs, e, fs.freereg - 1) | ||
535 | end | ||
536 | |||
537 | ------------------------------------------------------------------------ | ||
538 | -- | ||
539 | -- * used in multiple locations | ||
540 | ------------------------------------------------------------------------ | ||
541 | function luaK:exp2anyreg(fs, e) | ||
542 | self:dischargevars(fs, e) | ||
543 | if e.k == "VNONRELOC" then | ||
544 | if not self:hasjumps(e) then -- exp is already in a register | ||
545 | return e.info | ||
546 | end | ||
547 | if e.info >= fs.nactvar then -- reg. is not a local? | ||
548 | self:exp2reg(fs, e, e.info) -- put value on it | ||
549 | return e.info | ||
550 | end | ||
551 | end | ||
552 | self:exp2nextreg(fs, e) -- default | ||
553 | return e.info | ||
554 | end | ||
555 | |||
556 | ------------------------------------------------------------------------ | ||
557 | -- | ||
558 | -- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix() | ||
559 | -- * used in (lparser) luaY:index() | ||
560 | ------------------------------------------------------------------------ | ||
561 | function luaK:exp2val(fs, e) | ||
562 | if self:hasjumps(e) then | ||
563 | self:exp2anyreg(fs, e) | ||
564 | else | ||
565 | self:dischargevars(fs, e) | ||
566 | end | ||
567 | end | ||
568 | |||
569 | ------------------------------------------------------------------------ | ||
570 | -- | ||
571 | -- * used in multiple locations | ||
572 | ------------------------------------------------------------------------ | ||
573 | function luaK:exp2RK(fs, e) | ||
574 | self:exp2val(fs, e) | ||
575 | local k = e.k | ||
576 | if k == "VNIL" then | ||
577 | if fs.nk + luaY.MAXSTACK <= luaP.MAXARG_C then -- constant fit in argC? | ||
578 | e.info = self:nil_constant(fs) | ||
579 | e.k = "VK" | ||
580 | return e.info + luaY.MAXSTACK | ||
581 | end | ||
582 | elseif k == "VK" then | ||
583 | if e.info + luaY.MAXSTACK <= luaP.MAXARG_C then -- constant fit in argC? | ||
584 | return e.info + luaY.MAXSTACK | ||
585 | end | ||
586 | end | ||
587 | -- not a constant in the right range: put it in a register | ||
588 | return self:exp2anyreg(fs, e) | ||
589 | end | ||
590 | |||
591 | ------------------------------------------------------------------------ | ||
592 | -- | ||
593 | -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat() | ||
594 | ------------------------------------------------------------------------ | ||
595 | function luaK:storevar(fs, var, exp) | ||
596 | local k = var.k | ||
597 | if k == "VLOCAL" then | ||
598 | self:freeexp(fs, exp) | ||
599 | self:exp2reg(fs, exp, var.info) | ||
600 | return | ||
601 | elseif k == "VUPVAL" then | ||
602 | local e = self:exp2anyreg(fs, exp) | ||
603 | self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0) | ||
604 | elseif k == "VGLOBAL" then | ||
605 | local e = self:exp2anyreg(fs, exp) | ||
606 | self:codeABx(fs, "OP_SETGLOBAL", e, var.info) | ||
607 | elseif k == "VINDEXED" then | ||
608 | local e = self:exp2RK(fs, exp) | ||
609 | self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e) | ||
610 | else | ||
611 | lua_assert(0) -- invalid var kind to store | ||
612 | end | ||
613 | self:freeexp(fs, exp) | ||
614 | end | ||
615 | |||
616 | ------------------------------------------------------------------------ | ||
617 | -- | ||
618 | -- * used only in (lparser) luaY:primaryexp() | ||
619 | ------------------------------------------------------------------------ | ||
620 | function luaK:_self(fs, e, key) | ||
621 | self:exp2anyreg(fs, e) | ||
622 | self:freeexp(fs, e) | ||
623 | local func = fs.freereg | ||
624 | self:reserveregs(fs, 2) | ||
625 | self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key)) | ||
626 | self:freeexp(fs, key) | ||
627 | e.info = func | ||
628 | e.k = "VNONRELOC" | ||
629 | end | ||
630 | |||
631 | ------------------------------------------------------------------------ | ||
632 | -- | ||
633 | -- * used in luaK:goiftrue(), luaK:codenot() | ||
634 | ------------------------------------------------------------------------ | ||
635 | function luaK:invertjump(fs, e) | ||
636 | local pc = self:getjumpcontrol(fs, e.info) | ||
637 | lua_assert(luaP:testOpMode(luaP:GET_OPCODE(pc), "OpModeT") and | ||
638 | luaP:GET_OPCODE(pc) ~= "OP_TEST") | ||
639 | luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0) | ||
640 | end | ||
641 | |||
642 | ------------------------------------------------------------------------ | ||
643 | -- | ||
644 | -- * used in luaK:goiftrue(), luaK:goiffalse() | ||
645 | ------------------------------------------------------------------------ | ||
646 | function luaK:jumponcond(fs, e, cond) | ||
647 | if e.k == "VRELOCABLE" then | ||
648 | local ie = self:getcode(fs, e) | ||
649 | if luaP:GET_OPCODE(ie) == "OP_NOT" then | ||
650 | fs.pc = fs.pc - 1 -- remove previous OP_NOT | ||
651 | return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), luaP:GETARG_B(ie), | ||
652 | cond and 0 or 1) | ||
653 | end | ||
654 | -- else go through | ||
655 | end | ||
656 | self:discharge2anyreg(fs, e) | ||
657 | self:freeexp(fs, e) | ||
658 | return self:condjump(fs, "OP_TEST", luaP.NO_REG, e.info, cond and 1 or 0) | ||
659 | end | ||
660 | |||
661 | ------------------------------------------------------------------------ | ||
662 | -- | ||
663 | -- * used in luaK:infix(), (lparser) luaY:cond() | ||
664 | ------------------------------------------------------------------------ | ||
665 | function luaK:goiftrue(fs, e) | ||
666 | local pc -- pc of last jump | ||
667 | self:dischargevars(fs, e) | ||
668 | local k = e.k | ||
669 | if k == "VK" or k == "VTRUE" then | ||
670 | pc = self.NO_JUMP -- always true; do nothing | ||
671 | elseif k == "VFALSE" then | ||
672 | pc = self:jump(fs) -- always jump | ||
673 | elseif k == "VJMP" then | ||
674 | self:invertjump(fs, e) | ||
675 | pc = e.info | ||
676 | else | ||
677 | pc = self:jumponcond(fs, e, false) | ||
678 | end | ||
679 | e.f = self:concat(fs, e.f, pc) -- insert last jump in 'f' list | ||
680 | end | ||
681 | |||
682 | ------------------------------------------------------------------------ | ||
683 | -- | ||
684 | -- * used in luaK:infix(), (lparser) luaY:whilestat() | ||
685 | ------------------------------------------------------------------------ | ||
686 | function luaK:goiffalse(fs, e) | ||
687 | local pc -- pc of last jump | ||
688 | self:dischargevars(fs, e) | ||
689 | local k = e.k | ||
690 | if k == "VNIL" or k == "VFALSE"then | ||
691 | pc = self.NO_JUMP -- always false; do nothing | ||
692 | elseif k == "VTRUE" then | ||
693 | pc = self:jump(fs) -- always jump | ||
694 | elseif k == "VJMP" then | ||
695 | pc = e.info | ||
696 | else | ||
697 | pc = self:jumponcond(fs, e, true) | ||
698 | end | ||
699 | e.t = self:concat(fs, e.t, pc) -- insert last jump in 't' list | ||
700 | end | ||
701 | |||
702 | ------------------------------------------------------------------------ | ||
703 | -- | ||
704 | -- * used only in luaK:prefix() | ||
705 | ------------------------------------------------------------------------ | ||
706 | function luaK:codenot(fs, e) | ||
707 | self:dischargevars(fs, e) | ||
708 | local k = e.k | ||
709 | if k == "VNIL" or k == "VFALSE" then | ||
710 | e.k = "VTRUE" | ||
711 | elseif k == "VK" or k == "VTRUE" then | ||
712 | e.k = "VFALSE" | ||
713 | elseif k == "VJMP" then | ||
714 | self:invertjump(fs, e) | ||
715 | elseif k == "VRELOCABLE" or k == "VNONRELOC" then | ||
716 | self:discharge2anyreg(fs, e) | ||
717 | self:freeexp(fs, e) | ||
718 | e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0) | ||
719 | e.k = "VRELOCABLE" | ||
720 | else | ||
721 | lua_assert(0) -- cannot happen | ||
722 | end | ||
723 | -- interchange true and false lists | ||
724 | e.f, e.t = e.t, e.f | ||
725 | self:removevalues(fs, e.f) | ||
726 | self:removevalues(fs, e.t) | ||
727 | end | ||
728 | |||
729 | ------------------------------------------------------------------------ | ||
730 | -- | ||
731 | -- * used in (lparser) luaY:field(), luaY:primaryexp() | ||
732 | ------------------------------------------------------------------------ | ||
733 | function luaK:indexed(fs, t, k) | ||
734 | t.aux = self:exp2RK(fs, k) | ||
735 | t.k = "VINDEXED" | ||
736 | end | ||
737 | |||
738 | ------------------------------------------------------------------------ | ||
739 | -- | ||
740 | -- * used only in (lparser) luaY:subexpr() | ||
741 | ------------------------------------------------------------------------ | ||
742 | function luaK:prefix(fs, op, e) | ||
743 | if op == "OPR_MINUS" then | ||
744 | self:exp2val(fs, e) | ||
745 | if e.k == "VK" and self:ttisnumber(fs.f.k[e.info]) then | ||
746 | e.info = self:numberK(fs, -self:nvalue(fs.f.k[e.info])) | ||
747 | else | ||
748 | self:exp2anyreg(fs, e) | ||
749 | self:freeexp(fs, e) | ||
750 | e.info = self:codeABC(fs, "OP_UNM", 0, e.info, 0) | ||
751 | e.k = "VRELOCABLE" | ||
752 | end | ||
753 | else -- op == NOT | ||
754 | self:codenot(fs, e) | ||
755 | end | ||
756 | end | ||
757 | |||
758 | ------------------------------------------------------------------------ | ||
759 | -- | ||
760 | -- * used only in (lparser) luaY:subexpr() | ||
761 | ------------------------------------------------------------------------ | ||
762 | function luaK:infix(fs, op, v) | ||
763 | if op == "OPR_AND" then | ||
764 | self:goiftrue(fs, v) | ||
765 | self:patchtohere(fs, v.t) | ||
766 | v.t = self.NO_JUMP | ||
767 | elseif op == "OPR_OR" then | ||
768 | self:goiffalse(fs, v) | ||
769 | self:patchtohere(fs, v.f) | ||
770 | v.f = self.NO_JUMP | ||
771 | elseif op == "OPR_CONCAT" then | ||
772 | self:exp2nextreg(fs, v) -- operand must be on the 'stack' | ||
773 | else | ||
774 | self:exp2RK(fs, v) | ||
775 | end | ||
776 | end | ||
777 | |||
778 | ------------------------------------------------------------------------ | ||
779 | -- | ||
780 | -- grep "ORDER OPR" if you change these enums | ||
781 | -- * used only in luaK:posfix() | ||
782 | ------------------------------------------------------------------------ | ||
783 | luaK.arith_opc = { -- done as a table lookup instead of a calc | ||
784 | OPR_ADD = "OP_ADD", | ||
785 | OPR_SUB = "OP_SUB", | ||
786 | OPR_MULT = "OP_MUL", | ||
787 | OPR_DIV = "OP_DIV", | ||
788 | OPR_POW = "OP_POW", | ||
789 | } | ||
790 | luaK.test_opc = { -- was ops[] in the codebinop function | ||
791 | OPR_NE = "OP_EQ", | ||
792 | OPR_EQ = "OP_EQ", | ||
793 | OPR_LT = "OP_LT", | ||
794 | OPR_LE = "OP_LE", | ||
795 | OPR_GT = "OP_LT", | ||
796 | OPR_GE = "OP_LE", | ||
797 | } | ||
798 | function luaK:codebinop(fs, res, op, o1, o2) | ||
799 | if self.BinOpr[op] <= self.BinOpr["OPR_POW"] then -- arithmetic operator? | ||
800 | local opc = self.arith_opc[op] -- ORDER OP | ||
801 | res.info = self:codeABC(fs, opc, 0, o1, o2) | ||
802 | res.k = "VRELOCABLE" | ||
803 | else -- test operator | ||
804 | local cond = true | ||
805 | if self.BinOpr[op] >= self.BinOpr["OPR_GT"] then -- '>' or '>='? | ||
806 | -- exchange args and replace by '<' or '<=' | ||
807 | o1, o2 = o2, o1 -- o1 <==> o2 | ||
808 | elseif op == "OPR_NE" then | ||
809 | cond = false | ||
810 | end | ||
811 | res.info = self:condjump(fs, self.test_opc[op], cond and 1 or 0, o1, o2) | ||
812 | res.k = "VJMP" | ||
813 | end | ||
814 | end | ||
815 | |||
816 | ------------------------------------------------------------------------ | ||
817 | -- | ||
818 | -- * used only in (lparser) luaY:subexpr() | ||
819 | ------------------------------------------------------------------------ | ||
820 | function luaK:posfix(fs, op, e1, e2) | ||
821 | if op == "OPR_AND" then | ||
822 | lua_assert(e1.t == self.NO_JUMP) -- list must be closed | ||
823 | self:dischargevars(fs, e2) | ||
824 | e1.f = self:concat(fs, e1.f, e2.f) | ||
825 | e1.k = e2.k; e1.info = e2.info; e1.aux = e2.aux; e1.t = e2.t | ||
826 | elseif op == "OPR_OR" then | ||
827 | lua_assert(e1.f == self.NO_JUMP) -- list must be closed | ||
828 | self:dischargevars(fs, e2) | ||
829 | e1.t = self:concat(fs, e1.t, e2.t) | ||
830 | e1.k = e2.k; e1.info = e2.info; e1.aux = e2.aux; e1.f = e2.f | ||
831 | elseif op == "OPR_CONCAT" then | ||
832 | self:exp2val(fs, e2) | ||
833 | if e2.k == "VRELOCABLE" | ||
834 | and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then | ||
835 | lua_assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1) | ||
836 | self:freeexp(fs, e1) | ||
837 | luaP:SETARG_B(self:getcode(fs, e2), e1.info) | ||
838 | e1.k = e2.k; e1.info = e2.info | ||
839 | else | ||
840 | self:exp2nextreg(fs, e2) | ||
841 | self:freeexp(fs, e2) | ||
842 | self:freeexp(fs, e1) | ||
843 | e1.info = self:codeABC(fs, "OP_CONCAT", 0, e1.info, e2.info) | ||
844 | e1.k = "VRELOCABLE" | ||
845 | end | ||
846 | else | ||
847 | local o1 = self:exp2RK(fs, e1) | ||
848 | local o2 = self:exp2RK(fs, e2) | ||
849 | self:freeexp(fs, e2) | ||
850 | self:freeexp(fs, e1) | ||
851 | self:codebinop(fs, e1, op, o1, o2) | ||
852 | end | ||
853 | end | ||
854 | |||
855 | ------------------------------------------------------------------------ | ||
856 | -- adjusts debug information for last instruction written, in order to | ||
857 | -- change the line where item comes into existence | ||
858 | -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat() | ||
859 | ------------------------------------------------------------------------ | ||
860 | function luaK:fixline(fs, line) | ||
861 | fs.f.lineinfo[fs.pc - 1] = line | ||
862 | end | ||
863 | |||
864 | ------------------------------------------------------------------------ | ||
865 | -- general function to write an instruction into the instruction buffer, | ||
866 | -- sets debug information too | ||
867 | -- * used in luaK:codeABC(), luaK:codeABx() | ||
868 | -- * called directly by (lparser) luaY:whilestat() | ||
869 | ------------------------------------------------------------------------ | ||
870 | function luaK:code(fs, i, line) | ||
871 | local f = fs.f | ||
872 | self:dischargejpc(fs) -- 'pc' will change | ||
873 | -- put new instruction in code array | ||
874 | luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil, | ||
875 | luaY.MAX_INT, "code size overflow") | ||
876 | f.code[fs.pc] = i | ||
877 | -- save corresponding line information | ||
878 | luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil, | ||
879 | luaY.MAX_INT, "code size overflow") | ||
880 | f.lineinfo[fs.pc] = line | ||
881 | local pc = fs.pc | ||
882 | fs.pc = fs.pc + 1 | ||
883 | return pc | ||
884 | end | ||
885 | |||
886 | ------------------------------------------------------------------------ | ||
887 | -- writes an instruction of type ABC | ||
888 | -- * calls luaK:code() | ||
889 | ------------------------------------------------------------------------ | ||
890 | function luaK:codeABC(fs, o, a, b, c) | ||
891 | lua_assert(luaP:getOpMode(o) == "iABC") | ||
892 | return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline) | ||
893 | end | ||
894 | |||
895 | ------------------------------------------------------------------------ | ||
896 | -- writes an instruction of type ABx | ||
897 | -- * calls luaK:code(), called by luaK:codeAsBx() | ||
898 | ------------------------------------------------------------------------ | ||
899 | function luaK:codeABx(fs, o, a, bc) | ||
900 | lua_assert(luaP:getOpMode(o) == "iABx" or luaP:getOpMode(o) == "iAsBx") | ||
901 | return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline) | ||
902 | end | ||