Skip to content
Draft
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
3 changes: 2 additions & 1 deletion src/CTParser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ using Unicode

# sources
include("utils.jl")
include("reorder.jl")
include("onepass.jl")

end
end
55 changes: 50 additions & 5 deletions src/onepass.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1034,20 +1034,62 @@ end true # final boolean to show parsing log
"""
macro def(e)
try
code = def_fun(e)
code = def_fun(e; order = false)
return esc(code)
catch ex
:(throw($ex)) # can be caught by user
#try # I am not sure if this try is needed
code = def_fun(e; order = true)
e_ordered = QuoteNode(reorder(e))
code = quote
try
$code
catch ex_code_reorder
printstyled("\n▫ Parsing failed for original and reordered codes, throwing exception:\n", color = :red, bold = true)
printstyled("\n▫ Exception from original code:", color = :cyan, bold = true)
println(" " * string($ex))
printstyled("\n▫ Exception from reordered code:", color = :cyan, bold = true)
println(" " * string(ex_code_reorder))
printstyled("\n▫ Reordered code:", color = :cyan, bold = true)
println(" " * string($e_ordered))
println("")
rethrow(ex_code_reorder)
end
end
return esc(code)
# catch ex_code_reorder
# println("▫ Reordering failed, throwing exception:\n")
# println("Exception from reordered code: \n", ex_code_reorder)
# println("Exception from original code: \n", ex)
# :(throw($ex)) # can be caught by user
# end
end
end

macro def(ocp, e, log=false) # old syntax with ocp name in arguments for compatibility
try
code = def_fun(e; log = log)
code = def_fun(e; log = log, order = false)
code = :($ocp = $code)
return esc(code)
catch ex
:(throw($ex)) # can be caught by user
code = def_fun(e; log = log, order = true)
e_ordered = QuoteNode(reorder(e))
code = quote
try
$code
catch ex_code_reorder
printstyled("\n▫ Parsing failed for original and reordered codes, throwing exception:\n", color = :red, bold = true)
printstyled("\n▫ Exception from original code:", color = :cyan, bold = true)
println(" " * string($ex))
printstyled("\n▫ Exception from reordered code:", color = :cyan, bold = true)
println(" " * string(ex_code_reorder))
printstyled("\n▫ Reordered code:", color = :cyan, bold = true)
println(" " * string($e_ordered))
println("")
rethrow(ex_code_reorder)
end
end
code = :($ocp = $code)
return esc(code)
end
end

Expand All @@ -1066,11 +1108,14 @@ $(TYPEDSIGNATURES)

Core computation of `@def` macro, parsing an expression towards a CTModels.Model.
"""
function def_fun(e; log = false)
function def_fun(e; log = false, order::Bool = false)
pref = prefix()
p_ocp = __symgen(:p_ocp)
p = ParsingInfo()
ee = QuoteNode(e)
if order
e = reorder(e) # to reorder the expr before parsing
end
code = parse!(p, p_ocp, e; log = log, backend = :fun)
code = quote
$p_ocp = $pref.PreModel()
Expand Down
50 changes: 50 additions & 0 deletions src/reorder.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
function store!(data, e)
# assume data is a dict with keys:
# variable, declaration, misc, objective
# for each key, you have a vector of Expr already initialised
@match e begin
:(PRAGMA($a)) => push!(data[:misc], e)
:($a = $b) => push!(data[:declaration], e)
:($a, variable) => push!(data[:variable], e)
:($a, time) => push!(data[:declaration], e)
:($a, state) => push!(data[:declaration], e)
:($a, control) => push!(data[:declaration], e)
:($a → max) => push!(data[:objective], e)
:($a → min) => push!(data[:objective], e)
_ => begin
if e isa LineNumberNode
nothing
elseif e isa Expr && e.head == :block
map(e -> store!(data, e), e.args)
else
push!(data[:misc], e)
end
end
end
return nothing
end

function reorder(data::Dict)
# assume data is a dict with keys:
# variable, declaration, misc, objective
# for each key, you have a vector of Expr already initialised
code = Expr(:block)
keys = [:variable, :declaration, :misc, :objective]
for key ∈ keys
for e ∈ data[key]
code = code==Expr(:block) ? e : concat(code, e)
end
end
return code
end

function reorder(e::Expr)
data = Dict(
:variable => Vector{Expr}(),
:declaration => Vector{Expr}(),
:misc => Vector{Expr}(),
:objective => Vector{Expr}(),
)
store!(data, e)
return reorder(data)
end
29 changes: 29 additions & 0 deletions test/test_onepass_fun.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3157,4 +3157,33 @@ function test_onepass_fun()

end

test_name = "wrong order"
@testset "$test_name" begin println(test_name)

# Parameters
t0 = 0 # initial time
r0 = 1 # initial altitude
v0 = 0 # initial speed
m0 = 1 # initial mass
vmax = 0.1 # maximal authorized speed
mf = 0.6 # final mass to target

o = @def begin
u ∈ R, control
x(t0) == [r0, v0, m0]
r(tf) → max
x = (r, v, m) ∈ R³, state
t ∈ [t0, tf], time
m(tf) == mf, (1)
0 ≤ u(t) ≤ 1
r(t) ≥ r0
0 ≤ v(t) ≤ vmax
ẋ(t) == F0(x(t)) + u(t) * F1(x(t))
PRAGMA(1+1)
tf ∈ R, variable
end
@test o isa CTModels.Model

end

end
Loading
Loading