Skip to content

Commit 61e12ba

Browse files
authored
Merge pull request #2226 from ven-k/vkb/extend+dsl-component-defaults
Symbolic defaults for sub-components and base system kwargs + set base sys kwargs as component's kwargs
2 parents 35f2709 + a9fa244 commit 61e12ba

File tree

2 files changed

+291
-197
lines changed

2 files changed

+291
-197
lines changed

src/systems/model_parsing.jl

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ function _model_macro(mod, name, expr, isconnector)
2222
ext = Ref{Any}(nothing)
2323
eqs = Expr[]
2424
icon = Ref{Union{String, URI}}()
25-
vs = []
26-
ps = []
27-
kwargs = []
25+
kwargs, ps, sps, vs, = [], [], [], []
2826

2927
for arg in expr.args
3028
arg isa LineNumberNode && continue
3129
if arg.head == :macrocall
3230
parse_model!(exprs.args, comps, ext, eqs, icon, vs, ps,
33-
dict, mod, arg, kwargs)
31+
sps, dict, mod, arg, kwargs)
3432
elseif arg.head == :block
3533
push!(exprs.args, arg)
3634
elseif isconnector
@@ -213,8 +211,8 @@ function get_var(mod::Module, b)
213211
end
214212
end
215213

216-
function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict,
217-
mod, arg, kwargs)
214+
function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, sps,
215+
dict, mod, arg, kwargs)
218216
mname = arg.args[1]
219217
body = arg.args[end]
220218
if mname == Symbol("@components")
@@ -225,6 +223,8 @@ function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict,
225223
parse_variables!(exprs, vs, dict, mod, body, :variables, kwargs)
226224
elseif mname == Symbol("@parameters")
227225
parse_variables!(exprs, ps, dict, mod, body, :parameters, kwargs)
226+
elseif mname == Symbol("@structural_parameters")
227+
parse_structural_parameters!(exprs, sps, dict, mod, body, kwargs)
228228
elseif mname == Symbol("@equations")
229229
parse_equations!(exprs, eqs, dict, body)
230230
elseif mname == Symbol("@icon")
@@ -234,9 +234,28 @@ function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict,
234234
end
235235
end
236236

237+
function parse_structural_parameters!(exprs, sps, dict, mod, body, kwargs)
238+
Base.remove_linenums!(body)
239+
for arg in body.args
240+
MLStyle.@match arg begin
241+
Expr(:(=), a, b) => begin
242+
push!(sps, a)
243+
push!(kwargs, Expr(:kw, a, b))
244+
dict[:kwargs][a] = b
245+
end
246+
a => begin
247+
push!(sps, a)
248+
push!(kwargs, a)
249+
dict[:kwargs][a] = nothing
250+
end
251+
end
252+
end
253+
end
254+
237255
function parse_components!(exprs, cs, dict, body, kwargs)
238256
expr = Expr(:block)
239-
push!(exprs, expr)
257+
varexpr = Expr(:block)
258+
push!(exprs, varexpr)
240259
comps = Vector{Symbol}[]
241260
for arg in body.args
242261
arg isa LineNumberNode && continue
@@ -247,23 +266,25 @@ function parse_components!(exprs, cs, dict, body, kwargs)
247266
arg = deepcopy(arg)
248267
b = deepcopy(arg.args[2])
249268

250-
component_args!(a, b, expr, kwargs)
269+
component_args!(a, b, dict, expr, varexpr, kwargs)
251270

252-
push!(b.args, Expr(:kw, :name, Meta.quot(a)))
253271
arg.args[2] = b
254272
push!(expr.args, arg)
255273
end
256274
_ => error("`@components` only takes assignment expressions. Got $arg")
257275
end
258276
end
277+
278+
push!(exprs, :(@named $expr))
279+
259280
dict[:components] = comps
260281
end
261282

262283
function _rename(compname, varname)
263284
compname = Symbol(compname, :__, varname)
264285
end
265286

266-
function component_args!(a, b, expr, kwargs)
287+
function component_args!(a, b, dict, expr, varexpr, kwargs)
267288
# Whenever `b` is a function call, skip the first arg aka the function name.
268289
# Whenever it is a kwargs list, include it.
269290
start = b.head == :call ? 2 : 1
@@ -274,15 +295,58 @@ function component_args!(a, b, expr, kwargs)
274295
x::Symbol || Expr(:kw, x) => begin
275296
_v = _rename(a, x)
276297
b.args[i] = Expr(:kw, x, _v)
298+
push!(varexpr.args, :((@isdefined $x) && ($_v = $x)))
277299
push!(kwargs, Expr(:kw, _v, nothing))
300+
dict[:kwargs][_v] = nothing
278301
end
279302
Expr(:parameters, x...) => begin
280-
component_args!(a, arg, expr, kwargs)
303+
component_args!(a, arg, dict, expr, varexpr, kwargs)
281304
end
282305
Expr(:kw, x, y) => begin
283306
_v = _rename(a, x)
284307
b.args[i] = Expr(:kw, x, _v)
285-
push!(kwargs, Expr(:kw, _v, y))
308+
push!(varexpr.args, :($_v = $_v === nothing ? $y : $_v))
309+
push!(kwargs, Expr(:kw, _v, nothing))
310+
dict[:kwargs][_v] = nothing
311+
end
312+
_ => error("Could not parse $arg of component $a")
313+
end
314+
end
315+
end
316+
317+
function extend_args!(a, b, dict, expr, kwargs, varexpr, has_param = false)
318+
# Whenever `b` is a function call, skip the first arg aka the function name.
319+
# Whenver it is a kwargs list, include it.
320+
start = b.head == :call ? 2 : 1
321+
for i in start:lastindex(b.args)
322+
arg = b.args[i]
323+
arg isa LineNumberNode && continue
324+
MLStyle.@match arg begin
325+
x::Symbol => begin
326+
if b.head != :parameters
327+
if has_param
328+
popat!(b.args, i)
329+
push!(b.args[2].args, x)
330+
else
331+
b.args[i] = Expr(:parameters, x)
332+
end
333+
end
334+
push!(kwargs, Expr(:kw, x, nothing))
335+
dict[:kwargs][x] = nothing
336+
end
337+
Expr(:kw, x) => begin
338+
push!(kwargs, Expr(:kw, x, nothing))
339+
dict[:kwargs][x] = nothing
340+
end
341+
Expr(:kw, x, y) => begin
342+
b.args[i] = Expr(:kw, x, x)
343+
push!(varexpr.args, :($x = $x === nothing ? $y : $x))
344+
push!(kwargs, Expr(:kw, x, nothing))
345+
dict[:kwargs][x] = nothing
346+
end
347+
Expr(:parameters, x...) => begin
348+
has_param = true
349+
extend_args!(a, arg, dict, expr, kwargs, varexpr, has_param)
286350
end
287351
_ => error("Could not parse $arg of component $a")
288352
end
@@ -291,6 +355,8 @@ end
291355

292356
function parse_extend!(exprs, ext, dict, body, kwargs)
293357
expr = Expr(:block)
358+
varexpr = Expr(:block)
359+
push!(exprs, varexpr)
294360
push!(exprs, expr)
295361
body = deepcopy(body)
296362
MLStyle.@match body begin
@@ -302,13 +368,15 @@ function parse_extend!(exprs, ext, dict, body, kwargs)
302368
error("`@extend` destructuring only takes an tuple as LHS. Got $body")
303369
end
304370
a, b = b.args
305-
component_args!(a, b, expr, kwargs)
371+
extend_args!(a, b, dict, expr, kwargs, varexpr)
306372
vars, a, b
307373
end
308374
ext[] = a
309375
push!(b.args, Expr(:kw, :name, Meta.quot(a)))
310-
dict[:extend] = [Symbol.(vars.args), a, b.args[1]]
311376
push!(expr.args, :($a = $b))
377+
378+
dict[:extend] = [Symbol.(vars.args), a, b.args[1]]
379+
312380
if vars !== nothing
313381
push!(expr.args, :(@unpack $vars = $a))
314382
end

0 commit comments

Comments
 (0)