-
Notifications
You must be signed in to change notification settings - Fork 0
/
ldebug.lua
173 lines (172 loc) · 5.21 KB
/
ldebug.lua
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
-- this is gonna be typecheck and un implemented functions, 4 sure
function typecast(var,type_)
local vartype = type(var)
if vartype==type_ then return true,var end
if vartype=="string" then
if type_=="number" then
local new = tonumber(var)
if new then
return true, new
else
return false, nil
end
end
elseif vartype=="number" then
if type_=="string" then
return true, tostring(var)
end
end
return false, nil
end
function typecheck(var,pos,name,typ)
if type(typ)=="string" then
if type(var)~=typ then
error("bad argument #"..pos.." to '"..name.."' ("..typ.." expected, got "..(var==nil and "no value" or type(var))..")",3)
end
elseif type(typ)=="table" then
local mat = false
for _,v in next,typ do
if type(var)==v then mat=true;break end
end
if not mat then
error("bad argument #"..pos.." to '"..name.."' ("..typ[1].." expected, got "..(var==nil and "no value" or type(var))..")",3)
end
end
end
function typecheckv(name,types,...)
local can_cast = types.implicit_casting
local nargs,args = select('#',...),{...}
local ret = {}
for i,v in next,types do
if type(i)=="number" then
local val = args[i]
local type_ = type(val)
local is_none = i>nargs and val==nil
local required = not v.optional
if v.custom then
local success,reason = v[1](val,type_,is_none,(can_cast and typecast) or nil)
if required and success==nil then
error('bad argument #'..i.." to '"..name.."'"..(reason~=nil and " ("..reason..")" or ""),3)
end
if success~=nil then
val=success
end
else
local matched,bad_typecast = false,false
if not is_none then
if v.any then
matched=true
else
for ti,b in next,v do
--print('awlcast',typecast(val,b))
if type(ti)=="number" and (type_==b or can_cast) then
if can_cast then
local s,r = typecast(val,b)
--print('cast',s,r)
val=r
if not s then
bad_typecast=true;break
end
end
matched=true;break
end
end
end
end
--print(matched,required,bad_typecast)
if not matched then
if required or bad_typecast then
error("bad argument #"..i.." to '"..name.."' ("..v[1].." expected, got "..(is_none and 'no value' or type_)..")",3)
elseif v.default and is_none then
val=v.default
end
end
end
ret[i]=val
end
end
return unpack(ret)
end
local function tycui(name,types)
return function(...)
typecheckv(name,types,...)
error("'"..name.."' is unimplemented.")
end
end
local stacklvl = {'function','thread','number'};
local debug = {}
debug.getinfo = tycui('getinfo',{
implicit_casting=true;
stacklvl;
{function(val,type_,is_none,typecast)
if type_~="string" and not is_none then
if typecast then
local s,r = typecast(val,type_)
if s then
val=r
else
return false,'expected string, got '..(is_none and 'no value' or type_)
end
else
return false,'expected string, got '..(is_none and 'no value' or type_)
end
end
if (string.gsub(val,'nfSlu',''))~="" then
return false, 'invalid option'
end
return (is_none and 'nfSlu') or val
end,custom=true};
})
debug.getlocal = tycui('getlocal',{
implicit_casting=true;
stacklvl;
{'number'};
})
debug.setlocal = tycui('setlocal',{
implicit_casting=true;
stacklvl;
{'number'};
{any=true,optional=true};
})
debug.getupvalue = tycui('getupvalue',{
implicit_casting=true;
stacklvl;
{'number'};
})
debug.setupvalue = tycui('setupvalue',{
implicit_casting=true;
stacklvl;
{'number'};
{any=true,optional=true};
})
debug.sethook = tycui('sethook',{
implicit_casting=true;
{'function'};
{function(val,type_,is_none,typecast)
if type_~="string" then
if typecast then
local s,r = typecast(val,type_)
if s then
val=r
else
return nil,'expected string, got '..(is_none and 'no value' or type_)
end
else
return nil,'expected string, got '..(is_none and 'no value' or type_)
end
end
for i=1,#val do
local c = val:sub(i,i)
if c~="c" and c~="r" and c~="l" then return nil, 'invalid option' end
end
return val
end,custom=true};
{'number',optional=true};
})
debug.gethook = tycui('gethook',{stacklvl})
for _,v in next, {"setfenv", "getfenv", "getregistry", "getmetatable", "setmetatable", "debug"} do
debug[v] = function()
error("'"..v.."' is unimplemented.",2)
end
end
return debug