diff --git a/src/systems/model_parsing.jl b/src/systems/model_parsing.jl index 52ef0560d7..55017b87a7 100644 --- a/src/systems/model_parsing.jl +++ b/src/systems/model_parsing.jl @@ -178,15 +178,10 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs; (var, def) end Expr(:ref, a, b...) => begin + indices = map(i -> UnitRange(i.args[2], i.args[end]), b) parse_variable_def!(dict, mod, a, varclass, kwargs; - def, indices = [eval.(b)...]) + def, indices) end - #= Expr(:if, condition, a) => begin - var, def = [], [] - for var_def in a.args - parse_variable_def!(dict, mod, var_def, varclass, kwargs) - end - end =# _ => error("$arg cannot be parsed") end end @@ -301,7 +296,7 @@ function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, sps, parse_equations!(exprs, eqs, dict, body) elseif mname == Symbol("@icon") isassigned(icon) && error("This model has more than one icon.") - parse_icon!(icon, dict, body) + parse_icon!(body, dict, icon, mod) else error("$mname is not handled.") end @@ -614,7 +609,7 @@ function parse_equations!(exprs, eqs, dict, body) end end -function parse_icon!(icon, dict, body::String) +function parse_icon!(body::String, dict, icon, mod) icon_dir = get(ENV, "MTK_ICONS_DIR", joinpath(DEPOT_PATH[1], "mtk_icons")) dict[:icon] = icon[] = if isfile(body) URI("file:///" * abspath(body)) @@ -632,9 +627,8 @@ function parse_icon!(icon, dict, body::String) error("\n$body is not a valid icon") end end - -function parse_icon!(icon, dict, body::Expr) - parse_icon!(icon, dict, eval(body)) +function parse_icon!(body::Union{Expr, Symbol}, dict, icon, mod) + parse_icon!(Core.eval(mod, body), dict, icon, mod) end ### Parsing Components: diff --git a/test/model_parsing.jl b/test/model_parsing.jl index b1d990d1cf..ce1f0cc8a3 100644 --- a/test/model_parsing.jl +++ b/test/model_parsing.jl @@ -6,6 +6,7 @@ using Distributions using Unitful ENV["MTK_ICONS_DIR"] = "$(@__DIR__)/icons" +ground_logo = read(abspath(ENV["MTK_ICONS_DIR"], "ground.svg"), String) # Mock module used to test if the `@mtkmodel` macro works with fully-qualified names as well. module MyMockModule @@ -164,8 +165,7 @@ resistor = getproperty(rc, :resistor; namespace = false) @test get_gui_metadata(rc.resistor).layout == Resistor.structure[:icon] == read(joinpath(ENV["MTK_ICONS_DIR"], "resistor.svg"), String) -@test get_gui_metadata(rc.ground).layout == - read(abspath(ENV["MTK_ICONS_DIR"], "ground.svg"), String) +@test get_gui_metadata(rc.ground).layout == ground_logo @test get_gui_metadata(rc.capacitor).layout == URI("https://upload.wikimedia.org/wikipedia/commons/7/78/Capacitor_symbol.svg") @test OnePort.structure[:icon] == @@ -321,6 +321,23 @@ end @test A.structure[:components] == [[:cc, :C]] end +# Ensure that modules consisting MTKModels with component arrays and icons of +# `Expr` type and `unit` metadata can be precompiled. +@testset "Precompile packages with MTKModels" begin + push!(LOAD_PATH, joinpath(@__DIR__, "precompile_test")) + + using ModelParsingPrecompile: ModelWithComponentArray, ModelWithExprIcon + + @named model_with_component_array = ModelWithComponentArray() + + @test ModelWithComponentArray.structure[:parameters][:R][:unit] == u"Ω" + @test lastindex(parameters(model_with_component_array)) == 3 + + @test ModelWithExprIcon.structure[:icon] == ground_logo + + pop!(LOAD_PATH) +end + @testset "Conditional statements inside the blocks" begin @mtkmodel C begin end diff --git a/test/precompile_test/ModelParsingPrecompile.jl b/test/precompile_test/ModelParsingPrecompile.jl new file mode 100644 index 0000000000..9160a4d695 --- /dev/null +++ b/test/precompile_test/ModelParsingPrecompile.jl @@ -0,0 +1,16 @@ +module ModelParsingPrecompile + +using ModelingToolkit +using Unitful + +@mtkmodel ModelWithComponentArray begin + @parameters begin + R(t)[1:3] = 1, [description = "Parameter array", unit = u"Ω"] + end +end + +@mtkmodel ModelWithExprIcon begin + @icon read(abspath(@__DIR__, "..", "icons", "ground.svg"), String) +end + +end