@@ -37,7 +37,7 @@ function _model_macro(mod, name, expr, isconnector)
37
37
exprs = Expr (:block )
38
38
dict = Dict {Symbol, Any} ()
39
39
dict[:kwargs ] = Dict {Symbol, Any} ()
40
- comps = Symbol[]
40
+ comps = Union{ Symbol, Expr} []
41
41
ext = Ref {Any} (nothing )
42
42
eqs = Expr[]
43
43
icon = Ref {Union{String, URI}} ()
634
634
635
635
# ## Parsing Components:
636
636
637
- function component_args! (a, b, expr, varexpr, kwargs)
637
+ function component_args! (a, b, varexpr, kwargs; index_name = nothing )
638
638
# Whenever `b` is a function call, skip the first arg aka the function name.
639
639
# Whenever it is a kwargs list, include it.
640
640
start = b. head == :call ? 2 : 1
@@ -643,73 +643,115 @@ function component_args!(a, b, expr, varexpr, kwargs)
643
643
arg isa LineNumberNode && continue
644
644
MLStyle. @match arg begin
645
645
x:: Symbol || Expr (:kw , x) => begin
646
- _v = _rename (a, x)
647
- b. args[i] = Expr (:kw , x, _v)
648
- push! (varexpr. args, :((@isdefined $ x) && ($ _v = $ x)))
649
- push! (kwargs, Expr (:kw , _v, nothing ))
650
- # dict[:kwargs][_v] = nothing
646
+ varname, _varname = _rename (a, x)
647
+ b. args[i] = Expr (:kw , x, _varname)
648
+ push! (varexpr. args, :((if $ varname != = nothing
649
+ $ _varname = $ varname
650
+ elseif @isdefined $ x
651
+ # Allow users to define a var in `structural_parameters` and set
652
+ # that as positional arg of subcomponents; it is useful for cases
653
+ # where it needs to be passed to multiple subcomponents.
654
+ $ _varname = $ x
655
+ end )))
656
+ push! (kwargs, Expr (:kw , varname, nothing ))
657
+ # dict[:kwargs][varname] = nothing
651
658
end
652
659
Expr (:parameters , x... ) => begin
653
- component_args! (a, arg, expr, varexpr, kwargs)
660
+ component_args! (a, arg, varexpr, kwargs)
654
661
end
655
662
Expr (:kw , x, y) => begin
656
- _v = _rename (a, x)
657
- b. args[i] = Expr (:kw , x, _v)
658
- push! (varexpr. args, :($ _v = $ _v === nothing ? $ y : $ _v))
659
- push! (kwargs, Expr (:kw , _v, nothing ))
660
- # dict[:kwargs][_v] = nothing
663
+ varname, _varname = _rename (a, x)
664
+ b. args[i] = Expr (:kw , x, _varname)
665
+ if isnothing (index_name)
666
+ push! (varexpr. args, :($ _varname = $ varname === nothing ? $ y : $ varname))
667
+ else
668
+ push! (varexpr. args,
669
+ :($ _varname = $ varname === nothing ? $ y : $ varname[$ index_name]))
670
+ end
671
+ push! (kwargs, Expr (:kw , varname, nothing ))
672
+ # dict[:kwargs][varname] = nothing
661
673
end
662
674
_ => error (" Could not parse $arg of component $a " )
663
675
end
664
676
end
665
677
end
666
678
667
- function _parse_components! (exprs, body, kwargs)
668
- expr = Expr (:block )
679
+ model_name (name, range) = Symbol .(name, :_ , collect (range))
680
+
681
+ function _parse_components! (body, kwargs)
682
+ local expr
669
683
varexpr = Expr (:block )
670
- # push!(exprs, varexpr)
671
- comps = Vector{Union{Symbol, Expr}}[]
684
+ comps = Vector{Union{Union{Expr, Symbol}, Expr}}[]
672
685
comp_names = []
673
686
674
- for arg in body. args
675
- arg isa LineNumberNode && continue
676
- MLStyle. @match arg begin
677
- Expr (:block ) => begin
678
- # TODO : Do we need this?
679
- error (" Multiple `@components` block detected within a single block" )
680
- end
681
- Expr (:(= ), a, b) => begin
682
- arg = deepcopy (arg)
683
- b = deepcopy (arg. args[2 ])
687
+ Base. remove_linenums! (body)
688
+ arg = body. args[end ]
689
+
690
+ MLStyle. @match arg begin
691
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:(= ), c, d)))) => begin
692
+ array_varexpr = Expr (:block )
684
693
685
- component_args! (a, b, expr, varexpr, kwargs)
694
+ push! (comp_names, :($ a... ))
695
+ push! (comps, [a, b. args[1 ], d])
696
+ b = deepcopy (b)
686
697
687
- arg. args[2 ] = b
688
- push! (expr. args, arg)
689
- push! (comp_names, a)
698
+ component_args! (a, b, array_varexpr, kwargs; index_name = c)
699
+
700
+ expr = _named_idxs (a, d, :($ c -> $ b); extra_args = array_varexpr)
701
+ end
702
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:filter , e, Expr (:(= ), c, d))))) => begin
703
+ error (" List comprehensions with conditional statements aren't supported." )
704
+ end
705
+ Expr (:(= ), a, Expr (:comprehension , Expr (:generator , b, Expr (:(= ), c, d), e... ))) => begin
706
+ # Note that `e` is of the form `Tuple{Expr(:(=), c, d)}`
707
+ error (" More than one index isn't supported while building component array" )
708
+ end
709
+ Expr (:block ) => begin
710
+ # TODO : Do we need this?
711
+ error (" Multiple `@components` block detected within a single block" )
712
+ end
713
+ Expr (:(= ), a, Expr (:for , Expr (:(= ), c, d), b)) => begin
714
+ Base. remove_linenums! (b)
715
+ array_varexpr = Expr (:block )
716
+ push! (array_varexpr. args, b. args[1 : (end - 1 )]. .. )
717
+ push! (comp_names, :($ a... ))
718
+ push! (comps, [a, b. args[end ]. args[1 ], d])
719
+ b = deepcopy (b)
720
+
721
+ component_args! (a, b. args[end ], array_varexpr, kwargs; index_name = c)
722
+
723
+ expr = _named_idxs (a, d, :($ c -> $ (b. args[end ])); extra_args = array_varexpr)
724
+ end
725
+ Expr (:(= ), a, b) => begin
726
+ arg = deepcopy (arg)
727
+ b = deepcopy (arg. args[2 ])
728
+
729
+ component_args! (a, b, varexpr, kwargs)
730
+
731
+ arg. args[2 ] = b
732
+ expr = :(@named $ arg)
733
+ push! (comp_names, a)
690
734
if (isa (b. args[1 ], Symbol) || Meta. isexpr (b. args[1 ], :.))
691
- push! (comps, [a, b. args[1 ]])
735
+ push! (comps, [a, b. args[1 ]])
692
736
end
693
- end
694
- _ => error (" Couldn't parse the component body: $arg " )
695
737
end
738
+ _ => error (" Couldn't parse the component body: $arg " )
696
739
end
740
+
697
741
return comp_names, comps, expr, varexpr
698
742
end
699
743
700
744
function push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
701
745
blk = Expr (:block )
702
746
push! (blk. args, varexpr)
703
- push! (blk. args, :(@named begin
704
- $ (expr_vec. args... )
705
- end ))
747
+ push! (blk. args, expr_vec)
706
748
push! (blk. args, :($ push! (systems, $ (comp_names... ))))
707
749
push! (ifexpr. args, blk)
708
750
end
709
751
710
752
function handle_if_x! (mod, exprs, ifexpr, x, kwargs, condition = nothing )
711
753
push! (ifexpr. args, condition)
712
- comp_names, comps, expr_vec, varexpr = _parse_components! (ifexpr, x, kwargs)
754
+ comp_names, comps, expr_vec, varexpr = _parse_components! (x, kwargs)
713
755
push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
714
756
comps
715
757
end
@@ -725,7 +767,7 @@ function handle_if_y!(exprs, ifexpr, y, kwargs)
725
767
push! (ifexpr. args, elseifexpr)
726
768
(comps... ,)
727
769
else
728
- comp_names, comps, expr_vec, varexpr = _parse_components! (exprs, y, kwargs)
770
+ comp_names, comps, expr_vec, varexpr = _parse_components! (y, kwargs)
729
771
push_conditional_component! (ifexpr, expr_vec, comp_names, varexpr)
730
772
comps
731
773
end
@@ -750,25 +792,23 @@ function parse_components!(exprs, cs, dict, compbody, kwargs)
750
792
Expr (:if , condition, x, y) => begin
751
793
handle_conditional_components (condition, dict, exprs, kwargs, x, y)
752
794
end
753
- Expr (:( = ), a, b) => begin
754
- comp_names, comps, expr_vec, varexpr = _parse_components! (exprs,
755
- :(begin
795
+ # Either the arg is top level component declaration or an invalid cause - both are handled by `_parse_components`
796
+ _ => begin
797
+ comp_names, comps, expr_vec, varexpr = _parse_components! ( :(begin
756
798
$ arg
757
799
end ),
758
800
kwargs)
759
801
push! (cs, comp_names... )
760
802
push! (dict[:components ], comps... )
761
- push! (exprs, varexpr, :(@named begin
762
- $ (expr_vec. args... )
763
- end ))
803
+ push! (exprs, varexpr, expr_vec)
764
804
end
765
- _ => error (" Couldn't parse the component body $compbody " )
766
805
end
767
806
end
768
807
end
769
808
770
809
function _rename (compname, varname)
771
810
compname = Symbol (compname, :__ , varname)
811
+ (compname, Symbol (:_ , compname))
772
812
end
773
813
774
814
# Handle top level branching
0 commit comments