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