1 ----------------------------------------------------------------------
3 -- WARNING! You're entering a hackish area, proceed at your own risks!
5 -- This code partly results from the borrowing, then ruthless abuse, of
6 -- Yueliang's implementation of Lua 5.0 compiler. I claim
7 -- responsibility for all of the ugly, dirty stuff that you might spot
10 -- Eventually, this code will be rewritten, either in Lua or more
11 -- probably in C. Meanwhile, if you're interested into digging
12 -- metalua's sources, this is not the best part to invest your time
17 ----------------------------------------------------------------------
19 ----------------------------------------------------------------------
22 -- Summary: Compile ASTs to Lua 5.1 VM function prototype.
25 -- * Yueliang (http://luaforge.net/projects/yueliang),
26 -- yueliang-0.1.2/orig-5.0.2/lparser.lua
28 -- * Lua 5.1 sources (http://www.lua.org), src/lparser.c
30 ----------------------------------------------------------------------
32 -- Copyright (c) 2006-2008, Fabien Fleutot <metalua@gmail.com>.
34 -- This software is released under the MIT Licence, see licence.txt
37 ----------------------------------------------------------------------
39 module ("bytecode", package.seeall)
41 local debugf = function() end
47 MAX_INT = 2147483645 -- INT_MAX-2 for 32-bit systems (llimits.h)
48 MAXVARS = 200 -- (llimits.h)
49 MAXUPVALUES = 32 -- (llimits.h)
50 MAXPARAMS = 100 -- (llimits.h)
51 LUA_MAXPARSERLEVEL = 200 -- (llimits.h)
58 local function hasmultret (k)
59 return k=="VCALL" or k=="VVARARG"
62 -----------------------------------------------------------------------
63 -- Some ASTs take expression lists as children; it should be
64 -- acceptible to give an expression instead, and to automatically
65 -- interpret it as a single element list. That's what does this
66 -- function, adding a surrounding list iff needed.
68 -- WARNING: "Do" is the tag for chunks, which are essentially lists.
69 -- Therefore, we don't listify stuffs with a "Do" tag.
70 -----------------------------------------------------------------------
71 local function ensure_list (ast)
72 return ast.tag and ast.tag ~= "Do" and {ast} or ast end
74 -----------------------------------------------------------------------
75 -- Get a localvar structure { varname, startpc, endpc } from a
76 -- (zero-based) index of active variable. The catch is: don't get
77 -- confused between local index and active index.
79 -- locvars[x] contains { varname, startpc, endpc };
80 -- actvar[i] contains the index of the variable in locvars
81 -----------------------------------------------------------------------
82 local function getlocvar (fs, i)
83 return fs.f.locvars[fs.actvar[i]]
86 local function removevars (fs, tolevel)
87 while fs.nactvar > tolevel do
88 fs.nactvar = fs.nactvar - 1
89 -- There may be dummy locvars due to expr.Stat
90 -- FIXME: strange that they didn't disappear?!
91 local locvar = getlocvar (fs, fs.nactvar)
92 --printf("[REMOVEVARS] removing var #%i = %s", fs.nactvar,
93 -- locvar and tostringv(locvar) or "<nil>")
94 if locvar then locvar.endpc = fs.pc end
98 -----------------------------------------------------------------------
99 -- [f] has a list of all its local variables, active and inactive.
100 -- Some local vars can correspond to the same register, if they exist
101 -- in different scopes.
102 -- [fs.nlocvars] is the total number of local variables, not to be
103 -- confused with [fs.nactvar] the numebr of variables active at the
105 -- At this stage, the existence of the variable is not yet aknowledged,
106 -- since [fs.nactvar] and [fs.freereg] aren't updated.
107 -----------------------------------------------------------------------
108 local function registerlocalvar (fs, varname)
109 debugf("[locvar: %s = reg %i]", varname, fs.nlocvars)
111 f.locvars[fs.nlocvars] = { } -- LocVar
112 f.locvars[fs.nlocvars].varname = varname
113 local nlocvars = fs.nlocvars
114 fs.nlocvars = fs.nlocvars + 1
118 -----------------------------------------------------------------------
119 -- update the active vars counter in [fs] by adding [nvars] of them,
120 -- and sets those variables' [startpc] to the current [fs.pc].
121 -- These variables were allready created, but not yet counted, by
123 -----------------------------------------------------------------------
124 local function adjustlocalvars (fs, nvars)
125 --debugf("adjustlocalvars, nvars=%i, previous fs.nactvar=%i,"..
126 -- " #locvars=%i, #actvar=%i",
127 -- nvars, fs.nactvar, #fs.f.locvars, #fs.actvar)
129 fs.nactvar = fs.nactvar + nvars
130 for i = nvars, 1, -1 do
131 --printf ("adjusting actvar #%i", fs.nactvar - i)
132 getlocvar (fs, fs.nactvar - i).startpc = fs.pc
136 ------------------------------------------------------------------------
137 -- check whether, in an assignment to a local variable, the local variable
138 -- is needed in a previous assignment (to a table). If so, save original
139 -- local value in a safe place and use this safe copy in the previous
141 ------------------------------------------------------------------------
142 local function check_conflict (fs, lh, v)
143 local extra = fs.freereg -- eventual position to save local variable
144 local conflict = false
146 if lh.v.k == "VINDEXED" then
147 if lh.v.info == v.info then -- conflict?
149 lh.v.info = extra -- previous assignment will use safe copy
151 if lh.v.aux == v.info then -- conflict?
153 lh.v.aux = extra -- previous assignment will use safe copy
159 luaK:codeABC (fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
160 luaK:reserveregs (fs, 1)
164 -----------------------------------------------------------------------
165 -- Create an expdesc. To be updated when expdesc is lua-ified.
166 -----------------------------------------------------------------------
167 local function init_exp (e, k, i)
168 e.f, e.t, e.k, e.info = luaK.NO_JUMP, luaK.NO_JUMP, k, i end
170 -----------------------------------------------------------------------
171 -- Reserve the string in tthe constant pool, and return an expdesc
173 -----------------------------------------------------------------------
174 local function codestring (fs, e, str)
175 --printf( "codestring(%s)", disp.ast(str))
176 init_exp (e, "VK", luaK:stringK (fs, str))
179 -----------------------------------------------------------------------
180 -- search for a local variable named [name] in the function being
181 -- built by [fs]. Doesn't try to visit upvalues.
182 -----------------------------------------------------------------------
183 local function searchvar (fs, name)
184 for i = fs.nactvar - 1, 0, -1 do
185 -- Because of expr.Stat, there can be some actvars which don't
186 -- correspond to any locvar. Hence the checking for locvar's
187 -- nonnilness before getting the varname.
188 local locvar = getlocvar(fs, i)
189 if locvar and name == locvar.varname then
190 --printf("Found local var: %s; i = %i", tostringv(locvar), i)
194 return -1 -- not found
197 -----------------------------------------------------------------------
198 -- create and return a new proto [f]
199 -----------------------------------------------------------------------
200 local function newproto ()
223 ------------------------------------------------------------------------
224 -- create and return a function state [new_fs] as a sub-funcstate of [fs].
225 ------------------------------------------------------------------------
226 local function open_func (old_fs)
228 new_fs.upvalues = { }
230 local f = newproto ()
232 new_fs.prev = old_fs -- linked list of funcstates
234 new_fs.lasttarget = -1
235 new_fs.jpc = luaK.NO_JUMP
238 new_fs.h = {} -- constant table; was luaH_new call
243 new_fs.nestlevel = old_fs and old_fs.nestlevel or 0
244 f.maxstacksize = 2 -- registers 0/1 are always valid
246 new_fs.forward_gotos = { }
251 ------------------------------------------------------------------------
252 -- Finish to set up [f] according to final state of [fs]
253 ------------------------------------------------------------------------
254 local function close_func (fs)
256 --printf("[CLOSE_FUNC] remove any remaining var")
260 f.sizelineinfo = fs.pc
263 f.sizelocvars = fs.nlocvars
264 f.sizeupvalues = f.nups
265 assert (fs.bl == nil)
266 if next(fs.forward_gotos) then
267 local x = table.tostring(fs.forward_gotos)
268 error ("Unresolved goto: "..x)
272 ------------------------------------------------------------------------
274 ------------------------------------------------------------------------
275 local function pushclosure(fs, func, v)
279 init_exp (v, "VRELOCABLE", luaK:codeABx (fs, "OP_CLOSURE", 0, fs.np - 1))
280 for i = 0, func.f.nups - 1 do
281 local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
282 luaK:codeABC (fs, o, 0, func.upvalues[i].info, 0)
286 ------------------------------------------------------------------------
287 -- FIXME: is there a need for f=fs.f? if yes, why not always using it?
288 ------------------------------------------------------------------------
289 function indexupvalue(fs, name, v)
291 for i = 0, f.nups - 1 do
292 if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
293 assert(fs.f.upvalues[i] == name)
298 f.upvalues[f.nups] = name
299 assert (v.k == "VLOCAL" or v.k == "VUPVAL")
300 fs.upvalues[f.nups] = { k = v.k; info = v.info }
306 ------------------------------------------------------------------------
308 ------------------------------------------------------------------------
309 local function markupval(fs, level)
311 while bl and bl.nactvar > level do bl = bl.previous end
312 if bl then bl.upval = true end
318 local function bldepth(fs)
320 while x do i=i+1; x=x.previous end
325 ------------------------------------------------------------------------
327 ------------------------------------------------------------------------
328 local function enterblock (fs, bl, isbreakable)
329 bl.breaklist = luaK.NO_JUMP
330 bl.isbreakable = isbreakable
331 bl.nactvar = fs.nactvar
335 assert (fs.freereg == fs.nactvar)
338 ------------------------------------------------------------------------
340 ------------------------------------------------------------------------
341 local function leaveblock (fs)
344 --printf("[LEAVEBLOCK] Removing vars...")
345 removevars (fs, bl.nactvar)
346 --printf("[LEAVEBLOCK] ...Vars removed")
348 luaK:codeABC (fs, "OP_CLOSE", bl.nactvar, 0, 0)
350 -- a block either controls scope or breaks (never both)
351 assert (not bl.isbreakable or not bl.upval)
352 assert (bl.nactvar == fs.nactvar)
353 fs.freereg = fs.nactvar -- free registers
354 luaK:patchtohere (fs, bl.breaklist)
358 ------------------------------------------------------------------------
359 -- read a list of expressions from a list of ast [astlist]
360 -- starts at the [offset]th element of the list (defaults to 1)
361 ------------------------------------------------------------------------
362 local function explist(fs, astlist, v, offset)
364 if #astlist < offset then error "I don't handle empty expr lists yet" end
365 --printf("[EXPLIST] about to precompile 1st element %s", disp.ast(astlist[offset]))
366 expr.expr (fs, astlist[offset], v)
367 --printf("[EXPLIST] precompiled first element v=%s", tostringv(v))
368 for i = offset+1, #astlist do
369 luaK:exp2nextreg (fs, v)
370 --printf("[EXPLIST] flushed v=%s", tostringv(v))
371 expr.expr (fs, astlist[i], v)
372 --printf("[EXPLIST] precompiled element v=%s", tostringv(v))
374 return #astlist - offset + 1
377 ------------------------------------------------------------------------
379 ------------------------------------------------------------------------
380 local function funcargs (fs, ast, v, idx_from)
381 local args = { } -- expdesc
383 if #ast < idx_from then args.k = "VVOID" else
384 explist(fs, ast, args, idx_from)
385 luaK:setmultret(fs, args)
387 assert(v.k == "VNONRELOC")
388 local base = v.info -- base register for call
389 if hasmultret(args.k) then nparams = luaK.LUA_MULTRET else -- open call
390 if args.k ~= "VVOID" then
391 luaK:exp2nextreg(fs, args) end -- close last argument
392 nparams = fs.freereg - (base + 1)
394 init_exp(v, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
396 luaK:fixline(fs, ast.lineinfo.first[1])
398 luaK:fixline(fs, ast.line)
400 fs.freereg = base + 1 -- call remove function and arguments and leaves
401 -- (unless changed) one result
404 ------------------------------------------------------------------------
405 -- calculates log value for encoding the hash portion's size
406 ------------------------------------------------------------------------
407 local function log2(x)
408 -- math result is always one more than lua0_log2()
409 local mn, ex = math.frexp(x)
413 ------------------------------------------------------------------------
414 -- converts an integer to a "floating point byte", represented as
415 -- (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
416 ------------------------------------------------------------------------
418 -- local function int2fb(x)
419 -- local m = 0 -- mantissa
420 -- while x >= 8 do x = math.floor((x + 1) / 2); m = m + 1 end
424 local function int2fb(x)
427 x = math.floor ( (x+1) / 2)
431 else return (e+1) * 8 + x - 8 end
435 ------------------------------------------------------------------------
436 -- FIXME: to be unified with singlevar
437 ------------------------------------------------------------------------
438 local function singlevaraux(fs, n, var, base)
440 print("\n\nsinglevaraux: fs, n, var, base")
447 if fs == nil then -- no more levels?
448 init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
451 local v = searchvar(fs, n) -- look up at current level
453 init_exp(var, "VLOCAL", v)
455 markupval(fs, v) -- local will be used as an upval
457 else -- not found at current level; try upper one
458 if singlevaraux(fs.prev, n, var, false) == "VGLOBAL" then
460 var.info = indexupvalue (fs, n, var)
467 ------------------------------------------------------------------------
469 ------------------------------------------------------------------------
470 local function singlevar(fs, varname, var)
471 if singlevaraux(fs, varname, var, true) == "VGLOBAL" then
472 var.info = luaK:stringK (fs, varname) end
475 ------------------------------------------------------------------------
477 ------------------------------------------------------------------------
478 local function new_localvar (fs, name, n)
479 assert (type (name) == "string")
480 if fs.nactvar + n > MAXVARS then error ("too many local vars") end
481 fs.actvar[fs.nactvar + n] = registerlocalvar (fs, name)
482 --printf("[NEW_LOCVAR] %i = %s", fs.nactvar+n, name)
485 ------------------------------------------------------------------------
487 ------------------------------------------------------------------------
488 local function parlist (fs, ast_params)
489 local dots = (#ast_params > 0 and ast_params[#ast_params].tag == "Dots")
490 local nparams = dots and #ast_params - 1 or #ast_params
491 for i = 1, nparams do
492 assert (ast_params[i].tag == "Id", "Function parameters must be Ids")
493 new_localvar (fs, ast_params[i][1], i-1)
495 -- from [code_param]:
496 --checklimit (fs, fs.nactvar, self.MAXPARAMS, "parameters")
497 fs.f.numparams = fs.nactvar
498 fs.f.is_vararg = dots and VARARG_ISVARARG or 0
499 adjustlocalvars (fs, nparams)
500 fs.f.numparams = fs.nactvar --FIXME vararg must be taken in account
501 luaK:reserveregs (fs, fs.nactvar) -- reserve register for parameters
504 ------------------------------------------------------------------------
505 -- if there's more variables than expressions in an assignment,
506 -- some assignations to nil are made for extraneous vars.
507 -- Also handles multiret functions
508 ------------------------------------------------------------------------
509 local function adjust_assign (fs, nvars, nexps, e)
510 local extra = nvars - nexps
511 if hasmultret (e.k) then
512 extra = extra+1 -- includes call itself
513 if extra <= 0 then extra = 0 end
514 luaK:setreturns(fs, e, extra) -- call provides the difference
515 if extra > 1 then luaK:reserveregs(fs, extra-1) end
517 if e.k ~= "VVOID" then
518 luaK:exp2nextreg(fs, e) end -- close last expression
520 local reg = fs.freereg
521 luaK:reserveregs(fs, extra)
522 luaK:_nil(fs, reg, extra)
528 ------------------------------------------------------------------------
530 ------------------------------------------------------------------------
531 local function enterlevel (fs)
532 fs.nestlevel = fs.nestlevel + 1
533 assert (fs.nestlevel <= LUA_MAXPARSERLEVEL, "too many syntax levels")
536 ------------------------------------------------------------------------
538 ------------------------------------------------------------------------
539 local function leavelevel (fs)
540 fs.nestlevel = fs.nestlevel - 1
543 ------------------------------------------------------------------------
544 -- Parse conditions in if/then/else, while, repeat
545 ------------------------------------------------------------------------
546 local function cond (fs, ast)
548 expr.expr(fs, ast, v) -- read condition
549 if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
550 luaK:goiftrue (fs, v)
554 ------------------------------------------------------------------------
556 ------------------------------------------------------------------------
557 local function chunk (fs, ast)
561 stat.stat (fs, ast[i]);
562 fs.freereg = fs.nactvar
567 ------------------------------------------------------------------------
569 ------------------------------------------------------------------------
570 local function block (fs, ast)
572 enterblock (fs, bl, false)
574 stat.stat (fs, ast[i])
575 fs.freereg = fs.nactvar
577 assert (bl.breaklist == luaK.NO_JUMP)
581 ------------------------------------------------------------------------
582 -- Forin / Fornum body parser
588 ------------------------------------------------------------------------
589 local function forbody (fs, ast_body, base, nvars, isnum)
590 local bl = {} -- BlockCnt
591 adjustlocalvars (fs, 3) -- control variables
593 isnum and luaK:codeAsBx (fs, "OP_FORPREP", base, luaK.NO_JUMP)
595 enterblock (fs, bl, false) -- loop block
596 adjustlocalvars (fs, nvars) -- scope for declared variables
597 luaK:reserveregs (fs, nvars)
600 --luaK:patchtohere (fs, prep-1)
601 luaK:patchtohere (fs, prep)
603 isnum and luaK:codeAsBx (fs, "OP_FORLOOP", base, luaK.NO_JUMP)
604 or luaK:codeABC (fs, "OP_TFORLOOP", base, 0, nvars)
605 luaK:fixline (fs, ast_body.line) -- pretend that 'OP_FOR' starts the loop
606 luaK:patchlist (fs, isnum and endfor or luaK:jump(fs), prep + 1)
610 ------------------------------------------------------------------------
612 ------------------------------------------------------------------------
613 local function recfield (fs, ast, cc)
614 local reg = fs.freereg
615 local key, val = {}, {} -- expdesc
616 --FIXME: expr + exp2val = index -->
617 -- check reduncancy between exp2val and exp2rk
619 expr.expr(fs, ast[1], key);
620 luaK:exp2val (fs, key)
621 local keyreg = luaK:exp2RK (fs, key)
622 expr.expr(fs, ast[2], val)
623 local valreg = luaK:exp2RK (fs, val)
624 luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, keyreg, valreg)
625 fs.freereg = reg -- free registers
629 ------------------------------------------------------------------------
631 ------------------------------------------------------------------------
632 local function listfield(fs, ast, cc)
633 expr.expr(fs, ast, cc.v)
634 assert (cc.na <= luaP.MAXARG_Bx) -- FIXME check <= or <
636 cc.tostore = cc.tostore + 1
639 ------------------------------------------------------------------------
641 ------------------------------------------------------------------------
642 local function closelistfield(fs, cc)
643 if cc.v.k == "VVOID" then return end -- there is no list item
644 luaK:exp2nextreg(fs, cc.v)
646 if cc.tostore == luaP.LFIELDS_PER_FLUSH then
647 luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
652 ------------------------------------------------------------------------
653 -- The last field might be a call to a multireturn function. In that
654 -- case, we must unfold all of its results into the list.
655 ------------------------------------------------------------------------
656 local function lastlistfield(fs, cc)
657 if cc.tostore == 0 then return end
658 if hasmultret (cc.v.k) then
659 luaK:setmultret(fs, cc.v)
660 luaK:setlist (fs, cc.t.info, cc.na, luaK.LUA_MULTRET)
663 if cc.v.k ~= "VVOID" then luaK:exp2nextreg(fs, cc.v) end
664 luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
667 ------------------------------------------------------------------------
668 ------------------------------------------------------------------------
670 -- Statement parsers table
672 ------------------------------------------------------------------------
673 ------------------------------------------------------------------------
675 function stat.stat (fs, ast)
676 if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
677 -- debugf (" - Statement %s", disp.ast (ast) )
679 if not ast.tag then chunk (fs, ast) else
681 local parser = stat [ast.tag]
683 error ("A statement cannot have tag `"..ast.tag) end
686 --debugf (" - /Statement `%s", ast.tag or "<nil>")
687 debugf (" - /Statement `%s", ast.tag)
690 ------------------------------------------------------------------------
694 ------------------------------------------------------------------------
696 function stat.Break (fs, ast)
697 -- if ast.lineinfo then fs.lastline = ast.lineinfo.last[1]
698 local bl, upval = fs.bl, false
699 while bl and not bl.isbreakable do
700 if bl.upval then upval = true end
703 assert (bl, "no loop to break")
704 if upval then luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) end
705 bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
708 ------------------------------------------------------------------------
710 function stat.Return (fs, ast)
711 local e = {} -- expdesc
712 local first -- registers with returned values
715 if nret == 0 then first = 0
717 --printf("[RETURN] compiling explist")
719 --printf("[RETURN] explist e=%s", tostringv(e))
720 if hasmultret (e.k) then
721 luaK:setmultret(fs, e)
722 if e.k == "VCALL" and nret == 1 then
723 luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
724 assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
727 nret = luaK.LUA_MULTRET -- return all values
728 elseif nret == 1 then
729 --printf("[RETURN] 1 val: e=%s", tostringv(e))
730 first = luaK:exp2anyreg(fs, e)
731 --printf("[RETURN] 1 val in reg %i", first)
733 --printf("* Return multiple vals in nextreg %i", fs.freereg)
734 luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
735 first = fs.nactvar -- return all 'active' values
736 assert(nret == fs.freereg - first)
739 luaK:ret(fs, first, nret)
741 ------------------------------------------------------------------------
743 function stat.Local (fs, ast)
744 local names, values = ast[1], ast[2] or { }
745 for i = 1, #names do new_localvar (fs, names[i][1], i-1) end
747 if #values == 0 then e.k = "VVOID" else explist (fs, values, e) end
748 adjust_assign (fs, #names, #values, e)
749 adjustlocalvars (fs, #names)
752 ------------------------------------------------------------------------
754 function stat.Localrec (fs, ast)
755 assert(#ast[1]==1 and #ast[2]==1, "Multiple letrecs not implemented yet")
756 local ast_var, ast_val, e_var, e_val = ast[1][1], ast[2][1], { }, { }
757 new_localvar (fs, ast_var[1], 0)
758 init_exp (e_var, "VLOCAL", fs.freereg)
759 luaK:reserveregs (fs, 1)
760 adjustlocalvars (fs, 1)
761 expr.expr (fs, ast_val, e_val)
762 luaK:storevar (fs, e_var, e_val)
763 getlocvar (fs, fs.nactvar-1).startpc = fs.pc
766 ------------------------------------------------------------------------
768 function stat.If (fs, ast)
770 -- Degenerate case #1: no statement
771 if astlen==0 then return block(fs, { }) end
772 -- Degenerate case #2: only an else statement
773 if astlen==1 then return block(fs, ast[1]) end
775 local function test_then_block (fs, test, body)
776 local condexit = cond (fs, test);
781 local escapelist = luaK.NO_JUMP
783 local flist = test_then_block (fs, ast[1], ast[2]) -- 'then' statement
784 for i = 3, #ast - 1, 2 do -- 'elseif' statement
785 escapelist = luaK:concat( fs, escapelist, luaK:jump(fs))
786 luaK:patchtohere (fs, flist)
787 flist = test_then_block (fs, ast[i], ast[i+1])
789 if #ast % 2 == 1 then -- 'else' statement
790 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
791 luaK:patchtohere(fs, flist)
792 block (fs, ast[#ast])
794 escapelist = luaK:concat(fs, escapelist, flist)
796 luaK:patchtohere(fs, escapelist)
799 ------------------------------------------------------------------------
801 function stat.Forin (fs, ast)
802 local vars, vals, body = ast[1], ast[2], ast[3]
803 -- imitating forstat:
805 enterblock (fs, bl, true)
806 -- imitating forlist:
807 local e, base = { }, fs.freereg
808 new_localvar (fs, "(for generator)", 0)
809 new_localvar (fs, "(for state)", 1)
810 new_localvar (fs, "(for control)", 2)
811 for i = 1, #vars do new_localvar (fs, vars[i][1], i+2) end
812 explist (fs, vals, e)
813 adjust_assign (fs, 3, #vals, e)
814 luaK:checkstack (fs, 3)
815 forbody (fs, body, base, #vars, false)
820 ------------------------------------------------------------------------
822 function stat.Fornum (fs, ast)
824 local function exp1 (ast_e)
826 expr.expr (fs, ast_e, e)
827 luaK:exp2nextreg (fs, e)
829 -- imitating forstat:
831 enterblock (fs, bl, true)
833 local base = fs.freereg
834 new_localvar (fs, "(for index)", 0)
835 new_localvar (fs, "(for limit)", 1)
836 new_localvar (fs, "(for step)", 2)
837 new_localvar (fs, ast[1][1], 3)
838 exp1 (ast[2]) -- initial value
839 exp1 (ast[3]) -- limit
840 if #ast == 5 then exp1 (ast[4]) else -- default step = 1
841 luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
842 luaK:reserveregs(fs, 1)
844 forbody (fs, ast[#ast], base, 1, true)
849 ------------------------------------------------------------------------
850 function stat.Repeat (fs, ast)
851 local repeat_init = luaK:getlabel (fs)
852 local bl1, bl2 = { }, { }
853 enterblock (fs, bl1, true)
854 enterblock (fs, bl2, false)
856 local condexit = cond (fs, ast[2])
857 if not bl2.upval then
859 luaK:patchlist (fs, condexit, repeat_init)
862 luaK:patchtohere (fs, condexit)
864 luaK:patchlist (fs, luaK:jump (fs), repeat_init)
869 ------------------------------------------------------------------------
871 function stat.While (fs, ast)
872 local whileinit = luaK:getlabel (fs)
873 local condexit = cond (fs, ast[1])
875 enterblock (fs, bl, true)
877 luaK:patchlist (fs, luaK:jump (fs), whileinit)
879 luaK:patchtohere (fs, condexit);
882 ------------------------------------------------------------------------
884 -- FIXME: it's cumbersome to write this in this semi-recursive way.
885 function stat.Set (fs, ast)
886 local ast_lhs, ast_vals, e = ast[1], ast[2], { }
888 --print "\n\nSet ast_lhs ast_vals:"
889 --print(disp.ast(ast_lhs))
890 --print(disp.ast(ast_vals))
892 local function let_aux (lhs, nvars)
893 local legal = { VLOCAL=1, VUPVAL=1, VGLOBAL=1, VINDEXED=1 }
895 if not legal [lhs.v.k] then
896 error ("Bad lhs expr: "..table.tostring(ast_lhs))
898 if nvars < #ast_lhs then -- this is not the last lhs
899 local nv = { v = { }, prev = lhs }
900 expr.expr (fs, ast_lhs [nvars+1], nv.v)
901 if nv.v.k == "VLOCAL" then check_conflict (fs, lhs, nv.v) end
902 let_aux (nv, nvars+1)
903 else -- this IS the last lhs
904 explist (fs, ast_vals, e)
905 if #ast_vals < nvars then
906 adjust_assign (fs, nvars, #ast_vals, e)
907 elseif #ast_vals > nvars then
908 adjust_assign (fs, nvars, #ast_vals, e)
909 fs.freereg = fs.freereg - #ast_vals + nvars
910 else -- #ast_vals == nvars (and we're at last lhs)
911 luaK:setoneret (fs, e) -- close last expression
912 luaK:storevar (fs, lhs.v, e)
913 return -- avoid default
916 init_exp (e, "VNONRELOC", fs.freereg - 1) -- default assignment
917 luaK:storevar (fs, lhs.v, e)
920 local lhs = { v = { }, prev = nil }
921 expr.expr (fs, ast_lhs[1], lhs.v)
925 ------------------------------------------------------------------------
927 function stat.Call (fs, ast)
929 expr.Call (fs, ast, v)
930 luaP:SETARG_C (luaK:getcode(fs, v), 1)
933 ------------------------------------------------------------------------
935 function stat.Invoke (fs, ast)
937 expr.Invoke (fs, ast, v)
938 --FIXME: didn't check that, just copied from stat.Call
939 luaP:SETARG_C (luaK:getcode(fs, v), 1)
943 local function patch_goto (fs, src, dst)
948 ------------------------------------------------------------------------
950 -- fs.labels :: string => { nactvar :: int; pc :: int }
951 -- fs.forward_gotos :: string => list(int)
953 -- fs.labels goes from label ids to the number of active variables at
954 -- the label's PC, and that PC
956 -- fs.forward_gotos goes from label ids to the list of the PC where
957 -- some goto wants to jump to this label. Since gotos are actually made
958 -- up of two instructions OP_CLOSE and OP_JMP, it's the first instruction's
959 -- PC that's stored in fs.forward_gotos
961 -- Note that backward gotos aren't stored: since their destination is knowns
962 -- when they're compiled, their target is directly set.
963 ------------------------------------------------------------------------
965 ------------------------------------------------------------------------
966 -- Set a Label to jump to with Goto
967 ------------------------------------------------------------------------
968 function stat.Label (fs, ast)
969 local label_id = ast[1]
970 if type(label_id)=='table' then label_id=label_id[1] end
971 -- printf("Label %s at PC %i", label_id, fs.pc)
972 -------------------------------------------------------------------
973 -- Register the label, so that future gotos can use it.
974 -------------------------------------------------------------------
975 if fs.labels [label_id] then error "Duplicate label in function"
976 else fs.labels [label_id] = { pc = fs.pc; nactvar = fs.nactvar } end
977 local gotos = fs.forward_gotos [label_id]
979 ----------------------------------------------------------------
980 -- Patch forward gotos which were targetting this label.
981 ----------------------------------------------------------------
982 for _, goto_pc in ipairs(gotos) do
983 local close_instr = fs.f.code[goto_pc]
984 local jmp_instr = fs.f.code[goto_pc+1]
985 local goto_nactvar = luaP:GETARG_A (close_instr)
986 if fs.nactvar < goto_nactvar then
987 luaP:SETARG_A (close_instr, fs.nactvar) end
988 luaP:SETARG_sBx (jmp_instr, fs.pc - goto_pc - 2)
990 ----------------------------------------------------------------
991 -- Gotos are patched, they can be forgotten about (when the
992 -- function will be finished, it will be checked that all gotos
993 -- have been patched, by checking that forward_goto is empty).
994 ----------------------------------------------------------------
995 fs.forward_gotos[label_id] = nil
999 ------------------------------------------------------------------------
1000 -- jumps to a label set with stat.Label.
1001 -- Argument must be a String or an Id
1002 -- FIXME/optim: get rid of useless OP_CLOSE when nactvar doesn't change.
1003 -- Thsi must be done both here for backward gotos, and in
1004 -- stat.Label for forward gotos.
1005 ------------------------------------------------------------------------
1006 function stat.Goto (fs, ast)
1007 local label_id = ast[1]
1008 if type(label_id)=='table' then label_id=label_id[1] end
1009 -- printf("Goto %s at PC %i", label_id, fs.pc)
1010 local label = fs.labels[label_id]
1012 ----------------------------------------------------------------
1013 -- Backward goto: the label already exists, so I can get its
1014 -- nactvar and address directly. nactvar is used to close
1015 -- upvalues if we get out of scoping blocks by jumping.
1016 ----------------------------------------------------------------
1017 if fs.nactvar > label.nactvar then
1018 luaK:codeABC (fs, "OP_CLOSE", label.nactvar, 0, 0) end
1019 local offset = label.pc - fs.pc - 1
1020 luaK:codeAsBx (fs, "OP_JMP", 0, offset)
1022 ----------------------------------------------------------------
1023 -- Forward goto: will be patched when the matching label is
1024 -- found, forward_gotos[label_id] keeps the PC of the CLOSE
1025 -- instruction just before the JMP. [stat.Label] will use it to
1026 -- patch the OP_CLOSE and the OP_JMP.
1027 ----------------------------------------------------------------
1028 if not fs.forward_gotos[label_id] then
1029 fs.forward_gotos[label_id] = { } end
1030 table.insert (fs.forward_gotos[label_id], fs.pc)
1031 luaK:codeABC (fs, "OP_CLOSE", fs.nactvar, 0, 0)
1032 luaK:codeAsBx (fs, "OP_JMP", 0, luaK.NO_JUMP)
1036 ------------------------------------------------------------------------
1037 ------------------------------------------------------------------------
1039 -- Expression parsers table
1041 ------------------------------------------------------------------------
1042 ------------------------------------------------------------------------
1044 function expr.expr (fs, ast, v)
1045 if type(ast) ~= "table" then
1046 error ("Expr AST expected, got "..table.tostring(ast)) end
1048 if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1050 --debugf (" - Expression %s", tostringv (ast))
1051 local parser = expr[ast.tag]
1052 if parser then parser (fs, ast, v)
1053 elseif not ast.tag then
1054 error ("No tag in expression "..table.tostring(ast, 'nohash', 80))
1056 error ("No parser for node `"..ast.tag) end
1057 debugf (" - /`%s", ast.tag)
1060 ------------------------------------------------------------------------
1062 function expr.Nil (fs, ast, v) init_exp (v, "VNIL", 0) end
1063 function expr.True (fs, ast, v) init_exp (v, "VTRUE", 0) end
1064 function expr.False (fs, ast, v) init_exp (v, "VFALSE", 0) end
1065 function expr.String (fs, ast, v) codestring (fs, v, ast[1]) end
1066 function expr.Number (fs, ast, v)
1067 init_exp (v, "VKNUM", 0)
1071 function expr.Paren (fs, ast, v)
1072 expr.expr (fs, ast[1], v)
1073 luaK:setoneret (fs, v)
1076 function expr.Dots (fs, ast, v)
1077 assert (fs.f.is_vararg ~= 0, "No vararg in this function")
1078 -- NEEDSARG flag is set if and only if the function is a vararg,
1079 -- but no vararg has been used yet in its code.
1080 if fs.f.is_vararg < VARARG_NEEDSARG then
1081 fs.f.is_varag = fs.f.is_vararg - VARARG_NEEDSARG end
1082 init_exp (v, "VVARARG", luaK:codeABC (fs, "OP_VARARG", 0, 1, 0))
1085 ------------------------------------------------------------------------
1087 function expr.Table (fs, ast, v)
1088 local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
1089 local cc = { v = { } , na = 0, nh = 0, tostore = 0, t = v } -- ConsControl
1090 init_exp (v, "VRELOCABLE", pc)
1091 init_exp (cc.v, "VVOID", 0) -- no value (yet)
1092 luaK:exp2nextreg (fs, v) -- fix it at stack top (for gc)
1094 assert(cc.v.k == "VVOID" or cc.tostore > 0)
1095 closelistfield(fs, cc);
1096 (ast[i].tag == "Pair" and recfield or listfield) (fs, ast[i], cc)
1098 lastlistfield(fs, cc)
1100 -- Configure [OP_NEWTABLE] dimensions
1101 luaP:SETARG_B(fs.f.code[pc], int2fb(cc.na)) -- set initial array size
1102 luaP:SETARG_C(fs.f.code[pc], int2fb(cc.nh)) -- set initial table size
1103 --printv(fs.f.code[pc])
1107 ------------------------------------------------------------------------
1109 function expr.Function (fs, ast, v)
1110 if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1112 local new_fs = open_func(fs)
1113 if ast.lineinfo then
1114 new_fs.f.lineDefined, new_fs.f.lastLineDefined =
1115 ast.lineinfo.first[1], ast.lineinfo.last[1]
1117 parlist (new_fs, ast[1])
1118 chunk (new_fs, ast[2])
1120 pushclosure(fs, new_fs, v)
1123 ------------------------------------------------------------------------
1125 function expr.Op (fs, ast, v)
1126 if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1130 expr.expr (fs, ast[2], v)
1131 luaK:prefix (fs, op, v)
1132 elseif #ast == 3 then
1134 expr.expr (fs, ast[2], v)
1135 luaK:infix (fs, op, v)
1136 expr.expr (fs, ast[3], v2)
1137 luaK:posfix (fs, op, v, v2)
1139 error "Wrong arg number"
1143 ------------------------------------------------------------------------
1145 function expr.Call (fs, ast, v)
1146 expr.expr (fs, ast[1], v)
1147 luaK:exp2nextreg (fs, v)
1148 funcargs(fs, ast, v, 2)
1149 --debugf("after expr.Call: %s, %s", v.k, luaP.opnames[luaK:getcode(fs, v).OP])
1152 ------------------------------------------------------------------------
1153 -- `Invoke{ table key args }
1154 function expr.Invoke (fs, ast, v)
1155 expr.expr (fs, ast[1], v)
1156 luaK:dischargevars (fs, v)
1158 codestring (fs, key, ast[2][1])
1159 luaK:_self (fs, v, key)
1160 funcargs (fs, ast, v, 3)
1163 ------------------------------------------------------------------------
1165 function expr.Index (fs, ast, v)
1167 print"\n\nBAD INDEX AST:"
1169 error "generalized indexes not implemented" end
1171 if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1173 --assert(fs.lastline ~= 0, ast.tag)
1175 expr.expr (fs, ast[1], v)
1176 luaK:exp2anyreg (fs, v)
1179 expr.expr (fs, ast[2], k)
1180 luaK:exp2val (fs, k)
1181 luaK:indexed (fs, v, k)
1184 ------------------------------------------------------------------------
1186 function expr.Id (fs, ast, v)
1187 assert (ast.tag == "Id")
1188 singlevar (fs, ast[1], v)
1191 ------------------------------------------------------------------------
1193 function expr.Stat (fs, ast, v)
1194 --printf(" * Stat: %i actvars, first freereg is %i", fs.nactvar, fs.freereg)
1195 --printf(" actvars: %s", table.tostring(fs.actvar))
1197 -- Protect temporary stack values by pretending they are local
1198 -- variables. Local vars are in registers 0 ... fs.nactvar-1,
1199 -- and temporary unnamed variables in fs.nactvar ... fs.freereg-1
1200 local save_nactvar = fs.nactvar
1202 -- Eventually, the result should go on top of stack *after all
1203 -- `Stat{ } related computation and string usage is over. The index
1204 -- of this destination register is kept here:
1205 local dest_reg = fs.freereg
1207 -- There might be variables in actvar whose register is > nactvar,
1208 -- and therefore will not be protected by the "nactvar := freereg"
1209 -- trick. Indeed, `Local only increases nactvar after the variable
1210 -- content has been computed. Therefore, in
1211 -- "local foo = -{`Stat{...}}", variable foo will be messed up by
1212 -- the compilation of `Stat.
1213 -- FIX: save the active variables at indices >= nactvar in
1214 -- save_actvar, and restore them after `Stat has been computer.
1216 -- I use a while rather than for loops and length operators because
1217 -- fs.actvar is a 0-based array...
1218 local save_actvar = { } do
1219 local i = fs.nactvar
1221 local v = fs.actvar[i]
1222 if not v then break end
1223 --printf("save hald-baked actvar %s at index %i", table.tostring(v), i)
1229 fs.nactvar = fs.freereg -- Now temp unnamed registers are protected
1230 enterblock (fs, { }, false)
1232 expr.expr (fs, ast[2], v)
1233 luaK:exp2nextreg (fs, v)
1235 luaK:exp2reg (fs, v, dest_reg)
1237 -- Reserve the newly allocated stack level
1238 -- Puzzled note: here was written "fs.freereg = fs.freereg+1".
1239 -- I'm pretty sure it should rather be dest_reg+1, but maybe
1240 -- both are equivalent?
1241 fs.freereg = dest_reg+1
1243 -- Restore nactvar, so that intermediate stacked value stop
1245 --printf(" nactvar back from %i to %i", fs.nactvar, save_nactvar)
1246 fs.nactvar = save_nactvar
1248 -- restore messed-up unregistered local vars
1249 for i, j in pairs(save_actvar) do
1250 --printf(" Restoring actvar %i", i)
1253 --printf(" * End of Stat")
1258 ------------------------------------------------------------------------
1259 -- Main function: ast --> proto
1260 ------------------------------------------------------------------------
1261 function metalua_compile (ast, source)
1262 local fs = open_func (nil)
1263 fs.f.is_vararg = VARARG_ISVARARG
1266 assert (fs.prev == nil)
1267 assert (fs.f.nups == 0)
1268 assert (fs.nestlevel == 0)
1269 if source then fs.f.source = source end