|
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