]> git.lizzy.rs Git - metalua.git/blob - src/compiler/compile.lua
Merge remote branch 'origin/master'
[metalua.git] / src / compiler / compile.lua
1 ----------------------------------------------------------------------
2 --
3 -- WARNING! You're entering a hackish area, proceed at your own risks!
4 --
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
8 -- in it.
9 --
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
13 -- on.
14 --
15 -- End of warning.
16 --
17 ----------------------------------------------------------------------
18
19 ----------------------------------------------------------------------
20 -- Metalua.
21 --
22 -- Summary: Compile ASTs to Lua 5.1 VM function prototype. 
23 -- Largely based on:
24 --
25 -- * Yueliang (http://luaforge.net/projects/yueliang),
26 --   yueliang-0.1.2/orig-5.0.2/lparser.lua
27 --
28 -- * Lua 5.1 sources (http://www.lua.org), src/lparser.c
29 --
30 ----------------------------------------------------------------------
31 --
32 -- Copyright (c) 2006-2008, Fabien Fleutot <metalua@gmail.com>.
33 --
34 -- This software is released under the MIT Licence, see licence.txt
35 -- for details.
36 --
37 ----------------------------------------------------------------------
38
39 module ("bytecode", package.seeall)
40
41 local debugf = function() end
42 --local debugf=printf
43
44 local stat = { }
45 local expr = { }
46
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)
52
53 -- from lobject.h
54 VARARG_HASARG   = 1
55 VARARG_ISVARARG = 2
56 VARARG_NEEDSARG = 4
57
58 local function hasmultret (k) 
59    return k=="VCALL" or k=="VVARARG"
60 end
61
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.
67 --
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
73
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.
78 --
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]] 
84 end
85
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
95   end
96 end
97
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
104 -- current PC.
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)
110    local f = fs.f
111    f.locvars[fs.nlocvars] = { } -- LocVar
112    f.locvars[fs.nlocvars].varname = varname
113    local nlocvars = fs.nlocvars
114    fs.nlocvars = fs.nlocvars + 1
115    return nlocvars
116 end
117
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
122 -- new_localvar.
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)
128
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
133    end
134 end
135
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
140 -- assignment.
141 ------------------------------------------------------------------------
142 local function check_conflict (fs, lh, v)
143   local extra = fs.freereg  -- eventual position to save local variable
144   local conflict = false
145   while lh do
146     if lh.v.k == "VINDEXED" then
147       if lh.v.info == v.info then  -- conflict?
148         conflict = true
149         lh.v.info = extra  -- previous assignment will use safe copy
150       end
151       if lh.v.aux == v.info then  -- conflict?
152         conflict = true
153         lh.v.aux = extra  -- previous assignment will use safe copy
154       end
155     end
156     lh = lh.prev
157   end
158   if conflict then
159     luaK:codeABC (fs, "OP_MOVE", fs.freereg, v.info, 0)  -- make copy
160     luaK:reserveregs (fs, 1)
161   end
162 end
163
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
169
170 -----------------------------------------------------------------------
171 -- Reserve the string in tthe constant pool, and return an expdesc
172 -- referring to it.
173 -----------------------------------------------------------------------
174 local function codestring (fs, e, str)
175   --printf( "codestring(%s)", disp.ast(str))
176   init_exp (e, "VK", luaK:stringK (fs, str))
177 end
178
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)
191          return i 
192       end
193    end
194    return -1  -- not found
195 end
196
197 -----------------------------------------------------------------------
198 -- create and return a new proto [f]
199 -----------------------------------------------------------------------
200 local function newproto () 
201   local f = {}
202   f.k = {}
203   f.sizek = 0
204   f.p = {}
205   f.sizep = 0
206   f.code = {}
207   f.sizecode = 0
208   f.sizelineinfo = 0
209   f.sizeupvalues = 0
210   f.nups = 0
211   f.upvalues = {}
212   f.numparams = 0
213   f.is_vararg = 0
214   f.maxstacksize = 0
215   f.lineinfo = {}
216   f.sizelocvars = 0
217   f.locvars = {}
218   f.lineDefined = 0
219   f.source = nil
220   return f
221 end
222
223 ------------------------------------------------------------------------
224 -- create and return a function state [new_fs] as a sub-funcstate of [fs].
225 ------------------------------------------------------------------------
226 local function open_func (old_fs)
227   local new_fs = { }
228   new_fs.upvalues = { }
229   new_fs.actvar = { }
230   local f = newproto ()
231   new_fs.f = f
232   new_fs.prev = old_fs  -- linked list of funcstates
233   new_fs.pc = 0
234   new_fs.lasttarget = -1
235   new_fs.jpc = luaK.NO_JUMP
236   new_fs.freereg = 0
237   new_fs.nk = 0
238   new_fs.h = {}  -- constant table; was luaH_new call
239   new_fs.np = 0
240   new_fs.nlocvars = 0
241   new_fs.nactvar = 0
242   new_fs.bl = nil
243   new_fs.nestlevel =  old_fs and old_fs.nestlevel or 0
244   f.maxstacksize = 2  -- registers 0/1 are always valid
245   new_fs.lastline = 0
246   new_fs.forward_gotos = { }
247   new_fs.labels = { }
248   return new_fs
249 end
250
251 ------------------------------------------------------------------------
252 -- Finish to set up [f] according to final state of [fs]
253 ------------------------------------------------------------------------
254 local function close_func (fs)
255   local f = fs.f
256   --printf("[CLOSE_FUNC] remove any remaining var")
257   removevars (fs, 0)
258   luaK:ret (fs, 0, 0)
259   f.sizecode = fs.pc
260   f.sizelineinfo = fs.pc
261   f.sizek = fs.nk
262   f.sizep = fs.np
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)
269   end
270 end
271
272 ------------------------------------------------------------------------
273 -- 
274 ------------------------------------------------------------------------
275 local function pushclosure(fs, func, v)
276    local f = fs.f
277    f.p [fs.np] = func.f
278    fs.np = fs.np + 1
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)
283   end
284 end
285
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)
290    local f = fs.f
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)
294          return i
295       end
296    end
297   -- new one
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 }
301   local nups = f.nups
302   f.nups = f.nups + 1
303   return nups
304 end
305
306 ------------------------------------------------------------------------
307 --
308 ------------------------------------------------------------------------
309 local function markupval(fs, level)
310   local bl = fs.bl
311   while bl and bl.nactvar > level do bl = bl.previous end
312   if bl then bl.upval = true end
313 end
314
315
316 --for debug only
317 --[[
318 local function bldepth(fs)
319    local i, x= 1, fs.bl
320    while x do i=i+1; x=x.previous end
321    return i
322 end
323 --]]
324
325 ------------------------------------------------------------------------
326 --
327 ------------------------------------------------------------------------
328 local function enterblock (fs, bl, isbreakable)
329   bl.breaklist = luaK.NO_JUMP
330   bl.isbreakable = isbreakable
331   bl.nactvar = fs.nactvar
332   bl.upval = false
333   bl.previous = fs.bl
334   fs.bl = bl
335   assert (fs.freereg == fs.nactvar)
336 end
337
338 ------------------------------------------------------------------------
339 --
340 ------------------------------------------------------------------------
341 local function leaveblock (fs)
342    local bl = fs.bl
343    fs.bl = bl.previous
344    --printf("[LEAVEBLOCK] Removing vars...")
345    removevars (fs, bl.nactvar)
346    --printf("[LEAVEBLOCK] ...Vars removed")
347    if bl.upval then
348       luaK:codeABC (fs, "OP_CLOSE", bl.nactvar, 0, 0)
349    end
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)
355 end
356
357
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)
363   offset = offset or 1
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))
373   end
374   return #astlist - offset + 1
375 end
376
377 ------------------------------------------------------------------------
378 -- 
379 ------------------------------------------------------------------------
380 local function funcargs (fs, ast, v, idx_from)
381   local args = { }  -- expdesc
382   local nparams
383   if #ast < idx_from then args.k = "VVOID" else
384      explist(fs, ast, args, idx_from)
385      luaK:setmultret(fs, args)
386   end
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)
393   end
394   init_exp(v, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
395   if ast.lineinfo then
396      luaK:fixline(fs, ast.lineinfo.first[1])
397   else 
398     luaK:fixline(fs, ast.line)
399   end
400   fs.freereg = base + 1  -- call remove function and arguments and leaves
401                          -- (unless changed) one result
402 end
403
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)
410   return ex - 1
411 end
412
413 ------------------------------------------------------------------------
414 -- converts an integer to a "floating point byte", represented as
415 -- (mmmmmxxx), where the real value is (xxx) * 2^(mmmmm)
416 ------------------------------------------------------------------------
417
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
421 --   return m * 8 + x
422 -- end
423
424 local function int2fb(x)
425    local e = 0
426    while x >= 16 do
427       x = math.floor ( (x+1) / 2)
428       e = e+1
429    end
430    if x<8 then return x
431    else return (e+1) * 8 + x - 8 end
432 end
433
434
435 ------------------------------------------------------------------------
436 -- FIXME: to be unified with singlevar
437 ------------------------------------------------------------------------
438 local function singlevaraux(fs, n, var, base)
439 --[[
440 print("\n\nsinglevaraux: fs, n, var, base")
441 printv(fs)
442 printv(n)
443 printv(var)
444 printv(base)
445 print("\n")
446 --]]
447    if fs == nil then  -- no more levels?
448       init_exp(var, "VGLOBAL", luaP.NO_REG)  -- default is global variable
449       return "VGLOBAL"
450    else
451       local v = searchvar(fs, n)  -- look up at current level
452       if v >= 0 then
453          init_exp(var, "VLOCAL", v)
454          if not base then
455             markupval(fs, v)  -- local will be used as an upval
456          end
457       else  -- not found at current level; try upper one
458          if singlevaraux(fs.prev, n, var, false) == "VGLOBAL" then
459             return "VGLOBAL" end
460          var.info = indexupvalue (fs, n, var)
461          var.k = "VUPVAL"
462          return "VUPVAL"
463       end
464    end
465 end
466
467 ------------------------------------------------------------------------
468 -- 
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
473 end
474
475 ------------------------------------------------------------------------
476 -- 
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)
483 end
484
485 ------------------------------------------------------------------------
486 -- 
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)
494    end
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
502 end
503
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
516   else
517     if e.k ~= "VVOID" then 
518        luaK:exp2nextreg(fs, e) end  -- close last expression
519     if extra > 0 then
520       local reg = fs.freereg
521       luaK:reserveregs(fs, extra)
522       luaK:_nil(fs, reg, extra)
523     end
524   end
525 end
526
527
528 ------------------------------------------------------------------------
529 -- 
530 ------------------------------------------------------------------------
531 local function enterlevel (fs)
532    fs.nestlevel = fs.nestlevel + 1
533    assert (fs.nestlevel <= LUA_MAXPARSERLEVEL, "too many syntax levels")
534 end
535
536 ------------------------------------------------------------------------
537 -- 
538 ------------------------------------------------------------------------
539 local function leavelevel (fs)
540   fs.nestlevel = fs.nestlevel - 1
541 end
542
543 ------------------------------------------------------------------------
544 -- Parse conditions in if/then/else, while, repeat
545 ------------------------------------------------------------------------
546 local function cond (fs, ast)
547    local v = { }
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)
551    return v.f
552 end
553
554 ------------------------------------------------------------------------
555 -- 
556 ------------------------------------------------------------------------
557 local function chunk (fs, ast)
558    enterlevel (fs)
559    assert (not ast.tag)
560    for i=1, #ast do 
561       stat.stat (fs, ast[i]); 
562       fs.freereg = fs.nactvar
563    end
564    leavelevel (fs)
565 end
566
567 ------------------------------------------------------------------------
568 -- 
569 ------------------------------------------------------------------------
570 local function block (fs, ast)
571   local bl = {}
572   enterblock (fs, bl, false)
573   for i=1, #ast do
574      stat.stat (fs, ast[i])
575      fs.freereg = fs.nactvar
576   end
577   assert (bl.breaklist == luaK.NO_JUMP)
578   leaveblock (fs)
579 end  
580
581 ------------------------------------------------------------------------
582 -- Forin / Fornum body parser
583 -- [fs]
584 -- [body]
585 -- [base]
586 -- [nvars]
587 -- [isnum]
588 ------------------------------------------------------------------------
589 local function forbody (fs, ast_body, base, nvars, isnum)
590    local bl = {}  -- BlockCnt
591    adjustlocalvars (fs, 3)  -- control variables
592    local prep = 
593       isnum and luaK:codeAsBx (fs, "OP_FORPREP", base, luaK.NO_JUMP)
594       or luaK:jump (fs) 
595    enterblock (fs, bl, false)  -- loop block
596    adjustlocalvars (fs, nvars)  -- scope for declared variables
597    luaK:reserveregs (fs, nvars)
598    block (fs, ast_body)
599    leaveblock (fs)
600    --luaK:patchtohere (fs, prep-1)
601    luaK:patchtohere (fs, prep)
602    local endfor = 
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)
607 end
608
609
610 ------------------------------------------------------------------------
611 --
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
618   cc.nh = cc.nh + 1
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
626 end
627
628
629 ------------------------------------------------------------------------
630 --
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 <
635   cc.na = cc.na + 1
636   cc.tostore = cc.tostore + 1
637 end
638
639 ------------------------------------------------------------------------
640 --
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)
645    cc.v.k = "VVOID"
646    if cc.tostore == luaP.LFIELDS_PER_FLUSH then
647       luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
648       cc.tostore = 0
649    end
650 end
651
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)
661     cc.na = cc.na - 1
662   else
663     if cc.v.k ~= "VVOID" then luaK:exp2nextreg(fs, cc.v) end
664     luaK:setlist (fs, cc.t.info, cc.na, cc.tostore)
665   end
666 end
667 ------------------------------------------------------------------------
668 ------------------------------------------------------------------------
669 -- 
670 -- Statement parsers table
671 -- 
672 ------------------------------------------------------------------------
673 ------------------------------------------------------------------------
674
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) )
678
679    if not ast.tag then chunk (fs, ast) else
680
681       local parser = stat [ast.tag]
682       if not parser then 
683          error ("A statement cannot have tag `"..ast.tag) end
684       parser (fs, ast)
685    end
686    --debugf (" - /Statement `%s", ast.tag or "<nil>")
687    debugf (" - /Statement `%s", ast.tag)
688 end
689
690 ------------------------------------------------------------------------
691
692 stat.Do = block
693
694 ------------------------------------------------------------------------
695
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
701       bl = bl.previous
702    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))
706 end
707
708 ------------------------------------------------------------------------
709
710 function stat.Return (fs, ast)
711    local e = {}  -- expdesc
712    local first -- registers with returned values
713    local nret = #ast
714
715    if nret == 0 then first = 0
716    else
717       --printf("[RETURN] compiling explist")
718       explist (fs, ast, e)
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)
725          end
726          first = 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)
732       else
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)
737       end
738    end
739    luaK:ret(fs, first, nret)
740 end
741 ------------------------------------------------------------------------
742
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
746   local e = { }
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)
750 end
751
752 ------------------------------------------------------------------------
753
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
764 end
765
766 ------------------------------------------------------------------------
767
768 function stat.If (fs, ast)
769   local astlen = #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   
774
775   local function test_then_block (fs, test, body)
776     local condexit = cond (fs, test); 
777     block (fs, body) 
778     return condexit
779   end
780
781   local escapelist = luaK.NO_JUMP
782
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])
788   end
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])
793   else
794     escapelist = luaK:concat(fs, escapelist, flist)
795   end
796   luaK:patchtohere(fs, escapelist)
797 end
798
799 ------------------------------------------------------------------------
800
801 function stat.Forin (fs, ast)
802    local vars, vals, body = ast[1], ast[2], ast[3]
803    -- imitating forstat:
804    local bl = { }
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)
816    -- back to forstat:
817    leaveblock (fs)
818 end
819
820 ------------------------------------------------------------------------
821
822 function stat.Fornum (fs, ast)
823
824    local function exp1 (ast_e)
825       local e = { }
826       expr.expr (fs, ast_e, e)
827       luaK:exp2nextreg (fs, e)
828    end
829    -- imitating forstat:
830    local bl = { }
831    enterblock (fs, bl, true)
832    -- imitating fornum:
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)
843    end
844    forbody (fs, ast[#ast], base, 1, true)
845    -- back to forstat:
846    leaveblock (fs)
847 end
848
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)
855   chunk (fs, ast[1])
856   local condexit = cond (fs, ast[2])
857   if not bl2.upval then
858     leaveblock (fs)
859     luaK:patchlist (fs, condexit, repeat_init)
860   else
861     stat.Break (fs)
862     luaK:patchtohere (fs, condexit)
863     leaveblock (fs)
864     luaK:patchlist (fs, luaK:jump (fs), repeat_init)
865   end
866   leaveblock (fs)
867 end
868
869 ------------------------------------------------------------------------
870
871 function stat.While (fs, ast)
872    local whileinit = luaK:getlabel (fs)
873    local condexit = cond (fs, ast[1])
874    local bl = { }
875    enterblock (fs, bl, true)
876    block (fs, ast[2])
877    luaK:patchlist (fs, luaK:jump (fs), whileinit)
878    leaveblock (fs)
879    luaK:patchtohere (fs, condexit);
880 end
881
882 ------------------------------------------------------------------------
883
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], { }
887
888    --print "\n\nSet ast_lhs ast_vals:"
889    --print(disp.ast(ast_lhs))
890    --print(disp.ast(ast_vals))
891
892    local function let_aux (lhs, nvars)
893       local legal = { VLOCAL=1, VUPVAL=1, VGLOBAL=1, VINDEXED=1 }
894       --printv(lhs)
895       if not legal [lhs.v.k] then 
896          error ("Bad lhs expr: "..table.tostring(ast_lhs)) 
897       end
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
914          end
915       end
916       init_exp (e, "VNONRELOC", fs.freereg - 1)  -- default assignment
917       luaK:storevar (fs, lhs.v, e)
918    end
919
920    local lhs = { v = { }, prev = nil }
921    expr.expr (fs, ast_lhs[1], lhs.v)
922    let_aux( lhs, 1)
923 end  
924
925 ------------------------------------------------------------------------
926
927 function stat.Call (fs, ast)
928    local v = {  }
929    expr.Call (fs, ast, v)
930    luaP:SETARG_C (luaK:getcode(fs, v), 1)
931 end
932
933 ------------------------------------------------------------------------
934
935 function stat.Invoke (fs, ast)
936    local v = {  }
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)
940 end
941
942
943 local function patch_goto (fs, src, dst)
944
945 end
946
947
948 ------------------------------------------------------------------------
949 -- Goto/Label data:
950 -- fs.labels        :: string => { nactvar :: int; pc :: int }
951 -- fs.forward_gotos :: string => list(int)
952 --
953 -- fs.labels goes from label ids to the number of active variables at
954 -- the label's PC, and that PC
955 --
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
960 --
961 -- Note that backward gotos aren't stored: since their destination is knowns
962 -- when they're compiled, their target is directly set.
963 ------------------------------------------------------------------------
964
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]
978    if gotos then 
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)
989       end
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
996    end 
997 end
998
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]
1011    if label then
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)
1021    else
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)
1033    end
1034 end
1035
1036 ------------------------------------------------------------------------
1037 ------------------------------------------------------------------------
1038 -- 
1039 -- Expression parsers table
1040 -- 
1041 ------------------------------------------------------------------------
1042 ------------------------------------------------------------------------
1043
1044 function expr.expr (fs, ast, v)
1045    if type(ast) ~= "table" then 
1046       error ("Expr AST expected, got "..table.tostring(ast)) end
1047
1048    if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1049
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))
1055    else 
1056       error ("No parser for node `"..ast.tag) end
1057    debugf (" - /`%s", ast.tag)
1058 end
1059
1060 ------------------------------------------------------------------------
1061
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)
1068    v.nval = ast[1] 
1069 end
1070
1071 function expr.Paren (fs, ast, v) 
1072    expr.expr (fs, ast[1], v)
1073    luaK:setoneret (fs, v)
1074 end
1075
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))
1083 end
1084
1085 ------------------------------------------------------------------------
1086
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)
1093   for i = 1, #ast do
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)
1097   end    
1098   lastlistfield(fs, cc)
1099
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])
1104 end  
1105
1106
1107 ------------------------------------------------------------------------
1108
1109 function expr.Function (fs, ast, v)
1110    if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1111
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]
1116   end
1117   parlist (new_fs, ast[1])
1118   chunk (new_fs, ast[2])
1119   close_func (new_fs)
1120   pushclosure(fs, new_fs, v)
1121 end  
1122
1123 ------------------------------------------------------------------------
1124
1125 function expr.Op (fs, ast, v)
1126    if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1127    local op = ast[1]
1128
1129    if #ast == 2 then
1130       expr.expr (fs, ast[2], v)
1131       luaK:prefix (fs, op, v)
1132    elseif #ast == 3 then
1133       local v2 = { }
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)
1138    else
1139       error "Wrong arg number"
1140    end
1141 end  
1142
1143 ------------------------------------------------------------------------
1144
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])
1150 end  
1151
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)
1157    local key = { }
1158    codestring (fs, key, ast[2][1])
1159    luaK:_self (fs, v, key)
1160    funcargs (fs, ast, v, 3)
1161 end  
1162
1163 ------------------------------------------------------------------------
1164
1165 function expr.Index (fs, ast, v)
1166    if #ast ~= 2 then
1167       print"\n\nBAD INDEX AST:"
1168       table.print(ast)
1169       error "generalized indexes not implemented" end
1170
1171    if ast.lineinfo then fs.lastline = ast.lineinfo.last[1] end
1172
1173    --assert(fs.lastline ~= 0, ast.tag)
1174
1175    expr.expr (fs, ast[1], v)
1176    luaK:exp2anyreg (fs, v)
1177
1178    local k = { }
1179    expr.expr (fs, ast[2], k)
1180    luaK:exp2val (fs, k)
1181    luaK:indexed (fs, v, k)
1182 end  
1183
1184 ------------------------------------------------------------------------
1185
1186 function expr.Id (fs, ast, v)
1187    assert (ast.tag == "Id")
1188    singlevar (fs, ast[1], v)
1189 end
1190
1191 ------------------------------------------------------------------------
1192
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))
1196
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
1201
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
1206
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.
1215    --
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
1220       while true do
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)
1224          save_actvar[i] = v
1225          i=i+1
1226       end
1227    end
1228
1229    fs.nactvar = fs.freereg -- Now temp unnamed registers are protected
1230    enterblock (fs, { }, false)
1231    chunk (fs, ast[1])
1232    expr.expr (fs, ast[2], v)
1233    luaK:exp2nextreg (fs, v)
1234    leaveblock (fs)
1235    luaK:exp2reg (fs, v, dest_reg)
1236
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
1242
1243    -- Restore nactvar, so that intermediate stacked value stop
1244    -- being protected.
1245    --printf("   nactvar back from %i to %i", fs.nactvar, save_nactvar)
1246    fs.nactvar = save_nactvar
1247
1248    -- restore messed-up unregistered local vars
1249    for i, j in pairs(save_actvar) do
1250       --printf("   Restoring actvar %i", i)
1251       fs.actvar[i] = j
1252    end
1253    --printf(" * End of Stat")
1254 end
1255
1256
1257
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
1264   chunk (fs, ast)
1265   close_func (fs)
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
1270   return fs.f
1271 end