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