mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
language: Check rational precision for rational literals. (#514)
* language: Check rational precision for rational literals. A value like 0.00000000005 was truncated to 0.000000000. This change will throw an error instead and abort the compilation. It also checks for maximal/minimal bounds.
This commit is contained in:
parent
f1b077dd1a
commit
9f0b74176f
@ -101,12 +101,12 @@ import Data.List.Extra
|
||||
import qualified Data.Map.Strict as MS
|
||||
import Data.Maybe
|
||||
import qualified Data.NameMap as NM
|
||||
import Data.Ratio
|
||||
import qualified Data.Set as Set
|
||||
import Data.Tagged
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import Data.Tuple.Extra
|
||||
import Data.Ratio
|
||||
import "ghc-lib" GHC
|
||||
import "ghc-lib" GhcPlugins as GHC hiding ((<>))
|
||||
import "ghc-lib-parser" Pair
|
||||
@ -240,6 +240,27 @@ convertInt64 x
|
||||
| otherwise =
|
||||
unsupported "Int literal out of bounds" (negate x)
|
||||
|
||||
convertRational :: Integer -> Integer -> ConvertM LF.Expr
|
||||
convertRational num denom
|
||||
=
|
||||
-- the denominator needs to be a divisor of 10^10.
|
||||
-- num % denom * 10^10 needs to fit within a 128bit signed number.
|
||||
-- note that we can also get negative rationals here, hence we ask for upperBound128Bit - 1 as
|
||||
-- upper limit.
|
||||
if | 10 ^ maxPrecision `mod` denom == 0 &&
|
||||
abs (r * 10 ^ maxPrecision) <= upperBound128Bit - 1 ->
|
||||
pure $ EBuiltin $ BEDecimal $ fromRational r
|
||||
| otherwise ->
|
||||
unsupported
|
||||
("Rational is out of bounds: " ++
|
||||
show ((fromInteger num / fromInteger denom) :: Double) ++
|
||||
". Maximal supported precision is e^-10, maximal range after multiplying with 10^10 is [10^38 -1, -10^38 + 1]")
|
||||
(num, denom)
|
||||
where
|
||||
r = num % denom
|
||||
upperBound128Bit = 10 ^ (38 :: Integer)
|
||||
maxPrecision = 10 :: Integer
|
||||
|
||||
convertModule :: LF.Version -> MS.Map UnitId T.Text -> GhcModule -> Either Diagnostic LF.Module
|
||||
convertModule lfVersion pkgMap mod0 = runConvertM (ConversionEnv (gmPath mod0) Nothing) $ do
|
||||
definitions <- concat <$> traverse (convertBind env) (cm_binds x)
|
||||
@ -588,7 +609,7 @@ convertExpr env0 e = do
|
||||
ETmLam (varV1, field') $ ETmLam (varV2, record') $
|
||||
ERecUpd (fromTCon record') (mkField $ unpackFS name) (EVar varV2) (EVar varV1)
|
||||
go env (VarIs "fromRational") (LExpr (VarIs ":%" `App` tyInteger `App` Lit (LitNumber _ top _) `App` Lit (LitNumber _ bot _)) : args)
|
||||
= fmap (, args) $ pure $ EBuiltin $ BEDecimal $ fromRational $ top % bot
|
||||
= fmap (, args) $ convertRational top bot
|
||||
go env (VarIs "negate") (tyInt : LExpr (VarIs "$fAdditiveInt") : LExpr (untick -> VarIs "fromInteger" `App` Lit (LitNumber _ x _)) : args)
|
||||
= fmap (, args) $ convertInt64 (negate x)
|
||||
go env (VarIs "fromInteger") (LExpr (Lit (LitNumber _ x _)) : args)
|
||||
|
12
daml-foundations/daml-ghc/tests/RationalLowerBoundError.daml
Normal file
12
daml-foundations/daml-ghc/tests/RationalLowerBoundError.daml
Normal file
@ -0,0 +1,12 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that rational negative literals bigger or equal -10^38 + 1 fail.
|
||||
-- @ERROR Rational is out of bounds
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalLowerBoundError where
|
||||
|
||||
-- -10^38 / 10^10
|
||||
a = -10000000000000000000000000000.0000000000
|
11
daml-foundations/daml-ghc/tests/RationalLowerBoundMax.daml
Normal file
11
daml-foundations/daml-ghc/tests/RationalLowerBoundMax.daml
Normal file
@ -0,0 +1,11 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that rational negative literals bigger or equal -10^38 + 1 pass.
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalLowerBoundMax where
|
||||
|
||||
-- -10^38 + 1 / 10^10
|
||||
a = -9999999999999999999999999999.9999999999
|
10
daml-foundations/daml-ghc/tests/RationalPrecisionMax.daml
Normal file
10
daml-foundations/daml-ghc/tests/RationalPrecisionMax.daml
Normal file
@ -0,0 +1,10 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that the maximal precision of e^-10 in rational literals passes.
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalPrecisionUpperBound where
|
||||
|
||||
a = 0.0000000005
|
@ -0,0 +1,11 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that rational literals with precision higher then e^-10 fail.
|
||||
-- @ERROR Rational is out of bounds
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalPrecisionUpperBoundError where
|
||||
|
||||
a = 0.00000000005
|
12
daml-foundations/daml-ghc/tests/RationalUpperBoundError.daml
Normal file
12
daml-foundations/daml-ghc/tests/RationalUpperBoundError.daml
Normal file
@ -0,0 +1,12 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that rational positive literals fail when bigger than 10^38 -1 after multiplying with 10^10.
|
||||
-- @ERROR Rational is out of bounds
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalUpperBound where
|
||||
|
||||
-- 10^38 / 10^10
|
||||
a = 10000000000000000000000000000.0000000000
|
11
daml-foundations/daml-ghc/tests/RationalUpperBoundMax.daml
Normal file
11
daml-foundations/daml-ghc/tests/RationalUpperBoundMax.daml
Normal file
@ -0,0 +1,11 @@
|
||||
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
|
||||
-- All rights reserved.
|
||||
|
||||
-- Test that rational positive literals smaller or equal 10^38 -1 after multiplying with 10^10 pass.
|
||||
|
||||
daml 1.2
|
||||
|
||||
module RationalUpperBoundMax where
|
||||
|
||||
-- 10^38 -1 / 10^10
|
||||
a = 9999999999999999999999999999.9999999999
|
Loading…
Reference in New Issue
Block a user