diff options
Diffstat (limited to '')
-rw-r--r-- | LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lparser.lua | 1747 |
1 files changed, 1747 insertions, 0 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lparser.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lparser.lua new file mode 100644 index 0000000..2535056 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.1.3/lparser.lua | |||
@@ -0,0 +1,1747 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | lparser.lua | ||
4 | Lua 5 parser in Lua | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net> | ||
8 | The COPYRIGHT file describes the conditions | ||
9 | under which this software may be distributed. | ||
10 | |||
11 | See the ChangeLog for more information. | ||
12 | |||
13 | ----------------------------------------------------------------------]] | ||
14 | |||
15 | --[[-------------------------------------------------------------------- | ||
16 | -- Notes: | ||
17 | -- * some unused C code that were not converted are kept as comments | ||
18 | -- * LUA_COMPAT_VARARG option changed into a comment block | ||
19 | -- * for value/size specific code added, look for 'NOTE: ' | ||
20 | -- | ||
21 | -- Not implemented: | ||
22 | -- * luaX_newstring not needed by this Lua implementation | ||
23 | -- * luaG_checkcode() in lua_assert is not currently implemented | ||
24 | -- | ||
25 | -- Added: | ||
26 | -- * some constants added from various header files | ||
27 | -- * luaY.LUA_QS used in error_expected, check_match (from luaconf.h) | ||
28 | -- * luaY:LUA_QL needed for error messages (from luaconf.h) | ||
29 | -- * luaY:growvector (from lmem.h) -- skeleton only, limit checking | ||
30 | -- * luaY.SHRT_MAX (from <limits.h>) for registerlocalvar | ||
31 | -- * luaY:newproto (from lfunc.c) | ||
32 | -- * luaY:int2fb (from lobject.c) | ||
33 | -- * NOTE: HASARG_MASK, for implementing a VARARG_HASARG bit operation | ||
34 | -- * NOTE: value-specific code for VARARG_NEEDSARG to replace a bitop | ||
35 | -- | ||
36 | -- Changed in 5.1.x: | ||
37 | -- * various code changes are not detailed... | ||
38 | -- * names of constants may have changed, e.g. added a LUAI_ prefix | ||
39 | -- * struct expkind: added VKNUM, VVARARG; VCALL's info changed? | ||
40 | -- * struct expdesc: added nval | ||
41 | -- * struct FuncState: upvalues data type changed to upvaldesc | ||
42 | -- * macro hasmultret is new | ||
43 | -- * function checklimit moved to parser from lexer | ||
44 | -- * functions anchor_token, errorlimit, checknext are new | ||
45 | -- * checknext is new, equivalent to 5.0.x's check, see check too | ||
46 | -- * luaY:next and luaY:lookahead moved to lexer | ||
47 | -- * break keyword no longer skipped in luaY:breakstat | ||
48 | -- * function new_localvarstr replaced by new_localvarliteral | ||
49 | -- * registerlocalvar limits local variables to SHRT_MAX | ||
50 | -- * create_local deleted, new_localvarliteral used instead | ||
51 | -- * constant LUAI_MAXUPVALUES increased to 60 | ||
52 | -- * constants MAXPARAMS, LUA_MAXPARSERLEVEL, MAXSTACK removed | ||
53 | -- * function interface changed: singlevaraux, singlevar | ||
54 | -- * enterlevel and leavelevel uses nCcalls to track call depth | ||
55 | -- * added a name argument to main entry function, luaY:parser | ||
56 | -- * function luaY_index changed to yindex | ||
57 | -- * luaY:int2fb()'s table size encoding format has been changed | ||
58 | -- * luaY:log2() no longer needed for table constructors | ||
59 | -- * function code_params deleted, functionality folded in parlist | ||
60 | -- * vararg flags handling (is_vararg) changes; also see VARARG_* | ||
61 | -- * LUA_COMPATUPSYNTAX section for old-style upvalues removed | ||
62 | -- * repeatstat() calls chunk() instead of block() | ||
63 | -- * function interface changed: cond, test_then_block | ||
64 | -- * while statement implementation considerably simplified; MAXEXPWHILE | ||
65 | -- and EXTRAEXP no longer required, no limits to the complexity of a | ||
66 | -- while condition | ||
67 | -- * repeat, forbody statement implementation has major changes, | ||
68 | -- mostly due to new scoping behaviour of local variables | ||
69 | -- * OPR_MULT renamed to OPR_MUL | ||
70 | ----------------------------------------------------------------------]] | ||
71 | |||
72 | --requires luaP, luaX, luaK | ||
73 | luaY = {} | ||
74 | |||
75 | --[[-------------------------------------------------------------------- | ||
76 | -- Expression descriptor | ||
77 | -- * expkind changed to string constants; luaY:assignment was the only | ||
78 | -- function to use a relational operator with this enumeration | ||
79 | -- VVOID -- no value | ||
80 | -- VNIL -- no value | ||
81 | -- VTRUE -- no value | ||
82 | -- VFALSE -- no value | ||
83 | -- VK -- info = index of constant in 'k' | ||
84 | -- VKNUM -- nval = numerical value | ||
85 | -- VLOCAL -- info = local register | ||
86 | -- VUPVAL, -- info = index of upvalue in 'upvalues' | ||
87 | -- VGLOBAL -- info = index of table; aux = index of global name in 'k' | ||
88 | -- VINDEXED -- info = table register; aux = index register (or 'k') | ||
89 | -- VJMP -- info = instruction pc | ||
90 | -- VRELOCABLE -- info = instruction pc | ||
91 | -- VNONRELOC -- info = result register | ||
92 | -- VCALL -- info = instruction pc | ||
93 | -- VVARARG -- info = instruction pc | ||
94 | } ----------------------------------------------------------------------]] | ||
95 | |||
96 | --[[-------------------------------------------------------------------- | ||
97 | -- * expdesc in Lua 5.1.x has a union u and another struct s; this Lua | ||
98 | -- implementation ignores all instances of u and s usage | ||
99 | -- struct expdesc: | ||
100 | -- k -- (enum: expkind) | ||
101 | -- info, aux -- (int, int) | ||
102 | -- nval -- (lua_Number) | ||
103 | -- t -- patch list of 'exit when true' | ||
104 | -- f -- patch list of 'exit when false' | ||
105 | ----------------------------------------------------------------------]] | ||
106 | |||
107 | --[[-------------------------------------------------------------------- | ||
108 | -- struct upvaldesc: | ||
109 | -- k -- (lu_byte) | ||
110 | -- info -- (lu_byte) | ||
111 | ----------------------------------------------------------------------]] | ||
112 | |||
113 | --[[-------------------------------------------------------------------- | ||
114 | -- state needed to generate code for a given function | ||
115 | -- struct FuncState: | ||
116 | -- f -- current function header (table: Proto) | ||
117 | -- h -- table to find (and reuse) elements in 'k' (table: Table) | ||
118 | -- prev -- enclosing function (table: FuncState) | ||
119 | -- ls -- lexical state (table: LexState) | ||
120 | -- L -- copy of the Lua state (table: lua_State) | ||
121 | -- bl -- chain of current blocks (table: BlockCnt) | ||
122 | -- pc -- next position to code (equivalent to 'ncode') | ||
123 | -- lasttarget -- 'pc' of last 'jump target' | ||
124 | -- jpc -- list of pending jumps to 'pc' | ||
125 | -- freereg -- first free register | ||
126 | -- nk -- number of elements in 'k' | ||
127 | -- np -- number of elements in 'p' | ||
128 | -- nlocvars -- number of elements in 'locvars' | ||
129 | -- nactvar -- number of active local variables | ||
130 | -- upvalues[LUAI_MAXUPVALUES] -- upvalues (table: upvaldesc) | ||
131 | -- actvar[LUAI_MAXVARS] -- declared-variable stack | ||
132 | ----------------------------------------------------------------------]] | ||
133 | |||
134 | ------------------------------------------------------------------------ | ||
135 | -- constants used by parser | ||
136 | -- * picks up duplicate values from luaX if required | ||
137 | ------------------------------------------------------------------------ | ||
138 | luaY.LUA_QS = luaX.LUA_QS or "'%s'" -- (from luaconf.h) | ||
139 | |||
140 | luaY.SHRT_MAX = 32767 -- (from <limits.h>) | ||
141 | luaY.LUAI_MAXVARS = 200 -- (luaconf.h) | ||
142 | luaY.LUAI_MAXUPVALUES = 60 -- (luaconf.h) | ||
143 | luaY.MAX_INT = luaX.MAX_INT or 2147483645 -- (from llimits.h) | ||
144 | -- * INT_MAX-2 for 32-bit systems | ||
145 | luaY.LUAI_MAXCCALLS = 200 -- (from luaconf.h) | ||
146 | |||
147 | luaY.VARARG_HASARG = 1 -- (from lobject.h) | ||
148 | -- NOTE: HASARG_MASK is value-specific | ||
149 | luaY.HASARG_MASK = 2 -- this was added for a bitop in parlist() | ||
150 | luaY.VARARG_ISVARARG = 2 | ||
151 | -- NOTE: there is some value-specific code that involves VARARG_NEEDSARG | ||
152 | luaY.VARARG_NEEDSARG = 4 | ||
153 | |||
154 | luaY.LUA_MULTRET = -1 -- (lua.h) | ||
155 | |||
156 | --[[-------------------------------------------------------------------- | ||
157 | -- other functions | ||
158 | ----------------------------------------------------------------------]] | ||
159 | |||
160 | ------------------------------------------------------------------------ | ||
161 | -- LUA_QL describes how error messages quote program elements. | ||
162 | -- CHANGE it if you want a different appearance. (from luaconf.h) | ||
163 | ------------------------------------------------------------------------ | ||
164 | function luaY:LUA_QL(x) | ||
165 | return "'"..x.."'" | ||
166 | end | ||
167 | |||
168 | ------------------------------------------------------------------------ | ||
169 | -- this is a stripped-down luaM_growvector (from lmem.h) which is a | ||
170 | -- macro based on luaM_growaux (in lmem.c); all the following does is | ||
171 | -- reproduce the size limit checking logic of the original function | ||
172 | -- so that error behaviour is identical; all arguments preserved for | ||
173 | -- convenience, even those which are unused | ||
174 | -- * set the t field to nil, since this originally does a sizeof(t) | ||
175 | -- * size (originally a pointer) is never updated, their final values | ||
176 | -- are set by luaY:close_func(), so overall things should still work | ||
177 | ------------------------------------------------------------------------ | ||
178 | function luaY:growvector(L, v, nelems, size, t, limit, e) | ||
179 | if nelems >= limit then | ||
180 | error(e) -- was luaG_runerror | ||
181 | end | ||
182 | end | ||
183 | |||
184 | ------------------------------------------------------------------------ | ||
185 | -- initialize a new function prototype structure (from lfunc.c) | ||
186 | -- * used only in open_func() | ||
187 | ------------------------------------------------------------------------ | ||
188 | function luaY:newproto(L) | ||
189 | local f = {} -- Proto | ||
190 | -- luaC_link(L, obj2gco(f), LUA_TPROTO); /* GC */ | ||
191 | f.k = {} | ||
192 | f.sizek = 0 | ||
193 | f.p = {} | ||
194 | f.sizep = 0 | ||
195 | f.code = {} | ||
196 | f.sizecode = 0 | ||
197 | f.sizelineinfo = 0 | ||
198 | f.sizeupvalues = 0 | ||
199 | f.nups = 0 | ||
200 | f.upvalues = {} | ||
201 | f.numparams = 0 | ||
202 | f.is_vararg = 0 | ||
203 | f.maxstacksize = 0 | ||
204 | f.lineinfo = {} | ||
205 | f.sizelocvars = 0 | ||
206 | f.locvars = {} | ||
207 | f.lineDefined = 0 | ||
208 | f.lastlinedefined = 0 | ||
209 | f.source = nil | ||
210 | return f | ||
211 | end | ||
212 | |||
213 | ------------------------------------------------------------------------ | ||
214 | -- converts an integer to a "floating point byte", represented as | ||
215 | -- (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if | ||
216 | -- eeeee != 0 and (xxx) otherwise. | ||
217 | ------------------------------------------------------------------------ | ||
218 | function luaY:int2fb(x) | ||
219 | local e = 0 -- exponent | ||
220 | while x >= 16 do | ||
221 | x = math.floor((x + 1) / 2) | ||
222 | e = e + 1 | ||
223 | end | ||
224 | if x < 8 then | ||
225 | return x | ||
226 | else | ||
227 | return ((e + 1) * 8) + (x - 8) | ||
228 | end | ||
229 | end | ||
230 | |||
231 | --[[-------------------------------------------------------------------- | ||
232 | -- parser functions | ||
233 | ----------------------------------------------------------------------]] | ||
234 | |||
235 | ------------------------------------------------------------------------ | ||
236 | -- true of the kind of expression produces multiple return values | ||
237 | ------------------------------------------------------------------------ | ||
238 | function luaY:hasmultret(k) | ||
239 | return k == "VCALL" or k == "VVARARG" | ||
240 | end | ||
241 | |||
242 | ------------------------------------------------------------------------ | ||
243 | -- convenience function to access active local i, returns entry | ||
244 | ------------------------------------------------------------------------ | ||
245 | function luaY:getlocvar(fs, i) | ||
246 | return fs.f.locvars[ fs.actvar[i] ] | ||
247 | end | ||
248 | |||
249 | ------------------------------------------------------------------------ | ||
250 | -- check a limit, string m provided as an error message | ||
251 | ------------------------------------------------------------------------ | ||
252 | function luaY:checklimit(fs, v, l, m) | ||
253 | if v > l then self:errorlimit(fs, l, m) end | ||
254 | end | ||
255 | |||
256 | --[[-------------------------------------------------------------------- | ||
257 | -- nodes for block list (list of active blocks) | ||
258 | -- struct BlockCnt: | ||
259 | -- previous -- chain (table: BlockCnt) | ||
260 | -- breaklist -- list of jumps out of this loop | ||
261 | -- nactvar -- # active local variables outside the breakable structure | ||
262 | -- upval -- true if some variable in the block is an upvalue (boolean) | ||
263 | -- isbreakable -- true if 'block' is a loop (boolean) | ||
264 | ----------------------------------------------------------------------]] | ||
265 | |||
266 | ------------------------------------------------------------------------ | ||
267 | -- prototypes for recursive non-terminal functions | ||
268 | ------------------------------------------------------------------------ | ||
269 | -- prototypes deleted; not required in Lua | ||
270 | |||
271 | ------------------------------------------------------------------------ | ||
272 | -- reanchor if last token is has a constant string, see close_func() | ||
273 | -- * used only in close_func() | ||
274 | ------------------------------------------------------------------------ | ||
275 | function luaY:anchor_token(ls) | ||
276 | if ls.t.token == "TK_NAME" or ls.t.token == "TK_STRING" then | ||
277 | -- not relevant to Lua implementation of parser | ||
278 | -- local ts = ls.t.seminfo | ||
279 | -- luaX_newstring(ls, getstr(ts), ts->tsv.len); /* C */ | ||
280 | end | ||
281 | end | ||
282 | |||
283 | ------------------------------------------------------------------------ | ||
284 | -- throws a syntax error if token expected is not there | ||
285 | ------------------------------------------------------------------------ | ||
286 | function luaY:error_expected(ls, token) | ||
287 | luaX:syntaxerror(ls, | ||
288 | string.format(self.LUA_QS.." expected", luaX:token2str(ls, token))) | ||
289 | end | ||
290 | |||
291 | ------------------------------------------------------------------------ | ||
292 | -- prepares error message for display, for limits exceeded | ||
293 | -- * used only in checklimit() | ||
294 | ------------------------------------------------------------------------ | ||
295 | function luaY:errorlimit(fs, limit, what) | ||
296 | local msg = (fs.f.linedefined == 0) and | ||
297 | string.format("main function has more than %d %s", limit, what) or | ||
298 | string.format("function at line %d has more than %d %s", | ||
299 | fs.f.linedefined, limit, what) | ||
300 | luaX:lexerror(fs.ls, msg, 0) | ||
301 | end | ||
302 | |||
303 | ------------------------------------------------------------------------ | ||
304 | -- tests for a token, returns outcome | ||
305 | -- * return value changed to boolean | ||
306 | ------------------------------------------------------------------------ | ||
307 | function luaY:testnext(ls, c) | ||
308 | if ls.t.token == c then | ||
309 | luaX:next(ls) | ||
310 | return true | ||
311 | else | ||
312 | return false | ||
313 | end | ||
314 | end | ||
315 | |||
316 | ------------------------------------------------------------------------ | ||
317 | -- check for existence of a token, throws error if not found | ||
318 | ------------------------------------------------------------------------ | ||
319 | function luaY:check(ls, c) | ||
320 | if ls.t.token ~= c then | ||
321 | self:error_expected(ls, c) | ||
322 | end | ||
323 | end | ||
324 | |||
325 | ------------------------------------------------------------------------ | ||
326 | -- verify existence of a token, then skip it | ||
327 | ------------------------------------------------------------------------ | ||
328 | function luaY:checknext(ls, c) | ||
329 | self:check(ls, c) | ||
330 | luaX:next(ls) | ||
331 | end | ||
332 | |||
333 | ------------------------------------------------------------------------ | ||
334 | -- throws error if condition not matched | ||
335 | ------------------------------------------------------------------------ | ||
336 | function luaY:check_condition(ls, c, msg) | ||
337 | if not c then luaX:syntaxerror(ls, msg) end | ||
338 | end | ||
339 | |||
340 | ------------------------------------------------------------------------ | ||
341 | -- verifies token conditions are met or else throw error | ||
342 | ------------------------------------------------------------------------ | ||
343 | function luaY:check_match(ls, what, who, where) | ||
344 | if not self:testnext(ls, what) then | ||
345 | if where == ls.linenumber then | ||
346 | self:error_expected(ls, what) | ||
347 | else | ||
348 | luaX:syntaxerror(ls, string.format( | ||
349 | self.LUA_QS.." expected (to close "..self.LUA_QS.." at line %d)", | ||
350 | luaX:token2str(ls, what), luaX:token2str(ls, who), where)) | ||
351 | end | ||
352 | end | ||
353 | end | ||
354 | |||
355 | ------------------------------------------------------------------------ | ||
356 | -- expect that token is a name, return the name | ||
357 | ------------------------------------------------------------------------ | ||
358 | function luaY:str_checkname(ls) | ||
359 | self:check(ls, "TK_NAME") | ||
360 | local ts = ls.t.seminfo | ||
361 | luaX:next(ls) | ||
362 | return ts | ||
363 | end | ||
364 | |||
365 | ------------------------------------------------------------------------ | ||
366 | -- initialize a struct expdesc, expression description data structure | ||
367 | ------------------------------------------------------------------------ | ||
368 | function luaY:init_exp(e, k, i) | ||
369 | e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP | ||
370 | e.k = k | ||
371 | e.info = i | ||
372 | end | ||
373 | |||
374 | ------------------------------------------------------------------------ | ||
375 | -- adds given string s in string pool, sets e as VK | ||
376 | ------------------------------------------------------------------------ | ||
377 | function luaY:codestring(ls, e, s) | ||
378 | self:init_exp(e, "VK", luaK:stringK(ls.fs, s)) | ||
379 | end | ||
380 | |||
381 | ------------------------------------------------------------------------ | ||
382 | -- consume a name token, adds it to string pool, sets e as VK | ||
383 | ------------------------------------------------------------------------ | ||
384 | function luaY:checkname(ls, e) | ||
385 | self:codestring(ls, e, self:str_checkname(ls)) | ||
386 | end | ||
387 | |||
388 | ------------------------------------------------------------------------ | ||
389 | -- creates struct entry for a local variable | ||
390 | -- * used only in new_localvar() | ||
391 | ------------------------------------------------------------------------ | ||
392 | function luaY:registerlocalvar(ls, varname) | ||
393 | local fs = ls.fs | ||
394 | local f = fs.f | ||
395 | self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars, | ||
396 | nil, self.SHRT_MAX, "too many local variables") | ||
397 | -- loop to initialize empty f.locvar positions not required | ||
398 | f.locvars[fs.nlocvars] = {} -- LocVar | ||
399 | f.locvars[fs.nlocvars].varname = varname | ||
400 | -- luaC_objbarrier(ls.L, f, varname) /* GC */ | ||
401 | local nlocvars = fs.nlocvars | ||
402 | fs.nlocvars = fs.nlocvars + 1 | ||
403 | return nlocvars | ||
404 | end | ||
405 | |||
406 | ------------------------------------------------------------------------ | ||
407 | -- creates a new local variable given a name and an offset from nactvar | ||
408 | -- * used in fornum(), forlist(), parlist(), body() | ||
409 | ------------------------------------------------------------------------ | ||
410 | function luaY:new_localvarliteral(ls, v, n) | ||
411 | self:new_localvar(ls, v, n) | ||
412 | end | ||
413 | |||
414 | ------------------------------------------------------------------------ | ||
415 | -- register a local variable, set in active variable list | ||
416 | ------------------------------------------------------------------------ | ||
417 | function luaY:new_localvar(ls, name, n) | ||
418 | local fs = ls.fs | ||
419 | self:checklimit(fs, fs.nactvar + n + 1, self.LUAI_MAXVARS, "local variables") | ||
420 | fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name) | ||
421 | end | ||
422 | |||
423 | ------------------------------------------------------------------------ | ||
424 | -- adds nvars number of new local variables, set debug information | ||
425 | ------------------------------------------------------------------------ | ||
426 | function luaY:adjustlocalvars(ls, nvars) | ||
427 | local fs = ls.fs | ||
428 | fs.nactvar = fs.nactvar + nvars | ||
429 | for i = nvars, 1, -1 do | ||
430 | self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc | ||
431 | end | ||
432 | end | ||
433 | |||
434 | ------------------------------------------------------------------------ | ||
435 | -- removes a number of locals, set debug information | ||
436 | ------------------------------------------------------------------------ | ||
437 | function luaY:removevars(ls, tolevel) | ||
438 | local fs = ls.fs | ||
439 | while fs.nactvar > tolevel do | ||
440 | fs.nactvar = fs.nactvar - 1 | ||
441 | self:getlocvar(fs, fs.nactvar).endpc = fs.pc | ||
442 | end | ||
443 | end | ||
444 | |||
445 | ------------------------------------------------------------------------ | ||
446 | -- returns an existing upvalue index based on the given name, or | ||
447 | -- creates a new upvalue struct entry and returns the new index | ||
448 | -- * used only in singlevaraux() | ||
449 | ------------------------------------------------------------------------ | ||
450 | function luaY:indexupvalue(fs, name, v) | ||
451 | local f = fs.f | ||
452 | for i = 0, f.nups - 1 do | ||
453 | if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then | ||
454 | lua_assert(f.upvalues[i] == name) | ||
455 | return i | ||
456 | end | ||
457 | end | ||
458 | -- new one | ||
459 | self:checklimit(fs, f.nups + 1, self.LUAI_MAXUPVALUES, "upvalues") | ||
460 | self:growvector(fs.L, f.upvalues, f.nups, f.sizeupvalues, | ||
461 | nil, self.MAX_INT, "") | ||
462 | -- loop to initialize empty f.upvalues positions not required | ||
463 | f.upvalues[f.nups] = name | ||
464 | -- luaC_objbarrier(fs->L, f, name); /* GC */ | ||
465 | lua_assert(v.k == "VLOCAL" or v.k == "VUPVAL") | ||
466 | -- this is a partial copy; only k & info fields used | ||
467 | fs.upvalues[f.nups] = { k = v.k, info = v.info } | ||
468 | local nups = f.nups | ||
469 | f.nups = f.nups + 1 | ||
470 | return nups | ||
471 | end | ||
472 | |||
473 | ------------------------------------------------------------------------ | ||
474 | -- search the local variable namespace of the given fs for a match | ||
475 | -- * used only in singlevaraux() | ||
476 | ------------------------------------------------------------------------ | ||
477 | function luaY:searchvar(fs, n) | ||
478 | for i = fs.nactvar - 1, 0, -1 do | ||
479 | if n == self:getlocvar(fs, i).varname then | ||
480 | return i | ||
481 | end | ||
482 | end | ||
483 | return -1 -- not found | ||
484 | end | ||
485 | |||
486 | ------------------------------------------------------------------------ | ||
487 | -- * mark upvalue flags in function states up to a given level | ||
488 | -- * used only in singlevaraux() | ||
489 | ------------------------------------------------------------------------ | ||
490 | function luaY:markupval(fs, level) | ||
491 | local bl = fs.bl | ||
492 | while bl and bl.nactvar > level do bl = bl.previous end | ||
493 | if bl then bl.upval = true end | ||
494 | end | ||
495 | |||
496 | ------------------------------------------------------------------------ | ||
497 | -- handle locals, globals and upvalues and related processing | ||
498 | -- * search mechanism is recursive, calls itself to search parents | ||
499 | -- * used only in singlevar() | ||
500 | ------------------------------------------------------------------------ | ||
501 | function luaY:singlevaraux(fs, n, var, base) | ||
502 | if fs == nil then -- no more levels? | ||
503 | self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable | ||
504 | return "VGLOBAL" | ||
505 | else | ||
506 | local v = self:searchvar(fs, n) -- look up at current level | ||
507 | if v >= 0 then | ||
508 | self:init_exp(var, "VLOCAL", v) | ||
509 | if base == 0 then | ||
510 | self:markupval(fs, v) -- local will be used as an upval | ||
511 | end | ||
512 | return "VLOCAL" | ||
513 | else -- not found at current level; try upper one | ||
514 | if self:singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then | ||
515 | return "VGLOBAL" | ||
516 | end | ||
517 | var.info = self:indexupvalue(fs, n, var) -- else was LOCAL or UPVAL | ||
518 | var.k = "VUPVAL" -- upvalue in this level | ||
519 | return "VUPVAL" | ||
520 | end--if v | ||
521 | end--if fs | ||
522 | end | ||
523 | |||
524 | ------------------------------------------------------------------------ | ||
525 | -- consume a name token, creates a variable (global|local|upvalue) | ||
526 | -- * used in prefixexp(), funcname() | ||
527 | ------------------------------------------------------------------------ | ||
528 | function luaY:singlevar(ls, var) | ||
529 | local varname = self:str_checkname(ls) | ||
530 | local fs = ls.fs | ||
531 | if self:singlevaraux(fs, varname, var, 1) == "VGLOBAL" then | ||
532 | var.info = luaK:stringK(fs, varname) -- info points to global name | ||
533 | end | ||
534 | end | ||
535 | |||
536 | ------------------------------------------------------------------------ | ||
537 | -- adjust RHS to match LHS in an assignment | ||
538 | -- * used in assignment(), forlist(), localstat() | ||
539 | ------------------------------------------------------------------------ | ||
540 | function luaY:adjust_assign(ls, nvars, nexps, e) | ||
541 | local fs = ls.fs | ||
542 | local extra = nvars - nexps | ||
543 | if self:hasmultret(e.k) then | ||
544 | extra = extra + 1 -- includes call itself | ||
545 | if extra <= 0 then extra = 0 end | ||
546 | luaK:setreturns(fs, e, extra) -- last exp. provides the difference | ||
547 | if extra > 1 then luaK:reserveregs(fs, extra - 1) end | ||
548 | else | ||
549 | if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression | ||
550 | if extra > 0 then | ||
551 | local reg = fs.freereg | ||
552 | luaK:reserveregs(fs, extra) | ||
553 | luaK:_nil(fs, reg, extra) | ||
554 | end | ||
555 | end | ||
556 | end | ||
557 | |||
558 | ------------------------------------------------------------------------ | ||
559 | -- tracks and limits parsing depth, assert check at end of parsing | ||
560 | ------------------------------------------------------------------------ | ||
561 | function luaY:enterlevel(ls) | ||
562 | ls.L.nCcalls = ls.L.nCcalls + 1 | ||
563 | if ls.L.nCcalls > self.LUAI_MAXCCALLS then | ||
564 | luaX:lexerror(ls, "chunk has too many syntax levels", 0) | ||
565 | end | ||
566 | end | ||
567 | |||
568 | ------------------------------------------------------------------------ | ||
569 | -- tracks parsing depth, a pair with luaY:enterlevel() | ||
570 | ------------------------------------------------------------------------ | ||
571 | function luaY:leavelevel(ls) | ||
572 | ls.L.nCcalls = ls.L.nCcalls - 1 | ||
573 | end | ||
574 | |||
575 | ------------------------------------------------------------------------ | ||
576 | -- enters a code unit, initializes elements | ||
577 | ------------------------------------------------------------------------ | ||
578 | function luaY:enterblock(fs, bl, isbreakable) | ||
579 | bl.breaklist = luaK.NO_JUMP | ||
580 | bl.isbreakable = isbreakable | ||
581 | bl.nactvar = fs.nactvar | ||
582 | bl.upval = false | ||
583 | bl.previous = fs.bl | ||
584 | fs.bl = bl | ||
585 | lua_assert(fs.freereg == fs.nactvar) | ||
586 | end | ||
587 | |||
588 | ------------------------------------------------------------------------ | ||
589 | -- leaves a code unit, close any upvalues | ||
590 | ------------------------------------------------------------------------ | ||
591 | function luaY:leaveblock(fs) | ||
592 | local bl = fs.bl | ||
593 | fs.bl = bl.previous | ||
594 | self:removevars(fs.ls, bl.nactvar) | ||
595 | if bl.upval then | ||
596 | luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) | ||
597 | end | ||
598 | -- a block either controls scope or breaks (never both) | ||
599 | lua_assert(not bl.isbreakable or not bl.upval) | ||
600 | lua_assert(bl.nactvar == fs.nactvar) | ||
601 | fs.freereg = fs.nactvar -- free registers | ||
602 | luaK:patchtohere(fs, bl.breaklist) | ||
603 | end | ||
604 | |||
605 | ------------------------------------------------------------------------ | ||
606 | -- implement the instantiation of a function prototype, append list of | ||
607 | -- upvalues after the instantiation instruction | ||
608 | -- * used only in body() | ||
609 | ------------------------------------------------------------------------ | ||
610 | function luaY:pushclosure(ls, func, v) | ||
611 | local fs = ls.fs | ||
612 | local f = fs.f | ||
613 | self:growvector(ls.L, f.p, fs.np, f.sizep, nil, | ||
614 | luaP.MAXARG_Bx, "constant table overflow") | ||
615 | -- loop to initialize empty f.p positions not required | ||
616 | f.p[fs.np] = func.f | ||
617 | fs.np = fs.np + 1 | ||
618 | -- luaC_objbarrier(ls->L, f, func->f); /* C */ | ||
619 | self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1)) | ||
620 | for i = 0, func.f.nups - 1 do | ||
621 | local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL" | ||
622 | luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0) | ||
623 | end | ||
624 | end | ||
625 | |||
626 | ------------------------------------------------------------------------ | ||
627 | -- opening of a function | ||
628 | ------------------------------------------------------------------------ | ||
629 | function luaY:open_func(ls, fs) | ||
630 | local L = ls.L | ||
631 | local f = self:newproto(ls.L) | ||
632 | fs.f = f | ||
633 | fs.prev = ls.fs -- linked list of funcstates | ||
634 | fs.ls = ls | ||
635 | fs.L = L | ||
636 | ls.fs = fs | ||
637 | fs.pc = 0 | ||
638 | fs.lasttarget = -1 | ||
639 | fs.jpc = luaK.NO_JUMP | ||
640 | fs.freereg = 0 | ||
641 | fs.nk = 0 | ||
642 | fs.np = 0 | ||
643 | fs.nlocvars = 0 | ||
644 | fs.nactvar = 0 | ||
645 | fs.bl = nil | ||
646 | f.source = ls.source | ||
647 | f.maxstacksize = 2 -- registers 0/1 are always valid | ||
648 | fs.h = {} -- constant table; was luaH_new call | ||
649 | -- anchor table of constants and prototype (to avoid being collected) | ||
650 | -- sethvalue2s(L, L->top, fs->h); incr_top(L); /* C */ | ||
651 | -- setptvalue2s(L, L->top, f); incr_top(L); | ||
652 | end | ||
653 | |||
654 | ------------------------------------------------------------------------ | ||
655 | -- closing of a function | ||
656 | ------------------------------------------------------------------------ | ||
657 | function luaY:close_func(ls) | ||
658 | local L = ls.L | ||
659 | local fs = ls.fs | ||
660 | local f = fs.f | ||
661 | self:removevars(ls, 0) | ||
662 | luaK:ret(fs, 0, 0) -- final return | ||
663 | -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p, | ||
664 | -- f->locvars, f->upvalues; not required for Lua table arrays | ||
665 | f.sizecode = fs.pc | ||
666 | f.sizelineinfo = fs.pc | ||
667 | f.sizek = fs.nk | ||
668 | f.sizep = fs.np | ||
669 | f.sizelocvars = fs.nlocvars | ||
670 | f.sizeupvalues = f.nups | ||
671 | --lua_assert(luaG_checkcode(f)) -- currently not implemented | ||
672 | lua_assert(fs.bl == nil) | ||
673 | ls.fs = fs.prev | ||
674 | -- the following is not required for this implementation; kept here | ||
675 | -- for completeness | ||
676 | -- L->top -= 2; /* remove table and prototype from the stack */ | ||
677 | -- last token read was anchored in defunct function; must reanchor it | ||
678 | if fs then self:anchor_token(ls) end | ||
679 | end | ||
680 | |||
681 | ------------------------------------------------------------------------ | ||
682 | -- parser initialization function | ||
683 | -- * note additional sub-tables needed for LexState, FuncState | ||
684 | ------------------------------------------------------------------------ | ||
685 | function luaY:parser(L, z, buff, name) | ||
686 | local lexstate = {} -- LexState | ||
687 | lexstate.t = {} | ||
688 | lexstate.lookahead = {} | ||
689 | local funcstate = {} -- FuncState | ||
690 | funcstate.upvalues = {} | ||
691 | funcstate.actvar = {} | ||
692 | -- the following nCcalls initialization added for convenience | ||
693 | L.nCcalls = 0 | ||
694 | lexstate.buff = buff | ||
695 | luaX:setinput(L, lexstate, z, name) | ||
696 | self:open_func(lexstate, funcstate) | ||
697 | funcstate.f.is_vararg = self.VARARG_ISVARARG -- main func. is always vararg | ||
698 | luaX:next(lexstate) -- read first token | ||
699 | self:chunk(lexstate) | ||
700 | self:check(lexstate, "TK_EOS") | ||
701 | self:close_func(lexstate) | ||
702 | lua_assert(funcstate.prev == nil) | ||
703 | lua_assert(funcstate.f.nups == 0) | ||
704 | lua_assert(lexstate.fs == nil) | ||
705 | return funcstate.f | ||
706 | end | ||
707 | |||
708 | --[[-------------------------------------------------------------------- | ||
709 | -- GRAMMAR RULES | ||
710 | ----------------------------------------------------------------------]] | ||
711 | |||
712 | ------------------------------------------------------------------------ | ||
713 | -- parse a function name suffix, for function call specifications | ||
714 | -- * used in primaryexp(), funcname() | ||
715 | ------------------------------------------------------------------------ | ||
716 | function luaY:field(ls, v) | ||
717 | -- field -> ['.' | ':'] NAME | ||
718 | local fs = ls.fs | ||
719 | local key = {} -- expdesc | ||
720 | luaK:exp2anyreg(fs, v) | ||
721 | luaX:next(ls) -- skip the dot or colon | ||
722 | self:checkname(ls, key) | ||
723 | luaK:indexed(fs, v, key) | ||
724 | end | ||
725 | |||
726 | ------------------------------------------------------------------------ | ||
727 | -- parse a table indexing suffix, for constructors, expressions | ||
728 | -- * used in recfield(), primaryexp() | ||
729 | ------------------------------------------------------------------------ | ||
730 | function luaY:yindex(ls, v) | ||
731 | -- index -> '[' expr ']' | ||
732 | luaX:next(ls) -- skip the '[' | ||
733 | self:expr(ls, v) | ||
734 | luaK:exp2val(ls.fs, v) | ||
735 | self:checknext(ls, "]") | ||
736 | end | ||
737 | |||
738 | --[[-------------------------------------------------------------------- | ||
739 | -- Rules for Constructors | ||
740 | ----------------------------------------------------------------------]] | ||
741 | |||
742 | --[[-------------------------------------------------------------------- | ||
743 | -- struct ConsControl: | ||
744 | -- v -- last list item read (table: struct expdesc) | ||
745 | -- t -- table descriptor (table: struct expdesc) | ||
746 | -- nh -- total number of 'record' elements | ||
747 | -- na -- total number of array elements | ||
748 | -- tostore -- number of array elements pending to be stored | ||
749 | ----------------------------------------------------------------------]] | ||
750 | |||
751 | ------------------------------------------------------------------------ | ||
752 | -- parse a table record (hash) field | ||
753 | -- * used in constructor() | ||
754 | ------------------------------------------------------------------------ | ||
755 | function luaY:recfield(ls, cc) | ||
756 | -- recfield -> (NAME | '['exp1']') = exp1 | ||
757 | local fs = ls.fs | ||
758 | local reg = ls.fs.freereg | ||
759 | local key, val = {}, {} -- expdesc | ||
760 | if ls.t.token == "TK_NAME" then | ||
761 | self:checklimit(fs, cc.nh, self.MAX_INT, "items in a constructor") | ||
762 | self:checkname(ls, key) | ||
763 | else -- ls->t.token == '[' | ||
764 | self:yindex(ls, key) | ||
765 | end | ||
766 | cc.nh = cc.nh + 1 | ||
767 | self:checknext(ls, "=") | ||
768 | local rkkey = luaK:exp2RK(fs, key) | ||
769 | self:expr(ls, val) | ||
770 | luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, rkkey, luaK:exp2RK(fs, val)) | ||
771 | fs.freereg = reg -- free registers | ||
772 | end | ||
773 | |||
774 | ------------------------------------------------------------------------ | ||
775 | -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH) | ||
776 | -- * used in constructor() | ||
777 | ------------------------------------------------------------------------ | ||
778 | function luaY:closelistfield(fs, cc) | ||
779 | if cc.v.k == "VVOID" then return end -- there is no list item | ||
780 | luaK:exp2nextreg(fs, cc.v) | ||
781 | cc.v.k = "VVOID" | ||
782 | if cc.tostore == luaP.LFIELDS_PER_FLUSH then | ||
783 | luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) -- flush | ||
784 | cc.tostore = 0 -- no more items pending | ||
785 | end | ||
786 | end | ||
787 | |||
788 | ------------------------------------------------------------------------ | ||
789 | -- emit a set list instruction at the end of parsing list constructor | ||
790 | -- * used in constructor() | ||
791 | ------------------------------------------------------------------------ | ||
792 | function luaY:lastlistfield(fs, cc) | ||
793 | if cc.tostore == 0 then return end | ||
794 | if self:hasmultret(cc.v.k) then | ||
795 | luaK:setmultret(fs, cc.v) | ||
796 | luaK:setlist(fs, cc.t.info, cc.na, self.LUA_MULTRET) | ||
797 | cc.na = cc.na - 1 -- do not count last expression (unknown number of elements) | ||
798 | else | ||
799 | if cc.v.k ~= "VVOID" then | ||
800 | luaK:exp2nextreg(fs, cc.v) | ||
801 | end | ||
802 | luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) | ||
803 | end | ||
804 | end | ||
805 | |||
806 | ------------------------------------------------------------------------ | ||
807 | -- parse a table list (array) field | ||
808 | -- * used in constructor() | ||
809 | ------------------------------------------------------------------------ | ||
810 | function luaY:listfield(ls, cc) | ||
811 | self:expr(ls, cc.v) | ||
812 | self:checklimit(ls.fs, cc.na, self.MAX_INT, "items in a constructor") | ||
813 | cc.na = cc.na + 1 | ||
814 | cc.tostore = cc.tostore + 1 | ||
815 | end | ||
816 | |||
817 | ------------------------------------------------------------------------ | ||
818 | -- parse a table constructor | ||
819 | -- * used in funcargs(), simpleexp() | ||
820 | ------------------------------------------------------------------------ | ||
821 | function luaY:constructor(ls, t) | ||
822 | -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}' | ||
823 | -- field -> recfield | listfield | ||
824 | -- fieldsep -> ',' | ';' | ||
825 | local fs = ls.fs | ||
826 | local line = ls.linenumber | ||
827 | local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0) | ||
828 | local cc = {} -- ConsControl | ||
829 | cc.v = {} | ||
830 | cc.na, cc.nh, cc.tostore = 0, 0, 0 | ||
831 | cc.t = t | ||
832 | self:init_exp(t, "VRELOCABLE", pc) | ||
833 | self:init_exp(cc.v, "VVOID", 0) -- no value (yet) | ||
834 | luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc) | ||
835 | self:checknext(ls, "{") | ||
836 | repeat | ||
837 | lua_assert(cc.v.k == "VVOID" or cc.tostore > 0) | ||
838 | if ls.t.token == "}" then break end | ||
839 | self:closelistfield(fs, cc) | ||
840 | local c = ls.t.token | ||
841 | |||
842 | if c == "TK_NAME" then -- may be listfields or recfields | ||
843 | luaX:lookahead(ls) | ||
844 | if ls.lookahead.token ~= "=" then -- expression? | ||
845 | self:listfield(ls, cc) | ||
846 | else | ||
847 | self:recfield(ls, cc) | ||
848 | end | ||
849 | elseif c == "[" then -- constructor_item -> recfield | ||
850 | self:recfield(ls, cc) | ||
851 | else -- constructor_part -> listfield | ||
852 | self:listfield(ls, cc) | ||
853 | end | ||
854 | until not self:testnext(ls, ",") and not self:testnext(ls, ";") | ||
855 | self:check_match(ls, "}", "{", line) | ||
856 | self:lastlistfield(fs, cc) | ||
857 | luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size | ||
858 | luaP:SETARG_C(fs.f.code[pc], self:int2fb(cc.nh)) -- set initial table size | ||
859 | end | ||
860 | |||
861 | -- }====================================================================== | ||
862 | |||
863 | ------------------------------------------------------------------------ | ||
864 | -- parse the arguments (parameters) of a function declaration | ||
865 | -- * used in body() | ||
866 | ------------------------------------------------------------------------ | ||
867 | function luaY:parlist(ls) | ||
868 | -- parlist -> [ param { ',' param } ] | ||
869 | local fs = ls.fs | ||
870 | local f = fs.f | ||
871 | local nparams = 0 | ||
872 | f.is_vararg = 0 | ||
873 | if ls.t.token ~= ")" then -- is 'parlist' not empty? | ||
874 | repeat | ||
875 | local c = ls.t.token | ||
876 | if c == "TK_NAME" then -- param -> NAME | ||
877 | self:new_localvar(ls, self:str_checkname(ls), nparams) | ||
878 | nparams = nparams + 1 | ||
879 | elseif c == "TK_DOTS" then -- param -> `...' | ||
880 | luaX:next(ls) | ||
881 | -- [[ | ||
882 | -- #if defined(LUA_COMPAT_VARARG) | ||
883 | -- use `arg' as default name | ||
884 | self:new_localvarliteral(ls, "arg", nparams) | ||
885 | nparams = nparams + 1 | ||
886 | f.is_vararg = self.VARARG_HASARG + self.VARARG_NEEDSARG | ||
887 | -- #endif | ||
888 | --]] | ||
889 | f.is_vararg = f.is_vararg + self.VARARG_ISVARARG | ||
890 | else | ||
891 | luaX:syntaxerror(ls, "<name> or "..self:LUA_QL("...").." expected") | ||
892 | end | ||
893 | until f.is_vararg ~= 0 or not self:testnext(ls, ",") | ||
894 | end--if | ||
895 | self:adjustlocalvars(ls, nparams) | ||
896 | -- NOTE: the following works only when HASARG_MASK is 2! | ||
897 | f.numparams = fs.nactvar - (f.is_vararg % self.HASARG_MASK) | ||
898 | luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters | ||
899 | end | ||
900 | |||
901 | ------------------------------------------------------------------------ | ||
902 | -- parse function declaration body | ||
903 | -- * used in simpleexp(), localfunc(), funcstat() | ||
904 | ------------------------------------------------------------------------ | ||
905 | function luaY:body(ls, e, needself, line) | ||
906 | -- body -> '(' parlist ')' chunk END | ||
907 | local new_fs = {} -- FuncState | ||
908 | new_fs.upvalues = {} | ||
909 | new_fs.actvar = {} | ||
910 | self:open_func(ls, new_fs) | ||
911 | new_fs.f.lineDefined = line | ||
912 | self:checknext(ls, "(") | ||
913 | if needself then | ||
914 | self:new_localvarliteral(ls, "self", 0) | ||
915 | self:adjustlocalvars(ls, 1) | ||
916 | end | ||
917 | self:parlist(ls) | ||
918 | self:checknext(ls, ")") | ||
919 | self:chunk(ls) | ||
920 | new_fs.f.lastlinedefined = ls.linenumber | ||
921 | self:check_match(ls, "TK_END", "TK_FUNCTION", line) | ||
922 | self:close_func(ls) | ||
923 | self:pushclosure(ls, new_fs, e) | ||
924 | end | ||
925 | |||
926 | ------------------------------------------------------------------------ | ||
927 | -- parse a list of comma-separated expressions | ||
928 | -- * used is multiple locations | ||
929 | ------------------------------------------------------------------------ | ||
930 | function luaY:explist1(ls, v) | ||
931 | -- explist1 -> expr { ',' expr } | ||
932 | local n = 1 -- at least one expression | ||
933 | self:expr(ls, v) | ||
934 | while self:testnext(ls, ",") do | ||
935 | luaK:exp2nextreg(ls.fs, v) | ||
936 | self:expr(ls, v) | ||
937 | n = n + 1 | ||
938 | end | ||
939 | return n | ||
940 | end | ||
941 | |||
942 | ------------------------------------------------------------------------ | ||
943 | -- parse the parameters of a function call | ||
944 | -- * contrast with parlist(), used in function declarations | ||
945 | -- * used in primaryexp() | ||
946 | ------------------------------------------------------------------------ | ||
947 | function luaY:funcargs(ls, f) | ||
948 | local fs = ls.fs | ||
949 | local args = {} -- expdesc | ||
950 | local nparams | ||
951 | local line = ls.linenumber | ||
952 | local c = ls.t.token | ||
953 | if c == "(" then -- funcargs -> '(' [ explist1 ] ')' | ||
954 | if line ~= ls.lastline then | ||
955 | luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)") | ||
956 | end | ||
957 | luaX:next(ls) | ||
958 | if ls.t.token == ")" then -- arg list is empty? | ||
959 | args.k = "VVOID" | ||
960 | else | ||
961 | self:explist1(ls, args) | ||
962 | luaK:setmultret(fs, args) | ||
963 | end | ||
964 | self:check_match(ls, ")", "(", line) | ||
965 | elseif c == "{" then -- funcargs -> constructor | ||
966 | self:constructor(ls, args) | ||
967 | elseif c == "TK_STRING" then -- funcargs -> STRING | ||
968 | self:codestring(ls, args, ls.t.seminfo) | ||
969 | luaX:next(ls) -- must use 'seminfo' before 'next' | ||
970 | else | ||
971 | luaX:syntaxerror(ls, "function arguments expected") | ||
972 | return | ||
973 | end | ||
974 | lua_assert(f.k == "VNONRELOC") | ||
975 | local base = f.info -- base register for call | ||
976 | if self:hasmultret(args.k) then | ||
977 | nparams = self.LUA_MULTRET -- open call | ||
978 | else | ||
979 | if args.k ~= "VVOID" then | ||
980 | luaK:exp2nextreg(fs, args) -- close last argument | ||
981 | end | ||
982 | nparams = fs.freereg - (base + 1) | ||
983 | end | ||
984 | self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2)) | ||
985 | luaK:fixline(fs, line) | ||
986 | fs.freereg = base + 1 -- call remove function and arguments and leaves | ||
987 | -- (unless changed) one result | ||
988 | end | ||
989 | |||
990 | --[[-------------------------------------------------------------------- | ||
991 | -- Expression parsing | ||
992 | ----------------------------------------------------------------------]] | ||
993 | |||
994 | ------------------------------------------------------------------------ | ||
995 | -- parses an expression in parentheses or a single variable | ||
996 | -- * used in primaryexp() | ||
997 | ------------------------------------------------------------------------ | ||
998 | function luaY:prefixexp(ls, v) | ||
999 | -- prefixexp -> NAME | '(' expr ')' | ||
1000 | local c = ls.t.token | ||
1001 | if c == "(" then | ||
1002 | local line = ls.linenumber | ||
1003 | luaX:next(ls) | ||
1004 | self:expr(ls, v) | ||
1005 | self:check_match(ls, ")", "(", line) | ||
1006 | luaK:dischargevars(ls.fs, v) | ||
1007 | elseif c == "TK_NAME" then | ||
1008 | self:singlevar(ls, v) | ||
1009 | else | ||
1010 | luaX:syntaxerror(ls, "unexpected symbol") | ||
1011 | end--if c | ||
1012 | return | ||
1013 | end | ||
1014 | |||
1015 | ------------------------------------------------------------------------ | ||
1016 | -- parses a prefixexp (an expression in parentheses or a single variable) | ||
1017 | -- or a function call specification | ||
1018 | -- * used in simpleexp(), assignment(), exprstat() | ||
1019 | ------------------------------------------------------------------------ | ||
1020 | function luaY:primaryexp(ls, v) | ||
1021 | -- primaryexp -> | ||
1022 | -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } | ||
1023 | local fs = ls.fs | ||
1024 | self:prefixexp(ls, v) | ||
1025 | while true do | ||
1026 | local c = ls.t.token | ||
1027 | if c == "." then -- field | ||
1028 | self:field(ls, v) | ||
1029 | elseif c == "[" then -- '[' exp1 ']' | ||
1030 | local key = {} -- expdesc | ||
1031 | luaK:exp2anyreg(fs, v) | ||
1032 | self:yindex(ls, key) | ||
1033 | luaK:indexed(fs, v, key) | ||
1034 | elseif c == ":" then -- ':' NAME funcargs | ||
1035 | local key = {} -- expdesc | ||
1036 | luaX:next(ls) | ||
1037 | self:checkname(ls, key) | ||
1038 | luaK:_self(fs, v, key) | ||
1039 | self:funcargs(ls, v) | ||
1040 | elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs | ||
1041 | luaK:exp2nextreg(fs, v) | ||
1042 | self:funcargs(ls, v) | ||
1043 | else | ||
1044 | return | ||
1045 | end--if c | ||
1046 | end--while | ||
1047 | end | ||
1048 | |||
1049 | ------------------------------------------------------------------------ | ||
1050 | -- parses general expression types, constants handled here | ||
1051 | -- * used in subexpr() | ||
1052 | ------------------------------------------------------------------------ | ||
1053 | function luaY:simpleexp(ls, v) | ||
1054 | -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | | ||
1055 | -- constructor | FUNCTION body | primaryexp | ||
1056 | local c = ls.t.token | ||
1057 | if c == "TK_NUMBER" then | ||
1058 | self:init_exp(v, "VKNUM", 0) | ||
1059 | v.nval = ls.t.seminfo | ||
1060 | elseif c == "TK_STRING" then | ||
1061 | self:codestring(ls, v, ls.t.seminfo) | ||
1062 | elseif c == "TK_NIL" then | ||
1063 | self:init_exp(v, "VNIL", 0) | ||
1064 | elseif c == "TK_TRUE" then | ||
1065 | self:init_exp(v, "VTRUE", 0) | ||
1066 | elseif c == "TK_FALSE" then | ||
1067 | self:init_exp(v, "VFALSE", 0) | ||
1068 | elseif c == "TK_DOTS" then -- vararg | ||
1069 | local fs = ls.fs | ||
1070 | self:check_condition(ls, fs.f.is_vararg ~= 0, | ||
1071 | "cannot use "..self:LUA_QL("...").." outside a vararg function"); | ||
1072 | -- NOTE: the following substitutes for a bitop, but is value-specific | ||
1073 | local is_vararg = fs.f.is_vararg | ||
1074 | if is_vararg >= self.VARARG_NEEDSARG then | ||
1075 | fs.f.is_vararg = is_vararg - self.VARARG_NEEDSARG -- don't need 'arg' | ||
1076 | end | ||
1077 | self:init_exp(v, "VVARARG", luaK:codeABC(fs, "OP_VARARG", 0, 1, 0)) | ||
1078 | elseif c == "{" then -- constructor | ||
1079 | self:constructor(ls, v) | ||
1080 | return | ||
1081 | elseif c == "TK_FUNCTION" then | ||
1082 | luaX:next(ls) | ||
1083 | self:body(ls, v, false, ls.linenumber) | ||
1084 | return | ||
1085 | else | ||
1086 | self:primaryexp(ls, v) | ||
1087 | return | ||
1088 | end--if c | ||
1089 | luaX:next(ls) | ||
1090 | end | ||
1091 | |||
1092 | ------------------------------------------------------------------------ | ||
1093 | -- Translates unary operators tokens if found, otherwise returns | ||
1094 | -- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr(). | ||
1095 | -- * used in subexpr() | ||
1096 | ------------------------------------------------------------------------ | ||
1097 | function luaY:getunopr(op) | ||
1098 | if op == "TK_NOT" then | ||
1099 | return "OPR_NOT" | ||
1100 | elseif op == "-" then | ||
1101 | return "OPR_MINUS" | ||
1102 | elseif op == "#" then | ||
1103 | return "OPR_LEN" | ||
1104 | else | ||
1105 | return "OPR_NOUNOPR" | ||
1106 | end | ||
1107 | end | ||
1108 | |||
1109 | ------------------------------------------------------------------------ | ||
1110 | -- Translates binary operator tokens if found, otherwise returns | ||
1111 | -- OPR_NOBINOPR. Code generation uses OPR_* style tokens. | ||
1112 | -- * used in subexpr() | ||
1113 | ------------------------------------------------------------------------ | ||
1114 | luaY.getbinopr_table = { | ||
1115 | ["+"] = "OPR_ADD", | ||
1116 | ["-"] = "OPR_SUB", | ||
1117 | ["*"] = "OPR_MUL", | ||
1118 | ["/"] = "OPR_DIV", | ||
1119 | ["%"] = "OPR_MOD", | ||
1120 | ["^"] = "OPR_POW", | ||
1121 | ["TK_CONCAT"] = "OPR_CONCAT", | ||
1122 | ["TK_NE"] = "OPR_NE", | ||
1123 | ["TK_EQ"] = "OPR_EQ", | ||
1124 | ["<"] = "OPR_LT", | ||
1125 | ["TK_LE"] = "OPR_LE", | ||
1126 | [">"] = "OPR_GT", | ||
1127 | ["TK_GE"] = "OPR_GE", | ||
1128 | ["TK_AND"] = "OPR_AND", | ||
1129 | ["TK_OR"] = "OPR_OR", | ||
1130 | } | ||
1131 | function luaY:getbinopr(op) | ||
1132 | local opr = self.getbinopr_table[op] | ||
1133 | if opr then return opr else return "OPR_NOBINOPR" end | ||
1134 | end | ||
1135 | |||
1136 | ------------------------------------------------------------------------ | ||
1137 | -- the following priority table consists of pairs of left/right values | ||
1138 | -- for binary operators (was a static const struct); grep for ORDER OPR | ||
1139 | -- * the following struct is replaced: | ||
1140 | -- static const struct { | ||
1141 | -- lu_byte left; /* left priority for each binary operator */ | ||
1142 | -- lu_byte right; /* right priority */ | ||
1143 | -- } priority[] = { /* ORDER OPR */ | ||
1144 | ------------------------------------------------------------------------ | ||
1145 | luaY.priority = { | ||
1146 | {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, -- `+' `-' `/' `%' | ||
1147 | {10, 9}, {5, 4}, -- power and concat (right associative) | ||
1148 | {3, 3}, {3, 3}, -- equality | ||
1149 | {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order | ||
1150 | {2, 2}, {1, 1} -- logical (and/or) | ||
1151 | } | ||
1152 | |||
1153 | luaY.UNARY_PRIORITY = 8 -- priority for unary operators | ||
1154 | |||
1155 | ------------------------------------------------------------------------ | ||
1156 | -- Parse subexpressions. Includes handling of unary operators and binary | ||
1157 | -- operators. A subexpr is given the rhs priority level of the operator | ||
1158 | -- immediately left of it, if any (limit is -1 if none,) and if a binop | ||
1159 | -- is found, limit is compared with the lhs priority level of the binop | ||
1160 | -- in order to determine which executes first. | ||
1161 | ------------------------------------------------------------------------ | ||
1162 | |||
1163 | ------------------------------------------------------------------------ | ||
1164 | -- subexpr -> (simpleexp | unop subexpr) { binop subexpr } | ||
1165 | -- where 'binop' is any binary operator with a priority higher than 'limit' | ||
1166 | -- * for priority lookups with self.priority[], 1=left and 2=right | ||
1167 | -- * recursively called | ||
1168 | -- * used in expr() | ||
1169 | ------------------------------------------------------------------------ | ||
1170 | function luaY:subexpr(ls, v, limit) | ||
1171 | self:enterlevel(ls) | ||
1172 | local uop = self:getunopr(ls.t.token) | ||
1173 | if uop ~= "OPR_NOUNOPR" then | ||
1174 | luaX:next(ls) | ||
1175 | self:subexpr(ls, v, self.UNARY_PRIORITY) | ||
1176 | luaK:prefix(ls.fs, uop, v) | ||
1177 | else | ||
1178 | self:simpleexp(ls, v) | ||
1179 | end | ||
1180 | -- expand while operators have priorities higher than 'limit' | ||
1181 | local op = self:getbinopr(ls.t.token) | ||
1182 | while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do | ||
1183 | local v2 = {} -- expdesc | ||
1184 | luaX:next(ls) | ||
1185 | luaK:infix(ls.fs, op, v) | ||
1186 | -- read sub-expression with higher priority | ||
1187 | local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2]) | ||
1188 | luaK:posfix(ls.fs, op, v, v2) | ||
1189 | op = nextop | ||
1190 | end | ||
1191 | self:leavelevel(ls) | ||
1192 | return op -- return first untreated operator | ||
1193 | end | ||
1194 | |||
1195 | ------------------------------------------------------------------------ | ||
1196 | -- Expression parsing starts here. Function subexpr is entered with the | ||
1197 | -- left operator (which is non-existent) priority of -1, which is lower | ||
1198 | -- than all actual operators. Expr information is returned in parm v. | ||
1199 | -- * used in multiple locations | ||
1200 | ------------------------------------------------------------------------ | ||
1201 | function luaY:expr(ls, v) | ||
1202 | self:subexpr(ls, v, 0) | ||
1203 | end | ||
1204 | |||
1205 | -- }==================================================================== | ||
1206 | |||
1207 | --[[-------------------------------------------------------------------- | ||
1208 | -- Rules for Statements | ||
1209 | ----------------------------------------------------------------------]] | ||
1210 | |||
1211 | ------------------------------------------------------------------------ | ||
1212 | -- checks next token, used as a look-ahead | ||
1213 | -- * returns boolean instead of 0|1 | ||
1214 | -- * used in retstat(), chunk() | ||
1215 | ------------------------------------------------------------------------ | ||
1216 | function luaY:block_follow(token) | ||
1217 | if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END" | ||
1218 | or token == "TK_UNTIL" or token == "TK_EOS" then | ||
1219 | return true | ||
1220 | else | ||
1221 | return false | ||
1222 | end | ||
1223 | end | ||
1224 | |||
1225 | ------------------------------------------------------------------------ | ||
1226 | -- parse a code block or unit | ||
1227 | -- * used in multiple functions | ||
1228 | ------------------------------------------------------------------------ | ||
1229 | function luaY:block(ls) | ||
1230 | -- block -> chunk | ||
1231 | local fs = ls.fs | ||
1232 | local bl = {} -- BlockCnt | ||
1233 | self:enterblock(fs, bl, false) | ||
1234 | self:chunk(ls) | ||
1235 | lua_assert(bl.breaklist == luaK.NO_JUMP) | ||
1236 | self:leaveblock(fs) | ||
1237 | end | ||
1238 | |||
1239 | ------------------------------------------------------------------------ | ||
1240 | -- structure to chain all variables in the left-hand side of an | ||
1241 | -- assignment | ||
1242 | -- struct LHS_assign: | ||
1243 | -- prev -- (table: struct LHS_assign) | ||
1244 | -- v -- variable (global, local, upvalue, or indexed) (table: expdesc) | ||
1245 | ------------------------------------------------------------------------ | ||
1246 | |||
1247 | ------------------------------------------------------------------------ | ||
1248 | -- check whether, in an assignment to a local variable, the local variable | ||
1249 | -- is needed in a previous assignment (to a table). If so, save original | ||
1250 | -- local value in a safe place and use this safe copy in the previous | ||
1251 | -- assignment. | ||
1252 | -- * used in assignment() | ||
1253 | ------------------------------------------------------------------------ | ||
1254 | function luaY:check_conflict(ls, lh, v) | ||
1255 | local fs = ls.fs | ||
1256 | local extra = fs.freereg -- eventual position to save local variable | ||
1257 | local conflict = false | ||
1258 | while lh do | ||
1259 | if lh.v.k == "VINDEXED" then | ||
1260 | if lh.v.info == v.info then -- conflict? | ||
1261 | conflict = true | ||
1262 | lh.v.info = extra -- previous assignment will use safe copy | ||
1263 | end | ||
1264 | if lh.v.aux == v.info then -- conflict? | ||
1265 | conflict = true | ||
1266 | lh.v.aux = extra -- previous assignment will use safe copy | ||
1267 | end | ||
1268 | end | ||
1269 | lh = lh.prev | ||
1270 | end | ||
1271 | if conflict then | ||
1272 | luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy | ||
1273 | luaK:reserveregs(fs, 1) | ||
1274 | end | ||
1275 | end | ||
1276 | |||
1277 | ------------------------------------------------------------------------ | ||
1278 | -- parse a variable assignment sequence | ||
1279 | -- * recursively called | ||
1280 | -- * used in exprstat() | ||
1281 | ------------------------------------------------------------------------ | ||
1282 | function luaY:assignment(ls, lh, nvars) | ||
1283 | local e = {} -- expdesc | ||
1284 | -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED | ||
1285 | local c = lh.v.k | ||
1286 | self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL" | ||
1287 | or c == "VINDEXED", "syntax error") | ||
1288 | if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment | ||
1289 | local nv = {} -- LHS_assign | ||
1290 | nv.v = {} | ||
1291 | nv.prev = lh | ||
1292 | self:primaryexp(ls, nv.v) | ||
1293 | if nv.v.k == "VLOCAL" then | ||
1294 | self:check_conflict(ls, lh, nv.v) | ||
1295 | end | ||
1296 | self:checklimit(ls.fs, nvars, self.LUAI_MAXCCALLS - ls.L.nCcalls, | ||
1297 | "variables in assignment") | ||
1298 | self:assignment(ls, nv, nvars + 1) | ||
1299 | else -- assignment -> '=' explist1 | ||
1300 | self:checknext(ls, "=") | ||
1301 | local nexps = self:explist1(ls, e) | ||
1302 | if nexps ~= nvars then | ||
1303 | self:adjust_assign(ls, nvars, nexps, e) | ||
1304 | if nexps > nvars then | ||
1305 | ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values | ||
1306 | end | ||
1307 | else | ||
1308 | luaK:setoneret(ls.fs, e) -- close last expression | ||
1309 | luaK:storevar(ls.fs, lh.v, e) | ||
1310 | return -- avoid default | ||
1311 | end | ||
1312 | end | ||
1313 | self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment | ||
1314 | luaK:storevar(ls.fs, lh.v, e) | ||
1315 | end | ||
1316 | |||
1317 | ------------------------------------------------------------------------ | ||
1318 | -- parse condition in a repeat statement or an if control structure | ||
1319 | -- * used in repeatstat(), test_then_block() | ||
1320 | ------------------------------------------------------------------------ | ||
1321 | function luaY:cond(ls) | ||
1322 | -- cond -> exp | ||
1323 | local v = {} -- expdesc | ||
1324 | self:expr(ls, v) -- read condition | ||
1325 | if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here | ||
1326 | luaK:goiftrue(ls.fs, v) | ||
1327 | return v.f | ||
1328 | end | ||
1329 | |||
1330 | ------------------------------------------------------------------------ | ||
1331 | -- parse a break statement | ||
1332 | -- * used in statements() | ||
1333 | ------------------------------------------------------------------------ | ||
1334 | function luaY:breakstat(ls) | ||
1335 | -- stat -> BREAK | ||
1336 | local fs = ls.fs | ||
1337 | local bl = fs.bl | ||
1338 | local upval = false | ||
1339 | while bl and not bl.isbreakable do | ||
1340 | if bl.upval then upval = true end | ||
1341 | bl = bl.previous | ||
1342 | end | ||
1343 | if not bl then | ||
1344 | luaX:syntaxerror(ls, "no loop to break") | ||
1345 | end | ||
1346 | if upval then | ||
1347 | luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0) | ||
1348 | end | ||
1349 | bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs)) | ||
1350 | end | ||
1351 | |||
1352 | ------------------------------------------------------------------------ | ||
1353 | -- parse a while-do control structure, body processed by block() | ||
1354 | -- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by | ||
1355 | -- the function's implementation can be removed | ||
1356 | -- * used in statements() | ||
1357 | ------------------------------------------------------------------------ | ||
1358 | function luaY:whilestat(ls, line) | ||
1359 | -- whilestat -> WHILE cond DO block END | ||
1360 | local fs = ls.fs | ||
1361 | local bl = {} -- BlockCnt | ||
1362 | luaX:next(ls) -- skip WHILE | ||
1363 | local whileinit = luaK:getlabel(fs) | ||
1364 | local condexit = self:cond(ls) | ||
1365 | self:enterblock(fs, bl, true) | ||
1366 | self:checknext(ls, "TK_DO") | ||
1367 | self:block(ls) | ||
1368 | luaK:patchlist(fs, luaK:jump(fs), whileinit) | ||
1369 | self:check_match(ls, "TK_END", "TK_WHILE", line) | ||
1370 | self:leaveblock(fs) | ||
1371 | luaK:patchtohere(fs, condexit) -- false conditions finish the loop | ||
1372 | end | ||
1373 | |||
1374 | ------------------------------------------------------------------------ | ||
1375 | -- parse a repeat-until control structure, body parsed by chunk() | ||
1376 | -- * used in statements() | ||
1377 | ------------------------------------------------------------------------ | ||
1378 | function luaY:repeatstat(ls, line) | ||
1379 | -- repeatstat -> REPEAT block UNTIL cond | ||
1380 | local fs = ls.fs | ||
1381 | local repeat_init = luaK:getlabel(fs) | ||
1382 | local bl1, bl2 = {}, {} -- BlockCnt | ||
1383 | self:enterblock(fs, bl1, true) -- loop block | ||
1384 | self:enterblock(fs, bl2, false) -- scope block | ||
1385 | luaX:next(ls) -- skip REPEAT | ||
1386 | self:chunk(ls) | ||
1387 | self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line) | ||
1388 | local condexit = self:cond(ls) -- read condition (inside scope block) | ||
1389 | if not bl2.upval then -- no upvalues? | ||
1390 | self:leaveblock(fs) -- finish scope | ||
1391 | luaK:patchlist(ls.fs, condexit, repeat_init) -- close the loop | ||
1392 | else -- complete semantics when there are upvalues | ||
1393 | self:breakstat(ls) -- if condition then break | ||
1394 | luaK:patchtohere(ls.fs, condexit) -- else... | ||
1395 | self:leaveblock(fs) -- finish scope... | ||
1396 | luaK:patchlist(ls.fs, luaK:jump(fs), repeat_init) -- and repeat | ||
1397 | end | ||
1398 | self:leaveblock(fs) -- finish loop | ||
1399 | end | ||
1400 | |||
1401 | ------------------------------------------------------------------------ | ||
1402 | -- parse the single expressions needed in numerical for loops | ||
1403 | -- * used in fornum() | ||
1404 | ------------------------------------------------------------------------ | ||
1405 | function luaY:exp1(ls) | ||
1406 | local e = {} -- expdesc | ||
1407 | self:expr(ls, e) | ||
1408 | local k = e.k | ||
1409 | luaK:exp2nextreg(ls.fs, e) | ||
1410 | return k | ||
1411 | end | ||
1412 | |||
1413 | ------------------------------------------------------------------------ | ||
1414 | -- parse a for loop body for both versions of the for loop | ||
1415 | -- * used in fornum(), forlist() | ||
1416 | ------------------------------------------------------------------------ | ||
1417 | function luaY:forbody(ls, base, line, nvars, isnum) | ||
1418 | -- forbody -> DO block | ||
1419 | local bl = {} -- BlockCnt | ||
1420 | local fs = ls.fs | ||
1421 | self:adjustlocalvars(ls, 3) -- control variables | ||
1422 | self:checknext(ls, "TK_DO") | ||
1423 | local prep = isnum and luaK:codeAsBx(fs, "OP_FORPREP", base, luaK.NO_JUMP) | ||
1424 | or luaK:jump(fs) | ||
1425 | self:enterblock(fs, bl, false) -- scope for declared variables | ||
1426 | self:adjustlocalvars(ls, nvars) | ||
1427 | luaK:reserveregs(fs, nvars) | ||
1428 | self:block(ls) | ||
1429 | self:leaveblock(fs) -- end of scope for declared variables | ||
1430 | luaK:patchtohere(fs, prep) | ||
1431 | local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP) | ||
1432 | or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars) | ||
1433 | luaK:fixline(fs, line) -- pretend that `OP_FOR' starts the loop | ||
1434 | luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep + 1) | ||
1435 | end | ||
1436 | |||
1437 | ------------------------------------------------------------------------ | ||
1438 | -- parse a numerical for loop, calls forbody() | ||
1439 | -- * used in forstat() | ||
1440 | ------------------------------------------------------------------------ | ||
1441 | function luaY:fornum(ls, varname, line) | ||
1442 | -- fornum -> NAME = exp1,exp1[,exp1] forbody | ||
1443 | local fs = ls.fs | ||
1444 | local base = fs.freereg | ||
1445 | self:new_localvarliteral(ls, "(for index)", 0) | ||
1446 | self:new_localvarliteral(ls, "(for limit)", 1) | ||
1447 | self:new_localvarliteral(ls, "(for step)", 2) | ||
1448 | self:new_localvar(ls, varname, 3) | ||
1449 | self:checknext(ls, '=') | ||
1450 | self:exp1(ls) -- initial value | ||
1451 | self:checknext(ls, ",") | ||
1452 | self:exp1(ls) -- limit | ||
1453 | if self:testnext(ls, ",") then | ||
1454 | self:exp1(ls) -- optional step | ||
1455 | else -- default step = 1 | ||
1456 | luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1)) | ||
1457 | luaK:reserveregs(fs, 1) | ||
1458 | end | ||
1459 | self:forbody(ls, base, line, 1, true) | ||
1460 | end | ||
1461 | |||
1462 | ------------------------------------------------------------------------ | ||
1463 | -- parse a generic for loop, calls forbody() | ||
1464 | -- * used in forstat() | ||
1465 | ------------------------------------------------------------------------ | ||
1466 | function luaY:forlist(ls, indexname) | ||
1467 | -- forlist -> NAME {,NAME} IN explist1 forbody | ||
1468 | local fs = ls.fs | ||
1469 | local e = {} -- expdesc | ||
1470 | local nvars = 0 | ||
1471 | local base = fs.freereg | ||
1472 | -- create control variables | ||
1473 | self:new_localvarliteral(ls, "(for generator)", nvars) | ||
1474 | nvars = nvars + 1 | ||
1475 | self:new_localvarliteral(ls, "(for state)", nvars) | ||
1476 | nvars = nvars + 1 | ||
1477 | self:new_localvarliteral(ls, "(for control)", nvars) | ||
1478 | nvars = nvars + 1 | ||
1479 | -- create declared variables | ||
1480 | self:new_localvar(ls, indexname, nvars) | ||
1481 | nvars = nvars + 1 | ||
1482 | while self:testnext(ls, ",") do | ||
1483 | self:new_localvar(ls, self:str_checkname(ls), nvars) | ||
1484 | nvars = nvars + 1 | ||
1485 | end | ||
1486 | self:checknext(ls, "TK_IN") | ||
1487 | local line = ls.linenumber | ||
1488 | self:adjust_assign(ls, 3, self:explist1(ls, e), e) | ||
1489 | luaK:checkstack(fs, 3) -- extra space to call generator | ||
1490 | self:forbody(ls, base, line, nvars - 3, false) | ||
1491 | end | ||
1492 | |||
1493 | ------------------------------------------------------------------------ | ||
1494 | -- initial parsing for a for loop, calls fornum() or forlist() | ||
1495 | -- * used in statements() | ||
1496 | ------------------------------------------------------------------------ | ||
1497 | function luaY:forstat(ls, line) | ||
1498 | -- forstat -> FOR (fornum | forlist) END | ||
1499 | local fs = ls.fs | ||
1500 | local bl = {} -- BlockCnt | ||
1501 | self:enterblock(fs, bl, true) -- scope for loop and control variables | ||
1502 | luaX:next(ls) -- skip `for' | ||
1503 | local varname = self:str_checkname(ls) -- first variable name | ||
1504 | local c = ls.t.token | ||
1505 | if c == "=" then | ||
1506 | self:fornum(ls, varname, line) | ||
1507 | elseif c == "," or c == "TK_IN" then | ||
1508 | self:forlist(ls, varname) | ||
1509 | else | ||
1510 | luaX:syntaxerror(ls, self:LUA_QL("=").." or "..self:LUA_QL("in").." expected") | ||
1511 | end | ||
1512 | self:check_match(ls, "TK_END", "TK_FOR", line) | ||
1513 | self:leaveblock(fs) -- loop scope (`break' jumps to this point) | ||
1514 | end | ||
1515 | |||
1516 | ------------------------------------------------------------------------ | ||
1517 | -- parse part of an if control structure, including the condition | ||
1518 | -- * used in ifstat() | ||
1519 | ------------------------------------------------------------------------ | ||
1520 | function luaY:test_then_block(ls) | ||
1521 | -- test_then_block -> [IF | ELSEIF] cond THEN block | ||
1522 | luaX:next(ls) -- skip IF or ELSEIF | ||
1523 | local condexit = self:cond(ls) | ||
1524 | self:checknext(ls, "TK_THEN") | ||
1525 | self:block(ls) -- `then' part | ||
1526 | return condexit | ||
1527 | end | ||
1528 | |||
1529 | ------------------------------------------------------------------------ | ||
1530 | -- parse an if control structure | ||
1531 | -- * used in statements() | ||
1532 | ------------------------------------------------------------------------ | ||
1533 | function luaY:ifstat(ls, line) | ||
1534 | -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END | ||
1535 | local fs = ls.fs | ||
1536 | local escapelist = luaK.NO_JUMP | ||
1537 | local flist = self:test_then_block(ls) -- IF cond THEN block | ||
1538 | while ls.t.token == "TK_ELSEIF" do | ||
1539 | escapelist = luaK:concat(fs, escapelist, luaK:jump(fs)) | ||
1540 | luaK:patchtohere(fs, flist) | ||
1541 | flist = self:test_then_block(ls) -- ELSEIF cond THEN block | ||
1542 | end | ||
1543 | if ls.t.token == "TK_ELSE" then | ||
1544 | escapelist = luaK:concat(fs, escapelist, luaK:jump(fs)) | ||
1545 | luaK:patchtohere(fs, flist) | ||
1546 | luaX:next(ls) -- skip ELSE (after patch, for correct line info) | ||
1547 | self:block(ls) -- 'else' part | ||
1548 | else | ||
1549 | escapelist = luaK:concat(fs, escapelist, flist) | ||
1550 | end | ||
1551 | luaK:patchtohere(fs, escapelist) | ||
1552 | self:check_match(ls, "TK_END", "TK_IF", line) | ||
1553 | end | ||
1554 | |||
1555 | ------------------------------------------------------------------------ | ||
1556 | -- parse a local function statement | ||
1557 | -- * used in statements() | ||
1558 | ------------------------------------------------------------------------ | ||
1559 | function luaY:localfunc(ls) | ||
1560 | local v, b = {}, {} -- expdesc | ||
1561 | local fs = ls.fs | ||
1562 | self:new_localvar(ls, self:str_checkname(ls), 0) | ||
1563 | self:init_exp(v, "VLOCAL", fs.freereg) | ||
1564 | luaK:reserveregs(fs, 1) | ||
1565 | self:adjustlocalvars(ls, 1) | ||
1566 | self:body(ls, b, false, ls.linenumber) | ||
1567 | luaK:storevar(fs, v, b) | ||
1568 | -- debug information will only see the variable after this point! | ||
1569 | self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc | ||
1570 | end | ||
1571 | |||
1572 | ------------------------------------------------------------------------ | ||
1573 | -- parse a local variable declaration statement | ||
1574 | -- * used in statements() | ||
1575 | ------------------------------------------------------------------------ | ||
1576 | function luaY:localstat(ls) | ||
1577 | -- stat -> LOCAL NAME {',' NAME} ['=' explist1] | ||
1578 | local nvars = 0 | ||
1579 | local nexps | ||
1580 | local e = {} -- expdesc | ||
1581 | repeat | ||
1582 | self:new_localvar(ls, self:str_checkname(ls), nvars) | ||
1583 | nvars = nvars + 1 | ||
1584 | until not self:testnext(ls, ",") | ||
1585 | if self:testnext(ls, "=") then | ||
1586 | nexps = self:explist1(ls, e) | ||
1587 | else | ||
1588 | e.k = "VVOID" | ||
1589 | nexps = 0 | ||
1590 | end | ||
1591 | self:adjust_assign(ls, nvars, nexps, e) | ||
1592 | self:adjustlocalvars(ls, nvars) | ||
1593 | end | ||
1594 | |||
1595 | ------------------------------------------------------------------------ | ||
1596 | -- parse a function name specification | ||
1597 | -- * used in funcstat() | ||
1598 | ------------------------------------------------------------------------ | ||
1599 | function luaY:funcname(ls, v) | ||
1600 | -- funcname -> NAME {field} [':' NAME] | ||
1601 | local needself = false | ||
1602 | self:singlevar(ls, v) | ||
1603 | while ls.t.token == "." do | ||
1604 | self:field(ls, v) | ||
1605 | end | ||
1606 | if ls.t.token == ":" then | ||
1607 | needself = true | ||
1608 | self:field(ls, v) | ||
1609 | end | ||
1610 | return needself | ||
1611 | end | ||
1612 | |||
1613 | ------------------------------------------------------------------------ | ||
1614 | -- parse a function statement | ||
1615 | -- * used in statements() | ||
1616 | ------------------------------------------------------------------------ | ||
1617 | function luaY:funcstat(ls, line) | ||
1618 | -- funcstat -> FUNCTION funcname body | ||
1619 | local v, b = {}, {} -- expdesc | ||
1620 | luaX:next(ls) -- skip FUNCTION | ||
1621 | local needself = self:funcname(ls, v) | ||
1622 | self:body(ls, b, needself, line) | ||
1623 | luaK:storevar(ls.fs, v, b) | ||
1624 | luaK:fixline(ls.fs, line) -- definition 'happens' in the first line | ||
1625 | end | ||
1626 | |||
1627 | ------------------------------------------------------------------------ | ||
1628 | -- parse a function call with no returns or an assignment statement | ||
1629 | -- * used in statements() | ||
1630 | ------------------------------------------------------------------------ | ||
1631 | function luaY:exprstat(ls) | ||
1632 | -- stat -> func | assignment | ||
1633 | local fs = ls.fs | ||
1634 | local v = {} -- LHS_assign | ||
1635 | v.v = {} | ||
1636 | self:primaryexp(ls, v.v) | ||
1637 | if v.v.k == "VCALL" then -- stat -> func | ||
1638 | luaP:SETARG_C(luaK:getcode(fs, v.v), 1) -- call statement uses no results | ||
1639 | else -- stat -> assignment | ||
1640 | v.prev = nil | ||
1641 | self:assignment(ls, v, 1) | ||
1642 | end | ||
1643 | end | ||
1644 | |||
1645 | ------------------------------------------------------------------------ | ||
1646 | -- parse a return statement | ||
1647 | -- * used in statements() | ||
1648 | ------------------------------------------------------------------------ | ||
1649 | function luaY:retstat(ls) | ||
1650 | -- stat -> RETURN explist | ||
1651 | local fs = ls.fs | ||
1652 | local e = {} -- expdesc | ||
1653 | local first, nret -- registers with returned values | ||
1654 | luaX:next(ls) -- skip RETURN | ||
1655 | if self:block_follow(ls.t.token) or ls.t.token == ";" then | ||
1656 | first, nret = 0, 0 -- return no values | ||
1657 | else | ||
1658 | nret = self:explist1(ls, e) -- optional return values | ||
1659 | if self:hasmultret(e.k) then | ||
1660 | luaK:setmultret(fs, e) | ||
1661 | if e.k == "VCALL" and nret == 1 then -- tail call? | ||
1662 | luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL") | ||
1663 | lua_assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar) | ||
1664 | end | ||
1665 | first = fs.nactvar | ||
1666 | nret = self.LUA_MULTRET -- return all values | ||
1667 | else | ||
1668 | if nret == 1 then -- only one single value? | ||
1669 | first = luaK:exp2anyreg(fs, e) | ||
1670 | else | ||
1671 | luaK:exp2nextreg(fs, e) -- values must go to the 'stack' | ||
1672 | first = fs.nactvar -- return all 'active' values | ||
1673 | lua_assert(nret == fs.freereg - first) | ||
1674 | end | ||
1675 | end--if | ||
1676 | end--if | ||
1677 | luaK:ret(fs, first, nret) | ||
1678 | end | ||
1679 | |||
1680 | ------------------------------------------------------------------------ | ||
1681 | -- initial parsing for statements, calls a lot of functions | ||
1682 | -- * returns boolean instead of 0|1 | ||
1683 | -- * used in chunk() | ||
1684 | ------------------------------------------------------------------------ | ||
1685 | function luaY:statement(ls) | ||
1686 | local line = ls.linenumber -- may be needed for error messages | ||
1687 | local c = ls.t.token | ||
1688 | if c == "TK_IF" then -- stat -> ifstat | ||
1689 | self:ifstat(ls, line) | ||
1690 | return false | ||
1691 | elseif c == "TK_WHILE" then -- stat -> whilestat | ||
1692 | self:whilestat(ls, line) | ||
1693 | return false | ||
1694 | elseif c == "TK_DO" then -- stat -> DO block END | ||
1695 | luaX:next(ls) -- skip DO | ||
1696 | self:block(ls) | ||
1697 | self:check_match(ls, "TK_END", "TK_DO", line) | ||
1698 | return false | ||
1699 | elseif c == "TK_FOR" then -- stat -> forstat | ||
1700 | self:forstat(ls, line) | ||
1701 | return false | ||
1702 | elseif c == "TK_REPEAT" then -- stat -> repeatstat | ||
1703 | self:repeatstat(ls, line) | ||
1704 | return false | ||
1705 | elseif c == "TK_FUNCTION" then -- stat -> funcstat | ||
1706 | self:funcstat(ls, line) | ||
1707 | return false | ||
1708 | elseif c == "TK_LOCAL" then -- stat -> localstat | ||
1709 | luaX:next(ls) -- skip LOCAL | ||
1710 | if self:testnext(ls, "TK_FUNCTION") then -- local function? | ||
1711 | self:localfunc(ls) | ||
1712 | else | ||
1713 | self:localstat(ls) | ||
1714 | end | ||
1715 | return false | ||
1716 | elseif c == "TK_RETURN" then -- stat -> retstat | ||
1717 | self:retstat(ls) | ||
1718 | return true -- must be last statement | ||
1719 | elseif c == "TK_BREAK" then -- stat -> breakstat | ||
1720 | luaX:next(ls) -- skip BREAK | ||
1721 | self:breakstat(ls) | ||
1722 | return true -- must be last statement | ||
1723 | else | ||
1724 | self:exprstat(ls) | ||
1725 | return false -- to avoid warnings | ||
1726 | end--if c | ||
1727 | end | ||
1728 | |||
1729 | ------------------------------------------------------------------------ | ||
1730 | -- parse a chunk, which consists of a bunch of statements | ||
1731 | -- * used in parser(), body(), block(), repeatstat() | ||
1732 | ------------------------------------------------------------------------ | ||
1733 | function luaY:chunk(ls) | ||
1734 | -- chunk -> { stat [';'] } | ||
1735 | local islast = false | ||
1736 | self:enterlevel(ls) | ||
1737 | while not islast and not self:block_follow(ls.t.token) do | ||
1738 | islast = self:statement(ls) | ||
1739 | self:testnext(ls, ";") | ||
1740 | lua_assert(ls.fs.f.maxstacksize >= ls.fs.freereg and | ||
1741 | ls.fs.freereg >= ls.fs.nactvar) | ||
1742 | ls.fs.freereg = ls.fs.nactvar -- free registers | ||
1743 | end | ||
1744 | self:leavelevel(ls) | ||
1745 | end | ||
1746 | |||
1747 | -- }====================================================================== | ||