Skip to content

Commit

Permalink
Merge pull request #840 from samply/ToRatio
Browse files Browse the repository at this point in the history
Implement CQL ToRatio
  • Loading branch information
alexanderkiel authored Nov 29, 2022
2 parents 8b7e57c + 4e6824d commit cf8977d
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 44 deletions.
4 changes: 2 additions & 2 deletions docs/conformance/cql.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ The section numbers refer to the documentation of the [ELM Specification](https:
| 22.11. | ConvertsToLong || | |
| 22.12. | ConvertsToInteger || | |
| 22.13. | ConvertsToQuantity || | |
| 22.14. | ConvertsToRatio | | | |
| 22.14. | ConvertsToRatio | | | |
| 22.15. | ConvertsToString || | |
| 22.16. | ConvertsToTime || | |
| 22.17. | Descendents || | |
Expand All @@ -351,7 +351,7 @@ The section numbers refer to the documentation of the [ELM Specification](https:
| 22.26. | ToList || | |
| 22.27. | ToLong || | |
| 22.28. | ToQuantity || | |
| 22.29. | ToRatio | | | |
| 22.29. | ToRatio | | | |
| 22.30. | ToString || | |
| 22.31. | ToTime || | |

Expand Down
11 changes: 9 additions & 2 deletions modules/cql/src/blaze/elm/compiler/type_operators.clj
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@
(some? (p/to-quantity operand))))


;; TODO 22.14. ConvertsToRatio
;; 22.14. ConvertsToRatio
(defunop converts-to-ratio [operand]
(when (some? operand)
(some? (p/to-ratio operand))))


;; 22.15. ConvertsToString
(defunop converts-to-string [operand]
Expand Down Expand Up @@ -355,7 +359,10 @@
(p/to-quantity x))


;; TODO 22.29. ToRatio
;; 22.29. ToRatio
(defunop to-ratio [x]
(p/to-ratio x))


;; 22.30. ToString
(defunop to-string [x]
Expand Down
8 changes: 8 additions & 0 deletions modules/cql/src/blaze/elm/deps_infer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@
(derive :elm.deps.type/converts-to-quantity :elm.deps.type/unary-expression)


;; 22.14. ConvertsToRatio
(derive :elm.deps.type/converts-to-ratio :elm.deps.type/unary-expression)


;; 22.15. ConvertsToString
(derive :elm.deps.type/converts-to-string :elm.deps.type/unary-expression)

Expand Down Expand Up @@ -684,6 +688,10 @@
(derive :elm.deps.type/to-quantity :elm.deps.type/unary-expression)


;; 22.29. ToRatio
(derive :elm.deps.type/to-ratio :elm.deps.type/unary-expression)


;; 22.30. ToString
(derive :elm.deps.type/to-string :elm.deps.type/unary-expression)

Expand Down
6 changes: 6 additions & 0 deletions modules/cql/src/blaze/elm/nil.clj
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@
(to-quantity [_]))


;; 22.29. ToRatio
(extend-protocol p/ToRatio
nil
(to-ratio [_]))


;; 22.30. ToString
(extend-protocol p/ToString
nil
Expand Down
8 changes: 8 additions & 0 deletions modules/cql/src/blaze/elm/normalizer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,10 @@
(derive :elm.normalizer.type/converts-to-quantity :elm.normalizer.type/unary-expression)


;; 22.14. ConvertsToRatio
(derive :elm.normalizer.type/converts-to-ratio :elm.normalizer.type/unary-expression)


;; 22.15. ConvertsToString
(derive :elm.normalizer.type/converts-to-string :elm.normalizer.type/unary-expression)

Expand Down Expand Up @@ -494,6 +498,10 @@
(derive :elm.normalizer.type/to-quantity :elm.normalizer.type/unary-expression)


;; 22.29. ToRatio
(derive :elm.normalizer.type/to-ratio :elm.normalizer.type/unary-expression)


;; 22.30. ToString
(derive :elm.normalizer.type/to-string :elm.normalizer.type/unary-expression)

Expand Down
5 changes: 5 additions & 0 deletions modules/cql/src/blaze/elm/protocols.clj
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,11 @@
(to-quantity [x]))


;; 22.29. ToRatio
(defprotocol ToRatio
(to-ratio [x]))


;; 22.30. ToString
(defprotocol ToString
(to-string [x]))
Expand Down
13 changes: 12 additions & 1 deletion modules/cql/src/blaze/elm/ratio.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
Section numbers are according to
https://cql.hl7.org/04-logicalspecification.html."
(:require
[blaze.elm.protocols :as p]))
[blaze.elm.protocols :as p]
[clojure.string :as str]))


(set! *warn-on-reflection* true)
Expand Down Expand Up @@ -36,6 +37,16 @@
(p/divide (:denominator x) (:numerator x))))


;; 22.29. ToRatio
(extend-protocol p/ToRatio
String
(to-ratio [s]
(let [[numerator denominator] (str/split s #":" 2)]
(when-let [numerator (p/to-quantity numerator)]
(when-let [denominator (p/to-quantity denominator)]
(ratio numerator denominator))))))


;; 22.30. ToString
(extend-protocol p/ToString
Ratio
Expand Down
119 changes: 80 additions & 39 deletions modules/cql/test/blaze/elm/compiler/type_operators_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
[blaze.elm.protocols :as p]
[blaze.elm.quantity :as quantity]
[blaze.elm.quantity-spec]
[blaze.elm.ratio :as ratio]
[blaze.fhir.spec.type.system :as system]
[clojure.spec.test.alpha :as st]
[clojure.test :as test :refer [are deftest is testing]]))
Expand Down Expand Up @@ -744,7 +745,7 @@
(is (= '(converts-to-quantity (param-ref "x")) (core/-form expr))))))


;; TODO 22.14. ConvertsToRatio
;; 22.14. ConvertsToRatio
;;
;; The ConvertsToRatio operator returns true if the value of its argument is or
;; can be converted to a Ratio value. The operator accepts strings using the
Expand All @@ -760,6 +761,30 @@
;; a valid Ratio value, the result is false.
;;
;; If the argument is null, the result is null.
(deftest compile-converts-to-ratio-test
(testing "String"
(are [x] (true? (tu/compile-unop elm/converts-to-ratio elm/string x))
"-1'm':-1'm'"
"0'm':0'm'"
"1'm':1'm'")

(are [x] (false? (tu/compile-unop elm/converts-to-ratio elm/string x))
""
"a"
"0'm';0'm'"))

(testing "dynamic"
(are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-ratio x)))
#elm/parameter-ref "A"))

(tu/testing-unary-null elm/converts-to-ratio)

(testing "form"
(let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}}
elm #elm/converts-to-ratio #elm/parameter-ref "x"
expr (c/compile compile-ctx elm)]
(is (= '(converts-to-ratio (param-ref "x")) (core/-form expr))))))


;; 22.15. ConvertsToString
;;
Expand Down Expand Up @@ -1451,17 +1476,15 @@
;; The operator is used to implement list promotion efficiently.
(deftest compile-to-list-test
(testing "Boolean"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-list elm/boolean x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-list elm/boolean x))
"false" [false]))

(testing "Integer"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-list elm/integer x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-list elm/integer x))
"1" [1]))

(testing "Null"
(is (= [] (core/-eval (c/compile {} #elm/to-list{:type "Null"}) {} nil nil))))
(is (= [] (c/compile {} #elm/to-list{:type "Null"}))))

(testing "form"
(let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}}
Expand Down Expand Up @@ -1552,9 +1575,7 @@
;; If the argument is null, the result is null.
(deftest compile-to-quantity-test
(testing "String"
(are [x res] (p/equal res (core/-eval (tu/compile-unop elm/to-quantity
elm/string x)
{} nil nil))
(are [x res] (p/equal res (tu/compile-unop elm/to-quantity elm/string x))
"-1" (quantity/quantity -1 "1")
"1" (quantity/quantity 1 "1")

Expand All @@ -1566,8 +1587,7 @@

"1.1 'm'" (quantity/quantity 1.1M "m"))

(are [x] (nil? (core/-eval (tu/compile-unop elm/to-quantity elm/string x)
{} nil nil))
(are [x] (nil? (tu/compile-unop elm/to-quantity elm/string x))
(str (- decimal/min 1e-8M))
(str (+ decimal/max 1e-8M))
(str (- decimal/min 1e-8M) "'m'")
Expand All @@ -1576,21 +1596,16 @@
"a"))

(testing "Integer"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-quantity elm/integer x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-quantity elm/integer x))
"1" (quantity/quantity 1 "1")))

(testing "Decimal"
(are [x res] (p/equal res (core/-eval (tu/compile-unop elm/to-quantity
elm/decimal x)
{} nil nil))
(are [x res] (p/equal res (tu/compile-unop elm/to-quantity elm/decimal x))
"1" (quantity/quantity 1 "1")
"1.1" (quantity/quantity 1.1M "1")))

(testing "Ratio"
(are [x res] (p/equal res (core/-eval (tu/compile-unop elm/to-quantity
elm/ratio x)
{} nil nil))
(are [x res] (p/equal res (tu/compile-unop elm/to-quantity elm/ratio x))
[[1] [1]] (quantity/quantity 1 "1")
[[-1] [1]] (quantity/quantity -1 "1")

Expand All @@ -1610,7 +1625,7 @@
(is (= '(to-quantity (param-ref "x")) (core/-form expr))))))


;; TODO 22.29. ToRatio
;; 22.29. ToRatio
;;
;; The ToRatio operator converts the value of its argument to a Ratio value.
;; The operator accepts strings using the following format:
Expand All @@ -1625,6 +1640,43 @@
;; a valid Ratio value, the result is null.
;;
;; If the argument is null, the result is null.
(deftest compile-to-ratio-test
(testing "String"
(are [x res] (p/equal res (tu/compile-unop elm/to-ratio elm/string x))
"-1:-1" (ratio/ratio (quantity/quantity -1 "1") (quantity/quantity -1 "1"))
"1:1" (ratio/ratio (quantity/quantity 1 "1") (quantity/quantity 1 "1"))
"1:100" (ratio/ratio (quantity/quantity 1 "1") (quantity/quantity 100 "1"))
"100:1" (ratio/ratio (quantity/quantity 100 "1") (quantity/quantity 1 "1"))

"1'm':1'm'" (ratio/ratio (quantity/quantity 1 "m") (quantity/quantity 1 "m"))
"1 'm':1 'm'" (ratio/ratio (quantity/quantity 1 "m") (quantity/quantity 1 "m"))
"1 'm':1 'm'" (ratio/ratio (quantity/quantity 1 "m") (quantity/quantity 1 "m"))

"2'm':1'm'" (ratio/ratio (quantity/quantity 2 "m") (quantity/quantity 1 "m"))
"1'm':2'm'" (ratio/ratio (quantity/quantity 1 "m") (quantity/quantity 2 "m"))

"1'cm':1'm'" (ratio/ratio (quantity/quantity 1 "cm") (quantity/quantity 1 "m"))
"1'm':1'cm'" (ratio/ratio (quantity/quantity 1 "m") (quantity/quantity 1 "cm"))

"10 'm':10 'm'" (ratio/ratio (quantity/quantity 10 "m") (quantity/quantity 10 "m"))

"1.1 'm':1.1 'm'" (ratio/ratio (quantity/quantity 1.1M "m") (quantity/quantity 1.1M "m"))))

(are [x] (nil? (tu/compile-unop elm/to-ratio elm/string x))
":"
"a"
""
"1:"
":1"
"1:1:1")

(tu/testing-unary-null elm/to-ratio)

(testing "form"
(let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}}
elm #elm/to-ratio #elm/parameter-ref "x"
expr (c/compile compile-ctx elm)]
(is (= '(to-ratio (param-ref "x")) (core/-form expr))))))


;; 22.30. ToString
Expand All @@ -1644,21 +1696,18 @@
;; If the argument is null, the result is null.
(deftest compile-to-string-test
(testing "Boolean"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/boolean x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/boolean x))
"true" "true"
"false" "false"))

(testing "Integer"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/integer x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/integer x))
"-1" "-1"
"0" "0"
"1" "1"))

(testing "Decimal"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/decimal x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/decimal x))
"-1" "-1"
"0" "0"
"1" "1"
Expand All @@ -1676,35 +1725,27 @@
"0.000000005" "0.00000001"))

(testing "Quantity"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/quantity
x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/quantity x))
[1 "m"] "1 'm'"
[1M "m"] "1 'm'"
[1.1M "m"] "1.1 'm'"))

(testing "Date"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/date x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/date x))
"2019" "2019"
"2019-01" "2019-01"
"2019-01-01" "2019-01-01"))

(testing "DateTime"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/date-time
x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/date-time x))
"2019-01-01T01:00" "2019-01-01T01:00"))

(testing "Time"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/time x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/time x))
"01:00" "01:00"))

(testing "Ratio"
(are [x res] (= res (core/-eval (tu/compile-unop elm/to-string elm/ratio
x)
{} nil nil))
(are [x res] (= res (tu/compile-unop elm/to-string elm/ratio x))
[[1 "m"] [1 "m"]] "1 'm':1 'm'"
[[1 "m"] [2 "m"]] "1 'm':2 'm'"
[[1M "m"] [1M "m"]] "1 'm':1 'm'"
Expand Down
10 changes: 10 additions & 0 deletions modules/cql/test/blaze/elm/literal.clj
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,11 @@
{:type "ConvertsToQuantity" :operand operand})


;; 22.14. ConvertsToRatio
(defn converts-to-ratio [operand]
{:type "ConvertsToRatio" :operand operand})


;; 22.15. ConvertsToString
(defn converts-to-string [operand]
{:type "ConvertsToString" :operand operand})
Expand Down Expand Up @@ -936,6 +941,11 @@
{:type "ToQuantity" :operand operand})


;; 22.29. ToRatio
(defn to-ratio [operand]
{:type "ToRatio" :operand operand})


;; 22.30. ToString
(defn to-string [operand]
{:type "ToString" :operand operand})
Expand Down
Loading

0 comments on commit cf8977d

Please sign in to comment.