1 -------------------------------------------------------------------------------
2 -- Copyright (c) 2006-2013 Kein-Hong Man, Fabien Fleutot and others.
4 -- All rights reserved.
6 -- This program and the accompanying materials are made available
7 -- under the terms of the Eclipse Public License v1.0 which
8 -- accompanies this distribution, and is available at
9 -- http://www.eclipse.org/legal/epl-v10.html
11 -- This program and the accompanying materials are also made available
12 -- under the terms of the MIT public license which accompanies this
13 -- distribution, and is available at http://www.lua.org/license.html
16 -- Kein-Hong Man - Initial implementation for Lua 5.0, part of Yueliang
17 -- Fabien Fleutot - Port to Lua 5.1, integration with Metalua
19 -------------------------------------------------------------------------------
21 ----------------------------------------------------------------------
23 -- This code mainly results from the borrowing, then ruthless abuse, of
24 -- Yueliang's implementation of Lua 5.0 compiler.
26 ---------------------------------------------------------------------
28 local pp = require 'metalua.pprint'
30 local luaK = require 'metalua.compiler.bytecode.lcode'
31 local luaP = require 'metalua.compiler.bytecode.lopcodes'
33 local debugf = function() end
41 M.MAX_INT = 2147483645 -- INT_MAX-2 for 32-bit systems (llimits.h)
42 M.MAXVARS = 200 -- (llimits.h)
43 M.MAXUPVALUES = 32 -- (llimits.h)
44 M.MAXPARAMS = 100 -- (llimits.h)
45 M.LUA_MAXPARSERLEVEL = 200 -- (llimits.h)
52 local function hasmultret (k)
53 return k=="VCALL" or k=="VVARARG"
56 -----------------------------------------------------------------------
57 -- Some ASTs take expression lists as children; it should be
58 -- acceptible to give an expression instead, and to automatically
59 -- interpret it as a single element list. That's what does this
60 -- function, adding a surrounding list iff needed.
62 -- WARNING: "Do" is the tag for chunks, which are essentially lists.
63 -- Therefore, we don't listify stuffs with a "Do" tag.
64 -----------------------------------------------------------------------
65 local function ensure_list (ast)
66 return ast.tag and ast.tag ~= "Do" and {ast} or ast end
68 -----------------------------------------------------------------------
69 -- Get a localvar structure { varname, startpc, endpc } from a
70 -- (zero-based) index of active variable. The catch is: don't get
71 -- confused between local index and active index.
73 -- locvars[x] contains { varname, startpc, endpc };
74 -- actvar[i] contains the index of the variable in locvars
75 -----------------------------------------------------------------------
76 local function getlocvar (fs, i)
77 return fs.f.locvars[fs.actvar[i]]
80 local function removevars (fs, tolevel)
81 while fs.nactvar > tolevel do
82 fs.nactvar = fs.nactvar - 1
83 -- There may be dummy locvars due to expr.Stat
84 -- FIXME: strange that they didn't disappear?!
85 local locvar = getlocvar (fs, fs.nactvar)
86 --printf("[REMOVEVARS] removing var #%i = %s", fs.nactvar,
87 -- locvar and tostringv(locvar) or "<nil>")
88 if locvar then locvar.endpc = fs.pc end
92 -----------------------------------------------------------------------
93 -- [f] has a list of all its local variables, active and inactive.
94 -- Some local vars can correspond to the same register, if they exist
95 -- in different scopes.
96 -- [fs.nlocvars] is the total number of local variables, not to be
97 -- confused with [fs.nactvar] the numebr of variables active at the
99 -- At this stage, the existence of the variable is not yet aknowledged,
100 -- since [fs.nactvar] and [fs.freereg] aren't updated.
101 -----------------------------------------------------------------------
102 local function registerlocalvar (fs, varname)
103 --debugf("[locvar: %s = reg %i]", varname, fs.nlocvars)
105 f.locvars[fs.nlocvars] = { } -- LocVar
106 f.locvars[fs.nlocvars].varname = varname
107 local nlocvars = fs.nlocvars
108 fs.nlocvars = fs.nlocvars + 1
112 -----------------------------------------------------------------------
113 -- update the active vars counter in [fs] by adding [nvars] of them,
114 -- and sets those variables' [startpc] to the current [fs.pc].
115 -- These variables were allready created, but not yet counted, by
117 -----------------------------------------------------------------------
118 local function adjustlocalvars (fs, nvars)
119 --debugf("adjustlocalvars, nvars=%i, previous fs.nactvar=%i,"..
120 -- " #locvars=%i, #actvar=%i",
121 -- nvars, fs.nactvar, #fs.f.locvars, #fs.actvar)
123 fs.nactvar = fs.nactvar + nvars
124 for i = nvars, 1, -1 do
125 --printf ("adjusting actvar #%i", fs.nactvar - i)
126 getlocvar (fs, fs.nactvar - i).startpc = fs.pc
130 ------------------------------------------------------------------------
131 -- check whether, in an assignment to a local variable, the local variable
132 -- is needed in a previous assignment (to a table). If so, save original
133 -- local value in a safe place and use this safe copy in the previous
135 ------------------------------------------------------------------------
136 local function check_conflict (fs, lh, v)
137 local extra = fs.freereg -- eventual position to save local variable
138 local conflict = false
140 if lh.v.k == "VINDEXED" then
141 if lh.v.info == v.info then -- conflict?
143 lh.v.info = extra -- previous assignment will use safe copy
145 if lh.v.aux == v.info then -- conflict?
147 lh.v.aux = extra -- previous assignment will use safe copy
153 luaK:codeABC (fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
154 luaK:reserveregs (fs, 1)
158 -----------------------------------------------------------------------
159 -- Create an expdesc. To be updated when expdesc is lua-ified.
160 -----------------------------------------------------------------------
161 local function init_exp (e, k, i)
162 e.f, e.t, e.k, e.info = luaK.NO_JUMP, luaK.NO_JUMP, k, i end
164 -----------------------------------------------------------------------
165 -- Reserve the string in tthe constant pool, and return an expdesc
167 -----------------------------------------------------------------------
168 local function codestring (fs, e, str)
169 --printf( "codestring(%s)", disp.ast(str))
170 init_exp (e, "VK", luaK:stringK (fs, str))
173 -----------------------------------------------------------------------
174 -- search for a local variable named [name] in the function being
175 -- built by [fs]. Doesn't try to visit upvalues.
176 -----------------------------------------------------------------------
177 local function searchvar (fs, name)
178 for i = fs.nactvar - 1, 0, -1 do
179 -- Because of expr.Stat, there can be some actvars which don't
180 -- correspond to any locvar. Hence the checking for locvar's
181 -- nonnilness before getting the varname.
182 local locvar = getlocvar(fs, i)
183 if locvar and name == locvar.varname then
184 --printf("Found local var: %s; i = %i", tostringv(locvar), i)
188 return -1 -- not found
191 -----------------------------------------------------------------------
192 -- create and return a new proto [f]
193 -----------------------------------------------------------------------
194 local function newproto ()
217 ------------------------------------------------------------------------
218 -- create and return a function state [new_fs] as a sub-funcstate of [fs].
219 ------------------------------------------------------------------------
220 local function open_func (old_fs)
222 new_fs.upvalues = { }
224 local f = newproto ()
226 new_fs.prev = old_fs -- linked list of funcstates
228 new_fs.lasttarget = -1
229 new_fs.jpc = luaK.NO_JUMP
232 new_fs.h = {} -- constant table; was luaH_new call
237 new_fs.nestlevel = old_fs and old_fs.nestlevel or 0
238 f.maxstacksize = 2 -- registers 0/1 are always valid
240 new_fs.forward_gotos = { }
245 ------------------------------------------------------------------------
246 -- Finish to set up [f] according to final state of [fs]
247 ------------------------------------------------------------------------
248 local function close_func (fs)
250 --printf("[CLOSE_FUNC] remove any remaining var")
254 f.sizelineinfo = fs.pc
257 f.sizelocvars = fs.nlocvars
258 f.sizeupvalues = f.nups
259 assert (fs.bl == nil)
260 if next(fs.forward_gotos) then
261 local x = pp.tostring(fs.forward_gotos)
262 error ("Unresolved goto: "..x)
266 ------------------------------------------------------------------------
268 ------------------------------------------------------------------------
269 local function pushclosure(fs, func, v)
273 init_exp (v, "VRELOCABLE", luaK:codeABx (fs, "OP_CLOSURE", 0, fs.np - 1))
274 for i = 0, func.f.nups - 1 do
275 local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
276 luaK:codeABC (fs, o, 0, func.upvalues[i].info, 0)
280 ------------------------------------------------------------------------
281 -- FIXME: is there a need for f=fs.f? if yes, why not always using it?
282 ------------------------------------------------------------------------
283 local function indexupvalue(fs, name, v)
285 for i = 0, f.nups - 1 do
286 if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
287 assert(fs.f.upvalues[i] == name)
292 f.upvalues[f.nups] = name
293 assert (v.k == "VLOCAL" or v.k == "VUPVAL")
294 fs.upvalues[f.nups] = { k = v.k; info = v.info }
300 ------------------------------------------------------------------------
302 ------------------------------------------------------------------------
303 local function markupval(fs, level)
305 while bl and bl.nactvar > level do bl = bl.previous end
306 if bl then bl.upval = true end
312 local function bldepth(fs)
314 while x do i=i+1; x=x.previous end
319 ------------------------------------------------------------------------
321 ------------------------------------------------------------------------
322 local function enterblock (fs, bl, isbreakable)
323 bl.breaklist = luaK.NO_JUMP
324 bl.isbreakable = isbreakable
325 bl.nactvar = fs.nactvar
329 assert (fs.freereg == fs.nactvar)
332 ------------------------------------------------------------------------
334 ------------------------------------------------------------------------
335 local function leaveblock (fs)
338 --printf("[LEAVEBLOCK] Removing vars...")
339 removevars (fs, bl.nactvar)
340 --printf("[LEAVEBLOCK] ...Vars removed")
342 luaK:codeABC (fs, "OP_CLOSE", bl.nactvar, 0, 0)
344 -- a block either controls scope or breaks (never both)
345 assert (not bl.isbreakable or not bl.upval)
346 assert (bl.nactvar == fs.nactvar)
347 fs.freereg = fs.nactvar -- free registers
348 luaK:patchtohere (fs, bl.breaklist)
352 ------------------------------------------------------------------------
353 -- read a list of expressions from a list of ast [astlist]
354 -- starts at the [offset]th element of the list (defaults to 1)
355 ------------------------------------------------------------------------
356 local function explist(fs, astlist, v, offset)
358 if #astlist < offset then error "I don't handle empty expr lists yet" end
359 --printf("[EXPLIST] about to precompile 1st element %s", disp.ast(astlist[offset]))
360 expr.expr (fs, astlist[offset], v)
361 --printf("[EXPLIST] precompiled first element v=%s", tostringv(v))
362 for i = offset+1, #astlist do
363 luaK:exp2nextreg (fs, v)
364 --printf("[EXPLIST] flushed v=%s", tostringv(v))
365 expr.expr (fs, astlist[i], v)
366 --printf("[EXPLIST] precompiled element v=%s", tostringv(v))
368 return #astlist - offset + 1
371 ------------------------------------------------------------------------
373 ------------------------------------------------------------------------
374 local function funcargs (fs, ast, v, idx_from)
375 local args = { } -- expdesc
377 if #ast < idx_from then args.k = "VVOID" else
378 explist(fs, ast, args, idx_from)
379 luaK:setmultret(fs, args)
381 assert(v.k == "VNONRELOC")
382 local base = v.info -- base register for call
383 if hasmultret(args.k) then nparams = luaK.LUA_MULTRET else -- open call
384 if args.k ~= "VVOID" then
385 luaK:exp2nextreg(fs, args) end -- close last argument
386 nparams = fs.freereg - (base + 1)
388 init_exp(v, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
390 luaK:fixline(fs, ast.lineinfo.first.line)
392 luaK:fixline(fs, ast.line)
394 fs.freereg = base + 1 -- call remove function and arguments and leaves
395 -- (unless changed) one result
398 ------------------------------------------------------------------------
399 -- calculates log value for encoding the hash portion's size
400 ------------------------------------------------------------------------
401 local function log2(x)
402 -- math result is always one more than lua0_log2()
403 local mn, ex = math.frexp(x)
407 ------------------------------------------------------------------------
408 -- converts an integer to a "floating point byte", represented as
409 -- (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
410 ------------------------------------------------------------------------
412 -- local function int2fb(x)
413 -- local m = 0 -- mantissa
414 -- while x >= 8 do x = math.floor((x + 1) / 2); m = m + 1 end
418 local function int2fb(x)
421 x = math.floor ( (x+1) / 2)
425 else return (e+1) * 8 + x - 8 end
429 ------------------------------------------------------------------------
430 -- FIXME: to be unified with singlevar
431 ------------------------------------------------------------------------
432 local function singlevaraux(fs, n, var, base)
434 print("\n\nsinglevaraux: fs, n, var, base")
441 if fs == nil then -- no more levels?
442 init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
445 local v = searchvar(fs, n) -- look up at current level
447 init_exp(var, "VLOCAL", v)
449 markupval(fs, v) -- local will be used as an upval
451 else -- not found at current level; try upper one
452 if singlevaraux(fs.prev, n, var, false) == "VGLOBAL" then
454 var.info = indexupvalue (fs, n, var)
461 ------------------------------------------------------------------------
463 ------------------------------------------------------------------------
464 local function singlevar(fs, varname, var)
465 if singlevaraux(fs, varname, var, true) == "VGLOBAL" then
466 var.info = luaK:stringK (fs, varname) end
469 ------------------------------------------------------------------------
471 ------------------------------------------------------------------------
472 local function new_localvar (fs, name, n)
473 assert (type (name) == "string")
474 if fs.nactvar + n > M.MAXVARS then error ("too many local vars") end
475 fs.actvar[fs.nactvar + n] = registerlocalvar (fs, name)
476 --printf("[NEW_LOCVAR] %i = %s", fs.nactvar+n, name)
479 ------------------------------------------------------------------------
481 ------------------------------------------------------------------------
482 local function parlist (fs, ast_params)
483 local dots = (#ast_params > 0 and ast_params[#ast_params].tag == "Dots")
484 local nparams = dots and #ast_params - 1 or #ast_params
485 for i = 1, nparams do
486 assert (ast_params[i].tag == "Id", "Function parameters must be Ids")
487 new_localvar (fs, ast_params[i][1], i-1)
489 -- from [code_param]:
490 --checklimit (fs, fs.nactvar, self.M.MAXPARAMS, "parameters")
491 fs.f.numparams = fs.nactvar
492 fs.f.is_vararg = dots and M.VARARG_ISVARARG or 0
493 adjustlocalvars (fs, nparams)
494 fs.f.numparams = fs.nactvar --FIXME vararg must be taken in account
495 luaK:reserveregs (fs, fs.nactvar) -- reserve register for parameters
498 ------------------------------------------------------------------------
499 -- if there's more variables than expressions in an assignment,
500 -- some assignations to nil are made for extraneous vars.
501 -- Also handles multiret functions
502 ------------------------------------------------------------------------
503 local function adjust_assign (fs, nvars, nexps, e)
504 local extra = nvars - nexps
505 if hasmultret (e.k) then
506 extra = extra+1 -- includes call itself
507 if extra <= 0 then extra = 0 end
508 luaK:setreturns(fs, e, extra) -- call provides the difference
509 if extra > 1 then luaK:reserveregs(fs, extra-1) end
511 if e.k ~= "VVOID" then
512 luaK:exp2nextreg(fs, e) end -- close last expression
514 local reg = fs.freereg
515 luaK:reserveregs(fs, extra)
516 luaK:_nil(fs, reg, extra)
522 ------------------------------------------------------------------------
524 ------------------------------------------------------------------------
525 local function enterlevel (fs)
526 fs.nestlevel = fs.nestlevel + 1
527 assert (fs.nestlevel <= M.LUA_MAXPARSERLEVEL, "too many syntax levels")
530 ------------------------------------------------------------------------
532 ------------------------------------------------------------------------
533 local function leavelevel (fs)
534 fs.nestlevel = fs.nestlevel - 1
537 ------------------------------------------------------------------------
538 -- Parse conditions in if/then/else, while, repeat
539 ------------------------------------------------------------------------
540 local function cond (fs, ast)
542 expr.expr(fs, ast, v) -- read condition
543 if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
544 luaK:goiftrue (fs, v)
548 ------------------------------------------------------------------------
550 ------------------------------------------------------------------------
551 local function chunk (fs, ast)
555 stat.stat (fs, ast[i]);
556 fs.freereg = fs.nactvar
561 ------------------------------------------------------------------------
563 ------------------------------------------------------------------------
564 local function block (fs, ast)
566 enterblock (fs, bl, false)
568 stat.stat (fs, ast[i])
569 fs.freereg = fs.nactvar
571 assert (bl.breaklist == luaK.NO_JUMP)
575 ------------------------------------------------------------------------
576 -- Forin / Fornum body parser
582 ------------------------------------------------------------------------
583 local function forbody (fs, ast_body, base, nvars, isnum)
584 local bl = {} -- BlockCnt
585 adjustlocalvars (fs, 3) -- control variables
587 isnum and luaK:codeAsBx (fs, "OP_FORPREP", base, luaK.NO_JUMP)
589 enterblock (fs, bl, false) -- loop block
590 adjustlocalvars (fs, nvars) -- scope for declared variables
591 luaK:reserveregs (fs, nvars)
594 --luaK:patchtohere (fs, prep-1)
595 luaK:patchtohere (fs, prep)
597 isnum and luaK:codeAsBx (fs, "OP_FORLOOP", base, luaK.NO_JUMP)
598 or luaK:codeABC (fs, "OP_TFORLOOP", base, 0, nvars)
599 luaK:fixline (fs, ast_body.line) -- pretend that 'OP_FOR' starts the loop
600 luaK:patchlist (fs, isnum and endfor or luaK:jump(fs), prep + 1)
604 ------------------------------------------------------------------------
606 ------------------------------------------------------------------------
607 local function recfield (fs, ast, cc)
608 local reg = fs.freereg
609 local key, val = {}, {} -- expdesc
610 --FIXME: expr + exp2val = index -->
611 -- check reduncancy between exp2val and exp2rk
613 expr.expr(fs, ast[1], key);
614 luaK:exp2val (fs, key)
615 local keyreg = luaK:exp2RK (fs, key)
616 expr.expr(fs, ast[2], val)
617 local valreg = luaK:exp2RK (fs, val)
618 luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, keyreg, valreg)
619 fs.freereg = reg -- free registers
623 ------------------------------------------------------------------------
625 ------------------------------------------------------------------------
626 local function listfield(fs, ast, cc)
627 expr.expr(fs, ast, cc.v)
628 assert (cc.na <= luaP.MAXARG_Bx) -- FIXME check <= or <
630 cc.tostore = cc.tostore + 1
633 ------------------------------------------------------------------------
635 ------------------------------------------------------------------------
636 local function closelistfield(fs, cc)
637 if cc.v.k == "VVOID" then return end -- there is no list item
638 luaK:exp2nextreg(fs, cc.v)
640 if cc.tostore == luaP.LFIELDS_PER_FLUSH then
641 luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
646 ------------------------------------------------------------------------
647 -- The last field might be a call to a multireturn function. In that
648 -- case, we must unfold all of its results into the list.
649 ------------------------------------------------------------------------
650 local function lastlistfield(fs, cc)
651 if cc.tostore == 0 then return end
652 if hasmultret (cc.v.k) then
653 luaK:setmultret(fs, cc.v)
654 luaK:setlist (fs, cc.t.info, cc.na, luaK.LUA_MULTRET)
657 if cc.v.k ~= "VVOID" then luaK:exp2nextreg(fs, cc.v) end
658 luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
661 ------------------------------------------------------------------------
662 ------------------------------------------------------------------------
664 -- Statement parsers table
666 ------------------------------------------------------------------------
667 ------------------------------------------------------------------------
669 function stat.stat (fs, ast)
670 if ast.lineinfo then fs.lastline = ast.lineinfo.last.line end
671 --debugf (" - Statement %s", table.tostring (ast) )
673 if not ast.tag then chunk (fs, ast) else
675 local parser = stat [ast.tag]
677 error ("A statement cannot have tag `"..ast.tag) end
680 --debugf (" - /Statement `%s", ast.tag)
683 ------------------------------------------------------------------------
687 ------------------------------------------------------------------------
689 function stat.Break (fs, ast)
690 -- if ast.lineinfo then fs.lastline = ast.lineinfo.last.line
691 local bl, upval = fs.bl, false
692 while bl and not bl.isbreakable do
693 if bl.upval then upval = true end
696 assert (bl, "no loop to break")
697 if upval then luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) end
698 bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
701 ------------------------------------------------------------------------
703 function stat.Return (fs, ast)
704 local e = {} -- expdesc
705 local first -- registers with returned values
708 if nret == 0 then first = 0
710 --printf("[RETURN] compiling explist")
712 --printf("[RETURN] explist e=%s", tostringv(e))
713 if hasmultret (e.k) then
714 luaK:setmultret(fs, e)
715 if e.k == "VCALL" and nret == 1 then
716 luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
717 assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
720 nret = luaK.LUA_MULTRET -- return all values
721 elseif nret == 1 then
722 first = luaK:exp2anyreg(fs, e)
724 --printf("* Return multiple vals in nextreg %i", fs.freereg)
725 luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
726 first = fs.nactvar -- return all 'active' values
727 assert(nret == fs.freereg - first)
730 luaK:ret(fs, first, nret)
732 ------------------------------------------------------------------------
734 function stat.Local (fs, ast)
735 local names, values = ast[1], ast[2] or { }
736 for i = 1, #names do new_localvar (fs, names[i][1], i-1) end
738 if #values == 0 then e.k = "VVOID" else explist (fs, values, e) end
739 adjust_assign (fs, #names, #values, e)
740 adjustlocalvars (fs, #names)
743 ------------------------------------------------------------------------
745 function stat.Localrec (fs, ast)
746 assert(#ast[1]==1 and #ast[2]==1, "Multiple letrecs not implemented yet")
747 local ast_var, ast_val, e_var, e_val = ast[1][1], ast[2][1], { }, { }
748 new_localvar (fs, ast_var[1], 0)
749 init_exp (e_var, "VLOCAL", fs.freereg)
750 luaK:reserveregs (fs, 1)
751 adjustlocalvars (fs, 1)
752 expr.expr (fs, ast_val, e_val)
753 luaK:storevar (fs, e_var, e_val)
754 getlocvar (fs, fs.nactvar-1).startpc = fs.pc
757 ------------------------------------------------------------------------
759 function stat.If (fs, ast)
761 -- Degenerate case #1: no statement
762 if astlen==0 then return block(fs, { }) end
763 -- Degenerate case #2: only an else statement
764 if astlen==1 then return block(fs, ast[1]) end
766 local function test_then_block (fs, test, body)
767 local condexit = cond (fs, test);
772 local escapelist = luaK.NO_JUMP
774 local flist = test_then_block (fs, ast[1], ast[2]) -- 'then' statement
775 for i = 3, #ast - 1, 2 do -- 'elseif' statement
776 escapelist = luaK:concat( fs, escapelist, luaK:jump(fs))
777 luaK:patchtohere (fs, flist)
778 flist = test_then_block (fs, ast[i], ast[i+1])
780 if #ast % 2 == 1 then -- 'else' statement
781 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
782 luaK:patchtohere(fs, flist)
783 block (fs, ast[#ast])
785 escapelist = luaK:concat(fs, escapelist, flist)
787 luaK:patchtohere(fs, escapelist)
790 ------------------------------------------------------------------------
792 function stat.Forin (fs, ast)
793 local vars, vals, body = ast[1], ast[2], ast[3]
794 -- imitating forstat:
796 enterblock (fs, bl, true)
797 -- imitating forlist:
798 local e, base = { }, fs.freereg
799 new_localvar (fs, "(for generator)", 0)
800 new_localvar (fs, "(for state)", 1)
801 new_localvar (fs, "(for control)", 2)
802 for i = 1, #vars do new_localvar (fs, vars[i][1], i+2) end
803 explist (fs, vals, e)
804 adjust_assign (fs, 3, #vals, e)
805 luaK:checkstack (fs, 3)
806 forbody (fs, body, base, #vars, false)
811 ------------------------------------------------------------------------
813 function stat.Fornum (fs, ast)
815 local function exp1 (ast_e)
817 expr.expr (fs, ast_e, e)
818 luaK:exp2nextreg (fs, e)
820 -- imitating forstat:
822 enterblock (fs, bl, true)
824 local base = fs.freereg
825 new_localvar (fs, "(for index)", 0)
826 new_localvar (fs, "(for limit)", 1)
827 new_localvar (fs, "(for step)", 2)
828 new_localvar (fs, ast[1][1], 3)
829 exp1 (ast[2]) -- initial value
830 exp1 (ast[3]) -- limit
831 if #ast == 5 then exp1 (ast[4]) else -- default step = 1
832 luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
833 luaK:reserveregs(fs, 1)
835 forbody (fs, ast[#ast], base, 1, true)
840 ------------------------------------------------------------------------
841 function stat.Repeat (fs, ast)
842 local repeat_init = luaK:getlabel (fs)
843 local bl1, bl2 = { }, { }
844 enterblock (fs, bl1, true)
845 enterblock (fs, bl2, false)
847 local condexit = cond (fs, ast[2])
848 if not bl2.upval then
850 luaK:patchlist (fs, condexit, repeat_init)
853 luaK:patchtohere (fs, condexit)
855 luaK:patchlist (fs, luaK:jump (fs), repeat_init)
860 ------------------------------------------------------------------------
862 function stat.While (fs, ast)
863 local whileinit = luaK:getlabel (fs)
864 local condexit = cond (fs, ast[1])
866 enterblock (fs, bl, true)
868 luaK:patchlist (fs, luaK:jump (fs), whileinit)
870 luaK:patchtohere (fs, condexit);
873 ------------------------------------------------------------------------
875 -- FIXME: it's cumbersome to write this in this semi-recursive way.
876 function stat.Set (fs, ast)
877 local ast_lhs, ast_vals, e = ast[1], ast[2], { }
879 --print "\n\nSet ast_lhs ast_vals:"
880 --print(disp.ast(ast_lhs))
881 --print(disp.ast(ast_vals))
883 local function let_aux (lhs, nvars)
884 local legal = { VLOCAL=1, VUPVAL=1, VGLOBAL=1, VINDEXED=1 }
886 if not legal [lhs.v.k] then
887 error ("Bad lhs expr: "..pp.tostring(ast_lhs))
889 if nvars < #ast_lhs then -- this is not the last lhs
890 local nv = { v = { }, prev = lhs }
891 expr.expr (fs, ast_lhs [nvars+1], nv.v)
892 if nv.v.k == "VLOCAL" then check_conflict (fs, lhs, nv.v) end
893 let_aux (nv, nvars+1)
894 else -- this IS the last lhs
895 explist (fs, ast_vals, e)
896 if #ast_vals < nvars then
897 adjust_assign (fs, nvars, #ast_vals, e)
898 elseif #ast_vals > nvars then
899 adjust_assign (fs, nvars, #ast_vals, e)
900 fs.freereg = fs.freereg - #ast_vals + nvars
901 else -- #ast_vals == nvars (and we're at last lhs)
902 luaK:setoneret (fs, e) -- close last expression
903 luaK:storevar (fs, lhs.v, e)
904 return -- avoid default
907 init_exp (e, "VNONRELOC", fs.freereg - 1) -- default assignment
908 luaK:storevar (fs, lhs.v, e)
911 local lhs = { v = { }, prev = nil }
912 expr.expr (fs, ast_lhs[1], lhs.v)
916 ------------------------------------------------------------------------
918 function stat.Call (fs, ast)
920 expr.Call (fs, ast, v)
921 luaP:SETARG_C (luaK:getcode(fs, v), 1)
924 ------------------------------------------------------------------------
926 function stat.Invoke (fs, ast)
928 expr.Invoke (fs, ast, v)
929 --FIXME: didn't check that, just copied from stat.Call
930 luaP:SETARG_C (luaK:getcode(fs, v), 1)
934 local function patch_goto (fs, src, dst)
939 ------------------------------------------------------------------------
941 -- fs.labels :: string => { nactvar :: int; pc :: int }
942 -- fs.forward_gotos :: string => list(int)
944 -- fs.labels goes from label ids to the number of active variables at
945 -- the label's PC, and that PC
947 -- fs.forward_gotos goes from label ids to the list of the PC where
948 -- some goto wants to jump to this label. Since gotos are actually made
949 -- up of two instructions OP_CLOSE and OP_JMP, it's the first instruction's
950 -- PC that's stored in fs.forward_gotos
952 -- Note that backward gotos aren't stored: since their destination is knowns
953 -- when they're compiled, their target is directly set.
954 ------------------------------------------------------------------------
956 ------------------------------------------------------------------------
957 -- Set a Label to jump to with Goto
958 ------------------------------------------------------------------------
959 function stat.Label (fs, ast)
960 local label_id = ast[1]
961 if type(label_id)=='table' then label_id=label_id[1] end
962 -- printf("Label %s at PC %i", label_id, fs.pc)
963 -------------------------------------------------------------------
964 -- Register the label, so that future gotos can use it.
965 -------------------------------------------------------------------
966 if fs.labels [label_id] then error "Duplicate label in function"
967 else fs.labels [label_id] = { pc = fs.pc; nactvar = fs.nactvar } end
968 local gotos = fs.forward_gotos [label_id]
970 ----------------------------------------------------------------
971 -- Patch forward gotos which were targetting this label.
972 ----------------------------------------------------------------
973 for _, goto_pc in ipairs(gotos) do
974 local close_instr = fs.f.code[goto_pc]
975 local jmp_instr = fs.f.code[goto_pc+1]
976 local goto_nactvar = luaP:GETARG_A (close_instr)
977 if fs.nactvar < goto_nactvar then
978 luaP:SETARG_A (close_instr, fs.nactvar) end
979 luaP:SETARG_sBx (jmp_instr, fs.pc - goto_pc - 2)
981 ----------------------------------------------------------------
982 -- Gotos are patched, they can be forgotten about (when the
983 -- function will be finished, it will be checked that all gotos
984 -- have been patched, by checking that forward_goto is empty).
985 ----------------------------------------------------------------
986 fs.forward_gotos[label_id] = nil
990 ------------------------------------------------------------------------
991 -- jumps to a label set with stat.Label.
992 -- Argument must be a String or an Id
993 -- FIXME/optim: get rid of useless OP_CLOSE when nactvar doesn't change.
994 -- Thsi must be done both here for backward gotos, and in
995 -- stat.Label for forward gotos.
996 ------------------------------------------------------------------------
997 function stat.Goto (fs, ast)
998 local label_id = ast[1]
999 if type(label_id)=='table' then label_id=label_id[1] end
1000 -- printf("Goto %s at PC %i", label_id, fs.pc)
1001 local label = fs.labels[label_id]
1003 ----------------------------------------------------------------
1004 -- Backward goto: the label already exists, so I can get its
1005 -- nactvar and address directly. nactvar is used to close
1006 -- upvalues if we get out of scoping blocks by jumping.
1007 ----------------------------------------------------------------
1008 if fs.nactvar > label.nactvar then
1009 luaK:codeABC (fs, "OP_CLOSE", label.nactvar, 0, 0) end
1010 local offset = label.pc - fs.pc - 1
1011 luaK:codeAsBx (fs, "OP_JMP", 0, offset)
1013 ----------------------------------------------------------------
1014 -- Forward goto: will be patched when the matching label is
1015 -- found, forward_gotos[label_id] keeps the PC of the CLOSE
1016 -- instruction just before the JMP. [stat.Label] will use it to
1017 -- patch the OP_CLOSE and the OP_JMP.
1018 ----------------------------------------------------------------
1019 if not fs.forward_gotos[label_id] then
1020 fs.forward_gotos[label_id] = { } end
1021 table.insert (fs.forward_gotos[label_id], fs.pc)
1022 luaK:codeABC (fs, "OP_CLOSE", fs.nactvar, 0, 0)
1023 luaK:codeAsBx (fs, "OP_JMP", 0, luaK.NO_JUMP)
1027 ------------------------------------------------------------------------
1028 ------------------------------------------------------------------------
1030 -- Expression parsers table
1032 ------------------------------------------------------------------------
1033 ------------------------------------------------------------------------
1035 function expr.expr (fs, ast, v)
1036 if type(ast) ~= "table" then
1037 error ("Expr AST expected, got "..pp.tostring(ast)) end
1039 if ast.lineinfo then fs.lastline = ast.lineinfo.last.line end
1041 --debugf (" - Expression %s", table.tostring (ast))
1042 local parser = expr[ast.tag]
1043 if parser then parser (fs, ast, v)
1044 elseif not ast.tag then
1045 error ("No tag in expression "..
1046 pp.tostring(ast, {line_max=80, hide_hash=1, metalua_tag=1}))
1048 error ("No parser for node `"..ast.tag) end
1049 --debugf (" - /Expression `%s", ast.tag)
1052 ------------------------------------------------------------------------
1054 function expr.Nil (fs, ast, v) init_exp (v, "VNIL", 0) end
1055 function expr.True (fs, ast, v) init_exp (v, "VTRUE", 0) end
1056 function expr.False (fs, ast, v) init_exp (v, "VFALSE", 0) end
1057 function expr.String (fs, ast, v) codestring (fs, v, ast[1]) end
1058 function expr.Number (fs, ast, v)
1059 init_exp (v, "VKNUM", 0)
1063 function expr.Paren (fs, ast, v)
1064 expr.expr (fs, ast[1], v)
1065 luaK:setoneret (fs, v)
1068 function expr.Dots (fs, ast, v)
1069 assert (fs.f.is_vararg ~= 0, "No vararg in this function")
1070 -- NEEDSARG flag is set if and only if the function is a vararg,
1071 -- but no vararg has been used yet in its code.
1072 if fs.f.is_vararg < M.VARARG_NEEDSARG then
1073 fs.f.is_varag = fs.f.is_vararg - M.VARARG_NEEDSARG end
1074 init_exp (v, "VVARARG", luaK:codeABC (fs, "OP_VARARG", 0, 1, 0))
1077 ------------------------------------------------------------------------
1079 function expr.Table (fs, ast, v)
1080 local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
1081 local cc = { v = { } , na = 0, nh = 0, tostore = 0, t = v } -- ConsControl
1082 init_exp (v, "VRELOCABLE", pc)
1083 init_exp (cc.v, "VVOID", 0) -- no value (yet)
1084 luaK:exp2nextreg (fs, v) -- fix it at stack top (for gc)
1086 assert(cc.v.k == "VVOID" or cc.tostore > 0)
1087 closelistfield(fs, cc);
1088 (ast[i].tag == "Pair" and recfield or listfield) (fs, ast[i], cc)
1090 lastlistfield(fs, cc)
1092 -- Configure [OP_NEWTABLE] dimensions
1093 luaP:SETARG_B(fs.f.code[pc], int2fb(cc.na)) -- set initial array size
1094 luaP:SETARG_C(fs.f.code[pc], int2fb(cc.nh)) -- set initial table size
1095 --printv(fs.f.code[pc])
1099 ------------------------------------------------------------------------
1101 function expr.Function (fs, ast, v)
1102 if ast.lineinfo then fs.lastline = ast.lineinfo.last.line end
1104 local new_fs = open_func(fs)
1105 if ast.lineinfo then
1106 new_fs.f.lineDefined, new_fs.f.lastLineDefined =
1107 ast.lineinfo.first.line, ast.lineinfo.last.line
1109 parlist (new_fs, ast[1])
1110 chunk (new_fs, ast[2])
1112 pushclosure(fs, new_fs, v)
1115 ------------------------------------------------------------------------
1117 function expr.Op (fs, ast, v)
1118 if ast.lineinfo then fs.lastline = ast.lineinfo.last.line end
1122 expr.expr (fs, ast[2], v)
1123 luaK:prefix (fs, op, v)
1124 elseif #ast == 3 then
1126 expr.expr (fs, ast[2], v)
1127 luaK:infix (fs, op, v)
1128 expr.expr (fs, ast[3], v2)
1129 luaK:posfix (fs, op, v, v2)
1131 error "Wrong arg number"
1135 ------------------------------------------------------------------------
1137 function expr.Call (fs, ast, v)
1138 expr.expr (fs, ast[1], v)
1139 luaK:exp2nextreg (fs, v)
1140 funcargs(fs, ast, v, 2)
1141 --debugf("after expr.Call: %s, %s", v.k, luaP.opnames[luaK:getcode(fs, v).OP])
1144 ------------------------------------------------------------------------
1145 -- `Invoke{ table key args }
1146 function expr.Invoke (fs, ast, v)
1147 expr.expr (fs, ast[1], v)
1148 luaK:dischargevars (fs, v)
1150 codestring (fs, key, ast[2][1])
1151 luaK:_self (fs, v, key)
1152 funcargs (fs, ast, v, 3)
1155 ------------------------------------------------------------------------
1157 function expr.Index (fs, ast, v)
1159 print"\n\nBAD INDEX AST:"
1161 error "generalized indexes not implemented" end
1163 if ast.lineinfo then fs.lastline = ast.lineinfo.last.line end
1165 --assert(fs.lastline ~= 0, ast.tag)
1167 expr.expr (fs, ast[1], v)
1168 luaK:exp2anyreg (fs, v)
1171 expr.expr (fs, ast[2], k)
1172 luaK:exp2val (fs, k)
1173 luaK:indexed (fs, v, k)
1176 ------------------------------------------------------------------------
1178 function expr.Id (fs, ast, v)
1179 assert (ast.tag == "Id")
1180 singlevar (fs, ast[1], v)
1183 ------------------------------------------------------------------------
1185 function expr.Stat (fs, ast, v)
1186 --printf(" * Stat: %i actvars, first freereg is %i", fs.nactvar, fs.freereg)
1187 --printf(" actvars: %s", table.tostring(fs.actvar))
1189 -- Protect temporary stack values by pretending they are local
1190 -- variables. Local vars are in registers 0 ... fs.nactvar-1,
1191 -- and temporary unnamed variables in fs.nactvar ... fs.freereg-1
1192 local save_nactvar = fs.nactvar
1194 -- Eventually, the result should go on top of stack *after all
1195 -- `Stat{ } related computation and string usage is over. The index
1196 -- of this destination register is kept here:
1197 local dest_reg = fs.freereg
1199 -- There might be variables in actvar whose register is > nactvar,
1200 -- and therefore will not be protected by the "nactvar := freereg"
1201 -- trick. Indeed, `Local only increases nactvar after the variable
1202 -- content has been computed. Therefore, in
1203 -- "local foo = -{`Stat{...}}", variable foo will be messed up by
1204 -- the compilation of `Stat.
1205 -- FIX: save the active variables at indices >= nactvar in
1206 -- save_actvar, and restore them after `Stat has been computed.
1208 -- I use a while rather than for loops and length operators because
1209 -- fs.actvar is a 0-based array...
1210 local save_actvar = { } do
1211 local i = fs.nactvar
1213 local v = fs.actvar[i]
1214 if not v then break end
1215 --printf("save hald-baked actvar %s at index %i", table.tostring(v), i)
1221 fs.nactvar = fs.freereg -- Now temp unnamed registers are protected
1222 enterblock (fs, { }, false)
1224 expr.expr (fs, ast[2], v)
1225 luaK:exp2nextreg (fs, v)
1227 luaK:exp2reg (fs, v, dest_reg)
1229 -- Reserve the newly allocated stack level
1230 -- Puzzled note: here was written "fs.freereg = fs.freereg+1".
1231 -- I'm pretty sure it should rather be dest_reg+1, but maybe
1232 -- both are equivalent?
1233 fs.freereg = dest_reg+1
1235 -- Restore nactvar, so that intermediate stacked value stop
1237 --printf(" nactvar back from %i to %i", fs.nactvar, save_nactvar)
1238 fs.nactvar = save_nactvar
1240 -- restore messed-up unregistered local vars
1241 for i, j in pairs(save_actvar) do
1242 --printf(" Restoring actvar %i", i)
1245 --printf(" * End of Stat")
1248 ------------------------------------------------------------------------
1249 -- Main function: ast --> proto
1250 ------------------------------------------------------------------------
1251 function M.ast_to_proto (ast, source)
1252 local fs = open_func (nil)
1253 fs.f.is_vararg = M.VARARG_ISVARARG
1256 assert (fs.prev == nil)
1257 assert (fs.f.nups == 0)
1258 assert (fs.nestlevel == 0)
1259 if source then fs.f.source = source end