@@ -10,6 +10,98 @@ macro connector(expr)
10
10
esc (component_post_processing (expr, true ))
11
11
end
12
12
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
+
13
105
abstract type AbstractConnectorType end
14
106
struct StreamConnector <: AbstractConnectorType end
15
107
struct RegularConnector <: AbstractConnectorType end
0 commit comments