Skip to content

Commit 8546ec5

Browse files
committed
Simple component parser
1 parent 262dd15 commit 8546ec5

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
lines changed

Project.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800"
2828
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
2929
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
3030
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
31+
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
3132
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
3233
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
3334
RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
@@ -46,6 +47,12 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
4647
UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
4748
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
4849

50+
[weakdeps]
51+
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
52+
53+
[extensions]
54+
MTKDeepDiffsExt = "DeepDiffs"
55+
4956
[compat]
5057
AbstractTrees = "0.3, 0.4"
5158
ArrayInterface = "6, 7"
@@ -67,6 +74,7 @@ JuliaFormatter = "1"
6774
JumpProcesses = "9.1"
6875
LabelledArrays = "1.3"
6976
Latexify = "0.11, 0.12, 0.13, 0.14, 0.15, 0.16"
77+
MLStyle = "0.4.17"
7078
MacroTools = "0.5"
7179
NaNMath = "0.3, 1"
7280
RecursiveArrayTools = "2.3"
@@ -84,9 +92,6 @@ UnPack = "0.1, 1.0"
8492
Unitful = "1.1"
8593
julia = "1.6"
8694

87-
[extensions]
88-
MTKDeepDiffsExt = "DeepDiffs"
89-
9095
[extras]
9196
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
9297
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
@@ -113,6 +118,3 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
113118

114119
[targets]
115120
test = ["AmplNLWriter", "BenchmarkTools", "ControlSystemsMTK", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "OrdinaryDiffEq", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials"]
116-
117-
[weakdeps]
118-
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"

src/ModelingToolkit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export JumpProblem, DiscreteProblem
181181
export NonlinearSystem, OptimizationSystem, ConstraintsSystem
182182
export alias_elimination, flatten
183183
export connect, @connector, Connection, Flow, Stream, instream
184-
export @component
184+
export @component, @model
185185
export isinput, isoutput, getbounds, hasbounds, isdisturbance, istunable, getdist, hasdist,
186186
tunable_parameters, isirreducible, getdescription, hasdescription, isbinaryvar,
187187
isintegervar

src/systems/connectors.jl

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,98 @@ macro connector(expr)
1010
esc(component_post_processing(expr, true))
1111
end
1212

13+
macro connector(name::Symbol, body)
14+
esc(connector_macro((@__MODULE__), name, body))
15+
end
16+
17+
using MLStyle
18+
function connector_macro(mod, name, body)
19+
if !Meta.isexpr(body, :block)
20+
err = """
21+
connector body must be a block! It should be in the form of
22+
```
23+
@connector Pin begin
24+
v(t) = 1
25+
(i(t) = 1), [connect = Flow]
26+
end
27+
```
28+
"""
29+
error(err)
30+
end
31+
vs = Num[]
32+
dict = Dict{Symbol, Any}()
33+
for arg in body.args
34+
arg isa LineNumberNode && continue
35+
push!(vs, Num(parse_variable_def!(dict, mod, arg)))
36+
end
37+
iv = get(dict, :independent_variable, nothing)
38+
if iv === nothing
39+
error("$name doesn't have a independent variable")
40+
end
41+
ODESystem(Equation[], iv, vs, []; name)
42+
end
43+
44+
function parse_variable_def!(dict, mod, arg)
45+
MLStyle.@match arg begin
46+
::Symbol => generate_var(arg)
47+
Expr(:call, a, b) => generate_var!(dict, a, set_iv!(dict, b))
48+
Expr(:(=), a, b) => setdefault(parse_variable_def!(dict, mod, a), parse_default(mod, b))
49+
Expr(:tuple, a, b) => set_var_metadata(parse_variable_def!(dict, mod, a), parse_metadata(mod, b))
50+
_ => error("$arg cannot be parsed")
51+
end
52+
end
53+
54+
generate_var(a) = Symbolics.variable(a)
55+
function generate_var!(dict, a, b)
56+
iv = generate_var(b)
57+
prev_iv = get!(dict, :independent_variable) do
58+
iv
59+
end
60+
@assert isequal(iv, prev_iv)
61+
Symbolics.variable(a, T = SymbolicUtils.FnType{Tuple{Real}, Real})(iv)
62+
end
63+
function set_iv!(dict, b)
64+
prev_b = get!(dict, :independent_variable_name) do
65+
b
66+
end
67+
if prev_b != b
68+
error("Conflicting independent variable $prev_b and $b")
69+
end
70+
b
71+
end
72+
function parse_default(mod, a)
73+
a = Base.remove_linenums!(deepcopy(a))
74+
MLStyle.@match a begin
75+
Expr(:block, a) => get_var(mod, a)
76+
_ => error("Cannot parse default $a")
77+
end
78+
end
79+
function parse_metadata(mod, a)
80+
MLStyle.@match a begin
81+
Expr(:vect, eles...) => map(Base.Fix1(parse_metadata, mod), eles)
82+
Expr(:(=), a, b) => Symbolics.option_to_metadata_type(Val(a)) => get_var(mod, b)
83+
_ => error("Cannot parse metadata $a")
84+
end
85+
end
86+
function set_var_metadata(a, ms)
87+
for (m, v) in ms
88+
a = setmetadata(a, m, v)
89+
end
90+
a
91+
end
92+
function get_var(mod::Module, b)
93+
b isa Symbol ? getproperty(mod, b) : b
94+
end
95+
macro model(name::Symbol, expr)
96+
model_macro(name, expr)
97+
end
98+
function model_macro(name, expr)
99+
for arg in expr.args
100+
arg isa LineNumberNode && continue
101+
arg.head == :macrocall && compose
102+
end
103+
end
104+
13105
abstract type AbstractConnectorType end
14106
struct StreamConnector <: AbstractConnectorType end
15107
struct RegularConnector <: AbstractConnectorType end

0 commit comments

Comments
 (0)