@@ -10,241 +10,6 @@ macro connector(expr)
10
10
esc (component_post_processing (expr, true ))
11
11
end
12
12
13
- macro connector (name:: Symbol , body)
14
- esc (connector_macro (__module__, name, body))
15
- end
16
-
17
- struct Model{F, S}
18
- f:: F
19
- structure:: S
20
- end
21
- (m:: Model )(args... ; kw... ) = m. f (args... ; kw... )
22
-
23
- using MLStyle
24
- function connector_macro (mod, name, body)
25
- if ! Meta. isexpr (body, :block )
26
- err = """
27
- connector body must be a block! It should be in the form of
28
- ```
29
- @connector Pin begin
30
- v(t) = 1
31
- (i(t) = 1), [connect = Flow]
32
- end
33
- ```
34
- """
35
- error (err)
36
- end
37
- vs = Num[]
38
- dict = Dict {Symbol, Any} ()
39
- for arg in body. args
40
- arg isa LineNumberNode && continue
41
- push! (vs, Num (parse_variable_def! (dict, mod, arg, :variables )))
42
- end
43
- iv = get (dict, :independent_variable , nothing )
44
- if iv === nothing
45
- error (" $name doesn't have a independent variable" )
46
- end
47
- quote
48
- $ name = $ Model ((; name) -> begin
49
- var"#___sys___" = $ ODESystem ($ (Equation[]), $ iv, $ vs, $ ([]);
50
- name)
51
- $ Setfield. @set! (var"#___sys___" . connector_type= $ connector_type (var"#___sys___" ))
52
- end , $ dict)
53
- end
54
- end
55
-
56
- function parse_variable_def! (dict, mod, arg, varclass)
57
- MLStyle. @match arg begin
58
- :: Symbol => generate_var! (dict, arg, varclass)
59
- Expr (:call , a, b) => generate_var! (dict, a, b, varclass)
60
- Expr (:(= ), a, b) => begin
61
- var = parse_variable_def! (dict, mod, a, varclass)
62
- def = parse_default (mod, b)
63
- dict[varclass][getname (var)][:default ] = def
64
- setdefault (var, def)
65
- end
66
- Expr (:tuple , a, b) => begin
67
- var = parse_variable_def! (dict, mod, a, varclass)
68
- meta = parse_metadata (mod, b)
69
- if (ct = get (meta, VariableConnectType, nothing )) != = nothing
70
- dict[varclass][getname (var)][:connection_type ] = nameof (ct)
71
- end
72
- set_var_metadata (var, meta)
73
- end
74
- _ => error (" $arg cannot be parsed" )
75
- end
76
- end
77
-
78
- function generate_var (a, varclass)
79
- var = Symbolics. variable (a)
80
- if varclass == :parameters
81
- var = toparam (var)
82
- end
83
- var
84
- end
85
- function generate_var! (dict, a, varclass)
86
- var = generate_var (a, varclass)
87
- vd = get! (dict, varclass) do
88
- Dict {Symbol, Dict{Symbol, Any}} ()
89
- end
90
- vd[a] = Dict {Symbol, Any} ()
91
- var
92
- end
93
- function generate_var! (dict, a, b, varclass)
94
- iv = generate_var (b, :variables )
95
- prev_iv = get! (dict, :independent_variable ) do
96
- iv
97
- end
98
- @assert isequal (iv, prev_iv)
99
- vd = get! (dict, varclass) do
100
- Dict {Symbol, Dict{Symbol, Any}} ()
101
- end
102
- vd[a] = Dict {Symbol, Any} ()
103
- var = Symbolics. variable (a, T = SymbolicUtils. FnType{Tuple{Real}, Real})(iv)
104
- if varclass == :parameters
105
- var = toparam (var)
106
- end
107
- var
108
- end
109
- function parse_default (mod, a)
110
- a = Base. remove_linenums! (deepcopy (a))
111
- MLStyle. @match a begin
112
- Expr (:block , a) => get_var (mod, a)
113
- :: Symbol => get_var (mod, a)
114
- :: Number => a
115
- _ => error (" Cannot parse default $a " )
116
- end
117
- end
118
- function parse_metadata (mod, a)
119
- MLStyle. @match a begin
120
- Expr (:vect , eles... ) => Dict (parse_metadata (mod, e) for e in eles)
121
- Expr (:(= ), a, b) => Symbolics. option_to_metadata_type (Val (a)) => get_var (mod, b)
122
- _ => error (" Cannot parse metadata $a " )
123
- end
124
- end
125
- function set_var_metadata (a, ms)
126
- for (m, v) in ms
127
- a = setmetadata (a, m, v)
128
- end
129
- a
130
- end
131
- function get_var (mod:: Module , b)
132
- b isa Symbol ? getproperty (mod, b) : b
133
- end
134
- macro model (name:: Symbol , expr)
135
- esc (model_macro (__module__, name, expr))
136
- end
137
- function model_macro (mod, name, expr)
138
- exprs = Expr (:block )
139
- dict = Dict {Symbol, Any} ()
140
- comps = Symbol[]
141
- ext = Ref {Any} (nothing )
142
- vs = Symbol[]
143
- ps = Symbol[]
144
- eqs = Expr[]
145
- for arg in expr. args
146
- arg isa LineNumberNode && continue
147
- arg. head == :macrocall || error (" $arg is not valid syntax. Expected a macro call." )
148
- parse_model! (exprs. args, comps, ext, eqs, vs, ps, dict, mod, arg)
149
- end
150
- iv = get (dict, :independent_variable , nothing )
151
- if iv === nothing
152
- iv = dict[:independent_variable ] = variable (:t )
153
- end
154
- sys = :($ ODESystem ($ Equation[$ (eqs... )], $ iv, [$ (vs... )], [$ (ps... )];
155
- systems = [$ (comps... )], name))
156
- if ext[] === nothing
157
- push! (exprs. args, sys)
158
- else
159
- push! (exprs. args, :($ extend ($ sys, $ (ext[]))))
160
- end
161
- :($ name = $ Model ((; name) -> $ exprs, $ dict))
162
- end
163
- function parse_model! (exprs, comps, ext, eqs, vs, ps, dict, mod, arg)
164
- mname = arg. args[1 ]
165
- body = arg. args[end ]
166
- if mname == Symbol (" @components" )
167
- parse_components! (exprs, comps, dict, body)
168
- elseif mname == Symbol (" @extend" )
169
- parse_extend! (exprs, ext, dict, body)
170
- elseif mname == Symbol (" @variables" )
171
- parse_variables! (exprs, vs, dict, mod, body, :variables )
172
- elseif mname == Symbol (" @parameters" )
173
- parse_variables! (exprs, ps, dict, mod, body, :parameters )
174
- elseif mname == Symbol (" @equations" )
175
- parse_equations! (exprs, eqs, dict, body)
176
- else
177
- error (" $mname is not handled." )
178
- end
179
- end
180
- function parse_components! (exprs, cs, dict, body)
181
- expr = Expr (:block )
182
- push! (exprs, expr)
183
- comps = Vector{String}[]
184
- for arg in body. args
185
- arg isa LineNumberNode && continue
186
- MLStyle. @match arg begin
187
- Expr (:(= ), a, b) => begin
188
- push! (cs, a)
189
- push! (comps, [String (a), String (b. args[1 ])])
190
- arg = deepcopy (arg)
191
- b = deepcopy (arg. args[2 ])
192
- push! (b. args, Expr (:kw , :name , Meta. quot (a)))
193
- arg. args[2 ] = b
194
- push! (expr. args, arg)
195
- end
196
- _ => error (" `@components` only takes assignment expressions. Got $arg " )
197
- end
198
- end
199
- dict[:components ] = comps
200
- end
201
- function parse_extend! (exprs, ext, dict, body)
202
- expr = Expr (:block )
203
- push! (exprs, expr)
204
- body = deepcopy (body)
205
- MLStyle. @match body begin
206
- Expr (:(= ), a, b) => begin
207
- vars = nothing
208
- if Meta. isexpr (b, :(= ))
209
- vars = a
210
- if ! Meta. isexpr (vars, :tuple )
211
- error (" `@extend` destructuring only takes an tuple as LHS. Got $body " )
212
- end
213
- a, b = b. args
214
- vars, a, b
215
- end
216
- ext[] = a
217
- push! (b. args, Expr (:kw , :name , Meta. quot (a)))
218
- dict[:extend ] = [Symbol .(vars. args), a, readable_code (b)]
219
- push! (expr. args, :($ a = $ b))
220
- if vars != = nothing
221
- push! (expr. args, :(@unpack $ vars = $ a))
222
- end
223
- end
224
- _ => error (" `@extend` only takes an assignment expression. Got $body " )
225
- end
226
- end
227
- function parse_variables! (exprs, vs, dict, mod, body, varclass)
228
- expr = Expr (:block )
229
- push! (exprs, expr)
230
- for arg in body. args
231
- arg isa LineNumberNode && continue
232
- vv = parse_variable_def! (dict, mod, arg, varclass)
233
- v = Num (vv)
234
- name = getname (v)
235
- push! (vs, name)
236
- push! (expr. args, :($ name = $ v))
237
- end
238
- end
239
- function parse_equations! (exprs, eqs, dict, body)
240
- for arg in body. args
241
- arg isa LineNumberNode && continue
242
- push! (eqs, arg)
243
- end
244
- # TODO : does this work with TOML?
245
- dict[:equations ] = readable_code .(eqs)
246
- end
247
-
248
13
abstract type AbstractConnectorType end
249
14
struct StreamConnector <: AbstractConnectorType end
250
15
struct RegularConnector <: AbstractConnectorType end
0 commit comments