@@ -50,9 +50,11 @@ import Dhall.Syntax
5050 )
5151
5252import Data.Foldable (toList )
53+ import Data.Ratio ((%) )
5354import Data.Void (Void , absurd )
5455import GHC.Float (double2Float , float2Double )
5556import Numeric.Half (fromHalf , toHalf )
57+ import Prelude hiding (exponent )
5658
5759import qualified Codec.CBOR.ByteArray
5860import qualified Codec.CBOR.Decoding as Decoding
@@ -66,6 +68,7 @@ import qualified Data.ByteString.Short
6668import qualified Data.Foldable as Foldable
6769import qualified Data.List.NonEmpty as NonEmpty
6870import qualified Data.Sequence
71+ import qualified Data.Time as Time
6972import qualified Dhall.Crypto
7073import qualified Dhall.Map
7174import qualified Dhall.Syntax as Syntax
@@ -133,16 +136,19 @@ decodeExpressionInternal decodeEmbed = go
133136
134137 case Data.ByteString.Short. length sb of
135138 4 | sb == " Bool" -> return Bool
139+ | sb == " Date" -> return Date
136140 | sb == " List" -> return List
137141 | sb == " None" -> return None
138142 | sb == " Text" -> return Text
143+ | sb == " Time" -> return Time
139144 | sb == " Type" -> return (Const Type )
140145 | sb == " Kind" -> return (Const Kind )
141146 | sb == " Sort" -> return (Const Sort )
142147 6 | sb == " Double" -> return Double
143148 7 | sb == " Integer" -> return Integer
144149 | sb == " Natural" -> return Natural
145150 8 | sb == " Optional" -> return Optional
151+ | sb == " TimeZone" -> return TimeZone
146152 9 | sb == " List/fold" -> return ListFold
147153 | sb == " List/head" -> return ListHead
148154 | sb == " List/last" -> return ListLast
@@ -566,6 +572,73 @@ decodeExpressionInternal decodeEmbed = go
566572
567573 return (With l ks₁ r)
568574
575+ 30 -> do
576+ _YYYY <- Decoding. decodeInt
577+ _MM <- Decoding. decodeInt
578+ _HH <- Decoding. decodeInt
579+
580+ case Time. fromGregorianValid (fromIntegral _YYYY) _MM _HH of
581+ Nothing ->
582+ die " Invalid date"
583+ Just day ->
584+ return (DateLiteral day)
585+ 31 -> do
586+ hh <- Decoding. decodeInt
587+ mm <- Decoding. decodeInt
588+ tag₂ <- Decoding. decodeTag
589+
590+ case tag₂ of
591+ 4 -> do
592+ return ()
593+ _ -> do
594+ die (" Unexpected tag for decimal fraction: " <> show tag)
595+ n <- Decoding. decodeListLen
596+
597+ case n of
598+ 2 -> do
599+ return ()
600+ _ -> do
601+ die (" Invalid list length for decimal fraction: " <> show n)
602+
603+ exponent <- Decoding. decodeInt
604+
605+ tokenType₂ <- Decoding. peekTokenType
606+
607+ mantissa <- case tokenType₂ of
608+ TypeUInt -> do
609+ fromIntegral <$> Decoding. decodeWord
610+
611+ TypeUInt64 -> do
612+ fromIntegral <$> Decoding. decodeWord64
613+
614+ TypeNInt -> do
615+ ! i <- fromIntegral <$> Decoding. decodeNegWord
616+
617+ return (- 1 - i)
618+
619+ TypeNInt64 -> do
620+ ! i <- fromIntegral <$> Decoding. decodeNegWord64
621+
622+ return (- 1 - i)
623+ TypeInteger -> do
624+ Decoding. decodeInteger
625+ _ ->
626+ die (" Unexpected token type for mantissa: " <> show tokenType₂)
627+ let precision = fromIntegral (negate exponent )
628+
629+ let ss = fromRational (mantissa % (10 ^ precision))
630+
631+ return (TimeLiteral (Time. TimeOfDay hh mm ss) precision)
632+ 32 -> do
633+ b <- Decoding. decodeBool
634+ _HH <- Decoding. decodeInt
635+ _MM <- Decoding. decodeInt
636+
637+ let sign = if b then id else negate
638+
639+ let minutes = sign (_HH * 60 + _MM)
640+
641+ return (TimeZoneLiteral (Time. TimeZone minutes False " " ))
569642 _ ->
570643 die (" Unexpected tag: " <> show tag)
571644
@@ -674,6 +747,15 @@ encodeExpressionInternal encodeEmbed = go
674747 TextShow ->
675748 Encoding. encodeUtf8ByteArray " Text/show"
676749
750+ Date ->
751+ Encoding. encodeUtf8ByteArray " Date"
752+
753+ Time ->
754+ Encoding. encodeUtf8ByteArray " Time"
755+
756+ TimeZone ->
757+ Encoding. encodeUtf8ByteArray " TimeZone"
758+
677759 List ->
678760 Encoding. encodeUtf8ByteArray " List"
679761
@@ -936,6 +1018,49 @@ encodeExpressionInternal encodeEmbed = go
9361018 (encodeList (fmap Encoding. encodeString ks))
9371019 (go r)
9381020
1021+ DateLiteral day ->
1022+ encodeList4
1023+ (Encoding. encodeInt 30 )
1024+ (Encoding. encodeInt (fromInteger _YYYY))
1025+ (Encoding. encodeInt _MM)
1026+ (Encoding. encodeInt _DD)
1027+ where
1028+ (_YYYY, _MM, _DD) = Time. toGregorian day
1029+
1030+ TimeLiteral (Time. TimeOfDay hh mm ss) precision ->
1031+ encodeList4
1032+ (Encoding. encodeInt 31 )
1033+ (Encoding. encodeInt hh)
1034+ (Encoding. encodeInt mm)
1035+ ( Encoding. encodeTag 4
1036+ <> encodeList2
1037+ (Encoding. encodeInt exponent )
1038+ encodedMantissa
1039+ )
1040+ where
1041+ exponent = negate (fromIntegral precision)
1042+
1043+ mantissa :: Integer
1044+ mantissa = truncate (ss * 10 ^ precision)
1045+
1046+ encodedMantissa
1047+ | fromIntegral (minBound :: Int ) <= mantissa
1048+ && mantissa <= fromIntegral (maxBound :: Int ) =
1049+ Encoding. encodeInt (fromInteger mantissa)
1050+ | otherwise =
1051+ Encoding. encodeInteger mantissa
1052+
1053+ TimeZoneLiteral (Time. TimeZone minutes _ _) ->
1054+ encodeList4
1055+ (Encoding. encodeInt 32 )
1056+ (Encoding. encodeBool sign)
1057+ (Encoding. encodeInt _HH)
1058+ (Encoding. encodeInt _MM)
1059+ where
1060+ sign = 0 <= minutes
1061+
1062+ (_HH, _MM) = abs minutes `divMod` 60
1063+
9391064 Note _ b ->
9401065 go b
9411066
0 commit comments