@@ -14,6 +14,12 @@ macro connector(name::Symbol, body)
14
14
esc (connector_macro ((@__MODULE__ ), name, body))
15
15
end
16
16
17
+ struct Model{F, S}
18
+ f:: F
19
+ structure:: S
20
+ end
21
+ (m:: Model )(args... ; kw... ) = m. f (args... ; kw... )
22
+
17
23
using MLStyle
18
24
function connector_macro (mod, name, body)
19
25
if ! Meta. isexpr (body, :block )
@@ -32,33 +38,55 @@ function connector_macro(mod, name, body)
32
38
dict = Dict {Symbol, Any} ()
33
39
for arg in body. args
34
40
arg isa LineNumberNode && continue
35
- push! (vs, Num (parse_variable_def! (dict, mod, arg)))
41
+ push! (vs, Num (parse_variable_def! (dict, mod, arg, :variables )))
36
42
end
37
43
iv = get (dict, :independent_variable , nothing )
38
- if iv === nothing
44
+ if iv === nothing
39
45
error (" $name doesn't have a independent variable" )
40
46
end
41
- ODESystem (Equation[], iv, vs, []; name)
47
+ quote
48
+ $ name = $ Model ((; name) -> $ ODESystem ($ (Equation[]), $ iv, $ vs, $ ([]); name), $ dict)
49
+ end
42
50
end
43
51
44
- function parse_variable_def! (dict, mod, arg)
52
+ function parse_variable_def! (dict, mod, arg, varclass )
45
53
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))
54
+ :: Symbol => generate_var (arg, varclass)
55
+ Expr (:call , a, b) => generate_var! (dict, a, set_iv! (dict, b), varclass)
56
+ Expr (:(= ), a, b) => begin
57
+ var = parse_variable_def! (dict, mod, a, varclass)
58
+ def = parse_default (mod, b)
59
+ dict[varclass][getname (var)][:default ] = def
60
+ setdefault (var, def)
61
+ end
62
+ Expr (:tuple , a, b) => begin
63
+ var = parse_variable_def! (dict, mod, a, varclass)
64
+ meta = parse_metadata (mod, b)
65
+ if (ct = get (meta, VariableConnectType, nothing )) != = nothing
66
+ dict[varclass][getname (var)][:connection_type ] = nameof (ct)
67
+ end
68
+ set_var_metadata (var, meta)
69
+ end
50
70
_ => error (" $arg cannot be parsed" )
51
71
end
52
72
end
53
73
54
74
generate_var (a) = Symbolics. variable (a)
55
- function generate_var! (dict, a, b)
75
+ function generate_var! (dict, a, b, varclass )
56
76
iv = generate_var (b)
57
77
prev_iv = get! (dict, :independent_variable ) do
58
78
iv
59
79
end
60
80
@assert isequal (iv, prev_iv)
61
- Symbolics. variable (a, T = SymbolicUtils. FnType{Tuple{Real}, Real})(iv)
81
+ vd = get! (dict, varclass) do
82
+ Dict {Symbol, Dict{Symbol, Any}} ()
83
+ end
84
+ vd[a] = Dict {Symbol, Any} ()
85
+ var = Symbolics. variable (a, T = SymbolicUtils. FnType{Tuple{Real}, Real})(iv)
86
+ if varclass == :parameters
87
+ var = toparam (var)
88
+ end
89
+ var
62
90
end
63
91
function set_iv! (dict, b)
64
92
prev_b = get! (dict, :independent_variable_name ) do
@@ -78,7 +106,7 @@ function parse_default(mod, a)
78
106
end
79
107
function parse_metadata (mod, a)
80
108
MLStyle. @match a begin
81
- Expr (:vect , eles... ) => map (Base . Fix1 ( parse_metadata, mod), eles)
109
+ Expr (:vect , eles... ) => Dict ( parse_metadata (mod, e) for e in eles)
82
110
Expr (:(= ), a, b) => Symbolics. option_to_metadata_type (Val (a)) => get_var (mod, b)
83
111
_ => error (" Cannot parse metadata $a " )
84
112
end
@@ -97,54 +125,71 @@ macro model(name::Symbol, expr)
97
125
end
98
126
function model_macro (mod, name, expr)
99
127
exprs = Expr (:block )
128
+ dict = Dict {Symbol, Any} ()
100
129
for arg in expr. args
101
130
arg isa LineNumberNode && continue
102
131
arg. head == :macrocall || error (" $arg is not valid syntax. Expected a macro call." )
103
- parse_model! (exprs. args, mod, arg)
132
+ parse_model! (exprs. args, dict, mod, arg)
133
+ end
134
+ iv = get (dict, :independent_variable , nothing )
135
+ if iv === nothing
136
+ error (" $name doesn't have a independent variable" )
104
137
end
105
- exprs
138
+ push! (exprs. args,
139
+ :($ ODESystem (var"#___eqs___" , $ iv, var"#___vs___" , $ ([]);
140
+ systems = var"#___comps___" , name)))
141
+ :($ name = $ Model ((; name) -> $ exprs, $ dict))
106
142
end
107
- function parse_model! (exprs, mod, arg)
143
+ function parse_model! (exprs, dict, mod, arg)
108
144
mname = arg. args[1 ]
109
145
vs = Num[]
110
- dict = Dict {Symbol, Any} ()
111
146
body = arg. args[end ]
112
147
if mname == Symbol (" @components" )
113
148
parse_components! (exprs, dict, body)
114
149
elseif mname == Symbol (" @variables" )
115
- parse_variables! (exprs, vs, dict, mod, body)
150
+ parse_variables! (exprs, vs, dict, mod, body, :variables )
116
151
elseif mname == Symbol (" @equations" )
117
152
parse_equations! (exprs, dict, body)
118
153
else
119
154
error (" $mname is not handled." )
120
155
end
121
156
end
122
157
function parse_components! (exprs, dict, body)
158
+ expr = Expr (:block )
159
+ push! (exprs, expr)
123
160
comps = Pair{String, String}[]
124
- comp_name = Symbol ( " #___comp___ " )
161
+ names = Symbol[]
125
162
for arg in body. args
126
163
arg isa LineNumberNode && continue
127
164
MLStyle. @match arg begin
128
165
Expr (:(= ), a, b) => begin
166
+ push! (names, a)
129
167
arg = deepcopy (arg)
130
168
b = deepcopy (arg. args[2 ])
131
169
push! (b. args, Expr (:kw , :name , Meta. quot (a)))
132
170
arg. args[2 ] = b
133
171
push! (comps, String (a) => readable_code (b))
134
- push! (exprs, @show arg)
172
+ push! (expr . args, arg)
135
173
end
136
174
_ => error (" `@components` only takes assignment expressions. Got $arg " )
137
175
end
138
176
end
177
+ push! (expr. args, :(var"#___comps___" = [$ (names... )]))
139
178
dict[:components ] = comps
140
179
end
141
- function parse_variables! (exprs, vs, dict, mod, body)
180
+ function parse_variables! (exprs, vs, dict, mod, body, varclass)
181
+ expr = Expr (:block )
182
+ push! (exprs, expr)
183
+ names = Symbol[]
142
184
for arg in body. args
143
185
arg isa LineNumberNode && continue
144
- v = Num (parse_variable_def! (dict, mod, arg))
186
+ v = Num (parse_variable_def! (dict, mod, arg, varclass ))
145
187
push! (vs, v)
146
- push! (exprs, :($ (getname (v)) = $ v))
188
+ name = getname (v)
189
+ push! (names, name)
190
+ push! (expr. args, :($ name = $ v))
147
191
end
192
+ push! (expr. args, :(var"#___vs___" = [$ (names... )]))
148
193
end
149
194
function parse_equations! (exprs, dict, body)
150
195
eqs = :(Equation[])
0 commit comments