|
6 | 6 | (m::Model)(args...; kw...) = m.f(args...; kw...) |
7 | 7 |
|
8 | 8 | for f in (:connector, :mtkmodel) |
| 9 | + isconnector = f == :connector ? true : false |
9 | 10 | @eval begin |
10 | 11 | macro $f(name::Symbol, body) |
11 | | - esc($(Symbol(f, :_macro))(__module__, name, body)) |
| 12 | + esc($(:_model_macro)(__module__, name, body, $isconnector)) |
12 | 13 | end |
13 | 14 | end |
14 | 15 | end |
15 | 16 |
|
16 | | -@inline is_kwarg(::Symbol) = false |
17 | | -@inline is_kwarg(e::Expr) = (e.head == :parameters) |
18 | | - |
19 | | -function connector_macro(mod, name, body) |
20 | | - if !Meta.isexpr(body, :block) |
21 | | - err = """ |
22 | | - connector body must be a block! It should be in the form of |
23 | | - ``` |
24 | | - @connector Pin begin |
25 | | - v(t) = 1 |
26 | | - (i(t) = 1), [connect = Flow] |
27 | | - end |
28 | | - ``` |
29 | | - """ |
30 | | - error(err) |
31 | | - end |
32 | | - vs = [] |
33 | | - kwargs = [] |
34 | | - icon = Ref{Union{String, URI}}() |
| 17 | +function _model_macro(mod, name, expr, isconnector) |
| 18 | + exprs = Expr(:block) |
35 | 19 | dict = Dict{Symbol, Any}() |
36 | 20 | dict[:kwargs] = Dict{Symbol, Any}() |
37 | | - expr = Expr(:block) |
38 | | - for arg in body.args |
| 21 | + comps = Symbol[] |
| 22 | + ext = Ref{Any}(nothing) |
| 23 | + eqs = Expr[] |
| 24 | + icon = Ref{Union{String, URI}}() |
| 25 | + vs = [] |
| 26 | + ps = [] |
| 27 | + kwargs = [] |
| 28 | + |
| 29 | + for arg in expr.args |
39 | 30 | arg isa LineNumberNode && continue |
40 | | - if arg.head == :macrocall && arg.args[1] == Symbol("@icon") |
41 | | - parse_icon!(icon, dict, dict, arg.args[end]) |
42 | | - continue |
| 31 | + if arg.head == :macrocall |
| 32 | + parse_model!(exprs.args, comps, ext, eqs, icon, vs, ps, |
| 33 | + dict, mod, arg, kwargs) |
| 34 | + elseif arg.head == :block |
| 35 | + push!(exprs.args, arg) |
| 36 | + elseif isconnector |
| 37 | + # Connectors can have variables listed without `@variables` prefix or |
| 38 | + # begin block. |
| 39 | + parse_variable_arg!(exprs, vs, dict, mod, arg, :variables, kwargs) |
| 40 | + else |
| 41 | + error("$arg is not valid syntax. Expected a macro call.") |
43 | 42 | end |
44 | | - parse_variable_arg!(expr, vs, dict, mod, arg, :variables, kwargs) |
45 | 43 | end |
| 44 | + |
46 | 45 | iv = get(dict, :independent_variable, nothing) |
47 | 46 | if iv === nothing |
48 | | - error("$name doesn't have a independent variable") |
| 47 | + iv = dict[:independent_variable] = variable(:t) |
49 | 48 | end |
50 | | - gui_metadata = isassigned(icon) ? GUIMetadata(GlobalRef(mod, name), icon[]) : |
| 49 | + |
| 50 | + gui_metadata = isassigned(icon) > 0 ? GUIMetadata(GlobalRef(mod, name), icon[]) : |
51 | 51 | GUIMetadata(GlobalRef(mod, name)) |
52 | 52 |
|
53 | | - quote |
54 | | - $name = $Model((; name, $(kwargs...)) -> begin |
55 | | - $expr |
56 | | - var"#___sys___" = $ODESystem($(Equation[]), $iv, [$(vs...)], $([]); |
57 | | - name, gui_metadata = $gui_metadata) |
58 | | - $Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___")) |
59 | | - end, $dict, true) |
| 53 | + sys = :($ODESystem($Equation[$(eqs...)], $iv, [$(vs...)], [$(ps...)]; |
| 54 | + name, systems = [$(comps...)], gui_metadata = $gui_metadata)) |
| 55 | + |
| 56 | + if ext[] === nothing |
| 57 | + push!(exprs.args, :(var"#___sys___" = $sys)) |
| 58 | + else |
| 59 | + push!(exprs.args, :(var"#___sys___" = $extend($sys, $(ext[])))) |
60 | 60 | end |
| 61 | + |
| 62 | + isconnector && push!(exprs.args, |
| 63 | + :($Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___")))) |
| 64 | + |
| 65 | + f = :($(Symbol(:__, name, :__))(; name, $(kwargs...)) = $exprs) |
| 66 | + :($name = $Model($f, $dict, $isconnector)) |
61 | 67 | end |
62 | 68 |
|
63 | 69 | function parse_variable_def!(dict, mod, arg, varclass, kwargs, def = nothing) |
@@ -207,48 +213,6 @@ function get_var(mod::Module, b) |
207 | 213 | end |
208 | 214 | end |
209 | 215 |
|
210 | | -function mtkmodel_macro(mod, name, expr) |
211 | | - exprs = Expr(:block) |
212 | | - dict = Dict{Symbol, Any}() |
213 | | - dict[:kwargs] = Dict{Symbol, Any}() |
214 | | - comps = Symbol[] |
215 | | - ext = Ref{Any}(nothing) |
216 | | - eqs = Expr[] |
217 | | - icon = Ref{Union{String, URI}}() |
218 | | - vs = [] |
219 | | - ps = [] |
220 | | - kwargs = [] |
221 | | - |
222 | | - for arg in expr.args |
223 | | - arg isa LineNumberNode && continue |
224 | | - if arg.head == :macrocall |
225 | | - parse_model!(exprs.args, comps, ext, eqs, icon, vs, ps, |
226 | | - dict, mod, arg, kwargs) |
227 | | - elseif arg.head == :block |
228 | | - push!(exprs.args, arg) |
229 | | - else |
230 | | - error("$arg is not valid syntax. Expected a macro call.") |
231 | | - end |
232 | | - end |
233 | | - iv = get(dict, :independent_variable, nothing) |
234 | | - if iv === nothing |
235 | | - iv = dict[:independent_variable] = variable(:t) |
236 | | - end |
237 | | - |
238 | | - gui_metadata = isassigned(icon) > 0 ? GUIMetadata(GlobalRef(mod, name), icon[]) : |
239 | | - GUIMetadata(GlobalRef(mod, name)) |
240 | | - |
241 | | - sys = :($ODESystem($Equation[$(eqs...)], $iv, [$(vs...)], [$(ps...)]; |
242 | | - systems = [$(comps...)], name, gui_metadata = $gui_metadata)) #, defaults = $defaults)) |
243 | | - if ext[] === nothing |
244 | | - push!(exprs.args, sys) |
245 | | - else |
246 | | - push!(exprs.args, :($extend($sys, $(ext[])))) |
247 | | - end |
248 | | - |
249 | | - :($name = $Model((; name, $(kwargs...)) -> $exprs, $dict, false)) |
250 | | -end |
251 | | - |
252 | 216 | function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict, |
253 | 217 | mod, arg, kwargs) |
254 | 218 | mname = arg.args[1] |
|
0 commit comments