Skip to content

Commit 963634b

Browse files
Merge pull request #900 from pepijndevos/varscope
Implement variable scope
2 parents c3561ea + 611d03c commit 963634b

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

src/ModelingToolkit.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export Differential, expand_derivatives, @derivatives
158158
export IntervalDomain, ProductDomain, , CircleDomain
159159
export Equation, ConstrainedEquation
160160
export Term, Sym
161+
export SymScope, LocalScope, ParentScope, GlobalScope
161162
export independent_variable, states, parameters, equations, controls, observed, structure
162163
export structural_simplify
163164

src/systems/abstractsystem.jl

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,22 +226,22 @@ function Base.getproperty(sys::AbstractSystem, name::Symbol; namespace=true)
226226
i = findfirst(x->getname(x) == name, sts)
227227

228228
if i !== nothing
229-
return namespace ? rename(sts[i],renamespace(sysname,name)) : sts[i]
229+
return namespace ? renamespace(sysname,sts[i]) : sts[i]
230230
end
231231

232232
if has_ps(sys)
233233
ps = get_ps(sys)
234234
i = findfirst(x->getname(x) == name,ps)
235235
if i !== nothing
236-
return namespace ? rename(ps[i],renamespace(sysname,name)) : ps[i]
236+
return namespace ? renamespace(sysname,ps[i]) : ps[i]
237237
end
238238
end
239239

240240
if has_observed(sys)
241241
obs = get_observed(sys)
242242
i = findfirst(x->getname(x.lhs)==name,obs)
243243
if i !== nothing
244-
return namespace ? rename(obs[i].lhs,renamespace(sysname,name)) : obs[i]
244+
return namespace ? renamespace(sysname,obs[i]) : obs[i]
245245
end
246246
end
247247

@@ -268,11 +268,32 @@ function Base.setproperty!(sys::AbstractSystem, prop::Symbol, val)
268268
end
269269
end
270270

271+
abstract type SymScope end
272+
273+
struct LocalScope <: SymScope end
274+
LocalScope(sym::Union{Num, Sym}) = setmetadata(sym, SymScope, LocalScope())
275+
276+
struct ParentScope <: SymScope
277+
parent::SymScope
278+
end
279+
ParentScope(sym::Union{Num, Sym}) = setmetadata(sym, SymScope, ParentScope(getmetadata(value(sym), SymScope, LocalScope())))
280+
281+
struct GlobalScope <: SymScope end
282+
GlobalScope(sym::Union{Num, Sym}) = setmetadata(sym, SymScope, GlobalScope())
283+
271284
function renamespace(namespace, x)
272285
if x isa Num
273286
renamespace(namespace, value(x))
274287
elseif x isa Symbolic
275-
rename(x, renamespace(namespace, getname(x)))
288+
let scope = getmetadata(x, SymScope, LocalScope())
289+
if scope isa LocalScope
290+
rename(x, renamespace(namespace, getname(x)))
291+
elseif scope isa ParentScope
292+
setmetadata(x, SymScope, scope.parent)
293+
else # GlobalScope
294+
x
295+
end
296+
end
276297
else
277298
Symbol(namespace,:₊,x)
278299
end
@@ -300,7 +321,7 @@ function namespace_equation(eq::Equation,name,iv)
300321
end
301322

302323
function namespace_expr(O::Sym,name,iv)
303-
isequal(O, iv) ? O : rename(O,renamespace(name,nameof(O)))
324+
isequal(O, iv) ? O : renamespace(name,O)
304325
end
305326

306327
_symparam(s::Symbolic{T}) where {T} = T
@@ -309,7 +330,7 @@ function namespace_expr(O,name,iv) where {T}
309330
if istree(O)
310331
renamed = map(a->namespace_expr(a,name,iv), arguments(O))
311332
if operation(O) isa Sym
312-
renamed_op = rename(O,renamespace(name, getname(O)))
333+
rename(O,getname(renamespace(name, O)))
313334
else
314335
similarterm(O,operation(O),renamed)
315336
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using SafeTestsets, Test
22

3+
@safetestset "Varialbe scope tests" begin include("variable_scope.jl") end
34
@safetestset "Symbolic parameters test" begin include("symbolic_parameters.jl") end
45
@safetestset "Parsing Test" begin include("variable_parsing.jl") end
56
@safetestset "Simplify Test" begin include("simplify.jl") end

test/variable_scope.jl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using ModelingToolkit
2+
using Test
3+
4+
@parameters t
5+
@variables a b(t) c d
6+
7+
b = ParentScope(b)
8+
c = ParentScope(ParentScope(c))
9+
d = GlobalScope(d)
10+
11+
renamed(nss, sym) = ModelingToolkit.getname(foldr(ModelingToolkit.renamespace, nss, init=sym))
12+
13+
@test renamed([:foo :bar :baz], a) == :foo₊bar₊baz₊a
14+
@test renamed([:foo :bar :baz], b) == :foo₊bar₊b
15+
@test renamed([:foo :bar :baz], c) == :foo₊c
16+
@test renamed([:foo :bar :baz], d) == :d
17+
18+
eqs = [
19+
0 ~ a
20+
0 ~ b
21+
0 ~ c
22+
0 ~ d
23+
]
24+
@named sub4 = NonlinearSystem(eqs, [a, b, c, d], [])
25+
@named sub3 = NonlinearSystem(eqs, [a, b, c, d], [])
26+
@named sub2 = NonlinearSystem([], [], [], systems=[sub3, sub4])
27+
@named sub1 = NonlinearSystem([], [], [], systems=[sub2])
28+
@named sys = NonlinearSystem([], [], [], systems=[sub1])
29+
30+
names = ModelingToolkit.getname.(states(sys))
31+
@test :d in names
32+
@test :sub1₊c in names
33+
@test :sub1₊sub2₊b in names
34+
@test :sub1₊sub2₊sub3₊a in names
35+
@test :sub1₊sub2₊sub4₊a in names

0 commit comments

Comments
 (0)