Skip to content

Commit 9f843c8

Browse files
committed
Add possibility to create array of variables
1 parent 93fe6bd commit 9f843c8

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

src/variables.jl

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ struct Variable <: Function
1919
known::Bool
2020
Variable(name; known = false) = new(name, known)
2121
end
22+
function Variable(name, indices...; known = false)
23+
var_name = Symbol("$name[$(join(indices, ","))]")
24+
Variable(var_name; known=known)
25+
end
26+
2227
(x::Variable)(args...) = Operation(x, collect(Expression, args))
2328

2429
Base.isequal(x::Variable, y::Variable) = (x.name, x.known) == (y.name, y.known)
@@ -74,29 +79,64 @@ function _parse_vars(macroname, known, x)
7479
x = flatten_expr!(x)
7580
for _var in x
7681
iscall = isa(_var, Expr) && _var.head == :call
77-
issym = _var isa Symbol
78-
@assert iscall || issym "@$macroname expects a tuple of expressions or an expression of a tuple (`@$macroname x y z(t)` or `@$macroname x, y, z(t)`)"
82+
isarray = isa(_var, Expr) && _var.head == :ref
83+
issym = _var isa Symbol
84+
@assert iscall || isarray || issym "@$macroname expects a tuple of expressions or an expression of a tuple (`@$macroname x y z(t) v[1:3] w[1:2,1:4]` or `@$macroname x, y, z(t) v[1:3] w[1:2,1:4]`)"
7985

8086
if iscall
81-
var_name = _var.args[1]
82-
if _var.args[end] == :..
83-
expr = :($var_name = $Variable($(Meta.quot(var_name)); known = $known))
84-
else
85-
expr = :($var_name = $Variable($(Meta.quot(var_name)); known = $known)($(_var.args[2:end]...)))
86-
end
87+
var_name, expr = _construct_vars(_var.args[1], known, _var.args[2:end])
8788
else
88-
# Implicit 0-args call
89-
var_name = _var
90-
expr = :($var_name = $Variable($(Meta.quot(var_name)); known = $known)())
89+
var_name, expr = _construct_vars(_var, known, nothing)
9190
end
92-
9391
push!(var_names, var_name)
9492
push!(ex.args, expr)
9593
end
9694
push!(ex.args, build_expr(:tuple, var_names))
9795
return ex
9896
end
9997

98+
function _construct_vars(_var, known, call_args)
99+
issym = _var isa Symbol
100+
isarray = isa(_var, Expr) && _var.head == :ref
101+
if isarray
102+
var_name = _var.args[1]
103+
indices = _var.args[2:end]
104+
expr = _construct_array_vars(var_name, known, call_args, indices...)
105+
else
106+
# Implicit 0-args call
107+
var_name = _var
108+
expr = _construct_var(var_name, known, call_args)
109+
end
110+
var_name, :($var_name = $expr)
111+
end
112+
113+
function _construct_var(var_name, known, call_args)
114+
if call_args === nothing
115+
:(Variable($(Meta.quot(var_name)); known = $known)())
116+
elseif call_args[end] == :..
117+
:(Variable($(Meta.quot(var_name)); known = $known))
118+
else
119+
:(Variable($(Meta.quot(var_name)); known = $known)($(call_args...)))
120+
end
121+
end
122+
123+
function _construct_var(var_name, known, call_args, ind)
124+
if call_args === nothing
125+
:(Variable($(Meta.quot(var_name)), $ind...; known = $known)())
126+
elseif call_args[end] == :..
127+
:(Variable($(Meta.quot(var_name)), $ind...; known = $known))
128+
else
129+
:(Variable($(Meta.quot(var_name)), $ind...; known = $known)($(call_args...)))
130+
end
131+
end
132+
133+
134+
function _construct_array_vars(var_name, known, call_args, indices...)
135+
:(map(Iterators.product($(indices...))) do ind
136+
$(_construct_var(var_name, known, call_args, :ind))
137+
end)
138+
end
139+
100140

101141
"""
102142
$(SIGNATURES)

test/variable_parsing.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,25 @@ D1 = Differential(t)
3434
@test @macroexpand(@variables x, y, z(t)) == @macroexpand(@variables x y z(t))
3535

3636
convert(Expression, :($x == 0 ? $y : $x))
37+
38+
# Test array expressions
39+
@parameters begin
40+
t[1:2]
41+
s[1:2:4,1:2]
42+
end
43+
@parameters σ[1:2](..)
44+
45+
t1 = [Variable(:t, 1; known = true)(),
46+
Variable(:t, 2; known = true)()]
47+
s1 = [Variable(:s, 1, 1; known = true)() Variable(:s, 1, 2; known = true)()
48+
Variable(:s, 3, 1; known = true)() Variable(:s, 3, 2; known = true)()]
49+
σ1 = [Variable(, 1; known = true),
50+
Variable(, 2; known = true)]
51+
@test isequal(t1, t)
52+
@test isequal(s1, s)
53+
@test isequal(σ1, σ)
54+
55+
@parameters t
56+
@variables x[1:2](t)
57+
x1 = [Variable(:x, 1)(t), Variable(:x, 2)(t)]
58+
@test isequal(x1, x)

0 commit comments

Comments
 (0)