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