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