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