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