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