Skip to content

Commit 5f56f04

Browse files
committed
refactor: implicitly promote vars/pars as kwargs
+ allow expressions as default val of pars/vars + all pars/vars are promoted as kwarg with constant or `nothing` as the default value and update them as dict[:kwargs]
1 parent a7f77f3 commit 5f56f04

File tree

2 files changed

+66
-47
lines changed

2 files changed

+66
-47
lines changed

src/systems/model_parsing.jl

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,6 @@ for f in (:connector, :model)
99
macro $f(name::Symbol, body)
1010
esc($(Symbol(f, :_macro))(__module__, name, body))
1111
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
2412
end
2513
end
2614

@@ -43,14 +31,15 @@ function connector_macro(mod, name, body; arglist = Set([]), kwargs = Set([]))
4331
vs = []
4432
icon = Ref{Union{String, URI}}()
4533
dict = Dict{Symbol, Any}()
34+
dict[:kwargs] = Dict{Symbol, Any}()
4635
expr = Expr(:block)
4736
for arg in body.args
4837
arg isa LineNumberNode && continue
4938
if arg.head == :macrocall && arg.args[1] == Symbol("@icon")
5039
parse_icon!(icon, dict, dict, arg.args[end])
5140
continue
5241
end
53-
parse_variable_arg!(expr, vs, dict, mod, arg, :variables)
42+
parse_variable_arg!(expr, vs, dict, mod, arg, :variables, kwargs)
5443
end
5544
iv = get(dict, :independent_variable, nothing)
5645
if iv === nothing
@@ -68,18 +57,33 @@ function connector_macro(mod, name, body; arglist = Set([]), kwargs = Set([]))
6857
end
6958
end
7059

71-
function parse_variable_def!(dict, mod, arg, varclass)
60+
function parse_variable_def!(dict, mod, arg, varclass, kwargs, def = nothing)
7261
arg isa LineNumberNode && return
7362
MLStyle.@match arg begin
74-
::Symbol => (generate_var!(dict, arg, varclass), nothing)
75-
Expr(:call, a, b) => (generate_var!(dict, a, b, varclass), nothing)
63+
a::Symbol => begin
64+
push!(kwargs, Expr(:kw, a, def))
65+
var = generate_var!(dict, a, varclass)
66+
dict[:kwargs][getname(var)] = def
67+
(var, nothing)
68+
end
69+
Expr(:call, a, b) => begin
70+
push!(kwargs, Expr(:kw, a, def))
71+
var = generate_var!(dict, a, b, varclass)
72+
dict[:kwargs][getname(var)] = def
73+
(var, nothing)
74+
end
7675
Expr(:(=), a, b) => begin
77-
var, _ = parse_variable_def!(dict, mod, a, varclass)
76+
Base.remove_linenums!(b)
7877
def, meta = parse_default(mod, b)
78+
var, _ = parse_variable_def!(dict, mod, a, varclass, kwargs, def)
7979
dict[varclass][getname(var)][:default] = def
8080
if typeof(def) != Symbol
8181
var = setdefault(var, def)
8282
def = nothing
83+
else
84+
def in [keys(dict[:kwargs])...;] ||
85+
error("$def is not a known parameter or variable")
86+
var = setdefault(var, def)
8387
end
8488
if !isnothing(meta)
8589
if (ct = get(meta, VariableConnectType, nothing)) !== nothing
@@ -90,7 +94,7 @@ function parse_variable_def!(dict, mod, arg, varclass)
9094
(var, def)
9195
end
9296
Expr(:tuple, a, b) => begin
93-
var, _ = parse_variable_def!(dict, mod, a, varclass)
97+
var, _ = parse_variable_def!(dict, mod, a, varclass, kwargs)
9498
meta = parse_metadata(mod, b)
9599
if (ct = get(meta, VariableConnectType, nothing)) !== nothing
96100
dict[varclass][getname(var)][:connection_type] = nameof(ct)
@@ -110,6 +114,7 @@ function generate_var(a, varclass)
110114
end
111115

112116
function generate_var!(dict, a, varclass)
117+
#var = generate_var(Symbol("#", a), varclass)
113118
var = generate_var(a, varclass)
114119
vd = get!(dict, varclass) do
115120
Dict{Symbol, Dict{Symbol, Any}}()
@@ -145,6 +150,14 @@ function parse_default(mod, a)
145150
(def, meta)
146151
end
147152
::Symbol || ::Number => (a, nothing)
153+
Expr(:call, a...) => begin
154+
def = parse_default.(Ref(mod), a)
155+
expr = Expr(:call)
156+
for (d, _) in def
157+
push!(expr.args, d)
158+
end
159+
(expr, nothing)
160+
end
148161
_ => error("Cannot parse default $a")
149162
end
150163
end
@@ -171,6 +184,7 @@ end
171184
function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
172185
exprs = Expr(:block)
173186
dict = Dict{Symbol, Any}()
187+
dict[:kwargs] = Dict{Symbol, Any}()
174188
comps = Symbol[]
175189
ext = Ref{Any}(nothing)
176190
eqs = Expr[]
@@ -198,7 +212,7 @@ function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
198212
nothing
199213

200214
sys = :($ODESystem($Equation[$(eqs...)], $iv, [$(vs...)], [$(ps...)];
201-
systems = [$(comps...)], name, gui_metadata = $gui_metadata))
215+
systems = [$(comps...)], name, gui_metadata = $gui_metadata)) #, defaults = $defaults))
202216
if ext[] === nothing
203217
push!(exprs.args, sys)
204218
else
@@ -217,9 +231,9 @@ function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict,
217231
elseif mname == Symbol("@extend")
218232
parse_extend!(exprs, ext, dict, body)
219233
elseif mname == Symbol("@variables")
220-
parse_variables!(exprs, vs, dict, mod, body, :variables)
234+
parse_variables!(exprs, vs, dict, mod, body, :variables, kwargs)
221235
elseif mname == Symbol("@parameters")
222-
parse_variables!(exprs, ps, dict, mod, body, :parameters)
236+
parse_variables!(exprs, ps, dict, mod, body, :parameters, kwargs)
223237
elseif mname == Symbol("@equations")
224238
parse_equations!(exprs, eqs, dict, body)
225239
elseif mname == Symbol("@icon")
@@ -321,21 +335,20 @@ function parse_extend!(exprs, ext, dict, body)
321335
end
322336
end
323337

324-
function parse_variable_arg!(expr, vs, dict, mod, arg, varclass)
325-
vv, def = parse_variable_def!(dict, mod, arg, varclass)
338+
function parse_variable_arg!(expr, vs, dict, mod, arg, varclass, kwargs)
339+
vv, _ = parse_variable_def!(dict, mod, arg, varclass, kwargs)
326340
v = Num(vv)
327341
name = getname(v)
328342
push!(vs, name)
329-
def === nothing ? push!(expr.args, :($name = $v)) :
330-
push!(expr.args, :($name = $setdefault($v, $def)))
343+
push!(expr.args, :($name = $name === nothing ? $vv : $setdefault($vv, $name)))
331344
end
332345

333-
function parse_variables!(exprs, vs, dict, mod, body, varclass)
346+
function parse_variables!(exprs, vs, dict, mod, body, varclass, kwargs)
334347
expr = Expr(:block)
335348
push!(exprs, expr)
336349
for arg in body.args
337350
arg isa LineNumberNode && continue
338-
parse_variable_arg!(expr, vs, dict, mod, arg, varclass)
351+
parse_variable_arg!(expr, vs, dict, mod, arg, varclass, kwargs)
339352
end
340353
end
341354

test/model_parsing.jl

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ end
1010
@connector RealOutput begin
1111
u(t), [output = true]
1212
end
13-
@model Constant(; k = 1) begin
13+
@model Constant begin
1414
@components begin
1515
output = RealOutput()
1616
end
1717
@parameters begin
18-
k = k, [description = "Constant output value of block"]
18+
k, [description = "Constant output value of block"]
1919
end
2020
@equations begin
2121
output.u ~ k
@@ -25,13 +25,13 @@ end
2525
@variables t
2626
D = Differential(t)
2727

28-
@connector Pin(; v_start = 0) begin
29-
v(t) = v_start # Potential at the pin [V]
28+
@connector Pin begin
29+
v(t) # 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 = π)
34+
@named p = Pin(; v = π)
3535
@test getdefault(p.v) == π
3636

3737
@model OnePort begin
@@ -64,10 +64,10 @@ end
6464
end
6565

6666
resistor_log = "$(@__DIR__)/logo/resistor.svg"
67-
@model Resistor(; R = 1) begin
67+
@model Resistor begin
6868
@extend v, i = oneport = OnePort()
6969
@parameters begin
70-
R = R
70+
R
7171
end
7272
@icon begin
7373
"""<?xml version="1.0" encoding="UTF-8"?>
@@ -90,10 +90,10 @@ l15 0" stroke="black" stroke-width="1" stroke-linejoin="bevel" fill="none"></pat
9090
end
9191
end
9292

93-
@model Capacitor(; C = 1) begin
93+
@model Capacitor begin
9494
@extend v, i = oneport = OnePort()
9595
@parameters begin
96-
C = C
96+
C
9797
end
9898
@icon "https://upload.wikimedia.org/wikipedia/commons/7/78/Capacitor_symbol.svg"
9999
@equations begin
@@ -116,7 +116,7 @@ end
116116
resistor = Resistor(; R)
117117
capacitor = Capacitor(; C = 10)
118118
source = Voltage()
119-
constant = Constant()
119+
constant = Constant(; k = 1)
120120
ground = Ground()
121121
end
122122
@equations begin
@@ -145,33 +145,39 @@ end
145145

146146
@test length(equations(structural_simplify(rc))) == 1
147147

148-
@model MockModel(; cval, gval, jval = 6) begin
148+
@model MockModel begin
149149
@parameters begin
150150
a
151151
b(t)
152-
c(t) = cval
152+
cval
153+
jval
154+
kval
155+
c(t) = cval + cval
153156
d = 2
154157
e, [description = "e"]
155158
f = 3, [description = "f"]
156-
g = gval, [description = "g"]
157159
h(t), [description = "h(t)"]
158-
i(t) = 5, [description = "i(t)"]
160+
i(t) = 4, [description = "i(t)"]
159161
j(t) = jval, [description = "j(t)"]
162+
k = kval, [description = "k"]
160163
end
161164
end
162165

163-
@named model = MockModel(cval = 1, gval = 4)
166+
kval = 5
167+
@named model = MockModel(; kval, cval = 1)
164168

165169
@test hasmetadata(model.e, VariableDescription)
166170
@test hasmetadata(model.f, VariableDescription)
167-
@test hasmetadata(model.g, VariableDescription)
168171
@test hasmetadata(model.h, VariableDescription)
169172
@test hasmetadata(model.i, VariableDescription)
170173
@test hasmetadata(model.j, VariableDescription)
174+
@test hasmetadata(model.k, VariableDescription)
171175

172-
@test getdefault(model.c) == 1
176+
@test getdefault(model.cval) == 1
177+
@test getdefault(model.c) == 2
173178
@test getdefault(model.d) == 2
179+
@test_throws KeyError getdefault(model.e)
174180
@test getdefault(model.f) == 3
175-
@test getdefault(model.g) == 4
176-
@test getdefault(model.i) == 5
177-
@test getdefault(model.j) == 6
181+
@test getdefault(model.i) == 4
182+
@test getdefault(model.j) == :jval
183+
@test getdefault(model.k) == kval

0 commit comments

Comments
 (0)