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