@@ -597,13 +597,16 @@ function Base.show(io::IO, ::MIME"text/plain", sys::AbstractSystem)
597
597
return nothing
598
598
end
599
599
600
- function _named (expr)
600
+ function split_assign (expr)
601
601
if ! (expr isa Expr && expr. head === :(= ) && expr. args[2 ]. head === :call )
602
602
throw (ArgumentError (" expression should be of the form `sys = foo(a, b)`" ))
603
603
end
604
604
name, call = expr. args
605
+ end
605
606
607
+ function _named (name, call, runtime= false )
606
608
has_kw = false
609
+ call isa Expr || throw (Meta. ParseError (" The rhs must be an Expr. Got $call ." ))
607
610
if length (call. args) >= 2 && call. args[2 ] isa Expr
608
611
# canonicalize to use `:parameters`
609
612
if call. args[2 ]. head === :kw
@@ -626,18 +629,78 @@ function _named(expr)
626
629
kws = call. args[2 ]. args
627
630
628
631
if ! any (kw-> (kw isa Symbol ? kw : kw. args[1 ]) == :name , kws) # don't overwrite `name` kwarg
629
- pushfirst! (kws, Expr (:kw , :name , Meta. quot (name)))
632
+ pushfirst! (kws, Expr (:kw , :name , runtime ? name : Meta. quot (name)))
633
+ end
634
+ call
635
+ end
636
+
637
+ function _named_idxs (name:: Symbol , idxs, call)
638
+ if call. head != = :->
639
+ throw (ArgumentError (" Not an anonymous function" ))
640
+ end
641
+ if ! isa (call. args[1 ], Symbol)
642
+ throw (ArgumentError (" not a single-argument anonymous function" ))
630
643
end
631
- :($ name = $ call)
644
+ sym, ex = call. args
645
+ ex = Base. Cartesian. poplinenum (ex)
646
+ ex = _named (:(Symbol ($ (Meta. quot (name)), :_ , $ sym)), ex, true )
647
+ ex = Base. Cartesian. poplinenum (ex)
648
+ :($ name = $ map ($ sym-> $ ex, $ idxs))
632
649
end
633
650
651
+ check_name (name) = name isa Symbol || throw (Meta. ParseError (" The lhs must be a symbol (a) or a ref (a[1:10]). Got $name ." ))
652
+
634
653
"""
635
- $(SIGNATURES)
654
+ @named y = foo(x)
655
+ @named y[1:10] = foo(x)
656
+ @named y 1:10 i -> foo(x*i)
636
657
637
658
Rewrite `@named y = foo(x)` to `y = foo(x; name=:y)`.
659
+
660
+ Rewrite `@named y[1:10] = foo(x)` to `y = map(i′->foo(x; name=Symbol(:y_, i′)), 1:10)`.
661
+
662
+ Rewrite `@named y 1:10 i -> foo(x*i)` to `y = map(i->foo(x*i; name=Symbol(:y_, i)), 1:10)`.
663
+
664
+ Examples:
665
+ ```julia
666
+ julia> using ModelingToolkit
667
+
668
+ julia> foo(i; name) = i, name
669
+ foo (generic function with 1 method)
670
+
671
+ julia> x = 41
672
+ 41
673
+
674
+ julia> @named y = foo(x)
675
+ (41, :y)
676
+
677
+ julia> @named y[1:3] = foo(x)
678
+ 3-element Vector{Tuple{Int64, Symbol}}:
679
+ (41, :y_1)
680
+ (41, :y_2)
681
+ (41, :y_3)
682
+
683
+ julia> @named y 1:3 i -> foo(x*i)
684
+ 3-element Vector{Tuple{Int64, Symbol}}:
685
+ (41, :y_1)
686
+ (82, :y_2)
687
+ (123, :y_3)
688
+ ```
638
689
"""
639
690
macro named (expr)
640
- esc (_named (expr))
691
+ name, call = split_assign (expr)
692
+ if Meta. isexpr (name, :ref )
693
+ name, idxs = name. args
694
+ check_name (name)
695
+ esc (_named_idxs (name, idxs, :($ (gensym ()) -> $ call)))
696
+ else
697
+ check_name (name)
698
+ esc (:($ name = $ (_named (name, call))))
699
+ end
700
+ end
701
+
702
+ macro named (name:: Symbol , idxs, call)
703
+ esc (_named_idxs (name, idxs, call))
641
704
end
642
705
643
706
function _config (expr, namespace)
@@ -854,15 +917,14 @@ Base.:(&)(sys::AbstractSystem, basesys::AbstractSystem; name::Symbol=nameof(sys)
854
917
compose multiple systems together. The resulting system would inherit the first
855
918
system's name.
856
919
"""
857
- compose (syss:: AbstractSystem... ; name= nameof (first (syss))) = compose (collect (syss); name= name)
858
- function compose (syss:: AbstractArray{<:AbstractSystem} ; name= nameof (first (syss)))
859
- nsys = length (syss)
860
- nsys >= 2 || throw (ArgumentError (" There must be at least 2 systems. Got $nsys systems." ))
861
- sys = first (syss)
920
+ function compose (sys:: AbstractSystem , systems:: AbstractArray{<:AbstractSystem} ; name= nameof (first (syss)))
921
+ nsys = length (systems)
922
+ nsys >= 1 || throw (ArgumentError (" There must be at least 1 subsystem. Got $nsys subsystems." ))
862
923
@set! sys. name = name
863
- @set! sys. systems = syss[ 2 : end ]
924
+ @set! sys. systems = systems
864
925
return sys
865
926
end
927
+ compose (syss:: AbstractSystem... ; name= nameof (first (syss))) = compose (first (syss), collect (syss[2 : end ]); name= name)
866
928
Base.:(∘ )(sys1:: AbstractSystem , sys2:: AbstractSystem ) = compose (sys1, sys2)
867
929
868
930
UnPack. unpack (sys:: ModelingToolkit.AbstractSystem , :: Val{p} ) where p = getproperty (sys, p; namespace= false )
0 commit comments