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