Skip to content

Commit 8b75e01

Browse files
committed
feat: support ternary operators inside the @equations
- and ternary conditional statements at the top level of the block - adds relevant tests
1 parent 597bd0a commit 8b75e01

File tree

2 files changed

+141
-67
lines changed

2 files changed

+141
-67
lines changed

src/systems/model_parsing.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,14 @@ function handle_y_vars(y, dict, mod, varclass, kwargs)
559559
end
560560

561561
function handle_if_x_equations!(condition, dict, ifexpr, x)
562-
push!(ifexpr.args, condition, :(push!(equations, $(x.args...))))
563-
# push!(dict[:equations], [:if, readable_code(condition), readable_code.(x.args)])
564-
readable_code.(x.args)
562+
if Meta.isexpr(x, :block)
563+
push!(ifexpr.args, condition, :(push!(equations, $(x.args...))))
564+
return readable_code.(x.args)
565+
else
566+
push!(ifexpr.args, condition, :(push!(equations, $x)))
567+
return readable_code(x)
568+
end
569+
# push!(dict[:equations], [:if, readable_code(condition), readable_code.(x.args)])
565570
end
566571

567572
function handle_if_y_equations!(ifexpr, y, dict)
@@ -574,8 +579,12 @@ function handle_if_y_equations!(ifexpr, y, dict)
574579
push!(ifexpr.args, elseifexpr)
575580
(eq_entry...,)
576581
else
577-
push!(ifexpr.args, :(push!(equations, $(y.args...))))
578-
readable_code.(y.args)
582+
if Meta.isexpr(y, :block)
583+
push!(ifexpr.args, :(push!(equations, $(y.args...))))
584+
else
585+
push!(ifexpr.args, :(push!(equations, $(y))))
586+
end
587+
readable_code.(y.args)
579588
end
580589
end
581590

test/model_parsing.jl

Lines changed: 127 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using ModelingToolkit, Test
2-
using ModelingToolkit: get_gui_metadata,
3-
get_ps, getdefault, getname, scalarize,
4-
VariableDescription, RegularConnector
2+
using ModelingToolkit: get_gui_metadata, get_systems, get_connector_type,
3+
get_ps, getdefault, getname, scalarize, VariableDescription, RegularConnector
54
using URIs: URI
65
using Distributions
76
using Unitful
@@ -303,7 +302,7 @@ end
303302
end
304303

305304
@named aa = A()
306-
@test aa.connector_type == RegularConnector()
305+
@test get_connector_type(aa) == RegularConnector()
307306

308307
@test A.isconnector == true
309308

@@ -314,7 +313,7 @@ end
314313
@test A.structure[:components] == [[:cc, :C]]
315314
end
316315

317-
@testset "Conditional components, equations and parameters" begin
316+
@testset "Conditional statements inside the blocks" begin
318317
@mtkmodel C begin end
319318

320319
# Conditional statements inside @components, @equations
@@ -326,21 +325,21 @@ end
326325
@parameters begin
327326
eq = flag == 1 ? 1 : 0
328327
if flag == 1
329-
a1
328+
if_parameter
330329
elseif flag == 2
331-
a2
330+
elseif_parameter
332331
else
333-
a3
332+
else_parameter
334333
end
335334
end
336335
@components begin
337-
sys0 = C()
336+
default_sys = C()
338337
if flag == 1
339-
sys1 = C()
338+
if_sys = C()
340339
elseif flag == 2
341-
sys2 = C()
340+
elseif_sys = C()
342341
else
343-
sys3 = C()
342+
else_sys = C()
344343
end
345344
end
346345
@equations begin
@@ -352,94 +351,160 @@ end
352351
else
353352
eq ~ 3
354353
end
354+
flag == 1 ? eq ~ 4 : eq ~ 5
355355
end
356356
end
357357

358-
@named in_sys_1 = InsideTheBlock()
359-
in_sys_1 = complete(in_sys_1)
360-
@named in_sys_2 = InsideTheBlock(flag = 2)
361-
in_sys_2 = complete(in_sys_2)
362-
@named in_sys_3 = InsideTheBlock(flag = 3)
363-
in_sys_3 = complete(in_sys_3)
364-
365-
@test nameof.(parameters(in_sys_1)) == [:a1, :eq]
366-
@test nameof.(parameters(in_sys_2)) == [:a2, :eq]
367-
@test nameof.(parameters(in_sys_3)) == [:a3, :eq]
368-
369-
@test nameof.(in_sys_1.systems) == [:sys1, :sys0]
370-
@test nameof.(in_sys_2.systems) == [:sys2, :sys0]
371-
@test nameof.(in_sys_3.systems) == [:sys3, :sys0]
372-
373-
@test all([in_sys_1.eq ~ 0, in_sys_1.eq ~ 1] .∈ [equations(in_sys_1)])
374-
@test all([in_sys_2.eq ~ 0, in_sys_2.eq ~ 2] .∈ [equations(in_sys_2)])
375-
@test all([in_sys_3.eq ~ 0, in_sys_3.eq ~ 3] .∈ [equations(in_sys_3)])
358+
@named if_in_sys = InsideTheBlock()
359+
if_in_sys = complete(if_in_sys)
360+
@named elseif_in_sys = InsideTheBlock(flag = 2)
361+
elseif_in_sys = complete(elseif_in_sys)
362+
@named else_in_sys = InsideTheBlock(flag = 3)
363+
else_in_sys = complete(else_in_sys)
364+
365+
@test nameof.(parameters(if_in_sys)) == [:if_parameter, :eq]
366+
@test nameof.(parameters(elseif_in_sys)) == [:elseif_parameter, :eq]
367+
@test nameof.(parameters(else_in_sys)) == [:else_parameter, :eq]
368+
369+
@test nameof.(get_systems(if_in_sys)) == [:if_sys, :default_sys]
370+
@test nameof.(get_systems(elseif_in_sys)) == [:elseif_sys, :default_sys]
371+
@test nameof.(get_systems(else_in_sys)) == [:else_sys, :default_sys]
372+
373+
@test all([
374+
if_in_sys.eq ~ 0,
375+
if_in_sys.eq ~ 1,
376+
if_in_sys.eq ~ 4,
377+
] .∈ [equations(if_in_sys)])
378+
@test all([
379+
elseif_in_sys.eq ~ 0,
380+
elseif_in_sys.eq ~ 2,
381+
elseif_in_sys.eq ~ 5,
382+
] .∈ [equations(elseif_in_sys)])
383+
@test all([
384+
else_in_sys.eq ~ 0,
385+
else_in_sys.eq ~ 3,
386+
else_in_sys.eq ~ 5,
387+
] .∈ [equations(else_in_sys)])
388+
389+
@test getdefault(if_in_sys.eq) == 1
390+
@test getdefault(elseif_in_sys.eq) == 0
391+
end
376392

377-
@test getdefault(in_sys_1.eq) == 1
378-
@test getdefault(in_sys_2.eq) == 0
393+
@testset "Conditional statements outside the blocks" begin
394+
@mtkmodel C begin end
379395

380396
# Branching statement outside the begin blocks
381397
@mtkmodel OutsideTheBlock begin
382398
@structural_parameters begin
383-
condition = 2
399+
condition = 0
384400
end
401+
385402
@parameters begin
386-
a0
403+
default_parameter
387404
end
388405
@components begin
389-
sys0 = C()
406+
default_sys = C()
390407
end
391408
@equations begin
392-
a0 ~ 0
409+
default_parameter ~ 0
393410
end
394411

395412
if condition == 1
396413
@parameters begin
397-
a1
414+
if_parameter
398415
end
399416
@equations begin
400-
a1 ~ 0
417+
if_parameter ~ 0
401418
end
402419
@components begin
403-
sys1 = C()
420+
if_sys = C()
404421
end
405422
elseif condition == 2
406423
@parameters begin
407-
a2
424+
elseif_parameter
408425
end
409426
@equations begin
410-
a2 ~ 0
427+
elseif_parameter ~ 0
411428
end
412429
@components begin
413-
sys2 = C()
430+
elseif_sys = C()
414431
end
415432
else
416433
@parameters begin
417-
a3
434+
else_parameter
418435
end
419436
@equations begin
420-
a3 ~ 0
437+
else_parameter ~ 0
421438
end
422439
@components begin
423-
sys3 = C()
440+
else_sys = C()
424441
end
425442
end
426443
end
427444

428-
@named out_sys_1 = OutsideTheBlock(condition = 1)
429-
out_sys_1 = complete(out_sys_1)
430-
@named out_sys_2 = OutsideTheBlock(condition = 2)
431-
out_sys_2 = complete(out_sys_2)
432-
@named out_sys_3 = OutsideTheBlock(condition = 10)
433-
out_sys_3 = complete(out_sys_3)
434-
435-
@test nameof.(out_sys_1.systems) == [:sys1, :sys0]
436-
@test nameof.(out_sys_2.systems) == [:sys2, :sys0]
437-
@test nameof.(out_sys_3.systems) == [:sys3, :sys0]
438-
439-
@test Equation[out_sys_1.a1 ~ 0
440-
out_sys_1.a0 ~ 0] == equations(out_sys_1)
441-
@test Equation[out_sys_2.a2 ~ 0
442-
out_sys_1.a0 ~ 0] == equations(out_sys_2)
443-
@test Equation[out_sys_3.a3 ~ 0
444-
out_sys_1.a0 ~ 0] == equations(out_sys_3)
445+
@named if_out_sys = OutsideTheBlock(condition = 1)
446+
if_out_sys = complete(if_out_sys)
447+
@named elseif_out_sys = OutsideTheBlock(condition = 2)
448+
elseif_out_sys = complete(elseif_out_sys)
449+
@named else_out_sys = OutsideTheBlock(condition = 10)
450+
else_out_sys = complete(else_out_sys)
451+
@named ternary_out_sys = OutsideTheBlock(condition = 4)
452+
else_out_sys = complete(else_out_sys)
453+
454+
@test nameof.(parameters(if_out_sys)) == [:if_parameter, :default_parameter]
455+
@test nameof.(parameters(elseif_out_sys)) == [:elseif_parameter, :default_parameter]
456+
@test nameof.(parameters(else_out_sys)) == [:else_parameter, :default_parameter]
457+
458+
@test nameof.(get_systems(if_out_sys)) == [:if_sys, :default_sys]
459+
@test nameof.(get_systems(elseif_out_sys)) == [:elseif_sys, :default_sys]
460+
@test nameof.(get_systems(else_out_sys)) == [:else_sys, :default_sys]
461+
462+
@test Equation[if_out_sys.if_parameter ~ 0
463+
if_out_sys.default_parameter ~ 0] == equations(if_out_sys)
464+
@test Equation[elseif_out_sys.elseif_parameter ~ 0
465+
elseif_out_sys.default_parameter ~ 0] == equations(elseif_out_sys)
466+
@test Equation[else_out_sys.else_parameter ~ 0
467+
else_out_sys.default_parameter ~ 0] == equations(else_out_sys)
468+
469+
@mtkmodel TernaryBranchingOutsideTheBlock begin
470+
@structural_parameters begin
471+
condition = true
472+
end
473+
condition ? begin
474+
@parameters begin
475+
ternary_parameter_true
476+
end
477+
@equations begin
478+
ternary_parameter_true ~ 0
479+
end
480+
@components begin
481+
ternary_sys_true = C()
482+
end
483+
end : begin
484+
@parameters begin
485+
ternary_parameter_false
486+
end
487+
@equations begin
488+
ternary_parameter_false ~ 0
489+
end
490+
@components begin
491+
ternary_sys_false = C()
492+
end
493+
end
494+
end
495+
496+
@named ternary_true = TernaryBranchingOutsideTheBlock()
497+
ternary_true = complete(ternary_true)
498+
499+
@named ternary_false = TernaryBranchingOutsideTheBlock(condition = false)
500+
ternary_false = complete(ternary_false)
501+
502+
@test nameof.(parameters(ternary_true)) == [:ternary_parameter_true]
503+
@test nameof.(parameters(ternary_false)) == [:ternary_parameter_false]
504+
505+
@test nameof.(get_systems(ternary_true)) == [:ternary_sys_true]
506+
@test nameof.(get_systems(ternary_false)) == [:ternary_sys_false]
507+
508+
@test Equation[ternary_true.ternary_parameter_true ~ 0] == equations(ternary_true)
509+
@test Equation[ternary_false.ternary_parameter_false ~ 0] == equations(ternary_false)
445510
end

0 commit comments

Comments
 (0)