@@ -73,64 +73,59 @@ Base.Symbol(vn::VarName) = Symbol(string(vn)) # simplified symbol
73
73
74
74
75
75
"""
76
- inspace(vn::Union{VarName, Symbol, Expr }, space::Tuple)
76
+ inspace(vn::Union{VarName, Symbol}, space::Tuple)
77
77
78
78
Check whether `vn`'s variable symbol is in `space`.
79
79
"""
80
- inspace (:: VarName , :: Tuple{} ) = true
81
- inspace (vn:: VarName , space:: Tuple ):: Bool = getsym (vn) in space || _in (string (vn), space)
80
+ inspace (vn, space:: Tuple{} ) = true # empty space is treated as universal set
82
81
inspace (vn, space:: Tuple ) = vn in space
82
+ inspace (vn:: VarName , space:: Tuple{} ) = true
83
+ inspace (vn:: VarName , space:: Tuple ) = any (_in (vn, s) for s in space)
83
84
84
- _in (:: String , :: Tuple{} ) = false
85
- _in (vn_str:: String , space:: Tuple ):: Bool = _in (vn_str, Base. tail (space))
86
- function _in (vn_str:: String , space:: Tuple{Expr,Vararg} ):: Bool
87
- # Collect expressions from space
88
- expr = first (space)
89
- # Filter `(` and `)` out and get a string representation of `exprs`
90
- expr_str = replace (string (expr), r" \( |\) " => " " )
91
- # Check if `vn_str` is in `expr_strs`
92
- valid = occursin (expr_str, vn_str)
93
- return valid || _in (vn_str, Base. tail (space))
85
+ _in (vn:: VarName , s:: Symbol ) = getsym (vn) == s
86
+ _in (vn:: VarName , s:: VarName ) = subsumes (s, vn)
87
+
88
+
89
+ """
90
+ subsumes(u::VarName, v::VarName)
91
+
92
+ Check whether the variable name `v` describes a sub-range of the variable `u`. Supported
93
+ indexing:
94
+
95
+ - Scalar: `x` subsumes `x[1, 2]`, `x[1, 2]` subsumes `x[1, 2][3]`, etc.
96
+ - Array of scalar: `x[[1, 2], 3]` subsumes `x[1, 3]`, `x[1:3]` subsumes `x[2][1]`, etc.
97
+ (basically everything that fulfills `issubset`).
98
+ - Slices: `x[2, :]` subsumes `x[2, 10][1]`, etc.
99
+
100
+ Currently _not_ supported are:
101
+
102
+ - Boolean indexing, literal `CartesianIndex` (these could be added, though)
103
+ - Linear indexing of multidimensional arrays: `x[4]` does not subsume `x[2, 2]` for `x` a matrix
104
+ - Trailing ones: `x[2, 1]` does not subsume `x[2]` for `x` a vector
105
+ """
106
+ function subsumes (u:: VarName , v:: VarName )
107
+ return getsym (u) == getsym (v) && subsumes (u. indexing, v. indexing)
108
+ end
109
+
110
+ subsumes (:: Tuple{} , :: Tuple{} ) = true # x subsumes x
111
+ subsumes (:: Tuple{} , :: Tuple ) = true # x subsumes x[1]
112
+ subsumes (:: Tuple , :: Tuple{} ) = false # x[1] does not subsume x
113
+ function subsumes (t:: Tuple , u:: Tuple ) # does x[i]... subsume x[j]...?
114
+ return _issubindex (first (t), first (u)) && subsumes (Base. tail (t), Base. tail (u))
115
+ end
116
+
117
+ const AnyIndex = Union{Int, AbstractVector{Int}, Colon}
118
+ _issubindex_ (:: Tuple{Vararg{AnyIndex}} , :: Tuple{Vararg{AnyIndex}} ) = false
119
+ function _issubindex (t:: NTuple{N, AnyIndex} , u:: NTuple{N, AnyIndex} ) where {N}
120
+ return all (_issubrange (j, i) for (i, j) in zip (t, u))
94
121
end
95
122
123
+ const ConcreteIndex = Union{Int, AbstractVector{Int}} # this include all kinds of ranges
124
+ """ Determine whether indices `i` are contained in `j`, treating `:` as universal set."""
125
+ _issubrange (i:: ConcreteIndex , j:: ConcreteIndex ) = issubset (i, j)
126
+ _issubrange (i:: Union{ConcreteIndex, Colon} , j:: Colon ) = true
127
+ _issubrange (i:: Colon , j:: ConcreteIndex ) = true
96
128
97
- # inspace(::Union{VarName, Symbol, Expr}, ::Tuple{}) = true
98
- # inspace(vn::Union{VarName, Symbol, Expr}, space::Tuple) = any(_ismatch(vn, s) for s in space)
99
-
100
- # _ismatch(vn, s) = (_name(vn) == _name(s)) && _isprefix(_indexing(s), _indexing(vn))
101
-
102
- # _isprefix(::Tuple{}, ::Tuple{}) = true
103
- # _isprefix(::Tuple{}, ::Tuple) = true
104
- # _isprefix(::Tuple, ::Tuple{}) = false
105
- # _isprefix(t::Tuple, u::Tuple) = _subsumes(first(t), first(u)) && _isprefix(Base.tail(t), Base.tail(u))
106
-
107
- # const ConcreteIndex = Union{Int, AbstractVector{Int}} # this include all kinds of ranges
108
- # """Determine whether `i` is a valid if `j` is."""
109
- # _subsumes(i::ConcreteIndex, j::ConcreteIndex) = issubset(i, j)
110
- # _subsumes(i::Union{ConcreteIndex, Colon}, j::Colon) = true
111
- # _subsumes(i::Colon, j::ConcreteIndex) = false
112
-
113
- # _name(vn::Symbol) = vn
114
- # _name(vn::VarName) = getsym(vn)
115
- # function _name(vn::Expr)
116
- # if Meta.isexpr(vn, :ref)
117
- # _name(vn.args[1])
118
- # else
119
- # throw("VarName: Mis-formed variable name $(vn)!")
120
- # end
121
- # end
122
-
123
- # _indexing(vn::Symbol) = ()
124
- # _indexing(vn::VarName) = getindexing(vn)
125
- # function _indexing(vn::Expr)
126
- # if Meta.isexpr(vn, :ref)
127
- # init = _indexing(vn.args[1])
128
- # last = Tuple(vn.args[2:end])
129
- # return (init..., last)
130
- # else
131
- # throw("VarName: Mis-formed variable name $(vn)!")
132
- # end
133
- # end
134
129
135
130
136
131
"""
0 commit comments