Skip to content

Commit 43034fe

Browse files
committed
fix: set metadata correctly whenever var/par has a default value
1 parent 879383a commit 43034fe

File tree

1 file changed

+53
-32
lines changed

1 file changed

+53
-32
lines changed

src/systems/model_parsing.jl

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,13 @@ function connector_macro(mod, name, body)
2424
vs = Num[]
2525
icon = Ref{Union{String, URI}}()
2626
dict = Dict{Symbol, Any}()
27-
kwargs = []
2827
for arg in body.args
2928
arg isa LineNumberNode && continue
3029
if arg.head == :macrocall && arg.args[1] == Symbol("@icon")
3130
parse_icon!(icon, dict, dict, arg.args[end])
3231
continue
3332
end
34-
push!(vs, Num(parse_variable_def!(dict, mod, arg, :variables, kwargs)))
33+
push!(vs, Num(parse_variable_def!(dict, mod, arg, :variables)))
3534
end
3635
iv = get(dict, :independent_variable, nothing)
3736
if iv === nothing
@@ -48,19 +47,25 @@ function connector_macro(mod, name, body)
4847
end
4948
end
5049

51-
function parse_variable_def!(dict, mod, arg, varclass, kwargs)
50+
function parse_variable_def!(dict, mod, arg, varclass)
5251
MLStyle.@match arg begin
5352
::Symbol => generate_var!(dict, arg, varclass)
5453
Expr(:call, a, b) => generate_var!(dict, a, b, varclass)
5554
Expr(:(=), a, b) => begin
56-
var = parse_variable_def!(dict, mod, a, varclass, kwargs)
57-
def = parse_default(mod, b, kwargs)
55+
var = parse_variable_def!(dict, mod, a, varclass)
56+
def, meta = parse_default(mod, b)
5857
dict[varclass][getname(var)][:default] = def
5958
var = setdefault(var, def)
59+
if !isnothing(meta)
60+
if (ct = get(meta, VariableConnectType, nothing)) !== nothing
61+
dict[varclass][getname(var)][:connection_type] = nameof(ct)
62+
end
63+
var = set_var_metadata(var, meta)
64+
end
6065
var
6166
end
6267
Expr(:tuple, a, b) => begin
63-
var = parse_variable_def!(dict, mod, a, varclass, kwargs)
68+
var = parse_variable_def!(dict, mod, a, varclass)
6469
meta = parse_metadata(mod, b)
6570
if (ct = get(meta, VariableConnectType, nothing)) !== nothing
6671
dict[varclass][getname(var)][:connection_type] = nameof(ct)
@@ -75,25 +80,33 @@ function parse_variables_with_kw!(exprs, var, dict, mod, body, varexpr, varclass
7580
for arg in body.args
7681
arg isa LineNumberNode && continue
7782
MLStyle.@match arg begin
78-
Expr(:(=), a, b::Number) => parse_variables!(exprs, var, dict, mod, arg, varclass, kwargs)
83+
::Symbol || Expr(:tuple, a, b) || Expr(:call, a, b) || Expr(:(=), a, b::Number) => begin
84+
parse_variables!(exprs, var, dict, mod, arg, varclass)
85+
end
7986
Expr(:(=), a, b::Symbol) => begin
8087
isdefined(mod, b) ?
81-
parse_variables!(exprs, var, dict, mod, arg, varclass, kwargs) :
82-
push!(varexpr.args[end].args[end].args, arg)
88+
parse_variables!(exprs, var, dict, mod, arg, varclass) :
89+
push!(varexpr.args[end].args[end].args, arg)
8390
end
8491
Expr(:(=), a, b) => begin
8592
def = Base.remove_linenums!(b)
8693
MLStyle.@match def begin
87-
Expr(:tuple, x::Symbol, y) || x::Symbol => begin
88-
push!(varexpr.args[end].args[end].args, :($a = $(def.args[end])))
94+
Expr(:tuple, x::Symbol, y) => begin
95+
isdefined(mod, x) ?
96+
parse_variables!(exprs, var, dict, mod, arg, varclass) :
97+
push!(varexpr.args[end].args[end].args, arg)
8998
end
90-
Expr(:tuple, x::Number, y) => (@info "111"; parse_variables!(exprs, var, dict, mod, arg, varclass, kwargs))
91-
::Number => parse_variables!(exprs, var, dict, mod, arg, varclass, kwargs)
92-
::Expr => push!(varexpr.args[end].args[end].args, :($a = $(def.args[end])))
93-
_ => @info "Got $def"
99+
::Symbol => push!(varexpr.args[end].args[end].args,
100+
:($a = $(def.args[end])))
101+
::Number || Expr(:tuple, x::Number, y) => begin
102+
parse_variables!(exprs, var, dict, mod, arg, varclass)
103+
end
104+
::Expr => push!(varexpr.args[end].args[end].args,
105+
:($a = $(def.args[end])))
106+
_ => error("Got $def")
94107
end
95108
end
96-
_ => "got $arg"
109+
_ => error("Could not parse this $varclass definition $arg")
97110
end
98111
end
99112
dict[:kwargs] = kwargs
@@ -133,12 +146,17 @@ function generate_var!(dict, a, b, varclass)
133146
var
134147
end
135148

136-
function parse_default(mod, a, kwargs)
149+
function parse_default(mod, a)
137150
a = Base.remove_linenums!(deepcopy(a))
138151
MLStyle.@match a begin
139-
Expr(:block, a) => get_var(mod, a)
140-
::Symbol => get_var(mod, a)
141-
::Number => a
152+
Expr(:block, x) => parse_default(mod, x)
153+
Expr(:tuple, x, y) => begin
154+
def, _ = parse_default(mod, x)
155+
meta = parse_metadata(mod, y)
156+
(def, meta)
157+
end
158+
::Symbol => (get_var(mod, a), nothing)
159+
::Number => (a, nothing)
142160
_ => error("Cannot parse default $a")
143161
end
144162
end
@@ -173,7 +191,8 @@ macro model(fcall::Expr, expr)
173191
fcall.head == :call || "Couldn't comprehend the model $arg"
174192

175193
arglist, kwargs = if lastindex(fcall.args) > 1 && is_kwarg(fcall.args[2])
176-
(lastindex(fcall.args) > 2 ? (@info 1; Set(fcall.args[3:end])) : (@info 2; Set())), Set(fcall.args[2].args)
194+
(lastindex(fcall.args) > 2 ? Set(fcall.args[3:end]) : Set()),
195+
Set(fcall.args[2].args)
177196
else
178197
Set(), Set(fcall.args[2:end])
179198
end
@@ -189,15 +208,14 @@ function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
189208
icon = Ref{Union{String, URI}}()
190209
vs = []
191210
ps = []
192-
parexpr = :(pss = @parameters begin
193-
end)
194-
varexpr = :(vss = @variables begin
195-
end)
211+
parexpr = :(pss = @parameters begin end)
212+
varexpr = :(vss = @variables begin end)
196213

197214
for arg in expr.args
198215
arg isa LineNumberNode && continue
199216
if arg.head == :macrocall
200-
parse_model!(exprs.args, comps, ext, eqs, icon, vs, varexpr, ps, parexpr, dict, mod, arg, kwargs)
217+
parse_model!(exprs.args, comps, ext, eqs, icon, vs, varexpr, ps,
218+
parexpr, dict, mod, arg, kwargs)
201219
elseif arg.head == :block
202220
push!(exprs.args, arg)
203221
else
@@ -213,7 +231,7 @@ function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
213231
push!(exprs.args, parexpr)
214232

215233
gui_metadata = isassigned(icon) > 0 ? GUIMetadata(GlobalRef(mod, name), icon[]) :
216-
nothing
234+
nothing
217235

218236
sys = :($ODESystem($Equation[$(eqs...)], $iv, [$(vs...), vss...], [$(ps...), pss...];
219237
systems = [$(comps...)], name, gui_metadata = $gui_metadata))
@@ -226,7 +244,8 @@ function model_macro(mod, name, expr; arglist = Set([]), kwargs = Set([]))
226244
:($name = $Model(($(arglist...); name, $(kwargs...)) -> $exprs, $dict))
227245
end
228246

229-
function parse_model!(exprs, comps, ext, eqs, icon, vs, varexpr, ps, parexpr, dict, mod, arg, kwargs)
247+
function parse_model!(exprs, comps, ext, eqs, icon, vs, varexpr, ps, parexpr, dict,
248+
mod, arg, kwargs)
230249
mname = arg.args[1]
231250
body = arg.args[end]
232251
if mname == Symbol("@components")
@@ -276,7 +295,9 @@ function _rename(compname, varname)
276295
end
277296

278297
function component_args!(a, b, expr, kwargs)
279-
start = b.head == :parameters ? 1 : 2
298+
# Whenever `b` is a function call, skip the first arg aka the function name.
299+
# Whenver it is a kwargs list, include it.
300+
start = b.head == :call ? 2 : 1
280301
for i in start:lastindex(b.args)
281302
arg = b.args[i]
282303
arg isa LineNumberNode && continue
@@ -304,7 +325,7 @@ function component_args!(a, b, expr, kwargs)
304325
push!(expr.args, :($y = $_v))
305326
push!(kwargs, Expr(:kw, _v, y))
306327
end
307-
_ => "Got this: $arg"
328+
_ => error("Could not parse $arg of component $a")
308329
end
309330
end
310331
end
@@ -336,11 +357,11 @@ function parse_extend!(exprs, ext, dict, body)
336357
end
337358
end
338359

339-
function parse_variables!(exprs, vs, dict, mod, arg, varclass, kwargs)
360+
function parse_variables!(exprs, vs, dict, mod, arg, varclass)
340361
expr = Expr(:block)
341362
push!(exprs, expr)
342363
arg isa LineNumberNode && return
343-
vv = parse_variable_def!(dict, mod, arg, varclass, kwargs)
364+
vv = parse_variable_def!(dict, mod, arg, varclass)
344365
v = Num(vv)
345366
name = getname(v)
346367
push!(vs, name)

0 commit comments

Comments
 (0)