Skip to content

Commit

Permalink
Optimize CQL Logical Expressions
Browse files Browse the repository at this point in the history
Closes: #1944
  • Loading branch information
alexanderkiel committed Jul 30, 2024
1 parent b5ae6c9 commit 92124b7
Show file tree
Hide file tree
Showing 16 changed files with 763 additions and 120 deletions.
1 change: 1 addition & 0 deletions cljfmt.edn
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
do-sync [[:block 1]]
do-async [[:block 1]]
has-form [[:block 1]]
testing-optimize [[:block 1]]
reg-collector [[:block 1]]
deftests [[:block 1]]
satisfies-prop [[:block 1]]
Expand Down
46 changes: 41 additions & 5 deletions modules/cql/src/blaze/elm/compiler/logical_operators.clj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
(-resolve-params [_ parameters]
(core/resolve-params-helper and-nil-op parameters x))
(-optimize [_ node]
(core/optimize-helper and-nil-op node x))
(let [x (core/-optimize x node)]
(condp identical? x
true nil
false false
nil nil
(and-nil-op x))))
(-eval [_ context resource scope]
(when (false? (core/-eval x context resource scope))
false))
Expand Down Expand Up @@ -68,6 +73,8 @@
b-count (or (core/-patient-count b-op) Long/MAX_VALUE)]
(- a-count b-count)))

(declare dynamic-and)

(defn and-op [a b]
(reify-expr core/Expression
(-attach-cache [_ cache]
Expand Down Expand Up @@ -105,7 +112,12 @@
(-resolve-params [_ parameters]
(core/resolve-params-helper and-op parameters a b))
(-optimize [_ node]
(core/optimize-helper and-op node a b))
(let [a (core/-optimize a node)]
(condp identical? a
true (core/-optimize b node)
false false
nil (nil-and (core/-optimize b node))
(dynamic-and a (core/-optimize b node)))))
(-eval [_ context resource scope]
(let [a (core/-eval a context resource scope)]
(if (false? a)
Expand Down Expand Up @@ -160,7 +172,12 @@
(-resolve-params [_ parameters]
(core/resolve-params-helper or-nil-op parameters x))
(-optimize [_ node]
(core/optimize-helper or-nil-op node x))
(let [x (core/-optimize x node)]
(condp identical? x
true true
false nil
nil nil
(or-nil-op x))))
(-eval [_ context resource scope]
(when (true? (core/-eval x context resource scope))
true))
Expand Down Expand Up @@ -212,6 +229,8 @@
b-count (or (core/-patient-count b-op) Long/MAX_VALUE)]
(- b-count a-count)))

(declare dynamic-or)

(defn or-op [a b]
(reify-expr core/Expression
(-attach-cache [_ cache]
Expand Down Expand Up @@ -249,7 +268,12 @@
(-resolve-params [_ parameters]
(core/resolve-params-helper or-op parameters a b))
(-optimize [_ node]
(core/optimize-helper or-op node a b))
(let [a (core/-optimize a node)]
(condp identical? a
true true
false (core/-optimize b node)
nil (nil-or (core/-optimize b node))
(dynamic-or a (core/-optimize b node)))))
(-eval [_ context resource scope]
(let [a (core/-eval a context resource scope)]
(if (true? a)
Expand Down Expand Up @@ -281,6 +305,8 @@
(dynamic-or a (core/compile* context b)))))

;; 13.5 Xor
(declare dynamic-xor)

(defn- xor-op [a b]
(reify-expr core/Expression
(-attach-cache [_ cache]
Expand All @@ -290,7 +316,17 @@
(-resolve-params [_ parameters]
(core/resolve-params-helper xor-op parameters a b))
(-optimize [_ node]
(core/optimize-helper xor-op node a b))
(let [a (core/-optimize a node)]
(condp identical? a
true (let [b (core/-optimize b node)]
(condp identical? b
true false
false true
nil nil
(not-op b)))
false (core/-optimize b node)
nil nil
(dynamic-xor a (core/-optimize b node)))))
(-eval [_ context resource scope]
(when-some [a (core/-eval a context resource scope)]
(when-some [b (core/-eval b context resource scope)]
Expand Down
10 changes: 6 additions & 4 deletions modules/cql/src/blaze/elm/compiler/macros.clj
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,15 @@
~elm-expr)
`(~op
(core/-resolve-params ~operand ~'parameters))))
(~'-optimize [~'_ ~'node]
(~'-optimize [~'_ ~node]
~(if elm-expr-binding
`(~op
(core/-optimize ~operand ~'node)
(core/-optimize ~operand ~node)
~elm-expr)
`(~op
(core/-optimize ~operand ~'node))))
`(let [~operand (core/-optimize ~operand ~node)]
(if (core/static? ~operand)
(let [~operand-binding ~operand] ~@body)
(~op ~operand)))))
(~'-eval [~'_ ~context ~resource ~scope]
(let ~(generate-binding-vector
operand-binding `(core/-eval ~operand ~context ~resource ~scope)
Expand Down
109 changes: 100 additions & 9 deletions modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,17 @@

(ctu/testing-unary-null elm/abs)

(ctu/testing-unary-op elm/abs))
(ctu/testing-unary-op elm/abs)

(ctu/testing-optimize elm/abs
(testing "0"
#ctu/optimize-to 0
0)

(testing "-1, 1"
#ctu/optimize-to -1
#ctu/optimize-to 1
1)))

;; 16.2. Add
;;
Expand Down Expand Up @@ -377,7 +387,16 @@

(ctu/testing-unary-null elm/ceiling)

(ctu/testing-unary-op elm/ceiling))
(ctu/testing-unary-op elm/ceiling)

(ctu/testing-optimize elm/ceiling
(testing "1"
#ctu/optimize-to 1
1)

(testing "1.1"
#ctu/optimize-to 1.1M
2)))

;; 16.4. Divide
;;
Expand Down Expand Up @@ -476,11 +495,21 @@
(deftest compile-exp-test
(are [x res] (= res (c/compile {} (elm/exp x)))
#elm/integer "0" 1M
#elm/integer "1" 2.71828183M
#elm/decimal "0" 1M)

(ctu/testing-unary-null elm/exp)

(ctu/testing-unary-op elm/exp))
(ctu/testing-unary-op elm/exp)

(ctu/testing-optimize elm/exp
(testing "0"
#ctu/optimize-to 0
1M)

(testing "1"
#ctu/optimize-to 1
2.71828183M)))

;; 16.6. Floor
;;
Expand All @@ -495,7 +524,16 @@

(ctu/testing-unary-null elm/floor)

(ctu/testing-unary-op elm/floor))
(ctu/testing-unary-op elm/floor)

(ctu/testing-optimize elm/floor
(testing "1"
#ctu/optimize-to 1
1)

(testing "1.1"
#ctu/optimize-to 1.1M
1)))

;; 16.7. HighBoundary
;;
Expand Down Expand Up @@ -579,7 +617,16 @@

(ctu/testing-unary-null elm/ln)

(ctu/testing-unary-op elm/ln))
(ctu/testing-unary-op elm/ln)

(ctu/testing-optimize elm/ln
(testing "1"
#ctu/optimize-to 1
0M)

(testing "2"
#ctu/optimize-to 2
0.69314718M)))

;; 16.11. MaxValue
;;
Expand Down Expand Up @@ -774,7 +821,16 @@

(ctu/testing-unary-null elm/negate)

(ctu/testing-unary-op elm/negate))
(ctu/testing-unary-op elm/negate)

(ctu/testing-optimize elm/negate
(testing "1"
#ctu/optimize-to 1
-1)

(testing "1M"
#ctu/optimize-to 1M
-1M)))

;; 16.16. Power
;;
Expand Down Expand Up @@ -889,7 +945,20 @@

(ctu/testing-unary-null elm/predecessor)

(ctu/testing-unary-op elm/predecessor))
(ctu/testing-unary-op elm/predecessor)

(ctu/testing-optimize elm/predecessor
(testing "Integer 0"
#ctu/optimize-to 0
-1)

(testing "Decimal 0"
#ctu/optimize-to 0M
-1E-8M)

(testing "Date 2019"
#ctu/optimize-to (system/date 2019)
(system/date 2018))))

;; 16.19. Round
;;
Expand Down Expand Up @@ -1227,7 +1296,20 @@

(ctu/testing-unary-null elm/successor)

(ctu/testing-unary-op elm/successor))
(ctu/testing-unary-op elm/successor)

(ctu/testing-optimize elm/successor
(testing "Integer 0"
#ctu/optimize-to 0
1)

(testing "Decimal 0"
#ctu/optimize-to 0M
1E-8M)

(testing "Date 2019"
#ctu/optimize-to (system/date 2019)
(system/date 2020))))

;; 16.22. Truncate
;;
Expand All @@ -1242,7 +1324,16 @@

(ctu/testing-unary-null elm/truncate)

(ctu/testing-unary-op elm/truncate))
(ctu/testing-unary-op elm/truncate)

(ctu/testing-optimize elm/truncate
(testing "Integer 1"
#ctu/optimize-to 1
1)

(testing "Decimal 1.1"
#ctu/optimize-to 1.1M
1)))

;; 16.23. TruncatedDivide
;;
Expand Down
20 changes: 10 additions & 10 deletions modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -223,19 +223,19 @@
(testing "multi-conditional"
(let [elm {:type "Case"
:caseItem
[{:when {:type "Optimizeable" :id "w"}
:then {:type "Optimizeable" :id "t"}}]
:else {:type "Optimizeable" :id "e"}}
[{:when #ctu/optimizeable "w"
:then #ctu/optimizeable "t"}]
:else #ctu/optimizeable "e"}
expr (st/with-instrument-disabled (c/optimize nil (c/compile {} elm)))]
(has-form expr '(case (optimized "w") (optimized "t") (optimized "e")))))

(testing "comparand-based"
(let [elm {:type "Case"
:comparand {:type "Optimizeable" :id "c"}
:comparand #ctu/optimizeable "c"
:caseItem
[{:when {:type "Optimizeable" :id "w"}
:then {:type "Optimizeable" :id "t"}}]
:else {:type "Optimizeable" :id "e"}}
[{:when #ctu/optimizeable "w"
:then #ctu/optimizeable "t"}]
:else #ctu/optimizeable "e"}
expr (st/with-instrument-disabled (c/optimize nil (c/compile {} elm)))]
(has-form expr '(case (optimized "c") (optimized "w") (optimized "t") (optimized "e"))))))

Expand Down Expand Up @@ -333,9 +333,9 @@
(has-form expr '(if "c" "t" "e"))))

(testing "optimize"
(let [elm #elm/if [{:type "Optimizeable" :id "c"}
{:type "Optimizeable" :id "t"}
{:type "Optimizeable" :id "e"}]
(let [elm #elm/if [#ctu/optimizeable "c"
#ctu/optimizeable "t"
#ctu/optimizeable "e"]
expr (st/with-instrument-disabled (c/optimize nil (c/compile {} elm)))]
(has-form expr '(if (optimized "c") (optimized "t") (optimized "e")))))

Expand Down
11 changes: 10 additions & 1 deletion modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,16 @@

(ctu/testing-unary-null elm/date-from)

(ctu/testing-unary-op elm/date-from))
(ctu/testing-unary-op elm/date-from)

(ctu/testing-optimize elm/date-from
(testing "2019"
#ctu/optimize-to (system/date 2019)
(system/date 2019))

(testing "2019-04-17T12:48"
#ctu/optimize-to (system/date-time 2019 4 17 12 48)
(system/date 2019 4 17))))

;; 18.8. DateTime
;;
Expand Down
Loading

0 comments on commit 92124b7

Please sign in to comment.