diff options
Diffstat (limited to '')
-rw-r--r-- | LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua | 1125 |
1 files changed, 1125 insertions, 0 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua new file mode 100644 index 0000000..4dc8548 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua | |||
@@ -0,0 +1,1125 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | lcode.lua | ||
4 | Lua 5 code generator in Lua | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2005-2007 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 | -- * luaM_growvector uses the faux luaY:growvector, for limit checking | ||
21 | -- * some function parameters changed to boolean, additional code | ||
22 | -- translates boolean back to 1/0 for instruction fields | ||
23 | -- | ||
24 | -- Not implemented: | ||
25 | -- * NOTE there is a failed assert in luaK:addk, a porting problem | ||
26 | -- | ||
27 | -- Added: | ||
28 | -- * constant MAXSTACK from llimits.h | ||
29 | -- * luaK:ttisnumber(o) (from lobject.h) | ||
30 | -- * luaK:nvalue(o) (from lobject.h) | ||
31 | -- * luaK:setnilvalue(o) (from lobject.h) | ||
32 | -- * luaK:setnvalue(o, x) (from lobject.h) | ||
33 | -- * luaK:setbvalue(o, x) (from lobject.h) | ||
34 | -- * luaK:sethvalue(o, x) (from lobject.h), parameter L deleted | ||
35 | -- * luaK:setsvalue(o, x) (from lobject.h), parameter L deleted | ||
36 | -- * luaK:numadd, luaK:numsub, luaK:nummul, luaK:numdiv, luaK:nummod, | ||
37 | -- luaK:numpow, luaK:numunm, luaK:numisnan (from luaconf.h) | ||
38 | -- * copyexp(e1, e2) added in luaK:posfix to copy expdesc struct | ||
39 | -- | ||
40 | -- Changed in 5.1.x: | ||
41 | -- * enum BinOpr has a new entry, OPR_MOD | ||
42 | -- * enum UnOpr has a new entry, OPR_LEN | ||
43 | -- * binopistest, unused in 5.0.x, has been deleted | ||
44 | -- * macro setmultret is new | ||
45 | -- * functions isnumeral, luaK_ret, boolK are new | ||
46 | -- * funcion nilK was named nil_constant in 5.0.x | ||
47 | -- * function interface changed: need_value, patchtestreg, concat | ||
48 | -- * TObject now a TValue | ||
49 | -- * functions luaK_setreturns, luaK_setoneret are new | ||
50 | -- * function luaK:setcallreturns deleted, to be replaced by: | ||
51 | -- luaK:setmultret, luaK:ret, luaK:setreturns, luaK:setoneret | ||
52 | -- * functions constfolding, codearith, codecomp are new | ||
53 | -- * luaK:codebinop has been deleted | ||
54 | -- * function luaK_setlist is new | ||
55 | -- * OPR_MULT renamed to OPR_MUL | ||
56 | ----------------------------------------------------------------------]] | ||
57 | |||
58 | -- requires luaP, luaX, luaY | ||
59 | luaK = {} | ||
60 | |||
61 | ------------------------------------------------------------------------ | ||
62 | -- constants used by code generator | ||
63 | ------------------------------------------------------------------------ | ||
64 | -- maximum stack for a Lua function | ||
65 | luaK.MAXSTACK = 250 -- (from llimits.h) | ||
66 | |||
67 | --[[-------------------------------------------------------------------- | ||
68 | -- other functions | ||
69 | ----------------------------------------------------------------------]] | ||
70 | |||
71 | ------------------------------------------------------------------------ | ||
72 | -- emulation of TValue macros (these are from lobject.h) | ||
73 | -- * TValue is a table since lcode passes references around | ||
74 | -- * tt member field removed, using Lua's type() instead | ||
75 | -- * for setsvalue, sethvalue, parameter L (deleted here) in lobject.h | ||
76 | -- is used in an assert for testing, see checkliveness(g,obj) | ||
77 | ------------------------------------------------------------------------ | ||
78 | function luaK:ttisnumber(o) | ||
79 | if o then return type(o.value) == "number" else return false end | ||
80 | end | ||
81 | function luaK:nvalue(o) return o.value end | ||
82 | function luaK:setnilvalue(o) o.value = nil end | ||
83 | function luaK:setsvalue(o, x) o.value = x end | ||
84 | luaK.setnvalue = luaK.setsvalue | ||
85 | luaK.sethvalue = luaK.setsvalue | ||
86 | luaK.setbvalue = luaK.setsvalue | ||
87 | |||
88 | ------------------------------------------------------------------------ | ||
89 | -- The luai_num* macros define the primitive operations over numbers. | ||
90 | -- * this is not the entire set of primitive operations from luaconf.h | ||
91 | -- * used in luaK:constfolding() | ||
92 | ------------------------------------------------------------------------ | ||
93 | function luaK:numadd(a, b) return a + b end | ||
94 | function luaK:numsub(a, b) return a - b end | ||
95 | function luaK:nummul(a, b) return a * b end | ||
96 | function luaK:numdiv(a, b) return a / b end | ||
97 | function luaK:nummod(a, b) return a % b end | ||
98 | -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */ | ||
99 | function luaK:numpow(a, b) return a ^ b end | ||
100 | function luaK:numunm(a) return -a end | ||
101 | function luaK:numisnan(a) return not a == a end | ||
102 | -- a NaN cannot equal another NaN | ||
103 | |||
104 | --[[-------------------------------------------------------------------- | ||
105 | -- code generator functions | ||
106 | ----------------------------------------------------------------------]] | ||
107 | |||
108 | ------------------------------------------------------------------------ | ||
109 | -- Marks the end of a patch list. It is an invalid value both as an absolute | ||
110 | -- address, and as a list link (would link an element to itself). | ||
111 | ------------------------------------------------------------------------ | ||
112 | luaK.NO_JUMP = -1 | ||
113 | |||
114 | ------------------------------------------------------------------------ | ||
115 | -- grep "ORDER OPR" if you change these enums | ||
116 | ------------------------------------------------------------------------ | ||
117 | luaK.BinOpr = { | ||
118 | OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5, | ||
119 | OPR_CONCAT = 6, | ||
120 | OPR_NE = 7, OPR_EQ = 8, | ||
121 | OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12, | ||
122 | OPR_AND = 13, OPR_OR = 14, | ||
123 | OPR_NOBINOPR = 15, | ||
124 | } | ||
125 | |||
126 | -- * UnOpr is used by luaK:prefix's op argument, but not directly used | ||
127 | -- because the function receives the symbols as strings, e.g. "OPR_NOT" | ||
128 | luaK.UnOpr = { | ||
129 | OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3 | ||
130 | } | ||
131 | |||
132 | ------------------------------------------------------------------------ | ||
133 | -- returns the instruction object for given e (expdesc), was a macro | ||
134 | ------------------------------------------------------------------------ | ||
135 | function luaK:getcode(fs, e) | ||
136 | return fs.f.code[e.info] | ||
137 | end | ||
138 | |||
139 | ------------------------------------------------------------------------ | ||
140 | -- codes an instruction with a signed Bx (sBx) field, was a macro | ||
141 | -- * used in luaK:jump(), (lparser) luaY:forbody() | ||
142 | ------------------------------------------------------------------------ | ||
143 | function luaK:codeAsBx(fs, o, A, sBx) | ||
144 | return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx) | ||
145 | end | ||
146 | |||
147 | ------------------------------------------------------------------------ | ||
148 | -- set the expdesc e instruction for multiple returns, was a macro | ||
149 | ------------------------------------------------------------------------ | ||
150 | function luaK:setmultret(fs, e) | ||
151 | self:setreturns(fs, e, luaY.LUA_MULTRET) | ||
152 | end | ||
153 | |||
154 | ------------------------------------------------------------------------ | ||
155 | -- there is a jump if patch lists are not identical, was a macro | ||
156 | -- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val() | ||
157 | ------------------------------------------------------------------------ | ||
158 | function luaK:hasjumps(e) | ||
159 | return e.t ~= e.f | ||
160 | end | ||
161 | |||
162 | ------------------------------------------------------------------------ | ||
163 | -- true if the expression is a constant number (for constant folding) | ||
164 | -- * used in constfolding(), infix() | ||
165 | ------------------------------------------------------------------------ | ||
166 | function luaK:isnumeral(e) | ||
167 | return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP | ||
168 | end | ||
169 | |||
170 | ------------------------------------------------------------------------ | ||
171 | -- codes loading of nil, optimization done if consecutive locations | ||
172 | -- * used in luaK:discharge2reg(), (lparser) luaY:adjust_assign() | ||
173 | ------------------------------------------------------------------------ | ||
174 | function luaK:_nil(fs, from, n) | ||
175 | if fs.pc > fs.lasttarget then -- no jumps to current position? | ||
176 | if fs.pc == 0 then -- function start? | ||
177 | if from >= fs.nactvar then | ||
178 | return -- positions are already clean | ||
179 | end | ||
180 | else | ||
181 | local previous = fs.f.code[fs.pc - 1] | ||
182 | if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then | ||
183 | local pfrom = luaP:GETARG_A(previous) | ||
184 | local pto = luaP:GETARG_B(previous) | ||
185 | if pfrom <= from and from <= pto + 1 then -- can connect both? | ||
186 | if from + n - 1 > pto then | ||
187 | luaP:SETARG_B(previous, from + n - 1) | ||
188 | end | ||
189 | return | ||
190 | end | ||
191 | end | ||
192 | end | ||
193 | end | ||
194 | self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization | ||
195 | end | ||
196 | |||
197 | ------------------------------------------------------------------------ | ||
198 | -- | ||
199 | -- * used in multiple locations | ||
200 | ------------------------------------------------------------------------ | ||
201 | function luaK:jump(fs) | ||
202 | local jpc = fs.jpc -- save list of jumps to here | ||
203 | fs.jpc = self.NO_JUMP | ||
204 | local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP) | ||
205 | j = self:concat(fs, j, jpc) -- keep them on hold | ||
206 | return j | ||
207 | end | ||
208 | |||
209 | ------------------------------------------------------------------------ | ||
210 | -- codes a RETURN instruction | ||
211 | -- * used in luaY:close_func(), luaY:retstat() | ||
212 | ------------------------------------------------------------------------ | ||
213 | function luaK:ret(fs, first, nret) | ||
214 | self:codeABC(fs, "OP_RETURN", first, nret + 1, 0) | ||
215 | end | ||
216 | |||
217 | ------------------------------------------------------------------------ | ||
218 | -- | ||
219 | -- * used in luaK:jumponcond(), luaK:codecomp() | ||
220 | ------------------------------------------------------------------------ | ||
221 | function luaK:condjump(fs, op, A, B, C) | ||
222 | self:codeABC(fs, op, A, B, C) | ||
223 | return self:jump(fs) | ||
224 | end | ||
225 | |||
226 | ------------------------------------------------------------------------ | ||
227 | -- | ||
228 | -- * used in luaK:patchlistaux(), luaK:concat() | ||
229 | ------------------------------------------------------------------------ | ||
230 | function luaK:fixjump(fs, pc, dest) | ||
231 | local jmp = fs.f.code[pc] | ||
232 | local offset = dest - (pc + 1) | ||
233 | lua_assert(dest ~= self.NO_JUMP) | ||
234 | if math.abs(offset) > luaP.MAXARG_sBx then | ||
235 | luaX:syntaxerror(fs.ls, "control structure too long") | ||
236 | end | ||
237 | luaP:SETARG_sBx(jmp, offset) | ||
238 | end | ||
239 | |||
240 | ------------------------------------------------------------------------ | ||
241 | -- returns current 'pc' and marks it as a jump target (to avoid wrong | ||
242 | -- optimizations with consecutive instructions not in the same basic block). | ||
243 | -- * used in multiple locations | ||
244 | -- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL | ||
245 | ------------------------------------------------------------------------ | ||
246 | function luaK:getlabel(fs) | ||
247 | fs.lasttarget = fs.pc | ||
248 | return fs.pc | ||
249 | end | ||
250 | |||
251 | ------------------------------------------------------------------------ | ||
252 | -- | ||
253 | -- * used in luaK:need_value(), luaK:removevalues(), luaK:patchlistaux(), | ||
254 | -- luaK:concat() | ||
255 | ------------------------------------------------------------------------ | ||
256 | function luaK:getjump(fs, pc) | ||
257 | local offset = luaP:GETARG_sBx(fs.f.code[pc]) | ||
258 | if offset == self.NO_JUMP then -- point to itself represents end of list | ||
259 | return self.NO_JUMP -- end of list | ||
260 | else | ||
261 | return (pc + 1) + offset -- turn offset into absolute position | ||
262 | end | ||
263 | end | ||
264 | |||
265 | ------------------------------------------------------------------------ | ||
266 | -- | ||
267 | -- * used in luaK:need_value(), luaK:patchtestreg(), luaK:invertjump() | ||
268 | ------------------------------------------------------------------------ | ||
269 | function luaK:getjumpcontrol(fs, pc) | ||
270 | local pi = fs.f.code[pc] | ||
271 | local ppi = fs.f.code[pc - 1] | ||
272 | if pc >= 1 and luaP:testTMode(luaP:GET_OPCODE(ppi)) ~= 0 then | ||
273 | return ppi | ||
274 | else | ||
275 | return pi | ||
276 | end | ||
277 | end | ||
278 | |||
279 | ------------------------------------------------------------------------ | ||
280 | -- check whether list has any jump that do not produce a value | ||
281 | -- (or produce an inverted value) | ||
282 | -- * return value changed to boolean | ||
283 | -- * used only in luaK:exp2reg() | ||
284 | ------------------------------------------------------------------------ | ||
285 | function luaK:need_value(fs, list) | ||
286 | while list ~= self.NO_JUMP do | ||
287 | local i = self:getjumpcontrol(fs, list) | ||
288 | if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then return true end | ||
289 | list = self:getjump(fs, list) | ||
290 | end | ||
291 | return false -- not found | ||
292 | end | ||
293 | |||
294 | ------------------------------------------------------------------------ | ||
295 | -- | ||
296 | -- * used in luaK:removevalues(), luaK:patchlistaux() | ||
297 | ------------------------------------------------------------------------ | ||
298 | function luaK:patchtestreg(fs, node, reg) | ||
299 | local i = self:getjumpcontrol(fs, node) | ||
300 | if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then | ||
301 | return false -- cannot patch other instructions | ||
302 | end | ||
303 | if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then | ||
304 | luaP:SETARG_A(i, reg) | ||
305 | else -- no register to put value or register already has the value | ||
306 | -- due to use of a table as i, i cannot be replaced by another table | ||
307 | -- so the following is required; there is no change to ARG_C | ||
308 | luaP:SET_OPCODE(i, "OP_TEST") | ||
309 | local b = luaP:GETARG_B(i) | ||
310 | luaP:SETARG_A(i, b) | ||
311 | luaP:SETARG_B(i, 0) | ||
312 | -- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); /* C */ | ||
313 | end | ||
314 | return true | ||
315 | end | ||
316 | |||
317 | ------------------------------------------------------------------------ | ||
318 | -- | ||
319 | -- * used only in luaK:codenot() | ||
320 | ------------------------------------------------------------------------ | ||
321 | function luaK:removevalues(fs, list) | ||
322 | while list ~= self.NO_JUMP do | ||
323 | self:patchtestreg(fs, list, luaP.NO_REG) | ||
324 | list = self:getjump(fs, list) | ||
325 | end | ||
326 | end | ||
327 | |||
328 | ------------------------------------------------------------------------ | ||
329 | -- | ||
330 | -- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg() | ||
331 | ------------------------------------------------------------------------ | ||
332 | function luaK:patchlistaux(fs, list, vtarget, reg, dtarget) | ||
333 | while list ~= self.NO_JUMP do | ||
334 | local _next = self:getjump(fs, list) | ||
335 | if self:patchtestreg(fs, list, reg) then | ||
336 | self:fixjump(fs, list, vtarget) | ||
337 | else | ||
338 | self:fixjump(fs, list, dtarget) -- jump to default target | ||
339 | end | ||
340 | list = _next | ||
341 | end | ||
342 | end | ||
343 | |||
344 | ------------------------------------------------------------------------ | ||
345 | -- | ||
346 | -- * used only in luaK:code() | ||
347 | ------------------------------------------------------------------------ | ||
348 | function luaK:dischargejpc(fs) | ||
349 | self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc) | ||
350 | fs.jpc = self.NO_JUMP | ||
351 | end | ||
352 | |||
353 | ------------------------------------------------------------------------ | ||
354 | -- | ||
355 | -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody() | ||
356 | ------------------------------------------------------------------------ | ||
357 | function luaK:patchlist(fs, list, target) | ||
358 | if target == fs.pc then | ||
359 | self:patchtohere(fs, list) | ||
360 | else | ||
361 | lua_assert(target < fs.pc) | ||
362 | self:patchlistaux(fs, list, target, luaP.NO_REG, target) | ||
363 | end | ||
364 | end | ||
365 | |||
366 | ------------------------------------------------------------------------ | ||
367 | -- | ||
368 | -- * used in multiple locations | ||
369 | ------------------------------------------------------------------------ | ||
370 | function luaK:patchtohere(fs, list) | ||
371 | self:getlabel(fs) | ||
372 | fs.jpc = self:concat(fs, fs.jpc, list) | ||
373 | end | ||
374 | |||
375 | ------------------------------------------------------------------------ | ||
376 | -- * l1 was a pointer, now l1 is returned and callee assigns the value | ||
377 | -- * used in multiple locations | ||
378 | ------------------------------------------------------------------------ | ||
379 | function luaK:concat(fs, l1, l2) | ||
380 | if l2 == self.NO_JUMP then return l1 | ||
381 | elseif l1 == self.NO_JUMP then | ||
382 | return l2 | ||
383 | else | ||
384 | local list = l1 | ||
385 | local _next = self:getjump(fs, list) | ||
386 | while _next ~= self.NO_JUMP do -- find last element | ||
387 | list = _next | ||
388 | _next = self:getjump(fs, list) | ||
389 | end | ||
390 | self:fixjump(fs, list, l2) | ||
391 | end | ||
392 | return l1 | ||
393 | end | ||
394 | |||
395 | ------------------------------------------------------------------------ | ||
396 | -- | ||
397 | -- * used in luaK:reserveregs(), (lparser) luaY:forlist() | ||
398 | ------------------------------------------------------------------------ | ||
399 | function luaK:checkstack(fs, n) | ||
400 | local newstack = fs.freereg + n | ||
401 | if newstack > fs.f.maxstacksize then | ||
402 | if newstack >= self.MAXSTACK then | ||
403 | luaX:syntaxerror(fs.ls, "function or expression too complex") | ||
404 | end | ||
405 | fs.f.maxstacksize = newstack | ||
406 | end | ||
407 | end | ||
408 | |||
409 | ------------------------------------------------------------------------ | ||
410 | -- | ||
411 | -- * used in multiple locations | ||
412 | ------------------------------------------------------------------------ | ||
413 | function luaK:reserveregs(fs, n) | ||
414 | self:checkstack(fs, n) | ||
415 | fs.freereg = fs.freereg + n | ||
416 | end | ||
417 | |||
418 | ------------------------------------------------------------------------ | ||
419 | -- | ||
420 | -- * used in luaK:freeexp(), luaK:dischargevars() | ||
421 | ------------------------------------------------------------------------ | ||
422 | function luaK:freereg(fs, reg) | ||
423 | if not luaP:ISK(reg) and reg >= fs.nactvar then | ||
424 | fs.freereg = fs.freereg - 1 | ||
425 | lua_assert(reg == fs.freereg) | ||
426 | end | ||
427 | end | ||
428 | |||
429 | ------------------------------------------------------------------------ | ||
430 | -- | ||
431 | -- * used in multiple locations | ||
432 | ------------------------------------------------------------------------ | ||
433 | function luaK:freeexp(fs, e) | ||
434 | if e.k == "VNONRELOC" then | ||
435 | self:freereg(fs, e.info) | ||
436 | end | ||
437 | end | ||
438 | |||
439 | ------------------------------------------------------------------------ | ||
440 | -- * TODO NOTE implementation is not 100% correct, since the assert fails | ||
441 | -- * luaH_set, setobj deleted; direct table access used instead | ||
442 | -- * used in luaK:stringK(), luaK:numberK(), luaK:boolK(), luaK:nilK() | ||
443 | ------------------------------------------------------------------------ | ||
444 | function luaK:addk(fs, k, v) | ||
445 | local L = fs.L | ||
446 | local idx = fs.h[k.value] | ||
447 | --TValue *idx = luaH_set(L, fs->h, k); /* C */ | ||
448 | local f = fs.f | ||
449 | if self:ttisnumber(idx) then | ||
450 | --TODO this assert currently FAILS (last tested for 5.0.2) | ||
451 | --lua_assert(fs.f.k[self:nvalue(idx)] == v) | ||
452 | --lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); /* C */ | ||
453 | return self:nvalue(idx) | ||
454 | else -- constant not found; create a new entry | ||
455 | idx = {} | ||
456 | self:setnvalue(idx, fs.nk) | ||
457 | fs.h[k.value] = idx | ||
458 | -- setnvalue(idx, cast_num(fs->nk)); /* C */ | ||
459 | luaY:growvector(L, f.k, fs.nk, f.sizek, nil, | ||
460 | luaP.MAXARG_Bx, "constant table overflow") | ||
461 | -- loop to initialize empty f.k positions not required | ||
462 | f.k[fs.nk] = v | ||
463 | -- setobj(L, &f->k[fs->nk], v); /* C */ | ||
464 | -- luaC_barrier(L, f, v); /* GC */ | ||
465 | local nk = fs.nk | ||
466 | fs.nk = fs.nk + 1 | ||
467 | return nk | ||
468 | end | ||
469 | |||
470 | end | ||
471 | |||
472 | ------------------------------------------------------------------------ | ||
473 | -- creates and sets a string object | ||
474 | -- * used in (lparser) luaY:codestring(), luaY:singlevar() | ||
475 | ------------------------------------------------------------------------ | ||
476 | function luaK:stringK(fs, s) | ||
477 | local o = {} -- TValue | ||
478 | self:setsvalue(o, s) | ||
479 | return self:addk(fs, o, o) | ||
480 | end | ||
481 | |||
482 | ------------------------------------------------------------------------ | ||
483 | -- creates and sets a number object | ||
484 | -- * used in luaK:prefix() for negative (or negation of) numbers | ||
485 | -- * used in (lparser) luaY:simpleexp(), luaY:fornum() | ||
486 | ------------------------------------------------------------------------ | ||
487 | function luaK:numberK(fs, r) | ||
488 | local o = {} -- TValue | ||
489 | self:setnvalue(o, r) | ||
490 | return self:addk(fs, o, o) | ||
491 | end | ||
492 | |||
493 | ------------------------------------------------------------------------ | ||
494 | -- creates and sets a boolean object | ||
495 | -- * used only in luaK:exp2RK() | ||
496 | ------------------------------------------------------------------------ | ||
497 | function luaK:boolK(fs, b) | ||
498 | local o = {} -- TValue | ||
499 | self:setbvalue(o, b) | ||
500 | return self:addk(fs, o, o) | ||
501 | end | ||
502 | |||
503 | ------------------------------------------------------------------------ | ||
504 | -- creates and sets a nil object | ||
505 | -- * used only in luaK:exp2RK() | ||
506 | ------------------------------------------------------------------------ | ||
507 | function luaK:nilK(fs) | ||
508 | local k, v = {}, {} -- TValue | ||
509 | self:setnilvalue(v) | ||
510 | -- cannot use nil as key; instead use table itself to represent nil | ||
511 | self:sethvalue(k, fs.h) | ||
512 | return self:addk(fs, k, v) | ||
513 | end | ||
514 | |||
515 | ------------------------------------------------------------------------ | ||
516 | -- | ||
517 | -- * used in luaK:setmultret(), (lparser) luaY:adjust_assign() | ||
518 | ------------------------------------------------------------------------ | ||
519 | function luaK:setreturns(fs, e, nresults) | ||
520 | if e.k == "VCALL" then -- expression is an open function call? | ||
521 | luaP:SETARG_C(self:getcode(fs, e), nresults + 1) | ||
522 | elseif e.k == "VVARARG" then | ||
523 | luaP:SETARG_B(self:getcode(fs, e), nresults + 1); | ||
524 | luaP:SETARG_A(self:getcode(fs, e), fs.freereg); | ||
525 | luaK:reserveregs(fs, 1) | ||
526 | end | ||
527 | end | ||
528 | |||
529 | ------------------------------------------------------------------------ | ||
530 | -- | ||
531 | -- * used in luaK:dischargevars(), (lparser) luaY:assignment() | ||
532 | ------------------------------------------------------------------------ | ||
533 | function luaK:setoneret(fs, e) | ||
534 | if e.k == "VCALL" then -- expression is an open function call? | ||
535 | e.k = "VNONRELOC" | ||
536 | e.info = luaP:GETARG_A(self:getcode(fs, e)) | ||
537 | elseif e.k == "VVARARG" then | ||
538 | luaP:SETARG_B(self:getcode(fs, e), 2) | ||
539 | e.k = "VRELOCABLE" -- can relocate its simple result | ||
540 | end | ||
541 | end | ||
542 | |||
543 | ------------------------------------------------------------------------ | ||
544 | -- | ||
545 | -- * used in multiple locations | ||
546 | ------------------------------------------------------------------------ | ||
547 | function luaK:dischargevars(fs, e) | ||
548 | local k = e.k | ||
549 | if k == "VLOCAL" then | ||
550 | e.k = "VNONRELOC" | ||
551 | elseif k == "VUPVAL" then | ||
552 | e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0) | ||
553 | e.k = "VRELOCABLE" | ||
554 | elseif k == "VGLOBAL" then | ||
555 | e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info) | ||
556 | e.k = "VRELOCABLE" | ||
557 | elseif k == "VINDEXED" then | ||
558 | self:freereg(fs, e.aux) | ||
559 | self:freereg(fs, e.info) | ||
560 | e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux) | ||
561 | e.k = "VRELOCABLE" | ||
562 | elseif k == "VVARARG" or k == "VCALL" then | ||
563 | self:setoneret(fs, e) | ||
564 | else | ||
565 | -- there is one value available (somewhere) | ||
566 | end | ||
567 | end | ||
568 | |||
569 | ------------------------------------------------------------------------ | ||
570 | -- | ||
571 | -- * used only in luaK:exp2reg() | ||
572 | ------------------------------------------------------------------------ | ||
573 | function luaK:code_label(fs, A, b, jump) | ||
574 | self:getlabel(fs) -- those instructions may be jump targets | ||
575 | return self:codeABC(fs, "OP_LOADBOOL", A, b, jump) | ||
576 | end | ||
577 | |||
578 | ------------------------------------------------------------------------ | ||
579 | -- | ||
580 | -- * used in luaK:discharge2anyreg(), luaK:exp2reg() | ||
581 | ------------------------------------------------------------------------ | ||
582 | function luaK:discharge2reg(fs, e, reg) | ||
583 | self:dischargevars(fs, e) | ||
584 | local k = e.k | ||
585 | if k == "VNIL" then | ||
586 | self:_nil(fs, reg, 1) | ||
587 | elseif k == "VFALSE" or k == "VTRUE" then | ||
588 | self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0) | ||
589 | elseif k == "VK" then | ||
590 | self:codeABx(fs, "OP_LOADK", reg, e.info) | ||
591 | elseif k == "VKNUM" then | ||
592 | self:codeABx(fs, "OP_LOADK", reg, self:numberK(fs, e.nval)) | ||
593 | elseif k == "VRELOCABLE" then | ||
594 | local pc = self:getcode(fs, e) | ||
595 | luaP:SETARG_A(pc, reg) | ||
596 | elseif k == "VNONRELOC" then | ||
597 | if reg ~= e.info then | ||
598 | self:codeABC(fs, "OP_MOVE", reg, e.info, 0) | ||
599 | end | ||
600 | else | ||
601 | lua_assert(e.k == "VVOID" or e.k == "VJMP") | ||
602 | return -- nothing to do... | ||
603 | end | ||
604 | e.info = reg | ||
605 | e.k = "VNONRELOC" | ||
606 | end | ||
607 | |||
608 | ------------------------------------------------------------------------ | ||
609 | -- | ||
610 | -- * used in luaK:jumponcond(), luaK:codenot() | ||
611 | ------------------------------------------------------------------------ | ||
612 | function luaK:discharge2anyreg(fs, e) | ||
613 | if e.k ~= "VNONRELOC" then | ||
614 | self:reserveregs(fs, 1) | ||
615 | self:discharge2reg(fs, e, fs.freereg - 1) | ||
616 | end | ||
617 | end | ||
618 | |||
619 | ------------------------------------------------------------------------ | ||
620 | -- | ||
621 | -- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar() | ||
622 | ------------------------------------------------------------------------ | ||
623 | function luaK:exp2reg(fs, e, reg) | ||
624 | self:discharge2reg(fs, e, reg) | ||
625 | if e.k == "VJMP" then | ||
626 | e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list | ||
627 | end | ||
628 | if self:hasjumps(e) then | ||
629 | local final -- position after whole expression | ||
630 | local p_f = self.NO_JUMP -- position of an eventual LOAD false | ||
631 | local p_t = self.NO_JUMP -- position of an eventual LOAD true | ||
632 | if self:need_value(fs, e.t) or self:need_value(fs, e.f) then | ||
633 | local fj = (e.k == "VJMP") and self.NO_JUMP or self:jump(fs) | ||
634 | p_f = self:code_label(fs, reg, 0, 1) | ||
635 | p_t = self:code_label(fs, reg, 1, 0) | ||
636 | self:patchtohere(fs, fj) | ||
637 | end | ||
638 | final = self:getlabel(fs) | ||
639 | self:patchlistaux(fs, e.f, final, reg, p_f) | ||
640 | self:patchlistaux(fs, e.t, final, reg, p_t) | ||
641 | end | ||
642 | e.f, e.t = self.NO_JUMP, self.NO_JUMP | ||
643 | e.info = reg | ||
644 | e.k = "VNONRELOC" | ||
645 | end | ||
646 | |||
647 | ------------------------------------------------------------------------ | ||
648 | -- | ||
649 | -- * used in multiple locations | ||
650 | ------------------------------------------------------------------------ | ||
651 | function luaK:exp2nextreg(fs, e) | ||
652 | self:dischargevars(fs, e) | ||
653 | self:freeexp(fs, e) | ||
654 | self:reserveregs(fs, 1) | ||
655 | self:exp2reg(fs, e, fs.freereg - 1) | ||
656 | end | ||
657 | |||
658 | ------------------------------------------------------------------------ | ||
659 | -- | ||
660 | -- * used in multiple locations | ||
661 | ------------------------------------------------------------------------ | ||
662 | function luaK:exp2anyreg(fs, e) | ||
663 | self:dischargevars(fs, e) | ||
664 | if e.k == "VNONRELOC" then | ||
665 | if not self:hasjumps(e) then -- exp is already in a register | ||
666 | return e.info | ||
667 | end | ||
668 | if e.info >= fs.nactvar then -- reg. is not a local? | ||
669 | self:exp2reg(fs, e, e.info) -- put value on it | ||
670 | return e.info | ||
671 | end | ||
672 | end | ||
673 | self:exp2nextreg(fs, e) -- default | ||
674 | return e.info | ||
675 | end | ||
676 | |||
677 | ------------------------------------------------------------------------ | ||
678 | -- | ||
679 | -- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix() | ||
680 | -- * used in (lparser) luaY:yindex() | ||
681 | ------------------------------------------------------------------------ | ||
682 | function luaK:exp2val(fs, e) | ||
683 | if self:hasjumps(e) then | ||
684 | self:exp2anyreg(fs, e) | ||
685 | else | ||
686 | self:dischargevars(fs, e) | ||
687 | end | ||
688 | end | ||
689 | |||
690 | ------------------------------------------------------------------------ | ||
691 | -- | ||
692 | -- * used in multiple locations | ||
693 | ------------------------------------------------------------------------ | ||
694 | function luaK:exp2RK(fs, e) | ||
695 | self:exp2val(fs, e) | ||
696 | local k = e.k | ||
697 | if k == "VKNUM" or k == "VTRUE" or k == "VFALSE" or k == "VNIL" then | ||
698 | if fs.nk <= luaP.MAXINDEXRK then -- constant fit in RK operand? | ||
699 | -- converted from a 2-deep ternary operator expression | ||
700 | if e.k == "VNIL" then | ||
701 | e.info = self:nilK(fs) | ||
702 | else | ||
703 | e.info = (e.k == "VKNUM") and self:numberK(fs, e.nval) | ||
704 | or self:boolK(fs, e.k == "VTRUE") | ||
705 | end | ||
706 | e.k = "VK" | ||
707 | return luaP:RKASK(e.info) | ||
708 | end | ||
709 | elseif k == "VK" then | ||
710 | if e.info <= luaP.MAXINDEXRK then -- constant fit in argC? | ||
711 | return luaP:RKASK(e.info) | ||
712 | end | ||
713 | else | ||
714 | -- default | ||
715 | end | ||
716 | -- not a constant in the right range: put it in a register | ||
717 | return self:exp2anyreg(fs, e) | ||
718 | end | ||
719 | |||
720 | ------------------------------------------------------------------------ | ||
721 | -- | ||
722 | -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat() | ||
723 | ------------------------------------------------------------------------ | ||
724 | function luaK:storevar(fs, var, ex) | ||
725 | local k = var.k | ||
726 | if k == "VLOCAL" then | ||
727 | self:freeexp(fs, ex) | ||
728 | self:exp2reg(fs, ex, var.info) | ||
729 | return | ||
730 | elseif k == "VUPVAL" then | ||
731 | local e = self:exp2anyreg(fs, ex) | ||
732 | self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0) | ||
733 | elseif k == "VGLOBAL" then | ||
734 | local e = self:exp2anyreg(fs, ex) | ||
735 | self:codeABx(fs, "OP_SETGLOBAL", e, var.info) | ||
736 | elseif k == "VINDEXED" then | ||
737 | local e = self:exp2RK(fs, ex) | ||
738 | self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e) | ||
739 | else | ||
740 | lua_assert(0) -- invalid var kind to store | ||
741 | end | ||
742 | self:freeexp(fs, ex) | ||
743 | end | ||
744 | |||
745 | ------------------------------------------------------------------------ | ||
746 | -- | ||
747 | -- * used only in (lparser) luaY:primaryexp() | ||
748 | ------------------------------------------------------------------------ | ||
749 | function luaK:_self(fs, e, key) | ||
750 | self:exp2anyreg(fs, e) | ||
751 | self:freeexp(fs, e) | ||
752 | local func = fs.freereg | ||
753 | self:reserveregs(fs, 2) | ||
754 | self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key)) | ||
755 | self:freeexp(fs, key) | ||
756 | e.info = func | ||
757 | e.k = "VNONRELOC" | ||
758 | end | ||
759 | |||
760 | ------------------------------------------------------------------------ | ||
761 | -- | ||
762 | -- * used in luaK:goiftrue(), luaK:codenot() | ||
763 | ------------------------------------------------------------------------ | ||
764 | function luaK:invertjump(fs, e) | ||
765 | local pc = self:getjumpcontrol(fs, e.info) | ||
766 | lua_assert(luaP:testTMode(luaP:GET_OPCODE(pc)) ~= 0 and | ||
767 | luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and | ||
768 | luaP:GET_OPCODE(pc) ~= "OP_TEST") | ||
769 | luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0) | ||
770 | end | ||
771 | |||
772 | ------------------------------------------------------------------------ | ||
773 | -- | ||
774 | -- * used in luaK:goiftrue(), luaK:goiffalse() | ||
775 | ------------------------------------------------------------------------ | ||
776 | function luaK:jumponcond(fs, e, cond) | ||
777 | if e.k == "VRELOCABLE" then | ||
778 | local ie = self:getcode(fs, e) | ||
779 | if luaP:GET_OPCODE(ie) == "OP_NOT" then | ||
780 | fs.pc = fs.pc - 1 -- remove previous OP_NOT | ||
781 | return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0, cond and 0 or 1) | ||
782 | end | ||
783 | -- else go through | ||
784 | end | ||
785 | self:discharge2anyreg(fs, e) | ||
786 | self:freeexp(fs, e) | ||
787 | return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0) | ||
788 | end | ||
789 | |||
790 | ------------------------------------------------------------------------ | ||
791 | -- | ||
792 | -- * used in luaK:infix(), (lparser) luaY:cond() | ||
793 | ------------------------------------------------------------------------ | ||
794 | function luaK:goiftrue(fs, e) | ||
795 | local pc -- pc of last jump | ||
796 | self:dischargevars(fs, e) | ||
797 | local k = e.k | ||
798 | if k == "VK" or k == "VKNUM" or k == "VTRUE" then | ||
799 | pc = self.NO_JUMP -- always true; do nothing | ||
800 | elseif k == "VFALSE" then | ||
801 | pc = self:jump(fs) -- always jump | ||
802 | elseif k == "VJMP" then | ||
803 | self:invertjump(fs, e) | ||
804 | pc = e.info | ||
805 | else | ||
806 | pc = self:jumponcond(fs, e, false) | ||
807 | end | ||
808 | e.f = self:concat(fs, e.f, pc) -- insert last jump in `f' list | ||
809 | self:patchtohere(fs, e.t) | ||
810 | e.t = self.NO_JUMP | ||
811 | end | ||
812 | |||
813 | ------------------------------------------------------------------------ | ||
814 | -- | ||
815 | -- * used in luaK:infix() | ||
816 | ------------------------------------------------------------------------ | ||
817 | function luaK:goiffalse(fs, e) | ||
818 | local pc -- pc of last jump | ||
819 | self:dischargevars(fs, e) | ||
820 | local k = e.k | ||
821 | if k == "VNIL" or k == "VFALSE"then | ||
822 | pc = self.NO_JUMP -- always false; do nothing | ||
823 | elseif k == "VTRUE" then | ||
824 | pc = self:jump(fs) -- always jump | ||
825 | elseif k == "VJMP" then | ||
826 | pc = e.info | ||
827 | else | ||
828 | pc = self:jumponcond(fs, e, true) | ||
829 | end | ||
830 | e.t = self:concat(fs, e.t, pc) -- insert last jump in `t' list | ||
831 | self:patchtohere(fs, e.f) | ||
832 | e.f = self.NO_JUMP | ||
833 | end | ||
834 | |||
835 | ------------------------------------------------------------------------ | ||
836 | -- | ||
837 | -- * used only in luaK:prefix() | ||
838 | ------------------------------------------------------------------------ | ||
839 | function luaK:codenot(fs, e) | ||
840 | self:dischargevars(fs, e) | ||
841 | local k = e.k | ||
842 | if k == "VNIL" or k == "VFALSE" then | ||
843 | e.k = "VTRUE" | ||
844 | elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then | ||
845 | e.k = "VFALSE" | ||
846 | elseif k == "VJMP" then | ||
847 | self:invertjump(fs, e) | ||
848 | elseif k == "VRELOCABLE" or k == "VNONRELOC" then | ||
849 | self:discharge2anyreg(fs, e) | ||
850 | self:freeexp(fs, e) | ||
851 | e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0) | ||
852 | e.k = "VRELOCABLE" | ||
853 | else | ||
854 | lua_assert(0) -- cannot happen | ||
855 | end | ||
856 | -- interchange true and false lists | ||
857 | e.f, e.t = e.t, e.f | ||
858 | self:removevalues(fs, e.f) | ||
859 | self:removevalues(fs, e.t) | ||
860 | end | ||
861 | |||
862 | ------------------------------------------------------------------------ | ||
863 | -- | ||
864 | -- * used in (lparser) luaY:field(), luaY:primaryexp() | ||
865 | ------------------------------------------------------------------------ | ||
866 | function luaK:indexed(fs, t, k) | ||
867 | t.aux = self:exp2RK(fs, k) | ||
868 | t.k = "VINDEXED" | ||
869 | end | ||
870 | |||
871 | ------------------------------------------------------------------------ | ||
872 | -- | ||
873 | -- * used only in luaK:codearith() | ||
874 | ------------------------------------------------------------------------ | ||
875 | function luaK:constfolding(op, e1, e2) | ||
876 | local r | ||
877 | if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end | ||
878 | local v1 = e1.nval | ||
879 | local v2 = e2.nval | ||
880 | if op == "OP_ADD" then | ||
881 | r = self:numadd(v1, v2) | ||
882 | elseif op == "OP_SUB" then | ||
883 | r = self:numsub(v1, v2) | ||
884 | elseif op == "OP_MUL" then | ||
885 | r = self:nummul(v1, v2) | ||
886 | elseif op == "OP_DIV" then | ||
887 | if v2 == 0 then return false end -- do not attempt to divide by 0 | ||
888 | r = self:numdiv(v1, v2) | ||
889 | elseif op == "OP_MOD" then | ||
890 | if v2 == 0 then return false end -- do not attempt to divide by 0 | ||
891 | r = self:nummod(v1, v2) | ||
892 | elseif op == "OP_POW" then | ||
893 | r = self:numpow(v1, v2) | ||
894 | elseif op == "OP_UNM" then | ||
895 | r = self:numunm(v1) | ||
896 | elseif op == "OP_LEN" then | ||
897 | return false -- no constant folding for 'len' | ||
898 | else | ||
899 | lua_assert(0) | ||
900 | r = 0 | ||
901 | end | ||
902 | if self:numisnan(r) then return false end -- do not attempt to produce NaN | ||
903 | e1.nval = r | ||
904 | return true | ||
905 | end | ||
906 | |||
907 | ------------------------------------------------------------------------ | ||
908 | -- | ||
909 | -- * used in luaK:prefix(), luaK:posfix() | ||
910 | ------------------------------------------------------------------------ | ||
911 | function luaK:codearith(fs, op, e1, e2) | ||
912 | if self:constfolding(op, e1, e2) then | ||
913 | return | ||
914 | else | ||
915 | local o2 = (op ~= "OP_UNM" and op ~= "OP_LEN") and self:exp2RK(fs, e2) or 0 | ||
916 | local o1 = self:exp2RK(fs, e1) | ||
917 | if o1 > o2 then | ||
918 | self:freeexp(fs, e1) | ||
919 | self:freeexp(fs, e2) | ||
920 | else | ||
921 | self:freeexp(fs, e2) | ||
922 | self:freeexp(fs, e1) | ||
923 | end | ||
924 | e1.info = self:codeABC(fs, op, 0, o1, o2) | ||
925 | e1.k = "VRELOCABLE" | ||
926 | end | ||
927 | end | ||
928 | |||
929 | ------------------------------------------------------------------------ | ||
930 | -- | ||
931 | -- * used only in luaK:posfix() | ||
932 | ------------------------------------------------------------------------ | ||
933 | function luaK:codecomp(fs, op, cond, e1, e2) | ||
934 | local o1 = self:exp2RK(fs, e1) | ||
935 | local o2 = self:exp2RK(fs, e2) | ||
936 | self:freeexp(fs, e2) | ||
937 | self:freeexp(fs, e1) | ||
938 | if cond == 0 and op ~= "OP_EQ" then | ||
939 | -- exchange args to replace by `<' or `<=' | ||
940 | o1, o2 = o2, o1 -- o1 <==> o2 | ||
941 | cond = 1 | ||
942 | end | ||
943 | e1.info = self:condjump(fs, op, cond, o1, o2) | ||
944 | e1.k = "VJMP" | ||
945 | end | ||
946 | |||
947 | ------------------------------------------------------------------------ | ||
948 | -- | ||
949 | -- * used only in (lparser) luaY:subexpr() | ||
950 | ------------------------------------------------------------------------ | ||
951 | function luaK:prefix(fs, op, e) | ||
952 | local e2 = {} -- expdesc | ||
953 | e2.t, e2.f = self.NO_JUMP, self.NO_JUMP | ||
954 | e2.k = "VKNUM" | ||
955 | e2.nval = 0 | ||
956 | if op == "OPR_MINUS" then | ||
957 | if not self:isnumeral(e) then | ||
958 | self:exp2anyreg(fs, e) -- cannot operate on non-numeric constants | ||
959 | end | ||
960 | self:codearith(fs, "OP_UNM", e, e2) | ||
961 | elseif op == "OPR_NOT" then | ||
962 | self:codenot(fs, e) | ||
963 | elseif op == "OPR_LEN" then | ||
964 | self:exp2anyreg(fs, e) -- cannot operate on constants | ||
965 | self:codearith(fs, "OP_LEN", e, e2) | ||
966 | else | ||
967 | lua_assert(0) | ||
968 | end | ||
969 | end | ||
970 | |||
971 | ------------------------------------------------------------------------ | ||
972 | -- | ||
973 | -- * used only in (lparser) luaY:subexpr() | ||
974 | ------------------------------------------------------------------------ | ||
975 | function luaK:infix(fs, op, v) | ||
976 | if op == "OPR_AND" then | ||
977 | self:goiftrue(fs, v) | ||
978 | elseif op == "OPR_OR" then | ||
979 | self:goiffalse(fs, v) | ||
980 | elseif op == "OPR_CONCAT" then | ||
981 | self:exp2nextreg(fs, v) -- operand must be on the 'stack' | ||
982 | elseif op == "OPR_ADD" or op == "OPR_SUB" or | ||
983 | op == "OPR_MUL" or op == "OPR_DIV" or | ||
984 | op == "OPR_MOD" or op == "OPR_POW" then | ||
985 | if not self:isnumeral(v) then self:exp2RK(fs, v) end | ||
986 | else | ||
987 | self:exp2RK(fs, v) | ||
988 | end | ||
989 | end | ||
990 | |||
991 | ------------------------------------------------------------------------ | ||
992 | -- | ||
993 | -- * used only in (lparser) luaY:subexpr() | ||
994 | ------------------------------------------------------------------------ | ||
995 | -- table lookups to simplify testing | ||
996 | luaK.arith_op = { | ||
997 | OPR_ADD = "OP_ADD", OPR_SUB = "OP_SUB", OPR_MUL = "OP_MUL", | ||
998 | OPR_DIV = "OP_DIV", OPR_MOD = "OP_MOD", OPR_POW = "OP_POW", | ||
999 | } | ||
1000 | luaK.comp_op = { | ||
1001 | OPR_EQ = "OP_EQ", OPR_NE = "OP_EQ", OPR_LT = "OP_LT", | ||
1002 | OPR_LE = "OP_LE", OPR_GT = "OP_LT", OPR_GE = "OP_LE", | ||
1003 | } | ||
1004 | luaK.comp_cond = { | ||
1005 | OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1, | ||
1006 | OPR_LE = 1, OPR_GT = 0, OPR_GE = 0, | ||
1007 | } | ||
1008 | function luaK:posfix(fs, op, e1, e2) | ||
1009 | -- needed because e1 = e2 doesn't copy values... | ||
1010 | -- * in 5.0.x, only k/info/aux/t/f copied, t for AND, f for OR | ||
1011 | -- but here, all elements are copied for completeness' sake | ||
1012 | local function copyexp(e1, e2) | ||
1013 | e1.k = e2.k | ||
1014 | e1.info = e2.info; e1.aux = e2.aux | ||
1015 | e1.nval = e2.nval | ||
1016 | e1.t = e2.t; e1.f = e2.f | ||
1017 | end | ||
1018 | if op == "OPR_AND" then | ||
1019 | lua_assert(e1.t == self.NO_JUMP) -- list must be closed | ||
1020 | self:dischargevars(fs, e2) | ||
1021 | e2.f = self:concat(fs, e2.f, e1.f) | ||
1022 | copyexp(e1, e2) | ||
1023 | elseif op == "OPR_OR" then | ||
1024 | lua_assert(e1.f == self.NO_JUMP) -- list must be closed | ||
1025 | self:dischargevars(fs, e2) | ||
1026 | e2.t = self:concat(fs, e2.t, e1.t) | ||
1027 | copyexp(e1, e2) | ||
1028 | elseif op == "OPR_CONCAT" then | ||
1029 | self:exp2val(fs, e2) | ||
1030 | if e2.k == "VRELOCABLE" and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then | ||
1031 | lua_assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1) | ||
1032 | self:freeexp(fs, e1) | ||
1033 | luaP:SETARG_B(self:getcode(fs, e2), e1.info) | ||
1034 | e1.k = "VRELOCABLE" | ||
1035 | e1.info = e2.info | ||
1036 | else | ||
1037 | self:exp2nextreg(fs, e2) -- operand must be on the 'stack' | ||
1038 | self:codearith(fs, "OP_CONCAT", e1, e2) | ||
1039 | end | ||
1040 | else | ||
1041 | -- the following uses a table lookup in place of conditionals | ||
1042 | local arith = self.arith_op[op] | ||
1043 | if arith then | ||
1044 | self:codearith(fs, arith, e1, e2) | ||
1045 | else | ||
1046 | local comp = self.comp_op[op] | ||
1047 | if comp then | ||
1048 | self:codecomp(fs, comp, self.comp_cond[op], e1, e2) | ||
1049 | else | ||
1050 | lua_assert(0) | ||
1051 | end | ||
1052 | end--if arith | ||
1053 | end--if op | ||
1054 | end | ||
1055 | |||
1056 | ------------------------------------------------------------------------ | ||
1057 | -- adjusts debug information for last instruction written, in order to | ||
1058 | -- change the line where item comes into existence | ||
1059 | -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat() | ||
1060 | ------------------------------------------------------------------------ | ||
1061 | function luaK:fixline(fs, line) | ||
1062 | fs.f.lineinfo[fs.pc - 1] = line | ||
1063 | end | ||
1064 | |||
1065 | ------------------------------------------------------------------------ | ||
1066 | -- general function to write an instruction into the instruction buffer, | ||
1067 | -- sets debug information too | ||
1068 | -- * used in luaK:codeABC(), luaK:codeABx() | ||
1069 | -- * called directly by (lparser) luaY:whilestat() | ||
1070 | ------------------------------------------------------------------------ | ||
1071 | function luaK:code(fs, i, line) | ||
1072 | local f = fs.f | ||
1073 | self:dischargejpc(fs) -- 'pc' will change | ||
1074 | -- put new instruction in code array | ||
1075 | luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil, | ||
1076 | luaY.MAX_INT, "code size overflow") | ||
1077 | f.code[fs.pc] = i | ||
1078 | -- save corresponding line information | ||
1079 | luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil, | ||
1080 | luaY.MAX_INT, "code size overflow") | ||
1081 | f.lineinfo[fs.pc] = line | ||
1082 | local pc = fs.pc | ||
1083 | fs.pc = fs.pc + 1 | ||
1084 | return pc | ||
1085 | end | ||
1086 | |||
1087 | ------------------------------------------------------------------------ | ||
1088 | -- writes an instruction of type ABC | ||
1089 | -- * calls luaK:code() | ||
1090 | ------------------------------------------------------------------------ | ||
1091 | function luaK:codeABC(fs, o, a, b, c) | ||
1092 | lua_assert(luaP:getOpMode(o) == luaP.OpMode.iABC) | ||
1093 | lua_assert(luaP:getBMode(o) ~= luaP.OpArgMask.OpArgN or b == 0) | ||
1094 | lua_assert(luaP:getCMode(o) ~= luaP.OpArgMask.OpArgN or c == 0) | ||
1095 | return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline) | ||
1096 | end | ||
1097 | |||
1098 | ------------------------------------------------------------------------ | ||
1099 | -- writes an instruction of type ABx | ||
1100 | -- * calls luaK:code(), called by luaK:codeAsBx() | ||
1101 | ------------------------------------------------------------------------ | ||
1102 | function luaK:codeABx(fs, o, a, bc) | ||
1103 | lua_assert(luaP:getOpMode(o) == luaP.OpMode.iABx or | ||
1104 | luaP:getOpMode(o) == luaP.OpMode.iAsBx) | ||
1105 | lua_assert(luaP:getCMode(o) == luaP.OpArgMask.OpArgN) | ||
1106 | return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline) | ||
1107 | end | ||
1108 | |||
1109 | ------------------------------------------------------------------------ | ||
1110 | -- | ||
1111 | -- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield() | ||
1112 | ------------------------------------------------------------------------ | ||
1113 | function luaK:setlist(fs, base, nelems, tostore) | ||
1114 | local c = math.floor((nelems - 1)/luaP.LFIELDS_PER_FLUSH) + 1 | ||
1115 | local b = (tostore == luaY.LUA_MULTRET) and 0 or tostore | ||
1116 | lua_assert(tostore ~= 0) | ||
1117 | if c <= luaP.MAXARG_C then | ||
1118 | self:codeABC(fs, "OP_SETLIST", base, b, c) | ||
1119 | else | ||
1120 | self:codeABC(fs, "OP_SETLIST", base, b, 0) | ||
1121 | self:code(fs, luaP:CREATE_Inst(c), fs.ls.lastline) | ||
1122 | end | ||
1123 | fs.freereg = base + 1 -- free registers with list values | ||
1124 | end | ||
1125 | |||