-
Notifications
You must be signed in to change notification settings - Fork 0
/
fb.lua
176 lines (143 loc) · 4.5 KB
/
fb.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
--[[
Function block processing
#########################
1. Built-in function block (/)
2. Specify a function block (/)
3. Specify a function chart (/)
4. Use a function chart as a function block
5. Instantiate a function chart (/)
6. Single-step a function chart (/)
--]]
local data = require('data_item')
local function fb_reset_default(fb)
for _, item in pairs(fb.data_items) do
item:reset()
end
fb.has_changed = false
end
local function fb_new(fb_spec, name, fc_inst)
local fb_inst = {}
fb_inst.name = name
fb_inst.fb_spec = fb_spec
fb_inst.reset = fb_spec.reset
local data_items = {}
local data = {}
for _, data_spec in pairs(fb_spec.data_specs) do
local data_item_name = name .. '.' .. data_spec.name
data_item = data_spec:new_item(data_item_name, nil, fb_inst)
data_items[data_item_name] = data_item
data[data_spec.name] = data_item
end
fb_inst.data_items = data_items
fb_inst.data = data
fb_inst.fc_inst = fc_inst
return fb_inst
end
-- Specification for a function block
-- ----------------------------------
-- name: A unique name for the function block
-- inputs: A list of the input variables
-- outputs: A list of the output variables
-- algorithm: A function that re-calculates the outputs
-- reset: One of
-- * nil: state_vars are reset to their default values
-- * function: the function sets each state var
-- * table: state vars are reset to values from the table
-- There are three ways to create a new function block spec:
-- * call the function passing the inputs parameters as positional parameters
-- * call the function, passing a table as a parameter with positional parameters
-- * call the function, passing a table as a parameter with named parameters
local function fb_spec_new(name, inputs, outputs, state_vars, algorithm, reset, time)
local fb_spec = {}
if type(name) == 'table' then
local t = name
if #t ~= 0 then
fb_spec.name = t[1]
fb_spec.input_specs = t[2] or {}
fb_spec.output_specs = t[3] or {}
fb_spec.state_var_specs = t[4] or {}
fb_spec.algorithm = t[5] or function() return true end
fb_spec.reset = t[6]
fb_spec.time = t[7]
else
fb_spec.name = t.name
fb_spec.input_specs = t.inputs or {}
fb_spec.output_specs = t.outputs or {}
fb_spec.state_var_specs = t.state_vars or {}
fb_spec.algorithm = t.algorithm or function() return true end
fb_spec.reset = t.reset
fb_spec.time = t.time
end
else
fb_spec.name = name or '<noname>'
fb_spec.input_specs = inputs or {}
fb_spec.output_specs = outputs or {}
fb_spec.state_var_specs = state_vars or {}
fb_spec.algorithm = algorithm or function() return true end
fb_spec.reset = reset
fb_spec.time = time
end
fb_spec.new_inst = fb_new
if type(fb_spec.reset) == 'function' or type(fb_spec.reset) == 'table' then
fb_spec.reset = reset
else
-- TODO: Log that we are using default reset function
fb_spec.reset = fb_reset_default
end
local valid = true
local msgs = {}
if fb_spec.name == nil then
valid = false
msgs[#msgs+1] = "No name provided."
end
local data_specs = {}
for _, s in ipairs(fb_spec.input_specs) do
s.fb_spec = fb_spec
fb_spec.input_specs[s.name] = s
if data_specs[s.name] ~= nil then
valid = false
msgs[#msgs+1] = 'Duplicate name: ' .. s.name
else
data_specs[s.name] = s
end
end
for _, s in ipairs(fb_spec.output_specs) do
s.fb_spec = fb_spec
fb_spec.output_specs[s.name] = s
if data_specs[s.name] ~= nil then
valid = false
msgs[#msgs+1] = 'Duplicate name: ' .. s.name
else
data_specs[s.name] = s
end
end
for _, s in ipairs(fb_spec.state_var_specs) do
s.fb_spec = fb_spec
fb_spec.state_var_specs[s.name] = s
if data_specs[s.name] ~= nil then
valid = false
msgs[#msgs+1] = 'Duplicate name: ' .. s.name
else
data_specs[s.name] = s
end
end
fb_spec.data_specs = data_specs
if valid then
return fb_spec
else
return err, table.concat(msgs, '\n')
end
end
local function fb_reset(fb)
if type(fb.reset) == 'function' then
fb.reset(fb)
elseif type (fb.reset) == 'table' then
else
fb_reset_default(fb)
end
end
local fb =
{
spec_new = fb_spec_new,
}
return fb