-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathvar.lua
More file actions
132 lines (122 loc) · 3.52 KB
/
var.lua
File metadata and controls
132 lines (122 loc) · 3.52 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
local var = {}
require 'stringx'
require 'tablex'
function var.getvar(n, tblctx)
tblctx = tblctx or _G
-- dotted name -> nested field access:
local dotPos = string.find(n, '%.')
if dotPos then
assert(dotPos > 1, 'unsupported syntax')
local n1 = n:sub(1, dotPos - 1)
n = n:sub(dotPos + 1)
assert(n ~= '', 'unsupported syntax')
tblctx = tblctx[n1]
if tblctx == nil then return nil end
return var.getvar(n, tblctx, opts)
end
-- square-brackets index operator:
local base, idx = n:match('^(.-)%[(%d+)%]$')
if base then
local i = tonumber(idx)
tblctx = tblctx[base]
return tblctx and tblctx[i] or nil
end
-- simple field access:
return tblctx[n]
end
function var.setvar(n, v, tblctx)
tblctx = tblctx or _G
local ns = string.split(n, '.', true)
if #ns > 1 then
if tblctx[ns[1]] == nil then tblctx[ns[1]] = {} end
var.setvar(table.join(table.slice(ns, 2), '.'), v, tblctx[ns[1]])
return
end
local is = string.split(n, '[', true)
if #is == 1 then
tblctx[n] = v
return
end
assert(#is == 2, 'unsupported syntax')
local it = string.split(is[2], ']', true)
assert(#it == 2, 'unsupported syntax')
assert(it[2] == '', 'unsupported syntax')
local i = it[1]
i = tonumber(i)
tblctx[is[1]][i] = v
end
function var.getlocals(level)
local ret = {}
local i = 0
while true do
i = i + 1
if level then
local name, value = debug.getlocal(level + 1, i)
if not name then return ret end
ret[name] = value
else
if not pcall(
function()
ret[i] = var.getlocals(i)
end
) then break end
if not next(ret[i]) then break end
end
end
return ret
end
function var.f(str)
str = str:gsub(
'{(.-)}',
function(name0)
local value, opts, name = nil, {pctopt = 's'}, name0
if name:sub(-1, -1) == '=' then
opts.equal = true
name = name:sub(1, -2)
end
if name:find(':') then
local p = string.split(name, ':')
assert(#p == 2, 'incorrect syntax')
name = p[1]
opts.pctopt = p[2]
end
for i = 1, 1e100 do
local n, v = debug.getlocal(4, i)
if not n then break end
if name == n then
value = v;
break
end
end
if value == nil and _G[name] then value = _G[name] end
if value ~= nil then
value = string.format('%' .. opts.pctopt, value)
if opts.equal then value = name .. '=' .. value end
return value
else
return string.format('{%s}', name0)
end
end
)
return str
end
function var.unittest()
a = 'x1'
assert(var.getvar 'a' == 'x1')
b = {c = 'x2'}
assert(var.getvar 'b.c' == 'x2')
d = {'x3', 'y3', 'z3'}
assert(var.getvar 'd[3]' == 'z3')
e = {f = {'a', 'b'}}
assert(var.getvar 'e.f[1]' == 'a')
var.setvar('e.f[1]', 'A')
assert(var.getvar 'e.f[1]' == 'A')
var.setvar('g.h', 'x')
assert(g.h == 'x')
local l1 = 'a'
local l2 = 'b'
local L = var.getlocals(1)
assert(L.l1 == 'a' and L.l2 == 'b')
print(debug.getinfo(1, 'S').source, 'tests passed')
end
return var