-
Notifications
You must be signed in to change notification settings - Fork 105
Expand file tree
/
Copy pathreadwrite.lua
More file actions
144 lines (140 loc) · 2.54 KB
/
readwrite.lua
File metadata and controls
144 lines (140 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
local source, level = ...
level = (level or 0) + 2
local _load
local _pack
local _unpack
if _VERSION == "Lua 5.1" then
_load = loadstring
_pack = function (...)
local t = {...}
t.n = select("#", ...)
return t
end
_unpack = unpack
else
_load = load
_pack = table.pack
_unpack = table.unpack
end
local f = assert(debug.getinfo(level,"f").func, "can't find function")
local args_name = {}
local args_value = {}
local updates = {}
local env
do
local i = 1
while true do
local name, value = debug.getupvalue(f, i)
if name == nil then
break
end
if #name > 0 then
if name == "_ENV" then
env = value
else
args_name[#args_name+1] = name
args_value[name] = value
updates[#updates+1] = ("{'u',name=%q,idx=%d,val=%s}"):format(name, i, name)
end
end
i = i + 1
end
end
if not env and getfenv then
env = getfenv(f)
end
do
local i = 1
while true do
local name, value = debug.getlocal(level, i)
if name == nil then
break
end
if name:byte() ~= 40 then -- '('
args_name[#args_name+1] = name
args_value[name] = value
updates[#updates+1] = ("{'l',name=%q,idx=%d,val=%s}"):format(name, i, name)
end
i = i + 1
end
end
local full_source
if #args_name > 0 then
full_source = ([[
local $ARGS
return function(...)
$SOURCE
end,
function()
return {$UPDATES}
end
]]):gsub("%$(%w+)", {
ARGS = table.concat(args_name, ","),
SOURCE = source,
UPDATES = table.concat(updates, ','),
})
else
full_source = ([[
return function(...)
$SOURCE
end,
function()
return {$UPDATES}
end
]]):gsub("%$(%w+)", {
SOURCE = source,
UPDATES = table.concat(updates, ','),
})
end
local compiled = env
and assert(_load(full_source, '=(EVAL)', "t", env))
or assert(_load(full_source, '=(EVAL)'))
if env and setfenv then
setfenv(compiled, env)
end
local func, update = compiled()
local found = {}
do
local i = 1
while true do
local name = debug.getupvalue(func, i)
if name == nil then
break
end
if name ~= "_ENV" then
debug.setupvalue(func, i, args_value[name])
end
found[name] = true
i = i + 1
end
end
local rets
do
local vararg, v = debug.getlocal(level, -1)
if vararg then
local vargs = { v }
local i = 2
while true do
vararg, v = debug.getlocal(level, -i)
if vararg then
vargs[i] = v
else
break
end
i = i + 1
end
rets = _pack(func(_unpack(vargs)))
else
rets = _pack(func())
end
end
for _, info in ipairs(update()) do
if found[info.name] then
if info[1] == 'l' then
debug.setlocal(level, info.idx, info.val)
else
debug.setupvalue(f, info.idx, info.val)
end
end
end
return _unpack(rets)