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