@@ -24,6 +24,8 @@ struct Model{F, S}
24
24
end
25
25
(m:: Model )(args... ; kw... ) = m. f (args... ; kw... )
26
26
27
+ Base. parentmodule (m:: Model ) = parentmodule (m. f)
28
+
27
29
for f in (:connector , :mtkmodel )
28
30
isconnector = f == :connector ? true : false
29
31
@eval begin
@@ -40,7 +42,7 @@ function _model_macro(mod, name, expr, isconnector)
40
42
:kwargs => Dict {Symbol, Dict} (),
41
43
:structural_parameters => Dict {Symbol, Dict} ()
42
44
)
43
- comps = Symbol[]
45
+ comps = Union{ Symbol, Expr} []
44
46
ext = Ref {Any} (nothing )
45
47
eqs = Expr[]
46
48
icon = Ref {Union{String, URI}} ()
745
747
746
748
# ## Parsing Components:
747
749
748
- function component_args! (a, b, expr, varexpr, kwargs)
750
+ function component_args! (a, b, varexpr, kwargs; index_name = nothing )
749
751
# Whenever `b` is a function call, skip the first arg aka the function name.
750
752
# Whenever it is a kwargs list, include it.
751
753
start = b. head == :call ? 2 : 1
@@ -754,73 +756,115 @@ function component_args!(a, b, expr, varexpr, kwargs)
754
756
arg isa LineNumberNode && continue
755
757
MLStyle. @match arg begin
756
758
x:: Symbol || Expr (:kw , x) => begin
757
- _v = _rename (a, x)
758
- b. args[i] = Expr (:kw , x, _v)
759
- push! (varexpr. args, :((@isdefined $ x) && ($ _v = $ x)))
760
- push! (kwargs, Expr (:kw , _v, nothing ))
761
- # dict[:kwargs][_v] = nothing
759
+ varname, _varname = _rename (a, x)
760
+ b. args[i] = Expr (:kw , x, _varname)
761
+ push! (varexpr. args, :((if $ varname != = nothing
762
+ $ _varname = $ varname
763
+ elseif @isdefined $ x
764
+ # Allow users to define a var in `structural_parameters` and set
765
+ # that as positional arg of subcomponents; it is useful for cases
766
+ # where it needs to be passed to multiple subcomponents.
767
+ $ _varname = $ x
768
+ end )))
769
+ push! (kwargs, Expr (:kw , varname, nothing ))
770
+ # dict[:kwargs][varname] = nothing
762
771
end
763
772
Expr (:parameters , x... ) => begin
764
- component_args! (a, arg, expr, varexpr, kwargs)
773
+ component_args! (a, arg, varexpr, kwargs)
765
774
end
766
775
Expr (:kw , x, y) => begin
767
- _v = _rename (a, x)
768
- b. args[i] = Expr (:kw , x, _v)
769
- push! (varexpr. args, :($ _v = $ _v === nothing ? $ y : $ _v))
770
- push! (kwargs, Expr (:kw , _v, nothing ))
771
- # dict[:kwargs][_v] = nothing
776
+ varname, _varname = _rename (a, x)
777
+ b. args[i] = Expr (:kw , x, _varname)
778
+ if isnothing (index_name)
779
+ push! (varexpr. args, :($ _varname = $ varname === nothing ? $ y : $ varname))
780
+ else
781
+ push! (varexpr. args,
782
+ :($ _varname = $ varname === nothing ? $ y : $ varname[$ index_name]))
783
+ end
784
+ push! (kwargs, Expr (:kw , varname, nothing ))
785
+ # dict[:kwargs][varname] = nothing
772
786
end
773
787
_ => error (" Could not parse $arg of component $a " )
774
788
end
775
789
end
776
790
end
777
791
778
- function _parse_components! (exprs, body, kwargs)
779
- expr = Expr (:block )
792
+ model_name (name, range) = Symbol .(name, :_ , collect (range))
793
+
794
+ function _parse_components! (body, kwargs)
795
+ local expr
780
796
varexpr = Expr (:block )
781
- # push!(exprs, varexpr)
782
- comps = Vector{Union{Symbol, Expr}}[]
797
+ comps = Vector{Union{Union{Expr, Symbol}, Expr}}[]
783
798
comp_names = []
784
799
785
- for arg in body. args
786
- arg isa LineNumberNode && continue
787
- MLStyle. @match arg begin
788
- Expr (:block ) => begin
789
- # TODO : Do we need this?
790
- error (" Multiple `@components` block detected within a single block" )
791
- end
792
- Expr (:(= ), a, b) => begin
793
- arg = deepcopy (arg)
794
- b = deepcopy (arg. args[2 ])
800
+ Base. remove_linenums! (body)
801
+ arg = body. args[end ]
795
802
796
- component_args! (a, b, expr, varexpr, kwargs)
803
+ MLStyle. @match arg begin
804
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:(= ), c, d)))) => begin
805
+ array_varexpr = Expr (:block )
797
806
798
- arg. args[2 ] = b
799
- push! (expr. args, arg)
800
- push! (comp_names, a)
801
- if (isa (b. args[1 ], Symbol) || Meta. isexpr (b. args[1 ], :.))
802
- push! (comps, [a, b. args[1 ]])
803
- end
807
+ push! (comp_names, :($ a... ))
808
+ push! (comps, [a, b. args[1 ], d])
809
+ b = deepcopy (b)
810
+
811
+ component_args! (a, b, array_varexpr, kwargs; index_name = c)
812
+
813
+ expr = _named_idxs (a, d, :($ c -> $ b); extra_args = array_varexpr)
814
+ end
815
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:filter , e, Expr (:(= ), c, d))))) => begin
816
+ error (" List comprehensions with conditional statements aren't supported." )
817
+ end
818
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:(= ), c, d), e... ))) => begin
819
+ # Note that `e` is of the form `Tuple{Expr(:(=), c, d)}`
820
+ error (" More than one index isn't supported while building component array" )
821
+ end
822
+ Expr (:block ) => begin
823
+ # TODO : Do we need this?
824
+ error (" Multiple `@components` block detected within a single block" )
825
+ end
826
+ Expr (:(= ), a, Expr (:for , Expr (:(= ), c, d), b)) => begin
827
+ Base. remove_linenums! (b)
828
+ array_varexpr = Expr (:block )
829
+ push! (array_varexpr. args, b. args[1 : (end - 1 )]. .. )
830
+ push! (comp_names, :($ a... ))
831
+ push! (comps, [a, b. args[end ]. args[1 ], d])
832
+ b = deepcopy (b)
833
+
834
+ component_args! (a, b. args[end ], array_varexpr, kwargs; index_name = c)
835
+
836
+ expr = _named_idxs (a, d, :($ c -> $ (b. args[end ])); extra_args = array_varexpr)
837
+ end
838
+ Expr (:(= ), a, b) => begin
839
+ arg = deepcopy (arg)
840
+ b = deepcopy (arg. args[2 ])
841
+
842
+ component_args! (a, b, varexpr, kwargs)
843
+
844
+ arg. args[2 ] = b
845
+ expr = :(@named $ arg)
846
+ push! (comp_names, a)
847
+ if (isa (b. args[1 ], Symbol) || Meta. isexpr (b. args[1 ], :.))
848
+ push! (comps, [a, b. args[1 ]])
804
849
end
805
- _ => error (" Couldn't parse the component body: $arg " )
806
850
end
851
+ _ => error (" Couldn't parse the component body: $arg " )
807
852
end
853
+
808
854
return comp_names, comps, expr, varexpr
809
855
end
810
856
811
857
function push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
812
858
blk = Expr (:block )
813
859
push! (blk. args, varexpr)
814
- push! (blk. args, :(@named begin
815
- $ (expr_vec. args... )
816
- end ))
860
+ push! (blk. args, expr_vec)
817
861
push! (blk. args, :($ push! (systems, $ (comp_names... ))))
818
862
push! (ifexpr. args, blk)
819
863
end
820
864
821
865
function handle_if_x! (mod, exprs, ifexpr, x, kwargs, condition = nothing )
822
866
push! (ifexpr. args, condition)
823
- comp_names, comps, expr_vec, varexpr = _parse_components! (ifexpr, x, kwargs)
867
+ comp_names, comps, expr_vec, varexpr = _parse_components! (x, kwargs)
824
868
push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
825
869
comps
826
870
end
@@ -836,7 +880,7 @@ function handle_if_y!(exprs, ifexpr, y, kwargs)
836
880
push! (ifexpr. args, elseifexpr)
837
881
(comps... ,)
838
882
else
839
- comp_names, comps, expr_vec, varexpr = _parse_components! (exprs, y, kwargs)
883
+ comp_names, comps, expr_vec, varexpr = _parse_components! (y, kwargs)
840
884
push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
841
885
comps
842
886
end
@@ -861,25 +905,23 @@ function parse_components!(exprs, cs, dict, compbody, kwargs)
861
905
Expr (:if , condition, x, y) => begin
862
906
handle_conditional_components (condition, dict, exprs, kwargs, x, y)
863
907
end
864
- Expr (:( = ), a, b) => begin
865
- comp_names, comps, expr_vec, varexpr = _parse_components! (exprs,
866
- :(begin
908
+ # Either the arg is top level component declaration or an invalid cause - both are handled by `_parse_components`
909
+ _ => begin
910
+ comp_names, comps, expr_vec, varexpr = _parse_components! ( :(begin
867
911
$ arg
868
912
end ),
869
913
kwargs)
870
914
push! (cs, comp_names... )
871
915
push! (dict[:components ], comps... )
872
- push! (exprs, varexpr, :(@named begin
873
- $ (expr_vec. args... )
874
- end ))
916
+ push! (exprs, varexpr, expr_vec)
875
917
end
876
- _ => error (" Couldn't parse the component body $compbody " )
877
918
end
878
919
end
879
920
end
880
921
881
922
function _rename (compname, varname)
882
923
compname = Symbol (compname, :__ , varname)
924
+ (compname, Symbol (:_ , compname))
883
925
end
884
926
885
927
# Handle top level branching
0 commit comments