diff --git a/src/systems/model_parsing.jl b/src/systems/model_parsing.jl index 63c14a8d40..b7aac9c12d 100644 --- a/src/systems/model_parsing.jl +++ b/src/systems/model_parsing.jl @@ -1,6 +1,7 @@ struct Model{F, S} f::F structure::S + isconnector::Bool end (m::Model)(args...; kw...) = m.f(args...; kw...) @@ -54,11 +55,27 @@ function connector_macro(mod, name, body) var"#___sys___" = $ODESystem($(Equation[]), $iv, [$(vs...)], $([]); name, gui_metadata = $gui_metadata) $Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___")) - end, $dict) + end, $dict, true) end end function parse_variable_def!(dict, mod, arg, varclass, kwargs, def = nothing) + metatypes = [(:connection_type, VariableConnectType), + (:description, VariableDescription), + (:unit, VariableUnit), + (:bounds, VariableBounds), + (:noise, VariableNoiseType), + (:input, VariableInput), + (:output, VariableOutput), + (:irreducible, VariableIrreducible), + (:state_priority, VariableStatePriority), + (:misc, VariableMisc), + (:disturbance, VariableDisturbance), + (:tunable, VariableTunable), + (:dist, VariableDistribution), + (:binary, VariableBinary), + (:integer, VariableInteger)] + arg isa LineNumberNode && return MLStyle.@match arg begin a::Symbol => begin @@ -78,9 +95,12 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, def = nothing) def, meta = parse_default(mod, b) var, _ = parse_variable_def!(dict, mod, a, varclass, kwargs, def) dict[varclass][getname(var)][:default] = def - if !isnothing(meta) - if (ct = get(meta, VariableConnectType, nothing)) !== nothing - dict[varclass][getname(var)][:connection_type] = nameof(ct) + if meta !== nothing + for (type, key) in metatypes + if (mt = get(meta, key, nothing)) !== nothing + key == VariableConnectType && (mt = nameof(mt)) + dict[varclass][getname(var)][type] = mt + end end var = set_var_metadata(var, meta) end @@ -89,8 +109,14 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, def = nothing) Expr(:tuple, a, b) => begin var, def = parse_variable_def!(dict, mod, a, varclass, kwargs) meta = parse_metadata(mod, b) - if (ct = get(meta, VariableConnectType, nothing)) !== nothing - dict[varclass][getname(var)][:connection_type] = nameof(ct) + if meta !== nothing + for (type, key) in metatypes + if (mt = get(meta, key, nothing)) !== nothing + key == VariableConnectType && (mt = nameof(mt)) + dict[varclass][getname(var)][type] = mt + end + end + var = set_var_metadata(var, meta) end (set_var_metadata(var, meta), def) end @@ -213,7 +239,7 @@ function mtkmodel_macro(mod, name, expr) push!(exprs.args, :($extend($sys, $(ext[])))) end - :($name = $Model((; name, $(kwargs...)) -> $exprs, $dict)) + :($name = $Model((; name, $(kwargs...)) -> $exprs, $dict, false)) end function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, dict, @@ -240,13 +266,13 @@ end function parse_components!(exprs, cs, dict, body, kwargs) expr = Expr(:block) push!(exprs, expr) - comps = Vector{String}[] + comps = Vector{Symbol}[] for arg in body.args arg isa LineNumberNode && continue MLStyle.@match arg begin Expr(:(=), a, b) => begin push!(cs, a) - push!(comps, [String(a), String(b.args[1])]) + push!(comps, [a, b.args[1]]) arg = deepcopy(arg) b = deepcopy(arg.args[2]) diff --git a/test/model_parsing.jl b/test/model_parsing.jl index 817aae94ac..17be63c955 100644 --- a/test/model_parsing.jl +++ b/test/model_parsing.jl @@ -33,6 +33,7 @@ end @named p = Pin(; v = π) @test getdefault(p.v) == π +@test Pin.isconnector == true @mtkmodel OnePort begin @components begin @@ -51,6 +52,8 @@ end end end +@test OnePort.isconnector == false + @mtkmodel Ground begin @components begin g = Pin() @@ -94,16 +97,16 @@ end @parameters begin C end - @variables begin - v = 0.0 - end - @extend v, i = oneport = OnePort(; v = v) + @extend v, i = oneport = OnePort(; v = 0.0) @icon "https://upload.wikimedia.org/wikipedia/commons/7/78/Capacitor_symbol.svg" @equations begin D(v) ~ i / C end end +@named capacitor = Capacitor(C = 10, oneport.v = 10.0) +@test getdefault(capacitor.v) == 10.0 + @mtkmodel Voltage begin @extend v, i = oneport = OnePort() @components begin @@ -133,6 +136,7 @@ end @named rc = RC(; resistor.R = 20) @test getdefault(rc.resistor.R) == 20 @test getdefault(rc.capacitor.C) == 10 +@test getdefault(rc.capacitor.v) == 0.0 @test getdefault(rc.constant.k) == 1 @test get_gui_metadata(rc.resistor).layout == Resistor.structure[:icon] == @@ -212,3 +216,18 @@ getdefault(a.b.k) == 1 getdefault(a.b.i) == 20 getdefault(a.b.j) == 30 getdefault(a.b.k) == 40 + +metadata = Dict(:description => "Variable to test metadata in the Model.structure", + :input => true, :bounds => :((-1, 1)), :connection_type => :Flow, :integer => true, + :binary => false, :tunable => false, :disturbance => true, :dist => :(Normal(1, 1))) + +@connector MockMeta begin + m(t), + [description = "Variable to test metadata in the Model.structure", + input = true, bounds = (-1, 1), connect = Flow, integer = true, + binary = false, tunable = false, disturbance = true, dist = Normal(1, 1)] +end + +for (k, v) in metadata + @test MockMeta.structure[:variables][:m][k] == v +end