-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathflux.lua
184 lines (154 loc) · 3.98 KB
/
flux.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
174
175
176
177
178
179
180
181
182
183
184
local flux = {}
local lexer = require("flux.lexer")
flux.tokenize = lexer.tokenize
local init_data
local weak_key = { __mode = "k" }
local weak_value = { __mode = "v" }
local modules = {
default = {}
}
local names = setmetatable({}, weak_key)
local objects = setmetatable({}, weak_value)
local dependents = setmetatable({}, weak_key)
local requirements_rev = setmetatable({}, weak_key)
local requirements = setmetatable({}, weak_key)
local modes = setmetatable({}, weak_key)
function flux.init(init_data_)
init_data = init_data_
end
function flux.register(name, object)
names[object] = name
objects[name] = object
return object
end
function flux.load_modules(dirname, basename)
local lfs = require("lfs")
for f in lfs.dir(dirname) do
local name = f:match("^(.*)%.lua$")
if name then
local pok, mod = pcall(require, basename .. "." .. name)
if pok and mod then
local aliases = mod.init(init_data)
modules[name] = mod
if aliases then
for _, alias in ipairs(aliases) do
modules[alias] = mod
end
end
else
io.stderr:write("----------------------------------------\n")
io.stderr:write("Error loading module " .. name .. ":\n")
io.stderr:write(mod .. "\n")
io.stderr:write("----------------------------------------\n")
end
end
end
end
function flux.depend(a, b)
dependents[a] = dependents[a] or setmetatable({}, weak_key)
dependents[a][b] = true
end
function flux.each_dependent(a)
local k
if not dependents[a] then
return function() end
end
return function()
k = next(dependents[a], k)
return k
end
end
function flux.undepend(a, b)
if dependents[a] then
dependents[a][b] = nil
end
end
function flux.require(a, b)
requirements[a] = requirements[a] or setmetatable({}, weak_key)
requirements[a][b] = true
requirements_rev[b] = requirements_rev[b] or setmetatable({}, weak_key)
requirements_rev[b][a] = true
end
function flux.each_requirement(a)
local k
if not requirements[a] then
return function() end
end
return function()
k = next(requirements[a], k)
return k
end
end
function flux.each_requirement_rev(b)
local k
if not requirements_rev[b] then
return function() end
end
return function()
k = next(requirements_rev[b], k)
return k
end
end
function flux.unrequire(a, b)
if requirements[a] then
requirements[a][b] = nil
end
end
function flux.get(name, fallback)
return objects[name]
end
local function call(op, object, ...)
local mode = modes[object]
if mode and modules[mode] and modules[mode][op] then
return modules[mode][op](object, ...)
else
return false
end
end
function flux.eval(object, trigger_object, loop_ctrl)
loop_ctrl = loop_ctrl or {}
if loop_ctrl[object] then
return
end
loop_ctrl[object] = true
for req in flux.each_requirement(object) do
flux.eval(req, object, loop_ctrl)
end
call("eval", object, trigger_object)
for req in flux.each_requirement_rev(object) do
flux.eval(req, object, loop_ctrl)
end
for dep in flux.each_dependent(object) do
flux.eval(dep, object, loop_ctrl)
end
end
function flux.on_key(object, key, is_text, is_repeat)
return call("on_key", object, key, is_text, is_repeat)
end
function flux.value(name, fallback)
if objects[name] then
local ok, value = call("value", objects[name])
if ok then
return true, value
end
end
return false, fallback
end
function flux.frame()
for _, mod in pairs(modules) do
if mod.frame then
mod.frame()
end
end
end
function flux.set_mode(object, mode, creator_object)
if modules[mode] then
modes[object] = mode
call("enable", object, creator_object)
end
return object
end
function flux.get_mode(object)
return modes[object] or "default"
end
return flux