From 558f748816b50884c8dd9fe321979d60c8362272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kukie=C5=82a?= <53443372+kukimik@users.noreply.github.com> Date: Tue, 13 May 2025 19:57:51 +0000 Subject: [PATCH] Add Date and Time component extraction builtins --- dhall-bash/src/Dhall/Bash.hs | 6 ++ dhall-json/src/Dhall/JSON.hs | 18 ++++++ dhall-nix/src/Dhall/Nix.hs | 30 ++++++++- dhall/src/Dhall/Binary.hs | 24 +++++++ dhall/src/Dhall/Diff.hs | 36 +++++++++++ dhall/src/Dhall/Eval.hs | 96 ++++++++++++++++++++++++++++ dhall/src/Dhall/Normalize.hs | 24 +++++++ dhall/src/Dhall/Parser/Expression.hs | 6 ++ dhall/src/Dhall/Parser/Token.hs | 48 ++++++++++++++ dhall/src/Dhall/Pretty/Internal.hs | 12 ++++ dhall/src/Dhall/Syntax/Expr.hs | 12 ++++ dhall/src/Dhall/Syntax/Operations.hs | 12 ++++ dhall/src/Dhall/TypeCheck.hs | 18 ++++++ dhall/tests/Dhall/Test/QuickCheck.hs | 6 ++ 14 files changed, 347 insertions(+), 1 deletion(-) diff --git a/dhall-bash/src/Dhall/Bash.hs b/dhall-bash/src/Dhall/Bash.hs index 756c5532d..c3238974f 100644 --- a/dhall-bash/src/Dhall/Bash.hs +++ b/dhall-bash/src/Dhall/Bash.hs @@ -320,9 +320,15 @@ dhallToStatement expr0 var0 = go (Dhall.Core.normalize expr0) go e@(Date ) = Left (UnsupportedStatement e) go e@(DateLiteral {}) = Left (UnsupportedStatement e) go e@(DateShow ) = Left (UnsupportedStatement e) + go e@(DateYear ) = Left (UnsupportedStatement e) + go e@(DateMonth ) = Left (UnsupportedStatement e) + go e@(DateDay ) = Left (UnsupportedStatement e) go e@(Time ) = Left (UnsupportedStatement e) go e@(TimeLiteral {}) = Left (UnsupportedStatement e) go e@(TimeShow ) = Left (UnsupportedStatement e) + go e@(TimeHour ) = Left (UnsupportedStatement e) + go e@(TimeMinute ) = Left (UnsupportedStatement e) + go e@(TimeSecond ) = Left (UnsupportedStatement e) go e@(TimeZone ) = Left (UnsupportedStatement e) go e@(TimeZoneLiteral {}) = Left (UnsupportedStatement e) go e@(TimeZoneShow ) = Left (UnsupportedStatement e) diff --git a/dhall-json/src/Dhall/JSON.hs b/dhall-json/src/Dhall/JSON.hs index 563326fc9..a49d99b09 100644 --- a/dhall-json/src/Dhall/JSON.hs +++ b/dhall-json/src/Dhall/JSON.hs @@ -900,6 +900,15 @@ convertToHomogeneousMaps (Conversion {..}) e0 = loop (Core.normalize e0) Core.DateShow -> Core.DateShow + Core.DateYear -> + Core.DateYear + + Core.DateMonth -> + Core.DateMonth + + Core.DateDay -> + Core.DateDay + Core.Time -> Core.Time @@ -909,6 +918,15 @@ convertToHomogeneousMaps (Conversion {..}) e0 = loop (Core.normalize e0) Core.TimeShow -> Core.TimeShow + Core.TimeHour -> + Core.TimeHour + + Core.TimeMinute -> + Core.TimeMinute + + Core.TimeSecond -> + Core.TimeSecond + Core.TimeZone -> Core.TimeZone diff --git a/dhall-nix/src/Dhall/Nix.hs b/dhall-nix/src/Dhall/Nix.hs index 2ca4af69a..265101806 100644 --- a/dhall-nix/src/Dhall/Nix.hs +++ b/dhall-nix/src/Dhall/Nix.hs @@ -105,6 +105,7 @@ import Data.Void (Void, absurd) import Lens.Micro (toListOf, rewriteOf) import Numeric (showHex) import Data.Char (ord, isDigit, isAsciiLower, isAsciiUpper) +import Data.String (fromString) import Dhall.Core ( Binding (..) @@ -336,6 +337,19 @@ dhallToNix e = rewriteShadowed = rewriteOf Dhall.Core.subExpressions renameShadowed + -- Template of a Nix function that extracts a substring using regex + -- and parses the result as an integer + regexSubstrToInt argName regex = + (fromString argName) + ==> ( "builtins.fromJSON" + @@ ( "builtins.head" + @@ ( "builtins.match" + @@ (Nix.mkStr regex) + @@ (fromString argName) + ) + ) + ) + loop (Const _) = return untranslatable loop (Var (V a 0)) = return (Nix.mkSym (zEncodeSymbol a)) loop (Var a ) = Left (CannotReferenceShadowedVariable a) @@ -607,13 +621,27 @@ dhallToNix e = loop TimeLiteral{} = undefined loop TimeZoneLiteral{} = undefined -- We currently model `Date`/`Time`/`TimeZone` literals as strings in Nix, - -- so the corresponding show functions are the identity function + -- so the corresponding show functions are the identity function, and the + -- functions extracting the year/month/day and hour/minute/second components + -- find the corresponding substring and parse it as an integer. loop DateShow = return ("date" ==> "date") loop TimeShow = return ("time" ==> "time") loop TimeZoneShow = return ("timeZone" ==> "timeZone") + loop DateYear = + return (regexSubstrToInt "date" "0*([0-9]+)-[0-9]{2}-[0-9]{2}") + loop DateMonth = + return (regexSubstrToInt "date" "[0-9]{4}-0?([0-9]+)-[0-9]{2}") + loop DateDay = + return (regexSubstrToInt "date" "[0-9]{4}-[0-9]{2}-0?([0-9]+)") + loop TimeHour = + return (regexSubstrToInt "time" "0?([0-9]+):[0-9]{2}:[0-9]{2}.*") + loop TimeMinute = + return (regexSubstrToInt "time" "[0-9]{2}:0?([0-9]+):[0-9]{2}.*") + loop TimeSecond = + return (regexSubstrToInt "time" "[0-9]{2}:[0-9]{2}:0?([0-9]+).*") loop (Record _) = return untranslatable loop (RecordLit a) = do a' <- traverse (loop . Dhall.Core.recordFieldValue) a diff --git a/dhall/src/Dhall/Binary.hs b/dhall/src/Dhall/Binary.hs index ebe05cddc..a9795aac7 100644 --- a/dhall/src/Dhall/Binary.hs +++ b/dhall/src/Dhall/Binary.hs @@ -150,16 +150,22 @@ decodeExpressionInternal decodeEmbed = go | sb == "Natural" -> return Natural 8 | sb == "Optional" -> return Optional | sb == "TimeZone" -> return TimeZone + | sb == "Date/day" -> return DateDay 9 | sb == "Date/show" -> return DateShow | sb == "List/fold" -> return ListFold | sb == "List/head" -> return ListHead | sb == "List/last" -> return ListLast | sb == "Text/show" -> return TextShow | sb == "Time/show" -> return TimeShow + | sb == "Date/year" -> return DateYear + | sb == "Time/hour" -> return TimeHour 10 | sb == "List/build" -> return ListBuild + | sb == "Date/month" -> return DateMonth 11 | sb == "Double/show" -> return DoubleShow | sb == "List/length" -> return ListLength | sb == "Natural/odd" -> return NaturalOdd + | sb == "Time/minute" -> return TimeMinute + | sb == "Time/second" -> return TimeSecond 12 | sb == "Integer/show" -> return IntegerShow | sb == "List/indexed" -> return ListIndexed | sb == "List/reverse" -> return ListReverse @@ -780,12 +786,30 @@ encodeExpressionInternal encodeEmbed = go DateShow -> Encoding.encodeUtf8ByteArray "Date/show" + DateYear -> + Encoding.encodeUtf8ByteArray "Date/year" + + DateMonth -> + Encoding.encodeUtf8ByteArray "Date/month" + + DateDay -> + Encoding.encodeUtf8ByteArray "Date/day" + Time -> Encoding.encodeUtf8ByteArray "Time" TimeShow -> Encoding.encodeUtf8ByteArray "Time/show" + TimeHour -> + Encoding.encodeUtf8ByteArray "Time/hour" + + TimeMinute -> + Encoding.encodeUtf8ByteArray "Time/minute" + + TimeSecond -> + Encoding.encodeUtf8ByteArray "Time/second" + TimeZone -> Encoding.encodeUtf8ByteArray "TimeZone" diff --git a/dhall/src/Dhall/Diff.hs b/dhall/src/Dhall/Diff.hs index 46f332b78..035b5fbb6 100644 --- a/dhall/src/Dhall/Diff.hs +++ b/dhall/src/Dhall/Diff.hs @@ -1316,6 +1316,24 @@ diffPrimitiveExpression l r@DateShow = mismatch l r diffPrimitiveExpression l@DateShow r= mismatch l r +diffPrimitiveExpression DateYear DateYear = + "…" +diffPrimitiveExpression l r@DateYear = + mismatch l r +diffPrimitiveExpression l@DateYear r= + mismatch l r +diffPrimitiveExpression DateMonth DateMonth = + "…" +diffPrimitiveExpression l r@DateMonth = + mismatch l r +diffPrimitiveExpression l@DateMonth r= + mismatch l r +diffPrimitiveExpression DateDay DateDay = + "…" +diffPrimitiveExpression l r@DateDay = + mismatch l r +diffPrimitiveExpression l@DateDay r= + mismatch l r diffPrimitiveExpression Time Time = "…" diffPrimitiveExpression l r@Time = @@ -1328,6 +1346,24 @@ diffPrimitiveExpression l r@TimeShow = mismatch l r diffPrimitiveExpression l@TimeShow r= mismatch l r +diffPrimitiveExpression TimeHour TimeHour = + "…" +diffPrimitiveExpression l r@TimeHour = + mismatch l r +diffPrimitiveExpression l@TimeHour r= + mismatch l r +diffPrimitiveExpression TimeMinute TimeMinute = + "…" +diffPrimitiveExpression l r@TimeMinute = + mismatch l r +diffPrimitiveExpression l@TimeMinute r= + mismatch l r +diffPrimitiveExpression TimeSecond TimeSecond = + "…" +diffPrimitiveExpression l r@TimeSecond = + mismatch l r +diffPrimitiveExpression l@TimeSecond r= + mismatch l r diffPrimitiveExpression TimeZone TimeZone = "…" diffPrimitiveExpression l r@TimeZone = diff --git a/dhall/src/Dhall/Eval.hs b/dhall/src/Dhall/Eval.hs index 73ba65b7a..cbc3c5ded 100644 --- a/dhall/src/Dhall/Eval.hs +++ b/dhall/src/Dhall/Eval.hs @@ -49,6 +49,12 @@ module Dhall.Eval ( , dateShow , timeShow , timezoneShow + , getYear + , getMonth + , getDay + , getHour + , getMinute + , getSecond ) where import Data.Bifunctor (first) @@ -211,9 +217,15 @@ data Val a | VDate | VDateLiteral Time.Day | VDateShow !(Val a) + | VDateYear !(Val a) + | VDateMonth !(Val a) + | VDateDay !(Val a) | VTime | VTimeLiteral Time.TimeOfDay Word | VTimeShow !(Val a) + | VTimeHour !(Val a) + | VTimeMinute !(Val a) + | VTimeSecond !(Val a) | VTimeZone | VTimeZoneLiteral Time.TimeZone | VTimeZoneShow !(Val a) @@ -681,6 +693,18 @@ eval !env t0 = VPrim $ \case VDateLiteral d -> VTextLit (VChunks [] (dateShow d)) t -> VDateShow t + DateYear -> + VPrim $ \case + VDateLiteral d -> VNaturalLit (getYear d) + t -> VDateYear t + DateMonth -> + VPrim $ \case + VDateLiteral d -> VNaturalLit (getMonth d) + t -> VDateMonth t + DateDay -> + VPrim $ \case + VDateLiteral d -> VNaturalLit (getDay d) + t -> VDateDay t Time -> VTime TimeLiteral t p -> @@ -689,6 +713,18 @@ eval !env t0 = VPrim $ \case VTimeLiteral d p -> VTextLit (VChunks [] (timeShow d p)) t -> VTimeShow t + TimeHour -> + VPrim $ \case + VTimeLiteral d _ -> VNaturalLit (getHour d) + t -> VTimeHour t + TimeMinute -> + VPrim $ \case + VTimeLiteral d _ -> VNaturalLit (getMinute d) + t -> VTimeMinute t + TimeSecond -> + VPrim $ \case + VTimeLiteral d _ -> VNaturalLit (getSecond d) + t -> VTimeSecond t TimeZone -> VTimeZone TimeZoneLiteral z -> @@ -946,6 +982,30 @@ timeShow (TimeOfDay hh mm seconds) precision = timezoneShow :: TimeZone -> Text timezoneShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%Ez" +-- | Utility that powers the @Date/year@ built-in +getYear :: Day -> Natural +getYear = fromIntegral . (\(y,_,_) -> y) . Time.toGregorian + +-- | Utility that powers the @Date/month@ built-in +getMonth :: Day -> Natural +getMonth = fromIntegral . (\(_,m,_) -> m) . Time.toGregorian + +-- | Utility that powers the @Date/day@ built-in +getDay :: Day -> Natural +getDay = fromIntegral . (\(_,_,d) -> d) . Time.toGregorian + +-- | Utility that powers the @Time/hour@ built-in +getHour :: TimeOfDay -> Natural +getHour (TimeOfDay h _ _) = fromIntegral h + +-- | Utility that powers the @Time/minute@ built-in +getMinute :: TimeOfDay -> Natural +getMinute (TimeOfDay _ m _) = fromIntegral m + +-- | Utility that powers the @Time/second@ built-in +getSecond :: TimeOfDay -> Natural +getSecond (TimeOfDay _ _ picoseconds) = floor picoseconds + conv :: forall a. Eq a => Environment a -> Val a -> Val a -> Bool conv !env t0 t0' = case (t0, t0') of @@ -1055,12 +1115,24 @@ conv !env t0 t0' = l == r (VDateShow t, VDateShow t') -> conv env t t' + (VDateYear t, VDateYear t') -> + conv env t t' + (VDateMonth t, VDateMonth t') -> + conv env t t' + (VDateDay t, VDateDay t') -> + conv env t t' (VTime, VTime) -> True (VTimeLiteral tl pl, VTimeLiteral tr pr) -> tl == tr && pl == pr (VTimeShow t, VTimeShow t') -> conv env t t' + (VTimeHour t, VTimeHour t') -> + conv env t t' + (VTimeMinute t, VTimeMinute t') -> + conv env t t' + (VTimeSecond t, VTimeSecond t') -> + conv env t t' (VTimeZone, VTimeZone) -> True (VTimeZoneLiteral l, VTimeZoneLiteral r) -> @@ -1277,12 +1349,24 @@ quote !env !t0 = DateLiteral d VDateShow t -> DateShow `qApp` t + VDateYear t -> + DateYear `qApp` t + VDateMonth t -> + DateMonth `qApp` t + VDateDay t -> + DateDay `qApp` t VTime -> Time VTimeLiteral t p -> TimeLiteral t p VTimeShow t -> TimeShow `qApp` t + VTimeHour t -> + TimeHour `qApp` t + VTimeMinute t -> + TimeMinute `qApp` t + VTimeSecond t -> + TimeSecond `qApp` t VTimeZone -> TimeZone VTimeZoneLiteral z -> @@ -1486,12 +1570,24 @@ alphaNormalize = goEnv EmptyNames DateLiteral d DateShow -> DateShow + DateYear -> + DateYear + DateMonth -> + DateMonth + DateDay -> + DateDay Time -> Time TimeLiteral t p -> TimeLiteral t p TimeShow -> TimeShow + TimeHour -> + TimeHour + TimeMinute -> + TimeMinute + TimeSecond -> + TimeSecond TimeZone -> TimeZone TimeZoneLiteral z -> diff --git a/dhall/src/Dhall/Normalize.hs b/dhall/src/Dhall/Normalize.hs index c51377dfd..8c301b692 100644 --- a/dhall/src/Dhall/Normalize.hs +++ b/dhall/src/Dhall/Normalize.hs @@ -387,10 +387,16 @@ normalizeWithM ctx e0 = loop (Syntax.denote e0) loop (TextLit (Chunks [] text)) where text = Eval.dateShow date + App DateYear (DateLiteral date) -> pure (NaturalLit (Eval.getYear date)) + App DateMonth (DateLiteral date) -> pure (NaturalLit (Eval.getMonth date)) + App DateDay (DateLiteral date) -> pure (NaturalLit (Eval.getDay date)) App TimeShow (TimeLiteral time precision) -> loop (TextLit (Chunks [] text)) where text = Eval.timeShow time precision + App TimeHour (TimeLiteral time _) -> pure (NaturalLit (Eval.getHour time)) + App TimeMinute (TimeLiteral time _) -> pure (NaturalLit (Eval.getMinute time)) + App TimeSecond (TimeLiteral time _) -> pure (NaturalLit (Eval.getSecond time)) App TimeZoneShow (TimeZoneLiteral timezone) -> loop (TextLit (Chunks [] text)) where @@ -504,9 +510,15 @@ normalizeWithM ctx e0 = loop (Syntax.denote e0) Date -> pure Date DateLiteral d -> pure (DateLiteral d) DateShow -> pure DateShow + DateYear -> pure DateYear + DateMonth -> pure DateMonth + DateDay -> pure DateDay Time -> pure Time TimeLiteral t p -> pure (TimeLiteral t p) TimeShow -> pure TimeShow + TimeHour -> pure TimeHour + TimeMinute -> pure TimeMinute + TimeSecond -> pure TimeSecond TimeZone -> pure TimeZone TimeZoneLiteral z -> pure (TimeZoneLiteral z) TimeZoneShow -> pure TimeZoneShow @@ -807,7 +819,13 @@ isNormalized e0 = loop (Syntax.denote e0) App NaturalOdd (NaturalLit _) -> False App NaturalShow (NaturalLit _) -> False App DateShow (DateLiteral _) -> False + App DateYear (DateLiteral _) -> False + App DateMonth (DateLiteral _) -> False + App DateDay (DateLiteral _) -> False App TimeShow (TimeLiteral _ _) -> False + App TimeHour (TimeLiteral _ _) -> False + App TimeMinute (TimeLiteral _ _) -> False + App TimeSecond (TimeLiteral _ _) -> False App TimeZoneShow (TimeZoneLiteral _) -> False App (App NaturalSubtract (NaturalLit _)) (NaturalLit _) -> False App (App NaturalSubtract (NaturalLit 0)) _ -> False @@ -911,9 +929,15 @@ isNormalized e0 = loop (Syntax.denote e0) Date -> True DateLiteral _ -> True DateShow -> True + DateYear -> True + DateMonth -> True + DateDay -> True Time -> True TimeLiteral _ _ -> True TimeShow -> True + TimeHour -> True + TimeMinute -> True + TimeSecond -> True TimeZone -> True TimeZoneLiteral _ -> True TimeZoneShow -> True diff --git a/dhall/src/Dhall/Parser/Expression.hs b/dhall/src/Dhall/Parser/Expression.hs index 0f75be90a..1954bcb19 100644 --- a/dhall/src/Dhall/Parser/Expression.hs +++ b/dhall/src/Dhall/Parser/Expression.hs @@ -724,6 +724,9 @@ parsers embedded = Parsers{..} 'D' -> choice [ DateShow <$ _DateShow + , DateYear <$ _DateYear + , DateMonth <$ _DateMonth + , DateDay <$ _DateDay , Date <$ _Date , DoubleShow <$ _DoubleShow , Double <$ _Double @@ -754,6 +757,9 @@ parsers embedded = Parsers{..} , TimeZoneShow <$ _TimeZoneShow , TimeZone <$ _TimeZone , TimeShow <$ _TimeShow + , TimeHour <$ _TimeHour + , TimeMinute <$ _TimeMinute + , TimeSecond <$ _TimeSecond , Time <$ _Time , BoolLit True <$ _True , Const Type <$ _Type diff --git a/dhall/src/Dhall/Parser/Token.hs b/dhall/src/Dhall/Parser/Token.hs index e17dff164..a2fc7b828 100644 --- a/dhall/src/Dhall/Parser/Token.hs +++ b/dhall/src/Dhall/Parser/Token.hs @@ -81,8 +81,14 @@ module Dhall.Parser.Token ( _TextShow, _Date, _DateShow, + _DateYear, + _DateMonth, + _DateDay, _Time, _TimeShow, + _TimeHour, + _TimeMinute, + _TimeSecond, _TimeZone, _TimeZoneShow, _List, @@ -1209,6 +1215,27 @@ _Date = builtin "Date" _DateShow :: Parser () _DateShow = builtin "Date/show" +{-| Parse the @Date/year@ built-in + + This corresponds to the @Date-year@ rule from the official grammar +-} +_DateYear :: Parser () +_DateYear = builtin "Date/year" + +{-| Parse the @Date/month@ built-in + + This corresponds to the @Date-month@ rule from the official grammar +-} +_DateMonth :: Parser () +_DateMonth = builtin "Date/month" + +{-| Parse the @Date/day@ built-in + + This corresponds to the @Date-day@ rule from the official grammar +-} +_DateDay :: Parser () +_DateDay = builtin "Date/day" + {-| Parse the @Time@ bult-in This corresponds to the @Time@ rule from the official grammar @@ -1223,6 +1250,27 @@ _Time = builtin "Time" _TimeShow :: Parser () _TimeShow = builtin "Time/show" +{-| Parse the @Time/hour@ built-in + + This corresponds to the @Time-hour@ rule from the official grammar +-} +_TimeHour :: Parser () +_TimeHour = builtin "Time/hour" + +{-| Parse the @Time/minute@ built-in + + This corresponds to the @Time-minute@ rule from the official grammar +-} +_TimeMinute :: Parser () +_TimeMinute = builtin "Time/minute" + +{-| Parse the @Time/second@ built-in + + This corresponds to the @Time-second@ rule from the official grammar +-} +_TimeSecond :: Parser () +_TimeSecond = builtin "Time/second" + {-| Parse the @TimeZone@ bult-in This corresponds to the @TimeZone@ rule from the official grammar diff --git a/dhall/src/Dhall/Pretty/Internal.hs b/dhall/src/Dhall/Pretty/Internal.hs index fdd545d3c..14dfc8546 100644 --- a/dhall/src/Dhall/Pretty/Internal.hs +++ b/dhall/src/Dhall/Pretty/Internal.hs @@ -1370,6 +1370,12 @@ prettyPrinters characterSet = (_HHHH, _MM, _DD) = Time.toGregorian day prettyPrimitiveExpression DateShow = builtin "Date/show" + prettyPrimitiveExpression DateYear = + builtin "Date/year" + prettyPrimitiveExpression DateMonth = + builtin "Date/month" + prettyPrimitiveExpression DateDay = + builtin "Date/day" prettyPrimitiveExpression Time = builtin "Time" prettyPrimitiveExpression (TimeLiteral (Time.TimeOfDay hh mm seconds) precision) = @@ -1392,6 +1398,12 @@ prettyPrinters characterSet = | otherwise = "." <> Pretty.pretty (Printf.printf "%0*d" precision fraction :: String) prettyPrimitiveExpression TimeShow = builtin "Time/show" + prettyPrimitiveExpression TimeHour = + builtin "Time/hour" + prettyPrimitiveExpression TimeMinute = + builtin "Time/minute" + prettyPrimitiveExpression TimeSecond = + builtin "Time/second" prettyPrimitiveExpression TimeZone = builtin "TimeZone" prettyPrimitiveExpression (TimeZoneLiteral (Time.TimeZone minutes _ _)) = diff --git a/dhall/src/Dhall/Syntax/Expr.hs b/dhall/src/Dhall/Syntax/Expr.hs index 660e1ba05..1e92840cc 100644 --- a/dhall/src/Dhall/Syntax/Expr.hs +++ b/dhall/src/Dhall/Syntax/Expr.hs @@ -152,6 +152,12 @@ data Expr s a | DateLiteral Time.Day -- | > DateShow ~ Date/show | DateShow + -- | > DateYear ~ Date/year + | DateYear + -- | > DateMonth ~ Date/month + | DateMonth + -- | > DateDay ~ Date/day + | DateDay -- | > Time ~ Time | Time -- | > TimeLiteral (TimeOfDay hh mm ss) _ ~ hh:mm:ss @@ -161,6 +167,12 @@ data Expr s a -- ^ Precision -- | > TimeShow ~ Time/show | TimeShow + -- | > TimeHour ~ Time/hour + | TimeHour + -- | > TimeMinute ~ Time/minute + | TimeMinute + -- | > TimeSecond ~ Time/second + | TimeSecond -- | > TimeZone ~ TimeZone | TimeZone -- | > TimeZoneLiteral (TimeZone ( 60 * _HH + _MM) _ _) ~ +HH:MM diff --git a/dhall/src/Dhall/Syntax/Operations.hs b/dhall/src/Dhall/Syntax/Operations.hs index d59a1eb41..ee1e8e338 100644 --- a/dhall/src/Dhall/Syntax/Operations.hs +++ b/dhall/src/Dhall/Syntax/Operations.hs @@ -114,9 +114,15 @@ unsafeSubExpressions _ TextShow = pure TextShow unsafeSubExpressions _ Date = pure Date unsafeSubExpressions _ (DateLiteral a) = pure (DateLiteral a) unsafeSubExpressions _ DateShow = pure DateShow +unsafeSubExpressions _ DateYear = pure DateYear +unsafeSubExpressions _ DateMonth = pure DateMonth +unsafeSubExpressions _ DateDay = pure DateDay unsafeSubExpressions _ Time = pure Time unsafeSubExpressions _ (TimeLiteral a b) = pure (TimeLiteral a b) unsafeSubExpressions _ TimeShow = pure TimeShow +unsafeSubExpressions _ TimeHour = pure TimeHour +unsafeSubExpressions _ TimeMinute = pure TimeMinute +unsafeSubExpressions _ TimeSecond = pure TimeSecond unsafeSubExpressions _ TimeZone = pure TimeZone unsafeSubExpressions _ (TimeZoneLiteral a) = pure (TimeZoneLiteral a) unsafeSubExpressions _ TimeZoneShow = pure TimeZoneShow @@ -262,6 +268,12 @@ reservedIdentifiers = reservedKeywords <> , "Date/show" , "Time/show" , "TimeZone/show" + , "Date/year" + , "Date/month" + , "Date/day" + , "Time/hour" + , "Time/minute" + , "Time/second" , "Bool" , "Bytes" , "True" diff --git a/dhall/src/Dhall/TypeCheck.hs b/dhall/src/Dhall/TypeCheck.hs index 9c2a30355..1c9f20a87 100644 --- a/dhall/src/Dhall/TypeCheck.hs +++ b/dhall/src/Dhall/TypeCheck.hs @@ -591,6 +591,15 @@ infer typer = loop DateShow -> return (VDate ~> VText) + DateYear -> + return (VDate ~> VNatural) + + DateMonth -> + return (VDate ~> VNatural) + + DateDay -> + return (VDate ~> VNatural) + Time -> return (VConst Type) @@ -600,6 +609,15 @@ infer typer = loop TimeShow -> return (VTime ~> VText) + TimeHour -> + return (VTime ~> VNatural) + + TimeMinute -> + return (VTime ~> VNatural) + + TimeSecond -> + return (VTime ~> VNatural) + TimeZone -> return (VConst Type) diff --git a/dhall/tests/Dhall/Test/QuickCheck.hs b/dhall/tests/Dhall/Test/QuickCheck.hs index b73156be3..baed906a0 100644 --- a/dhall/tests/Dhall/Test/QuickCheck.hs +++ b/dhall/tests/Dhall/Test/QuickCheck.hs @@ -389,9 +389,15 @@ instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where % (1 :: W "Date") % (1 :: W "DateLiteral") % (1 :: W "DateShow") + % (1 :: W "DateYear") + % (1 :: W "DateMonth") + % (1 :: W "DateDay") % (1 :: W "Time") % (1 :: W "TimeLiteral") % (1 :: W "TimeShow") + % (1 :: W "TimeHour") + % (1 :: W "TimeMinute") + % (1 :: W "TimeSecond") % (1 :: W "TimeZone") % (1 :: W "TimeZoneLiteral") % (1 :: W "TimeZoneShow")