aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua
diff options
context:
space:
mode:
Diffstat (limited to 'LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua')
-rw-r--r--LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua1125
1 files changed, 0 insertions, 1125 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
deleted file mode 100644
index 4dc8548..0000000
--- a/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lcode.lua
+++ /dev/null
@@ -1,1125 +0,0 @@
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
59luaK = {}
60
61------------------------------------------------------------------------
62-- constants used by code generator
63------------------------------------------------------------------------
64-- maximum stack for a Lua function
65luaK.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------------------------------------------------------------------------
78function luaK:ttisnumber(o)
79 if o then return type(o.value) == "number" else return false end
80end
81function luaK:nvalue(o) return o.value end
82function luaK:setnilvalue(o) o.value = nil end
83function luaK:setsvalue(o, x) o.value = x end
84luaK.setnvalue = luaK.setsvalue
85luaK.sethvalue = luaK.setsvalue
86luaK.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------------------------------------------------------------------------
93function luaK:numadd(a, b) return a + b end
94function luaK:numsub(a, b) return a - b end
95function luaK:nummul(a, b) return a * b end
96function luaK:numdiv(a, b) return a / b end
97function luaK:nummod(a, b) return a % b end
98 -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */
99function luaK:numpow(a, b) return a ^ b end
100function luaK:numunm(a) return -a end
101function 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------------------------------------------------------------------------
112luaK.NO_JUMP = -1
113
114------------------------------------------------------------------------
115-- grep "ORDER OPR" if you change these enums
116------------------------------------------------------------------------
117luaK.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"
128luaK.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------------------------------------------------------------------------
135function luaK:getcode(fs, e)
136 return fs.f.code[e.info]
137end
138
139------------------------------------------------------------------------
140-- codes an instruction with a signed Bx (sBx) field, was a macro
141-- * used in luaK:jump(), (lparser) luaY:forbody()
142------------------------------------------------------------------------
143function luaK:codeAsBx(fs, o, A, sBx)
144 return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
145end
146
147------------------------------------------------------------------------
148-- set the expdesc e instruction for multiple returns, was a macro
149------------------------------------------------------------------------
150function luaK:setmultret(fs, e)
151 self:setreturns(fs, e, luaY.LUA_MULTRET)
152end
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------------------------------------------------------------------------
158function luaK:hasjumps(e)
159 return e.t ~= e.f
160end
161
162------------------------------------------------------------------------
163-- true if the expression is a constant number (for constant folding)
164-- * used in constfolding(), infix()
165------------------------------------------------------------------------
166function luaK:isnumeral(e)
167 return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP
168end
169
170------------------------------------------------------------------------
171-- codes loading of nil, optimization done if consecutive locations
172-- * used in luaK:discharge2reg(), (lparser) luaY:adjust_assign()
173------------------------------------------------------------------------
174function 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
195end
196
197------------------------------------------------------------------------
198--
199-- * used in multiple locations
200------------------------------------------------------------------------
201function 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
207end
208
209------------------------------------------------------------------------
210-- codes a RETURN instruction
211-- * used in luaY:close_func(), luaY:retstat()
212------------------------------------------------------------------------
213function luaK:ret(fs, first, nret)
214 self:codeABC(fs, "OP_RETURN", first, nret + 1, 0)
215end
216
217------------------------------------------------------------------------
218--
219-- * used in luaK:jumponcond(), luaK:codecomp()
220------------------------------------------------------------------------
221function luaK:condjump(fs, op, A, B, C)
222 self:codeABC(fs, op, A, B, C)
223 return self:jump(fs)
224end
225
226------------------------------------------------------------------------
227--
228-- * used in luaK:patchlistaux(), luaK:concat()
229------------------------------------------------------------------------
230function 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)
238end
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------------------------------------------------------------------------
246function luaK:getlabel(fs)
247 fs.lasttarget = fs.pc
248 return fs.pc
249end
250
251------------------------------------------------------------------------
252--
253-- * used in luaK:need_value(), luaK:removevalues(), luaK:patchlistaux(),
254-- luaK:concat()
255------------------------------------------------------------------------
256function 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
263end
264
265------------------------------------------------------------------------
266--
267-- * used in luaK:need_value(), luaK:patchtestreg(), luaK:invertjump()
268------------------------------------------------------------------------
269function 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
277end
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------------------------------------------------------------------------
285function 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
292end
293
294------------------------------------------------------------------------
295--
296-- * used in luaK:removevalues(), luaK:patchlistaux()
297------------------------------------------------------------------------
298function 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
315end
316
317------------------------------------------------------------------------
318--
319-- * used only in luaK:codenot()
320------------------------------------------------------------------------
321function 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
326end
327
328------------------------------------------------------------------------
329--
330-- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg()
331------------------------------------------------------------------------
332function 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
342end
343
344------------------------------------------------------------------------
345--
346-- * used only in luaK:code()
347------------------------------------------------------------------------
348function luaK:dischargejpc(fs)
349 self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
350 fs.jpc = self.NO_JUMP
351end
352
353------------------------------------------------------------------------
354--
355-- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody()
356------------------------------------------------------------------------
357function 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
364end
365
366------------------------------------------------------------------------
367--
368-- * used in multiple locations
369------------------------------------------------------------------------
370function luaK:patchtohere(fs, list)
371 self:getlabel(fs)
372 fs.jpc = self:concat(fs, fs.jpc, list)
373end
374
375------------------------------------------------------------------------
376-- * l1 was a pointer, now l1 is returned and callee assigns the value
377-- * used in multiple locations
378------------------------------------------------------------------------
379function 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
393end
394
395------------------------------------------------------------------------
396--
397-- * used in luaK:reserveregs(), (lparser) luaY:forlist()
398------------------------------------------------------------------------
399function 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
407end
408
409------------------------------------------------------------------------
410--
411-- * used in multiple locations
412------------------------------------------------------------------------
413function luaK:reserveregs(fs, n)
414 self:checkstack(fs, n)
415 fs.freereg = fs.freereg + n
416end
417
418------------------------------------------------------------------------
419--
420-- * used in luaK:freeexp(), luaK:dischargevars()
421------------------------------------------------------------------------
422function 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
427end
428
429------------------------------------------------------------------------
430--
431-- * used in multiple locations
432------------------------------------------------------------------------
433function luaK:freeexp(fs, e)
434 if e.k == "VNONRELOC" then
435 self:freereg(fs, e.info)
436 end
437end
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------------------------------------------------------------------------
444function 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
470end
471
472------------------------------------------------------------------------
473-- creates and sets a string object
474-- * used in (lparser) luaY:codestring(), luaY:singlevar()
475------------------------------------------------------------------------
476function luaK:stringK(fs, s)
477 local o = {} -- TValue
478 self:setsvalue(o, s)
479 return self:addk(fs, o, o)
480end
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------------------------------------------------------------------------
487function luaK:numberK(fs, r)
488 local o = {} -- TValue
489 self:setnvalue(o, r)
490 return self:addk(fs, o, o)
491end
492
493------------------------------------------------------------------------
494-- creates and sets a boolean object
495-- * used only in luaK:exp2RK()
496------------------------------------------------------------------------
497function luaK:boolK(fs, b)
498 local o = {} -- TValue
499 self:setbvalue(o, b)
500 return self:addk(fs, o, o)
501end
502
503------------------------------------------------------------------------
504-- creates and sets a nil object
505-- * used only in luaK:exp2RK()
506------------------------------------------------------------------------
507function 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)
513end
514
515------------------------------------------------------------------------
516--
517-- * used in luaK:setmultret(), (lparser) luaY:adjust_assign()
518------------------------------------------------------------------------
519function 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
527end
528
529------------------------------------------------------------------------
530--
531-- * used in luaK:dischargevars(), (lparser) luaY:assignment()
532------------------------------------------------------------------------
533function 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
541end
542
543------------------------------------------------------------------------
544--
545-- * used in multiple locations
546------------------------------------------------------------------------
547function 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
567end
568
569------------------------------------------------------------------------
570--
571-- * used only in luaK:exp2reg()
572------------------------------------------------------------------------
573function 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)
576end
577
578------------------------------------------------------------------------
579--
580-- * used in luaK:discharge2anyreg(), luaK:exp2reg()
581------------------------------------------------------------------------
582function 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"
606end
607
608------------------------------------------------------------------------
609--
610-- * used in luaK:jumponcond(), luaK:codenot()
611------------------------------------------------------------------------
612function 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
617end
618
619------------------------------------------------------------------------
620--
621-- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar()
622------------------------------------------------------------------------
623function 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"
645end
646
647------------------------------------------------------------------------
648--
649-- * used in multiple locations
650------------------------------------------------------------------------
651function 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)
656end
657
658------------------------------------------------------------------------
659--
660-- * used in multiple locations
661------------------------------------------------------------------------
662function 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
675end
676
677------------------------------------------------------------------------
678--
679-- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix()
680-- * used in (lparser) luaY:yindex()
681------------------------------------------------------------------------
682function luaK:exp2val(fs, e)
683 if self:hasjumps(e) then
684 self:exp2anyreg(fs, e)
685 else
686 self:dischargevars(fs, e)
687 end
688end
689
690------------------------------------------------------------------------
691--
692-- * used in multiple locations
693------------------------------------------------------------------------
694function 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)
718end
719
720------------------------------------------------------------------------
721--
722-- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat()
723------------------------------------------------------------------------
724function 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)
743end
744
745------------------------------------------------------------------------
746--
747-- * used only in (lparser) luaY:primaryexp()
748------------------------------------------------------------------------
749function 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"
758end
759
760------------------------------------------------------------------------
761--
762-- * used in luaK:goiftrue(), luaK:codenot()
763------------------------------------------------------------------------
764function 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)
770end
771
772------------------------------------------------------------------------
773--
774-- * used in luaK:goiftrue(), luaK:goiffalse()
775------------------------------------------------------------------------
776function 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)
788end
789
790------------------------------------------------------------------------
791--
792-- * used in luaK:infix(), (lparser) luaY:cond()
793------------------------------------------------------------------------
794function 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
811end
812
813------------------------------------------------------------------------
814--
815-- * used in luaK:infix()
816------------------------------------------------------------------------
817function 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
833end
834
835------------------------------------------------------------------------
836--
837-- * used only in luaK:prefix()
838------------------------------------------------------------------------
839function 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)
860end
861
862------------------------------------------------------------------------
863--
864-- * used in (lparser) luaY:field(), luaY:primaryexp()
865------------------------------------------------------------------------
866function luaK:indexed(fs, t, k)
867 t.aux = self:exp2RK(fs, k)
868 t.k = "VINDEXED"
869end
870
871------------------------------------------------------------------------
872--
873-- * used only in luaK:codearith()
874------------------------------------------------------------------------
875function 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
905end
906
907------------------------------------------------------------------------
908--
909-- * used in luaK:prefix(), luaK:posfix()
910------------------------------------------------------------------------
911function 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
927end
928
929------------------------------------------------------------------------
930--
931-- * used only in luaK:posfix()
932------------------------------------------------------------------------
933function 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"
945end
946
947------------------------------------------------------------------------
948--
949-- * used only in (lparser) luaY:subexpr()
950------------------------------------------------------------------------
951function 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
969end
970
971------------------------------------------------------------------------
972--
973-- * used only in (lparser) luaY:subexpr()
974------------------------------------------------------------------------
975function 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
989end
990
991------------------------------------------------------------------------
992--
993-- * used only in (lparser) luaY:subexpr()
994------------------------------------------------------------------------
995-- table lookups to simplify testing
996luaK.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}
1000luaK.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}
1004luaK.comp_cond = {
1005 OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1,
1006 OPR_LE = 1, OPR_GT = 0, OPR_GE = 0,
1007}
1008function 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
1054end
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------------------------------------------------------------------------
1061function luaK:fixline(fs, line)
1062 fs.f.lineinfo[fs.pc - 1] = line
1063end
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------------------------------------------------------------------------
1071function 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
1085end
1086
1087------------------------------------------------------------------------
1088-- writes an instruction of type ABC
1089-- * calls luaK:code()
1090------------------------------------------------------------------------
1091function 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)
1096end
1097
1098------------------------------------------------------------------------
1099-- writes an instruction of type ABx
1100-- * calls luaK:code(), called by luaK:codeAsBx()
1101------------------------------------------------------------------------
1102function 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)
1107end
1108
1109------------------------------------------------------------------------
1110--
1111-- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield()
1112------------------------------------------------------------------------
1113function 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
1124end
1125