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