Skip to content

Implement ifelse in DSL for for loops #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: rethink_parser
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 37 additions & 10 deletions src/MacroModelling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2172,12 +2172,13 @@ function convert_to_ss_equation(eq::Expr)::Expr
end


function replace_indices_inside_for_loop(exxpr,index_variable,indices,concatenate, operator)
@assert operator ∈ [:+,:*] "Only :+ and :* allowed as operators in for loops."
function replace_indices_inside_for_loop(exxpr, index_variable, indices, concatenate, operator)
@assert operator ∈ [:+, :*] "Only :+ and :* allowed as operators in for loops."
calls = []
indices = indices.args[1] == :(:) ? eval(indices) : [indices.args...]
index_syms = Symbol[i for i in indices if i isa Symbol]
for idx in indices
push!(calls, postwalk(x -> begin
replaced = postwalk(x -> begin
x isa Expr ?
x.head == :ref ?
@capture(x, name_{index_}[time_]) ?
Expand Down Expand Up @@ -2205,16 +2206,42 @@ function replace_indices_inside_for_loop(exxpr,index_variable,indices,concatenat
x :
x :
@capture(x, name_) ?
name == index_variable && idx isa Int ?
:($idx) :
name == index_variable ?
idx isa Int ?
:($idx) :
QuoteNode(idx) :
x isa Symbol ?
occursin("{" * string(index_variable) * "}", string(x)) ?
Symbol(replace(string(x), "{" * string(index_variable) * "}" => "{" * string(idx) * "}")) :
Symbol(replace(string(x), "{" * string(index_variable) * "}" => "{" * string(idx) * "}")) :
x in index_syms ? QuoteNode(x) :
x :
x :
x :
x
end,
exxpr))
x
end, exxpr)

skip = false
if replaced isa Expr && replaced.head == :if
cond = replaced.args[1]
try
val = eval(cond)
if val
replaced = replaced.args[2]
elseif length(replaced.args) >= 3
replaced = replaced.args[3]
else
skip = true
end
catch
end
elseif replaced isa Expr && replaced.head == :call && replaced.args[1] == :ifelse
cond = replaced.args[2]
try
val = eval(cond)
replaced = val ? replaced.args[3] : replaced.args[4]
catch
end
end
skip || push!(calls, replaced)
end

if concatenate
Expand Down
7 changes: 7 additions & 0 deletions test/models/for_if_no_else.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@model IfNoElseLoop begin
for co in [H, F]
if co == H
x{co}[0] = 1
end
end
end
9 changes: 9 additions & 0 deletions test/models/for_if_statement.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@model IfStatementLoop begin
for co in [H, F]
if co == H
x{co}[0] = 1
else
x{co}[0] = 2
end
end
end
5 changes: 5 additions & 0 deletions test/models/for_ifelse.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@model IfElseLoop begin
for co in [H, F]
x{co}[0] = ifelse(co == H, 1, 2)
end
end
18 changes: 18 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ println("Threads used: ", Threads.nthreads())

include("functionality_tests.jl")

@testset "for loop ifelse" begin
include("models/for_ifelse.jl")
@test length(IfElseLoop.dyn_equations) == 2
@test IfElseLoop.var == [:x◖H◗, :x◖F◗]
end

@testset "for loop if" begin
include("models/for_if_statement.jl")
@test length(IfStatementLoop.dyn_equations) == 2
@test IfStatementLoop.var == [:x◖H◗, :x◖F◗]
end

@testset "for loop if no else" begin
include("models/for_if_no_else.jl")
@test length(IfNoElseLoop.dyn_equations) == 1
@test IfNoElseLoop.var == [:x◖H◗]
end

# @testset verbose = true "Code formatting (JuliaFormatter.jl)" begin
# @test format(MacroModelling; verbose=true, overwrite=true)
# end
Expand Down
Loading