Skip to content

Commit a7f77f3

Browse files
committed
feat: connectors now accept args/kwargs + default values can be set for @variables in connector
- This allows to pass default values of variables via kwargs
1 parent 9b25993 commit a7f77f3

File tree

2 files changed

+37
-31
lines changed

2 files changed

+37
-31
lines changed

src/systems/model_parsing.jl

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
1-
macro connector(name::Symbol, body)
2-
esc(connector_macro(__module__, name, body))
3-
end
4-
51
struct Model{F, S}
62
f::F
73
structure::S
84
end
95
(m::Model)(args...; kw...) = m.f(args...; kw...)
106

11-
function connector_macro(mod, name, body)
7+
for f in (:connector, :model)
8+
@eval begin
9+
macro $f(name::Symbol, body)
10+
esc($(Symbol(f, :_macro))(__module__, name, body))
11+
end
12+
13+
macro $f(fcall::Expr, body)
14+
fcall.head == :call || "Couldn't comprehend the $f $arg"
15+
16+
arglist, kwargs = if lastindex(fcall.args) > 1 && is_kwarg(fcall.args[2])
17+
(lastindex(fcall.args) > 2 ? Set(fcall.args[3:end]) : Set()),
18+
Set(fcall.args[2].args)
19+
else
20+
Set(), Set(fcall.args[2:end])
21+
end
22+
esc($(Symbol(f, :_macro))(__module__, fcall.args[1], body; arglist, kwargs))
23+
end
24+
end
25+
end
26+
27+
@inline is_kwarg(::Symbol) = false
28+
@inline is_kwarg(e::Expr) = (e.head == :parameters)
29+
30+
function connector_macro(mod, name, body; arglist = Set([]), kwargs = Set([]))
1231
if !Meta.isexpr(body, :block)
1332
err = """
1433
connector body must be a block! It should be in the form of
@@ -21,16 +40,17 @@ function connector_macro(mod, name, body)
2140
"""
2241
error(err)
2342
end
24-
vs = Num[]
43+
vs = []
2544
icon = Ref{Union{String, URI}}()
2645
dict = Dict{Symbol, Any}()
46+
expr = Expr(:block)
2747
for arg in body.args
2848
arg isa LineNumberNode && continue
2949
if arg.head == :macrocall && arg.args[1] == Symbol("@icon")
3050
parse_icon!(icon, dict, dict, arg.args[end])
3151
continue
3252
end
33-
push!(vs, Num(parse_variable_def!(dict, mod, arg, :variables)))
53+
parse_variable_arg!(expr, vs, dict, mod, arg, :variables)
3454
end
3555
iv = get(dict, :independent_variable, nothing)
3656
if iv === nothing
@@ -39,8 +59,9 @@ function connector_macro(mod, name, body)
3959
gui_metadata = isassigned(icon) ? GUIMetadata(GlobalRef(mod, name), icon[]) :
4060
nothing
4161
quote
42-
$name = $Model((; name) -> begin
43-
var"#___sys___" = $ODESystem($(Equation[]), $iv, $vs, $([]);
62+
$name = $Model(($(arglist...); name, $(kwargs...)) -> begin
63+
$expr
64+
var"#___sys___" = $ODESystem($(Equation[]), $iv, [$(vs...)], $([]);
4465
name, gui_metadata = $gui_metadata)
4566
$Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___"))
4667
end, $dict)
@@ -147,25 +168,6 @@ function get_var(mod::Module, b)
147168
b isa Symbol ? getproperty(mod, b) : b
148169
end
149170

150-
macro model(name::Symbol, expr)
151-
esc(model_macro(__module__, name, expr))
152-
end
153-
154-
@inline is_kwarg(::Symbol) = false
155-
@inline is_kwarg(e::Expr) = (e.head == :parameters)
156-
157-
macro model(fcall::Expr, expr)
158-
fcall.head == :call || "Couldn't comprehend the model $arg"
159-
160-
arglist, kwargs = if lastindex(fcall.args) > 1 && is_kwarg(fcall.args[2])
161-
(lastindex(fcall.args) > 2 ? Set(fcall.args[3:end]) : Set()),
162-
Set(fcall.args[2].args)
163-
else
164-
Set(), Set(fcall.args[2:end])
165-
end
166-
esc(model_macro(__module__, fcall.args[1], expr; arglist, kwargs))
167-
end
168-
169171
function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
170172
exprs = Expr(:block)
171173
dict = Dict{Symbol, Any}()
@@ -324,7 +326,8 @@ function parse_variable_arg!(expr, vs, dict, mod, arg, varclass)
324326
v = Num(vv)
325327
name = getname(v)
326328
push!(vs, name)
327-
def === nothing ? push!(expr.args, :($name = $v)) : push!(expr.args, :($name = $setdefault($v, $def)))
329+
def === nothing ? push!(expr.args, :($name = $v)) :
330+
push!(expr.args, :($name = $setdefault($v, $def)))
328331
end
329332

330333
function parse_variables!(exprs, vs, dict, mod, body, varclass)

test/model_parsing.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ end
2525
@variables t
2626
D = Differential(t)
2727

28-
@connector Pin begin
29-
v(t) = 0 # Potential at the pin [V]
28+
@connector Pin(; v_start = 0) begin
29+
v(t) = v_start # Potential at the pin [V]
3030
i(t), [connect = Flow] # Current flowing into the pin [A]
3131
@icon "pin.png"
3232
end
3333

34+
@named p = Pin(; v_start = π)
35+
@test getdefault(p.v) == π
36+
3437
@model OnePort begin
3538
@components begin
3639
p = Pin()

0 commit comments

Comments
 (0)