· 4 years ago · Feb 22, 2021, 03:30 PM
1-- This is for exploits, not for scripts in your game, and this is ss executor for a exploit, is like: Synapse x + Krnl/Sk8r/Mommy
2
3-- Instances: --
4
5local Executer = Instance.new("ScreenGui")
6local Frame = Instance.new("Frame")
7local source = Instance.new("TextBox")
8local Clear = Instance.new("TextButton")
9local TextLabel = Instance.new("TextLabel")
10local Execute = Instance.new("TextButton")
11local Close = Instance.new("TextButton")
12local Open = Instance.new("TextButton")
13
14--Properties:
15
16Executer.Name = "Executer"
17Executer.Parent = game.CoreGui
18
19Frame.Parent = Executer
20Frame.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
21Frame.BorderColor3 = Color3.fromRGB(56, 56, 56)
22Frame.Position = UDim2.new(0.254995227, 0, 0.216318831, 0)
23Frame.Size = UDim2.new(0, 243, 0, 165)
24Frame.Visible = true
25
26source.Name = "source"
27source.Parent = Frame
28source.BackgroundColor3 = Color3.fromRGB(113, 113, 113)
29source.Position = UDim2.new(0.0521642119, 0, 0.19400838, 0)
30source.Size = UDim2.new(0, 215, 0, 76)
31source.Font = Enum.Font.Code
32source.PlaceholderColor3 = Color3.fromRGB(255, 255, 255)
33source.PlaceholderText = "Put ur script here"
34source.Text = ""
35source.TextColor3 = Color3.fromRGB(0, 0, 0)
36source.TextSize = 14.000
37source.TextWrapped = true
38source.TextYAlignment = Enum.TextYAlignment.Top
39source.Visible = true
40
41Clear.Name = "Clear"
42Clear.Parent = Frame
43Clear.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
44Clear.BorderColor3 = Color3.fromRGB(56, 56, 56)
45Clear.Position = UDim2.new(0.739106536, 0, 0.687631488, 0)
46Clear.Size = UDim2.new(0, 55, 0, 50)
47Clear.Font = Enum.Font.SourceSans
48Clear.Text = "Clear"
49Clear.TextColor3 = Color3.fromRGB(255, 255, 255)
50Clear.TextScaled = true
51Clear.TextSize = 14.000
52Clear.TextStrokeColor3 = Color3.fromRGB(255, 255, 255)
53Clear.TextWrapped = true
54Clear.Visible = true
55
56TextLabel.Parent = Frame
57TextLabel.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
58TextLabel.BackgroundTransparency = 1.000
59TextLabel.Position = UDim2.new(0.04265403, 0, 0.00459372764, 0)
60TextLabel.Size = UDim2.new(0, 179, 0, 37)
61TextLabel.Font = Enum.Font.SourceSans
62TextLabel.Text = "DylanVN23's executer"
63TextLabel.TextColor3 = Color3.fromRGB(0, 0, 0)
64TextLabel.TextScaled = true
65TextLabel.TextSize = 14.000
66TextLabel.TextWrapped = true
67TextLabel.Visible = true
68
69Execute.Name = "Execute"
70Execute.Parent = Frame
71Execute.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
72Execute.BorderColor3 = Color3.fromRGB(56, 56, 56)
73Execute.Position = UDim2.new(-0.000230073929, 0, 0.693692088, 0)
74Execute.Size = UDim2.new(0, 53, 0, 50)
75Execute.Font = Enum.Font.SourceSans
76Execute.Text = "Execute"
77Execute.TextColor3 = Color3.fromRGB(255, 255, 255)
78Execute.TextScaled = true
79Execute.TextSize = 14.000
80Execute.TextWrapped = true
81Execute.Visible = true
82
83Close.Name = "Close"
84Close.Parent = Frame
85Close.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
86Close.Position = UDim2.new(0.88625592, 0, 0.00459372764, 0)
87Close.Size = UDim2.new(0, 23, 0, 23)
88Close.Font = Enum.Font.SourceSansBold
89Close.Text = "X"
90Close.TextColor3 = Color3.fromRGB(0, 0, 0)
91Close.TextScaled = true
92Close.TextSize = 14.000
93Close.TextWrapped = true
94Close.Visible = true
95
96Open.Name = "Open"
97Open.Parent = Executer
98Open.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
99Open.BorderColor3 = Color3.fromRGB(56, 56, 56)
100Open.Position = UDim2.new(0.000951474765, 0, 0.246679321, 0)
101Open.Size = UDim2.new(0, 200, 0, 50)
102Open.Font = Enum.Font.SourceSansBold
103Open.Text = "My Executer"
104Open.TextColor3 = Color3.fromRGB(254, 254, 254)
105Open.TextScaled = true
106Open.TextSize = 14.000
107Open.TextWrapped = true
108Open.Visible = true
109
110-- Module Scripts:
111
112local fake_module_scripts = {}
113
114do -- nil.Loadstring
115 local script = Instance.new('ModuleScript', nil)
116 script.Name = "Loadstring"
117 local function module_script()
118 --[[
119 Credit to einsteinK.
120 Credit to Stravant for LBI.
121
122 Credit to the creators of all the other modules used in this.
123
124 Sceleratis was here and decided modify some things.
125
126 einsteinK was here again to fix a bug in LBI for if-statements
127 --]]
128
129 local waitDeps = {
130 'Rerubi';
131 'LuaK';
132 'LuaP';
133 'LuaU';
134 'LuaX';
135 'LuaY';
136 'LuaZ';
137 }
138
139 for i,v in pairs(waitDeps) do script:WaitForChild(v) end
140
141 local luaX = require(script.LuaX)
142 local luaY = require(script.LuaY)
143 local luaZ = require(script.LuaZ)
144 local luaU = require(script.LuaU)
145 local rerubi = require(script.Rerubi)
146
147 luaX:init()
148 local LuaState = {}
149
150 getfenv().script = nil
151
152 return function(str,env)
153 local f,writer,buff,name
154 local env = env or getfenv(2)
155 local name = (env.script and env.script:GetFullName())
156 local ran,error = pcall(function()
157 local zio = luaZ:init(luaZ:make_getS(str), nil)
158 if not zio then return error() end
159 local func = luaY:parser(LuaState, zio, nil, name or "nil")
160 writer, buff = luaU:make_setS()
161 luaU:dump(LuaState, func, writer, buff)
162 f = rerubi(buff.data, env)
163 end)
164
165 if ran then
166 return f,buff.data
167 else
168 return nil,error
169 end
170 end
171 end
172 fake_module_scripts[script] = module_script
173end
174do -- nil.LuaZ
175 local script = Instance.new('ModuleScript', nil)
176 script.Name = "LuaZ"
177 local function module_script()
178 --[[--------------------------------------------------------------------
179
180 lzio.lua
181 Lua buffered streams in Lua
182 This file is part of Yueliang.
183
184 Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
185 The COPYRIGHT file describes the conditions
186 under which this software may be distributed.
187
188 See the ChangeLog for more information.
189
190 ----------------------------------------------------------------------]]
191
192 --[[--------------------------------------------------------------------
193 -- Notes:
194 -- * EOZ is implemented as a string, "EOZ"
195 -- * Format of z structure (ZIO)
196 -- z.n -- bytes still unread
197 -- z.p -- last read position position in buffer
198 -- z.reader -- chunk reader function
199 -- z.data -- additional data
200 -- * Current position, p, is now last read index instead of a pointer
201 --
202 -- Not implemented:
203 -- * luaZ_lookahead: used only in lapi.c:lua_load to detect binary chunk
204 -- * luaZ_read: used only in lundump.c:ezread to read +1 bytes
205 -- * luaZ_openspace: dropped; let Lua handle buffers as strings (used in
206 -- lundump.c:LoadString & lvm.c:luaV_concat)
207 -- * luaZ buffer macros: dropped; buffers are handled as strings
208 -- * lauxlib.c:getF reader implementation has an extraline flag to
209 -- skip over a shbang (#!) line, this is not implemented here
210 --
211 -- Added:
212 -- (both of the following are vaguely adapted from lauxlib.c)
213 -- * luaZ:make_getS: create Reader from a string
214 -- * luaZ:make_getF: create Reader that reads from a file
215 --
216 -- Changed in 5.1.x:
217 -- * Chunkreader renamed to Reader (ditto with Chunkwriter)
218 -- * Zio struct: no more name string, added Lua state for reader
219 -- (however, Yueliang readers do not require a Lua state)
220 ----------------------------------------------------------------------]]
221
222 local luaZ = {}
223
224 ------------------------------------------------------------------------
225 -- * reader() should return a string, or nil if nothing else to parse.
226 -- Additional data can be set only during stream initialization
227 -- * Readers are handled in lauxlib.c, see luaL_load(file|buffer|string)
228 -- * LUAL_BUFFERSIZE=BUFSIZ=512 in make_getF() (located in luaconf.h)
229 -- * Original Reader typedef:
230 -- const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
231 -- * This Lua chunk reader implementation:
232 -- returns string or nil, no arguments to function
233 ------------------------------------------------------------------------
234
235 ------------------------------------------------------------------------
236 -- create a chunk reader from a source string
237 ------------------------------------------------------------------------
238 function luaZ:make_getS(buff)
239 local b = buff
240 return function() -- chunk reader anonymous function here
241 if not b then return nil end
242 local data = b
243 b = nil
244 return data
245 end
246 end
247
248 ------------------------------------------------------------------------
249 -- create a chunk reader from a source file
250 ------------------------------------------------------------------------
251 --[[
252 function luaZ:make_getF(filename)
253 local LUAL_BUFFERSIZE = 512
254 local h = io.open(filename, "r")
255 if not h then return nil end
256 return function() -- chunk reader anonymous function here
257 if not h or io.type(h) == "closed file" then return nil end
258 local buff = h:read(LUAL_BUFFERSIZE)
259 if not buff then h:close(); h = nil end
260 return buff
261 end
262 end
263 --]]
264 ------------------------------------------------------------------------
265 -- creates a zio input stream
266 -- returns the ZIO structure, z
267 ------------------------------------------------------------------------
268 function luaZ:init(reader, data, name)
269 if not reader then return end
270 local z = {}
271 z.reader = reader
272 z.data = data or ""
273 z.name = name
274 -- set up additional data for reading
275 if not data or data == "" then z.n = 0 else z.n = #data end
276 z.p = 0
277 return z
278 end
279
280 ------------------------------------------------------------------------
281 -- fill up input buffer
282 ------------------------------------------------------------------------
283 function luaZ:fill(z)
284 local buff = z.reader()
285 z.data = buff
286 if not buff or buff == "" then return "EOZ" end
287 z.n, z.p = #buff - 1, 1
288 return string.sub(buff, 1, 1)
289 end
290
291 ------------------------------------------------------------------------
292 -- get next character from the input stream
293 -- * local n, p are used to optimize code generation
294 ------------------------------------------------------------------------
295 function luaZ:zgetc(z)
296 local n, p = z.n, z.p + 1
297 if n > 0 then
298 z.n, z.p = n - 1, p
299 return string.sub(z.data, p, p)
300 else
301 return self:fill(z)
302 end
303 end
304
305 return luaZ
306 end
307 fake_module_scripts[script] = module_script
308end
309do -- nil.LuaX
310 local script = Instance.new('ModuleScript', nil)
311 script.Name = "LuaX"
312 local function module_script()
313 --[[--------------------------------------------------------------------
314
315 llex.lua
316 Lua lexical analyzer in Lua
317 This file is part of Yueliang.
318
319 Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
320 The COPYRIGHT file describes the conditions
321 under which this software may be distributed.
322
323 See the ChangeLog for more information.
324
325 ----------------------------------------------------------------------]]
326
327 --[[--------------------------------------------------------------------
328 -- Notes:
329 -- * intended to 'imitate' llex.c code; performance is not a concern
330 -- * tokens are strings; code structure largely retained
331 -- * deleted stuff (compared to llex.c) are noted, comments retained
332 -- * nextc() returns the currently read character to simplify coding
333 -- here; next() in llex.c does not return anything
334 -- * compatibility code is marked with "--#" comments
335 --
336 -- Added:
337 -- * luaX:chunkid (function luaO_chunkid from lobject.c)
338 -- * luaX:str2d (function luaO_str2d from lobject.c)
339 -- * luaX.LUA_QS used in luaX:lexerror (from luaconf.h)
340 -- * luaX.LUA_COMPAT_LSTR in luaX:read_long_string (from luaconf.h)
341 -- * luaX.MAX_INT used in luaX:inclinenumber (from llimits.h)
342 --
343 -- To use the lexer:
344 -- (1) luaX:init() to initialize the lexer
345 -- (2) luaX:setinput() to set the input stream to lex
346 -- (3) call luaX:next() or luaX:luaX:lookahead() to get tokens,
347 -- until "TK_EOS": luaX:next()
348 -- * since EOZ is returned as a string, be careful when regexp testing
349 --
350 -- Not implemented:
351 -- * luaX_newstring: not required by this Lua implementation
352 -- * buffer MAX_SIZET size limit (from llimits.h) test not implemented
353 -- in the interest of performance
354 -- * locale-aware number handling is largely redundant as Lua's
355 -- tonumber() function is already capable of this
356 --
357 -- Changed in 5.1.x:
358 -- * TK_NAME token order moved down
359 -- * string representation for TK_NAME, TK_NUMBER, TK_STRING changed
360 -- * token struct renamed to lower case (LS -> ls)
361 -- * LexState struct: removed nestlevel, added decpoint
362 -- * error message functions have been greatly simplified
363 -- * token2string renamed to luaX_tokens, exposed in llex.h
364 -- * lexer now handles all kinds of newlines, including CRLF
365 -- * shbang first line handling removed from luaX:setinput;
366 -- it is now done in lauxlib.c (luaL_loadfile)
367 -- * next(ls) macro renamed to nextc(ls) due to new luaX_next function
368 -- * EXTRABUFF and MAXNOCHECK removed due to lexer changes
369 -- * checkbuffer(ls, len) macro deleted
370 -- * luaX:read_numeral now has 3 support functions: luaX:trydecpoint,
371 -- luaX:buffreplace and (luaO_str2d from lobject.c) luaX:str2d
372 -- * luaX:read_numeral is now more promiscuous in slurping characters;
373 -- hexadecimal numbers was added, locale-aware decimal points too
374 -- * luaX:skip_sep is new; used by luaX:read_long_string
375 -- * luaX:read_long_string handles new-style long blocks, with some
376 -- optional compatibility code
377 -- * luaX:llex: parts changed to support new-style long blocks
378 -- * luaX:llex: readname functionality has been folded in
379 -- * luaX:llex: removed test for control characters
380 --
381 --------------------------------------------------------------------]]
382
383 local luaZ = require(script.Parent.LuaZ)
384
385 local luaX = {}
386
387 -- FIRST_RESERVED is not required as tokens are manipulated as strings
388 -- TOKEN_LEN deleted; maximum length of a reserved word not needed
389
390 ------------------------------------------------------------------------
391 -- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED
392 ------------------------------------------------------------------------
393
394 -- terminal symbols denoted by reserved words: TK_AND to TK_WHILE
395 -- other terminal symbols: TK_NAME to TK_EOS
396 luaX.RESERVED = [[
397 TK_AND and
398 TK_BREAK break
399 TK_DO do
400 TK_ELSE else
401 TK_ELSEIF elseif
402 TK_END end
403 TK_FALSE false
404 TK_FOR for
405 TK_FUNCTION function
406 TK_IF if
407 TK_IN in
408 TK_LOCAL local
409 TK_NIL nil
410 TK_NOT not
411 TK_OR or
412 TK_REPEAT repeat
413 TK_RETURN return
414 TK_THEN then
415 TK_TRUE true
416 TK_UNTIL until
417 TK_WHILE while
418 TK_CONCAT ..
419 TK_DOTS ...
420 TK_EQ ==
421 TK_GE >=
422 TK_LE <=
423 TK_NE ~=
424 TK_NAME <name>
425 TK_NUMBER <number>
426 TK_STRING <string>
427 TK_EOS <eof>]]
428
429 -- NUM_RESERVED is not required; number of reserved words
430
431 --[[--------------------------------------------------------------------
432 -- Instead of passing seminfo, the Token struct (e.g. ls.t) is passed
433 -- so that lexer functions can use its table element, ls.t.seminfo
434 --
435 -- SemInfo (struct no longer needed, a mixed-type value is used)
436 --
437 -- Token (struct of ls.t and ls.lookahead):
438 -- token -- token symbol
439 -- seminfo -- semantics information
440 --
441 -- LexState (struct of ls; ls is initialized by luaX:setinput):
442 -- current -- current character (charint)
443 -- linenumber -- input line counter
444 -- lastline -- line of last token 'consumed'
445 -- t -- current token (table: struct Token)
446 -- lookahead -- look ahead token (table: struct Token)
447 -- fs -- 'FuncState' is private to the parser
448 -- L -- LuaState
449 -- z -- input stream
450 -- buff -- buffer for tokens
451 -- source -- current source name
452 -- decpoint -- locale decimal point
453 -- nestlevel -- level of nested non-terminals
454 ----------------------------------------------------------------------]]
455
456 -- luaX.tokens (was luaX_tokens) is now a hash; see luaX:init
457
458 luaX.MAXSRC = 80
459 luaX.MAX_INT = 2147483645 -- constants from elsewhere (see above)
460 luaX.LUA_QS = "'%s'"
461 luaX.LUA_COMPAT_LSTR = 1
462 --luaX.MAX_SIZET = 4294967293
463
464 ------------------------------------------------------------------------
465 -- initialize lexer
466 -- * original luaX_init has code to create and register token strings
467 -- * luaX.tokens: TK_* -> token
468 -- * luaX.enums: token -> TK_* (used in luaX:llex)
469 ------------------------------------------------------------------------
470 function luaX:init()
471 local tokens, enums = {}, {}
472 for v in string.gmatch(self.RESERVED, "[^\n]+") do
473 local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)")
474 tokens[tok] = str
475 enums[str] = tok
476 end
477 self.tokens = tokens
478 self.enums = enums
479 end
480
481 ------------------------------------------------------------------------
482 -- returns a suitably-formatted chunk name or id
483 -- * from lobject.c, used in llex.c and ldebug.c
484 -- * the result, out, is returned (was first argument)
485 ------------------------------------------------------------------------
486 function luaX:chunkid(source, bufflen)
487 local out
488 local first = string.sub(source, 1, 1)
489 if first == "=" then
490 out = string.sub(source, 2, bufflen) -- remove first char
491 else -- out = "source", or "...source"
492 if first == "@" then
493 source = string.sub(source, 2) -- skip the '@'
494 bufflen = bufflen - #" '...' "
495 local l = #source
496 out = ""
497 if l > bufflen then
498 source = string.sub(source, 1 + l - bufflen) -- get last part of file name
499 out = out.."..."
500 end
501 out = out..source
502 else -- out = [string "string"]
503 local len = string.find(source, "[\n\r]") -- stop at first newline
504 len = len and (len - 1) or #source
505 bufflen = bufflen - #(" [string \"...\"] ")
506 if len > bufflen then len = bufflen end
507 out = "[string \""
508 if len < #source then -- must truncate?
509 out = out..string.sub(source, 1, len).."..."
510 else
511 out = out..source
512 end
513 out = out.."\"]"
514 end
515 end
516 return out
517 end
518
519 --[[--------------------------------------------------------------------
520 -- Support functions for lexer
521 -- * all lexer errors eventually reaches lexerror:
522 syntaxerror -> lexerror
523 ----------------------------------------------------------------------]]
524
525 ------------------------------------------------------------------------
526 -- look up token and return keyword if found (also called by parser)
527 ------------------------------------------------------------------------
528 function luaX:token2str(ls, token)
529 if string.sub(token, 1, 3) ~= "TK_" then
530 if string.find(token, "%c") then
531 return string.format("char(%d)", string.byte(token))
532 end
533 return token
534 else
535 end
536 return self.tokens[token]
537 end
538
539 ------------------------------------------------------------------------
540 -- throws a lexer error
541 -- * txtToken has been made local to luaX:lexerror
542 -- * can't communicate LUA_ERRSYNTAX, so it is unimplemented
543 ------------------------------------------------------------------------
544 function luaX:lexerror(ls, msg, token)
545 local function txtToken(ls, token)
546 if token == "TK_NAME" or
547 token == "TK_STRING" or
548 token == "TK_NUMBER" then
549 return ls.buff
550 else
551 return self:token2str(ls, token)
552 end
553 end
554 local buff = self:chunkid(ls.source, self.MAXSRC)
555 local msg = string.format("%s:%d: %s", buff, ls.linenumber, msg)
556 if token then
557 msg = string.format("%s near "..self.LUA_QS, msg, txtToken(ls, token))
558 end
559 -- luaD_throw(ls->L, LUA_ERRSYNTAX)
560 error(msg)
561 end
562
563 ------------------------------------------------------------------------
564 -- throws a syntax error (mainly called by parser)
565 -- * ls.t.token has to be set by the function calling luaX:llex
566 -- (see luaX:next and luaX:lookahead elsewhere in this file)
567 ------------------------------------------------------------------------
568 function luaX:syntaxerror(ls, msg)
569 self:lexerror(ls, msg, ls.t.token)
570 end
571
572 ------------------------------------------------------------------------
573 -- move on to next line
574 ------------------------------------------------------------------------
575 function luaX:currIsNewline(ls)
576 return ls.current == "\n" or ls.current == "\r"
577 end
578
579 function luaX:inclinenumber(ls)
580 local old = ls.current
581 -- lua_assert(currIsNewline(ls))
582 self:nextc(ls) -- skip '\n' or '\r'
583 if self:currIsNewline(ls) and ls.current ~= old then
584 self:nextc(ls) -- skip '\n\r' or '\r\n'
585 end
586 ls.linenumber = ls.linenumber + 1
587 if ls.linenumber >= self.MAX_INT then
588 self:syntaxerror(ls, "chunk has too many lines")
589 end
590 end
591
592 ------------------------------------------------------------------------
593 -- initializes an input stream for lexing
594 -- * if ls (the lexer state) is passed as a table, then it is filled in,
595 -- otherwise it has to be retrieved as a return value
596 -- * LUA_MINBUFFER not used; buffer handling not required any more
597 ------------------------------------------------------------------------
598 function luaX:setinput(L, ls, z, source)
599 if not ls then ls = {} end -- create struct
600 if not ls.lookahead then ls.lookahead = {} end
601 if not ls.t then ls.t = {} end
602 ls.decpoint = "."
603 ls.L = L
604 ls.lookahead.token = "TK_EOS" -- no look-ahead token
605 ls.z = z
606 ls.fs = nil
607 ls.linenumber = 1
608 ls.lastline = 1
609 ls.source = source
610 self:nextc(ls) -- read first char
611 end
612
613 --[[--------------------------------------------------------------------
614 -- LEXICAL ANALYZER
615 ----------------------------------------------------------------------]]
616
617 ------------------------------------------------------------------------
618 -- checks if current character read is found in the set 'set'
619 ------------------------------------------------------------------------
620 function luaX:check_next(ls, set)
621 if not string.find(set, ls.current, 1, 1) then
622 return false
623 end
624 self:save_and_next(ls)
625 return true
626 end
627
628 ------------------------------------------------------------------------
629 -- retrieve next token, checking the lookahead buffer if necessary
630 -- * note that the macro next(ls) in llex.c is now luaX:nextc
631 -- * utilized used in lparser.c (various places)
632 ------------------------------------------------------------------------
633 function luaX:next(ls)
634 ls.lastline = ls.linenumber
635 if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token?
636 -- this must be copy-by-value
637 ls.t.seminfo = ls.lookahead.seminfo -- use this one
638 ls.t.token = ls.lookahead.token
639 ls.lookahead.token = "TK_EOS" -- and discharge it
640 else
641 ls.t.token = self:llex(ls, ls.t) -- read next token
642 end
643 end
644
645 ------------------------------------------------------------------------
646 -- fill in the lookahead buffer
647 -- * utilized used in lparser.c:constructor
648 ------------------------------------------------------------------------
649 function luaX:lookahead(ls)
650 -- lua_assert(ls.lookahead.token == "TK_EOS")
651 ls.lookahead.token = self:llex(ls, ls.lookahead)
652 end
653
654 ------------------------------------------------------------------------
655 -- gets the next character and returns it
656 -- * this is the next() macro in llex.c; see notes at the beginning
657 ------------------------------------------------------------------------
658 function luaX:nextc(ls)
659 local c = luaZ:zgetc(ls.z)
660 ls.current = c
661 return c
662 end
663
664 ------------------------------------------------------------------------
665 -- saves the given character into the token buffer
666 -- * buffer handling code removed, not used in this implementation
667 -- * test for maximum token buffer length not used, makes things faster
668 ------------------------------------------------------------------------
669
670 function luaX:save(ls, c)
671 local buff = ls.buff
672 -- if you want to use this, please uncomment luaX.MAX_SIZET further up
673 --if #buff > self.MAX_SIZET then
674 -- self:lexerror(ls, "lexical element too long")
675 --end
676 ls.buff = buff..c
677 end
678
679 ------------------------------------------------------------------------
680 -- save current character into token buffer, grabs next character
681 -- * like luaX:nextc, returns the character read for convenience
682 ------------------------------------------------------------------------
683 function luaX:save_and_next(ls)
684 self:save(ls, ls.current)
685 return self:nextc(ls)
686 end
687
688 ------------------------------------------------------------------------
689 -- LUA_NUMBER
690 -- * luaX:read_numeral is the main lexer function to read a number
691 -- * luaX:str2d, luaX:buffreplace, luaX:trydecpoint are support functions
692 ------------------------------------------------------------------------
693
694 ------------------------------------------------------------------------
695 -- string to number converter (was luaO_str2d from lobject.c)
696 -- * returns the number, nil if fails (originally returns a boolean)
697 -- * conversion function originally lua_str2number(s,p), a macro which
698 -- maps to the strtod() function by default (from luaconf.h)
699 ------------------------------------------------------------------------
700 function luaX:str2d(s)
701 local result = tonumber(s)
702 if result then return result end
703 -- conversion failed
704 if string.lower(string.sub(s, 1, 2)) == "0x" then -- maybe an hexadecimal constant?
705 result = tonumber(s, 16)
706 if result then return result end -- most common case
707 -- Was: invalid trailing characters?
708 -- In C, this function then skips over trailing spaces.
709 -- true is returned if nothing else is found except for spaces.
710 -- If there is still something else, then it returns a false.
711 -- All this is not necessary using Lua's tonumber.
712 end
713 return nil
714 end
715
716 ------------------------------------------------------------------------
717 -- single-character replacement, for locale-aware decimal points
718 ------------------------------------------------------------------------
719 function luaX:buffreplace(ls, from, to)
720 local result, buff = "", ls.buff
721 for p = 1, #buff do
722 local c = string.sub(buff, p, p)
723 if c == from then c = to end
724 result = result..c
725 end
726 ls.buff = result
727 end
728
729 ------------------------------------------------------------------------
730 -- Attempt to convert a number by translating '.' decimal points to
731 -- the decimal point character used by the current locale. This is not
732 -- needed in Yueliang as Lua's tonumber() is already locale-aware.
733 -- Instead, the code is here in case the user implements localeconv().
734 ------------------------------------------------------------------------
735 function luaX:trydecpoint(ls, Token)
736 -- format error: try to update decimal point separator
737 local old = ls.decpoint
738 -- translate the following to Lua if you implement localeconv():
739 -- struct lconv *cv = localeconv();
740 -- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
741 self:buffreplace(ls, old, ls.decpoint) -- try updated decimal separator
742 local seminfo = self:str2d(ls.buff)
743 Token.seminfo = seminfo
744 if not seminfo then
745 -- format error with correct decimal point: no more options
746 self:buffreplace(ls, ls.decpoint, ".") -- undo change (for error message)
747 self:lexerror(ls, "malformed number", "TK_NUMBER")
748 end
749 end
750
751 ------------------------------------------------------------------------
752 -- main number conversion function
753 -- * "^%w$" needed in the scan in order to detect "EOZ"
754 ------------------------------------------------------------------------
755 function luaX:read_numeral(ls, Token)
756 -- lua_assert(string.find(ls.current, "%d"))
757 repeat
758 self:save_and_next(ls)
759 until string.find(ls.current, "%D") and ls.current ~= "."
760 if self:check_next(ls, "Ee") then -- 'E'?
761 self:check_next(ls, "+-") -- optional exponent sign
762 end
763 while string.find(ls.current, "^%w$") or ls.current == "_" do
764 self:save_and_next(ls)
765 end
766 self:buffreplace(ls, ".", ls.decpoint) -- follow locale for decimal point
767 local seminfo = self:str2d(ls.buff)
768 Token.seminfo = seminfo
769 if not seminfo then -- format error?
770 self:trydecpoint(ls, Token) -- try to update decimal point separator
771 end
772 end
773
774 ------------------------------------------------------------------------
775 -- count separators ("=") in a long string delimiter
776 -- * used by luaX:read_long_string
777 ------------------------------------------------------------------------
778 function luaX:skip_sep(ls)
779 local count = 0
780 local s = ls.current
781 -- lua_assert(s == "[" or s == "]")
782 self:save_and_next(ls)
783 while ls.current == "=" do
784 self:save_and_next(ls)
785 count = count + 1
786 end
787 return (ls.current == s) and count or (-count) - 1
788 end
789
790 ------------------------------------------------------------------------
791 -- reads a long string or long comment
792 ------------------------------------------------------------------------
793 function luaX:read_long_string(ls, Token, sep)
794 local cont = 0
795 self:save_and_next(ls) -- skip 2nd '['
796 if self:currIsNewline(ls) then -- string starts with a newline?
797 self:inclinenumber(ls) -- skip it
798 end
799 while true do
800 local c = ls.current
801 if c == "EOZ" then
802 self:lexerror(ls, Token and "unfinished long string" or
803 "unfinished long comment", "TK_EOS")
804 elseif c == "[" then
805 --# compatibility code start
806 if self.LUA_COMPAT_LSTR then
807 if self:skip_sep(ls) == sep then
808 self:save_and_next(ls) -- skip 2nd '['
809 cont = cont + 1
810 --# compatibility code start
811 if self.LUA_COMPAT_LSTR == 1 then
812 if sep == 0 then
813 self:lexerror(ls, "nesting of [[...]] is deprecated", "[")
814 end
815 end
816 --# compatibility code end
817 end
818 end
819 --# compatibility code end
820 elseif c == "]" then
821 if self:skip_sep(ls) == sep then
822 self:save_and_next(ls) -- skip 2nd ']'
823 --# compatibility code start
824 if self.LUA_COMPAT_LSTR and self.LUA_COMPAT_LSTR == 2 then
825 cont = cont - 1
826 if sep == 0 and cont >= 0 then break end
827 end
828 --# compatibility code end
829 break
830 end
831 elseif self:currIsNewline(ls) then
832 self:save(ls, "\n")
833 self:inclinenumber(ls)
834 if not Token then ls.buff = "" end -- avoid wasting space
835 else -- default
836 if Token then
837 self:save_and_next(ls)
838 else
839 self:nextc(ls)
840 end
841 end--if c
842 end--while
843 if Token then
844 local p = 3 + sep
845 Token.seminfo = string.sub(ls.buff, p, -p)
846 end
847 end
848
849 ------------------------------------------------------------------------
850 -- reads a string
851 -- * has been restructured significantly compared to the original C code
852 ------------------------------------------------------------------------
853
854 function luaX:read_string(ls, del, Token)
855 self:save_and_next(ls)
856 while ls.current ~= del do
857 local c = ls.current
858 if c == "EOZ" then
859 self:lexerror(ls, "unfinished string", "TK_EOS")
860 elseif self:currIsNewline(ls) then
861 self:lexerror(ls, "unfinished string", "TK_STRING")
862 elseif c == "\\" then
863 c = self:nextc(ls) -- do not save the '\'
864 if self:currIsNewline(ls) then -- go through
865 self:save(ls, "\n")
866 self:inclinenumber(ls)
867 elseif c ~= "EOZ" then -- will raise an error next loop
868 -- escapes handling greatly simplified here:
869 local i = string.find("abfnrtv", c, 1, 1)
870 if i then
871 self:save(ls, string.sub("\a\b\f\n\r\t\v", i, i))
872 self:nextc(ls)
873 elseif not string.find(c, "%d") then
874 self:save_and_next(ls) -- handles \\, \", \', and \?
875 else -- \xxx
876 c, i = 0, 0
877 repeat
878 c = 10 * c + ls.current
879 self:nextc(ls)
880 i = i + 1
881 until i >= 3 or not string.find(ls.current, "%d")
882 if c > 255 then -- UCHAR_MAX
883 self:lexerror(ls, "escape sequence too large", "TK_STRING")
884 end
885 self:save(ls, string.char(c))
886 end
887 end
888 else
889 self:save_and_next(ls)
890 end--if c
891 end--while
892 self:save_and_next(ls) -- skip delimiter
893 Token.seminfo = string.sub(ls.buff, 2, -2)
894 end
895
896 ------------------------------------------------------------------------
897 -- main lexer function
898 ------------------------------------------------------------------------
899 function luaX:llex(ls, Token)
900 ls.buff = ""
901 while true do
902 local c = ls.current
903 ----------------------------------------------------------------
904 if self:currIsNewline(ls) then
905 self:inclinenumber(ls)
906 ----------------------------------------------------------------
907 elseif c == "-" then
908 c = self:nextc(ls)
909 if c ~= "-" then return "-" end
910 -- else is a comment
911 local sep = -1
912 if self:nextc(ls) == '[' then
913 sep = self:skip_sep(ls)
914 ls.buff = "" -- 'skip_sep' may dirty the buffer
915 end
916 if sep >= 0 then
917 self:read_long_string(ls, nil, sep) -- long comment
918 ls.buff = ""
919 else -- else short comment
920 while not self:currIsNewline(ls) and ls.current ~= "EOZ" do
921 self:nextc(ls)
922 end
923 end
924 ----------------------------------------------------------------
925 elseif c == "[" then
926 local sep = self:skip_sep(ls)
927 if sep >= 0 then
928 self:read_long_string(ls, Token, sep)
929 return "TK_STRING"
930 elseif sep == -1 then
931 return "["
932 else
933 self:lexerror(ls, "invalid long string delimiter", "TK_STRING")
934 end
935 ----------------------------------------------------------------
936 elseif c == "=" then
937 c = self:nextc(ls)
938 if c ~= "=" then return "="
939 else self:nextc(ls); return "TK_EQ" end
940 ----------------------------------------------------------------
941 elseif c == "<" then
942 c = self:nextc(ls)
943 if c ~= "=" then return "<"
944 else self:nextc(ls); return "TK_LE" end
945 ----------------------------------------------------------------
946 elseif c == ">" then
947 c = self:nextc(ls)
948 if c ~= "=" then return ">"
949 else self:nextc(ls); return "TK_GE" end
950 ----------------------------------------------------------------
951 elseif c == "~" then
952 c = self:nextc(ls)
953 if c ~= "=" then return "~"
954 else self:nextc(ls); return "TK_NE" end
955 ----------------------------------------------------------------
956 elseif c == "\"" or c == "'" then
957 self:read_string(ls, c, Token)
958 return "TK_STRING"
959 ----------------------------------------------------------------
960 elseif c == "." then
961 c = self:save_and_next(ls)
962 if self:check_next(ls, ".") then
963 if self:check_next(ls, ".") then
964 return "TK_DOTS" -- ...
965 else return "TK_CONCAT" -- ..
966 end
967 elseif not string.find(c, "%d") then
968 return "."
969 else
970 self:read_numeral(ls, Token)
971 return "TK_NUMBER"
972 end
973 ----------------------------------------------------------------
974 elseif c == "EOZ" then
975 return "TK_EOS"
976 ----------------------------------------------------------------
977 else -- default
978 if string.find(c, "%s") then
979 -- lua_assert(self:currIsNewline(ls))
980 self:nextc(ls)
981 elseif string.find(c, "%d") then
982 self:read_numeral(ls, Token)
983 return "TK_NUMBER"
984 elseif string.find(c, "[_%a]") then
985 -- identifier or reserved word
986 repeat
987 c = self:save_and_next(ls)
988 until c == "EOZ" or not string.find(c, "[_%w]")
989 local ts = ls.buff
990 local tok = self.enums[ts]
991 if tok then return tok end -- reserved word?
992 Token.seminfo = ts
993 return "TK_NAME"
994 else
995 self:nextc(ls)
996 return c -- single-char tokens (+ - / ...)
997 end
998 ----------------------------------------------------------------
999 end--if c
1000 end--while
1001 end
1002
1003 return luaX
1004 end
1005 fake_module_scripts[script] = module_script
1006end
1007do -- nil.LuaY
1008 local script = Instance.new('ModuleScript', nil)
1009 script.Name = "LuaY"
1010 local function module_script()
1011 --[[--------------------------------------------------------------------
1012
1013 lparser.lua
1014 Lua 5 parser in Lua
1015 This file is part of Yueliang.
1016
1017 Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
1018 The COPYRIGHT file describes the conditions
1019 under which this software may be distributed.
1020
1021 See the ChangeLog for more information.
1022
1023 ----------------------------------------------------------------------]]
1024
1025 --[[--------------------------------------------------------------------
1026 -- Notes:
1027 -- * some unused C code that were not converted are kept as comments
1028 -- * LUA_COMPAT_VARARG option changed into a comment block
1029 -- * for value/size specific code added, look for 'NOTE: '
1030 --
1031 -- Not implemented:
1032 -- * luaX_newstring not needed by this Lua implementation
1033 -- * luaG_checkcode() in assert is not currently implemented
1034 --
1035 -- Added:
1036 -- * some constants added from various header files
1037 -- * luaY.LUA_QS used in error_expected, check_match (from luaconf.h)
1038 -- * luaY:LUA_QL needed for error messages (from luaconf.h)
1039 -- * luaY:growvector (from lmem.h) -- skeleton only, limit checking
1040 -- * luaY.SHRT_MAX (from <limits.h>) for registerlocalvar
1041 -- * luaY:newproto (from lfunc.c)
1042 -- * luaY:int2fb (from lobject.c)
1043 -- * NOTE: HASARG_MASK, for implementing a VARARG_HASARG bit operation
1044 -- * NOTE: value-specific code for VARARG_NEEDSARG to replace a bitop
1045 --
1046 -- Changed in 5.1.x:
1047 -- * various code changes are not detailed...
1048 -- * names of constants may have changed, e.g. added a LUAI_ prefix
1049 -- * struct expkind: added VKNUM, VVARARG; VCALL's info changed?
1050 -- * struct expdesc: added nval
1051 -- * struct FuncState: upvalues data type changed to upvaldesc
1052 -- * macro hasmultret is new
1053 -- * function checklimit moved to parser from lexer
1054 -- * functions anchor_token, errorlimit, checknext are new
1055 -- * checknext is new, equivalent to 5.0.x's check, see check too
1056 -- * luaY:next and luaY:lookahead moved to lexer
1057 -- * break keyword no longer skipped in luaY:breakstat
1058 -- * function new_localvarstr replaced by new_localvarliteral
1059 -- * registerlocalvar limits local variables to SHRT_MAX
1060 -- * create_local deleted, new_localvarliteral used instead
1061 -- * constant LUAI_MAXUPVALUES increased to 60
1062 -- * constants MAXPARAMS, LUA_MAXPARSERLEVEL, MAXSTACK removed
1063 -- * function interface changed: singlevaraux, singlevar
1064 -- * enterlevel and leavelevel uses nCcalls to track call depth
1065 -- * added a name argument to main entry function, luaY:parser
1066 -- * function luaY_index changed to yindex
1067 -- * luaY:int2fb()'s table size encoding format has been changed
1068 -- * luaY:log2() no longer needed for table constructors
1069 -- * function code_params deleted, functionality folded in parlist
1070 -- * vararg flags handling (is_vararg) changes; also see VARARG_*
1071 -- * LUA_COMPATUPSYNTAX section for old-style upvalues removed
1072 -- * repeatstat() calls chunk() instead of block()
1073 -- * function interface changed: cond, test_then_block
1074 -- * while statement implementation considerably simplified; MAXEXPWHILE
1075 -- and EXTRAEXP no longer required, no limits to the complexity of a
1076 -- while condition
1077 -- * repeat, forbody statement implementation has major changes,
1078 -- mostly due to new scoping behaviour of local variables
1079 -- * OPR_MULT renamed to OPR_MUL
1080 ----------------------------------------------------------------------]]
1081
1082 --requires luaP, luaX, luaK
1083 local luaY = {}
1084 local luaX = require(script.Parent.LuaX)
1085 local luaK = require(script.Parent.LuaK)(luaY)
1086 local luaP = require(script.Parent.LuaP)
1087
1088 --[[--------------------------------------------------------------------
1089 -- Expression descriptor
1090 -- * expkind changed to string constants; luaY:assignment was the only
1091 -- function to use a relational operator with this enumeration
1092 -- VVOID -- no value
1093 -- VNIL -- no value
1094 -- VTRUE -- no value
1095 -- VFALSE -- no value
1096 -- VK -- info = index of constant in 'k'
1097 -- VKNUM -- nval = numerical value
1098 -- VLOCAL -- info = local register
1099 -- VUPVAL, -- info = index of upvalue in 'upvalues'
1100 -- VGLOBAL -- info = index of table; aux = index of global name in 'k'
1101 -- VINDEXED -- info = table register; aux = index register (or 'k')
1102 -- VJMP -- info = instruction pc
1103 -- VRELOCABLE -- info = instruction pc
1104 -- VNONRELOC -- info = result register
1105 -- VCALL -- info = instruction pc
1106 -- VVARARG -- info = instruction pc
1107 } ----------------------------------------------------------------------]]
1108
1109 --[[--------------------------------------------------------------------
1110 -- * expdesc in Lua 5.1.x has a union u and another struct s; this Lua
1111 -- implementation ignores all instances of u and s usage
1112 -- struct expdesc:
1113 -- k -- (enum: expkind)
1114 -- info, aux -- (int, int)
1115 -- nval -- (lua_Number)
1116 -- t -- patch list of 'exit when true'
1117 -- f -- patch list of 'exit when false'
1118 ----------------------------------------------------------------------]]
1119
1120 --[[--------------------------------------------------------------------
1121 -- struct upvaldesc:
1122 -- k -- (lu_byte)
1123 -- info -- (lu_byte)
1124 ----------------------------------------------------------------------]]
1125
1126 --[[--------------------------------------------------------------------
1127 -- state needed to generate code for a given function
1128 -- struct FuncState:
1129 -- f -- current function header (table: Proto)
1130 -- h -- table to find (and reuse) elements in 'k' (table: Table)
1131 -- prev -- enclosing function (table: FuncState)
1132 -- ls -- lexical state (table: LexState)
1133 -- L -- copy of the Lua state (table: lua_State)
1134 -- bl -- chain of current blocks (table: BlockCnt)
1135 -- pc -- next position to code (equivalent to 'ncode')
1136 -- lasttarget -- 'pc' of last 'jump target'
1137 -- jpc -- list of pending jumps to 'pc'
1138 -- freereg -- first free register
1139 -- nk -- number of elements in 'k'
1140 -- np -- number of elements in 'p'
1141 -- nlocvars -- number of elements in 'locvars'
1142 -- nactvar -- number of active local variables
1143 -- upvalues[LUAI_MAXUPVALUES] -- upvalues (table: upvaldesc)
1144 -- actvar[LUAI_MAXVARS] -- declared-variable stack
1145 ----------------------------------------------------------------------]]
1146
1147 ------------------------------------------------------------------------
1148 -- constants used by parser
1149 -- * picks up duplicate values from luaX if required
1150 ------------------------------------------------------------------------
1151
1152 luaY.LUA_QS = luaX.LUA_QS or "'%s'" -- (from luaconf.h)
1153
1154 luaY.SHRT_MAX = 32767 -- (from <limits.h>)
1155 luaY.LUAI_MAXVARS = 200 -- (luaconf.h)
1156 luaY.LUAI_MAXUPVALUES = 60 -- (luaconf.h)
1157 luaY.MAX_INT = luaX.MAX_INT or 2147483645 -- (from llimits.h)
1158 -- * INT_MAX-2 for 32-bit systems
1159 luaY.LUAI_MAXCCALLS = 200 -- (from luaconf.h)
1160
1161 luaY.VARARG_HASARG = 1 -- (from lobject.h)
1162 -- NOTE: HASARG_MASK is value-specific
1163 luaY.HASARG_MASK = 2 -- this was added for a bitop in parlist()
1164 luaY.VARARG_ISVARARG = 2
1165 -- NOTE: there is some value-specific code that involves VARARG_NEEDSARG
1166 luaY.VARARG_NEEDSARG = 4
1167
1168 luaY.LUA_MULTRET = -1 -- (lua.h)
1169
1170 --[[--------------------------------------------------------------------
1171 -- other functions
1172 ----------------------------------------------------------------------]]
1173
1174 ------------------------------------------------------------------------
1175 -- LUA_QL describes how error messages quote program elements.
1176 -- CHANGE it if you want a different appearance. (from luaconf.h)
1177 ------------------------------------------------------------------------
1178 function luaY:LUA_QL(x)
1179 return "'"..x.."'"
1180 end
1181
1182 ------------------------------------------------------------------------
1183 -- this is a stripped-down luaM_growvector (from lmem.h) which is a
1184 -- macro based on luaM_growaux (in lmem.c); all the following does is
1185 -- reproduce the size limit checking logic of the original function
1186 -- so that error behaviour is identical; all arguments preserved for
1187 -- convenience, even those which are unused
1188 -- * set the t field to nil, since this originally does a sizeof(t)
1189 -- * size (originally a pointer) is never updated, their final values
1190 -- are set by luaY:close_func(), so overall things should still work
1191 ------------------------------------------------------------------------
1192 function luaY:growvector(L, v, nelems, size, t, limit, e)
1193 if nelems >= limit then
1194 error(e) -- was luaG_runerror
1195 end
1196 end
1197
1198 ------------------------------------------------------------------------
1199 -- initialize a new function prototype structure (from lfunc.c)
1200 -- * used only in open_func()
1201 ------------------------------------------------------------------------
1202 function luaY:newproto(L)
1203 local f = {} -- Proto
1204 -- luaC_link(L, obj2gco(f), LUA_TPROTO); /* GC */
1205 f.k = {}
1206 f.sizek = 0
1207 f.p = {}
1208 f.sizep = 0
1209 f.code = {}
1210 f.sizecode = 0
1211 f.sizelineinfo = 0
1212 f.sizeupvalues = 0
1213 f.nups = 0
1214 f.upvalues = {}
1215 f.numparams = 0
1216 f.is_vararg = 0
1217 f.maxstacksize = 0
1218 f.lineinfo = {}
1219 f.sizelocvars = 0
1220 f.locvars = {}
1221 f.lineDefined = 0
1222 f.lastlinedefined = 0
1223 f.source = nil
1224 return f
1225 end
1226
1227 ------------------------------------------------------------------------
1228 -- converts an integer to a "floating point byte", represented as
1229 -- (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
1230 -- eeeee != 0 and (xxx) otherwise.
1231 ------------------------------------------------------------------------
1232 function luaY:int2fb(x)
1233 local e = 0 -- exponent
1234 while x >= 16 do
1235 x = math.floor((x + 1) / 2)
1236 e = e + 1
1237 end
1238 if x < 8 then
1239 return x
1240 else
1241 return ((e + 1) * 8) + (x - 8)
1242 end
1243 end
1244
1245 --[[--------------------------------------------------------------------
1246 -- parser functions
1247 ----------------------------------------------------------------------]]
1248
1249 ------------------------------------------------------------------------
1250 -- true of the kind of expression produces multiple return values
1251 ------------------------------------------------------------------------
1252 function luaY:hasmultret(k)
1253 return k == "VCALL" or k == "VVARARG"
1254 end
1255
1256 ------------------------------------------------------------------------
1257 -- convenience function to access active local i, returns entry
1258 ------------------------------------------------------------------------
1259 function luaY:getlocvar(fs, i)
1260 return fs.f.locvars[ fs.actvar[i] ]
1261 end
1262
1263 ------------------------------------------------------------------------
1264 -- check a limit, string m provided as an error message
1265 ------------------------------------------------------------------------
1266 function luaY:checklimit(fs, v, l, m)
1267 if v > l then self:errorlimit(fs, l, m) end
1268 end
1269
1270 --[[--------------------------------------------------------------------
1271 -- nodes for block list (list of active blocks)
1272 -- struct BlockCnt:
1273 -- previous -- chain (table: BlockCnt)
1274 -- breaklist -- list of jumps out of this loop
1275 -- nactvar -- # active local variables outside the breakable structure
1276 -- upval -- true if some variable in the block is an upvalue (boolean)
1277 -- isbreakable -- true if 'block' is a loop (boolean)
1278 ----------------------------------------------------------------------]]
1279
1280 ------------------------------------------------------------------------
1281 -- prototypes for recursive non-terminal functions
1282 ------------------------------------------------------------------------
1283 -- prototypes deleted; not required in Lua
1284
1285 ------------------------------------------------------------------------
1286 -- reanchor if last token is has a constant string, see close_func()
1287 -- * used only in close_func()
1288 ------------------------------------------------------------------------
1289 function luaY:anchor_token(ls)
1290 if ls.t.token == "TK_NAME" or ls.t.token == "TK_STRING" then
1291 -- not relevant to Lua implementation of parser
1292 -- local ts = ls.t.seminfo
1293 -- luaX_newstring(ls, getstr(ts), ts->tsv.len); /* C */
1294 end
1295 end
1296
1297 ------------------------------------------------------------------------
1298 -- throws a syntax error if token expected is not there
1299 ------------------------------------------------------------------------
1300 function luaY:error_expected(ls, token)
1301 luaX:syntaxerror(ls,
1302 string.format(self.LUA_QS.." expected", luaX:token2str(ls, token)))
1303 end
1304
1305 ------------------------------------------------------------------------
1306 -- prepares error message for display, for limits exceeded
1307 -- * used only in checklimit()
1308 ------------------------------------------------------------------------
1309 function luaY:errorlimit(fs, limit, what)
1310 local msg = (fs.f.linedefined == 0) and
1311 string.format("main function has more than %d %s", limit, what) or
1312 string.format("function at line %d has more than %d %s",
1313 fs.f.linedefined, limit, what)
1314 luaX:lexerror(fs.ls, msg, 0)
1315 end
1316
1317 ------------------------------------------------------------------------
1318 -- tests for a token, returns outcome
1319 -- * return value changed to boolean
1320 ------------------------------------------------------------------------
1321 function luaY:testnext(ls, c)
1322 if ls.t.token == c then
1323 luaX:next(ls)
1324 return true
1325 else
1326 return false
1327 end
1328 end
1329
1330 ------------------------------------------------------------------------
1331 -- check for existence of a token, throws error if not found
1332 ------------------------------------------------------------------------
1333 function luaY:check(ls, c)
1334 if ls.t.token ~= c then
1335 self:error_expected(ls, c)
1336 end
1337 end
1338
1339 ------------------------------------------------------------------------
1340 -- verify existence of a token, then skip it
1341 ------------------------------------------------------------------------
1342 function luaY:checknext(ls, c)
1343 self:check(ls, c)
1344 luaX:next(ls)
1345 end
1346
1347 ------------------------------------------------------------------------
1348 -- throws error if condition not matched
1349 ------------------------------------------------------------------------
1350 function luaY:check_condition(ls, c, msg)
1351 if not c then luaX:syntaxerror(ls, msg) end
1352 end
1353
1354 ------------------------------------------------------------------------
1355 -- verifies token conditions are met or else throw error
1356 ------------------------------------------------------------------------
1357 function luaY:check_match(ls, what, who, where)
1358 if not self:testnext(ls, what) then
1359 if where == ls.linenumber then
1360 self:error_expected(ls, what)
1361 else
1362 luaX:syntaxerror(ls, string.format(
1363 self.LUA_QS.." expected (to close "..self.LUA_QS.." at line %d)",
1364 luaX:token2str(ls, what), luaX:token2str(ls, who), where))
1365 end
1366 end
1367 end
1368
1369 ------------------------------------------------------------------------
1370 -- expect that token is a name, return the name
1371 ------------------------------------------------------------------------
1372 function luaY:str_checkname(ls)
1373 self:check(ls, "TK_NAME")
1374 local ts = ls.t.seminfo
1375 luaX:next(ls)
1376 return ts
1377 end
1378
1379 ------------------------------------------------------------------------
1380 -- initialize a struct expdesc, expression description data structure
1381 ------------------------------------------------------------------------
1382 function luaY:init_exp(e, k, i)
1383 e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP
1384 e.k = k
1385 e.info = i
1386 end
1387
1388 ------------------------------------------------------------------------
1389 -- adds given string s in string pool, sets e as VK
1390 ------------------------------------------------------------------------
1391 function luaY:codestring(ls, e, s)
1392 self:init_exp(e, "VK", luaK:stringK(ls.fs, s))
1393 end
1394
1395 ------------------------------------------------------------------------
1396 -- consume a name token, adds it to string pool, sets e as VK
1397 ------------------------------------------------------------------------
1398 function luaY:checkname(ls, e)
1399 self:codestring(ls, e, self:str_checkname(ls))
1400 end
1401
1402 ------------------------------------------------------------------------
1403 -- creates struct entry for a local variable
1404 -- * used only in new_localvar()
1405 ------------------------------------------------------------------------
1406 function luaY:registerlocalvar(ls, varname)
1407 local fs = ls.fs
1408 local f = fs.f
1409 self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars,
1410 nil, self.SHRT_MAX, "too many local variables")
1411 -- loop to initialize empty f.locvar positions not required
1412 f.locvars[fs.nlocvars] = {} -- LocVar
1413 f.locvars[fs.nlocvars].varname = varname
1414 -- luaC_objbarrier(ls.L, f, varname) /* GC */
1415 local nlocvars = fs.nlocvars
1416 fs.nlocvars = fs.nlocvars + 1
1417 return nlocvars
1418 end
1419
1420 ------------------------------------------------------------------------
1421 -- creates a new local variable given a name and an offset from nactvar
1422 -- * used in fornum(), forlist(), parlist(), body()
1423 ------------------------------------------------------------------------
1424 function luaY:new_localvarliteral(ls, v, n)
1425 self:new_localvar(ls, v, n)
1426 end
1427
1428 ------------------------------------------------------------------------
1429 -- register a local variable, set in active variable list
1430 ------------------------------------------------------------------------
1431 function luaY:new_localvar(ls, name, n)
1432 local fs = ls.fs
1433 self:checklimit(fs, fs.nactvar + n + 1, self.LUAI_MAXVARS, "local variables")
1434 fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name)
1435 end
1436
1437 ------------------------------------------------------------------------
1438 -- adds nvars number of new local variables, set debug information
1439 ------------------------------------------------------------------------
1440 function luaY:adjustlocalvars(ls, nvars)
1441 local fs = ls.fs
1442 fs.nactvar = fs.nactvar + nvars
1443 for i = nvars, 1, -1 do
1444 self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc
1445 end
1446 end
1447
1448 ------------------------------------------------------------------------
1449 -- removes a number of locals, set debug information
1450 ------------------------------------------------------------------------
1451 function luaY:removevars(ls, tolevel)
1452 local fs = ls.fs
1453 while fs.nactvar > tolevel do
1454 fs.nactvar = fs.nactvar - 1
1455 self:getlocvar(fs, fs.nactvar).endpc = fs.pc
1456 end
1457 end
1458
1459 ------------------------------------------------------------------------
1460 -- returns an existing upvalue index based on the given name, or
1461 -- creates a new upvalue struct entry and returns the new index
1462 -- * used only in singlevaraux()
1463 ------------------------------------------------------------------------
1464 function luaY:indexupvalue(fs, name, v)
1465 local f = fs.f
1466 for i = 0, f.nups - 1 do
1467 if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
1468 assert(f.upvalues[i] == name)
1469 return i
1470 end
1471 end
1472 -- new one
1473 self:checklimit(fs, f.nups + 1, self.LUAI_MAXUPVALUES, "upvalues")
1474 self:growvector(fs.L, f.upvalues, f.nups, f.sizeupvalues,
1475 nil, self.MAX_INT, "")
1476 -- loop to initialize empty f.upvalues positions not required
1477 f.upvalues[f.nups] = name
1478 -- luaC_objbarrier(fs->L, f, name); /* GC */
1479 assert(v.k == "VLOCAL" or v.k == "VUPVAL")
1480 -- this is a partial copy; only k & info fields used
1481 fs.upvalues[f.nups] = { k = v.k, info = v.info }
1482 local nups = f.nups
1483 f.nups = f.nups + 1
1484 return nups
1485 end
1486
1487 ------------------------------------------------------------------------
1488 -- search the local variable namespace of the given fs for a match
1489 -- * used only in singlevaraux()
1490 ------------------------------------------------------------------------
1491 function luaY:searchvar(fs, n)
1492 for i = fs.nactvar - 1, 0, -1 do
1493 if n == self:getlocvar(fs, i).varname then
1494 return i
1495 end
1496 end
1497 return -1 -- not found
1498 end
1499
1500 ------------------------------------------------------------------------
1501 -- * mark upvalue flags in function states up to a given level
1502 -- * used only in singlevaraux()
1503 ------------------------------------------------------------------------
1504 function luaY:markupval(fs, level)
1505 local bl = fs.bl
1506 while bl and bl.nactvar > level do bl = bl.previous end
1507 if bl then bl.upval = true end
1508 end
1509
1510 ------------------------------------------------------------------------
1511 -- handle locals, globals and upvalues and related processing
1512 -- * search mechanism is recursive, calls itself to search parents
1513 -- * used only in singlevar()
1514 ------------------------------------------------------------------------
1515 function luaY:singlevaraux(fs, n, var, base)
1516 if fs == nil then -- no more levels?
1517 self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
1518 return "VGLOBAL"
1519 else
1520 local v = self:searchvar(fs, n) -- look up at current level
1521 if v >= 0 then
1522 self:init_exp(var, "VLOCAL", v)
1523 if base == 0 then
1524 self:markupval(fs, v) -- local will be used as an upval
1525 end
1526 return "VLOCAL"
1527 else -- not found at current level; try upper one
1528 if self:singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then
1529 return "VGLOBAL"
1530 end
1531 var.info = self:indexupvalue(fs, n, var) -- else was LOCAL or UPVAL
1532 var.k = "VUPVAL" -- upvalue in this level
1533 return "VUPVAL"
1534 end--if v
1535 end--if fs
1536 end
1537
1538 ------------------------------------------------------------------------
1539 -- consume a name token, creates a variable (global|local|upvalue)
1540 -- * used in prefixexp(), funcname()
1541 ------------------------------------------------------------------------
1542 function luaY:singlevar(ls, var)
1543 local varname = self:str_checkname(ls)
1544 local fs = ls.fs
1545 if self:singlevaraux(fs, varname, var, 1) == "VGLOBAL" then
1546 var.info = luaK:stringK(fs, varname) -- info points to global name
1547 end
1548 end
1549
1550 ------------------------------------------------------------------------
1551 -- adjust RHS to match LHS in an assignment
1552 -- * used in assignment(), forlist(), localstat()
1553 ------------------------------------------------------------------------
1554 function luaY:adjust_assign(ls, nvars, nexps, e)
1555 local fs = ls.fs
1556 local extra = nvars - nexps
1557 if self:hasmultret(e.k) then
1558 extra = extra + 1 -- includes call itself
1559 if extra <= 0 then extra = 0 end
1560 luaK:setreturns(fs, e, extra) -- last exp. provides the difference
1561 if extra > 1 then luaK:reserveregs(fs, extra - 1) end
1562 else
1563 if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression
1564 if extra > 0 then
1565 local reg = fs.freereg
1566 luaK:reserveregs(fs, extra)
1567 luaK:_nil(fs, reg, extra)
1568 end
1569 end
1570 end
1571
1572 ------------------------------------------------------------------------
1573 -- tracks and limits parsing depth, assert check at end of parsing
1574 ------------------------------------------------------------------------
1575 function luaY:enterlevel(ls)
1576 ls.L.nCcalls = ls.L.nCcalls + 1
1577 if ls.L.nCcalls > self.LUAI_MAXCCALLS then
1578 luaX:lexerror(ls, "chunk has too many syntax levels", 0)
1579 end
1580 end
1581
1582 ------------------------------------------------------------------------
1583 -- tracks parsing depth, a pair with luaY:enterlevel()
1584 ------------------------------------------------------------------------
1585 function luaY:leavelevel(ls)
1586 ls.L.nCcalls = ls.L.nCcalls - 1
1587 end
1588
1589 ------------------------------------------------------------------------
1590 -- enters a code unit, initializes elements
1591 ------------------------------------------------------------------------
1592 function luaY:enterblock(fs, bl, isbreakable)
1593 bl.breaklist = luaK.NO_JUMP
1594 bl.isbreakable = isbreakable
1595 bl.nactvar = fs.nactvar
1596 bl.upval = false
1597 bl.previous = fs.bl
1598 fs.bl = bl
1599 assert(fs.freereg == fs.nactvar)
1600 end
1601
1602 ------------------------------------------------------------------------
1603 -- leaves a code unit, close any upvalues
1604 ------------------------------------------------------------------------
1605 function luaY:leaveblock(fs)
1606 local bl = fs.bl
1607 fs.bl = bl.previous
1608 self:removevars(fs.ls, bl.nactvar)
1609 if bl.upval then
1610 luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
1611 end
1612 -- a block either controls scope or breaks (never both)
1613 assert(not bl.isbreakable or not bl.upval)
1614 assert(bl.nactvar == fs.nactvar)
1615 fs.freereg = fs.nactvar -- free registers
1616 luaK:patchtohere(fs, bl.breaklist)
1617 end
1618
1619 ------------------------------------------------------------------------
1620 -- implement the instantiation of a function prototype, append list of
1621 -- upvalues after the instantiation instruction
1622 -- * used only in body()
1623 ------------------------------------------------------------------------
1624 function luaY:pushclosure(ls, func, v)
1625 local fs = ls.fs
1626 local f = fs.f
1627 self:growvector(ls.L, f.p, fs.np, f.sizep, nil,
1628 luaP.MAXARG_Bx, "constant table overflow")
1629 -- loop to initialize empty f.p positions not required
1630 f.p[fs.np] = func.f
1631 fs.np = fs.np + 1
1632 -- luaC_objbarrier(ls->L, f, func->f); /* C */
1633 self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1))
1634 for i = 0, func.f.nups - 1 do
1635 local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
1636 luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0)
1637 end
1638 end
1639
1640 ------------------------------------------------------------------------
1641 -- opening of a function
1642 ------------------------------------------------------------------------
1643 function luaY:open_func(ls, fs)
1644 local L = ls.L
1645 local f = self:newproto(ls.L)
1646 fs.f = f
1647 fs.prev = ls.fs -- linked list of funcstates
1648 fs.ls = ls
1649 fs.L = L
1650 ls.fs = fs
1651 fs.pc = 0
1652 fs.lasttarget = -1
1653 fs.jpc = luaK.NO_JUMP
1654 fs.freereg = 0
1655 fs.nk = 0
1656 fs.np = 0
1657 fs.nlocvars = 0
1658 fs.nactvar = 0
1659 fs.bl = nil
1660 f.source = ls.source
1661 f.maxstacksize = 2 -- registers 0/1 are always valid
1662 fs.h = {} -- constant table; was luaH_new call
1663 -- anchor table of constants and prototype (to avoid being collected)
1664 -- sethvalue2s(L, L->top, fs->h); incr_top(L); /* C */
1665 -- setptvalue2s(L, L->top, f); incr_top(L);
1666 end
1667
1668 ------------------------------------------------------------------------
1669 -- closing of a function
1670 ------------------------------------------------------------------------
1671 function luaY:close_func(ls)
1672 local L = ls.L
1673 local fs = ls.fs
1674 local f = fs.f
1675 self:removevars(ls, 0)
1676 luaK:ret(fs, 0, 0) -- final return
1677 -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p,
1678 -- f->locvars, f->upvalues; not required for Lua table arrays
1679 f.sizecode = fs.pc
1680 f.sizelineinfo = fs.pc
1681 f.sizek = fs.nk
1682 f.sizep = fs.np
1683 f.sizelocvars = fs.nlocvars
1684 f.sizeupvalues = f.nups
1685 --assert(luaG_checkcode(f)) -- currently not implemented
1686 assert(fs.bl == nil)
1687 ls.fs = fs.prev
1688 -- the following is not required for this implementation; kept here
1689 -- for completeness
1690 -- L->top -= 2; /* remove table and prototype from the stack */
1691 -- last token read was anchored in defunct function; must reanchor it
1692 if fs then self:anchor_token(ls) end
1693 end
1694
1695 ------------------------------------------------------------------------
1696 -- parser initialization function
1697 -- * note additional sub-tables needed for LexState, FuncState
1698 ------------------------------------------------------------------------
1699 function luaY:parser(L, z, buff, name)
1700 local lexstate = {} -- LexState
1701 lexstate.t = {}
1702 lexstate.lookahead = {}
1703 local funcstate = {} -- FuncState
1704 funcstate.upvalues = {}
1705 funcstate.actvar = {}
1706 -- the following nCcalls initialization added for convenience
1707 L.nCcalls = 0
1708 lexstate.buff = buff
1709 luaX:setinput(L, lexstate, z, name)
1710 self:open_func(lexstate, funcstate)
1711 funcstate.f.is_vararg = self.VARARG_ISVARARG -- main func. is always vararg
1712 luaX:next(lexstate) -- read first token
1713 self:chunk(lexstate)
1714 self:check(lexstate, "TK_EOS")
1715 self:close_func(lexstate)
1716 assert(funcstate.prev == nil)
1717 assert(funcstate.f.nups == 0)
1718 assert(lexstate.fs == nil)
1719 return funcstate.f
1720 end
1721
1722 --[[--------------------------------------------------------------------
1723 -- GRAMMAR RULES
1724 ----------------------------------------------------------------------]]
1725
1726 ------------------------------------------------------------------------
1727 -- parse a function name suffix, for function call specifications
1728 -- * used in primaryexp(), funcname()
1729 ------------------------------------------------------------------------
1730 function luaY:field(ls, v)
1731 -- field -> ['.' | ':'] NAME
1732 local fs = ls.fs
1733 local key = {} -- expdesc
1734 luaK:exp2anyreg(fs, v)
1735 luaX:next(ls) -- skip the dot or colon
1736 self:checkname(ls, key)
1737 luaK:indexed(fs, v, key)
1738 end
1739
1740 ------------------------------------------------------------------------
1741 -- parse a table indexing suffix, for constructors, expressions
1742 -- * used in recfield(), primaryexp()
1743 ------------------------------------------------------------------------
1744 function luaY:yindex(ls, v)
1745 -- index -> '[' expr ']'
1746 luaX:next(ls) -- skip the '['
1747 self:expr(ls, v)
1748 luaK:exp2val(ls.fs, v)
1749 self:checknext(ls, "]")
1750 end
1751
1752 --[[--------------------------------------------------------------------
1753 -- Rules for Constructors
1754 ----------------------------------------------------------------------]]
1755
1756 --[[--------------------------------------------------------------------
1757 -- struct ConsControl:
1758 -- v -- last list item read (table: struct expdesc)
1759 -- t -- table descriptor (table: struct expdesc)
1760 -- nh -- total number of 'record' elements
1761 -- na -- total number of array elements
1762 -- tostore -- number of array elements pending to be stored
1763 ----------------------------------------------------------------------]]
1764
1765 ------------------------------------------------------------------------
1766 -- parse a table record (hash) field
1767 -- * used in constructor()
1768 ------------------------------------------------------------------------
1769 function luaY:recfield(ls, cc)
1770 -- recfield -> (NAME | '['exp1']') = exp1
1771 local fs = ls.fs
1772 local reg = ls.fs.freereg
1773 local key, val = {}, {} -- expdesc
1774 if ls.t.token == "TK_NAME" then
1775 self:checklimit(fs, cc.nh, self.MAX_INT, "items in a constructor")
1776 self:checkname(ls, key)
1777 else -- ls->t.token == '['
1778 self:yindex(ls, key)
1779 end
1780 cc.nh = cc.nh + 1
1781 self:checknext(ls, "=")
1782 local rkkey = luaK:exp2RK(fs, key)
1783 self:expr(ls, val)
1784 luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, rkkey, luaK:exp2RK(fs, val))
1785 fs.freereg = reg -- free registers
1786 end
1787
1788 ------------------------------------------------------------------------
1789 -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH)
1790 -- * used in constructor()
1791 ------------------------------------------------------------------------
1792 function luaY:closelistfield(fs, cc)
1793 if cc.v.k == "VVOID" then return end -- there is no list item
1794 luaK:exp2nextreg(fs, cc.v)
1795 cc.v.k = "VVOID"
1796 if cc.tostore == luaP.LFIELDS_PER_FLUSH then
1797 luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) -- flush
1798 cc.tostore = 0 -- no more items pending
1799 end
1800 end
1801
1802 ------------------------------------------------------------------------
1803 -- emit a set list instruction at the end of parsing list constructor
1804 -- * used in constructor()
1805 ------------------------------------------------------------------------
1806 function luaY:lastlistfield(fs, cc)
1807 if cc.tostore == 0 then return end
1808 if self:hasmultret(cc.v.k) then
1809 luaK:setmultret(fs, cc.v)
1810 luaK:setlist(fs, cc.t.info, cc.na, self.LUA_MULTRET)
1811 cc.na = cc.na - 1 -- do not count last expression (unknown number of elements)
1812 else
1813 if cc.v.k ~= "VVOID" then
1814 luaK:exp2nextreg(fs, cc.v)
1815 end
1816 luaK:setlist(fs, cc.t.info, cc.na, cc.tostore)
1817 end
1818 end
1819
1820 ------------------------------------------------------------------------
1821 -- parse a table list (array) field
1822 -- * used in constructor()
1823 ------------------------------------------------------------------------
1824 function luaY:listfield(ls, cc)
1825 self:expr(ls, cc.v)
1826 self:checklimit(ls.fs, cc.na, self.MAX_INT, "items in a constructor")
1827 cc.na = cc.na + 1
1828 cc.tostore = cc.tostore + 1
1829 end
1830
1831 ------------------------------------------------------------------------
1832 -- parse a table constructor
1833 -- * used in funcargs(), simpleexp()
1834 ------------------------------------------------------------------------
1835 function luaY:constructor(ls, t)
1836 -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}'
1837 -- field -> recfield | listfield
1838 -- fieldsep -> ',' | ';'
1839 local fs = ls.fs
1840 local line = ls.linenumber
1841 local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
1842 local cc = {} -- ConsControl
1843 cc.v = {}
1844 cc.na, cc.nh, cc.tostore = 0, 0, 0
1845 cc.t = t
1846 self:init_exp(t, "VRELOCABLE", pc)
1847 self:init_exp(cc.v, "VVOID", 0) -- no value (yet)
1848 luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc)
1849 self:checknext(ls, "{")
1850 repeat
1851 assert(cc.v.k == "VVOID" or cc.tostore > 0)
1852 if ls.t.token == "}" then break end
1853 self:closelistfield(fs, cc)
1854 local c = ls.t.token
1855
1856 if c == "TK_NAME" then -- may be listfields or recfields
1857 luaX:lookahead(ls)
1858 if ls.lookahead.token ~= "=" then -- expression?
1859 self:listfield(ls, cc)
1860 else
1861 self:recfield(ls, cc)
1862 end
1863 elseif c == "[" then -- constructor_item -> recfield
1864 self:recfield(ls, cc)
1865 else -- constructor_part -> listfield
1866 self:listfield(ls, cc)
1867 end
1868 until not self:testnext(ls, ",") and not self:testnext(ls, ";")
1869 self:check_match(ls, "}", "{", line)
1870 self:lastlistfield(fs, cc)
1871 luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size
1872 luaP:SETARG_C(fs.f.code[pc], self:int2fb(cc.nh)) -- set initial table size
1873 end
1874
1875 -- }======================================================================
1876
1877 ------------------------------------------------------------------------
1878 -- parse the arguments (parameters) of a function declaration
1879 -- * used in body()
1880 ------------------------------------------------------------------------
1881 function luaY:parlist(ls)
1882 -- parlist -> [ param { ',' param } ]
1883 local fs = ls.fs
1884 local f = fs.f
1885 local nparams = 0
1886 f.is_vararg = 0
1887 if ls.t.token ~= ")" then -- is 'parlist' not empty?
1888 repeat
1889 local c = ls.t.token
1890 if c == "TK_NAME" then -- param -> NAME
1891 self:new_localvar(ls, self:str_checkname(ls), nparams)
1892 nparams = nparams + 1
1893 elseif c == "TK_DOTS" then -- param -> `...'
1894 luaX:next(ls)
1895 -- [[
1896 -- #if defined(LUA_COMPAT_VARARG)
1897 -- use `arg' as default name
1898 self:new_localvarliteral(ls, "arg", nparams)
1899 nparams = nparams + 1
1900 f.is_vararg = self.VARARG_HASARG + self.VARARG_NEEDSARG
1901 -- #endif
1902 --]]
1903 f.is_vararg = f.is_vararg + self.VARARG_ISVARARG
1904 else
1905 luaX:syntaxerror(ls, "<name> or "..self:LUA_QL("...").." expected")
1906 end
1907 until f.is_vararg ~= 0 or not self:testnext(ls, ",")
1908 end--if
1909 self:adjustlocalvars(ls, nparams)
1910 -- NOTE: the following works only when HASARG_MASK is 2!
1911 f.numparams = fs.nactvar - (f.is_vararg % self.HASARG_MASK)
1912 luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters
1913 end
1914
1915 ------------------------------------------------------------------------
1916 -- parse function declaration body
1917 -- * used in simpleexp(), localfunc(), funcstat()
1918 ------------------------------------------------------------------------
1919 function luaY:body(ls, e, needself, line)
1920 -- body -> '(' parlist ')' chunk END
1921 local new_fs = {} -- FuncState
1922 new_fs.upvalues = {}
1923 new_fs.actvar = {}
1924 self:open_func(ls, new_fs)
1925 new_fs.f.lineDefined = line
1926 self:checknext(ls, "(")
1927 if needself then
1928 self:new_localvarliteral(ls, "self", 0)
1929 self:adjustlocalvars(ls, 1)
1930 end
1931 self:parlist(ls)
1932 self:checknext(ls, ")")
1933 self:chunk(ls)
1934 new_fs.f.lastlinedefined = ls.linenumber
1935 self:check_match(ls, "TK_END", "TK_FUNCTION", line)
1936 self:close_func(ls)
1937 self:pushclosure(ls, new_fs, e)
1938 end
1939
1940 ------------------------------------------------------------------------
1941 -- parse a list of comma-separated expressions
1942 -- * used is multiple locations
1943 ------------------------------------------------------------------------
1944 function luaY:explist1(ls, v)
1945 -- explist1 -> expr { ',' expr }
1946 local n = 1 -- at least one expression
1947 self:expr(ls, v)
1948 while self:testnext(ls, ",") do
1949 luaK:exp2nextreg(ls.fs, v)
1950 self:expr(ls, v)
1951 n = n + 1
1952 end
1953 return n
1954 end
1955
1956 ------------------------------------------------------------------------
1957 -- parse the parameters of a function call
1958 -- * contrast with parlist(), used in function declarations
1959 -- * used in primaryexp()
1960 ------------------------------------------------------------------------
1961 function luaY:funcargs(ls, f)
1962 local fs = ls.fs
1963 local args = {} -- expdesc
1964 local nparams
1965 local line = ls.linenumber
1966 local c = ls.t.token
1967 if c == "(" then -- funcargs -> '(' [ explist1 ] ')'
1968 if line ~= ls.lastline then
1969 luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)")
1970 end
1971 luaX:next(ls)
1972 if ls.t.token == ")" then -- arg list is empty?
1973 args.k = "VVOID"
1974 else
1975 self:explist1(ls, args)
1976 luaK:setmultret(fs, args)
1977 end
1978 self:check_match(ls, ")", "(", line)
1979 elseif c == "{" then -- funcargs -> constructor
1980 self:constructor(ls, args)
1981 elseif c == "TK_STRING" then -- funcargs -> STRING
1982 self:codestring(ls, args, ls.t.seminfo)
1983 luaX:next(ls) -- must use 'seminfo' before 'next'
1984 else
1985 luaX:syntaxerror(ls, "function arguments expected")
1986 return
1987 end
1988 assert(f.k == "VNONRELOC")
1989 local base = f.info -- base register for call
1990 if self:hasmultret(args.k) then
1991 nparams = self.LUA_MULTRET -- open call
1992 else
1993 if args.k ~= "VVOID" then
1994 luaK:exp2nextreg(fs, args) -- close last argument
1995 end
1996 nparams = fs.freereg - (base + 1)
1997 end
1998 self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
1999 luaK:fixline(fs, line)
2000 fs.freereg = base + 1 -- call remove function and arguments and leaves
2001 -- (unless changed) one result
2002 end
2003
2004 --[[--------------------------------------------------------------------
2005 -- Expression parsing
2006 ----------------------------------------------------------------------]]
2007
2008 ------------------------------------------------------------------------
2009 -- parses an expression in parentheses or a single variable
2010 -- * used in primaryexp()
2011 ------------------------------------------------------------------------
2012 function luaY:prefixexp(ls, v)
2013 -- prefixexp -> NAME | '(' expr ')'
2014 local c = ls.t.token
2015 if c == "(" then
2016 local line = ls.linenumber
2017 luaX:next(ls)
2018 self:expr(ls, v)
2019 self:check_match(ls, ")", "(", line)
2020 luaK:dischargevars(ls.fs, v)
2021 elseif c == "TK_NAME" then
2022 self:singlevar(ls, v)
2023 else
2024 luaX:syntaxerror(ls, "unexpected symbol")
2025 end--if c
2026 return
2027 end
2028
2029 ------------------------------------------------------------------------
2030 -- parses a prefixexp (an expression in parentheses or a single variable)
2031 -- or a function call specification
2032 -- * used in simpleexp(), assignment(), exprstat()
2033 ------------------------------------------------------------------------
2034 function luaY:primaryexp(ls, v)
2035 -- primaryexp ->
2036 -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs }
2037 local fs = ls.fs
2038 self:prefixexp(ls, v)
2039 while true do
2040 local c = ls.t.token
2041 if c == "." then -- field
2042 self:field(ls, v)
2043 elseif c == "[" then -- '[' exp1 ']'
2044 local key = {} -- expdesc
2045 luaK:exp2anyreg(fs, v)
2046 self:yindex(ls, key)
2047 luaK:indexed(fs, v, key)
2048 elseif c == ":" then -- ':' NAME funcargs
2049 local key = {} -- expdesc
2050 luaX:next(ls)
2051 self:checkname(ls, key)
2052 luaK:_self(fs, v, key)
2053 self:funcargs(ls, v)
2054 elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs
2055 luaK:exp2nextreg(fs, v)
2056 self:funcargs(ls, v)
2057 else
2058 return
2059 end--if c
2060 end--while
2061 end
2062
2063 ------------------------------------------------------------------------
2064 -- parses general expression types, constants handled here
2065 -- * used in subexpr()
2066 ------------------------------------------------------------------------
2067 function luaY:simpleexp(ls, v)
2068 -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
2069 -- constructor | FUNCTION body | primaryexp
2070 local c = ls.t.token
2071 if c == "TK_NUMBER" then
2072 self:init_exp(v, "VKNUM", 0)
2073 v.nval = ls.t.seminfo
2074 elseif c == "TK_STRING" then
2075 self:codestring(ls, v, ls.t.seminfo)
2076 elseif c == "TK_NIL" then
2077 self:init_exp(v, "VNIL", 0)
2078 elseif c == "TK_TRUE" then
2079 self:init_exp(v, "VTRUE", 0)
2080 elseif c == "TK_FALSE" then
2081 self:init_exp(v, "VFALSE", 0)
2082 elseif c == "TK_DOTS" then -- vararg
2083 local fs = ls.fs
2084 self:check_condition(ls, fs.f.is_vararg ~= 0,
2085 "cannot use "..self:LUA_QL("...").." outside a vararg function");
2086 -- NOTE: the following substitutes for a bitop, but is value-specific
2087 local is_vararg = fs.f.is_vararg
2088 if is_vararg >= self.VARARG_NEEDSARG then
2089 fs.f.is_vararg = is_vararg - self.VARARG_NEEDSARG -- don't need 'arg'
2090 end
2091 self:init_exp(v, "VVARARG", luaK:codeABC(fs, "OP_VARARG", 0, 1, 0))
2092 elseif c == "{" then -- constructor
2093 self:constructor(ls, v)
2094 return
2095 elseif c == "TK_FUNCTION" then
2096 luaX:next(ls)
2097 self:body(ls, v, false, ls.linenumber)
2098 return
2099 else
2100 self:primaryexp(ls, v)
2101 return
2102 end--if c
2103 luaX:next(ls)
2104 end
2105
2106 ------------------------------------------------------------------------
2107 -- Translates unary operators tokens if found, otherwise returns
2108 -- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr().
2109 -- * used in subexpr()
2110 ------------------------------------------------------------------------
2111 function luaY:getunopr(op)
2112 if op == "TK_NOT" then
2113 return "OPR_NOT"
2114 elseif op == "-" then
2115 return "OPR_MINUS"
2116 elseif op == "#" then
2117 return "OPR_LEN"
2118 else
2119 return "OPR_NOUNOPR"
2120 end
2121 end
2122
2123 ------------------------------------------------------------------------
2124 -- Translates binary operator tokens if found, otherwise returns
2125 -- OPR_NOBINOPR. Code generation uses OPR_* style tokens.
2126 -- * used in subexpr()
2127 ------------------------------------------------------------------------
2128 luaY.getbinopr_table = {
2129 ["+"] = "OPR_ADD",
2130 ["-"] = "OPR_SUB",
2131 ["*"] = "OPR_MUL",
2132 ["/"] = "OPR_DIV",
2133 ["%"] = "OPR_MOD",
2134 ["^"] = "OPR_POW",
2135 ["TK_CONCAT"] = "OPR_CONCAT",
2136 ["TK_NE"] = "OPR_NE",
2137 ["TK_EQ"] = "OPR_EQ",
2138 ["<"] = "OPR_LT",
2139 ["TK_LE"] = "OPR_LE",
2140 [">"] = "OPR_GT",
2141 ["TK_GE"] = "OPR_GE",
2142 ["TK_AND"] = "OPR_AND",
2143 ["TK_OR"] = "OPR_OR",
2144 }
2145 function luaY:getbinopr(op)
2146 local opr = self.getbinopr_table[op]
2147 if opr then return opr else return "OPR_NOBINOPR" end
2148 end
2149
2150 ------------------------------------------------------------------------
2151 -- the following priority table consists of pairs of left/right values
2152 -- for binary operators (was a static const struct); grep for ORDER OPR
2153 -- * the following struct is replaced:
2154 -- static const struct {
2155 -- lu_byte left; /* left priority for each binary operator */
2156 -- lu_byte right; /* right priority */
2157 -- } priority[] = { /* ORDER OPR */
2158 ------------------------------------------------------------------------
2159 luaY.priority = {
2160 {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, -- `+' `-' `/' `%'
2161 {10, 9}, {5, 4}, -- power and concat (right associative)
2162 {3, 3}, {3, 3}, -- equality
2163 {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order
2164 {2, 2}, {1, 1} -- logical (and/or)
2165 }
2166
2167 luaY.UNARY_PRIORITY = 8 -- priority for unary operators
2168
2169 ------------------------------------------------------------------------
2170 -- Parse subexpressions. Includes handling of unary operators and binary
2171 -- operators. A subexpr is given the rhs priority level of the operator
2172 -- immediately left of it, if any (limit is -1 if none,) and if a binop
2173 -- is found, limit is compared with the lhs priority level of the binop
2174 -- in order to determine which executes first.
2175 ------------------------------------------------------------------------
2176
2177 ------------------------------------------------------------------------
2178 -- subexpr -> (simpleexp | unop subexpr) { binop subexpr }
2179 -- where 'binop' is any binary operator with a priority higher than 'limit'
2180 -- * for priority lookups with self.priority[], 1=left and 2=right
2181 -- * recursively called
2182 -- * used in expr()
2183 ------------------------------------------------------------------------
2184 function luaY:subexpr(ls, v, limit)
2185 self:enterlevel(ls)
2186 local uop = self:getunopr(ls.t.token)
2187 if uop ~= "OPR_NOUNOPR" then
2188 luaX:next(ls)
2189 self:subexpr(ls, v, self.UNARY_PRIORITY)
2190 luaK:prefix(ls.fs, uop, v)
2191 else
2192 self:simpleexp(ls, v)
2193 end
2194 -- expand while operators have priorities higher than 'limit'
2195 local op = self:getbinopr(ls.t.token)
2196 while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do
2197 local v2 = {} -- expdesc
2198 luaX:next(ls)
2199 luaK:infix(ls.fs, op, v)
2200 -- read sub-expression with higher priority
2201 local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2])
2202 luaK:posfix(ls.fs, op, v, v2)
2203 op = nextop
2204 end
2205 self:leavelevel(ls)
2206 return op -- return first untreated operator
2207 end
2208
2209 ------------------------------------------------------------------------
2210 -- Expression parsing starts here. Function subexpr is entered with the
2211 -- left operator (which is non-existent) priority of -1, which is lower
2212 -- than all actual operators. Expr information is returned in parm v.
2213 -- * used in multiple locations
2214 ------------------------------------------------------------------------
2215 function luaY:expr(ls, v)
2216 self:subexpr(ls, v, 0)
2217 end
2218
2219 -- }====================================================================
2220
2221 --[[--------------------------------------------------------------------
2222 -- Rules for Statements
2223 ----------------------------------------------------------------------]]
2224
2225 ------------------------------------------------------------------------
2226 -- checks next token, used as a look-ahead
2227 -- * returns boolean instead of 0|1
2228 -- * used in retstat(), chunk()
2229 ------------------------------------------------------------------------
2230 function luaY:block_follow(token)
2231 if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END"
2232 or token == "TK_UNTIL" or token == "TK_EOS" then
2233 return true
2234 else
2235 return false
2236 end
2237 end
2238
2239 ------------------------------------------------------------------------
2240 -- parse a code block or unit
2241 -- * used in multiple functions
2242 ------------------------------------------------------------------------
2243 function luaY:block(ls)
2244 -- block -> chunk
2245 local fs = ls.fs
2246 local bl = {} -- BlockCnt
2247 self:enterblock(fs, bl, false)
2248 self:chunk(ls)
2249 assert(bl.breaklist == luaK.NO_JUMP)
2250 self:leaveblock(fs)
2251 end
2252
2253 ------------------------------------------------------------------------
2254 -- structure to chain all variables in the left-hand side of an
2255 -- assignment
2256 -- struct LHS_assign:
2257 -- prev -- (table: struct LHS_assign)
2258 -- v -- variable (global, local, upvalue, or indexed) (table: expdesc)
2259 ------------------------------------------------------------------------
2260
2261 ------------------------------------------------------------------------
2262 -- check whether, in an assignment to a local variable, the local variable
2263 -- is needed in a previous assignment (to a table). If so, save original
2264 -- local value in a safe place and use this safe copy in the previous
2265 -- assignment.
2266 -- * used in assignment()
2267 ------------------------------------------------------------------------
2268 function luaY:check_conflict(ls, lh, v)
2269 local fs = ls.fs
2270 local extra = fs.freereg -- eventual position to save local variable
2271 local conflict = false
2272 while lh do
2273 if lh.v.k == "VINDEXED" then
2274 if lh.v.info == v.info then -- conflict?
2275 conflict = true
2276 lh.v.info = extra -- previous assignment will use safe copy
2277 end
2278 if lh.v.aux == v.info then -- conflict?
2279 conflict = true
2280 lh.v.aux = extra -- previous assignment will use safe copy
2281 end
2282 end
2283 lh = lh.prev
2284 end
2285 if conflict then
2286 luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
2287 luaK:reserveregs(fs, 1)
2288 end
2289 end
2290
2291 ------------------------------------------------------------------------
2292 -- parse a variable assignment sequence
2293 -- * recursively called
2294 -- * used in exprstat()
2295 ------------------------------------------------------------------------
2296 function luaY:assignment(ls, lh, nvars)
2297 local e = {} -- expdesc
2298 -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED
2299 local c = lh.v.k
2300 self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL"
2301 or c == "VINDEXED", "syntax error")
2302 if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment
2303 local nv = {} -- LHS_assign
2304 nv.v = {}
2305 nv.prev = lh
2306 self:primaryexp(ls, nv.v)
2307 if nv.v.k == "VLOCAL" then
2308 self:check_conflict(ls, lh, nv.v)
2309 end
2310 self:checklimit(ls.fs, nvars, self.LUAI_MAXCCALLS - ls.L.nCcalls,
2311 "variables in assignment")
2312 self:assignment(ls, nv, nvars + 1)
2313 else -- assignment -> '=' explist1
2314 self:checknext(ls, "=")
2315 local nexps = self:explist1(ls, e)
2316 if nexps ~= nvars then
2317 self:adjust_assign(ls, nvars, nexps, e)
2318 if nexps > nvars then
2319 ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values
2320 end
2321 else
2322 luaK:setoneret(ls.fs, e) -- close last expression
2323 luaK:storevar(ls.fs, lh.v, e)
2324 return -- avoid default
2325 end
2326 end
2327 self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment
2328 luaK:storevar(ls.fs, lh.v, e)
2329 end
2330
2331 ------------------------------------------------------------------------
2332 -- parse condition in a repeat statement or an if control structure
2333 -- * used in repeatstat(), test_then_block()
2334 ------------------------------------------------------------------------
2335 function luaY:cond(ls)
2336 -- cond -> exp
2337 local v = {} -- expdesc
2338 self:expr(ls, v) -- read condition
2339 if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
2340 luaK:goiftrue(ls.fs, v)
2341 return v.f
2342 end
2343
2344 ------------------------------------------------------------------------
2345 -- parse a break statement
2346 -- * used in statements()
2347 ------------------------------------------------------------------------
2348 function luaY:breakstat(ls)
2349 -- stat -> BREAK
2350 local fs = ls.fs
2351 local bl = fs.bl
2352 local upval = false
2353 while bl and not bl.isbreakable do
2354 if bl.upval then upval = true end
2355 bl = bl.previous
2356 end
2357 if not bl then
2358 luaX:syntaxerror(ls, "no loop to break")
2359 end
2360 if upval then
2361 luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
2362 end
2363 bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
2364 end
2365
2366 ------------------------------------------------------------------------
2367 -- parse a while-do control structure, body processed by block()
2368 -- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by
2369 -- the function's implementation can be removed
2370 -- * used in statements()
2371 ------------------------------------------------------------------------
2372 function luaY:whilestat(ls, line)
2373 -- whilestat -> WHILE cond DO block END
2374 local fs = ls.fs
2375 local bl = {} -- BlockCnt
2376 luaX:next(ls) -- skip WHILE
2377 local whileinit = luaK:getlabel(fs)
2378 local condexit = self:cond(ls)
2379 self:enterblock(fs, bl, true)
2380 self:checknext(ls, "TK_DO")
2381 self:block(ls)
2382 luaK:patchlist(fs, luaK:jump(fs), whileinit)
2383 self:check_match(ls, "TK_END", "TK_WHILE", line)
2384 self:leaveblock(fs)
2385 luaK:patchtohere(fs, condexit) -- false conditions finish the loop
2386 end
2387
2388 ------------------------------------------------------------------------
2389 -- parse a repeat-until control structure, body parsed by chunk()
2390 -- * used in statements()
2391 ------------------------------------------------------------------------
2392 function luaY:repeatstat(ls, line)
2393 -- repeatstat -> REPEAT block UNTIL cond
2394 local fs = ls.fs
2395 local repeat_init = luaK:getlabel(fs)
2396 local bl1, bl2 = {}, {} -- BlockCnt
2397 self:enterblock(fs, bl1, true) -- loop block
2398 self:enterblock(fs, bl2, false) -- scope block
2399 luaX:next(ls) -- skip REPEAT
2400 self:chunk(ls)
2401 self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line)
2402 local condexit = self:cond(ls) -- read condition (inside scope block)
2403 if not bl2.upval then -- no upvalues?
2404 self:leaveblock(fs) -- finish scope
2405 luaK:patchlist(ls.fs, condexit, repeat_init) -- close the loop
2406 else -- complete semantics when there are upvalues
2407 self:breakstat(ls) -- if condition then break
2408 luaK:patchtohere(ls.fs, condexit) -- else...
2409 self:leaveblock(fs) -- finish scope...
2410 luaK:patchlist(ls.fs, luaK:jump(fs), repeat_init) -- and repeat
2411 end
2412 self:leaveblock(fs) -- finish loop
2413 end
2414
2415 ------------------------------------------------------------------------
2416 -- parse the single expressions needed in numerical for loops
2417 -- * used in fornum()
2418 ------------------------------------------------------------------------
2419 function luaY:exp1(ls)
2420 local e = {} -- expdesc
2421 self:expr(ls, e)
2422 local k = e.k
2423 luaK:exp2nextreg(ls.fs, e)
2424 return k
2425 end
2426
2427 ------------------------------------------------------------------------
2428 -- parse a for loop body for both versions of the for loop
2429 -- * used in fornum(), forlist()
2430 ------------------------------------------------------------------------
2431 function luaY:forbody(ls, base, line, nvars, isnum)
2432 -- forbody -> DO block
2433 local bl = {} -- BlockCnt
2434 local fs = ls.fs
2435 self:adjustlocalvars(ls, 3) -- control variables
2436 self:checknext(ls, "TK_DO")
2437 local prep = isnum and luaK:codeAsBx(fs, "OP_FORPREP", base, luaK.NO_JUMP)
2438 or luaK:jump(fs)
2439 self:enterblock(fs, bl, false) -- scope for declared variables
2440 self:adjustlocalvars(ls, nvars)
2441 luaK:reserveregs(fs, nvars)
2442 self:block(ls)
2443 self:leaveblock(fs) -- end of scope for declared variables
2444 luaK:patchtohere(fs, prep)
2445 local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP)
2446 or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars)
2447 luaK:fixline(fs, line) -- pretend that `OP_FOR' starts the loop
2448 luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep + 1)
2449 end
2450
2451 ------------------------------------------------------------------------
2452 -- parse a numerical for loop, calls forbody()
2453 -- * used in forstat()
2454 ------------------------------------------------------------------------
2455 function luaY:fornum(ls, varname, line)
2456 -- fornum -> NAME = exp1,exp1[,exp1] forbody
2457 local fs = ls.fs
2458 local base = fs.freereg
2459 self:new_localvarliteral(ls, "(for index)", 0)
2460 self:new_localvarliteral(ls, "(for limit)", 1)
2461 self:new_localvarliteral(ls, "(for step)", 2)
2462 self:new_localvar(ls, varname, 3)
2463 self:checknext(ls, '=')
2464 self:exp1(ls) -- initial value
2465 self:checknext(ls, ",")
2466 self:exp1(ls) -- limit
2467 if self:testnext(ls, ",") then
2468 self:exp1(ls) -- optional step
2469 else -- default step = 1
2470 luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
2471 luaK:reserveregs(fs, 1)
2472 end
2473 self:forbody(ls, base, line, 1, true)
2474 end
2475
2476 ------------------------------------------------------------------------
2477 -- parse a generic for loop, calls forbody()
2478 -- * used in forstat()
2479 ------------------------------------------------------------------------
2480 function luaY:forlist(ls, indexname)
2481 -- forlist -> NAME {,NAME} IN explist1 forbody
2482 local fs = ls.fs
2483 local e = {} -- expdesc
2484 local nvars = 0
2485 local base = fs.freereg
2486 -- create control variables
2487 self:new_localvarliteral(ls, "(for generator)", nvars)
2488 nvars = nvars + 1
2489 self:new_localvarliteral(ls, "(for state)", nvars)
2490 nvars = nvars + 1
2491 self:new_localvarliteral(ls, "(for control)", nvars)
2492 nvars = nvars + 1
2493 -- create declared variables
2494 self:new_localvar(ls, indexname, nvars)
2495 nvars = nvars + 1
2496 while self:testnext(ls, ",") do
2497 self:new_localvar(ls, self:str_checkname(ls), nvars)
2498 nvars = nvars + 1
2499 end
2500 self:checknext(ls, "TK_IN")
2501 local line = ls.linenumber
2502 self:adjust_assign(ls, 3, self:explist1(ls, e), e)
2503 luaK:checkstack(fs, 3) -- extra space to call generator
2504 self:forbody(ls, base, line, nvars - 3, false)
2505 end
2506
2507 ------------------------------------------------------------------------
2508 -- initial parsing for a for loop, calls fornum() or forlist()
2509 -- * used in statements()
2510 ------------------------------------------------------------------------
2511 function luaY:forstat(ls, line)
2512 -- forstat -> FOR (fornum | forlist) END
2513 local fs = ls.fs
2514 local bl = {} -- BlockCnt
2515 self:enterblock(fs, bl, true) -- scope for loop and control variables
2516 luaX:next(ls) -- skip `for'
2517 local varname = self:str_checkname(ls) -- first variable name
2518 local c = ls.t.token
2519 if c == "=" then
2520 self:fornum(ls, varname, line)
2521 elseif c == "," or c == "TK_IN" then
2522 self:forlist(ls, varname)
2523 else
2524 luaX:syntaxerror(ls, self:LUA_QL("=").." or "..self:LUA_QL("in").." expected")
2525 end
2526 self:check_match(ls, "TK_END", "TK_FOR", line)
2527 self:leaveblock(fs) -- loop scope (`break' jumps to this point)
2528 end
2529
2530 ------------------------------------------------------------------------
2531 -- parse part of an if control structure, including the condition
2532 -- * used in ifstat()
2533 ------------------------------------------------------------------------
2534 function luaY:test_then_block(ls)
2535 -- test_then_block -> [IF | ELSEIF] cond THEN block
2536 luaX:next(ls) -- skip IF or ELSEIF
2537 local condexit = self:cond(ls)
2538 self:checknext(ls, "TK_THEN")
2539 self:block(ls) -- `then' part
2540 return condexit
2541 end
2542
2543 ------------------------------------------------------------------------
2544 -- parse an if control structure
2545 -- * used in statements()
2546 ------------------------------------------------------------------------
2547 function luaY:ifstat(ls, line)
2548 -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END
2549 local fs = ls.fs
2550 local escapelist = luaK.NO_JUMP
2551 local flist = self:test_then_block(ls) -- IF cond THEN block
2552 while ls.t.token == "TK_ELSEIF" do
2553 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
2554 luaK:patchtohere(fs, flist)
2555 flist = self:test_then_block(ls) -- ELSEIF cond THEN block
2556 end
2557 if ls.t.token == "TK_ELSE" then
2558 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
2559 luaK:patchtohere(fs, flist)
2560 luaX:next(ls) -- skip ELSE (after patch, for correct line info)
2561 self:block(ls) -- 'else' part
2562 else
2563 escapelist = luaK:concat(fs, escapelist, flist)
2564 end
2565 luaK:patchtohere(fs, escapelist)
2566 self:check_match(ls, "TK_END", "TK_IF", line)
2567 end
2568
2569 ------------------------------------------------------------------------
2570 -- parse a local function statement
2571 -- * used in statements()
2572 ------------------------------------------------------------------------
2573 function luaY:localfunc(ls)
2574 local v, b = {}, {} -- expdesc
2575 local fs = ls.fs
2576 self:new_localvar(ls, self:str_checkname(ls), 0)
2577 self:init_exp(v, "VLOCAL", fs.freereg)
2578 luaK:reserveregs(fs, 1)
2579 self:adjustlocalvars(ls, 1)
2580 self:body(ls, b, false, ls.linenumber)
2581 luaK:storevar(fs, v, b)
2582 -- debug information will only see the variable after this point!
2583 self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc
2584 end
2585
2586 ------------------------------------------------------------------------
2587 -- parse a local variable declaration statement
2588 -- * used in statements()
2589 ------------------------------------------------------------------------
2590 function luaY:localstat(ls)
2591 -- stat -> LOCAL NAME {',' NAME} ['=' explist1]
2592 local nvars = 0
2593 local nexps
2594 local e = {} -- expdesc
2595 repeat
2596 self:new_localvar(ls, self:str_checkname(ls), nvars)
2597 nvars = nvars + 1
2598 until not self:testnext(ls, ",")
2599 if self:testnext(ls, "=") then
2600 nexps = self:explist1(ls, e)
2601 else
2602 e.k = "VVOID"
2603 nexps = 0
2604 end
2605 self:adjust_assign(ls, nvars, nexps, e)
2606 self:adjustlocalvars(ls, nvars)
2607 end
2608
2609 ------------------------------------------------------------------------
2610 -- parse a function name specification
2611 -- * used in funcstat()
2612 ------------------------------------------------------------------------
2613 function luaY:funcname(ls, v)
2614 -- funcname -> NAME {field} [':' NAME]
2615 local needself = false
2616 self:singlevar(ls, v)
2617 while ls.t.token == "." do
2618 self:field(ls, v)
2619 end
2620 if ls.t.token == ":" then
2621 needself = true
2622 self:field(ls, v)
2623 end
2624 return needself
2625 end
2626
2627 ------------------------------------------------------------------------
2628 -- parse a function statement
2629 -- * used in statements()
2630 ------------------------------------------------------------------------
2631 function luaY:funcstat(ls, line)
2632 -- funcstat -> FUNCTION funcname body
2633 local v, b = {}, {} -- expdesc
2634 luaX:next(ls) -- skip FUNCTION
2635 local needself = self:funcname(ls, v)
2636 self:body(ls, b, needself, line)
2637 luaK:storevar(ls.fs, v, b)
2638 luaK:fixline(ls.fs, line) -- definition 'happens' in the first line
2639 end
2640
2641 ------------------------------------------------------------------------
2642 -- parse a function call with no returns or an assignment statement
2643 -- * used in statements()
2644 ------------------------------------------------------------------------
2645 function luaY:exprstat(ls)
2646 -- stat -> func | assignment
2647 local fs = ls.fs
2648 local v = {} -- LHS_assign
2649 v.v = {}
2650 self:primaryexp(ls, v.v)
2651 if v.v.k == "VCALL" then -- stat -> func
2652 luaP:SETARG_C(luaK:getcode(fs, v.v), 1) -- call statement uses no results
2653 else -- stat -> assignment
2654 v.prev = nil
2655 self:assignment(ls, v, 1)
2656 end
2657 end
2658
2659 ------------------------------------------------------------------------
2660 -- parse a return statement
2661 -- * used in statements()
2662 ------------------------------------------------------------------------
2663 function luaY:retstat(ls)
2664 -- stat -> RETURN explist
2665 local fs = ls.fs
2666 local e = {} -- expdesc
2667 local first, nret -- registers with returned values
2668 luaX:next(ls) -- skip RETURN
2669 if self:block_follow(ls.t.token) or ls.t.token == ";" then
2670 first, nret = 0, 0 -- return no values
2671 else
2672 nret = self:explist1(ls, e) -- optional return values
2673 if self:hasmultret(e.k) then
2674 luaK:setmultret(fs, e)
2675 if e.k == "VCALL" and nret == 1 then -- tail call?
2676 luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
2677 assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
2678 end
2679 first = fs.nactvar
2680 nret = self.LUA_MULTRET -- return all values
2681 else
2682 if nret == 1 then -- only one single value?
2683 first = luaK:exp2anyreg(fs, e)
2684 else
2685 luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
2686 first = fs.nactvar -- return all 'active' values
2687 assert(nret == fs.freereg - first)
2688 end
2689 end--if
2690 end--if
2691 luaK:ret(fs, first, nret)
2692 end
2693
2694 ------------------------------------------------------------------------
2695 -- initial parsing for statements, calls a lot of functions
2696 -- * returns boolean instead of 0|1
2697 -- * used in chunk()
2698 ------------------------------------------------------------------------
2699 function luaY:statement(ls)
2700 local line = ls.linenumber -- may be needed for error messages
2701 local c = ls.t.token
2702 if c == "TK_IF" then -- stat -> ifstat
2703 self:ifstat(ls, line)
2704 return false
2705 elseif c == "TK_WHILE" then -- stat -> whilestat
2706 self:whilestat(ls, line)
2707 return false
2708 elseif c == "TK_DO" then -- stat -> DO block END
2709 luaX:next(ls) -- skip DO
2710 self:block(ls)
2711 self:check_match(ls, "TK_END", "TK_DO", line)
2712 return false
2713 elseif c == "TK_FOR" then -- stat -> forstat
2714 self:forstat(ls, line)
2715 return false
2716 elseif c == "TK_REPEAT" then -- stat -> repeatstat
2717 self:repeatstat(ls, line)
2718 return false
2719 elseif c == "TK_FUNCTION" then -- stat -> funcstat
2720 self:funcstat(ls, line)
2721 return false
2722 elseif c == "TK_LOCAL" then -- stat -> localstat
2723 luaX:next(ls) -- skip LOCAL
2724 if self:testnext(ls, "TK_FUNCTION") then -- local function?
2725 self:localfunc(ls)
2726 else
2727 self:localstat(ls)
2728 end
2729 return false
2730 elseif c == "TK_RETURN" then -- stat -> retstat
2731 self:retstat(ls)
2732 return true -- must be last statement
2733 elseif c == "TK_BREAK" then -- stat -> breakstat
2734 luaX:next(ls) -- skip BREAK
2735 self:breakstat(ls)
2736 return true -- must be last statement
2737 else
2738 self:exprstat(ls)
2739 return false -- to avoid warnings
2740 end--if c
2741 end
2742
2743 ------------------------------------------------------------------------
2744 -- parse a chunk, which consists of a bunch of statements
2745 -- * used in parser(), body(), block(), repeatstat()
2746 ------------------------------------------------------------------------
2747 function luaY:chunk(ls)
2748 -- chunk -> { stat [';'] }
2749 local islast = false
2750 self:enterlevel(ls)
2751 while not islast and not self:block_follow(ls.t.token) do
2752 islast = self:statement(ls)
2753 self:testnext(ls, ";")
2754 assert(ls.fs.f.maxstacksize >= ls.fs.freereg and
2755 ls.fs.freereg >= ls.fs.nactvar)
2756 ls.fs.freereg = ls.fs.nactvar -- free registers
2757 end
2758 self:leavelevel(ls)
2759 end
2760
2761 -- }======================================================================
2762 return luaY
2763 end
2764 fake_module_scripts[script] = module_script
2765end
2766do -- nil.LuaK
2767 local script = Instance.new('ModuleScript', nil)
2768 script.Name = "LuaK"
2769 local function module_script()
2770 --[[--------------------------------------------------------------------
2771
2772 lcode.lua
2773 Lua 5 code generator in Lua
2774 This file is part of Yueliang.
2775
2776 Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
2777 The COPYRIGHT file describes the conditions
2778 under which this software may be distributed.
2779
2780 See the ChangeLog for more information.
2781
2782 ----------------------------------------------------------------------]]
2783
2784 --[[--------------------------------------------------------------------
2785 -- Notes:
2786 -- * one function manipulate a pointer argument with a simple data type
2787 -- (can't be emulated by a table, ambiguous), now returns that value:
2788 -- luaK:concat(fs, l1, l2)
2789 -- * luaM_growvector uses the faux luaY:growvector, for limit checking
2790 -- * some function parameters changed to boolean, additional code
2791 -- translates boolean back to 1/0 for instruction fields
2792 --
2793 -- Not implemented:
2794 -- * NOTE there is a failed assert in luaK:addk, a porting problem
2795 --
2796 -- Added:
2797 -- * constant MAXSTACK from llimits.h
2798 -- * luaK:ttisnumber(o) (from lobject.h)
2799 -- * luaK:nvalue(o) (from lobject.h)
2800 -- * luaK:setnilvalue(o) (from lobject.h)
2801 -- * luaK:setnvalue(o, x) (from lobject.h)
2802 -- * luaK:setbvalue(o, x) (from lobject.h)
2803 -- * luaK:sethvalue(o, x) (from lobject.h), parameter L deleted
2804 -- * luaK:setsvalue(o, x) (from lobject.h), parameter L deleted
2805 -- * luaK:numadd, luaK:numsub, luaK:nummul, luaK:numdiv, luaK:nummod,
2806 -- luaK:numpow, luaK:numunm, luaK:numisnan (from luaconf.h)
2807 -- * copyexp(e1, e2) added in luaK:posfix to copy expdesc struct
2808 --
2809 -- Changed in 5.1.x:
2810 -- * enum BinOpr has a new entry, OPR_MOD
2811 -- * enum UnOpr has a new entry, OPR_LEN
2812 -- * binopistest, unused in 5.0.x, has been deleted
2813 -- * macro setmultret is new
2814 -- * functions isnumeral, luaK_ret, boolK are new
2815 -- * funcion nilK was named nil_constant in 5.0.x
2816 -- * function interface changed: need_value, patchtestreg, concat
2817 -- * TObject now a TValue
2818 -- * functions luaK_setreturns, luaK_setoneret are new
2819 -- * function luaK:setcallreturns deleted, to be replaced by:
2820 -- luaK:setmultret, luaK:ret, luaK:setreturns, luaK:setoneret
2821 -- * functions constfolding, codearith, codecomp are new
2822 -- * luaK:codebinop has been deleted
2823 -- * function luaK_setlist is new
2824 -- * OPR_MULT renamed to OPR_MUL
2825 ----------------------------------------------------------------------]]
2826
2827 -- requires luaP, luaX, luaY
2828 local luaK = {}
2829 local luaP = require(script.Parent.LuaP)
2830 local luaX = require(script.Parent.LuaX)
2831
2832 ------------------------------------------------------------------------
2833 -- constants used by code generator
2834 ------------------------------------------------------------------------
2835 -- maximum stack for a Lua function
2836 luaK.MAXSTACK = 250 -- (from llimits.h)
2837
2838 --[[--------------------------------------------------------------------
2839 -- other functions
2840 ----------------------------------------------------------------------]]
2841
2842 ------------------------------------------------------------------------
2843 -- emulation of TValue macros (these are from lobject.h)
2844 -- * TValue is a table since lcode passes references around
2845 -- * tt member field removed, using Lua's type() instead
2846 -- * for setsvalue, sethvalue, parameter L (deleted here) in lobject.h
2847 -- is used in an assert for testing, see checkliveness(g,obj)
2848 ------------------------------------------------------------------------
2849 function luaK:ttisnumber(o)
2850 if o then return type(o.value) == "number" else return false end
2851 end
2852 function luaK:nvalue(o) return o.value end
2853 function luaK:setnilvalue(o) o.value = nil end
2854 function luaK:setsvalue(o, x) o.value = x end
2855 luaK.setnvalue = luaK.setsvalue
2856 luaK.sethvalue = luaK.setsvalue
2857 luaK.setbvalue = luaK.setsvalue
2858
2859 ------------------------------------------------------------------------
2860 -- The luai_num* macros define the primitive operations over numbers.
2861 -- * this is not the entire set of primitive operations from luaconf.h
2862 -- * used in luaK:constfolding()
2863 ------------------------------------------------------------------------
2864 function luaK:numadd(a, b) return a + b end
2865 function luaK:numsub(a, b) return a - b end
2866 function luaK:nummul(a, b) return a * b end
2867 function luaK:numdiv(a, b) return a / b end
2868 function luaK:nummod(a, b) return a % b end
2869 -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */
2870 function luaK:numpow(a, b) return a ^ b end
2871 function luaK:numunm(a) return -a end
2872 function luaK:numisnan(a) return not a == a end
2873 -- a NaN cannot equal another NaN
2874
2875 --[[--------------------------------------------------------------------
2876 -- code generator functions
2877 ----------------------------------------------------------------------]]
2878
2879 ------------------------------------------------------------------------
2880 -- Marks the end of a patch list. It is an invalid value both as an absolute
2881 -- address, and as a list link (would link an element to itself).
2882 ------------------------------------------------------------------------
2883 luaK.NO_JUMP = -1
2884
2885 ------------------------------------------------------------------------
2886 -- grep "ORDER OPR" if you change these enums
2887 ------------------------------------------------------------------------
2888 luaK.BinOpr = {
2889 OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5,
2890 OPR_CONCAT = 6,
2891 OPR_NE = 7, OPR_EQ = 8,
2892 OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12,
2893 OPR_AND = 13, OPR_OR = 14,
2894 OPR_NOBINOPR = 15,
2895 }
2896
2897 -- * UnOpr is used by luaK:prefix's op argument, but not directly used
2898 -- because the function receives the symbols as strings, e.g. "OPR_NOT"
2899 luaK.UnOpr = {
2900 OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3
2901 }
2902
2903 ------------------------------------------------------------------------
2904 -- returns the instruction object for given e (expdesc), was a macro
2905 ------------------------------------------------------------------------
2906 function luaK:getcode(fs, e)
2907 return fs.f.code[e.info]
2908 end
2909
2910 ------------------------------------------------------------------------
2911 -- codes an instruction with a signed Bx (sBx) field, was a macro
2912 -- * used in luaK:jump(), (lparser) luaY:forbody()
2913 ------------------------------------------------------------------------
2914 function luaK:codeAsBx(fs, o, A, sBx)
2915 return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
2916 end
2917
2918 ------------------------------------------------------------------------
2919 -- set the expdesc e instruction for multiple returns, was a macro
2920 ------------------------------------------------------------------------
2921 function luaK:setmultret(fs, e)
2922 self:setreturns(fs, e, luaY.LUA_MULTRET)
2923 end
2924
2925 ------------------------------------------------------------------------
2926 -- there is a jump if patch lists are not identical, was a macro
2927 -- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val()
2928 ------------------------------------------------------------------------
2929 function luaK:hasjumps(e)
2930 return e.t ~= e.f
2931 end
2932
2933 ------------------------------------------------------------------------
2934 -- true if the expression is a constant number (for constant folding)
2935 -- * used in constfolding(), infix()
2936 ------------------------------------------------------------------------
2937 function luaK:isnumeral(e)
2938 return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP
2939 end
2940
2941 ------------------------------------------------------------------------
2942 -- codes loading of nil, optimization done if consecutive locations
2943 -- * used in luaK:discharge2reg(), (lparser) luaY:adjust_assign()
2944 ------------------------------------------------------------------------
2945 function luaK:_nil(fs, from, n)
2946 if fs.pc > fs.lasttarget then -- no jumps to current position?
2947 if fs.pc == 0 then -- function start?
2948 if from >= fs.nactvar then
2949 return -- positions are already clean
2950 end
2951 else
2952 local previous = fs.f.code[fs.pc - 1]
2953 if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
2954 local pfrom = luaP:GETARG_A(previous)
2955 local pto = luaP:GETARG_B(previous)
2956 if pfrom <= from and from <= pto + 1 then -- can connect both?
2957 if from + n - 1 > pto then
2958 luaP:SETARG_B(previous, from + n - 1)
2959 end
2960 return
2961 end
2962 end
2963 end
2964 end
2965 self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
2966 end
2967
2968 ------------------------------------------------------------------------
2969 --
2970 -- * used in multiple locations
2971 ------------------------------------------------------------------------
2972 function luaK:jump(fs)
2973 local jpc = fs.jpc -- save list of jumps to here
2974 fs.jpc = self.NO_JUMP
2975 local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
2976 j = self:concat(fs, j, jpc) -- keep them on hold
2977 return j
2978 end
2979
2980 ------------------------------------------------------------------------
2981 -- codes a RETURN instruction
2982 -- * used in luaY:close_func(), luaY:retstat()
2983 ------------------------------------------------------------------------
2984 function luaK:ret(fs, first, nret)
2985 self:codeABC(fs, "OP_RETURN", first, nret + 1, 0)
2986 end
2987
2988 ------------------------------------------------------------------------
2989 --
2990 -- * used in luaK:jumponcond(), luaK:codecomp()
2991 ------------------------------------------------------------------------
2992 function luaK:condjump(fs, op, A, B, C)
2993 self:codeABC(fs, op, A, B, C)
2994 return self:jump(fs)
2995 end
2996
2997 ------------------------------------------------------------------------
2998 --
2999 -- * used in luaK:patchlistaux(), luaK:concat()
3000 ------------------------------------------------------------------------
3001 function luaK:fixjump(fs, pc, dest)
3002 local jmp = fs.f.code[pc]
3003 local offset = dest - (pc + 1)
3004 assert(dest ~= self.NO_JUMP)
3005 if math.abs(offset) > luaP.MAXARG_sBx then
3006 luaX:syntaxerror(fs.ls, "control structure too long")
3007 end
3008 luaP:SETARG_sBx(jmp, offset)
3009 end
3010
3011 ------------------------------------------------------------------------
3012 -- returns current 'pc' and marks it as a jump target (to avoid wrong
3013 -- optimizations with consecutive instructions not in the same basic block).
3014 -- * used in multiple locations
3015 -- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL
3016 ------------------------------------------------------------------------
3017 function luaK:getlabel(fs)
3018 fs.lasttarget = fs.pc
3019 return fs.pc
3020 end
3021
3022 ------------------------------------------------------------------------
3023 --
3024 -- * used in luaK:need_value(), luaK:removevalues(), luaK:patchlistaux(),
3025 -- luaK:concat()
3026 ------------------------------------------------------------------------
3027 function luaK:getjump(fs, pc)
3028 local offset = luaP:GETARG_sBx(fs.f.code[pc])
3029 if offset == self.NO_JUMP then -- point to itself represents end of list
3030 return self.NO_JUMP -- end of list
3031 else
3032 return (pc + 1) + offset -- turn offset into absolute position
3033 end
3034 end
3035
3036 ------------------------------------------------------------------------
3037 --
3038 -- * used in luaK:need_value(), luaK:patchtestreg(), luaK:invertjump()
3039 ------------------------------------------------------------------------
3040 function luaK:getjumpcontrol(fs, pc)
3041 local pi = fs.f.code[pc]
3042 local ppi = fs.f.code[pc - 1]
3043 if pc >= 1 and luaP:testTMode(luaP:GET_OPCODE(ppi)) ~= 0 then
3044 return ppi
3045 else
3046 return pi
3047 end
3048 end
3049
3050 ------------------------------------------------------------------------
3051 -- check whether list has any jump that do not produce a value
3052 -- (or produce an inverted value)
3053 -- * return value changed to boolean
3054 -- * used only in luaK:exp2reg()
3055 ------------------------------------------------------------------------
3056 function luaK:need_value(fs, list)
3057 while list ~= self.NO_JUMP do
3058 local i = self:getjumpcontrol(fs, list)
3059 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then return true end
3060 list = self:getjump(fs, list)
3061 end
3062 return false -- not found
3063 end
3064
3065 ------------------------------------------------------------------------
3066 --
3067 -- * used in luaK:removevalues(), luaK:patchlistaux()
3068 ------------------------------------------------------------------------
3069 function luaK:patchtestreg(fs, node, reg)
3070 local i = self:getjumpcontrol(fs, node)
3071 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
3072 return false -- cannot patch other instructions
3073 end
3074 if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
3075 luaP:SETARG_A(i, reg)
3076 else -- no register to put value or register already has the value
3077 -- due to use of a table as i, i cannot be replaced by another table
3078 -- so the following is required; there is no change to ARG_C
3079 luaP:SET_OPCODE(i, "OP_TEST")
3080 local b = luaP:GETARG_B(i)
3081 luaP:SETARG_A(i, b)
3082 luaP:SETARG_B(i, 0)
3083 -- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); /* C */
3084 end
3085 return true
3086 end
3087
3088 ------------------------------------------------------------------------
3089 --
3090 -- * used only in luaK:codenot()
3091 ------------------------------------------------------------------------
3092 function luaK:removevalues(fs, list)
3093 while list ~= self.NO_JUMP do
3094 self:patchtestreg(fs, list, luaP.NO_REG)
3095 list = self:getjump(fs, list)
3096 end
3097 end
3098
3099 ------------------------------------------------------------------------
3100 --
3101 -- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg()
3102 ------------------------------------------------------------------------
3103 function luaK:patchlistaux(fs, list, vtarget, reg, dtarget)
3104 while list ~= self.NO_JUMP do
3105 local _next = self:getjump(fs, list)
3106 if self:patchtestreg(fs, list, reg) then
3107 self:fixjump(fs, list, vtarget)
3108 else
3109 self:fixjump(fs, list, dtarget) -- jump to default target
3110 end
3111 list = _next
3112 end
3113 end
3114
3115 ------------------------------------------------------------------------
3116 --
3117 -- * used only in luaK:code()
3118 ------------------------------------------------------------------------
3119 function luaK:dischargejpc(fs)
3120 self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
3121 fs.jpc = self.NO_JUMP
3122 end
3123
3124 ------------------------------------------------------------------------
3125 --
3126 -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody()
3127 ------------------------------------------------------------------------
3128 function luaK:patchlist(fs, list, target)
3129 if target == fs.pc then
3130 self:patchtohere(fs, list)
3131 else
3132 assert(target < fs.pc)
3133 self:patchlistaux(fs, list, target, luaP.NO_REG, target)
3134 end
3135 end
3136
3137 ------------------------------------------------------------------------
3138 --
3139 -- * used in multiple locations
3140 ------------------------------------------------------------------------
3141 function luaK:patchtohere(fs, list)
3142 self:getlabel(fs)
3143 fs.jpc = self:concat(fs, fs.jpc, list)
3144 end
3145
3146 ------------------------------------------------------------------------
3147 -- * l1 was a pointer, now l1 is returned and callee assigns the value
3148 -- * used in multiple locations
3149 ------------------------------------------------------------------------
3150 function luaK:concat(fs, l1, l2)
3151 if l2 == self.NO_JUMP then return l1
3152 elseif l1 == self.NO_JUMP then
3153 return l2
3154 else
3155 local list = l1
3156 local _next = self:getjump(fs, list)
3157 while _next ~= self.NO_JUMP do -- find last element
3158 list = _next
3159 _next = self:getjump(fs, list)
3160 end
3161 self:fixjump(fs, list, l2)
3162 end
3163 return l1
3164 end
3165
3166 ------------------------------------------------------------------------
3167 --
3168 -- * used in luaK:reserveregs(), (lparser) luaY:forlist()
3169 ------------------------------------------------------------------------
3170 function luaK:checkstack(fs, n)
3171 local newstack = fs.freereg + n
3172 if newstack > fs.f.maxstacksize then
3173 if newstack >= self.MAXSTACK then
3174 luaX:syntaxerror(fs.ls, "function or expression too complex")
3175 end
3176 fs.f.maxstacksize = newstack
3177 end
3178 end
3179
3180 ------------------------------------------------------------------------
3181 --
3182 -- * used in multiple locations
3183 ------------------------------------------------------------------------
3184 function luaK:reserveregs(fs, n)
3185 self:checkstack(fs, n)
3186 fs.freereg = fs.freereg + n
3187 end
3188
3189 ------------------------------------------------------------------------
3190 --
3191 -- * used in luaK:freeexp(), luaK:dischargevars()
3192 ------------------------------------------------------------------------
3193 function luaK:freereg(fs, reg)
3194 if not luaP:ISK(reg) and reg >= fs.nactvar then
3195 fs.freereg = fs.freereg - 1
3196 assert(reg == fs.freereg)
3197 end
3198 end
3199
3200 ------------------------------------------------------------------------
3201 --
3202 -- * used in multiple locations
3203 ------------------------------------------------------------------------
3204 function luaK:freeexp(fs, e)
3205 if e.k == "VNONRELOC" then
3206 self:freereg(fs, e.info)
3207 end
3208 end
3209
3210 ------------------------------------------------------------------------
3211 -- * TODO NOTE implementation is not 100% correct, since the assert fails
3212 -- * luaH_set, setobj deleted; direct table access used instead
3213 -- * used in luaK:stringK(), luaK:numberK(), luaK:boolK(), luaK:nilK()
3214 ------------------------------------------------------------------------
3215 function luaK:addk(fs, k, v)
3216 local L = fs.L
3217 local idx = fs.h[k.value]
3218 --TValue *idx = luaH_set(L, fs->h, k); /* C */
3219 local f = fs.f
3220 if self:ttisnumber(idx) then
3221 --TODO this assert currently FAILS (last tested for 5.0.2)
3222 --assert(fs.f.k[self:nvalue(idx)] == v)
3223 --assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); /* C */
3224 return self:nvalue(idx)
3225 else -- constant not found; create a new entry
3226 idx = {}
3227 self:setnvalue(idx, fs.nk)
3228 fs.h[k.value] = idx
3229 -- setnvalue(idx, cast_num(fs->nk)); /* C */
3230 luaY:growvector(L, f.k, fs.nk, f.sizek, nil,
3231 luaP.MAXARG_Bx, "constant table overflow")
3232 -- loop to initialize empty f.k positions not required
3233 f.k[fs.nk] = v
3234 -- setobj(L, &f->k[fs->nk], v); /* C */
3235 -- luaC_barrier(L, f, v); /* GC */
3236 local nk = fs.nk
3237 fs.nk = fs.nk + 1
3238 return nk
3239 end
3240
3241 end
3242
3243 ------------------------------------------------------------------------
3244 -- creates and sets a string object
3245 -- * used in (lparser) luaY:codestring(), luaY:singlevar()
3246 ------------------------------------------------------------------------
3247 function luaK:stringK(fs, s)
3248 local o = {} -- TValue
3249 self:setsvalue(o, s)
3250 return self:addk(fs, o, o)
3251 end
3252
3253 ------------------------------------------------------------------------
3254 -- creates and sets a number object
3255 -- * used in luaK:prefix() for negative (or negation of) numbers
3256 -- * used in (lparser) luaY:simpleexp(), luaY:fornum()
3257 ------------------------------------------------------------------------
3258 function luaK:numberK(fs, r)
3259 local o = {} -- TValue
3260 self:setnvalue(o, r)
3261 return self:addk(fs, o, o)
3262 end
3263
3264 ------------------------------------------------------------------------
3265 -- creates and sets a boolean object
3266 -- * used only in luaK:exp2RK()
3267 ------------------------------------------------------------------------
3268 function luaK:boolK(fs, b)
3269 local o = {} -- TValue
3270 self:setbvalue(o, b)
3271 return self:addk(fs, o, o)
3272 end
3273
3274 ------------------------------------------------------------------------
3275 -- creates and sets a nil object
3276 -- * used only in luaK:exp2RK()
3277 ------------------------------------------------------------------------
3278 function luaK:nilK(fs)
3279 local k, v = {}, {} -- TValue
3280 self:setnilvalue(v)
3281 -- cannot use nil as key; instead use table itself to represent nil
3282 self:sethvalue(k, fs.h)
3283 return self:addk(fs, k, v)
3284 end
3285
3286 ------------------------------------------------------------------------
3287 --
3288 -- * used in luaK:setmultret(), (lparser) luaY:adjust_assign()
3289 ------------------------------------------------------------------------
3290 function luaK:setreturns(fs, e, nresults)
3291 if e.k == "VCALL" then -- expression is an open function call?
3292 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
3293 elseif e.k == "VVARARG" then
3294 luaP:SETARG_B(self:getcode(fs, e), nresults + 1);
3295 luaP:SETARG_A(self:getcode(fs, e), fs.freereg);
3296 luaK:reserveregs(fs, 1)
3297 end
3298 end
3299
3300 ------------------------------------------------------------------------
3301 --
3302 -- * used in luaK:dischargevars(), (lparser) luaY:assignment()
3303 ------------------------------------------------------------------------
3304 function luaK:setoneret(fs, e)
3305 if e.k == "VCALL" then -- expression is an open function call?
3306 e.k = "VNONRELOC"
3307 e.info = luaP:GETARG_A(self:getcode(fs, e))
3308 elseif e.k == "VVARARG" then
3309 luaP:SETARG_B(self:getcode(fs, e), 2)
3310 e.k = "VRELOCABLE" -- can relocate its simple result
3311 end
3312 end
3313
3314 ------------------------------------------------------------------------
3315 --
3316 -- * used in multiple locations
3317 ------------------------------------------------------------------------
3318 function luaK:dischargevars(fs, e)
3319 local k = e.k
3320 if k == "VLOCAL" then
3321 e.k = "VNONRELOC"
3322 elseif k == "VUPVAL" then
3323 e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
3324 e.k = "VRELOCABLE"
3325 elseif k == "VGLOBAL" then
3326 e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
3327 e.k = "VRELOCABLE"
3328 elseif k == "VINDEXED" then
3329 self:freereg(fs, e.aux)
3330 self:freereg(fs, e.info)
3331 e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
3332 e.k = "VRELOCABLE"
3333 elseif k == "VVARARG" or k == "VCALL" then
3334 self:setoneret(fs, e)
3335 else
3336 -- there is one value available (somewhere)
3337 end
3338 end
3339
3340 ------------------------------------------------------------------------
3341 --
3342 -- * used only in luaK:exp2reg()
3343 ------------------------------------------------------------------------
3344 function luaK:code_label(fs, A, b, jump)
3345 self:getlabel(fs) -- those instructions may be jump targets
3346 return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
3347 end
3348
3349 ------------------------------------------------------------------------
3350 --
3351 -- * used in luaK:discharge2anyreg(), luaK:exp2reg()
3352 ------------------------------------------------------------------------
3353 function luaK:discharge2reg(fs, e, reg)
3354 self:dischargevars(fs, e)
3355 local k = e.k
3356 if k == "VNIL" then
3357 self:_nil(fs, reg, 1)
3358 elseif k == "VFALSE" or k == "VTRUE" then
3359 self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
3360 elseif k == "VK" then
3361 self:codeABx(fs, "OP_LOADK", reg, e.info)
3362 elseif k == "VKNUM" then
3363 self:codeABx(fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
3364 elseif k == "VRELOCABLE" then
3365 local pc = self:getcode(fs, e)
3366 luaP:SETARG_A(pc, reg)
3367 elseif k == "VNONRELOC" then
3368 if reg ~= e.info then
3369 self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
3370 end
3371 else
3372 assert(e.k == "VVOID" or e.k == "VJMP")
3373 return -- nothing to do...
3374 end
3375 e.info = reg
3376 e.k = "VNONRELOC"
3377 end
3378
3379 ------------------------------------------------------------------------
3380 --
3381 -- * used in luaK:jumponcond(), luaK:codenot()
3382 ------------------------------------------------------------------------
3383 function luaK:discharge2anyreg(fs, e)
3384 if e.k ~= "VNONRELOC" then
3385 self:reserveregs(fs, 1)
3386 self:discharge2reg(fs, e, fs.freereg - 1)
3387 end
3388 end
3389
3390 ------------------------------------------------------------------------
3391 --
3392 -- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar()
3393 ------------------------------------------------------------------------
3394 function luaK:exp2reg(fs, e, reg)
3395 self:discharge2reg(fs, e, reg)
3396 if e.k == "VJMP" then
3397 e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
3398 end
3399 if self:hasjumps(e) then
3400 local final -- position after whole expression
3401 local p_f = self.NO_JUMP -- position of an eventual LOAD false
3402 local p_t = self.NO_JUMP -- position of an eventual LOAD true
3403 if self:need_value(fs, e.t) or self:need_value(fs, e.f) then
3404 local fj = (e.k == "VJMP") and self.NO_JUMP or self:jump(fs)
3405 p_f = self:code_label(fs, reg, 0, 1)
3406 p_t = self:code_label(fs, reg, 1, 0)
3407 self:patchtohere(fs, fj)
3408 end
3409 final = self:getlabel(fs)
3410 self:patchlistaux(fs, e.f, final, reg, p_f)
3411 self:patchlistaux(fs, e.t, final, reg, p_t)
3412 end
3413 e.f, e.t = self.NO_JUMP, self.NO_JUMP
3414 e.info = reg
3415 e.k = "VNONRELOC"
3416 end
3417
3418 ------------------------------------------------------------------------
3419 --
3420 -- * used in multiple locations
3421 ------------------------------------------------------------------------
3422 function luaK:exp2nextreg(fs, e)
3423 self:dischargevars(fs, e)
3424 self:freeexp(fs, e)
3425 self:reserveregs(fs, 1)
3426 self:exp2reg(fs, e, fs.freereg - 1)
3427 end
3428
3429 ------------------------------------------------------------------------
3430 --
3431 -- * used in multiple locations
3432 ------------------------------------------------------------------------
3433 function luaK:exp2anyreg(fs, e)
3434 self:dischargevars(fs, e)
3435 if e.k == "VNONRELOC" then
3436 if not self:hasjumps(e) then -- exp is already in a register
3437 return e.info
3438 end
3439 if e.info >= fs.nactvar then -- reg. is not a local?
3440 self:exp2reg(fs, e, e.info) -- put value on it
3441 return e.info
3442 end
3443 end
3444 self:exp2nextreg(fs, e) -- default
3445 return e.info
3446 end
3447
3448 ------------------------------------------------------------------------
3449 --
3450 -- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix()
3451 -- * used in (lparser) luaY:yindex()
3452 ------------------------------------------------------------------------
3453 function luaK:exp2val(fs, e)
3454 if self:hasjumps(e) then
3455 self:exp2anyreg(fs, e)
3456 else
3457 self:dischargevars(fs, e)
3458 end
3459 end
3460
3461 ------------------------------------------------------------------------
3462 --
3463 -- * used in multiple locations
3464 ------------------------------------------------------------------------
3465 function luaK:exp2RK(fs, e)
3466 self:exp2val(fs, e)
3467 local k = e.k
3468 if k == "VKNUM" or k == "VTRUE" or k == "VFALSE" or k == "VNIL" then
3469 if fs.nk <= luaP.MAXINDEXRK then -- constant fit in RK operand?
3470 -- converted from a 2-deep ternary operator expression
3471 if e.k == "VNIL" then
3472 e.info = self:nilK(fs)
3473 else
3474 e.info = (e.k == "VKNUM") and self:numberK(fs, e.nval)
3475 or self:boolK(fs, e.k == "VTRUE")
3476 end
3477 e.k = "VK"
3478 return luaP:RKASK(e.info)
3479 end
3480 elseif k == "VK" then
3481 if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
3482 return luaP:RKASK(e.info)
3483 end
3484 else
3485 -- default
3486 end
3487 -- not a constant in the right range: put it in a register
3488 return self:exp2anyreg(fs, e)
3489 end
3490
3491 ------------------------------------------------------------------------
3492 --
3493 -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat()
3494 ------------------------------------------------------------------------
3495 function luaK:storevar(fs, var, ex)
3496 local k = var.k
3497 if k == "VLOCAL" then
3498 self:freeexp(fs, ex)
3499 self:exp2reg(fs, ex, var.info)
3500 return
3501 elseif k == "VUPVAL" then
3502 local e = self:exp2anyreg(fs, ex)
3503 self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
3504 elseif k == "VGLOBAL" then
3505 local e = self:exp2anyreg(fs, ex)
3506 self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
3507 elseif k == "VINDEXED" then
3508 local e = self:exp2RK(fs, ex)
3509 self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
3510 else
3511 assert(0) -- invalid var kind to store
3512 end
3513 self:freeexp(fs, ex)
3514 end
3515
3516 ------------------------------------------------------------------------
3517 --
3518 -- * used only in (lparser) luaY:primaryexp()
3519 ------------------------------------------------------------------------
3520 function luaK:_self(fs, e, key)
3521 self:exp2anyreg(fs, e)
3522 self:freeexp(fs, e)
3523 local func = fs.freereg
3524 self:reserveregs(fs, 2)
3525 self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
3526 self:freeexp(fs, key)
3527 e.info = func
3528 e.k = "VNONRELOC"
3529 end
3530
3531 ------------------------------------------------------------------------
3532 --
3533 -- * used in luaK:goiftrue(), luaK:codenot()
3534 ------------------------------------------------------------------------
3535 function luaK:invertjump(fs, e)
3536 local pc = self:getjumpcontrol(fs, e.info)
3537 assert(luaP:testTMode(luaP:GET_OPCODE(pc)) ~= 0 and
3538 luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
3539 luaP:GET_OPCODE(pc) ~= "OP_TEST")
3540 luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
3541 end
3542
3543 ------------------------------------------------------------------------
3544 --
3545 -- * used in luaK:goiftrue(), luaK:goiffalse()
3546 ------------------------------------------------------------------------
3547 function luaK:jumponcond(fs, e, cond)
3548 if e.k == "VRELOCABLE" then
3549 local ie = self:getcode(fs, e)
3550 if luaP:GET_OPCODE(ie) == "OP_NOT" then
3551 fs.pc = fs.pc - 1 -- remove previous OP_NOT
3552 return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0, cond and 0 or 1)
3553 end
3554 -- else go through
3555 end
3556 self:discharge2anyreg(fs, e)
3557 self:freeexp(fs, e)
3558 return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
3559 end
3560
3561 ------------------------------------------------------------------------
3562 --
3563 -- * used in luaK:infix(), (lparser) luaY:cond()
3564 ------------------------------------------------------------------------
3565 function luaK:goiftrue(fs, e)
3566 local pc -- pc of last jump
3567 self:dischargevars(fs, e)
3568 local k = e.k
3569 if k == "VK" or k == "VKNUM" or k == "VTRUE" then
3570 pc = self.NO_JUMP -- always true; do nothing
3571 elseif k == "VFALSE" then
3572 pc = self:jump(fs) -- always jump
3573 elseif k == "VJMP" then
3574 self:invertjump(fs, e)
3575 pc = e.info
3576 else
3577 pc = self:jumponcond(fs, e, false)
3578 end
3579 e.f = self:concat(fs, e.f, pc) -- insert last jump in `f' list
3580 self:patchtohere(fs, e.t)
3581 e.t = self.NO_JUMP
3582 end
3583
3584 ------------------------------------------------------------------------
3585 --
3586 -- * used in luaK:infix()
3587 ------------------------------------------------------------------------
3588 function luaK:goiffalse(fs, e)
3589 local pc -- pc of last jump
3590 self:dischargevars(fs, e)
3591 local k = e.k
3592 if k == "VNIL" or k == "VFALSE"then
3593 pc = self.NO_JUMP -- always false; do nothing
3594 elseif k == "VTRUE" then
3595 pc = self:jump(fs) -- always jump
3596 elseif k == "VJMP" then
3597 pc = e.info
3598 else
3599 pc = self:jumponcond(fs, e, true)
3600 end
3601 e.t = self:concat(fs, e.t, pc) -- insert last jump in `t' list
3602 self:patchtohere(fs, e.f)
3603 e.f = self.NO_JUMP
3604 end
3605
3606 ------------------------------------------------------------------------
3607 --
3608 -- * used only in luaK:prefix()
3609 ------------------------------------------------------------------------
3610 function luaK:codenot(fs, e)
3611 self:dischargevars(fs, e)
3612 local k = e.k
3613 if k == "VNIL" or k == "VFALSE" then
3614 e.k = "VTRUE"
3615 elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
3616 e.k = "VFALSE"
3617 elseif k == "VJMP" then
3618 self:invertjump(fs, e)
3619 elseif k == "VRELOCABLE" or k == "VNONRELOC" then
3620 self:discharge2anyreg(fs, e)
3621 self:freeexp(fs, e)
3622 e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
3623 e.k = "VRELOCABLE"
3624 else
3625 assert(0) -- cannot happen
3626 end
3627 -- interchange true and false lists
3628 e.f, e.t = e.t, e.f
3629 self:removevalues(fs, e.f)
3630 self:removevalues(fs, e.t)
3631 end
3632
3633 ------------------------------------------------------------------------
3634 --
3635 -- * used in (lparser) luaY:field(), luaY:primaryexp()
3636 ------------------------------------------------------------------------
3637 function luaK:indexed(fs, t, k)
3638 t.aux = self:exp2RK(fs, k)
3639 t.k = "VINDEXED"
3640 end
3641
3642 ------------------------------------------------------------------------
3643 --
3644 -- * used only in luaK:codearith()
3645 ------------------------------------------------------------------------
3646 function luaK:constfolding(op, e1, e2)
3647 local r
3648 if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
3649 local v1 = e1.nval
3650 local v2 = e2.nval
3651 if op == "OP_ADD" then
3652 r = self:numadd(v1, v2)
3653 elseif op == "OP_SUB" then
3654 r = self:numsub(v1, v2)
3655 elseif op == "OP_MUL" then
3656 r = self:nummul(v1, v2)
3657 elseif op == "OP_DIV" then
3658 if v2 == 0 then return false end -- do not attempt to divide by 0
3659 r = self:numdiv(v1, v2)
3660 elseif op == "OP_MOD" then
3661 if v2 == 0 then return false end -- do not attempt to divide by 0
3662 r = self:nummod(v1, v2)
3663 elseif op == "OP_POW" then
3664 r = self:numpow(v1, v2)
3665 elseif op == "OP_UNM" then
3666 r = self:numunm(v1)
3667 elseif op == "OP_LEN" then
3668 return false -- no constant folding for 'len'
3669 else
3670 assert(0)
3671 r = 0
3672 end
3673 if self:numisnan(r) then return false end -- do not attempt to produce NaN
3674 e1.nval = r
3675 return true
3676 end
3677
3678 ------------------------------------------------------------------------
3679 --
3680 -- * used in luaK:prefix(), luaK:posfix()
3681 ------------------------------------------------------------------------
3682 function luaK:codearith(fs, op, e1, e2)
3683 if self:constfolding(op, e1, e2) then
3684 return
3685 else
3686 local o2 = (op ~= "OP_UNM" and op ~= "OP_LEN") and self:exp2RK(fs, e2) or 0
3687 local o1 = self:exp2RK(fs, e1)
3688 if o1 > o2 then
3689 self:freeexp(fs, e1)
3690 self:freeexp(fs, e2)
3691 else
3692 self:freeexp(fs, e2)
3693 self:freeexp(fs, e1)
3694 end
3695 e1.info = self:codeABC(fs, op, 0, o1, o2)
3696 e1.k = "VRELOCABLE"
3697 end
3698 end
3699
3700 ------------------------------------------------------------------------
3701 --
3702 -- * used only in luaK:posfix()
3703 ------------------------------------------------------------------------
3704 function luaK:codecomp(fs, op, cond, e1, e2)
3705 local o1 = self:exp2RK(fs, e1)
3706 local o2 = self:exp2RK(fs, e2)
3707 self:freeexp(fs, e2)
3708 self:freeexp(fs, e1)
3709 if cond == 0 and op ~= "OP_EQ" then
3710 -- exchange args to replace by `<' or `<='
3711 o1, o2 = o2, o1 -- o1 <==> o2
3712 cond = 1
3713 end
3714 e1.info = self:condjump(fs, op, cond, o1, o2)
3715 e1.k = "VJMP"
3716 end
3717
3718 ------------------------------------------------------------------------
3719 --
3720 -- * used only in (lparser) luaY:subexpr()
3721 ------------------------------------------------------------------------
3722 function luaK:prefix(fs, op, e)
3723 local e2 = {} -- expdesc
3724 e2.t, e2.f = self.NO_JUMP, self.NO_JUMP
3725 e2.k = "VKNUM"
3726 e2.nval = 0
3727 if op == "OPR_MINUS" then
3728 if not self:isnumeral(e) then
3729 self:exp2anyreg(fs, e) -- cannot operate on non-numeric constants
3730 end
3731 self:codearith(fs, "OP_UNM", e, e2)
3732 elseif op == "OPR_NOT" then
3733 self:codenot(fs, e)
3734 elseif op == "OPR_LEN" then
3735 self:exp2anyreg(fs, e) -- cannot operate on constants
3736 self:codearith(fs, "OP_LEN", e, e2)
3737 else
3738 assert(0)
3739 end
3740 end
3741
3742 ------------------------------------------------------------------------
3743 --
3744 -- * used only in (lparser) luaY:subexpr()
3745 ------------------------------------------------------------------------
3746 function luaK:infix(fs, op, v)
3747 if op == "OPR_AND" then
3748 self:goiftrue(fs, v)
3749 elseif op == "OPR_OR" then
3750 self:goiffalse(fs, v)
3751 elseif op == "OPR_CONCAT" then
3752 self:exp2nextreg(fs, v) -- operand must be on the 'stack'
3753 elseif op == "OPR_ADD" or op == "OPR_SUB" or
3754 op == "OPR_MUL" or op == "OPR_DIV" or
3755 op == "OPR_MOD" or op == "OPR_POW" then
3756 if not self:isnumeral(v) then self:exp2RK(fs, v) end
3757 else
3758 self:exp2RK(fs, v)
3759 end
3760 end
3761
3762 ------------------------------------------------------------------------
3763 --
3764 -- * used only in (lparser) luaY:subexpr()
3765 ------------------------------------------------------------------------
3766 -- table lookups to simplify testing
3767 luaK.arith_op = {
3768 OPR_ADD = "OP_ADD", OPR_SUB = "OP_SUB", OPR_MUL = "OP_MUL",
3769 OPR_DIV = "OP_DIV", OPR_MOD = "OP_MOD", OPR_POW = "OP_POW",
3770 }
3771 luaK.comp_op = {
3772 OPR_EQ = "OP_EQ", OPR_NE = "OP_EQ", OPR_LT = "OP_LT",
3773 OPR_LE = "OP_LE", OPR_GT = "OP_LT", OPR_GE = "OP_LE",
3774 }
3775 luaK.comp_cond = {
3776 OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1,
3777 OPR_LE = 1, OPR_GT = 0, OPR_GE = 0,
3778 }
3779 function luaK:posfix(fs, op, e1, e2)
3780 -- needed because e1 = e2 doesn't copy values...
3781 -- * in 5.0.x, only k/info/aux/t/f copied, t for AND, f for OR
3782 -- but here, all elements are copied for completeness' sake
3783 local function copyexp(e1, e2)
3784 e1.k = e2.k
3785 e1.info = e2.info; e1.aux = e2.aux
3786 e1.nval = e2.nval
3787 e1.t = e2.t; e1.f = e2.f
3788 end
3789 if op == "OPR_AND" then
3790 assert(e1.t == self.NO_JUMP) -- list must be closed
3791 self:dischargevars(fs, e2)
3792 e2.f = self:concat(fs, e2.f, e1.f)
3793 copyexp(e1, e2)
3794 elseif op == "OPR_OR" then
3795 assert(e1.f == self.NO_JUMP) -- list must be closed
3796 self:dischargevars(fs, e2)
3797 e2.t = self:concat(fs, e2.t, e1.t)
3798 copyexp(e1, e2)
3799 elseif op == "OPR_CONCAT" then
3800 self:exp2val(fs, e2)
3801 if e2.k == "VRELOCABLE" and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
3802 assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
3803 self:freeexp(fs, e1)
3804 luaP:SETARG_B(self:getcode(fs, e2), e1.info)
3805 e1.k = "VRELOCABLE"
3806 e1.info = e2.info
3807 else
3808 self:exp2nextreg(fs, e2) -- operand must be on the 'stack'
3809 self:codearith(fs, "OP_CONCAT", e1, e2)
3810 end
3811 else
3812 -- the following uses a table lookup in place of conditionals
3813 local arith = self.arith_op[op]
3814 if arith then
3815 self:codearith(fs, arith, e1, e2)
3816 else
3817 local comp = self.comp_op[op]
3818 if comp then
3819 self:codecomp(fs, comp, self.comp_cond[op], e1, e2)
3820 else
3821 assert(0)
3822 end
3823 end--if arith
3824 end--if op
3825 end
3826
3827 ------------------------------------------------------------------------
3828 -- adjusts debug information for last instruction written, in order to
3829 -- change the line where item comes into existence
3830 -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat()
3831 ------------------------------------------------------------------------
3832 function luaK:fixline(fs, line)
3833 fs.f.lineinfo[fs.pc - 1] = line
3834 end
3835
3836 ------------------------------------------------------------------------
3837 -- general function to write an instruction into the instruction buffer,
3838 -- sets debug information too
3839 -- * used in luaK:codeABC(), luaK:codeABx()
3840 -- * called directly by (lparser) luaY:whilestat()
3841 ------------------------------------------------------------------------
3842 function luaK:code(fs, i, line)
3843 local f = fs.f
3844 self:dischargejpc(fs) -- 'pc' will change
3845 -- put new instruction in code array
3846 luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil,
3847 luaY.MAX_INT, "code size overflow")
3848 f.code[fs.pc] = i
3849 -- save corresponding line information
3850 luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil,
3851 luaY.MAX_INT, "code size overflow")
3852 f.lineinfo[fs.pc] = line
3853 local pc = fs.pc
3854 fs.pc = fs.pc + 1
3855 return pc
3856 end
3857
3858 ------------------------------------------------------------------------
3859 -- writes an instruction of type ABC
3860 -- * calls luaK:code()
3861 ------------------------------------------------------------------------
3862 function luaK:codeABC(fs, o, a, b, c)
3863 assert(luaP:getOpMode(o) == luaP.OpMode.iABC)
3864 assert(luaP:getBMode(o) ~= luaP.OpArgMask.OpArgN or b == 0)
3865 assert(luaP:getCMode(o) ~= luaP.OpArgMask.OpArgN or c == 0)
3866 return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
3867 end
3868
3869 ------------------------------------------------------------------------
3870 -- writes an instruction of type ABx
3871 -- * calls luaK:code(), called by luaK:codeAsBx()
3872 ------------------------------------------------------------------------
3873 function luaK:codeABx(fs, o, a, bc)
3874 assert(luaP:getOpMode(o) == luaP.OpMode.iABx or
3875 luaP:getOpMode(o) == luaP.OpMode.iAsBx)
3876 assert(luaP:getCMode(o) == luaP.OpArgMask.OpArgN)
3877 return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
3878 end
3879
3880 ------------------------------------------------------------------------
3881 --
3882 -- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield()
3883 ------------------------------------------------------------------------
3884 function luaK:setlist(fs, base, nelems, tostore)
3885 local c = math.floor((nelems - 1)/luaP.LFIELDS_PER_FLUSH) + 1
3886 local b = (tostore == luaY.LUA_MULTRET) and 0 or tostore
3887 assert(tostore ~= 0)
3888 if c <= luaP.MAXARG_C then
3889 self:codeABC(fs, "OP_SETLIST", base, b, c)
3890 else
3891 self:codeABC(fs, "OP_SETLIST", base, b, 0)
3892 self:code(fs, luaP:CREATE_Inst(c), fs.ls.lastline)
3893 end
3894 fs.freereg = base + 1 -- free registers with list values
3895 end
3896
3897 return function(a) luaY = a return luaK end
3898 end
3899 fake_module_scripts[script] = module_script
3900end
3901do -- nil.LuaU
3902 local script = Instance.new('ModuleScript', nil)
3903 script.Name = "LuaU"
3904 local function module_script()
3905 --[[--------------------------------------------------------------------
3906
3907 ldump.lua
3908 Save precompiled Lua chunks
3909 This file is part of Yueliang.
3910
3911 Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
3912 The COPYRIGHT file describes the conditions
3913 under which this software may be distributed.
3914
3915 See the ChangeLog for more information.
3916
3917 ----------------------------------------------------------------------]]
3918
3919 --[[--------------------------------------------------------------------
3920 -- Notes:
3921 -- * WARNING! byte order (little endian) and data type sizes for header
3922 -- signature values hard-coded; see luaU:header
3923 -- * chunk writer generators are included, see below
3924 -- * one significant difference is that instructions are still in table
3925 -- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to
3926 -- convert them into 4-char strings
3927 --
3928 -- Not implemented:
3929 -- * DumpVar, DumpMem has been removed
3930 -- * DumpVector folded into folded into DumpDebug, DumpCode
3931 --
3932 -- Added:
3933 -- * for convenience, the following two functions have been added:
3934 -- luaU:make_setS: create a chunk writer that writes to a string
3935 -- luaU:make_setF: create a chunk writer that writes to a file
3936 -- (lua.h contains a typedef for lua_Writer/lua_Chunkwriter, and
3937 -- a Lua-based implementation exists, writer() in lstrlib.c)
3938 -- * luaU:ttype(o) (from lobject.h)
3939 -- * for converting number types to its binary equivalent:
3940 -- luaU:from_double(x): encode double value for writing
3941 -- luaU:from_int(x): encode integer value for writing
3942 -- (error checking is limited for these conversion functions)
3943 -- (double conversion does not support denormals or NaNs)
3944 --
3945 -- Changed in 5.1.x:
3946 -- * the dumper was mostly rewritten in Lua 5.1.x, so notes on the
3947 -- differences between 5.0.x and 5.1.x is limited
3948 -- * LUAC_VERSION bumped to 0x51, LUAC_FORMAT added
3949 -- * developer is expected to adjust LUAC_FORMAT in order to identify
3950 -- non-standard binary chunk formats
3951 -- * header signature code is smaller, has been simplified, and is
3952 -- tested as a single unit; its logic is shared with the undumper
3953 -- * no more endian conversion, invalid endianness mean rejection
3954 -- * opcode field sizes are no longer exposed in the header
3955 -- * code moved to front of a prototype, followed by constants
3956 -- * debug information moved to the end of the binary chunk, and the
3957 -- relevant functions folded into a single function
3958 -- * luaU:dump returns a writer status code
3959 -- * chunk writer now implements status code because dumper uses it
3960 -- * luaU:endianness removed
3961 ----------------------------------------------------------------------]]
3962
3963 --requires luaP
3964 local luaU = {}
3965 local luaP = require(script.Parent.LuaP)
3966
3967 -- mark for precompiled code ('<esc>Lua') (from lua.h)
3968 luaU.LUA_SIGNATURE = "\27Lua"
3969
3970 -- constants used by dumper (from lua.h)
3971 luaU.LUA_TNUMBER = 3
3972 luaU.LUA_TSTRING = 4
3973 luaU.LUA_TNIL = 0
3974 luaU.LUA_TBOOLEAN = 1
3975 luaU.LUA_TNONE = -1
3976
3977 -- constants for header of binary files (from lundump.h)
3978 luaU.LUAC_VERSION = 0x51 -- this is Lua 5.1
3979 luaU.LUAC_FORMAT = 0 -- this is the official format
3980 luaU.LUAC_HEADERSIZE = 12 -- size of header of binary files
3981
3982 --[[--------------------------------------------------------------------
3983 -- Additional functions to handle chunk writing
3984 -- * to use make_setS and make_setF, see test_ldump.lua elsewhere
3985 ----------------------------------------------------------------------]]
3986
3987 ------------------------------------------------------------------------
3988 -- create a chunk writer that writes to a string
3989 -- * returns the writer function and a table containing the string
3990 -- * to get the final result, look in buff.data
3991 ------------------------------------------------------------------------
3992 function luaU:make_setS()
3993 local buff = {}
3994 buff.data = ""
3995 local writer =
3996 function(s, buff) -- chunk writer
3997 if not s then return 0 end
3998 buff.data = buff.data..s
3999 return 0
4000 end
4001 return writer, buff
4002 end
4003
4004 ------------------------------------------------------------------------
4005 -- create a chunk writer that writes to a file
4006 -- * returns the writer function and a table containing the file handle
4007 -- * if a nil is passed, then writer should close the open file
4008 ------------------------------------------------------------------------
4009
4010 --[[
4011 function luaU:make_setF(filename)
4012 local buff = {}
4013 buff.h = io.open(filename, "wb")
4014 if not buff.h then return nil end
4015 local writer =
4016 function(s, buff) -- chunk writer
4017 if not buff.h then return 0 end
4018 if not s then
4019 if buff.h:close() then return 0 end
4020 else
4021 if buff.h:write(s) then return 0 end
4022 end
4023 return 1
4024 end
4025 return writer, buff
4026 end--]]
4027
4028 ------------------------------------------------------------------------
4029 -- works like the lobject.h version except that TObject used in these
4030 -- scripts only has a 'value' field, no 'tt' field (native types used)
4031 ------------------------------------------------------------------------
4032 function luaU:ttype(o)
4033 local tt = type(o.value)
4034 if tt == "number" then return self.LUA_TNUMBER
4035 elseif tt == "string" then return self.LUA_TSTRING
4036 elseif tt == "nil" then return self.LUA_TNIL
4037 elseif tt == "boolean" then return self.LUA_TBOOLEAN
4038 else
4039 return self.LUA_TNONE -- the rest should not appear
4040 end
4041 end
4042
4043 -----------------------------------------------------------------------
4044 -- converts a IEEE754 double number to an 8-byte little-endian string
4045 -- * luaU:from_double() and luaU:from_int() are adapted from ChunkBake
4046 -- * supports +/- Infinity, but not denormals or NaNs
4047 -----------------------------------------------------------------------
4048 function luaU:from_double(x)
4049 local function grab_byte(v)
4050 local c = v % 256
4051 return (v - c) / 256, string.char(c)
4052 end
4053 local sign = 0
4054 if x < 0 then sign = 1; x = -x end
4055 local mantissa, exponent = math.frexp(x)
4056 if x == 0 then -- zero
4057 mantissa, exponent = 0, 0
4058 elseif x == 1/0 then
4059 mantissa, exponent = 0, 2047
4060 else
4061 mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
4062 exponent = exponent + 1022
4063 end
4064 local v, byte = "" -- convert to bytes
4065 x = math.floor(mantissa)
4066 for i = 1,6 do
4067 x, byte = grab_byte(x); v = v..byte -- 47:0
4068 end
4069 x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
4070 x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
4071 return v
4072 end
4073
4074 -----------------------------------------------------------------------
4075 -- converts a number to a little-endian 32-bit integer string
4076 -- * input value assumed to not overflow, can be signed/unsigned
4077 -----------------------------------------------------------------------
4078 function luaU:from_int(x)
4079 local v = ""
4080 x = math.floor(x)
4081 if x < 0 then x = 4294967296 + x end -- ULONG_MAX+1
4082 for i = 1, 4 do
4083 local c = x % 256
4084 v = v..string.char(c); x = math.floor(x / 256)
4085 end
4086 return v
4087 end
4088
4089 --[[--------------------------------------------------------------------
4090 -- Functions to make a binary chunk
4091 -- * many functions have the size parameter removed, since output is
4092 -- in the form of a string and some sizes are implicit or hard-coded
4093 ----------------------------------------------------------------------]]
4094
4095 --[[--------------------------------------------------------------------
4096 -- struct DumpState:
4097 -- L -- lua_State (not used in this script)
4098 -- writer -- lua_Writer (chunk writer function)
4099 -- data -- void* (chunk writer context or data already written)
4100 -- strip -- if true, don't write any debug information
4101 -- status -- if non-zero, an error has occured
4102 ----------------------------------------------------------------------]]
4103
4104 ------------------------------------------------------------------------
4105 -- dumps a block of bytes
4106 -- * lua_unlock(D.L), lua_lock(D.L) unused
4107 ------------------------------------------------------------------------
4108 function luaU:DumpBlock(b, D)
4109 if D.status == 0 then
4110 -- lua_unlock(D->L);
4111 D.status = D.write(b, D.data)
4112 -- lua_lock(D->L);
4113 end
4114 end
4115
4116 ------------------------------------------------------------------------
4117 -- dumps a char
4118 ------------------------------------------------------------------------
4119 function luaU:DumpChar(y, D)
4120 self:DumpBlock(string.char(y), D)
4121 end
4122
4123 ------------------------------------------------------------------------
4124 -- dumps a 32-bit signed or unsigned integer (for int) (hard-coded)
4125 ------------------------------------------------------------------------
4126 function luaU:DumpInt(x, D)
4127 self:DumpBlock(self:from_int(x), D)
4128 end
4129
4130 ------------------------------------------------------------------------
4131 -- dumps a lua_Number (hard-coded as a double)
4132 ------------------------------------------------------------------------
4133 function luaU:DumpNumber(x, D)
4134 self:DumpBlock(self:from_double(x), D)
4135 end
4136
4137 ------------------------------------------------------------------------
4138 -- dumps a Lua string (size type is hard-coded)
4139 ------------------------------------------------------------------------
4140 function luaU:DumpString(s, D)
4141 if s == nil then
4142 self:DumpInt(0, D)
4143 else
4144 s = s.."\0" -- include trailing '\0'
4145 self:DumpInt(#s, D)
4146 self:DumpBlock(s, D)
4147 end
4148 end
4149
4150 ------------------------------------------------------------------------
4151 -- dumps instruction block from function prototype
4152 ------------------------------------------------------------------------
4153 function luaU:DumpCode(f, D)
4154 local n = f.sizecode
4155 --was DumpVector
4156 self:DumpInt(n, D)
4157 for i = 0, n - 1 do
4158 self:DumpBlock(luaP:Instruction(f.code[i]), D)
4159 end
4160 end
4161
4162 ------------------------------------------------------------------------
4163 -- dump constant pool from function prototype
4164 -- * bvalue(o), nvalue(o) and rawtsvalue(o) macros removed
4165 ------------------------------------------------------------------------
4166 function luaU:DumpConstants(f, D)
4167 local n = f.sizek
4168 self:DumpInt(n, D)
4169 for i = 0, n - 1 do
4170 local o = f.k[i] -- TValue
4171 local tt = self:ttype(o)
4172 self:DumpChar(tt, D)
4173 if tt == self.LUA_TNIL then
4174 elseif tt == self.LUA_TBOOLEAN then
4175 self:DumpChar(o.value and 1 or 0, D)
4176 elseif tt == self.LUA_TNUMBER then
4177 self:DumpNumber(o.value, D)
4178 elseif tt == self.LUA_TSTRING then
4179 self:DumpString(o.value, D)
4180 else
4181 --lua_assert(0) -- cannot happen
4182 end
4183 end
4184 n = f.sizep
4185 self:DumpInt(n, D)
4186 for i = 0, n - 1 do
4187 self:DumpFunction(f.p[i], f.source, D)
4188 end
4189 end
4190
4191 ------------------------------------------------------------------------
4192 -- dump debug information
4193 ------------------------------------------------------------------------
4194 function luaU:DumpDebug(f, D)
4195 local n
4196 n = D.strip and 0 or f.sizelineinfo -- dump line information
4197 --was DumpVector
4198 self:DumpInt(n, D)
4199 for i = 0, n - 1 do
4200 self:DumpInt(f.lineinfo[i], D)
4201 end
4202 n = D.strip and 0 or f.sizelocvars -- dump local information
4203 self:DumpInt(n, D)
4204 for i = 0, n - 1 do
4205 self:DumpString(f.locvars[i].varname, D)
4206 self:DumpInt(f.locvars[i].startpc, D)
4207 self:DumpInt(f.locvars[i].endpc, D)
4208 end
4209 n = D.strip and 0 or f.sizeupvalues -- dump upvalue information
4210 self:DumpInt(n, D)
4211 for i = 0, n - 1 do
4212 self:DumpString(f.upvalues[i], D)
4213 end
4214 end
4215
4216 ------------------------------------------------------------------------
4217 -- dump child function prototypes from function prototype
4218 ------------------------------------------------------------------------
4219 function luaU:DumpFunction(f, p, D)
4220 local source = f.source
4221 if source == p or D.strip then source = nil end
4222 self:DumpString(source, D)
4223 self:DumpInt(f.lineDefined, D)
4224 self:DumpInt(f.lastlinedefined, D)
4225 self:DumpChar(f.nups, D)
4226 self:DumpChar(f.numparams, D)
4227 self:DumpChar(f.is_vararg, D)
4228 self:DumpChar(f.maxstacksize, D)
4229 self:DumpCode(f, D)
4230 self:DumpConstants(f, D)
4231 self:DumpDebug(f, D)
4232 end
4233
4234 ------------------------------------------------------------------------
4235 -- dump Lua header section (some sizes hard-coded)
4236 ------------------------------------------------------------------------
4237 function luaU:DumpHeader(D)
4238 local h = self:header()
4239 assert(#h == self.LUAC_HEADERSIZE) -- fixed buffer now an assert
4240 self:DumpBlock(h, D)
4241 end
4242
4243 ------------------------------------------------------------------------
4244 -- make header (from lundump.c)
4245 -- returns the header string
4246 ------------------------------------------------------------------------
4247 function luaU:header()
4248 local x = 1
4249 return self.LUA_SIGNATURE..
4250 string.char(
4251 self.LUAC_VERSION,
4252 self.LUAC_FORMAT,
4253 x, -- endianness (1=little)
4254 4, -- sizeof(int)
4255 4, -- sizeof(size_t)
4256 4, -- sizeof(Instruction)
4257 8, -- sizeof(lua_Number)
4258 0) -- is lua_Number integral?
4259 end
4260
4261 ------------------------------------------------------------------------
4262 -- dump Lua function as precompiled chunk
4263 -- (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
4264 -- * w, data are created from make_setS, make_setF
4265 ------------------------------------------------------------------------
4266 function luaU:dump(L, f, w, data, strip)
4267 local D = {} -- DumpState
4268 D.L = L
4269 D.write = w
4270 D.data = data
4271 D.strip = strip
4272 D.status = 0
4273 self:DumpHeader(D)
4274 self:DumpFunction(f, nil, D)
4275 -- added: for a chunk writer writing to a file, this final call with
4276 -- nil data is to indicate to the writer to close the file
4277 D.write(nil, D.data)
4278 return D.status
4279 end
4280
4281 return luaU
4282 end
4283 fake_module_scripts[script] = module_script
4284end
4285do -- nil.LuaP
4286 local script = Instance.new('ModuleScript', nil)
4287 script.Name = "LuaP"
4288 local function module_script()
4289 --[[--------------------------------------------------------------------
4290
4291 lopcodes.lua
4292 Lua 5 virtual machine opcodes in Lua
4293 This file is part of Yueliang.
4294
4295 Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
4296 The COPYRIGHT file describes the conditions
4297 under which this software may be distributed.
4298
4299 See the ChangeLog for more information.
4300
4301 ----------------------------------------------------------------------]]
4302
4303 --[[--------------------------------------------------------------------
4304 -- Notes:
4305 -- * an Instruction is a table with OP, A, B, C, Bx elements; this
4306 -- makes the code easy to follow and should allow instruction handling
4307 -- to work with doubles and ints
4308 -- * WARNING luaP:Instruction outputs instructions encoded in little-
4309 -- endian form and field size and positions are hard-coded
4310 --
4311 -- Not implemented:
4312 -- *
4313 --
4314 -- Added:
4315 -- * luaP:CREATE_Inst(c): create an inst from a number (for OP_SETLIST)
4316 -- * luaP:Instruction(i): convert field elements to a 4-char string
4317 -- * luaP:DecodeInst(x): convert 4-char string into field elements
4318 --
4319 -- Changed in 5.1.x:
4320 -- * POS_OP added, instruction field positions changed
4321 -- * some symbol names may have changed, e.g. LUAI_BITSINT
4322 -- * new operators for RK indices: BITRK, ISK(x), INDEXK(r), RKASK(x)
4323 -- * OP_MOD, OP_LEN is new
4324 -- * OP_TEST is now OP_TESTSET, OP_TEST is new
4325 -- * OP_FORLOOP, OP_TFORLOOP adjusted, OP_FORPREP is new
4326 -- * OP_TFORPREP deleted
4327 -- * OP_SETLIST and OP_SETLISTO merged and extended
4328 -- * OP_VARARG is new
4329 -- * many changes to implementation of OpMode data
4330 ----------------------------------------------------------------------]]
4331
4332 local luaP = {}
4333
4334 --[[
4335 ===========================================================================
4336 We assume that instructions are unsigned numbers.
4337 All instructions have an opcode in the first 6 bits.
4338 Instructions can have the following fields:
4339 'A' : 8 bits
4340 'B' : 9 bits
4341 'C' : 9 bits
4342 'Bx' : 18 bits ('B' and 'C' together)
4343 'sBx' : signed Bx
4344
4345 A signed argument is represented in excess K; that is, the number
4346 value is the unsigned value minus K. K is exactly the maximum value
4347 for that argument (so that -max is represented by 0, and +max is
4348 represented by 2*max), which is half the maximum for the corresponding
4349 unsigned argument.
4350 ===========================================================================
4351 --]]
4352
4353 luaP.OpMode = { iABC = 0, iABx = 1, iAsBx = 2 } -- basic instruction format
4354
4355 ------------------------------------------------------------------------
4356 -- size and position of opcode arguments.
4357 -- * WARNING size and position is hard-coded elsewhere in this script
4358 ------------------------------------------------------------------------
4359 luaP.SIZE_C = 9
4360 luaP.SIZE_B = 9
4361 luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B
4362 luaP.SIZE_A = 8
4363
4364 luaP.SIZE_OP = 6
4365
4366 luaP.POS_OP = 0
4367 luaP.POS_A = luaP.POS_OP + luaP.SIZE_OP
4368 luaP.POS_C = luaP.POS_A + luaP.SIZE_A
4369 luaP.POS_B = luaP.POS_C + luaP.SIZE_C
4370 luaP.POS_Bx = luaP.POS_C
4371
4372 ------------------------------------------------------------------------
4373 -- limits for opcode arguments.
4374 -- we use (signed) int to manipulate most arguments,
4375 -- so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
4376 ------------------------------------------------------------------------
4377 -- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is
4378 -- running on a Lua VM with double or int as LUA_NUMBER
4379
4380 luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1
4381 luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed
4382
4383 luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1
4384 luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1
4385 luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1
4386
4387 -- creates a mask with 'n' 1 bits at position 'p'
4388 -- MASK1(n,p) deleted, not required
4389 -- creates a mask with 'n' 0 bits at position 'p'
4390 -- MASK0(n,p) deleted, not required
4391
4392 --[[--------------------------------------------------------------------
4393 Visual representation for reference:
4394
4395 31 | | | 0 bit position
4396 +-----+-----+-----+----------+
4397 | B | C | A | Opcode | iABC format
4398 +-----+-----+-----+----------+
4399 - 9 - 9 - 8 - 6 - field sizes
4400 +-----+-----+-----+----------+
4401 | [s]Bx | A | Opcode | iABx | iAsBx format
4402 +-----+-----+-----+----------+
4403
4404 ----------------------------------------------------------------------]]
4405
4406 ------------------------------------------------------------------------
4407 -- the following macros help to manipulate instructions
4408 -- * changed to a table object representation, very clean compared to
4409 -- the [nightmare] alternatives of using a number or a string
4410 -- * Bx is a separate element from B and C, since there is never a need
4411 -- to split Bx in the parser or code generator
4412 ------------------------------------------------------------------------
4413
4414 -- these accept or return opcodes in the form of string names
4415 function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end
4416 function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end
4417
4418 function luaP:GETARG_A(i) return i.A end
4419 function luaP:SETARG_A(i, u) i.A = u end
4420
4421 function luaP:GETARG_B(i) return i.B end
4422 function luaP:SETARG_B(i, b) i.B = b end
4423
4424 function luaP:GETARG_C(i) return i.C end
4425 function luaP:SETARG_C(i, b) i.C = b end
4426
4427 function luaP:GETARG_Bx(i) return i.Bx end
4428 function luaP:SETARG_Bx(i, b) i.Bx = b end
4429
4430 function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end
4431 function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end
4432
4433 function luaP:CREATE_ABC(o,a,b,c)
4434 return {OP = self.OpCode[o], A = a, B = b, C = c}
4435 end
4436
4437 function luaP:CREATE_ABx(o,a,bc)
4438 return {OP = self.OpCode[o], A = a, Bx = bc}
4439 end
4440
4441 ------------------------------------------------------------------------
4442 -- create an instruction from a number (for OP_SETLIST)
4443 ------------------------------------------------------------------------
4444 function luaP:CREATE_Inst(c)
4445 local o = c % 64
4446 c = (c - o) / 64
4447 local a = c % 256
4448 c = (c - a) / 256
4449 return self:CREATE_ABx(o, a, c)
4450 end
4451
4452 ------------------------------------------------------------------------
4453 -- returns a 4-char string little-endian encoded form of an instruction
4454 ------------------------------------------------------------------------
4455 function luaP:Instruction(i)
4456 if i.Bx then
4457 -- change to OP/A/B/C format
4458 i.C = i.Bx % 512
4459 i.B = (i.Bx - i.C) / 512
4460 end
4461 local I = i.A * 64 + i.OP
4462 local c0 = I % 256
4463 I = i.C * 64 + (I - c0) / 256 -- 6 bits of A left
4464 local c1 = I % 256
4465 I = i.B * 128 + (I - c1) / 256 -- 7 bits of C left
4466 local c2 = I % 256
4467 local c3 = (I - c2) / 256
4468 return string.char(c0, c1, c2, c3)
4469 end
4470
4471 ------------------------------------------------------------------------
4472 -- decodes a 4-char little-endian string into an instruction struct
4473 ------------------------------------------------------------------------
4474 function luaP:DecodeInst(x)
4475 local byte = string.byte
4476 local i = {}
4477 local I = byte(x, 1)
4478 local op = I % 64
4479 i.OP = op
4480 I = byte(x, 2) * 4 + (I - op) / 64 -- 2 bits of c0 left
4481 local a = I % 256
4482 i.A = a
4483 I = byte(x, 3) * 4 + (I - a) / 256 -- 2 bits of c1 left
4484 local c = I % 512
4485 i.C = c
4486 i.B = byte(x, 4) * 2 + (I - c) / 512 -- 1 bits of c2 left
4487 local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))]
4488 if opmode ~= "iABC" then
4489 i.Bx = i.B * 512 + i.C
4490 end
4491 return i
4492 end
4493
4494 ------------------------------------------------------------------------
4495 -- Macros to operate RK indices
4496 -- * these use arithmetic instead of bit ops
4497 ------------------------------------------------------------------------
4498
4499 -- this bit 1 means constant (0 means register)
4500 luaP.BITRK = math.ldexp(1, luaP.SIZE_B - 1)
4501
4502 -- test whether value is a constant
4503 function luaP:ISK(x) return x >= self.BITRK end
4504
4505 -- gets the index of the constant
4506 function luaP:INDEXK(x) return x - self.BITRK end
4507
4508 luaP.MAXINDEXRK = luaP.BITRK - 1
4509
4510 -- code a constant index as a RK value
4511 function luaP:RKASK(x) return x + self.BITRK end
4512
4513 ------------------------------------------------------------------------
4514 -- invalid register that fits in 8 bits
4515 ------------------------------------------------------------------------
4516 luaP.NO_REG = luaP.MAXARG_A
4517
4518 ------------------------------------------------------------------------
4519 -- R(x) - register
4520 -- Kst(x) - constant (in constant table)
4521 -- RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
4522 ------------------------------------------------------------------------
4523
4524 ------------------------------------------------------------------------
4525 -- grep "ORDER OP" if you change these enums
4526 ------------------------------------------------------------------------
4527
4528 --[[--------------------------------------------------------------------
4529 Lua virtual machine opcodes (enum OpCode):
4530 ------------------------------------------------------------------------
4531 name args description
4532 ------------------------------------------------------------------------
4533 OP_MOVE A B R(A) := R(B)
4534 OP_LOADK A Bx R(A) := Kst(Bx)
4535 OP_LOADBOOL A B C R(A) := (Bool)B; if (C) pc++
4536 OP_LOADNIL A B R(A) := ... := R(B) := nil
4537 OP_GETUPVAL A B R(A) := UpValue[B]
4538 OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)]
4539 OP_GETTABLE A B C R(A) := R(B)[RK(C)]
4540 OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A)
4541 OP_SETUPVAL A B UpValue[B] := R(A)
4542 OP_SETTABLE A B C R(A)[RK(B)] := RK(C)
4543 OP_NEWTABLE A B C R(A) := {} (size = B,C)
4544 OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
4545 OP_ADD A B C R(A) := RK(B) + RK(C)
4546 OP_SUB A B C R(A) := RK(B) - RK(C)
4547 OP_MUL A B C R(A) := RK(B) * RK(C)
4548 OP_DIV A B C R(A) := RK(B) / RK(C)
4549 OP_MOD A B C R(A) := RK(B) % RK(C)
4550 OP_POW A B C R(A) := RK(B) ^ RK(C)
4551 OP_UNM A B R(A) := -R(B)
4552 OP_NOT A B R(A) := not R(B)
4553 OP_LEN A B R(A) := length of R(B)
4554 OP_CONCAT A B C R(A) := R(B).. ... ..R(C)
4555 OP_JMP sBx pc+=sBx
4556 OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++
4557 OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++
4558 OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++
4559 OP_TEST A C if not (R(A) <=> C) then pc++
4560 OP_TESTSET A B C if (R(B) <=> C) then R(A) := R(B) else pc++
4561 OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
4562 OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1))
4563 OP_RETURN A B return R(A), ... ,R(A+B-2) (see note)
4564 OP_FORLOOP A sBx R(A)+=R(A+2);
4565 if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
4566 OP_FORPREP A sBx R(A)-=R(A+2); pc+=sBx
4567 OP_TFORLOOP A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
4568 if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++
4569 OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
4570 OP_CLOSE A close all variables in the stack up to (>=) R(A)
4571 OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
4572 OP_VARARG A B R(A), R(A+1), ..., R(A+B-1) = vararg
4573 ----------------------------------------------------------------------]]
4574
4575 luaP.opnames = {} -- opcode names
4576 luaP.OpCode = {} -- lookup name -> number
4577 luaP.ROpCode = {} -- lookup number -> name
4578
4579 ------------------------------------------------------------------------
4580 -- ORDER OP
4581 ------------------------------------------------------------------------
4582 local i = 0
4583 for v in string.gmatch([[
4584 MOVE LOADK LOADBOOL LOADNIL GETUPVAL
4585 GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE
4586 NEWTABLE SELF ADD SUB MUL
4587 DIV MOD POW UNM NOT
4588 LEN CONCAT JMP EQ LT
4589 LE TEST TESTSET CALL TAILCALL
4590 RETURN FORLOOP FORPREP TFORLOOP SETLIST
4591 CLOSE CLOSURE VARARG
4592 ]], "%S+") do
4593 local n = "OP_"..v
4594 luaP.opnames[i] = v
4595 luaP.OpCode[n] = i
4596 luaP.ROpCode[i] = n
4597 i = i + 1
4598 end
4599 luaP.NUM_OPCODES = i
4600
4601 --[[
4602 ===========================================================================
4603 Notes:
4604 (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
4605 and can be 0: OP_CALL then sets 'top' to last_result+1, so
4606 next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'.
4607 (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
4608 set top (like in OP_CALL with C == 0).
4609 (*) In OP_RETURN, if (B == 0) then return up to 'top'
4610 (*) In OP_SETLIST, if (B == 0) then B = 'top';
4611 if (C == 0) then next 'instruction' is real C
4612 (*) For comparisons, A specifies what condition the test should accept
4613 (true or false).
4614 (*) All 'skips' (pc++) assume that next instruction is a jump
4615 ===========================================================================
4616 --]]
4617
4618 --[[--------------------------------------------------------------------
4619 masks for instruction properties. The format is:
4620 bits 0-1: op mode
4621 bits 2-3: C arg mode
4622 bits 4-5: B arg mode
4623 bit 6: instruction set register A
4624 bit 7: operator is a test
4625
4626 for OpArgMask:
4627 OpArgN - argument is not used
4628 OpArgU - argument is used
4629 OpArgR - argument is a register or a jump offset
4630 OpArgK - argument is a constant or register/constant
4631 ----------------------------------------------------------------------]]
4632
4633 -- was enum OpArgMask
4634 luaP.OpArgMask = { OpArgN = 0, OpArgU = 1, OpArgR = 2, OpArgK = 3 }
4635
4636 ------------------------------------------------------------------------
4637 -- e.g. to compare with symbols, luaP:getOpMode(...) == luaP.OpCode.iABC
4638 -- * accepts opcode parameter as strings, e.g. "OP_MOVE"
4639 ------------------------------------------------------------------------
4640
4641 function luaP:getOpMode(m)
4642 return self.opmodes[self.OpCode[m]] % 4
4643 end
4644
4645 function luaP:getBMode(m)
4646 return math.floor(self.opmodes[self.OpCode[m]] / 16) % 4
4647 end
4648
4649 function luaP:getCMode(m)
4650 return math.floor(self.opmodes[self.OpCode[m]] / 4) % 4
4651 end
4652
4653 function luaP:testAMode(m)
4654 return math.floor(self.opmodes[self.OpCode[m]] / 64) % 2
4655 end
4656
4657 function luaP:testTMode(m)
4658 return math.floor(self.opmodes[self.OpCode[m]] / 128)
4659 end
4660
4661 -- luaP_opnames[] is set above, as the luaP.opnames table
4662
4663 -- number of list items to accumulate before a SETLIST instruction
4664 luaP.LFIELDS_PER_FLUSH = 50
4665
4666 ------------------------------------------------------------------------
4667 -- build instruction properties array
4668 -- * deliberately coded to look like the C equivalent
4669 ------------------------------------------------------------------------
4670 local function opmode(t, a, b, c, m)
4671 local luaP = luaP
4672 return t * 128 + a * 64 +
4673 luaP.OpArgMask[b] * 16 + luaP.OpArgMask[c] * 4 + luaP.OpMode[m]
4674 end
4675
4676 -- ORDER OP
4677 luaP.opmodes = {
4678 -- T A B C mode opcode
4679 opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_LOADK
4680 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_LOADBOOL
4681 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LOADNIL
4682 opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_GETUPVAL
4683 opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_GETGLOBAL
4684 opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_GETTABLE
4685 opmode(0, 0, "OpArgK", "OpArgN", "iABx"), -- OP_SETGLOBAL
4686 opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_SETUPVAL
4687 opmode(0, 0, "OpArgK", "OpArgK", "iABC"), -- OP_SETTABLE
4688 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_NEWTABLE
4689 opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_SELF
4690 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_ADD
4691 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_SUB
4692 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MUL
4693 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_DIV
4694 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MOD
4695 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_POW
4696 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_UNM
4697 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_NOT
4698 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LEN
4699 opmode(0, 1, "OpArgR", "OpArgR", "iABC"), -- OP_CONCAT
4700 opmode(0, 0, "OpArgR", "OpArgN", "iAsBx"), -- OP_JMP
4701 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_EQ
4702 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LT
4703 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LE
4704 opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TEST
4705 opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TESTSET
4706 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_CALL
4707 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_TAILCALL
4708 opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_RETURN
4709 opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORLOOP
4710 opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORPREP
4711 opmode(1, 0, "OpArgN", "OpArgU", "iABC"), -- OP_TFORLOOP
4712 opmode(0, 0, "OpArgU", "OpArgU", "iABC"), -- OP_SETLIST
4713 opmode(0, 0, "OpArgN", "OpArgN", "iABC"), -- OP_CLOSE
4714 opmode(0, 1, "OpArgU", "OpArgN", "iABx"), -- OP_CLOSURE
4715 opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_VARARG
4716 }
4717 -- an awkward way to set a zero-indexed table...
4718 luaP.opmodes[0] =
4719 opmode(0, 1, "OpArgR", "OpArgN", "iABC") -- OP_MOVE
4720
4721 return luaP
4722 end
4723 fake_module_scripts[script] = module_script
4724end
4725do -- nil.Rerubi
4726 local script = Instance.new('ModuleScript', nil)
4727 script.Name = "Rerubi"
4728 local function module_script()
4729 local Select = select;
4730 local Byte = string.byte;
4731 local Sub = string.sub;
4732
4733 local Opmode = {
4734 {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgK', c='OpArgN'}, {b = 'OpArgU', c='OpArgU'},
4735 {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgU', c='OpArgN'}, {b = 'OpArgK', c='OpArgN'},
4736 {b = 'OpArgR', c='OpArgK'}, {b = 'OpArgK', c='OpArgN'}, {b = 'OpArgU', c='OpArgN'},
4737 {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgU', c='OpArgU'}, {b = 'OpArgR', c='OpArgK'},
4738 {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgK', c='OpArgK'},
4739 {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgK', c='OpArgK'},
4740 {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgR', c='OpArgN'},
4741 {b = 'OpArgR', c='OpArgR'}, {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgK', c='OpArgK'},
4742 {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgK', c='OpArgK'}, {b = 'OpArgR', c='OpArgU'},
4743 {b = 'OpArgR', c='OpArgU'}, {b = 'OpArgU', c='OpArgU'}, {b = 'OpArgU', c='OpArgU'},
4744 {b = 'OpArgU', c='OpArgN'}, {b = 'OpArgR', c='OpArgN'}, {b = 'OpArgR', c='OpArgN'},
4745 {b = 'OpArgN', c='OpArgU'}, {b = 'OpArgU', c='OpArgU'}, {b = 'OpArgN', c='OpArgN'},
4746 {b = 'OpArgU', c='OpArgN'}, {b = 'OpArgU', c='OpArgN'}
4747 };
4748
4749 local Opcode = { -- Opcode types.
4750 'ABC', 'ABx', 'ABC', 'ABC';
4751 'ABC', 'ABx', 'ABC', 'ABx';
4752 'ABC', 'ABC', 'ABC', 'ABC';
4753 'ABC', 'ABC', 'ABC', 'ABC';
4754 'ABC', 'ABC', 'ABC', 'ABC';
4755 'ABC', 'ABC', 'AsBx', 'ABC';
4756 'ABC', 'ABC', 'ABC', 'ABC';
4757 'ABC', 'ABC', 'ABC', 'AsBx';
4758 'AsBx', 'ABC', 'ABC', 'ABC';
4759 'ABx', 'ABC';
4760 };
4761
4762 -- rlbi author -> Rerumu
4763 -- special thanks;
4764 -- @cntkillme for providing faster bit extraction
4765 -- @Eternal for being #1 bug finder and providing better float decoder
4766 -- @stravant for contributing to the original project this is derived from
4767
4768 -- rerubi is an upgrade to the original Lua VM in Lua
4769 -- the prime goal of rerubi is to be the fastest:tm: alternative
4770 -- to a Lua in Lua bytecode execution
4771
4772 local function gBit(Bit, Start, End) -- No tail-calls, yay.
4773 if End then -- Thanks to cntkillme for giving input on this shorter, better approach.
4774 local Res = (Bit / 2 ^ (Start - 1)) % 2 ^ ((End - 1) - (Start - 1) + 1);
4775
4776 return Res - Res % 1;
4777 else
4778 local Plc = 2 ^ (Start - 1);
4779
4780 if (Bit % (Plc + Plc) >= Plc) then
4781 return 1;
4782 else
4783 return 0;
4784 end;
4785 end;
4786 end;
4787
4788 local function GetMeaning(ByteString)
4789 local Pos = 1;
4790 local gSizet;
4791 local gInt;
4792
4793 local function gBits8() -- Get the next byte in the stream.
4794 local F = Byte(ByteString, Pos, Pos);
4795
4796 Pos = Pos + 1;
4797
4798 return F;
4799 end;
4800
4801 local function gBits32()
4802 local W, X, Y, Z = Byte(ByteString, Pos, Pos + 3);
4803
4804 Pos = Pos + 4;
4805
4806 return (Z * 16777216) + (Y * 65536) + (X * 256) + W;
4807 end;
4808
4809 local function gBits64()
4810 return gBits32() * 4294967296 + gBits32();
4811 end;
4812
4813 local function gFloat()
4814 -- thanks @Eternal for giving me this so I could mangle it in here and have it work
4815 local Left = gBits32();
4816 local Right = gBits32();
4817 local IsNormal = 1
4818 local Mantissa = (gBit(Right, 1, 20) * (2 ^ 32))
4819 + Left;
4820
4821 local Exponent = gBit(Right, 21, 31);
4822 local Sign = ((-1) ^ gBit(Right, 32));
4823
4824 if (Exponent == 0) then
4825 if (Mantissa == 0) then
4826 return Sign * 0 -- +-0
4827 else
4828 Exponent = 1
4829 IsNormal = 0
4830 end
4831 elseif (Exponent == 2047) then
4832 if (Mantissa == 0) then
4833 return Sign * (1 / 0) -- +-Inf
4834 else
4835 return Sign * (0 / 0) -- +-Q/Nan
4836 end
4837 end
4838
4839 -- sign * 2**e-1023 * isNormal.mantissa
4840 return math.ldexp(Sign, Exponent - 1023) * (IsNormal + (Mantissa / (2 ^ 52)))
4841 end;
4842
4843 local function gString(Len)
4844 local Str;
4845
4846 if Len then
4847 Str = Sub(ByteString, Pos, Pos + Len - 1);
4848
4849 Pos = Pos + Len;
4850 else
4851 Len = gSizet();
4852
4853 if (Len == 0) then return; end;
4854
4855 Str = Sub(ByteString, Pos, Pos + Len - 1);
4856
4857 Pos = Pos + Len;
4858 end;
4859
4860 return Str;
4861 end;
4862
4863 local function ChunkDecode()
4864 local Instr = {};
4865 local Const = {};
4866 local Proto = {};
4867 local Chunk = {
4868 Instr = Instr; -- Instructions
4869 Const = Const; -- Constants
4870 Proto = Proto; -- Prototypes
4871 Lines = {}; -- Lines
4872 Name = gString(); -- Grab name string.
4873 FirstL = gInt(); -- First line.
4874 LastL = gInt(); -- Last line.
4875 Upvals = gBits8(); -- Upvalue count.
4876 Args = gBits8(); -- Arg count.
4877 Vargs = gBits8(); -- Vararg type.
4878 Stack = gBits8(); -- Stack.
4879 };
4880 local ConstantReferences = {}; -- for an optimization
4881
4882 if Chunk.Name then
4883 Chunk.Name = Sub(Chunk.Name, 1, -2);
4884 end;
4885
4886
4887 for Idx = 1, gInt() do -- Loading instructions to the chunk.
4888 local Data = gBits32();
4889 local Opco = gBit(Data, 1, 6);
4890 local Type = Opcode[Opco + 1];
4891 local Mode = Opmode[Opco + 1];
4892
4893 local Inst = {
4894 Enum = Opco;
4895 Value = Data;
4896 gBit(Data, 7, 14); -- Register A.
4897 };
4898
4899 if (Type == 'ABC') then -- Most common, basic instruction type.
4900 Inst[2] = gBit(Data, 24, 32);
4901 Inst[3] = gBit(Data, 15, 23);
4902 elseif (Type == 'ABx') then
4903 Inst[2] = gBit(Data, 15, 32);
4904 elseif (Type == 'AsBx') then
4905 Inst[2] = gBit(Data, 15, 32) - 131071;
4906 end;
4907
4908 -- Precompute data for some instructions
4909 do
4910 -- TEST and TESTSET
4911 if Opco == 26 or Opco == 27 then
4912 Inst[3] = Inst[3] == 0;
4913 end
4914
4915 -- EQ, LT, LE
4916 if Opco >= 23 and Opco <= 25 then
4917 Inst[1] = Inst[1] ~= 0;
4918 end
4919
4920 -- Anything that looks at a constant using B
4921 if Mode.b == 'OpArgK' then
4922 Inst[3] = Inst[3] or false; -- Simply to guarantee that Inst[4] is inserted in the array part
4923 if Inst[2] >= 256 then
4924 local Cons = Inst[2] - 256;
4925 Inst[4] = Cons;
4926
4927 local ReferenceData = ConstantReferences[Cons];
4928 if not ReferenceData then
4929 ReferenceData = {};
4930 ConstantReferences[Cons] = ReferenceData;
4931 end
4932
4933 ReferenceData[#ReferenceData + 1] = {Inst = Inst, Register = 4}
4934 end
4935 end
4936
4937 -- Anything that looks at a constant using C
4938 if Mode.c == 'OpArgK' then
4939 Inst[4] = Inst[4] or false -- Simply to guarantee that Inst[5] is inserted in the array part
4940 if Inst[3] >= 256 then
4941 local Cons = Inst[3] - 256;
4942 Inst[5] = Cons;
4943
4944 local ReferenceData = ConstantReferences[Cons];
4945 if not ReferenceData then
4946 ReferenceData = {};
4947 ConstantReferences[Cons] = ReferenceData;
4948 end
4949
4950 ReferenceData[#ReferenceData + 1] = {Inst = Inst, Register = 5}
4951 end
4952 end
4953 end
4954
4955 Instr[Idx] = Inst;
4956 end;
4957
4958 for Idx = 1, gInt() do -- Load constants.
4959 local Type = gBits8();
4960 local Cons;
4961
4962 if (Type == 1) then -- Boolean
4963 Cons = (gBits8() ~= 0);
4964 elseif (Type == 3) then -- Float/Double
4965 Cons = gFloat();
4966 elseif (Type == 4) then
4967 Cons = Sub(gString(), 1, -2);
4968 end;
4969
4970 -- Finish precomputing constants
4971 local Refs = ConstantReferences[Idx - 1];
4972 if Refs then
4973 for i = 1, #Refs do
4974 Refs[i].Inst[Refs[i].Register] = Cons
4975 end
4976 end
4977
4978 -- Write Constant to pool
4979 Const[Idx - 1] = Cons;
4980 end;
4981
4982 for Idx = 1, gInt() do -- Nested function prototypes.
4983 Proto[Idx - 1] = ChunkDecode();
4984 end;
4985
4986 do -- Debugging
4987 local Lines = Chunk.Lines;
4988
4989 for Idx = 1, gInt() do
4990 Lines[Idx] = gBits32();
4991 end;
4992
4993 for _ = 1, gInt() do -- Locals in stack.
4994 gString(); -- Name of local.
4995 gBits32(); -- Starting point.
4996 gBits32(); -- End point.
4997 end;
4998
4999 for _ = 1, gInt() do -- Upvalues.
5000 gString(); -- Name of upvalue.
5001 end;
5002 end;
5003
5004 return Chunk; -- Finished chunk.
5005 end;
5006
5007 do -- Most of this chunk I was too lazy to reformat or change
5008 assert(gString(4) == "\27Lua", "Lua bytecode expected.");
5009 assert(gBits8() == 0x51, "Only Lua 5.1 is supported.");
5010
5011 gBits8(); -- Probably version control.
5012 gBits8(); -- Is small endians.
5013
5014 local IntSize = gBits8(); -- Int size
5015 local Sizet = gBits8(); -- size_t
5016
5017 if (IntSize == 4) then
5018 gInt = gBits32;
5019 elseif (IntSize == 8) then
5020 gInt = gBits64;
5021 else
5022 error('Integer size not supported', 2);
5023 end;
5024
5025 if (Sizet == 4) then
5026 gSizet = gBits32;
5027 elseif (Sizet == 8) then
5028 gSizet = gBits64;
5029 else
5030 error('Sizet size not supported', 2);
5031 end;
5032
5033 assert(gString(3) == "\4\8\0", "Unsupported bytecode target platform");
5034 end;
5035
5036 return ChunkDecode();
5037 end;
5038
5039 local function _Returns(...)
5040 return Select('#', ...), {...};
5041 end;
5042
5043 local function Wrap(Chunk, Env, Upvalues)
5044 local Instr = Chunk.Instr;
5045 local Const = Chunk.Const;
5046 local Proto = Chunk.Proto;
5047
5048 local function OnError(Err, Position) -- Handle your errors in whatever way.
5049 local Name = Chunk.Name or 'Code';
5050 local Line = Chunk.Lines[Position] or '?';
5051
5052 error(string.format('%s:%s: %s', Name, Line, tostring(Err)), 0);
5053 end;
5054
5055 return function(...)
5056 -- Returned function to run bytecode chunk (Don't be stupid, you can't setfenv this to work your way).
5057 local InstrPoint, Top = 1, -1;
5058 local Vararg, Varargsz = {}, Select('#', ...) - 1;
5059
5060 local GStack = {};
5061 local Lupvals = {};
5062 local Stack = setmetatable({}, {
5063 __index = GStack;
5064 __newindex = function(_, Key, Value)
5065 if (Key > Top) then
5066 Top = Key;
5067 end;
5068
5069 GStack[Key] = Value;
5070 end;
5071 });
5072
5073 local function Loop()
5074 local Inst, Enum;
5075
5076 while true do
5077 Inst = Instr[InstrPoint];
5078 Enum = Inst.Enum;
5079 InstrPoint = InstrPoint + 1;
5080
5081 if (Enum == 0) then -- MOVE
5082 Stack[Inst[1]] = Stack[Inst[2]];
5083 elseif (Enum == 1) then -- LOADK
5084 Stack[Inst[1]] = Const[Inst[2]];
5085 elseif (Enum == 2) then -- LOADBOOL
5086 Stack[Inst[1]] = (Inst[2] ~= 0);
5087
5088 if (Inst[3] ~= 0) then
5089 InstrPoint = InstrPoint + 1;
5090 end;
5091 elseif (Enum == 3) then -- LOADNIL
5092 local Stk = Stack;
5093
5094 for Idx = Inst[1], Inst[2] do
5095 Stk[Idx] = nil;
5096 end;
5097 elseif (Enum == 4) then -- GETUPVAL
5098 Stack[Inst[1]] = Upvalues[Inst[2]];
5099 elseif (Enum == 5) then -- GETGLOBAL
5100 Stack[Inst[1]] = Env[Const[Inst[2]]];
5101 elseif (Enum == 6) then -- GETTABLE
5102 local Stk = Stack;
5103 Stk[Inst[1]] = Stk[Inst[2]][Inst[5] or Stk[Inst[3]]];
5104 elseif (Enum == 7) then -- SETGLOBAL
5105 Env[Const[Inst[2]]] = Stack[Inst[1]];
5106 elseif (Enum == 8) then -- SETUPVAL
5107 Upvalues[Inst[2]] = Stack[Inst[1]];
5108 elseif (Enum == 9) then -- SETTABLE
5109 local Stk = Stack
5110 Stk[Inst[1]][Inst[4] or Stk[Inst[2]]] = Inst[5] or Stk[Inst[3]]
5111 elseif (Enum == 10) then -- NEWTABLE
5112 Stack[Inst[1]] = {};
5113 elseif (Enum == 11) then -- SELF
5114 local Stk = Stack;
5115 local A = Inst[1];
5116 local B = Stk[Inst[2]];
5117 local C = Inst[5] or Stk[Inst[3]];
5118 Stk[A + 1] = B;
5119 Stk[A] = B[C];
5120 elseif (Enum == 12) then -- ADD
5121 local Stk = Stack;
5122 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) + (Inst[5] or Stk[Inst[3]]);
5123 elseif (Enum == 13) then -- SUB
5124 local Stk = Stack;
5125 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) - (Inst[5] or Stk[Inst[3]]);
5126 elseif (Enum == 14) then -- MUL
5127 local Stk = Stack;
5128 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) * (Inst[5] or Stk[Inst[3]]);
5129 elseif (Enum == 15) then -- DIV
5130 local Stk = Stack;
5131 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) / (Inst[5] or Stk[Inst[3]]);
5132 elseif (Enum == 16) then -- MOD
5133 local Stk = Stack;
5134 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) % (Inst[5] or Stk[Inst[3]]);
5135 elseif (Enum == 17) then -- POW
5136 local Stk = Stack;
5137 Stk[Inst[1]] = (Inst[4] or Stk[Inst[2]]) ^ (Inst[5] or Stk[Inst[3]]);
5138 elseif (Enum == 18) then -- UNM
5139 Stack[Inst[1]] = -Stack[Inst[2]];
5140 elseif (Enum == 19) then -- NOT
5141 Stack[Inst[1]] = (not Stack[Inst[2]]);
5142 elseif (Enum == 20) then -- LEN
5143 Stack[Inst[1]] = #Stack[Inst[2]];
5144 elseif (Enum == 21) then -- CONCAT
5145 local Stk = Stack;
5146 local B = Inst[2];
5147 local K = Stk[B];
5148
5149 for Idx = B + 1, Inst[3] do
5150 K = K .. Stk[Idx];
5151 end;
5152
5153 Stack[Inst[1]] = K;
5154 elseif (Enum == 22) then -- JMP
5155 InstrPoint = InstrPoint + Inst[2];
5156 elseif (Enum == 23) then -- EQ
5157 local Stk = Stack;
5158 local B = Inst[4] or Stk[Inst[2]];
5159 local C = Inst[5] or Stk[Inst[3]];
5160
5161 if (B == C) ~= Inst[1] then
5162 InstrPoint = InstrPoint + 1;
5163 end;
5164 elseif (Enum == 24) then -- LT
5165 local Stk = Stack;
5166 local B = Inst[4] or Stk[Inst[2]];
5167 local C = Inst[5] or Stk[Inst[3]];
5168
5169 if (B < C) ~= Inst[1] then
5170 InstrPoint = InstrPoint + 1;
5171 end;
5172 elseif (Enum == 25) then -- LE
5173 local Stk = Stack;
5174 local B = Inst[4] or Stk[Inst[2]];
5175 local C = Inst[5] or Stk[Inst[3]];
5176
5177 if (B <= C) ~= Inst[1] then
5178 InstrPoint = InstrPoint + 1;
5179 end;
5180 elseif (Enum == 26) then -- TEST
5181 if Inst[3] then
5182 if Stack[Inst[1]] then
5183 InstrPoint = InstrPoint + 1;
5184 end
5185 elseif Stack[Inst[1]] then
5186 else
5187 InstrPoint = InstrPoint + 1;
5188 end
5189 elseif (Enum == 27) then -- TESTSET
5190 local B = Stack[Inst[2]];
5191
5192 if Inst[3] then
5193 if B then
5194 InstrPoint = InstrPoint + 1;
5195 else
5196 Stack[Inst[1]] = B
5197 end
5198 elseif B then
5199 Stack[Inst[1]] = B
5200 else
5201 InstrPoint = InstrPoint + 1;
5202 end
5203 elseif (Enum == 28) then -- CALL
5204 local A = Inst[1];
5205 local B = Inst[2];
5206 local C = Inst[3];
5207 local Stk = Stack;
5208 local Args, Results;
5209 local Limit, Edx;
5210
5211 Args = {};
5212
5213 if (B ~= 1) then
5214 if (B ~= 0) then
5215 Limit = A + B - 1;
5216 else
5217 Limit = Top;
5218 end;
5219
5220 Edx = 0;
5221
5222 for Idx = A + 1, Limit do
5223 Edx = Edx + 1;
5224
5225 Args[Edx] = Stk[Idx];
5226 end;
5227
5228 Limit, Results = _Returns(Stk[A](unpack(Args, 1, Limit - A)));
5229 else
5230 Limit, Results = _Returns(Stk[A]());
5231 end;
5232
5233 Top = A - 1;
5234
5235 if (C ~= 1) then
5236 if (C ~= 0) then
5237 Limit = A + C - 2;
5238 else
5239 Limit = Limit + A - 1;
5240 end;
5241
5242 Edx = 0;
5243
5244 for Idx = A, Limit do
5245 Edx = Edx + 1;
5246
5247 Stk[Idx] = Results[Edx];
5248 end;
5249 end;
5250 elseif (Enum == 29) then -- TAILCALL
5251 local A = Inst[1];
5252 local B = Inst[2];
5253 local Stk = Stack;
5254 local Args, Results;
5255 local Limit;
5256 local Rets = 0;
5257
5258 Args = {};
5259
5260 if (B ~= 1) then
5261 if (B ~= 0) then
5262 Limit = A + B - 1;
5263 else
5264 Limit = Top;
5265 end
5266
5267 for Idx = A + 1, Limit do
5268 Args[#Args + 1] = Stk[Idx];
5269 end
5270
5271 Results = {Stk[A](unpack(Args, 1, Limit - A))};
5272 else
5273 Results = {Stk[A]()};
5274 end;
5275
5276 for Index in pairs(Results) do -- get return count
5277 if (Index > Rets) then
5278 Rets = Index;
5279 end;
5280 end;
5281
5282 return Results, Rets;
5283 elseif (Enum == 30) then -- RETURN
5284 local A = Inst[1];
5285 local B = Inst[2];
5286 local Stk = Stack;
5287 local Edx, Output;
5288 local Limit;
5289
5290 if (B == 1) then
5291 return;
5292 elseif (B == 0) then
5293 Limit = Top;
5294 else
5295 Limit = A + B - 2;
5296 end;
5297
5298 Output = {};
5299 Edx = 0;
5300
5301 for Idx = A, Limit do
5302 Edx = Edx + 1;
5303
5304 Output[Edx] = Stk[Idx];
5305 end;
5306
5307 return Output, Edx;
5308 elseif (Enum == 31) then -- FORLOOP
5309 local A = Inst[1];
5310 local Stk = Stack;
5311
5312 local Step = Stk[A + 2];
5313 local Index = Stk[A] + Step;
5314
5315 Stk[A] = Index;
5316
5317 if (Step > 0) then
5318 if Index <= Stk[A + 1] then
5319 InstrPoint = InstrPoint + Inst[2];
5320
5321 Stk[A + 3] = Index;
5322 end;
5323 else
5324 if Index >= Stk[A + 1] then
5325 InstrPoint = InstrPoint + Inst[2];
5326
5327 Stk[A + 3] = Index;
5328 end
5329 end
5330 elseif (Enum == 32) then -- FORPREP
5331 local A = Inst[1];
5332 local Stk = Stack;
5333
5334 -- As per mirroring the real vm
5335 Stk[A] = assert(tonumber(Stk[A]), '`for` initial value must be a number');
5336 Stk[A + 1] = assert(tonumber(Stk[A + 1]), '`for` limit must be a number');
5337 Stk[A + 2] = assert(tonumber(Stk[A + 2]), '`for` step must be a number');
5338
5339 Stk[A] = Stk[A] - Stk[A + 2];
5340
5341 InstrPoint = InstrPoint + Inst[2];
5342 elseif (Enum == 33) then -- TFORLOOP
5343 local A = Inst[1];
5344 local C = Inst[3];
5345 local Stk = Stack;
5346
5347 local Offset = A + 2;
5348 local Result = {Stk[A](Stk[A + 1], Stk[A + 2])};
5349
5350 for Idx = 1, C do
5351 Stack[Offset + Idx] = Result[Idx];
5352 end;
5353
5354 if (Stk[A + 3] ~= nil) then
5355 Stk[A + 2] = Stk[A + 3];
5356 else
5357 InstrPoint = InstrPoint + 1;
5358 end;
5359 elseif (Enum == 34) then -- SETLIST
5360 local A = Inst[1];
5361 local B = Inst[2];
5362 local C = Inst[3];
5363 local Stk = Stack;
5364
5365 if (C == 0) then
5366 InstrPoint = InstrPoint + 1;
5367 C = Instr[InstrPoint].Value;
5368 end;
5369
5370 local Offset = (C - 1) * 50;
5371 local T = Stk[A]; -- Assuming T is the newly created table.
5372
5373 if (B == 0) then
5374 B = Top - A;
5375 end;
5376
5377 for Idx = 1, B do
5378 T[Offset + Idx] = Stk[A + Idx];
5379 end;
5380 elseif (Enum == 35) then -- CLOSE
5381 local A = Inst[1];
5382 local Cls = {}; -- Slight doubts on any issues this may cause
5383
5384 for Idx = 1, #Lupvals do
5385 local List = Lupvals[Idx];
5386
5387 for Idz = 0, #List do
5388 local Upv = List[Idz];
5389 local Stk = Upv[1];
5390 local Pos = Upv[2];
5391
5392 if (Stk == Stack) and (Pos >= A) then
5393 Cls[Pos] = Stk[Pos];
5394 Upv[1] = Cls; -- @memcorrupt credit me for the spoonfeed
5395 end;
5396 end;
5397 end;
5398 elseif (Enum == 36) then -- CLOSURE
5399 local NewProto = Proto[Inst[2]];
5400 local Stk = Stack;
5401
5402 local Indexes;
5403 local NewUvals;
5404
5405 if (NewProto.Upvals ~= 0) then
5406 Indexes = {};
5407 NewUvals = setmetatable({}, {
5408 __index = function(_, Key)
5409 local Val = Indexes[Key];
5410
5411 return Val[1][Val[2]];
5412 end,
5413 __newindex = function(_, Key, Value)
5414 local Val = Indexes[Key];
5415
5416 Val[1][Val[2]] = Value;
5417 end;
5418 }
5419 );
5420
5421 for Idx = 1, NewProto.Upvals do
5422 local Mvm = Instr[InstrPoint];
5423
5424 if (Mvm.Enum == 0) then -- MOVE
5425 Indexes[Idx - 1] = {Stk, Mvm[2]};
5426 elseif (Mvm.Enum == 4) then -- GETUPVAL
5427 Indexes[Idx - 1] = {Upvalues, Mvm[2]};
5428 end;
5429
5430 InstrPoint = InstrPoint + 1;
5431 end;
5432
5433 Lupvals[#Lupvals + 1] = Indexes;
5434 end;
5435
5436 Stk[Inst[1]] = Wrap(NewProto, Env, NewUvals);
5437 elseif (Enum == 37) then -- VARARG
5438 local A = Inst[1];
5439 local B = Inst[2];
5440 local Stk, Vars = Stack, Vararg;
5441
5442 Top = A - 1;
5443
5444 for Idx = A, A + (B > 0 and B - 1 or Varargsz) do
5445 Stk[Idx] = Vars[Idx - A];
5446 end;
5447 end;
5448 end;
5449 end;
5450
5451 local Args = {...};
5452
5453 for Idx = 0, Varargsz do
5454 if (Idx >= Chunk.Args) then
5455 Vararg[Idx - Chunk.Args] = Args[Idx + 1];
5456 else
5457 Stack[Idx] = Args[Idx + 1];
5458 end;
5459 end;
5460
5461 local A, B, C = pcall(Loop); -- Pcalling to allow yielding
5462
5463 if A then -- We're always expecting this to come out true (because errorless code)
5464 if B and (C > 0) then -- So I flipped the conditions.
5465 return unpack(B, 1, C);
5466 end;
5467
5468 return;
5469 else
5470 OnError(B, InstrPoint - 1); -- Didn't get time to test the `-1` honestly, but I assume it works properly
5471 end;
5472 end;
5473 end;
5474
5475 return function(BCode, Env) -- lua_function LoadBytecode (string BCode, table Env)
5476 local Buffer = GetMeaning(BCode);
5477
5478 return Wrap(Buffer, Env or getfenv(0)), Buffer;
5479 end;
5480
5481 end
5482 fake_module_scripts[script] = module_script
5483end
5484