dhall 1.36.0 → 1.42.3
raw patch · 1162 files changed
Files
- CHANGELOG.md +284/−2
- LICENSE +1/−1
- benchmark/deep-nested-large-record/Main.hs +11/−12
- benchmark/examples/cpkg.dhall too large to diff
- benchmark/examples/issue108.dhall +0/−63
- benchmark/examples/normalize/ChurchEval.dhall +0/−22
- benchmark/examples/normalize/FunCompose.dhall +0/−18
- benchmark/examples/normalize/ListBench.dhall +0/−75
- benchmark/examples/normalize/ListBenchAlt.dhall +0/−45
- benchmark/parser/Main.hs +35/−34
- benchmark/parser/examples/cpkg.dhall too large to diff
- benchmark/parser/examples/issue108.dhall +63/−0
- benchmark/parser/examples/issue108.dhallb binary
- benchmark/parser/examples/kubernetes.dhallb too large to diff
- benchmark/parser/examples/normalize/ChurchEval.dhall +22/−0
- benchmark/parser/examples/normalize/FunCompose.dhall +18/−0
- benchmark/parser/examples/normalize/ListBench.dhall +75/−0
- benchmark/parser/examples/normalize/ListBenchAlt.dhall +45/−0
- dhall-lang/Prelude/Bool/and +2/−1
- dhall-lang/Prelude/Bool/build +2/−1
- dhall-lang/Prelude/Bool/equal.dhall +6/−0
- dhall-lang/Prelude/Bool/even +2/−1
- dhall-lang/Prelude/Bool/fold +2/−1
- dhall-lang/Prelude/Bool/not +2/−1
- dhall-lang/Prelude/Bool/odd +2/−1
- dhall-lang/Prelude/Bool/or +2/−1
- dhall-lang/Prelude/Bool/package.dhall +20/−8
- dhall-lang/Prelude/Bool/show +2/−1
- dhall-lang/Prelude/Date/package.dhall +5/−0
- dhall-lang/Prelude/Date/show.dhall +15/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/Type.dhall +5/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/intersect.dhall +69/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/invert.dhall +48/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/none.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/package.dhall +53/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/r.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/rw.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/rwx.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/rx.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/toAccess.dhall +20/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/toAccessWith.dhall +42/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/union.dhall +64/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/w.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Mask/x.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/Type.dhall +5/−0
- dhall-lang/Prelude/DirectoryTree/Access/equal.dhall +29/−0
- dhall-lang/Prelude/DirectoryTree/Access/none.dhall +4/−0
- dhall-lang/Prelude/DirectoryTree/Access/package.dhall +17/−0
- dhall-lang/Prelude/DirectoryTree/Access/schema.dhall +12/−0
- dhall-lang/Prelude/DirectoryTree/Entry/BinaryFileEntry.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/DirectoryEntry.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/Metadata.dhall +24/−0
- dhall-lang/Prelude/DirectoryTree/Entry/TextFileEntry.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/Type.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/binary-file.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/directory.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Entry/entry.dhall +24/−0
- dhall-lang/Prelude/DirectoryTree/Entry/package.dhall +37/−0
- dhall-lang/Prelude/DirectoryTree/Entry/text-file.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Group/Type.dhall +1/−0
- dhall-lang/Prelude/DirectoryTree/Group/id.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Group/name.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Group/package.dhall +13/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/Type.dhall +10/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/all.dhall +9/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/directory.dhall +17/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/executable.dhall +17/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/file.dhall +17/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/group.dhall +14/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/intersect.dhall +24/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/invert.dhall +22/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/none.dhall +12/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/other.dhall +14/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/package.dhall +41/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/toMode.dhall +28/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/toModeWith.dhall +149/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/union.dhall +24/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Mask/user.dhall +14/−0
- dhall-lang/Prelude/DirectoryTree/Mode/Type.dhall +10/−0
- dhall-lang/Prelude/DirectoryTree/Mode/equal.dhall +34/−0
- dhall-lang/Prelude/DirectoryTree/Mode/none.dhall +9/−0
- dhall-lang/Prelude/DirectoryTree/Mode/package.dhall +17/−0
- dhall-lang/Prelude/DirectoryTree/Mode/schema.dhall +12/−0
- dhall-lang/Prelude/DirectoryTree/Tree/Make.dhall +20/−0
- dhall-lang/Prelude/DirectoryTree/Tree/Type.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/Tree/makeTree.dhall +32/−0
- dhall-lang/Prelude/DirectoryTree/Tree/makeTreeFromList.dhall +42/−0
- dhall-lang/Prelude/DirectoryTree/Tree/makeTreesFromList.dhall +36/−0
- dhall-lang/Prelude/DirectoryTree/Tree/package.dhall +21/−0
- dhall-lang/Prelude/DirectoryTree/User/Type.dhall +1/−0
- dhall-lang/Prelude/DirectoryTree/User/id.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/User/name.dhall +6/−0
- dhall-lang/Prelude/DirectoryTree/User/package.dhall +13/−0
- dhall-lang/Prelude/DirectoryTree/package.dhall +25/−0
- dhall-lang/Prelude/Double/package.dhall +2/−1
- dhall-lang/Prelude/Double/show +2/−1
- dhall-lang/Prelude/Function/compose +2/−1
- dhall-lang/Prelude/Function/compose.dhall +6/−6
- dhall-lang/Prelude/Function/composeList.dhall +35/−0
- dhall-lang/Prelude/Function/identity +2/−1
- dhall-lang/Prelude/Function/package.dhall +8/−2
- dhall-lang/Prelude/Integer/abs +2/−1
- dhall-lang/Prelude/Integer/add +2/−1
- dhall-lang/Prelude/Integer/add.dhall +2/−1
- dhall-lang/Prelude/Integer/clamp +2/−1
- dhall-lang/Prelude/Integer/equal +2/−1
- dhall-lang/Prelude/Integer/equal.dhall +2/−1
- dhall-lang/Prelude/Integer/greaterThan +2/−1
- dhall-lang/Prelude/Integer/greaterThan.dhall +4/−2
- dhall-lang/Prelude/Integer/greaterThanEqual +2/−1
- dhall-lang/Prelude/Integer/greaterThanEqual.dhall +2/−1
- dhall-lang/Prelude/Integer/lessThan +2/−1
- dhall-lang/Prelude/Integer/lessThan.dhall +2/−1
- dhall-lang/Prelude/Integer/lessThanEqual +2/−1
- dhall-lang/Prelude/Integer/lessThanEqual.dhall +8/−4
- dhall-lang/Prelude/Integer/multiply +2/−1
- dhall-lang/Prelude/Integer/multiply.dhall +2/−2
- dhall-lang/Prelude/Integer/negate +2/−1
- dhall-lang/Prelude/Integer/negative +2/−1
- dhall-lang/Prelude/Integer/negative.dhall +2/−1
- dhall-lang/Prelude/Integer/nonNegative +2/−1
- dhall-lang/Prelude/Integer/nonNegative.dhall +2/−1
- dhall-lang/Prelude/Integer/nonPositive +2/−1
- dhall-lang/Prelude/Integer/package.dhall +36/−18
- dhall-lang/Prelude/Integer/positive +2/−1
- dhall-lang/Prelude/Integer/positive.dhall +4/−2
- dhall-lang/Prelude/Integer/show +2/−1
- dhall-lang/Prelude/Integer/subtract +2/−1
- dhall-lang/Prelude/Integer/subtract.dhall +2/−1
- dhall-lang/Prelude/Integer/toDouble +2/−1
- dhall-lang/Prelude/Integer/toNatural +2/−1
- dhall-lang/Prelude/Integer/toNatural.dhall +2/−1
- dhall-lang/Prelude/JSON/Format +2/−1
- dhall-lang/Prelude/JSON/Format.dhall +0/−1
- dhall-lang/Prelude/JSON/Nesting +2/−1
- dhall-lang/Prelude/JSON/Tagged +2/−1
- dhall-lang/Prelude/JSON/Tagged.dhall +2/−1
- dhall-lang/Prelude/JSON/Type +2/−1
- dhall-lang/Prelude/JSON/array +2/−1
- dhall-lang/Prelude/JSON/array.dhall +4/−2
- dhall-lang/Prelude/JSON/bool +2/−1
- dhall-lang/Prelude/JSON/bool.dhall +2/−1
- dhall-lang/Prelude/JSON/core.dhall +30/−15
- dhall-lang/Prelude/JSON/double +2/−1
- dhall-lang/Prelude/JSON/double.dhall +2/−1
- dhall-lang/Prelude/JSON/integer +2/−1
- dhall-lang/Prelude/JSON/integer.dhall +2/−1
- dhall-lang/Prelude/JSON/keyText +2/−1
- dhall-lang/Prelude/JSON/keyText.dhall +2/−1
- dhall-lang/Prelude/JSON/keyValue +2/−1
- dhall-lang/Prelude/JSON/keyValue.dhall +2/−1
- dhall-lang/Prelude/JSON/natural +2/−1
- dhall-lang/Prelude/JSON/natural.dhall +2/−1
- dhall-lang/Prelude/JSON/null +2/−1
- dhall-lang/Prelude/JSON/null.dhall +2/−1
- dhall-lang/Prelude/JSON/number +2/−1
- dhall-lang/Prelude/JSON/number.dhall +4/−2
- dhall-lang/Prelude/JSON/object +2/−1
- dhall-lang/Prelude/JSON/object.dhall +4/−2
- dhall-lang/Prelude/JSON/omitNullFields +2/−1
- dhall-lang/Prelude/JSON/omitNullFields.dhall +6/−3
- dhall-lang/Prelude/JSON/package.dhall +16/−6
- dhall-lang/Prelude/JSON/render +2/−1
- dhall-lang/Prelude/JSON/render.dhall +6/−3
- dhall-lang/Prelude/JSON/renderAs +2/−1
- dhall-lang/Prelude/JSON/renderAs.dhall +69/−39
- dhall-lang/Prelude/JSON/renderCompact.dhall +61/−0
- dhall-lang/Prelude/JSON/renderInteger.dhall +2/−2
- dhall-lang/Prelude/JSON/renderYAML +2/−1
- dhall-lang/Prelude/JSON/renderYAML.dhall +6/−4
- dhall-lang/Prelude/JSON/string +2/−1
- dhall-lang/Prelude/JSON/string.dhall +2/−1
- dhall-lang/Prelude/JSON/tagInline +2/−1
- dhall-lang/Prelude/JSON/tagInline.dhall +4/−2
- dhall-lang/Prelude/JSON/tagNested +2/−1
- dhall-lang/Prelude/JSON/tagNested.dhall +4/−2
- dhall-lang/Prelude/List/all +2/−1
- dhall-lang/Prelude/List/any +2/−1
- dhall-lang/Prelude/List/build +2/−1
- dhall-lang/Prelude/List/concat +2/−1
- dhall-lang/Prelude/List/concatMap +2/−1
- dhall-lang/Prelude/List/default +2/−1
- dhall-lang/Prelude/List/drop +2/−1
- dhall-lang/Prelude/List/drop.dhall +2/−1
- dhall-lang/Prelude/List/empty +2/−1
- dhall-lang/Prelude/List/filter +2/−1
- dhall-lang/Prelude/List/filterMap.dhall +45/−0
- dhall-lang/Prelude/List/fold +2/−1
- dhall-lang/Prelude/List/fold.dhall +17/−25
- dhall-lang/Prelude/List/foldLeft.dhall +60/−0
- dhall-lang/Prelude/List/generate +2/−1
- dhall-lang/Prelude/List/head +2/−1
- dhall-lang/Prelude/List/index +2/−1
- dhall-lang/Prelude/List/index.dhall +2/−1
- dhall-lang/Prelude/List/indexed +2/−1
- dhall-lang/Prelude/List/iterate +2/−1
- dhall-lang/Prelude/List/last +2/−1
- dhall-lang/Prelude/List/length +2/−1
- dhall-lang/Prelude/List/map +2/−1
- dhall-lang/Prelude/List/mapMaybe.dhall +37/−0
- dhall-lang/Prelude/List/mapWithIndex.dhall +41/−0
- dhall-lang/Prelude/List/null +2/−1
- dhall-lang/Prelude/List/package.dhall +70/−27
- dhall-lang/Prelude/List/partition +2/−1
- dhall-lang/Prelude/List/replicate +2/−1
- dhall-lang/Prelude/List/reverse +2/−1
- dhall-lang/Prelude/List/shifted +2/−1
- dhall-lang/Prelude/List/take +2/−1
- dhall-lang/Prelude/List/take.dhall +2/−1
- dhall-lang/Prelude/List/unpackOptionals +2/−1
- dhall-lang/Prelude/List/unpackOptionals.dhall +5/−9
- dhall-lang/Prelude/List/unzip +2/−1
- dhall-lang/Prelude/List/zip +2/−1
- dhall-lang/Prelude/List/zip.dhall +2/−1
- dhall-lang/Prelude/Location/Type +2/−1
- dhall-lang/Prelude/Location/Type.dhall +1/−2
- dhall-lang/Prelude/Location/package.dhall +2/−1
- dhall-lang/Prelude/Map/Entry +2/−1
- dhall-lang/Prelude/Map/Type +2/−1
- dhall-lang/Prelude/Map/empty +2/−1
- dhall-lang/Prelude/Map/empty.dhall +2/−1
- dhall-lang/Prelude/Map/keyText +2/−1
- dhall-lang/Prelude/Map/keyValue +2/−1
- dhall-lang/Prelude/Map/keys +2/−1
- dhall-lang/Prelude/Map/keys.dhall +6/−3
- dhall-lang/Prelude/Map/map +2/−1
- dhall-lang/Prelude/Map/map.dhall +6/−3
- dhall-lang/Prelude/Map/mapMaybe.dhall +56/−0
- dhall-lang/Prelude/Map/package.dhall +22/−9
- dhall-lang/Prelude/Map/unpackOptionals.dhall +6/−4
- dhall-lang/Prelude/Map/values +2/−1
- dhall-lang/Prelude/Map/values.dhall +6/−3
- dhall-lang/Prelude/Monoid +2/−1
- dhall-lang/Prelude/Natural/build +2/−1
- dhall-lang/Prelude/Natural/enumerate +2/−1
- dhall-lang/Prelude/Natural/equal +2/−1
- dhall-lang/Prelude/Natural/equal.dhall +2/−1
- dhall-lang/Prelude/Natural/even +2/−1
- dhall-lang/Prelude/Natural/fold +2/−1
- dhall-lang/Prelude/Natural/fold.dhall +8/−15
- dhall-lang/Prelude/Natural/greaterThan +2/−1
- dhall-lang/Prelude/Natural/greaterThan.dhall +2/−1
- dhall-lang/Prelude/Natural/greaterThanEqual +2/−1
- dhall-lang/Prelude/Natural/greaterThanEqual.dhall +2/−1
- dhall-lang/Prelude/Natural/isZero +2/−1
- dhall-lang/Prelude/Natural/lessThan +2/−1
- dhall-lang/Prelude/Natural/lessThan.dhall +4/−2
- dhall-lang/Prelude/Natural/lessThanEqual +2/−1
- dhall-lang/Prelude/Natural/listMax +2/−1
- dhall-lang/Prelude/Natural/listMax.dhall +4/−2
- dhall-lang/Prelude/Natural/listMin +2/−1
- dhall-lang/Prelude/Natural/listMin.dhall +4/−2
- dhall-lang/Prelude/Natural/max +2/−1
- dhall-lang/Prelude/Natural/max.dhall +2/−1
- dhall-lang/Prelude/Natural/min +2/−1
- dhall-lang/Prelude/Natural/min.dhall +2/−1
- dhall-lang/Prelude/Natural/odd +2/−1
- dhall-lang/Prelude/Natural/package.dhall +44/−22
- dhall-lang/Prelude/Natural/product +2/−1
- dhall-lang/Prelude/Natural/show +2/−1
- dhall-lang/Prelude/Natural/sort +2/−1
- dhall-lang/Prelude/Natural/sort.dhall +6/−3
- dhall-lang/Prelude/Natural/subtract +2/−1
- dhall-lang/Prelude/Natural/sum +2/−1
- dhall-lang/Prelude/Natural/toDouble +2/−1
- dhall-lang/Prelude/Natural/toInteger +2/−1
- dhall-lang/Prelude/NonEmpty/Type.dhall +9/−0
- dhall-lang/Prelude/NonEmpty/all.dhall +34/−0
- dhall-lang/Prelude/NonEmpty/any.dhall +34/−0
- dhall-lang/Prelude/NonEmpty/concat.dhall +61/−0
- dhall-lang/Prelude/NonEmpty/concatMap.dhall +56/−0
- dhall-lang/Prelude/NonEmpty/head.dhall +13/−0
- dhall-lang/Prelude/NonEmpty/index.dhall +33/−0
- dhall-lang/Prelude/NonEmpty/indexed.dhall +41/−0
- dhall-lang/Prelude/NonEmpty/last.dhall +17/−0
- dhall-lang/Prelude/NonEmpty/length.dhall +16/−0
- dhall-lang/Prelude/NonEmpty/make.dhall +18/−0
- dhall-lang/Prelude/NonEmpty/map.dhall +30/−0
- dhall-lang/Prelude/NonEmpty/package.dhall +73/−0
- dhall-lang/Prelude/NonEmpty/reverse.dhall +35/−0
- dhall-lang/Prelude/NonEmpty/shifted.dhall +101/−0
- dhall-lang/Prelude/NonEmpty/singleton.dhall +14/−0
- dhall-lang/Prelude/NonEmpty/toList.dhall +17/−0
- dhall-lang/Prelude/NonEmpty/unzip.dhall +58/−0
- dhall-lang/Prelude/NonEmpty/zip.dhall +63/−0
- dhall-lang/Prelude/Operator/package.dhall +85/−0
- dhall-lang/Prelude/Optional/all +2/−1
- dhall-lang/Prelude/Optional/any +2/−1
- dhall-lang/Prelude/Optional/build +2/−1
- dhall-lang/Prelude/Optional/concat +2/−1
- dhall-lang/Prelude/Optional/concatMap.dhall +23/−0
- dhall-lang/Prelude/Optional/default +2/−1
- dhall-lang/Prelude/Optional/equal.dhall +24/−0
- dhall-lang/Prelude/Optional/filter +2/−1
- dhall-lang/Prelude/Optional/fold +2/−1
- dhall-lang/Prelude/Optional/fold.dhall +2/−3
- dhall-lang/Prelude/Optional/head +2/−1
- dhall-lang/Prelude/Optional/last +2/−1
- dhall-lang/Prelude/Optional/length +2/−1
- dhall-lang/Prelude/Optional/map +2/−1
- dhall-lang/Prelude/Optional/null +2/−1
- dhall-lang/Prelude/Optional/package.dhall +36/−14
- dhall-lang/Prelude/Optional/toList +2/−1
- dhall-lang/Prelude/Optional/unzip +2/−1
- dhall-lang/Prelude/Text/concat +2/−1
- dhall-lang/Prelude/Text/concatMap +2/−1
- dhall-lang/Prelude/Text/concatMapSep +2/−1
- dhall-lang/Prelude/Text/concatSep +2/−1
- dhall-lang/Prelude/Text/default +2/−1
- dhall-lang/Prelude/Text/defaultMap +2/−1
- dhall-lang/Prelude/Text/lowerASCII.dhall +56/−0
- dhall-lang/Prelude/Text/package.dhall +34/−9
- dhall-lang/Prelude/Text/replicate +2/−1
- dhall-lang/Prelude/Text/replicate.dhall +4/−3
- dhall-lang/Prelude/Text/shell-escape.dhall +16/−0
- dhall-lang/Prelude/Text/show +2/−1
- dhall-lang/Prelude/Text/spaces +2/−1
- dhall-lang/Prelude/Text/spaces.dhall +2/−2
- dhall-lang/Prelude/Text/upperASCII.dhall +56/−0
- dhall-lang/Prelude/Time/package.dhall +5/−0
- dhall-lang/Prelude/Time/show.dhall +15/−0
- dhall-lang/Prelude/TimeZone/package.dhall +5/−0
- dhall-lang/Prelude/TimeZone/show.dhall +15/−0
- dhall-lang/Prelude/XML/Type +2/−1
- dhall-lang/Prelude/XML/Type.dhall +3/−1
- dhall-lang/Prelude/XML/attribute +2/−1
- dhall-lang/Prelude/XML/attribute.dhall +0/−1
- dhall-lang/Prelude/XML/element +2/−1
- dhall-lang/Prelude/XML/element.dhall +5/−4
- dhall-lang/Prelude/XML/emptyAttributes +2/−1
- dhall-lang/Prelude/XML/emptyAttributes.dhall +0/−1
- dhall-lang/Prelude/XML/leaf +2/−1
- dhall-lang/Prelude/XML/leaf.dhall +4/−3
- dhall-lang/Prelude/XML/package.dhall +18/−7
- dhall-lang/Prelude/XML/rawText.dhall +40/−0
- dhall-lang/Prelude/XML/render +2/−1
- dhall-lang/Prelude/XML/render.dhall +87/−11
- dhall-lang/Prelude/XML/text +2/−1
- dhall-lang/Prelude/XML/text.dhall +4/−3
- dhall-lang/Prelude/package.dhall +48/−15
- dhall-lang/tests/binary-decode/success/unit/BytesA.dhallb binary
- dhall-lang/tests/binary-decode/success/unit/BytesB.dhall +23/−0
- dhall-lang/tests/binary-decode/success/unit/DateA.dhallb +1/−0
- dhall-lang/tests/binary-decode/success/unit/DateB.dhall +1/−0
- dhall-lang/tests/binary-decode/success/unit/TimeA.dhallb binary
- dhall-lang/tests/binary-decode/success/unit/TimeB.dhall +1/−0
- dhall-lang/tests/binary-decode/success/unit/TimeZoneA.dhallb binary
- dhall-lang/tests/binary-decode/success/unit/TimeZoneB.dhall +1/−0
- dhall-lang/tests/import/data/cors/AllowedAll.dhall +1/−0
- dhall-lang/tests/import/data/cors/Empty.dhall +1/−0
- dhall-lang/tests/import/data/cors/NoCORS.dhall +1/−0
- dhall-lang/tests/import/data/cors/Null.dhall +1/−0
- dhall-lang/tests/import/data/cors/OnlyGithub.dhall +1/−0
- dhall-lang/tests/import/data/cors/OnlyOther.dhall +1/−0
- dhall-lang/tests/import/data/cors/OnlySelf.dhall +1/−0
- dhall-lang/tests/import/data/cors/Prelude.dhall +1/−0
- dhall-lang/tests/import/data/cors/SelfImportAbsolute.dhall +1/−0
- dhall-lang/tests/import/data/cors/SelfImportRelative.dhall +1/−0
- dhall-lang/tests/import/data/cycle.dhall +1/−1
- dhall-lang/tests/import/data/doesNotParse.dhall +1/−0
- dhall-lang/tests/import/data/example.bin +1/−0
- dhall-lang/tests/import/data/userAgent.dhall +1/−0
- dhall-lang/tests/import/failure/cycle.dhall +0/−1
- dhall-lang/tests/import/failure/hashMismatch.dhall +0/−1
- dhall-lang/tests/import/failure/importBoundary.dhall +0/−1
- dhall-lang/tests/import/failure/missing.dhall +0/−1
- dhall-lang/tests/import/failure/originHeadersFromRemote.dhall +1/−0
- dhall-lang/tests/import/failure/originHeadersFromRemoteENV.dhall +11/−0
- dhall-lang/tests/import/failure/referentiallyInsane.dhall +0/−13
- dhall-lang/tests/import/failure/unit/404.dhall +1/−0
- dhall-lang/tests/import/failure/unit/Cycle.dhall +1/−0
- dhall-lang/tests/import/failure/unit/DontRecoverCycle.dhall +1/−0
- dhall-lang/tests/import/failure/unit/DontRecoverHashMismatch.dhall +3/−0
- dhall-lang/tests/import/failure/unit/DontRecoverParseError.dhall +1/−0
- dhall-lang/tests/import/failure/unit/DontRecoverTypeError.dhall +1/−0
- dhall-lang/tests/import/failure/unit/EnvFromRemote.dhall +13/−0
- dhall-lang/tests/import/failure/unit/FileMissing.dhall +1/−0
- dhall-lang/tests/import/failure/unit/HashMismatch.dhall +1/−0
- dhall-lang/tests/import/failure/unit/HashMismatch2.dhall +2/−0
- dhall-lang/tests/import/failure/unit/Missing.dhall +1/−0
- dhall-lang/tests/import/failure/unit/VarAcrossImportBoundary.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/Empty.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/NoCORS.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/Null.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/OnlyOther.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/OnlySelf.dhall +1/−0
- dhall-lang/tests/import/failure/unit/cors/TwoHops.dhall +1/−0
- dhall-lang/tests/import/home/hello.dhall +1/−0
- dhall-lang/tests/import/success/headerForwardingA.dhall +5/−9
- dhall-lang/tests/import/success/headerForwardingB.dhall +1/−26
- dhall-lang/tests/import/success/originHeadersA.dhall +1/−0
- dhall-lang/tests/import/success/originHeadersB.dhall +5/−0
- dhall-lang/tests/import/success/originHeadersENV.dhall +10/−0
- dhall-lang/tests/import/success/originHeadersImportA.dhall +1/−0
- dhall-lang/tests/import/success/originHeadersImportB.dhall +5/−0
- dhall-lang/tests/import/success/originHeadersImportENV.dhall +10/−0
- dhall-lang/tests/import/success/originHeadersImportFromEnvA.dhall +1/−0
- dhall-lang/tests/import/success/originHeadersImportFromEnvB.dhall +5/−0
- dhall-lang/tests/import/success/originHeadersImportFromEnvENV.dhall +11/−0
- dhall-lang/tests/import/success/originHeadersOverrideA.dhall +3/−0
- dhall-lang/tests/import/success/originHeadersOverrideB.dhall +5/−0
- dhall-lang/tests/import/success/originHeadersOverrideENV.dhall +10/−0
- dhall-lang/tests/import/success/unit/AlternativeHashMismatchA.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeHashMismatchB.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeParseErrorA.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeParseErrorB.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeTypeErrorA.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeTypeErrorB.dhall +0/−1
- dhall-lang/tests/import/success/unit/AlternativeWithVariableA.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithVariableB.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1A.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable1B.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2A.dhall +1/−0
- dhall-lang/tests/import/success/unit/AlternativeWithWrongVariable2B.dhall +1/−0
- dhall-lang/tests/import/success/unit/AsBytesA.dhall +1/−0
- dhall-lang/tests/import/success/unit/AsBytesB.dhall +1/−0
- dhall-lang/tests/import/success/unit/DontCacheIfHashA.dhall +5/−0
- dhall-lang/tests/import/success/unit/DontCacheIfHashB.dhall +1/−0
- dhall-lang/tests/import/success/unit/ImportRelativeToHomeA.dhall +1/−0
- dhall-lang/tests/import/success/unit/ImportRelativeToHomeB.dhall +1/−0
- dhall-lang/tests/import/success/unit/MixImportModesA.dhall +2/−0
- dhall-lang/tests/import/success/unit/MixImportModesB.dhall +1/−0
- dhall-lang/tests/import/success/unit/RecoverTransitiveFailureA.dhall +1/−0
- dhall-lang/tests/import/success/unit/RecoverTransitiveFailureB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/AllowedAllA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/AllowedAllB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/NoCORSFromLocalB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/OnlyGithubA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/OnlyGithubB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/PreludeA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/PreludeB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2A.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportAbsolute2B.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportAbsoluteB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportRelative2A.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportRelative2B.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportRelativeA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/SelfImportRelativeB.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/TwoHopsA.dhall +1/−0
- dhall-lang/tests/import/success/unit/cors/TwoHopsB.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationA.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ComplexRecordSimplificationB.dhall +3/−0
- dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/regression/ToMapQuotedFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/remoteSystemsA.dhall +2/−2
- dhall-lang/tests/normalization/success/unit/BytesA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/BytesB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/BytesLiteralA.dhall +23/−0
- dhall-lang/tests/normalization/success/unit/BytesLiteralB.dhall +23/−0
- dhall-lang/tests/normalization/success/unit/RecordSortFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordSortFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/RecordTypeSortFieldsB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/ShowConstructorEmptyB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/ShowConstructorNonEmptyB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceAbstractA.dhall +2/−3
- dhall-lang/tests/normalization/success/unit/TextReplaceAbstractB.dhall +1/−1
- dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackA.dhall +4/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceAbstractHaystackB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1A.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty1B.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2A.dhall +2/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty2B.dhall +2/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3A.dhall +3/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmpty3B.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceEmptyA.dhall +0/−1
- dhall-lang/tests/normalization/success/unit/TextReplaceEmptyB.dhall +0/−1
- dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceOverlappingB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceVarA.dhall +3/−0
- dhall-lang/tests/normalization/success/unit/TextReplaceVarB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/TimeAsRecordA.dhall +2/−0
- dhall-lang/tests/normalization/success/unit/TimeAsRecordB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOnOptionalNoneB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOnOptionalSomeB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOptionalDeeplyNestedB.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOptionalNestedA.dhall +1/−0
- dhall-lang/tests/normalization/success/unit/WithOptionalNestedB.dhall +1/−0
- dhall-lang/tests/parser/failure/boundBuiltins.dhall +1/−1
- dhall-lang/tests/parser/failure/bytesInvalid.dhall +1/−0
- dhall-lang/tests/parser/failure/bytesOddLength.dhall +1/−0
- dhall-lang/tests/parser/failure/spacing/LetNoSpace3.dhall +1/−0
- dhall-lang/tests/parser/failure/spacing/LetNoSpace4.dhall +1/−0
- dhall-lang/tests/parser/failure/time/DateTimeZone.dhall +2/−0
- dhall-lang/tests/parser/failure/time/InvalidDayOfMonth.dhall +2/−0
- dhall-lang/tests/parser/failure/time/InvalidHour.dhall +2/−0
- dhall-lang/tests/parser/failure/time/InvalidLeapSecond.dhall +3/−0
- dhall-lang/tests/parser/failure/time/InvalidMinute.dhall +2/−0
- dhall-lang/tests/parser/failure/time/InvalidMonth.dhall +2/−0
- dhall-lang/tests/parser/failure/time/InvalidSecond.dhall +2/−0
- dhall-lang/tests/parser/failure/time/NegativeYear.dhall +2/−0
- dhall-lang/tests/parser/failure/time/YearTooLarge.dhall +2/−0
- dhall-lang/tests/parser/failure/unit/WithWhitespace.dhall +2/−0
- dhall-lang/tests/parser/failure/unit/showConstructorAlone.dhall +1/−0
- dhall-lang/tests/parser/success/binaryA.dhall +8/−0
- dhall-lang/tests/parser/success/binaryB.dhallb binary
- dhall-lang/tests/parser/success/builtinsA.dhall +28/−24
- dhall-lang/tests/parser/success/builtinsB.dhallb +1/−1
- dhall-lang/tests/parser/success/bytesA.dhall +25/−0
- dhall-lang/tests/parser/success/bytesB.dhallb binary
- dhall-lang/tests/parser/success/listWithCommentA.dhall +3/−0
- dhall-lang/tests/parser/success/listWithCommentB.dhallb +1/−0
- dhall-lang/tests/parser/success/mixedBlockLineCommentA.dhall +6/−0
- dhall-lang/tests/parser/success/mixedBlockLineCommentB.dhallb +1/−0
- dhall-lang/tests/parser/success/text/multilinePreserveCommentA.dhall +8/−0
- dhall-lang/tests/parser/success/text/multilinePreserveCommentB.dhallb +2/−0
- dhall-lang/tests/parser/success/text/preserveCommentA.dhall +1/−8
- dhall-lang/tests/parser/success/text/preserveCommentB.dhallb +1/−2
- dhall-lang/tests/parser/success/text/unicodeBracedA.dhall +1/−0
- dhall-lang/tests/parser/success/text/unicodeBracedB.dhallb +1/−0
- dhall-lang/tests/parser/success/text/unicodeEscapedA.dhall +1/−0
- dhall-lang/tests/parser/success/text/unicodeEscapedB.dhallb +1/−0
- dhall-lang/tests/parser/success/text/unicodePlane16A.dhall +1/−0
- dhall-lang/tests/parser/success/text/unicodePlane16B.dhallb +1/−0
- dhall-lang/tests/parser/success/time/DateTimeA.dhall +1/−0
- dhall-lang/tests/parser/success/time/DateTimeB.dhallb binary
- dhall-lang/tests/parser/success/time/DateTimeTimeZoneA.dhall +1/−0
- dhall-lang/tests/parser/success/time/DateTimeTimeZoneB.dhallb binary
- dhall-lang/tests/parser/success/time/LowercaseTA.dhall +2/−0
- dhall-lang/tests/parser/success/time/LowercaseTB.dhallb binary
- dhall-lang/tests/parser/success/time/TimeTimeZoneA.dhall +1/−0
- dhall-lang/tests/parser/success/time/TimeTimeZoneB.dhallb binary
- dhall-lang/tests/parser/success/time/TimeTimeZoneZA.dhall +5/−0
- dhall-lang/tests/parser/success/time/TimeTimeZoneZB.dhallb binary
- dhall-lang/tests/parser/success/unit/DateA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/DateB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/DateLiteralA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/DateLiteralB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/DeBruijnIndexA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/DeBruijnIndexB.dhallb binary
- dhall-lang/tests/parser/success/unit/DoubleLitSecretelyIntA.dhall +0/−5
- dhall-lang/tests/parser/success/unit/DoubleLitSecretelyIntB.dhallb binary
- dhall-lang/tests/parser/success/unit/DoubleLitSecretlyIntA.dhall +5/−0
- dhall-lang/tests/parser/success/unit/DoubleLitSecretlyIntB.dhallb binary
- dhall-lang/tests/parser/success/unit/ForallUnicodeA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/ForallUnicodeB.dhallb binary
- dhall-lang/tests/parser/success/unit/ListWithNewlineA.dhall +11/−0
- dhall-lang/tests/parser/success/unit/ListWithNewlineB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/RecordFieldAccessA.dhall +0/−1
- dhall-lang/tests/parser/success/unit/RecordFieldAccessB.dhallb binary
- dhall-lang/tests/parser/success/unit/RecordLitEmptyBothCommasA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/RecordLitEmptyBothCommasB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/RecordProjectFieldsA.dhall +0/−1
- dhall-lang/tests/parser/success/unit/RecordProjectFieldsB.dhallb binary
- dhall-lang/tests/parser/success/unit/RecordTypeEmptyA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/RecordTypeEmptyB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/ShebangA.dhall +2/−0
- dhall-lang/tests/parser/success/unit/ShebangB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/ShebangNixA.dhall +3/−0
- dhall-lang/tests/parser/success/unit/ShebangNixB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/ShowConstructorA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/ShowConstructorB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/ShowConstructorWithValueA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/ShowConstructorWithValueB.dhallb binary
- dhall-lang/tests/parser/success/unit/TimeA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/TimeB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/TimeLiteralA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/TimeLiteralB.dhallb binary
- dhall-lang/tests/parser/success/unit/TimeZoneA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/TimeZoneB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/TimeZoneLiteralA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/TimeZoneLiteralB.dhallb binary
- dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineA.dhall +2/−0
- dhall-lang/tests/parser/success/unit/TrailingLineCommentWithoutNewlineB.dhallb +1/−0
- dhall-lang/tests/parser/success/unit/WithSomeA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/WithSomeB.dhallb binary
- dhall-lang/tests/parser/success/unit/operators/EquivalenceAssocA.dhall +1/−0
- dhall-lang/tests/parser/success/unit/operators/EquivalenceAssocB.dhallb binary
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeA.dhall +1/−1
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocA.dhall +1/−1
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeAssocB.dhallb binary
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordMergeB.dhallb binary
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeA.dhall +1/−1
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeAssocA.dhall +1/−1
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeAssocB.dhallb binary
- dhall-lang/tests/parser/success/unit/operators/RecursiveRecordTypeMergeB.dhallb binary
- dhall-lang/tests/parser/success/withQuestionMarkA.dhall +1/−0
- dhall-lang/tests/parser/success/withQuestionMarkB.dhallb binary
- dhall-lang/tests/semantic-hash/success/prelude/Bool/and/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/and/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/build/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/build/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/3A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/not/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/not/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/3A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/or/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/or/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/show/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Bool/show/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Double/show/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Double/show/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Integer/show/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Integer/show/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/all/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/all/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/any/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/any/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/build/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/build/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/concat/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/concat/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/filter/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/filter/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/fold/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/fold/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/fold/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/generate/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/generate/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/head/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/head/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/indexed/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/indexed/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/iterate/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/iterate/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/last/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/last/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/length/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/length/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/map/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/map/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/null/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/null/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/replicate/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/replicate/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/reverse/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/reverse/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/shifted/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/shifted/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/unzip/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/List/unzip/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/build/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/build/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/even/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/even/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/product/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/product/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/show/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/show/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/all/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/all/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/any/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/any/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/build/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/build/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/head/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/head/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/head/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/last/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/last/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/last/2A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/length/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/length/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/map/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/map/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/null/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/null/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concat/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concat/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/1A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/show/0A.dhall +1/−1
- dhall-lang/tests/semantic-hash/success/prelude/Text/show/1A.dhall +1/−1
- dhall-lang/tests/type-inference/failure/DateApplyTime.dhall +3/−0
- dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldName.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AnnotationRecordWrongFieldType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AssertAlphaTrap2.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AssertDoubleZeros.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AssertNotEquivalence.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/AssertTriviallyFalse.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/CompletionMissingRequiredField.dhall +6/−0
- dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongDefaultType.dhall +6/−0
- dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongFieldName.dhall +6/−0
- dhall-lang/tests/type-inference/failure/unit/CompletionWithWrongOverridenType.dhall +6/−0
- dhall-lang/tests/type-inference/failure/unit/EmptyToMap.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/EquivalenceNotSameType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/EquivalenceNotTerms.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionApplicationArgumentNotMatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionApplicationIsNotFunction.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionArgumentTypeNotAType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionTypeArgumentTypeNotAType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionTypeKindSort.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionTypeOutputTypeNotAType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/FunctionTypeTypeSort.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/HeterogenousToMap.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/IfBranchesNotMatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/IfBranchesNotTermTypeOrKind.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/IfNotBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/LetInSort.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/LetWithNonterminatingAnnotation.dhall +14/−0
- dhall-lang/tests/type-inference/failure/unit/LetWithWrongAnnotation.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ListLiteralEmptyNotType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ListLiteralNotType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ListLiteralTypesNotMatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeAlternativeHasNoHandler.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeAnnotationMismatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeAnnotationNotType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation1.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeEmptyNeedsDirectAnnotation2.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeEmptyWithoutAnnotation.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeHandlerFreeVar.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotFunction.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotInUnion.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeHandlerNotMatchAlternativeType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeHandlersWithDifferentType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeLhsNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler1.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeMissingHandler2.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeRhsNotUnion.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MergeUnusedHandler.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MistypedToMap1.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MistypedToMap2.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MistypedToMap3.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/MistypedToMap4.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/NaturalSubtractNotNatural.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/NestedAnnotInnerWrong.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/NestedAnnotOuterWrong.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/NonRecordToMap.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorAndNotBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorEqualNotBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateLhsNotList.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateListsNotMatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateNotListsButMatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorListConcatenateRhsNotList.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorNotEqualNotBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorOrNotBool.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorPlusNotNatural.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateLhsNotText.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorTextConcatenateRhsNotText.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OperatorTimesNotNatural.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxAbsent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/OptionalDeprecatedSyntaxPresent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsAbstract.dhall +13/−0
- dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsCollidingRecords.dhall +8/−0
- dhall-lang/tests/type-inference/failure/unit/RecordLitDuplicateFieldsNotRecords.dhall +7/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeFieldTypeMismatch.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionByTypeNotPresent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionDuplicateFields.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionEmpty.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotPresent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordProjectionNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordSelectionEmpty.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotPresent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordSelectionNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordSelectionTypeNotUnionType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordTypeDuplicateFields.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecordTypeValueMember.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeLhsNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeOverlapping.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordMergeRhsNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeLhsNotRecordType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeOverlapping.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RecursiveRecordTypeMergeRhsNotRecordType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalBuild.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RemovedBuiltinOptionalFold.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeLhsNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/RightBiasedRecordMergeRhsNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyApplied.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ShowConstructorNotFullyAppliedOptional.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ShowConstructorWrongArgument.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/SomeNotType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/Sort.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/TextLiteralInterpolateNotText.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/ToMapEmptyInvalidAnnotation.dhall +2/−0
- dhall-lang/tests/type-inference/failure/unit/ToMapWrongKind.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/TypeAnnotationWrong.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/UnionConstructorFieldNotPresent.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/UnionDeprecatedConstructorsKeyword.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants1.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/UnionTypeDuplicateVariants2.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/UnionTypeNotType.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/VariableFree.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/WithInfersKind.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/WithInvalidOverrideA.dhall +6/−0
- dhall-lang/tests/type-inference/failure/unit/WithNotOptional.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/WithNotRecord.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/WithOptionalRecordTypeChanged.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/WithOptionalTypeChanged.dhall +1/−0
- dhall-lang/tests/type-inference/failure/unit/Z.dhall +4/−0
- dhall-lang/tests/type-inference/success/prelude/Bool/and/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/and/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/build/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/build/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/even/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/even/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/even/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/even/3A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/fold/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/fold/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/not/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/not/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/odd/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/odd/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/odd/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/odd/3A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/or/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/or/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/show/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Bool/show/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Double/show/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Double/show/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Integer/show/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Integer/show/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/all/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/all/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/any/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/any/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/build/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/build/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/concat/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/concat/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/concatMap/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/concatMap/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/filter/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/filter/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/fold/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/fold/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/fold/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/generate/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/generate/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/head/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/head/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/indexed/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/indexed/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/iterate/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/iterate/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/last/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/last/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/length/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/length/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/map/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/map/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/null/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/null/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/replicate/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/replicate/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/reverse/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/reverse/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/shifted/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/shifted/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/unzip/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/List/unzip/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/build/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/build/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/even/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/even/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/fold/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/fold/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/fold/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/isZero/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/isZero/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/odd/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/odd/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/product/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/product/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/show/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/show/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/sum/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/sum/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/all/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/all/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/any/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/any/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/build/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/build/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/concat/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/concat/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/concat/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/filter/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/filter/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/fold/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/fold/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/head/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/head/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/head/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/last/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/last/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/last/2A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/length/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/length/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/map/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/map/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/null/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/null/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/toList/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/toList/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/unzip/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Optional/unzip/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concat/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concat/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatMap/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatMap/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatSep/0A.dhall +1/−1
- dhall-lang/tests/type-inference/success/prelude/Text/concatSep/1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/preludeB.dhall +193/−7
- dhall-lang/tests/type-inference/success/unit/BytesLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/BytesLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ConstructorShiftA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ConstructorShiftB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/IfBranchesKindA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/IfBranchesKindB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/IfBranchesTypeA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/IfBranchesTypeB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/MergeOneWithAnnotation1A.dhall +1/−1
- dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ShowConstructorEmptyB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ShowConstructorNonEmptyB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ShowConstructorOptionalB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/ToMapInferTypeFromRecordA.dhall +1/−1
- dhall-lang/tests/type-inference/success/unit/TypeAnnotationFunctionA.dhall +1/−1
- dhall-lang/tests/type-inference/success/unit/WithInfersKindA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/WithInfersKindB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/WithOptionalTypeUnchangedB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateTimeLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/DateTimeTimeZoneLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeTimeZoneLiteralB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeZoneA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeZoneB.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralA.dhall +1/−0
- dhall-lang/tests/type-inference/success/unit/time/TimeZoneLiteralB.dhall +1/−0
- dhall.cabal +124/−362
- doctest/Main.hs +15/−10
- ghc-src/Dhall/Crypto.hs +12/−13
- ghc-src/Dhall/Import/HTTP.hs +72/−23
- ghc-src/Dhall/Import/Manager.hs +1/−1
- ghcjs-src/Dhall/Crypto.hs +13/−12
- ghcjs-src/Dhall/Import/HTTP.hs +18/−3
- man/dhall.1 +1/−1
- src/Dhall.hs +579/−2893
- src/Dhall/Binary.hs +208/−64
- src/Dhall/Core.hs +10/−9
- src/Dhall/Deriving.hs +0/−1
- src/Dhall/Diff.hs +145/−36
- src/Dhall/DirectoryTree.hs +394/−80
- src/Dhall/DirectoryTree/Types.hs +267/−0
- src/Dhall/Eval.hs +258/−106
- src/Dhall/Format.hs +38/−35
- src/Dhall/Freeze.hs +217/−112
- src/Dhall/Import.hs +330/−167
- src/Dhall/Import/Headers.hs +129/−0
- src/Dhall/Import/Types.hs +62/−48
- src/Dhall/Lint.hs +8/−9
- src/Dhall/Main.hs +209/−106
- src/Dhall/Map.hs +102/−62
- src/Dhall/Marshal/Decode.hs +1712/−0
- src/Dhall/Marshal/Encode.hs +1068/−0
- src/Dhall/Marshal/Internal.hs +193/−0
- src/Dhall/Normalize.hs +439/−349
- src/Dhall/Optics.hs +51/−19
- src/Dhall/Package.hs +297/−0
- src/Dhall/Parser.hs +8/−7
- src/Dhall/Parser/Combinators.hs +31/−34
- src/Dhall/Parser/Expression.hs +279/−93
- src/Dhall/Parser/Token.hs +226/−47
- src/Dhall/Pretty.hs +5/−0
- src/Dhall/Pretty/Internal.hs +383/−120
- src/Dhall/Pretty/Internal.hs-boot +20/−4
- src/Dhall/Repl.hs +59/−39
- src/Dhall/Schemas.hs +38/−34
- src/Dhall/Src.hs +1/−1
- src/Dhall/Syntax.hs +31/−1448
- src/Dhall/Syntax.hs-boot +0/−7
- src/Dhall/Syntax/Binding.hs +57/−0
- src/Dhall/Syntax/Chunks.hs +141/−0
- src/Dhall/Syntax/Chunks.hs-boot +8/−0
- src/Dhall/Syntax/Const.hs +29/−0
- src/Dhall/Syntax/Expr.hs +267/−0
- src/Dhall/Syntax/Expr.hs-boot +8/−0
- src/Dhall/Syntax/FunctionBinding.hs +53/−0
- src/Dhall/Syntax/Import.hs +139/−0
- src/Dhall/Syntax/Instances/Applicative.hs +36/−0
- src/Dhall/Syntax/Instances/Bifunctor.hs +44/−0
- src/Dhall/Syntax/Instances/Data.hs +28/−0
- src/Dhall/Syntax/Instances/Eq.hs +67/−0
- src/Dhall/Syntax/Instances/Foldable.hs +20/−0
- src/Dhall/Syntax/Instances/Functor.hs +37/−0
- src/Dhall/Syntax/Instances/Lift.hs +42/−0
- src/Dhall/Syntax/Instances/Monad.hs +36/−0
- src/Dhall/Syntax/Instances/NFData.hs +35/−0
- src/Dhall/Syntax/Instances/Ord.hs +45/−0
- src/Dhall/Syntax/Instances/Pretty.hs +135/−0
- src/Dhall/Syntax/Instances/Pretty.hs-boot +8/−0
- src/Dhall/Syntax/Instances/Show.hs +36/−0
- src/Dhall/Syntax/Instances/Traversable.hs +22/−0
- src/Dhall/Syntax/MultiLet.hs +62/−0
- src/Dhall/Syntax/Operations.hs +394/−0
- src/Dhall/Syntax/Operations.hs-boot +5/−0
- src/Dhall/Syntax/RecordField.hs +93/−0
- src/Dhall/Syntax/Types.hs +55/−0
- src/Dhall/Syntax/Types.hs-boot +14/−0
- src/Dhall/Syntax/Var.hs +47/−0
- src/Dhall/TH.hs +349/−120
- src/Dhall/Tutorial.hs +32/−30
- src/Dhall/TypeCheck.hs +436/−388
- src/Dhall/URL.hs +2/−4
- src/Dhall/Util.hs +120/−33
- tests/Dhall/Test/Dhall.hs +26/−19
- tests/Dhall/Test/Diff.hs +11/−13
- tests/Dhall/Test/DirectoryTree.hs +149/−0
- tests/Dhall/Test/Format.hs +11/−12
- tests/Dhall/Test/Freeze.hs +18/−9
- tests/Dhall/Test/Import.hs +147/−45
- tests/Dhall/Test/Lint.hs +11/−13
- tests/Dhall/Test/Main.hs +10/−1
- tests/Dhall/Test/Normalization.hs +25/−16
- tests/Dhall/Test/Package.hs +270/−0
- tests/Dhall/Test/Parser.hs +8/−7
- tests/Dhall/Test/QuickCheck.hs +45/−24
- tests/Dhall/Test/Regression.hs +37/−7
- tests/Dhall/Test/Schemas.hs +11/−13
- tests/Dhall/Test/SemanticHash.hs +2/−4
- tests/Dhall/Test/Substitution.hs +1/−1
- tests/Dhall/Test/TH.hs +149/−2
- tests/Dhall/Test/Tags.hs +8/−7
- tests/Dhall/Test/TypeInference.hs +9/−7
- tests/Dhall/Test/Util.hs +156/−52
- tests/format/ipfsB.dhall +2/−1
- tests/format/issue1400-2B.dhall +2/−1
- tests/format/issue2078A.dhall +1/−0
- tests/format/issue2078B.dhall +3/−0
- tests/format/issue2601A.dhall +11/−0
- tests/format/issue2601B.dhall +11/−0
- tests/format/letAnnotatedShortA.dhall +1/−0
- tests/format/letAnnotatedShortB.dhall +5/−0
- tests/format/negativeTimeZoneA.dhall +1/−0
- tests/format/negativeTimeZoneB.dhall +1/−0
- tests/format/numericLiteralsA.dhall +1/−1
- tests/format/numericLiteralsB.dhall +1/−1
- tests/format/parenthesizeUsingA.dhall +6/−0
- tests/format/parenthesizeUsingB.dhall +6/−0
- tests/format/preserveShebangA.dhall +2/−0
- tests/format/preserveShebangB.dhall +2/−0
- tests/format/sha256PrintingB.dhall +2/−1
- tests/format/timePrecisionA.dhall +3/−0
- tests/format/timePrecisionB.dhall +3/−0
- tests/format/withQuestionA.dhall +1/−0
- tests/format/withQuestionB.dhall +1/−0
- tests/freeze/True.dhall +0/−1
- tests/freeze/cached/True.dhall +1/−0
- tests/freeze/cached/cachedA.dhall +2/−0
- tests/freeze/cached/cachedB.dhall +3/−0
- tests/freeze/cached/idempotentA.dhall +5/−0
- tests/freeze/cached/idempotentB.dhall +3/−0
- tests/freeze/cached/incorrectHashA.dhall +1/−0
- tests/freeze/cached/incorrectHashB.dhall +3/−0
- tests/freeze/cached/protectedA.dhall +1/−0
- tests/freeze/cached/protectedB.dhall +3/−0
- tests/freeze/cached/unprotectedA.dhall +1/−0
- tests/freeze/cached/unprotectedB.dhall +3/−0
- tests/freeze/cachedA.dhall +0/−2
- tests/freeze/cachedB.dhall +0/−2
- tests/freeze/incorrectHashA.dhall +0/−1
- tests/freeze/incorrectHashB.dhall +0/−2
- tests/freeze/protectedA.dhall +0/−1
- tests/freeze/protectedB.dhall +0/−2
- tests/freeze/secure/True.dhall +1/−0
- tests/freeze/secure/cachedA.dhall +2/−0
- tests/freeze/secure/cachedB.dhall +2/−0
- tests/freeze/secure/incorrectHashA.dhall +1/−0
- tests/freeze/secure/incorrectHashB.dhall +2/−0
- tests/freeze/secure/protectedA.dhall +1/−0
- tests/freeze/secure/protectedB.dhall +2/−0
- tests/freeze/secure/unprotectedA.dhall +1/−0
- tests/freeze/secure/unprotectedB.dhall +2/−0
- tests/freeze/unprotectedA.dhall +0/−1
- tests/freeze/unprotectedB.dhall +0/−2
- tests/package/dir/package.dhall +0/−0
- tests/package/dir/subdirectory1/test.dhall +0/−0
- tests/package/dir/subdirectory2/wrong-extension.txt +0/−0
- tests/package/dir/test.dhall +0/−0
- tests/package/dir/wrong-extension.txt +0/−0
- tests/package/empty/wrong-extension.txt +0/−0
- tests/package/other/package.dhall +0/−0
- tests/package/package.dhall +0/−0
- tests/package/test.dhall +0/−0
- tests/package/test/test.dhall +0/−0
- tests/regression/issue2088.dhall +1/−0
- tests/th/HigherKindSingle.dhall +1/−0
- tests/th/HigherKindUnion.dhall +1/−0
- tests/th/Time.dhall +1/−0
- tests/to-directory-tree/fixpoint-allow-path-separators.dhall +25/−0
- tests/to-directory-tree/fixpoint-empty.dhall +3/−0
- tests/to-directory-tree/fixpoint-helper.dhall +30/−0
- tests/to-directory-tree/fixpoint-permissions.dhall +24/−0
- tests/to-directory-tree/fixpoint-simple.dhall +25/−0
- tests/to-directory-tree/fixpoint-usergroup.dhall +25/−0
- tests/to-directory-tree/type.dhall +36/−0
@@ -1,3 +1,279 @@+1.42.3++* [Fix the typechecking rule for `Optional` + `with`](https://github.com/dhall-lang/dhall-haskell/pull/2650)+* [Add `*WithIndex` instances for `Map`](https://github.com/dhall-lang/dhall-haskell/pull/2633)+* [`dhall package`: Add support for automatic sub-packags](https://github.com/dhall-lang/dhall-haskell/pull/2639)+* [`dhall to-directory-tree`: Add `binary-file` support](https://github.com/dhall-lang/dhall-haskell/pull/2641)+* [Support GHC 9.12.1](https://github.com/dhall-lang/dhall-haskell/pull/2649)+* [`dhall to-directory-tree`: create parents of files when using fixpoint representation](https://github.com/dhall-lang/dhall-haskell/pull/2653)++1.42.2++* [Supports standard version 23.1.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.1.0)+ * [Allow `Natural` and `Integer` literals in binary notation](https://github.com/dhall-lang/dhall-haskell/pull/2540)+* Fix macOS build [[#2561](https://github.com/dhall-lang/dhall-haskell/pull/2561)] / [[#2586](https://github.com/dhall-lang/dhall-haskell/pull/2586)]+* [`dhall to-directory-tree`: Fix support for empty `Map`s](https://github.com/dhall-lang/dhall-haskell/pull/2609)+* [`Dhall.TH`: Improve recompilation checking](https://github.com/dhall-lang/dhall-haskell/pull/2620)+ * `Dhall.TH` utilities now use `addDependentFile` internally so that GHC will recompile if any Dhall dependencies change+* Performance improvements+ * Optimize `Natural/fold`: [[#2585](https://github.com/dhall-lang/dhall-haskell/pull/2585)] / [[#2596](https://github.com/dhall-lang/dhall-haskell/pull/2596)]+ * [Improve `Dhall.Map.traverseWithKey` performance](https://github.com/dhall-lang/dhall-haskell/pull/2589)+ * The fold will now short-circuit if it reaches a fixed point+ * [#2611](https://github.com/dhall-lang/dhall-haskell/pull/2611)+* Fixes and improvements to test suite+ * [#2593](https://github.com/dhall-lang/dhall-haskell/pull/2593)+* Fixes and improvements to haddocks+ * [#2546](https://github.com/dhall-lang/dhall-haskell/pull/2546)+* Fixes and improvements to code formatting+ * [#2608](https://github.com/dhall-lang/dhall-haskell/pull/2608)++1.42.1++* Add several new entrypoints to `Dhall` module [[#2534](https://github.com/dhall-lang/dhall-haskell/pull/2534)] / [[#2544](https://github.com/dhall-lang/dhall-haskell/pull/2544)]+* Build against latest versions of:+ * [`ansi-terminal`](https://github.com/dhall-lang/dhall-haskell/pull/2521)+ * [`optparse-applicative`](https://github.com/dhall-lang/dhall-haskell/pull/2543)+ * [`optparse-generic`](https://github.com/dhall-lang/dhall-haskell/pull/2519)+ * [`lens`](https://github.com/dhall-lang/dhall-haskell/pull/2539)+ * `template-haskell` [[#2532](https://github.com/dhall-lang/dhall-haskell/pull/2532)] / [[#2542](https://github.com/dhall-lang/dhall-haskell/pull/2542)]+ * [`unix-compat`](https://github.com/dhall-lang/dhall-haskell/pull/2532)+1.42.0++* [Supports standard version 23.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v23.0.0)+ * [BREAKING CHANGE TO THE API AND LANGUAGE: Language support for `Bytes` literals](https://github.com/dhall-lang/dhall-haskell/pull/2499)+ * This is a breaking change to the API due to adding new `Bytes` and `BytesLiteral` constructors to the `Expr` type+ * This is a breaking change to the language now that `Bytes` is a reserved identifier+ * [BREAKING CHANGE TO THE API AND LANGUAGE: New `{Date,Time,TimeZone}/show` builtins](https://github.com/dhall-lang/dhall-haskell/pull/2493)+ * This is a breaking change to the API due to adding new `{Date,Time,TimeZone}Show` constructors to the `Expr` type+ * This is a breaking change to the language now that `{Date,Time,TimeZone}/show` are not reserved identifiers+* [BREAKING CHANGE: `dhall lint` no longer sorts `let` bindings](https://github.com/dhall-lang/dhall-haskell/pull/2503)+ * This had to be removed because the old behavior was not always correct+ * The old behavior would sometimes change the behavior of a Dhall program or break the program+ * Out of an abundance of caution we're disabling the feature until it can be properly fixed (which is't trivial)+* [BUG FIX: Fix pretty-printing of `Time` literals](https://github.com/dhall-lang/dhall-haskell/pull/2466)+ * The pretty-printer was stripping leading zeros from the fractional component+ of seconds+* [BUG FIX: Fix custom normalizers to work for things other than functions](https://github.com/dhall-lang/dhall-haskell/pull/2464)+ * Before this change you could extend the language with custom functions, but+ not custom values (e.g. `foo = 1`)+* [BUG FIX: Don't URL encode path components](https://github.com/dhall-lang/dhall-haskell/pull/2505)+ * The pretty-printer was URL-encoding path components, which is not correct (according to the standard)+ * URL path components are supposed to be already URL-encoded by the user and left undisturbed by the interpreter (which is now what it correctly does)+* New `dhall package` command: [#2478](https://github.com/dhall-lang/dhall-haskell/pull/2487), [#2508](https://github.com/dhall-lang/dhall-haskell/pull/2508)+ * This command makes it easier to turn a directory full of Dhall expressions+ into a dhall package (e.g. `package.dhall`)+* [Improved `dhall to-directory-tree` subcommand](https://github.com/dhall-lang/dhall-haskell/pull/2437)+ * The `dhall to-directory-tree` subcommand now optionally supports specifying+ metadata for generated paths+ * For a worked example, see: https://github.com/dhall-lang/dhall-haskell/blob/main/dhall/examples/to-directory-tree.dhall+* `dhall freeze --cache --all` is now idempotent: [#2486](https://github.com/dhall-lang/dhall-haskell/pull/2486), [#2500](https://github.com/dhall-lang/dhall-haskell/pull/2500)+ * Before this change a second run would fail due to attempting to resolve+ the `missing` import it would generate+* [New Template Haskell options for adding strictness annotations to generated Haskell types](https://github.com/dhall-lang/dhall-haskell/pull/2504)+* [Template Haskell can now generate higher-kinded Haskell types from higher-kinded Dhall types](https://github.com/dhall-lang/dhall-haskell/pull/2506)+* [New `Dhall.Freeze` utilities for working with custom evaluators](https://github.com/dhall-lang/dhall-haskell/pull/2478)+* [Add `Data` instances for `Import` and various other types](https://github.com/dhall-lang/dhall-haskell/pull/2462)+* [Add `Eq` instances for `InvalidDecoder` and `ExtractError`](https://github.com/dhall-lang/dhall-haskell/pull/2482)++1.41.2++* [BUG FIX: Fix `:hash` REPL command to α-normalize input](https://github.com/dhall-lang/dhall-haskell/pull/2420)+* [Add `{From,To}Dhall` instances for `DayOfWeek`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* [Add `{From,To}Dhall` instances for `ShortText`](https://github.com/dhall-lang/dhall-haskell/pull/2413)+* Performance improvements+ * [#2423](https://github.com/dhall-lang/dhall-haskell/pull/2423)+* Fixes and improvements to haddocks+ * [#2396](https://github.com/dhall-lang/dhall-haskell/pull/2396)+* Fixes and improvements to test suite+ * [#2342](https://github.com/dhall-lang/dhall-haskell/pull/2382)+ * [#2394](https://github.com/dhall-lang/dhall-haskell/pull/2394)+* Build against newer dependencies+ * [`pretty-simple-4.1`](https://github.com/dhall-lang/dhall-haskell/pull/2408)+ * [`aeson-2.1`](https://github.com/dhall-lang/dhall-haskell/pull/2424)+ * [`vector-0.13`](https://github.com/dhall-lang/dhall-haskell/pull/2427)+ * [`turtle-1.6`](https://github.com/dhall-lang/dhall-haskell/pull/2431)++1.41.1++* [BUG FIX: Don't escape `?` path component when pretty-printing `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2392)++1.41.0++* [Support standard version 22.0.0](https://github.com/dhall-lang/dhall-lang/releases/tag/v22.0.0)+ * [Allow `with` expressions to update `Optional` values using `?`](https://github.com/dhall-lang/dhall-haskell/pull/2386)+ * [Add `showConstructor` keyword](https://github.com/dhall-lang/dhall-haskell/pull/2384)+* [BUG FIX: Fix pretty-printing of time zones](https://github.com/dhall-lang/dhall-haskell/pull/2379)+ * Timezones with a negative offset were previously being rendered with two+ leading minus signs instead of one+* [BUG FIX: `dhall freeze --cache` to work with standard version 21.0.0](https://github.com/dhall-lang/dhall-haskell/pull/2350)+ * `dhall freeze` will now use `missing sha256:…` for the first import so that+ the latter import will be tried if the import is not in cache+ * The old behavior is incompatible with standard version 21.0.0 because the+ new behavior of the `?` operator doesn't fall back on hash mismatches+* [BUG FIX: Allow `with` expression to update a field named `Some`](https://github.com/dhall-lang/dhall-haskell/pull/2354)+ * This fixes a discrepancy between the Haskell implementation and the standard+ where the Haskell implementation would not permit+ `{ Some = 0 } with Some = 1 `+* [Fix `dhall {format,lint,freeze}` to preserve leading shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2364)+* [Add `FromDhall` instances for `Int{8,16,32,64}`](https://github.com/dhall-lang/dhall-haskell/pull/2349)++1.40.2++* [Supports standard version 21.1.0](https://github.com/dhall-lang/dhall-haskell/pull/2236)+ * [The interpreter now supports customizing headers using a `headers.dhall`+ configuration file](https://github.com/dhall-lang/dhall-haskell/pull/2236)+ * [Generalize grammar for certain annotations](https://github.com/dhall-lang/dhall-haskell/pull/2320)+ * [Add support for a trailing line comment without a newline](https://github.com/dhall-lang/dhall-haskell/pull/2309)+* [BUG FIX: `dhall repl` no longer ignores type annotations on `:let` commands](https://github.com/dhall-lang/dhall-haskell/pull/2297)+ * Before this fix, `:let x : T = 3` would ignore the `: T` type annotation+* [BUG FIX: Don't accept a bar after an empty union](https://github.com/dhall-lang/dhall-haskell/pull/2338)+ * Before this fix, the interpreter would accept something like `<>|`, which+ is not valid according to the standard grammar+* New `FromDhall`/`ToDhall` instances for `Day`/`TimeOfDay`/`TimeZone` [#2294](https://github.com/dhall-lang/dhall-haskell/pull/2294) [#2300](https://github.com/dhall-lang/dhall-haskell/pull/2300)+ * These types correspond to the recent temporal literals added to the+ language+* [New `subExpressionsWith` `Traversal`](https://github.com/dhall-lang/dhall-haskell/pull/2302)+* [Add Template Haskell support for modifying field names in generated Haskell+ types](https://github.com/dhall-lang/dhall-haskell/pull/2285)+ * This adds a new `makeHaskellTypesWith` utility with takes a+ `GenerateOptions` function argument for customizing the code-generation+ logic+ * This comes in handy when Dhall fields have names are reserved keywords in+ Haskell code. You can now transform the Haskell field names to avoid+ collisions+* [Support GHC 9.2](https://github.com/dhall-lang/dhall-haskell/pull/2328)+* Fixes and improvements to documentation+ * [#2290](https://github.com/dhall-lang/dhall-haskell/pull/2290)+* Fixes and improvements to error messages+ * [#2303](https://github.com/dhall-lang/dhall-haskell/pull/2303)++1.40.1++* [BUG FIX: Fix equivalence check for `Date` / `Time` / `TimeZone`](https://github.com/dhall-lang/dhall-haskell/pull/2291)+ * This fixes a serious bug in the recently introduced support for temporal+ literals where they would fail to type-check when given a correct type+ annotation or when they were checked against an existing type+ * For example, `00:00:00 : Time` was failing to type-check++1.40.0++* [Almost supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+ * The main thing that is missing is support for the `headers.dhall` file+ * [BREAKING CHANGE TO THE LANGUAGE: Add support for `Date` / `Time` / `TimeZone` ](https://github.com/dhall-lang/dhall-haskell/pull/2247)+ * This is a breaking change because `Date`, `Time`, and `TimeZone` are+ now reserved identifiers+ * [Improved fallback behavior for `?`](https://github.com/dhall-lang/dhall-haskell/pull/2203)+* [BREAKING CHANGE TO THE LANGUAGE: Require whitespace before `with`](https://github.com/dhall-lang/dhall-haskell/pull/2213)+ * The parser now requires whitespace before the `with` keyword, which brings+ the Haskell implementation into closer compliance with the standard+ * In practice this is a technically breaking change which will not affect+ most programs+* [New `FromDhall` instances for `Predicate`, `Equivalence`, and `Op`](https://github.com/dhall-lang/dhall-haskell/pull/2278)+* [`dhall lint` will now sort `let` bindings with imports](https://github.com/dhall-lang/dhall-haskell/pull/2205)+ * `dhall lint` now reorders `let` bindings to move imports to the top so+ long as doing so does not change the behavior of the program+* Fixes and improvements to code formatting+ * [#2280](https://github.com/dhall-lang/dhall-haskell/pull/2280)+* Fixes and improvements to error messages+ * [#2244](https://github.com/dhall-lang/dhall-haskell/pull/2244)+ * [#2238](https://github.com/dhall-lang/dhall-haskell/pull/2238)++1.39.0++* [Supports version 20.2.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.2.0)+ * [Add support for Unix shebangs](https://github.com/dhall-lang/dhall-haskell/pull/2175)+* [BREAKING CHANGE TO THE API: `dhall {format,freeze,lint}` now accept multiple+ files](https://github.com/dhall-lang/dhall-haskell/pull/2169)+ * The `--inplace` flag is no longer necessary and you can now specify+ multiple files to update in place on the command line, like+ `dhall format foo.dhall bar.dhall`+ * The `--inplace` flag is still accepted, but does nothing, and will emit a+ warning+ * This is a breaking change to the API for formatting/freezing/linting files+ because now you can specify multiple inputs instead of one input+* [BREAKING CHANGE: Pre-6.0.0 hashes are no longer supported](https://github.com/dhall-lang/dhall-haskell/pull/2190)+ * The interpreter no longer provides backwards compatibility for integrity+ checks computed before standard version 6.0.0+ * This is a breaking change to the API of the `Dhall.Binary` module, where+ certain utilities are no longer parameterized on a `StandardVersion`+ * This is also a breaking change to any Dhall code that depended on these+ really old integrity checks+* [BUG FIX: Formatting `≡` now correctly preserves the original character set](https://github.com/dhall-lang/dhall-haskell/pull/2176)+* [BUG FIX: Don't panic on `Text/replace ""`](https://github.com/dhall-lang/dhall-haskell/pull/2184)+* [Quasiquotation support for Dhall](https://github.com/dhall-lang/dhall-haskell/pull/2198)+ * You can now convert a Dhall expression to the corresponding syntax tree+ using a quasiquoter like this: `[dhall| \x -> x + 2 ]`+* [New `Dhall.Marshal.{Encode,Decode}` modules](https://github.com/dhall-lang/dhall-haskell/pull/2193)+ * These modules split up the `Dhall` module into two smaller modules for+ encoding and decoding logic, respectively+ * The `Dhall` module still re-exports the same functionality as before, so+ this is not a breaking change+* [Support GHC 9.0.1](https://github.com/dhall-lang/dhall-haskell/pull/2154)+* Fixes and improvements to code formatting+ * [Improve pretty-printing of `sha256`](https://github.com/dhall-lang/dhall-haskell/pull/2189)++1.38.1++* [Add `INLINABLE` annotations in more places](https://github.com/dhall-lang/dhall-haskell/pull/2164)+ * This may improve performance by enabling more specializations+* [Fix `hashable`-related test failures](https://github.com/dhall-lang/dhall-haskell/pull/2152)+* [Fix support for GHC 8.4.4](https://github.com/dhall-lang/dhall-haskell/pull/2143)+ * … by using `GeneralizedNewtypeDeriving` (with a `z`)+* [Allow doctest-0.18](https://github.com/dhall-lang/dhall-haskell/pull/2148)+* [Allow bytestring-0.11](https://github.com/dhall-lang/dhall-haskell/pull/2144)++1.38.0++* [BREAKING CHANGE: Detect preferred character set from input](https://github.com/dhall-lang/dhall-haskell/pull/2108)+ * `dhall format` will now preserve the character set of the formatted file+ by default. In other words, if the file uses ASCII punctuation then+ `dhall format` will format the file using ASCII punctuation.+ * If the file contains both ASCII and Unicode punctuation it will prefer+ Unicode by default+ * This is a breaking change because the `Lam` / `Pi` / `Combine` /+ `CombineTypes`, and `Prefer` constructors now take an additional argument+ to record which character set was used+* [BUG FIX: Fix CORS compliance check](https://github.com/dhall-lang/dhall-haskell/pull/2121)+ * Previous versions were not correctly enforcing CORS compliance+ * This implies that some imports that would have worked previously by+ accident will now fail; specifically: an import from one domain+ transitively importing something from another domain that has not opted+ into CORS+* [Add `ToDhall (Fix f)` instance](https://github.com/dhall-lang/dhall-haskell/pull/2122)+* Fixes and improvements to error messages+ * [#2130](https://github.com/dhall-lang/dhall-haskell/pull/2130)++1.37.1++* [Fix performance regression for `with` expressions](https://github.com/dhall-lang/dhall-haskell/pull/2112)++1.37.0++* [Supports version 20.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v20.0.0)+ * [Implement revised `Text/replace` β-normalization](https://github.com/dhall-lang/dhall-haskell/pull/2072)+ * [Allow `Text/replace ""` to support an abstract haystack](https://github.com/dhall-lang/dhall-haskell/pull/2084)+ * [Support `if` expressions returning a type or kind](https://github.com/dhall-lang/dhall-haskell/pull/2080)+* BREAKING CHANGE TO THE API: [Improve error message for duplicate projection label](https://github.com/dhall-lang/dhall-haskell/pull/2097)+ * This also makes the implementation more standards-compliant, by treating+ a duplicate label as a type error instead of a parse error+ * This is a breaking change since the `Project` constructor now stores a+ `[Text]` instead of `Set Text`+* [Add `--cache` flag to `dhall hash`](https://github.com/dhall-lang/dhall-haskell/pull/2093)+ * This flag adds the hashed expression to the cache when enabled+* [Deprecate `Inject` / `Interpret`](https://github.com/dhall-lang/dhall-haskell/pull/2099)+ * You should instead use `ToDhall` / `FromDhall`, respectively+* Fixes and improvements to the haddocks:+ * [#2098](https://github.com/dhall-lang/dhall-haskell/pull/2098)+ * [#2100](https://github.com/dhall-lang/dhall-haskell/pull/2100)+* Fixes and improvements to error messages:+ * [#2082](https://github.com/dhall-lang/dhall-haskell/pull/2082)+ * [#2095](https://github.com/dhall-lang/dhall-haskell/pull/2095)+* Fixes and improvements to the parser:+ * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2089)+* Fixes and improvements to the pretty printer:+ * [#2083](https://github.com/dhall-lang/dhall-haskell/pull/2083)+ * [#2101](https://github.com/dhall-lang/dhall-haskell/pull/2101)+ 1.36.0 * [Supports version 19.0.0 of the standard](https://github.com/dhall-lang/dhall-lang/releases/tag/v19.0.0)@@ -114,6 +390,12 @@ * If you really don't want to handle the new error-related wrapper, you can get the old behavior using a partial pattern match (which will be partial, still an improvement over the previous behavior, which was hanging)+* BREAKING CHANGE: [Records can no longer contain attributes named after language keywords](https://github.com/dhall-lang/dhall-haskell/pull/1801)+ * This is a bugfix, because the language standard disallows using+ keywords as record labels. However, some users were relying on+ this bug.+ * If you need to use a keyword as a record label, enclose it in backticks:+ ``{ `assert` = 1 }``. * [Fix invalid cache entries](https://github.com/dhall-lang/dhall-haskell/pull/1793) * The interpreter will now correct cached expressions that are incorrect and warn you when this happens@@ -850,7 +1132,7 @@ * This allows the `dhall` package to be built without using `TemplateHaskell` * See: https://github.com/dhall-lang/dhall-haskell/pull/928-* Increase lines of context for error messages +* Increase lines of context for error messages * Error messages now provide at least 20 lines of context instead of 3 before truncating large expressions * See: https://github.com/dhall-lang/dhall-haskell/pull/916@@ -1233,7 +1515,7 @@ expression * You can pin the new hashes by supplying the `--protocol-version 1.0` option on the command line until you need support for newer language- features + features * This also includes a breaking change to `ImportType` in the API * BREAKING CHANGE TO THE LANGUAGE: Disallow combining records of terms and types
@@ -1,4 +1,4 @@-Copyright (c) 2020 Gabriel Gonzalez+Copyright (c) 2020 Gabriella Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without
@@ -1,14 +1,13 @@ {-# LANGUAGE OverloadedStrings #-} module Main (main) where -import Data.Void (Void)-import Gauge (defaultMain)+import Data.Void (Void)+import Test.Tasty.Bench import qualified Data.Sequence as Seq import qualified Dhall.Core as Core import qualified Dhall.Import as Import import qualified Dhall.TypeCheck as TypeCheck-import qualified Gauge dhallPreludeImport :: Core.Import dhallPreludeImport = Core.Import@@ -22,8 +21,8 @@ } } -issue412 :: Core.Expr s Void -> Gauge.Benchmarkable-issue412 prelude = Gauge.whnf TypeCheck.typeOf expr+issue412 :: Core.Expr s Void -> Benchmarkable+issue412 prelude = whnf TypeCheck.typeOf expr where expr = Core.Let (Core.Binding Nothing "prelude" Nothing Nothing Nothing prelude)@@ -34,8 +33,8 @@ little = Core.makeFieldSelection "little" foo = Core.makeFieldSelection "Foo" -unionPerformance :: Core.Expr s Void -> Gauge.Benchmarkable-unionPerformance prelude = Gauge.whnf TypeCheck.typeOf expr+unionPerformance :: Core.Expr s Void -> Benchmarkable+unionPerformance prelude = whnf TypeCheck.typeOf expr where expr = Core.Let@@ -54,7 +53,7 @@ Nothing (prelude `Core.Field` types `Core.Field` big) )- (Core.Prefer Core.PreferFromSource "big" "big")+ (Core.Prefer mempty Core.PreferFromSource "big" "big") ) ) "x"@@ -64,10 +63,10 @@ main :: IO () main = defaultMain- [ Gauge.env prelude $ \p ->- Gauge.bgroup "Prelude"- [ Gauge.bench "issue 412" (issue412 p)- , Gauge.bench "union performance" (unionPerformance p)+ [ env prelude $ \p ->+ bgroup "Prelude"+ [ bench "issue 412" (issue412 p)+ , bench "union performance" (unionPerformance p) ] ] where prelude = Import.load (Core.Embed dhallPreludeImport)
file too large to diff
@@ -1,63 +0,0 @@-λ ( xs : List { cores : Natural , host : Text , key : Text , mandatoryFeatures :-List Text , platforms : List < AArch64_Linux : {} | ARMv5tel_Linux : {} |-ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} |-PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD :-{} | X86_64_Linux : {} | X86_64_Solaris : {} > , speedFactor : Natural ,-supportedFeatures : List Text , user : Optional Text } )→ List/fold { cores :-Natural , host : Text , key : Text , mandatoryFeatures : List Text , platforms :-List < AArch64_Linux : {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} |-I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} | PowerPC_Linux : {} |-X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux :-{} | X86_64_Solaris : {} > , speedFactor : Natural , supportedFeatures : List-Text , user : Optional Text } xs Text ( λ ( x : { cores : Natural , host : Text-, key : Text , mandatoryFeatures : List Text , platforms : List < AArch64_Linux-: {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux :-{} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} |-X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris :-{} > , speedFactor : Natural , supportedFeatures : List Text , user : Optional-Text } ) → λ(y : Text) →-merge { None = x.host, Some = λ(user : Text) → "${user}@${x.host}" } x.user-++ " " ++ ( merge { Empty = λ(_ : {}) → "",-NonEmpty = λ(result : Text) → result } ( List/fold < AArch64_Linux : {} |-ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |-MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :-{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > x.platforms-< Empty : {} | NonEmpty : Text > ( λ ( element : < AArch64_Linux : {} |-ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |-MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :-{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > ) →-λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <-NonEmpty : Text | Empty : {} >.NonEmpty ( merge { AArch64_Linux = λ(_ : {}) →-"aarch64-linux" , ARMv5tel_Linux = λ(_ : {}) → "armv5tel-linux" , ARMv7l_Linux =-λ(_ : {}) → "armv7l-linux" , I686_Cygwin = λ(_ : {}) → "i686-cygwin" ,-I686_Linux = λ(_ : {}) → "i686-linux" , MIPS64el_Linux = λ(_ : {}) →-"mips64el-linux" , PowerPC_Linux = λ(_ : {}) → "powerpc-linux" , X86_64_Cygwin =-λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin = λ(_ : {}) → "x86_64-darwin" ,-X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" , X86_64_Linux = λ(_ : {}) →-"x86_64-linux" , X86_64_Solaris = λ(_ : {}) → "x86_64-solaris" } element ) ,-NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty ( (-merge { AArch64_Linux = λ(_ : {}) → "aarch64-linux" , ARMv5tel_Linux = λ(_ : {})-→ "armv5tel-linux" , ARMv7l_Linux = λ(_ : {}) → "armv7l-linux" , I686_Cygwin =-λ(_ : {}) → "i686-cygwin" , I686_Linux = λ(_ : {}) → "i686-linux" ,-MIPS64el_Linux = λ(_ : {}) → "mips64el-linux" , PowerPC_Linux = λ(_ : {}) →-"powerpc-linux" , X86_64_Cygwin = λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin =-λ(_ : {}) → "x86_64-darwin" , X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" ,-X86_64_Linux = λ(_ : {}) → "x86_64-linux" , X86_64_Solaris = λ(_ : {}) →-"x86_64-solaris" } element ) ++ "," ++ result ) } status : < Empty : {} |-NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=}) ) : Text ) ++-" " ++ x.key ++ " " ++ Integer/show (Natural/toInteger x.cores) ++ " " ++-Integer/show (Natural/toInteger x.speedFactor) ++ " " ++ ( merge { Empty = λ(_ :-{}) → "", NonEmpty = λ(result : Text) → result } ( List/fold Text-x.supportedFeatures < Empty : {} | NonEmpty : Text > ( λ(element : Text) →-λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <-NonEmpty : Text | Empty : {} >.NonEmpty element , NonEmpty = λ(result : Text) →-< NonEmpty : Text | Empty : {} >.NonEmpty (element ++ "," ++ result) } status :-< Empty : {} | NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=})-) : Text ) ++ " " ++ ( merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result :-Text) → result } ( List/fold Text x.mandatoryFeatures < Empty : {} | NonEmpty :-Text > ( λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) →-merge { Empty = λ(_ : {}) → < NonEmpty : Text | Empty : {} >.NonEmpty element ,-NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty-(element ++ "," ++ result) } status : < Empty : {} | NonEmpty : Text > ) (<-Empty : {} | NonEmpty : Text->.Empty {=}) ) : Text ) ++ "\n" ++ y ) ""
@@ -1,22 +0,0 @@--let Nat = ∀(N : Type) → (N → N) → N → N-let n2 = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s z)-let n5 = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s (s (s (s z))))--let mul =- λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N (b N s) z--let add =- λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N s (b N s z)--let n10 = mul n2 n5-let n100 = mul n10 n10-let n1k = mul n10 n100-let n10k = mul n100 n100-let n100k = mul n10 n10k-let n1M = mul n10k n100-let n5M = mul n1M n5-let n10M = mul n1M n10-let n20M = mul n10M n2--in n1M Natural (λ (x:Natural) → x + 1) 0
@@ -1,18 +0,0 @@--let compose- : ∀(a : Type) → ∀(b : Type) → ∀(c : Type) → (a → b) → (b → c) → a → c- = λ(A : Type)- → λ(B : Type)- → λ(C : Type)- → λ(f : A → B)- → λ(g : B → C)- → λ(x : A)- → g (f x)--let composeN : ∀ (a : Type) → Natural → (a → a) → a → a- = λ (a : Type)- → λ (n : Natural)- → λ (f : a → a)- → Natural/fold n (a → a) (compose a a a f) (λ (x : a) → x)--in composeN Natural 100000 (λ (x : Natural) → x + 1) 0
@@ -1,75 +0,0 @@--let iterate- = λ(n : Natural)- → λ(a : Type)- → λ(f : a → a)- → λ(x : a)- → List/build- a- ( λ(list : Type)- → λ(cons : a → list → list)- → List/fold- { index : Natural, value : {} }- ( List/indexed- {}- ( List/build- {}- ( λ(list : Type)- → λ(cons : {} → list → list)- → Natural/fold n list (cons {=})- )- )- )- list- ( λ(y : { index : Natural, value : {} })- → cons (Natural/fold y.index a f x)- )- )--let countTo =- λ (x : Natural)- → iterate x Natural (λ (x : Natural) → x + 1) 0--let sum =- λ (xs : List Natural)- → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0---let map- : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b- = λ(a : Type)- → λ(b : Type)- → λ(f : a → b)- → λ(xs : List a)- → List/build- b- ( λ(list : Type)- → λ(cons : b → list → list)- → List/fold a xs list (λ(x : a) → cons (f x))- )--let any- : ∀(a : Type) → (a → Bool) → List a → Bool- = λ(a : Type)- → λ(f : a → Bool)- → λ(xs : List a)- → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False--let filter- : ∀(a : Type) → (a → Bool) → List a → List a- = λ(a : Type)- → λ(f : a → Bool)- → λ(xs : List a)- → List/build- a- ( λ(list : Type)- → λ(cons : a → list → list)- → List/fold- a- xs- list- (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)- )--in sum (filter Natural Natural/even- (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
@@ -1,45 +0,0 @@--let iterate =- λ(n : Natural)- → λ(a : Type)- → λ(f : a → a)- → λ(x : a)- → (Natural/fold n- (a → List a → {fst:a, snd:List a})- (λ (hyp : a → List a → {fst:a, snd:List a}) →- λ (x : a) → λ (xs : List a)- → let tup = hyp x xs- in {fst = f (tup.fst), snd = tup.snd # [tup.fst]})- (λ (x : a) → λ (xs : List a) → {fst=x, snd=xs})- x ([] : List a)).snd--let countTo =- λ (x : Natural)- → iterate x Natural (λ (x : Natural) → x + 1) 0--let sum =- λ (xs : List Natural)- → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0--let map- = λ(a : Type)- → λ(b : Type)- → λ(f : a → b)- → λ(xs : List a)- → List/fold a xs (List b) (λ (x : a) → λ (xs : List b) → [f x] # xs) ([] : List b)--let any- = λ(a : Type)- → λ(f : a → Bool)- → λ(xs : List a)- → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False--let filter- = λ(a : Type)- → λ(f : a → Bool)- → λ(xs : List a)- → List/fold a xs (List a)- (λ (x : a) → λ (xs : List a) → if f x then [x] # xs else xs) ([] : List a)--in sum (filter Natural Natural/even- (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
@@ -1,54 +1,54 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} module Main where import Control.Exception (throw) import Control.Monad (forM)-import Data.Map (Map, foldrWithKey, singleton, unions)+import Data.Map (Map)+import Data.Text (Text) import Data.Void (Void)-import Gauge (bench, bgroup, defaultMain, env, nf, whnf)--import System.Directory+import Test.Tasty.Bench import qualified Data.ByteString.Lazy-import qualified Data.Text as T-import qualified Data.Text.IO as TIO+import qualified Data.Map as Map+import qualified Data.Text as Text+import qualified Data.Text.IO import qualified Dhall.Binary import qualified Dhall.Core as Dhall import qualified Dhall.Parser as Dhall-import qualified Gauge+import qualified System.Directory as Directory -type PreludeFiles = Map FilePath T.Text+type PreludeFiles = Map FilePath Text loadPreludeFiles :: IO PreludeFiles loadPreludeFiles = loadDirectory "./dhall-lang/Prelude" where loadDirectory :: FilePath -> IO PreludeFiles loadDirectory dir =- withCurrentDirectory dir $ do- files <- getCurrentDirectory >>= listDirectory+ Directory.withCurrentDirectory dir $ do+ files <- Directory.getCurrentDirectory >>= Directory.listDirectory results <- forM files $ \file -> do- file' <- makeAbsolute file- doesExist <- doesFileExist file'+ file' <- Directory.makeAbsolute file+ doesExist <- Directory.doesFileExist file' if doesExist then loadFile file' else loadDirectory file'- pure $ unions results+ pure $ Map.unions results loadFile :: FilePath -> IO PreludeFiles- loadFile path = singleton path <$> TIO.readFile path+ loadFile path = Map.singleton path <$> Data.Text.IO.readFile path -benchParser :: PreludeFiles -> Gauge.Benchmark+benchParser :: PreludeFiles -> Benchmark benchParser = bgroup "exprFromText"- . foldrWithKey (\name expr -> (benchExprFromText name expr :)) []+ . Map.foldrWithKey (\name expr -> (benchExprFromText name expr :)) [] -benchExprFromText :: String -> T.Text -> Gauge.Benchmark-benchExprFromText name expr =+benchExprFromText :: String -> Text -> Benchmark+benchExprFromText name !expr = bench name $ whnf (Dhall.exprFromText "(input)") expr -benchExprFromBytes- :: String -> Data.ByteString.Lazy.ByteString -> Gauge.Benchmark+benchExprFromBytes :: String -> Data.ByteString.Lazy.ByteString -> Benchmark benchExprFromBytes name bs = bench name (nf f bs) where f bytes =@@ -56,8 +56,8 @@ Left exception -> error (show exception) Right expression -> expression :: Dhall.Expr Void Dhall.Import -benchNfExprFromText :: String -> T.Text -> Gauge.Benchmark-benchNfExprFromText name expr =+benchNfExprFromText :: String -> Text -> Benchmark+benchNfExprFromText name !expr = bench name $ nf (either throw id . Dhall.exprFromText "(input)") expr main :: IO ()@@ -71,20 +71,21 @@ ] , env kubernetesExample $ benchExprFromBytes "Kubernetes/Binary"- , benchExprFromText "Long variable names" (T.replicate 1000000 "x")- , benchExprFromText "Large number of function arguments" (T.replicate 10000 "x ")- , benchExprFromText "Long double-quoted strings" ("\"" <> T.replicate 1000000 "x" <> "\"")- , benchExprFromText "Long single-quoted strings" ("''" <> T.replicate 1000000 "x" <> "''")- , benchExprFromText "Whitespace" (T.replicate 1000000 " " <> "x")- , benchExprFromText "Line comment" ("x -- " <> T.replicate 1000000 " ")- , benchExprFromText "Block comment" ("x {- " <> T.replicate 1000000 " " <> "-}")+ , benchExprFromText "Long variable names" (Text.replicate 1000000 "x")+ , benchExprFromText "Large number of function arguments" (Text.replicate 10000 "x ")+ , benchExprFromText "Long double-quoted strings" ("\"" <> Text.replicate 1000000 "x" <> "\"")+ , benchExprFromText "Long single-quoted strings" ("''" <> Text.replicate 1000000 "x" <> "''")+ , benchExprFromText "Whitespace" (Text.replicate 1000000 " " <> "x")+ , benchExprFromText "Line comment" ("x -- " <> Text.replicate 1000000 " ")+ , benchExprFromText "Block comment" ("x {- " <> Text.replicate 1000000 " " <> "-}") , benchExprFromText "Deeply nested parentheses" "((((((((((((((((x))))))))))))))))" , benchParser prelude , env cpkgExample $ benchNfExprFromText "CPkg/Text" ]- where cpkgExample = TIO.readFile "benchmark/examples/cpkg.dhall"- issue108Text = TIO.readFile "benchmark/examples/issue108.dhall"- issue108Bytes = Data.ByteString.Lazy.readFile "benchmark/examples/issue108.dhall.bin"- issues = (,) <$> issue108Text <*> issue108Bytes- kubernetesExample = Data.ByteString.Lazy.readFile "benchmark/examples/kubernetes.dhall.bin"+ where+ cpkgExample = Data.Text.IO.readFile "benchmark/parser/examples/cpkg.dhall"+ issue108Text = Data.Text.IO.readFile "benchmark/parser/examples/issue108.dhall"+ issue108Bytes = Data.ByteString.Lazy.readFile "benchmark/parser/examples/issue108.dhallb"+ issues = (,) <$> issue108Text <*> issue108Bytes+ kubernetesExample = Data.ByteString.Lazy.readFile "benchmark/parser/examples/kubernetes.dhallb"
file too large to diff
@@ -0,0 +1,63 @@+λ ( xs : List { cores : Natural , host : Text , key : Text , mandatoryFeatures :+List Text , platforms : List < AArch64_Linux : {} | ARMv5tel_Linux : {} |+ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} |+PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD :+{} | X86_64_Linux : {} | X86_64_Solaris : {} > , speedFactor : Natural ,+supportedFeatures : List Text , user : Optional Text } )→ List/fold { cores :+Natural , host : Text , key : Text , mandatoryFeatures : List Text , platforms :+List < AArch64_Linux : {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} |+I686_Cygwin : {} | I686_Linux : {} | MIPS64el_Linux : {} | PowerPC_Linux : {} |+X86_64_Cygwin : {} | X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux :+{} | X86_64_Solaris : {} > , speedFactor : Natural , supportedFeatures : List+Text , user : Optional Text } xs Text ( λ ( x : { cores : Natural , host : Text+, key : Text , mandatoryFeatures : List Text , platforms : List < AArch64_Linux+: {} | ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux :+{} | MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} |+X86_64_Darwin : {} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris :+{} > , speedFactor : Natural , supportedFeatures : List Text , user : Optional+Text } ) → λ(y : Text) →+merge { None = x.host, Some = λ(user : Text) → "${user}@${x.host}" } x.user+++ " " ++ ( merge { Empty = λ(_ : {}) → "",+NonEmpty = λ(result : Text) → result } ( List/fold < AArch64_Linux : {} |+ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |+MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :+{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > x.platforms+< Empty : {} | NonEmpty : Text > ( λ ( element : < AArch64_Linux : {} |+ARMv5tel_Linux : {} | ARMv7l_Linux : {} | I686_Cygwin : {} | I686_Linux : {} |+MIPS64el_Linux : {} | PowerPC_Linux : {} | X86_64_Cygwin : {} | X86_64_Darwin :+{} | X86_64_FreeBSD : {} | X86_64_Linux : {} | X86_64_Solaris : {} > ) →+λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <+NonEmpty : Text | Empty : {} >.NonEmpty ( merge { AArch64_Linux = λ(_ : {}) →+"aarch64-linux" , ARMv5tel_Linux = λ(_ : {}) → "armv5tel-linux" , ARMv7l_Linux =+λ(_ : {}) → "armv7l-linux" , I686_Cygwin = λ(_ : {}) → "i686-cygwin" ,+I686_Linux = λ(_ : {}) → "i686-linux" , MIPS64el_Linux = λ(_ : {}) →+"mips64el-linux" , PowerPC_Linux = λ(_ : {}) → "powerpc-linux" , X86_64_Cygwin =+λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin = λ(_ : {}) → "x86_64-darwin" ,+X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" , X86_64_Linux = λ(_ : {}) →+"x86_64-linux" , X86_64_Solaris = λ(_ : {}) → "x86_64-solaris" } element ) ,+NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty ( (+merge { AArch64_Linux = λ(_ : {}) → "aarch64-linux" , ARMv5tel_Linux = λ(_ : {})+→ "armv5tel-linux" , ARMv7l_Linux = λ(_ : {}) → "armv7l-linux" , I686_Cygwin =+λ(_ : {}) → "i686-cygwin" , I686_Linux = λ(_ : {}) → "i686-linux" ,+MIPS64el_Linux = λ(_ : {}) → "mips64el-linux" , PowerPC_Linux = λ(_ : {}) →+"powerpc-linux" , X86_64_Cygwin = λ(_ : {}) → "x86_64-cygwin" , X86_64_Darwin =+λ(_ : {}) → "x86_64-darwin" , X86_64_FreeBSD = λ(_ : {}) → "x86_64-freebsd" ,+X86_64_Linux = λ(_ : {}) → "x86_64-linux" , X86_64_Solaris = λ(_ : {}) →+"x86_64-solaris" } element ) ++ "," ++ result ) } status : < Empty : {} |+NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=}) ) : Text ) +++" " ++ x.key ++ " " ++ Integer/show (Natural/toInteger x.cores) ++ " " +++Integer/show (Natural/toInteger x.speedFactor) ++ " " ++ ( merge { Empty = λ(_ :+{}) → "", NonEmpty = λ(result : Text) → result } ( List/fold Text+x.supportedFeatures < Empty : {} | NonEmpty : Text > ( λ(element : Text) →+λ(status : < Empty : {} | NonEmpty : Text >) → merge { Empty = λ(_ : {}) → <+NonEmpty : Text | Empty : {} >.NonEmpty element , NonEmpty = λ(result : Text) →+< NonEmpty : Text | Empty : {} >.NonEmpty (element ++ "," ++ result) } status :+< Empty : {} | NonEmpty : Text > ) (< Empty : {} | NonEmpty : Text >.Empty {=})+) : Text ) ++ " " ++ ( merge { Empty = λ(_ : {}) → "", NonEmpty = λ(result :+Text) → result } ( List/fold Text x.mandatoryFeatures < Empty : {} | NonEmpty :+Text > ( λ(element : Text) → λ(status : < Empty : {} | NonEmpty : Text >) →+merge { Empty = λ(_ : {}) → < NonEmpty : Text | Empty : {} >.NonEmpty element ,+NonEmpty = λ(result : Text) → < NonEmpty : Text | Empty : {} >.NonEmpty+(element ++ "," ++ result) } status : < Empty : {} | NonEmpty : Text > ) (<+Empty : {} | NonEmpty : Text+>.Empty {=}) ) : Text ) ++ "\n" ++ y ) ""
binary file changed (absent → 3818 bytes)
file too large to diff
@@ -0,0 +1,22 @@++let Nat = ∀(N : Type) → (N → N) → N → N+let n2 = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s z)+let n5 = λ(N : Type) → λ(s : N → N) → λ(z : N) → s (s (s (s (s z))))++let mul =+ λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N (b N s) z++let add =+ λ(a : Nat) → λ(b : Nat) → λ(N : Type) → λ(s : N → N) → λ(z : N) → a N s (b N s z)++let n10 = mul n2 n5+let n100 = mul n10 n10+let n1k = mul n10 n100+let n10k = mul n100 n100+let n100k = mul n10 n10k+let n1M = mul n10k n100+let n5M = mul n1M n5+let n10M = mul n1M n10+let n20M = mul n10M n2++in n1M Natural (λ (x:Natural) → x + 1) 0
@@ -0,0 +1,18 @@++let compose+ : ∀(a : Type) → ∀(b : Type) → ∀(c : Type) → (a → b) → (b → c) → a → c+ = λ(A : Type)+ → λ(B : Type)+ → λ(C : Type)+ → λ(f : A → B)+ → λ(g : B → C)+ → λ(x : A)+ → g (f x)++let composeN : ∀ (a : Type) → Natural → (a → a) → a → a+ = λ (a : Type)+ → λ (n : Natural)+ → λ (f : a → a)+ → Natural/fold n (a → a) (compose a a a f) (λ (x : a) → x)++in composeN Natural 100000 (λ (x : Natural) → x + 1) 0
@@ -0,0 +1,75 @@++let iterate+ = λ(n : Natural)+ → λ(a : Type)+ → λ(f : a → a)+ → λ(x : a)+ → List/build+ a+ ( λ(list : Type)+ → λ(cons : a → list → list)+ → List/fold+ { index : Natural, value : {} }+ ( List/indexed+ {}+ ( List/build+ {}+ ( λ(list : Type)+ → λ(cons : {} → list → list)+ → Natural/fold n list (cons {=})+ )+ )+ )+ list+ ( λ(y : { index : Natural, value : {} })+ → cons (Natural/fold y.index a f x)+ )+ )++let countTo =+ λ (x : Natural)+ → iterate x Natural (λ (x : Natural) → x + 1) 0++let sum =+ λ (xs : List Natural)+ → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0+++let map+ : ∀(a : Type) → ∀(b : Type) → (a → b) → List a → List b+ = λ(a : Type)+ → λ(b : Type)+ → λ(f : a → b)+ → λ(xs : List a)+ → List/build+ b+ ( λ(list : Type)+ → λ(cons : b → list → list)+ → List/fold a xs list (λ(x : a) → cons (f x))+ )++let any+ : ∀(a : Type) → (a → Bool) → List a → Bool+ = λ(a : Type)+ → λ(f : a → Bool)+ → λ(xs : List a)+ → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False++let filter+ : ∀(a : Type) → (a → Bool) → List a → List a+ = λ(a : Type)+ → λ(f : a → Bool)+ → λ(xs : List a)+ → List/build+ a+ ( λ(list : Type)+ → λ(cons : a → list → list)+ → List/fold+ a+ xs+ list+ (λ(x : a) → λ(xs : list) → if f x then cons x xs else xs)+ )++in sum (filter Natural Natural/even+ (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
@@ -0,0 +1,45 @@++let iterate =+ λ(n : Natural)+ → λ(a : Type)+ → λ(f : a → a)+ → λ(x : a)+ → (Natural/fold n+ (a → List a → {fst:a, snd:List a})+ (λ (hyp : a → List a → {fst:a, snd:List a}) →+ λ (x : a) → λ (xs : List a)+ → let tup = hyp x xs+ in {fst = f (tup.fst), snd = tup.snd # [tup.fst]})+ (λ (x : a) → λ (xs : List a) → {fst=x, snd=xs})+ x ([] : List a)).snd++let countTo =+ λ (x : Natural)+ → iterate x Natural (λ (x : Natural) → x + 1) 0++let sum =+ λ (xs : List Natural)+ → List/fold Natural xs Natural (λ (x : Natural) → λ (acc : Natural) → x + acc) 0++let map+ = λ(a : Type)+ → λ(b : Type)+ → λ(f : a → b)+ → λ(xs : List a)+ → List/fold a xs (List b) (λ (x : a) → λ (xs : List b) → [f x] # xs) ([] : List b)++let any+ = λ(a : Type)+ → λ(f : a → Bool)+ → λ(xs : List a)+ → List/fold a xs Bool (λ(x : a) → λ(r : Bool) → f x || r) False++let filter+ = λ(a : Type)+ → λ(f : a → Bool)+ → λ(xs : List a)+ → List/fold a xs (List a)+ (λ (x : a) → λ (xs : List a) → if f x then [x] # xs else xs) ([] : List a)++in sum (filter Natural Natural/even+ (map Natural Natural (λ(x:Natural) → x + 10) (countTo 1000)))
@@ -1,2 +1,3 @@- ./and.dhall sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d+ missing+ sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d ? ./and.dhall
@@ -1,2 +1,3 @@- ./build.dhall sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b+ missing+ sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b ? ./build.dhall
@@ -0,0 +1,6 @@+--| Returns `True` if both arguments are equal and returns `False` otherwise+let equal+ : Bool -> Bool -> Bool+ = \(x : Bool) -> \(y : Bool) -> x == y++in equal
@@ -1,2 +1,3 @@- ./even.dhall sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5+ missing+ sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5 ? ./even.dhall
@@ -1,2 +1,3 @@- ./fold.dhall sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae+ missing+ sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae ? ./fold.dhall
@@ -1,2 +1,3 @@- ./not.dhall sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4 ? ./not.dhall
@@ -1,2 +1,3 @@- ./odd.dhall sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999+ missing+ sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999 ? ./odd.dhall
@@ -1,2 +1,3 @@- ./or.dhall sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4+ missing+ sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4 ? ./or.dhall
@@ -1,25 +1,37 @@ { and =- ./and.dhall sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d+ missing+ sha256:0b2114fa33cd76652e4360f012bc082718944fe4c5b28c975483178f8d9b0a6d ? ./and.dhall , build =- ./build.dhall sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b+ missing+ sha256:add7cb9acacac705410088d876a7e4488e046a7aded304f06c51accffd7f1b7b ? ./build.dhall+, equal =+ missing+ sha256:f0dc047ca14644c2a979bb126f2a3c6659ec770c66bd7beb70ae4a9d05815709+ ? ./equal.dhall , even =- ./even.dhall sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5+ missing+ sha256:72a05ee550636a3acb768360fa51ba0db0326763e0cf1ceb737f0f3607fc0fe5 ? ./even.dhall , fold =- ./fold.dhall sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae+ missing+ sha256:39f60baf3950268c2e849e91dc6279ee41cd6b81892d54020d4fcd2ce30a96ae ? ./fold.dhall , not =- ./not.dhall sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4 ? ./not.dhall , odd =- ./odd.dhall sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999+ missing+ sha256:6360fca3a745de32bd186cc7b71487a6398cd47d5119064eae491872c41d1999 ? ./odd.dhall , or =- ./or.dhall sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4+ missing+ sha256:5c50738e84e1c4fed8343ebd57608500e1b61ac1f502aa52d6d6edb5c20b99e4 ? ./or.dhall , show =- ./show.dhall sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61+ missing+ sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61 ? ./show.dhall }
@@ -1,2 +1,3 @@- ./show.dhall sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61+ missing+ sha256:f85f6d2d921c37a2122cb2e2f8a0170e305b699debd0e6df5ef3370d806b5f61 ? ./show.dhall
@@ -0,0 +1,5 @@+{ show =+ missing+ sha256:8a0eb9732cbc3c8f161b7cb05b183493befacc4728d2d9b7ee1384f19106a5ff+ ? ./show.dhall+}
@@ -0,0 +1,15 @@+{-+Render a `Date` as `Text` using the same representation as Dhall source code+(i.e. `YYYY-MM-DD`)+-}+let show+ : Date → Text+ = Date/show++let example0 = assert : show 2000-09-02 ≡ "2000-09-02"++let example1 = assert : show 9999-12-31 ≡ "9999-12-31"++let example2 = assert : show 0000-01-01 ≡ "0000-01-01"++in show
@@ -0,0 +1,5 @@+{-|+A (total) set of access rights; See chmod(5) for an explanation of the flags.+For a partial set of of access rights see `Access`.+-}+{ execute : Bool, read : Bool, write : Bool }
@@ -0,0 +1,69 @@+{-|+@intersect a b@ intesects the flags of the two `Mask`s @a@ and @b@. This+resembles the bitwise "and", i.e. the value of a flag is 'True' if and only if+it is set to 'True' in both @a@ and @b@. As a consequence @intersect a rwx == a@+and @intersect a none == none@ for all @a@.+-}+let Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall++let intersect+ : Mask -> Mask -> Mask+ = \(m1 : Mask) ->+ \(m2 : Mask) ->+ { read = m1.read && m2.read+ , write = m1.write && m2.write+ , execute = m1.execute && m2.execute+ }++let example0 =+ let r =+ missing+ sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+ ? ./r.dhall++ let w =+ missing+ sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+ ? ./w.dhall++ let x =+ missing+ sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+ ? ./x.dhall++ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ in assert : intersect r (intersect w (intersect x rwx)) === none++let example1 =+ \(a : Mask) ->+ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ in assert+ : intersect a rwx+ === { execute = a.execute, read = a.read, write = a.write }++let example2 =+ \(a : Mask) ->+ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ in assert : intersect a none === none++in intersect
@@ -0,0 +1,48 @@+{-|+Inverts the flags set in a `Mask`.+-}+let Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall++let Bool/not =+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ ? ../../../Bool/not.dhall++let invert+ : Mask -> Mask+ = \(m : Mask) ->+ { read = Bool/not m.read+ , write = Bool/not m.write+ , execute = Bool/not m.execute+ }++let example0 =+ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ in assert : invert rwx === none++let example1 =+ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ in assert : invert none === rwx++in invert
@@ -0,0 +1,4 @@+ { read = False, write = False, execute = False }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,53 @@+{ Type =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall+, intersect =+ missing+ sha256:7c7dab3e305f43cba556e0778b5a797cf8e9b1d1a6c6f6fe0ea311c329919663+ ? ./intersect.dhall+, invert =+ missing+ sha256:8807fb02f694fe2117f8a7f794e5afbb967ec36eac3405184bf9232c33cdd830+ ? ./invert.dhall+, none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall+, r =+ missing+ sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+ ? ./r.dhall+, rw =+ missing+ sha256:c3cce19f462b841e64adafbdf2963699a0031f5fc08b041c8ad364483c544d8b+ ? ./rw.dhall+, rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall+, rx =+ missing+ sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+ ? ./rx.dhall+, toAccess =+ missing+ sha256:78fe016f0273b2551c8590da71bf204cc26d6879c6b84622d4d8ad5624328438+ ? ./toAccess.dhall+, toAccessWith =+ missing+ sha256:814ab74ad292c121620a1f468837d4a5473323423bf68c1bceca69e7b3c59077+ ? ./toAccessWith.dhall+, union =+ missing+ sha256:b40c4cbb266991e3f764af075e9db544b59c16b3d9aa680c0cf6cb7552da191f+ ? ./union.dhall+, w =+ missing+ sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+ ? ./w.dhall+, x =+ missing+ sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+ ? ./x.dhall+}
@@ -0,0 +1,4 @@+ { read = True, write = False, execute = False }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,4 @@+ { read = True, write = True, execute = False }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,4 @@+ { read = True, write = True, execute = True }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,4 @@+ { read = True, write = False, execute = True }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,20 @@+{-|+Convert a `Mask` value to an `Access` value. For a partial conversion see+`toAccessWith`.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../Type.dhall++let Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall++let toAccess+ : Mask -> Access+ = \(m : Mask) ->+ { execute = Some m.execute, read = Some m.read, write = Some m.write }++in toAccess
@@ -0,0 +1,42 @@+{-|+@toAccessWith x m@ converts some fields of a `Mask` @m@ to an `Access` setting:+If the respective field is set in the first `Mask` @x@, then the flag will be+set to the flags value given in @m@. Otherwise, the value set in @m@ is ignored+and the value of the flag in the result is `None`.++For a motivation of this function see the documenation on `toModeWith`.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../Type.dhall++let Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall++let toAccessWith+ : Mask -> Mask -> Access+ = \(set : Mask) ->+ \(m : Mask) ->+ { execute = if set.execute then Some m.execute else None Bool+ , read = if set.read then Some m.read else None Bool+ , write = if set.write then Some m.write else None Bool+ }++let example0 =+ \(a : Mask) ->+ let Access/none =+ missing+ sha256:955a2eed689139c811d4b9ef3dd8d0c484392b18c3bb8752c59fd69dbdaf4881+ ? ../none.dhall++ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ in assert : toAccessWith none a === Access/none++in toAccessWith
@@ -0,0 +1,64 @@+{-|+@union a b@ combines the flags of the two `Mask`s @a@ and @b@. This resembles+the bitwise "or", i.e. the value of a flag is 'True' if it is set to 'True' in+either @a@ and @b@. As a consequence @union a rwx == rwx@ and+@union a none == a@ for all @a@.+-}+let Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall++let union+ : Mask -> Mask -> Mask+ = \(m1 : Mask) ->+ \(m2 : Mask) ->+ { read = m1.read || m2.read+ , write = m1.write || m2.write+ , execute = m1.execute || m2.execute+ }++let example0 =+ let r =+ missing+ sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+ ? ./r.dhall++ let w =+ missing+ sha256:9d10dfc672f61bbb2828c7be2121aae2502938c25adb47bb8cce3c40ba99821b+ ? ./w.dhall++ let x =+ missing+ sha256:a966fd88c05a5912a6daa8409e0c9e396f0a4810b51def1e1f62a95e18235f10+ ? ./x.dhall++ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ in assert : union r (union w x) === rwx++let example1 =+ \(a : Mask) ->+ let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ./rwx.dhall++ in assert : union a rwx === rwx++let example1 =+ \(a : Mask) ->+ let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ./none.dhall++ in assert+ : union a none+ === { execute = a.execute, read = a.read, write = a.write }++in union
@@ -0,0 +1,4 @@+ { read = False, write = True, execute = False }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,4 @@+ { read = False, write = False, execute = True }+: missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ./Type.dhall
@@ -0,0 +1,5 @@+{-|+A (partial) set of access rights; See chmod(5) for an explanation of the flags.+For a total set of access rights see `Mask`.+-}+{ execute : Optional Bool, read : Optional Bool, write : Optional Bool }
@@ -0,0 +1,29 @@+{-|+`equal` checks if two `Access` settings are equal.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ./Type.dhall++let Bool/equal =+ missing+ sha256:f0dc047ca14644c2a979bb126f2a3c6659ec770c66bd7beb70ae4a9d05815709+ ? ../../Bool/equal.dhall++let Optional/equal =+ missing+ sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+ ? ../../Optional/equal.dhall++let f+ : Optional Bool -> Optional Bool -> Bool+ = Optional/equal Bool Bool/equal++let equal+ : Access -> Access -> Bool+ = \(a1 : Access) ->+ \(a2 : Access) ->+ f a1.execute a2.execute && f a1.read a2.read && f a1.write a2.write++in equal
@@ -0,0 +1,4 @@+ { read = None Bool, write = None Bool, execute = None Bool }+: missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ./Type.dhall
@@ -0,0 +1,17 @@+{ Mask =+ missing+ sha256:ed736de51ea15a2ef671eaa7219dfbf3138bb52acfd0ae17894acf2ec4b06369+ ? ./Mask/package.dhall+, Type =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ./Type.dhall+, equal =+ missing+ sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+ ? ./equal.dhall+, schema =+ missing+ sha256:7d33a584a42a5d92411d5ca623e27ccb397762905be86ecfd01b106719fae690+ ? ./schema.dhall+}
@@ -0,0 +1,12 @@+{-|+A schema for blank access rights.+-}+{ Type =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ./Type.dhall+, default =+ missing+ sha256:955a2eed689139c811d4b9ef3dd8d0c484392b18c3bb8752c59fd69dbdaf4881+ ? ./none.dhall+}
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+ ? ./Type.dhall++in Entry Bytes
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+ ? ./Type.dhall++in \(tree : Type) -> Entry (List tree)
@@ -0,0 +1,24 @@+{-|+An `Entry` without content. That in turn implies that the type of the entry+(i.e. whether it is a file or a directory) is not (yet) fixed as well.+-}+let User =+ missing+ sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+ ? ../User/Type.dhall++let Group =+ missing+ sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+ ? ../Group/Type.dhall++let Mode =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ../Mode/Type.dhall++in { name : Text+ , user : Optional User+ , group : Optional Group+ , mode : Optional Mode+ }
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+ ? ./Type.dhall++in Entry Text
@@ -0,0 +1,6 @@+let Metadata =+ missing+ sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+ ? ./Metadata.dhall++in \(content : Type) -> Metadata //\\ { content : content }
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+ ? ./entry.dhall++in Entry Bytes
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+ ? ./entry.dhall++in \(tree : Type) -> Entry (List tree)
@@ -0,0 +1,24 @@+let Entry =+ missing+ sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+ ? ./Type.dhall++let User =+ missing+ sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+ ? ../User/Type.dhall++let Group =+ missing+ sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+ ? ../Group/Type.dhall++let Mode =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ../Mode/Type.dhall++in \(content : Type) ->+ { Type = Entry content+ , default = { user = None User, group = None Group, mode = None Mode }+ }
@@ -0,0 +1,37 @@+{ BinaryFileEntry =+ missing+ sha256:f027db2893f6f38bbe6d868a91f22de530e85407237f00b147427c87d32bf55c+ ? ./BinaryFileEntry.dhall+, DirectoryEntry =+ missing+ sha256:163a4536fdd05ce122d793ceda01d03fcffb29463817ae8b7b5601bf4a06ce6e+ ? ./DirectoryEntry.dhall+, Metadata =+ missing+ sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+ ? ./Metadata.dhall+, TextFileEntry =+ missing+ sha256:23a8cb29d96aeb623501519d9a62c5c49659e8d1c30b4ae4f2399809e3fd3a01+ ? ./TextFileEntry.dhall+, Type =+ missing+ sha256:75148ae19175750e38705e11cda8dcc775b2ac08f22518ff2ef3f33a6273ef15+ ? ./Type.dhall+, binary-file =+ missing+ sha256:bd49df43268c259e3d0bef995917c3ab517ae7b98bf1faac8f4a7e8a602e3465+ ? ./binary-file.dhall+, directory =+ missing+ sha256:0bee17310a21efa5b06f139b6731fdcee4f9e0245ef711c2b0127b8938dfed2e+ ? ./directory.dhall+, entry =+ missing+ sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+ ? ./entry.dhall+, text-file =+ missing+ sha256:c5d76fd43216668d03df9945183fe7b3c55486aedcc77324c3372bd63e283b78+ ? ./text-file.dhall+}
@@ -0,0 +1,6 @@+let Entry =+ missing+ sha256:742610b2a13e55ae6e344b54aa8a7ee1bfec8e8b313a1132eae9286309b520e6+ ? ./entry.dhall++in Entry Text
@@ -0,0 +1,1 @@+< GroupId : Natural | GroupName : Text >
@@ -0,0 +1,6 @@+let Group =+ missing+ sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+ ? ./Type.dhall++in Group.GroupId
@@ -0,0 +1,6 @@+let Group =+ missing+ sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+ ? ./Type.dhall++in Group.GroupName
@@ -0,0 +1,13 @@+{ Type =+ missing+ sha256:83e6e8846153d94abf6f879808c94f5cdba3f486cc9e392eb6124b1dc67368cf+ ? ./Type.dhall+, id =+ missing+ sha256:2bf9e546f56a583243d419a652caba16ca4053df9ccb3c5b242506d86806944b+ ? ./id.dhall+, name =+ missing+ sha256:51ac5c407f2939ab0c80bf2896d292ee6049bd8ba10acda0af327a3777f2205d+ ? ./name.dhall+}
@@ -0,0 +1,10 @@+{-|+A complete mode with all access rights specified explicitely. For an incomplete+mode where some access rights might not be set see `Mode`.+-}+let Access/Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ../../Access/Mask/Type.dhall++in { user : Access/Mask, group : Access/Mask, other : Access/Mask }
@@ -0,0 +1,9 @@+{-|+Permissions with all flags set: rwxrwxrwx+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++in { user = rwx, group = rwx, other = rwx }
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for directories: rwxr-xr-x+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++let rx =+ missing+ sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+ ? ../../Access/Mask/rx.dhall++in { user = rwx, group = rx, other = rx }+ : missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for executable files: rwxr-xr-x+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++let rx =+ missing+ sha256:d9beaa853c0de6984c3e5b0e313b573942900f8024fd9aaad743d73df458dc5e+ ? ../../Access/Mask/rx.dhall++in { user = rwx, group = rx, other = rx }+ : missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall
@@ -0,0 +1,17 @@+{-|+Permissions commonly used for regular files: rw-r--r--+-}+let r =+ missing+ sha256:26d7fc8df6194a8051946eac88d0d7fecce690bff6819e69b3c74edf65ac027a+ ? ../../Access/Mask/r.dhall++let rw =+ missing+ sha256:c3cce19f462b841e64adafbdf2963699a0031f5fc08b041c8ad364483c544d8b+ ? ../../Access/Mask/rw.dhall++in { user = rw, group = r, other = r }+ : missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall
@@ -0,0 +1,14 @@+{-|+Permissions with group flags set: ---rwx---+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ../../Access/Mask/none.dhall++in { user = none, group = rwx, other = none }
@@ -0,0 +1,24 @@+{-|+Calculates the intersection of the access rights of two `Mask`s using+`Access/intersect`.+-}+let Mask =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall++let Access/intersect =+ missing+ sha256:7c7dab3e305f43cba556e0778b5a797cf8e9b1d1a6c6f6fe0ea311c329919663+ ? ../../Access/Mask/intersect.dhall++let intersect+ : Mask -> Mask -> Mask+ = \(m1 : Mask) ->+ \(m2 : Mask) ->+ { user = Access/intersect m1.user m2.user+ , group = Access/intersect m1.group m2.group+ , other = Access/intersect m1.other m2.other+ }++in intersect
@@ -0,0 +1,22 @@+{-|+Inverts each access right set in a `Mask` using `Access/invert`.+-}+let Mask =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall++let Access/invert =+ missing+ sha256:8807fb02f694fe2117f8a7f794e5afbb967ec36eac3405184bf9232c33cdd830+ ? ../../Access/Mask/invert.dhall++let invert+ : Mask -> Mask+ = \(m : Mask) ->+ { user = Access/invert m.user+ , group = Access/invert m.group+ , other = Access/invert m.other+ }++in invert
@@ -0,0 +1,12 @@+{-|+Permissions with no flags set: ---------+-}+let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ../../Access/Mask/none.dhall++in { user = none, group = none, other = none }+ : missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall
@@ -0,0 +1,14 @@+{-|+Permissions with other flags set: ------rwx+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ../../Access/Mask/none.dhall++in { user = none, group = none, other = rwx }
@@ -0,0 +1,41 @@+{ Type =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall+, directory =+ missing+ sha256:a43f235f0caa25c7cabd89ac5d77e466e0c0ebf3339046993c18e481930243fd+ ? ./directory.dhall+, executable =+ missing+ sha256:a43f235f0caa25c7cabd89ac5d77e466e0c0ebf3339046993c18e481930243fd+ ? ./executable.dhall+, file =+ missing+ sha256:32d34228d48a707996272d1c9681171ddcd6651f72eeb3de9727d1c26ba99df3+ ? ./file.dhall+, intersect =+ missing+ sha256:146be962523ef619d3a250699f977b69c3e5f6c24b975453f351c0e807266fc8+ ? ./intersect.dhall+, invert =+ missing+ sha256:07a13d8c233d0a9fd6b3a11475987c10619072fec882c96bc5499bfb3c01e9b2+ ? ./invert.dhall+, none =+ missing+ sha256:7cac21e2b72cadf3ee0bf10680df4902ca73b6ee070219df5eac1a24cd66ccdf+ ? ./none.dhall+, toMode =+ missing+ sha256:af2b0dab799374afa0a2f28551446760ff29f4697c200da0a8b0a8def7feee2a+ ? ./toMode.dhall+, toModeWith =+ missing+ sha256:b92327bec9141cc1a55bc3f11ae2584af0883b94fe2513376fc40f1da5ade9b2+ ? ./toModeWith.dhall+, union =+ missing+ sha256:3bb32fc6ea21f661571e46d90e450e0340b2f2b65482ba7bd1a30514e1b39fc2+ ? ./union.dhall+}
@@ -0,0 +1,28 @@+{-|+Convert a `Mask` value to a `Mode` value. For a partial conversion see+`toModeWith`.+-}+let Mode =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ../Type.dhall++let Mask =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall++let Access/toAccess =+ missing+ sha256:78fe016f0273b2551c8590da71bf204cc26d6879c6b84622d4d8ad5624328438+ ? ../../Access/Mask/toAccess.dhall++let toMode+ : Mask -> Mode+ = \(m : Mask) ->+ { user = Some (Access/toAccess m.user)+ , group = Some (Access/toAccess m.group)+ , other = Some (Access/toAccess m.other)+ }++in toMode
@@ -0,0 +1,149 @@+{-|+@toModeWith x m@ converts some fields of a `Mask` @m@ to a `Mode`: If the+respective field is set in the first `Mask` @x@, then the flag will be set to+the flags value given in @m@. Otherwise, the value set in @m@ is ignored and the+value of the flag in the result is `None`.++The function is motivated by the following use case:+Alice has her umask set to 022 and new files will have permissions set to+rw-r--r--. Bob has the umask set to 077, hence newly created files will have+rw------- permissions. Now Eve distributes Dhall code writing a file with the+following mode to the filesystem:+```dhall+let mask = ./other.dhall++let permissions = ./all.dhall++in+toModeWith mask permissions+```+The written file will have rw-r--rwx permissions for Alice and rw----rwx+permissions for Bob as the `toModeWith mask` produces a `Mode` that will only+apply the permissions for the 'other' part.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../../Access/Type.dhall++let Access/Mask =+ missing+ sha256:c0fa7626b69e117086439a7b4ee15d1a80e16e38fe2ccc13f55e6dd26030b4df+ ? ../../Access/Mask/Type.dhall++let Mode =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ../Type.dhall++let Mask =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall++let Access/equal =+ missing+ sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+ ? ../../Access/equal.dhall++let Access/toAccessWith =+ missing+ sha256:814ab74ad292c121620a1f468837d4a5473323423bf68c1bceca69e7b3c59077+ ? ../../Access/Mask/toAccessWith.dhall++let f+ : Access/Mask -> Access/Mask -> Optional Access+ = \(set : Access/Mask) ->+ \(m : Access/Mask) ->+ let x = Access/toAccessWith set m++ in if Access/equal+ { execute = None Bool, read = None Bool, write = None Bool }+ x+ then None Access+ else Some x++let toModeWith+ : Mask -> Mask -> Mode+ = \(set : Mask) ->+ \(m : Mask) ->+ { user = f set.user m.user+ , group = f set.group m.group+ , other = f set.other m.other+ }++let example0 =+ \(a : Mask) ->+ let none =+ missing+ sha256:7cac21e2b72cadf3ee0bf10680df4902ca73b6ee070219df5eac1a24cd66ccdf+ ? ./none.dhall++ let Mode/none =+ missing+ sha256:0ed46da7e6acbdff9e4c9e27a9f2770075a7cd6cb6bb565765c62093df1b5563+ ? ../none.dhall++ in assert : toModeWith none a === Mode/none++let example1 =+ \(a : Mask) ->+ let toMode =+ missing+ sha256:af2b0dab799374afa0a2f28551446760ff29f4697c200da0a8b0a8def7feee2a+ ? ./toMode.dhall++ let all =+ missing+ sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+ ? ./all.dhall++ in assert : toModeWith all a === toMode a++let example2 =+ let mask =+ missing+ sha256:94bf82678d8d1c4f370a96f3831d3ad4464fbee508ffb37e93a479a1d9ee25cf+ ? ./other.dhall++ let permissions =+ missing+ sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+ ? ./all.dhall++ let rwx = { read = Some True, write = Some True, execute = Some True }++ in assert+ : toModeWith mask permissions+ === { user = None Access, group = None Access, other = Some rwx }++let example3 =+ let union =+ missing+ sha256:3bb32fc6ea21f661571e46d90e450e0340b2f2b65482ba7bd1a30514e1b39fc2+ ? ./union.dhall++ let group =+ missing+ sha256:faa567630372f77bb5cd2fa4fe7cb4760d2f9f79e35df80917e6e0064decf7cf+ ? ./group.dhall++ let other =+ missing+ sha256:94bf82678d8d1c4f370a96f3831d3ad4464fbee508ffb37e93a479a1d9ee25cf+ ? ./other.dhall++ let permissions =+ missing+ sha256:758415eca8dfee675dfef93ace9af82abb36bb3319b8e6295537ed18f9b5d3dd+ ? ./all.dhall++ let mask = union group other++ let rwx = { read = Some True, write = Some True, execute = Some True }++ in assert+ : toModeWith mask permissions+ === { user = None Access, group = Some rwx, other = Some rwx }++in toModeWith
@@ -0,0 +1,24 @@+{-|+Calculates the union of the access rights set by both `Mask`s using+`Access/union`.+-}+let Mask =+ missing+ sha256:4f97762058f24053e03997565a78800a5a2586159deaa265a4ee84a3d94ad471+ ? ./Type.dhall++let Access/union =+ missing+ sha256:b40c4cbb266991e3f764af075e9db544b59c16b3d9aa680c0cf6cb7552da191f+ ? ../../Access/Mask/union.dhall++let union+ : Mask -> Mask -> Mask+ = \(m1 : Mask) ->+ \(m2 : Mask) ->+ { user = Access/union m1.user m2.user+ , group = Access/union m1.group m2.group+ , other = Access/union m1.other m2.other+ }++in union
@@ -0,0 +1,14 @@+{-|+Permissions with all user flags set: rwx------+-}+let rwx =+ missing+ sha256:cafda16b1ecc0d2f9a63f3aab229a02e18aebb054283c73e50517f1e3727cd27+ ? ../../Access/Mask/rwx.dhall++let none =+ missing+ sha256:db6c3bb734bb3288441f2664379706052943eaba35c021326a600d41ca766925+ ? ../../Access/Mask/none.dhall++in { user = rwx, group = none, other = none }
@@ -0,0 +1,10 @@+{-|+An incomplete mode where some access rights might not be set explicitely. For a+complete mode with all access rights specified explicitely see `Mask`.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../Access/Type.dhall++in { user : Optional Access, group : Optional Access, other : Optional Access }
@@ -0,0 +1,34 @@+{-|+`equal` checks if two `Mode`s are equal.+-}+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../Access/Type.dhall++let Mode =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ./Type.dhall++let Access/equal =+ missing+ sha256:5fa90f55505780a7be942275d6bbb2b1f1fb7857364332ed732a0241c2165e53+ ? ../Access/equal.dhall++let Optional/equal =+ missing+ sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+ ? ../../Optional/equal.dhall++let f+ : Optional Access -> Optional Access -> Bool+ = Optional/equal Access Access/equal++let equal+ : Mode -> Mode -> Bool+ = \(m1 : Mode) ->+ \(m2 : Mode) ->+ f m1.user m2.user && f m1.group m2.group && f m1.other m2.other++in equal
@@ -0,0 +1,9 @@+let Access =+ missing+ sha256:50689ae80f8c8dcd6e7af33fbc20ea871afb92ec87104253cdbae01f838f6c38+ ? ../Access/Type.dhall++in { user = None Access, group = None Access, other = None Access }+ : missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ./Type.dhall
@@ -0,0 +1,17 @@+{ Mask =+ missing+ sha256:ce2c7ac1b81c2184b906cdd07c79936ba0eaf0445f1e383f53fd18d688ee7044+ ? ./Mask/package.dhall+, Type =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ./Type.dhall+, equal =+ missing+ sha256:32fee2d3a56a2162d6c98fb63d47d31f98b352f22cc60c8b506011c9b5230e56+ ? ./equal.dhall+, schema =+ missing+ sha256:49f8eff9612d761c1bd424299b68317ad0f3ba325e4d22ec8acb550c2f1c0a40+ ? ./schema.dhall+}
@@ -0,0 +1,12 @@+{-|+A schema for a blank file mode.+-}+{ Type =+ missing+ sha256:f05819ec2145e7dabf4aa167338bee6d326aabd81355dcf0b078e358bd34ec60+ ? ./Type.dhall+, default =+ missing+ sha256:0ed46da7e6acbdff9e4c9e27a9f2770075a7cd6cb6bb565765c62093df1b5563+ ? ./none.dhall+}
@@ -0,0 +1,20 @@+let Directory =+ missing+ sha256:163a4536fdd05ce122d793ceda01d03fcffb29463817ae8b7b5601bf4a06ce6e+ ? ../Entry/DirectoryEntry.dhall++let BinaryFile =+ missing+ sha256:f027db2893f6f38bbe6d868a91f22de530e85407237f00b147427c87d32bf55c+ ? ../Entry/BinaryFileEntry.dhall++let TextFile =+ missing+ sha256:23a8cb29d96aeb623501519d9a62c5c49659e8d1c30b4ae4f2399809e3fd3a01+ ? ../Entry/TextFileEntry.dhall++in \(tree : Type) ->+ { directory : Directory tree -> tree+ , binary-file : BinaryFile -> tree+ , file : TextFile -> tree+ }
@@ -0,0 +1,6 @@+let Make =+ missing+ sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+ ? ./Make.dhall++in forall (tree : Type) -> forall (make : Make tree) -> List tree
@@ -0,0 +1,32 @@+{-|+@makeTree tree make parents x@ places the tree @x@ below the directory @parent@.+@parent@ is given as a list of 'Metadata' values where each of those will be+used to create the respective level of the directory tree.+-}+let Make =+ missing+ sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+ ? ./Make.dhall++let Metadata =+ missing+ sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+ ? ../Entry/Metadata.dhall++let makeTree+ : forall (tree : Type) -> Make tree -> List Metadata -> tree -> tree+ = \(tree : Type) ->+ \(make : Make tree) ->+ \(parents : List Metadata) ->+ \(leaf : tree) ->+ List/fold+ Metadata+ parents+ tree+ ( \(directory : Metadata) ->+ \(result : tree) ->+ make.directory (directory /\ { content = [ result ] })+ )+ leaf++in makeTree
@@ -0,0 +1,42 @@+{-|+@makeTreeFromList tree make parents xs@ places the trees @xs@ below the+directory @parent@. @parent@ is given as a non-empty list of 'Metadata' values+where each of those will be used to create the respective level of the directory+tree.+-}+let Make =+ missing+ sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+ ? ./Make.dhall++let Metadata =+ missing+ sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+ ? ../Entry/Metadata.dhall++let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ../../NonEmpty/Type.dhall++let makeTreesFromList =+ missing+ sha256:02fce5b194da66c2f98bd05af0a3bfdccf0b57d7971f17bcafee436652d9a88e+ ? ./makeTreesFromList.dhall++let makeTreeFromList+ : forall (tree : Type) ->+ Make tree ->+ NonEmpty Metadata ->+ List tree ->+ tree+ = \(tree : Type) ->+ \(make : Make tree) ->+ \(parents : NonEmpty Metadata) ->+ \(leaves : List tree) ->+ make.directory+ ( parents.head+ /\ { content = makeTreesFromList tree make parents.tail leaves }+ )++in makeTreeFromList
@@ -0,0 +1,36 @@+{-|+@makeTreesFromList tree make parents xs@ places the trees @xs@ below the+directory @parent@. @parent@ is given as a list of 'Metadata' values where each+of those will be used to create the respective level of the directory tree.+-}+let Make =+ missing+ sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+ ? ./Make.dhall++let Metadata =+ missing+ sha256:8c240a00094238a73904af63ac0924b3e6aba1655312f20a2a27f88554e2febe+ ? ../Entry/Metadata.dhall++let makeTreesFromList+ : forall (tree : Type) ->+ Make tree ->+ List Metadata ->+ List tree ->+ List tree+ = \(tree : Type) ->+ \(make : Make tree) ->+ \(parents : List Metadata) ->+ \(leaves : List tree) ->+ List/fold+ Metadata+ parents+ (List tree)+ ( \(directory : Metadata) ->+ \(content : List tree) ->+ [ make.directory (directory /\ { content }) ]+ )+ leaves++in makeTreesFromList
@@ -0,0 +1,21 @@+{ Make =+ missing+ sha256:33c52c16f76b41c3635b57a38ce0286f1ad8b3163a3f07a3b41b808ac5bfeb5b+ ? ./Make.dhall+, Type =+ missing+ sha256:60b4d351213c6d851d7b2163ada40290b3c492a27326a2066fdec1a3915fb33b+ ? ./Type.dhall+, makeTree =+ missing+ sha256:2c1339fa63b4947864e1a6eede3c296288b53cf91a09d0d6881ae56790342e44+ ? ./makeTree.dhall+, makeTreeFromList =+ missing+ sha256:b894c9398e123d7262320684ac6301c2efe44d9d4f5a303b99d14e9be6b3150f+ ? ./makeTreeFromList.dhall+, makeTreesFromList =+ missing+ sha256:02fce5b194da66c2f98bd05af0a3bfdccf0b57d7971f17bcafee436652d9a88e+ ? ./makeTreesFromList.dhall+}
@@ -0,0 +1,1 @@+< UserId : Natural | UserName : Text >
@@ -0,0 +1,6 @@+let User =+ missing+ sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+ ? ./Type.dhall++in User.UserId
@@ -0,0 +1,6 @@+let User =+ missing+ sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+ ? ./Type.dhall++in User.UserName
@@ -0,0 +1,13 @@+{ Type =+ missing+ sha256:8b25916612d2c9b17130d16b55c6bdb085dd118e692f72bf351a83b1d0ac8833+ ? ./Type.dhall+, id =+ missing+ sha256:b572ca9f08a04e8e472f1b6141fd71ff27cc7f22d1e72be50eba5f54798b5a6d+ ? ./id.dhall+, name =+ missing+ sha256:9cfd68599bbd626d3f32c9caa3f09b358ecc08659ef2540b24a4b17b49027015+ ? ./name.dhall+}
@@ -0,0 +1,25 @@+{ Access =+ missing+ sha256:12f2ac90297a81c6e5a548bbf568fc7c93c906a6528432aa74faab6ec859de30+ ? ./Access/package.dhall+, Entry =+ missing+ sha256:795db8b6c2bc28fdff6fbcc832c5b4cb6931c1f62ffa84674280c24d4f2eacd8+ ? ./Entry/package.dhall+, Group =+ missing+ sha256:76a0d7e4606bdb91ab001b245cbd411939333b3fc3934ecbb5d41982d1ea001f+ ? ./Group/package.dhall+, Mode =+ missing+ sha256:6687ff7703fe9abdc4af9b3404af3d1c7d21a523d10a0c0b57d102a0bd87843f+ ? ./Mode/package.dhall+, Tree =+ missing+ sha256:6a64c27fa8a0c95830a4cc836651257235da0d985b7f93d11813cdb7a72e646b+ ? ./Tree/package.dhall+, User =+ missing+ sha256:eee7762ea4769371278907a4e33b3808d88430dda32dfc0536dc9bb2bb49d46a+ ? ./User/package.dhall+}
@@ -1,4 +1,5 @@ { show =- ./show.dhall sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f+ missing+ sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f ? ./show.dhall }
@@ -1,2 +1,3 @@- ./show.dhall sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f+ missing+ sha256:ae645813cc4d8505a265df4d7564c95482f62bb3e07fc81681959599b6cee04f ? ./show.dhall
@@ -1,2 +1,3 @@- ./compose.dhall sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+ missing+ sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013 ? ./compose.dhall
@@ -1,12 +1,12 @@ --| Compose two functions into one. let compose : ∀(a : Type) → ∀(b : Type) → ∀(c : Type) → (a → b) → (b → c) → a → c- = λ(A : Type) →- λ(B : Type) →- λ(C : Type) →- λ(f : A → B) →- λ(g : B → C) →- λ(x : A) →+ = λ(a : Type) →+ λ(b : Type) →+ λ(c : Type) →+ λ(f : a → b) →+ λ(g : b → c) →+ λ(x : a) → g (f x) let example0 =
@@ -0,0 +1,35 @@+{-|+Composes a list of functions starting from the left.+-}+let compose =+ missing+ sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+ ? ./compose.dhall++let identity =+ missing+ sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+ ? ./identity.dhall++let composeList+ : ∀(a : Type) → List (a → a) → a → a+ = λ(a : Type) →+ λ(functions : List (a → a)) →+ List/fold (a → a) functions (a → a) (compose a a a) (identity a)++let example0 =+ assert+ : composeList+ Natural+ [ λ(x : Natural) → x * 2, λ(x : Natural) → x + 1 ]+ 1+ ≡ 3++let property0 =+ λ(a : Type) →+ λ(f : a → a) →+ λ(g : a → a) →+ λ(h : a → a) →+ assert : composeList a [ f, g, h ] ≡ (λ(x : a) → h (g (f x)))++in composeList
@@ -1,2 +1,3 @@- ./identity.dhall sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+ missing+ sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4 ? ./identity.dhall
@@ -1,7 +1,13 @@ { compose =- ./compose.dhall sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013+ missing+ sha256:65ad8bbea530b3d8968785a7cf4a9a7976b67059aa15e3b61fcba600a40ae013 ? ./compose.dhall+, composeList =+ missing+ sha256:2c6931544d8b5a5b14514098c07bd1813f67b16834588d056df3c0bc2e489937+ ? ./composeList.dhall , identity =- ./identity.dhall sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+ missing+ sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4 ? ./identity.dhall }
@@ -1,2 +1,3 @@- ./abs.dhall sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+ missing+ sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1 ? ./abs.dhall
@@ -1,2 +1,3 @@- ./add.dhall sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+ missing+ sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b ? ./add.dhall
@@ -1,6 +1,7 @@ --| `add m n` computes `m + n`. let Integer/subtract =- ./subtract.dhall sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+ missing+ sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda ? ./subtract.dhall let add
@@ -1,2 +1,3 @@- ./clamp.dhall sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+ missing+ sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2 ? ./clamp.dhall
@@ -1,2 +1,3 @@- ./equal.dhall sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+ missing+ sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8 ? ./equal.dhall
@@ -1,6 +1,7 @@ --| `equal` checks if two Integers are equal. let Natural/equal =- ../Natural/equal.dhall sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+ missing+ sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60 ? ../Natural/equal.dhall let equal
@@ -1,2 +1,3 @@- ./greaterThan.dhall sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+ missing+ sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b ? ./greaterThan.dhall
@@ -1,10 +1,12 @@ --| `greaterThan` checks if one Integer is greater than another. let Bool/not =- ../Bool/not.dhall sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4 ? ../Bool/not.dhall let lessThanEqual =- ./lessThanEqual.dhall sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+ missing+ sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc ? ./lessThanEqual.dhall let greaterThan
@@ -1,2 +1,3 @@- ./greaterThanEqual.dhall sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+ missing+ sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958 ? ./greaterThanEqual.dhall
@@ -2,7 +2,8 @@ `greaterThanEqual` checks if one Integer is greater than or equal to another. -} let lessThanEqual =- ./lessThanEqual.dhall sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+ missing+ sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc ? ./lessThanEqual.dhall let greaterThanEqual
@@ -1,2 +1,3 @@- ./lessThan.dhall sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+ missing+ sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0 ? ./lessThan.dhall
@@ -1,6 +1,7 @@ --| `lessThan` checks if one Integer is less than another. let greaterThan =- ./greaterThan.dhall sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+ missing+ sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b ? ./greaterThan.dhall let lessThan
@@ -1,2 +1,3 @@- ./lessThanEqual.dhall sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+ missing+ sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc ? ./lessThanEqual.dhall
@@ -1,18 +1,22 @@ --| `lessThanEqual` checks if one Integer is less than or equal to another. let Natural/greaterThanEqual =- ../Natural/greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ../Natural/greaterThanEqual.dhall let Natural/lessThanEqual =- ../Natural/lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ../Natural/lessThanEqual.dhall let nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall let nonNegative =- ./nonNegative.dhall sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+ missing+ sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663 ? ./nonNegative.dhall let lessThanEqual
@@ -1,2 +1,3 @@- ./multiply.dhall sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+ missing+ sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d ? ./multiply.dhall
@@ -1,7 +1,7 @@ --| `multiply m n` computes `m * n`.- let nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall let multiplyNonNegative =
@@ -1,2 +1,3 @@- ./negate.dhall sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+ missing+ sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d ? ./negate.dhall
@@ -1,2 +1,3 @@- ./negative.dhall sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+ missing+ sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570 ? ./negative.dhall
@@ -4,7 +4,8 @@ `negative` is more efficient than `./lessThan +0` or `./lessThanEqual -1`. -} let positive =- ./positive.dhall sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+ missing+ sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3 ? ./positive.dhall let negative
@@ -1,2 +1,3 @@- ./nonNegative.dhall sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+ missing+ sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663 ? ./nonNegative.dhall
@@ -4,7 +4,8 @@ `nonNegative` is more efficient than `./greaterThanEqual +0` or `./greaterThan -1`. -} let nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall let nonNegative
@@ -1,2 +1,3 @@- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall
@@ -1,55 +1,73 @@ { abs =- ./abs.dhall sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1+ missing+ sha256:35212fcbe1e60cb95b033a4a9c6e45befca4a298aa9919915999d09e69ddced1 ? ./abs.dhall , add =- ./add.dhall sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b+ missing+ sha256:7da1306a0bf87c5668beead2a1db1b18861e53d7ce1f38057b2964b649f59c3b ? ./add.dhall , clamp =- ./clamp.dhall sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2+ missing+ sha256:ea42096cf3e024fadfaf910e0b839005b0ea7514fff11e5a3950a77694d9c5d2 ? ./clamp.dhall , equal =- ./equal.dhall sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8+ missing+ sha256:2d99a205086aa77eea17ae1dab22c275f3eb007bccdc8d9895b93497ebfc39f8 ? ./equal.dhall , greaterThan =- ./greaterThan.dhall sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b+ missing+ sha256:d23affd73029fc9aaf867c2c7b86510ca2802d3f0d1f3e1d1a93ffd87b7cb64b ? ./greaterThan.dhall , greaterThanEqual =- ./greaterThanEqual.dhall sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958+ missing+ sha256:a9fa2dc5cd6067a23b39d7fe8d14a63109583b320429fb0e446658a5aae0a958 ? ./greaterThanEqual.dhall , lessThan =- ./lessThan.dhall sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0+ missing+ sha256:eeaa0081d10c6c97464ef193c40f1aa5cbb12f0202972ab42f3d310c2fd6a3f0 ? ./lessThan.dhall , lessThanEqual =- ./lessThanEqual.dhall sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc+ missing+ sha256:e3cca9f3942f81fa78a2bea23c0c24519c67cfe438116c38e797e12dcd26f6bc ? ./lessThanEqual.dhall , multiply =- ./multiply.dhall sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d+ missing+ sha256:dcb1ed7c8475ece8d67db92cd249fc728541778ff82509e28c3760e341880e4d ? ./multiply.dhall , negate =- ./negate.dhall sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d+ missing+ sha256:2373c992e1de93634bc6a8781eb073b2a92a70170133e49762a785f3a136df5d ? ./negate.dhall , negative =- ./negative.dhall sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570+ missing+ sha256:23e4b3c61eea9e878a7f83bf25fd0ea2c6a6d60174890d65be885828b690a570 ? ./negative.dhall , nonNegative =- ./nonNegative.dhall sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+ missing+ sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663 ? ./nonNegative.dhall , nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall , positive =- ./positive.dhall sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+ missing+ sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3 ? ./positive.dhall , show =- ./show.dhall sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+ missing+ sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9 ? ./show.dhall , subtract =- ./subtract.dhall sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+ missing+ sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda ? ./subtract.dhall , toDouble =- ./toDouble.dhall sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+ missing+ sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7 ? ./toDouble.dhall , toNatural =- ./toNatural.dhall sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+ missing+ sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e ? ./toNatural.dhall }
@@ -1,2 +1,3 @@- ./positive.dhall sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3+ missing+ sha256:7bdbf50fcdb83d01f74c7e2a92bf5c9104eff5d8c5b4587e9337f0caefcfdbe3 ? ./positive.dhall
@@ -4,11 +4,13 @@ `positive` is more efficient than `./greaterThan +0` or `./greaterThanEqual +1`. -} let not =- ../Bool/not.dhall sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4 ? ../Bool/not.dhall let nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall let positive
@@ -1,2 +1,3 @@- ./show.dhall sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9+ missing+ sha256:ecf8b0594cd5181bc45d3b7ea0d44d3ba9ad5dac6ec17bb8968beb65f4b1baa9 ? ./show.dhall
@@ -1,2 +1,3 @@- ./subtract.dhall sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda+ missing+ sha256:a34d36272fa8ae4f1ec8b56222fe8dc8a2ec55ec6538b840de0cbe207b006fda ? ./subtract.dhall
@@ -1,6 +1,7 @@ --| `subtract m n` computes `n - m`. let nonPositive =- ./nonPositive.dhall sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b+ missing+ sha256:e00a852eed5b84ff60487097d8aadce53c9e5301f53ff4954044bd68949fac3b ? ./nonPositive.dhall let subtractNonNegative =
@@ -1,2 +1,3 @@- ./toDouble.dhall sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7+ missing+ sha256:77bc5d635dc4d952f37cc96f2a681d5ac503b4e8b21fc00055b1946adb5beda7 ? ./toDouble.dhall
@@ -1,2 +1,3 @@- ./toNatural.dhall sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e+ missing+ sha256:4d128730d74e7f832e53873cb5204aa91b79758be5ce4e1aa991fe1951304a0e ? ./toNatural.dhall
@@ -2,7 +2,8 @@ Convert an `Integer` to an `Optional Natural`, with negative numbers becoming `None Natural`. -} let nonNegative =- ./nonNegative.dhall sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+ missing+ sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663 ? ./nonNegative.dhall let toNatural
@@ -1,2 +1,3 @@- ./Format.dhall sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+ missing+ sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac ? ./Format.dhall
@@ -4,5 +4,4 @@ You should not need to use this type directly, simply use `./render` or `./renderYAML` as appropriate. -}- < YAML | JSON >
@@ -1,2 +1,3 @@- ./Nesting.dhall sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ missing+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting.dhall
@@ -1,2 +1,3 @@- ./Tagged.dhall sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+ missing+ sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194 ? ./Tagged.dhall
@@ -65,7 +65,8 @@ = λ(a : Type) → { field : Text , nesting :- ./Nesting.dhall sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ missing+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting.dhall , contents : a }
@@ -1,2 +1,3 @@- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall
@@ -1,2 +1,3 @@- ./array.dhall sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+ missing+ sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8 ? ./array.dhall
@@ -13,11 +13,13 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let array
@@ -1,2 +1,3 @@- ./bool.dhall sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+ missing+ sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39 ? ./bool.dhall
@@ -12,7 +12,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let bool
@@ -8,48 +8,63 @@ `package.dhall` to avoid import cycles. -} { Type =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall , Tagged =- ./Tagged.dhall sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+ missing+ sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194 ? ./Tagged.dhall , Nesting =- ./Nesting.dhall sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ missing+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting.dhall , keyText =- ./keyText.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./keyText.dhall , keyValue =- ./keyValue.dhall sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+ missing+ sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c ? ./keyValue.dhall , string =- ./string.dhall sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+ missing+ sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e ? ./string.dhall , number =- ./number.dhall sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+ missing+ sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32 ? ./number.dhall , double =- ./double.dhall sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+ missing+ sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32 ? ./double.dhall , integer =- ./integer.dhall sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+ missing+ sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40 ? ./integer.dhall , natural =- ./natural.dhall sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+ missing+ sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5 ? ./natural.dhall , object =- ./object.dhall sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+ missing+ sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac ? ./object.dhall , array =- ./array.dhall sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8+ missing+ sha256:fb6346a9c63638fe3c59f8108e19eebdbddc51389ec5570bab4c25f890ccccc8 ? ./array.dhall , bool =- ./bool.dhall sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39+ missing+ sha256:e043d9ed01e5b45899059e128243f3dae7ce65f293f0015ce816fc36d30f7f39 ? ./bool.dhall , null =- ./null.dhall sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+ missing+ sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8 ? ./null.dhall , renderInteger =- ./renderInteger.dhall sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+ missing+ sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c ? ./renderInteger.dhall }
@@ -1,2 +1,3 @@- ./double.dhall sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+ missing+ sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32 ? ./double.dhall
@@ -12,7 +12,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let double
@@ -1,2 +1,3 @@- ./integer.dhall sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40+ missing+ sha256:c81a417397fc6f62155ec71fdd8d2047f981f0881295b307de3dd88747bf7e40 ? ./integer.dhall
@@ -12,7 +12,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let integer
@@ -1,2 +1,3 @@- ./keyText.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./keyText.dhall
@@ -1,2 +1,3 @@- ../Map/keyText.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ../Map/keyText.dhall
@@ -1,2 +1,3 @@- ./keyValue.dhall sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+ missing+ sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c ? ./keyValue.dhall
@@ -1,2 +1,3 @@- ../Map/keyValue.dhall sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+ missing+ sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c ? ../Map/keyValue.dhall
@@ -1,2 +1,3 @@- ./natural.dhall sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5+ missing+ sha256:a839dc6789f19f820e9cbf70c60f41f3b057c59ece1d226d04db5aca447eb0e5 ? ./natural.dhall
@@ -8,7 +8,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let natural
@@ -1,2 +1,3 @@- ./null.dhall sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8+ missing+ sha256:1eeb9aee38eb8dde0e64efbaf60f24612c8194cc00b510bfb627c2ee2e1877b8 ? ./null.dhall
@@ -8,7 +8,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let null
@@ -1,2 +1,3 @@- ./number.dhall sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+ missing+ sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32 ? ./number.dhall
@@ -12,11 +12,13 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let double =- ./double.dhall sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32+ missing+ sha256:e70162c73c4978ad0d0d99505f61c7d990f3abadfcc08b34388b29c0934a7a32 ? ./double.dhall let number
@@ -1,2 +1,3 @@- ./object.dhall sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac+ missing+ sha256:869aede785c34798be9f9fd457ece73e7f683f352ae4555f791516a365faf4ac ? ./object.dhall
@@ -19,11 +19,13 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let object
@@ -1,2 +1,3 @@- ./omitNullFields.dhall sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+ missing+ sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0 ? ./omitNullFields.dhall
@@ -3,15 +3,18 @@ for a configuration to encode absent fields -} let JSON =- ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+ missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5 ? ./core.dhall let List/concatMap =- ../List/concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64 ? ../List/concatMap.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let omitNullFields
@@ -1,19 +1,29 @@ { render =- ./render.dhall sha256:b5e5aee66b8fc018b50e1019a76340deafe5f8176854ea3611476d79990785da+ missing+ sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836 ? ./render.dhall+ , renderCompact =+ missing+ sha256:e6c8809fbe193fddd430f94350d69cefd45e7aaf8bd379e51b750fde75008562+ ? ./renderCompact.dhall , renderYAML =- ./renderYAML.dhall sha256:dad92a120956ae852be7496d1e1955bbf3f60834ab2ad32641269098f2846477+ missing+ sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478 ? ./renderYAML.dhall , omitNullFields =- ./omitNullFields.dhall sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0+ missing+ sha256:e6850e70094540b75edeb46f4d6038324a62def8d63544a1e9541f79739db6f0 ? ./omitNullFields.dhall , tagInline =- ./tagInline.dhall sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+ missing+ sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4 ? ./tagInline.dhall , tagNested =- ./tagNested.dhall sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+ missing+ sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f ? ./tagNested.dhall }-∧ ( ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+∧ ( missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5 ? ./core.dhall )
@@ -1,2 +1,3 @@- ./render.dhall sha256:b5e5aee66b8fc018b50e1019a76340deafe5f8176854ea3611476d79990785da+ missing+ sha256:36befdd8bb5a1c2b372709da245a8d074533b86429e137b894c08ad16fa34836 ? ./render.dhall
@@ -5,15 +5,18 @@ more sophisticated you should use `dhall-to-json` or `dhall-to-yaml` -} let JSON =- ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+ missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5 ? ./core.dhall let renderAs =- ./renderAs.dhall sha256:5576473c02bc447d40d08bf103aaeca9637c1040367fdf07ff70032ba3e28043+ missing+ sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471 ? ./renderAs.dhall let Format =- ./Format.dhall sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+ missing+ sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac ? ./Format.dhall let render
@@ -1,2 +1,3 @@- ./renderAs.dhall sha256:5576473c02bc447d40d08bf103aaeca9637c1040367fdf07ff70032ba3e28043+ missing+ sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471 ? ./renderAs.dhall
@@ -1,33 +1,49 @@ --| Render a `JSON` value as `Text` in either JSON or YAML format.- let JSON =- ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+ missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5 ? ./core.dhall let Function/identity =- ../Function/identity.dhall sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4+ missing+ sha256:f78b96792b459cb664f41c6119bd8897dd04353a3343521d436cd82ad71cb4d4 ? ../Function/identity.dhall let Text/concatMap =- ../Text/concatMap.dhall sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+ missing+ sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f ? ../Text/concatMap.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall -let List/concatMap =- ../List/concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64- ? ../List/concatMap.dhall+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ../NonEmpty/Type.dhall -let NonEmpty- : Type → Type- = λ(a : Type) → { head : a, tail : List a }+let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ../NonEmpty/toList.dhall -let NonEmpty/singleton- : ∀(a : Type) → a → NonEmpty a- = λ(a : Type) → λ(x : a) → { head = x, tail = [] : List a }+let NonEmpty/concat =+ missing+ sha256:6d55181938c06c6b806877028f6a241912e9c0935d9a10dd958775bf21e0f64d+ ? ../NonEmpty/concat.dhall +let NonEmpty/map =+ missing+ sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+ ? ../NonEmpty/map.dhall++let NonEmpty/singleton =+ missing+ sha256:c9197aabe97695f7ca66f7419bf172d806b2c915594a8fc0d2ff6495db496ff2+ ? ../NonEmpty/singleton.dhall+ let List/uncons : ∀(a : Type) → List a → Optional (NonEmpty a) = {- This version uses the `ls` argument only once to prevent cache blowups at the price@@ -54,28 +70,6 @@ ) (None (NonEmpty a)) -let NonEmpty/toList- : ∀(a : Type) → NonEmpty a → List a- = λ(a : Type) → λ(nonEmpty : NonEmpty a) → [ nonEmpty.head ] # nonEmpty.tail--let NonEmpty/concat- : ∀(a : Type) → NonEmpty (NonEmpty a) → NonEmpty a- = λ(a : Type) →- λ(lss : NonEmpty (NonEmpty a)) →- { head = lss.head.head- , tail =- lss.head.tail- # List/concatMap (NonEmpty a) a (NonEmpty/toList a) lss.tail- }--let NonEmpty/map- : ∀(a : Type) → ∀(b : Type) → (a → b) → NonEmpty a → NonEmpty b- = λ(a : Type) →- λ(b : Type) →- λ(fn : a → b) →- λ(ls : NonEmpty a) →- { head = fn ls.head, tail = List/map a b fn ls.tail }- let NonEmpty/mapHead : ∀(a : Type) → (a → a) → NonEmpty a → NonEmpty a = λ(a : Type) →@@ -190,11 +184,28 @@ let indentTail = NonEmpty/mapTail Text addIndent let Format =- ./Format.dhall sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+ missing+ sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac ? ./Format.dhall let ObjectField = { mapKey : Text, mapValue : Block } +let -- Essentially the same thing as `Text/show`, except that this does not+ -- escape `$`+ escape =+ List/fold+ (Text → Text)+ [ Text/replace "\"" "\\\""+ , Text/replace "\b" "\\b"+ , Text/replace "\f" "\\f"+ , Text/replace "\n" "\\n"+ , Text/replace "\r" "\\r"+ , Text/replace "\t" "\\t"+ , Text/replace "\\" "\\\\"+ ]+ Text+ (λ(replace : Text → Text) → λ(text : Text) → replace text)+ let renderJSONStruct = λ(prefix : Text) → λ(suffix : Text) →@@ -225,7 +236,7 @@ let renderObject = λ(format : Format) → λ(fields : NonEmpty ObjectField) →- let keystr = λ(field : ObjectField) → "${Text/show field.mapKey}:"+ let keystr = λ(field : ObjectField) → "\"${escape field.mapKey}\":" let prefixKeyOnFirst = λ(field : ObjectField) →@@ -294,7 +305,7 @@ blockToText ( json Block- { string = λ(x : Text) → Block.Simple (Text/show x)+ { string = λ(x : Text) → Block.Simple "\"${escape x}\"" , double = λ(x : Double) → Block.Simple (Double/show x) , integer = λ(x : Integer) → Block.Simple (JSON.renderInteger x) , object = manyBlocks ObjectField "{}" (renderObject format)@@ -424,5 +435,24 @@ '' in True++let example3 =+ let specialCharacters =+ ''+ "\${"\b\f"}+ ${"\r"} $''++ let data =+ JSON.object+ [ { mapKey = specialCharacters+ , mapValue = JSON.string specialCharacters+ }+ ]++ in assert+ : renderAs Format.JSON data+ ≡ ''+ { "\"\\\b\f\n\r\t$": "\"\\\b\f\n\r\t$" }+ '' in renderAs
@@ -0,0 +1,61 @@+--| This renders JSON on a single line+let JSON =+ missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+ ? ./core.dhall++let Text/concatMapSep =+ missing+ sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+ ? ../Text/concatMapSep++let renderInteger =+ missing+ sha256:15b8d2ae46d5002832741927af787761df49798c911e2bf85db7a7b9cb5c078c+ ? ./renderInteger.dhall++let renderCompact+ : JSON.Type → Text+ = λ(j : JSON.Type) →+ j+ Text+ { string = Text/show+ , double = Double/show+ , integer = renderInteger+ , object =+ λ(x : List { mapKey : Text, mapValue : Text }) →+ let body =+ Text/concatMapSep+ ","+ { mapKey : Text, mapValue : Text }+ ( λ(e : { mapKey : Text, mapValue : Text }) →+ " ${Text/show e.mapKey}: ${e.mapValue}"+ )+ x++ in "{${body} }"+ , array =+ λ(x : List Text) →+ let body = Text/concatMapSep "," Text (λ(y : Text) → " ${y}") x++ in "[${body} ]"+ , bool = λ(x : Bool) → if x then "true" else "false"+ , null = "null"+ }++let example =+ assert+ : renderCompact+ ( JSON.array+ [ JSON.bool True+ , JSON.string "Hello"+ , JSON.object+ [ { mapKey = "foo", mapValue = JSON.null }+ , { mapKey = "bar", mapValue = JSON.double 1.1 }+ , { mapKey = "baz", mapValue = JSON.integer +2 }+ ]+ ]+ )+ ≡ "[ true, \"Hello\", { \"foo\": null, \"bar\": 1.1, \"baz\": 2 } ]"++in renderCompact
@@ -2,9 +2,9 @@ Render an `Integer` value as a `JSON number`, according to the JSON standard, in which a number may not start with a plus sign (`+`). -}- let Integer/nonNegative =- ../Integer/nonNegative.dhall sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663+ missing+ sha256:b463373f070df6b1c8c7082051e0810fee38b360bab35256187c8c2b6af5c663 ? ../Integer/nonNegative.dhall let renderInteger
@@ -1,2 +1,3 @@- ./renderYAML.dhall sha256:dad92a120956ae852be7496d1e1955bbf3f60834ab2ad32641269098f2846477+ missing+ sha256:bc71449397bbf48103c3ebbdd570cd27313115e94b2b1b96761d257d5c02d478 ? ./renderYAML.dhall
@@ -8,17 +8,19 @@ For anything more sophisticated you should use `dhall-to-json` or `dhall-to-yaml`. -}- let JSON =- ./core.dhall sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5+ missing+ sha256:5dc1135d5481cfd6fde625aaed9fcbdb7aa7c14f2e76726aa5fdef028a5c10f5 ? ./core.dhall let renderAs =- ./renderAs.dhall sha256:5576473c02bc447d40d08bf103aaeca9637c1040367fdf07ff70032ba3e28043+ missing+ sha256:c23be039c9601a33d6546fd99a8d72bee8dde5f46176d57cc96613b31a3bb471 ? ./renderAs.dhall let Format =- ./Format.dhall sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac+ missing+ sha256:d7936b510cfc091faa994652af0eb5feb889cd44bc989edbe4f1eb8c5623caac ? ./Format.dhall let renderYAML
@@ -1,2 +1,3 @@- ./string.dhall sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e+ missing+ sha256:7ddb3a3b9f3ed09ed011d621a10ad9825185cd03503be98a81d42f6afb77940e ? ./string.dhall
@@ -12,7 +12,8 @@ ``` -} let JSON =- ./Type.dhall sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759+ missing+ sha256:40edbc9371979426df63e064333b02689b969c4cfbbccfa481216d2d1a6e9759 ? ./Type.dhall let string
@@ -1,2 +1,3 @@- ./tagInline.dhall sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4+ missing+ sha256:49559ac11906ba6cc9eac25753e31e7addb13bc760df108024174c55523984c4 ? ./tagInline.dhall
@@ -1,10 +1,12 @@ --| Prepare a union value for JSON- or YAML-encoding with the inline layout let Nesting =- ./Nesting.dhall sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ missing+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting.dhall let Tagged =- ./Tagged.dhall sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+ missing+ sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194 ? ./Tagged.dhall let tagInline
@@ -1,2 +1,3 @@- ./tagNested.dhall sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f+ missing+ sha256:93a7415853b7677c832246efadc8e880c1b641a23589286a836a384ca311d26f ? ./tagNested.dhall
@@ -1,10 +1,12 @@ --| Prepare a union value for JSON- or YAML-encoding with the nested layout let Nesting =- ./Nesting.dhall sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ missing+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting.dhall let Tagged =- ./Tagged.dhall sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194+ missing+ sha256:21feca7d2b23f210d0696131d792e18a7d24fdcc85d41a49ba85b98670eba194 ? ./Tagged.dhall let tagNested
@@ -1,2 +1,3 @@- ./all.dhall sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15+ missing+ sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15 ? ./all.dhall
@@ -1,2 +1,3 @@- ./any.dhall sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8+ missing+ sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8 ? ./any.dhall
@@ -1,2 +1,3 @@- ./build.dhall sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42+ missing+ sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42 ? ./build.dhall
@@ -1,2 +1,3 @@- ./concat.dhall sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b+ missing+ sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b ? ./concat.dhall
@@ -1,2 +1,3 @@- ./concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64 ? ./concatMap.dhall
@@ -1,2 +1,3 @@- ./default.dhall sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+ missing+ sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379 ? ./default.dhall
@@ -1,2 +1,3 @@- ./drop.dhall sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+ missing+ sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf ? ./drop.dhall
@@ -1,6 +1,7 @@ --| Remove first `n` elements of a list let Natural/greaterThanEqual =- ../Natural/greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ../Natural/greaterThanEqual.dhall let drop
@@ -1,2 +1,3 @@- ./empty.dhall sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+ missing+ sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147 ? ./empty.dhall
@@ -1,2 +1,3 @@- ./filter.dhall sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6+ missing+ sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6 ? ./filter.dhall
@@ -0,0 +1,45 @@+--| Transform a list by applying a function to each element and omitting None results.+let List/concatMap =+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ ? ./concatMap.dhall++let Optional/toList =+ missing+ sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+ ? ../Optional/toList.dhall++let filterMap+ : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → List a → List b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ List/concatMap a b (λ(x : a) → Optional/toList b (f x))++let example0 =+ assert+ : filterMap+ (List Natural)+ Natural+ (List/head Natural)+ [ [ 1 ], [] : List Natural, [ 3, 4 ] ]+ ≡ [ 1, 3 ]++let example1 =+ let Example = < Left : Bool | Right : Natural >++ in assert+ : filterMap+ Example+ Natural+ ( λ(x : Example) →+ merge+ { Left = λ(_ : Bool) → None Natural+ , Right = λ(n : Natural) → Some n+ }+ x+ )+ [ Example.Left False, Example.Right 2, Example.Left True ]+ ≡ [ 2 ]++in filterMap
@@ -1,2 +1,3 @@- ./fold.dhall sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814+ missing+ sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814 ? ./fold.dhall
@@ -18,34 +18,26 @@ : fold Natural [ 2, 3, 5 ]- Natural- (λ(x : Natural) → λ(y : Natural) → x + y)- 0- ≡ 10+ Text+ (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+ "0"+ ≡ "2350" let example1 =- assert- : ( λ(nil : Natural) →- fold- Natural- [ 2, 3, 5 ]- Natural- (λ(x : Natural) → λ(y : Natural) → x + y)- nil- )- ≡ (λ(nil : Natural) → 2 + (3 + (5 + nil)))+ λ(nil : Text) →+ assert+ : fold+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Natural) → λ(y : Text) → Natural/show x ++ y)+ nil+ ≡ "2" ++ ("3" ++ ("5" ++ nil)) let example2 =- assert- : ( λ(list : Type) →- λ(cons : Natural → list → list) →- λ(nil : list) →- fold Natural [ 2, 3, 5 ] list cons nil- )- ≡ ( λ(list : Type) →- λ(cons : Natural → list → list) →- λ(nil : list) →- cons 2 (cons 3 (cons 5 nil))- )+ λ(cons : Natural → Text → Text) →+ λ(nil : Text) →+ assert+ : fold Natural [ 2, 3, 5 ] Text cons nil ≡ cons 2 (cons 3 (cons 5 nil)) in fold
@@ -0,0 +1,60 @@+{-|+`foldLeft` is like `List/fold` except that the accumulation starts from the left++If you treat the list `[ x, y, z ]` as `cons (cons (cons nil x) y) z`, then+`foldLeft` just replaces each `cons` and `nil` with something else+-}+let foldLeft+ : ∀(a : Type) →+ List a →+ ∀(list : Type) →+ ∀(cons : list → a → list) →+ ∀(nil : list) →+ list+ = λ(a : Type) →+ λ(xs : List a) →+ λ(list : Type) →+ λ(cons : list → a → list) →+ λ(nil : list) →+ List/fold+ a+ xs+ (list → list)+ (λ(x : a) → λ(f : list → list) → λ(l : list) → f (cons l x))+ (λ(l : list) → l)+ nil++let example0 =+ assert+ : foldLeft+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+ "0"+ ≡ "0235"++let example1 =+ assert+ : ( λ(nil : Text) →+ foldLeft+ Natural+ [ 2, 3, 5 ]+ Text+ (λ(x : Text) → λ(y : Natural) → x ++ Natural/show y)+ nil+ )+ ≡ (λ(nil : Text) → nil ++ "2" ++ "3" ++ "5")++let example2 =+ assert+ : ( λ(cons : Text → Natural → Text) →+ λ(nil : Text) →+ foldLeft Natural [ 2, 3, 5 ] Text cons nil+ )+ ≡ ( λ(cons : Text → Natural → Text) →+ λ(nil : Text) →+ cons (cons (cons nil 2) 3) 5+ )++in foldLeft
@@ -1,2 +1,3 @@- ./generate.dhall sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4+ missing+ sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4 ? ./generate.dhall
@@ -1,2 +1,3 @@- ./head.dhall sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026+ missing+ sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026 ? ./head.dhall
@@ -1,2 +1,3 @@- ./index.dhall sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+ missing+ sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63 ? ./index.dhall
@@ -1,6 +1,7 @@ --| Retrieve an element from a `List` using its 0-based index let drop =- ./drop.dhall sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+ missing+ sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf ? ./drop.dhall let index
@@ -1,2 +1,3 @@- ./indexed.dhall sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f+ missing+ sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f ? ./indexed.dhall
@@ -1,2 +1,3 @@- ./iterate.dhall sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26+ missing+ sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26 ? ./iterate.dhall
@@ -1,2 +1,3 @@- ./last.dhall sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d+ missing+ sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d ? ./last.dhall
@@ -1,2 +1,3 @@- ./length.dhall sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461+ missing+ sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461 ? ./length.dhall
@@ -1,2 +1,3 @@- ./map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ./map.dhall
@@ -0,0 +1,37 @@+--| Apply a function across a list, keeping only the `Some` results.+let List/unpackOptionals =+ missing+ sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+ ? ./unpackOptionals.dhall++let List/map =+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ ? ./map.dhall++let mapMaybe+ : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → List a → List b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ λ(xs : List a) →+ List/unpackOptionals b (List/map a (Optional b) f xs)++let property =+ λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ assert : mapMaybe a b f ([] : List a) ≡ ([] : List b)++let example0 =+ assert+ : mapMaybe+ Natural+ Text+ ( λ(n : Natural) →+ if Natural/isZero n then None Text else Some (Natural/show n)+ )+ [ 0, 1, 2, 3 ]+ ≡ [ "1", "2", "3" ]++in mapMaybe
@@ -0,0 +1,41 @@+--| Transform a list by applying a function to each element with its index+let List/map =+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ ? ./map.dhall++let List/mapWithIndex+ : ∀(a : Type) → ∀(b : Type) → (Natural → a → b) → List a → List b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : Natural → a → b) →+ λ(xs : List a) →+ List/map+ { index : Natural, value : a }+ b+ (λ(i : { index : Natural, value : a }) → f i.index i.value)+ (List/indexed a xs)++let List/empty =+ missing+ sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+ ? ./empty.dhall++let List/replicate =+ missing+ sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+ ? ./replicate.dhall++let example0 =+ assert+ : List/mapWithIndex+ Text+ (List Text)+ ( λ(index : Natural) →+ λ(value : Text) →+ List/replicate index Text value+ )+ [ "A", "B", "C" ]+ ≡ [ List/empty Text, [ "B" ], [ "C", "C" ] ]++in List/mapWithIndex
@@ -1,2 +1,3 @@- ./null.dhall sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80+ missing+ sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80 ? ./null.dhall
@@ -1,82 +1,125 @@ { all =- ./all.dhall sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15+ missing+ sha256:7ac5bb6f77e9ffe9e2356d90968d39764a9a32f75980206e6b12f815bb83dd15 ? ./all.dhall , any =- ./any.dhall sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8+ missing+ sha256:b8e9e13b25e799f342a81f6eda4075906eb1a19dfdcb10a0ca25925eba4033b8 ? ./any.dhall , build =- ./build.dhall sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42+ missing+ sha256:8cf73fc1e115cfcb79bb9cd490bfcbd45c824e93c57a0e64c86c0c72e9ebbe42 ? ./build.dhall , concat =- ./concat.dhall sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b+ missing+ sha256:54e43278be13276e03bd1afa89e562e94a0a006377ebea7db14c7562b0de292b ? ./concat.dhall , concatMap =- ./concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64 ? ./concatMap.dhall , default =- ./default.dhall sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379+ missing+ sha256:fd77809e497227403f42848ffcda05a3efab442d961027c34f3e31d5d24e6379 ? ./default.dhall , drop =- ./drop.dhall sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+ missing+ sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf ? ./drop.dhall , empty =- ./empty.dhall sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147+ missing+ sha256:b2f561f35098c457353723c93a22bd5de28d26ecc5370814bef9dfda421e0147 ? ./empty.dhall , filter =- ./filter.dhall sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6+ missing+ sha256:8ebfede5bbfe09675f246c33eb83964880ac615c4b1be8d856076fdbc4b26ba6 ? ./filter.dhall+, filterMap =+ missing+ sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+ ? ./filterMap.dhall , fold =- ./fold.dhall sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814+ missing+ sha256:10bb945c25ab3943bd9df5a32e633cbfae112b7d3af38591784687e436a8d814 ? ./fold.dhall+, foldLeft =+ missing+ sha256:3c6ab57950fe644906b7bbdef0b9523440b6ee17773ebb8cbd41ffacb8bfab61+ ? ./foldLeft.dhall , generate =- ./generate.dhall sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4+ missing+ sha256:78ff1ad96c08b88a8263eea7bc8381c078225cfcb759c496f792edb5a5e0b1a4 ? ./generate.dhall , head =- ./head.dhall sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026+ missing+ sha256:0d2e65ba0aea908377e46d22020dc3ad970284f4ee4eb8e6b8c51e53038c0026 ? ./head.dhall , index =- ./index.dhall sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+ missing+ sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63 ? ./index.dhall , indexed =- ./indexed.dhall sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f+ missing+ sha256:58bb44457fa81adf26f5123c1b2e8bef0c5aa22dac5fa5ebdfb7da84563b027f ? ./indexed.dhall , iterate =- ./iterate.dhall sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26+ missing+ sha256:e4999ccce190a2e2a6ab9cb188e3af6c40df474087827153005293f11bfe1d26 ? ./iterate.dhall , last =- ./last.dhall sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d+ missing+ sha256:741226b741af152a1638491cdff7f3aa74baf080ada2e63429483f3d195a984d ? ./last.dhall , length =- ./length.dhall sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461+ missing+ sha256:42c6812c7a9e3c6e6fad88f77c5b3849503964e071cb784e22c38c888a401461 ? ./length.dhall , map =- ./map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ./map.dhall+, mapMaybe =+ missing+ sha256:6f3c4f8c94577b46e7d30f8df7e82a269b0ad0a7e18c0f0370f243fd1127e77f+ ? ./mapMaybe.dhall+, mapWithIndex =+ missing+ sha256:98599e0b55c5d3ae75264ba90657c6f68c7ce32834bd12b215acaea711eed6eb+ ? ./mapWithIndex.dhall , null =- ./null.dhall sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80+ missing+ sha256:2338e39637e9a50d66ae1482c0ed559bbcc11e9442bfca8f8c176bbcd9c4fc80 ? ./null.dhall , partition =- ./partition.dhall sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+ missing+ sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03 ? ./partition.dhall , replicate =- ./replicate.dhall sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+ missing+ sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347 ? ./replicate.dhall , reverse =- ./reverse.dhall sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d+ missing+ sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d ? ./reverse.dhall , shifted =- ./shifted.dhall sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+ missing+ sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe ? ./shifted.dhall , take =- ./take.dhall sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+ missing+ sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa ? ./take.dhall , unpackOptionals =- ./unpackOptionals.dhall sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+ missing+ sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4 ? ./unpackOptionals.dhall , unzip =- ./unzip.dhall sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+ missing+ sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9 ? ./unzip.dhall , zip =- ./zip.dhall sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+ missing+ sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da ? ./zip.dhall }
@@ -1,2 +1,3 @@- ./partition.dhall sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+ missing+ sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03 ? ./partition.dhall
@@ -1,2 +1,3 @@- ./replicate.dhall sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+ missing+ sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347 ? ./replicate.dhall
@@ -1,2 +1,3 @@- ./reverse.dhall sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d+ missing+ sha256:ad99d224d61852de6696da5a7d04c98dbe676fe67d5e4ef4f19e9aaa27006e9d ? ./reverse.dhall
@@ -1,2 +1,3 @@- ./shifted.dhall sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+ missing+ sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe ? ./shifted.dhall
@@ -1,2 +1,3 @@- ./take.dhall sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa+ missing+ sha256:b3e08ee8c3a5bf3d8ccee6b2b2008fbb8e51e7373aef6f1af67ad10078c9fbfa ? ./take.dhall
@@ -1,6 +1,7 @@ --| Truncate a list to the first `n` elements let Natural/lessThan =- ../Natural/lessThan.dhall sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+ missing+ sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c ? ../Natural/lessThan.dhall let take
@@ -1,2 +1,3 @@- ./unpackOptionals.dhall sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4+ missing+ sha256:0cbaa920f429cf7fc3907f8a9143203fe948883913560e6e1043223e6b3d05e4 ? ./unpackOptionals.dhall
@@ -1,16 +1,12 @@ --| Unpack Optionals in a List, omitting None items.--let List/concatMap =- ./concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64- ? ./concatMap.dhall--let Optional/toList =- ../Optional/toList.dhall sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4- ? ../Optional/toList.dhall+let List/filterMap =+ missing+ sha256:94b7ed4204d1c79aaf55527ef51024e7085b8dd2896952cffbd12d8f95e16f46+ ? ./filterMap.dhall let unpackOptionals : ∀(a : Type) → ∀(l : List (Optional a)) → List a- = λ(a : Type) → List/concatMap (Optional a) a (Optional/toList a)+ = λ(a : Type) → List/filterMap (Optional a) a (λ(x : Optional a) → x) let property1 = λ(a : Type) → λ(x : a) → assert : unpackOptionals a [ Some x ] ≡ [ x ]
@@ -1,2 +1,3 @@- ./unzip.dhall sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9+ missing+ sha256:4d6003e9e683a289fe33f4c90f958eb1e08ea0bbb474210fcd90d1885c9660e9 ? ./unzip.dhall
@@ -1,2 +1,3 @@- ./zip.dhall sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+ missing+ sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da ? ./zip.dhall
@@ -4,7 +4,8 @@ The resulting `List` will have the length of the shortest of its arguments. -} let List/index =- ./index.dhall sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+ missing+ sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63 ? ./index.dhall let zip
@@ -1,2 +1,3 @@- ./Type.dhall sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+ missing+ sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529 ? ./Type.dhall
@@ -5,8 +5,7 @@ let example0 = assert- : missing sha256:f428188ff9d77ea15bc2bcd0da3f8ed81b304e175b07ade42a3b0fb02941b2aa as Location- ? missing as Location+ : missing as Location ≡ < Environment : Text | Local : Text | Missing
@@ -1,4 +1,5 @@ { Type =- ./Type.dhall sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529+ missing+ sha256:613ebb491aeef4ff06368058b4f0e6e3bb8a58d8c145131fc0b947aac045a529 ? ./Type.dhall }
@@ -1,2 +1,3 @@- ./Entry.dhall sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry.dhall
@@ -1,2 +1,3 @@- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall
@@ -1,2 +1,3 @@- ./empty.dhall sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+ missing+ sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52 ? ./empty.dhall
@@ -1,6 +1,7 @@ --| An empty `Map` of the given key and value types let Map =- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall let empty
@@ -1,2 +1,3 @@- ./keyText.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./keyText.dhall
@@ -1,2 +1,3 @@- ./keyValue.dhall sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+ missing+ sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c ? ./keyValue.dhall
@@ -1,2 +1,3 @@- ./keys.dhall sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+ missing+ sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7 ? ./keys.dhall
@@ -1,14 +1,17 @@ --| Get all of the keys of a `Map` as a `List` let Map =- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall let Entry =- ./Entry.dhall sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry.dhall let List/map =- ../List/map sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map let keys
@@ -1,2 +1,3 @@- ./map.dhall sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+ missing+ sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0 ? ./map.dhall
@@ -1,14 +1,17 @@ --| Transform a `Map` by applying a function to each value let Map =- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall let Entry =- ./Entry.dhall sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let map
@@ -0,0 +1,56 @@+--| Apply a function across the values of a `Map k v`, dropping+-- entries whose values return `None`.+let Map/empty =+ missing+ sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+ ? ./empty.dhall++let Map/unpackOptionals =+ missing+ sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+ ? ./unpackOptionals.dhall++let Map/map =+ missing+ sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+ ? ./map.dhall++let Map/Type =+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ ? ./Type.dhall++let mapMaybe+ : ∀(k : Type) →+ ∀(a : Type) →+ ∀(b : Type) →+ (a → Optional b) →+ Map/Type k a →+ Map/Type k b+ = λ(k : Type) →+ λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ λ(m : Map/Type k a) →+ Map/unpackOptionals k b (Map/map k a (Optional b) f m)++let property =+ λ(k : Type) →+ λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ assert : mapMaybe k a b f (Map/empty k a) ≡ Map/empty k b++let example0 =+ assert+ : mapMaybe+ Text+ Natural+ Text+ ( λ(n : Natural) →+ if Natural/isZero n then None Text else Some (Natural/show n)+ )+ (toMap { foo = 2, bar = 0 })+ ≡ toMap { foo = "2" }++in mapMaybe
@@ -1,28 +1,41 @@ { Type =- ./Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type , Entry =- ./Entry sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry , empty =- ./empty sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52+ missing+ sha256:4c612558b8bbe8f955550ed3fb295d57b1b864c85cd52615b52d0ee0e9682e52 ? ./empty , keyText =- ./keyText sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./keyText , keyValue =- ./keyValue sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c+ missing+ sha256:a0a97199d280c4cce72ffcbbf93b7ceda0a569cf4d173ac98e0aaaa78034b98c ? ./keyValue , keys =- ./keys sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7+ missing+ sha256:d13ec34e6acf7c349d82272ef09a37c7bdf37f0dab489e9df47a1ff215d9f5e7 ? ./keys , map =- ./map sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0+ missing+ sha256:23e09b0b9f08649797dfe1ca39755d5e1c7cad2d0944bdd36c7a0bf804bde8d0 ? ./map+, mapMaybe =+ missing+ sha256:4ea58b720d7af38cef3ef07bef36e476caeed21032cd4a9dc733868a74d9a521+ ? ./mapMaybe.dhall , unpackOptionals =- ./unpackOptionals.dhall sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22+ missing+ sha256:66c3e6f6f81418cf99342e1dba739617c01af4b27c1ca5e2e1d7bce64a522e22 ? ./unpackOptionals.dhall , values =- ./values sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+ missing+ sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8 ? ./values }
@@ -1,16 +1,18 @@ --| Turn a `Map k (Optional v)` into a `Map k v` by dropping all -- entries with value `None`.- let List/concatMap =- ../List/concatMap.dhall sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64 ? ../List/concatMap.dhall let Map/Entry =- ./Entry.dhall sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry.dhall let Map/Type =- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall let unpackOptionals
@@ -1,2 +1,3 @@- ./values.dhall sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8+ missing+ sha256:ae02cfb06a9307cbecc06130e84fd0c7b96b7f1f11648961e1b030ec00940be8 ? ./values.dhall
@@ -1,14 +1,17 @@ --| Get all of the values of a `Map` as a `List` let Map =- ./Type.dhall sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed+ missing+ sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed ? ./Type.dhall let Entry =- ./Entry.dhall sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346+ missing+ sha256:f334283bdd9cd88e6ea510ca914bc221fc2dab5fb424d24514b2e0df600d5346 ? ./Entry.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let values
@@ -1,2 +1,3 @@- ./Monoid.dhall sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+ missing+ sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af ? ./Monoid.dhall
@@ -1,2 +1,3 @@- ./build.dhall sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c+ missing+ sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c ? ./build.dhall
@@ -1,2 +1,3 @@- ./enumerate.dhall sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+ missing+ sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3 ? ./enumerate.dhall
@@ -1,2 +1,3 @@- ./equal.dhall sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+ missing+ sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60 ? ./equal.dhall
@@ -1,6 +1,7 @@ --| `equal` checks if two Naturals are equal. let lessThanEqual =- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall let equal
@@ -1,2 +1,3 @@- ./even.dhall sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66+ missing+ sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66 ? ./even.dhall
@@ -1,2 +1,3 @@- ./fold.dhall sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+ missing+ sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06 ? ./fold.dhall
@@ -12,24 +12,17 @@ natural = Natural/fold -let example0 = assert : fold 3 Natural (λ(x : Natural) → 5 * x) 1 ≡ 125+let example0 = assert : fold 3 Text (λ(x : Text) → "A" ++ x) "B" ≡ "AAAB" let example1 =- assert- : (λ(zero : Natural) → fold 3 Natural (λ(x : Natural) → 5 * x) zero)- ≡ (λ(zero : Natural) → 5 * (5 * (5 * zero)))+ λ(zero : Text) →+ assert+ : fold 3 Text (λ(x : Text) → "A" ++ x) zero+ ≡ "A" ++ ("A" ++ ("A" ++ zero)) let example2 =- assert- : ( λ(natural : Type) →- λ(succ : natural → natural) →- λ(zero : natural) →- fold 3 natural succ zero- )- ≡ ( λ(natural : Type) →- λ(succ : natural → natural) →- λ(zero : natural) →- succ (succ (succ zero))- )+ λ(succ : Text → Text) →+ λ(zero : Text) →+ assert : fold 3 Text succ zero ≡ succ (succ (succ zero)) in fold
@@ -1,2 +1,3 @@- ./greaterThan.dhall sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+ missing+ sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c ? ./greaterThan.dhall
@@ -1,6 +1,7 @@ --| `greaterThan` checks if one Natural is strictly greater than another. let lessThan =- ./lessThan.dhall sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+ missing+ sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c ? ./lessThan.dhall let greaterThan
@@ -1,2 +1,3 @@- ./greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ./greaterThanEqual.dhall
@@ -2,7 +2,8 @@ `greaterThanEqual` checks if one Natural is greater than or equal to another. -} let lessThanEqual =- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall let greaterThanEqual
@@ -1,2 +1,3 @@- ./isZero.dhall sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+ missing+ sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1 ? ./isZero.dhall
@@ -1,2 +1,3 @@- ./lessThan.dhall sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+ missing+ sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c ? ./lessThan.dhall
@@ -1,10 +1,12 @@ --| `lessThan` checks if one Natural is strictly less than another. let greaterThanEqual =- ./greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ./greaterThanEqual.dhall let Bool/not =- ../Bool/not.dhall sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4+ missing+ sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4 ? ../Bool/not.dhall let lessThan
@@ -1,2 +1,3 @@- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall
@@ -1,2 +1,3 @@- ./listMax.dhall sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+ missing+ sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472 ? ./listMax.dhall
@@ -3,11 +3,13 @@ `List` is empty -} let max =- ./max.dhall sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+ missing+ sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7 ? ./max.dhall let Optional/map =- ../Optional/map.dhall sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+ missing+ sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa ? ../Optional/map.dhall let listMax
@@ -1,2 +1,3 @@- ./listMin.dhall sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+ missing+ sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6 ? ./listMin.dhall
@@ -3,11 +3,13 @@ `List` is empty -} let min =- ./min.dhall sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+ missing+ sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710 ? ./min.dhall let Optional/map =- ../Optional/map.dhall sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+ missing+ sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa ? ../Optional/map.dhall let listMin
@@ -1,2 +1,3 @@- ./max.dhall sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+ missing+ sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7 ? ./max.dhall
@@ -1,6 +1,7 @@ --| `max a b` returns the larger of `a` or `b` let lessThanEqual =- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall let max
@@ -1,2 +1,3 @@- ./min.dhall sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+ missing+ sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710 ? ./min.dhall
@@ -1,6 +1,7 @@ --| `min a b` returns the smaller of `a` or `b` let lessThanEqual =- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall let min
@@ -1,2 +1,3 @@- ./odd.dhall sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5+ missing+ sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5 ? ./odd.dhall
@@ -1,67 +1,89 @@ { build =- ./build.dhall sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c+ missing+ sha256:e7e25e6c4f1d8e573606ed1bef725396ac2de5c68f7c5d329ffc5822085b984c ? ./build.dhall , enumerate =- ./enumerate.dhall sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3+ missing+ sha256:0cf083980a752b21ce0df9fc2222a4c139f50909e2353576e26a191002aa1ce3 ? ./enumerate.dhall , even =- ./even.dhall sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66+ missing+ sha256:b85b8b56892dfef881e1c0e79eade0b949528f792aac0ea42432b315ede4ee66 ? ./even.dhall , fold =- ./fold.dhall sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06+ missing+ sha256:fd01c931e585a8f5fd049af7b076b862ea164f1813b34800c7616a49e549ee06 ? ./fold.dhall , isZero =- ./isZero.dhall sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1+ missing+ sha256:1be98236800ed2d5cff44f16ca02b34b0c37dfa239d9e0d63d9d2c6eeae3d1d1 ? ./isZero.dhall , odd =- ./odd.dhall sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5+ missing+ sha256:ab3c729262c642ec1cdb72a81e910fcfaf2aea13e3961d0bf1bec83efea5aac5 ? ./odd.dhall , product =- ./product.dhall sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6+ missing+ sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6 ? ./product.dhall , sum =- ./sum.dhall sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037+ missing+ sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037 ? ./sum.dhall , show =- ./show.dhall sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21+ missing+ sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21 ? ./show.dhall , toDouble =- ./toDouble.dhall sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81+ missing+ sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81 ? ./toDouble.dhall , toInteger =- ./toInteger.dhall sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f+ missing+ sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f ? ./toInteger.dhall , lessThan =- ./lessThan.dhall sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c+ missing+ sha256:3381b66749290769badf8855d8a3f4af62e8de52d1364d838a9d1e20c94fa70c ? ./lessThan.dhall , lessThanEqual =- ./lessThanEqual.dhall sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99+ missing+ sha256:1a5caa2b80a42b9f58fff58e47ac0d9a9946d0b2d36c54034b8ddfe3cb0f3c99 ? ./lessThanEqual.dhall , equal =- ./equal.dhall sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60+ missing+ sha256:7f108edfa35ddc7cebafb24dc073478e93a802e13b5bc3fd22f4768c9b066e60 ? ./equal.dhall , greaterThanEqual =- ./greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ./greaterThanEqual.dhall , greaterThan =- ./greaterThan.dhall sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c+ missing+ sha256:f702abcdfcd7ad73619b9285d7e41c3a1d017fb6b8d037cf40bd93bf30c09b2c ? ./greaterThan.dhall , min =- ./min.dhall sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710+ missing+ sha256:f25f9c462e4dbf0eb15f9ff6ac840c6e9c82255a7f4f2ab408bdab338e028710 ? ./min.dhall , max =- ./max.dhall sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7+ missing+ sha256:1f3b18da330223ab039fad11693da72c7e68d516f50502c73f41a89a097b62f7 ? ./max.dhall , listMin =- ./listMin.dhall sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+ missing+ sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6 ? ./listMin.dhall , listMax =- ./listMax.dhall sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472+ missing+ sha256:20906ffcc9970f740106d4516cb7868b43d75ff8c9f00ff8a9680ae68c48a472 ? ./listMax.dhall , sort =- ./sort.dhall sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+ missing+ sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260 ? ./sort.dhall , subtract =- ./subtract.dhall sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+ missing+ sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745 ? ./subtract.dhall }
@@ -1,2 +1,3 @@- ./product.dhall sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6+ missing+ sha256:e3e6fd76207875b81d39f79fdbc90b5e640444c04fb3d84c2c9326748f0b26e6 ? ./product.dhall
@@ -1,2 +1,3 @@- ./show.dhall sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21+ missing+ sha256:684ed560ad86f438efdea229eca122c29e8e14f397ed32ec97148d578ca5aa21 ? ./show.dhall
@@ -1,2 +1,3 @@- ./sort.dhall sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260+ missing+ sha256:36ce8b3e5538454763987ca904d8d7c5ba34c2147434a19eddd51f684432b260 ? ./sort.dhall
@@ -1,14 +1,17 @@ --| `sort` sorts a `List` of `Natural`s in ascending order let greaterThanEqual =- ./greaterThanEqual.dhall sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4+ missing+ sha256:30ebfab0febd7aa0ccccfdf3dc36ee6d50f0117f35dd4a9b034750b7e885a1a4 ? ./greaterThanEqual.dhall let listMin =- ./listMin.dhall sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6+ missing+ sha256:ee70b0d010bbca6012162e8ae1f6e9d9bd10a152675509b0f23145b98b5d43c6 ? ./listMin.dhall let List/partition =- ../List/partition.dhall sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03+ missing+ sha256:38147ac6d750a6492736dd90cc967bf09aa405c499de943c64fab7b86ae02f03 ? ../List/partition.dhall let Accumulator = { sorted : List Natural, rest : List Natural }
@@ -1,2 +1,3 @@- ./subtract.dhall sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745+ missing+ sha256:b9277ac637d09142a3a3ac79137ef5955c42f8b33b6746d59db2c9d75ccdd745 ? ./subtract.dhall
@@ -1,2 +1,3 @@- ./sum.dhall sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037+ missing+ sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037 ? ./sum.dhall
@@ -1,2 +1,3 @@- ./toDouble.dhall sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81+ missing+ sha256:d5eb52143dcd35b46a6f0cdb2d3cbf31a14b6daeba56e29066f8e344c9fb6e81 ? ./toDouble.dhall
@@ -1,2 +1,3 @@- ./toInteger.dhall sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f+ missing+ sha256:160d2d278619f3da34a1f4f02e739a447e4f2aa5a2978c45b710515b41491e1f ? ./toInteger.dhall
@@ -0,0 +1,9 @@+{-|+A `NonEmpty` list has at least one element and supports many of the same+operations as `List`s+-}+let NonEmpty+ : Type → Type+ = λ(a : Type) → { head : a, tail : List a }++in NonEmpty
@@ -0,0 +1,34 @@+{-|+Returns `True` if the supplied function returns `True` for all elements in the+`NonEmpty` list+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall++let all+ : ∀(a : Type) → (a → Bool) → NonEmpty a → Bool+ = λ(a : Type) →+ λ(f : a → Bool) →+ λ(xs : NonEmpty a) →+ List/fold+ a+ (NonEmpty/toList a xs)+ Bool+ (λ(x : a) → λ(r : Bool) → f x && r)+ True++let example0 =+ assert : all Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ False++let example1 =+ assert+ : all Natural Natural/even { head = 2, tail = [] : List Natural } ≡ True++in all
@@ -0,0 +1,34 @@+{-|+Returns `True` if the supplied function returns `True` for any element in the+`NonEmpty` list+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall++let any+ : ∀(a : Type) → (a → Bool) → NonEmpty a → Bool+ = λ(a : Type) →+ λ(f : a → Bool) →+ λ(xs : NonEmpty a) →+ List/fold+ a+ (NonEmpty/toList a xs)+ Bool+ (λ(x : a) → λ(r : Bool) → f x || r)+ False++let example0 =+ assert : any Natural Natural/even { head = 2, tail = [ 3, 5 ] } ≡ True++let example1 =+ assert+ : any Natural Natural/even { head = 3, tail = [] : List Natural } ≡ False++in any
@@ -0,0 +1,61 @@+{-|+Concatenate a `NonEmpty` list of `NonEmpty` lists into a single `NonEmpty`+list+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall++let List/concatMap =+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ ? ../List/concatMap.dhall++let concat+ : ∀(a : Type) → NonEmpty (NonEmpty a) → NonEmpty a+ = λ(a : Type) →+ λ(xss : NonEmpty (NonEmpty a)) →+ { head = xss.head.head+ , tail =+ xss.head.tail+ # List/concatMap (NonEmpty a) a (NonEmpty/toList a) xss.tail+ }++let example0 =+ assert+ : concat+ Natural+ { head = { head = 0, tail = [ 1, 2 ] }+ , tail =+ [ { head = 3, tail = [ 4 ] }, { head = 5, tail = [ 6, 7, 8 ] } ]+ }+ ≡ { head = 0, tail = [ 1, 2, 3, 4, 5, 6, 7, 8 ] }++let example1 =+ assert+ : concat+ Natural+ { head = { head = 0, tail = [] : List Natural }+ , tail =+ [ { head = 1, tail = [] : List Natural }+ , { head = 2, tail = [] : List Natural }+ ]+ }+ ≡ { head = 0, tail = [ 1, 2 ] : List Natural }++let example2 =+ assert+ : concat+ Natural+ { head = { head = 0, tail = [] : List Natural }+ , tail = [] : List (NonEmpty Natural)+ }+ ≡ { head = 0, tail = [] : List Natural }++in concat
@@ -0,0 +1,56 @@+{-|+Transform a `NonEmpty` list by applying a function to each element and+flattening the results+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall++let List/concatMap =+ missing+ sha256:3b2167061d11fda1e4f6de0522cbe83e0d5ac4ef5ddf6bb0b2064470c5d3fb64+ ? ../List/concatMap.dhall++let concatMap+ : ∀(a : Type) → ∀(b : Type) → (a → NonEmpty b) → NonEmpty a → NonEmpty b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : a → NonEmpty b) →+ λ(xs : NonEmpty a) →+ let ys = f xs.head++ in { head = ys.head+ , tail =+ ys.tail+ # List/concatMap+ a+ b+ (λ(x : a) → NonEmpty/toList b (f x))+ xs.tail+ }++let example0 =+ assert+ : concatMap+ Natural+ Natural+ (λ(n : Natural) → { head = n, tail = [ n ] })+ { head = 2, tail = [ 3, 5 ] }+ ≡ { head = 2, tail = [ 2, 3, 3, 5, 5 ] }++let example1 =+ assert+ : concatMap+ Natural+ Natural+ (λ(n : Natural) → { head = n, tail = [ n ] })+ { head = 2, tail = [] : List Natural }+ ≡ { head = 2, tail = [ 2 ] }++in concatMap
@@ -0,0 +1,13 @@+--| Retrieve the first element of the `NonEmpty` list+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let head+ : ∀(a : Type) → NonEmpty a → a+ = λ(a : Type) → λ(xs : NonEmpty a) → xs.head++let example = assert : head Natural { head = 0, tail = [ 1, 2 ] } ≡ 0++in head
@@ -0,0 +1,33 @@+--| Retrieve an element from a `NonEmpty` list using its 0-based index+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let List/index =+ missing+ sha256:e657b55ecae4d899465c3032cb1a64c6aa6dc2aa3034204f3c15ce5c96c03e63+ ? ../List/index.dhall++let index+ : Natural → ∀(a : Type) → NonEmpty a → Optional a+ = λ(n : Natural) →+ λ(a : Type) →+ λ(xs : NonEmpty a) →+ if Natural/isZero n+ then Some xs.head+ else List/index (Natural/subtract 1 n) a xs.tail++let property =+ λ(n : Natural) →+ λ(a : Type) →+ λ(xs : NonEmpty a) →+ assert : index 0 a xs ≡ Some xs.head++let example0 = assert : index 1 Natural { head = 2, tail = [ 3, 5 ] } ≡ Some 3++let example1 =+ assert+ : index 1 Natural { head = 2, tail = [] : List Natural } ≡ None Natural++in index
@@ -0,0 +1,41 @@+--| Tag each element of the `NonEmpty` list with its index+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let List/map =+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ ? ../List/map.dhall++let indexed+ : ∀(a : Type) → NonEmpty a → NonEmpty { index : Natural, value : a }+ = λ(a : Type) →+ λ(xs : NonEmpty a) →+ { head = { index = 0, value = xs.head }+ , tail =+ List/map+ { index : Natural, value : a }+ { index : Natural, value : a }+ ( λ(ix : { index : Natural, value : a }) →+ { index = ix.index + 1, value = ix.value }+ )+ (List/indexed a xs.tail)+ }++let example0 =+ assert+ : indexed Bool { head = True, tail = [ False, True ] }+ ≡ { head = { index = 0, value = True }+ , tail = [ { index = 1, value = False }, { index = 2, value = True } ]+ }++let example1 =+ assert+ : indexed Bool { head = True, tail = [] : List Bool }+ ≡ { head = { index = 0, value = True }+ , tail = [] : List { index : Natural, value : Bool }+ }++in indexed
@@ -0,0 +1,17 @@+--| Retrieve the last element of the `NonEmpty` list+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let last+ : ∀(a : Type) → NonEmpty a → a+ = λ(a : Type) →+ λ(xs : NonEmpty a) →+ merge { Some = λ(x : a) → x, None = xs.head } (List/last a xs.tail)++let example0 = assert : last Natural { head = 0, tail = [ 1, 2 ] } ≡ 2++let example1 = assert : last Natural { head = 0, tail = [] : List Natural } ≡ 0++in last
@@ -0,0 +1,16 @@+--| Returns the number of elements in a `NonEmpty` list+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let length+ : ∀(a : Type) → NonEmpty a → Natural+ = λ(a : Type) → λ(xs : NonEmpty a) → List/length a xs.tail + 1++let example0 = assert : length Natural { head = 0, tail = [ 1, 2 ] } ≡ 3++let example1 =+ assert : length Natural { head = 0, tail = [] : List Natural } ≡ 1++in length
@@ -0,0 +1,18 @@+{-|+Create a `NonEmpty` list using a function instead of a record++This might come in handy if you want to decouple the `NonEmpty` list+construction from the specific names of the fields.+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let make+ : ∀(a : Type) → ∀(head : a) → ∀(tail : List a) → NonEmpty a+ = λ(a : Type) → λ(head : a) → λ(tail : List a) → { head, tail }++let example = assert : make Natural 1 [ 2, 3 ] ≡ { head = 1, tail = [ 2, 3 ] }++in make
@@ -0,0 +1,30 @@+--| Transform a `NonEmpty` list by applying a function to each element+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let List/map =+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ ? ../List/map.dhall++let map+ : ∀(a : Type) → ∀(b : Type) → (a → b) → NonEmpty a → NonEmpty b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : a → b) →+ λ(xs : NonEmpty a) →+ { head = f xs.head, tail = List/map a b f xs.tail }++let example0 =+ assert+ : map Natural Bool Natural/even { head = 2, tail = [ 3, 5 ] }+ ≡ { head = True, tail = [ False, False ] }++let example1 =+ assert+ : map Natural Bool Natural/even { head = 2, tail = [] : List Natural }+ ≡ { head = True, tail = [] : List Bool }++in map
@@ -0,0 +1,73 @@+{ Type =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall+, all =+ missing+ sha256:f2f9389d94f4deb5b918b2e50c1093b57e00b37ddd3ab2b43959993b1cb519b6+ ? ./all.dhall+, any =+ missing+ sha256:7662b665840e41b12a28190eec3aaab9201fcb90c00a8ec3666d549e1020992f+ ? ./any.dhall+, concat =+ missing+ sha256:6d55181938c06c6b806877028f6a241912e9c0935d9a10dd958775bf21e0f64d+ ? ./concat.dhall+, concatMap =+ missing+ sha256:fc33fa9449dc8f74dd8c8be379b7b7c4b0433e2b65650370d81d9a7111a590e2+ ? ./concatMap.dhall+, head =+ missing+ sha256:6b9551c97b89fe666d2e03392a4af5e87abfdbdb0aa0e29fc4b3aa1b318474e7+ ? ./head.dhall+, index =+ missing+ sha256:0ba2fcc9227fab10676cd61b47a18d779818a19c16727c7cc4b4c78e114fd663+ ? ./index.dhall+, indexed =+ missing+ sha256:9dae2c1fecd142df837e98769b5bbdd0bfe25c35a93af1064b4e62f9c780ae6b+ ? ./indexed.dhall+, last =+ missing+ sha256:f83115492b6e408d0b662a68440620f7f3df07b56e7ed66dab77a6e65b121250+ ? ./last.dhall+, length =+ missing+ sha256:eef3b857a164487cfdb960e3298c4731970b7a430011289cba35a9ad722ac989+ ? ./length.dhall+, make =+ missing+ sha256:549de393673c4773c80a50ea578ea50d7f2c4c2eda31956e73fabc4e486f3b1e+ ? ./make.dhall+, map =+ missing+ sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+ ? ./map.dhall+, reverse =+ missing+ sha256:a6d810cdd3badffd4e7ca82091609a855cffac900c82d7ff3724463fbc2d5ff2+ ? ./reverse.dhall+, shifted =+ missing+ sha256:36156973d6916aed10cfd8c59be7c019516bf0a2c47b499a17a8ef0611e1c189+ ? ./shifted.dhall+, singleton =+ missing+ sha256:c9197aabe97695f7ca66f7419bf172d806b2c915594a8fc0d2ff6495db496ff2+ ? ./singleton.dhall+, toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall+, unzip =+ missing+ sha256:d0b925bea32a29aad5cb48a84e8ef8cff750308afe1dd20b24eca19e4e999abc+ ? ./unzip.dhall+, zip =+ missing+ sha256:073f8b4808b6d1db84964f772f6291e6ea193602163438db43fa282c560c01e4+ ? ./zip.dhall+}
@@ -0,0 +1,35 @@+--| Reverse a `NonEmpty` list+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let List/drop =+ missing+ sha256:af983ba3ead494dd72beed05c0f3a17c36a4244adedf7ced502c6512196ed0cf+ ? ../List/drop.dhall++let reverse+ : ∀(a : Type) → NonEmpty a → NonEmpty a+ = λ(a : Type) →+ λ(xs : NonEmpty a) →+ let ys = List/reverse a xs.tail++ in merge+ { Some =+ λ(y : a) → { head = y, tail = List/drop 1 a ys # [ xs.head ] }+ , None = { head = xs.head, tail = [] : List a }+ }+ (List/head a ys)++let example =+ assert+ : reverse Natural { head = 0, tail = [ 1, 2 ] }+ ≡ { head = 2, tail = [ 1, 0 ] }++let example1 =+ assert+ : reverse Natural { head = 0, tail = [] : List Natural }+ ≡ { head = 0, tail = [] : List Natural }++in reverse
@@ -0,0 +1,101 @@+{-|+Combine a `NonEmpty` list of `NonEmpty` lists, offsetting the `index` of each+element by the number of elements in preceding lists+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/toList =+ missing+ sha256:0977fe14b77232a4451dcf409c43df4589c4b3cdde7b613aab8df183be1b53f5+ ? ./toList.dhall++let List/map =+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ ? ../List/map.dhall++let List/shifted =+ missing+ sha256:54fb22c7e952ebce1cfc0fcdd33ce4cfa817bff9d6564af268dea6685f8b5dfe+ ? ../List/shifted.dhall++let shifted+ : ∀(a : Type) →+ NonEmpty (NonEmpty { index : Natural, value : a }) →+ NonEmpty { index : Natural, value : a }+ = λ(a : Type) →+ λ(kvss : NonEmpty (NonEmpty { index : Natural, value : a })) →+ { head = kvss.head.head+ , tail =+ List/shifted+ a+ ( [ kvss.head.tail ]+ # List/map+ (NonEmpty { index : Natural, value : a })+ (List { index : Natural, value : a })+ ( λ(kvs : NonEmpty { index : Natural, value : a }) →+ List/map+ { index : Natural, value : a }+ { index : Natural, value : a }+ ( λ(kv : { index : Natural, value : a }) →+ { index = kv.index + 1, value = kv.value }+ )+ (NonEmpty/toList { index : Natural, value : a } kvs)+ )+ kvss.tail+ )+ }++let example0 =+ assert+ : shifted+ Bool+ { head =+ { head = { index = 0, value = True }+ , tail =+ [ { index = 1, value = True }, { index = 2, value = True } ]+ }+ , tail =+ [ { head = { index = 0, value = False }+ , tail = [ { index = 1, value = False } ]+ }+ , { head = { index = 0, value = True }+ , tail =+ [ { index = 1, value = True }+ , { index = 2, value = True }+ , { index = 3, value = True }+ ]+ }+ ]+ }+ ≡ { head = { index = 0, value = True }+ , tail =+ [ { index = 1, value = True }+ , { index = 2, value = True }+ , { index = 3, value = False }+ , { index = 4, value = False }+ , { index = 5, value = True }+ , { index = 6, value = True }+ , { index = 7, value = True }+ , { index = 8, value = True }+ ]+ }++let example1 =+ assert+ : shifted+ Bool+ { head =+ { head = { index = 0, value = True }+ , tail = [] : List { index : Natural, value : Bool }+ }+ , tail = [] : List (NonEmpty { index : Natural, value : Bool })+ }+ ≡ { head = { index = 0, value = True }+ , tail = [] : List { index : Natural, value : Bool }+ }++in shifted
@@ -0,0 +1,14 @@+--| Create a `NonEmpty` list with just one element+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let singleton+ : ∀(a : Type) → a → NonEmpty a+ = λ(a : Type) → λ(x : a) → { head = x, tail = [] : List a }++let example =+ assert : singleton Natural 2 ≡ { head = 2, tail = [] : List Natural }++in singleton
@@ -0,0 +1,17 @@+--| Convert a `NonEmpty` list into the equivalent `List`+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let toList+ : ∀(a : Type) → NonEmpty a → List a+ = λ(a : Type) → λ(xs : NonEmpty a) → [ xs.head ] # xs.tail++let example0 =+ assert : toList Natural { head = 2, tail = [ 3, 5 ] } ≡ [ 2, 3, 5 ]++let example1 =+ assert : toList Natural { head = 2, tail = [] : List Natural } ≡ [ 2 ]++in toList
@@ -0,0 +1,58 @@+--| Unzip a `NonEmpty` list into two separate `NonEmpty` lists+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let NonEmpty/map =+ missing+ sha256:93d53afe874bb2eed946c21ca5ada3c9716b7d00e6d8edfaba6484cd9c5a00bd+ ? ./map.dhall++let unzip+ : ∀(a : Type) →+ ∀(b : Type) →+ NonEmpty { _1 : a, _2 : b } →+ { _1 : NonEmpty a, _2 : NonEmpty b }+ = λ(a : Type) →+ λ(b : Type) →+ λ(xs : NonEmpty { _1 : a, _2 : b }) →+ { _1 =+ NonEmpty/map+ { _1 : a, _2 : b }+ a+ (λ(x : { _1 : a, _2 : b }) → x._1)+ xs+ , _2 =+ NonEmpty/map+ { _1 : a, _2 : b }+ b+ (λ(x : { _1 : a, _2 : b }) → x._2)+ xs+ }++let example0 =+ assert+ : unzip+ Text+ Bool+ { head = { _1 = "ABC", _2 = True }+ , tail = [ { _1 = "DEF", _2 = False }, { _1 = "GHI", _2 = True } ]+ }+ ≡ { _1 = { head = "ABC", tail = [ "DEF", "GHI" ] }+ , _2 = { head = True, tail = [ False, True ] }+ }++let example1 =+ assert+ : unzip+ Text+ Bool+ { head = { _1 = "ABC", _2 = True }+ , tail = [] : List { _1 : Text, _2 : Bool }+ }+ ≡ { _1 = { head = "ABC", tail = [] : List Text }+ , _2 = { head = True, tail = [] : List Bool }+ }++in unzip
@@ -0,0 +1,63 @@+{-|+Zip two `NonEmpty` lists into a single `NonEmpty`++The resulting `NonEmpty` will have the length of the shortest of its arguments.+-}+let NonEmpty =+ missing+ sha256:e2e247455a858317e470e0e4affca8ac07f9f130570ece9cb7ac1f4ea3deb87f+ ? ./Type.dhall++let List/zip =+ missing+ sha256:85ed955eabf3998767f4ad2a28e57d40cd4c68a95519d79e9b622f1d26d979da+ ? ../List/zip.dhall++let zip+ : ∀(a : Type) →+ NonEmpty a →+ ∀(b : Type) →+ NonEmpty b →+ NonEmpty { _1 : a, _2 : b }+ = λ(a : Type) →+ λ(xs : NonEmpty a) →+ λ(b : Type) →+ λ(ys : NonEmpty b) →+ { head = { _1 = xs.head, _2 = ys.head }+ , tail = List/zip a xs.tail b ys.tail+ }++let example0 =+ assert+ : zip+ Text+ { head = "ABC", tail = [ "DEF", "GHI" ] }+ Natural+ { head = 1, tail = [ 2, 3 ] }+ ≡ { head = { _1 = "ABC", _2 = 1 }+ , tail = [ { _1 = "DEF", _2 = 2 }, { _1 = "GHI", _2 = 3 } ]+ }++let example1 =+ assert+ : zip+ Text+ { head = "ABC", tail = [ "DEF" ] }+ Bool+ { head = True, tail = [] : List Bool }+ ≡ { head = { _1 = "ABC", _2 = True }+ , tail = [] : List { _1 : Text, _2 : Bool }+ }++let example2 =+ assert+ : zip+ Text+ { head = "ABC", tail = [] : List Text }+ Natural+ { head = 1, tail = [ 2 ] }+ ≡ { head = { _1 = "ABC", _2 = 1 }+ , tail = [] : List { _1 : Text, _2 : Natural }+ }++in zip
@@ -0,0 +1,85 @@+{-+Note: This package does not use one file per function because the operator+names contain symbols such as `*` that may cause problems.+-}+let {-+ `+` m n++ computes `m + n`+ -} `+`+ : Natural → Natural → Natural+ = λ(m : Natural) → λ(n : Natural) → m + n++let example1 = assert : `+` 2 1 ≡ 3++let {-+ `*` m n++ computes `m * n`+ -} `*`+ : Natural → Natural → Natural+ = λ(m : Natural) → λ(n : Natural) → m * n++let example2 = assert : `*` 21 2 ≡ 42++let {-+ `++` m n++ computes `m ++ n`+ -} `++`+ : Text → Text → Text+ = λ(m : Text) → λ(n : Text) → m ++ n++let example3 = assert : `++` "Hello" "Dhall" ≡ "HelloDhall"++let {-+ `#` Type m n++ computes `m # n`+ -} `#`+ : ∀(type : Type) → List type → List type → List type+ = λ(type : Type) → λ(m : List type) → λ(n : List type) → m # n++let example4 = assert : `#` Natural [ 1, 2 ] [ 3 ] ≡ [ 1, 2, 3 ]++let {-+ `==` m n++ computes `m == n`+ -} `==`+ : Bool → Bool → Bool+ = λ(m : Bool) → λ(n : Bool) → m == n++let example5 = assert : `==` True False ≡ False++let {-+ `!=` m n++ computes `m != n`+ -} `!=`+ : Bool → Bool → Bool+ = λ(m : Bool) → λ(n : Bool) → m != n++let example6 = assert : `!=` True False ≡ True++let {-+ `&&` m n++ computes `m && n`+ -} `&&`+ : Bool → Bool → Bool+ = λ(m : Bool) → λ(n : Bool) → m && n++let example7 = assert : `&&` False True ≡ False++let {-+ `||` m n++ computes `m || n`+ -} `||`+ : Bool → Bool → Bool+ = λ(m : Bool) → λ(n : Bool) → m || n++let example8 = assert : `||` False True ≡ True++in { `+`, `*`, `++`, `#`, `==`, `!=`, `&&`, `||` }
@@ -1,2 +1,3 @@- ./all.dhall sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+ missing+ sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695 ? ./all.dhall
@@ -1,2 +1,3 @@- ./any.dhall sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+ missing+ sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435 ? ./any.dhall
@@ -1,2 +1,3 @@- ./build.dhall sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+ missing+ sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1 ? ./build.dhall
@@ -1,2 +1,3 @@- ./concat.dhall sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+ missing+ sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a ? ./concat.dhall
@@ -0,0 +1,23 @@+--| Transform the value with a function and flatten the resulting `Optional`+let concatMap+ : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → Optional a → Optional b+ = λ(a : Type) →+ λ(b : Type) →+ λ(f : a → Optional b) →+ λ(o : Optional a) →+ merge { Some = f, None = None b } o++let exampleFun+ : Natural → Optional Natural+ = λ(n : Natural) → if Natural/even n then Some (n + 1) else None Natural++let example0 =+ assert : concatMap Natural Natural exampleFun (Some 1) ≡ None Natural++let example1 = assert : concatMap Natural Natural exampleFun (Some 2) ≡ Some 3++let example2 =+ assert+ : concatMap Natural Natural exampleFun (None Natural) ≡ None Natural++in concatMap
@@ -1,2 +1,3 @@- ./default.dhall sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+ missing+ sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad ? ./default.dhall
@@ -0,0 +1,24 @@+let Optional/fold =+ missing+ sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+ ? ./fold.dhall++let Optional/null =+ missing+ sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+ ? ./null.dhall++let equal+ : forall (a : Type) -> (a -> a -> Bool) -> Optional a -> Optional a -> Bool+ = \(a : Type) ->+ \(compare : a -> a -> Bool) ->+ \(ox : Optional a) ->+ \(oy : Optional a) ->+ Optional/fold+ a+ ox+ Bool+ (\(x : a) -> Optional/fold a oy Bool (compare x) False)+ (Optional/null a oy)++in equal
@@ -1,2 +1,3 @@- ./filter.dhall sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+ missing+ sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83 ? ./filter.dhall
@@ -1,2 +1,3 @@- ./fold.dhall sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+ missing+ sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf ? ./fold.dhall
@@ -13,9 +13,8 @@ λ(none : optional) → merge { Some = some, None = none } o -let example0 = assert : fold Natural (Some 2) Natural (λ(x : Natural) → x) 0 ≡ 2+let example0 = assert : fold Natural (Some 2) Text Natural/show "0" ≡ "2" -let example1 =- assert : fold Natural (None Natural) Natural (λ(x : Natural) → x) 0 ≡ 0+let example1 = assert : fold Natural (None Natural) Text Natural/show "0" ≡ "0" in fold
@@ -1,2 +1,3 @@- ./head.dhall sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+ missing+ sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c ? ./head.dhall
@@ -1,2 +1,3 @@- ./last.dhall sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+ missing+ sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707 ? ./last.dhall
@@ -1,2 +1,3 @@- ./length.dhall sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+ missing+ sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85 ? ./length.dhall
@@ -1,2 +1,3 @@- ./map.dhall sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+ missing+ sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa ? ./map.dhall
@@ -1,2 +1,3 @@- ./null.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+ missing+ sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc ? ./null.dhall
@@ -1,43 +1,65 @@ { all =- ./all.dhall sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695+ missing+ sha256:a303004b6def0a2a05bf5f0a8d54e84dd45d8bef581789186ac04924956a1695 ? ./all.dhall , any =- ./any.dhall sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435+ missing+ sha256:96a5cf4f31b3c598b09161dd3082f0a09f4328a4cefda6a7e09894b37b17b435 ? ./any.dhall , build =- ./build.dhall sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1+ missing+ sha256:28e61294bf2dd59dc57cf74f719d1568e60b5ba46c28eac586bc937eff4a2af1 ? ./build.dhall , concat =- ./concat.dhall sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a+ missing+ sha256:b7736bd3ebeab14c3912dfb534d0c970a025b001d06c2d5461d4b0e289e3cb7a ? ./concat.dhall+, concatMap =+ missing+ sha256:c06ae93e900a99299c9b4ec4912ca5395a0103ea88292205b08dd7e345632818+ ? ./concatMap.dhall , default =- ./default.dhall sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad+ missing+ sha256:5bd665b0d6605c374b3c4a7e2e2bd3b9c1e39323d41441149ed5e30d86e889ad ? ./default.dhall+, equal =+ missing+ sha256:5411888399fe9c6720f7f3b59caf5eff3e8e8c30402d09f34e46a4457649a35a+ ? ./equal.dhall , filter =- ./filter.dhall sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83+ missing+ sha256:54f0a487d578801819613fe000050c038c632edf1f9ccc57677e98ae0ef56b83 ? ./filter.dhall , fold =- ./fold.dhall sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf+ missing+ sha256:c5b9d72f6f62bdaa0e196ac1c742cc175cd67a717b880fb8aec1333a5a4132cf ? ./fold.dhall , head =- ./head.dhall sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c+ missing+ sha256:4f256c9338b60a1933f41f2a8fafd861930a1e41770a644cdbac0622676fa34c ? ./head.dhall , last =- ./last.dhall sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707+ missing+ sha256:50400771ae19e9b75efa6581feec318ae1ade0b6a60e215df428c66c4b052707 ? ./last.dhall , length =- ./length.dhall sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85+ missing+ sha256:f168337c5244ded68c05ecf32ce068b6b87158881d07e87b8cb6853fc6982a85 ? ./length.dhall , map =- ./map.dhall sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa+ missing+ sha256:501534192d988218d43261c299cc1d1e0b13d25df388937add784778ab0054fa ? ./map.dhall , null =- ./null.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc+ missing+ sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc ? ./null.dhall , toList =- ./toList.dhall sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+ missing+ sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4 ? ./toList.dhall , unzip =- ./unzip.dhall sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+ missing+ sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708 ? ./unzip.dhall }
@@ -1,2 +1,3 @@- ./toList.dhall sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4+ missing+ sha256:d78f160c619119ef12389e48a629ce293d69f7624c8d016b7a4767ab400344c4 ? ./toList.dhall
@@ -1,2 +1,3 @@- ./unzip.dhall sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708+ missing+ sha256:d016c01ba91657a2f35609aa29087963d0f506bab0f41d5e8b7cd289dff39708 ? ./unzip.dhall
@@ -1,2 +1,3 @@- ./concat.dhall sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+ missing+ sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0 ? ./concat.dhall
@@ -1,2 +1,3 @@- ./concatMap.dhall sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+ missing+ sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f ? ./concatMap.dhall
@@ -1,2 +1,3 @@- ./concatMapSep.dhall sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+ missing+ sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840 ? ./concatMapSep.dhall
@@ -1,2 +1,3 @@- ./concatSep.dhall sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+ missing+ sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58 ? ./concatSep.dhall
@@ -1,2 +1,3 @@- ./default.dhall sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+ missing+ sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf ? ./default.dhall
@@ -1,2 +1,3 @@- ./defaultMap.dhall sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+ missing+ sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588 ? ./defaultMap.dhall
@@ -0,0 +1,56 @@+{-|+Lowercase all ASCII characters++Note that this will also lowercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let lowerASCII+ : Text → Text+ = List/fold+ (Text → Text)+ [ Text/replace "A" "a"+ , Text/replace "B" "b"+ , Text/replace "C" "c"+ , Text/replace "D" "d"+ , Text/replace "E" "e"+ , Text/replace "F" "f"+ , Text/replace "G" "g"+ , Text/replace "H" "h"+ , Text/replace "I" "i"+ , Text/replace "J" "j"+ , Text/replace "K" "k"+ , Text/replace "L" "l"+ , Text/replace "M" "m"+ , Text/replace "N" "n"+ , Text/replace "O" "o"+ , Text/replace "P" "p"+ , Text/replace "Q" "q"+ , Text/replace "R" "r"+ , Text/replace "S" "s"+ , Text/replace "T" "t"+ , Text/replace "U" "u"+ , Text/replace "V" "v"+ , Text/replace "W" "w"+ , Text/replace "X" "x"+ , Text/replace "Y" "y"+ , Text/replace "Z" "z"+ ]+ Text+ (λ(replacement : Text → Text) → replacement)++let example0 = assert : lowerASCII "ABCdef" ≡ "abcdef"++let -- This does not lowercase precomposed Unicode characters+ --+ -- • The `Á` in the following example is U+00C1+ example1 =+ assert : lowerASCII "Á" ≡ "Á"++let -- … but this does lowercase decomposed Unicode characters+ --+ -- • The `Á` in the following example is U+0041 U+0301+ -- • The `á` in the following example is U+0061 U+0301+ example1 =+ assert : lowerASCII "Á" ≡ "á"++in lowerASCII
@@ -1,28 +1,53 @@ { concat =- ./concat.dhall sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+ missing+ sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0 ? ./concat.dhall , concatMap =- ./concatMap.dhall sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+ missing+ sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f ? ./concatMap.dhall , concatMapSep =- ./concatMapSep.dhall sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840+ missing+ sha256:c272aca80a607bc5963d1fcb38819e7e0d3e72ac4d02b1183b1afb6a91340840 ? ./concatMapSep.dhall , concatSep =- ./concatSep.dhall sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58+ missing+ sha256:e4401d69918c61b92a4c0288f7d60a6560ca99726138ed8ebc58dca2cd205e58 ? ./concatSep.dhall , default =- ./default.dhall sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf+ missing+ sha256:f532c8891b1e427d90a6cc07cf7e793a4c84b0765e1bfe69f186ee2ec91c1edf ? ./default.dhall , defaultMap =- ./defaultMap.dhall sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588+ missing+ sha256:3a3fa1264f6198800c27483cb144de2c5366484876d60b9c739a710ce0288588 ? ./defaultMap.dhall+, lowerASCII =+ missing+ sha256:26b076651120b907e869396bd3dc16271f2e12433062b2f26f296968a69515e7+ ? ./lowerASCII.dhall+, replace =+ missing+ sha256:7d132df0e091a43817bba8afa06d1bb487ee51c091430404ad6f8c78bc0328a6+ ? ./replace.dhall , replicate =- ./replicate.dhall sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+ missing+ sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f ? ./replicate.dhall+, shell-escape =+ missing+ sha256:d53521b3f478cb18a7d63730bc0e3153c2124b70d6ac9a1f610ce7db67cfc7a2+ ? ./shell-escape.dhall , show =- ./show.dhall sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+ missing+ sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784 ? ./show.dhall , spaces =- ./spaces.dhall sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+ missing+ sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc ? ./spaces.dhall+, upperASCII =+ missing+ sha256:45ae4fbd814b0474e65c28a4ee92b23b979892fa5bb73730bc99675ae790ca29+ ? ./upperASCII.dhall }
@@ -1,2 +1,3 @@- ./replicate.dhall sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+ missing+ sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f ? ./replicate.dhall
@@ -1,11 +1,12 @@ --| Build a Text by copying the given Text the specified number of times- let concat =- ./concat.dhall sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+ missing+ sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0 ? ./concat.dhall let List/replicate =- ../List/replicate.dhall sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347+ missing+ sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347 ? ../List/replicate.dhall let replicate
@@ -0,0 +1,16 @@+{-|+Escape a Text value such that it can be used safely in shells.+The escaping is done by replacing all `'` with `'"'"'` and wraps that string in+single quotes.++This works for all POSIX-compliant shells and some other shells like csh.+-}+let shell-escape+ : Text -> Text+ = \(xs : Text) -> "'${Text/replace "'" "'\"'\"'" xs}'"++let example0 = assert : shell-escape "foo" === "'foo'"++let example1 = assert : shell-escape "foo'bar" === "'foo'\"'\"'bar'"++in shell-escape
@@ -1,2 +1,3 @@- ./show.dhall sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784+ missing+ sha256:c9dc5de3e5f32872dbda57166804865e5e80785abe358ff61f1d8ac45f1f4784 ? ./show.dhall
@@ -1,2 +1,3 @@- ./spaces.dhall sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc+ missing+ sha256:fccfd4f26601e006bf6a79ca948dbd37c676cdd0db439554447320293d23b3dc ? ./spaces.dhall
@@ -4,9 +4,9 @@ This function is particularly helpful when trying to generate Text where whitespace is significant, i.e. with nested indentation. -}- let replicate =- ./replicate.dhall sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f+ missing+ sha256:1b398b1d464b3a6c7264a690ac3cacb443b5683b43348c859d68e7c2cb925c4f ? ./replicate.dhall let spaces
@@ -0,0 +1,56 @@+{-|+Uppercase all ASCII characters++Note that this will also uppercase decomposed Unicode characters that contain+codepoints in the ASCII range+-}+let upperASCII+ : Text → Text+ = List/fold+ (Text → Text)+ [ Text/replace "a" "A"+ , Text/replace "b" "B"+ , Text/replace "c" "C"+ , Text/replace "d" "D"+ , Text/replace "e" "E"+ , Text/replace "f" "F"+ , Text/replace "g" "G"+ , Text/replace "h" "H"+ , Text/replace "i" "I"+ , Text/replace "j" "J"+ , Text/replace "k" "K"+ , Text/replace "l" "L"+ , Text/replace "m" "M"+ , Text/replace "n" "N"+ , Text/replace "o" "O"+ , Text/replace "p" "P"+ , Text/replace "q" "Q"+ , Text/replace "r" "R"+ , Text/replace "s" "S"+ , Text/replace "t" "T"+ , Text/replace "u" "U"+ , Text/replace "v" "V"+ , Text/replace "w" "W"+ , Text/replace "x" "X"+ , Text/replace "y" "Y"+ , Text/replace "z" "Z"+ ]+ Text+ (λ(replacement : Text → Text) → replacement)++let example0 = assert : upperASCII "ABCdef" ≡ "ABCDEF"++let -- This does not uppercase precomposed Unicode characters+ --+ -- • The `á` in the following example is U+00E1+ example1 =+ assert : upperASCII "á" ≡ "á"++let -- … but this does uppercase decomposed Unicode characters+ --+ -- • The `Á` in the following example is U+0041 U+0301+ -- • The `á` in the following example is U+0061 U+0301+ example1 =+ assert : upperASCII "á" ≡ "Á"++in upperASCII
@@ -0,0 +1,5 @@+{ show =+ missing+ sha256:8cabfe35dd0ee25ca65708105e860cbf4b789e0d73134aa905580799e2a46719+ ? ./show.dhall+}
@@ -0,0 +1,15 @@+{-+Render a `Time` as `Text` using the same representation as Dhall source code+(i.e. `hh:mm:ss`)+-}+let show+ : Time → Text+ = Time/show++let example0 = assert : show 03:15:47.90 ≡ "03:15:47.90"++let example1 = assert : show 00:00:00 ≡ "00:00:00"++let example2 = assert : show 11:59:59 ≡ "11:59:59"++in show
@@ -0,0 +1,5 @@+{ show =+ missing+ sha256:d183361f1c4c656bad3b170ec8b8d6705f564faebf94e4ef10c76061104ff061+ ? ./show.dhall+}
@@ -0,0 +1,15 @@+{-+Render a `TimeZone` as `Text` using the same representation as Dhall source code+(i.e. `±HH:MM`)+-}+let show+ : TimeZone → Text+ = TimeZone/show++let example0 = assert : show +07:00 ≡ "+07:00"++let example1 = assert : show +00:00 ≡ "+00:00"++let example2 = assert : show -05:00 ≡ "-05:00"++in show
@@ -1,2 +1,3 @@- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall
@@ -15,6 +15,8 @@ → λ ( xml : { text : Text → XML+ , rawText :+ Text → XML , element : { attributes : List { mapKey : Text, mapValue : Text }@@ -44,12 +46,12 @@ } ``` -}- let XML/Type : Type = ∀(XML : Type) → ∀ ( xml : { text : Text → XML+ , rawText : Text → XML , element : { attributes : List { mapKey : Text, mapValue : Text } , content : List XML
@@ -1,2 +1,3 @@- ./attribute.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./attribute.dhall
@@ -1,5 +1,4 @@ --| Builds a key-value record with a Text key and value.- let attribute : Text → Text → { mapKey : Text, mapValue : Text } = λ(key : Text) → λ(value : Text) → { mapKey = key, mapValue = value }
@@ -1,2 +1,3 @@- ./element.dhall sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b+ missing+ sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9 ? ./element.dhall
@@ -18,14 +18,14 @@ = "<foo><bar n=\"1\"/><baz n=\"2\"/></foo>" ``` -}-- let XML =- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall let List/map =- ../List/map.dhall sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680+ missing+ sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680 ? ../List/map.dhall let Args =@@ -41,6 +41,7 @@ λ(XML : Type) → λ ( xml : { text : Text → XML+ , rawText : Text → XML , element : { attributes : List { mapKey : Text, mapValue : Text } , content : List XML
@@ -1,2 +1,3 @@- ./emptyAttributes.dhall sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+ missing+ sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5 ? ./emptyAttributes.dhall
@@ -1,3 +1,2 @@ --| Create an empty XML attribute List.- [] : List { mapKey : Text, mapValue : Text }
@@ -1,2 +1,3 @@- ./leaf.dhall sha256:4383e4fc4bf6a29ac2052776972eb59d5355a1cd067cded80d4ff32840969261+ missing+ sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506 ? ./leaf.dhall
@@ -9,13 +9,14 @@ = "<foobar/>" ``` -}- let XML =- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall let element =- ./element.dhall sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b+ missing+ sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9 ? ./element.dhall let leaf
@@ -1,22 +1,33 @@ { Type =- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall , attribute =- ./attribute.dhall sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc+ missing+ sha256:f7b6c802ca5764d03d5e9a6e48d9cb167c01392f775d9c2c87b83cdaa60ea0cc ? ./attribute.dhall , render =- ./render.dhall sha256:8d034f7f97cded14a96147565d489be840e5678480d175b962b2600d85a3230e+ missing+ sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66 ? ./render.dhall , element =- ./element.dhall sha256:e0b948053c8cd8ccca9c39244d89e3f42db43d222531c18151551dfc75208b4b+ missing+ sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9 ? ./element.dhall , leaf =- ./leaf.dhall sha256:4383e4fc4bf6a29ac2052776972eb59d5355a1cd067cded80d4ff32840969261+ missing+ sha256:5dcedf79a3664a362479f470220bb2f4932facde657c285fd8a3c24ab137c506 ? ./leaf.dhall , text =- ./text.dhall sha256:c83cd721d32d7dc28c04ce429c0cb22812639e572637ec348578a58ffb68844f+ missing+ sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab ? ./text.dhall+, rawText =+ missing+ sha256:2af9d72c151677d4110039e361b7e9faaf2947e6c9d29aa72aea351ad797e05d+ ? ./rawText.dhall , emptyAttributes =- ./emptyAttributes.dhall sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+ missing+ sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5 ? ./emptyAttributes.dhall }
@@ -0,0 +1,40 @@+{-|+Create a Text value to be inserted into an XML element as content with no+character escaping.++```+let XML = ./package.dhall++in XML.render+ ( XML.element+ { name = "location"+ , attributes = XML.emptyAttributes+ , content = [ XML.rawText "<bar n=\"1\"/>" ]+ }+ )+= "<foo><bar n=\"1\"/></foo>"+```+-}+let XML =+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9+ ? ./Type.dhall++let rawText+ : Text → XML+ = λ(d : Text) →+ λ(XML : Type) →+ λ ( xml+ : { text : Text → XML+ , rawText : Text → XML+ , element :+ { attributes : List { mapKey : Text, mapValue : Text }+ , content : List XML+ , name : Text+ } →+ XML+ }+ ) →+ xml.rawText d++in rawText
@@ -1,2 +1,3 @@- ./render.dhall sha256:8d034f7f97cded14a96147565d489be840e5678480d175b962b2600d85a3230e+ missing+ sha256:395c293702c85d99f6f2b461f3eee320f9fe5749c320c2e8b9ea799a7d210b66 ? ./render.dhall
@@ -1,10 +1,6 @@ {-| Render an `XML` value as `Text` -*WARNING:* rendering does not include any XML injection mitigations,-therefore it should not be used to process arbitrary strings into-element attributes or element data.- For indentation and schema validation, see the `xmllint` utility bundled with libxml2. @@ -12,7 +8,7 @@ let XML = ./package.dhall in XML.render- ( XML.node+ ( XML.element { name = "foo" , attributes = [ XML.attribute "a" "x", XML.attribute "b" (Natural/show 2) ] , content = [ XML.leaf { name = "bar", attributes = XML.emptyAttributes } ]@@ -22,29 +18,65 @@ ``` -}- let XML =- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall let Text/concatMap =- ../Text/concatMap.dhall sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f+ missing+ sha256:7a0b0b99643de69d6f94ba49441cd0fa0507cbdfa8ace0295f16097af37e226f ? ../Text/concatMap.dhall let Text/concat =- ../Text/concat.dhall sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0+ missing+ sha256:731265b0288e8a905ecff95c97333ee2db614c39d69f1514cb8eed9259745fc0 ? ../Text/concat.dhall +let element =+ missing+ sha256:79266d604e147caf37e985581523b684f7bac66de0c93dd828841df3dfc445f9+ ? ./element.dhall++let text =+ missing+ sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab+ ? ./text.dhall++let emptyAttributes =+ missing+ sha256:11b86e2d3f3c75d47a1d580213d2a03fd2c36d64f3e9b6381de0ba23472f64d5+ ? ./emptyAttributes.dhall+ let Attr = { mapKey : Text, mapValue : Text } -let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${x.mapValue}\""+let esc = λ(x : Text) → λ(y : Text) → Text/replace x "&${y};" +let `escape&` = esc "&" "amp"++let `escape<` = esc "<" "lt"++let `escape>` = esc ">" "gt"++let `escape'` = esc "'" "apos"++let `escape"` = esc "\"" "quot"++let escapeCommon = λ(text : Text) → `escape<` (`escape&` text)++let escapeAttr = λ(text : Text) → `escape"` (`escape'` (escapeCommon text))++let escapeText = λ(text : Text) → `escape>` (escapeCommon text)++let renderAttr = λ(x : Attr) → " ${x.mapKey}=\"${escapeAttr x.mapValue}\""+ let render : XML → Text = λ(x : XML) → x Text- { text = λ(d : Text) → d+ { text = escapeText+ , rawText = λ(t : Text) → t , element = λ ( elem : { attributes : List { mapKey : Text, mapValue : Text }@@ -60,5 +92,49 @@ else ">${Text/concat elem.content}</${elem.name}>" ) }++let simple =+ λ(name : Text) →+ λ(content : List XML) →+ element { name, attributes = emptyAttributes, content }++let example0 =+ assert+ : render+ ( simple+ "note"+ [ simple "to" [ text "Tove" ]+ , simple "from" [ text "Jani" ]+ , simple "heading" [ text "Reminder" ]+ , simple "body" [ text "Don't forget me this weekend!" ]+ ]+ )+ ≡ Text/replace+ "\n"+ ""+ ''+ <note>+ <to>Tove</to>+ <from>Jani</from>+ <heading>Reminder</heading>+ <body>Don't forget me this weekend!</body>+ </note>+ ''++let example1 =+ assert+ : render+ ( element+ { name = "escape"+ , attributes = toMap { attribute = "<>'\"&" }+ , content = [ text "<>'\"&" ]+ }+ )+ ≡ Text/replace+ "\n"+ ""+ ''+ <escape attribute="<>'"&"><>'"&</escape>+ '' in render
@@ -1,2 +1,3 @@- ./text.dhall sha256:c83cd721d32d7dc28c04ce429c0cb22812639e572637ec348578a58ffb68844f+ missing+ sha256:a59670560a08bfc815893dee1f3eae21a5252400f8a619d1cd7bdd9f48eea2ab ? ./text.dhall
@@ -5,7 +5,7 @@ let XML = ./package.dhall in XML.render- ( XML.node+ ( XML.element { name = "location" , attributes = XML.emptyAttributes , content = [ XML.text "/foo/bar" ]@@ -14,9 +14,9 @@ = "<location>/foo/bar</location>" ``` -}- let XML =- ./Type.dhall sha256:461930f3aab769ba537d1a4fd71f411504b0c8d1c1a78d65177be8ded0df8a5c+ missing+ sha256:ab91a0edaf0513e0083b1dfae5efa160adc99b0e589775a4a699ab77cce528a9 ? ./Type.dhall let text@@ -25,6 +25,7 @@ λ(XML : Type) → λ ( xml : { text : Text → XML+ , rawText : Text → XML , element : { attributes : List { mapKey : Text, mapValue : Text } , content : List XML
@@ -1,40 +1,73 @@ { Bool =- ./Bool/package.dhall sha256:7ee950e7c2142be5923f76d00263e536b71d96cb9c190d7743c1679501ddeb0a+ missing+ sha256:dde2b9b71afdd26878c06e90cd2cde4488063457d5fbe30e02baed3bec5eede6 ? ./Bool/package.dhall+, Date =+ missing+ sha256:fc0c5efc924fa99aa8e5dea5d78c3dc1a24cb550028342b90149ea78cb5ca873+ ? ./Date/package.dhall , Double =- ./Double/package.dhall sha256:b8d20ab3216083622ae371fb42a6732bc67bb2d66e84989c8ddba7556a336cf7+ missing+ sha256:b8d20ab3216083622ae371fb42a6732bc67bb2d66e84989c8ddba7556a336cf7 ? ./Double/package.dhall , Function =- ./Function/package.dhall sha256:6d17cf0fd4fabe1737fb117f87c04b8ff82b299915a5b673c0a543b134b8fffe+ missing+ sha256:f4ca848f69034f9d7a74e12c556c3a3396966c1de3a9427a102d1aff4580192f ? ./Function/package.dhall , Integer =- ./Integer/package.dhall sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0+ missing+ sha256:d1a572ca3a764781496847e4921d7d9a881c18ffcfac6ae28d0e5299066938a0 ? ./Integer/package.dhall+, JSON =+ missing+ sha256:5f98b7722fd13509ef448b075e02b9ff98312ae7a406cf53ed25012dbc9990ac+ ? ./JSON/package.dhall , List =- ./List/package.dhall sha256:547cd881988c6c5e3673ae80491224158e93a4627690db0196cb5efbbf00d2ba+ missing+ sha256:26d1b4cd800219d8b67043c638926aa6e5517ea74a0bd3e371974514621bca04 ? ./List/package.dhall , Location =- ./Location/package.dhall sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470+ missing+ sha256:0eb4e4a60814018009c720f6820aaa13cf9491eb1b09afb7b832039c6ee4d470 ? ./Location/package.dhall , Map =- ./Map/package.dhall sha256:c6602939eb75ddaf43e75a37e1f27ace97e03685ceb9d77605b4372547f7cfa8+ missing+ sha256:c5e79a9de642644a09b96a2ec3147c5d8662b7926f09610e751c0c0f6ed0b30a ? ./Map/package.dhall , Monoid =- ./Monoid.dhall sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af+ missing+ sha256:26fafa098600ef7a54ef9dba5ada416bbbdd21df1af306c052420c61553ad4af ? ./Monoid.dhall , Natural =- ./Natural/package.dhall sha256:ee9ed2b28a417ed4e9a0c284801b928bf91b3fbdc1a68616347678c1821f1ddf+ missing+ sha256:ee9ed2b28a417ed4e9a0c284801b928bf91b3fbdc1a68616347678c1821f1ddf ? ./Natural/package.dhall+, NonEmpty =+ missing+ sha256:c24686a230a4b3cd51e5a57cd4510b4f8242f813d7823d41bac5954e7af56f7a+ ? ./NonEmpty/package.dhall+, Operator =+ missing+ sha256:861f724704a7b4755c96f173e54d03f314492a2d046723404c31ff612b7bf2e6+ ? ./Operator/package.dhall , Optional =- ./Optional/package.dhall sha256:4324b2bf84ded40f67485f14355e4cb7b237a8f173e713c791ec44cebebc552c+ missing+ sha256:74331dfe59c09db65edc7ec4498bff92473c8c06d92752f9470d26e25f91320c ? ./Optional/package.dhall-, JSON =- ./JSON/package.dhall sha256:79dfc281a05bc7b78f927e0da0c274ee5709b1c55c9e5f59499cb28e9d6f3ec0- ? ./JSON/package.dhall , Text =- ./Text/package.dhall sha256:819a967038fbf6f28cc289fa2651e42835f70b326210c86e51acf48f46f913d8+ missing+ sha256:79b671a70ac459b799a53bbb8a383cc8b81b40421745c54bf0fb1143168cbd6f ? ./Text/package.dhall+, Time =+ missing+ sha256:6715c4c71a113429fef8b94e4561a93c288942dad9dfd75ac545de96c5b5652a+ ? ./Time/package.dhall+, TimeZone =+ missing+ sha256:c17fd403c637856f34c8287168b92974e8c1a3a7331967f75276d179057084fd+ ? ./TimeZone/package.dhall , XML =- ./XML/package.dhall sha256:137e7b106b2e9743970e5d37b21a165f2e40f56ab593a4dd10605c9acd686fc6+ missing+ sha256:2e111f0952087d42072b059f0bf4c95861a46bffa67ad4c8c39086edf405f32e ? ./XML/package.dhall }
binary file changed (absent → 114 bytes)
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
@@ -0,0 +1,1 @@+Ð
@@ -0,0 +1,1 @@+2000-01-01
binary file changed (absent → 9 bytes)
@@ -0,0 +1,1 @@+12:00:00
binary file changed (absent → 6 bytes)
@@ -0,0 +1,1 @@++08:00
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/AllowedAll.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Empty.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/Null.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyGithub.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlyOther.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/OnlySelf.dhall
@@ -0,0 +1,1 @@+https://prelude.dhall-lang.org/List/length
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
@@ -1,1 +1,1 @@-../failure/cycle.dhall+../failure/unit/Cycle.dhall
@@ -0,0 +1,1 @@+[
@@ -0,0 +1,1 @@+#Eg«Íï
@@ -0,0 +1,1 @@+"Dhall (from import)"
@@ -1,1 +0,0 @@-../data/cycle.dhall
@@ -1,1 +0,0 @@-../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -1,1 +0,0 @@-\(x: Bool) -> ../data/importBoundary.dhall
@@ -1,1 +0,0 @@-missing
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
@@ -0,0 +1,11 @@+-- Use of a remote import causes Cyclic Import on env:DHALL_HEADERS+toMap+ { DHALL_HEADERS =+ ''+ toMap {+ `httpbin.org:443` = toMap {+ `User-Agent` = http://example.com as Text+ }+ }+ ''+ }
@@ -1,13 +0,0 @@-{- The following remote import attempts to import an environment variable, which- must be disallowed by the referential sanity check-- One reason for doing this is to protect against remote imports exfiltrating- environment variables (such as via custom headers). Only referentially- opaque imports (i.e. local imports) have permission to refer to other- referentially opaque imports in order to protect against this attack.-- The referential sanity check also ensures that remote imports are- referentially transparent. Or in other words, any import that is globally- addressable must have a meaning that is not context-sensitive.--}-https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/data/referentiallyOpaque.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/nonexistent-file.dhall
@@ -0,0 +1,1 @@+../../data/cycle.dhall
@@ -0,0 +1,1 @@+../../data/cycle.dhall ? 0
@@ -0,0 +1,3 @@+-- This fails because the `?` operator does not recover from integrity check+-- failures+../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ? 0
@@ -0,0 +1,1 @@+../../data/doesNotParse.dhall ? 0
@@ -0,0 +1,1 @@+../../data/doesNotTypecheck.dhall ? 0
@@ -0,0 +1,13 @@+{- The following remote import attempts to import an environment variable, which+ must be disallowed by the referential sanity check++ One reason for doing this is to protect against remote imports exfiltrating+ environment variables (such as via custom headers). Only referentially+ opaque imports (i.e. local imports) have permission to refer to other+ referentially opaque imports in order to protect against this attack.++ The referential sanity check also ensures that remote imports are+ referentially transparent. Or in other words, any import that is globally+ addressable must have a meaning that is not context-sensitive.+-}+https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/tests/import/data/referentiallyOpaque.dhall
@@ -0,0 +1,1 @@+./not-a-file.dhall
@@ -0,0 +1,1 @@+../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -0,0 +1,2 @@+-- This ensures that even if the file gets imported without hash first, the hash check is not skipped later+../../data/simple.dhall + ../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ../../data/simple.dhall
@@ -0,0 +1,1 @@+missing
@@ -0,0 +1,1 @@+\(x: Bool) -> ../../data/importBoundary.dhall
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Empty.dhall
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/NoCORS.dhall
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/Null.dhall
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyOther.dhall
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsFail.dhall
@@ -0,0 +1,1 @@+"hello"
@@ -1,16 +1,12 @@ {- This test verifies that header-forwarding works correctly for relative imports within the same domain - `test.dhall-lang.org` is the same as `prelude.dhall-lang.org` except that- `test.dhall-lang.org` rejects all requests without a `Test` header.+ `test.dhall-lang.org/foo` returns `./bar` and `test.dhall-lang.org/foo`+ returns `True`, and both URLs reject all requests without a `Test` header. This test requires that the initial import to- `https://test.dhall-lang.org/Bool/package.dhall` forwards the `Test` header- to the transitive relative imports of `https://test.dhall-lang.org/Bool/*` in+ `https://test.dhall-lang.org/foo` forwards the `Test` header+ to the transitive relative import of `https://test.dhall-lang.org/bar` in order to succeed.-- Note: You will need to update this test whenever the `Bool` package in the- Prelude changes (sorry) -}-https://test.dhall-lang.org/Bool/package.dhall- using [ { mapKey = "Test", mapValue = "Example" } ]+https://test.dhall-lang.org/foo using (toMap { Test = "Example" })
@@ -1,26 +1,1 @@-{ and =- λ(xs : List Bool)- → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l && r) True-, build =- λ(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool)- → f Bool True False-, even =- λ(xs : List Bool)- → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x == y) True-, fold =- λ(b : Bool)- → λ(bool : Type)- → λ(true : bool)- → λ(false : bool)- → if b then true else false-, not =- λ(b : Bool) → b == False-, odd =- λ(xs : List Bool)- → List/fold Bool xs Bool (λ(x : Bool) → λ(y : Bool) → x != y) False-, or =- λ(xs : List Bool)- → List/fold Bool xs Bool (λ(l : Bool) → λ(r : Bool) → l || r) False-, show =- λ(b : Bool) → if b then "True" else "False"-}+True
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
@@ -0,0 +1,5 @@+''+{+ "user-agent": "Dhall"+}+''
@@ -0,0 +1,10 @@+toMap+ { DHALL_HEADERS =+ ''+ toMap {+ `httpbin.org:443` = toMap {+ `User-Agent` = "Dhall"+ }+ }+ ''+ }
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
@@ -0,0 +1,5 @@+''+{+ "user-agent": "Dhall (from import)"+}+''
@@ -0,0 +1,10 @@+toMap+ { DHALL_HEADERS =+ ''+ toMap {+ `httpbin.org:443` = toMap {+ `User-Agent` = ./dhall-lang/tests/import/data/userAgent.dhall+ }+ }+ ''+ }
@@ -0,0 +1,1 @@+https://httpbin.org/user-agent as Text
@@ -0,0 +1,5 @@+''+{+ "user-agent": "Dhall (from env)"+}+''
@@ -0,0 +1,11 @@+toMap+ { DHALL_HEADERS =+ ''+ toMap {+ `httpbin.org:443` = toMap {+ `User-Agent` = env:USER_AGENT as Text+ }+ }+ ''+ , USER_AGENT = "Dhall (from env)"+ }
@@ -0,0 +1,3 @@+https://httpbin.org/user-agent+ using [ { mapKey = "User-Agent", mapValue = "inline-header" } ]+ as Text
@@ -0,0 +1,5 @@+''+{+ "user-agent": "user-header"+}+''
@@ -0,0 +1,10 @@+toMap+ { DHALL_HEADERS =+ ''+ toMap {+ `httpbin.org:443` = toMap {+ `User-Agent` = "user-header"+ }+ }+ ''+ }
@@ -1,1 +0,0 @@-../../data/simple.dhall sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ? 42
@@ -1,1 +0,0 @@-42
@@ -1,1 +0,0 @@-../../data/example.txt ? 42
@@ -1,1 +0,0 @@-42
@@ -1,1 +0,0 @@-../../data/doesNotTypecheck.dhall ? 42
@@ -1,1 +0,0 @@-42
@@ -0,0 +1,1 @@+let x = 0 in (missing ? x)
@@ -0,0 +1,1 @@+let x = 0 in x
@@ -0,0 +1,1 @@+\(x: Natural) -> x ? y
@@ -0,0 +1,1 @@+λ(x : Natural) → x
@@ -0,0 +1,1 @@+\(x: Natural) -> (y + missing) ? x
@@ -0,0 +1,1 @@+λ(x : Natural) → x
@@ -0,0 +1,1 @@+../../data/example.bin as Bytes
@@ -0,0 +1,1 @@+0x"0123456789abcdef"
@@ -0,0 +1,5 @@+-- The let triggers a loading of `simple.dhall` in the cache,+-- but the second import uses a hash that corresponds to a different file already in the content-addressed store.+-- This test ensures that we retrieve the value corresponding to the hash and not the path even if the path is in cache.+let x = ../../data/simple.dhall+in ../../data/simple.dhall sha256:3871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc
@@ -0,0 +1,1 @@+let x = 3 in λ(_ : Type) → λ(_ : Optional _) → merge { `None` = True, `Some` = λ(_ : _@1) → False } _
@@ -0,0 +1,1 @@+~/hello.dhall ++ " world"
@@ -0,0 +1,1 @@+"hello" ++ " world"
@@ -0,0 +1,2 @@+-- This is to ensure caching doesn't accidentally confuse import modes+{ n = ../../data/simple.dhall, txt = ../../data/simple.dhall as Text, loc = ../../data/simple.dhall as Location }
@@ -0,0 +1,1 @@+{ loc = < Environment: Text | Local: Text | Missing | Remote: Text >.Local "./dhall-lang/tests/import/data/simple.dhall", n = 3, txt = "3\n" }
@@ -0,0 +1,1 @@+../../failure/unit/FileMissing.dhall ? 0
@@ -0,0 +1,1 @@+0
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/AllowedAll.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/NoCORS.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/acee30866a179c9e9bb3fc02ec8be2883685eb14/tests/import/data/cors/Prelude.dhall
@@ -0,0 +1,1 @@+List/length
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportAbsolute.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportAbsolute.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/SelfImportRelative.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/SelfImportRelative.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+https://test.dhall-lang.org/cors/TwoHopsSuccess.dhall
@@ -0,0 +1,1 @@+42
@@ -0,0 +1,1 @@+\(foo: { x: Bool, y: Bool }) -> \(bar: { x: Bool }) -> (foo.{x, y} // bar).{ x }
@@ -0,0 +1,3 @@+λ(foo : { x : Bool, y : Bool }) →+λ(bar : { x : Bool }) →+ (foo.{ x, y } ⫽ bar).{ x }
@@ -0,0 +1,1 @@+toMap { `if` = 0, `foo%bar` = 1 }
@@ -0,0 +1,1 @@+[ { mapKey = "foo%bar", mapValue = 1 }, { mapKey = "if", mapValue = 0 } ]
@@ -1,6 +1,6 @@-let Text/concatMap = ../../../Prelude/Text/concatMap+let Text/concatMap = ../../../Prelude/Text/concatMap.dhall -let Text/concatSep = ../../../Prelude/Text/concatSep+let Text/concatSep = ../../../Prelude/Text/concatSep.dhall let Row = { cores :
@@ -0,0 +1,1 @@+Bytes
@@ -0,0 +1,1 @@+Bytes
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
@@ -0,0 +1,23 @@+[ 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+]
@@ -0,0 +1,1 @@+{ b = 1, a = 0 }
@@ -0,0 +1,1 @@+{ a = 0, b = 1 }
@@ -0,0 +1,1 @@+{ b : Bool, a : Natural }
@@ -0,0 +1,1 @@+{ a : Natural, b : Bool }
@@ -0,0 +1,1 @@+showConstructor <A>.A
@@ -0,0 +1,1 @@+"A"
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
@@ -0,0 +1,1 @@+"A"
@@ -1,4 +1,3 @@-{- This test verifies that an implementation correctly permits both the- "replacement" and the "haystack" to be abstract.+{- This test verifies that an implementation works with an abstract "replacement". -}-λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"+λ(x : Text) → Text/replace "a" "-${x}-" "_a__a_"
@@ -1,1 +1,1 @@-λ(x : Text) → λ(y : Text) → "_-${x}-_${y}_-${x}-_"+λ(x : Text) → "_-${x}-__-${x}-_"
@@ -0,0 +1,4 @@+{- This test verifies that an implementation does not beta normalize with an+ abstract "haystack".+-}+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
@@ -0,0 +1,1 @@+λ(x : Text) → λ(y : Text) → Text/replace "a" "-${x}-" "_a_${y}_a_"
@@ -0,0 +1,1 @@+Text/replace ""
@@ -0,0 +1,1 @@+Text/replace ""
@@ -0,0 +1,2 @@+λ(replacement : Text) →+ Text/replace "" replacement
@@ -0,0 +1,2 @@+λ(replacement : Text) →+ Text/replace "" replacement
@@ -0,0 +1,3 @@+λ(replacement : Text) →+λ(haystack : Text) →+ Text/replace "" replacement haystack
@@ -0,0 +1,1 @@+λ(replacement : Text) → λ(haystack : Text) → haystack
@@ -1,1 +0,0 @@-Text/replace "" "bar" "foo"
@@ -1,1 +0,0 @@-"foo"
@@ -0,0 +1,1 @@+Text/replace "aa" "b" "aaaaa"
@@ -0,0 +1,1 @@+"bba"
@@ -0,0 +1,3 @@+{- This test verifies that an implementation works with a variable as "replacement".+-}+λ(x : Text) → Text/replace "a" x "aaa"
@@ -0,0 +1,1 @@+λ(x : Text) → "${x}${x}${x}"
@@ -0,0 +1,2 @@+-- Timestamps are records, and this is a no-op+2000-01-01T12:00:00+08:00.{ time, date, timeZone }
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
@@ -0,0 +1,1 @@+(None Natural) with ? = 1
@@ -0,0 +1,1 @@+None Natural
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
@@ -0,0 +1,1 @@+Some 1
@@ -0,0 +1,1 @@+(Some { x = Some { y = Some { z = Some 0 } } }) with ?.x.?.y.?.z.? = 1
@@ -0,0 +1,1 @@+Some { x = Some { y = Some { z = Some 1 } } }
@@ -0,0 +1,1 @@+{ x = Some 0 } with x.? = 1
@@ -0,0 +1,1 @@+{ x = Some 1 }
@@ -1,6 +1,6 @@ {- Builtin names are disallowed in bound variables.- The grammar doesn't explicitely disallow this, but the implementation should+ The grammar doesn't explicitly disallow this, but the implementation should refuse it. See the comments above the `nonreserved-label` rule. -} let Bool : Natural = 1 in Bool
@@ -0,0 +1,1 @@+0x"invalid"
@@ -0,0 +1,1 @@+0x"0"
@@ -0,0 +1,1 @@+let x = NaNin x
@@ -0,0 +1,1 @@+let x = 3let y = x in y
@@ -0,0 +1,2 @@+-- A date and time zone is not valid (because the time is missing)+2011-04-01+02:00
@@ -0,0 +1,2 @@+-- April only has 30 days+2000-04-31
@@ -0,0 +1,2 @@+-- Hours must range between 0-23+24:00:00
@@ -0,0 +1,3 @@+-- Leap seconds are not permitted by the Dhall standard, even though RFC 3339+-- supports them+2016-12-31T23:59:60
@@ -0,0 +1,2 @@+-- Minutes must range between 0-59+00:60:00
@@ -0,0 +1,2 @@+-- Months must be between 1-12+2000-13-01
@@ -0,0 +1,2 @@+-- Seconds must range between 0-59 (and leap seconds are not supported)+00:00:60
@@ -0,0 +1,2 @@+-- Negative years are not permitted+-0001-01-01
@@ -0,0 +1,2 @@+-- Only 4-digit years are permitted+10000-01-01
@@ -0,0 +1,2 @@+-- For https://github.com/dhall-lang/dhall-haskell/issues/2212+{=}with foo = 0with bar = 1
@@ -0,0 +1,1 @@+showConstructor
@@ -0,0 +1,8 @@+ λ(x : Bool)+→ λ(x : Bool)+→ { example0 = 0b0+ , example1 = 0b10+ , example2 = -0b11001+ , example3 = +0b100+ , example4 = x@0b01+ }
binary file changed (absent → 83 bytes)
@@ -1,36 +1,40 @@-[ Natural/fold-, Natural/build-, Natural/isZero-, Natural/even-, Natural/odd-, Natural/toInteger-, Natural/show-, Integer/toDouble-, Integer/show-, Integer/negate-, Integer/clamp-, Natural/subtract+[ Date/show , Double/show+, Integer/clamp+, Integer/negate+, Integer/show+, Integer/toDouble , List/build , List/fold-, List/length , List/head-, List/last , List/indexed+, List/last+, List/length , List/reverse-, Text/show+, Natural/build+, Natural/even+, Natural/fold+, Natural/isZero+, Natural/odd+, Natural/show+, Natural/subtract+, Natural/toInteger , Text/replace+, Text/show+, Time/show+, TimeZone/show , Bool-, True+, Bytes+, Date+, Double , False-, Optional-, None-, Natural , Integer-, Double-, Text , List-, Type-, Kind-, Sort+, Natural+, None+, Optional+, Text+, Time+, TimeZone+, True ]
@@ -1,1 +1,1 @@-%ölNatural/foldmNatural/buildnNatural/isZerolNatural/evenkNatural/oddqNatural/toIntegerlNatural/showpInteger/toDoublelInteger/shownInteger/negatemInteger/clamppNatural/subtractkDouble/showjList/buildiList/foldkList/lengthiList/headiList/lastlList/indexedlList/reverseiText/showlText/replacedBoolõôhOptionaldNonegNaturalgIntegerfDoubledTextdListdTypedKinddSort+)öiDate/showkDouble/showmInteger/clampnInteger/negatelInteger/showpInteger/toDoublejList/buildiList/foldiList/headlList/indexediList/lastkList/lengthlList/reversemNatural/buildlNatural/evenlNatural/foldnNatural/isZerokNatural/oddlNatural/showpNatural/subtractqNatural/toIntegerlText/replaceiText/showiTime/showmTimeZone/showdBooleBytesdDatefDoubleôgIntegerdListgNaturaldNonehOptionaldTextdTimehTimeZoneõ
@@ -0,0 +1,25 @@+[ 0x""+, 0x"00"+, 0x"01"+, 0x"02"+, 0x"03"+, 0x"04"+, 0x"05"+, 0x"06"+, 0x"07"+, 0x"08"+, 0x"09"+, 0x"0a"+, 0x"0b"+, 0x"0c"+, 0x"0d"+, 0x"0e"+, 0x"0f"+, 0x"0A"+, 0x"0B"+, 0x"0C"+, 0x"0D"+, 0x"0E"+, 0x"0F"+, 0x"000102030405060708090a0b0c0d0e0f0A0B0C0D0E0F"+]
binary file changed (absent → 144 bytes)
@@ -0,0 +1,3 @@+[+ 1, -- item one+{- foo -} 2, 3 ]
@@ -0,0 +1,1 @@+ ö
@@ -0,0 +1,6 @@+{- foo -}+-- bar+{- --baz -}+-- {- qux -}++1
@@ -0,0 +1,1 @@+
@@ -0,0 +1,8 @@+{- A comment within the interior of a multi-line literal counts as part of the+ literal+-}++''+-- Hello+{- world -}+''
@@ -0,0 +1,2 @@+u-- Hello+{- world -}
@@ -1,8 +1,1 @@-{- A comment within the interior of a multi-line literal counts as part of the- literal--}--''--- Hello-{- world -}-''+"-- $--$--{--}$"
@@ -1,2 +1,1 @@-u-- Hello-{- world -}+n-- $--$--{--}$
@@ -0,0 +1,1 @@+"\u{1}\u{10}\u{100}\u{1000}\u{10000}\u{100000}"
@@ -0,0 +1,1 @@+oÄáðô
@@ -0,0 +1,1 @@+"A\u2115B\u{1FA00}C\u{43}D\u{00000001F574}E\u0022F"
@@ -0,0 +1,1 @@+sAâBð¨CCDð´E"F
@@ -0,0 +1,1 @@+"\u{10fffd}\u{1fffd}"
@@ -0,0 +1,1 @@+hô¿½ð¿½
@@ -0,0 +1,1 @@+1960-12-25T04:23:34
binary file changed (absent → 32 bytes)
@@ -0,0 +1,1 @@+2020-01-01T12:00:00-08:00
binary file changed (absent → 45 bytes)
@@ -0,0 +1,2 @@+-- Check that lowercase `t` is supported+2000-01-01t12:00:00
binary file changed (absent → 30 bytes)
@@ -0,0 +1,1 @@+00:00:00+00:00
binary file changed (absent → 32 bytes)
@@ -0,0 +1,5 @@+-- Same as `./TimeTimeZoneA.dhall`, but with `Z` as the `TimeZone`+--+-- This ensures that implementation still parse `Z` in conjunction with a time,+-- even if `Z` by itself is not permitted+00:00:00Z
binary file changed (absent → 32 bytes)
@@ -0,0 +1,1 @@+Date
@@ -0,0 +1,1 @@+dDate
@@ -0,0 +1,1 @@+2020-01-01
@@ -0,0 +1,1 @@+ä
@@ -0,0 +1,1 @@+x == x@0
binary file changed (absent → 11 bytes)
@@ -1,5 +0,0 @@-{-- Some languages do not make principled distinctions between number types, so- this checks that this Double is not silently considered as a Natural--}-1.0
binary file changed (3 → absent bytes)
@@ -0,0 +1,5 @@+{-+ Some languages do not make principled distinctions between number types, so+ this checks that this Double is not silently considered as a Natural+-}+1.0
binary file changed (absent → 3 bytes)
@@ -0,0 +1,1 @@+∀(x : T) -> y
binary file changed (absent → 12 bytes)
@@ -0,0 +1,11 @@+[ [+ 1,+ 2,+ 3,+ ]+, [+ , 1+ , 2+ , 3+ ]+]
@@ -0,0 +1,1 @@+ö ö ö
@@ -1,1 +0,0 @@-r.x
binary file changed (8 → absent bytes)
@@ -0,0 +1,1 @@+{ , =, }
@@ -0,0 +1,1 @@+
@@ -1,1 +0,0 @@-r.{ x, y, z }
binary file changed (12 → absent bytes)
@@ -0,0 +1,1 @@+{}
@@ -0,0 +1,1 @@+
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"A"
@@ -0,0 +1,1 @@+aA
@@ -0,0 +1,3 @@+#! /usr/bin/env nix-shell+#! nix-shell -i "dhall --file" -p dhall+42
@@ -0,0 +1,1 @@+*
@@ -0,0 +1,1 @@+showConstructor <A>.A
@@ -0,0 +1,1 @@+" ¡aAöaA
@@ -0,0 +1,1 @@+showConstructor (<A : Bool>.A False)
binary file changed (absent → 20 bytes)
@@ -0,0 +1,1 @@+Time
@@ -0,0 +1,1 @@+dTime
@@ -0,0 +1,1 @@+12:00:00
binary file changed (absent → 9 bytes)
@@ -0,0 +1,1 @@+TimeZone
@@ -0,0 +1,1 @@+hTimeZone
@@ -0,0 +1,1 @@++08:00
binary file changed (absent → 6 bytes)
@@ -0,0 +1,2 @@+-- This test verifies that a trailing line comment does not require a newline+1--
@@ -0,0 +1,1 @@+
@@ -0,0 +1,1 @@+{ Some = 0 } with Some = 1
binary file changed (absent → 23 bytes)
@@ -0,0 +1,1 @@+w === x === y === z
binary file changed (absent → 25 bytes)
@@ -1,1 +1,1 @@-x //\\ y+x /\ y
@@ -1,1 +1,1 @@-w //\\ x //\\ y //\\ z+w /\ x /\ y /\ z
binary file changed (25 → 25 bytes)
binary file changed (11 → 11 bytes)
@@ -1,1 +1,1 @@-x /\ y+x //\\ y
@@ -1,1 +1,1 @@-w /\ x /\ y /\ z+w //\\ x //\\ y //\\ z
binary file changed (25 → 25 bytes)
binary file changed (11 → 11 bytes)
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
binary file changed (absent → 14 bytes)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and [ True, False, True ]+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and ([] : List Bool)+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True, False ]+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True ]+../../../../../../Prelude/Bool/even.dhall [ False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False ]+../../../../../../Prelude/Bool/even.dhall [ False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even ([] : List Bool)+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold True Natural 0 1+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold False Natural 0 1+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not True+../../../../../../Prelude/Bool/not.dhall True
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not False+../../../../../../Prelude/Bool/not.dhall False
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False ]+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True ]+../../../../../../Prelude/Bool/odd.dhall [ True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or [ True, False, True ]+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or ([] : List Bool)+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show True+../../../../../../Prelude/Bool/show.dhall True
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show False+../../../../../../Prelude/Bool/show.dhall False
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show -3.1+../../../../../../Prelude/Double/show.dhall -3.1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show 0.4+../../../../../../Prelude/Double/show.dhall 0.4
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show -3+../../../../../../Prelude/Integer/show.dhall -3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show +0+../../../../../../Prelude/Integer/show.dhall +0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble -3+../../../../../../Prelude/Integer/toDouble.dhall -3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble +2+../../../../../../Prelude/Integer/toDouble.dhall +2
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ]
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [] : List Natural , [] : List Natural , [] : List Natural
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/fold+../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
@@ -1,5 +1,5 @@ λ(nil : Natural)-→ ../../../../../../Prelude/List/fold+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
@@ -1,4 +1,4 @@ λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 9 Natural 1+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 0 Natural 1+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/shifted+../../../../../../Prelude/List/shifted.dhall Bool [ [ { index = 0, value = True } , { index = 1, value = True }
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/unzip+../../../../../../Prelude/List/unzip.dhall Text Bool [ { _1 = "ABC", _2 = True }
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 10+../../../../../../Prelude/Natural/enumerate.dhall 10
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 0+../../../../../../Prelude/Natural/enumerate.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 3+../../../../../../Prelude/Natural/even.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 0+../../../../../../Prelude/Natural/even.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
@@ -1,1 +1,1 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
@@ -1,4 +1,4 @@ λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 2+../../../../../../Prelude/Natural/isZero.dhall 2
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 0+../../../../../../Prelude/Natural/isZero.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 3+../../../../../../Prelude/Natural/odd.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 0+../../../../../../Prelude/Natural/odd.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product ([] : List Natural)+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 3+../../../../../../Prelude/Natural/show.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 0+../../../../../../Prelude/Natural/show.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 3+../../../../../../Prelude/Natural/toDouble.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 0+../../../../../../Prelude/Natural/toDouble.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 3+../../../../../../Prelude/Natural/toInteger.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 0+../../../../../../Prelude/Natural/toInteger.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (Some 2)+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (None Natural)+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (Some 2)+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (None Natural)+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat ([] : List Text)+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/show "ABC"+../../../../../../Prelude/Text/show.dhall "ABC"
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/show "\u0000 \$ \\ \n \u263a"+../../../../../../Prelude/Text/show.dhall "\u0000 \$ \\ \n \u263a"
@@ -0,0 +1,3 @@+-- This parses, but will fail to type-check, because in the absence of the `T`+-- it is interpreted as a `Date` applied to a `Time`+2020-01-01 12:00:00
@@ -0,0 +1,1 @@+{ x = 1 } : { y : Natural }
@@ -0,0 +1,1 @@+{ x = 1 } : { x : Text }
@@ -0,0 +1,1 @@+assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
@@ -0,0 +1,1 @@+\(_: Bool) -> assert : (\(_: Bool) -> _) === (\(x: Bool) -> _)
@@ -0,0 +1,1 @@+assert : -0.0 ≡ +0.0
@@ -0,0 +1,1 @@+assert : Bool
@@ -0,0 +1,1 @@+assert : 1 === 2
@@ -0,0 +1,6 @@+let Example =+ { Type = { name : Text, id : Optional Natural }+ , default = { id = None Natural }+ }++in Example::{=}
@@ -0,0 +1,6 @@+let Example =+ { Type = { name : Text, id : Optional Natural }+ , default = { name = True, id = None Natural }+ }++in Example::{=}
@@ -0,0 +1,6 @@+let Example =+ { Type = { name : Text, id : Optional Natural }+ , default = { name = "", id = None Natural }+ }++in Example::{ nam = "John Doe" }
@@ -0,0 +1,6 @@+let Example =+ { Type = { name : Text, id : Optional Natural }+ , default = { name = "", id = None Natural }+ }++in Example::{ name = True }
@@ -0,0 +1,1 @@+toMap {=}
@@ -0,0 +1,1 @@+1 === False
@@ -0,0 +1,1 @@+Bool === Bool
@@ -0,0 +1,1 @@+(λ(_ : Natural) → _) True
@@ -0,0 +1,1 @@+True True
@@ -0,0 +1,1 @@+λ(_ : 1) → _
@@ -0,0 +1,1 @@+2 → _
@@ -0,0 +1,1 @@+Kind → Sort
@@ -0,0 +1,1 @@+Bool -> 1
@@ -0,0 +1,1 @@+Type → Sort
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= "Bar" }
@@ -0,0 +1,1 @@+if True then 1 else ""
@@ -0,0 +1,1 @@+if True then Kind else Kind
@@ -0,0 +1,1 @@+if 1 then 1 else 1
@@ -0,0 +1,1 @@+\(x: let x = 0 in Sort) -> 1
@@ -0,0 +1,14 @@+-- When you check if an inferred type is equivalent to an annotation,+-- you must alpha-beta-normalize both sides first. But it is not safe+-- to beta-normalise an expression which hasn't first been+-- typechecked.+--+-- This test contains an annotation which doesn't typecheck, and+-- which, when beta-normalized, doesn't terminate. It exists to+-- verify that implementations typecheck the annotation before+-- checking equivalence.+let a+ : (λ(x : Natural) → x x) (λ(x : Natural) → x x)+ = 3++in 5
@@ -0,0 +1,1 @@+let x : Natural = True in True
@@ -0,0 +1,1 @@+[] : List Type
@@ -0,0 +1,1 @@+[ Bool ]
@@ -0,0 +1,1 @@+[ True, 1 ]
@@ -0,0 +1,1 @@+merge {=} (< x : Bool >.x True)
@@ -0,0 +1,1 @@+merge { x = 0 } < x >.x : Bool
@@ -0,0 +1,1 @@+merge {=} <> : Type
@@ -0,0 +1,1 @@+\(x: { True: Natural, False: Natural }) -> merge x True
@@ -0,0 +1,1 @@+\(x: <>) -> (merge {=} x) : Bool
@@ -0,0 +1,1 @@+\(x: <>) -> let y: Bool = merge {=} x in 1
@@ -0,0 +1,1 @@+merge {=} <>
@@ -0,0 +1,1 @@+merge { x = None } (<x: Type>.x Bool)
@@ -0,0 +1,1 @@+merge { x = True } (< x : Bool >.x True)
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } <> : Bool
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _ } (< x : Natural >.x 1)
@@ -0,0 +1,1 @@+merge { x = λ(_ : Bool) → _, y = λ(_ : Natural) → _ } (< x : Bool | y : Natural >.x True)
@@ -0,0 +1,1 @@+merge True < x >.x
@@ -0,0 +1,1 @@+merge {=} <x>.x
@@ -0,0 +1,1 @@+merge { x = 0 } <x | y>.x
@@ -0,0 +1,1 @@+merge {=} True
@@ -0,0 +1,1 @@+merge { x = 1, y = 2 } < x >.x
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : Natural
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List Natural
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Natural, mapValue : Natural }
@@ -0,0 +1,1 @@+toMap { foo= 1, bar= 4 } : List { mapKey : Text, mapValue : Text }
@@ -0,0 +1,1 @@+Natural/subtract True True
@@ -0,0 +1,1 @@+(0 : Bool) : Natural
@@ -0,0 +1,1 @@+(0 : Natural) : Bool
@@ -0,0 +1,1 @@+toMap "text"
@@ -0,0 +1,1 @@+1 && 1
@@ -0,0 +1,1 @@+1 == 1
@@ -0,0 +1,1 @@+1 # [ True ]
@@ -0,0 +1,1 @@+[ True ] # [ 1 ]
@@ -0,0 +1,1 @@+1 # 2
@@ -0,0 +1,1 @@+[ True ] # 1
@@ -0,0 +1,1 @@+1 != 1
@@ -0,0 +1,1 @@+1 || 1
@@ -0,0 +1,1 @@+True + True
@@ -0,0 +1,1 @@+1 ++ ""
@@ -0,0 +1,1 @@+"" ++ 1
@@ -0,0 +1,1 @@+True * True
@@ -0,0 +1,1 @@+[] : Optional Bool
@@ -0,0 +1,1 @@+[ 1 ] : Optional Natural
@@ -0,0 +1,13 @@+{- This test illustrates that duplicate fields need not be literals in order+ to be properly normalized. One or both of the duplicate fields can be+ abstract because field duplication delegates its behavior to the `∧`+ operator++ This particular example fails because it desugars to:++ λ(r : { y : Natural }) → { x = { y = 1 } ∧ r }++ ... and the `∧` operator can infer that the two records collide on the+ field `y`+-}+λ(r : { y : Natural }) → { x = { y = 1 }, x = r }
@@ -0,0 +1,8 @@+{- This fails because the expression desugars to:++ { x = { y = 0 } ∧ { y = 0 } }++ ... which is ill-typed due to `∧` forbidding collisions and the two `y`+ fields collide.+-}+{ x = { y = 0 }, x = { y = 0 } }
@@ -0,0 +1,7 @@+{- This fails because the expression desugars to:++ { x = 0 ∧ 0 }++ ... which is ill-typed due to ∧ only working on records+-}+{ x = 0, x = 0 }
@@ -0,0 +1,1 @@+{ y = {=} }.( {y : Natural} )
@@ -0,0 +1,1 @@+{ y = {=} }.( {x : Natural} )
@@ -0,0 +1,1 @@+{ x = 1 }.{ x, x }
@@ -0,0 +1,1 @@+{=}.{ x }
@@ -0,0 +1,1 @@+{ y = {=} }.{ x }
@@ -0,0 +1,1 @@+True.{ x }
@@ -0,0 +1,1 @@+{=}.x
@@ -0,0 +1,1 @@+{ y = {=} }.x
@@ -0,0 +1,1 @@+True.x
@@ -0,0 +1,1 @@+Bool.x
@@ -0,0 +1,1 @@+{ x: Natural, x: Natural }
@@ -0,0 +1,1 @@+{ x : True }
@@ -0,0 +1,1 @@+True ∧ {=}
@@ -0,0 +1,1 @@+{ x = True } ∧ { x = False }
@@ -0,0 +1,1 @@+{=} ∧ True
@@ -0,0 +1,1 @@+Bool ⩓ {}
@@ -0,0 +1,1 @@+{ x : Bool } ⩓ { x : Natural }
@@ -0,0 +1,1 @@+{} ⩓ Bool
@@ -0,0 +1,1 @@+Optional/build
@@ -0,0 +1,1 @@+Optional/fold
@@ -0,0 +1,1 @@+True ⫽ {=}
@@ -0,0 +1,1 @@+{=} ⫽ True
@@ -0,0 +1,1 @@+showConstructor < A : Bool >.A
@@ -0,0 +1,1 @@+showConstructor None
@@ -0,0 +1,1 @@+showConstructor 0
@@ -0,0 +1,1 @@+Some Bool
@@ -0,0 +1,1 @@+Sort
@@ -0,0 +1,1 @@+"${1}"
@@ -0,0 +1,2 @@+-- The mapKey must be Text+toMap {=} : List { mapKey : Bool, mapValue : Text }
@@ -0,0 +1,1 @@+toMap { x = Bool }
@@ -0,0 +1,1 @@+1 : Bool
@@ -0,0 +1,1 @@+< x : Bool >.y
@@ -0,0 +1,1 @@+constructors < Left : Natural | Right : Bool >
@@ -0,0 +1,1 @@+<x | x>
@@ -0,0 +1,1 @@+<x | x: Natural>
@@ -0,0 +1,1 @@+< x : True >
@@ -0,0 +1,1 @@+x
@@ -0,0 +1,1 @@+Some ({=} with x = Bool)
@@ -0,0 +1,6 @@+{- The `with` keyword cannot "descend" past a field that is not a record++ In the following example, the `a` field is not a record, therefore there is+ no possibility of adding or overriding `a` with an inner `b` field+-}+{ a = 1 } with a.b = 2
@@ -0,0 +1,1 @@+{ x = 0 } with ? = 1
@@ -0,0 +1,1 @@+5 with a = 10
@@ -0,0 +1,1 @@+(None { x : Natural }) with ?.x = True
@@ -0,0 +1,1 @@+(None Natural) with ? = "hello"
@@ -0,0 +1,4 @@+-- The purpose of this test is to check that an implementation is not parsing a+-- standalone `Z` as a `TimeOffset`. Instead, this should be treated as an+-- unbound variable named `Z`+Z
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and [ True, False, True ]+../../../../../../Prelude/Bool/and.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/and ([] : List Bool)+../../../../../../Prelude/Bool/and.dhall ([] : List Bool)
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → true)
@@ -1,2 +1,2 @@-../../../../../../Prelude/Bool/build +../../../../../../Prelude/Bool/build.dhall (λ(bool : Type) → λ(true : bool) → λ(false : bool) → false)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True, False ]+../../../../../../Prelude/Bool/even.dhall [ False, True, False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False, True ]+../../../../../../Prelude/Bool/even.dhall [ False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even [ False ]+../../../../../../Prelude/Bool/even.dhall [ False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/even ([] : List Bool)+../../../../../../Prelude/Bool/even.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold True Natural 0 1+../../../../../../Prelude/Bool/fold.dhall True Natural 0 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/fold False Natural 0 1+../../../../../../Prelude/Bool/fold.dhall False Natural 0 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not True+../../../../../../Prelude/Bool/not.dhall True
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/not False+../../../../../../Prelude/Bool/not.dhall False
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False, True ]+../../../../../../Prelude/Bool/odd.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True, False ]+../../../../../../Prelude/Bool/odd.dhall [ True, False ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd [ True ]+../../../../../../Prelude/Bool/odd.dhall [ True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/odd ([] : List Bool)+../../../../../../Prelude/Bool/odd.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or [ True, False, True ]+../../../../../../Prelude/Bool/or.dhall [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/or ([] : List Bool)+../../../../../../Prelude/Bool/or.dhall ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show True+../../../../../../Prelude/Bool/show.dhall True
@@ -1,1 +1,1 @@-../../../../../../Prelude/Bool/show False+../../../../../../Prelude/Bool/show.dhall False
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show -3.1+../../../../../../Prelude/Double/show.dhall -3.1
@@ -1,1 +1,1 @@-../../../../../../Prelude/Double/show 0.4+../../../../../../Prelude/Double/show.dhall 0.4
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show -3+../../../../../../Prelude/Integer/show.dhall -3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/show +0+../../../../../../Prelude/Integer/show.dhall +0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble -3+../../../../../../Prelude/Integer/toDouble.dhall -3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Integer/toDouble +2+../../../../../../Prelude/Integer/toDouble.dhall +2
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/all.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/all Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/all.dhall Natural Natural/even ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/any.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/any Natural Natural/even ([] : List Natural)+../../../../../../Prelude/List/any.dhall Natural Natural/even ([] : List Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/build+../../../../../../Prelude/List/build.dhall Text ( λ(list : Type) → λ(cons : Text → list → list)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [ 0, 1, 2 ] , [ 3, 4 ] , [ 5, 6, 7, 8 ]
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/concat Natural+../../../../../../Prelude/List/concat.dhall Natural [ [] : List Natural , [] : List Natural , [] : List Natural
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/concatMap Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)+../../../../../../Prelude/List/concatMap.dhall Natural Natural (λ(n : Natural) → [ n, n ]) ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/filter Natural Natural/odd [ 2, 3, 5 ]+../../../../../../Prelude/List/filter.dhall Natural Natural/odd [ 2, 3, 5 ]
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/fold+../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
@@ -1,5 +1,5 @@ λ(nil : Natural)-→ ../../../../../../Prelude/List/fold+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] Natural
@@ -1,4 +1,4 @@ λ(list : Type) → λ(cons : Natural → list → list) → λ(nil : list)-→ ../../../../../../Prelude/List/fold Natural [ 2, 3, 5 ] list cons nil+→ ../../../../../../Prelude/List/fold.dhall Natural [ 2, 3, 5 ] list cons nil
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 5 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 5 Bool Natural/even
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/generate 0 Bool Natural/even+../../../../../../Prelude/List/generate.dhall 0 Bool Natural/even
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/head.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/head Natural ([] : List Natural)+../../../../../../Prelude/List/head.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool [ True, False, True ]+../../../../../../Prelude/List/indexed.dhall Bool [ True, False, True ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/indexed Bool ([] : List Bool)+../../../../../../Prelude/List/indexed.dhall Bool ([] : List Bool)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 10 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 10 Natural (λ(x : Natural) → x * 2) 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/iterate 0 Natural (λ(x : Natural) → x * 2) 1+../../../../../../Prelude/List/iterate.dhall 0 Natural (λ(x : Natural) → x * 2) 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/last.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/last Natural ([] : List Natural)+../../../../../../Prelude/List/last.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/length.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/length Natural ([] : List Natural)+../../../../../../Prelude/List/length.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even [ 2, 3, 5 ]+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/map Natural Bool Natural/even ([] : List Natural)+../../../../../../Prelude/List/map.dhall Natural Bool Natural/even ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/null.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/null Natural ([] : List Natural)+../../../../../../Prelude/List/null.dhall Natural ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 9 Natural 1+../../../../../../Prelude/List/replicate.dhall 9 Natural 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/replicate 0 Natural 1+../../../../../../Prelude/List/replicate.dhall 0 Natural 1
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural [ 0, 1, 2 ]+../../../../../../Prelude/List/reverse.dhall Natural [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/reverse Natural ([] : List Natural)+../../../../../../Prelude/List/reverse.dhall Natural ([] : List Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/shifted+../../../../../../Prelude/List/shifted.dhall Bool [ [ { index = 0, value = True } , { index = 1, value = True }
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/shifted Bool ([] : List (List { index : Natural, value : Bool }))+../../../../../../Prelude/List/shifted.dhall Bool ([] : List (List { index : Natural, value : Bool }))
@@ -1,4 +1,4 @@-../../../../../../Prelude/List/unzip+../../../../../../Prelude/List/unzip.dhall Text Bool [ { _1 = "ABC", _2 = True }
@@ -1,1 +1,1 @@-../../../../../../Prelude/List/unzip Text Bool ([] : List { _1 : Text, _2 : Bool })+../../../../../../Prelude/List/unzip.dhall Text Bool ([] : List { _1 : Text, _2 : Bool })
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Natural/build+../../../../../../Prelude/Natural/build.dhall ( λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 10+../../../../../../Prelude/Natural/enumerate.dhall 10
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/enumerate 0+../../../../../../Prelude/Natural/enumerate.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 3+../../../../../../Prelude/Natural/even.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/even 0+../../../../../../Prelude/Natural/even.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) 1+../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) 1
@@ -1,1 +1,1 @@-λ(zero : Natural) → ../../../../../../Prelude/Natural/fold 3 Natural (λ(x : Natural) → 5 * x) zero+λ(zero : Natural) → ../../../../../../Prelude/Natural/fold.dhall 3 Natural (λ(x : Natural) → 5 * x) zero
@@ -1,4 +1,4 @@ λ(natural : Type) → λ(succ : natural → natural) → λ(zero : natural)-→ ../../../../../../Prelude/Natural/fold 3 natural succ zero+→ ../../../../../../Prelude/Natural/fold.dhall 3 natural succ zero
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 2+../../../../../../Prelude/Natural/isZero.dhall 2
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/isZero 0+../../../../../../Prelude/Natural/isZero.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 3+../../../../../../Prelude/Natural/odd.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/odd 0+../../../../../../Prelude/Natural/odd.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product [ 2, 3, 5 ]+../../../../../../Prelude/Natural/product.dhall [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/product ([] : List Natural)+../../../../../../Prelude/Natural/product.dhall ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 3+../../../../../../Prelude/Natural/show.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/show 0+../../../../../../Prelude/Natural/show.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum [ 2, 3, 5 ]+../../../../../../Prelude/Natural/sum.dhall [ 2, 3, 5 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/sum ([] : List Natural)+../../../../../../Prelude/Natural/sum.dhall ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 3+../../../../../../Prelude/Natural/toDouble.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toDouble 0+../../../../../../Prelude/Natural/toDouble.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 3+../../../../../../Prelude/Natural/toInteger.dhall 3
@@ -1,1 +1,1 @@-../../../../../../Prelude/Natural/toInteger 0+../../../../../../Prelude/Natural/toInteger.dhall 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (Some 3)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (Some 3)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/all Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/all.dhall Natural Natural/even (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/any Natural Natural/even (None Natural)+../../../../../../Prelude/Optional/any.dhall Natural Natural/even (None Natural)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
@@ -1,4 +1,4 @@-../../../../../../Prelude/Optional/build+../../../../../../Prelude/Optional/build.dhall Natural ( λ(optional : Type) → λ(some : Natural → optional)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (Some 1))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (Some 1))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (Some (None Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (Some (None Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/concat Natural (None (Optional Natural))+../../../../../../Prelude/Optional/concat.dhall Natural (None (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/even (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/even (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/filter Natural Natural/odd (Some 2)+../../../../../../Prelude/Optional/filter.dhall Natural Natural/odd (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (Some 2) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (Some 2) Natural (λ(x : Natural) → x) 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/fold Natural (None Natural) Natural (λ(x : Natural) → x) 0+../../../../../../Prelude/Optional/fold.dhall Natural (None Natural) Natural (λ(x : Natural) → x) 0
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, Some 1, Some 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/head.dhall Natural [ None Natural, None Natural ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/head Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/head.dhall Natural ([] : List (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, Some 1, Some 2 ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, Some 1, Some 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural [ None Natural, None Natural ]+../../../../../../Prelude/Optional/last.dhall Natural [ None Natural, None Natural ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/last Natural ([] : List (Optional Natural))+../../../../../../Prelude/Optional/last.dhall Natural ([] : List (Optional Natural))
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (Some 2)+../../../../../../Prelude/Optional/length.dhall Natural (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/length Natural (None Natural)+../../../../../../Prelude/Optional/length.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (Some 3)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (Some 3)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/map Natural Bool Natural/even (None Natural)+../../../../../../Prelude/Optional/map.dhall Natural Bool Natural/even (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (Some 2)+../../../../../../Prelude/Optional/null.dhall Natural (Some 2)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/null Natural (None Natural)+../../../../../../Prelude/Optional/null.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (Some 1)+../../../../../../Prelude/Optional/toList.dhall Natural (Some 1)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/toList Natural (None Natural)+../../../../../../Prelude/Optional/toList.dhall Natural (None Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (Some { _1 = "ABC", _2 = True })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (Some { _1 = "ABC", _2 = True })
@@ -1,1 +1,1 @@-../../../../../../Prelude/Optional/unzip Text Bool (None { _1 : Text, _2 : Bool })+../../../../../../Prelude/Optional/unzip.dhall Text Bool (None { _1 : Text, _2 : Bool })
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concat.dhall [ "ABC", "DEF", "GHI" ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concat ([] : List Text)+../../../../../../Prelude/Text/concat.dhall ([] : List Text)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMap Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)+../../../../../../Prelude/Text/concatMap.dhall Natural (λ(n : Natural) → "${Natural/show n} ") ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show [ 0, 1, 2 ]+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show [ 0, 1, 2 ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatMapSep ", " Natural Natural/show ([] : List Natural)+../../../../../../Prelude/Text/concatMapSep.dhall ", " Natural Natural/show ([] : List Natural)
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " [ "ABC", "DEF", "GHI" ]+../../../../../../Prelude/Text/concatSep.dhall ", " [ "ABC", "DEF", "GHI" ]
@@ -1,1 +1,1 @@-../../../../../../Prelude/Text/concatSep ", " ([] : List Text)+../../../../../../Prelude/Text/concatSep.dhall ", " ([] : List Text)
@@ -2,6 +2,7 @@ { and : ∀(xs : List Bool) → Bool , build : ∀(f : ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool) → Bool+ , equal : ∀(x : Bool) → ∀(y : Bool) → Bool , even : ∀(xs : List Bool) → Bool , fold : ∀(b : Bool) → ∀(bool : Type) → ∀(true : bool) → ∀(false : bool) → bool@@ -10,16 +11,18 @@ , or : ∀(xs : List Bool) → Bool , show : ∀(b : Bool) → Text }+, Date : { show : Date → Text } , Double : { show : Double → Text } , Function : { compose :- ∀(A : Type) →- ∀(B : Type) →- ∀(C : Type) →- ∀(f : A → B) →- ∀(g : B → C) →- ∀(x : A) →- C+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(c : Type) →+ ∀(f : a → b) →+ ∀(g : b → c) →+ ∀(x : a) →+ c+ , composeList : ∀(a : Type) → ∀(functions : List (a → a)) → a → a , identity : ∀(a : Type) → ∀(x : a) → a } , Integer :@@ -239,6 +242,22 @@ JSON ) → Text+ , renderCompact :+ ∀ ( j+ : ∀(JSON : Type) →+ ∀ ( json+ : { array : List JSON → JSON+ , bool : Bool → JSON+ , double : Double → JSON+ , integer : Integer → JSON+ , null : JSON+ , object : List { mapKey : Text, mapValue : JSON } → JSON+ , string : Text → JSON+ }+ ) →+ JSON+ ) →+ Text , renderInteger : ∀(integer : Integer) → Text , renderYAML : ∀ ( json@@ -296,6 +315,12 @@ , drop : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → List a , empty : ∀(a : Type) → List a , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : List a) → List a+ , filterMap :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → Optional b) →+ ∀(xs : List a) →+ List b , fold : ∀(a : Type) → List a →@@ -303,6 +328,13 @@ ∀(cons : a → list → list) → ∀(nil : list) → list+ , foldLeft :+ ∀(a : Type) →+ ∀(xs : List a) →+ ∀(list : Type) →+ ∀(cons : list → a → list) →+ ∀(nil : list) →+ list , generate : ∀(n : Natural) → ∀(a : Type) → ∀(f : Natural → a) → List a , head : ∀(a : Type) → List a → Optional a , index : ∀(n : Natural) → ∀(a : Type) → ∀(xs : List a) → Optional a@@ -311,6 +343,18 @@ , last : ∀(a : Type) → List a → Optional a , length : ∀(a : Type) → List a → Natural , map : ∀(a : Type) → ∀(b : Type) → ∀(f : a → b) → ∀(xs : List a) → List b+ , mapMaybe :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → Optional b) →+ ∀(xs : List a) →+ List b+ , mapWithIndex :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : Natural → a → b) →+ ∀(xs : List a) →+ List b , null : ∀(a : Type) → ∀(xs : List a) → Bool , partition : ∀(a : Type) →@@ -361,6 +405,13 @@ ∀(f : a → b) → ∀(m : List { mapKey : k, mapValue : a }) → List { mapKey : k, mapValue : b }+ , mapMaybe :+ ∀(k : Type) →+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → Optional b) →+ ∀(m : List { mapKey : k, mapValue : a }) →+ List { mapKey : k, mapValue : b } , unpackOptionals : ∀(k : Type) → ∀(v : Type) →@@ -408,6 +459,102 @@ , toDouble : ∀(n : Natural) → Double , toInteger : Natural → Integer }+, NonEmpty :+ { Type : ∀(a : Type) → Type+ , all :+ ∀(a : Type) →+ ∀(f : a → Bool) →+ ∀(xs : { head : a, tail : List a }) →+ Bool+ , any :+ ∀(a : Type) →+ ∀(f : a → Bool) →+ ∀(xs : { head : a, tail : List a }) →+ Bool+ , concat :+ ∀(a : Type) →+ ∀ ( xss+ : { head : { head : a, tail : List a }+ , tail : List { head : a, tail : List a }+ }+ ) →+ { head : a, tail : List a }+ , concatMap :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → { head : b, tail : List b }) →+ ∀(xs : { head : a, tail : List a }) →+ { head : b, tail : List b }+ , head : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+ , index :+ ∀(n : Natural) →+ ∀(a : Type) →+ ∀(xs : { head : a, tail : List a }) →+ Optional a+ , indexed :+ ∀(a : Type) →+ ∀(xs : { head : a, tail : List a }) →+ { head : { index : Natural, value : a }+ , tail : List { index : Natural, value : a }+ }+ , last : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → a+ , length : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → Natural+ , make :+ ∀(a : Type) →+ ∀(head : a) →+ ∀(tail : List a) →+ { head : a, tail : List a }+ , map :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → b) →+ ∀(xs : { head : a, tail : List a }) →+ { head : b, tail : List b }+ , reverse :+ ∀(a : Type) →+ ∀(xs : { head : a, tail : List a }) →+ { head : a, tail : List a }+ , shifted :+ ∀(a : Type) →+ ∀ ( kvss+ : { head :+ { head : { index : Natural, value : a }+ , tail : List { index : Natural, value : a }+ }+ , tail :+ List+ { head : { index : Natural, value : a }+ , tail : List { index : Natural, value : a }+ }+ }+ ) →+ { head : { index : Natural, value : a }+ , tail : List { index : Natural, value : a }+ }+ , singleton : ∀(a : Type) → ∀(x : a) → { head : a, tail : List a }+ , toList : ∀(a : Type) → ∀(xs : { head : a, tail : List a }) → List a+ , unzip :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(xs : { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }) →+ { _1 : { head : a, tail : List a }, _2 : { head : b, tail : List b } }+ , zip :+ ∀(a : Type) →+ ∀(xs : { head : a, tail : List a }) →+ ∀(b : Type) →+ ∀(ys : { head : b, tail : List b }) →+ { head : { _1 : a, _2 : b }, tail : List { _1 : a, _2 : b } }+ }+, Operator :+ { `!=` : ∀(m : Bool) → ∀(n : Bool) → Bool+ , `#` : ∀(type : Type) → ∀(m : List type) → ∀(n : List type) → List type+ , `&&` : ∀(m : Bool) → ∀(n : Bool) → Bool+ , `*` : ∀(m : Natural) → ∀(n : Natural) → Natural+ , `+` : ∀(m : Natural) → ∀(n : Natural) → Natural+ , `++` : ∀(m : Text) → ∀(n : Text) → Text+ , `==` : ∀(m : Bool) → ∀(n : Bool) → Bool+ , `||` : ∀(m : Bool) → ∀(n : Bool) → Bool+ } , Optional : { all : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool , any : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Bool@@ -421,7 +568,19 @@ ) → Optional a , concat : ∀(a : Type) → ∀(x : Optional (Optional a)) → Optional a+ , concatMap :+ ∀(a : Type) →+ ∀(b : Type) →+ ∀(f : a → Optional b) →+ ∀(o : Optional a) →+ Optional b , default : ∀(a : Type) → ∀(default : a) → ∀(o : Optional a) → a+ , equal :+ ∀(a : Type) →+ ∀(compare : a → a → Bool) →+ ∀(ox : Optional a) →+ ∀(oy : Optional a) →+ Bool , filter : ∀(a : Type) → ∀(f : a → Bool) → ∀(xs : Optional a) → Optional a , fold : ∀(a : Type) →@@ -459,10 +618,17 @@ , concatSep : ∀(separator : Text) → ∀(elements : List Text) → Text , default : ∀(o : Optional Text) → Text , defaultMap : ∀(a : Type) → ∀(f : a → Text) → ∀(o : Optional a) → Text+ , lowerASCII : ∀(nil : Text) → Text+ , replace :+ ∀(needle : Text) → ∀(replacement : Text) → ∀(haystack : Text) → Text , replicate : ∀(num : Natural) → ∀(text : Text) → Text+ , shell-escape : ∀(xs : Text) → Text , show : Text → Text , spaces : ∀(a : Natural) → Text+ , upperASCII : ∀(nil : Text) → Text }+, Time : { show : Time → Text }+, TimeZone : { show : TimeZone → Text } , XML : { Type : Type , attribute :@@ -481,6 +647,7 @@ , name : Text } → XML+ , rawText : Text → XML , text : Text → XML } ) →@@ -497,6 +664,7 @@ , name : Text } → XML+ , rawText : Text → XML , text : Text → XML } ) →@@ -516,10 +684,26 @@ , name : Text } → XML+ , rawText : Text → XML , text : Text → XML } ) → XML+ , rawText :+ ∀(d : Text) →+ ∀(XML : Type) →+ ∀ ( xml+ : { element :+ { attributes : List { mapKey : Text, mapValue : Text }+ , content : List XML+ , name : Text+ } →+ XML+ , rawText : Text → XML+ , text : Text → XML+ }+ ) →+ XML , render : ∀ ( x : ∀(XML : Type) →@@ -530,6 +714,7 @@ , name : Text } → XML+ , rawText : Text → XML , text : Text → XML } ) →@@ -546,6 +731,7 @@ , name : Text } → XML+ , rawText : Text → XML , text : Text → XML } ) →
@@ -0,0 +1,1 @@+0x"0123456789abcdefABCDEF"
@@ -0,0 +1,1 @@+Bytes
@@ -0,0 +1,1 @@+λ(t : Type) → < t : t >.t
@@ -0,0 +1,1 @@+∀(t : Type) → ∀(t : t) → < t : t@1 >
@@ -0,0 +1,1 @@+if True then (Type -> Type) else Type
@@ -0,0 +1,1 @@+Kind
@@ -0,0 +1,1 @@+if True then Bool else Natural
@@ -0,0 +1,1 @@+Type
@@ -1,1 +1,1 @@-merge { x = λ(y : Bool) → y } < x >.x : (Bool → Bool)+merge { x = λ(y : Bool) → y } < x >.x : (∀(y : Bool) → Bool)
@@ -0,0 +1,1 @@+showConstructor <A>.A
@@ -0,0 +1,1 @@+Text
@@ -0,0 +1,1 @@+showConstructor (< A : Bool>.A False)
@@ -0,0 +1,1 @@+Text
@@ -0,0 +1,1 @@+showConstructor (Some 0)
@@ -0,0 +1,1 @@+Text
@@ -1,1 +1,1 @@-toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : Bool → Bool }+toMap { x = λ(x : Bool) → x } : List { mapKey : Text, mapValue : ∀(x : Bool) → Bool }
@@ -1,1 +1,1 @@-(λ(x : Bool) → x) : Bool → Bool+(λ(x : Bool) → x) : ∀(x : Bool) → Bool
@@ -0,0 +1,1 @@+Some ({ x = Bool } with x = 0)
@@ -0,0 +1,1 @@+Optional { x : Natural }
@@ -0,0 +1,1 @@+(Some 0) with ? = 1
@@ -0,0 +1,1 @@+Optional Natural
@@ -0,0 +1,1 @@+Date
@@ -0,0 +1,1 @@+Type
@@ -0,0 +1,1 @@+2000-01-01
@@ -0,0 +1,1 @@+Date
@@ -0,0 +1,1 @@+2000-01-01T12:00:00
@@ -0,0 +1,1 @@+{ date : Date, time : Time }
@@ -0,0 +1,1 @@+2000-01-01T12:00:00+08:00
@@ -0,0 +1,1 @@+{ date : Date, time : Time, timeZone : TimeZone }
@@ -0,0 +1,1 @@+Time
@@ -0,0 +1,1 @@+Type
@@ -0,0 +1,1 @@+12:00:00
@@ -0,0 +1,1 @@+Time
@@ -0,0 +1,1 @@+12:00:00+08:00
@@ -0,0 +1,1 @@+{ time : Time, timeZone : TimeZone }
@@ -0,0 +1,1 @@+TimeZone
@@ -0,0 +1,1 @@+Type
@@ -0,0 +1,1 @@++08:00
@@ -0,0 +1,1 @@+TimeZone
@@ -1,13 +1,12 @@+Cabal-Version: 2.4 Name: dhall-Version: 1.36.0-Cabal-Version: >=1.10+Version: 1.42.3 Build-Type: Simple-Tested-With: GHC == 8.4.3, GHC == 8.6.1-License: BSD3+License: BSD-3-Clause License-File: LICENSE-Copyright: 2017 Gabriel Gonzalez-Author: Gabriel Gonzalez-Maintainer: Gabriel439@gmail.com+Copyright: 2017 Gabriella Gonzalez+Author: Gabriella Gonzalez+Maintainer: GenuineGabriella@gmail.com Bug-Reports: https://github.com/dhall-lang/dhall-haskell/issues Synopsis: A configuration language guaranteed to terminate Description:@@ -25,10 +24,10 @@ Data-Files: man/dhall.1 Extra-Source-Files:- benchmark/deep-nested-large-record/*.dhall- benchmark/examples/*.dhall- benchmark/examples/normalize/*.dhall CHANGELOG.md+ benchmark/**/*.dhall+ benchmark/**/*.dhallb+ dhall-lang/Prelude/**/*.dhall dhall-lang/Prelude/Bool/and dhall-lang/Prelude/Bool/build dhall-lang/Prelude/Bool/even@@ -36,16 +35,10 @@ dhall-lang/Prelude/Bool/not dhall-lang/Prelude/Bool/odd dhall-lang/Prelude/Bool/or- dhall-lang/Prelude/Bool/package.dhall dhall-lang/Prelude/Bool/show- dhall-lang/Prelude/Bool/*.dhall- dhall-lang/Prelude/Double/package.dhall dhall-lang/Prelude/Double/show- dhall-lang/Prelude/Double/*.dhall dhall-lang/Prelude/Function/compose dhall-lang/Prelude/Function/identity- dhall-lang/Prelude/Function/package.dhall- dhall-lang/Prelude/Function/*.dhall dhall-lang/Prelude/Integer/abs dhall-lang/Prelude/Integer/add dhall-lang/Prelude/Integer/clamp@@ -59,20 +52,17 @@ dhall-lang/Prelude/Integer/negative dhall-lang/Prelude/Integer/nonNegative dhall-lang/Prelude/Integer/nonPositive- dhall-lang/Prelude/Integer/package.dhall dhall-lang/Prelude/Integer/positive dhall-lang/Prelude/Integer/show dhall-lang/Prelude/Integer/subtract dhall-lang/Prelude/Integer/toDouble dhall-lang/Prelude/Integer/toNatural- dhall-lang/Prelude/Integer/*.dhall dhall-lang/Prelude/JSON/Format dhall-lang/Prelude/JSON/Nesting dhall-lang/Prelude/JSON/Tagged dhall-lang/Prelude/JSON/Type dhall-lang/Prelude/JSON/array dhall-lang/Prelude/JSON/bool- dhall-lang/Prelude/JSON/core.dhall dhall-lang/Prelude/JSON/double dhall-lang/Prelude/JSON/integer dhall-lang/Prelude/JSON/keyText@@ -82,15 +72,12 @@ dhall-lang/Prelude/JSON/number dhall-lang/Prelude/JSON/object dhall-lang/Prelude/JSON/omitNullFields- dhall-lang/Prelude/JSON/package.dhall dhall-lang/Prelude/JSON/render dhall-lang/Prelude/JSON/renderAs- dhall-lang/Prelude/JSON/renderInteger.dhall dhall-lang/Prelude/JSON/renderYAML dhall-lang/Prelude/JSON/string dhall-lang/Prelude/JSON/tagInline dhall-lang/Prelude/JSON/tagNested- dhall-lang/Prelude/JSON/*.dhall dhall-lang/Prelude/List/all dhall-lang/Prelude/List/any dhall-lang/Prelude/List/build@@ -110,7 +97,6 @@ dhall-lang/Prelude/List/length dhall-lang/Prelude/List/map dhall-lang/Prelude/List/null- dhall-lang/Prelude/List/package.dhall dhall-lang/Prelude/List/partition dhall-lang/Prelude/List/replicate dhall-lang/Prelude/List/reverse@@ -119,10 +105,7 @@ dhall-lang/Prelude/List/unpackOptionals dhall-lang/Prelude/List/unzip dhall-lang/Prelude/List/zip- dhall-lang/Prelude/List/*.dhall dhall-lang/Prelude/Location/Type- dhall-lang/Prelude/Location/package.dhall- dhall-lang/Prelude/Location/*.dhall dhall-lang/Prelude/Map/Entry dhall-lang/Prelude/Map/Type dhall-lang/Prelude/Map/empty@@ -130,9 +113,7 @@ dhall-lang/Prelude/Map/keyValue dhall-lang/Prelude/Map/keys dhall-lang/Prelude/Map/map- dhall-lang/Prelude/Map/package.dhall dhall-lang/Prelude/Map/values- dhall-lang/Prelude/Map/*.dhall dhall-lang/Prelude/Monoid dhall-lang/Prelude/Natural/build dhall-lang/Prelude/Natural/enumerate@@ -149,7 +130,6 @@ dhall-lang/Prelude/Natural/max dhall-lang/Prelude/Natural/min dhall-lang/Prelude/Natural/odd- dhall-lang/Prelude/Natural/package.dhall dhall-lang/Prelude/Natural/product dhall-lang/Prelude/Natural/show dhall-lang/Prelude/Natural/sort@@ -157,7 +137,6 @@ dhall-lang/Prelude/Natural/sum dhall-lang/Prelude/Natural/toDouble dhall-lang/Prelude/Natural/toInteger- dhall-lang/Prelude/Natural/*.dhall dhall-lang/Prelude/Optional/all dhall-lang/Prelude/Optional/any dhall-lang/Prelude/Optional/build@@ -170,281 +149,34 @@ dhall-lang/Prelude/Optional/length dhall-lang/Prelude/Optional/map dhall-lang/Prelude/Optional/null- dhall-lang/Prelude/Optional/package.dhall dhall-lang/Prelude/Optional/toList dhall-lang/Prelude/Optional/unzip- dhall-lang/Prelude/Optional/*.dhall dhall-lang/Prelude/Text/concat dhall-lang/Prelude/Text/concatMap dhall-lang/Prelude/Text/concatMapSep dhall-lang/Prelude/Text/concatSep dhall-lang/Prelude/Text/default dhall-lang/Prelude/Text/defaultMap- dhall-lang/Prelude/Text/package.dhall dhall-lang/Prelude/Text/replicate dhall-lang/Prelude/Text/show dhall-lang/Prelude/Text/spaces- dhall-lang/Prelude/Text/*.dhall dhall-lang/Prelude/XML/Type dhall-lang/Prelude/XML/attribute dhall-lang/Prelude/XML/element dhall-lang/Prelude/XML/emptyAttributes dhall-lang/Prelude/XML/leaf- dhall-lang/Prelude/XML/package.dhall dhall-lang/Prelude/XML/render dhall-lang/Prelude/XML/text- dhall-lang/Prelude/XML/*.dhall- dhall-lang/Prelude/*.dhall- dhall-lang/Prelude/package.dhall- dhall-lang/tests/alpha-normalization/success/unit/*.dhall- dhall-lang/tests/alpha-normalization/success/regression/*.dhall- dhall-lang/tests/binary-decode/failure/unit/*.dhallb- dhall-lang/tests/binary-decode/success/unit/*.dhall- dhall-lang/tests/binary-decode/success/unit/*.dhallb- dhall-lang/tests/binary-decode/success/unit/imports/*.dhall- dhall-lang/tests/binary-decode/success/unit/imports/*.dhallb+ dhall-lang/tests/**/*.dhall+ dhall-lang/tests/**/*.dhallb+ dhall-lang/tests/**/*.hash+ dhall-lang/tests/**/*.txt+ dhall-lang/tests/**/*.bin dhall-lang/tests/import/cache/dhall/12203871180b87ecaba8b53fffb2a8b52d3fce98098fab09a6f759358b9e8042eedc dhall-lang/tests/import/cache/dhall/1220618f785ce8f3930a9144398f576f0a992544b51212bc9108c31b4e670dc6ed21- dhall-lang/tests/import/data/*.dhall- dhall-lang/tests/import/data/*.txt- dhall-lang/tests/import/failure/*.dhall- dhall-lang/tests/import/failure/unit/*.dhall- dhall-lang/tests/import/success/*.dhall- dhall-lang/tests/import/success/unit/*.dhall- dhall-lang/tests/import/success/unit/asLocation/*.dhall- dhall-lang/tests/normalization/success/*.dhall- dhall-lang/tests/normalization/success/haskell-tutorial/access/*.dhall- dhall-lang/tests/normalization/success/haskell-tutorial/combineTypes/*.dhall- dhall-lang/tests/normalization/success/haskell-tutorial/prefer/*.dhall- dhall-lang/tests/normalization/success/haskell-tutorial/projection/*.dhall- dhall-lang/tests/normalization/success/regression/*.dhall- dhall-lang/tests/normalization/success/simple/*.dhall- dhall-lang/tests/normalization/success/simplifications/*.dhall- dhall-lang/tests/normalization/success/unit/*.dhall- dhall-lang/tests/parser/failure/*.dhall- dhall-lang/tests/parser/failure/spacing/*.dhall- dhall-lang/tests/parser/failure/unit/*.dhall- dhall-lang/tests/parser/success/*.dhall- dhall-lang/tests/parser/success/*.dhallb- dhall-lang/tests/parser/success/text/*.dhall- dhall-lang/tests/parser/success/text/*.dhallb- dhall-lang/tests/parser/success/unit/*.dhall- dhall-lang/tests/parser/success/unit/*.dhallb- dhall-lang/tests/parser/success/unit/operators/*.dhall- dhall-lang/tests/parser/success/unit/operators/*.dhallb- dhall-lang/tests/parser/success/unit/import/*.dhall- dhall-lang/tests/parser/success/unit/import/*.dhallb- dhall-lang/tests/parser/success/unit/import/urls/*.dhall- dhall-lang/tests/parser/success/unit/import/urls/*.dhallb- dhall-lang/tests/semantic-hash/success/*.dhall- dhall-lang/tests/semantic-hash/success/*.hash- dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.dhall- dhall-lang/tests/semantic-hash/success/haskell-tutorial/access/*.hash- dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.dhall- dhall-lang/tests/semantic-hash/success/haskell-tutorial/combineTypes/*.hash- dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.dhall- dhall-lang/tests/semantic-hash/success/haskell-tutorial/prefer/*.hash- dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.dhall- dhall-lang/tests/semantic-hash/success/haskell-tutorial/projection/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/and/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/build/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/even/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/fold/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/not/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/odd/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/or/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Bool/show/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Double/show/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Integer/show/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Integer/toDouble/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/all/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/all/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/any/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/any/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/build/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/build/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/concat/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/concatMap/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/filter/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/fold/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/generate/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/head/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/head/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/indexed/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/iterate/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/last/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/last/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/length/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/length/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/map/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/map/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/null/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/null/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/replicate/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/reverse/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/shifted/*.hash- dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/List/unzip/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/build/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/enumerate/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/even/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/fold/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/isZero/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/odd/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/product/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/show/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/sum/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/toDouble/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Natural/toInteger/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/all/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/any/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/build/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/concat/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/filter/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/fold/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/head/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/last/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/length/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/map/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/null/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/toList/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Optional/unzip/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Text/concat/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMap/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Text/concatMapSep/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Text/concatSep/*.hash- dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.dhall- dhall-lang/tests/semantic-hash/success/prelude/Text/show/*.hash- dhall-lang/tests/semantic-hash/success/simple/*.dhall- dhall-lang/tests/semantic-hash/success/simple/*.hash- dhall-lang/tests/semantic-hash/success/simplifications/*.dhall- dhall-lang/tests/semantic-hash/success/simplifications/*.hash- dhall-lang/tests/type-inference/failure/*.dhall- dhall-lang/tests/type-inference/success/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/and/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/build/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/even/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/fold/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/not/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/odd/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/or/*.dhall- dhall-lang/tests/type-inference/success/prelude/Bool/show/*.dhall- dhall-lang/tests/type-inference/success/prelude/Double/show/*.dhall- dhall-lang/tests/type-inference/success/prelude/Integer/show/*.dhall- dhall-lang/tests/type-inference/success/prelude/Integer/toDouble/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/all/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/any/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/build/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/concat/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/concatMap/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/filter/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/fold/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/generate/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/head/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/indexed/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/iterate/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/last/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/length/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/map/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/null/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/replicate/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/reverse/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/shifted/*.dhall- dhall-lang/tests/type-inference/success/prelude/List/unzip/*.dhall- dhall-lang/tests/type-inference/success/prelude/Monoid/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/build/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/enumerate/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/even/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/fold/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/isZero/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/odd/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/product/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/show/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/sum/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/toDouble/*.dhall- dhall-lang/tests/type-inference/success/prelude/Natural/toInteger/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/all/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/any/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/build/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/concat/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/filter/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/fold/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/head/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/last/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/length/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/map/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/null/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/toList/*.dhall- dhall-lang/tests/type-inference/success/prelude/Optional/unzip/*.dhall- dhall-lang/tests/type-inference/success/prelude/Text/concat/*.dhall- dhall-lang/tests/type-inference/success/prelude/Text/concatMap/*.dhall- dhall-lang/tests/type-inference/success/prelude/Text/concatMapSep/*.dhall- dhall-lang/tests/type-inference/success/prelude/Text/concatSep/*.dhall- dhall-lang/tests/type-inference/success/regression/*.dhall- dhall-lang/tests/type-inference/success/simple/*.dhall- dhall-lang/tests/type-inference/success/simple/access/*.dhall- dhall-lang/tests/type-inference/success/unit/*.dhall- tests/diff/*.dhall- tests/diff/*.txt- tests/format/*.dhall- tests/freeze/*.dhall- tests/lint/success/*.dhall- tests/recursive/*.dhall- tests/regression/*.dhall- tests/schemas/*.dhall- tests/tags/*.dhall- tests/tags/*.tags- tests/th/*.dhall- tests/tutorial/*.dhall+ tests/**/*.dhall+ tests/**/*.tags+ tests/**/*.txt Source-Repository head Type: git@@ -466,62 +198,85 @@ Default: False Manual: True -Library- Hs-Source-Dirs: src+Flag network-tests+ Description: Enable tests which depend on an internet connection+ Default: True+ Manual: True++Common common Build-Depends: base >= 4.11.0.0 && < 5 ,- aeson >= 1.0.0.0 && < 1.6 ,+ aeson >= 1.0.0.0 && < 2.3 , aeson-pretty < 0.9 ,- ansi-terminal >= 0.6.3.1 && < 0.12,+ ansi-terminal >= 0.6.3.1 && < 1.2 , atomic-write >= 0.2.0.7 && < 0.3 ,- bytestring < 0.11,+ base16-bytestring >= 1.0.0.0 ,+ bytestring < 0.13, case-insensitive < 1.3 , cborg >= 0.2.0.0 && < 0.3 , cborg-json >= 0.2.2.0 && < 0.3 ,- containers >= 0.5.8.0 && < 0.7 ,+ containers >= 0.5.8.0 && < 0.9 , contravariant < 1.6 , data-fix < 0.4 ,- deepseq < 1.5 ,- Diff >= 0.2 && < 0.5 ,+ deepseq < 1.6 ,+ Diff >= 0.2 && < 1.1 , directory >= 1.3.0.0 && < 1.4 , dotgen >= 0.4.2 && < 0.5 , either >= 5 && < 5.1, exceptions >= 0.8.3 && < 0.11,- filepath >= 1.4 && < 1.5 ,+ filepath >= 1.4 && < 1.6 , half >= 0.2.2.3 && < 0.4 , haskeline >= 0.7.2.1 && < 0.9 ,- hashable >= 1.2 && < 1.4 ,- lens-family-core >= 1.0.0 && < 2.2 ,- megaparsec >= 7 && < 9.1 ,- memory >= 0.14 && < 0.16,- mmorph < 1.2 ,- mtl >= 2.2.1 && < 2.3 ,+ hashable >= 1.2 && < 1.6 ,+ indexed-traversable < 0.2 ,+ microlens >= 0.4.14.0 && < 0.5 ,+ microlens-mtl >= 0.1 && < 0.3 ,+ -- megaparsec follows SemVer: https://github.com/mrkkrp/megaparsec/issues/469#issuecomment-927918469+ megaparsec >= 8 && < 10 ,+ mmorph < 1.3 ,+ mtl >= 2.2.1 && < 2.4 , network-uri >= 2.6 && < 2.7 ,- optparse-applicative >= 0.14.0.0 && < 0.17,+ optparse-applicative >= 0.14.0.0 && < 0.20, parsers >= 0.12.4 && < 0.13, parser-combinators ,- prettyprinter >= 1.5.1 && < 1.8 ,- prettyprinter-ansi-terminal >= 1.1.1 && < 1.2 ,- pretty-simple < 4.1 ,- profunctors >= 3.1.2 && < 5.7 ,+ prettyprinter >= 1.7.0 && < 1.8 ,+ prettyprinter-ansi-terminal >= 1.1.2 && < 1.2 ,+ pretty-simple < 4.2 , repline >= 0.4.0.0 && < 0.5 , serialise >= 0.2.0.0 && < 0.3 , scientific >= 0.3.0.0 && < 0.4 ,- template-haskell >= 2.13.0.0 && < 2.17,- text >= 0.11.1.0 && < 1.3 ,- text-manipulate >= 0.2.0.1 && < 0.3 ,+ template-haskell >= 2.13.0.0 && < 2.24,+ text >= 0.11.1.0 && < 2.2 ,+ text-manipulate >= 0.2.0.1 && < 0.4 ,+ text-short >= 0.1 && < 0.2 , th-lift-instances >= 0.1.13 && < 0.2 ,- transformers >= 0.2.0.0 && < 0.6 ,- transformers-compat >= 0.6.2 && < 0.7 ,+ time >= 1.9 && < 1.15,+ transformers >= 0.5.2.0 && < 0.7 ,+ unix-compat >= 0.4.2 && < 0.8 , unordered-containers >= 0.1.3.0 && < 0.3 ,- uri-encode < 1.6 ,- vector >= 0.11.0.0 && < 0.13+ vector >= 0.11.0.0 && < 0.14++ if !os(windows)+ Build-Depends:+ unix >= 2.7 && < 2.9 ,+ if flag(with-http) CPP-Options: -DWITH_HTTP if flag(use-http-client-tls) CPP-Options: -DUSE_HTTP_CLIENT_TLS+ if flag(network-tests)+ CPP-Options:+ -DNETWORK_TESTS+ if flag(cross)+ CPP-Options: -DCROSS++ GHC-Options: -Wall -Wcompat -Wincomplete-uni-patterns -optP-Wno-unicode-homoglyph++Library+ Import: common+ Hs-Source-Dirs: src if impl(ghcjs) Hs-Source-Dirs: ghcjs-src Build-Depends:@@ -530,7 +285,7 @@ else Hs-Source-Dirs: ghc-src Build-Depends:- cryptonite >= 0.23 && < 1.0+ cryptohash-sha256 if flag(with-http) Build-Depends: http-types >= 0.7.0 && < 0.13,@@ -580,8 +335,11 @@ Dhall.Import Dhall.Lint Dhall.Main+ Dhall.Marshal.Decode+ Dhall.Marshal.Encode Dhall.Map Dhall.Optics+ Dhall.Package Dhall.Parser Dhall.Parser.Expression Dhall.Parser.Token@@ -603,12 +361,39 @@ Exposed-Modules: Dhall.Deriving Other-Modules:+ Dhall.DirectoryTree.Types Dhall.Eval Dhall.Import.Types+ Dhall.Import.Headers+ Dhall.Marshal.Internal Dhall.Normalize Dhall.Parser.Combinators Dhall.Pretty.Internal Dhall.Syntax+ Dhall.Syntax.Binding+ Dhall.Syntax.Chunks+ Dhall.Syntax.Const+ Dhall.Syntax.Expr+ Dhall.Syntax.FunctionBinding+ Dhall.Syntax.Import+ Dhall.Syntax.Instances.Applicative+ Dhall.Syntax.Instances.Bifunctor+ Dhall.Syntax.Instances.Data+ Dhall.Syntax.Instances.Eq+ Dhall.Syntax.Instances.Foldable+ Dhall.Syntax.Instances.Functor+ Dhall.Syntax.Instances.Lift+ Dhall.Syntax.Instances.Monad+ Dhall.Syntax.Instances.NFData+ Dhall.Syntax.Instances.Ord+ Dhall.Syntax.Instances.Pretty+ Dhall.Syntax.Instances.Show+ Dhall.Syntax.Instances.Traversable+ Dhall.Syntax.MultiLet+ Dhall.Syntax.Operations+ Dhall.Syntax.RecordField+ Dhall.Syntax.Types+ Dhall.Syntax.Var Dhall.URL Paths_dhall Autogen-Modules:@@ -618,118 +403,95 @@ Dhall.Import.HTTP Dhall.Import.Manager - GHC-Options: -Wall -fwarn-incomplete-uni-patterns Default-Language: Haskell2010 Executable dhall+ Import: common Hs-Source-Dirs: dhall Main-Is: Main.hs- Build-Depends: base, dhall- GHC-Options: -Wall -rtsopts+ Build-Depends: dhall+ GHC-Options: -rtsopts Default-Language: Haskell2010 Test-Suite tasty+ Import: common Type: exitcode-stdio-1.0 Hs-Source-Dirs: tests Main-Is: Dhall/Test/Main.hs- GHC-Options: -Wall Other-Modules: Dhall.Test.Dhall Dhall.Test.Diff+ Dhall.Test.DirectoryTree Dhall.Test.Tags Dhall.Test.Format Dhall.Test.Freeze Dhall.Test.Import Dhall.Test.Lint Dhall.Test.Normalization+ Dhall.Test.Package Dhall.Test.Parser Dhall.Test.QuickCheck Dhall.Test.Regression Dhall.Test.Schemas Dhall.Test.SemanticHash Dhall.Test.Substitution- Dhall.Test.TH Dhall.Test.Tutorial Dhall.Test.TypeInference Dhall.Test.Util+ if !flag(cross)+ Other-Modules:+ Dhall.Test.TH Build-Depends:- base >= 4 && < 5 ,- bytestring < 0.11,- cborg >= 0.2.0.0 && < 0.3 ,- containers ,- data-fix ,- deepseq >= 1.2.0.1 && < 1.5 , dhall ,- directory ,- either ,- filepath , foldl < 1.5 ,- generic-random >= 1.3.0.0 && < 1.4 ,+ generic-random >= 1.3.0.0 && < 1.6 , http-client , http-client-tls ,- lens-family-core ,- megaparsec ,- prettyprinter ,- QuickCheck >= 2.10 && < 2.15,+ QuickCheck >= 2.14 && < 2.17, quickcheck-instances >= 0.3.12 && < 0.4 ,- scientific ,- serialise , special-values < 0.2 , spoon < 0.4 ,- tasty >= 0.11.2 && < 1.4 ,+ tasty >= 0.11.2 && < 1.6 , tasty-expected-failure < 0.13, tasty-hunit >= 0.10 && < 0.11,- tasty-quickcheck >= 0.9.2 && < 0.11,- tasty-silver < 3.2 ,- template-haskell ,- text >= 0.11.1.0 && < 1.3 ,- transformers ,- turtle < 1.6 ,- unordered-containers ,- vector >= 0.11.0.0 && < 0.13- if flag(with-http)- CPP-Options:- -DWITH_HTTP+ tasty-quickcheck >= 0.9.2 && < 0.12,+ tasty-silver < 3.4 ,+ temporary >= 1.2.1 && < 1.4 ,+ turtle >= 1.6 && < 1.7 , Default-Language: Haskell2010 Test-Suite doctest+ Import: common Type: exitcode-stdio-1.0 Hs-Source-Dirs: doctest Main-Is: Main.hs- GHC-Options: -Wall Build-Depends:- base ,- directory ,- filepath < 1.5 , mockery < 0.4 ,- doctest >= 0.7.0 && < 0.18+ doctest >= 0.7.0+ if os(windows)+ -- https://github.com/dhall-lang/dhall-haskell/issues/2237+ Buildable: False Default-Language: Haskell2010 Benchmark dhall-parser+ Import: common Type: exitcode-stdio-1.0 Hs-Source-Dirs: benchmark/parser Main-Is: Main.hs Build-Depends:- base >= 4 && < 5 ,- bytestring ,- containers >= 0.5.0.0 && < 0.7, dhall ,- directory ,- gauge >= 0.2.3 && < 0.3,- text >= 0.11.1.0 && < 1.3+ tasty-bench >= 0.4 && < 0.5, Default-Language: Haskell2010 Other-Extensions: TypeApplications- ghc-options: -rtsopts -Wall+ Ghc-Options: -rtsopts Benchmark deep-nested-large-record+ Import: common Type: exitcode-stdio-1.0 Hs-Source-Dirs: benchmark/deep-nested-large-record Main-Is: Main.hs Build-Depends:- base >= 4 && < 5 ,- containers >= 0.5.0.0 && < 0.7, dhall ,- gauge >= 0.2.3 && < 0.3+ tasty-bench >= 0.4 && < 0.5, Default-Language: Haskell2010- ghc-options: -Wall
@@ -1,22 +1,26 @@ {-# LANGUAGE CPP #-} -module Main where+module Main (main) where import System.FilePath ((</>)) import qualified GHC.IO.Encoding import qualified System.Directory+import qualified System.Environment import qualified System.IO import qualified Test.DocTest import qualified Test.Mockery.Directory main :: IO () main = do- GHC.IO.Encoding.setLocaleEncoding System.IO.utf8- pwd <- System.Directory.getCurrentDirectory+ args <- System.Environment.getArgs+ pwd <- System.Directory.getCurrentDirectory prefix <- System.Directory.makeAbsolute pwd+ let src = prefix </> "src" + System.Environment.setEnv "XDG_CACHE_HOME" (pwd </> ".cache")+ Test.Mockery.Directory.inTempDirectory $ do writeFile "makeBools.dhall" "λ(n : Bool) → [ n && True, n && False, n || True, n || False ]" writeFile "bool1" "True"@@ -31,11 +35,12 @@ , "in { name = \"Simon\", favoriteFont = Font.`Comic Sans` } : Person" ] - Test.DocTest.doctest+ Test.DocTest.doctest $ [ "-DWITH_HTTP" , "-DUSE_HTTP_CLIENT_TLS" , "--fast"- , prefix </> "ghc-src"+ ] <> args <>+ [ prefix </> "ghc-src" -- Unfortunately we cannot target the entire @src@ directory. -- The reason is that src/Dhall/Version.hs depends on@@ -44,11 +49,11 @@ -- Instead, we target a selection of modules whose combined module -- dependency tree covers all modules that contain doctests. - -- , prefix </> "src"- , "-i" <> (prefix </> "src")+ -- , src+ , "-i" <> src #if __GLASGOW_HASKELL__ >= 806- , prefix </> "src/Dhall/Deriving.hs"+ , src </> "Dhall/Deriving.hs" #endif- , prefix </> "src/Dhall/Tags.hs"- , prefix </> "src/Dhall/Tutorial.hs"+ , src </> "Dhall/Tags.hs"+ , src </> "Dhall/Tutorial.hs" ]
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} @@ -13,18 +14,18 @@ ) where import Control.DeepSeq (NFData)-import Crypto.Hash (SHA256)-import Data.ByteArray (ByteArrayAccess, convert)-import Data.ByteArray.Encoding (Base (Base16), convertToBase) import Data.ByteString (ByteString)+import Data.Data (Data) import GHC.Generics (Generic) -import qualified Crypto.Hash-import qualified Data.ByteString.Char8 as ByteString.Char8+import qualified Crypto.Hash.SHA256+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Base16 as Base16+import qualified Data.ByteString.Char8 as ByteString.Char8 -- | A SHA256 digest newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }- deriving (Eq, Generic, Ord, NFData, ByteArrayAccess)+ deriving (Data, Eq, Generic, Ord, NFData) instance Show SHA256Digest where show = toString@@ -33,16 +34,14 @@ `Nothing` if the conversion fails -} sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest-sha256DigestFromByteString bytes = SHA256Digest . convert <$> mh- where- mh = Crypto.Hash.digestFromByteString bytes :: Maybe (Crypto.Hash.Digest SHA256)+sha256DigestFromByteString bytes+ | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+ | otherwise = Nothing -- | Hash a `ByteString` and return the hash as a `SHA256Digest` sha256Hash :: ByteString -> SHA256Digest-sha256Hash bytes = SHA256Digest $ convert h- where- h = Crypto.Hash.hash bytes :: Crypto.Hash.Digest SHA256+sha256Hash = SHA256Digest . Crypto.Hash.SHA256.hash -- | 'String' representation of a 'SHA256Digest' toString :: SHA256Digest -> String-toString (SHA256Digest bytes) = ByteString.Char8.unpack $ convertToBase Base16 bytes+toString (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes
@@ -1,8 +1,11 @@+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Dhall.Import.HTTP ( fetchFromHttpUrl+ , fetchFromHttpUrlBytes+ , originHeadersFileExpr ) where import Control.Exception (Exception)@@ -11,29 +14,35 @@ import Data.ByteString (ByteString) import Data.CaseInsensitive (CI) import Data.Dynamic (toDyn)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Text.Encoding (decodeUtf8) import Dhall.Core- ( Import (..)+ ( Expr (..)+ , Directory (..)+ , File (..)+ , FilePrefix (..)+ , Import (..) , ImportHashed (..)+ , ImportMode (..) , ImportType (..) , Scheme (..) , URL (..) ) import Dhall.Import.Types+import Dhall.Parser (Src) import Dhall.URL (renderURL)+import System.Directory (getXdgDirectory, XdgDirectory(XdgConfig))+import System.FilePath (splitDirectories) -import Network.HTTP.Client- ( HttpException (..)- , HttpExceptionContent (..)- )+import Network.HTTP.Client (HttpException (..), HttpExceptionContent (..)) import qualified Control.Exception import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.ByteString.Lazy as ByteString.Lazy+import qualified Data.HashMap.Strict as HashMap import qualified Data.Text as Text import qualified Data.Text.Encoding-import qualified Data.Text.Lazy-import qualified Data.Text.Lazy.Encoding import qualified Dhall.Util import qualified Network.HTTP.Client as HTTP import qualified Network.HTTP.Types@@ -65,6 +74,11 @@ <> "\ESC[1;31mError\ESC[0m: The remote host took too long to respond\n" <> "\n" <> "URL: " <> url <> "\n"+ ConnectionTimeout ->+ "\n"+ <> "\ESC[1;31mError\ESC[0m: Connection establishment took too long\n"+ <> "\n"+ <> "URL: " <> url <> "\n" StatusCodeException response body -> prefix <> suffix where prefix@@ -141,7 +155,10 @@ prefixedText = Text.unlines prefixedLines - e' -> "\n" <> show e' <> "\n"+ e' -> "\n"+ <> "\ESC[1;31mError\ESC[0m: " <> show e'+ <> "\n"+ <> "URL: " <> url <> "\n" newManager :: StateT Status IO Manager newManager = do@@ -233,20 +250,36 @@ Control.Exception.throwIO (NotCORSCompliant {..}) corsCompliant _ _ _ = return () -type HTTPHeader = Network.HTTP.Types.Header+addHeaders :: OriginHeaders -> Maybe [HTTPHeader] -> HTTP.Request -> HTTP.Request+addHeaders originHeaders urlHeaders request =+ request { HTTP.requestHeaders = (filterHeaders urlHeaders) <> perOriginHeaders }+ where+ origin = decodeUtf8 (HTTP.host request) <> ":" <> Text.pack (show (HTTP.port request))+ + perOriginHeaders = HashMap.lookupDefault [] origin originHeaders -fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text-fetchFromHttpUrl childURL mheaders = do+ filterHeaders = foldMap (filter (not . overridden))++ overridden :: HTTPHeader -> Bool+ overridden (key, _value) = any (matchesKey key) perOriginHeaders++ matchesKey :: CI ByteString -> HTTPHeader -> Bool+ matchesKey key (candidate, _value) = key == candidate++fetchFromHttpUrlBytes+ :: URL -> Maybe [HTTPHeader] -> StateT Status IO ByteString+fetchFromHttpUrlBytes childURL mheaders = do+ Status { _loadOriginHeaders } <- State.get++ originHeaders <- _loadOriginHeaders+ manager <- newManager let childURLString = Text.unpack (renderURL childURL) - request <- liftIO (HTTP.parseUrlThrow childURLString)+ baseRequest <- liftIO (HTTP.parseUrlThrow childURLString) - let requestWithHeaders =- case mheaders of- Nothing -> request- Just headers -> request { HTTP.requestHeaders = headers }+ let requestWithHeaders = addHeaders originHeaders mheaders baseRequest let io = HTTP.httpLbs requestWithHeaders manager @@ -258,14 +291,30 @@ Status {..} <- State.get - let Chained parentImport = NonEmpty.head _stack+ case _stack of+ -- We ignore the first import in the stack since that is the same import+ -- as the `childUrl`+ _ :| Chained parentImport : _ -> do+ let parentImportType = importType (importHashed parentImport) - let parentImportType = importType (importHashed parentImport)+ corsCompliant parentImportType childURL (HTTP.responseHeaders response)+ _ -> do+ return () - corsCompliant parentImportType childURL (HTTP.responseHeaders response)+ return (ByteString.Lazy.toStrict (HTTP.responseBody response)) - let bytes = HTTP.responseBody response+fetchFromHttpUrl :: URL -> Maybe [HTTPHeader] -> StateT Status IO Text.Text+fetchFromHttpUrl childURL mheaders = do+ bytes <- fetchFromHttpUrlBytes childURL mheaders - case Data.Text.Lazy.Encoding.decodeUtf8' bytes of+ case Data.Text.Encoding.decodeUtf8' bytes of Left err -> liftIO (Control.Exception.throwIO err)- Right text -> return (Data.Text.Lazy.toStrict text)+ Right text -> return text++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = do+ directoryStr <- getXdgDirectory XdgConfig "dhall"+ let components = map Text.pack (splitDirectories directoryStr)+ let directory = Directory (reverse components)+ let file = (File directory "headers.dhall")+ return (Embed (Import (ImportHashed Nothing (Local Absolute file)) Code))
@@ -16,7 +16,7 @@ , defaultNewManager ) where -import Network.HTTP.Client (Manager, newManager)+import Network.HTTP.Client (Manager, newManager) import qualified Network.HTTP.Client as HTTP #ifdef USE_HTTP_CLIENT_TLS
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE JavaScriptFFI #-}+{-# LANGUAGE JavaScriptFFI #-} {-| This module provides implementations of cryptographic utilities that only work for GHCJS@@ -12,32 +13,32 @@ , sha256Hash ) where -import Control.DeepSeq (NFData)-import Data.ByteArray (ByteArrayAccess)-import Data.ByteArray.Encoding (Base(Base16), convertToBase)-import Data.ByteString (ByteString)-import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import Data.ByteString (ByteString)+import Data.Data (Data)+import GHC.Generics (Generic) import JavaScript.TypedArray.ArrayBuffer (ArrayBuffer)-import System.IO.Unsafe (unsafePerformIO)+import System.IO.Unsafe (unsafePerformIO) import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Base16 as Base16 import qualified Data.ByteString.Char8 as ByteString.Char8 import qualified GHCJS.Buffer as Buffer -- | A SHA256 digest newtype SHA256Digest = SHA256Digest { unSHA256Digest :: ByteString }- deriving (Eq, Generic, Ord, NFData, ByteArrayAccess)+ deriving (Data, Eq, Generic, Ord, NFData) instance Show SHA256Digest where- show (SHA256Digest bytes) = ByteString.Char8.unpack $ convertToBase Base16 bytes+ show (SHA256Digest bytes) = ByteString.Char8.unpack $ Base16.encode bytes {-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning `Nothing` if the conversion fails -} sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest sha256DigestFromByteString bytes- | ByteString.length bytes == 32 = Just $ SHA256Digest bytes- | otherwise = Nothing+ | ByteString.length bytes == 32 = Just (SHA256Digest bytes)+ | otherwise = Nothing -- Use NodeJS' crypto module if there's a 'process' module, e.g. we're running -- inside GHCJS' THRunner. If we're running in the browser, use the WebCrypto
@@ -2,17 +2,21 @@ module Dhall.Import.HTTP ( fetchFromHttpUrl+ , fetchFromHttpUrlBytes+ , originHeadersFileExpr ) where import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.State.Strict (StateT) import Data.ByteString (ByteString) import Data.CaseInsensitive (CI)-import Dhall.Core (URL (..))-import Dhall.Import.Types (Status)+import Dhall.Core (URL (..), Expr (..))+import Dhall.Import.Types (Import, Status)+import Dhall.Parser (Src) import Dhall.URL (renderURL) -import qualified Data.Text as Text+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text.Encoding import qualified JavaScript.XHR fetchFromHttpUrl@@ -35,3 +39,14 @@ return body fetchFromHttpUrl _ _ = fail "Dhall does not yet support custom headers when built using GHCJS"++fetchFromHTTPUrlBytes+ :: URL+ -> Maybe [(CI ByteString, ByteString)]+ -> StateT Status IO ByteString+fetchFromHTTPUrlBytes childUrl mheader = do+ text <- fetchFromHTTPUrl childUrl mheader+ return (Text.Encoding.encodeUtf8 text)++originHeadersFileExpr :: IO (Expr Src Import)+originHeadersFileExpr = return Missing
@@ -97,4 +97,4 @@ .SH BUGS .PP Please report any bugs you may come across to-https://github.com/dhall-language/dhall-haskell/issues.+https://github.com/dhall-lang/dhall-haskell/issues.
@@ -1,2893 +1,579 @@-{-# LANGUAGE ApplicativeDo #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}--{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining- how to use the language, the compiler, and this library--}--module Dhall- (- -- * Input- input- , inputWithSettings- , inputFile- , inputFileWithSettings- , inputExpr- , inputExprWithSettings- , rootDirectory- , sourceName- , startingContext- , substitutions- , normalizer- , newManager- , defaultInputSettings- , InputSettings- , defaultEvaluateSettings- , EvaluateSettings- , HasEvaluateSettings(..)- , detailed-- -- * Decoders- , Decoder (..)- , RecordDecoder(..)- , UnionDecoder(..)- , Encoder(..)- , FromDhall(..)- , Interpret- , InvalidDecoder(..)- , ExtractErrors- , ExtractError(..)- , Extractor- , MonadicExtractor- , typeError- , extractError- , toMonadic- , fromMonadic- , ExpectedTypeErrors- , ExpectedTypeError(..)- , Expector- , auto- , genericAuto- , genericAutoWith- , InterpretOptions(..)- , InputNormalizer(..)- , defaultInputNormalizer- , SingletonConstructors(..)- , defaultInterpretOptions- , bool- , natural- , integer- , word- , word8- , word16- , word32- , word64- , int- , int8- , int16- , int32- , int64- , scientific- , double- , lazyText- , strictText- , maybe- , sequence- , list- , vector- , function- , functionWith- , setFromDistinctList- , setIgnoringDuplicates- , hashSetFromDistinctList- , hashSetIgnoringDuplicates- , Dhall.map- , hashMap- , pairFromMapEntry- , unit- , void- , string- , pair- , record- , field- , union- , constructor- , GenericFromDhall(..)- , GenericFromDhallUnion(..)- , ToDhall(..)- , Inject- , inject- , genericToDhall- , genericToDhallWith- , RecordEncoder(..)- , encodeFieldWith- , encodeField- , recordEncoder- , UnionEncoder(..)- , encodeConstructorWith- , encodeConstructor- , unionEncoder- , (>|<)- , GenericToDhall(..)-- -- * Miscellaneous- , DhallErrors(..)- , showDhallErrors- , rawInput- , (>$<)- , (>*<)- , Result-- -- * Re-exports- , Natural- , Seq- , Text- , Vector- , Generic- ) where--import Control.Applicative (Alternative, empty, liftA2)-import Control.Exception (Exception)-import Control.Monad (guard)-import Control.Monad.Trans.State.Strict-import Data.Coerce (coerce)-import Data.Either.Validation- ( Validation (..)- , eitherToValidation- , validationToEither- )-import Data.Fix (Fix (..))-import Data.Functor.Contravariant (Contravariant (..), Op (..), (>$<))-import Data.Functor.Contravariant.Divisible (Divisible (..), divided)-import Data.Hashable (Hashable)-import Data.HashMap.Strict (HashMap)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Map (Map)-import Data.Scientific (Scientific)-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)-import Data.Typeable (Proxy (..), Typeable)-import Data.Vector (Vector)-import Data.Void (Void)-import Data.Word (Word8, Word16, Word32, Word64)-import Data.Int (Int8, Int16, Int32, Int64)-import Dhall.Import (Imported (..))-import Dhall.Parser (Src (..))-import Dhall.Syntax- ( Chunks (..)- , DhallDouble (..)- , Expr (..)- , FunctionBinding (..)- , RecordField (..)- , Var (..)- )-import Dhall.TypeCheck (DetailedTypeError (..), TypeError)-import GHC.Generics-import Lens.Family (LensLike', view)-import Numeric.Natural (Natural)-import Prelude hiding (maybe, sequence)-import System.FilePath (takeDirectory)--import qualified Control.Applicative-import qualified Control.Exception-import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.Foldable-import qualified Data.Functor.Compose-import qualified Data.Functor.Product-import qualified Data.HashMap.Strict as HashMap-import qualified Data.HashSet-import qualified Data.List-import qualified Data.List.NonEmpty-import qualified Data.Map-import qualified Data.Maybe-import qualified Data.Scientific-import qualified Data.Sequence-import qualified Data.Set-import qualified Data.Text-import qualified Data.Text.IO-import qualified Data.Text.Lazy-import qualified Data.Vector-import qualified Data.Void-import qualified Dhall.Context-import qualified Dhall.Core as Core-import qualified Dhall.Import-import qualified Dhall.Map-import qualified Dhall.Parser-import qualified Dhall.Pretty.Internal-import qualified Dhall.Substitution-import qualified Dhall.TypeCheck-import qualified Dhall.Util-import qualified Lens.Family---- $setup--- >>> :set -XOverloadedStrings--- >>> :set -XRecordWildCards--- >>> import Data.Word (Word8, Word16, Word32, Word64)--- >>> import Dhall.Pretty.Internal (prettyExpr)--{-| A newtype suitable for collecting one or more errors--}-newtype DhallErrors e = DhallErrors- { getErrors :: NonEmpty e- } deriving (Eq, Functor, Semigroup)--instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)--{-| Render a given prefix and some errors to a string.--}-showDhallErrors :: Show e => String -> DhallErrors e -> String-showDhallErrors _ (DhallErrors (e :| [])) = show e-showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)- where- prefix =- "Multiple errors were encountered" ++ ctx ++ ": \n\- \ \n"--{-| Useful synonym for the `Validation` type used when marshalling Dhall- expressions--}-type Extractor s a = Validation (ExtractErrors s a)--{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall- code--}-type MonadicExtractor s a = Either (ExtractErrors s a)--{-| Generate a type error during extraction by specifying the expected type- and the actual type.- The expected type is not yet determined.--}-typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b-typeError expected actual = Failure $ case expected of- Failure e -> fmap ExpectedTypeError e- Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual---- | Turn a `Data.Text.Text` message into an extraction failure-extractError :: Text -> Extractor s a b-extractError = Failure . DhallErrors . pure . ExtractError--{-| Useful synonym for the `Validation` type used when marshalling Dhall- expressions--}-type Expector = Validation ExpectedTypeErrors--{-| One or more errors returned when determining the Dhall type of a- Haskell expression--}-type ExpectedTypeErrors = DhallErrors ExpectedTypeError--{-| Error type used when determining the Dhall type of a Haskell expression--}-data ExpectedTypeError = RecursiveTypeError- deriving (Eq, Show)--instance Exception ExpectedTypeError--instance Show ExpectedTypeErrors where- show = showDhallErrors " while determining the expected type"---- | Switches from an @Applicative@ extraction result, able to accumulate errors,--- to a @Monad@ extraction result, able to chain sequential operations-toMonadic :: Extractor s a b -> MonadicExtractor s a b-toMonadic = validationToEither---- | Switches from a @Monad@ extraction result, able to chain sequential errors,--- to an @Applicative@ extraction result, able to accumulate errors-fromMonadic :: MonadicExtractor s a b -> Extractor s a b-fromMonadic = eitherToValidation--{-| One or more errors returned from extracting a Dhall expression to a- Haskell expression--}-type ExtractErrors s a = DhallErrors (ExtractError s a)--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where- show = showDhallErrors " during extraction"--{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,- as expressions are type-checked against the expected type before being passed to @extract@), or- a term-level error, described with a freeform text value.--}-data ExtractError s a =- TypeMismatch (InvalidDecoder s a)- | ExpectedTypeError ExpectedTypeError- | ExtractError Text--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where- show (TypeMismatch e) = show e- show (ExpectedTypeError e) = show e- show (ExtractError es) =- _ERROR <> ": Failed extraction \n\- \ \n\- \The expression type-checked successfully but the transformation to the target \n\- \type failed with the following error: \n\- \ \n\- \" <> Data.Text.unpack es <> "\n\- \ \n"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)--{-| Every `Decoder` must obey the contract that if an expression's type matches- the `expected` type then the `extract` function must not fail with a type- error. However, decoding may still fail for other reasons (such as the- decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate- elements).-- This error type is used to indicate an internal error in the implementation- of a `Decoder` where the expected type matched the Dhall expression, but the- expression supplied to the extraction function did not match the expected- type. If this happens that means that the `Decoder` itself needs to be- fixed.--}-data InvalidDecoder s a = InvalidDecoder- { invalidDecoderExpected :: Expr s a- , invalidDecoderExpression :: Expr s a- }- deriving (Typeable)--instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where- show InvalidDecoder { .. } =- _ERROR <> ": Invalid Dhall.Decoder \n\- \ \n\- \Every Decoder must provide an extract function that succeeds if an expression \n\- \matches the expected type. You provided a Decoder that disobeys this contract \n\- \ \n\- \The Decoder provided has the expected dhall type: \n\- \ \n\- \" <> show txt0 <> "\n\- \ \n\- \and it couldn't extract a value from the well-typed expression: \n\- \ \n\- \" <> show txt1 <> "\n\- \ \n"- where- txt0 = Dhall.Util.insert invalidDecoderExpected- txt1 = Dhall.Util.insert invalidDecoderExpression---- | @since 1.16-data InputSettings = InputSettings- { _rootDirectory :: FilePath- , _sourceName :: FilePath- , _evaluateSettings :: EvaluateSettings- }---- | Default input settings: resolves imports relative to @.@ (the--- current working directory), report errors as coming from @(input)@,--- and default evaluation settings from 'defaultEvaluateSettings'.------ @since 1.16-defaultInputSettings :: InputSettings-defaultInputSettings = InputSettings- { _rootDirectory = "."- , _sourceName = "(input)"- , _evaluateSettings = defaultEvaluateSettings- }----- | Access the directory to resolve imports relative to.------ @since 1.16-rootDirectory- :: (Functor f)- => LensLike' f InputSettings FilePath-rootDirectory k s =- fmap (\x -> s { _rootDirectory = x }) (k (_rootDirectory s))---- | Access the name of the source to report locations from; this is--- only used in error messages, so it's okay if this is a best guess--- or something symbolic.------ @since 1.16-sourceName- :: (Functor f)- => LensLike' f InputSettings FilePath-sourceName k s =- fmap (\x -> s { _sourceName = x}) (k (_sourceName s))---- | @since 1.16-data EvaluateSettings = EvaluateSettings- { _substitutions :: Dhall.Substitution.Substitutions Src Void- , _startingContext :: Dhall.Context.Context (Expr Src Void)- , _normalizer :: Maybe (Core.ReifiedNormalizer Void)- , _newManager :: IO Dhall.Import.Manager- }---- | Default evaluation settings: no extra entries in the initial--- context, and no special normalizer behaviour.------ @since 1.16-defaultEvaluateSettings :: EvaluateSettings-defaultEvaluateSettings = EvaluateSettings- { _substitutions = Dhall.Substitution.empty- , _startingContext = Dhall.Context.empty- , _normalizer = Nothing- , _newManager = Dhall.Import.defaultNewManager- }---- | Access the starting context used for evaluation and type-checking.------ @since 1.16-startingContext- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Dhall.Context.Context (Expr Src Void))-startingContext = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Dhall.Context.Context (Expr Src Void))- l k s = fmap (\x -> s { _startingContext = x}) (k (_startingContext s))---- | Access the custom substitutions.------ @since 1.30-substitutions- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Dhall.Substitution.Substitutions Src Void)-substitutions = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Dhall.Substitution.Substitutions Src Void)- l k s = fmap (\x -> s { _substitutions = x }) (k (_substitutions s))---- | Access the custom normalizer.------ @since 1.16-normalizer- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (Maybe (Core.ReifiedNormalizer Void))-normalizer = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (Maybe (Core.ReifiedNormalizer Void))- l k s = fmap (\x -> s { _normalizer = x }) (k (_normalizer s))---- | Access the HTTP manager initializer.------ @since 1.36-newManager- :: (Functor f, HasEvaluateSettings s)- => LensLike' f s (IO Dhall.Import.Manager)-newManager = evaluateSettings . l- where- l :: (Functor f)- => LensLike' f EvaluateSettings (IO Dhall.Import.Manager)- l k s = fmap (\x -> s { _newManager = x }) (k (_newManager s))---- | @since 1.16-class HasEvaluateSettings s where- evaluateSettings- :: (Functor f)- => LensLike' f s EvaluateSettings--instance HasEvaluateSettings InputSettings where- evaluateSettings k s =- fmap (\x -> s { _evaluateSettings = x }) (k (_evaluateSettings s))--instance HasEvaluateSettings EvaluateSettings where- evaluateSettings = id--{-| Type-check and evaluate a Dhall program, decoding the result into Haskell-- The first argument determines the type of value that you decode:-->>> input integer "+2"-2->>> input (vector double) "[1.0, 2.0]"-[1.0,2.0]-- Use `auto` to automatically select which type to decode based on the- inferred return type:-->>> input auto "True" :: IO Bool-True-- This uses the settings from 'defaultInputSettings'.--}-input- :: Decoder a- -- ^ The decoder for the Dhall value- -> Text- -- ^ The Dhall program- -> IO a- -- ^ The decoded value in Haskell-input =- inputWithSettings defaultInputSettings--{-| Extend 'input' with a root directory to resolve imports relative- to, a file to mention in errors as the source, a custom typing- context, and a custom normalization process.--@since 1.16--}-inputWithSettings- :: InputSettings- -> Decoder a- -- ^ The decoder for the Dhall value- -> Text- -- ^ The Dhall program- -> IO a- -- ^ The decoded value in Haskell-inputWithSettings settings (Decoder {..}) txt = do- expected' <- case expected of- Success x -> return x- Failure e -> Control.Exception.throwIO e-- let suffix = Dhall.Pretty.Internal.prettyToStrictText expected'- let annotate substituted = case substituted of- Note (Src begin end bytes) _ ->- Note (Src begin end bytes') (Annot substituted expected')- where- bytes' = bytes <> " : " <> suffix- _ ->- Annot substituted expected'-- normExpr <- inputHelper annotate settings txt-- case extract normExpr of- Success x -> return x- Failure e -> Control.Exception.throwIO e--{-| Type-check and evaluate a Dhall program that is read from the- file-system.-- This uses the settings from 'defaultEvaluateSettings'.-- @since 1.16--}-inputFile- :: Decoder a- -- ^ The decoder for the Dhall value- -> FilePath- -- ^ The path to the Dhall program.- -> IO a- -- ^ The decoded value in Haskell.-inputFile =- inputFileWithSettings defaultEvaluateSettings--{-| Extend 'inputFile' with a custom typing context and a custom- normalization process.--@since 1.16--}-inputFileWithSettings- :: EvaluateSettings- -> Decoder a- -- ^ The decoder for the Dhall value- -> FilePath- -- ^ The path to the Dhall program.- -> IO a- -- ^ The decoded value in Haskell.-inputFileWithSettings settings ty path = do- text <- Data.Text.IO.readFile path- let inputSettings = InputSettings- { _rootDirectory = takeDirectory path- , _sourceName = path- , _evaluateSettings = settings- }- inputWithSettings inputSettings ty text--{-| Similar to `input`, but without interpreting the Dhall `Expr` into a Haskell- type.-- Uses the settings from 'defaultInputSettings'.--}-inputExpr- :: Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputExpr =- inputExprWithSettings defaultInputSettings--{-| Extend 'inputExpr' with a root directory to resolve imports relative- to, a file to mention in errors as the source, a custom typing- context, and a custom normalization process.--@since 1.16--}-inputExprWithSettings- :: InputSettings- -> Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputExprWithSettings = inputHelper id--{-| Helper function for the input* function family--@since 1.30--}-inputHelper- :: (Expr Src Void -> Expr Src Void)- -> InputSettings- -> Text- -- ^ The Dhall program- -> IO (Expr Src Void)- -- ^ The fully normalized AST-inputHelper annotate settings txt = do- expr <- Core.throws (Dhall.Parser.exprFromText (view sourceName settings) txt)-- let InputSettings {..} = settings-- let EvaluateSettings {..} = _evaluateSettings-- let transform =- Lens.Family.set Dhall.Import.substitutions _substitutions- . Lens.Family.set Dhall.Import.normalizer _normalizer- . Lens.Family.set Dhall.Import.startingContext _startingContext-- let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)-- expr' <- State.evalStateT (Dhall.Import.loadWith expr) status-- let substituted = Dhall.Substitution.substitute expr' $ view substitutions settings- let annot = annotate substituted- _ <- Core.throws (Dhall.TypeCheck.typeWith (view startingContext settings) annot)- pure (Core.normalizeWith (view normalizer settings) substituted)---- | Use this function to extract Haskell values directly from Dhall AST.--- The intended use case is to allow easy extraction of Dhall values for--- making the function `Core.normalizeWith` easier to use.------ For other use cases, use `input` from "Dhall" module. It will give you--- a much better user experience.-rawInput- :: Alternative f- => Decoder a- -- ^ The decoder for the Dhall value- -> Expr s Void- -- ^ a closed form Dhall program, which evaluates to the expected type- -> f a- -- ^ The decoded value in Haskell-rawInput (Decoder {..}) expr =- case extract (Core.normalize expr) of- Success x -> pure x- Failure _e -> empty--{-| Use this to provide more detailed error messages-->> input auto "True" :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> True : Integer->-> (input):1:1-->> detailed (input auto "True") :: IO Integer-> *** Exception: Error: Expression doesn't match annotation->-> Explanation: You can annotate an expression with its type or kind using the-> ❰:❱ symbol, like this:->->-> ┌───────┐-> │ x : t │ ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱-> └───────┘->-> The type checker verifies that the expression's type or kind matches the-> provided annotation->-> For example, all of the following are valid annotations that the type checker-> accepts:->->-> ┌─────────────┐-> │ 1 : Natural │ ❰1❱ is an expression that has type ❰Natural❱, so the type-> └─────────────┘ checker accepts the annotation->->-> ┌───────────────────────┐-> │ Natural/even 2 : Bool │ ❰Natural/even 2❱ has type ❰Bool❱, so the type-> └───────────────────────┘ checker accepts the annotation->->-> ┌────────────────────┐-> │ List : Type → Type │ ❰List❱ is an expression that has kind ❰Type → Type❱,-> └────────────────────┘ so the type checker accepts the annotation->->-> ┌──────────────────┐-> │ List Text : Type │ ❰List Text❱ is an expression that has kind ❰Type❱, so-> └──────────────────┘ the type checker accepts the annotation->->-> However, the following annotations are not valid and the type checker will-> reject them:->->-> ┌──────────┐-> │ 1 : Text │ The type checker rejects this because ❰1❱ does not have type-> └──────────┘ ❰Text❱->->-> ┌─────────────┐-> │ List : Type │ ❰List❱ does not have kind ❰Type❱-> └─────────────┘->->-> You or the interpreter annotated this expression:->-> ↳ True->-> ... with this type or kind:->-> ↳ Integer->-> ... but the inferred type or kind of the expression is actually:->-> ↳ Bool->-> Some common reasons why you might get this error:->-> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation-> matching the expected type->-> For example, if you run the following Haskell code:->->-> ┌───────────────────────────────┐-> │ >>> input auto "1" :: IO Text │-> └───────────────────────────────┘->->-> ... then the interpreter will actually type check the following annotated-> expression:->->-> ┌──────────┐-> │ 1 : Text │-> └──────────┘->->-> ... and then type-checking will fail->-> ────────────────────────────────────────────────────────────────────────────────->-> True : Integer->-> (input):1:1---}-detailed :: IO a -> IO a-detailed =- Control.Exception.handle handler1 . Control.Exception.handle handler0- where- handler0 :: Imported (TypeError Src Void) -> IO a- handler0 (Imported ps e) =- Control.Exception.throwIO (Imported ps (DetailedTypeError e))-- handler1 :: TypeError Src Void -> IO a- handler1 e = Control.Exception.throwIO (DetailedTypeError e)--{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall- into Haskell-- You can produce `Decoder`s either explicitly:--> example :: Decoder (Vector Text)-> example = vector text-- ... or implicitly using `auto`:--> example :: Decoder (Vector Text)-> example = auto-- You can consume `Decoder`s using the `input` function:--> input :: Decoder a -> Text -> IO a--}-data Decoder a = Decoder- { extract :: Expr Src Void -> Extractor Src Void a- -- ^ Extracts Haskell value from the Dhall expression- , expected :: Expector (Expr Src Void)- -- ^ Dhall type of the Haskell value- }- deriving (Functor)--{-| Decode a `Prelude.Bool`-->>> input bool "True"-True--}-bool :: Decoder Bool-bool = Decoder {..}- where- extract (BoolLit b) = pure b- extract expr = typeError expected expr-- expected = pure Bool--{-| Decode a `Prelude.Natural`-->>> input natural "42"-42--}-natural :: Decoder Natural-natural = Decoder {..}- where- extract (NaturalLit n) = pure n- extract expr = typeError expected expr-- expected = pure Natural--{-| Decode an `Prelude.Integer`-->>> input integer "+42"-42--}-integer :: Decoder Integer-integer = Decoder {..}- where- extract (IntegerLit n) = pure n- extract expr = typeError expected expr-- expected = pure Integer--wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a-wordHelper name = Decoder {..}- where- extract (NaturalLit n)- | toInteger n <= toInteger (maxBound @a) =- pure (fromIntegral n)- | otherwise =- extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))- extract expr =- typeError expected expr-- expected = pure Natural--{-| Decode a `Word` from a Dhall @Natural@-->>> input word "42"-42--}-word :: Decoder Word-word = wordHelper "Word"--{-| Decode a `Word8` from a Dhall @Natural@-->>> input word8 "42"-42--}-word8 :: Decoder Word8-word8 = wordHelper "Word8"--{-| Decode a `Word16` from a Dhall @Natural@-->>> input word16 "42"-42--}-word16 :: Decoder Word16-word16 = wordHelper "Word16"--{-| Decode a `Word32` from a Dhall @Natural@-->>> input word32 "42"-42--}-word32 :: Decoder Word32-word32 = wordHelper "Word32"--{-| Decode a `Word64` from a Dhall @Natural@-->>> input word64 "42"-42--}-word64 :: Decoder Word64-word64 = wordHelper "Word64"--intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a-intHelper name = Decoder {..}- where- extract (IntegerLit n)- | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =- pure (fromIntegral n)- | otherwise =- extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))- extract expr =- typeError expected expr-- expected = pure Integer--{-| Decode an `Int` from a Dhall @Integer@-->>> input int "-42"--42--}-int :: Decoder Int-int = intHelper "Int"--{-| Decode an `Int8` from a Dhall @Integer@-->>> input int8 "-42"--42--}-int8 :: Decoder Int8-int8 = intHelper "Int8"--{-| Decode an `Int16` from a Dhall @Integer@-->>> input int16 "-42"--42--}-int16 :: Decoder Int16-int16 = intHelper "Int16"--{-| Decode an `Int32` from a Dhall @Integer@-->>> input int32 "-42"--42--}-int32 :: Decoder Int32-int32 = intHelper "Int32"--{-| Decode an `Int64` from a Dhall @Integer@-->>> input int64 "-42"--42--}-int64 :: Decoder Int64-int64 = intHelper "Int64"--{-| Decode a `Scientific`-r-->>> input scientific "1e100"-1.0e100--}-scientific :: Decoder Scientific-scientific = fmap Data.Scientific.fromFloatDigits double--{-| Decode a `Prelude.Double`-->>> input double "42.0"-42.0--}-double :: Decoder Double-double = Decoder {..}- where- extract (DoubleLit (DhallDouble n)) = pure n- extract expr = typeError expected expr-- expected = pure Double--{-| Decode lazy `Data.Text.Text`-->>> input lazyText "\"Test\""-"Test"--}-lazyText :: Decoder Data.Text.Lazy.Text-lazyText = fmap Data.Text.Lazy.fromStrict strictText--{-| Decode strict `Data.Text.Text`-->>> input strictText "\"Test\""-"Test"--}-strictText :: Decoder Text-strictText = Decoder {..}- where- extract (TextLit (Chunks [] t)) = pure t- extract expr = typeError expected expr-- expected = pure Text--{-| Decode a `Maybe`-->>> input (maybe natural) "Some 1"-Just 1--}-maybe :: Decoder a -> Decoder (Maybe a)-maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (Some e ) = fmap Just (extractIn e)- extractOut (App None _) = pure Nothing- extractOut expr = typeError expectedOut expr-- expectedOut = App Optional <$> expectedIn--{-| Decode a `Seq`-->>> input (sequence natural) "[1, 2, 3]"-fromList [1,2,3]--}-sequence :: Decoder a -> Decoder (Seq a)-sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (ListLit _ es) = traverse extractIn es- extractOut expr = typeError expectedOut expr-- expectedOut = App List <$> expectedIn--{-| Decode a list-->>> input (list natural) "[1, 2, 3]"-[1,2,3]--}-list :: Decoder a -> Decoder [a]-list = fmap Data.Foldable.toList . sequence--{-| Decode a `Vector`-->>> input (vector natural) "[1, 2, 3]"-[1,2,3]--}-vector :: Decoder a -> Decoder (Vector a)-vector = fmap Data.Vector.fromList . list--{-| Decode a Dhall function into a Haskell function-->>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)->>> f 0-True->>> f 1-False--}-function- :: Encoder a- -> Decoder b- -> Decoder (a -> b)-function = functionWith defaultInputNormalizer--{-| Decode a Dhall function into a Haskell function using the specified normalizer-->>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)->>> f 0-True->>> f 1-False--}-functionWith- :: InputNormalizer- -> Encoder a- -> Decoder b- -> Decoder (a -> b)-functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =- Decoder extractOut expectedOut- where- normalizer_ = Just (getInputNormalizer inputNormalizer)-- extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of- Success o -> o- Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )-- expectedOut = Pi "_" declared <$> expectedIn--{-| Decode a `Data.Set.Set` from a `List`-->>> input (setIgnoringDuplicates natural) "[1, 2, 3]"-fromList [1,2,3]--Duplicate elements are ignored.-->>> input (setIgnoringDuplicates natural) "[1, 1, 3]"-fromList [1,3]---}-setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)-setIgnoringDuplicates = fmap Data.Set.fromList . list--{-| Decode a `Data.HashSet.HashSet` from a `List`-->>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"-fromList [1,2,3]--Duplicate elements are ignored.-->>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"-fromList [1,3]---}-hashSetIgnoringDuplicates :: (Hashable a, Ord a)- => Decoder a- -> Decoder (Data.HashSet.HashSet a)-hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list--{-| Decode a `Data.Set.Set` from a `List` with distinct elements-->>> input (setFromDistinctList natural) "[1, 2, 3]"-fromList [1,2,3]--An error is thrown if the list contains duplicates.--> >>> input (setFromDistinctList natural) "[1, 1, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> One duplicate element in the list: 1->--> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> 2 duplicates were found in the list, including 1->---}-setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)-setFromDistinctList = setHelper Data.Set.size Data.Set.fromList--{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements-->>> input (hashSetFromDistinctList natural) "[1, 2, 3]"-fromList [1,2,3]--An error is thrown if the list contains duplicates.--> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> One duplicate element in the list: 1->--> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"-> *** Exception: Error: Failed extraction->-> The expression type-checked successfully but the transformation to the target-> type failed with the following error:->-> 2 duplicates were found in the list, including 1->---}-hashSetFromDistinctList :: (Hashable a, Ord a, Show a)- => Decoder a- -> Decoder (Data.HashSet.HashSet a)-hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList---setHelper :: (Eq a, Foldable t, Show a)- => (t a -> Int)- -> ([a] -> t a)- -> Decoder a- -> Decoder (t a)-setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut- where- extractOut (ListLit _ es) = case traverse extractIn es of- Success vSeq- | sameSize -> Success vSet- | otherwise -> extractError err- where- vList = Data.Foldable.toList vSeq- vSet = toSet vList- sameSize = size vSet == Data.Sequence.length vSeq- duplicates = vList Data.List.\\ Data.Foldable.toList vSet- err | length duplicates == 1 =- "One duplicate element in the list: "- <> (Data.Text.pack $ show $ head duplicates)- | otherwise = Data.Text.pack $ unwords- [ show $ length duplicates- , "duplicates were found in the list, including"- , show $ head duplicates- ]- Failure f -> Failure f- extractOut expr = typeError expectedOut expr-- expectedOut = App List <$> expectedIn--{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@-->>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"-fromList [("a",True),("b",False)]->>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"-fromList [("foo",True)]--If there are duplicate @mapKey@s, later @mapValue@s take precedence:-->>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"->>> input (Dhall.map natural bool) expr-fromList [(1,False)]---}-map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)-map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))--{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@-->>> input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }"-fromList [("a",True),("b",False)]->>> input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"-fromList [("foo",True)]--If there are duplicate @mapKey@s, later @mapValue@s take precedence:-->>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"->>> input (Dhall.hashMap natural bool) expr-fromList [(1,False)]---}-hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)-hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))--{-| Decode a tuple from a @Prelude.Map.Entry@ record-->>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"-("foo",3)--}-pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)-pairFromMapEntry k v = Decoder extractOut expectedOut- where- extractOut (RecordLit kvs)- | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs- , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs- = liftA2 (,) (extract k key) (extract v value)- extractOut expr = typeError expectedOut expr-- expectedOut = do- k' <- Core.makeRecordField <$> expected k- v' <- Core.makeRecordField <$> expected v- pure $ Record $ Dhall.Map.fromList- [ ("mapKey", k')- , ("mapValue", v')]--{-| Decode @()@ from an empty record.-->>> input unit "{=}" -- GHC doesn't print the result if it is ()---}-unit :: Decoder ()-unit = Decoder {..}- where- extract (RecordLit fields)- | Data.Foldable.null fields = pure ()- extract expr = typeError expected expr-- expected = pure $ Record mempty--{-| Decode 'Void' from an empty union.--Since @<>@ is uninhabited, @'input' 'void'@ will always fail.--}-void :: Decoder Void-void = union mempty--{-| Decode a `String`-->>> input string "\"ABC\""-"ABC"---}-string :: Decoder String-string = Data.Text.Lazy.unpack <$> lazyText--{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.-->>> input (pair natural bool) "{ _1 = 42, _2 = False }"-(42,False)--}-pair :: Decoder a -> Decoder b -> Decoder (a, b)-pair l r = Decoder extractOut expectedOut- where- extractOut expr@(RecordLit fields) =- (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)- (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)- <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)- (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)- extractOut expr = typeError expectedOut expr-- expectedOut = do- l' <- Core.makeRecordField <$> expected l- r' <- Core.makeRecordField <$> expected r- pure $ Record $ Dhall.Map.fromList- [ ("_1", l')- , ("_2", r')]--{-| Any value that implements `FromDhall` can be automatically decoded based on- the inferred return type of `input`-->>> input auto "[1, 2, 3]" :: IO (Vector Natural)-[1,2,3]->>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)-fromList [("a",False),("b",True)]-- This class auto-generates a default implementation for types that- implement `Generic`. This does not auto-generate an instance for recursive- types.-- The default instance can be tweaked using 'genericAutoWith' and custom- 'InterpretOptions', or using- [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)- and 'Dhall.Deriving.Codec' from "Dhall.Deriving".--}-class FromDhall a where- autoWith :: InputNormalizer -> Decoder a- default autoWith- :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a- autoWith _ = genericAuto--{-| A compatibility alias for `FromDhall`--This will eventually be removed.--}-type Interpret = FromDhall--instance FromDhall Void where- autoWith _ = void--instance FromDhall () where- autoWith _ = unit--instance FromDhall Bool where- autoWith _ = bool--instance FromDhall Natural where- autoWith _ = natural--instance FromDhall Word where- autoWith _ = word--instance FromDhall Word8 where- autoWith _ = word8--instance FromDhall Word16 where- autoWith _ = word16--instance FromDhall Word32 where- autoWith _ = word32--instance FromDhall Word64 where- autoWith _ = word64--instance FromDhall Integer where- autoWith _ = integer--instance FromDhall Int where- autoWith _ = int--instance FromDhall Int8 where- autoWith _ = int8--instance FromDhall Int16 where- autoWith _ = int16--instance FromDhall Int32 where- autoWith _ = int32--instance FromDhall Int64 where- autoWith _ = int64--instance FromDhall Scientific where- autoWith _ = scientific--instance FromDhall Double where- autoWith _ = double--instance {-# OVERLAPS #-} FromDhall [Char] where- autoWith _ = string--instance FromDhall Data.Text.Lazy.Text where- autoWith _ = lazyText--instance FromDhall Text where- autoWith _ = strictText--instance FromDhall a => FromDhall (Maybe a) where- autoWith opts = maybe (autoWith opts)--instance FromDhall a => FromDhall (Seq a) where- autoWith opts = sequence (autoWith opts)--instance FromDhall a => FromDhall [a] where- autoWith opts = list (autoWith opts)--instance FromDhall a => FromDhall (Vector a) where- autoWith opts = vector (autoWith opts)--{-| Note that this instance will throw errors in the presence of duplicates in- the list. To ignore duplicates, use `setIgnoringDuplicates`.--}-instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where- autoWith opts = setFromDistinctList (autoWith opts)--{-| Note that this instance will throw errors in the presence of duplicates in- the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.--}-instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where- autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)--instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where- autoWith inputNormalizer = Dhall.map (autoWith inputNormalizer) (autoWith inputNormalizer)--instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where- autoWith inputNormalizer = Dhall.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)--instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where- autoWith inputNormalizer =- functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)--instance (FromDhall a, FromDhall b) => FromDhall (a, b)--{-| Use the default input normalizer for interpreting a configuration file--> auto = autoWith defaultInputNormalizer--}-auto :: FromDhall a => Decoder a-auto = autoWith defaultInputNormalizer--{-| This type is exactly the same as `Data.Fix.Fix` except with a different- `FromDhall` instance. This intermediate type simplifies the implementation- of the inner loop for the `FromDhall` instance for `Fix`--}-newtype Result f = Result { _unResult :: f (Result f) }--resultToFix :: Functor f => Result f -> Fix f-resultToFix (Result x) = Fix (fmap resultToFix x)--instance FromDhall (f (Result f)) => FromDhall (Result f) where- autoWith inputNormalizer = Decoder {..}- where- extract (App _ expr) =- fmap Result (Dhall.extract (autoWith inputNormalizer) expr)- extract expr = typeError expected expr-- expected = pure "result"---- | You can use this instance to marshal recursive types from Dhall to Haskell.------ Here is an example use of this instance:------ > {-# LANGUAGE DeriveAnyClass #-}--- > {-# LANGUAGE DeriveFoldable #-}--- > {-# LANGUAGE DeriveFunctor #-}--- > {-# LANGUAGE DeriveTraversable #-}--- > {-# LANGUAGE DeriveGeneric #-}--- > {-# LANGUAGE KindSignatures #-}--- > {-# LANGUAGE QuasiQuotes #-}--- > {-# LANGUAGE StandaloneDeriving #-}--- > {-# LANGUAGE TypeFamilies #-}--- > {-# LANGUAGE TemplateHaskell #-}--- >--- > import Data.Fix (Fix(..))--- > import Data.Text (Text)--- > import Dhall (FromDhall)--- > import GHC.Generics (Generic)--- > import Numeric.Natural (Natural)--- >--- > import qualified Data.Fix as Fix--- > import qualified Data.Functor.Foldable as Foldable--- > import qualified Data.Functor.Foldable.TH as TH--- > import qualified Dhall--- > import qualified NeatInterpolation--- >--- > data Expr--- > = Lit Natural--- > | Add Expr Expr--- > | Mul Expr Expr--- > deriving (Show)--- >--- > TH.makeBaseFunctor ''Expr--- >--- > deriving instance Generic (ExprF a)--- > deriving instance FromDhall a => FromDhall (ExprF a)--- >--- > example :: Text--- > example = [NeatInterpolation.text|--- > \(Expr : Type)--- > -> let ExprF =--- > < LitF :--- > Natural--- > | AddF :--- > { _1 : Expr, _2 : Expr }--- > | MulF :--- > { _1 : Expr, _2 : Expr }--- > >--- >--- > in \(Fix : ExprF -> Expr)--- > -> let Lit = \(x : Natural) -> Fix (ExprF.LitF x)--- >--- > let Add =--- > \(x : Expr)--- > -> \(y : Expr)--- > -> Fix (ExprF.AddF { _1 = x, _2 = y })--- >--- > let Mul =--- > \(x : Expr)--- > -> \(y : Expr)--- > -> Fix (ExprF.MulF { _1 = x, _2 = y })--- >--- > in Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))--- > |]--- >--- > convert :: Fix ExprF -> Expr--- > convert = Fix.foldFix Foldable.embed--- >--- > main :: IO ()--- > main = do--- > x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)--- >--- > print (convert x :: Expr)-instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where- autoWith inputNormalizer = Decoder {..}- where- extract expr0 = extract0 expr0- where- die = typeError expected expr0-- extract0 (Lam (FunctionBinding { functionBindingVariable = x }) expr) =- extract1 (rename x "result" expr)- extract0 _ = die-- extract1 (Lam (FunctionBinding { functionBindingVariable = y }) expr) =- extract2 (rename y "Make" expr)- extract1 _ = die-- extract2 expr = fmap resultToFix (Dhall.extract (autoWith inputNormalizer) expr)-- rename a b expr- | a /= b = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)- | otherwise = expr-- expected = (\x -> Pi "result" (Const Core.Type) (Pi "Make" (Pi "_" x "result") "result"))- <$> Dhall.expected (autoWith inputNormalizer :: Decoder (f (Result f)))--{-| `genericAuto` is the default implementation for `auto` if you derive- `FromDhall`. The difference is that you can use `genericAuto` without- having to explicitly provide a `FromDhall` instance for a type as long as- the type derives `Generic`--}-genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a-genericAuto = genericAutoWith defaultInterpretOptions--{-| `genericAutoWith` is a configurable version of `genericAuto`.--}-genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a-genericAutoWith options = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p defaultInputNormalizer options) 1))- where- withProxy :: (Proxy a -> Decoder a) -> Decoder a- withProxy f = f Proxy---{-| Use these options to tweak how Dhall derives a generic implementation of- `FromDhall`--}-data InterpretOptions = InterpretOptions- { fieldModifier :: Text -> Text- -- ^ Function used to transform Haskell field names into their corresponding- -- Dhall field names- , constructorModifier :: Text -> Text- -- ^ Function used to transform Haskell constructor names into their- -- corresponding Dhall alternative names- , singletonConstructors :: SingletonConstructors- -- ^ Specify how to handle constructors with only one field. The default is- -- `Smart`- }---- | This is only used by the `FromDhall` instance for functions in order--- to normalize the function input before marshaling the input into a--- Dhall expression-newtype InputNormalizer = InputNormalizer- { getInputNormalizer :: Core.ReifiedNormalizer Void }---- | Default normalization-related settings (no custom normalization)-defaultInputNormalizer :: InputNormalizer-defaultInputNormalizer = InputNormalizer- { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }--{-| This type specifies how to model a Haskell constructor with 1 field in- Dhall-- For example, consider the following Haskell datatype definition:-- > data Example = Foo { x :: Double } | Bar Double-- Depending on which option you pick, the corresponding Dhall type could be:-- > < Foo : Double | Bar : Double > -- Bare-- > < Foo : { x : Double } | Bar : { _1 : Double } > -- Wrapped-- > < Foo : { x : Double } | Bar : Double > -- Smart--}-data SingletonConstructors- = Bare- -- ^ Never wrap the field in a record- | Wrapped- -- ^ Always wrap the field in a record- | Smart- -- ^ Only fields in a record if they are named--{-| Default interpret options for generics-based instances,- which you can tweak or override, like this:--> genericAutoWith-> (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })--}-defaultInterpretOptions :: InterpretOptions-defaultInterpretOptions = InterpretOptions- { fieldModifier =- id- , constructorModifier =- id- , singletonConstructors =- Smart- }--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation--}-class GenericFromDhall t f where- genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))--instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where- genericAutoWithNormalizer p inputNormalizer options = do- res <- genericAutoWithNormalizer p inputNormalizer options- pure (fmap M1 res)--instance GenericFromDhall t V1 where- genericAutoWithNormalizer _ _ _ = pure Decoder {..}- where- extract expr = typeError expected expr-- expected = pure $ Union mempty--unsafeExpectUnion- :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))-unsafeExpectUnion _ (Union kts) =- kts-unsafeExpectUnion name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectRecord- :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)-unsafeExpectRecord _ (Record kts) =- kts-unsafeExpectRecord name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectUnionLit- :: Text- -> Expr Src Void- -> (Text, Maybe (Expr Src Void))-unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =- (k, Nothing)-unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =- (k, Just v)-unsafeExpectUnionLit name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--unsafeExpectRecordLit- :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)-unsafeExpectRecordLit _ (RecordLit kvs) =- kvs-unsafeExpectRecordLit name expression =- Core.internalError- (name <> ": Unexpected constructor: " <> Core.pretty expression)--notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)-notEmptyRecordLit e = case e of- RecordLit m | null m -> Nothing- _ -> Just e--notEmptyRecord :: Expr s a -> Maybe (Expr s a)-notEmptyRecord e = case e of- Record m | null m -> Nothing- _ -> Just e-extractUnionConstructor- :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))-extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =- return (fld, e, Dhall.Map.delete fld kts)-extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =- return (fld, RecordLit mempty, Dhall.Map.delete fld kts)-extractUnionConstructor _ =- empty--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation for a union type--}-class GenericFromDhallUnion t f where- genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)--instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where- genericUnionAutoWithNormalizer p inputNormalizer options =- (<>)- (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)- (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)--instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where- genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =- constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)- where- n :: M1 C c1 f1 a- n = undefined-- name = constructorModifier (Data.Text.pack (conName n))--instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where- genericAutoWithNormalizer p inputNormalizer options =- pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))--instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where- genericAutoWithNormalizer p inputNormalizer options = do- res <- genericAutoWithNormalizer p inputNormalizer options- pure (fmap M1 res)--instance GenericFromDhall t U1 where- genericAutoWithNormalizer _ _ _ = pure (Decoder {..})- where- extract _ = pure U1-- expected = pure expected'-- expected' = Record (Dhall.Map.fromList [])--getSelName :: Selector s => M1 i s f a -> State Int Text-getSelName n = case selName n of- "" -> do i <- get- put (i + 1)- pure (Data.Text.pack ("_" ++ show i))- nn -> pure (Data.Text.pack nn)--instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where- genericAutoWithNormalizer p inputNormalizer options = do- Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options- Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options-- let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL- let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR-- let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)-- let extract expression =- liftA2 (:*:) (extractL expression) (extractR expression)-- return (Decoder {..})--instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where- genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do- let nR :: M1 S s (K1 i a) r- nR = undefined-- nameR <- fmap fieldModifier (getSelName nR)-- Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options-- let Decoder extractR expectedR = autoWith inputNormalizer-- let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL-- let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of- Just expressionR ->- liftA2 (:*:)- (extractL expression)- (fmap (M1 . K1) (extractR expressionR))- _ -> die- _ -> die-- return (Decoder {..})--instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where- genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do- let nL :: M1 S s (K1 i a) r- nL = undefined-- nameL <- fmap fieldModifier (getSelName nL)-- let Decoder extractL expectedL = autoWith inputNormalizer-- Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options-- let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR-- let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of- Just expressionL ->- liftA2 (:*:)- (fmap (M1 . K1) (extractL expressionL))- (extractR expression)- _ -> die- _ -> die-- return (Decoder {..})--instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do- let nL :: M1 S s1 (K1 i1 a1) r- nL = undefined-- let nR :: M1 S s2 (K1 i2 a2) r- nR = undefined-- nameL <- fmap fieldModifier (getSelName nL)- nameR <- fmap fieldModifier (getSelName nR)-- let Decoder extractL expectedL = autoWith inputNormalizer- let Decoder extractR expectedR = autoWith inputNormalizer-- let expected = do- l <- Core.makeRecordField <$> expectedL- r <- Core.makeRecordField <$> expectedR- pure $ Record- (Dhall.Map.fromList- [ (nameL, l)- , (nameR, r)- ]- )-- let extract expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of- Just (expressionL, expressionR) ->- liftA2 (:*:)- (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))- (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))- Nothing -> die- _ -> die-- return (Decoder {..})--instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where- genericAutoWithNormalizer _ _ _ = pure $ Decoder- { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError- , expected = Failure $ DhallErrors $ pure RecursiveTypeError- }--instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where- genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do- let n :: M1 S s (K1 i a) r- n = undefined-- name <- fmap fieldModifier (getSelName n)-- let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer-- let expected =- case singletonConstructors of- Bare ->- expected'- Smart | selName n == "" ->- expected'- _ ->- Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'-- let extract0 expression = fmap (M1 . K1) (extract' expression)-- let extract1 expression = do- let die = typeError expected expression-- case expression of- RecordLit kvs ->- case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of- Just subExpression ->- fmap (M1 . K1) (extract' subExpression)- Nothing ->- die- _ -> die-- let extract =- case singletonConstructors of- Bare -> extract0- Smart | selName n == "" -> extract0- _ -> extract1-- return (Decoder {..})--{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from- Haskell into Dhall--}-data Encoder a = Encoder- { embed :: a -> Expr Src Void- -- ^ Embeds a Haskell value as a Dhall expression- , declared :: Expr Src Void- -- ^ Dhall type of the Haskell value- }--instance Contravariant Encoder where- contramap f (Encoder embed declared) = Encoder embed' declared- where- embed' x = embed (f x)--{-| This class is used by `FromDhall` instance for functions:--> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)-- You can convert Dhall functions with "simple" inputs (i.e. instances of this- class) into Haskell functions. This works by:-- * Marshaling the input to the Haskell function into a Dhall expression (i.e.- @x :: Expr Src Void@)- * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input- (i.e. @App f x@)- * Normalizing the syntax tree (i.e. @normalize (App f x)@)- * Marshaling the resulting Dhall expression back into a Haskell value-- This class auto-generates a default implementation for types that- implement `Generic`. This does not auto-generate an instance for recursive- types.-- The default instance can be tweaked using 'genericToDhallWith' and custom- 'InterpretOptions', or using- [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)- and 'Dhall.Deriving.Codec' from "Dhall.Deriving".--}-class ToDhall a where- injectWith :: InputNormalizer -> Encoder a- default injectWith- :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a- injectWith _ = genericToDhall--{-| A compatibility alias for `ToDhall`--This will eventually be removed.--}-type Inject = ToDhall--{-| Use the default input normalizer for injecting a value--> inject = injectWith defaultInputNormalizer--}-inject :: ToDhall a => Encoder a-inject = injectWith defaultInputNormalizer--{-| Use the default options for injecting a value, whose structure is-determined generically.--This can be used when you want to use 'ToDhall' on types that you don't-want to define orphan instances for.--}-genericToDhall- :: (Generic a, GenericToDhall (Rep a)) => Encoder a-genericToDhall- = genericToDhallWith defaultInterpretOptions--{-| Use custom options for injecting a value, whose structure is-determined generically.--This can be used when you want to use 'ToDhall' on types that you don't-want to define orphan instances for.--}-genericToDhallWith- :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a-genericToDhallWith options- = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer defaultInputNormalizer options) 1)--instance ToDhall Void where- injectWith _ = Encoder {..}- where- embed = Data.Void.absurd-- declared = Union mempty--instance ToDhall Bool where- injectWith _ = Encoder {..}- where- embed = BoolLit-- declared = Bool--instance ToDhall Data.Text.Lazy.Text where- injectWith _ = Encoder {..}- where- embed text =- TextLit (Chunks [] (Data.Text.Lazy.toStrict text))-- declared = Text--instance ToDhall Text where- injectWith _ = Encoder {..}- where- embed text = TextLit (Chunks [] text)-- declared = Text--instance {-# OVERLAPS #-} ToDhall String where- injectWith inputNormalizer =- contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)--instance ToDhall Natural where- injectWith _ = Encoder {..}- where- embed = NaturalLit-- declared = Natural--instance ToDhall Integer where- injectWith _ = Encoder {..}- where- embed = IntegerLit-- declared = Integer--instance ToDhall Int where- injectWith _ = Encoder {..}- where- embed = IntegerLit . toInteger-- declared = Integer--{-|-->>> embed inject (12 :: Word)-NaturalLit 12--}--instance ToDhall Word where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word8)-NaturalLit 12--}--instance ToDhall Word8 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word16)-NaturalLit 12--}--instance ToDhall Word16 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word32)-NaturalLit 12--}--instance ToDhall Word32 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--{-|-->>> embed inject (12 :: Word64)-NaturalLit 12--}--instance ToDhall Word64 where- injectWith _ = Encoder {..}- where- embed = NaturalLit . fromIntegral-- declared = Natural--instance ToDhall Double where- injectWith _ = Encoder {..}- where- embed = DoubleLit . DhallDouble-- declared = Double--instance ToDhall Scientific where- injectWith inputNormalizer =- contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)--instance ToDhall () where- injectWith _ = Encoder {..}- where- embed = const (RecordLit mempty)-- declared = Record mempty--instance ToDhall a => ToDhall (Maybe a) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut (Just x ) = Some (embedIn x)- embedOut Nothing = App None declaredIn-- Encoder embedIn declaredIn = injectWith inputNormalizer-- declaredOut = App Optional declaredIn--instance ToDhall a => ToDhall (Seq a) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut xs = ListLit listType (fmap embedIn xs)- where- listType- | null xs = Just (App List declaredIn)- | otherwise = Nothing-- declaredOut = App List declaredIn-- Encoder embedIn declaredIn = injectWith inputNormalizer--instance ToDhall a => ToDhall [a] where- injectWith = fmap (contramap Data.Sequence.fromList) injectWith--instance ToDhall a => ToDhall (Vector a) where- injectWith = fmap (contramap Data.Vector.toList) injectWith--{-| Note that the output list will be sorted-->>> let x = Data.Set.fromList ["mom", "hi" :: Text]->>> prettyExpr $ embed inject x-[ "hi", "mom" ]---}-instance ToDhall a => ToDhall (Data.Set.Set a) where- injectWith = fmap (contramap Data.Set.toAscList) injectWith--{-| Note that the output list may not be sorted-->>> let x = Data.HashSet.fromList ["hi", "mom" :: Text]->>> prettyExpr $ embed inject x-[ "mom", "hi" ]---}-instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where- injectWith = fmap (contramap Data.HashSet.toList) injectWith--instance (ToDhall a, ToDhall b) => ToDhall (a, b)--{-| Embed a `Data.Map` as a @Prelude.Map.Type@-->>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])-[ { mapKey = 1, mapValue = True } ]-->>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)-[] : List { mapKey : Natural, mapValue : Bool }---}-instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut m = ListLit listType (mapEntries m)- where- listType- | Data.Map.null m = Just declaredOut- | otherwise = Nothing-- declaredOut = App List (Record $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField declaredK)- , ("mapValue", Core.makeRecordField declaredV)- ])-- mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList- recordPair (k, v) = RecordLit $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField $ embedK k)- , ("mapValue", Core.makeRecordField $ embedV v)- ]-- Encoder embedK declaredK = injectWith inputNormalizer- Encoder embedV declaredV = injectWith inputNormalizer--{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@-->>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])-[ { mapKey = 1, mapValue = True } ]-->>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)-[] : List { mapKey : Natural, mapValue : Bool }---}-instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where- injectWith inputNormalizer = Encoder embedOut declaredOut- where- embedOut m = ListLit listType (mapEntries m)- where- listType- | HashMap.null m = Just declaredOut- | otherwise = Nothing-- declaredOut = App List (Record $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField declaredK)- , ("mapValue", Core.makeRecordField declaredV)- ])-- mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList- recordPair (k, v) = RecordLit $ Dhall.Map.fromList- [ ("mapKey", Core.makeRecordField $ embedK k)- , ("mapValue", Core.makeRecordField $ embedV v)- ]-- Encoder embedK declaredK = injectWith inputNormalizer- Encoder embedV declaredV = injectWith inputNormalizer--{-| This is the underlying class that powers the `FromDhall` class's support- for automatically deriving a generic implementation--}-class GenericToDhall f where- genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))--instance GenericToDhall f => GenericToDhall (M1 D d f) where- genericToDhallWithNormalizer inputNormalizer options = do- res <- genericToDhallWithNormalizer inputNormalizer options- pure (contramap unM1 res)--instance GenericToDhall f => GenericToDhall (M1 C c f) where- genericToDhallWithNormalizer inputNormalizer options = do- res <- genericToDhallWithNormalizer inputNormalizer options- pure (contramap unM1 res)--instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where- genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do- let Encoder { embed = embed', declared = declared' } =- injectWith inputNormalizer-- let n :: M1 S s (K1 i a) r- n = undefined-- name <- fieldModifier <$> getSelName n-- let embed0 (M1 (K1 x)) = embed' x-- let embed1 (M1 (K1 x)) =- RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))-- let embed =- case singletonConstructors of- Bare -> embed0- Smart | selName n == "" -> embed0- _ -> embed1-- let declared =- case singletonConstructors of- Bare ->- declared'- Smart | selName n == "" ->- declared'- _ ->- Record (Dhall.Map.singleton name $ Core.makeRecordField declared')-- return (Encoder {..})--instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 (M1 l)) =- case notEmptyRecordLit (embedL l) of- Nothing ->- Field declared $ Core.makeFieldSelection keyL- Just valL ->- App (Field declared $ Core.makeFieldSelection keyL) valL-- embed (R1 (M1 r)) =- case notEmptyRecordLit (embedR r) of- Nothing ->- Field declared $ Core.makeFieldSelection keyR- Just valR ->- App (Field declared $ Core.makeFieldSelection keyR) valR-- declared =- Union- (Dhall.Map.fromList- [ (keyL, notEmptyRecord declaredL)- , (keyR, notEmptyRecord declaredR)- ]- )-- nL :: M1 i c1 f1 a- nL = undefined-- nR :: M1 i c2 f2 a- nR = undefined-- keyL = constructorModifier (Data.Text.pack (conName nL))- keyR = constructorModifier (Data.Text.pack (conName nR))-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1--instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 l) =- case maybeValL of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- where- (keyL, maybeValL) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)- embed (R1 (M1 r)) =- case notEmptyRecordLit (embedR r) of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR-- nR :: M1 i c h a- nR = undefined-- keyR = constructorModifier (Data.Text.pack (conName nR))-- declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL--instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where- genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})- where- embed (L1 (M1 l)) =- case notEmptyRecordLit (embedL l) of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- embed (R1 r) =- case maybeValR of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR- where- (keyR, maybeValR) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)-- nL :: M1 i c f a- nL = undefined-- keyL = constructorModifier (Data.Text.pack (conName nL))-- declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR--instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where- genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})- where- embed (L1 l) =- case maybeValL of- Nothing -> Field declared $ Core.makeFieldSelection keyL- Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL- where- (keyL, maybeValL) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)- embed (R1 r) =- case maybeValR of- Nothing -> Field declared $ Core.makeFieldSelection keyR- Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR- where- (keyR, maybeValR) =- unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)-- declared = Union (Dhall.Map.union ktsL ktsR)-- Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1- Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1-- ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL- ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR--instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where- genericToDhallWithNormalizer inputNormalizer options = do- Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options- Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options-- let embed (l :*: r) =- RecordLit (Dhall.Map.union mapL mapR)- where- mapL =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)-- mapR =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)-- let declared = Record (Dhall.Map.union mapL mapR)- where- mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL- mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR-- pure (Encoder {..})--instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where- genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do- let nR :: M1 S s (K1 i a) r- nR = undefined-- nameR <- fmap fieldModifier (getSelName nR)-- Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options-- let Encoder embedR declaredR = injectWith inputNormalizer-- let embed (l :*: M1 (K1 r)) =- RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)- where- mapL =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)-- let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)- where- mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL-- return (Encoder {..})--instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where- genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do- let nL :: M1 S s (K1 i a) r- nL = undefined-- nameL <- fmap fieldModifier (getSelName nL)-- let Encoder embedL declaredL = injectWith inputNormalizer-- Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options-- let embed (M1 (K1 l) :*: r) =- RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)- where- mapR =- unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)-- let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)- where- mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR-- return (Encoder {..})--instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where- genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do- let nL :: M1 S s1 (K1 i1 a1) r- nL = undefined-- let nR :: M1 S s2 (K1 i2 a2) r- nR = undefined-- nameL <- fmap fieldModifier (getSelName nL)- nameR <- fmap fieldModifier (getSelName nR)-- let Encoder embedL declaredL = injectWith inputNormalizer- let Encoder embedR declaredR = injectWith inputNormalizer-- let embed (M1 (K1 l) :*: M1 (K1 r)) =- RecordLit $- Dhall.Map.fromList- [ (nameL, Core.makeRecordField $ embedL l)- , (nameR, Core.makeRecordField $ embedR r) ]--- let declared =- Record $ Dhall.Map.fromList- [ (nameL, Core.makeRecordField declaredL)- , (nameR, Core.makeRecordField declaredR) ]--- return (Encoder {..})--instance GenericToDhall U1 where- genericToDhallWithNormalizer _ _ = pure (Encoder {..})- where- embed _ = RecordLit mempty-- declared = Record mempty--{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'- from a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Project = Project- { projectName :: Text- , projectDescription :: Text- , projectStars :: Natural- }-:}-- And assume that we have the following Dhall record that we would like to- parse as a @Project@:--> { name =-> "dhall-haskell"-> , description =-> "A configuration language guaranteed to terminate"-> , stars =-> 289-> }-- Our decoder has type 'Decoder' @Project@, but we can't build that out of any- smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).- However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:-->>> :{-project :: Decoder Project-project =- record- ( Project <$> field "name" strictText- <*> field "description" strictText- <*> field "stars" natural- )-:}--}--newtype RecordDecoder a =- RecordDecoder- ( Data.Functor.Product.Product- ( Control.Applicative.Const- (Dhall.Map.Map Text (Expector (Expr Src Void)))- )- ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)- )- a- )- deriving (Functor, Applicative)----- | Run a 'RecordDecoder' to build a 'Decoder'.-record :: RecordDecoder a -> Dhall.Decoder a-record- (RecordDecoder- (Data.Functor.Product.Pair- (Control.Applicative.Const fields)- (Data.Functor.Compose.Compose extract)- )- ) = Decoder {..}- where- expected = Record <$> traverse (fmap Core.makeRecordField) fields----- | Parse a single field of a record.-field :: Text -> Decoder a -> RecordDecoder a-field key (Decoder {..}) =- RecordDecoder- ( Data.Functor.Product.Pair- ( Control.Applicative.Const- (Dhall.Map.singleton key expected)- )- ( Data.Functor.Compose.Compose extractBody )- )- where- extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of- Just v -> extract v- _ -> typeError expected expr- extractBody expr = typeError expected expr--{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union-- For example, let's take the following Haskell data type:-->>> :{-data Status = Queued Natural- | Result Text- | Errored Text-:}-- And assume that we have the following Dhall union that we would like to- parse as a @Status@:--> < Result : Text-> | Queued : Natural-> | Errored : Text-> >.Result "Finish successfully"-- Our decoder has type 'Decoder' @Status@, but we can't build that out of any- smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).- However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:-->>> :{-status :: Decoder Status-status = union- ( ( Queued <$> constructor "Queued" natural )- <> ( Result <$> constructor "Result" strictText )- <> ( Errored <$> constructor "Errored" strictText )- )-:}---}-newtype UnionDecoder a =- UnionDecoder- ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )- deriving (Functor)--instance Semigroup (UnionDecoder a) where- (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))--instance Monoid (UnionDecoder a) where- mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))---- | Run a 'UnionDecoder' to build a 'Decoder'.-union :: UnionDecoder a -> Decoder a-union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}- where- extract expr = case expected' of- Failure e -> Failure $ fmap ExpectedTypeError e- Success x -> extract' expr x-- extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.extract) $ do- (fld, e1, rest) <- extractUnionConstructor e0-- t <- Dhall.Map.lookup fld mp-- guard $- Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')-- pure (t, e1)-- expected = Union <$> expected'-- expected' = traverse (fmap notEmptyRecord . Dhall.expected) mp---- | Parse a single constructor of a union-constructor :: Text -> Decoder a -> UnionDecoder a-constructor key valueDecoder = UnionDecoder- ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )---- | Infix 'divided'-(>*<) :: Divisible f => f a -> f b -> f (a, b)-(>*<) = divided--infixr 5 >*<--{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build- an 'Encoder' for a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Project = Project- { projectName :: Text- , projectDescription :: Text- , projectStars :: Natural- }-:}-- And assume that we have the following Dhall record that we would like to- parse as a @Project@:--> { name =-> "dhall-haskell"-> , description =-> "A configuration language guaranteed to terminate"-> , stars =-> 289-> }-- Our encoder has type 'Encoder' @Project@, but we can't build that out of any- smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).- However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:-->>> :{-injectProject :: Encoder Project-injectProject =- recordEncoder- ( adapt >$< encodeFieldWith "name" inject- >*< encodeFieldWith "description" inject- >*< encodeFieldWith "stars" inject- )- where- adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}-- Or, since we are simply using the `ToDhall` instance to inject each field, we could write-->>> :{-injectProject :: Encoder Project-injectProject =- recordEncoder- ( adapt >$< encodeField "name"- >*< encodeField "description"- >*< encodeField "stars"- )- where- adapt (Project{..}) = (projectName, (projectDescription, projectStars))-:}---}--newtype RecordEncoder a- = RecordEncoder (Dhall.Map.Map Text (Encoder a))--instance Contravariant RecordEncoder where- contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord--instance Divisible RecordEncoder where- divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =- RecordEncoder- $ Dhall.Map.union- ((contramap $ fst . f) <$> bEncoderRecord)- ((contramap $ snd . f) <$> cEncoderRecord)- conquer = RecordEncoder mempty--{-| Specify how to encode one field of a record by supplying an explicit- `Encoder` for that field--}-encodeFieldWith :: Text -> Encoder a -> RecordEncoder a-encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType--{-| Specify how to encode one field of a record using the default `ToDhall`- instance for that type--}-encodeField :: ToDhall a => Text -> RecordEncoder a-encodeField name = encodeFieldWith name inject---- | Convert a `RecordEncoder` into the equivalent `Encoder`-recordEncoder :: RecordEncoder a -> Encoder a-recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType- where- recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord- makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord--{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.-- For example, let's take the following Haskell data type:-->>> :{-data Status = Queued Natural- | Result Text- | Errored Text-:}-- And assume that we have the following Dhall union that we would like to- parse as a @Status@:--> < Result : Text-> | Queued : Natural-> | Errored : Text-> >.Result "Finish successfully"-- Our encoder has type 'Encoder' @Status@, but we can't build that out of any- smaller encoders, as 'Encoder's cannot be combined.- However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:-->>> :{-injectStatus :: Encoder Status-injectStatus = adapt >$< unionEncoder- ( encodeConstructorWith "Queued" inject- >|< encodeConstructorWith "Result" inject- >|< encodeConstructorWith "Errored" inject- )- where- adapt (Queued n) = Left n- adapt (Result t) = Right (Left t)- adapt (Errored e) = Right (Right e)-:}-- Or, since we are simply using the `ToDhall` instance to inject each branch, we could write-->>> :{-injectStatus :: Encoder Status-injectStatus = adapt >$< unionEncoder- ( encodeConstructor "Queued"- >|< encodeConstructor "Result"- >|< encodeConstructor "Errored"- )- where- adapt (Queued n) = Left n- adapt (Result t) = Right (Left t)- adapt (Errored e) = Right (Right e)-:}---}-newtype UnionEncoder a =- UnionEncoder- ( Data.Functor.Product.Product- ( Control.Applicative.Const- ( Dhall.Map.Map- Text- ( Expr Src Void )- )- )- ( Op (Text, Expr Src Void) )- a- )- deriving (Contravariant)---- | Combines two 'UnionEncoder' values. See 'UnionEncoder' for usage--- notes.------ Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';--- however, this allows 'UnionEncoder' to not need a 'Divisible' instance--- itself (since no instance is possible).-(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)-UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))- >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =- UnionEncoder- ( Data.Functor.Product.Pair- ( Control.Applicative.Const (mx <> my) )- ( Op (either fx fy) )- )--infixr 5 >|<---- | Convert a `UnionEncoder` into the equivalent `Encoder`-unionEncoder :: UnionEncoder a -> Encoder a-unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =- Encoder- { embed = \x ->- let (name, y) = embedF x- in case notEmptyRecordLit y of- Nothing -> Field (Union fields') $ Core.makeFieldSelection name- Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val- , declared =- Union fields'- }- where- fields' = fmap notEmptyRecord fields--{-| Specify how to encode an alternative by providing an explicit `Encoder`- for that alternative--}-encodeConstructorWith- :: Text- -> Encoder a- -> UnionEncoder a-encodeConstructorWith name encodeType = UnionEncoder $- Data.Functor.Product.Pair- ( Control.Applicative.Const- ( Dhall.Map.singleton- name- ( declared encodeType )- )- )- ( Op ( (name,) . embed encodeType )- )--{-| Specify how to encode an alternative by using the default `ToDhall` instance- for that type--}-encodeConstructor- :: ToDhall a- => Text- -> UnionEncoder a-encodeConstructor name = encodeConstructorWith name inject+{-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall+ (+ -- * Input+ input+ , inputWithSettings+ , inputFile+ , inputFileWithSettings+ , inputExpr+ , inputExprWithSettings+ , interpretExpr+ , interpretExprWithSettings+ , fromExpr+ , fromExprWithSettings+ , rootDirectory+ , sourceName+ , startingContext+ , substitutions+ , normalizer+ , newManager+ , defaultInputSettings+ , InputSettings+ , defaultEvaluateSettings+ , EvaluateSettings+ , HasEvaluateSettings(..)+ , detailed++ -- * Decoders+ , module Dhall.Marshal.Decode++ -- * Encoders+ , module Dhall.Marshal.Encode++ -- * Individual phases+ , parseWithSettings+ , resolveWithSettings+ , resolveAndStatusWithSettings+ , typecheckWithSettings+ , checkWithSettings+ , expectWithSettings+ , normalizeWithSettings++ -- * Miscellaneous+ , rawInput+ ) where++import Control.Applicative (Alternative, empty)+import Control.Monad.Catch (MonadThrow, throwM)+import Data.Either.Validation (Validation (..))+import Data.Void (Void)+import Dhall.Import (Imported (..), Status)+import Dhall.Parser (Src (..))+import Dhall.Syntax (Expr (..), Import)+import Dhall.TypeCheck (DetailedTypeError (..), TypeError)+import GHC.Generics+import Lens.Micro (Lens', lens)+import Lens.Micro.Extras (view)+import Prelude hiding (maybe, sequence)+import System.FilePath (takeDirectory)++import qualified Control.Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Text.IO+import qualified Dhall.Context+import qualified Dhall.Core as Core+import qualified Dhall.Import+import qualified Dhall.Parser+import qualified Dhall.Pretty.Internal+import qualified Dhall.Substitution+import qualified Dhall.TypeCheck+import qualified Lens.Micro as Lens++import Dhall.Marshal.Decode+import Dhall.Marshal.Encode++-- | @since 1.16+data InputSettings = InputSettings+ { _rootDirectory :: FilePath+ , _sourceName :: FilePath+ , _evaluateSettings :: EvaluateSettings+ }++-- | Default input settings: resolves imports relative to @.@ (the+-- current working directory), report errors as coming from @(input)@,+-- and default evaluation settings from 'defaultEvaluateSettings'.+--+-- @since 1.16+defaultInputSettings :: InputSettings+defaultInputSettings = InputSettings+ { _rootDirectory = "."+ , _sourceName = "(input)"+ , _evaluateSettings = defaultEvaluateSettings+ }+++-- | Access the directory to resolve imports relative to.+--+-- @since 1.16+rootDirectory :: Lens' InputSettings FilePath+rootDirectory = lens _rootDirectory (\s x -> s { _rootDirectory = x })++-- | Access the name of the source to report locations from; this is+-- only used in error messages, so it's okay if this is a best guess+-- or something symbolic.+--+-- @since 1.16+sourceName :: Lens' InputSettings FilePath+sourceName = lens _sourceName (\s x -> s { _sourceName = x})++-- | @since 1.16+data EvaluateSettings = EvaluateSettings+ { _substitutions :: Dhall.Substitution.Substitutions Src Void+ , _startingContext :: Dhall.Context.Context (Expr Src Void)+ , _normalizer :: Maybe (Core.ReifiedNormalizer Void)+ , _newManager :: IO Dhall.Import.Manager+ }++-- | Default evaluation settings: no extra entries in the initial+-- context, and no special normalizer behaviour.+--+-- @since 1.16+defaultEvaluateSettings :: EvaluateSettings+defaultEvaluateSettings = EvaluateSettings+ { _substitutions = Dhall.Substitution.empty+ , _startingContext = Dhall.Context.empty+ , _normalizer = Nothing+ , _newManager = Dhall.Import.defaultNewManager+ }++-- | Access the starting context used for evaluation and type-checking.+--+-- @since 1.16+startingContext+ :: (HasEvaluateSettings s)+ => Lens' s (Dhall.Context.Context (Expr Src Void))+startingContext =+ evaluateSettings+ . lens _startingContext (\s x -> s { _startingContext = x})++-- | Access the custom substitutions.+--+-- @since 1.30+substitutions+ :: (HasEvaluateSettings s)+ => Lens' s (Dhall.Substitution.Substitutions Src Void)+substitutions =+ evaluateSettings+ . lens _substitutions (\s x -> s { _substitutions = x })++-- | Access the custom normalizer.+--+-- @since 1.16+normalizer+ :: (HasEvaluateSettings s)+ => Lens' s (Maybe (Core.ReifiedNormalizer Void))+normalizer =+ evaluateSettings+ . lens _normalizer (\s x -> s { _normalizer = x })++-- | Access the HTTP manager initializer.+--+-- @since 1.36+newManager+ :: (HasEvaluateSettings s)+ => Lens' s (IO Dhall.Import.Manager)+newManager =+ evaluateSettings+ . lens _newManager (\s x -> s { _newManager = x })++-- | @since 1.16+class HasEvaluateSettings s where+ evaluateSettings :: Lens' s EvaluateSettings++instance HasEvaluateSettings InputSettings where+ evaluateSettings =+ lens _evaluateSettings (\s x -> s { _evaluateSettings = x })++instance HasEvaluateSettings EvaluateSettings where+ evaluateSettings = id++-- | Parse an expression, using the supplied `InputSettings`+parseWithSettings :: MonadThrow m => InputSettings -> Text -> m (Expr Src Import)+parseWithSettings settings text =+ either throwM return (Dhall.Parser.exprFromText (view sourceName settings) text)++-- | Type-check an expression, using the supplied `InputSettings`+typecheckWithSettings :: MonadThrow m => InputSettings -> Expr Src Void -> m ()+typecheckWithSettings settings expression =+ either throwM (return . const ()) (Dhall.TypeCheck.typeWith (view startingContext settings) expression)++{-| Type-check an expression against a type provided as a Dhall expreession,+ using the supplied `InputSettings`+-}+checkWithSettings ::+ MonadThrow m =>+ -- | The input settings+ InputSettings ->+ -- | The expected type of the expression+ Expr Src Void ->+ -- | The expression to check+ Expr Src Void ->+ m ()+checkWithSettings settings type_ expression = do+ let suffix = Dhall.Pretty.Internal.prettyToStrictText type_++ let annotated = case expression of+ Note (Src begin end bytes) _ ->+ Note (Src begin end bytes') (Annot expression type_)+ where+ bytes' = bytes <> " : " <> suffix+ _ ->+ Annot expression type_++ typecheckWithSettings settings annotated++{-| Type-check an expression against a `Decoder`'s expected type, using the+ supplied `InputSettings`.+ This is equivalent of using the 'expected' type of a @Decoder@ as the second+ argument to 'checkWithSettings'.+-}+expectWithSettings :: MonadThrow m => InputSettings -> Decoder a -> Expr Src Void -> m ()+expectWithSettings settings Decoder{..} expression = do+ expected' <- case expected of+ Success x -> return x+ Failure e -> throwM e++ checkWithSettings settings expected' expression++{-| Resolve an expression, using the supplied `InputSettings`++ Note that this also applies any substitutions specified in the+ `InputSettings`+-}+resolveWithSettings :: InputSettings -> Expr Src Import -> IO (Expr Src Void)+resolveWithSettings settings expression =+ fst <$> resolveAndStatusWithSettings settings expression++-- | A version of 'resolveWithSettings' that also returns the import 'Status'+-- together with the resolved expression.+resolveAndStatusWithSettings+ :: InputSettings+ -> Expr Src Import+ -> IO (Expr Src Void, Status)+resolveAndStatusWithSettings settings expression = do+ let InputSettings{..} = settings++ let EvaluateSettings{..} = _evaluateSettings++ let transform =+ Lens.set Dhall.Import.substitutions _substitutions+ . Lens.set Dhall.Import.normalizer _normalizer+ . Lens.set Dhall.Import.startingContext _startingContext++ let status = transform (Dhall.Import.emptyStatusWithManager _newManager _rootDirectory)++ (resolved, status') <- State.runStateT (Dhall.Import.loadWith expression) status++ let substituted = Dhall.Substitution.substitute resolved (view substitutions settings)++ pure (substituted, status')++-- | Normalize an expression, using the supplied `InputSettings`+normalizeWithSettings :: InputSettings -> Expr Src Void -> Expr Src Void+normalizeWithSettings settings =+ Core.normalizeWith (view normalizer settings)++{-| Type-check and evaluate a Dhall program, decoding the result into Haskell++ The first argument determines the type of value that you decode:++>>> input integer "+2"+2+>>> input (vector double) "[1.0, 2.0]"+[1.0,2.0]++ Use `auto` to automatically select which type to decode based on the+ inferred return type:++>>> input auto "True" :: IO Bool+True++ This uses the settings from 'defaultInputSettings'.+-}+input+ :: Decoder a+ -- ^ The decoder for the Dhall value+ -> Text+ -- ^ The Dhall program+ -> IO a+ -- ^ The decoded value in Haskell+input =+ inputWithSettings defaultInputSettings++{-| Extend 'input' with a root directory to resolve imports relative+ to, a file to mention in errors as the source, a custom typing+ context, and a custom normalization process.++@since 1.16+-}+inputWithSettings+ :: InputSettings+ -> Decoder a+ -- ^ The decoder for the Dhall value+ -> Text+ -- ^ The Dhall program+ -> IO a+ -- ^ The decoded value in Haskell+inputWithSettings settings decoder@Decoder{..} text = do+ parsed <- parseWithSettings settings text++ resolved <- resolveWithSettings settings parsed++ expectWithSettings settings decoder resolved++ let normalized = normalizeWithSettings settings resolved++ case extract normalized of+ Success x -> return x+ Failure e -> Control.Exception.throwIO e++{-| Type-check and evaluate a Dhall program that is read from the+ file-system.++ This uses the settings from 'defaultEvaluateSettings'.++ @since 1.16+-}+inputFile+ :: Decoder a+ -- ^ The decoder for the Dhall value+ -> FilePath+ -- ^ The path to the Dhall program.+ -> IO a+ -- ^ The decoded value in Haskell.+inputFile =+ inputFileWithSettings defaultEvaluateSettings++{-| Extend 'inputFile' with a custom typing context and a custom+ normalization process.++@since 1.16+-}+inputFileWithSettings+ :: EvaluateSettings+ -> Decoder a+ -- ^ The decoder for the Dhall value+ -> FilePath+ -- ^ The path to the Dhall program.+ -> IO a+ -- ^ The decoded value in Haskell.+inputFileWithSettings settings ty path = do+ text <- Data.Text.IO.readFile path+ let inputSettings = InputSettings+ { _rootDirectory = takeDirectory path+ , _sourceName = path+ , _evaluateSettings = settings+ }+ inputWithSettings inputSettings ty text++{-| Similar to `input`, but without interpreting the Dhall `Expr` into a Haskell+ type.++ Uses the settings from 'defaultInputSettings'.+-}+inputExpr+ :: Text+ -- ^ The Dhall program+ -> IO (Expr Src Void)+ -- ^ The fully normalized AST+inputExpr =+ inputExprWithSettings defaultInputSettings++{-| Extend 'inputExpr' with a root directory to resolve imports relative+ to, a file to mention in errors as the source, a custom typing+ context, and a custom normalization process.++@since 1.16+-}+inputExprWithSettings+ :: InputSettings+ -> Text+ -- ^ The Dhall program+ -> IO (Expr Src Void)+ -- ^ The fully normalized AST+inputExprWithSettings settings text = do+ parsed <- parseWithSettings settings text++ resolved <- resolveWithSettings settings parsed++ _ <- typecheckWithSettings settings resolved++ pure (Core.normalizeWith (view normalizer settings) resolved)++{-| Interpret a Dhall Expression++ This takes care of import resolution, type-checking, and normalization+-}+interpretExpr :: Expr Src Import -> IO (Expr Src Void)+interpretExpr = interpretExprWithSettings defaultInputSettings++-- | Like `interpretExpr`, but customizable using `InputSettings`+interpretExprWithSettings+ :: InputSettings -> Expr Src Import -> IO (Expr Src Void)+interpretExprWithSettings settings parsed = do+ resolved <- resolveWithSettings settings parsed++ typecheckWithSettings settings resolved++ pure (Core.normalizeWith (view normalizer settings) resolved)++{- | Decode a Dhall expression++ This takes care of import resolution, type-checking and normalization+-}+fromExpr :: Decoder a -> Expr Src Import -> IO a+fromExpr = fromExprWithSettings defaultInputSettings++-- | Like `fromExpr`, but customizable using `InputSettings`+fromExprWithSettings :: InputSettings -> Decoder a -> Expr Src Import -> IO a+fromExprWithSettings settings decoder@Decoder{..} expression = do+ resolved <- resolveWithSettings settings expression++ expectWithSettings settings decoder resolved++ let normalized = Core.normalizeWith (view normalizer settings) resolved++ case extract normalized of+ Success x -> return x+ Failure e -> Control.Exception.throwIO e++-- | Use this function to extract Haskell values directly from Dhall AST.+-- The intended use case is to allow easy extraction of Dhall values for+-- making the function `Core.normalizeWith` easier to use.+--+-- For other use cases, use `input` from "Dhall" module. It will give you+-- a much better user experience.+rawInput+ :: Alternative f+ => Decoder a+ -- ^ The decoder for the Dhall value+ -> Expr s Void+ -- ^ a closed form Dhall program, which evaluates to the expected type+ -> f a+ -- ^ The decoded value in Haskell+rawInput (Decoder {..}) expr =+ case extract (Core.normalize expr) of+ Success x -> pure x+ Failure _e -> empty++{-| Use this to provide more detailed error messages++>> input auto "True" :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> True : Integer+>+> (input):1:1++>> detailed (input auto "True") :: IO Integer+> *** Exception: Error: Expression doesn't match annotation+>+> Explanation: You can annotate an expression with its type or kind using the+> ❰:❱ symbol, like this:+>+>+> ┌───────┐+> │ x : t │ ❰x❱ is an expression and ❰t❱ is the annotated type or kind of ❰x❱+> └───────┘+>+> The type checker verifies that the expression's type or kind matches the+> provided annotation+>+> For example, all of the following are valid annotations that the type checker+> accepts:+>+>+> ┌─────────────┐+> │ 1 : Natural │ ❰1❱ is an expression that has type ❰Natural❱, so the type+> └─────────────┘ checker accepts the annotation+>+>+> ┌───────────────────────┐+> │ Natural/even 2 : Bool │ ❰Natural/even 2❱ has type ❰Bool❱, so the type+> └───────────────────────┘ checker accepts the annotation+>+>+> ┌────────────────────┐+> │ List : Type → Type │ ❰List❱ is an expression that has kind ❰Type → Type❱,+> └────────────────────┘ so the type checker accepts the annotation+>+>+> ┌──────────────────┐+> │ List Text : Type │ ❰List Text❱ is an expression that has kind ❰Type❱, so+> └──────────────────┘ the type checker accepts the annotation+>+>+> However, the following annotations are not valid and the type checker will+> reject them:+>+>+> ┌──────────┐+> │ 1 : Text │ The type checker rejects this because ❰1❱ does not have type+> └──────────┘ ❰Text❱+>+>+> ┌─────────────┐+> │ List : Type │ ❰List❱ does not have kind ❰Type❱+> └─────────────┘+>+>+> You or the interpreter annotated this expression:+>+> ↳ True+>+> ... with this type or kind:+>+> ↳ Integer+>+> ... but the inferred type or kind of the expression is actually:+>+> ↳ Bool+>+> Some common reasons why you might get this error:+>+> ● The Haskell Dhall interpreter implicitly inserts a top-level annotation+> matching the expected type+>+> For example, if you run the following Haskell code:+>+>+> ┌───────────────────────────────┐+> │ >>> input auto "1" :: IO Text │+> └───────────────────────────────┘+>+>+> ... then the interpreter will actually type check the following annotated+> expression:+>+>+> ┌──────────┐+> │ 1 : Text │+> └──────────┘+>+>+> ... and then type-checking will fail+>+> ────────────────────────────────────────────────────────────────────────────────+>+> True : Integer+>+> (input):1:1++-}+detailed :: IO a -> IO a+detailed =+ Control.Exception.handle handler1 . Control.Exception.handle handler0+ where+ handler0 :: Imported (TypeError Src Void) -> IO a+ handler0 (Imported ps e) =+ Control.Exception.throwIO (Imported ps (DetailedTypeError e))++ handler1 :: TypeError Src Void -> IO a+ handler1 e = Control.Exception.throwIO (DetailedTypeError e)
@@ -13,15 +13,11 @@ -} module Dhall.Binary- ( -- * Standard versions- StandardVersion(..)- , renderStandardVersion-- -- * Encoding and decoding- , encodeExpression+ ( -- * Encoding and decoding+ encodeExpression , decodeExpression - -- * Exceptions+ -- * Exceptions , DecodingFailure(..) ) where @@ -51,61 +47,33 @@ , Scheme (..) , URL (..) , Var (..)+ , WithComponent (..) ) import Data.Foldable (toList)-import Data.Text (Text)+import Data.Ratio ((%)) import Data.Void (Void, absurd) import GHC.Float (double2Float, float2Double) import Numeric.Half (fromHalf, toHalf)+import Prelude hiding (exponent) import qualified Codec.CBOR.ByteArray import qualified Codec.CBOR.Decoding as Decoding import qualified Codec.CBOR.Encoding as Encoding import qualified Codec.CBOR.Read as Read import qualified Codec.Serialise as Serialise-import qualified Data.ByteArray import qualified Data.ByteString import qualified Data.ByteString.Lazy import qualified Data.ByteString.Short import qualified Data.Foldable as Foldable import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Sequence+import qualified Data.Time as Time import qualified Dhall.Crypto import qualified Dhall.Map-import qualified Dhall.Set import qualified Dhall.Syntax as Syntax import qualified Text.Printf as Printf -{-| Supported version strings-- This exists primarily for backwards compatibility for expressions encoded- before Dhall removed version tags from the binary encoding--}-data StandardVersion- = NoVersion- -- ^ No version string- | V_5_0_0- -- ^ Version "5.0.0"- | V_4_0_0- -- ^ Version "4.0.0"- | V_3_0_0- -- ^ Version "3.0.0"- | V_2_0_0- -- ^ Version "2.0.0"- | V_1_0_0- -- ^ Version "1.0.0"- deriving (Enum, Bounded)---- | Render a `StandardVersion` as `Data.Text.Text`-renderStandardVersion :: StandardVersion -> Text-renderStandardVersion NoVersion = "none"-renderStandardVersion V_1_0_0 = "1.0.0"-renderStandardVersion V_2_0_0 = "2.0.0"-renderStandardVersion V_3_0_0 = "3.0.0"-renderStandardVersion V_4_0_0 = "4.0.0"-renderStandardVersion V_5_0_0 = "5.0.0"- {-| Convert a function applied to multiple arguments to the base function and the list of arguments -}@@ -168,20 +136,26 @@ case Data.ByteString.Short.length sb of 4 | sb == "Bool" -> return Bool+ | sb == "Date" -> return Date | sb == "List" -> return List | sb == "None" -> return None | sb == "Text" -> return Text+ | sb == "Time" -> return Time | sb == "Type" -> return (Const Type) | sb == "Kind" -> return (Const Kind) | sb == "Sort" -> return (Const Sort)+ 5 | sb == "Bytes" -> return Bytes 6 | sb == "Double" -> return Double 7 | sb == "Integer" -> return Integer | sb == "Natural" -> return Natural 8 | sb == "Optional" -> return Optional- 9 | sb == "List/fold" -> return ListFold+ | sb == "TimeZone" -> return TimeZone+ 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 10 | sb == "List/build" -> return ListBuild 11 | sb == "Double/show" -> return DoubleShow | sb == "List/length" -> return ListLength@@ -195,6 +169,7 @@ | sb == "Text/replace" -> return TextReplace 13 | sb == "Integer/clamp" -> return IntegerClamp | sb == "Natural/build" -> return NaturalBuild+ | sb == "TimeZone/show" -> return TimeZoneShow 14 | sb == "Integer/negate" -> return IntegerNegate | sb == "Natural/isZero" -> return NaturalIsZero 16 | sb == "Integer/toDouble" -> return IntegerToDouble@@ -261,7 +236,7 @@ b <- go - return (Lam (Syntax.makeFunctionBinding "_" _A) b)+ return (Lam mempty (Syntax.makeFunctionBinding "_" _A) b) 4 -> do x <- Decoding.decodeString@@ -274,7 +249,7 @@ b <- go - return (Lam (Syntax.makeFunctionBinding x _A) b)+ return (Lam mempty (Syntax.makeFunctionBinding x _A) b) _ -> die ("Incorrect number of tokens used to encode a λ expression: " <> show len)@@ -286,7 +261,7 @@ _B <- go - return (Pi "_" _A _B)+ return (Pi mempty "_" _A _B) 4 -> do x <- Decoding.decodeString@@ -299,7 +274,7 @@ _B <- go - return (Pi x _A _B)+ return (Pi mempty x _A _B) _ -> die ("Incorrect number of tokens used to encode a ∀ expression: " <> show len)@@ -316,11 +291,11 @@ 5 -> return NaturalTimes 6 -> return TextAppend 7 -> return ListAppend- 8 -> return (Combine Nothing)- 9 -> return (Prefer PreferFromSource)- 10 -> return CombineTypes+ 8 -> return (Combine mempty Nothing)+ 9 -> return (Prefer mempty PreferFromSource)+ 10 -> return (CombineTypes mempty) 11 -> return ImportAlt- 12 -> return Equivalent+ 12 -> return (Equivalent mempty) 13 -> return RecordCompletion _ -> die ("Unrecognized operator code: " <> show opcode) @@ -415,7 +390,7 @@ TypeString -> do x <- Decoding.decodeString- return (Left (Dhall.Set.fromList [x]))+ return (Left [x]) _ -> die ("Unexpected token type for projection: " <> show tokenType₂)@@ -423,7 +398,7 @@ _ -> do xs <- replicateDecoder (len - 2) Decoding.decodeString - return (Left (Dhall.Set.fromList xs))+ return (Left xs) return (Project t xs) @@ -589,8 +564,19 @@ n <- Decoding.decodeListLen - ks₀ <- replicateDecoder n Decoding.decodeString+ let decodeWithComponent = do+ tokenType₂ <- Decoding.peekTokenType+ case tokenType₂ of+ TypeString -> do+ fmap WithLabel Decoding.decodeString+ _ -> do+ m <- Decoding.decodeInt + case m of+ 0 -> return WithQuestion+ _ -> die ("Unexpected integer encoding a with expression: " <> show n)+ ks₀ <- replicateDecoder n decodeWithComponent+ ks₁ <- case NonEmpty.nonEmpty ks₀ of Nothing -> die "0 field labels in decoded with expression"@@ -601,6 +587,82 @@ return (With l ks₁ r) + 30 -> do+ _YYYY <- Decoding.decodeInt+ _MM <- Decoding.decodeInt+ _HH <- Decoding.decodeInt++ case Time.fromGregorianValid (fromIntegral _YYYY) _MM _HH of+ Nothing ->+ die "Invalid date"+ Just day ->+ return (DateLiteral day)+ 31 -> do+ hh <- Decoding.decodeInt+ mm <- Decoding.decodeInt+ tag₂ <- Decoding.decodeTag++ case tag₂ of+ 4 -> do+ return ()+ _ -> do+ die ("Unexpected tag for decimal fraction: " <> show tag)+ n <- Decoding.decodeListLen++ case n of+ 2 -> do+ return ()+ _ -> do+ die ("Invalid list length for decimal fraction: " <> show n)++ exponent <- Decoding.decodeInt++ tokenType₂ <- Decoding.peekTokenType++ mantissa <- case tokenType₂ of+ TypeUInt -> do+ fromIntegral <$> Decoding.decodeWord++ TypeUInt64 -> do+ fromIntegral <$> Decoding.decodeWord64++ TypeNInt -> do+ !i <- fromIntegral <$> Decoding.decodeNegWord++ return (-1 - i)++ TypeNInt64 -> do+ !i <- fromIntegral <$> Decoding.decodeNegWord64++ return (-1 - i)+ TypeInteger -> do+ Decoding.decodeInteger+ _ ->+ die ("Unexpected token type for mantissa: " <> show tokenType₂)+ let precision = fromIntegral (negate exponent)++ let ss = fromRational (mantissa % (10 ^ precision))++ return (TimeLiteral (Time.TimeOfDay hh mm ss) precision)+ 32 -> do+ b <- Decoding.decodeBool+ _HH <- Decoding.decodeInt+ _MM <- Decoding.decodeInt++ let sign = if b then id else negate++ let minutes = sign (_HH * 60 + _MM)++ return (TimeZoneLiteral (Time.TimeZone minutes False ""))++ 33 -> do+ b <- Decoding.decodeBytes++ return (BytesLit b)++ 34 -> do+ t <- go+ return (ShowConstructor t) _ -> die ("Unexpected tag: " <> show tag) @@ -685,6 +747,9 @@ Bool -> Encoding.encodeUtf8ByteArray "Bool" + Bytes ->+ Encoding.encodeUtf8ByteArray "Bytes"+ Optional -> Encoding.encodeUtf8ByteArray "Optional" @@ -709,6 +774,24 @@ TextShow -> Encoding.encodeUtf8ByteArray "Text/show" + Date ->+ Encoding.encodeUtf8ByteArray "Date"++ DateShow ->+ Encoding.encodeUtf8ByteArray "Date/show"++ Time ->+ Encoding.encodeUtf8ByteArray "Time"++ TimeShow ->+ Encoding.encodeUtf8ByteArray "Time/show"++ TimeZone ->+ Encoding.encodeUtf8ByteArray "TimeZone"++ TimeZoneShow ->+ Encoding.encodeUtf8ByteArray "TimeZone/show"+ List -> Encoding.encodeUtf8ByteArray "List" @@ -731,26 +814,26 @@ where (function, arguments) = unApply a - Lam (FunctionBinding { functionBindingVariable = "_", functionBindingAnnotation = _A }) b ->+ Lam _ (FunctionBinding { functionBindingVariable = "_", functionBindingAnnotation = _A }) b -> encodeList3 (Encoding.encodeInt 1) (go _A) (go b) - Lam (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+ Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b -> encodeList4 (Encoding.encodeInt 1) (Encoding.encodeString x) (go _A) (go b) - Pi "_" _A _B ->+ Pi _ "_" _A _B -> encodeList3 (Encoding.encodeInt 2) (go _A) (go _B) - Pi x _A _B ->+ Pi _ x _A _B -> encodeList4 (Encoding.encodeInt 2) (Encoding.encodeString x)@@ -769,6 +852,11 @@ BoolNE l r -> encodeOperator 3 l r + BytesLit b ->+ encodeList2+ (Encoding.encodeInt 33)+ (Encoding.encodeBytes b)+ NaturalPlus l r -> encodeOperator 4 l r @@ -781,19 +869,19 @@ ListAppend l r -> encodeOperator 7 l r - Combine _ l r ->+ Combine _ _ l r -> encodeOperator 8 l r - Prefer _ l r ->+ Prefer _ _ l r -> encodeOperator 9 l r - CombineTypes l r ->+ CombineTypes _ l r -> encodeOperator 10 l r ImportAlt l r -> encodeOperator 11 l r - Equivalent l r ->+ Equivalent _ l r -> encodeOperator 12 l r RecordCompletion l r ->@@ -852,10 +940,10 @@ Project t (Left xs) -> encodeListN- (2 + Dhall.Set.size xs)+ (2 + length xs) ( Encoding.encodeInt 10 : go t- : map Encoding.encodeString (Dhall.Set.toList xs)+ : map Encoding.encodeString xs ) Project t (Right _T) ->@@ -968,9 +1056,60 @@ encodeList4 (Encoding.encodeInt 29) (go l)- (encodeList (fmap Encoding.encodeString ks))+ (encodeList (fmap encodeWithComponent ks)) (go r)+ where+ encodeWithComponent WithQuestion = Encoding.encodeInt 0+ encodeWithComponent (WithLabel k ) = Encoding.encodeString k + DateLiteral day ->+ encodeList4+ (Encoding.encodeInt 30)+ (Encoding.encodeInt (fromInteger _YYYY))+ (Encoding.encodeInt _MM)+ (Encoding.encodeInt _DD)+ where+ (_YYYY, _MM, _DD) = Time.toGregorian day++ TimeLiteral (Time.TimeOfDay hh mm ss) precision ->+ encodeList4+ (Encoding.encodeInt 31)+ (Encoding.encodeInt hh)+ (Encoding.encodeInt mm)+ ( Encoding.encodeTag 4+ <> encodeList2+ (Encoding.encodeInt exponent)+ encodedMantissa+ )+ where+ exponent = negate (fromIntegral precision)++ mantissa :: Integer+ mantissa = truncate (ss * 10 ^ precision)++ encodedMantissa+ | fromIntegral (minBound :: Int) <= mantissa+ && mantissa <= fromIntegral (maxBound :: Int) =+ Encoding.encodeInt (fromInteger mantissa)+ | otherwise =+ Encoding.encodeInteger mantissa++ TimeZoneLiteral (Time.TimeZone minutes _ _) ->+ encodeList4+ (Encoding.encodeInt 32)+ (Encoding.encodeBool sign)+ (Encoding.encodeInt _HH)+ (Encoding.encodeInt _MM)+ where+ sign = 0 <= minutes++ (_HH, _MM) = abs minutes `divMod` 60++ ShowConstructor t ->+ encodeList2+ (Encoding.encodeInt 34)+ (go t)+ Note _ b -> go b @@ -1045,6 +1184,7 @@ 0 -> return Code 1 -> return RawText 2 -> return Location+ 3 -> return RawBytes _ -> die ("Unexpected code for import mode: " <> show m) let remote scheme = do@@ -1181,9 +1321,13 @@ Encoding.encodeNull Just digest ->- Encoding.encodeBytes ("\x12\x20" <> Data.ByteArray.convert digest)+ Encoding.encodeBytes ("\x12\x20" <> Dhall.Crypto.unSHA256Digest digest) - m = Encoding.encodeInt (case importMode of Code -> 0; RawText -> 1; Location -> 2;)+ m = Encoding.encodeInt (case importMode of+ Code -> 0+ RawText -> 1+ Location -> 2+ RawBytes -> 3 ) Import{..} = import_
@@ -31,6 +31,7 @@ , makeFunctionBinding , FieldSelection (..) , makeFieldSelection+ , WithComponent (..) , Expr(..) -- * Normalization@@ -56,6 +57,7 @@ -- * Optics , subExpressions+ , subExpressionsWith , chunkExprs , bindingExprs , recordFieldExprs@@ -75,24 +77,22 @@ , Eval.textShow , censorExpression , censorText- , Syntax.desugarWith ) where -import Control.Exception (Exception)-import Control.Monad.IO.Class (MonadIO (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty)+import Control.Exception (Exception)+import Control.Monad.IO.Class (MonadIO (..))+import Data.Text (Text) import Dhall.Normalize import Dhall.Pretty.Internal-import Dhall.Src (Src (..))+import Dhall.Src (Src (..)) import Dhall.Syntax-import Instances.TH.Lift ()-import Lens.Family (over)+import Instances.TH.Lift ()+import Lens.Micro (over)+import Prettyprinter (Pretty) import qualified Control.Exception import qualified Data.Text import qualified Dhall.Eval as Eval-import qualified Dhall.Syntax as Syntax -- | Pretty-print a value pretty :: Pretty a => a -> Text@@ -142,6 +142,7 @@ throws :: (Exception e, MonadIO io) => Either e a -> io a throws (Left e) = liftIO (Control.Exception.throwIO e) throws (Right r) = return r+{-# INLINABLE throws #-} {- $setup >>> import qualified Codec.Serialise
@@ -1,7 +1,6 @@ {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE ViewPatterns #-} {-| This module provides functionality for concisely displaying the difference@@ -16,17 +17,16 @@ , diff ) where -import Data.Foldable (fold, toList)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Monoid (Any (..))-import Data.Sequence (Seq)-import Data.String (IsString (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Void (Void)-import Dhall.Map (Map)-import Dhall.Pretty.Internal (Ann)-import Dhall.Set (Set)+import Data.ByteString (ByteString)+import Data.Foldable (fold, toList)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Monoid (Any (..))+import Data.Sequence (Seq)+import Data.String (IsString (..))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Map (Map)+import Dhall.Pretty.Internal (Ann) import Dhall.Syntax ( Binding (..) , Chunks (..)@@ -36,19 +36,21 @@ , FunctionBinding (..) , RecordField (..) , Var (..)+ , WithComponent (..) )-import Numeric.Natural (Natural)+import Numeric.Natural (Natural)+import Prettyprinter (Doc, Pretty) -import qualified Data.Algorithm.Diff as Algo.Diff+import qualified Data.Algorithm.Diff as Algo.Diff import qualified Data.List.NonEmpty import qualified Data.Set import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc as Pretty+import qualified Data.Time as Time import qualified Dhall.Map-import qualified Dhall.Normalize as Normalize-import qualified Dhall.Pretty.Internal as Internal-import qualified Dhall.Set-import qualified Dhall.Syntax as Syntax+import qualified Dhall.Normalize as Normalize+import qualified Dhall.Pretty.Internal as Internal+import qualified Dhall.Syntax as Syntax+import qualified Prettyprinter as Pretty {-| This type is a `Doc` enriched with a `same` flag to efficiently track if any difference was detected@@ -123,8 +125,8 @@ equals :: Diff equals = token Internal.equals -forall :: Diff-forall = token (Internal.forall Internal.Unicode)+forall_ :: Diff+forall_ = token (Internal.forall_ Internal.Unicode) lambda :: Diff lambda = token (Internal.lambda Internal.Unicode)@@ -174,20 +176,21 @@ diffLabel :: Text -> Text -> Diff diffLabel = diffPrimitive (token . Internal.prettyLabel) -diffLabels :: Set Text -> Set Text -> Diff+diffLabels :: [Text] -> [Text] -> Diff diffLabels ksL ksR = braced (diffFieldNames <> (if anyEqual then [ ignore ] else [])) where- extraL = Dhall.Set.difference ksL ksR- extraR = Dhall.Set.difference ksR ksL+ setL = Data.Set.fromList ksL+ setR = Data.Set.fromList ksR + extraL = Data.Set.difference setL setR+ extraR = Data.Set.difference setR setL+ diffFieldNames = foldMap (adapt minus) extraL <> foldMap (adapt plus) extraR where adapt sign key = [ sign (token (Internal.prettyLabel key)) ] - anyEqual = not (Data.Set.null (Data.Set.intersection- (Dhall.Set.toSet ksL)- (Dhall.Set.toSet ksR)))+ anyEqual = not (Data.Set.null (Data.Set.intersection setL setR)) diffNatural :: Natural -> Natural -> Diff diffNatural = diffPrimitive (token . Internal.prettyNatural)@@ -195,6 +198,22 @@ diffDouble :: DhallDouble -> DhallDouble -> Diff diffDouble = diffPrimitive (token . Internal.prettyDouble . getDhallDouble) +diffDateLiteral :: Time.Day -> Time.Day -> Diff+diffDateLiteral =+ diffPrimitive (token . Internal.prettyExpr @(Expr Void Void) . DateLiteral)++diffTimeLiteral :: Time.TimeOfDay -> Word -> Time.TimeOfDay -> Word -> Diff+diffTimeLiteral tL pL tR pR =+ diffPrimitive+ (token . Internal.prettyExpr @(Expr Void Void) . uncurry TimeLiteral)+ (tL, pL)+ (tR, pR)++diffTimeZoneLiteral :: Time.TimeZone -> Time.TimeZone -> Diff+diffTimeZoneLiteral =+ diffPrimitive+ (token . Internal.prettyExpr @(Expr Void Void) . TimeZoneLiteral)+ diffConst :: Const -> Const -> Diff diffConst = diffPrimitive (token . Internal.prettyConst) @@ -357,7 +376,7 @@ diffTextSkeleton = difference textSkeleton textSkeleton - chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR) + chunks = zipWith chunkDiff (toEitherList cL) (toEitherList cR) chunkDiff a b = case (a, b) of@@ -365,6 +384,10 @@ (Right x, Right y) -> diff x y _ -> diffTextSkeleton +diffBytes :: ByteString -> ByteString -> Diff+diffBytes l r =+ "0x" <> diffText (Internal.prettyBase16 l) (Internal.prettyBase16 r)+ diffList :: (Eq a, Pretty a) => Seq (Expr Void a) -> Seq (Expr Void a) -> Diff@@ -514,6 +537,10 @@ <> keyword "else" <> " " <> ignore+skeleton (BytesLit {}) =+ "0x\""+ <> ignore+ <> "\"" skeleton (NaturalPlus {}) = ignore <> " "@@ -619,6 +646,10 @@ keyword "toMap" <> " " <> ignore+skeleton (ShowConstructor {}) =+ keyword "showConstructor"+ <> " "+ <> ignore skeleton (Field {}) = ignore <> dot@@ -648,8 +679,8 @@ enclosed' " " (rarrow <> " ") (docs l r) where docs- (Lam (FunctionBinding { functionBindingVariable = aL, functionBindingAnnotation = bL }) cL)- (Lam (FunctionBinding { functionBindingVariable = aR, functionBindingAnnotation = bR }) cR) =+ (Lam _ (FunctionBinding { functionBindingVariable = aL, functionBindingAnnotation = bL }) cL)+ (Lam _ (FunctionBinding { functionBindingVariable = aR, functionBindingAnnotation = bR }) cR) = Data.List.NonEmpty.cons (align doc) (docs cL cR) where doc = lambda@@ -708,14 +739,14 @@ diff l@(Pi {}) r@(Pi {}) = enclosed' " " (rarrow <> " ") (docs l r) where- docs (Pi aL bL cL) (Pi aR bR cR) =+ docs (Pi _ aL bL cL) (Pi _ aR bR cR) = Data.List.NonEmpty.cons (align doc) (docs cL cR) where doc | same docA && same docB = ignore | same docA = format mempty docB | otherwise =- forall+ forall_ <> lparen <> format " " docA <> colon@@ -766,6 +797,15 @@ mismatch l r diffAnnotatedExpression l r@(ToMap {}) = mismatch l r+diffAnnotatedExpression (ShowConstructor aL) (ShowConstructor aR) = align doc+ where+ doc = keyword "showConstructor"+ <> " "+ <> format " " (diffWithExpression aL aR)+diffAnnotatedExpression l@(ShowConstructor {}) r =+ mismatch l r+diffAnnotatedExpression l r@(ShowConstructor {}) =+ mismatch l r diffAnnotatedExpression (ListLit aL@(Just _) bL) (ListLit aR bR) = align doc where doc = format " " (diffList bL bR)@@ -902,7 +942,7 @@ diffCombineExpression l@(Combine {}) r@(Combine {}) = enclosed' " " (operator "∧" <> " ") (docs l r) where- docs (Combine _ aL bL) (Combine _ aR bR) =+ docs (Combine _ _ aL bL) (Combine _ _ aR bR) = Data.List.NonEmpty.cons (diffPreferExpression aL aR) (docs bL bR) docs aL aR = pure (diffPreferExpression aL aR)@@ -917,7 +957,7 @@ diffPreferExpression l@(Prefer {}) r@(Prefer {}) = enclosed' " " (operator "⫽" <> " ") (docs l r) where- docs (Prefer _ aL bL) (Prefer _ aR bR) =+ docs (Prefer _ _ aL bL) (Prefer _ _ aR bR) = Data.List.NonEmpty.cons (diffCombineTypesExpression aL aR) (docs bL bR) docs aL aR = pure (diffCombineTypesExpression aL aR)@@ -932,7 +972,7 @@ diffCombineTypesExpression l@(CombineTypes {}) r@(CombineTypes {}) = enclosed' " " (operator "*" <> " ") (docs l r) where- docs (CombineTypes aL bL) (CombineTypes aR bR) =+ docs (CombineTypes _ aL bL) (CombineTypes _ aR bR) = Data.List.NonEmpty.cons (diffTimesExpression aL aR) (docs bL bR) docs aL aR = pure (diffTimesExpression aL aR)@@ -993,7 +1033,7 @@ diffEquivalentExpression l@(Equivalent {}) r@(Equivalent {}) = enclosed' " " (operator "≡" <> " ") (docs l r) where- docs (Equivalent aL bL) (Equivalent aR bR) =+ docs (Equivalent _ aL bL) (Equivalent _ aR bR) = Data.List.NonEmpty.cons (diffApplicationExpression aL aR) (docs bL bR) docs aL aR = pure (diffApplicationExpression aL aR)@@ -1037,12 +1077,15 @@ ( format " " (diffImportExpression eL eR) <> "with " <> align- ( format " " (diffPath ksL ksR)+ ( format " " (diffPath (fmap toText ksL) (fmap toText ksR)) <> "= " <> diffOperatorExpression vL vR ) ) where+ toText WithQuestion = "?"+ toText (WithLabel k ) = k+ diffPath (kL :| []) (kR :| []) = diffLabel kL kR diffPath (kL₀ :| kL₁ : ksL') (kR₀ :| kR₁ : ksR') =@@ -1135,6 +1178,18 @@ mismatch l r diffPrimitiveExpression l r@Bool = mismatch l r+diffPrimitiveExpression Bytes Bytes =+ "…"+diffPrimitiveExpression l@Bytes r =+ mismatch l r+diffPrimitiveExpression l r@Bytes =+ mismatch l r+diffPrimitiveExpression (BytesLit l) (BytesLit r) =+ diffBytes l r+diffPrimitiveExpression l@(BytesLit {}) r =+ mismatch l r+diffPrimitiveExpression l r@(BytesLit {}) =+ mismatch l r diffPrimitiveExpression Natural Natural = "…" diffPrimitiveExpression l@Natural r =@@ -1249,6 +1304,42 @@ mismatch l r diffPrimitiveExpression l r@TextShow = mismatch l r+diffPrimitiveExpression Date Date =+ "…"+diffPrimitiveExpression l r@Date =+ mismatch l r+diffPrimitiveExpression l@Date r=+ mismatch l r+diffPrimitiveExpression DateShow DateShow =+ "…"+diffPrimitiveExpression l r@DateShow =+ mismatch l r+diffPrimitiveExpression l@DateShow r=+ mismatch l r+diffPrimitiveExpression Time Time =+ "…"+diffPrimitiveExpression l r@Time =+ mismatch l r+diffPrimitiveExpression l@Time r=+ mismatch l r+diffPrimitiveExpression TimeShow TimeShow =+ "…"+diffPrimitiveExpression l r@TimeShow =+ mismatch l r+diffPrimitiveExpression l@TimeShow r=+ mismatch l r+diffPrimitiveExpression TimeZone TimeZone =+ "…"+diffPrimitiveExpression l r@TimeZone =+ mismatch l r+diffPrimitiveExpression l@TimeZone r=+ mismatch l r+diffPrimitiveExpression TimeZoneShow TimeZoneShow =+ "…"+diffPrimitiveExpression l r@TimeZoneShow =+ mismatch l r+diffPrimitiveExpression l@TimeZoneShow r=+ mismatch l r diffPrimitiveExpression List List = "…" diffPrimitiveExpression l@List r =@@ -1341,6 +1432,24 @@ diffPrimitiveExpression l@(TextLit {}) r = mismatch l r diffPrimitiveExpression l r@(TextLit {}) =+ mismatch l r+diffPrimitiveExpression (DateLiteral l) (DateLiteral r) =+ diffDateLiteral l r+diffPrimitiveExpression l@(DateLiteral {}) r =+ mismatch l r+diffPrimitiveExpression l r@(DateLiteral {}) =+ mismatch l r+diffPrimitiveExpression (TimeLiteral tL pL) (TimeLiteral tR pR) =+ diffTimeLiteral tL pL tR pR+diffPrimitiveExpression l@(TimeLiteral {}) r =+ mismatch l r+diffPrimitiveExpression l r@(TimeLiteral {}) =+ mismatch l r+diffPrimitiveExpression (TimeZoneLiteral l) (TimeZoneLiteral r) =+ diffTimeZoneLiteral l r+diffPrimitiveExpression l@(TimeZoneLiteral {}) r =+ mismatch l r+diffPrimitiveExpression l r@(TimeZoneLiteral {}) = mismatch l r diffPrimitiveExpression (Record aL) (Record aR) = diffRecord aL aR
@@ -1,31 +1,67 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE ViewPatterns #-} +{-# OPTIONS_GHC -Wno-orphans #-}+ -- | Implementation of the @dhall to-directory-tree@ subcommand module Dhall.DirectoryTree ( -- * Filesystem toDirectoryTree , FilesystemError(..)++ -- * Low-level types and functions+ , module Dhall.DirectoryTree.Types+ , decodeDirectoryTree+ , directoryTreeType ) where -import Control.Applicative (empty)-import Control.Exception (Exception)-import Data.Void (Void)-import Dhall.Syntax (Chunks (..), Expr (..), RecordField (..))-import System.FilePath ((</>))+import Control.Applicative (empty)+import Control.Exception (Exception)+import Control.Monad (unless, when)+import Data.Either.Validation (Validation (..))+import Data.Functor.Identity (Identity (..))+import Data.Maybe (fromMaybe, isJust)+import Data.Sequence (Seq)+import Data.Text (Text)+import Data.Void (Void)+import Dhall.DirectoryTree.Types+import Dhall.Marshal.Decode (Decoder (..), Expector)+import Dhall.Src (Src)+import Dhall.Syntax+ ( Chunks (..)+ , Const (..)+ , Expr (..)+ , RecordField (..)+ , Var (..)+ )+import System.FilePath ((</>))+import System.PosixCompat.Types (FileMode, GroupID, UserID) -import qualified Control.Exception as Exception-import qualified Data.Foldable as Foldable-import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Dhall.Map as Map+import qualified Control.Exception as Exception+import qualified Data.ByteString as ByteString+import qualified Data.Foldable as Foldable+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO+import qualified Dhall.Core as Core+import qualified Dhall.Map as Map+import qualified Dhall.Marshal.Decode as Decode import qualified Dhall.Pretty-import qualified Dhall.Util as Util-import qualified System.Directory as Directory-import qualified System.FilePath as FilePath+import qualified Dhall.TypeCheck as TypeCheck+import qualified Dhall.Util as Util+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.String as Pretty+import qualified System.Directory as Directory+import qualified System.FilePath as FilePath+#ifdef mingw32_HOST_OS+import System.IO.Error (illegalOperationErrorType, mkIOError)+#else+import qualified System.Posix.User as Posix+#endif+import qualified System.PosixCompat.Files as Posix {-| Attempt to transform a Dhall record into a directory tree where: @@ -37,6 +73,9 @@ * @Optional@ values are omitted if @None@ + * There is a more advanced way to construct directory trees using a fixpoint+ encoding. See the documentation below on that.+ For example, the following Dhall record: > { dir = { `hello.txt` = "Hello\n" }@@ -59,8 +98,7 @@ > Goodbye Use this in conjunction with the Prelude's support for rendering JSON/YAML- in "pure Dhall" so that you can generate files containing JSON. For- example:+ in "pure Dhall" so that you can generate files containing JSON. For example: > let JSON = > https://prelude.dhall-lang.org/v12.0.0/JSON/package.dhall sha256:843783d29e60b558c2de431ce1206ce34bdfde375fcf06de8ec5bf77092fdef7@@ -81,17 +119,69 @@ > ! "bar": null > ! "foo": "Hello" - This utility does not take care of type-checking and normalizing the- provided expression. This will raise a `FilesystemError` exception upon- encountering an expression that cannot be converted as-is.+ /Advanced construction of directory trees/++ In addition to the ways described above using "simple" Dhall values to+ construct the directory tree there is one based on a fixpoint encoding. It+ works by passing a value of the following type to the interpreter:++ > let User = < UserId : Natural | UserName : Text >+ >+ > let Group = < GroupId : Natural | GroupName : Text >+ >+ > let Access =+ > { execute : Optional Bool+ > , read : Optional Bool+ > , write : Optional Bool+ > }+ >+ > let Mode =+ > { user : Optional Access+ > , group : Optional Access+ > , other : Optional Access+ > }+ >+ > let Entry =+ > \(content : Type) ->+ > { name : Text+ > , content : content+ > , user : Optional User+ > , group : Optional Group+ > , mode : Optional Mode+ > }+ >+ > in forall (tree : Type) ->+ > forall ( make+ > : { directory : Entry (List tree) -> tree+ > , file : Entry Text -> tree+ > }+ > ) ->+ > List tree++ The fact that the metadata for filesystem entries is modeled after the POSIX+ permission model comes with the unfortunate downside that it might not apply+ to other systems: There, changes to the metadata (user, group, permissions)+ might be a no-op and __no warning will be issued__.+ This is a leaking abstraction of the+ [unix-compat](https://hackage.haskell.org/package/unix-compat) package used+ internally.++ __NOTE__: This utility does not take care of type-checking and normalizing+ the provided expression. This will raise a `FilesystemError` exception or a+ `Dhall.Marshal.Decode.DhallErrors` exception upon encountering an expression+ that cannot be converted as-is. -}-toDirectoryTree :: FilePath -> Expr Void Void -> IO ()-toDirectoryTree path expression = case expression of+toDirectoryTree+ :: Bool -- ^ Whether to allow path separators in file names or not+ -> FilePath+ -> Expr Void Void+ -> IO ()+toDirectoryTree allowSeparators path expression = case expression of RecordLit keyValues -> Map.unorderedTraverseWithKey_ process $ recordFieldValue <$> keyValues - ListLit (Just (Record [ ("mapKey", recordFieldValue -> Text), ("mapValue", _) ])) [] ->- return ()+ ListLit (Just (App List (Record [ ("mapKey", recordFieldValue -> Text), ("mapValue", _) ]))) [] ->+ Directory.createDirectoryIfMissing allowSeparators path ListLit _ records | not (null records)@@ -102,14 +192,22 @@ Text.IO.writeFile path text Some value ->- toDirectoryTree path value+ toDirectoryTree allowSeparators path value - App (Field (Union _) _) value ->- toDirectoryTree path value+ App (Field (Union _) _) value -> do+ toDirectoryTree allowSeparators path value App None _ -> return () + -- If this pattern matches we assume the user wants to use the fixpoint+ -- approach, hence we typecheck it and output error messages like we would+ -- do for every other Dhall program.+ Lam _ _ (Lam _ _ _) -> do+ entries <- decodeDirectoryTree expression++ processFilesystemEntryList allowSeparators path entries+ _ -> die where@@ -124,18 +222,209 @@ empty process key value = do- if Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key- then die- else return ()+ when (not allowSeparators && Text.isInfixOf (Text.pack [ FilePath.pathSeparator ]) key) $+ die - Directory.createDirectoryIfMissing False path+ Directory.createDirectoryIfMissing allowSeparators path - toDirectoryTree (path </> Text.unpack key) value+ toDirectoryTree allowSeparators (path </> Text.unpack key) value die = Exception.throwIO FilesystemError{..} where unexpectedExpression = expression +-- | Decode a fixpoint directory tree from a Dhall expression.+decodeDirectoryTree :: Expr s Void -> IO (Seq FilesystemEntry)+decodeDirectoryTree (Core.alphaNormalize . Core.denote -> expression@(Lam _ _ (Lam _ _ body))) = do+ expected' <- case directoryTreeType of+ Success x -> return x+ Failure e -> Exception.throwIO e++ _ <- Core.throws $ TypeCheck.typeOf $ Annot expression expected'++ case Decode.extract decoder body of+ Success x -> return x+ Failure e -> Exception.throwIO e+ where+ decoder :: Decoder (Seq FilesystemEntry)+ decoder = Decode.auto+decodeDirectoryTree expr = Exception.throwIO $ FilesystemError $ Core.denote expr++-- | The type of a fixpoint directory tree expression.+directoryTreeType :: Expector (Expr Src Void)+directoryTreeType = Pi Nothing "tree" (Const Type)+ <$> (Pi Nothing "make" <$> makeType <*> pure (App List (Var (V "tree" 0))))++-- | The type of make part of a fixpoint directory tree expression.+makeType :: Expector (Expr Src Void)+makeType = Record . Map.fromList <$> sequenceA+ [ makeConstructor "directory" (Decode.auto :: Decoder DirectoryEntry)+ , makeConstructor "file" (Decode.auto :: Decoder TextFileEntry)+ , makeConstructor "binary-file" (Decode.auto :: Decoder BinaryFileEntry)+ ]+ where+ makeConstructor :: Text -> Decoder b -> Expector (Text, RecordField Src Void)+ makeConstructor name dec = (name,) . Core.makeRecordField+ <$> (Pi Nothing "_" <$> expected dec <*> pure (Var (V "tree" 0)))++-- | Resolve a `User` to a numerical id.+getUser :: User -> IO UserID+getUser (UserId uid) = return uid+getUser (UserName name) =+#ifdef mingw32_HOST_OS+ ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+ where x = "System.Posix.User.getUserEntryForName: not supported"+#else+ Posix.userID <$> Posix.getUserEntryForName name+#endif++-- | Resolve a `Group` to a numerical id.+getGroup :: Group -> IO GroupID+getGroup (GroupId gid) = return gid+getGroup (GroupName name) =+#ifdef mingw32_HOST_OS+ ioError $ mkIOError illegalOperationErrorType x Nothing Nothing+ where x = "System.Posix.User.getGroupEntryForName: not supported"+#else+ Posix.groupID <$> Posix.getGroupEntryForName name+#endif++-- | Process a `FilesystemEntry`. Writes the content to disk and apply the+-- metadata to the newly created item.+processFilesystemEntry :: Bool -> FilePath -> FilesystemEntry -> IO ()+processFilesystemEntry allowSeparators path (DirectoryEntry entry) =+ processEntryWith path entry $ \path' content -> do+ Directory.createDirectoryIfMissing allowSeparators path'+ processFilesystemEntryList allowSeparators path' content+processFilesystemEntry allowSeparators path (BinaryFileEntry entry) =+ processEntryWith path entry $ \path' content -> do+ when allowSeparators $ do+ Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+ ByteString.writeFile path' content+processFilesystemEntry allowSeparators path (TextFileEntry entry) =+ processEntryWith path entry $ \path' content -> do+ when allowSeparators $ do+ Directory.createDirectoryIfMissing True (FilePath.takeDirectory path')+ Text.IO.writeFile path' content++-- | A helper function used by 'processFilesystemEntry'.+processEntryWith+ :: FilePath+ -> Entry a+ -> (FilePath -> a -> IO ())+ -> IO ()+processEntryWith path entry f = do+ let path' = path </> entryName entry+ when (hasMetadata entry && not isMetadataSupported) $+ Exception.throwIO (MetadataUnsupportedError path')+ f path' (entryContent entry)+ -- It is important that we write the metadata after we wrote the content of+ -- the file as we might lock ourself out by changing ownership or+ -- permissions.+ applyMetadata entry path'++-- | Process a list of `FilesystemEntry`s.+processFilesystemEntryList :: Bool -> FilePath -> Seq FilesystemEntry -> IO ()+processFilesystemEntryList allowSeparators path = Foldable.traverse_+ (processFilesystemEntry allowSeparators path)++-- | Does this entry have some metadata set?+hasMetadata :: Entry a -> Bool+hasMetadata entry+ = isJust (entryUser entry)+ || isJust (entryGroup entry)+ || maybe False hasMode (entryMode entry)+ where+ hasMode :: Mode Maybe -> Bool+ hasMode mode+ = maybe False hasAccess (modeUser mode)+ || maybe False hasAccess (modeGroup mode)+ || maybe False hasAccess (modeOther mode)++ hasAccess :: Access Maybe -> Bool+ hasAccess access+ = isJust (accessExecute access)+ || isJust (accessRead access)+ || isJust (accessWrite access)++-- | Set the metadata of an object referenced by a path.+applyMetadata :: Entry a -> FilePath -> IO ()+applyMetadata entry fp = do+ s <- Posix.getFileStatus fp+ let user = Posix.fileOwner s+ group = Posix.fileGroup s+ mode = fileModeToMode $ Posix.fileMode s++ user' <- getUser $ fromMaybe (UserId user) (entryUser entry)+ group' <- getGroup $ fromMaybe (GroupId group) (entryGroup entry)+ unless ((user', group') == (user, group)) $+ Posix.setOwnerAndGroup fp user' group'++ let mode' = maybe mode (updateModeWith mode) (entryMode entry)+ unless (mode' == mode) $+ setFileMode fp $ modeToFileMode mode'++-- | Calculate the new `Mode` from the current mode and the changes specified by+-- the user.+updateModeWith :: Mode Identity -> Mode Maybe -> Mode Identity+updateModeWith x y = Mode+ { modeUser = combine modeUser modeUser+ , modeGroup = combine modeGroup modeGroup+ , modeOther = combine modeOther modeOther+ }+ where+ combine f g = maybe (f x) (Identity . updateAccessWith (runIdentity $ f x)) (g y)++-- | Calculate the new `Access` from the current permissions and the changes+-- specified by the user.+updateAccessWith :: Access Identity -> Access Maybe -> Access Identity+updateAccessWith x y = Access+ { accessExecute = combine accessExecute accessExecute+ , accessRead = combine accessRead accessRead+ , accessWrite = combine accessWrite accessWrite+ }+ where+ combine f g = maybe (f x) Identity (g y)++-- | Convert a filesystem mode given as a bitmask (`FileMode`) to an ADT+-- (`Mode`).+fileModeToMode :: FileMode -> Mode Identity+fileModeToMode mode = Mode+ { modeUser = Identity $ Access+ { accessExecute = Identity $ mode `hasFileMode` Posix.ownerExecuteMode+ , accessRead = Identity $ mode `hasFileMode` Posix.ownerReadMode+ , accessWrite = Identity $ mode `hasFileMode` Posix.ownerReadMode+ }+ , modeGroup = Identity $ Access+ { accessExecute = Identity $ mode `hasFileMode` Posix.groupExecuteMode+ , accessRead = Identity $ mode `hasFileMode` Posix.groupReadMode+ , accessWrite = Identity $ mode `hasFileMode` Posix.groupReadMode+ }+ , modeOther = Identity $ Access+ { accessExecute = Identity $ mode `hasFileMode` Posix.otherExecuteMode+ , accessRead = Identity $ mode `hasFileMode` Posix.otherReadMode+ , accessWrite = Identity $ mode `hasFileMode` Posix.otherReadMode+ }+ }++-- | Convert a filesystem mode given as an ADT (`Mode`) to a bitmask+-- (`FileMode`).+modeToFileMode :: Mode Identity -> FileMode+modeToFileMode mode = foldr Posix.unionFileModes Posix.nullFileMode $+ [ Posix.ownerExecuteMode | runIdentity $ accessExecute (runIdentity $ modeUser mode) ] <>+ [ Posix.ownerReadMode | runIdentity $ accessRead (runIdentity $ modeUser mode) ] <>+ [ Posix.ownerWriteMode | runIdentity $ accessWrite (runIdentity $ modeUser mode) ] <>+ [ Posix.groupExecuteMode | runIdentity $ accessExecute (runIdentity $ modeGroup mode) ] <>+ [ Posix.groupReadMode | runIdentity $ accessRead (runIdentity $ modeGroup mode) ] <>+ [ Posix.groupWriteMode | runIdentity $ accessWrite (runIdentity $ modeGroup mode) ] <>+ [ Posix.otherExecuteMode | runIdentity $ accessExecute (runIdentity $ modeOther mode) ] <>+ [ Posix.otherReadMode | runIdentity $ accessRead (runIdentity $ modeOther mode) ] <>+ [ Posix.otherWriteMode | runIdentity $ accessWrite (runIdentity $ modeOther mode) ]++-- | Check whether the second `FileMode` is contained in the first one.+hasFileMode :: FileMode -> FileMode -> Bool+hasFileMode mode x = (mode `Posix.intersectFileModes` x) == x+ {- | This error indicates that you supplied an invalid Dhall expression to the `toDirectoryTree` function. The Dhall expression could not be translated to a directory tree.@@ -143,59 +432,84 @@ newtype FilesystemError = FilesystemError { unexpectedExpression :: Expr Void Void } +instance Exception FilesystemError+ instance Show FilesystemError where show FilesystemError{..} = Pretty.renderString (Dhall.Pretty.layout message) where message =- Util._ERROR <> ": Not a valid directory tree expression \n\- \ \n\- \Explanation: Only a subset of Dhall expressions can be converted to a directory \n\- \tree. Specifically, record literals or maps can be converted to directories, \n\- \❰Text❱ literals can be converted to files, and ❰Optional❱ values are included if \n\- \❰Some❱ and omitted if ❰None❱. Values of union types can also be converted if \n\- \they are an alternative which has a non-nullary constructor whose argument is of \n\- \an otherwise convertible type. No other type of value can be translated to a \n\- \directory tree. \n\- \ \n\- \For example, this is a valid expression that can be translated to a directory \n\- \tree: \n\- \ \n\- \ \n\- \ ┌──────────────────────────────────┐ \n\- \ │ { `example.json` = \"[1, true]\" } │ \n\- \ └──────────────────────────────────┘ \n\- \ \n\- \ \n\- \In contrast, the following expression is not allowed due to containing a \n\- \❰Natural❱ field, which cannot be translated in this way: \n\- \ \n\- \ \n\- \ ┌───────────────────────┐ \n\- \ │ { `example.txt` = 1 } │ \n\- \ └───────────────────────┘ \n\- \ \n\- \ \n\- \Note that key names cannot contain path separators: \n\- \ \n\- \ \n\- \ ┌─────────────────────────────────────┐ \n\- \ │ { `directory/example.txt` = \"ABC\" } │ Invalid: Key contains a forward slash\n\- \ └─────────────────────────────────────┘ \n\- \ \n\- \ \n\- \Instead, you need to refactor the expression to use nested records instead: \n\- \ \n\- \ \n\- \ ┌───────────────────────────────────────────┐ \n\- \ │ { directory = { `example.txt` = \"ABC\" } } │ \n\- \ └───────────────────────────────────────────┘ \n\- \ \n\- \ \n\- \You tried to translate the following expression to a directory tree: \n\- \ \n\- \" <> Util.insert unexpectedExpression <> "\n\- \ \n\+ Util._ERROR <> ": Not a valid directory tree expression \n\\+ \ \n\\+ \Explanation: Only a subset of Dhall expressions can be converted to a directory \n\\+ \tree. Specifically, record literals or maps can be converted to directories, \n\\+ \❰Text❱ literals can be converted to files, and ❰Optional❱ values are included if \n\\+ \❰Some❱ and omitted if ❰None❱. Values of union types can also be converted if \n\\+ \they are an alternative which has a non-nullary constructor whose argument is of \n\\+ \an otherwise convertible type. Furthermore, there is a more advanced approach to \n\\+ \constructing a directory tree utilizing a fixpoint encoding. Consult the upstream \n\\+ \documentation of the `toDirectoryTree` function in the Dhall.Directory module for \n\\+ \further information on that. \n\\+ \No other type of value can be translated to a directory tree. \n\\+ \ \n\\+ \For example, this is a valid expression that can be translated to a directory \n\\+ \tree: \n\\+ \ \n\\+ \ \n\\+ \ ┌──────────────────────────────────┐ \n\\+ \ │ { `example.json` = \"[1, true]\" } │ \n\\+ \ └──────────────────────────────────┘ \n\\+ \ \n\\+ \ \n\\+ \In contrast, the following expression is not allowed due to containing a \n\\+ \❰Natural❱ field, which cannot be translated in this way: \n\\+ \ \n\\+ \ \n\\+ \ ┌───────────────────────┐ \n\\+ \ │ { `example.txt` = 1 } │ \n\\+ \ └───────────────────────┘ \n\\+ \ \n\\+ \ \n\\+ \Note that key names cannot contain path separators: \n\\+ \ \n\\+ \ \n\\+ \ ┌─────────────────────────────────────┐ \n\\+ \ │ { `directory/example.txt` = \"ABC\" } │ Invalid: Key contains a forward slash\n\\+ \ └─────────────────────────────────────┘ \n\\+ \ \n\\+ \ \n\\+ \Instead, you need to refactor the expression to use nested records instead: \n\\+ \ \n\\+ \ \n\\+ \ ┌───────────────────────────────────────────┐ \n\\+ \ │ { directory = { `example.txt` = \"ABC\" } } │ \n\\+ \ └───────────────────────────────────────────┘ \n\\+ \ \n\\+ \ \n\\+ \You tried to translate the following expression to a directory tree: \n\\+ \ \n\\+ \" <> Util.insert unexpectedExpression <> "\n\\+ \ \n\\ \... which is not an expression that can be translated to a directory tree. \n" -instance Exception FilesystemError+{- | This error indicates that you want to set some metadata for a file or+ directory, but that operation is not supported on your platform.+-}+newtype MetadataUnsupportedError =+ MetadataUnsupportedError { metadataForPath :: FilePath }++instance Exception MetadataUnsupportedError++instance Show MetadataUnsupportedError where+ show MetadataUnsupportedError{..} =+ Pretty.renderString (Dhall.Pretty.layout message)+ where+ message =+ Util._ERROR <> ": Setting metadata is not supported on this platform. \n\\+ \ \n\\+ \Explanation: Your Dhall expression indicates that you intend to set some metadata \n\\+ \like ownership or permissions for the following file or directory: \n\\+ \ \n\\+ \" <> Pretty.pretty metadataForPath <> "\n\\+ \ \n\\+ \... which is not supported on your platform. \n"
@@ -0,0 +1,267 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -Wno-orphans #-}++-- | Types used by the implementation of the @to-directory-tree@ subcommand+module Dhall.DirectoryTree.Types+ ( FilesystemEntry(DirectoryEntry, BinaryFileEntry, TextFileEntry, FileEntry)+ , DirectoryEntry+ , FileEntry+ , BinaryFileEntry+ , TextFileEntry+ , Entry(..)+ , User(..)+ , Group(..)+ , Mode(..)+ , Access(..)++ , setFileMode+ , prettyFileMode++ , isMetadataSupported+ ) where++import Data.ByteString (ByteString)+import Data.Functor.Identity (Identity (..))+import Data.Sequence (Seq)+import Data.Text (Text)+import Dhall.Marshal.Decode+ ( Decoder (..)+ , FromDhall (..)+ , Generic+ , InputNormalizer+ , InterpretOptions (..)+ )+import Dhall.Syntax (Expr (..), FieldSelection (..), Var (..))+import System.PosixCompat.Types (GroupID, UserID)++import qualified Data.Text as Text+import qualified Dhall.Marshal.Decode as Decode+import qualified System.PosixCompat.Files as Posix++#ifdef mingw32_HOST_OS+import Control.Monad (unless)+import Data.Word (Word32)+import System.IO (hPutStrLn, stderr)+import System.PosixCompat.Types (CMode)++import qualified Unsafe.Coerce++type FileMode = CMode+#else+import System.PosixCompat.Types (FileMode)++import qualified System.PosixCompat.Types as Posix+#endif++pattern Make :: Text -> Expr s a -> Expr s a+pattern Make label entry <- App (Field (Var (V "_" 0)) (fieldSelectionLabel -> label)) entry++-- | A directory in the filesystem.+type DirectoryEntry = Entry (Seq FilesystemEntry)++-- | A file in the filesystem.+{-# DEPRECATED FileEntry "`FileEntry` is deprecated and will be removed eventually. Please use `TextFileEntry` instead." #-}+type FileEntry = Entry Text++-- | A binary file in the filesystem.+type BinaryFileEntry = Entry ByteString++-- | A text file in the filesystem.+type TextFileEntry = Entry Text++-- | A filesystem entry.+data FilesystemEntry+ = DirectoryEntry (Entry (Seq FilesystemEntry))+ | BinaryFileEntry BinaryFileEntry+ | TextFileEntry TextFileEntry+ deriving (Eq, Generic, Ord, Show)++pattern FileEntry :: Entry Text -> FilesystemEntry+pattern FileEntry entry = TextFileEntry entry++instance FromDhall FilesystemEntry where+ autoWith normalizer = Decoder+ { expected = pure $ Var (V "tree" 0)+ , extract = \case+ Make "directory" entry ->+ DirectoryEntry <$> extract (autoWith normalizer) entry+ Make "file" entry ->+ TextFileEntry <$> extract (autoWith normalizer) entry+ Make "binary-file" entry ->+ BinaryFileEntry <$> extract (autoWith normalizer) entry+ expr -> Decode.typeError (expected (Decode.autoWith normalizer :: Decoder FilesystemEntry)) expr+ }++-- | A generic filesystem entry. This type holds the metadata that apply to all+-- entries. It is parametric over the content of such an entry.+data Entry a = Entry+ { entryName :: String+ , entryContent :: a+ , entryUser :: Maybe User+ , entryGroup :: Maybe Group+ , entryMode :: Maybe (Mode Maybe)+ }+ deriving (Eq, Generic, Ord, Show)++instance FromDhall a => FromDhall (Entry a) where+ autoWith = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+ { fieldModifier = Text.toLower . Text.drop (Text.length "entry")+ }++-- | A user identified either by id or name.+data User+ = UserId UserID+ | UserName String+ deriving (Eq, Generic, Ord, Show)++instance FromDhall User++#ifdef mingw32_HOST_OS+instance FromDhall UserID where+ autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CUid where+ autoWith normalizer = Posix.CUid <$> autoWith normalizer+#endif++-- | A group identified either by id or name.+data Group+ = GroupId GroupID+ | GroupName String+ deriving (Eq, Generic, Ord, Show)++instance FromDhall Group++#ifdef mingw32_HOST_OS+instance FromDhall GroupID where+ autoWith normalizer = Unsafe.Coerce.unsafeCoerce <$> autoWith @Word32 normalizer+#else+instance FromDhall Posix.CGid where+ autoWith normalizer = Posix.CGid <$> autoWith normalizer+#endif++-- | A filesystem mode. See chmod(1).+-- The parameter is meant to be instantiated by either `Identity` or `Maybe`+-- depending on the completeness of the information:+-- * For data read from the filesystem it will be `Identity`.+-- * For user-supplied data it will be `Maybe` as we want to be able to set+-- only specific bits.+data Mode f = Mode+ { modeUser :: f (Access f)+ , modeGroup :: f (Access f)+ , modeOther :: f (Access f)+ }+ deriving Generic++deriving instance Eq (Mode Identity)+deriving instance Eq (Mode Maybe)+deriving instance Ord (Mode Identity)+deriving instance Ord (Mode Maybe)+deriving instance Show (Mode Identity)+deriving instance Show (Mode Maybe)++instance FromDhall (Mode Identity) where+ autoWith = modeDecoder++instance FromDhall (Mode Maybe) where+ autoWith = modeDecoder++modeDecoder :: FromDhall (f (Access f)) => InputNormalizer -> Decoder (Mode f)+modeDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+ { fieldModifier = Text.toLower . Text.drop (Text.length "mode")+ }++-- | The permissions for a subject (user/group/other).+data Access f = Access+ { accessExecute :: f Bool+ , accessRead :: f Bool+ , accessWrite :: f Bool+ }+ deriving Generic++deriving instance Eq (Access Identity)+deriving instance Eq (Access Maybe)+deriving instance Ord (Access Identity)+deriving instance Ord (Access Maybe)+deriving instance Show (Access Identity)+deriving instance Show (Access Maybe)++instance FromDhall (Access Identity) where+ autoWith = accessDecoder++instance FromDhall (Access Maybe) where+ autoWith = accessDecoder++accessDecoder :: FromDhall (f Bool) => InputNormalizer -> Decoder (Access f)+accessDecoder = Decode.genericAutoWithInputNormalizer Decode.defaultInterpretOptions+ { fieldModifier = Text.toLower . Text.drop (Text.length "access")+ }++++-- | A wrapper around `Posix.setFileMode`. On Windows, it does check the+-- resulting file mode of the file/directory and emits a warning if it doesn't+-- match the desired file mode. On all other OS it is identical to+-- `Posix.setFileMode` as it is assumed to work correctly.+setFileMode :: FilePath -> FileMode -> IO ()+#ifdef mingw32_HOST_OS+setFileMode fp mode = do+ Posix.setFileMode fp mode+ mode' <- Posix.fileMode <$> Posix.getFileStatus fp+ unless (mode' == mode) $ hPutStrLn stderr $+ "Warning: Setting file mode did not succeed for " <> fp <> "\n" <>+ " Expected: " <> prettyFileMode mode <> "\n" <>+ " Actual: " <> prettyFileMode mode'+#else+setFileMode fp mode = Posix.setFileMode fp mode+#endif++-- | Pretty-print a `FileMode`. The format is similar to the one ls(1):+-- It is display as three blocks of three characters. The first block are the+-- permissions of the user, the second one are the ones of the group and the+-- third one the ones of other subjects. A @r@ denotes that the file or+-- directory is readable by the subject, a @w@ denotes that it is writable and+-- an @x@ denotes that it is executable. Unset permissions are represented by+-- @-@.+prettyFileMode :: FileMode -> String+prettyFileMode mode = userPP <> groupPP <> otherPP+ where+ userPP :: String+ userPP =+ isBitSet 'r' Posix.ownerReadMode <>+ isBitSet 'w' Posix.ownerWriteMode <>+ isBitSet 'x' Posix.ownerExecuteMode++ groupPP :: String+ groupPP =+ isBitSet 'r' Posix.groupReadMode <>+ isBitSet 'w' Posix.groupWriteMode <>+ isBitSet 'x' Posix.groupExecuteMode++ otherPP :: String+ otherPP =+ isBitSet 'r' Posix.otherReadMode <>+ isBitSet 'w' Posix.otherWriteMode <>+ isBitSet 'x' Posix.otherExecuteMode++ isBitSet :: Char -> FileMode -> String+ isBitSet c mask = if mask `Posix.intersectFileModes` mode /= Posix.nullFileMode+ then [c]+ else "-"++-- | Is setting metadata supported on this platform or not.+isMetadataSupported :: Bool+#ifdef mingw32_HOST_OS+isMetadataSupported = False+#else+isMetadataSupported = True+#endif
@@ -10,8 +10,6 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} -{-# OPTIONS_GHC -O #-}- {-| Eval-apply environment machine with conversion checking and quoting to normal forms. Fairly similar to GHCI's STG machine algorithmically, but much simpler, with no known call optimization or environment trimming.@@ -48,12 +46,18 @@ , Val(..) , (~>) , textShow+ , dateShow+ , timeShow+ , timezoneShow ) where +import Data.Bifunctor (first)+import Data.ByteString (ByteString) import Data.Foldable (foldr', toList)-import Data.List.NonEmpty (NonEmpty(..))+import Data.List.NonEmpty (NonEmpty (..)) import Data.Sequence (Seq, ViewL (..), ViewR (..)) import Data.Text (Text)+import Data.Time (Day, TimeOfDay (..), TimeZone) import Data.Void (Void) import Dhall.Map (Map) import Dhall.Set (Set)@@ -70,16 +74,18 @@ , PreferAnnotation (..) , RecordField (..) , Var (..)+ , WithComponent (..) ) import qualified Data.Char import qualified Data.Sequence as Sequence import qualified Data.Set import qualified Data.Text as Text+import qualified Data.Time as Time import qualified Dhall.Map as Map import qualified Dhall.Set import qualified Dhall.Syntax as Syntax-import qualified Text.Printf+import qualified Text.Printf as Printf data Environment a = Empty@@ -133,6 +139,10 @@ -- ^ The original function was a @Natural/subtract 0@. We need to preserve -- this information in case the @Natural/subtract@ ends up not being fully -- saturated, in which case we need to recover the unsaturated built-in+ | TextReplaceEmpty+ -- ^ The original function was a @Text/replace ""@+ | TextReplaceEmptyArgument (Val a)+ -- ^ The original function was a @Text/replace "" replacement@ deriving instance (Show a, Show (Val a -> Val a)) => Show (HLamInfo a) @@ -143,6 +153,7 @@ toVHPi (VPi a b@(Closure x _ _)) = Just (x, a, instantiate b) toVHPi (VHPi x a b ) = Just (x, a, b) toVHPi _ = Nothing+{-# INLINABLE toVHPi #-} data Val a = VConst !Const@@ -164,6 +175,9 @@ | VBoolNE !(Val a) !(Val a) | VBoolIf !(Val a) !(Val a) !(Val a) + | VBytes+ | VBytesLit ByteString+ | VNatural | VNaturalLit !Natural | VNaturalFold !(Val a) !(Val a) !(Val a) !(Val a)@@ -194,6 +208,16 @@ | VTextShow !(Val a) | VTextReplace !(Val a) !(Val a) !(Val a) + | VDate+ | VDateLiteral Time.Day+ | VDateShow !(Val a)+ | VTime+ | VTimeLiteral Time.TimeOfDay Word+ | VTimeShow !(Val a)+ | VTimeZone+ | VTimeZoneLiteral Time.TimeZone+ | VTimeZoneShow !(Val a)+ | VList !(Val a) | VListLit !(Maybe (Val a)) !(Seq (Val a)) | VListAppend !(Val a) !(Val a)@@ -216,12 +240,13 @@ | VPrefer !(Val a) !(Val a) | VMerge !(Val a) !(Val a) !(Maybe (Val a)) | VToMap !(Val a) !(Maybe (Val a))+ | VShowConstructor !(Val a) | VField !(Val a) !Text | VInject !(Map Text (Maybe (Val a))) !Text !(Maybe (Val a)) | VProject !(Val a) !(Either (Set Text) (Val a)) | VAssert !(Val a) | VEquivalent !(Val a) !(Val a)- | VWith !(Val a) (NonEmpty Text) !(Val a)+ | VWith !(Val a) (NonEmpty WithComponent) !(Val a) | VEmbed a -- | For use with "Text.Show.Functions".@@ -363,16 +388,15 @@ singletonVRecordLit v = VRecordLit (Map.singleton k v) {-# INLINE vField #-} -vTextReplaceSlow :: Text -> Val a -> VChunks a -> VChunks a-vTextReplaceSlow needle replacement haystack = go haystack+vTextReplace :: Text -> Val a -> Text -> VChunks a+vTextReplace needle replacement haystack = go haystack where- go (VChunks [] lastText) =- if Text.null suffix- then VChunks [] lastText- else+ go t+ | Text.null suffix = VChunks [] t+ | otherwise = let remainder = Text.drop (Text.length needle) suffix - rest = go (VChunks [] remainder)+ rest = go remainder in case replacement of VTextLit replacementChunks ->@@ -380,36 +404,7 @@ _ -> VChunks [(prefix, replacement)] "" <> rest where- (prefix, suffix) = Text.breakOn needle lastText- go (VChunks ((firstText, firstInterpolation) : chunks) lastText) =- if Text.null suffix- then- let rest = go (VChunks chunks lastText)-- in VChunks [(firstText, firstInterpolation)] "" <> rest- else- let remainder = Text.drop (Text.length needle) suffix-- rest =- go (VChunks ((remainder, firstInterpolation) : chunks) lastText)-- in case replacement of- VTextLit replacementChunks ->- VChunks [] prefix <> replacementChunks <> rest- _ ->- VChunks [(prefix, replacement)] "" <> rest- where- (prefix, suffix) = Text.breakOn needle firstText--vTextReplaceFast :: Text -> Text -> VChunks a -> VChunks a-vTextReplaceFast needle replacement (VChunks xys z) = VChunks xys' z'- where- xys' = do- (x, y) <- xys-- return (Text.replace needle replacement x, y)-- z' = Text.replace needle replacement z+ (prefix, suffix) = Text.breakOn needle t vProjectByFields :: Eq a => Environment a -> Val a -> Set Text -> Val a vProjectByFields env t ks =@@ -434,9 +429,9 @@ t' -> VProject t' (Left ks) -vWith :: Val a -> NonEmpty Text -> Val a -> Val a-vWith (VRecordLit kvs) (k :| [] ) v = VRecordLit (Map.insert k v kvs)-vWith (VRecordLit kvs) (k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs)+vWith :: Val a -> NonEmpty WithComponent -> Val a -> Val a+vWith (VRecordLit kvs) (WithLabel k :| [] ) v = VRecordLit (Map.insert k v kvs)+vWith (VRecordLit kvs) (WithLabel k₀ :| k₁ : ks) v = VRecordLit (Map.insert k₀ e₂ kvs) where e₁ = case Map.lookup k₀ kvs of@@ -444,6 +439,9 @@ Just e₁' -> e₁' e₂ = vWith e₁ (k₁ :| ks) v+vWith (VNone _T) (WithQuestion :| _ ) _ = VNone _T+vWith (VSome _) (WithQuestion :| [] ) v = VSome v+vWith (VSome t) (WithQuestion :| k₁ : ks) v = VSome (vWith t (k₁ :| ks) v) vWith e₀ ks v₀ = VWith e₀ ks v₀ eval :: forall a. Eq a => Environment a -> Expr Void a -> Val a@@ -453,9 +451,9 @@ VConst k Var v -> vVar env v- Lam (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = a }) t ->+ Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = a }) t -> VLam (eval env a) (Closure x env t)- Pi x a b ->+ Pi _ x a b -> VPi (eval env a) (Closure x env b) App t u -> vApp (eval env t) (eval env u)@@ -503,6 +501,10 @@ (b', VBoolLit True, VBoolLit False) -> b' (_, t', f') | conv env t' f' -> t' (b', t', f') -> VBoolIf b' t' f'+ Bytes ->+ VBytes+ BytesLit b ->+ VBytesLit b Natural -> VNatural NaturalLit n ->@@ -525,9 +527,12 @@ -- following issue: -- -- https://github.com/ghcjs/ghcjs/issues/782- let go !acc 0 = acc- go acc m = go (vApp succ acc) (m - 1)- in go zero (fromIntegral n' :: Integer)+ go zero (fromIntegral n' :: Integer) where+ go !acc 0 = acc+ go acc m =+ -- Detect a shortcut: if succ acc == acc then return acc immediately.+ let next = vApp succ acc+ in if conv env next acc then acc else go next (m - 1) _ -> inert NaturalBuild -> VPrim $ \case@@ -631,33 +636,67 @@ t -> VTextShow t TextReplace -> VPrim $ \needle ->- VPrim $ \replacement ->- VPrim $ \haystack ->- case haystack of- VTextLit haystackChunks ->- case needle of- VTextLit (VChunks [] "") ->- haystack- VTextLit (VChunks [] needleText) ->- case replacement of- VTextLit (VChunks [] replacementText) ->- VTextLit- (vTextReplaceFast- needleText- replacementText- haystackChunks- )- _ ->- VTextLit- (vTextReplaceSlow- needleText- replacement- haystackChunks- )- _ ->- VTextReplace needle replacement haystack+ let hLamInfo0 = case needle of+ VTextLit (VChunks [] "") -> TextReplaceEmpty+ _ -> Prim++ in VHLam hLamInfo0 $ \replacement ->+ let hLamInfo1 = case needle of+ VTextLit (VChunks [] "") ->+ TextReplaceEmptyArgument replacement _ ->- VTextReplace needle replacement haystack+ Prim+ in VHLam hLamInfo1 $ \haystack ->+ case needle of+ VTextLit (VChunks [] "") ->+ haystack++ VTextLit (VChunks [] needleText) ->+ case haystack of+ VTextLit (VChunks [] haystackText) ->+ case replacement of+ VTextLit (VChunks [] replacementText) ->+ VTextLit $ VChunks []+ (Text.replace+ needleText+ replacementText+ haystackText+ )+ _ ->+ VTextLit+ (vTextReplace+ needleText+ replacement+ haystackText+ )+ _ ->+ VTextReplace needle replacement haystack+ _ ->+ VTextReplace needle replacement haystack+ Date ->+ VDate+ DateLiteral d ->+ VDateLiteral d+ DateShow ->+ VPrim $ \case+ VDateLiteral d -> VTextLit (VChunks [] (dateShow d))+ t -> VDateShow t+ Time ->+ VTime+ TimeLiteral t p ->+ VTimeLiteral t p+ TimeShow ->+ VPrim $ \case+ VTimeLiteral d p -> VTextLit (VChunks [] (timeShow d p))+ t -> VTimeShow t+ TimeZone ->+ VTimeZone+ TimeZoneLiteral z ->+ VTimeZoneLiteral z+ TimeZoneShow ->+ VPrim $ \case+ VTimeZoneLiteral d -> VTextLit (VChunks [] (timezoneShow d))+ t -> VTimeZoneShow t List -> VPrim VList ListLit ma ts ->@@ -762,14 +801,14 @@ VRecordLit (Map.sort (eval env . recordFieldValue <$> kts)) Union kts -> VUnion (Map.sort (fmap (fmap (eval env)) kts))- Combine mk t u ->+ Combine _ mk t u -> vCombine mk (eval env t) (eval env u)- CombineTypes t u ->+ CombineTypes _ t u -> vCombineTypes (eval env t) (eval env u)- Prefer _ t u ->+ Prefer _ _ t u -> vPrefer env (eval env t) (eval env u) RecordCompletion t u ->- eval env (Annot (Prefer PreferFromCompletion (Field t def) u) (Field t typ))+ eval env (Annot (Prefer mempty PreferFromCompletion (Field t def) u) (Field t typ)) where def = Syntax.makeFieldSelection "default" typ = Syntax.makeFieldSelection "Type"@@ -803,19 +842,27 @@ in VListLit Nothing s (x', ma') -> VToMap x' ma'+ ShowConstructor x ->+ case eval env x of+ VInject m k _+ | Just _ <- Map.lookup k m -> VTextLit (VChunks [] k)+ | otherwise -> error errorMsg+ VSome _ -> VTextLit (VChunks [] "Some")+ VNone _ -> VTextLit (VChunks [] "None")+ x' -> VShowConstructor x' Field t (Syntax.fieldSelectionLabel -> k) -> vField (eval env t) k Project t (Left ks) ->- vProjectByFields env (eval env t) (Dhall.Set.sort ks)+ vProjectByFields env (eval env t) (Dhall.Set.sort (Dhall.Set.fromList ks)) Project t (Right e) -> case eval env e of VRecord kts ->- eval env (Project t (Left (Dhall.Set.fromSet (Map.keysSet kts))))+ vProjectByFields env (eval env t) (Dhall.Set.fromSet (Map.keysSet kts)) e' -> VProject (eval env t) (Right e') Assert t -> VAssert (eval env t)- Equivalent t u ->+ Equivalent _ t u -> VEquivalent (eval env t) (eval env u) With e₀ ks v -> vWith (eval env e₀) ks (eval env v)@@ -873,9 +920,32 @@ f '\r' = "\\r" f '\t' = "\\t" f '\f' = "\\f"- f c | c <= '\x1F' = Text.pack (Text.Printf.printf "\\u%04x" (Data.Char.ord c))+ f c | c <= '\x1F' = Text.pack (Printf.printf "\\u%04x" (Data.Char.ord c)) | otherwise = Text.singleton c +-- | Utility that powers the @Date/show@ built-in+dateShow :: Day -> Text+dateShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%0Y-%m-%d"++-- | Utility that powers the @Time/show@ built-in+timeShow :: TimeOfDay -> Word -> Text+timeShow (TimeOfDay hh mm seconds) precision =+ Text.pack (Printf.printf "%02d:%02d:%02d" hh mm ss <> suffix)+ where+ magnitude :: Integer+ magnitude = 10 ^ precision++ (ss, fraction) =+ truncate (seconds * fromInteger magnitude) `divMod` magnitude++ suffix+ | precision == 0 = ""+ | otherwise = Printf.printf ".%0*d" precision fraction++-- | Utility that powers the @TimeZone/show@ built-in+timezoneShow :: TimeZone -> Text+timezoneShow = Text.pack . Time.formatTime Time.defaultTimeLocale "%Ez"+ conv :: forall a. Eq a => Environment a -> Val a -> Val a -> Bool conv !env t0 t0' = case (t0, t0') of@@ -923,6 +993,10 @@ conv env t t' && conv env u u' (VBoolIf t u v, VBoolIf t' u' v') -> conv env t t' && conv env u u' && conv env v v'+ (VBytes, VBytes) ->+ True+ (VBytesLit l, VBytesLit r) ->+ l == r (VNatural, VNatural) -> True (VNaturalLit n, VNaturalLit n') ->@@ -975,6 +1049,24 @@ conv env t t' (VTextReplace a b c, VTextReplace a' b' c') -> conv env a a' && conv env b b' && conv env c c'+ (VDate, VDate) ->+ True+ (VDateLiteral l, VDateLiteral r) ->+ l == r+ (VDateShow t, VDateShow 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'+ (VTimeZone, VTimeZone) ->+ True+ (VTimeZoneLiteral l, VTimeZoneLiteral r) ->+ l == r+ (VTimeZoneShow t, VTimeZoneShow t') ->+ conv env t t' (VList a, VList a') -> conv env a a' (VListLit _ xs, VListLit _ xs') ->@@ -1017,6 +1109,8 @@ conv env t t' && conv env u u' (VToMap t _, VToMap t' _) -> conv env t t'+ (VShowConstructor t, VShowConstructor t') ->+ conv env t t' (VField t k, VField t' k') -> conv env t t' && k == k' (VProject t (Left ks), VProject t' (Left ks')) ->@@ -1054,6 +1148,7 @@ judgmentallyEqual :: Eq a => Expr s a -> Expr t a -> Bool judgmentallyEqual (Syntax.denote -> t) (Syntax.denote -> u) = conv Empty (eval Empty t) (eval Empty u)+{-# INLINABLE judgmentallyEqual #-} data Names = EmptyNames@@ -1083,21 +1178,29 @@ quote env t `qApp` u VLam a (freshClosure -> (x, v, t)) -> Lam+ mempty (Syntax.makeFunctionBinding x (quote env a)) (quoteBind x (instantiate t v)) VHLam i t -> case i of Typed (fresh -> (x, v)) a ->- Lam+ Lam mempty (Syntax.makeFunctionBinding x (quote env a)) (quoteBind x (t v))- Prim -> quote env (t VPrimVar)- NaturalSubtractZero -> App NaturalSubtract (NaturalLit 0)+ Prim ->+ quote env (t VPrimVar)+ NaturalSubtractZero ->+ App NaturalSubtract (NaturalLit 0)+ TextReplaceEmpty ->+ App TextReplace (TextLit (Chunks [] ""))+ TextReplaceEmptyArgument replacement ->+ App (App TextReplace (TextLit (Chunks [] "")))+ (quote env replacement) VPi a (freshClosure -> (x, v, b)) ->- Pi x (quote env a) (quoteBind x (instantiate b v))+ Pi mempty x (quote env a) (quoteBind x (instantiate b v)) VHPi (fresh -> (x, v)) a b ->- Pi x (quote env a) (quoteBind x (b v))+ Pi mempty x (quote env a) (quoteBind x (b v)) VBool -> Bool VBoolLit b ->@@ -1112,6 +1215,10 @@ BoolNE (quote env t) (quote env u) VBoolIf t u v -> BoolIf (quote env t) (quote env u) (quote env v)+ VBytes ->+ Bytes+ VBytesLit b ->+ BytesLit b VNatural -> Natural VNaturalLit n ->@@ -1164,6 +1271,24 @@ TextShow `qApp` t VTextReplace a b c -> TextReplace `qApp` a `qApp` b `qApp` c+ VDate ->+ Date+ VDateLiteral d ->+ DateLiteral d+ VDateShow t ->+ DateShow `qApp` t+ VTime ->+ Time+ VTimeLiteral t p ->+ TimeLiteral t p+ VTimeShow t ->+ TimeShow `qApp` t+ VTimeZone ->+ TimeZone+ VTimeZoneLiteral z ->+ TimeZoneLiteral z+ VTimeZoneShow t ->+ TimeZoneShow `qApp` t VList t -> List `qApp` t VListLit ma ts ->@@ -1197,23 +1322,25 @@ VUnion m -> Union (fmap (fmap (quote env)) m) VCombine mk t u ->- Combine mk (quote env t) (quote env u)+ Combine mempty mk (quote env t) (quote env u) VCombineTypes t u ->- CombineTypes (quote env t) (quote env u)+ CombineTypes mempty (quote env t) (quote env u) VPrefer t u ->- Prefer PreferFromSource (quote env t) (quote env u)+ Prefer mempty PreferFromSource (quote env t) (quote env u) VMerge t u ma -> Merge (quote env t) (quote env u) (fmap (quote env) ma) VToMap t ma -> ToMap (quote env t) (fmap (quote env) ma)+ VShowConstructor t ->+ ShowConstructor (quote env t) VField t k -> Field (quote env t) $ Syntax.makeFieldSelection k VProject t p ->- Project (quote env t) (fmap (quote env) p)+ Project (quote env t) (first Dhall.Set.toList (fmap (quote env) p)) VAssert t -> Assert (quote env t) VEquivalent t u ->- Equivalent (quote env t) (quote env u)+ Equivalent mempty (quote env t) (quote env u) VWith e ks v -> With (quote env e) ks (quote env v) VInject m k Nothing ->@@ -1253,6 +1380,7 @@ normalize :: Eq a => Expr s a -> Expr t a normalize = nf Empty+{-# INLINABLE normalize #-} alphaNormalize :: Expr s a -> Expr s a alphaNormalize = goEnv EmptyNames@@ -1272,10 +1400,10 @@ Const k Var (V x i) -> goVar e0 x i- Lam (FunctionBinding src0 x src1 src2 t) u ->- Lam (FunctionBinding src0 "_" src1 src2 (go t)) (goBind x u)- Pi x a b ->- Pi "_" (go a) (goBind x b)+ Lam cs (FunctionBinding src0 x src1 src2 t) u ->+ Lam cs (FunctionBinding src0 "_" src1 src2 (go t)) (goBind x u)+ Pi cs x a b ->+ Pi cs "_" (go a) (goBind x b) App t u -> App (go t) (go u) Let (Binding src0 x src1 mA src2 a) b ->@@ -1296,6 +1424,10 @@ BoolNE (go t) (go u) BoolIf b t f -> BoolIf (go b) (go t) (go f)+ Bytes ->+ Bytes+ BytesLit b ->+ BytesLit b Natural -> Natural NaturalLit n ->@@ -1348,6 +1480,24 @@ TextShow TextReplace -> TextReplace+ Date ->+ Date+ DateLiteral d ->+ DateLiteral d+ DateShow ->+ DateShow+ Time ->+ Time+ TimeLiteral t p ->+ TimeLiteral t p+ TimeShow ->+ TimeShow+ TimeZone ->+ TimeZone+ TimeZoneLiteral z ->+ TimeZoneLiteral z+ TimeZoneShow ->+ TimeZoneShow List -> List ListLit ma ts ->@@ -1380,26 +1530,28 @@ RecordLit (goRecordField <$> kts) Union kts -> Union (fmap (fmap go) kts)- Combine m t u ->- Combine m (go t) (go u)- CombineTypes t u ->- CombineTypes (go t) (go u)- Prefer b t u ->- Prefer b (go t) (go u)+ Combine cs m t u ->+ Combine cs m (go t) (go u)+ CombineTypes cs t u ->+ CombineTypes cs (go t) (go u)+ Prefer cs b t u ->+ Prefer cs b (go t) (go u) RecordCompletion t u -> RecordCompletion (go t) (go u) Merge x y ma -> Merge (go x) (go y) (fmap go ma) ToMap x ma -> ToMap (go x) (fmap go ma)+ ShowConstructor x ->+ ShowConstructor (go x) Field t k -> Field (go t) k Project t ks -> Project (go t) (fmap go ks) Assert t -> Assert (go t)- Equivalent t u ->- Equivalent (go t) (go u)+ Equivalent cs t u ->+ Equivalent cs (go t) (go u) With e k v -> With (go e) k (go v) Note s e ->
@@ -9,78 +9,83 @@ , format ) where -import Data.Foldable (for_)-import Dhall.Pretty (CharacterSet (..), annToAnsiStyle)-+import Data.Foldable (for_)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe (fromMaybe)+import Dhall.Pretty (CharacterSet, annToAnsiStyle, detectCharacterSet) import Dhall.Util ( Censor , CheckFailed (..) , Header (..)+ , Input (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed ) -import qualified Control.Exception import qualified Data.Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text import qualified Dhall.Import import qualified Dhall.Pretty import qualified Dhall.Util-import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty.Terminal+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.Console.ANSI import qualified System.FilePath import qualified System.IO -- | Arguments to the `format` subcommand data Format = Format- { characterSet :: CharacterSet- , censor :: Censor- , input :: PossiblyTransitiveInput- , outputMode :: OutputMode+ { chosenCharacterSet :: Maybe CharacterSet+ , censor :: Censor+ , transitivity :: Transitivity+ , inputs :: NonEmpty Input+ , outputMode :: OutputMode } -- | Implementation of the @dhall format@ subcommand format :: Format -> IO ()-format (Format { input = input0, ..}) = go input0+format (Format { inputs = inputs0, transitivity = transitivity0, ..}) =+ handleMultipleChecksFailed "format" "formatted" go inputs0 where go input = do let directory = case input of- NonTransitiveStandardInput ->+ StandardInput -> "."- PossiblyTransitiveInputFile file _ ->+ InputFile file -> System.FilePath.takeDirectory file let status = Dhall.Import.emptyStatus directory let layoutHeaderAndExpr (Header header, expr) =+ let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet+ in Dhall.Pretty.layout ( Pretty.pretty header <> Dhall.Pretty.prettyCharacterSet characterSet expr <> "\n") - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Data.Text.IO.readFile file - return (text, transitivity)-- NonTransitiveStandardInput -> do+ return (file, text, transitivity0)+ StandardInput -> do text <- Data.Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) - headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText + headerAndExpr@(_, parsedExpression) <- Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText+ case transitivity of Transitive -> for_ parsedExpression $ \import_ -> do maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return ()@@ -90,16 +95,16 @@ let formattedText = Pretty.Text.renderStrict docStream case outputMode of- Write ->+ Write -> do case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == formattedText then return () else AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy docStream) - NonTransitiveStandardInput -> do+ StandardInput -> do supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout Pretty.Terminal.renderIO@@ -108,12 +113,10 @@ then (fmap annToAnsiStyle docStream) else (Pretty.unAnnotateS docStream)) - Check ->- if originalText == formattedText- then return ()- else do- let command = "format"-- let modified = "formatted"+ return (Right ()) - Control.Exception.throwIO CheckFailed{..}+ Check ->+ return $+ if originalText == formattedText+ then Right ()+ else Left CheckFailed{..}
@@ -1,5 +1,5 @@-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-} @@ -8,21 +8,32 @@ module Dhall.Freeze ( -- * Freeze freeze- , freezeWithManager , freezeExpression- , freezeExpressionWithManager , freezeImport- , freezeImportWithManager , freezeRemoteImport- , freezeRemoteImportWithManager + -- * Freeze with custom evaluation settings+ , freezeWithSettings+ , freezeExpressionWithSettings+ , freezeImportWithSettings+ , freezeRemoteImportWithSettings+ -- * Types , Scope(..) , Intent(..)++ -- * Deprecated functions+ , freezeWithManager+ , freezeExpressionWithManager+ , freezeImportWithManager+ , freezeRemoteImportWithManager ) where import Data.Foldable (for_)-import Dhall.Pretty (CharacterSet)+import Data.List.NonEmpty (NonEmpty)+import Data.Maybe (fromMaybe)+import Dhall (EvaluateSettings)+import Dhall.Pretty (CharacterSet, detectCharacterSet) import Dhall.Syntax ( Expr (..) , Import (..)@@ -33,35 +44,56 @@ ( Censor , CheckFailed (..) , Header (..)+ , Input (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed )+import Lens.Micro (set, transformMOf, transformOf)+import Lens.Micro.Extras (view) import System.Console.ANSI (hSupportsANSI) -import qualified Control.Exception as Exception-import qualified Control.Monad.Trans.State.Strict as State-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text-import qualified Dhall.Core as Core+import qualified Control.Exception as Exception+import qualified Control.Monad.Trans.State.Strict as State+import qualified Data.Text.IO as Text.IO+import qualified Dhall+import qualified Dhall.Core as Core import qualified Dhall.Import-import qualified Dhall.Optics import qualified Dhall.Pretty import qualified Dhall.TypeCheck-import qualified Dhall.Util as Util-import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified Dhall.Util as Util+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.FilePath import qualified System.IO +-- | Specifies which imports to freeze+data Scope+ = OnlyRemoteImports+ -- ^ Freeze only remote imports (i.e. URLs)+ | AllImports+ -- ^ Freeze all imports (including paths and environment variables)++-- | Specifies why we are adding semantic integrity checks+data Intent+ = Secure+ -- ^ Protect imports with an integrity check without a fallback so that+ -- import resolution fails if the import changes+ | Cache+ -- ^ Protect imports with an integrity check and also add a fallback import+ -- import without an integrity check. This is useful if you only want to+ -- cache imports when possible but still gracefully degrade to resolving+ -- them if the semantic integrity check has changed.+ -- | Retrieve an `Import` and update the hash to match the latest contents freezeImport :: FilePath -- ^ Current working directory -> Import -> IO Import-freezeImport = freezeImportWithManager Dhall.Import.defaultNewManager+freezeImport = freezeImportWithSettings Dhall.defaultEvaluateSettings -- | See 'freezeImport'. freezeImportWithManager@@ -69,7 +101,88 @@ -> FilePath -> Import -> IO Import-freezeImportWithManager newManager directory import_ = do+freezeImportWithManager newManager = freezeImportWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeImportWithManager "Use freezeImportWithSettings directly" #-}++-- | Freeze an import only if the import is a `Remote` import+freezeRemoteImport+ :: FilePath+ -- ^ Current working directory+ -> Import+ -> IO Import+freezeRemoteImport = freezeRemoteImportWithSettings Dhall.defaultEvaluateSettings++-- | See 'freezeRemoteImport'.+freezeRemoteImportWithManager+ :: IO Dhall.Import.Manager+ -> FilePath+ -> Import+ -> IO Import+freezeRemoteImportWithManager newManager = freezeRemoteImportWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeRemoteImportWithManager "Use freezeRemoteImportWithSettings directly" #-}++-- | Implementation of the @dhall freeze@ subcommand+freeze+ :: OutputMode+ -> Transitivity+ -> NonEmpty Input+ -> Scope+ -> Intent+ -> Maybe CharacterSet+ -> Censor+ -> IO ()+freeze = freezeWithSettings Dhall.defaultEvaluateSettings++-- | See 'freeze'.+freezeWithManager+ :: IO Dhall.Import.Manager+ -> OutputMode+ -> Transitivity+ -> NonEmpty Input+ -> Scope+ -> Intent+ -> Maybe CharacterSet+ -> Censor+ -> IO ()+freezeWithManager newManager = freezeWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeWithManager "Use freezeWithSettings directly" #-}++{-| Slightly more pure version of the `freeze` function++ This still requires `IO` to freeze the import, but now the input and output+ expression are passed in explicitly+-}+freezeExpression+ :: FilePath+ -- ^ Starting directory+ -> Scope+ -> Intent+ -> Expr s Import+ -> IO (Expr s Import)+freezeExpression = freezeExpressionWithSettings Dhall.defaultEvaluateSettings++-- | See 'freezeExpression'.+freezeExpressionWithManager+ :: IO Dhall.Import.Manager+ -> FilePath+ -> Scope+ -> Intent+ -> Expr s Import+ -> IO (Expr s Import)+freezeExpressionWithManager newManager = freezeExpressionWithSettings (set Dhall.newManager newManager Dhall.defaultEvaluateSettings)+{-# DEPRECATED freezeExpressionWithManager "Use freezeExpressionWithSettings directly" #-}++--------------------------------------------------------------------------------+-- Versions that take EvaluateSettings+--------------------------------------------------------------------------------++-- | See 'freezeImport'.+freezeImportWithSettings+ :: EvaluateSettings+ -> FilePath+ -> Import+ -> IO Import+freezeImportWithSettings settings directory import_ = do let unprotectedImport = import_ { importHashed =@@ -78,15 +191,15 @@ } } - let status = Dhall.Import.emptyStatusWithManager newManager directory+ let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory expression <- State.evalStateT (Dhall.Import.loadWith (Embed unprotectedImport)) status - case Dhall.TypeCheck.typeOf expression of+ case Dhall.TypeCheck.typeWith (view Dhall.startingContext settings) expression of Left exception -> Exception.throwIO exception Right _ -> return () - let normalizedExpression = Core.alphaNormalize (Core.normalize expression)+ let normalizedExpression = Core.alphaNormalize (Core.normalizeWith (view Dhall.normalizer settings) expression) -- make sure the frozen import is present in the semantic cache Dhall.Import.writeExpressionToSemanticCache (Core.denote expression)@@ -99,100 +212,78 @@ return newImport --- | Freeze an import only if the import is a `Remote` import-freezeRemoteImport- :: FilePath- -- ^ Current working directory+-- | See 'freezeRemoteImport'.+freezeRemoteImportWithSettings+ :: EvaluateSettings+ -> FilePath -> Import -> IO Import-freezeRemoteImport = freezeRemoteImportWithManager Dhall.Import.defaultNewManager+freezeRemoteImportWithSettings settings directory import_ =+ case importType (importHashed import_) of+ Remote {} -> freezeImportWithSettings settings directory import_+ _ -> return import_ -- | See 'freezeRemoteImport'.-freezeRemoteImportWithManager- :: IO Dhall.Import.Manager+freezeNonMissingImportWithSettings+ :: EvaluateSettings -> FilePath -> Import -> IO Import-freezeRemoteImportWithManager newManager directory import_ =+freezeNonMissingImportWithSettings settings directory import_ = case importType (importHashed import_) of- Remote {} -> freezeImportWithManager newManager directory import_- _ -> return import_---- | Specifies which imports to freeze-data Scope- = OnlyRemoteImports- -- ^ Freeze only remote imports (i.e. URLs)- | AllImports- -- ^ Freeze all imports (including paths and environment variables)---- | Specifies why we are adding semantic integrity checks-data Intent- = Secure- -- ^ Protect imports with an integrity check without a fallback so that- -- import resolution fails if the import changes- | Cache- -- ^ Protect imports with an integrity check and also add a fallback import- -- import without an integrity check. This is useful if you only want to- -- cache imports when possible but still gracefully degrade to resolving- -- them if the semantic integrity check has changed.---- | Implementation of the @dhall freeze@ subcommand-freeze- :: OutputMode- -> PossiblyTransitiveInput- -> Scope- -> Intent- -> CharacterSet- -> Censor- -> IO ()-freeze = freezeWithManager Dhall.Import.defaultNewManager+ Missing -> return import_+ _ -> freezeImportWithSettings settings directory import_ -- | See 'freeze'.-freezeWithManager- :: IO Dhall.Import.Manager+freezeWithSettings+ :: EvaluateSettings -> OutputMode- -> PossiblyTransitiveInput+ -> Transitivity+ -> NonEmpty Input -> Scope -> Intent- -> CharacterSet+ -> Maybe CharacterSet -> Censor -> IO ()-freezeWithManager newManager outputMode input0 scope intent characterSet censor = go input0+freezeWithSettings settings outputMode transitivity0 inputs scope intent chosenCharacterSet censor =+ handleMultipleChecksFailed "freeze" "frozen" go inputs where go input = do let directory = case input of- NonTransitiveStandardInput ->+ StandardInput -> "."- PossiblyTransitiveInputFile file _ ->+ InputFile file -> System.FilePath.takeDirectory file - let status = Dhall.Import.emptyStatusWithManager newManager directory+ let status = Dhall.Import.emptyStatusWithManager (view Dhall.newManager settings) directory - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Text.IO.readFile file - return (text, transitivity)+ return (file, text, transitivity0) - NonTransitiveStandardInput -> do+ StandardInput -> do text <- Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) - (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor originalText+ (Header header, parsedExpression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText + let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet+ case transitivity of Transitive -> for_ parsedExpression $ \import_ -> do maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return () - frozenExpression <- freezeExpressionWithManager newManager directory scope intent parsedExpression+ frozenExpression <- freezeExpressionWithSettings settings directory scope intent parsedExpression let doc = Pretty.pretty header <> Dhall.Pretty.prettyCharacterSet characterSet frozenExpression@@ -207,7 +298,7 @@ let unAnnotated = Pretty.unAnnotateS stream case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == modifiedText then return () else@@ -215,7 +306,7 @@ file (Pretty.Text.renderLazy unAnnotated) - NonTransitiveStandardInput -> do+ StandardInput -> do supportsANSI <- System.Console.ANSI.hSupportsANSI System.IO.stdout if supportsANSI then@@ -223,45 +314,29 @@ else Pretty.renderIO System.IO.stdout unAnnotated - Check ->- if originalText == modifiedText- then return ()- else do- let command = "freeze"-- let modified = "frozen"-- Exception.throwIO CheckFailed{..}--{-| Slightly more pure version of the `freeze` function+ return (Right ()) - This still requires `IO` to freeze the import, but now the input and output- expression are passed in explicitly--}-freezeExpression- :: FilePath- -- ^ Starting directory- -> Scope- -> Intent- -> Expr s Import- -> IO (Expr s Import)-freezeExpression = freezeExpressionWithManager Dhall.Import.defaultNewManager+ Check ->+ return $+ if originalText == modifiedText+ then Right ()+ else Left CheckFailed{..} -- | See 'freezeExpression'.-freezeExpressionWithManager- :: IO Dhall.Import.Manager+freezeExpressionWithSettings+ :: EvaluateSettings -> FilePath -> Scope -> Intent -> Expr s Import -> IO (Expr s Import)-freezeExpressionWithManager newManager directory scope intent expression = do+freezeExpressionWithSettings settings directory scope intent expression = do let freezeScope = case scope of- AllImports -> freezeImportWithManager- OnlyRemoteImports -> freezeRemoteImportWithManager+ AllImports -> freezeNonMissingImportWithSettings+ OnlyRemoteImports -> freezeRemoteImportWithSettings - let freezeFunction = freezeScope newManager directory+ let freezeFunction = freezeScope settings directory let cache -- This case is necessary because `transformOf` is a bottom-up@@ -309,17 +384,21 @@ (Embed import_@(Import { importHashed = ImportHashed { hash = Nothing } })) = do frozenImport <- freezeFunction import_ + let frozenMissing = toMissing frozenImport+ {- The two imports can be the same if the import is local and `freezeFunction` only freezes remote imports by default -} if frozenImport /= import_- then return (ImportAlt (Embed frozenImport) (Embed import_))+ then return (ImportAlt (Embed frozenMissing) (Embed import_)) else return (Embed import_) cache (Embed import_@(Import { importHashed = ImportHashed { hash = Just _ } })) = do -- Regenerate the integrity check, just in case it's wrong frozenImport <- freezeFunction import_ + let frozenMissing = toMissing frozenImport+ -- `dhall freeze --cache` also works the other way around, adding an -- unprotected fallback import to imports that are already -- protected@@ -329,12 +408,38 @@ } } - return (ImportAlt (Embed frozenImport) (Embed thawedImport))+ return (ImportAlt (Embed frozenMissing) (Embed thawedImport)) cache expression_ = return expression_ - case intent of+ let uncache+ (ImportAlt+ (Core.shallowDenote -> Embed+ Import{ importHashed = ImportHashed { hash = Just expectedHash, importType = Missing } }+ )+ (Core.shallowDenote -> Embed+ import_@Import{ importHashed = ImportHashed{ hash = Nothing } }+ )+ ) = Embed+ (import_+ { importHashed = (importHashed import_)+ { hash = Just expectedHash+ }+ }+ )+ uncache expression_ = expression_++ let simplify (ImportAlt (Core.shallowDenote -> Embed import1) (Core.shallowDenote -> Embed import2))+ | import1 == import2 = Embed import1+ simplify expression_ = expression_++ transformOf Core.subExpressions simplify <$> case intent of Secure ->- traverse freezeFunction expression+ traverse freezeFunction (transformOf Core.subExpressions uncache expression) Cache ->- Dhall.Optics.transformMOf Core.subExpressions cache expression+ transformMOf Core.subExpressions cache expression++-- https://github.com/dhall-lang/dhall-haskell/issues/2347+toMissing :: Import -> Import+toMissing import_ =+ import_ { importHashed = (importHashed import_) { importType = Missing } }
@@ -1,12 +1,14 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wall #-} @@ -105,16 +107,16 @@ load , loadWithManager , loadRelativeTo- , loadRelativeToWithManager+ , loadWithStatus , loadWith , localToPath , hashExpression , hashExpressionToCode , writeExpressionToSemanticCache- , warnAboutMissingCaches , assertNoImports , Manager , defaultNewManager+ , CacheWarning(..) , Status(..) , SemanticCacheMode(..) , Chained@@ -123,6 +125,11 @@ , chainedChangeMode , emptyStatus , emptyStatusWithManager+ , envOriginHeaders+ , makeEmptyStatus+ , remoteStatus+ , remoteStatusWithManager+ , fetchRemote , stack , cache , Depends(..)@@ -147,26 +154,25 @@ , HashMismatch(..) ) where -import Control.Applicative (Alternative (..), liftA2)+import Control.Applicative (Alternative (..)) import Control.Exception ( Exception , IOException , SomeException , toException )-import Control.Monad (when)-import Control.Monad.Catch (MonadCatch (catch), handle, throwM)-import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Morph (hoist)-import Control.Monad.Trans.Class (lift)-import Control.Monad.Trans.State.Strict (StateT)-import Data.ByteString (ByteString)-import Data.CaseInsensitive (CI)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Text (Text)-import Data.Typeable (Typeable)-import Data.Void (Void, absurd)-import Dhall.Binary (StandardVersion (..))+import Control.Monad.Catch (MonadCatch (catch), handle, throwM)+import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Morph (hoist)+import Control.Monad.State.Strict (MonadState, StateT)+import Data.ByteString (ByteString)+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import Data.Typeable (Typeable)+import Data.Void (Void, absurd)+import Dhall.TypeCheck (TypeError)+import Dhall.Util (printWarning) import Dhall.Syntax ( Chunks (..)@@ -185,10 +191,17 @@ ) import System.FilePath ((</>))+import Text.Megaparsec (SourcePos (SourcePos), mkPos) #ifdef WITH_HTTP import Dhall.Import.HTTP #endif+import Dhall.Import.Headers+ ( normalizeHeaders+ , originHeadersTypeExpr+ , toHeaders+ , toOriginHeaders+ ) import Dhall.Import.Types import Dhall.Parser@@ -197,20 +210,19 @@ , SourcedException (..) , Src (..) )-import Lens.Family.State.Strict (zoom)+import Lens.Micro.Mtl (zoom) -import qualified Codec.CBOR.Encoding as Encoding import qualified Codec.CBOR.Write as Write import qualified Codec.Serialise+import qualified Control.Exception as Exception+import qualified Control.Monad.State.Strict as State import qualified Control.Monad.Trans.Maybe as Maybe-import qualified Control.Monad.Trans.State.Strict as State import qualified Data.ByteString import qualified Data.ByteString.Lazy-import qualified Data.CaseInsensitive-import qualified Data.Foldable import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Maybe as Maybe import qualified Data.Text as Text-import qualified Data.Text.Encoding+import qualified Data.Text.Encoding as Encoding import qualified Data.Text.IO import qualified Dhall.Binary import qualified Dhall.Core as Core@@ -282,7 +294,7 @@ instance Show ReferentiallyOpaque where show (ReferentiallyOpaque import_) =- "\nReferentially opaque import: " ++ Dhall.Pretty.Internal.prettyToString import_+ "\nLocal imports are not permitted from remote imports: " ++ Dhall.Pretty.Internal.prettyToString import_ -- | Extend another exception with the current import stack data Imported e = Imported@@ -351,9 +363,6 @@ throwMissingImport :: (MonadCatch m, Exception e) => e -> m a throwMissingImport e = throwM (MissingImports [toException e]) --- | HTTP headers-type HTTPHeader = (CI ByteString, ByteString)- -- | Exception thrown when a HTTP url is imported but dhall was built without -- the @with-http@ Cabal flag. data CannotImportHTTPURL =@@ -497,7 +506,7 @@ -- | Chain imports, also typecheck and normalize headers if applicable. chainImport :: Chained -> Import -> StateT Status IO Chained chainImport (Chained parent) child@(Import importHashed@(ImportHashed _ (Remote url)) _) = do- url' <- normalizeHeaders url+ url' <- normalizeHeadersIn url let child' = child { importHashed = importHashed { importType = Remote url' } } return (Chained (canonicalize (parent <> child'))) @@ -536,8 +545,10 @@ Status { .. } <- State.get mCached <- case _semanticCacheMode of- UseSemanticCache -> liftIO $ fetchFromSemanticCache semanticHash- IgnoreSemanticCache -> pure Nothing+ UseSemanticCache ->+ zoom cacheWarning (fetchFromSemanticCache semanticHash)+ IgnoreSemanticCache ->+ pure Nothing case mCached of Just bytesStrict -> do@@ -563,24 +574,32 @@ Nothing -> fetch where fetch = do- ImportSemantics { importSemantics } <- loadImportWithSemisemanticCache import_+ ImportSemantics{ importSemantics } <- loadImportWithSemisemanticCache import_ - let variants = map (\version -> encodeExpression version (Core.alphaNormalize importSemantics))- [ minBound .. maxBound ]- case Data.Foldable.find ((== semanticHash). Dhall.Crypto.sha256Hash) variants of- Just bytes -> liftIO $ writeToSemanticCache semanticHash bytes- Nothing -> do- let expectedHash = semanticHash- Status { _stack } <- State.get- let actualHash = hashExpression (Core.alphaNormalize importSemantics)- throwMissingImport (Imported _stack (HashMismatch {..}))+ let bytes = encodeExpression (Core.alphaNormalize importSemantics) - return (ImportSemantics {..})+ let actualHash = Dhall.Crypto.sha256Hash bytes + let expectedHash = semanticHash + if actualHash == expectedHash+ then do+ zoom cacheWarning (writeToSemanticCache semanticHash bytes) + else do+ Status{ _stack } <- State.get++ throwMissingImport (Imported _stack HashMismatch{..})++ return ImportSemantics{..}+++ -- Fetch encoded normal form from "semantic cache"-fetchFromSemanticCache :: Dhall.Crypto.SHA256Digest -> IO (Maybe Data.ByteString.ByteString)+fetchFromSemanticCache+ :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+ => Dhall.Crypto.SHA256Digest+ -> m (Maybe Data.ByteString.ByteString) fetchFromSemanticCache expectedHash = Maybe.runMaybeT $ do cacheFile <- getCacheFile "dhall" expectedHash True <- liftIO (Directory.doesFileExist cacheFile)@@ -589,12 +608,20 @@ -- | Ensure that the given expression is present in the semantic cache. The -- given expression should be alpha-beta-normal. writeExpressionToSemanticCache :: Expr Void Void -> IO ()-writeExpressionToSemanticCache expression = writeToSemanticCache hash bytes+writeExpressionToSemanticCache expression =+ -- Defaulting to not displaying the warning is for backwards compatibility+ -- with the old behavior+ State.evalStateT (writeToSemanticCache hash bytes) CacheWarned where- bytes = encodeExpression NoVersion expression+ bytes = encodeExpression expression+ hash = Dhall.Crypto.sha256Hash bytes -writeToSemanticCache :: Dhall.Crypto.SHA256Digest -> Data.ByteString.ByteString -> IO ()+writeToSemanticCache+ :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+ => Dhall.Crypto.SHA256Digest+ -> Data.ByteString.ByteString+ -> m () writeToSemanticCache hash bytes = do _ <- Maybe.runMaybeT $ do cacheFile <- getCacheFile "dhall" hash@@ -637,8 +664,9 @@ -- https://github.com/dhall-lang/dhall-haskell/issues/1098 for the reasoning -- behind semi-semantic caching. let semisemanticHash = computeSemisemanticHash (Core.denote resolvedExpr)- mCached <- lift $ fetchFromSemisemanticCache semisemanticHash + mCached <- zoom cacheWarning (fetchFromSemisemanticCache semisemanticHash)+ importSemantics <- case mCached of Just bytesStrict -> do let bytesLazy = Data.ByteString.Lazy.fromStrict bytesStrict@@ -668,23 +696,29 @@ let betaNormal = Core.normalizeWith _normalizer substitutedExpr - let bytes = encodeExpression NoVersion betaNormal+ let bytes = encodeExpression betaNormal - lift (writeToSemisemanticCache semisemanticHash bytes)+ zoom cacheWarning (writeToSemisemanticCache semisemanticHash bytes) return betaNormal return (ImportSemantics {..}) --- `as Text` imports aren't cached since they are well-typed and normal by--- construction+-- `as Text` and `as Bytes` imports aren't cached since they are well-typed and+-- normal by construction loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawText)) = do text <- fetchFresh importType -- importSemantics is alpha-beta-normal by construction! let importSemantics = TextLit (Chunks [] text) return (ImportSemantics {..})+loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) RawBytes)) = do+ bytes <- fetchBytes importType + -- importSemantics is alpha-beta-normal by construction!+ let importSemantics = BytesLit bytes+ return (ImportSemantics {..})+ -- `as Location` imports aren't cached since they are well-typed and normal by -- construction loadImportWithSemisemanticCache (Chained (Import (ImportHashed _ importType) Location)) = do@@ -718,20 +752,27 @@ computeSemisemanticHash resolvedExpr = hashExpression resolvedExpr -- Fetch encoded normal form from "semi-semantic cache"-fetchFromSemisemanticCache :: Dhall.Crypto.SHA256Digest -> IO (Maybe Data.ByteString.ByteString)+fetchFromSemisemanticCache+ :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+ => Dhall.Crypto.SHA256Digest+ -> m (Maybe Data.ByteString.ByteString) fetchFromSemisemanticCache semisemanticHash = Maybe.runMaybeT $ do cacheFile <- getCacheFile "dhall-haskell" semisemanticHash True <- liftIO (Directory.doesFileExist cacheFile) liftIO (Data.ByteString.readFile cacheFile) -writeToSemisemanticCache :: Dhall.Crypto.SHA256Digest -> Data.ByteString.ByteString -> IO ()+writeToSemisemanticCache+ :: (MonadState CacheWarning m, MonadCatch m, MonadIO m)+ => Dhall.Crypto.SHA256Digest+ -> Data.ByteString.ByteString+ -> m () writeToSemisemanticCache semisemanticHash bytes = do _ <- Maybe.runMaybeT $ do cacheFile <- getCacheFile "dhall-haskell" semisemanticHash liftIO (AtomicWrite.Binary.atomicWriteFile cacheFile bytes) return () --- Fetch source code directly from disk/network+-- | Fetch source code directly from disk/network fetchFresh :: ImportType -> StateT Status IO Text fetchFresh (Local prefix file) = do Status { _stack } <- State.get@@ -756,7 +797,31 @@ fetchFresh Missing = throwM (MissingImports []) +-- | Like `fetchFresh`, except for `Dhall.Syntax.Expr.Bytes`+fetchBytes :: ImportType -> StateT Status IO ByteString+fetchBytes (Local prefix file) = do+ Status { _stack } <- State.get+ path <- liftIO $ localToPath prefix file+ exists <- liftIO $ Directory.doesFileExist path+ if exists+ then liftIO $ Data.ByteString.readFile path+ else throwMissingImport (Imported _stack (MissingFile path)) +fetchBytes (Remote url) = do+ Status { _remoteBytes } <- State.get+ _remoteBytes url++fetchBytes (Env env) = do+ Status { _stack } <- State.get+ x <- liftIO $ System.Environment.lookupEnv (Text.unpack env)+ case x of+ Just string ->+ return (Encoding.encodeUtf8 (Text.pack string))+ Nothing ->+ throwMissingImport (Imported _stack (MissingEnvironmentVariable env))+fetchBytes Missing = throwM (MissingImports [])++-- | Fetch the text contents of a URL fetchRemote :: URL -> StateT Status IO Data.Text.Text #ifndef WITH_HTTP fetchRemote (url@URL { headers = maybeHeadersExpression }) = do@@ -775,48 +840,48 @@ fetchFromHttpUrl url' maybeHeaders #endif --- | Given a well-typed (of type `List { header : Text, value Text }` or--- `List { mapKey : Text, mapValue Text }`) headers expressions in normal form--- construct the corresponding binary http headers; otherwise return the empty--- list.-toHeaders :: Expr s a -> [HTTPHeader]-toHeaders (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybeHeaders)+-- | Fetch the text contents of a URL+fetchRemoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+#ifndef WITH_HTTP+fetchRemoteBytes (url@URL { headers = maybeHeadersExpression }) = do+ let maybeHeaders = fmap toHeaders maybeHeadersExpression+ let urlString = Text.unpack (Core.pretty url)+ Status { _stack } <- State.get+ throwMissingImport (Imported _stack (CannotImportHTTPURL urlString maybeHeaders))+#else+fetchRemoteBytes url = do+ zoom remoteBytes (State.put fetchFromHTTP)+ fetchFromHTTP url where- maybeHeaders = mapM toHeader hs-toHeaders _ = []--toHeader :: Expr s a -> Maybe HTTPHeader-toHeader (RecordLit m) = do- (Core.recordFieldValue -> TextLit (Chunks [] keyText), Core.recordFieldValue -> TextLit (Chunks [] valueText))- <- lookupHeader <|> lookupMapKey- let keyBytes = Data.Text.Encoding.encodeUtf8 keyText- let valueBytes = Data.Text.Encoding.encodeUtf8 valueText- return (Data.CaseInsensitive.mk keyBytes, valueBytes)- where- lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)- lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)-toHeader _ =- empty+ fetchFromHTTP :: URL -> StateT Status IO Data.ByteString.ByteString+ fetchFromHTTP (url'@URL { headers = maybeHeadersExpression }) = do+ let maybeHeaders = fmap toHeaders maybeHeadersExpression+ fetchFromHttpUrlBytes url' maybeHeaders+#endif getCacheFile- :: (MonadCatch m, Alternative m, MonadIO m) => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath+ :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+ => FilePath -> Dhall.Crypto.SHA256Digest -> m FilePath getCacheFile cacheName hash = do- cacheDirectory <- getOrCreateCacheDirectory False cacheName+ cacheDirectory <- getOrCreateCacheDirectory cacheName let cacheFile = cacheDirectory </> ("1220" <> show hash) return cacheFile --- | Warn if no cache directory is available-warnAboutMissingCaches :: (MonadCatch m, Alternative m, MonadIO m) => m ()-warnAboutMissingCaches = warn <|> return ()- where warn = Data.Foldable.traverse_ (getOrCreateCacheDirectory True) ["dhall", "dhall-haskell"]--getOrCreateCacheDirectory :: (MonadCatch m, Alternative m, MonadIO m) => Bool -> FilePath -> m FilePath-getOrCreateCacheDirectory showWarning cacheName = do+getOrCreateCacheDirectory+ :: (MonadCatch m, Alternative m, MonadState CacheWarning m, MonadIO m)+ => FilePath -> m FilePath+getOrCreateCacheDirectory cacheName = do let warn message = do- when showWarning (printWarning message)+ cacheWarningStatus <- State.get + case cacheWarningStatus of+ CacheWarned -> printWarning message+ CacheNotWarned -> return ()++ State.put CacheWarned+ empty let handler action dir (ioex :: IOException) = do@@ -857,14 +922,19 @@ then return () else do+ let render f = if f permissions then "✓" else "✗" let message = "The directory:\n" <> "\n" <> "↳ " <> dir <> "\n" <> "\n" <> "... does not give you permission to read, write, or search files.\n\n"+ <> "\n" <> "The directory's current permissions are:\n"- <> show permissions <> "\n"+ <> "\n"+ <> "• " <> render Directory.readable <> " readable\n"+ <> "• " <> render Directory.writable <> " writable\n"+ <> "• " <> render Directory.searchable <> " searchable\n" warn message @@ -908,7 +978,7 @@ setPermissions dir - cacheBaseDirectory <- getCacheBaseDirectory showWarning+ cacheBaseDirectory <- getCacheBaseDirectory let directory = cacheBaseDirectory </> cacheName @@ -926,8 +996,9 @@ return directory -getCacheBaseDirectory :: (Alternative m, MonadIO m) => Bool -> m FilePath-getCacheBaseDirectory showWarning = alternative₀ <|> alternative₁ <|> alternative₂+getCacheBaseDirectory+ :: (MonadState CacheWarning m, Alternative m, MonadIO m) => m FilePath+getCacheBaseDirectory = alternative₀ <|> alternative₁ <|> alternative₂ where alternative₀ = do maybeXDGCacheHome <-@@ -957,6 +1028,8 @@ where isWindows = System.Info.os == "mingw32" alternative₂ = do+ cacheWarningStatus <- State.get+ let message = "\n" <> "\ESC[1;33mWarning\ESC[0m: "@@ -965,68 +1038,156 @@ <> "You can provide a cache base directory by pointing the $XDG_CACHE_HOME\n" <> "environment variable to a directory with read and write permissions.\n" - when showWarning (liftIO (System.IO.hPutStrLn System.IO.stderr message))+ case cacheWarningStatus of+ CacheNotWarned ->+ liftIO (System.IO.hPutStrLn System.IO.stderr message)+ CacheWarned ->+ return () + State.put CacheWarned+ empty -- If the URL contains headers typecheck them and replace them with their normal -- forms.-normalizeHeaders :: URL -> StateT Status IO URL-normalizeHeaders url@URL { headers = Just headersExpression } = do+normalizeHeadersIn :: URL -> StateT Status IO URL+normalizeHeadersIn url@URL { headers = Just headersExpression } = do Status { _stack } <- State.get loadedExpr <- loadWith headersExpression+ let handler (e :: SomeException) = throwMissingImport (Imported _stack e)+ normalized <- liftIO $ handle handler (normalizeHeaders loadedExpr)+ return url { headers = Just (fmap absurd normalized) } - let go key₀ key₁ = do- let expected :: Expr Src Void- expected =- App List- ( Record $ Core.makeRecordField <$>- Dhall.Map.fromList- [ (key₀, Text)- , (key₁, Text)- ]- )+normalizeHeadersIn url = return url - let suffix_ = Dhall.Pretty.Internal.prettyToStrictText expected- let annot = case loadedExpr of- Note (Src begin end bytes) _ ->- Note (Src begin end bytes') (Annot loadedExpr expected)- where- bytes' = bytes <> " : " <> suffix_- _ ->- Annot loadedExpr expected+-- | Empty origin headers used for remote contexts+-- (and fallback when nothing is set in env or config file)+emptyOriginHeaders :: Expr Src Import+emptyOriginHeaders = ListLit (Just (fmap absurd originHeadersTypeExpr)) mempty - _ <- case (Dhall.TypeCheck.typeOf annot) of- Left err -> throwMissingImport (Imported _stack err)- Right _ -> return ()+-- | A fake Src to annotate headers expressions with.+-- We need to wrap headers expressions in a Note for nice error reporting,+-- and because ImportAlt handling only catches SourcedExceptions+headersSrc :: Src+headersSrc = Src {+ srcStart = SourcePos {+ sourceName = fakeSrcName,+ sourceLine = mkPos 1,+ sourceColumn = mkPos 1+ },+ srcEnd = SourcePos {+ sourceName = fakeSrcName,+ sourceLine = mkPos 1,+ sourceColumn = mkPos (Text.length fakeSrcText)+ },+ srcText = fakeSrcText+ }+ where+ fakeSrcText = "«Origin Header Configuration»"+ fakeSrcName = "[builtin]" - return (Core.normalize loadedExpr)+-- | Load headers only from the environment (used in tests)+envOriginHeaders :: Expr Src Import+envOriginHeaders = Note headersSrc (Embed (Import (ImportHashed Nothing (Env "DHALL_HEADERS")) Code)) - let handler₀ (e :: SomeException) = do- {- Try to typecheck using the preferred @mapKey@/@mapValue@ fields- and fall back to @header@/@value@ if that fails. However, if- @header@/@value@ still fails then re-throw the original exception- for @mapKey@ / @mapValue@. -}- let handler₁ (_ :: SomeException) =- throwMissingImport (Imported _stack e)+-- | Load headers in env, falling back to config file+defaultOriginHeaders :: IO (Expr Src Import)+#ifndef WITH_HTTP+defaultOriginHeaders = return emptyOriginHeaders+#else+defaultOriginHeaders = do+ fromFile <- originHeadersFileExpr+ return (Note headersSrc (ImportAlt envOriginHeaders (Note headersSrc fromFile)))+#endif - handle handler₁ (go "header" "value")+-- | Given a headers expression, return an origin headers loader+originHeadersLoader :: IO (Expr Src Import) -> StateT Status IO OriginHeaders+originHeadersLoader headersExpr = do - headersExpression' <-- handle handler₀ (go "mapKey" "mapValue")+ -- Load the headers using the parent stack, which should always be a local+ -- import (we only load headers for the first remote import) - return url { headers = Just (fmap absurd headersExpression') }+ status <- State.get -normalizeHeaders url = return url+ let parentStack = fromMaybe abortEmptyStack (nonEmpty (NonEmpty.tail (_stack status))) + let headerLoadStatus = status { _stack = parentStack }++ (headers, _) <- liftIO (State.runStateT doLoad headerLoadStatus)++ -- return cached headers next time+ _ <- State.modify (\state -> state { _loadOriginHeaders = return headers })++ return headers+ where+ abortEmptyStack = Core.internalError "Origin headers loaded with an empty stack"++ doLoad = do+ partialExpr <- liftIO headersExpr+ loaded <- loadWith (Note headersSrc (ImportAlt partialExpr emptyOriginHeaders))+ liftIO (toOriginHeaders loaded)+ -- | Default starting `Status`, importing relative to the given directory. emptyStatus :: FilePath -> Status-emptyStatus = emptyStatusWithManager defaultNewManager+emptyStatus = makeEmptyStatus defaultNewManager defaultOriginHeaders +-- | See 'emptyStatus'+emptyStatusWithManager+ :: IO Manager+ -> FilePath+ -> Status+emptyStatusWithManager newManager = makeEmptyStatus newManager defaultOriginHeaders+ -- | See 'emptyStatus'.-emptyStatusWithManager :: IO Manager -> FilePath -> Status-emptyStatusWithManager newManager = emptyStatusWith newManager fetchRemote+makeEmptyStatus+ :: IO Manager+ -> IO (Expr Src Import)+ -> FilePath+ -> Status+makeEmptyStatus newManager headersExpr rootDirectory =+ emptyStatusWith newManager (originHeadersLoader headersExpr) fetchRemote fetchRemoteBytes rootImport+ where+ prefix = if FilePath.isRelative rootDirectory+ then Here+ else Absolute + pathComponents =+ fmap Text.pack (reverse (FilePath.splitDirectories rootDirectory))++ directoryAsFile = File (Directory pathComponents) "."++ rootImport = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local prefix directoryAsFile+ }+ , importMode = Code+ }++{-| Default `Status` appropriate for a server interpreting Dhall code++ Using this `Status` ensures that interpreted Dhall code cannot access+ server-local resources (like files or environment variables)+-}+remoteStatus+ :: URL+ -- ^ Public address of the server+ -> Status+remoteStatus = remoteStatusWithManager defaultNewManager++-- | See `remoteStatus`+remoteStatusWithManager :: IO Manager -> URL -> Status+remoteStatusWithManager newManager url =+ emptyStatusWith newManager (originHeadersLoader (pure emptyOriginHeaders)) fetchRemote fetchRemoteBytes rootImport+ where+ rootImport = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Remote url+ }+ , importMode = Code+ }+ {-| Generalized version of `load` You can configure the desired behavior through the initial `Status` that you@@ -1072,11 +1233,29 @@ ImportAlt a b -> loadWith a `catch` handler₀ where- handler₀ (SourcedException (Src begin _ text₀) (MissingImports es₀)) =- loadWith b `catch` handler₁+ is :: forall e . Exception e => SomeException -> Bool+ is exception = Maybe.isJust (Exception.fromException @e exception)++ isNotResolutionError exception =+ is @(Imported (TypeError Src Void)) exception+ || is @(Imported Cycle ) exception+ || is @(Imported HashMismatch ) exception+ || is @(Imported ParseError ) exception++ handler₀ exception₀@(SourcedException (Src begin _ text₀) (MissingImports es₀))+ | any isNotResolutionError es₀ =+ throwM exception₀+ | otherwise = do+ loadWith b `catch` handler₁ where- handler₁ (SourcedException (Src _ end text₁) (MissingImports es₁)) =- throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁)))+ handler₁ exception₁@(SourcedException (Src _ end text₁) (MissingImports es₁))+ | any isNotResolutionError es₁ =+ throwM exception₁+ | otherwise =+ -- Fix the source span for the error message to encompass both+ -- alternatives, since both are equally to blame for the+ -- failure if neither succeeds.+ throwM (SourcedException (Src begin end text₂) (MissingImports (es₀ ++ es₁))) where text₂ = text₀ <> " ? " <> text₁ @@ -1087,7 +1266,7 @@ Let a b -> Let <$> bindingExprs loadWith a <*> loadWith b Record m -> Record <$> traverse (recordFieldExprs loadWith) m RecordLit m -> RecordLit <$> traverse (recordFieldExprs loadWith) m- Lam a b -> Lam <$> functionBindingExprs loadWith a <*> loadWith b+ Lam cs a b -> Lam cs <$> functionBindingExprs loadWith a <*> loadWith b Field a b -> Field <$> loadWith a <*> pure b expression -> Syntax.unsafeSubExpressions loadWith expression @@ -1097,61 +1276,41 @@ -- | See 'load'. loadWithManager :: IO Manager -> Expr Src Import -> IO (Expr Src Void)-loadWithManager newManager = loadRelativeToWithManager newManager "." UseSemanticCache--printWarning :: (MonadIO m) => String -> m ()-printWarning message = do- let warning =- "\n"- <> "\ESC[1;33mWarning\ESC[0m: "- <> message-- liftIO $ System.IO.hPutStrLn System.IO.stderr warning+loadWithManager newManager =+ loadWithStatus+ (makeEmptyStatus newManager defaultOriginHeaders ".")+ UseSemanticCache -- | Resolve all imports within an expression, importing relative to the given -- directory. loadRelativeTo :: FilePath -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)-loadRelativeTo = loadRelativeToWithManager defaultNewManager+loadRelativeTo parentDirectory = loadWithStatus+ (makeEmptyStatus defaultNewManager defaultOriginHeaders parentDirectory) -- | See 'loadRelativeTo'.-loadRelativeToWithManager- :: IO Manager- -> FilePath+loadWithStatus+ :: Status -> SemanticCacheMode -> Expr Src Import -> IO (Expr Src Void)-loadRelativeToWithManager newManager rootDirectory semanticCacheMode expression =+loadWithStatus status semanticCacheMode expression = State.evalStateT (loadWith expression)- (emptyStatusWithManager newManager rootDirectory) { _semanticCacheMode = semanticCacheMode }+ status { _semanticCacheMode = semanticCacheMode } -encodeExpression- :: StandardVersion- -- ^ `NoVersion` means to encode without the version tag- -> Expr Void Void- -> Data.ByteString.ByteString-encodeExpression _standardVersion expression = bytesStrict+encodeExpression :: Expr Void Void -> Data.ByteString.ByteString+encodeExpression expression = bytesStrict where intermediateExpression :: Expr Void Import intermediateExpression = fmap absurd expression - encoding =- case _standardVersion of- NoVersion ->- Codec.Serialise.encode intermediateExpression- s ->- Encoding.encodeListLen 2- <> Encoding.encodeString v- <> Codec.Serialise.encode intermediateExpression- where- v = Dhall.Binary.renderStandardVersion s+ encoding = Codec.Serialise.encode intermediateExpression bytesStrict = Write.toStrictByteString encoding -- | Hash a fully resolved expression hashExpression :: Expr Void Void -> Dhall.Crypto.SHA256Digest-hashExpression expression =- Dhall.Crypto.sha256Hash (encodeExpression NoVersion expression)+hashExpression = Dhall.Crypto.sha256Hash . encodeExpression {-| Convenience utility to hash a fully resolved expression and return the base-16 encoded hash with the @sha256:@ prefix@@ -1173,6 +1332,7 @@ assertNoImports :: MonadIO io => Expr Src Import -> io (Expr Src Void) assertNoImports expression = Core.throws (traverse (\_ -> Left ImportResolutionDisabled) expression)+{-# INLINABLE assertNoImports #-} {-| This function is used by the @--transitive@ option of the @dhall {freeze,format,lint}@ subcommands to determine which dependencies@@ -1205,6 +1365,9 @@ -- types are not interpreted and therefore don't need to be modified case importMode child of RawText ->+ ignore++ RawBytes -> ignore Location ->
@@ -0,0 +1,129 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-}++module Dhall.Import.Headers+ ( normalizeHeaders+ , originHeadersTypeExpr+ , toHeaders+ , toOriginHeaders+ ) where++import Control.Applicative (Alternative (..), liftA2)+import Control.Exception (SomeException)+import Control.Monad.Catch (handle, throwM)+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Core (Chunks (..), Expr (..))+import Dhall.Import.Types (HTTPHeader, OriginHeaders)+import Dhall.Parser (Src (..))++import qualified Data.CaseInsensitive+import qualified Data.Foldable+import qualified Data.HashMap.Strict as HashMap+import qualified Data.Text.Encoding+import qualified Dhall.Core as Core+import qualified Dhall.Map+import qualified Dhall.Pretty.Internal+import qualified Dhall.TypeCheck++-- | Given a well-typed (of type `List { header : Text, value Text }` or+-- `List { mapKey : Text, mapValue Text }`) headers expressions in normal form+-- construct the corresponding binary http headers; otherwise return the empty+-- list.+toHeaders :: Expr s a -> [HTTPHeader]+toHeaders (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybeHeaders)+ where+ maybeHeaders = mapM toHeader hs+toHeaders _ = []++toHeader :: Expr s a -> Maybe HTTPHeader+toHeader (RecordLit m) = do+ (Core.recordFieldValue -> TextLit (Chunks [] keyText), Core.recordFieldValue -> TextLit (Chunks [] valueText))+ <- lookupHeader <|> lookupMapKey+ let keyBytes = Data.Text.Encoding.encodeUtf8 keyText+ let valueBytes = Data.Text.Encoding.encodeUtf8 valueText+ return (Data.CaseInsensitive.mk keyBytes, valueBytes)+ where+ lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)+ lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+toHeader _ =+ empty++-- | Normalize, typecheck and return OriginHeaders from a given expression.+toOriginHeaders :: Expr Src Void -> IO OriginHeaders+toOriginHeaders expr = fmap convert (normalizeOriginHeaders expr)+ where+ convert :: Expr s a -> OriginHeaders+ convert (ListLit _ hs) = HashMap.fromList (originPairs hs)+ convert _ = mempty++ originPairs hs = Data.Foldable.toList (Data.Foldable.fold (mapM toOriginPair hs))++ toOriginPair :: Expr s a -> Maybe (Text, [HTTPHeader])+ toOriginPair (RecordLit m) = do+ (Core.recordFieldValue -> TextLit (Chunks [] keyText), Core.recordFieldValue -> value)+ <- lookupMapKey+ return (keyText, toHeaders value)+ where+ lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+ toOriginPair _ = Nothing++makeHeadersTypeExpr :: Text -> Text -> Expr Src Void+makeHeadersTypeExpr keyKey valueKey =+ App List+ ( Record $ Core.makeRecordField <$>+ Dhall.Map.fromList+ [ (keyKey, Text)+ , (valueKey, Text)+ ]+ )++headersTypeExpr :: Expr Src Void+headersTypeExpr = makeHeadersTypeExpr "mapKey" "mapValue"++leagacyHeadersTypeExpr :: Expr Src Void+leagacyHeadersTypeExpr = makeHeadersTypeExpr "header" "value"++originHeadersTypeExpr :: Expr Src Void+originHeadersTypeExpr =+ App List+ ( Record $ Core.makeRecordField <$>+ Dhall.Map.fromList+ [ ("mapKey", Text)+ , ("mapValue", headersTypeExpr)+ ]+ )++typecheck :: Expr Src Void -> Expr Src Void -> IO (Expr Src Void)+typecheck expected expr = do+ let suffix_ = Dhall.Pretty.Internal.prettyToStrictText expected+ let annot = case expr of+ Note (Src begin end bytes) _ ->+ Note (Src begin end bytes') (Annot expr expected)+ where+ bytes' = bytes <> " : " <> suffix_+ _ ->+ Annot expr expected++ _ <- case (Dhall.TypeCheck.typeOf annot) of+ Left err -> throwM err+ Right _ -> return ()++ return (Core.normalize expr)++normalizeHeaders :: Expr Src Void -> IO (Expr Src Void)+normalizeHeaders headersExpr = do+ let handler₀ (e :: SomeException) = do+ {- Try to typecheck using the preferred @mapKey@/@mapValue@ fields+ and fall back to @header@/@value@ if that fails. However, if+ @header@/@value@ still fails then re-throw the original exception+ for @mapKey@ / @mapValue@. -}+ let handler₁ (_ :: SomeException) = throwM e+ handle handler₁ (typecheck leagacyHeadersTypeExpr headersExpr)++ handle handler₀ (typecheck headersTypeExpr headersExpr)++normalizeOriginHeaders :: Expr Src Void -> IO (Expr Src Void)+normalizeOriginHeaders = typecheck originHeadersTypeExpr
@@ -8,27 +8,23 @@ import Control.Exception (Exception) import Control.Monad.Trans.State.Strict (StateT)+import Data.ByteString (ByteString)+import Data.CaseInsensitive (CI) import Data.Dynamic+import Data.HashMap.Strict (HashMap) import Data.List.NonEmpty (NonEmpty)-import Data.Text.Prettyprint.Doc (Pretty (..)) import Data.Void (Void) import Dhall.Context (Context) import Dhall.Core- ( Directory (..)- , Expr- , File (..)- , FilePrefix (..)+ ( Expr , Import (..)- , ImportHashed (..)- , ImportMode (..)- , ImportType (..) , ReifiedNormalizer (..) , URL ) import Dhall.Map (Map) import Dhall.Parser (Src)-import Lens.Family (LensLike')-import System.FilePath (isRelative, splitDirectories)+import Lens.Micro (Lens', lens)+import Prettyprinter (Pretty (..)) #ifdef WITH_HTTP import qualified Dhall.Import.Manager@@ -54,7 +50,7 @@ pretty (Chained import_) = pretty import_ -- | An import that has been fully interpeted-data ImportSemantics = ImportSemantics+newtype ImportSemantics = ImportSemantics { importSemantics :: Expr Void Void -- ^ The fully resolved import, typechecked and beta-normal. }@@ -84,7 +80,17 @@ pure () #endif +-- | HTTP headers+type HTTPHeader = (CI ByteString, ByteString) +-- | A map of site origin -> HTTP headers+type OriginHeaders = HashMap Data.Text.Text [HTTPHeader]++{-| Used internally to track whether or not we've already warned the user about+ caching issues+-}+data CacheWarning = CacheNotWarned | CacheWarned+ -- | State threaded throughout the import process data Status = Status { _stack :: NonEmpty Chained@@ -104,9 +110,16 @@ -- ^ Used to cache the `Dhall.Import.Manager.Manager` when making multiple -- requests + , _loadOriginHeaders :: StateT Status IO OriginHeaders+ -- ^ Load the origin headers from environment or configuration file.+ -- After loading once, further evaluations return the cached version.+ , _remote :: URL -> StateT Status IO Data.Text.Text -- ^ The remote resolver, fetches the content at the given URL. + , _remoteBytes :: URL -> StateT Status IO Data.ByteString.ByteString+ -- ^ Like `_remote`, except for `Dhall.Syntax.Expr.Bytes`+ , _substitutions :: Dhall.Substitution.Substitutions Src Void , _normalizer :: Maybe (ReifiedNormalizer Void)@@ -114,12 +127,23 @@ , _startingContext :: Context (Expr Src Void) , _semanticCacheMode :: SemanticCacheMode++ , _cacheWarning :: CacheWarning+ -- ^ Records whether or not we already warned the user about issues with+ -- cache directory } --- | Initial `Status`, parameterised over the HTTP 'Manager' and the remote resolver,--- importing relative to the given directory.-emptyStatusWith :: IO Manager -> (URL -> StateT Status IO Data.Text.Text) -> FilePath -> Status-emptyStatusWith _newManager _remote rootDirectory = Status {..}+-- | Initial `Status`, parameterised over the HTTP 'Manager',+-- the origin headers and the remote resolver,+-- importing relative to the given root import.+emptyStatusWith+ :: IO Manager+ -> StateT Status IO OriginHeaders+ -> (URL -> StateT Status IO Data.Text.Text)+ -> (URL -> StateT Status IO Data.ByteString.ByteString)+ -> Import+ -> Status+emptyStatusWith _newManager _loadOriginHeaders _remote _remoteBytes rootImport = Status {..} where _stack = pure (Chained rootImport) @@ -137,53 +161,43 @@ _semanticCacheMode = UseSemanticCache - prefix = if isRelative rootDirectory- then Here- else Absolute- pathComponents =- fmap Data.Text.pack (reverse (splitDirectories rootDirectory))-- dirAsFile = File (Directory pathComponents) "."-- -- Fake import to set the directory we're relative to.- rootImport = Import- { importHashed = ImportHashed- { hash = Nothing- , importType = Local prefix dirAsFile- }- , importMode = Code- }+ _cacheWarning = CacheNotWarned -- | Lens from a `Status` to its `_stack` field-stack :: Functor f => LensLike' f Status (NonEmpty Chained)-stack k s = fmap (\x -> s { _stack = x }) (k (_stack s))+stack :: Lens' Status (NonEmpty Chained)+stack = lens _stack (\s x -> s { _stack = x }) -- | Lens from a `Status` to its `_graph` field-graph :: Functor f => LensLike' f Status [Depends]-graph k s = fmap (\x -> s { _graph = x }) (k (_graph s))+graph :: Lens' Status [Depends]+graph = lens _graph (\s x -> s { _graph = x }) -- | Lens from a `Status` to its `_cache` field-cache :: Functor f => LensLike' f Status (Map Chained ImportSemantics)-cache k s = fmap (\x -> s { _cache = x }) (k (_cache s))+cache :: Lens' Status (Map Chained ImportSemantics)+cache = lens _cache (\s x -> s { _cache = x }) -- | Lens from a `Status` to its `_remote` field-remote- :: Functor f => LensLike' f Status (URL -> StateT Status IO Data.Text.Text)-remote k s = fmap (\x -> s { _remote = x }) (k (_remote s))+remote :: Lens' Status (URL -> StateT Status IO Data.Text.Text)+remote = lens _remote (\s x -> s { _remote = x }) +-- | Lens from a `Status` to its `_remote` field+remoteBytes :: Lens' Status (URL -> StateT Status IO Data.ByteString.ByteString)+remoteBytes = lens _remoteBytes (\s x -> s { _remoteBytes = x })+ -- | Lens from a `Status` to its `_substitutions` field-substitutions :: Functor f => LensLike' f Status (Dhall.Substitution.Substitutions Src Void)-substitutions k s =- fmap (\x -> s { _substitutions = x }) (k (_substitutions s))+substitutions :: Lens' Status (Dhall.Substitution.Substitutions Src Void)+substitutions = lens _substitutions (\s x -> s { _substitutions = x }) -- | Lens from a `Status` to its `_normalizer` field-normalizer :: Functor f => LensLike' f Status (Maybe (ReifiedNormalizer Void))-normalizer k s = fmap (\x -> s {_normalizer = x}) (k (_normalizer s))+normalizer :: Lens' Status (Maybe (ReifiedNormalizer Void))+normalizer = lens _normalizer (\s x -> s {_normalizer = x}) -- | Lens from a `Status` to its `_startingContext` field-startingContext :: Functor f => LensLike' f Status (Context (Expr Src Void))-startingContext k s =- fmap (\x -> s { _startingContext = x }) (k (_startingContext s))+startingContext :: Lens' Status (Context (Expr Src Void))+startingContext = lens _startingContext (\s x -> s { _startingContext = x })++-- | Lens from a `Status` to its `_cacheWarning` field+cacheWarning :: Lens' Status CacheWarning+cacheWarning = lens _cacheWarning (\s x -> s { _cacheWarning = x }) {-| This exception indicates that there was an internal error in Dhall's import-related logic
@@ -39,9 +39,8 @@ import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Text as Text import qualified Dhall.Core as Core-import qualified Dhall.Map as Map-import qualified Dhall.Optics-import qualified Lens.Family+import qualified Dhall.Map+import qualified Lens.Micro as Lens {-| Automatically improve a Dhall expression @@ -52,8 +51,8 @@ * consolidates nested @let@ bindings to use a multiple-@let@ binding with 'removeLetInLet' * fixes paths of the form @.\/..\/foo@ to @..\/foo@ -}-lint :: Expr s Import -> Expr s Import-lint = Dhall.Optics.rewriteOf subExpressions rewrite+lint :: Eq s => Expr s Import -> Expr s Import+lint = Lens.rewriteOf subExpressions rewrite where rewrite e = fixAssert e@@ -144,7 +143,7 @@ isOrContainsAssert :: Expr s a -> Bool isOrContainsAssert (Assert _) = True-isOrContainsAssert e = Lens.Family.anyOf subExpressions isOrContainsAssert e+isOrContainsAssert e = Lens.anyOf subExpressions isOrContainsAssert e -- | The difference between --@@ -176,7 +175,7 @@ (Core.shallowDenote -> App (Core.shallowDenote -> List) (Core.shallowDenote -> Record- (Map.sort ->+ (Dhall.Map.sort -> [ ("mapKey", Core.shallowDenote . Core.recordFieldValue -> Text) , ("mapValue", _) ]@@ -192,14 +191,14 @@ , Just keyValues' <- traverse convert keyValues = Just (ToMap- (RecordLit (Map.fromList (Foldable.toList keyValues')))+ (RecordLit (Dhall.Map.fromList (Foldable.toList keyValues'))) Nothing ) where convert keyValue = case Core.shallowDenote keyValue of RecordLit- (Map.sort ->+ (Dhall.Map.sort -> [ ("mapKey" , Core.shallowDenote . Core.recordFieldValue -> TextLit (Chunks [] key)) , ("mapValue", value) ]
@@ -21,34 +21,39 @@ , main ) where -import Control.Applicative (optional, (<|>))-import Control.Exception (Handler (..), SomeException)-import Control.Monad (when)-import Data.Foldable (for_)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Void (Void)-import Dhall.Freeze (Intent (..), Scope (..))+import Control.Applicative (optional, (<|>))+import Control.Exception (Handler (..), SomeException)+import Control.Monad (when)+import Data.Foldable (for_)+import Data.List.NonEmpty (NonEmpty (..), nonEmpty)+import Data.Maybe (fromMaybe)+import Data.Monoid (Endo (..))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Freeze (Intent (..), Scope (..)) import Dhall.Import ( Depends (..) , Imported (..) , SemanticCacheMode (..) , _semanticCacheMode )-import Dhall.Parser (Src)-import Dhall.Pretty (Ann, CharacterSet (..), annToAnsiStyle)-import Dhall.Schemas (Schemas (..))-import Dhall.TypeCheck- ( Censored (..)- , DetailedTypeError (..)- , TypeError+import Dhall.Package (PackagingMode (..), writePackage)+import Dhall.Parser (Src)+import Dhall.Pretty+ ( Ann+ , CharacterSet (..)+ , annToAnsiStyle+ , detectCharacterSet )-import Dhall.Version (dhallVersionString)-import Options.Applicative (Parser, ParserInfo)-import System.Exit (ExitCode, exitFailure)-import System.IO (Handle)-import Text.Dot ((.->.))+import Dhall.Schemas (Schemas (..))+import Dhall.TypeCheck (Censored (..), DetailedTypeError (..), TypeError)+import Dhall.Version (dhallVersionString)+import Lens.Micro (set)+import Options.Applicative (Parser, ParserInfo)+import Prettyprinter (Doc, Pretty)+import System.Exit (ExitCode, exitFailure)+import System.IO (Handle)+import Text.Dot ((.->.)) import Dhall.Core ( Expr (Annot)@@ -65,15 +70,15 @@ , Input (..) , Output (..) , OutputMode (..)- , PossiblyTransitiveInput (..) , Transitivity (..)+ , handleMultipleChecksFailed ) import qualified Codec.CBOR.JSON import qualified Codec.CBOR.Read import qualified Codec.CBOR.Write import qualified Control.Exception-import qualified Control.Monad.Trans.State.Strict as State+import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Aeson import qualified Data.Aeson.Encode.Pretty import qualified Data.ByteString.Lazy@@ -81,20 +86,18 @@ import qualified Data.Map import qualified Data.Text import qualified Data.Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text import qualified Dhall import qualified Dhall.Binary import qualified Dhall.Core import qualified Dhall.Diff-import qualified Dhall.DirectoryTree as DirectoryTree+import qualified Dhall.DirectoryTree as DirectoryTree import qualified Dhall.Format import qualified Dhall.Freeze import qualified Dhall.Import import qualified Dhall.Import.Types import qualified Dhall.Lint import qualified Dhall.Map+import qualified Dhall.Package import qualified Dhall.Pretty import qualified Dhall.Repl import qualified Dhall.Schemas@@ -103,9 +106,12 @@ import qualified Dhall.Util import qualified GHC.IO.Encoding import qualified Options.Applicative-import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite.LazyText import qualified System.Console.ANSI-import qualified System.Exit as Exit+import qualified System.Exit as Exit import qualified System.FilePath import qualified System.IO import qualified Text.Dot@@ -113,19 +119,13 @@ -- | Top-level program options data Options = Options- { mode :: Mode- , explain :: Bool- , plain :: Bool- , ascii :: Bool- , censor :: Censor+ { mode :: Mode+ , explain :: Bool+ , plain :: Bool+ , chosenCharacterSet :: Maybe CharacterSet+ , censor :: Censor } -ignoreSemanticCache :: Mode -> Bool-ignoreSemanticCache Default {..} = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache Resolve {..} = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache Type {..} = semanticCacheMode == IgnoreSemanticCache-ignoreSemanticCache _ = False- -- | The subcommands for the @dhall@ executable data Mode = Default@@ -149,11 +149,11 @@ } | Normalize { file :: Input , alpha :: Bool } | Repl- | Format { possiblyTransitiveInput :: PossiblyTransitiveInput, outputMode :: OutputMode }- | Freeze { possiblyTransitiveInput :: PossiblyTransitiveInput, all_ :: Bool, cache :: Bool, outputMode :: OutputMode }- | Hash { file :: Input }+ | Format { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input }+ | Freeze { deprecatedInPlace :: Bool, transitivity :: Transitivity, all_ :: Bool, cache :: Bool, outputMode :: OutputMode, inputs :: NonEmpty Input }+ | Hash { file :: Input, cache :: Bool } | Diff { expr1 :: Text, expr2 :: Text }- | Lint { possiblyTransitiveInput :: PossiblyTransitiveInput, outputMode :: OutputMode }+ | Lint { deprecatedInPlace :: Bool, transitivity :: Transitivity, outputMode :: OutputMode, inputs :: NonEmpty Input } | Tags { input :: Input , output :: Output@@ -163,9 +163,13 @@ | Encode { file :: Input, json :: Bool } | Decode { file :: Input, json :: Bool, quiet :: Bool } | Text { file :: Input, output :: Output }- | DirectoryTree { file :: Input, path :: FilePath }+ | DirectoryTree { allowSeparators :: Bool, file :: Input, path :: FilePath } | Schemas { file :: Input, outputMode :: OutputMode, schemas :: Text } | SyntaxTree { file :: Input, noted :: Bool }+ | Package+ { packageOptions :: Endo Dhall.Package.Options+ , packageFiles :: NonEmpty FilePath+ } -- | This specifies how to resolve transitive dependencies data ResolveMode@@ -201,7 +205,7 @@ <$> parseMode <*> switch "explain" "Explain error messages in more detail" <*> switch "plain" "Disable syntax highlighting"- <*> switch "ascii" "Format code using only ASCII syntax"+ <*> parseCharacterSet <*> parseCensor where switch name description =@@ -215,6 +219,19 @@ f True = Censor f False = NoCensor + parseCharacterSet =+ Options.Applicative.flag'+ (Just Unicode)+ ( Options.Applicative.long "unicode"+ <> Options.Applicative.help "Format code using only Unicode syntax"+ )+ <|> Options.Applicative.flag'+ (Just ASCII)+ ( Options.Applicative.long "ascii"+ <> Options.Applicative.help "Format code using only ASCII syntax"+ )+ <|> pure Nothing+ subcommand :: Group -> String -> String -> Parser a -> Parser a subcommand group name description parser = Options.Applicative.hsubparser@@ -235,17 +252,17 @@ Manipulate "format" "Standard code formatter for the Dhall language"- (Format <$> parseInplaceTransitive <*> parseCheck "formatted")+ (Format <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "formatted" <*> parseFiles) <|> subcommand Manipulate "freeze" "Add integrity checks to remote import statements of an expression"- (Freeze <$> parseInplaceTransitive <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen")+ (Freeze <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseAllFlag <*> parseCacheFlag <*> parseCheck "frozen" <*> parseFiles) <|> subcommand Manipulate "lint" "Improve Dhall code by using newer language features and removing dead code"- (Lint <$> parseInplaceTransitive <*> parseCheck "linted")+ (Lint <$> deprecatedInPlace <*> parseTransitiveSwitch <*> parseCheck "linted" <*> parseFiles) <|> subcommand Manipulate "rewrite-with-schemas"@@ -260,7 +277,7 @@ Generate "to-directory-tree" "Convert nested records of Text literals into a directory tree"- (DirectoryTree <$> parseFile <*> parseDirectoryTreeOutput)+ (DirectoryTree <$> parseDirectoryTreeAllowSeparators <*> parseFile <*> parseDirectoryTreeOutput) <|> subcommand Interpret "resolve"@@ -300,9 +317,14 @@ Miscellaneous "hash" "Compute semantic hashes for Dhall expressions"- (Hash <$> parseFile)+ (Hash <$> parseFile <*> parseCache) <|> subcommand Miscellaneous+ "package"+ "Create a package.dhall referencing the provided paths"+ (Package <$> parsePackageOptions <*> parsePackageFiles)+ <|> subcommand+ Miscellaneous "tags" "Generate etags file" (Tags <$> parseInput <*> parseTagsOutput <*> parseSuffixes <*> parseFollowSymlinks)@@ -325,6 +347,12 @@ <*> parseVersion ) where+ deprecatedInPlace =+ Options.Applicative.switch+ ( Options.Applicative.long "inplace"+ <> Options.Applicative.internal -- completely hidden from help+ )+ argument = fmap Data.Text.pack . Options.Applicative.strArgument@@ -342,6 +370,21 @@ <> Options.Applicative.action "file" ) + parseFiles = fmap f (Options.Applicative.many p)+ where+ -- Parse explicit stdin in the input filepaths+ parseStdin inputs+ | InputFile "-" `elem` inputs = StandardInput : filter (/= InputFile "-") inputs+ | otherwise = inputs++ f = fromMaybe (pure StandardInput) . nonEmpty . parseStdin . fmap InputFile++ p = Options.Applicative.strArgument+ ( Options.Applicative.help "Read expression from files instead of standard input"+ <> Options.Applicative.metavar "FILES"+ <> Options.Applicative.action "file"+ )+ parseOutput = fmap f (optional p) where f Nothing = StandardOutput@@ -415,22 +458,15 @@ <> Options.Applicative.action "file" ) + parseTransitiveSwitch = Options.Applicative.flag NonTransitive Transitive+ ( Options.Applicative.long "transitive"+ <> Options.Applicative.help "Modify the input and its transitive relative imports in-place"+ )+ parseInplaceNonTransitive = fmap InputFile parseInplace <|> pure StandardInput - parseInplaceTransitive =- fmap (\f -> PossiblyTransitiveInputFile f NonTransitive) parseInplace- <|> fmap (\f -> PossiblyTransitiveInputFile f Transitive) parseTransitive- <|> pure NonTransitiveStandardInput- where- parseTransitive = Options.Applicative.strOption- ( Options.Applicative.long "transitive"- <> Options.Applicative.help "Modify the specified file and its transitive relative imports in-place"- <> Options.Applicative.metavar "FILE"- <> Options.Applicative.action "file"- )- parseInput = fmap f (optional p) where f Nothing = StandardInput@@ -483,7 +519,7 @@ parseAllFlag = Options.Applicative.switch ( Options.Applicative.long "all"- <> Options.Applicative.help "Add integrity checks to all imports (not just remote imports)"+ <> Options.Applicative.help "Add integrity checks to all imports (not just remote imports) except for missing imports" ) parseCacheFlag =@@ -510,6 +546,12 @@ <> Options.Applicative.metavar "EXPR" ) + parseDirectoryTreeAllowSeparators =+ Options.Applicative.switch+ ( Options.Applicative.long "allow-path-separators"+ <> Options.Applicative.help "Whether to allow path separators in file names"+ )+ parseDirectoryTreeOutput = Options.Applicative.strOption ( Options.Applicative.long "output"@@ -524,6 +566,39 @@ <> Options.Applicative.help "Print `Note` constructors" ) + parseCache =+ Options.Applicative.switch+ ( Options.Applicative.long "cache"+ <> Options.Applicative.help "Cache the hashed expression"+ )++ parsePackageOptions :: Parser (Endo Dhall.Package.Options)+ parsePackageOptions = do+ packageMode <- (optional . Options.Applicative.flag' RecursiveSubpackages)+ ( Options.Applicative.short 'r'+ <> Options.Applicative.long "recursive"+ <> Options.Applicative.help "Create packages for all subdirectories first."+ )++ packageFileName <- (optional . Options.Applicative.strOption)+ ( Options.Applicative.long "name"+ <> Options.Applicative.help "The filename of the package"+ <> Options.Applicative.metavar "NAME"+ <> Options.Applicative.action "file"+ )++ pure $+ maybe mempty (Endo . set Dhall.Package.packagingMode) packageMode <>+ maybe mempty (Endo . set Dhall.Package.packageFileName) packageFileName++ parsePackageFiles = (:|) <$> p <*> Options.Applicative.many p+ where+ p = Options.Applicative.strArgument+ ( Options.Applicative.help "Paths that may either point to files or directories. If the latter is the case all *.dhall files in the directory will be included."+ <> Options.Applicative.metavar "PATH"+ <> Options.Applicative.action "file"+ )+ -- | `ParserInfo` for the `Options` type parserInfoOptions :: ParserInfo Options parserInfoOptions =@@ -543,10 +618,6 @@ -- | Run the command specified by the `Options` type command :: Options -> IO () command (Options {..}) = do- let characterSet = case ascii of- True -> ASCII- False -> Unicode- GHC.IO.Encoding.setLocaleEncoding System.IO.utf8 let rootDirectory = \case@@ -557,6 +628,16 @@ let getExpression = Dhall.Util.getExpression censor + -- The characterSet detection used here only works on the source+ -- expression, before any transformation is applied. This helper is there+ -- make sure the detection is done on the correct expr.+ let getExpressionAndCharacterSet file = do+ expr <- getExpression file++ let characterSet = fromMaybe (detectCharacterSet expr) chosenCharacterSet++ return (expr, characterSet)+ let handle io = Control.Exception.catches io [ Handler handleTypeError@@ -613,8 +694,8 @@ Pretty.renderIO h ansiStream Data.Text.IO.hPutStrLn h "" - let render :: Pretty a => Handle -> Expr Src a -> IO ()- render h expression = do+ let render :: Pretty a => Handle -> CharacterSet -> Expr Src a -> IO ()+ render h characterSet expression = do let doc = Dhall.Pretty.prettyCharacterSet characterSet expression renderDoc h doc@@ -625,8 +706,6 @@ AtomicWrite.LazyText.atomicWriteFile file (Pretty.Text.renderLazy stream) - when (not $ ignoreSemanticCache mode) Dhall.Import.warnAboutMissingCaches- handle $ case mode of Version -> putStrLn dhallVersionString@@ -638,7 +717,7 @@ Exit.exitSuccess else return () - expression <- getExpression file+ (expression, characterSet) <- getExpressionAndCharacterSet file resolvedExpression <- Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression@@ -658,7 +737,7 @@ else alphaNormalizedExpression case output of- StandardOutput -> render System.IO.stdout annotatedExpression+ StandardOutput -> render System.IO.stdout characterSet annotatedExpression OutputFile file_ -> writeDocToFile@@ -717,15 +796,15 @@ $ _cache Resolve { resolveMode = Nothing, ..} -> do- expression <- getExpression file+ (expression, characterSet) <- getExpressionAndCharacterSet file resolvedExpression <- Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression - render System.IO.stdout resolvedExpression+ render System.IO.stdout characterSet resolvedExpression Normalize {..} -> do- expression <- getExpression file+ (expression, characterSet) <- getExpressionAndCharacterSet file resolvedExpression <- Dhall.Import.assertNoImports expression @@ -738,10 +817,10 @@ then Dhall.Core.alphaNormalize normalizedExpression else normalizedExpression - render System.IO.stdout alphaNormalizedExpression+ render System.IO.stdout characterSet alphaNormalizedExpression Type {..} -> do- expression <- getExpression file+ (expression, characterSet) <- getExpressionAndCharacterSet file resolvedExpression <- Dhall.Import.loadRelativeTo (rootDirectory file) semanticCacheMode expression@@ -750,10 +829,12 @@ if quiet then return ()- else render System.IO.stdout inferredType+ else render System.IO.stdout characterSet inferredType Repl ->- Dhall.Repl.repl characterSet explain+ Dhall.Repl.repl+ (fromMaybe Unicode chosenCharacterSet) -- Default to Unicode if no characterSet specified+ explain Diff {..} -> do expression1 <- Dhall.inputExpr expr1@@ -768,16 +849,21 @@ then return () else Exit.exitFailure - Format {..} ->- Dhall.Format.format- Dhall.Format.Format{ input = possiblyTransitiveInput, ..}+ Format {..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated" + Dhall.Format.format Dhall.Format.Format{..}+ Freeze {..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"+ let scope = if all_ then AllImports else OnlyRemoteImports let intent = if cache then Cache else Secure - Dhall.Freeze.freeze outputMode possiblyTransitiveInput scope intent characterSet censor+ Dhall.Freeze.freeze outputMode transitivity inputs scope intent chosenCharacterSet censor Hash {..} -> do expression <- getExpression file@@ -790,37 +876,47 @@ let normalizedExpression = Dhall.Core.alphaNormalize (Dhall.Core.normalize resolvedExpression) + if cache+ then Dhall.Import.writeExpressionToSemanticCache normalizedExpression+ else return ()+ Data.Text.IO.putStrLn (Dhall.Import.hashExpressionToCode normalizedExpression) - Lint { possiblyTransitiveInput = input0, ..} -> go input0+ Lint { transitivity = transitivity0, ..} -> do+ when deprecatedInPlace $+ System.IO.hPutStrLn System.IO.stderr "Warning: the flag \"--inplace\" is deprecated"++ handleMultipleChecksFailed "lint" "linted" go inputs where go input = do let directory = case input of- NonTransitiveStandardInput -> "."- PossiblyTransitiveInputFile file _ -> System.FilePath.takeDirectory file+ StandardInput -> "."+ InputFile file -> System.FilePath.takeDirectory file let status = Dhall.Import.emptyStatus directory - (originalText, transitivity) <- case input of- PossiblyTransitiveInputFile file transitivity -> do+ (inputName, originalText, transitivity) <- case input of+ InputFile file -> do text <- Data.Text.IO.readFile file - return (text, transitivity)- NonTransitiveStandardInput -> do+ return (file, text, transitivity0)+ StandardInput -> do text <- Data.Text.IO.getContents - return (text, NonTransitive)+ return ("(input)", text, NonTransitive) (Header header, parsedExpression) <-- Dhall.Util.getExpressionAndHeaderFromStdinText censor originalText+ Dhall.Util.getExpressionAndHeaderFromStdinText censor inputName originalText + let characterSet = fromMaybe (detectCharacterSet parsedExpression) chosenCharacterSet+ case transitivity of Transitive -> for_ parsedExpression $ \import_ -> do maybeFilepath <- Dhall.Import.dependencyToFile status import_ for_ maybeFilepath $ \filepath ->- go (PossiblyTransitiveInputFile filepath Transitive)+ go (InputFile filepath) NonTransitive -> return ()@@ -835,23 +931,23 @@ let modifiedText = Pretty.Text.renderStrict stream <> "\n" case outputMode of- Write ->+ Write -> do case input of- PossiblyTransitiveInputFile file _ ->+ InputFile file -> if originalText == modifiedText then return () else writeDocToFile file doc - NonTransitiveStandardInput ->+ StandardInput -> renderDoc System.IO.stdout doc - Check ->- if originalText == modifiedText- then return ()- else do- let modified = "linted"+ return (Right ()) - Control.Exception.throwIO CheckFailed{ command = "lint", ..}+ Check ->+ return $+ if originalText == modifiedText+ then Right ()+ else Left CheckFailed{..} Encode {..} -> do expression <- getExpression file@@ -898,7 +994,7 @@ else do let doc = Dhall.Pretty.prettyCharacterSet- characterSet+ (fromMaybe Unicode chosenCharacterSet) -- default to Unicode (Dhall.Core.renote expression :: Expr Src Import) renderDoc System.IO.stdout doc@@ -947,7 +1043,7 @@ let normalizedExpression = Dhall.Core.normalize resolvedExpression - DirectoryTree.toDirectoryTree path normalizedExpression+ DirectoryTree.toDirectoryTree allowSeparators path normalizedExpression Dhall.Main.Schemas{..} -> Dhall.Schemas.schemasCommand Dhall.Schemas.Schemas{ input = file, ..}@@ -961,6 +1057,13 @@ let denoted :: Expr Void Import denoted = Dhall.Core.denote expression in Text.Pretty.Simple.pPrintNoColor denoted++ Package {..} -> do+ let options = appEndo+ (maybe mempty (Endo . set Dhall.Package.characterSet) chosenCharacterSet+ <> packageOptions+ ) Dhall.Package.defaultOptions+ writePackage options packageFiles -- | Entry point for the @dhall@ executable main :: IO ()
@@ -1,9 +1,11 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE ExplicitForAll #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-} -- | `Map` type used to represent records and unions @@ -33,6 +35,7 @@ -- * Deletion/Update , delete , filter+ , partition , restrictKeys , withoutKeys , mapMaybe@@ -75,9 +78,12 @@ import Language.Haskell.TH.Syntax (Lift) import Prelude hiding (filter, lookup) +import qualified Data.Foldable.WithIndex as Foldable.WithIndex+import qualified Data.Functor.WithIndex as Functor.WithIndex import qualified Data.List-import qualified Data.Map+import qualified Data.Map.Strict import qualified Data.Set+import qualified Data.Traversable.WithIndex as Traversable.WithIndex import qualified GHC.Exts import qualified Prelude @@ -88,7 +94,7 @@ This is done primarily to avoid a dependency on @insert-ordered-containers@ and also to improve performance -}-data Map k v = Map (Data.Map.Map k v) (Keys k)+data Map k v = Map (Data.Map.Strict.Map k v) (Keys k) deriving (Data, Generic, Lift, NFData) data Keys a@@ -98,7 +104,7 @@ instance (Ord k, Eq v) => Eq (Map k v) where m1 == m2 =- Data.Map.size (toMap m1) == Data.Map.size (toMap m2)+ Data.Map.Strict.size (toMap m1) == Data.Map.Strict.size (toMap m2) && toList m1 == toList m2 {-# INLINABLE (==) #-} @@ -141,7 +147,7 @@ prop> \x -> mempty <> x == (x :: Map Int Int) -} instance Ord k => Monoid (Map k v) where- mempty = Map Data.Map.empty (Original [])+ mempty = Map Data.Map.Strict.empty (Original []) {-# INLINABLE mempty #-} instance (Show k, Show v, Ord k) => Show (Map k v) where@@ -157,6 +163,18 @@ toList = Dhall.Map.toList +instance Ord k => Foldable.WithIndex.FoldableWithIndex k (Map k) where+ ifoldMap = foldMapWithKey+ {-# INLINABLE ifoldMap #-}++instance Functor.WithIndex.FunctorWithIndex k (Map k) where+ imap = mapWithKey+ {-# INLINABLE imap #-}++instance Ord k => Traversable.WithIndex.TraversableWithIndex k (Map k) where+ itraverse = traverseWithKey+ {-# INLINABLE itraverse #-}+ -- | Create an empty `Map` empty :: Ord k => Map k v empty = mempty@@ -169,7 +187,7 @@ singleton :: k -> v -> Map k v singleton k v = Map m ks where- m = Data.Map.singleton k v+ m = Data.Map.Strict.singleton k v ks = Original [k] {-# INLINABLE singleton #-}@@ -193,7 +211,7 @@ fromList :: Ord k => [(k, v)] -> Map k v fromList kvs = Map m ks where- m = Data.Map.fromList kvs+ m = Data.Map.Strict.fromList kvs ks = Original (nubOrd (map fst kvs)) {-# INLINABLE fromList #-}@@ -206,13 +224,13 @@ fromListWithKey :: Ord k => (k -> v -> v -> v) -> [(k, v)] -> Map k v fromListWithKey f kvs = Map m ks where- m = Data.Map.fromListWithKey f kvs+ m = Data.Map.Strict.fromListWithKey f kvs ks = Original (nubOrd (map fst kvs)) {-# INLINABLE fromListWithKey #-} --- | Create a `Map` from a @"Data.Map".`Data.Map.Map`@-fromMap :: Data.Map.Map k v -> Map k v+-- | Create a `Map` from a @"Data.Map.Strict".`Data.Map.Strict.Map`@+fromMap :: Data.Map.Strict.Map k v -> Map k v fromMap m = Map m Sorted {-| Remove duplicates from a list@@ -241,7 +259,7 @@ unorderedSingleton :: k -> v -> Map k v unorderedSingleton k v = Map m Sorted where- m = Data.Map.singleton k v+ m = Data.Map.Strict.singleton k v {-# INLINABLE unorderedSingleton #-} {-| Create a `Map` from a list of key-value pairs@@ -258,7 +276,7 @@ unorderedFromList :: Ord k => [(k, v)] -> Map k v unorderedFromList kvs = Map m Sorted where- m = Data.Map.fromList kvs+ m = Data.Map.Strict.fromList kvs {-# INLINABLE unorderedFromList #-} {-| Sort the keys of a `Map`, forgetting the original ordering@@ -283,7 +301,7 @@ -} isSorted :: Eq k => Map k v -> Bool isSorted (Map _ Sorted) = True-isSorted (Map m (Original ks)) = Data.Map.keys m == ks -- Or shortcut to False here?+isSorted (Map m (Original ks)) = Data.Map.Strict.keys m == ks -- Or shortcut to False here? {-# INLINABLE isSorted #-} {-| Insert a key-value pair into a `Map`, overriding any previous value stored@@ -297,10 +315,10 @@ fromList [("C",1),("A",3)] -} insert :: Ord k => k -> v -> Map k v -> Map k v-insert k v (Map m Sorted) = Map (Data.Map.insert k v m) Sorted+insert k v (Map m Sorted) = Map (Data.Map.Strict.insert k v m) Sorted insert k v (Map m (Original ks)) = Map m' (Original ks') where- (mayOldV, m') = Data.Map.insertLookupWithKey (\_k new _old -> new) k v m+ (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new _old -> new) k v m ks' | Just _ <- mayOldV = ks | otherwise = k : ks@@ -315,10 +333,10 @@ fromList [("C",3),("A",3)] -} insertWith :: Ord k => (v -> v -> v) -> k -> v -> Map k v -> Map k v-insertWith f k v (Map m Sorted) = Map (Data.Map.insertWith f k v m) Sorted+insertWith f k v (Map m Sorted) = Map (Data.Map.Strict.insertWith f k v m) Sorted insertWith f k v (Map m (Original ks)) = Map m' (Original ks') where- (mayOldV, m') = Data.Map.insertLookupWithKey (\_k new old -> f new old) k v m+ (mayOldV, m') = Data.Map.Strict.insertLookupWithKey (\_k new old -> f new old) k v m ks' | Just _ <- mayOldV = ks | otherwise = k : ks@@ -334,7 +352,7 @@ delete :: Ord k => k -> Map k v -> Map k v delete k (Map m ks) = Map m' ks' where- m' = Data.Map.delete k m+ m' = Data.Map.Strict.delete k m ks' = case ks of Sorted -> Sorted@@ -351,11 +369,26 @@ filter :: Ord k => (a -> Bool) -> Map k a -> Map k a filter predicate (Map m ks) = Map m' ks' where- m' = Data.Map.filter predicate m+ m' = Data.Map.Strict.filter predicate m - ks' = filterKeys (\k -> Data.Map.member k m') ks+ ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE filter #-} +{-| Split the map into values that do and don't satisfy the predicate++>>> partition even (fromList [("C",3),("B",2),("A",1)])+(fromList [("B",2)],fromList [("C",3),("A",1)])+>>> partition odd (fromList [("C",3),("B",2),("A",1)])+(fromList [("C",3),("A",1)],fromList [("B",2)])+-}+partition :: Ord k => (a -> Bool) -> Map k a -> (Map k a, Map k a)+partition predicate (Map m ks) = (Map mpass kpass, Map mfail kfail)+ where+ (mpass, mfail) = Data.Map.Strict.partition predicate m++ (kpass, kfail) = partitionKeys (\k -> Data.Map.Strict.member k mpass) ks+{-# INLINABLE partition #-}+ {-| Restrict a 'Map' to only those keys found in a @"Data.Set".'Data.Set.Set'@. >>> restrictKeys (fromList [("A",1),("B",2)]) (Data.Set.fromList ["A"])@@ -364,7 +397,7 @@ restrictKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a restrictKeys (Map m ks) s = Map m' ks' where- m' = Data.Map.restrictKeys m s+ m' = Data.Map.Strict.restrictKeys m s ks' = filterKeys (\k -> Data.Set.member k s) ks {-# INLINABLE restrictKeys #-}@@ -377,7 +410,7 @@ withoutKeys :: Ord k => Map k a -> Data.Set.Set k -> Map k a withoutKeys (Map m ks) s = Map m' ks' where- m' = Data.Map.withoutKeys m s+ m' = Data.Map.Strict.withoutKeys m s ks' = filterKeys (\k -> Data.Set.notMember k s) ks {-# INLINABLE withoutKeys #-}@@ -391,9 +424,9 @@ mapMaybe :: Ord k => (a -> Maybe b) -> Map k a -> Map k b mapMaybe f (Map m ks) = Map m' ks' where- m' = Data.Map.mapMaybe f m+ m' = Data.Map.Strict.mapMaybe f m - ks' = filterKeys (\k -> Data.Map.member k m') ks+ ks' = filterKeys (\k -> Data.Map.Strict.member k m') ks {-# INLINABLE mapMaybe #-} {-| Retrieve a key from a `Map`@@ -408,7 +441,7 @@ Nothing -} lookup :: Ord k => k -> Map k v -> Maybe v-lookup k (Map m _) = Data.Map.lookup k m+lookup k (Map m _) = Data.Map.Strict.lookup k m {-# INLINABLE lookup #-} {-| Retrieve the first key, value of the 'Map', if present,@@ -426,9 +459,9 @@ uncons :: Ord k => Map k v -> Maybe (k, v, Map k v) uncons (Map _ (Original [])) = Nothing uncons (Map m (Original (k:ks))) =- Just (k, m Data.Map.! k, Map (Data.Map.delete k m) (Original ks))+ Just (k, m Data.Map.Strict.! k, Map (Data.Map.Strict.delete k m) (Original ks)) uncons (Map m Sorted)- | Just ((k, v), m') <- Data.Map.minViewWithKey m = Just (k, v, Map m' Sorted)+ | Just ((k, v), m') <- Data.Map.Strict.minViewWithKey m = Just (k, v, Map m' Sorted) | otherwise = Nothing {-# INLINABLE uncons #-} @@ -444,7 +477,7 @@ False -} member :: Ord k => k -> Map k v -> Bool-member k (Map m _) = Data.Map.member k m+member k (Map m _) = Data.Map.Strict.member k m {-# INLINABLE member #-} {-|@@ -452,7 +485,7 @@ 1 -} size :: Map k v -> Int-size (Map m _) = Data.Map.size m+size (Map m _) = Data.Map.Strict.size m {-# INLINABLE size #-} {-| Combine two `Map`s, preferring keys from the first `Map`@@ -467,11 +500,11 @@ union :: Ord k => Map k v -> Map k v -> Map k v union (Map mL ksL) (Map mR ksR) = Map m ks where- m = Data.Map.union mL mR+ m = Data.Map.Strict.union mL mR ks = case (ksL, ksR) of (Original l, Original r) -> Original $- l <|> Prelude.filter (\k -> Data.Map.notMember k mL) r+ l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r _ -> Sorted {-# INLINABLE union #-} @@ -485,11 +518,11 @@ unionWith :: Ord k => (v -> v -> v) -> Map k v -> Map k v -> Map k v unionWith combine (Map mL ksL) (Map mR ksR) = Map m ks where- m = Data.Map.unionWith combine mL mR+ m = Data.Map.Strict.unionWith combine mL mR ks = case (ksL, ksR) of (Original l, Original r) -> Original $- l <|> Prelude.filter (\k -> Data.Map.notMember k mL) r+ l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k mL) r _ -> Sorted {-# INLINABLE unionWith #-} @@ -510,7 +543,7 @@ -> Map k c outerJoin fa fb fab (Map ma ksA) (Map mb ksB) = Map m ks where- m = Data.Map.mergeWithKey+ m = Data.Map.Strict.mergeWithKey (\k a b -> Just (fab k a b)) (fmap fa) (fmap fb)@@ -519,7 +552,7 @@ ks = case (ksA, ksB) of (Original l, Original r) -> Original $- l <|> Prelude.filter (\k -> Data.Map.notMember k ma) r+ l <|> Prelude.filter (\k -> Data.Map.Strict.notMember k ma) r _ -> Sorted {-# INLINABLE outerJoin #-} @@ -534,10 +567,10 @@ intersection :: Ord k => Map k a -> Map k b -> Map k a intersection (Map mL ksL) (Map mR _) = Map m ks where- m = Data.Map.intersection mL mR+ m = Data.Map.Strict.intersection mL mR -- Or forget order unless both maps are ordered?!- ks = filterKeys (\k -> Data.Map.member k m) ksL+ ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL {-# INLINABLE intersection #-} {-| Combine two `Map`s on their shared keys, using the supplied function to@@ -549,10 +582,10 @@ intersectionWith :: Ord k => (a -> b -> c) -> Map k a -> Map k b -> Map k c intersectionWith combine (Map mL ksL) (Map mR _) = Map m ks where- m = Data.Map.intersectionWith combine mL mR+ m = Data.Map.Strict.intersectionWith combine mL mR -- Or forget order unless both maps are ordered?!- ks = filterKeys (\k -> Data.Map.member k m) ksL+ ks = filterKeys (\k -> Data.Map.Strict.member k m) ksL {-# INLINABLE intersectionWith #-} {-| Compute the difference of two `Map`s by subtracting all keys from the@@ -564,9 +597,9 @@ difference :: Ord k => Map k a -> Map k b -> Map k a difference (Map mL ksL) (Map mR _) = Map m ks where- m = Data.Map.difference mL mR+ m = Data.Map.Strict.difference mL mR - ks = filterKeys (\k -> Data.Map.notMember k mR) ksL+ ks = filterKeys (\k -> Data.Map.Strict.notMember k mR) ksL {-# INLINABLE difference #-} {-| Fold all of the key-value pairs in a `Map`, in their original order@@ -575,7 +608,7 @@ ("BA",[1,2]) -} foldMapWithKey :: (Monoid m, Ord k) => (k -> a -> m) -> Map k a -> m-foldMapWithKey f (Map m Sorted) = Data.Map.foldMapWithKey f m+foldMapWithKey f (Map m Sorted) = Data.Map.Strict.foldMapWithKey f m foldMapWithKey f m = foldMap (uncurry f) (toList m) {-# INLINABLE foldMapWithKey #-} @@ -595,7 +628,7 @@ mapWithKey :: (k -> a -> b) -> Map k a -> Map k b mapWithKey f (Map m ks) = Map m' ks where- m' = Data.Map.mapWithKey f m+ m' = Data.Map.Strict.mapWithKey f m {-# INLINABLE mapWithKey #-} {-| Traverse all of the key-value pairs in a `Map`, in their original order@@ -606,9 +639,9 @@ traverseWithKey :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b) traverseWithKey f (Map m Sorted) =- fmap (\m' -> Map m' Sorted) (Data.Map.traverseWithKey f m)-traverseWithKey f m =- fmap fromList (traverse f' (toList m))+ fmap (\m' -> Map m' Sorted) (Data.Map.Strict.traverseWithKey f m)+traverseWithKey f m@(Map _ ks) =+ flip Map ks . Data.Map.Strict.fromList <$> traverse f' (toList m) where f' (k, a) = fmap ((,) k) (f k a) {-# INLINABLE traverseWithKey #-}@@ -619,7 +652,7 @@ unorderedTraverseWithKey :: Ord k => Applicative f => (k -> a -> f b) -> Map k a -> f (Map k b) unorderedTraverseWithKey f (Map m ks) =- fmap (\m' -> Map m' ks) (Data.Map.traverseWithKey f m)+ fmap (\m' -> Map m' ks) (Data.Map.Strict.traverseWithKey f m) {-# INLINABLE unorderedTraverseWithKey #-} {-| Traverse all of the key-value pairs in a 'Map', not preserving their@@ -631,7 +664,7 @@ unorderedTraverseWithKey_ :: Ord k => Applicative f => (k -> a -> f ()) -> Map k a -> f () unorderedTraverseWithKey_ f (Map m _) =- Data.Map.foldlWithKey' (\acc k v -> acc *> f k v) (pure ()) m+ Data.Map.Strict.foldlWithKey' (\acc k v -> acc *> f k v) (pure ()) m {-# INLINABLE unorderedTraverseWithKey_ #-} {-| Convert a `Map` to a list of key-value pairs in the original order of keys@@ -640,22 +673,22 @@ [("B",1),("A",2)] -} toList :: Ord k => Map k v -> [(k, v)]-toList (Map m Sorted) = Data.Map.toList m-toList (Map m (Original ks)) = fmap (\k -> (k, m Data.Map.! k)) ks+toList (Map m Sorted) = Data.Map.Strict.toList m+toList (Map m (Original ks)) = fmap (\k -> (k, m Data.Map.Strict.! k)) ks {-# INLINABLE toList #-} {-| Convert a `Map` to a list of key-value pairs in ascending order of keys -} toAscList :: Map k v -> [(k, v)]-toAscList (Map m _) = Data.Map.toAscList m+toAscList (Map m _) = Data.Map.Strict.toAscList m {-# INLINABLE toAscList #-} -{-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map".`Data.Map.Map`@+{-| Convert a @"Dhall.Map".`Map`@ to a @"Data.Map.Strict".`Data.Map.Strict.Map`@ >>> toMap (fromList [("B",1),("A",2)]) -- Order is lost upon conversion fromList [("A",2),("B",1)] -}-toMap :: Map k v -> Data.Map.Map k v+toMap :: Map k v -> Data.Map.Strict.Map k v toMap (Map m _) = m {-# INLINABLE toMap #-} @@ -665,7 +698,7 @@ ["B","A"] -} keys :: Map k v -> [k]-keys (Map m Sorted) = Data.Map.keys m+keys (Map m Sorted) = Data.Map.Strict.keys m keys (Map _ (Original ks)) = ks {-# INLINABLE keys #-} @@ -675,8 +708,8 @@ [1,2] -} elems :: Ord k => Map k v -> [v]-elems (Map m Sorted) = Data.Map.elems m-elems (Map m (Original ks)) = fmap (\k -> m Data.Map.! k) ks+elems (Map m Sorted) = Data.Map.Strict.elems m+elems (Map m (Original ks)) = fmap (\k -> m Data.Map.Strict.! k) ks {-# INLINABLE elems #-} {-| Return the @"Data.Set".'Data.Set.Set'@ of the keys@@ -685,13 +718,20 @@ fromList ["A","B"] -} keysSet :: Map k v -> Data.Set.Set k-keysSet (Map m _) = Data.Map.keysSet m+keysSet (Map m _) = Data.Map.Strict.keysSet m {-# INLINABLE keysSet #-} filterKeys :: (a -> Bool) -> Keys a -> Keys a filterKeys _ Sorted = Sorted filterKeys f (Original ks) = Original (Prelude.filter f ks) {-# INLINABLE filterKeys #-}++partitionKeys :: (a -> Bool) -> Keys a -> (Keys a, Keys a)+partitionKeys _ Sorted = (Sorted, Sorted)+partitionKeys f (Original ks) =+ let (kpass, kfail) = Data.List.partition f ks+ in (Original kpass, Original kfail)+{-# INLINABLE partitionKeys #-} {- $setup >>> import Test.QuickCheck (Arbitrary(..), oneof)
@@ -0,0 +1,1712 @@+{-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Decode+ ( -- * General+ Decoder (..)+ , FromDhall(..)+ , Interpret+ , auto++ -- * Building decoders+ -- ** Simple decoders+ , bool+ , unit+ , void+ -- ** Numbers+ , natural+ , word+ , word8+ , word16+ , word32+ , word64+ , integer+ , int+ , int8+ , int16+ , int32+ , int64+ , scientific+ , double+ -- ** Bytes+ , lazyBytes+ , strictBytes+ , shortBytes+ -- ** Textual+ , string+ , lazyText+ , strictText+ , shortText+ -- ** Time+ , timeOfDay+ , day+ , timeZone+ , localTime+ , zonedTime+ , utcTime+ , dayOfWeek+ -- ** Containers+ , maybe+ , pair+ , sequence+ , list+ , vector+ , setFromDistinctList+ , setIgnoringDuplicates+ , hashSetFromDistinctList+ , hashSetIgnoringDuplicates+ , Dhall.Marshal.Decode.map+ , hashMap+ , pairFromMapEntry+ -- ** Functions+ , function+ , functionWith+ -- ** Records+ , RecordDecoder(..)+ , record+ , field+ -- ** Unions+ , UnionDecoder(..)+ , union+ , constructor++ -- * Generic decoding+ , GenericFromDhall(..)+ , GenericFromDhallUnion(..)+ , genericAuto+ , genericAutoWith+ , genericAutoWithInputNormalizer++ -- * Decoding errors+ , DhallErrors(..)+ , showDhallErrors+ , InvalidDecoder(..)+ -- ** Extraction errors+ , ExtractErrors+ , ExtractError(..)+ , Extractor+ , typeError+ , extractError+ , MonadicExtractor+ , toMonadic+ , fromMonadic+ -- ** Typing errors+ , ExpectedTypeErrors+ , ExpectedTypeError(..)+ , Expector++ -- * Miscellaneous+ , InputNormalizer(..)+ , defaultInputNormalizer+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions+ , Result++ -- * Re-exports+ , Natural+ , Seq+ , Text+ , Vector+ , Generic+ ) where+++import Control.Applicative (empty, liftA2)+import Control.Exception (Exception)+import Control.Monad (guard)+import Control.Monad.Trans.State.Strict+import Data.Coerce (coerce)+import Data.Either.Validation+ ( Validation (..)+ , eitherToValidation+ , validationToEither+ )+import Data.Functor.Contravariant+ ( Equivalence (..)+ , Op (..)+ , Predicate (..)+ )+import Data.Functor.Identity (Identity (..))+import Data.Hashable (Hashable)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Typeable (Proxy (..), Typeable)+import Dhall.Parser (Src (..))+import Dhall.Syntax+ ( Chunks (..)+ , DhallDouble (..)+ , Expr (..)+ , FieldSelection (..)+ , FunctionBinding (..)+ , Var (..)+ )+import GHC.Generics+import Prelude hiding (maybe, sequence)+import Prettyprinter (Pretty)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Foldable+import qualified Data.Functor.Compose+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet+import qualified Data.List as List+import qualified Data.List.NonEmpty+import qualified Data.Map+import qualified Data.Maybe+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time as Time+import qualified Data.Vector+import qualified Dhall.Core as Core+import qualified Dhall.Map+import qualified Dhall.Util++import Dhall.Marshal.Encode+import Dhall.Marshal.Internal++-- $setup+-- >>> import Dhall (input)++{-| A @(Decoder a)@ represents a way to marshal a value of type @\'a\'@ from Dhall+ into Haskell.++ You can produce `Decoder`s either explicitly:++> example :: Decoder (Vector Text)+> example = vector text++ ... or implicitly using `auto`:++> example :: Decoder (Vector Text)+> example = auto++ You can consume `Decoder`s using the `Dhall.input` function:++> input :: Decoder a -> Text -> IO a+-}+data Decoder a = Decoder+ { extract :: Expr Src Void -> Extractor Src Void a+ -- ^ Extracts Haskell value from the Dhall expression+ , expected :: Expector (Expr Src Void)+ -- ^ Dhall type of the Haskell value+ }+ deriving (Functor)++{-| Any value that implements `FromDhall` can be automatically decoded based on+ the inferred return type of `Dhall.input`.++>>> input auto "[1, 2, 3]" :: IO (Vector Natural)+[1,2,3]+>>> input auto "toMap { a = False, b = True }" :: IO (Map Text Bool)+fromList [("a",False),("b",True)]++ This class auto-generates a default implementation for types that+ implement `Generic`. This does not auto-generate an instance for recursive+ types.++ The default instance can be tweaked using 'genericAutoWith'/'genericAutoWithInputNormalizer'+ and custom 'InterpretOptions', or using+ [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+ and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class FromDhall a where+ autoWith :: InputNormalizer -> Decoder a+ default autoWith+ :: (Generic a, GenericFromDhall a (Rep a)) => InputNormalizer -> Decoder a+ autoWith _ = genericAuto++-- | A compatibility alias for `FromDhall`.+type Interpret = FromDhall+{-# DEPRECATED Interpret "Use FromDhall instead" #-}++{-| Use the default input normalizer for interpreting an input.++> auto = autoWith defaultInputNormalizer+-}+auto :: FromDhall a => Decoder a+auto = autoWith defaultInputNormalizer++++instance FromDhall Void where+ autoWith _ = void++instance FromDhall () where+ autoWith _ = unit++instance FromDhall Bool where+ autoWith _ = bool++instance FromDhall Natural where+ autoWith _ = natural++instance FromDhall Word where+ autoWith _ = word++instance FromDhall Word8 where+ autoWith _ = word8++instance FromDhall Word16 where+ autoWith _ = word16++instance FromDhall Word32 where+ autoWith _ = word32++instance FromDhall Word64 where+ autoWith _ = word64++instance FromDhall Integer where+ autoWith _ = integer++instance FromDhall Int where+ autoWith _ = int++instance FromDhall Int8 where+ autoWith _ = int8++instance FromDhall Int16 where+ autoWith _ = int16++instance FromDhall Int32 where+ autoWith _ = int32++instance FromDhall Int64 where+ autoWith _ = int64++instance FromDhall Scientific where+ autoWith _ = scientific++instance FromDhall Double where+ autoWith _ = double++instance FromDhall Data.ByteString.Short.ShortByteString where+ autoWith _ = shortBytes++instance FromDhall Data.ByteString.Lazy.ByteString where+ autoWith _ = lazyBytes++instance FromDhall Data.ByteString.ByteString where+ autoWith _ = strictBytes++instance {-# OVERLAPS #-} FromDhall [Char] where+ autoWith _ = string++instance FromDhall Data.Text.Short.ShortText where+ autoWith _ = shortText++instance FromDhall Data.Text.Lazy.Text where+ autoWith _ = lazyText++instance FromDhall Text where+ autoWith _ = strictText++instance FromDhall a => FromDhall (Identity a) where+ autoWith opts = Identity <$> autoWith opts++instance FromDhall a => FromDhall (Maybe a) where+ autoWith opts = maybe (autoWith opts)++instance FromDhall a => FromDhall (Seq a) where+ autoWith opts = sequence (autoWith opts)++instance FromDhall a => FromDhall [a] where+ autoWith opts = list (autoWith opts)++instance FromDhall a => FromDhall (Vector a) where+ autoWith opts = vector (autoWith opts)++instance FromDhall Time.TimeOfDay where+ autoWith _ = timeOfDay++instance FromDhall Time.Day where+ autoWith _ = day++instance FromDhall Time.TimeZone where+ autoWith _ = timeZone++instance FromDhall Time.LocalTime where+ autoWith _ = localTime++instance FromDhall Time.ZonedTime where+ autoWith _ = zonedTime++instance FromDhall Time.UTCTime where+ autoWith _ = utcTime++instance FromDhall Time.DayOfWeek where+ autoWith _ = dayOfWeek++{-| Note that this instance will throw errors in the presence of duplicates in+ the list. To ignore duplicates, use `setIgnoringDuplicates`.+-}+instance (FromDhall a, Ord a, Show a) => FromDhall (Data.Set.Set a) where+ autoWith opts = setFromDistinctList (autoWith opts)++{-| Note that this instance will throw errors in the presence of duplicates in+ the list. To ignore duplicates, use `hashSetIgnoringDuplicates`.+-}+instance (FromDhall a, Hashable a, Ord a, Show a) => FromDhall (Data.HashSet.HashSet a) where+ autoWith inputNormalizer = hashSetFromDistinctList (autoWith inputNormalizer)++instance (Ord k, FromDhall k, FromDhall v) => FromDhall (Map k v) where+ autoWith inputNormalizer = Dhall.Marshal.Decode.map (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (Eq k, Hashable k, FromDhall k, FromDhall v) => FromDhall (HashMap k v) where+ autoWith inputNormalizer = Dhall.Marshal.Decode.hashMap (autoWith inputNormalizer) (autoWith inputNormalizer)++instance (ToDhall a, FromDhall b) => FromDhall (a -> b) where+ autoWith inputNormalizer =+ functionWith inputNormalizer (injectWith inputNormalizer) (autoWith inputNormalizer)++instance (FromDhall a, FromDhall b) => FromDhall (a, b)++instance FromDhall (f (Result f)) => FromDhall (Result f) where+ autoWith inputNormalizer = Decoder {..}+ where+ extract (App _ expr) =+ fmap Result (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)+ extract expr = typeError expected expr++ expected = pure "result"++deriving newtype instance (ToDhall x) => FromDhall (Predicate x)++deriving newtype instance (ToDhall x) => FromDhall (Equivalence x)++deriving newtype instance (FromDhall b, ToDhall x) => FromDhall (Op b x)++-- | You can use this instance to marshal recursive types from Dhall to Haskell.+--+-- Here is an example use of this instance:+--+-- > {-# LANGUAGE DeriveAnyClass #-}+-- > {-# LANGUAGE DeriveFoldable #-}+-- > {-# LANGUAGE DeriveFunctor #-}+-- > {-# LANGUAGE DeriveTraversable #-}+-- > {-# LANGUAGE DeriveGeneric #-}+-- > {-# LANGUAGE KindSignatures #-}+-- > {-# LANGUAGE QuasiQuotes #-}+-- > {-# LANGUAGE StandaloneDeriving #-}+-- > {-# LANGUAGE TypeFamilies #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- >+-- > import Data.Fix (Fix(..))+-- > import Data.Text (Text)+-- > import Dhall (FromDhall)+-- > import GHC.Generics (Generic)+-- > import Numeric.Natural (Natural)+-- >+-- > import qualified Data.Fix as Fix+-- > import qualified Data.Functor.Foldable as Foldable+-- > import qualified Data.Functor.Foldable.TH as TH+-- > import qualified Dhall+-- > import qualified NeatInterpolation+-- >+-- > data Expr+-- > = Lit Natural+-- > | Add Expr Expr+-- > | Mul Expr Expr+-- > deriving (Show)+-- >+-- > TH.makeBaseFunctor ''Expr+-- >+-- > deriving instance Generic (ExprF a)+-- > deriving instance FromDhall a => FromDhall (ExprF a)+-- >+-- > example :: Text+-- > example = [NeatInterpolation.text|+-- > \(Expr : Type)+-- > -> let ExprF =+-- > < LitF :+-- > Natural+-- > | AddF :+-- > { _1 : Expr, _2 : Expr }+-- > | MulF :+-- > { _1 : Expr, _2 : Expr }+-- > >+-- >+-- > in \(Fix : ExprF -> Expr)+-- > -> let Lit = \(x : Natural) -> Fix (ExprF.LitF x)+-- >+-- > let Add =+-- > \(x : Expr)+-- > -> \(y : Expr)+-- > -> Fix (ExprF.AddF { _1 = x, _2 = y })+-- >+-- > let Mul =+-- > \(x : Expr)+-- > -> \(y : Expr)+-- > -> Fix (ExprF.MulF { _1 = x, _2 = y })+-- >+-- > in Add (Mul (Lit 3) (Lit 7)) (Add (Lit 1) (Lit 2))+-- > |]+-- >+-- > convert :: Fix ExprF -> Expr+-- > convert = Fix.foldFix Foldable.embed+-- >+-- > main :: IO ()+-- > main = do+-- > x <- Dhall.input Dhall.auto example :: IO (Fix ExprF)+-- >+-- > print (convert x :: Expr)+instance (Functor f, FromDhall (f (Result f))) => FromDhall (Fix f) where+ autoWith inputNormalizer = Decoder {..}+ where+ extract expr0 = extract0 expr0+ where+ die = typeError expected expr0++ extract0 (Lam _ (FunctionBinding { functionBindingVariable = x }) expr) =+ extract1 (rename x "result" expr)+ extract0 _ = die++ extract1 (Lam _ (FunctionBinding { functionBindingVariable = y }) expr) =+ extract2 (rename y "Make" expr)+ extract1 _ = die++ extract2 expr = fmap resultToFix (Dhall.Marshal.Decode.extract (autoWith inputNormalizer) expr)++ rename a b expr+ | a /= b = Core.subst (V a 0) (Var (V b 0)) (Core.shift 1 (V b 0) expr)+ | otherwise = expr++ expected = (\x -> Pi mempty "result" (Const Core.Type) (Pi mempty "Make" (Pi mempty "_" x "result") "result"))+ <$> Dhall.Marshal.Decode.expected (autoWith inputNormalizer :: Decoder (f (Result f)))++resultToFix :: Functor f => Result f -> Fix f+resultToFix (Result x) = Fix (fmap resultToFix x)++++{-| This is the underlying class that powers the `FromDhall` class's support+ for automatically deriving a generic implementation.+-}+class GenericFromDhall t f where+ genericAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> State Int (Decoder (f a))++instance GenericFromDhall t f => GenericFromDhall t (M1 D d f) where+ genericAutoWithNormalizer p inputNormalizer options = do+ res <- genericAutoWithNormalizer p inputNormalizer options+ pure (fmap M1 res)++instance GenericFromDhall t V1 where+ genericAutoWithNormalizer _ _ _ = pure Decoder {..}+ where+ extract expr = typeError expected expr++ expected = pure $ Union mempty++instance GenericFromDhallUnion t (f :+: g) => GenericFromDhall t (f :+: g) where+ genericAutoWithNormalizer p inputNormalizer options =+ pure (union (genericUnionAutoWithNormalizer p inputNormalizer options))++instance GenericFromDhall t f => GenericFromDhall t (M1 C c f) where+ genericAutoWithNormalizer p inputNormalizer options = do+ res <- genericAutoWithNormalizer p inputNormalizer options+ pure (fmap M1 res)++instance GenericFromDhall t U1 where+ genericAutoWithNormalizer _ _ _ = pure (Decoder {..})+ where+ extract _ = pure U1++ expected = pure expected'++ expected' = Record (Dhall.Map.fromList [])++instance (GenericFromDhall t (f :*: g), GenericFromDhall t (h :*: i)) => GenericFromDhall t ((f :*: g) :*: (h :*: i)) where+ genericAutoWithNormalizer p inputNormalizer options = do+ Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options+ Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++ let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL+ let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++ let expected = Record <$> (Dhall.Map.union <$> ktsL <*> ktsR)++ let extract expression =+ liftA2 (:*:) (extractL expression) (extractR expression)++ return (Decoder {..})++instance (GenericFromDhall t (f :*: g), Selector s, FromDhall a) => GenericFromDhall t ((f :*: g) :*: M1 S s (K1 i a)) where+ genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+ let nR :: M1 S s (K1 i a) r+ nR = undefined++ nameR <- fmap fieldModifier (getSelName nR)++ Decoder extractL expectedL <- genericAutoWithNormalizer p inputNormalizer options++ let Decoder extractR expectedR = autoWith inputNormalizer++ let ktsL = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedL++ let expected = Record <$> (Dhall.Map.insert nameR . Core.makeRecordField <$> expectedR <*> ktsL)++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup nameR kvs of+ Just expressionR ->+ liftA2 (:*:)+ (extractL expression)+ (fmap (M1 . K1) (extractR expressionR))+ _ -> die+ _ -> die++ return (Decoder {..})++instance (Selector s, FromDhall a, GenericFromDhall t (f :*: g)) => GenericFromDhall t (M1 S s (K1 i a) :*: (f :*: g)) where+ genericAutoWithNormalizer p inputNormalizer options@InterpretOptions{..} = do+ let nL :: M1 S s (K1 i a) r+ nL = undefined++ nameL <- fmap fieldModifier (getSelName nL)++ let Decoder extractL expectedL = autoWith inputNormalizer++ Decoder extractR expectedR <- genericAutoWithNormalizer p inputNormalizer options++ let ktsR = unsafeExpectRecord "genericAutoWithNormalizer (:*:)" <$> expectedR++ let expected = Record <$> (Dhall.Map.insert nameL . Core.makeRecordField <$> expectedL <*> ktsR)++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup nameL kvs of+ Just expressionL ->+ liftA2 (:*:)+ (fmap (M1 . K1) (extractL expressionL))+ (extractR expression)+ _ -> die+ _ -> die++ return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a1 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPING #-} GenericFromDhall a2 (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPABLE #-} (Selector s1, Selector s2, FromDhall a1, FromDhall a2) => GenericFromDhall t (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+ let nL :: M1 S s1 (K1 i1 a1) r+ nL = undefined++ let nR :: M1 S s2 (K1 i2 a2) r+ nR = undefined++ nameL <- fmap fieldModifier (getSelName nL)+ nameR <- fmap fieldModifier (getSelName nR)++ let Decoder extractL expectedL = autoWith inputNormalizer+ let Decoder extractR expectedR = autoWith inputNormalizer++ let expected = do+ l <- Core.makeRecordField <$> expectedL+ r <- Core.makeRecordField <$> expectedR+ pure $ Record+ (Dhall.Map.fromList+ [ (nameL, l)+ , (nameR, r)+ ]+ )++ let extract expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case liftA2 (,) (Dhall.Map.lookup nameL kvs) (Dhall.Map.lookup nameR kvs) of+ Just (expressionL, expressionR) ->+ liftA2 (:*:)+ (fmap (M1 . K1) (extractL $ Core.recordFieldValue expressionL))+ (fmap (M1 . K1) (extractR $ Core.recordFieldValue expressionR))+ Nothing -> die+ _ -> die++ return (Decoder {..})++instance {-# OVERLAPPING #-} GenericFromDhall a (M1 S s (K1 i a)) where+ genericAutoWithNormalizer _ _ _ = pure $ Decoder+ { extract = \_ -> Failure $ DhallErrors $ pure $ ExpectedTypeError RecursiveTypeError+ , expected = Failure $ DhallErrors $ pure RecursiveTypeError+ }++instance {-# OVERLAPPABLE #-} (Selector s, FromDhall a) => GenericFromDhall t (M1 S s (K1 i a)) where+ genericAutoWithNormalizer _ inputNormalizer InterpretOptions{..} = do+ let n :: M1 S s (K1 i a) r+ n = undefined++ name <- fmap fieldModifier (getSelName n)++ let Decoder { extract = extract', expected = expected'} = autoWith inputNormalizer++ let expected =+ case singletonConstructors of+ Bare ->+ expected'+ Smart | selName n == "" ->+ expected'+ _ ->+ Record . Dhall.Map.singleton name . Core.makeRecordField <$> expected'++ let extract0 expression = fmap (M1 . K1) (extract' expression)++ let extract1 expression = do+ let die = typeError expected expression++ case expression of+ RecordLit kvs ->+ case Core.recordFieldValue <$> Dhall.Map.lookup name kvs of+ Just subExpression ->+ fmap (M1 . K1) (extract' subExpression)+ Nothing ->+ die+ _ -> die++ let extract =+ case singletonConstructors of+ Bare -> extract0+ Smart | selName n == "" -> extract0+ _ -> extract1++ return (Decoder {..})++{-| `genericAuto` is the default implementation for `auto` if you derive+ `FromDhall`. The difference is that you can use `genericAuto` without+ having to explicitly provide a `FromDhall` instance for a type as long as+ the type derives `Generic`.+-}+genericAuto :: (Generic a, GenericFromDhall a (Rep a)) => Decoder a+genericAuto = genericAutoWith defaultInterpretOptions++{-| `genericAutoWith` is a configurable version of `genericAuto`.+-}+genericAutoWith :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> Decoder a+genericAutoWith options = genericAutoWithInputNormalizer options defaultInputNormalizer++{-| `genericAutoWithInputNormalizer` is like `genericAutoWith`, but instead of+ using the `defaultInputNormalizer` it expects an custom `InputNormalizer`.+-}+genericAutoWithInputNormalizer :: (Generic a, GenericFromDhall a (Rep a)) => InterpretOptions -> InputNormalizer -> Decoder a+genericAutoWithInputNormalizer options inputNormalizer = withProxy (\p -> fmap to (evalState (genericAutoWithNormalizer p inputNormalizer options) 1))+ where+ withProxy :: (Proxy a -> Decoder a) -> Decoder a+ withProxy f = f Proxy++extractUnionConstructor+ :: Expr s a -> Maybe (Text, Expr s a, Dhall.Map.Map Text (Maybe (Expr s a)))+extractUnionConstructor (App (Field (Union kts) (Core.fieldSelectionLabel -> fld)) e) =+ return (fld, e, Dhall.Map.delete fld kts)+extractUnionConstructor (Field (Union kts) (Core.fieldSelectionLabel -> fld)) =+ return (fld, RecordLit mempty, Dhall.Map.delete fld kts)+extractUnionConstructor _ =+ empty++{-| This is the underlying class that powers the `FromDhall` class's support+ for automatically deriving a generic implementation for a union type.+-}+class GenericFromDhallUnion t f where+ genericUnionAutoWithNormalizer :: Proxy t -> InputNormalizer -> InterpretOptions -> UnionDecoder (f a)++instance (GenericFromDhallUnion t f1, GenericFromDhallUnion t f2) => GenericFromDhallUnion t (f1 :+: f2) where+ genericUnionAutoWithNormalizer p inputNormalizer options =+ (<>)+ (L1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)+ (R1 <$> genericUnionAutoWithNormalizer p inputNormalizer options)++instance (Constructor c1, GenericFromDhall t f1) => GenericFromDhallUnion t (M1 C c1 f1) where+ genericUnionAutoWithNormalizer p inputNormalizer options@(InterpretOptions {..}) =+ constructor name (evalState (genericAutoWithNormalizer p inputNormalizer options) 1)+ where+ n :: M1 C c1 f1 a+ n = undefined++ name = constructorModifier (Data.Text.pack (conName n))++++{-| Decode a `Prelude.Bool`.++>>> input bool "True"+True+-}+bool :: Decoder Bool+bool = Decoder {..}+ where+ extract (BoolLit b) = pure b+ extract expr = typeError expected expr++ expected = pure Bool++{-| Decode a `Prelude.Natural`.++>>> input natural "42"+42+-}+natural :: Decoder Natural+natural = Decoder {..}+ where+ extract (NaturalLit n) = pure n+ extract expr = typeError expected expr++ expected = pure Natural++{-| Decode an `Prelude.Integer`.++>>> input integer "+42"+42+-}+integer :: Decoder Integer+integer = Decoder {..}+ where+ extract (IntegerLit n) = pure n+ extract expr = typeError expected expr++ expected = pure Integer++wordHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+wordHelper name = Decoder {..}+ where+ extract (NaturalLit n)+ | toInteger n <= toInteger (maxBound @a) =+ pure (fromIntegral n)+ | otherwise =+ extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+ extract expr =+ typeError expected expr++ expected = pure Natural++{-| Decode a `Word` from a Dhall @Natural@.++>>> input word "42"+42+-}+word :: Decoder Word+word = wordHelper "Word"++{-| Decode a `Word8` from a Dhall @Natural@.++>>> input word8 "42"+42+-}+word8 :: Decoder Word8+word8 = wordHelper "Word8"++{-| Decode a `Word16` from a Dhall @Natural@.++>>> input word16 "42"+42+-}+word16 :: Decoder Word16+word16 = wordHelper "Word16"++{-| Decode a `Word32` from a Dhall @Natural@.++>>> input word32 "42"+42+-}+word32 :: Decoder Word32+word32 = wordHelper "Word32"++{-| Decode a `Word64` from a Dhall @Natural@.++>>> input word64 "42"+42+-}+word64 :: Decoder Word64+word64 = wordHelper "Word64"++intHelper :: forall a . (Bounded a, Integral a) => Text -> Decoder a+intHelper name = Decoder {..}+ where+ extract (IntegerLit n)+ | toInteger (minBound @a) <= n && n <= toInteger (maxBound @a) =+ pure (fromIntegral n)+ | otherwise =+ extractError ("Decoded " <> name <> " is out of bounds: " <> Data.Text.pack (show n))+ extract expr =+ typeError expected expr++ expected = pure Integer++{-| Decode an `Int` from a Dhall @Integer@.++>>> input int "-42"+-42+-}+int :: Decoder Int+int = intHelper "Int"++{-| Decode an `Int8` from a Dhall @Integer@.++>>> input int8 "-42"+-42+-}+int8 :: Decoder Int8+int8 = intHelper "Int8"++{-| Decode an `Int16` from a Dhall @Integer@.++>>> input int16 "-42"+-42+-}+int16 :: Decoder Int16+int16 = intHelper "Int16"++{-| Decode an `Int32` from a Dhall @Integer@.++>>> input int32 "-42"+-42+-}+int32 :: Decoder Int32+int32 = intHelper "Int32"++{-| Decode an `Int64` from a Dhall @Integer@.++>>> input int64 "-42"+-42+-}+int64 :: Decoder Int64+int64 = intHelper "Int64"++{-| Decode a `Scientific`.++>>> input scientific "1e100"+1.0e100+-}+scientific :: Decoder Scientific+scientific = fmap Data.Scientific.fromFloatDigits double++{-| Decode a `Prelude.Double`.++>>> input double "42.0"+42.0+-}+double :: Decoder Double+double = Decoder {..}+ where+ extract (DoubleLit (DhallDouble n)) = pure n+ extract expr = typeError expected expr++ expected = pure Double++{-| Decode a `Data.ByteString.Short.ShortByteString`++>>> input shortBytes "0x\"00FF\""+"\NUL\255"+-}+shortBytes :: Decoder Data.ByteString.Short.ShortByteString+shortBytes = fmap Data.ByteString.Short.toShort strictBytes++{-| Decode a lazy `Data.ByteString.Lazy.ByteString`.++>>> input lazyBytes "0x\"00FF\""+"\NUL\255"+-}+lazyBytes :: Decoder Data.ByteString.Lazy.ByteString+lazyBytes = fmap Data.ByteString.Lazy.fromStrict strictBytes++{-| Decode a strict `Data.ByteString.ByteString`++>>> input strictBytes "0x\"00FF\""+"\NUL\255"+-}+strictBytes :: Decoder Data.ByteString.ByteString+strictBytes = Decoder {..}+ where+ extract (BytesLit b) = pure b+ extract expr = typeError expected expr++ expected = pure Bytes++{-| Decode `Data.Text.Short.ShortText`.++>>> input shortText "\"Test\""+"Test"+-}+shortText :: Decoder Data.Text.Short.ShortText+shortText = fmap Data.Text.Short.fromText strictText++{-| Decode lazy `Data.Text.Lazy.Text`.++>>> input lazyText "\"Test\""+"Test"+-}+lazyText :: Decoder Data.Text.Lazy.Text+lazyText = fmap Data.Text.Lazy.fromStrict strictText++{-| Decode strict `Data.Text.Text`.++>>> input strictText "\"Test\""+"Test"+-}+strictText :: Decoder Text+strictText = Decoder {..}+ where+ extract (TextLit (Chunks [] t)) = pure t+ extract expr = typeError expected expr++ expected = pure Text++{-| Decode `Time.TimeOfDay`++>>> input timeOfDay "00:00:00"+00:00:00+-}+timeOfDay :: Decoder Time.TimeOfDay+timeOfDay = Decoder {..}+ where+ extract (TimeLiteral t _) = pure t+ extract expr = typeError expected expr++ expected = pure Time++{-| Decode `Time.Day`++>>> input day "2000-01-01"+2000-01-01+-}+day :: Decoder Time.Day+day = Decoder {..}+ where+ extract (DateLiteral d) = pure d+ extract expr = typeError expected expr++ expected = pure Date++{-| Decode `Time.TimeZone`++>>> input timeZone "+00:00"++0000+-}+timeZone :: Decoder Time.TimeZone+timeZone = Decoder {..}+ where+ extract (TimeZoneLiteral z) = pure z+ extract expr = typeError expected expr++ expected = pure TimeZone++{-| Decode `Time.LocalTime`++>>> input localTime "2020-01-01T12:34:56"+2020-01-01 12:34:56+-}+localTime :: Decoder Time.LocalTime+localTime = record $+ Time.LocalTime+ <$> field "date" day+ <*> field "time" timeOfDay++{-| Decode `Time.ZonedTime`++>>> input zonedTime "2020-01-01T12:34:56+02:00"+2020-01-01 12:34:56 +0200+-}+zonedTime :: Decoder Time.ZonedTime+zonedTime = record $+ adapt+ <$> field "date" day+ <*> field "time" timeOfDay+ <*> field "timeZone" timeZone+ where+ adapt date time = Time.ZonedTime (Time.LocalTime date time)++{-| Decode `Time.UTCTime`++>>> input utcTime "2020-01-01T12:34:56+02:00"+2020-01-01 10:34:56 UTC+-}+utcTime :: Decoder Time.UTCTime+utcTime = Time.zonedTimeToUTC <$> zonedTime++{-| Decode `Time.DayOfWeek`++>>> input dayOfWeek "< Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday >.Monday"+Monday+-}+dayOfWeek :: Decoder Time.DayOfWeek+dayOfWeek = Decoder{..}+ where+ extract expr@(Field _ FieldSelection{ fieldSelectionLabel }) =+ case fieldSelectionLabel of+ "Sunday" -> pure Time.Sunday+ "Monday" -> pure Time.Monday+ "Tuesday" -> pure Time.Tuesday+ "Wednesday" -> pure Time.Wednesday+ "Thursday" -> pure Time.Thursday+ "Friday" -> pure Time.Friday+ "Saturday" -> pure Time.Saturday+ _ -> typeError expected expr+ extract expr =+ typeError expected expr++ expected =+ pure+ (Union+ (Dhall.Map.fromList+ [ ("Sunday", Nothing)+ , ("Monday", Nothing)+ , ("Tuesday", Nothing)+ , ("Wednesday", Nothing)+ , ("Thursday", Nothing)+ , ("Friday", Nothing)+ , ("Saturday", Nothing)+ ]+ )+ )++{-| Decode a `Maybe`.++>>> input (maybe natural) "Some 1"+Just 1+-}+maybe :: Decoder a -> Decoder (Maybe a)+maybe (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (Some e ) = fmap Just (extractIn e)+ extractOut (App None _) = pure Nothing+ extractOut expr = typeError expectedOut expr++ expectedOut = App Optional <$> expectedIn++{-| Decode a `Seq`.++>>> input (sequence natural) "[1, 2, 3]"+fromList [1,2,3]+-}+sequence :: Decoder a -> Decoder (Seq a)+sequence (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (ListLit _ es) = traverse extractIn es+ extractOut expr = typeError expectedOut expr++ expectedOut = App List <$> expectedIn++{-| Decode a list.++>>> input (list natural) "[1, 2, 3]"+[1,2,3]+-}+list :: Decoder a -> Decoder [a]+list = fmap Data.Foldable.toList . sequence++{-| Decode a `Vector`.++>>> input (vector natural) "[1, 2, 3]"+[1,2,3]+-}+vector :: Decoder a -> Decoder (Vector a)+vector = fmap Data.Vector.fromList . list++{-| Decode a Dhall function into a Haskell function.++>>> f <- input (function inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+function+ :: Encoder a+ -> Decoder b+ -> Decoder (a -> b)+function = functionWith defaultInputNormalizer++{-| Decode a Dhall function into a Haskell function using the specified normalizer.++>>> f <- input (functionWith defaultInputNormalizer inject bool) "Natural/even" :: IO (Natural -> Bool)+>>> f 0+True+>>> f 1+False+-}+functionWith+ :: InputNormalizer+ -> Encoder a+ -> Decoder b+ -> Decoder (a -> b)+functionWith inputNormalizer (Encoder {..}) (Decoder extractIn expectedIn) =+ Decoder extractOut expectedOut+ where+ normalizer_ = Just (getInputNormalizer inputNormalizer)++ extractOut e = pure (\i -> case extractIn (Core.normalizeWith normalizer_ (App e (embed i))) of+ Success o -> o+ Failure _e -> error "FromDhall: You cannot decode a function if it does not have the correct type" )++ expectedOut = Pi mempty "_" declared <$> expectedIn++{-| Decode a `Data.Set.Set` from a `List`.++>>> input (setIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (setIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+setIgnoringDuplicates :: (Ord a) => Decoder a -> Decoder (Data.Set.Set a)+setIgnoringDuplicates = fmap Data.Set.fromList . list++{-| Decode a `Data.HashSet.HashSet` from a `List`.++>>> input (hashSetIgnoringDuplicates natural) "[1, 2, 3]"+fromList [1,2,3]++Duplicate elements are ignored.++>>> input (hashSetIgnoringDuplicates natural) "[1, 1, 3]"+fromList [1,3]++-}+hashSetIgnoringDuplicates :: (Hashable a, Ord a)+ => Decoder a+ -> Decoder (Data.HashSet.HashSet a)+hashSetIgnoringDuplicates = fmap Data.HashSet.fromList . list++{-| Decode a `Data.Set.Set` from a `List` with distinct elements.++>>> input (setFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (setFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (setFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+setFromDistinctList :: (Ord a, Show a) => Decoder a -> Decoder (Data.Set.Set a)+setFromDistinctList = setHelper Data.Set.size Data.Set.fromList++{-| Decode a `Data.HashSet.HashSet` from a `List` with distinct elements.++>>> input (hashSetFromDistinctList natural) "[1, 2, 3]"+fromList [1,2,3]++An error is thrown if the list contains duplicates.++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> One duplicate element in the list: 1+>++> >>> input (hashSetFromDistinctList natural) "[1, 1, 3, 3]"+> *** Exception: Error: Failed extraction+>+> The expression type-checked successfully but the transformation to the target+> type failed with the following error:+>+> 2 duplicates were found in the list, including 1+>++-}+hashSetFromDistinctList :: (Hashable a, Ord a, Show a)+ => Decoder a+ -> Decoder (Data.HashSet.HashSet a)+hashSetFromDistinctList = setHelper Data.HashSet.size Data.HashSet.fromList+++setHelper :: (Eq a, Foldable t, Show a)+ => (t a -> Int)+ -> ([a] -> t a)+ -> Decoder a+ -> Decoder (t a)+setHelper size toSet (Decoder extractIn expectedIn) = Decoder extractOut expectedOut+ where+ extractOut (ListLit _ es) = case traverse extractIn es of+ Success vSeq+ | sameSize -> Success vSet+ | otherwise -> extractError err+ where+ vList = Data.Foldable.toList vSeq+ vSet = toSet vList+ sameSize = size vSet == Data.Sequence.length vSeq+ duplicates = vList List.\\ Data.Foldable.toList vSet+ err | length duplicates == 1 =+ "One duplicate element in the list: "+ <> (Data.Text.pack $ show $ head duplicates)+ | otherwise = Data.Text.pack $ unwords+ [ show $ length duplicates+ , "duplicates were found in the list, including"+ , show $ head duplicates+ ]+ Failure f -> Failure f+ extractOut expr = typeError expectedOut expr++ expectedOut = App List <$> expectedIn++{-| Decode a `Map` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> input (Dhall.map strictText bool) "toMap { a = True, b = False }"+fromList [("a",True),("b",False)]+>>> input (Dhall.map strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]"+fromList [("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.map natural bool) expr+fromList [(1,False)]++-}+map :: Ord k => Decoder k -> Decoder v -> Decoder (Map k v)+map k v = fmap Data.Map.fromList (list (pairFromMapEntry k v))++{-| Decode a `HashMap` from a @toMap@ expression or generally a @Prelude.Map.Type@.++>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "toMap { a = True, b = False }")+[("a",True),("b",False)]+>>> fmap (List.sort . HashMap.toList) (input (Dhall.hashMap strictText bool) "[ { mapKey = \"foo\", mapValue = True } ]")+[("foo",True)]++If there are duplicate @mapKey@s, later @mapValue@s take precedence:++>>> let expr = "[ { mapKey = 1, mapValue = True }, { mapKey = 1, mapValue = False } ]"+>>> input (Dhall.hashMap natural bool) expr+fromList [(1,False)]++-}+hashMap :: (Eq k, Hashable k) => Decoder k -> Decoder v -> Decoder (HashMap k v)+hashMap k v = fmap HashMap.fromList (list (pairFromMapEntry k v))++{-| Decode a tuple from a @Prelude.Map.Entry@ record.++>>> input (pairFromMapEntry strictText natural) "{ mapKey = \"foo\", mapValue = 3 }"+("foo",3)+-}+pairFromMapEntry :: Decoder k -> Decoder v -> Decoder (k, v)+pairFromMapEntry k v = Decoder extractOut expectedOut+ where+ extractOut (RecordLit kvs)+ | Just key <- Core.recordFieldValue <$> Dhall.Map.lookup "mapKey" kvs+ , Just value <- Core.recordFieldValue <$> Dhall.Map.lookup "mapValue" kvs+ = liftA2 (,) (extract k key) (extract v value)+ extractOut expr = typeError expectedOut expr++ expectedOut = do+ k' <- Core.makeRecordField <$> expected k+ v' <- Core.makeRecordField <$> expected v+ pure $ Record $ Dhall.Map.fromList+ [ ("mapKey", k')+ , ("mapValue", v')]++{-| Decode @()@ from an empty record.++>>> input unit "{=}" -- GHC doesn't print the result if it is ()++-}+unit :: Decoder ()+unit = Decoder {..}+ where+ extract (RecordLit fields)+ | Data.Foldable.null fields = pure ()+ extract expr = typeError expected expr++ expected = pure $ Record mempty++{-| Decode 'Void' from an empty union.++Since @<>@ is uninhabited, @'Dhall.input' 'void'@ will always fail.+-}+void :: Decoder Void+void = union mempty++{-| Decode a `String`++>>> input string "\"ABC\""+"ABC"++-}+string :: Decoder String+string = Data.Text.Lazy.unpack <$> lazyText++{-| Given a pair of `Decoder`s, decode a tuple-record into their pairing.++>>> input (pair natural bool) "{ _1 = 42, _2 = False }"+(42,False)+-}+pair :: Decoder a -> Decoder b -> Decoder (a, b)+pair l r = Decoder extractOut expectedOut+ where+ extractOut expr@(RecordLit fields) =+ (,) <$> Data.Maybe.maybe (typeError expectedOut expr) (extract l)+ (Core.recordFieldValue <$> Dhall.Map.lookup "_1" fields)+ <*> Data.Maybe.maybe (typeError expectedOut expr) (extract r)+ (Core.recordFieldValue <$> Dhall.Map.lookup "_2" fields)+ extractOut expr = typeError expectedOut expr++ expectedOut = do+ l' <- Core.makeRecordField <$> expected l+ r' <- Core.makeRecordField <$> expected r+ pure $ Record $ Dhall.Map.fromList+ [ ("_1", l')+ , ("_2", r')]++++{-| The 'RecordDecoder' applicative functor allows you to build a 'Decoder'+ from a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Project = Project+ { projectName :: Text+ , projectDescription :: Text+ , projectStars :: Natural+ }+:}++ And assume that we have the following Dhall record that we would like to+ parse as a @Project@:++> { name =+> "dhall-haskell"+> , description =+> "A configuration language guaranteed to terminate"+> , stars =+> 289+> }++ Our decoder has type 'Decoder' @Project@, but we can't build that out of any+ smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+ However, we can use a 'RecordDecoder' to build a 'Decoder' for @Project@:++>>> :{+project :: Decoder Project+project =+ record+ ( Project <$> field "name" strictText+ <*> field "description" strictText+ <*> field "stars" natural+ )+:}+-}+newtype RecordDecoder a =+ RecordDecoder+ ( Data.Functor.Product.Product+ ( Control.Applicative.Const+ (Dhall.Map.Map Text (Expector (Expr Src Void)))+ )+ ( Data.Functor.Compose.Compose ((->) (Expr Src Void)) (Extractor Src Void)+ )+ a+ )+ deriving (Functor, Applicative)++-- | Run a 'RecordDecoder' to build a 'Decoder'.+record :: RecordDecoder a -> Dhall.Marshal.Decode.Decoder a+record+ (RecordDecoder+ (Data.Functor.Product.Pair+ (Control.Applicative.Const fields)+ (Data.Functor.Compose.Compose extract)+ )+ ) = Decoder {..}+ where+ expected = Record <$> traverse (fmap Core.makeRecordField) fields++-- | Parse a single field of a record.+field :: Text -> Decoder a -> RecordDecoder a+field key (Decoder {..}) =+ RecordDecoder+ ( Data.Functor.Product.Pair+ ( Control.Applicative.Const+ (Dhall.Map.singleton key expected)+ )+ ( Data.Functor.Compose.Compose extractBody )+ )+ where+ extractBody expr@(RecordLit fields) = case Core.recordFieldValue <$> Dhall.Map.lookup key fields of+ Just v -> extract v+ _ -> typeError expected expr+ extractBody expr = typeError expected expr++++{-| The 'UnionDecoder' monoid allows you to build a 'Decoder' from a Dhall union.++ For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+ | Result Text+ | Errored Text+:}++ And assume that we have the following Dhall union that we would like to+ parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++ Our decoder has type 'Decoder' @Status@, but we can't build that out of any+ smaller decoders, as 'Decoder's cannot be combined (they are only 'Functor's).+ However, we can use a 'UnionDecoder' to build a 'Decoder' for @Status@:++>>> :{+status :: Decoder Status+status = union+ ( ( Queued <$> constructor "Queued" natural )+ <> ( Result <$> constructor "Result" strictText )+ <> ( Errored <$> constructor "Errored" strictText )+ )+:}++-}+newtype UnionDecoder a =+ UnionDecoder+ ( Data.Functor.Compose.Compose (Dhall.Map.Map Text) Decoder a )+ deriving (Functor)++instance Semigroup (UnionDecoder a) where+ (<>) = coerce ((<>) :: Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a) -> Dhall.Map.Map Text (Decoder a))++instance Monoid (UnionDecoder a) where+ mempty = coerce (mempty :: Dhall.Map.Map Text (Decoder a))++-- | Run a 'UnionDecoder' to build a 'Decoder'.+union :: UnionDecoder a -> Decoder a+union (UnionDecoder (Data.Functor.Compose.Compose mp)) = Decoder {..}+ where+ extract expr = case expected' of+ Failure e -> Failure $ fmap ExpectedTypeError e+ Success x -> extract' expr x++ extract' e0 mp' = Data.Maybe.maybe (typeError expected e0) (uncurry Dhall.Marshal.Decode.extract) $ do+ (fld, e1, rest) <- extractUnionConstructor e0++ t <- Dhall.Map.lookup fld mp++ guard $+ Core.Union rest `Core.judgmentallyEqual` Core.Union (Dhall.Map.delete fld mp')++ pure (t, e1)++ expected = Union <$> expected'++ expected' = traverse (fmap notEmptyRecord . Dhall.Marshal.Decode.expected) mp++-- | Parse a single constructor of a union.+constructor :: Text -> Decoder a -> UnionDecoder a+constructor key valueDecoder = UnionDecoder+ ( Data.Functor.Compose.Compose (Dhall.Map.singleton key valueDecoder) )++++{-| A newtype suitable for collecting one or more errors.+-}+newtype DhallErrors e = DhallErrors+ { getErrors :: NonEmpty e+ } deriving (Eq, Functor, Semigroup)++instance (Show (DhallErrors e), Typeable e) => Exception (DhallErrors e)++{-| Render a given prefix and some errors to a string.+-}+showDhallErrors :: Show e => String -> DhallErrors e -> String+showDhallErrors _ (DhallErrors (e :| [])) = show e+showDhallErrors ctx (DhallErrors es) = prefix <> (unlines . Data.List.NonEmpty.toList . fmap show $ es)+ where+ prefix =+ "Multiple errors were encountered" ++ ctx ++ ": \n\+ \ \n"++{-| One or more errors returned from extracting a Dhall expression to a+ Haskell expression.+-}+type ExtractErrors s a = DhallErrors (ExtractError s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractErrors s a) where+ show = showDhallErrors " during extraction"++{-| Extraction of a value can fail for two reasons, either a type mismatch (which should not happen,+ as expressions are type-checked against the expected type before being passed to @extract@), or+ a term-level error, described with a freeform text value.+-}+data ExtractError s a =+ TypeMismatch (InvalidDecoder s a)+ | ExpectedTypeError ExpectedTypeError+ | ExtractError Text+ deriving (Eq)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (ExtractError s a) where+ show (TypeMismatch e) = show e+ show (ExpectedTypeError e) = show e+ show (ExtractError es) = unlines+ [ _ERROR <> ": Failed extraction "+ , " "+ , "The expression type-checked successfully but the transformation to the target "+ , "type failed with the following error: "+ , " "+ , Data.Text.unpack es+ , " "+ ]++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Exception (ExtractError s a)++{-| Useful synonym for the `Validation` type used when marshalling Dhall+ expressions.+-}+type Extractor s a = Validation (ExtractErrors s a)++{-| Generate a type error during extraction by specifying the expected type+ and the actual type.+ The expected type is not yet determined.+-}+typeError :: Expector (Expr s a) -> Expr s a -> Extractor s a b+typeError expected actual = Failure $ case expected of+ Failure e -> fmap ExpectedTypeError e+ Success expected' -> DhallErrors $ pure $ TypeMismatch $ InvalidDecoder expected' actual++-- | Turn a `Data.Text.Text` message into an extraction failure.+extractError :: Text -> Extractor s a b+extractError = Failure . DhallErrors . pure . ExtractError++{-| Useful synonym for the equivalent `Either` type used when marshalling Dhall+ code.+-}+type MonadicExtractor s a = Either (ExtractErrors s a)++-- | Switches from an @Applicative@ extraction result, able to accumulate errors,+-- to a @Monad@ extraction result, able to chain sequential operations.+toMonadic :: Extractor s a b -> MonadicExtractor s a b+toMonadic = validationToEither++-- | Switches from a @Monad@ extraction result, able to chain sequential errors,+-- to an @Applicative@ extraction result, able to accumulate errors.+fromMonadic :: MonadicExtractor s a b -> Extractor s a b+fromMonadic = eitherToValidation++{-| Every `Decoder` must obey the contract that if an expression's type matches+ the `expected` type then the `extract` function must not fail with a type+ error. However, decoding may still fail for other reasons (such as the+ decoder for `Data.Map.Set`s rejecting a Dhall @List@ with duplicate+ elements).++ This error type is used to indicate an internal error in the implementation+ of a `Decoder` where the expected type matched the Dhall expression, but the+ expression supplied to the extraction function did not match the expected+ type. If this happens that means that the `Decoder` itself needs to be+ fixed.+-}+data InvalidDecoder s a = InvalidDecoder+ { invalidDecoderExpected :: Expr s a+ , invalidDecoderExpression :: Expr s a+ }+ deriving (Eq, Typeable)++instance (Pretty s, Typeable s, Pretty a, Typeable a) => Exception (InvalidDecoder s a)++instance (Pretty s, Pretty a, Typeable s, Typeable a) => Show (InvalidDecoder s a) where+ show InvalidDecoder { .. } = unlines+ [ _ERROR <> ": Invalid Dhall.Decoder "+ , " "+ , "Every Decoder must provide an extract function that does not fail with a type "+ , "error if an expression matches the expected type. You provided a Decoder that "+ , "disobeys this contract "+ , " "+ , "The Decoder provided has the expected dhall type: "+ , " "+ , show (Dhall.Util.insert invalidDecoderExpected)+ , " "+ , "and it threw a type error during extraction from the well-typed expression: "+ , " "+ , show (Dhall.Util.insert invalidDecoderExpression)+ , " "+ ]++{-| Useful synonym for the `Validation` type used when marshalling Dhall+ expressions.+-}+type Expector = Validation ExpectedTypeErrors++{-| One or more errors returned when determining the Dhall type of a+ Haskell expression.+-}+type ExpectedTypeErrors = DhallErrors ExpectedTypeError++{-| Error type used when determining the Dhall type of a Haskell expression.+-}+data ExpectedTypeError = RecursiveTypeError+ deriving (Eq, Show)++instance Exception ExpectedTypeError++instance Show ExpectedTypeErrors where+ show = showDhallErrors " while determining the expected type"++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"
@@ -0,0 +1,1068 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Encode+ ( -- * General+ Encoder(..)+ , ToDhall(..)+ , Inject+ , inject++ -- * Building encoders++ -- ** Records+ , RecordEncoder(..)+ , recordEncoder+ , encodeField+ , encodeFieldWith+ -- ** Unions+ , UnionEncoder(..)+ , unionEncoder+ , encodeConstructor+ , encodeConstructorWith+ , (>|<)++ -- * Generic encoding+ , GenericToDhall(..)+ , genericToDhall+ , genericToDhallWith+ , genericToDhallWithInputNormalizer+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions++ -- * Miscellaneous+ , InputNormalizer(..)+ , defaultInputNormalizer+ , Result+ , (>$<)+ , (>*<)++ -- * Re-exports+ , Natural+ , Seq+ , Text+ , Vector+ , Generic+ ) where++import Control.Monad.Trans.State.Strict+import Data.Functor.Contravariant (Contravariant (..), Op (..), (>$<))+import Data.Functor.Contravariant.Divisible (Divisible (..), divided)+import Dhall.Parser (Src (..))+import Dhall.Syntax+ ( Chunks (..)+ , DhallDouble (..)+ , Expr (..)+ )+import GHC.Generics+import Prelude hiding (maybe, sequence)++import qualified Control.Applicative+import qualified Data.ByteString+import qualified Data.ByteString.Lazy+import qualified Data.ByteString.Short+import qualified Data.Functor.Product+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet+import qualified Data.Map+import qualified Data.Scientific+import qualified Data.Sequence+import qualified Data.Set+import qualified Data.Text+import qualified Data.Text.Lazy+import qualified Data.Text.Short+import qualified Data.Time as Time+import qualified Data.Vector+import qualified Data.Void+import qualified Dhall.Core as Core+import qualified Dhall.Map++import Dhall.Marshal.Internal++-- $setup+-- >>> :set -XRecordWildCards+-- >>> import Dhall.Pretty.Internal (prettyExpr)++{-| An @(Encoder a)@ represents a way to marshal a value of type @\'a\'@ from+ Haskell into Dhall.+-}+data Encoder a = Encoder+ { embed :: a -> Expr Src Void+ -- ^ Embeds a Haskell value as a Dhall expression+ , declared :: Expr Src Void+ -- ^ Dhall type of the Haskell value+ }++instance Contravariant Encoder where+ contramap f (Encoder embed declared) = Encoder embed' declared+ where+ embed' x = embed (f x)++{-| This class is used by `Dhall.Marshal.Decode.FromDhall` instance for functions:++> instance (ToDhall a, FromDhall b) => FromDhall (a -> b)++ You can convert Dhall functions with "simple" inputs (i.e. instances of this+ class) into Haskell functions. This works by:++ * Marshaling the input to the Haskell function into a Dhall expression (i.e.+ @x :: Expr Src Void@)+ * Applying the Dhall function (i.e. @f :: Expr Src Void@) to the Dhall input+ (i.e. @App f x@)+ * Normalizing the syntax tree (i.e. @normalize (App f x)@)+ * Marshaling the resulting Dhall expression back into a Haskell value++ This class auto-generates a default implementation for types that+ implement `Generic`. This does not auto-generate an instance for recursive+ types.++ The default instance can be tweaked using 'genericToDhallWith'/'genericToDhallWithInputNormalizer'+ and custom 'InterpretOptions', or using+ [DerivingVia](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-DerivingVia)+ and 'Dhall.Deriving.Codec' from "Dhall.Deriving".+-}+class ToDhall a where+ injectWith :: InputNormalizer -> Encoder a+ default injectWith+ :: (Generic a, GenericToDhall (Rep a)) => InputNormalizer -> Encoder a+ injectWith _ = genericToDhall++-- | A compatibility alias for `ToDhall`+type Inject = ToDhall+{-# DEPRECATED Inject "Use ToDhall instead" #-}++{-| Use the default input normalizer for injecting a value.++> inject = injectWith defaultInputNormalizer+-}+inject :: ToDhall a => Encoder a+inject = injectWith defaultInputNormalizer++++instance ToDhall Void where+ injectWith _ = Encoder {..}+ where+ embed = Data.Void.absurd++ declared = Union mempty++instance ToDhall Bool where+ injectWith _ = Encoder {..}+ where+ embed = BoolLit++ declared = Bool++instance ToDhall Data.ByteString.Short.ShortByteString where+ injectWith options =+ contramap Data.ByteString.Short.fromShort (injectWith options)++instance ToDhall Data.ByteString.Lazy.ByteString where+ injectWith options =+ contramap Data.ByteString.Lazy.toStrict (injectWith options)++instance ToDhall Data.ByteString.ByteString where+ injectWith _ = Encoder {..}+ where+ embed bytes = BytesLit bytes++ declared = Bytes++instance ToDhall Data.Text.Short.ShortText where+ injectWith _ = Encoder {..}+ where+ embed text =+ TextLit (Chunks [] (Data.Text.Short.toText text))++ declared = Text++instance ToDhall Data.Text.Lazy.Text where+ injectWith _ = Encoder {..}+ where+ embed text =+ TextLit (Chunks [] (Data.Text.Lazy.toStrict text))++ declared = Text++instance ToDhall Text where+ injectWith _ = Encoder {..}+ where+ embed text = TextLit (Chunks [] text)++ declared = Text++instance {-# OVERLAPS #-} ToDhall String where+ injectWith inputNormalizer =+ contramap Data.Text.pack (injectWith inputNormalizer :: Encoder Text)++instance ToDhall Natural where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit++ declared = Natural++instance ToDhall Integer where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit++ declared = Integer++instance ToDhall Int where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++instance ToDhall Int8 where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++instance ToDhall Int16 where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++instance ToDhall Int32 where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++instance ToDhall Int64 where+ injectWith _ = Encoder {..}+ where+ embed = IntegerLit . toInteger++ declared = Integer++{-| Encode a 'Word' to a Dhall @Natural@.++>>> embed inject (12 :: Word)+NaturalLit 12+-}+instance ToDhall Word where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word8' to a Dhall @Natural@.++>>> embed inject (12 :: Word8)+NaturalLit 12+-}+instance ToDhall Word8 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word16' to a Dhall @Natural@.++>>> embed inject (12 :: Word16)+NaturalLit 12+-}+instance ToDhall Word16 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word32' to a Dhall @Natural@.++>>> embed inject (12 :: Word32)+NaturalLit 12+-}+instance ToDhall Word32 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++{-| Encode a 'Word64' to a Dhall @Natural@.++>>> embed inject (12 :: Word64)+NaturalLit 12+-}+instance ToDhall Word64 where+ injectWith _ = Encoder {..}+ where+ embed = NaturalLit . fromIntegral++ declared = Natural++instance ToDhall Double where+ injectWith _ = Encoder {..}+ where+ embed = DoubleLit . DhallDouble++ declared = Double++instance ToDhall Scientific where+ injectWith inputNormalizer =+ contramap Data.Scientific.toRealFloat (injectWith inputNormalizer :: Encoder Double)++instance ToDhall () where+ injectWith _ = Encoder {..}+ where+ embed = const (RecordLit mempty)++ declared = Record mempty++instance ToDhall a => ToDhall (Maybe a) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut (Just x ) = Some (embedIn x)+ embedOut Nothing = App None declaredIn++ Encoder embedIn declaredIn = injectWith inputNormalizer++ declaredOut = App Optional declaredIn++instance ToDhall a => ToDhall (Seq a) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut xs = ListLit listType (fmap embedIn xs)+ where+ listType+ | null xs = Just (App List declaredIn)+ | otherwise = Nothing++ declaredOut = App List declaredIn++ Encoder embedIn declaredIn = injectWith inputNormalizer++instance ToDhall a => ToDhall [a] where+ injectWith = fmap (contramap Data.Sequence.fromList) injectWith++instance ToDhall a => ToDhall (Vector a) where+ injectWith = fmap (contramap Data.Vector.toList) injectWith++instance ToDhall Time.TimeOfDay where+ injectWith _ = Encoder {..}+ where+ embed timeOfDay = TimeLiteral timeOfDay 12++ declared = Time++instance ToDhall Time.Day where+ injectWith _ = Encoder {..}+ where+ embed = DateLiteral++ declared = Date++instance ToDhall Time.TimeZone where+ injectWith _ = Encoder {..}+ where+ embed = TimeZoneLiteral++ declared = TimeZone++instance ToDhall Time.LocalTime where+ injectWith _ = recordEncoder $+ adapt+ >$< encodeField "date"+ >*< encodeField "time"+ where+ adapt (Time.LocalTime date time) = (date, time)++instance ToDhall Time.ZonedTime where+ injectWith _ = recordEncoder $+ adapt+ >$< encodeField "date"+ >*< encodeField "time"+ >*< encodeField "timeZone"+ where+ adapt (Time.ZonedTime (Time.LocalTime date time) timeZone) = (date, (time, timeZone))++instance ToDhall Time.UTCTime where+ injectWith = contramap (Time.utcToZonedTime Time.utc) . injectWith++instance ToDhall Time.DayOfWeek where+ injectWith _ = Encoder{..}+ where+ embed Time.Sunday =+ Field declared (Core.makeFieldSelection "Sunday")+ embed Time.Monday =+ Field declared (Core.makeFieldSelection "Monday" )+ embed Time.Tuesday =+ Field declared (Core.makeFieldSelection "Tuesday")+ embed Time.Wednesday =+ Field declared (Core.makeFieldSelection "Wednesday")+ embed Time.Thursday =+ Field declared (Core.makeFieldSelection "Thursday")+ embed Time.Friday =+ Field declared (Core.makeFieldSelection "Friday")+ embed Time.Saturday =+ Field declared (Core.makeFieldSelection "Saturday")++ declared =+ Union+ (Dhall.Map.fromList+ [ ("Sunday", Nothing)+ , ("Monday", Nothing)+ , ("Tuesday", Nothing)+ , ("Wednesday", Nothing)+ , ("Thursday", Nothing)+ , ("Friday", Nothing)+ , ("Saturday", Nothing)+ ]+ )++{-| Note that the output list will be sorted.++>>> let x = Data.Set.fromList ["mom", "hi" :: Text]+>>> prettyExpr $ embed inject x+[ "hi", "mom" ]++-}+instance ToDhall a => ToDhall (Data.Set.Set a) where+ injectWith = fmap (contramap Data.Set.toAscList) injectWith++-- | Note that the output list may not be sorted+instance ToDhall a => ToDhall (Data.HashSet.HashSet a) where+ injectWith = fmap (contramap Data.HashSet.toList) injectWith++instance (ToDhall a, ToDhall b) => ToDhall (a, b)++{-| Embed a `Data.Map` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (Data.Map.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (Data.Map.fromList [] :: Data.Map.Map Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (Data.Map.Map k v) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut m = ListLit listType (mapEntries m)+ where+ listType+ | Data.Map.null m = Just declaredOut+ | otherwise = Nothing++ declaredOut = App List (Record $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField declaredK)+ , ("mapValue", Core.makeRecordField declaredV)+ ])++ mapEntries = Data.Sequence.fromList . fmap recordPair . Data.Map.toList+ recordPair (k, v) = RecordLit $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField $ embedK k)+ , ("mapValue", Core.makeRecordField $ embedV v)+ ]++ Encoder embedK declaredK = injectWith inputNormalizer+ Encoder embedV declaredV = injectWith inputNormalizer++{-| Embed a `Data.HashMap` as a @Prelude.Map.Type@.++>>> prettyExpr $ embed inject (HashMap.fromList [(1 :: Natural, True)])+[ { mapKey = 1, mapValue = True } ]++>>> prettyExpr $ embed inject (HashMap.fromList [] :: HashMap Natural Bool)+[] : List { mapKey : Natural, mapValue : Bool }++-}+instance (ToDhall k, ToDhall v) => ToDhall (HashMap k v) where+ injectWith inputNormalizer = Encoder embedOut declaredOut+ where+ embedOut m = ListLit listType (mapEntries m)+ where+ listType+ | HashMap.null m = Just declaredOut+ | otherwise = Nothing++ declaredOut = App List (Record $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField declaredK)+ , ("mapValue", Core.makeRecordField declaredV)+ ])++ mapEntries = Data.Sequence.fromList . fmap recordPair . HashMap.toList+ recordPair (k, v) = RecordLit $ Dhall.Map.fromList+ [ ("mapKey", Core.makeRecordField $ embedK k)+ , ("mapValue", Core.makeRecordField $ embedV v)+ ]++ Encoder embedK declaredK = injectWith inputNormalizer+ Encoder embedV declaredV = injectWith inputNormalizer++instance ToDhall (f (Result f)) => ToDhall (Result f) where+ injectWith inputNormalizer = Encoder {..}+ where+ embed = App "Make" . Dhall.Marshal.Encode.embed (injectWith inputNormalizer) . _unResult+ declared = "result"++instance forall f. (Functor f, ToDhall (f (Result f))) => ToDhall (Fix f) where+ injectWith inputNormalizer = Encoder {..}+ where+ embed fixf =+ Lam Nothing (Core.makeFunctionBinding "result" (Const Core.Type)) $+ Lam Nothing (Core.makeFunctionBinding "Make" makeType) $+ embed' . fixToResult $ fixf++ declared = Pi Nothing "result" (Const Core.Type) $ Pi Nothing "_" makeType "result"++ makeType = Pi Nothing "_" declared' "result"+ Encoder embed' _ = injectWith @(Dhall.Marshal.Internal.Result f) inputNormalizer+ Encoder _ declared' = injectWith @(f (Dhall.Marshal.Internal.Result f)) inputNormalizer++fixToResult :: Functor f => Fix f -> Result f+fixToResult (Fix x) = Result (fmap fixToResult x)++++{-| This is the underlying class that powers the `Dhall.Marshal.Decode.FromDhall` class's support+ for automatically deriving a generic implementation.+-}+class GenericToDhall f where+ genericToDhallWithNormalizer :: InputNormalizer -> InterpretOptions -> State Int (Encoder (f a))++instance GenericToDhall f => GenericToDhall (M1 D d f) where+ genericToDhallWithNormalizer inputNormalizer options = do+ res <- genericToDhallWithNormalizer inputNormalizer options+ pure (contramap unM1 res)++instance GenericToDhall f => GenericToDhall (M1 C c f) where+ genericToDhallWithNormalizer inputNormalizer options = do+ res <- genericToDhallWithNormalizer inputNormalizer options+ pure (contramap unM1 res)++instance (Selector s, ToDhall a) => GenericToDhall (M1 S s (K1 i a)) where+ genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+ let Encoder { embed = embed', declared = declared' } =+ injectWith inputNormalizer++ let n :: M1 S s (K1 i a) r+ n = undefined++ name <- fieldModifier <$> getSelName n++ let embed0 (M1 (K1 x)) = embed' x++ let embed1 (M1 (K1 x)) =+ RecordLit (Dhall.Map.singleton name (Core.makeRecordField $ embed' x))++ let embed =+ case singletonConstructors of+ Bare -> embed0+ Smart | selName n == "" -> embed0+ _ -> embed1++ let declared =+ case singletonConstructors of+ Bare ->+ declared'+ Smart | selName n == "" ->+ declared'+ _ ->+ Record (Dhall.Map.singleton name $ Core.makeRecordField declared')++ return (Encoder {..})++instance (Constructor c1, Constructor c2, GenericToDhall f1, GenericToDhall f2) => GenericToDhall (M1 C c1 f1 :+: M1 C c2 f2) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 (M1 l)) =+ case notEmptyRecordLit (embedL l) of+ Nothing ->+ Field declared $ Core.makeFieldSelection keyL+ Just valL ->+ App (Field declared $ Core.makeFieldSelection keyL) valL++ embed (R1 (M1 r)) =+ case notEmptyRecordLit (embedR r) of+ Nothing ->+ Field declared $ Core.makeFieldSelection keyR+ Just valR ->+ App (Field declared $ Core.makeFieldSelection keyR) valR++ declared =+ Union+ (Dhall.Map.fromList+ [ (keyL, notEmptyRecord declaredL)+ , (keyR, notEmptyRecord declaredR)+ ]+ )++ nL :: M1 i c1 f1 a+ nL = undefined++ nR :: M1 i c2 f2 a+ nR = undefined++ keyL = constructorModifier (Data.Text.pack (conName nL))+ keyR = constructorModifier (Data.Text.pack (conName nR))++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++instance (Constructor c, GenericToDhall (f :+: g), GenericToDhall h) => GenericToDhall ((f :+: g) :+: M1 C c h) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 l) =+ case maybeValL of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ where+ (keyL, maybeValL) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+ embed (R1 (M1 r)) =+ case notEmptyRecordLit (embedR r) of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR++ nR :: M1 i c h a+ nR = undefined++ keyR = constructorModifier (Data.Text.pack (conName nR))++ declared = Union (Dhall.Map.insert keyR (notEmptyRecord declaredR) ktsL)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL++instance (Constructor c, GenericToDhall f, GenericToDhall (g :+: h)) => GenericToDhall (M1 C c f :+: (g :+: h)) where+ genericToDhallWithNormalizer inputNormalizer options@(InterpretOptions {..}) = pure (Encoder {..})+ where+ embed (L1 (M1 l)) =+ case notEmptyRecordLit (embedL l) of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ embed (R1 r) =+ case maybeValR of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+ where+ (keyR, maybeValR) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++ nL :: M1 i c f a+ nL = undefined++ keyL = constructorModifier (Data.Text.pack (conName nL))++ declared = Union (Dhall.Map.insert keyL (notEmptyRecord declaredL) ktsR)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :+: g), GenericToDhall (h :+: i)) => GenericToDhall ((f :+: g) :+: (h :+: i)) where+ genericToDhallWithNormalizer inputNormalizer options = pure (Encoder {..})+ where+ embed (L1 l) =+ case maybeValL of+ Nothing -> Field declared $ Core.makeFieldSelection keyL+ Just valL -> App (Field declared $ Core.makeFieldSelection keyL) valL+ where+ (keyL, maybeValL) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedL l)+ embed (R1 r) =+ case maybeValR of+ Nothing -> Field declared $ Core.makeFieldSelection keyR+ Just valR -> App (Field declared $ Core.makeFieldSelection keyR) valR+ where+ (keyR, maybeValR) =+ unsafeExpectUnionLit "genericToDhallWithNormalizer (:+:)" (embedR r)++ declared = Union (Dhall.Map.union ktsL ktsR)++ Encoder embedL declaredL = evalState (genericToDhallWithNormalizer inputNormalizer options) 1+ Encoder embedR declaredR = evalState (genericToDhallWithNormalizer inputNormalizer options) 1++ ktsL = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredL+ ktsR = unsafeExpectUnion "genericToDhallWithNormalizer (:+:)" declaredR++instance (GenericToDhall (f :*: g), GenericToDhall (h :*: i)) => GenericToDhall ((f :*: g) :*: (h :*: i)) where+ genericToDhallWithNormalizer inputNormalizer options = do+ Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options+ Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++ let embed (l :*: r) =+ RecordLit (Dhall.Map.union mapL mapR)+ where+ mapL =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++ mapR =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++ let declared = Record (Dhall.Map.union mapL mapR)+ where+ mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL+ mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++ pure (Encoder {..})++instance (GenericToDhall (f :*: g), Selector s, ToDhall a) => GenericToDhall ((f :*: g) :*: M1 S s (K1 i a)) where+ genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+ let nR :: M1 S s (K1 i a) r+ nR = undefined++ nameR <- fmap fieldModifier (getSelName nR)++ Encoder embedL declaredL <- genericToDhallWithNormalizer inputNormalizer options++ let Encoder embedR declaredR = injectWith inputNormalizer++ let embed (l :*: M1 (K1 r)) =+ RecordLit (Dhall.Map.insert nameR (Core.makeRecordField $ embedR r) mapL)+ where+ mapL =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedL l)++ let declared = Record (Dhall.Map.insert nameR (Core.makeRecordField declaredR) mapL)+ where+ mapL = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredL++ return (Encoder {..})++instance (Selector s, ToDhall a, GenericToDhall (f :*: g)) => GenericToDhall (M1 S s (K1 i a) :*: (f :*: g)) where+ genericToDhallWithNormalizer inputNormalizer options@InterpretOptions{..} = do+ let nL :: M1 S s (K1 i a) r+ nL = undefined++ nameL <- fmap fieldModifier (getSelName nL)++ let Encoder embedL declaredL = injectWith inputNormalizer++ Encoder embedR declaredR <- genericToDhallWithNormalizer inputNormalizer options++ let embed (M1 (K1 l) :*: r) =+ RecordLit (Dhall.Map.insert nameL (Core.makeRecordField $ embedL l) mapR)+ where+ mapR =+ unsafeExpectRecordLit "genericToDhallWithNormalizer (:*:)" (embedR r)++ let declared = Record (Dhall.Map.insert nameL (Core.makeRecordField declaredL) mapR)+ where+ mapR = unsafeExpectRecord "genericToDhallWithNormalizer (:*:)" declaredR++ return (Encoder {..})++instance (Selector s1, Selector s2, ToDhall a1, ToDhall a2) => GenericToDhall (M1 S s1 (K1 i1 a1) :*: M1 S s2 (K1 i2 a2)) where+ genericToDhallWithNormalizer inputNormalizer InterpretOptions{..} = do+ let nL :: M1 S s1 (K1 i1 a1) r+ nL = undefined++ let nR :: M1 S s2 (K1 i2 a2) r+ nR = undefined++ nameL <- fmap fieldModifier (getSelName nL)+ nameR <- fmap fieldModifier (getSelName nR)++ let Encoder embedL declaredL = injectWith inputNormalizer+ let Encoder embedR declaredR = injectWith inputNormalizer++ let embed (M1 (K1 l) :*: M1 (K1 r)) =+ RecordLit $+ Dhall.Map.fromList+ [ (nameL, Core.makeRecordField $ embedL l)+ , (nameR, Core.makeRecordField $ embedR r) ]+++ let declared =+ Record $ Dhall.Map.fromList+ [ (nameL, Core.makeRecordField declaredL)+ , (nameR, Core.makeRecordField declaredR) ]+++ return (Encoder {..})++instance GenericToDhall U1 where+ genericToDhallWithNormalizer _ _ = pure (Encoder {..})+ where+ embed _ = RecordLit mempty++ declared = Record mempty++{-| Use the default options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhall+ :: (Generic a, GenericToDhall (Rep a)) => Encoder a+genericToDhall+ = genericToDhallWith defaultInterpretOptions++{-| Use custom options for injecting a value, whose structure is+determined generically.++This can be used when you want to use 'ToDhall' on types that you don't+want to define orphan instances for.+-}+genericToDhallWith+ :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> Encoder a+genericToDhallWith options = genericToDhallWithInputNormalizer options defaultInputNormalizer++{-| `genericToDhallWithInputNormalizer` is like `genericToDhallWith`, but+ instead of using the `defaultInputNormalizer` it expects an custom+ `InputNormalizer`.+-}+genericToDhallWithInputNormalizer+ :: (Generic a, GenericToDhall (Rep a)) => InterpretOptions -> InputNormalizer -> Encoder a+genericToDhallWithInputNormalizer options inputNormalizer+ = contramap GHC.Generics.from (evalState (genericToDhallWithNormalizer inputNormalizer options) 1)++++{-| The 'RecordEncoder' divisible (contravariant) functor allows you to build+ an 'Encoder' for a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Project = Project+ { projectName :: Text+ , projectDescription :: Text+ , projectStars :: Natural+ }+:}++ And assume that we have the following Dhall record that we would like to+ parse as a @Project@:++> { name =+> "dhall-haskell"+> , description =+> "A configuration language guaranteed to terminate"+> , stars =+> 289+> }++ Our encoder has type 'Encoder' @Project@, but we can't build that out of any+ smaller encoders, as 'Encoder's cannot be combined (they are only 'Contravariant's).+ However, we can use an 'RecordEncoder' to build an 'Encoder' for @Project@:++>>> :{+injectProject :: Encoder Project+injectProject =+ recordEncoder+ ( adapt >$< encodeFieldWith "name" inject+ >*< encodeFieldWith "description" inject+ >*< encodeFieldWith "stars" inject+ )+ where+ adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++ Or, since we are simply using the `ToDhall` instance to inject each field, we could write++>>> :{+injectProject :: Encoder Project+injectProject =+ recordEncoder+ ( adapt >$< encodeField "name"+ >*< encodeField "description"+ >*< encodeField "stars"+ )+ where+ adapt (Project{..}) = (projectName, (projectDescription, projectStars))+:}++-}+newtype RecordEncoder a+ = RecordEncoder (Dhall.Map.Map Text (Encoder a))++instance Contravariant RecordEncoder where+ contramap f (RecordEncoder encodeTypeRecord) = RecordEncoder $ contramap f <$> encodeTypeRecord++instance Divisible RecordEncoder where+ divide f (RecordEncoder bEncoderRecord) (RecordEncoder cEncoderRecord) =+ RecordEncoder+ $ Dhall.Map.union+ ((contramap $ fst . f) <$> bEncoderRecord)+ ((contramap $ snd . f) <$> cEncoderRecord)+ conquer = RecordEncoder mempty++-- | Convert a `RecordEncoder` into the equivalent `Encoder`.+recordEncoder :: RecordEncoder a -> Encoder a+recordEncoder (RecordEncoder encodeTypeRecord) = Encoder makeRecordLit recordType+ where+ recordType = Record $ (Core.makeRecordField . declared) <$> encodeTypeRecord+ makeRecordLit x = RecordLit $ (Core.makeRecordField . ($ x) . embed) <$> encodeTypeRecord++{-| Specify how to encode one field of a record using the default `ToDhall`+ instance for that type.+-}+encodeField :: ToDhall a => Text -> RecordEncoder a+encodeField name = encodeFieldWith name inject++{-| Specify how to encode one field of a record by supplying an explicit+ `Encoder` for that field.+-}+encodeFieldWith :: Text -> Encoder a -> RecordEncoder a+encodeFieldWith name encodeType = RecordEncoder $ Dhall.Map.singleton name encodeType++++{-| 'UnionEncoder' allows you to build an 'Encoder' for a Dhall record.++ For example, let's take the following Haskell data type:++>>> :{+data Status = Queued Natural+ | Result Text+ | Errored Text+:}++ And assume that we have the following Dhall union that we would like to+ parse as a @Status@:++> < Result : Text+> | Queued : Natural+> | Errored : Text+> >.Result "Finish successfully"++ Our encoder has type 'Encoder' @Status@, but we can't build that out of any+ smaller encoders, as 'Encoder's cannot be combined.+ However, we can use an 'UnionEncoder' to build an 'Encoder' for @Status@:++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+ ( encodeConstructorWith "Queued" inject+ >|< encodeConstructorWith "Result" inject+ >|< encodeConstructorWith "Errored" inject+ )+ where+ adapt (Queued n) = Left n+ adapt (Result t) = Right (Left t)+ adapt (Errored e) = Right (Right e)+:}++ Or, since we are simply using the `ToDhall` instance to inject each branch, we could write++>>> :{+injectStatus :: Encoder Status+injectStatus = adapt >$< unionEncoder+ ( encodeConstructor "Queued"+ >|< encodeConstructor "Result"+ >|< encodeConstructor "Errored"+ )+ where+ adapt (Queued n) = Left n+ adapt (Result t) = Right (Left t)+ adapt (Errored e) = Right (Right e)+:}++-}+newtype UnionEncoder a =+ UnionEncoder+ ( Data.Functor.Product.Product+ ( Control.Applicative.Const+ ( Dhall.Map.Map+ Text+ ( Expr Src Void )+ )+ )+ ( Op (Text, Expr Src Void) )+ a+ )+ deriving (Contravariant)++-- | Convert a `UnionEncoder` into the equivalent `Encoder`.+unionEncoder :: UnionEncoder a -> Encoder a+unionEncoder ( UnionEncoder ( Data.Functor.Product.Pair ( Control.Applicative.Const fields ) ( Op embedF ) ) ) =+ Encoder+ { embed = \x ->+ let (name, y) = embedF x+ in case notEmptyRecordLit y of+ Nothing -> Field (Union fields') $ Core.makeFieldSelection name+ Just val -> App (Field (Union fields') $ Core.makeFieldSelection name) val+ , declared =+ Union fields'+ }+ where+ fields' = fmap notEmptyRecord fields++{-| Specify how to encode an alternative by using the default `ToDhall` instance+ for that type.+-}+encodeConstructor+ :: ToDhall a+ => Text+ -> UnionEncoder a+encodeConstructor name = encodeConstructorWith name inject++{-| Specify how to encode an alternative by providing an explicit `Encoder`+ for that alternative.+-}+encodeConstructorWith+ :: Text+ -> Encoder a+ -> UnionEncoder a+encodeConstructorWith name encodeType = UnionEncoder $+ Data.Functor.Product.Pair+ ( Control.Applicative.Const+ ( Dhall.Map.singleton+ name+ ( declared encodeType )+ )+ )+ ( Op ( (name,) . embed encodeType )+ )++-- | Combines two 'UnionEncoder' values. See 'UnionEncoder' for usage+-- notes.+--+-- Ideally, this matches 'Data.Functor.Contravariant.Divisible.chosen';+-- however, this allows 'UnionEncoder' to not need a 'Divisible' instance+-- itself (since no instance is possible).+(>|<) :: UnionEncoder a -> UnionEncoder b -> UnionEncoder (Either a b)+UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const mx) (Op fx))+ >|< UnionEncoder (Data.Functor.Product.Pair (Control.Applicative.Const my) (Op fy)) =+ UnionEncoder+ ( Data.Functor.Product.Pair+ ( Control.Applicative.Const (mx <> my) )+ ( Op (either fx fy) )+ )++infixr 5 >|<++++-- | Infix 'divided'+(>*<) :: Divisible f => f a -> f b -> f (a, b)+(>*<) = divided++infixr 5 >*<
@@ -0,0 +1,193 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++{-| Please read the "Dhall.Tutorial" module, which contains a tutorial explaining+ how to use the language, the compiler, and this library+-}++module Dhall.Marshal.Internal+ ( InputNormalizer(..)+ , defaultInputNormalizer+ , InterpretOptions(..)+ , SingletonConstructors(..)+ , defaultInterpretOptions++ -- * Miscellaneous+ , Result(..)++ -- * Helpers for the generic deriving machinery+ , getSelName+ , notEmptyRecord+ , notEmptyRecordLit+ , unsafeExpectRecord+ , unsafeExpectRecordLit+ , unsafeExpectUnion+ , unsafeExpectUnionLit++ -- * Re-exports+ , Fix(..)+ , HashMap+ , Int8+ , Int16+ , Int32+ , Int64+ , Map+ , Natural+ , Scientific+ , Seq+ , Text+ , Vector+ , Void+ , Word8+ , Word16+ , Word32+ , Word64+ , Generic+ ) where++import Control.Monad.Trans.State.Strict+import Data.Fix (Fix (..))+import Data.HashMap.Strict (HashMap)+import Data.Int (Int16, Int32, Int64, Int8)+import Data.Map (Map)+import Data.Scientific (Scientific)+import Data.Sequence (Seq)+import Data.Text (Text)+import Data.Vector (Vector)+import Data.Void (Void)+import Data.Word (Word16, Word32, Word64, Word8)+import Dhall.Parser (Src (..))+import Dhall.Syntax (Expr (..), RecordField (..))+import GHC.Generics+import Numeric.Natural (Natural)+import Prelude hiding (maybe, sequence)++import qualified Data.Text+import qualified Dhall.Core as Core+import qualified Dhall.Map++{-| This type is exactly the same as `Data.Fix.Fix` except with a different+ `Dhall.Marshal.Decode.FromDhall` instance. This intermediate type+ simplifies the implementation of the inner loop for the+ `Dhall.Marshal.Decode.FromDhall` instance for `Fix`.+-}+newtype Result f = Result { _unResult :: f (Result f) }++{-| Use these options to tweak how Dhall derives a generic implementation of+ `Dhall.Marshal.Decode.FromDhall`.+-}+data InterpretOptions = InterpretOptions+ { fieldModifier :: Text -> Text+ -- ^ Function used to transform Haskell field names into their corresponding+ -- Dhall field names+ , constructorModifier :: Text -> Text+ -- ^ Function used to transform Haskell constructor names into their+ -- corresponding Dhall alternative names+ , singletonConstructors :: SingletonConstructors+ -- ^ Specify how to handle constructors with only one field. The default is+ -- `Smart`+ }++{-| This is only used by the `Dhall.Marshal.Decode.FromDhall` instance for+ functions in order to normalize the function input before marshaling the+ input into a Dhall expression.+-}+newtype InputNormalizer = InputNormalizer+ { getInputNormalizer :: Core.ReifiedNormalizer Void }++-- | Default normalization-related settings (no custom normalization)+defaultInputNormalizer :: InputNormalizer+defaultInputNormalizer = InputNormalizer+ { getInputNormalizer = Core.ReifiedNormalizer (const (pure Nothing)) }++{-| This type specifies how to model a Haskell constructor with 1 field in+ Dhall++ For example, consider the following Haskell datatype definition:++ > data Example = Foo { x :: Double } | Bar Double++ Depending on which option you pick, the corresponding Dhall type could be:++ > < Foo : Double | Bar : Double > -- Bare++ > < Foo : { x : Double } | Bar : { _1 : Double } > -- Wrapped++ > < Foo : { x : Double } | Bar : Double > -- Smart+-}+data SingletonConstructors+ = Bare+ -- ^ Never wrap the field in a record+ | Wrapped+ -- ^ Always wrap the field in a record+ | Smart+ -- ^ Only fields in a record if they are named++{-| Default interpret options for generics-based instances,+ which you can tweak or override, like this:++> genericAutoWith+> (defaultInterpretOptions { fieldModifier = Data.Text.Lazy.dropWhile (== '_') })+-}+defaultInterpretOptions :: InterpretOptions+defaultInterpretOptions = InterpretOptions+ { fieldModifier =+ id+ , constructorModifier =+ id+ , singletonConstructors =+ Smart+ }++unsafeExpectUnion+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (Maybe (Expr Src Void))+unsafeExpectUnion _ (Union kts) =+ kts+unsafeExpectUnion name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecord+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecord _ (Record kts) =+ kts+unsafeExpectRecord name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectUnionLit+ :: Text+ -> Expr Src Void+ -> (Text, Maybe (Expr Src Void))+unsafeExpectUnionLit _ (Field (Union _) (Core.fieldSelectionLabel -> k)) =+ (k, Nothing)+unsafeExpectUnionLit _ (App (Field (Union _) (Core.fieldSelectionLabel -> k)) v) =+ (k, Just v)+unsafeExpectUnionLit name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++unsafeExpectRecordLit+ :: Text -> Expr Src Void -> Dhall.Map.Map Text (RecordField Src Void)+unsafeExpectRecordLit _ (RecordLit kvs) =+ kvs+unsafeExpectRecordLit name expression =+ Core.internalError+ (name <> ": Unexpected constructor: " <> Core.pretty expression)++notEmptyRecordLit :: Expr s a -> Maybe (Expr s a)+notEmptyRecordLit e = case e of+ RecordLit m | null m -> Nothing+ _ -> Just e++notEmptyRecord :: Expr s a -> Maybe (Expr s a)+notEmptyRecord e = case e of+ Record m | null m -> Nothing+ _ -> Just e++getSelName :: Selector s => M1 i s f a -> State Int Text+getSelName n = case selName n of+ "" -> do i <- get+ put (i + 1)+ pure (Data.Text.pack ("_" ++ show i))+ nn -> pure (Data.Text.pack nn)
@@ -23,7 +23,7 @@ import Control.Applicative (empty) import Data.Foldable import Data.Functor.Identity (Identity (..))-import Data.List.NonEmpty (NonEmpty(..))+import Data.List.NonEmpty (NonEmpty (..)) import Data.Sequence (ViewL (..), ViewR (..)) import Data.Traversable import Instances.TH.Lift ()@@ -39,6 +39,7 @@ , PreferAnnotation (..) , RecordField (..) , Var (..)+ , WithComponent (..) ) import qualified Data.Sequence@@ -46,9 +47,8 @@ import qualified Data.Text as Text import qualified Dhall.Eval as Eval import qualified Dhall.Map-import qualified Dhall.Set import qualified Dhall.Syntax as Syntax-import qualified Lens.Family as Lens+import qualified Lens.Micro as Lens {-| Returns `True` if two expressions are α-equivalent and β-equivalent and `False` otherwise@@ -66,13 +66,13 @@ -} subst :: Var -> Expr s a -> Expr s a -> Expr s a subst _ _ (Const a) = Const a-subst (V x n) e (Lam (FunctionBinding src0 y src1 src2 _A) b) =- Lam (FunctionBinding src0 y src1 src2 _A') b'+subst (V x n) e (Lam cs (FunctionBinding src0 y src1 src2 _A) b) =+ Lam cs (FunctionBinding src0 y src1 src2 _A') b' where _A' = subst (V x n ) e _A b' = subst (V x n') (Syntax.shift 1 (V y 0) e) b n' = if x == y then n + 1 else n-subst (V x n) e (Pi y _A _B) = Pi y _A' _B'+subst (V x n) e (Pi cs y _A _B) = Pi cs y _A' _B' where _A' = subst (V x n ) e _A _B' = subst (V x n') (Syntax.shift 1 (V y 0) e) _B@@ -115,8 +115,8 @@ using De Bruijn indices to distinguish them >>> mfb = Syntax.makeFunctionBinding->>> alphaNormalize (Lam (mfb "a" (Const Type)) (Lam (mfb "b" (Const Type)) (Lam (mfb "x" "a") (Lam (mfb "y" "b") "x"))))-Lam (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Lam (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Var (V "_" 1)))))+>>> alphaNormalize (Lam mempty (mfb "a" (Const Type)) (Lam mempty (mfb "b" (Const Type)) (Lam mempty (mfb "x" "a") (Lam mempty (mfb "y" "b") "x"))))+Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Const Type}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Lam Nothing (FunctionBinding {functionBindingSrc0 = Nothing, functionBindingVariable = "_", functionBindingSrc1 = Nothing, functionBindingSrc2 = Nothing, functionBindingAnnotation = Var (V "_" 1)}) (Var (V "_" 1))))) α-normalization does not affect free variables: @@ -161,6 +161,7 @@ normalizeWith :: Eq a => Maybe (ReifiedNormalizer a) -> Expr s a -> Expr t a normalizeWith (Just ctx) t = runIdentity (normalizeWithM (getReifiedNormalizer ctx) t) normalizeWith _ t = Eval.normalize t+{-# INLINABLE normalizeWith #-} {-| This function generalizes `normalizeWith` by allowing the custom normalizer to use an arbitrary `Monad`@@ -172,27 +173,25 @@ :: (Monad m, Eq a) => NormalizerM m a -> Expr s a -> m (Expr t a) normalizeWithM ctx e0 = loop (Syntax.denote e0) where- loop = \case- Const k -> pure (Const k)- Var v -> pure (Var v)- Lam (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->- Lam <$> (Syntax.makeFunctionBinding x <$> _A') <*> b'- where- _A' = loop _A- b' = loop b- Pi x _A _B -> Pi x <$> _A' <*> _B'- where- _A' = loop _A- _B' = loop _B- App f a -> do- res <- ctx (App f a)- case res of- Just e1 -> loop e1- Nothing -> do+ loop e = ctx e >>= \case+ Just e' -> loop e'+ Nothing -> case e of+ Const k -> pure (Const k)+ Var v -> pure (Var v)+ Lam cs (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A }) b ->+ Lam cs <$> (Syntax.makeFunctionBinding x <$> _A') <*> b'+ where+ _A' = loop _A+ b' = loop b+ Pi cs x _A _B -> Pi cs x <$> _A' <*> _B'+ where+ _A' = loop _A+ _B' = loop _B+ App f a -> do f' <- loop f a' <- loop a case f' of- Lam (FunctionBinding _ x _ _ _A) b₀ -> do+ Lam _ (FunctionBinding _ x _ _ _A) b₀ -> do let a₂ = Syntax.shift 1 (V x 0) a' let b₁ = subst (V x 0) a₂ b₀@@ -212,14 +211,22 @@ strict = strictLoop (fromIntegral n0 :: Integer) lazy = loop ( lazyLoop (fromIntegral n0 :: Integer)) - strictLoop 0 = loop zero- strictLoop !n = App succ' <$> strictLoop (n - 1) >>= loop+ strictLoop !n = do+ z <- loop zero+ strictLoopShortcut n z + strictLoopShortcut 0 !previous = pure previous+ strictLoopShortcut !n !previous = do+ current <- loop (App succ' previous)+ if judgmentallyEqual previous current+ then pure previous+ else strictLoopShortcut (n - 1) current+ lazyLoop 0 = zero lazyLoop !n = App succ' (lazyLoop (n - 1)) App NaturalBuild g -> loop (App (App (App g Natural) succ) zero) where- succ = Lam (Syntax.makeFunctionBinding "n" Natural) (NaturalPlus "n" (NaturalLit 1))+ succ = Lam mempty (Syntax.makeFunctionBinding "n" Natural) (NaturalPlus "n" (NaturalLit 1)) zero = NaturalLit 0 App NaturalIsZero (NaturalLit n) -> pure (BoolLit (n == 0))@@ -261,8 +268,8 @@ list = App List _A₀ cons =- Lam (Syntax.makeFunctionBinding "a" _A₀)- (Lam+ Lam mempty (Syntax.makeFunctionBinding "a" _A₀)+ (Lam mempty (Syntax.makeFunctionBinding "as" (App List _A₁)) (ListAppend (ListLit Nothing (pure "a")) "as") )@@ -376,326 +383,382 @@ suffix loop (TextAppend (TextLit (Chunks [(prefix, replacement)] "")) (App (App (App TextReplace (TextLit (Chunks [] needleText))) replacement) (TextLit (Chunks ((remainder, firstInterpolation) : chunks) lastText))))+ App DateShow (DateLiteral date) ->+ loop (TextLit (Chunks [] text))+ where+ text = Eval.dateShow date+ App TimeShow (TimeLiteral time precision) ->+ loop (TextLit (Chunks [] text))+ where+ text = Eval.timeShow time precision+ App TimeZoneShow (TimeZoneLiteral timezone) ->+ loop (TextLit (Chunks [] text))+ where+ text = Eval.timezoneShow timezone _ -> do res2 <- ctx (App f' a') case res2 of Nothing -> pure (App f' a') Just app' -> loop app'- Let (Binding _ f _ _ _ r) b -> loop b''- where- r' = Syntax.shift 1 (V f 0) r- b' = subst (V f 0) r' b- b'' = Syntax.shift (-1) (V f 0) b'- Annot x _ -> loop x- Bool -> pure Bool- BoolLit b -> pure (BoolLit b)- BoolAnd x y -> decide <$> loop x <*> loop y- where- decide (BoolLit True ) r = r- decide (BoolLit False) _ = BoolLit False- decide l (BoolLit True ) = l- decide _ (BoolLit False) = BoolLit False- decide l r- | Eval.judgmentallyEqual l r = l- | otherwise = BoolAnd l r- BoolOr x y -> decide <$> loop x <*> loop y- where- decide (BoolLit False) r = r- decide (BoolLit True ) _ = BoolLit True- decide l (BoolLit False) = l- decide _ (BoolLit True ) = BoolLit True- decide l r- | Eval.judgmentallyEqual l r = l- | otherwise = BoolOr l r- BoolEQ x y -> decide <$> loop x <*> loop y- where- decide (BoolLit True ) r = r- decide l (BoolLit True ) = l- decide l r- | Eval.judgmentallyEqual l r = BoolLit True- | otherwise = BoolEQ l r- BoolNE x y -> decide <$> loop x <*> loop y- where- decide (BoolLit False) r = r- decide l (BoolLit False) = l- decide l r- | Eval.judgmentallyEqual l r = BoolLit False- | otherwise = BoolNE l r- BoolIf bool true false -> decide <$> loop bool <*> loop true <*> loop false- where- decide (BoolLit True ) l _ = l- decide (BoolLit False) _ r = r- decide b (BoolLit True) (BoolLit False) = b- decide b l r- | Eval.judgmentallyEqual l r = l- | otherwise = BoolIf b l r- Natural -> pure Natural- NaturalLit n -> pure (NaturalLit n)- NaturalFold -> pure NaturalFold- NaturalBuild -> pure NaturalBuild- NaturalIsZero -> pure NaturalIsZero- NaturalEven -> pure NaturalEven- NaturalOdd -> pure NaturalOdd- NaturalToInteger -> pure NaturalToInteger- NaturalShow -> pure NaturalShow- NaturalSubtract -> pure NaturalSubtract- NaturalPlus x y -> decide <$> loop x <*> loop y- where- decide (NaturalLit 0) r = r- decide l (NaturalLit 0) = l- decide (NaturalLit m) (NaturalLit n) = NaturalLit (m + n)- decide l r = NaturalPlus l r- NaturalTimes x y -> decide <$> loop x <*> loop y- where- decide (NaturalLit 1) r = r- decide l (NaturalLit 1) = l- decide (NaturalLit 0) _ = NaturalLit 0- decide _ (NaturalLit 0) = NaturalLit 0- decide (NaturalLit m) (NaturalLit n) = NaturalLit (m * n)- decide l r = NaturalTimes l r- Integer -> pure Integer- IntegerLit n -> pure (IntegerLit n)- IntegerClamp -> pure IntegerClamp- IntegerNegate -> pure IntegerNegate- IntegerShow -> pure IntegerShow- IntegerToDouble -> pure IntegerToDouble- Double -> pure Double- DoubleLit n -> pure (DoubleLit n)- DoubleShow -> pure DoubleShow- Text -> pure Text- TextLit (Chunks xys z) -> do- chunks' <- mconcat <$> chunks- case chunks' of- Chunks [("", x)] "" -> pure x- c -> pure (TextLit c)- where- chunks =- ((++ [Chunks [] z]) . concat) <$> traverse process xys+ Let (Binding _ f _ _ _ r) b -> loop b''+ where+ r' = Syntax.shift 1 (V f 0) r+ b' = subst (V f 0) r' b+ b'' = Syntax.shift (-1) (V f 0) b'+ Annot x _ -> loop x+ Bool -> pure Bool+ BoolLit b -> pure (BoolLit b)+ BoolAnd x y -> decide <$> loop x <*> loop y+ where+ decide (BoolLit True ) r = r+ decide (BoolLit False) _ = BoolLit False+ decide l (BoolLit True ) = l+ decide _ (BoolLit False) = BoolLit False+ decide l r+ | Eval.judgmentallyEqual l r = l+ | otherwise = BoolAnd l r+ BoolOr x y -> decide <$> loop x <*> loop y+ where+ decide (BoolLit False) r = r+ decide (BoolLit True ) _ = BoolLit True+ decide l (BoolLit False) = l+ decide _ (BoolLit True ) = BoolLit True+ decide l r+ | Eval.judgmentallyEqual l r = l+ | otherwise = BoolOr l r+ BoolEQ x y -> decide <$> loop x <*> loop y+ where+ decide (BoolLit True ) r = r+ decide l (BoolLit True ) = l+ decide l r+ | Eval.judgmentallyEqual l r = BoolLit True+ | otherwise = BoolEQ l r+ BoolNE x y -> decide <$> loop x <*> loop y+ where+ decide (BoolLit False) r = r+ decide l (BoolLit False) = l+ decide l r+ | Eval.judgmentallyEqual l r = BoolLit False+ | otherwise = BoolNE l r+ BoolIf bool true false -> decide <$> loop bool <*> loop true <*> loop false+ where+ decide (BoolLit True ) l _ = l+ decide (BoolLit False) _ r = r+ decide b (BoolLit True) (BoolLit False) = b+ decide b l r+ | Eval.judgmentallyEqual l r = l+ | otherwise = BoolIf b l r+ Bytes -> pure Bytes+ BytesLit b -> pure (BytesLit b)+ Natural -> pure Natural+ NaturalLit n -> pure (NaturalLit n)+ NaturalFold -> pure NaturalFold+ NaturalBuild -> pure NaturalBuild+ NaturalIsZero -> pure NaturalIsZero+ NaturalEven -> pure NaturalEven+ NaturalOdd -> pure NaturalOdd+ NaturalToInteger -> pure NaturalToInteger+ NaturalShow -> pure NaturalShow+ NaturalSubtract -> pure NaturalSubtract+ NaturalPlus x y -> decide <$> loop x <*> loop y+ where+ decide (NaturalLit 0) r = r+ decide l (NaturalLit 0) = l+ decide (NaturalLit m) (NaturalLit n) = NaturalLit (m + n)+ decide l r = NaturalPlus l r+ NaturalTimes x y -> decide <$> loop x <*> loop y+ where+ decide (NaturalLit 1) r = r+ decide l (NaturalLit 1) = l+ decide (NaturalLit 0) _ = NaturalLit 0+ decide _ (NaturalLit 0) = NaturalLit 0+ decide (NaturalLit m) (NaturalLit n) = NaturalLit (m * n)+ decide l r = NaturalTimes l r+ Integer -> pure Integer+ IntegerLit n -> pure (IntegerLit n)+ IntegerClamp -> pure IntegerClamp+ IntegerNegate -> pure IntegerNegate+ IntegerShow -> pure IntegerShow+ IntegerToDouble -> pure IntegerToDouble+ Double -> pure Double+ DoubleLit n -> pure (DoubleLit n)+ DoubleShow -> pure DoubleShow+ Text -> pure Text+ TextLit (Chunks xys z) -> do+ chunks' <- mconcat <$> chunks+ case chunks' of+ Chunks [("", x)] "" -> pure x+ c -> pure (TextLit c)+ where+ chunks =+ ((++ [Chunks [] z]) . concat) <$> traverse process xys - process (x, y) = do- y' <- loop y- case y' of- TextLit c -> pure [Chunks [] x, c]- _ -> pure [Chunks [(x, y')] mempty]- TextAppend x y -> loop (TextLit (Chunks [("", x), ("", y)] ""))- TextReplace -> pure TextReplace- TextShow -> pure TextShow- List -> pure List- ListLit t es- | Data.Sequence.null es -> ListLit <$> t' <*> pure Data.Sequence.empty- | otherwise -> ListLit Nothing <$> es'- where- t' = traverse loop t- es' = traverse loop es- ListAppend x y -> decide <$> loop x <*> loop y- where- decide (ListLit _ m) r | Data.Sequence.null m = r- decide l (ListLit _ n) | Data.Sequence.null n = l- decide (ListLit t m) (ListLit _ n) = ListLit t (m <> n)- decide l r = ListAppend l r- ListBuild -> pure ListBuild- ListFold -> pure ListFold- ListLength -> pure ListLength- ListHead -> pure ListHead- ListLast -> pure ListLast- ListIndexed -> pure ListIndexed- ListReverse -> pure ListReverse- Optional -> pure Optional- Some a -> Some <$> a'- where- a' = loop a- None -> pure None- Record kts -> Record . Dhall.Map.sort <$> kts'- where- f (RecordField s0 expr s1 s2) = (\e -> RecordField s0 e s1 s2) <$> loop expr- kts' = traverse f kts- RecordLit kvs -> RecordLit . Dhall.Map.sort <$> kvs'- where- f (RecordField s0 expr s1 s2) = (\e -> RecordField s0 e s1 s2) <$> loop expr- kvs' = traverse f kvs- Union kts -> Union . Dhall.Map.sort <$> kts'- where- kts' = traverse (traverse loop) kts- Combine mk x y -> decide <$> loop x <*> loop y- where- decide (RecordLit m) r | Data.Foldable.null m =- r- decide l (RecordLit n) | Data.Foldable.null n =- l- decide (RecordLit m) (RecordLit n) =- RecordLit (Dhall.Map.unionWith f m n)- where- f (RecordField _ expr _ _) (RecordField _ expr' _ _) =- Syntax.makeRecordField $ decide expr expr'- decide l r =- Combine mk l r- CombineTypes x y -> decide <$> loop x <*> loop y- where- decide (Record m) r | Data.Foldable.null m =- r- decide l (Record n) | Data.Foldable.null n =- l- decide (Record m) (Record n) =- Record (Dhall.Map.unionWith f m n)- where- f (RecordField _ expr _ _) (RecordField _ expr' _ _) =- Syntax.makeRecordField $ decide expr expr'- decide l r =- CombineTypes l r- Prefer _ x y -> decide <$> loop x <*> loop y- where- decide (RecordLit m) r | Data.Foldable.null m =- r- decide l (RecordLit n) | Data.Foldable.null n =- l- decide (RecordLit m) (RecordLit n) =- RecordLit (Dhall.Map.union n m)- decide l r | Eval.judgmentallyEqual l r =- l- decide l r =- Prefer PreferFromSource l r- RecordCompletion x y ->- loop (Annot (Prefer PreferFromCompletion (Field x def) y) (Field x typ))- where- def = Syntax.makeFieldSelection "default"- typ = Syntax.makeFieldSelection "Type"- Merge x y t -> do- x' <- loop x- y' <- loop y- case x' of- RecordLit kvsX ->+ process (x, y) = do+ y' <- loop y case y' of- Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->- case Dhall.Map.lookup kY ktsY of- Just Nothing ->- case recordFieldValue <$> Dhall.Map.lookup kY kvsX of- Just vX -> return vX- Nothing -> Merge x' y' <$> t'- _ ->- Merge x' y' <$> t'- App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) vY ->- case Dhall.Map.lookup kY ktsY of- Just (Just _) ->- case recordFieldValue <$> Dhall.Map.lookup kY kvsX of- Just vX -> loop (App vX vY)- Nothing -> Merge x' y' <$> t'- _ ->- Merge x' y' <$> t'- Some a ->- case recordFieldValue <$> Dhall.Map.lookup "Some" kvsX of- Just vX -> loop (App vX a)- Nothing -> Merge x' y' <$> t'- App None _ ->- case recordFieldValue <$> Dhall.Map.lookup "None" kvsX of- Just vX -> return vX- Nothing -> Merge x' y' <$> t'- _ -> Merge x' y' <$> t'- _ -> Merge x' y' <$> t'- where- t' = traverse loop t- ToMap x t -> do- x' <- loop x- t' <- traverse loop t- case x' of- RecordLit kvsX -> do- let entry (key, value) =- RecordLit- (Dhall.Map.fromList- [ ("mapKey" , Syntax.makeRecordField $ TextLit (Chunks [] key))- , ("mapValue", Syntax.makeRecordField value )- ]- )+ TextLit c -> pure [Chunks [] x, c]+ _ -> pure [Chunks [(x, y')] mempty]+ TextAppend x y -> loop (TextLit (Chunks [("", x), ("", y)] ""))+ TextReplace -> pure TextReplace+ TextShow -> pure TextShow+ Date -> pure Date+ DateLiteral d -> pure (DateLiteral d)+ DateShow -> pure DateShow+ Time -> pure Time+ TimeLiteral t p -> pure (TimeLiteral t p)+ TimeShow -> pure TimeShow+ TimeZone -> pure TimeZone+ TimeZoneLiteral z -> pure (TimeZoneLiteral z)+ TimeZoneShow -> pure TimeZoneShow+ List -> pure List+ ListLit t es+ | Data.Sequence.null es -> ListLit <$> t' <*> pure Data.Sequence.empty+ | otherwise -> ListLit Nothing <$> es'+ where+ t' = traverse loop t+ es' = traverse loop es+ ListAppend x y -> decide <$> loop x <*> loop y+ where+ decide (ListLit _ m) r | Data.Sequence.null m = r+ decide l (ListLit _ n) | Data.Sequence.null n = l+ decide (ListLit t m) (ListLit _ n) = ListLit t (m <> n)+ decide l r = ListAppend l r+ ListBuild -> pure ListBuild+ ListFold -> pure ListFold+ ListLength -> pure ListLength+ ListHead -> pure ListHead+ ListLast -> pure ListLast+ ListIndexed -> pure ListIndexed+ ListReverse -> pure ListReverse+ Optional -> pure Optional+ Some a -> Some <$> a'+ where+ a' = loop a+ None -> pure None+ Record kts -> Record . Dhall.Map.sort <$> kts'+ where+ f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+ kts' = traverse f kts+ RecordLit kvs -> RecordLit . Dhall.Map.sort <$> kvs'+ where+ f (RecordField s0 expr s1 s2) = (\expr' -> RecordField s0 expr' s1 s2) <$> loop expr+ kvs' = traverse f kvs+ Union kts -> Union . Dhall.Map.sort <$> kts'+ where+ kts' = traverse (traverse loop) kts+ Combine cs mk x y -> decide <$> loop x <*> loop y+ where+ decide (RecordLit m) r | Data.Foldable.null m =+ r+ decide l (RecordLit n) | Data.Foldable.null n =+ l+ decide (RecordLit m) (RecordLit n) =+ RecordLit (Dhall.Map.unionWith f m n)+ where+ f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+ Syntax.makeRecordField $ decide expr expr'+ decide l r =+ Combine cs mk l r+ CombineTypes cs x y -> decide <$> loop x <*> loop y+ where+ decide (Record m) r | Data.Foldable.null m =+ r+ decide l (Record n) | Data.Foldable.null n =+ l+ decide (Record m) (Record n) =+ Record (Dhall.Map.unionWith f m n)+ where+ f (RecordField _ expr _ _) (RecordField _ expr' _ _) =+ Syntax.makeRecordField $ decide expr expr'+ decide l r =+ CombineTypes cs l r+ Prefer cs _ x y -> decide <$> loop x <*> loop y+ where+ decide (RecordLit m) r | Data.Foldable.null m =+ r+ decide l (RecordLit n) | Data.Foldable.null n =+ l+ decide (RecordLit m) (RecordLit n) =+ RecordLit (Dhall.Map.union n m)+ decide l r | Eval.judgmentallyEqual l r =+ l+ decide l r =+ Prefer cs PreferFromSource l r+ RecordCompletion x y ->+ loop (Annot (Prefer mempty PreferFromCompletion (Field x def) y) (Field x typ))+ where+ def = Syntax.makeFieldSelection "default"+ typ = Syntax.makeFieldSelection "Type"+ Merge x y t -> do+ x' <- loop x+ y' <- loop y+ case x' of+ RecordLit kvsX ->+ case y' of+ Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+ case Dhall.Map.lookup kY ktsY of+ Just Nothing ->+ case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+ Just vX -> return vX+ Nothing -> Merge x' y' <$> t'+ _ ->+ Merge x' y' <$> t'+ App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) vY ->+ case Dhall.Map.lookup kY ktsY of+ Just (Just _) ->+ case recordFieldValue <$> Dhall.Map.lookup kY kvsX of+ Just vX -> loop (App vX vY)+ Nothing -> Merge x' y' <$> t'+ _ ->+ Merge x' y' <$> t'+ Some a ->+ case recordFieldValue <$> Dhall.Map.lookup "Some" kvsX of+ Just vX -> loop (App vX a)+ Nothing -> Merge x' y' <$> t'+ App None _ ->+ case recordFieldValue <$> Dhall.Map.lookup "None" kvsX of+ Just vX -> return vX+ Nothing -> Merge x' y' <$> t'+ _ -> Merge x' y' <$> t'+ _ -> Merge x' y' <$> t'+ where+ t' = traverse loop t+ ToMap x t -> do+ x' <- loop x+ t' <- traverse loop t+ case x' of+ RecordLit kvsX -> do+ let entry (key, value) =+ RecordLit+ (Dhall.Map.fromList+ [ ("mapKey" , Syntax.makeRecordField $ TextLit (Chunks [] key))+ , ("mapValue", Syntax.makeRecordField value )+ ]+ ) - let keyValues = Data.Sequence.fromList (map entry (Dhall.Map.toList $ recordFieldValue <$> kvsX))+ let keyValues = Data.Sequence.fromList (map entry (Dhall.Map.toList $ recordFieldValue <$> kvsX)) - let listType = case t' of- Just _ | null keyValues ->- t'- _ ->- Nothing+ let listType = case t' of+ Just _ | null keyValues ->+ t'+ _ ->+ Nothing - return (ListLit listType keyValues)- _ ->- return (ToMap x' t')- Field r k@FieldSelection{fieldSelectionLabel = x} -> do- let singletonRecordLit v = RecordLit (Dhall.Map.singleton x v)+ return (ListLit listType keyValues)+ _ ->+ return (ToMap x' t')+ ShowConstructor x -> do+ x' <- loop x+ return $ case x' of+ Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY) ->+ case Dhall.Map.lookup kY ktsY of+ Just Nothing -> TextLit (Chunks [] kY)+ _ -> ShowConstructor x'+ App (Field (Union ktsY) (Syntax.fieldSelectionLabel -> kY)) _ ->+ case Dhall.Map.lookup kY ktsY of+ Just (Just _) -> TextLit (Chunks [] kY)+ _ -> ShowConstructor x'+ Some _ ->+ TextLit (Chunks [] "Some")+ App None _ ->+ TextLit (Chunks [] "None")+ _ -> ShowConstructor x'+ Field r k@FieldSelection{fieldSelectionLabel = x} -> do+ let singletonRecordLit v = RecordLit (Dhall.Map.singleton x v) - r' <- loop r- case r' of- RecordLit kvs ->- case Dhall.Map.lookup x kvs of- Just v -> pure $ recordFieldValue v- Nothing -> Field <$> (RecordLit <$> traverse (Syntax.recordFieldExprs loop) kvs) <*> pure k- Project r_ _ -> loop (Field r_ k)- Prefer _ (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of- Just v -> pure (Field (Prefer PreferFromSource (singletonRecordLit v) r_) k)- Nothing -> loop (Field r_ k)- Prefer _ l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of- Just v -> pure $ recordFieldValue v- Nothing -> loop (Field l k)- Combine m (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of- Just v -> pure (Field (Combine m (singletonRecordLit v) r_) k)- Nothing -> loop (Field r_ k)- Combine m l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of- Just v -> pure (Field (Combine m l (singletonRecordLit v)) k)- Nothing -> loop (Field l k)- _ -> pure (Field r' k)- Project x (Left fields)-> do- x' <- loop x- let fieldsSet = Dhall.Set.toSet fields- case x' of- RecordLit kvs ->- pure (RecordLit (Dhall.Map.restrictKeys kvs fieldsSet))- Project y _ ->- loop (Project y (Left fields))- Prefer _ l (RecordLit rKvs) -> do- let rKs = Dhall.Map.keysSet rKvs- let l' = Project l (Left (Dhall.Set.fromSet (Data.Set.difference fieldsSet rKs)))- let r' = RecordLit (Dhall.Map.restrictKeys rKvs fieldsSet)- loop (Prefer PreferFromSource l' r')- _ | null fields -> pure (RecordLit mempty)- | otherwise -> pure (Project x' (Left (Dhall.Set.sort fields)))- Project r (Right e1) -> do- e2 <- loop e1+ r' <- loop r+ case r' of+ RecordLit kvs ->+ case Dhall.Map.lookup x kvs of+ Just v -> pure $ recordFieldValue v+ Nothing -> Field <$> (RecordLit <$> traverse (Syntax.recordFieldExprs loop) kvs) <*> pure k+ Project r_ _ -> loop (Field r_ k)+ Prefer cs _ (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+ Just v -> pure (Field (Prefer cs PreferFromSource (singletonRecordLit v) r_) k)+ Nothing -> loop (Field r_ k)+ Prefer _ _ l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+ Just v -> pure $ recordFieldValue v+ Nothing -> loop (Field l k)+ Combine cs m (RecordLit kvs) r_ -> case Dhall.Map.lookup x kvs of+ Just v -> pure (Field (Combine cs m (singletonRecordLit v) r_) k)+ Nothing -> loop (Field r_ k)+ Combine cs m l (RecordLit kvs) -> case Dhall.Map.lookup x kvs of+ Just v -> pure (Field (Combine cs m l (singletonRecordLit v)) k)+ Nothing -> loop (Field l k)+ _ -> pure (Field r' k)+ Project x (Left fields)-> do+ x' <- loop x+ let fieldsSet = Data.Set.fromList fields+ case x' of+ RecordLit kvs ->+ pure (RecordLit (Dhall.Map.restrictKeys kvs fieldsSet))+ Project y _ ->+ loop (Project y (Left fields))+ Prefer cs _ l (RecordLit rKvs) -> do+ let rKs = Dhall.Map.keysSet rKvs+ let l' = Project l (Left (Data.Set.toList (Data.Set.difference fieldsSet rKs)))+ let r' = RecordLit (Dhall.Map.restrictKeys rKvs fieldsSet)+ loop (Prefer cs PreferFromSource l' r')+ _ | null fields -> pure (RecordLit mempty)+ | otherwise -> pure (Project x' (Left (Data.Set.toList (Data.Set.fromList fields))))+ Project r (Right e1) -> do+ e2 <- loop e1 - case e2 of- Record kts ->- loop (Project r (Left (Dhall.Set.fromSet (Dhall.Map.keysSet kts))))- _ -> do- r' <- loop r- pure (Project r' (Right e2))- Assert t -> do- t' <- loop t+ case e2 of+ Record kts ->+ loop (Project r (Left (Data.Set.toList (Dhall.Map.keysSet kts))))+ _ -> do+ r' <- loop r+ pure (Project r' (Right e2))+ Assert t -> do+ t' <- loop t - pure (Assert t')- Equivalent l r -> do- l' <- loop l- r' <- loop r+ pure (Assert t')+ Equivalent cs l r -> do+ l' <- loop l+ r' <- loop r - pure (Equivalent l' r')- With e ks v -> do- e' <- loop e- v' <- loop v+ pure (Equivalent cs l' r')+ With r ks v -> do+ r' <- loop r+ v' <- loop v - case e' of- RecordLit kvs ->- case ks of- k :| [] ->- return (RecordLit (Dhall.Map.insert k (Syntax.makeRecordField v') kvs))- k₀ :| k₁ : ks' -> do- let e₁ =- case Dhall.Map.lookup k₀ kvs of- Nothing -> RecordLit mempty- Just r -> Syntax.recordFieldValue r+ case r' of+ RecordLit kvs ->+ case ks of+ WithLabel k :| [] ->+ return (RecordLit (Dhall.Map.insert k (Syntax.makeRecordField v') kvs))+ WithLabel k₀ :| k₁ : ks' -> do+ let e₁ =+ case Dhall.Map.lookup k₀ kvs of+ Nothing -> RecordLit mempty+ Just val -> Syntax.recordFieldValue val - e₂ <- loop (With e₁ (k₁ :| ks') v')+ e₂ <- loop (With e₁ (k₁ :| ks') v') - return (RecordLit (Dhall.Map.insert k₀ (Syntax.makeRecordField e₂) kvs))- _ ->- return (With e' ks v')- Note _ e' -> loop e'- ImportAlt l _r -> loop l- Embed a -> pure (Embed a)+ return (RecordLit (Dhall.Map.insert k₀ (Syntax.makeRecordField e₂) kvs))+ WithQuestion :| _ -> do+ return (With r' ks v')+ Some t ->+ case ks of+ WithQuestion :| [] -> do+ return (Some v')+ WithQuestion :| k : ks' -> do+ w <- loop (With t (k :| ks') v)+ return (Some w)+ WithLabel _ :| _ ->+ return (With r' ks v')+ App None _T ->+ case ks of+ WithQuestion :| _ ->+ return (App None _T)+ WithLabel _ :| _ ->+ return (With r' ks v')+ _ ->+ return (With r' ks v')+ Note _ e' -> loop e'+ ImportAlt l _r -> loop l+ Embed a -> pure (Embed a) -- | Use this to wrap you embedded functions (see `normalizeWith`) to make them -- polymorphic enough to be used.@@ -732,17 +795,20 @@ loop e = case e of Const _ -> True Var _ -> True- Lam (FunctionBinding Nothing _ Nothing Nothing a) b -> loop a && loop b- Lam _ _ -> False- Pi _ a b -> loop a && loop b+ Lam _ (FunctionBinding Nothing _ Nothing Nothing a) b -> loop a && loop b+ Lam _ _ _ -> False+ Pi _ _ a b -> loop a && loop b App f a -> loop f && loop a && case App f a of- App (Lam _ _) _ -> False+ App (Lam _ _ _) _ -> False App (App (App (App NaturalFold (NaturalLit _)) _) _) _ -> False App NaturalBuild _ -> False App NaturalIsZero (NaturalLit _) -> False App NaturalEven (NaturalLit _) -> False App NaturalOdd (NaturalLit _) -> False App NaturalShow (NaturalLit _) -> False+ App DateShow (DateLiteral _) -> False+ App TimeShow (TimeLiteral _ _) -> False+ App TimeZoneShow (TimeZoneLiteral _) -> False App (App NaturalSubtract (NaturalLit _)) (NaturalLit _) -> False App (App NaturalSubtract (NaturalLit 0)) _ -> False App (App NaturalSubtract _) (NaturalLit 0) -> False@@ -797,6 +863,8 @@ decide (BoolLit _) _ _ = False decide _ (BoolLit True) (BoolLit False) = False decide _ l r = not (Eval.judgmentallyEqual l r)+ Bytes -> True+ BytesLit _ -> True Natural -> True NaturalLit _ -> True NaturalFold -> True@@ -840,6 +908,15 @@ TextAppend _ _ -> False TextReplace -> True TextShow -> True+ Date -> True+ DateLiteral _ -> True+ DateShow -> True+ Time -> True+ TimeLiteral _ _ -> True+ TimeShow -> True+ TimeZone -> True+ TimeZoneLiteral _ -> True+ TimeZoneShow -> True List -> True ListLit t es -> all loop t && all loop es ListAppend x y -> loop x && loop y && decide x y@@ -867,19 +944,19 @@ decide (RecordField Nothing exp' Nothing Nothing) = loop exp' decide _ = False Union kts -> Dhall.Map.isSorted kts && all (all loop) kts- Combine _ x y -> loop x && loop y && decide x y+ Combine _ _ x y -> loop x && loop y && decide x y where decide (RecordLit m) _ | Data.Foldable.null m = False decide _ (RecordLit n) | Data.Foldable.null n = False decide (RecordLit _) (RecordLit _) = False decide _ _ = True- CombineTypes x y -> loop x && loop y && decide x y+ CombineTypes _ x y -> loop x && loop y && decide x y where decide (Record m) _ | Data.Foldable.null m = False decide _ (Record n) | Data.Foldable.null n = False decide (Record _) (Record _) = False decide _ _ = True- Prefer _ x y -> loop x && loop y && decide x y+ Prefer _ _ x y -> loop x && loop y && decide x y where decide (RecordLit m) _ | Data.Foldable.null m = False decide _ (RecordLit n) | Data.Foldable.null n = False@@ -897,13 +974,25 @@ ToMap x t -> case x of RecordLit _ -> False _ -> loop x && all loop t+ ShowConstructor x -> loop x && case x of+ Field (Union kts) (Syntax.fieldSelectionLabel -> k) ->+ case Dhall.Map.lookup k kts of+ Just Nothing -> False+ _ -> True+ App (Field (Union kts) (Syntax.fieldSelectionLabel -> k)) _ ->+ case Dhall.Map.lookup k kts of+ Just (Just _) -> False+ _ -> True+ Some _ -> False+ App None _ -> False+ _ -> True Field r (FieldSelection Nothing k Nothing) -> case r of RecordLit _ -> False Project _ _ -> False- Prefer _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r- Prefer _ _ (RecordLit _) -> False- Combine _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r- Combine _ _ (RecordLit m) -> Dhall.Map.keys m == [k] && loop r+ Prefer _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+ Prefer _ _ _ (RecordLit _) -> False+ Combine _ _ (RecordLit m) _ -> Dhall.Map.keys m == [k] && loop r+ Combine _ _ _ (RecordLit m) -> Dhall.Map.keys m == [k] && loop r _ -> loop r Field _ _ -> False Project r p -> loop r &&@@ -911,13 +1000,13 @@ Left s -> case r of RecordLit _ -> False Project _ _ -> False- Prefer _ _ (RecordLit _) -> False- _ -> not (Dhall.Set.null s) && Dhall.Set.isSorted s+ Prefer _ _ _ (RecordLit _) -> False+ _ -> not (null s) && Data.Set.toList (Data.Set.fromList s) == s Right e' -> case e' of Record _ -> False _ -> loop e' Assert t -> loop t- Equivalent l r -> loop l && loop r+ Equivalent _ l r -> loop l && loop r With{} -> False Note _ e' -> loop e' ImportAlt _ _ -> False@@ -929,7 +1018,7 @@ True >>> "x" `freeIn` "y" False->>> "x" `freeIn` Lam (Syntax.makeFunctionBinding "x" (Const Type)) "x"+>>> "x" `freeIn` Lam mempty (Syntax.makeFunctionBinding "x" (Const Type)) "x" False -} freeIn :: Eq a => Var -> Expr s a -> Bool@@ -941,6 +1030,7 @@ denote' = Syntax.denote strippedExpression = denote' expression+{-# INLINABLE freeIn #-} {- $setup >>> import Dhall.Syntax (Const(..))
@@ -3,51 +3,83 @@ for convenience -} -module Dhall.Optics- ( -- * Utilities- rewriteOf+{-# LANGUAGE RankNTypes #-}++module Dhall.Optics {-# DEPRECATED "Use the definitions from Lens.Micro of the microlens package directly." #-}+ ( Optic+ , Optic'+ -- * Utilities+ , anyOf+ , rewriteOf , transformOf , rewriteMOf , transformMOf , mapMOf+ , cosmosOf+ , to+ , foldOf ) where -import Control.Applicative (WrappedMonad (..))-import Data.Profunctor.Unsafe (( #. ))-import Lens.Family (ASetter, LensLike, over)+import Control.Applicative (Const (..), WrappedMonad (..))+import Data.Monoid (Any (..))+import Lens.Micro (ASetter, LensLike, Traversal, SimpleGetter)+import Lens.Micro.Internal ((#.)) +import qualified Lens.Micro++-- | Identical to @"Control.Lens.Getter".`Control.Lens.Getter.Getting`@+type Getting r s a = (a -> Const r a) -> s -> Const r s++-- | Identical to @"Control.Lens.Type".`Control.Lens.Type.Optic`@+type Optic p f s t a b = p a (f b) -> p s (f t)++-- | Identical to @"Control.Lens.Type".`Control.Lens.Type.Optic'`@+type Optic' p f s a = Optic p f s s a a++-- | Identical to @"Control.Lens".`Control.Lens.anyOf`@+anyOf :: Getting Any s a -> (a -> Bool) -> s -> Bool+anyOf = Lens.Micro.anyOf+{-# INLINE anyOf #-}+ -- | Identical to @"Control.Lens".`Control.Lens.rewriteOf`@ rewriteOf :: ASetter a b a b -> (b -> Maybe a) -> a -> b-rewriteOf l f = go- where- go = transformOf l (\x -> maybe x go (f x))+rewriteOf = Lens.Micro.rewriteOf {-# INLINE rewriteOf #-} -- | Identical to @"Control.Lens".`Control.Lens.transformOf`@ transformOf :: ASetter a b a b -> (b -> b) -> a -> b-transformOf l f = go- where- go = f . over l go+transformOf = Lens.Micro.transformOf {-# INLINE transformOf #-} -- | Identical to @"Control.Lens".`Control.Lens.rewriteMOf`@ rewriteMOf :: Monad m => LensLike (WrappedMonad m) a b a b -> (b -> m (Maybe a)) -> a -> m b-rewriteMOf l f = go- where- go = transformMOf l (\x -> f x >>= maybe (return x) go)+rewriteMOf = Lens.Micro.rewriteMOf {-# INLINE rewriteMOf #-} -- | Identical to @"Control.Lens".`Control.Lens.transformMOf`@ transformMOf :: Monad m => LensLike (WrappedMonad m) a b a b -> (b -> m b) -> a -> m b-transformMOf l f = go- where- go t = mapMOf l go t >>= f+transformMOf = Lens.Micro.transformMOf {-# INLINE transformMOf #-} -- | Identical to @"Control.Lens".`Control.Lens.mapMOf`@ mapMOf :: LensLike (WrappedMonad m) s t a b -> (a -> m b) -> s -> m t-mapMOf l cmd = unwrapMonad #. l (WrapMonad #. cmd)+mapMOf = Lens.Micro.mapMOf {-# INLINE mapMOf #-}++-- | Identical to @"Control.Lens.Plated".`Control.Lens.Plated.cosmosOf`@+cosmosOf :: Traversal s t s t -> Traversal s t s b+cosmosOf = Lens.Micro.cosmosOf+{-# INLINE cosmosOf #-}++-- | Identical to @"Control.Lens.Getter".`Control.Lens.Getter.to`@+to :: (s -> a) -> SimpleGetter s a+to = Lens.Micro.to+{-# INLINE to #-}++-- | Identical to @"Control.Lens.Fold".`Control.Lens.Fold.foldOf`@+foldOf :: Getting a s a -> s -> a+foldOf l = getConst #. l Const+{-# INLINE foldOf #-}
@@ -0,0 +1,297 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}++-- | Create a package.dhall from files and directory contents.++module Dhall.Package+ ( Options+ , defaultOptions+ , characterSet+ , packageFileName+ , packagingMode+ , PackagingMode(..)+ , writePackage+ , getPackagePathAndContent+ , PackageError(..)+ ) where++import Control.Exception (Exception, throwIO)+import Control.Monad+import Data.List.NonEmpty (NonEmpty (..))+import Data.Text (Text)+import qualified Data.Text as Text+import Data.Traversable (for)+import Dhall.Core+ ( Directory (..)+ , Expr (..)+ , File (..)+ , FilePrefix (..)+ , Import (..)+ , ImportHashed (..)+ , ImportMode (..)+ , ImportType (..)+ , RecordField (..)+ , makeRecordField+ )+import Dhall.Map (Map)+import qualified Dhall.Map as Map+import Dhall.Pretty (CharacterSet (..))+import qualified Dhall.Pretty+import Dhall.Util (_ERROR, renderExpression)+import Lens.Micro (Lens', lens)+import System.Directory+import System.FilePath++-- | Options for package creation.+data Options = Options+ { optionsCharacterSet :: CharacterSet+ , optionsPackageFileName :: String+ , optionsPackagingMode :: PackagingMode+ }++-- | The default options used for packaging.+--+-- The default values for the different settings are:+--+-- * The character set used is the one given by 'Dhall.Pretty.defaultCharacterSet'.+-- * The package file name is @package.dhall@.+-- * The packaging mode is 'OnlyThisPackage'.+defaultOptions :: Options+defaultOptions = Options+ { optionsCharacterSet = Dhall.Pretty.defaultCharacterSet+ , optionsPackageFileName = "package.dhall"+ , optionsPackagingMode = OnlyThisPackage+ }++-- | Access the character set used to render the package content.+characterSet :: Lens' Options CharacterSet+characterSet = lens optionsCharacterSet (\s x -> s { optionsCharacterSet = x })++-- | Access the file name used for the package file.+packageFileName :: Lens' Options String+packageFileName =+ lens optionsPackageFileName (\s x -> s { optionsPackageFileName = x })++-- | Access the packaging mode.+-- See the documentation of 'getPackagePathAndContent'.+packagingMode :: Lens' Options PackagingMode+packagingMode =+ lens optionsPackagingMode (\s x -> s { optionsPackagingMode = x })++-- | Whether to recursively create a package for each subdirectory or not.+-- See the documentation of 'getPackagePathAndContent'.+data PackagingMode+ = OnlyThisPackage+ | RecursiveSubpackages++-- | Create a package.dhall from files and directory contents.+-- For a description of how the package file is constructed see+-- 'getPackagePathAndContent'.+writePackage :: Options -> NonEmpty FilePath -> IO ()+writePackage options inputs = do+ (outputPath, expr) <- getPackagePathAndContent options inputs+ renderExpression (optionsCharacterSet options) True (Just outputPath) expr++-- | Get the path and the Dhall expression for a package file.+--+-- The location of the resulting package file is determined by the first path of the second argument:+--+-- * If it is a directory, it is also the output directory and the package+-- file will be placed there.+--+-- * If it is a file, then the directory that file resides in is the output+-- directory and the package file will be placed there.+--+-- All inputs provided as the second argument must be either in the output+-- directory or below it. They are processed depending on whether+-- the path points to a directory or a file:+--+-- * If the path points to a directory, all files with a @.dhall@ extensions+-- in that directory are included in the package.+--+-- If you passed `Recurse` to the this function, then in addition to these+-- files all subdirectories are traversed and a sub-package created for each+-- one. That sub-package will be included in the package too.+--+-- * If the path points to a regular file, it is included in the package+-- unless it is the path of the package file itself.+--+getPackagePathAndContent+ :: Options+ -> NonEmpty FilePath+ -> IO (FilePath, Expr s Import)+getPackagePathAndContent options (path :| paths) = do+ outputDir <- do+ isDirectory <- doesDirectoryExist path+ return $ if isDirectory then path else takeDirectory path+ outputDir' <- addTrailingPathSeparator <$> makeAbsolute (normalise outputDir)++ -- Check if the supplied @dir@ argument points to a filesystem entry below+ -- the output directory and return the path relative to the output directory.+ let checkOutputDir dir = do+ absoluteDir <- addTrailingPathSeparator <$> makeAbsolute (normalise dir)+ let relativeDir = makeRelative outputDir' absoluteDir+ unless (isRelative relativeDir) $+ throwIO $ AmbiguousOutputDirectory outputDir dir+ return relativeDir++ resultMap <- go Map.empty checkOutputDir (path:paths)+ return (outputDir </> outputFn, RecordLit $ Map.sort resultMap)+ where+ go+ :: Map Text (RecordField s Import)+ -> (FilePath -> IO FilePath)+ -> [FilePath]+ -> IO (Map Text (RecordField s Import))+ go !acc _checkOutputDir [] = return acc+ go !acc checkOutputDir (p:ps) = do+ isDirectory <- doesDirectoryExist p+ isFile <- doesFileExist p+ if | isDirectory -> do+ void $ checkOutputDir p+ entries <- listDirectory p+ (dhallFiles, subdirectories) <- foldMap+ ( \entry -> do+ let entry' = p </> entry+ isDirectoryEntry <- doesDirectoryExist entry'+ return $ if isDirectoryEntry+ then (mempty, [entry'])+ else if hasDhallExtension entry+ then ([entry'], mempty)+ else mempty+ ) entries+ subpackages <- case optionsPackagingMode options of+ RecursiveSubpackages ->+ for subdirectories $ \subdirectory -> do+ writePackage options (subdirectory :| [])+ return (subdirectory </> outputFn)+ OnlyThisPackage -> return []+ go acc checkOutputDir (dhallFiles <> subpackages <> ps)+ | isFile -> do+ dir <- checkOutputDir $ takeDirectory p++ let p' = normalise $ dir </> takeFileName p++ let resultMap = if p' == outputFn+ then Map.empty+ else filepathToMap outputFn p'++ acc' <- mergeMaps acc resultMap+ go acc' checkOutputDir ps+ | otherwise -> throwIO $ InvalidPath p++ hasDhallExtension :: FilePath -> Bool+ hasDhallExtension entry = takeExtension entry == ".dhall"++ outputFn :: String+ outputFn = optionsPackageFileName options++-- | Construct a nested 'Map' from a 'FilePath'.+-- For example, the filepath @some/file/path.dhall@ will result in something+-- similar to the following:+--+-- fromList+-- [ ("some", fromList+-- [ ("file", fromList+-- [ ("path", ./some/file/path.dhall)+-- ])+-- ])+-- ])+--+-- ... where ./some/file/path.dhall is a Dhall import. If the last component+-- equals the value passed in the @outputFn@ argument we produce a slightly+-- different result. Consider for example the Dhall Prelude: We have some+-- sub-packages there like @List/package.dhall@. If we want to construct the+-- top-level @package.dhall@ we want an entry like+--+-- > List = ./List/package.dhall+--+-- in there and not:+--+-- > List = { package = ./List/package.dhall }+--+filepathToMap :: FilePath -> FilePath -> Map Text (RecordField s Import)+filepathToMap outputFn = go [] . splitDirectories+ where+ go acc [] = go acc ["."]+ go !acc [x] =+ let import_ = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here File+ { directory = Directory acc+ , file = Text.pack x+ }+ }+ , importMode = Code+ }+ in Map.singleton (Text.pack $ dropExtension x) $ makeRecordField $ Embed import_+ go !acc [x, y] | y == outputFn =+ let import_ = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here File+ { directory = Directory (Text.pack x : acc)+ , file = Text.pack y+ }+ }+ , importMode = Code+ }+ in Map.singleton (Text.pack x) $ makeRecordField $ Embed import_+ go !acc (x:xs) = Map.singleton (Text.pack x) $ makeRecordField $ RecordLit $ go (Text.pack x : acc) xs++-- | Merge two 'Map's constructed with 'filepathToMap'.+-- It will throw an error if the arguments are not compatible with each other, e.g.+-- we cannot merge the following two maps:+--+-- > fromList [ ("file", ./file.dhall) ]+-- > fromList [ ("file", fromList [("nested", ./file/nested.dhall)]) ]+--+mergeMaps :: Map Text (RecordField s Import) -> Map Text (RecordField s Import) -> IO (Map Text (RecordField s Import))+mergeMaps x y = do+ let x' = fmap (:| []) x+ y' = fmap (:| []) y+ z = Map.unionWith (<>) x' y'+ for z $ \case+ v@RecordField{recordFieldValue = Embed{}} :| [] -> return v+ vs | Just rs <- traverse extractRecordLit vs -> makeRecordField . RecordLit . Map.sort <$> foldM mergeMaps Map.empty rs+ | otherwise -> throwIO $ IncompatiblePaths $ foldMap extractEmbeds vs+ where+ extractEmbeds :: RecordField s Import -> [Import]+ extractEmbeds RecordField{recordFieldValue = Embed import_} = [import_]+ extractEmbeds RecordField{recordFieldValue = RecordLit xs} = foldMap extractEmbeds xs+ extractEmbeds _ = mempty++ extractRecordLit :: RecordField s Import -> Maybe (Map Text (RecordField s Import))+ extractRecordLit RecordField{recordFieldValue = RecordLit xs} = Just xs+ extractRecordLit _ = Nothing++-- | Exception thrown when creating a package file.+data PackageError+ = AmbiguousOutputDirectory FilePath FilePath+ | IncompatiblePaths [Import]+ | InvalidPath FilePath++instance Exception PackageError++instance Show PackageError where+ show (AmbiguousOutputDirectory dir1 dir2) =+ _ERROR <> ": ❰dhall package❱ failed because the inputs make it impossible to\n\+ \determine the output directory of the package file. You asked to include files\n\+ \from the following directories in the package:\n\+ \\n" <> dir1 <>+ "\n" <> dir2 <>+ "\n\n\+ \Although those paths might point to the same location they are not lexically the\n\+ \same."++ show (IncompatiblePaths imports) =+ _ERROR <> ": ❰dhall package❱ failed because some inputs are not compatible with\n\+ \each other:\n\+ \\n" <> unlines (map (show . Dhall.Pretty.prettyExpr . Embed) imports)++ show (InvalidPath fp) =+ _ERROR <> ": ❰dhall package❱ failed because the input does not exist or is\n\+ \neither a directory nor a regular file:\n\+ \\n" <> fp
@@ -1,5 +1,5 @@-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} -- | This module contains Dhall's parsing logic @@ -21,12 +21,13 @@ , Parser(..) ) where -import Control.Exception (Exception)-import Data.Text (Text)-import Data.Void (Void)-import Dhall.Src (Src (..))+import Control.Applicative (many)+import Control.Exception (Exception)+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Src (Src (..)) import Dhall.Syntax-import Text.Megaparsec (ParseErrorBundle (..), PosState (..))+import Text.Megaparsec (ParseErrorBundle (..), PosState (..)) import qualified Data.Text as Text import qualified Dhall.Core as Core@@ -123,7 +124,7 @@ Right (txt, r) -> Right (createHeader txt, r) where parser = do- (bytes, _) <- Text.Megaparsec.match whitespace+ (bytes, _) <- Text.Megaparsec.match (many shebang *> whitespace) r <- expr Text.Megaparsec.eof return (bytes, r)
@@ -17,33 +17,30 @@ , satisfy , Dhall.Parser.Combinators.takeWhile , takeWhile1- , noDuplicates , toMap , toMapWith+ , base ) where -import Control.Applicative (Alternative (..), liftA2)-import Control.Exception (Exception)-import Control.Monad (MonadPlus (..))-import Data.String (IsString (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty (..))-import Data.Void (Void)-import Dhall.Map (Map)-import Dhall.Set (Set)-import Dhall.Src (Src (..))-import Text.Parser.Combinators (try, (<?>))-import Text.Parser.Token (TokenParsing (..))+import Control.Applicative (Alternative (..), liftA2)+import Control.Exception (Exception)+import Control.Monad (MonadPlus (..))+import Data.String (IsString (..))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Map (Map)+import Dhall.Src (Src (..))+import Prettyprinter (Pretty (..))+import Text.Parser.Combinators (try, (<?>))+import Text.Parser.Token (TokenParsing (..)) import qualified Control.Monad.Fail-import qualified Data.Char-import qualified Data.Set+import qualified Data.Char as Char import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty import qualified Dhall.Map import qualified Dhall.Pretty-import qualified Dhall.Set+import qualified Prettyprinter.Render.String as Pretty import qualified Text.Megaparsec import qualified Text.Megaparsec.Char import qualified Text.Parser.Char@@ -139,14 +136,8 @@ -- {-# INLINE mplus #-} instance Text.Megaparsec.MonadParsec Void Text Parser where-#if MIN_VERSION_megaparsec(8, 0, 0) parseError e = Parser (Text.Megaparsec.parseError e)-#else- failure u e = Parser (Text.Megaparsec.failure u e) - fancyFailure e = Parser (Text.Megaparsec.fancyFailure e)-#endif- label l (Parser p) = Parser (Text.Megaparsec.label l p) hidden (Parser p) = Parser (Text.Megaparsec.hidden p)@@ -178,6 +169,10 @@ updateParserState f = Parser (Text.Megaparsec.updateParserState f) +#if MIN_VERSION_megaparsec(9,4,0)+ mkParsec f = Parser (Text.Megaparsec.mkParsec f)+#endif+ instance Semigroup a => Semigroup (Parser a) where (<>) = liftA2 (<>) @@ -218,7 +213,7 @@ instance TokenParsing Parser where someSpace = Text.Parser.Token.Style.buildSomeSpaceParser- (Parser (Text.Megaparsec.skipSome (Text.Megaparsec.satisfy Data.Char.isSpace)))+ (Parser (Text.Megaparsec.skipSome (Text.Megaparsec.satisfy Char.isSpace))) Text.Parser.Token.Style.haskellCommentStyle highlight _ = id@@ -264,16 +259,6 @@ takeWhile1 :: (Char -> Bool) -> Parser Text takeWhile1 predicate = Parser (Text.Megaparsec.takeWhile1P Nothing predicate) --- | Construct a 'Set a' from a '[a]', failing if there was a duplicate element-noDuplicates :: Ord a => [a] -> Parser (Set a)-noDuplicates = go Dhall.Set.empty- where- go found [] = return found- go found (x:xs) =- if Data.Set.member x (Dhall.Set.toSet found)- then fail "Duplicate key"- else go (Dhall.Set.append x found) xs- -- | Creates a map with the given key-value pairs, failing if there was a -- duplicate key. toMap :: [(Text, a)] -> Parser (Map Text a)@@ -293,3 +278,15 @@ toMapWith combine kvs = sequence m where m = Dhall.Map.fromListWithKey combine (map (\(k, v) -> (k, pure v)) kvs)++-- | Convert a list of digits to the equivalent number+base :: Num n => [Char] -> n -> n+digits `base` b = foldl snoc 0 (map (fromIntegral . digitToNumber) digits)+ where+ snoc result number = result * b + number++ digitToNumber c+ | '0' <= c && c <= '9' = 0x0 + Char.ord c - Char.ord '0'+ | 'A' <= c && c <= 'F' = 0xA + Char.ord c - Char.ord 'A'+ | 'a' <= c && c <= 'f' = 0xa + Char.ord c - Char.ord 'a'+ | otherwise = error "Invalid hexadecimal digit"
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-}@@ -8,9 +9,7 @@ module Dhall.Parser.Expression where import Control.Applicative (Alternative (..), liftA2, optional)-import Data.ByteArray.Encoding (Base (..)) import Data.Foldable (foldl')-import Data.Functor (void) import Data.List.NonEmpty (NonEmpty (..)) import Data.Text (Text) import Dhall.Src (Src (..))@@ -20,14 +19,15 @@ import qualified Control.Monad import qualified Control.Monad.Combinators as Combinators import qualified Control.Monad.Combinators.NonEmpty as Combinators.NonEmpty-import qualified Data.ByteArray.Encoding-import qualified Data.ByteString+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Base16 as Base16 import qualified Data.Char as Char import qualified Data.List import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Sequence import qualified Data.Text import qualified Data.Text.Encoding+import qualified Data.Time as Time import qualified Dhall.Crypto import qualified Text.Megaparsec @@ -107,14 +107,186 @@ data Parsers a = Parsers { completeExpression_ :: Parser (Expr Src a) , importExpression_ :: Parser (Expr Src a)+ , letBinding :: Parser (Binding Src a) } --- | Given a parser for imports, +{-| Parse a numeric `TimeZone`++ This corresponds to the @time-numoffset@ rule from the official grammar+-}+timeNumOffset :: Parser (Expr s a)+timeNumOffset = do+ s <- signPrefix++ hour <- timeHour++ _ <- text ":"++ minute <- timeMinute++ let minutes = s (hour * 60 + minute)++ return (TimeZoneLiteral (Time.TimeZone minutes Prelude.False ""))++{-| Parse a numeric `TimeZone` or a @Z@++ This corresponds to the @time-offset@ rule from the official grammar+-}+timeOffset :: Parser (Expr s a)+timeOffset =+ (do _ <- text "Z"++ return (TimeZoneLiteral (Time.TimeZone 0 Prelude.False ""))+ )+ <|> timeNumOffset++{-| Parse a `Time`++ This corresponds to the @partial-time@ rule from the official grammar+-}+partialTime :: Parser (Expr s a)+partialTime = do+ hour <- timeHour++ _ <- text ":"++ minute <- timeMinute++ _ <- text ":"++ second <- timeSecond++ (fraction, precision) <- timeSecFrac <|> pure (0, 0)++ let time = Time.TimeOfDay hour minute (second + fraction)++ return (TimeLiteral time precision)++{-| Parse a `Date`++ This corresponds to the @full-date@ rule from the official grammar+-}+fullDate :: Parser (Expr s a)+fullDate = do+ year <- dateFullYear++ _ <- text "-"++ month <- dateMonth++ _ <- text "-"++ day <- dateMday++ case Time.fromGregorianValid year month day of+ Nothing -> fail "Invalid calendar day"+ Just d -> return (DateLiteral d)++{-| Parse a `Date`, `Time`, `TimeZone` or any valid permutation of them as a+ record++ This corresponds to the @temporal-literal@ rule from the official grammar+-}+temporalLiteral :: Parser (Expr s a)+temporalLiteral =+ try (do+ date <- fullDate++ _ <- text "T" <|> text "t"++ time <- partialTime++ timeZone <- timeOffset++ return+ (RecordLit+ [ ("date" , makeRecordField date)+ , ("time" , makeRecordField time)+ , ("timeZone", makeRecordField timeZone)+ ]+ )+ )+ <|> try (do+ date <- fullDate++ _ <- text "T" <|> text "t"++ time <- partialTime++ return+ (RecordLit+ [ ("date", makeRecordField date)+ , ("time", makeRecordField time)+ ]+ )+ )+ <|> try (do+ time <- partialTime++ timeZone <- timeOffset++ return+ (RecordLit+ [ ("time" , makeRecordField time)+ , ("timeZone", makeRecordField timeZone)+ ]+ )+ )+ <|> try fullDate+ <|> try partialTime+ <|> try timeNumOffset++-- | Parse a \"shebang\" line (i.e. an initial line beginning with @#!@)+shebang :: Parser ()+shebang = do+ _ <- text "#!"++ let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t'++ _ <- Dhall.Parser.Combinators.takeWhile predicate++ _ <- endOfLine++ return ()++-- | Given a parser for imports, parsers :: forall a. Parser a -> Parsers a-parsers embedded = Parsers {..}+parsers embedded = Parsers{..} where- completeExpression_ = whitespace *> expression <* whitespace+ completeExpression_ =+ whitespace+ *> expression+ <* whitespace+ <* optional lineCommentPrefix + letBinding = do+ src0 <- try (_let *> src nonemptyWhitespace)++ c <- label++ src1 <- src whitespace++ d <- optional (do+ _colon++ src2 <- src nonemptyWhitespace++ e <- expression++ whitespace++ return (Just src2, e) )++ _equal++ src3 <- src whitespace++ f <- expression++ whitespace++ return (Binding (Just src0) c (Just src1) d (Just src3) f)+ expression = noted ( choice@@ -128,7 +300,7 @@ ) <?> "expression" where alternative0 = do- _lambda+ cs <- _lambda whitespace _openParens src0 <- src whitespace@@ -140,10 +312,10 @@ whitespace _closeParens whitespace- _arrow+ cs' <- _arrow whitespace c <- expression- return (Lam (FunctionBinding (Just src0) a (Just src1) (Just src2) b) c)+ return (Lam (Just (cs <> cs')) (FunctionBinding (Just src0) a (Just src1) (Just src2) b) c) alternative1 = do try (_if *> nonemptyWhitespace)@@ -157,35 +329,7 @@ return (BoolIf a b c) alternative2 = do- let binding = do- src0 <- try (_let *> src nonemptyWhitespace)-- c <- label-- src1 <- src whitespace-- d <- optional (do- _colon-- src2 <- src nonemptyWhitespace-- e <- expression-- whitespace-- return (Just src2, e) )-- _equal-- src3 <- src whitespace-- f <- expression-- whitespace-- return (Binding (Just src0) c (Just src1) d (Just src3) f)-- as <- NonEmpty.some1 binding+ as <- NonEmpty.some1 letBinding try (_in *> nonemptyWhitespace) @@ -211,7 +355,7 @@ return (Dhall.Syntax.wrapInLets as b) alternative3 = do- try (_forall *> whitespace *> _openParens)+ cs <- try (_forall <* whitespace <* _openParens) whitespace a <- label whitespace@@ -221,10 +365,10 @@ whitespace _closeParens whitespace- _arrow+ cs' <- _arrow whitespace c <- expression- return (Pi a b c)+ return (Pi (Just (cs <> cs')) a b c) alternative4 = do try (_assert *> whitespace *> _colon)@@ -244,10 +388,14 @@ _ -> empty bs <- some (do- try (whitespace *> _with *> nonemptyWhitespace)+ try (nonemptyWhitespace *> _with *> nonemptyWhitespace) - keys <- Combinators.NonEmpty.sepBy1 anyLabel (try (whitespace *> _dot) *> whitespace)+ let withComponent =+ fmap WithLabel anyLabelOrSome+ <|> fmap (\_ -> WithQuestion) (text "?") + keys <- Combinators.NonEmpty.sepBy1 withComponent (try (whitespace *> _dot) *> whitespace)+ whitespace _equal@@ -266,26 +414,26 @@ whitespace let alternative5B0 = do- _arrow+ cs <- _arrow whitespace b <- expression whitespace- return (Pi "_" a b)+ return (Pi (Just cs) "_" a b) let alternative5B1 = do _colon nonemptyWhitespace case (shallowDenote a, a0Info) of (ListLit Nothing [], _) -> do- b <- applicationExpression+ b <- expression return (ListLit (Just b) []) (Merge c d Nothing, NakedMergeOrSomeOrToMap) -> do- b <- applicationExpression+ b <- expression return (Merge c d (Just b)) (ToMap c Nothing, NakedMergeOrSomeOrToMap) -> do- b <- applicationExpression+ b <- expression return (ToMap c (Just b)) _ -> do@@ -341,20 +489,20 @@ operatorParsers :: [Parser (Expr s a -> Expr s a -> Expr s a)] operatorParsers =- [ Equivalent <$ _equivalent <* whitespace- , ImportAlt <$ _importAlt <* nonemptyWhitespace- , BoolOr <$ _or <* whitespace- , NaturalPlus <$ _plus <* nonemptyWhitespace- , TextAppend <$ _textAppend <* whitespace- , ListAppend <$ _listAppend <* whitespace- , BoolAnd <$ _and <* whitespace- , Combine Nothing <$ _combine <* whitespace- , Prefer PreferFromSource <$ _prefer <* whitespace- , CombineTypes <$ _combineTypes <* whitespace- , NaturalTimes <$ _times <* whitespace+ [ Equivalent . Just <$> _equivalent <* whitespace+ , ImportAlt <$ _importAlt <* nonemptyWhitespace+ , BoolOr <$ _or <* whitespace+ , NaturalPlus <$ _plus <* nonemptyWhitespace+ , TextAppend <$ _textAppend <* whitespace+ , ListAppend <$ _listAppend <* whitespace+ , BoolAnd <$ _and <* whitespace+ , (\cs -> Combine (Just cs) Nothing) <$> _combine <* whitespace+ , (\cs -> Prefer (Just cs) PreferFromSource) <$> _prefer <* whitespace+ , CombineTypes . Just <$> _combineTypes <* whitespace+ , NaturalTimes <$ _times <* whitespace -- Make sure that `==` is not actually the prefix of `===`- , BoolEQ <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace- , BoolNE <$ _notEqual <* whitespace+ , BoolEQ <$ try (_doubleEqual <* Text.Megaparsec.notFollowedBy (char '=')) <* whitespace+ , BoolNE <$ _notEqual <* whitespace ] applicationExpression = snd <$> applicationExpressionWithInfo@@ -378,10 +526,15 @@ return (\a -> ToMap a Nothing, Just "argument to ❰toMap❱") - let alternative3 =+ let alternative3 = do+ try (_showConstructor *> nonemptyWhitespace)++ return (\a -> ShowConstructor a, Just "argument to ❰showConstructor❱")++ let alternative4 = return (id, Nothing) - (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3+ (f, maybeMessage) <- alternative0 <|> alternative1 <|> alternative2 <|> alternative3 <|> alternative4 let adapt parser = case maybeMessage of@@ -437,35 +590,44 @@ selectorExpression = noted (do a <- primitiveExpression - let recordType = whitespace *> _openParens *> whitespace *> expression <* whitespace <* _closeParens+ let recordType = _openParens *> whitespace *> expression <* whitespace <* _closeParens let field x e = Field e x let projectBySet xs e = Project e (Left xs) let projectByExpression xs e = Project e (Right xs) - let fieldSelection = do+ let alternatives = do src0 <- src whitespace- l <- anyLabel- pos <- Text.Megaparsec.getSourcePos - -- FIXME: Suffix whitespace can't be parsed given our limitation- -- about whitespace treatment, but for @dhall-docs@ this- -- is enough- let src1 = Src pos pos ""- return (FieldSelection (Just src0) l (Just src1))+ let fieldSelection = do+ l <- anyLabel - let alternatives =- fmap field fieldSelection- <|> fmap projectBySet (whitespace *> labels)- <|> fmap projectByExpression recordType+ pos <- Text.Megaparsec.getSourcePos + -- FIXME: Suffix whitespace can't be parsed given our limitation+ -- about whitespace treatment, but for @dhall-docs@ this+ -- is enough+ let src1 = Src pos pos ""++ return (FieldSelection (Just src0) l (Just src1))++ let result =+ fmap field fieldSelection+ <|> fmap projectBySet labels+ <|> fmap projectByExpression recordType++ result+ b <- Text.Megaparsec.many (try (whitespace *> _dot *> alternatives))+ return (foldl' (\e k -> k e) a b) ) primitiveExpression = noted ( choice- [ alternative00+ [ bytesLiteral+ , temporalLiteral+ , alternative00 , alternative01 , alternative02 , textLiteral@@ -561,7 +723,9 @@ 'D' -> choice- [ DoubleShow <$ _DoubleShow+ [ DateShow <$ _DateShow+ , Date <$ _Date+ , DoubleShow <$ _DoubleShow , Double <$ _Double ] 'L' ->@@ -576,13 +740,21 @@ , List <$ _List ] 'O' -> Optional <$ _Optional- 'B' -> Bool <$ _Bool+ 'B' ->+ choice+ [ Bool <$ _Bool+ , Bytes <$ _Bytes+ ] 'S' -> Const Sort <$ _Sort 'T' -> choice [ TextReplace <$ _TextReplace , TextShow <$ _TextShow , Text <$ _Text+ , TimeZoneShow <$ _TimeZoneShow+ , TimeZone <$ _TimeZone+ , TimeShow <$ _TimeShow+ , Time <$ _Time , BoolLit True <$ _True , Const Type <$ _Type ]@@ -671,7 +843,7 @@ let fourCharacterEscapeSequence = do ns <- Control.Monad.replicateM 4 hexNumber- + let number = toNumber ns Control.Monad.guard (validCodepoint number)@@ -711,7 +883,7 @@ , unescapedCharacterFast , unescapedCharacterSlow , tab- , endOfLine+ , endOfLine_ ] where escapeSingleQuotes = do@@ -750,7 +922,7 @@ where predicate c = c == '$' || c == '\'' - endOfLine = do+ endOfLine_ = do a <- "\n" <|> "\r\n" b <- singleQuoteContinue return (Chunks [] a <> b)@@ -762,17 +934,31 @@ singleQuoteLiteral = do _ <- text "''"+ _ <- endOfLine+ a <- singleQuoteContinue return (Dhall.Syntax.toDoubleQuoted a)- where- endOfLine = (void (char '\n') <|> void (text "\r\n")) <?> "newline" textLiteral = (do- literal <- doubleQuotedLiteral <|> singleQuoteLiteral- return (TextLit literal) ) <?> "literal"+ literal <- doubleQuotedLiteral <|> singleQuoteLiteral+ return (TextLit literal) ) <?> "literal" + bytesLiteral = (do+ _ <- text "0x\""++ let byte = do+ nibble0 <- Text.Megaparsec.satisfy hexdig+ nibble1 <- Text.Megaparsec.satisfy hexdig+ return ([nibble0, nibble1] `base` 16)++ bytes <- Text.Megaparsec.many byte++ _ <- char '"'++ return (BytesLit (ByteString.pack bytes)) ) <?> "literal"+ recordTypeOrLiteral firstSrc0 = choice [ emptyRecordLiteral@@ -876,7 +1062,7 @@ whitespace - let combine k = liftA2 $ \rf rf' -> makeRecordField $ Combine (Just k)+ let combine k = liftA2 $ \rf rf' -> makeRecordField $ Combine mempty (Just k) (recordFieldValue rf') (recordFieldValue rf) @@ -916,8 +1102,6 @@ let emptyUnionType = do try (optional (_bar *> whitespace) *> _closeAngle) - _ <- optional (_bar *> whitespace)- return (Union mempty) nonEmptyUnionType <|> emptyUnionType ) <?> "literal"@@ -1050,9 +1234,9 @@ _ <- text "sha256:" t <- count 64 (satisfy hexdig <?> "hex digit") let strictBytes16 = Data.Text.Encoding.encodeUtf8 t- strictBytes <- case Data.ByteArray.Encoding.convertFromBase Base16 strictBytes16 of+ strictBytes <- case Base16.decode strictBytes16 of Left string -> fail string- Right strictBytes -> return (strictBytes :: Data.ByteString.ByteString)+ Right strictBytes -> return strictBytes case Dhall.Crypto.sha256DigestFromByteString strictBytes of Nothing -> fail "Invalid sha256 hash" Just h -> pure h@@ -1080,7 +1264,9 @@ alternative = do try (whitespace *> _as *> nonemptyWhitespace) - (_Text >> pure RawText) <|> (_Location >> pure Location)+ (_Text >> pure RawText)+ <|> (_Location >> pure Location)+ <|> (_Bytes >> pure RawBytes) -- | 'ApplicationExprInfo' distinguishes certain subtypes of application -- expressions.
@@ -4,9 +4,11 @@ -- | Parse Dhall tokens. Even though we don't have a tokenizer per-se this --- module is useful for keeping some small parsing utilities. module Dhall.Parser.Token (+ endOfLine, validCodepoint, whitespace, lineComment,+ lineCommentPrefix, blockComment, nonemptyWhitespace, bashEnvironmentVariable,@@ -23,10 +25,18 @@ hexdig, identifier, hexNumber,+ signPrefix, doubleLiteral, doubleInfinity, naturalLiteral, integerLiteral,+ dateFullYear,+ dateMonth,+ dateMday,+ timeHour,+ timeMinute,+ timeSecond,+ timeSecFrac, _Optional, _if, _then,@@ -37,6 +47,7 @@ _using, _merge, _toMap,+ _showConstructor, _assert, _Some, _None,@@ -61,12 +72,19 @@ _ListIndexed, _ListReverse, _Bool,+ _Bytes, _Natural, _Integer, _Double, _Text, _TextReplace, _TextShow,+ _Date,+ _DateShow,+ _Time,+ _TimeShow,+ _TimeZone,+ _TimeZoneShow, _List, _True, _False,@@ -114,13 +132,14 @@ import Control.Applicative (Alternative (..), optional) import Data.Bits ((.&.))+import Data.Fixed (Pico) import Data.Functor (void, ($>))+import Data.Ratio ((%)) import Data.Text (Text)-import Dhall.Set (Set) import Dhall.Syntax import Text.Parser.Combinators (choice, try, (<?>)) -import qualified Control.Monad+import qualified Control.Monad as Monad import qualified Data.Char as Char import qualified Data.Foldable import qualified Data.HashSet@@ -128,7 +147,6 @@ import qualified Data.List.NonEmpty import qualified Data.Scientific as Scientific import qualified Data.Text-import qualified Dhall.Set import qualified Text.Megaparsec import qualified Text.Megaparsec.Char.Lexer import qualified Text.Parser.Char@@ -137,12 +155,18 @@ import Numeric.Natural (Natural) +-- | Match an end-of-line character sequence+endOfLine :: Parser Text+endOfLine =+ ( Text.Parser.Char.text "\n" + <|> Text.Parser.Char.text "\r\n"+ ) <?> "newline" -- | Returns `True` if the given `Int` is a valid Unicode codepoint validCodepoint :: Int -> Bool validCodepoint c =- not (category == Char.Surrogate - || c .&. 0xFFFE == 0xFFFE + not (category == Char.Surrogate+ || c .&. 0xFFFE == 0xFFFE || c .&. 0xFFFF == 0xFFFF) where category = Char.generalCategory (Char.chr c)@@ -180,6 +204,7 @@ || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f') +-- | Parse a leading @+@ or @-@ sign signPrefix :: Num a => Parser (a -> a) signPrefix = (do let positive = fmap (\_ -> id ) (char '+')@@ -268,17 +293,20 @@ a <- naturalLiteral return (sign (fromIntegral a)) ) <?> "literal" -{-| Parse a `Dhall.Syntax.Natural` literal +{-| Parse a `Dhall.Syntax.Natural` literal This corresponds to the @natural-literal@ rule from the official grammar -} naturalLiteral :: Parser Natural naturalLiteral = (do- a <- try (char '0' >> char 'x' >> Text.Megaparsec.Char.Lexer.hexadecimal)+ a <- binary+ <|> hexadecimal <|> decimal <|> (char '0' $> 0) return a ) <?> "literal" where+ binary = try (char '0' >> char 'b' >> Text.Megaparsec.Char.Lexer.binary)+ hexadecimal = try (char '0' >> char 'x' >> Text.Megaparsec.Char.Lexer.hexadecimal) decimal = do n <- headDigit ns <- many tailDigit@@ -298,7 +326,100 @@ where step acc x = acc * 10 + x +{-| Parse a 4-digit year + This corresponds to the @date-fullyear@ rule from the official grammar+-}+dateFullYear :: Parser Integer+dateFullYear = do+ digits <- Monad.replicateM 4 (Text.Parser.Char.satisfy digit)++ return (digits `base` 10)++{-| Parse a 2-digit month++ This corresponds to the @date-month@ rule from the official grammar+-}+dateMonth :: Parser Int+dateMonth = do+ digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++ let month = digits `base` 10++ if 1 <= month && month <= 12+ then return month+ else fail "Invalid month"++{-| Parse a 2-digit day of the month++ This corresponds to the @date-mday@ rule from the official grammar+-}+dateMday :: Parser Int+dateMday = do+ digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++ let day = digits `base` 10++ if 1 <= day && day <= 31+ then return day+ else fail "Invalid day"++{-| Parse a 2-digit hour++ This corresponds to the @time-hour@ rule from the official grammar+-}+timeHour :: Parser Int+timeHour = do+ digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++ let hour = digits `base` 10++ if 0 <= hour && hour < 24+ then return hour+ else fail "Invalid hour"++{-| Parse a 2-digit minute++ This corresponds to the @time-minute@ rule from the official grammar+-}+timeMinute :: Parser Int+timeMinute = do+ digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++ let minute = digits `base` 10++ if 0 <= minute && minute < 60+ then return minute+ else fail "Invalid minute"++{-| Parse a 2-digit second++ This corresponds to the @time-second@ rule from the official grammar+-}+timeSecond :: Parser Pico+timeSecond = do+ digits <- Monad.replicateM 2 (Text.Parser.Char.satisfy digit)++ let second = digits `base` 10++ if 0 <= second && second < 60+ then return second+ else fail "Invalid second"++{-| Parse the fractional component of a second++ This corresponds to the @time-secfrac@ rule from the official grammar+-}+timeSecFrac :: Parser (Pico, Word)+timeSecFrac = do+ _ <- Text.Parser.Char.text "."++ digits <- some (Text.Parser.Char.satisfy digit)++ let precision = fromIntegral (length digits)++ return (fromRational ((digits `base` 10) % (10 ^ precision)), precision)+ {-| Parse an identifier (i.e. a variable or built-in) Variables can have an optional index to disambiguate shadowed variables@@ -352,25 +473,23 @@ where predicate c = 'a' <= c && c <= 'f' --- | Parse a Dhall's single-line comment, starting from `--` and until the--- last character of the line /before/ the end-of-line character-lineComment :: Parser Text-lineComment = do+-- | Same as `lineComment` except that this doesn't parse the end-of-line+-- character+lineCommentPrefix :: Parser Text+lineCommentPrefix = do _ <- text "--" let predicate c = ('\x20' <= c && c <= '\x10FFFF') || c == '\t' commentText <- Dhall.Parser.Combinators.takeWhile predicate - endOfLine- return ("--" <> commentText)- where- endOfLine =- ( void (Text.Parser.Char.char '\n' )- <|> void (Text.Parser.Char.text "\r\n")- ) <?> "newline" +-- | Parse a Dhall's single-line comment, starting from `--` and until the+-- last character of the line /before/ the end-of-line character+lineComment :: Parser Text+lineComment = try (lineCommentPrefix <* endOfLine)+ -- | Parsed text doesn't include opening braces blockComment :: Parser Text blockComment = do@@ -398,8 +517,6 @@ where predicate c = '\x20' <= c && c <= '\x10FFFF' || c == '\n' || c == '\t' - endOfLine = (Text.Parser.Char.text "\r\n" <?> "newline")- blockCommentContinue :: Parser Text blockCommentContinue = endOfComment <|> continue where@@ -417,7 +534,7 @@ let t = Data.Text.cons c rest let isNotAKeyword = not $ t `Data.HashSet.member` reservedKeywords let isNotAReservedIdentifier = not $ t `Data.HashSet.member` reservedIdentifiers- Control.Monad.guard (isNotAKeyword && (allowReserved || isNotAReservedIdentifier))+ Monad.guard (isNotAKeyword && (allowReserved || isNotAReservedIdentifier)) return t headCharacter :: Char -> Bool@@ -443,22 +560,18 @@ This corresponds to the @labels@ rule in the official grammar -}-labels :: Parser (Set Text)+labels :: Parser [Text] labels = do _openBrace whitespace - xs <- nonEmptyLabels <|> emptyLabels-- _ <- optional (_comma *> whitespace)-- return xs+ nonEmptyLabels <|> emptyLabels where emptyLabels = do try (optional (_comma *> whitespace) *> _closeBrace) - pure Dhall.Set.empty+ pure [] nonEmptyLabels = do x <- try (optional (_comma *> whitespace) *> anyLabelOrSome)@@ -471,7 +584,7 @@ _closeBrace - noDuplicates (x : xs)+ return (x : xs) {-| Parse a label (e.g. a variable\/field\/alternative name) @@ -847,6 +960,13 @@ _toMap :: Parser () _toMap = keyword "toMap" +{-| Parse the @showConstructor@ keyword++ This corresponds to the @showConstructor@ rule from the official grammar+-}+_showConstructor :: Parser ()+_showConstructor = keyword "showConstructor"+ {-| Parse the @assert@ keyword This corresponds to the @assert@ rule from the official grammar@@ -1019,6 +1139,13 @@ _Bool :: Parser () _Bool = builtin "Bool" +{-| Parse the @Bytes@ built-in++ This corresponds to the @Bytes@ rule from the official grammar+-}+_Bytes :: Parser ()+_Bytes = builtin "Bytes"+ {-| Parse the @Optional@ built-in This corresponds to the @Optional@ rule from the official grammar@@ -1068,6 +1195,48 @@ _TextShow :: Parser () _TextShow = builtin "Text/show" +{-| Parse the @Date@ bult-in++ This corresponds to the @Date@ rule from the official grammar+-}+_Date :: Parser ()+_Date = builtin "Date"++{-| Parse the @Date/show@ built-in++ This corresponds to the @Date-show@ rule from the official grammar+-}+_DateShow :: Parser ()+_DateShow = builtin "Date/show"++{-| Parse the @Time@ bult-in++ This corresponds to the @Time@ rule from the official grammar+-}+_Time :: Parser ()+_Time = builtin "Time"++{-| Parse the @Time/show@ built-in++ This corresponds to the @Time-show@ rule from the official grammar+-}+_TimeShow :: Parser ()+_TimeShow = builtin "Time/show"++{-| Parse the @TimeZone@ bult-in++ This corresponds to the @TimeZone@ rule from the official grammar+-}+_TimeZone :: Parser ()+_TimeZone = builtin "TimeZone"++{-| Parse the @TimeZone/show@ built-in++ This corresponds to the @TimeZone-show@ rule from the official grammar+-}+_TimeZoneShow :: Parser ()+_TimeZoneShow = builtin "TimeZone/show"+ {-| Parse the @List@ built-in This corresponds to the @List@ rule from the official grammar@@ -1213,8 +1382,10 @@ _at = reservedChar '@' <?> "\"@\"" -- | Parse the equivalence symbol (@===@ or @≡@)-_equivalent :: Parser ()-_equivalent = (void (char '≡' <?> "\"≡\"") <|> void (text "===")) <?> "operator"+_equivalent :: Parser CharacterSet+_equivalent =+ (Unicode <$ char '≡' <?> "\"≡\"")+ <|> (ASCII <$ text "===" <?> "===") -- | Parse the @missing@ keyword _missing :: Parser ()@@ -1227,32 +1398,40 @@ _importAlt = operatorChar '?' -- | Parse the record combine operator (@/\\@ or @∧@)-_combine :: Parser ()-_combine = (void (char '∧' <?> "\"∧\"") <|> void (text "/\\")) <?> "operator"+_combine :: Parser CharacterSet+_combine =+ (Unicode <$ char '∧' <?> "\"∧\"")+ <|> (ASCII <$ text "/\\" <?> "/\\") -- | Parse the record type combine operator (@//\\\\@ or @⩓@)-_combineTypes :: Parser ()-_combineTypes = (void (char '⩓' <?> "\"⩓\"") <|> void (text "//\\\\")) <?> "operator"+_combineTypes :: Parser CharacterSet+_combineTypes =+ (Unicode <$ char '⩓' <?> "\"⩓\"")+ <|> (ASCII <$ text "//\\\\" <?> "//\\\\") -- | Parse the record \"prefer\" operator (@//@ or @⫽@)-_prefer :: Parser ()-_prefer = (void (char '⫽' <?> "\"⫽\"") <|> void (text "//")) <?> "operator"+_prefer :: Parser CharacterSet+_prefer =+ (Unicode <$ char '⫽' <?> "\"⫽\"")+ <|> (ASCII <$ text "//" <?> "//") -- | Parse a lambda (@\\@ or @λ@)-_lambda :: Parser ()-_lambda = void (Text.Parser.Char.satisfy predicate) <?> "\\"- where- predicate 'λ' = True- predicate '\\' = True- predicate _ = False+_lambda :: Parser CharacterSet+_lambda =+ (Unicode <$ char 'λ' <?> "\"λ\"")+ <|> (ASCII <$ char '\\' <?> "\\") -- | Parse a forall (@forall@ or @∀@)-_forall :: Parser ()-_forall = (void (char '∀' <?> "\"∀\"") <|> void (text "forall")) <?> "forall"+_forall :: Parser CharacterSet+_forall =+ (Unicode <$ char '∀' <?> "\"∀\"")+ <|> (ASCII <$ text "forall" <?> "forall") -- | Parse a right arrow (@->@ or @→@)-_arrow :: Parser ()-_arrow = (void (char '→' <?> "\"→\"") <|> void (text "->")) <?> "->"+_arrow :: Parser CharacterSet+_arrow =+ (Unicode <$ char '→' <?> "\"→\"")+ <|> (ASCII <$ text "->" <?> "->") -- | Parse a double colon (@::@) _doubleColon :: Parser ()
@@ -8,13 +8,18 @@ , prettyExpr , CharacterSet(..)+ , defaultCharacterSet+ , detectCharacterSet , prettyCharacterSet , Dhall.Pretty.Internal.layout , Dhall.Pretty.Internal.layoutOpts , escapeEnvironmentVariable+ , UnescapedLabel(..) , escapeLabel++ , temporalToText ) where import Dhall.Pretty.Internal
@@ -1,7 +1,11 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wall #-} @@ -16,6 +20,8 @@ , prettySrcExpr , CharacterSet(..)+ , defaultCharacterSet+ , detectCharacterSet , prettyCharacterSet , prettyImportExpression @@ -26,6 +32,7 @@ , prettyEnvironmentVariable , prettyConst+ , UnescapedLabel(..) , escapeLabel , prettyLabel , prettyAnyLabel@@ -36,6 +43,7 @@ , prettyDouble , prettyToStrictText , prettyToString+ , prettyBase16 , layout , layoutOpts @@ -50,7 +58,7 @@ , comma , dot , equals- , forall+ , forall_ , label , lambda , langle@@ -63,31 +71,48 @@ , rbrace , rbracket , rparen++ , temporalToText ) where -import Data.Foldable-import Data.List.NonEmpty (NonEmpty (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty, space)-import Dhall.Map (Map)-import Dhall.Set (Set)-import Dhall.Src (Src (..))-import Dhall.Syntax-import Numeric.Natural (Natural)+import Control.DeepSeq (NFData)+import Data.Aeson+ ( FromJSON (..)+ , Value (String)+ )+import Data.Aeson.Types (typeMismatch, unexpected)+import Data.ByteString (ByteString)+import Data.Data (Data)+import Data.Foldable+import Data.List.NonEmpty (NonEmpty (..))+import Data.Text (Text)+import Dhall.Map (Map)+import Dhall.Src (Src (..))+import Dhall.Syntax+import {-# SOURCE #-} Dhall.Syntax.Instances.Pretty ()+import GHC.Generics (Generic)+import Language.Haskell.TH.Syntax (Lift)+import Lens.Micro (cosmosOf, foldMapOf)+import Numeric.Natural (Natural)+import Prettyprinter (Doc, Pretty, space) +import qualified Control.Exception as Exception+import qualified Data.ByteString.Base16 as Base16 import qualified Data.Char import qualified Data.HashSet-import qualified Data.List-import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Maybe-import qualified Data.Set-import qualified Data.Text as Text-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Terminal-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty-import qualified Dhall.Map as Map-import qualified Dhall.Set+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Encoding+import qualified Data.Time as Time+import qualified Dhall.Map as Map+import qualified Dhall.Syntax.Operations as Operations+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.String as Pretty+import qualified Prettyprinter.Render.Terminal as Terminal+import qualified Prettyprinter.Render.Text as Pretty+import qualified Text.Printf as Printf {-| Annotation type used to tag elements in a pretty-printed document for syntax highlighting purposes@@ -113,14 +138,51 @@ annToAnsiStyle Operator = Terminal.bold <> Terminal.colorDull Terminal.Green -- | This type determines whether to render code as `ASCII` or `Unicode`-data CharacterSet = ASCII | Unicode deriving Show+data CharacterSet = ASCII | Unicode+ deriving (Eq, Ord, Show, Data, Generic, Lift, NFData) +-- | Since ASCII is a subset of Unicode, if either argument is Unicode, the+-- result is Unicode+instance Semigroup CharacterSet where+ Unicode <> _ = Unicode+ _ <> other = other++instance Monoid CharacterSet where+ mempty = ASCII++instance FromJSON CharacterSet where+ parseJSON (String "unicode") = pure Unicode+ parseJSON (String "ascii") = pure ASCII+ parseJSON v@(String _) = unexpected v+ parseJSON v = typeMismatch "String" v++-- | The character set used by default in functions throughout the Dhall code+-- base.+defaultCharacterSet :: CharacterSet+defaultCharacterSet = Unicode++-- | Detect which character set is used for the syntax of an expression+-- If any parts of the expression uses the Unicode syntax, the whole expression+-- is deemed to be using the Unicode syntax.+detectCharacterSet :: Expr Src a -> CharacterSet+detectCharacterSet = foldMapOf (cosmosOf subExpressions) exprToCharacterSet+ where+ exprToCharacterSet = \case+ Embed _ -> mempty -- Don't go down the embed route, otherwise: <<loop>>+ Lam (Just Unicode) _ _ -> Unicode+ Pi (Just Unicode) _ _ _ -> Unicode+ Combine (Just Unicode) _ _ _ -> Unicode+ CombineTypes (Just Unicode) _ _ -> Unicode+ Prefer (Just Unicode) _ _ _ -> Unicode+ Equivalent (Just Unicode) _ _ -> Unicode+ _ -> mempty+ -- | Pretty print an expression prettyExpr :: Pretty a => Expr s a -> Doc Ann prettyExpr = prettySrcExpr . denote prettySrcExpr :: Pretty a => Expr Src a -> Doc Ann-prettySrcExpr = prettyCharacterSet Unicode+prettySrcExpr = prettyCharacterSet defaultCharacterSet {-| Internal utility for pretty-printing, used when generating element lists to supply to `enclose` or `enclose'`. This utility indicates that the@@ -261,9 +323,9 @@ lambda Unicode = syntax "λ" lambda ASCII = syntax "\\" -forall :: CharacterSet -> Doc Ann-forall Unicode = syntax "∀"-forall ASCII = syntax "forall "+forall_ :: CharacterSet -> Doc Ann+forall_ Unicode = syntax "∀"+forall_ ASCII = syntax "forall " rarrow :: CharacterSet -> Doc Ann rarrow Unicode = syntax "→"@@ -348,7 +410,7 @@ arrows :: CharacterSet -> [ Doc Ann ] -> Doc Ann arrows characterSet docs = Pretty.group (Pretty.flatAlt long short) where- long = Pretty.align (mconcat (Data.List.intersperse Pretty.hardline docs'))+ long = Pretty.align (mconcat (List.intersperse Pretty.hardline docs')) where docs' = case unsnoc docs of Nothing -> docs@@ -361,7 +423,7 @@ last' = space <> space <> last_ - short = mconcat (Data.List.intersperse separator docs)+ short = mconcat (List.intersperse separator docs) where separator = space <> rarrow characterSet <> space @@ -420,7 +482,7 @@ combineShort x y = x <> y {-| Format an expression that holds a variable number of elements without a- trailing document such as nested `let`, nested lambdas, or nested `forall`s+ trailing document such as nested @let@, nested lambdas, or nested @forall@s -} enclose' :: Doc ann@@ -440,7 +502,7 @@ longLines = zipWith (<>) (beginLong : repeat sepLong) docsLong long =- Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))+ Pretty.align (mconcat (List.intersperse Pretty.hardline longLines)) short = mconcat (zipWith (<>) (beginShort : repeat sepShort) docsShort) @@ -463,29 +525,51 @@ tailCharacter :: Char -> Bool tailCharacter c = alphaNum c || c == '_' || c == '-' || c == '/' +-- | The set of labels which do not need to be escaped+data UnescapedLabel+ = NonReservedLabel+ -- ^ This corresponds to the `nonreserved-label` rule in the grammar+ | AnyLabel+ -- ^ This corresponds to the `any-label` rule in the grammar+ | AnyLabelOrSome+ -- ^ This corresponds to the `any-label-or-some` rule in the grammar+ -- | Escape a label if it is not valid when unquoted-escapeLabel :: Bool -> Text -> Text-escapeLabel allowReserved l =+escapeLabel :: UnescapedLabel -> Text -> Text+escapeLabel allowedLabel l = case Text.uncons l of Just (h, t)- | headCharacter h && Text.all tailCharacter t && (notReservedIdentifier || (allowReserved && someOrNotLanguageKeyword))+ | headCharacter h && Text.all tailCharacter t && allowed && l /= "?" -> l _ -> "`" <> l <> "`"- where- notReservedIdentifier = not (Data.HashSet.member l reservedIdentifiers)- someOrNotLanguageKeyword = l == "Some" || not (Data.HashSet.member l reservedKeywords)+ where+ allowed = case allowedLabel of+ NonReservedLabel -> notReservedIdentifier+ AnyLabel -> notReservedKeyword+ AnyLabelOrSome -> notReservedKeyword || l == "Some" -prettyLabelShared :: Bool -> Text -> Doc Ann+ notReservedIdentifier = not (Data.HashSet.member l reservedIdentifiers)++ notReservedKeyword = not (Data.HashSet.member l reservedKeywords)++prettyLabelShared :: UnescapedLabel -> Text -> Doc Ann prettyLabelShared b l = label (Pretty.pretty (escapeLabel b l)) prettyLabel :: Text -> Doc Ann-prettyLabel = prettyLabelShared False+prettyLabel = prettyLabelShared NonReservedLabel prettyAnyLabel :: Text -> Doc Ann-prettyAnyLabel = prettyLabelShared True+prettyAnyLabel = prettyLabelShared AnyLabel -prettyAnyLabels :: Foldable list => list (Maybe Src, Text, Maybe Src) -> Doc Ann-prettyAnyLabels keys = Pretty.group (Pretty.flatAlt long short)+prettyAnyLabelOrSome :: Text -> Doc Ann+prettyAnyLabelOrSome = prettyLabelShared AnyLabelOrSome++prettyKeys+ :: Foldable list+ => (key -> Doc Ann)+ -> list (Maybe Src, key, Maybe Src)+ -> Doc Ann+prettyKeys prettyK keys = Pretty.group (Pretty.flatAlt long short) where short = (mconcat . Pretty.punctuate dot . map prettyKey . toList) keys @@ -505,16 +589,14 @@ . Pretty.punctuate Pretty.hardline . Data.Maybe.catMaybes $ [ renderSrcMaybe mSrc0- , Just (prettyAnyLabel key)+ , Just (prettyK key) , renderSrcMaybe mSrc1 ] -prettyLabels :: Set Text -> Doc Ann+prettyLabels :: [Text] -> Doc Ann prettyLabels a- | Data.Set.null (Dhall.Set.toSet a) =- lbrace <> rbrace- | otherwise =- braces (map (duplicate . prettyAnyLabel) (Dhall.Set.toList a))+ | null a = lbrace <> rbrace+ | otherwise = braces (map (duplicate . prettyAnyLabelOrSome) a) prettyNumber :: Integer -> Doc Ann prettyNumber = literal . Pretty.pretty@@ -605,10 +687,10 @@ prettyCompleteExpression expression = Pretty.group (prettyExpression expression) - prettyExpression a0@(Lam _ _) =+ prettyExpression a0@(Lam _ _ _) = arrows characterSet (docs a0) where- docs (Lam (FunctionBinding { functionBindingVariable = a, functionBindingAnnotation = b }) c) =+ docs (Lam _ (FunctionBinding { functionBindingVariable = a, functionBindingAnnotation = b }) c) = Pretty.group (Pretty.flatAlt long short) : docs c where long = (lambda characterSet <> space)@@ -654,7 +736,7 @@ longLines = zipWith (<>) prefixesLong (docsLong True a0) long =- Pretty.align (mconcat (Data.List.intersperse Pretty.hardline longLines))+ Pretty.align (mconcat (List.intersperse Pretty.hardline longLines)) short = mconcat (zipWith (<>) prefixesShort (docsShort a0)) @@ -697,7 +779,12 @@ where MultiLet as b = multiLet a0 b0 - stripSpaces = Text.dropAround (\c -> c == ' ' || c == '\t')+ isSpace c = c == ' ' || c == '\t'+ stripSpaces =+ Text.dropAround isSpace+ . Text.intercalate "\n"+ . map (Text.dropWhileEnd isSpace)+ . Text.splitOn "\n" -- Strip a single newline character. Needed to ensure idempotency in -- cases where we add hard line breaks.@@ -736,13 +823,13 @@ ( keyword "in" <> " " <> prettyExpression b , keyword "in" <> " " <> prettyExpression b )- prettyExpression a0@(Pi _ _ _) =+ prettyExpression a0@(Pi _ _ _ _) = arrows characterSet (docs a0) where- docs (Pi "_" b c) = prettyOperatorExpression b : docs c- docs (Pi a b c) = Pretty.group (Pretty.flatAlt long short) : docs c+ docs (Pi _ "_" b c) = prettyOperatorExpression b : docs c+ docs (Pi _ a b c) = Pretty.group (Pretty.flatAlt long short) : docs c where- long = forall characterSet <> space+ long = forall_ characterSet <> space <> Pretty.align ( lparen <> space <> prettyLabel a@@ -753,7 +840,7 @@ <> rparen ) - short = forall characterSet <> lparen+ short = forall_ characterSet <> lparen <> prettyLabel a <> space <> colon <> space <> prettyExpression b@@ -781,7 +868,11 @@ <> Pretty.align (keyword "with" <> " " <> update) (update, _) =- prettyKeyValue prettyOperatorExpression equals (makeKeyValue b c)+ prettyKeyValue prettyKey prettyOperatorExpression equals+ (makeKeyValue b c)++ prettyKey (WithLabel text) = prettyAnyLabelOrSome text+ prettyKey WithQuestion = syntax "?" prettyExpression (Assert a) = Pretty.group (Pretty.flatAlt long short) where@@ -813,7 +904,7 @@ <> Pretty.indent 2 (prettyImportExpression_ b) <> Pretty.hardline <> colon <> space- <> prettyApplicationExpression c+ <> prettyExpression c ) short = keyword "merge" <> space@@ -821,7 +912,7 @@ <> " " <> prettyImportExpression_ b <> space <> colon <> space- <> prettyApplicationExpression c+ <> prettyExpression c prettyAnnotatedExpression (ToMap a (Just b)) = Pretty.group (Pretty.flatAlt long short) where@@ -832,13 +923,13 @@ <> Pretty.indent 2 (prettyImportExpression_ a) <> Pretty.hardline <> colon <> space- <> prettyApplicationExpression b+ <> prettyExpression b ) short = keyword "toMap" <> space <> prettyImportExpression_ a <> space <> colon <> space- <> prettyApplicationExpression b+ <> prettyExpression b prettyAnnotatedExpression a0@(Annot _ _) = enclose' ""@@ -858,7 +949,7 @@ prettyAnnotatedExpression (ListLit (Just a) b) = list (map prettyExpression (Data.Foldable.toList b)) <> " : "- <> prettyApplicationExpression a+ <> prettyExpression a prettyAnnotatedExpression a | Just doc <- preserveSource a = doc@@ -884,10 +975,10 @@ spacer = if Text.length op == 1 then " " else " " prettyEquivalentExpression :: Pretty a => Expr Src a -> Doc Ann- prettyEquivalentExpression a0@(Equivalent _ _) =+ prettyEquivalentExpression a0@(Equivalent _ _ _) = prettyOperator (equivalent characterSet) (docs a0) where- docs (Equivalent a b) = prettyImportAltExpression b : docs a+ docs (Equivalent _ a b) = prettyImportAltExpression b : docs a docs a | Just doc <- preserveSource a = [ doc ]@@ -1024,10 +1115,10 @@ prettyCombineExpression a prettyCombineExpression :: Pretty a => Expr Src a -> Doc Ann- prettyCombineExpression a0@(Combine _ _ _) =+ prettyCombineExpression a0@(Combine _ _ _ _) = prettyOperator (combine characterSet) (docs a0) where- docs (Combine _ a b) = prettyPreferExpression b : docs a+ docs (Combine _ _ a b) = prettyPreferExpression b : docs a docs a | Just doc <- preserveSource a = [ doc ]@@ -1047,7 +1138,7 @@ prettyPreferExpression a0@(Prefer {}) = prettyOperator (prefer characterSet) (docs a0) where- docs (Prefer _ a b) = prettyCombineTypesExpression b : docs a+ docs (Prefer _ _ a b) = prettyCombineTypesExpression b : docs a docs a | Just doc <- preserveSource a = [ doc ]@@ -1064,10 +1155,10 @@ prettyCombineTypesExpression a prettyCombineTypesExpression :: Pretty a => Expr Src a -> Doc Ann- prettyCombineTypesExpression a0@(CombineTypes _ _) =+ prettyCombineTypesExpression a0@(CombineTypes _ _ _) = prettyOperator (combineTypes characterSet) (docs a0) where- docs (CombineTypes a b) = prettyTimesExpression b : docs a+ docs (CombineTypes _ a b) = prettyTimesExpression b : docs a docs a | Just doc <- preserveSource a = [ doc ]@@ -1151,6 +1242,7 @@ Some a -> app (builtin "Some") (a : args) Merge a b Nothing -> app (keyword "merge") (a : b : args) ToMap a Nothing -> app (keyword "toMap") (a : args)+ ShowConstructor a -> app (keyword "showConstructor") (a : args) e | Note _ b <- e -> go args b | null args ->@@ -1224,6 +1316,8 @@ prettyConst k prettyPrimitiveExpression Bool = builtin "Bool"+ prettyPrimitiveExpression Bytes =+ builtin "Bytes" prettyPrimitiveExpression Natural = builtin "Natural" prettyPrimitiveExpression NaturalFold =@@ -1262,6 +1356,57 @@ builtin "Text/replace" prettyPrimitiveExpression TextShow = builtin "Text/show"+ prettyPrimitiveExpression Date =+ builtin "Date"+ prettyPrimitiveExpression (DateLiteral day) =+ literal+ ( Pretty.pretty (Printf.printf "%04d" _HHHH :: String)+ <> "-"+ <> Pretty.pretty (Printf.printf "%02d" _MM :: String)+ <> "-"+ <> Pretty.pretty (Printf.printf "%02d" _DD :: String)+ )+ where+ (_HHHH, _MM, _DD) = Time.toGregorian day+ prettyPrimitiveExpression DateShow =+ builtin "Date/show"+ prettyPrimitiveExpression Time =+ builtin "Time"+ prettyPrimitiveExpression (TimeLiteral (Time.TimeOfDay hh mm seconds) precision) =+ literal+ ( Pretty.pretty (Printf.printf "%02d" hh :: String)+ <> ":"+ <> Pretty.pretty (Printf.printf "%02d" mm :: String)+ <> ":"+ <> Pretty.pretty (Printf.printf "%02d" ss :: String)+ <> suffix+ )+ where+ magnitude :: Integer+ magnitude = 10 ^ precision++ (ss, fraction) = truncate (seconds * fromInteger magnitude) `divMod` magnitude++ suffix+ | precision == 0 = ""+ | otherwise = "." <> Pretty.pretty (Printf.printf "%0*d" precision fraction :: String)+ prettyPrimitiveExpression TimeShow =+ builtin "Time/show"+ prettyPrimitiveExpression TimeZone =+ builtin "TimeZone"+ prettyPrimitiveExpression (TimeZoneLiteral (Time.TimeZone minutes _ _)) =+ literal+ ( sign+ <> Pretty.pretty (Printf.printf "%02d" _HH :: String)+ <> ":"+ <> Pretty.pretty (Printf.printf "%02d" _MM :: String)+ )+ where+ sign = if 0 <= minutes then "+" else "-"++ (_HH, _MM) = abs minutes `divMod` 60+ prettyPrimitiveExpression TimeZoneShow =+ builtin "TimeZone/show" prettyPrimitiveExpression List = builtin "List" prettyPrimitiveExpression ListBuild =@@ -1295,6 +1440,8 @@ prettyDouble a prettyPrimitiveExpression (TextLit a) = prettyChunks a+ prettyPrimitiveExpression (BytesLit a) =+ prettyBytes a prettyPrimitiveExpression (Record a) = prettyRecord a prettyPrimitiveExpression (RecordLit a) =@@ -1319,11 +1466,12 @@ prettyKeyValue :: Pretty a- => (Expr Src a -> Doc Ann)+ => (key -> Doc Ann)+ -> (Expr Src a -> Doc Ann) -> Doc Ann- -> KeyValue Src a+ -> KeyValue key Src a -> (Doc Ann, Doc Ann)- prettyKeyValue prettyValue separator (KeyValue key mSrc val) =+ prettyKeyValue prettyKey prettyValue separator (KeyValue key mSrc val) = duplicate (Pretty.group (Pretty.flatAlt long short)) where completion _T r =@@ -1335,7 +1483,7 @@ _ -> prettySelectorExpression r - short = prettyAnyLabels key+ short = prettyKeys prettyKey key <> " " <> separator <> " "@@ -1345,7 +1493,7 @@ <> prettyValue val long = Pretty.align- ( prettyAnyLabels key+ ( prettyKeys prettyKey key <> preSeparator ) <> separator@@ -1387,11 +1535,23 @@ <> keyword "toMap" <> case shallowDenote val' of RecordCompletion _T r ->- completion _T r+ " "+ <> completion _T r _ -> Pretty.hardline <> " " <> prettyImportExpression_ val' + ShowConstructor val' ->+ " "+ <> keyword "showConstructor"+ <> case shallowDenote val' of+ RecordCompletion _T r ->+ " "+ <> completion _T r+ _ -> Pretty.hardline+ <> " "+ <> prettyImportExpression_ val'+ RecordCompletion _T r -> " " <> completion _T r @@ -1422,14 +1582,43 @@ prettyRecord :: Pretty a => Map Text (RecordField Src a) -> Doc Ann prettyRecord =- braces- . map (prettyKeyValue prettyExpression colon . adapt)+ ( braces+ . map (prettyKeyValue prettyAnyLabelOrSome prettyExpression colon . adapt) . Map.toList+ ) where adapt (key, RecordField mSrc0 val mSrc1 mSrc2) = KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val prettyRecordLit :: Pretty a => Map Text (RecordField Src a) -> Doc Ann- prettyRecordLit = prettyRecordLike braces+ prettyRecordLit m+ | [ ("date" , field -> d@DateLiteral{})+ , ("time" , field -> t@TimeLiteral{})+ , ("timeZone", field -> z@TimeZoneLiteral{})+ ] <- List.sortOn fst (Map.toList m) =+ literal+ ( prettyPrimitiveExpression d+ <> "T"+ <> prettyPrimitiveExpression t+ <> prettyPrimitiveExpression z+ )+ | [ ("date" , field -> d@DateLiteral{})+ , ("time" , field -> t@TimeLiteral{})+ ] <- List.sortOn fst (Map.toList m) =+ literal+ ( prettyPrimitiveExpression d+ <> "T"+ <> prettyPrimitiveExpression t+ )+ | [ ("time" , field -> t@TimeLiteral{})+ , ("timeZone", field -> z@TimeZoneLiteral{})+ ] <- List.sortOn fst (Map.toList m) =+ literal+ ( prettyPrimitiveExpression t+ <> prettyPrimitiveExpression z+ )+ where+ field = Dhall.Syntax.shallowDenote . recordFieldValue+ prettyRecordLit m = prettyRecordLike braces m prettyCompletionLit :: Pretty a => Int -> Map Text (RecordField Src a) -> Doc Ann prettyCompletionLit = prettyRecordLike . hangingBraces@@ -1451,19 +1640,23 @@ | Var (V key' 0) <- Dhall.Syntax.shallowDenote val , key == key' , not (containsComment mSrc2) ->- duplicate (prettyAnyLabels [(mSrc0, key, mSrc1)])+ duplicate (prettyKeys prettyAnyLabelOrSome [(mSrc0, key, mSrc1)]) _ ->- prettyKeyValue prettyExpression equals kv+ prettyKeyValue prettyAnyLabelOrSome prettyExpression equals kv prettyAlternative (key, Just val) =- prettyKeyValue prettyExpression colon (makeKeyValue (pure key) val)+ prettyKeyValue prettyAnyLabelOrSome prettyExpression colon (makeKeyValue (pure key) val) prettyAlternative (key, Nothing) =- duplicate (prettyAnyLabel key)+ duplicate (prettyAnyLabelOrSome key) prettyUnion :: Pretty a => Map Text (Maybe (Expr Src a)) -> Doc Ann prettyUnion = angles . map prettyAlternative . Map.toList + prettyBytes :: ByteString -> Doc Ann+ prettyBytes bytes =+ literal (Pretty.pretty ("0x\"" <> prettyBase16 bytes <> "\""))+ prettyChunks :: Pretty a => Chunks Src a -> Doc Ann prettyChunks chunks@(Chunks a b) | anyText (== '\n') =@@ -1497,7 +1690,7 @@ prettyMultilineText text = mconcat docs where- lines_ = Text.splitOn "\n" (escapeSingleQuotedText text)+ lines_ = Text.splitOn "\n" text -- Annotate only non-empty lines so trailing whitespace can be -- removed on empty ones.@@ -1505,8 +1698,7 @@ (if Text.null line then id else literal) (Pretty.pretty line) - docs =- Data.List.intersperse Pretty.hardline (map prettyLine lines_)+ docs = List.intersperse Pretty.hardline (map prettyLine lines_) prettyChunk (c, d) = prettyText c@@ -1526,8 +1718,10 @@ -- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t" multilineChunks :: Chunks s a -> Chunks s a multilineChunks =- escapeTrailingSingleQuote+ escapeSingleQuotedText+ . escapeTrailingSingleQuote . escapeControlCharacters+ . escapeSingleQuoteBeforeInterpolation . escapeSharedWhitespacePrefix -- | Escape any leading whitespace shared by all lines@@ -1574,38 +1768,68 @@ -- >>> escapeControlCharacters (Chunks [] "\n\NUL\b\f\t") -- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t" escapeControlCharacters :: Chunks s a -> Chunks s a-escapeControlCharacters (Chunks as0 b0) = Chunks as1 b1+escapeControlCharacters = splitWith (splitOnPredicate predicate) where- as1 = foldr f (map toChunk bs) as0+ predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n' - (bs, b1) = splitOnPredicate predicate b0+-- | Escape @'${@ correctly+--+-- See: https://github.com/dhall-lang/dhall-haskell/issues/2078+escapeSingleQuoteBeforeInterpolation :: Chunks s a -> Chunks s a+escapeSingleQuoteBeforeInterpolation = splitWith f+ where+ f text =+ case Text.splitOn "'${" text of+ -- `splitOn` should never return an empty list, but just in case…+ [] -> mempty+ t : ts -> loop t ts - f (t0, e) chunks = map toChunk ts1 ++ (t1, e) : chunks- where- (ts1, t1) = splitOnPredicate predicate t0+ loop head_ tail_ =+ case tail_ of+ [] ->+ Chunks [] head_+ newHead : newTail ->+ Chunks [ (head_, TextLit (Chunks [] "'")) ] "${"+ <> loop newHead newTail - predicate c = Data.Char.isControl c && c /= ' ' && c /= '\t' && c /= '\n'+{-| You can think of this as sort of like `concatMap` for `Chunks` - toChunk (t0, t1) = (t0, TextLit (Chunks [] t1))+ Given a function that splits plain text into interpolated chunks, apply+ that function to each uninterpolated span to yield a new+ possibly-interpolated span, and flatten the results.+-}+splitWith :: (Text -> Chunks s a) -> Chunks s a -> Chunks s a+splitWith splitter (Chunks xys z) = mconcat (xys' ++ [ splitter z ])+ where+ xys' = do+ (x, y) <- xys --- | Split `Data.Text.Text` on a predicate, preserving all parts of the original--- string.+ [ splitter x, Chunks [ ("", y) ] "" ]++-- | Split `Data.Text.Text` into interpolated chunks, where all characters+-- matching the predicate are pushed into a string interpolation. -- -- >>> splitOnPredicate (== 'x') ""--- ([],"")+-- Chunks [] "" -- >>> splitOnPredicate (== 'x') " xx "--- ([(" ","xx")]," ")+-- Chunks [(" ",TextLit (Chunks [] "xx"))] " " -- >>> splitOnPredicate (== 'x') "xx"--- ([("","xx")],"")+-- Chunks [("",TextLit (Chunks [] "xx"))] "" ----- prop> \(Fun _ p) s -> let {t = Text.pack s; (as, b) = splitOnPredicate p t} in foldMap (uncurry (<>)) as <> b == t-splitOnPredicate :: (Char -> Bool) -> Text -> ([(Text, Text)], Text)-splitOnPredicate p t = case Text.break p t of- (a, "") -> ([], a)- (a, b) -> case Text.span p b of- (c, d) -> case splitOnPredicate p d of- (e, f) -> ((a, c) : e, f)+-- prop> \(Fun _ p) s -> let {t = Text.pack s; Chunks xys z = splitOnPredicate p t} in foldMap (\(x, TextLit (Chunks [] y)) -> x <> y) xys <> z == t+splitOnPredicate :: (Char -> Bool) -> Text -> Chunks s a+splitOnPredicate predicate text+ | Text.null b =+ Chunks [] a+ | otherwise =+ Chunks ((a, TextLit (Chunks [] c)) : e) f+ where+ (a, b) = Text.break predicate text + (c, d) = Text.span predicate b++ Chunks e f = splitOnPredicate predicate d+ -- | Escape a trailing single quote by moving it into a string interpolation -- -- Otherwise the multiline-string would end with @'''@, which would be parsed@@ -1623,13 +1847,13 @@ pretty_ :: Pretty a => a -> Text pretty_ = prettyToStrictText -data KeyValue s a = KeyValue- { _keyValueKeys :: NonEmpty (Maybe s, Text, Maybe s)+data KeyValue k s a = KeyValue+ { _keyValueKeys :: NonEmpty (Maybe s, k , Maybe s) , _keyValueSrc :: Maybe s , _keyValueValue :: Expr s a } -makeKeyValue :: NonEmpty Text -> Expr s a -> KeyValue s a+makeKeyValue :: NonEmpty key -> Expr s a -> KeyValue key s a makeKeyValue keys expr = KeyValue (adapt <$> keys) Nothing expr where adapt key = (Nothing, key, Nothing)@@ -1637,17 +1861,18 @@ {- This utility function converts `{ x = { y = { z = 1 } } }` to `{ x.y.z = 1 }` -}-consolidateRecordLiteral :: Map Text (RecordField Src a) -> [KeyValue Src a]+consolidateRecordLiteral+ :: Map Text (RecordField Src a) -> [KeyValue Text Src a] consolidateRecordLiteral = concatMap adapt . Map.toList where- adapt :: (Text, RecordField Src a) -> [KeyValue Src a]+ adapt :: (Text, RecordField Src a) -> [KeyValue Text Src a] adapt (key, RecordField mSrc0 val mSrc1 mSrc2) | not (containsComment mSrc2) , RecordLit m <- e , [ KeyValue keys mSrc2' val' ] <- concatMap adapt (Map.toList m) = [ KeyValue (NonEmpty.cons (mSrc0, key, mSrc1) keys) mSrc2' val' ] - | Combine (Just _) l r <- e =+ | Combine _ (Just _) l r <- e = adapt (key, makeRecordField l) <> adapt (key, makeRecordField r) | otherwise = [ KeyValue (pure (mSrc0, key, mSrc1)) mSrc2 val ]@@ -1656,12 +1881,13 @@ -- | Escape a `Data.Text.Text` literal using Dhall's escaping rules for -- single-quoted @Text@-escapeSingleQuotedText :: Text -> Text-escapeSingleQuotedText inputText = outputText+escapeSingleQuotedText :: Chunks s a -> Chunks s a+escapeSingleQuotedText = splitWith f where- outputText = substitute "${" "''${" (substitute "''" "'''" inputText)-- substitute before after = Text.intercalate after . Text.splitOn before+ f inputText = Chunks [] outputText+ where+ outputText =+ Text.replace "${" "''${" (Text.replace "''" "'''" inputText) {-| Escape a `Data.Text.Text` literal using Dhall's escaping rules @@ -1722,6 +1948,43 @@ layoutOpts = Pretty.defaultLayoutOptions { Pretty.layoutPageWidth = Pretty.AvailablePerLine 80 1.0 }++{-| Convert an expression representing a temporal value to `Data.Text.Text`, if+ possible++ This is used by downstream integrations (e.g. `dhall-json` for treating+ temporal values as strings+-}+temporalToText :: Pretty a => Expr s a -> Maybe Text+temporalToText e = case e of+ RecordLit m+ | [ ("date" , field -> DateLiteral{})+ , ("time" , field -> TimeLiteral{})+ , ("timeZone", field -> TimeZoneLiteral{})+ ] <- List.sortOn fst (Map.toList m) -> rendered+ | [ ("date" , field -> DateLiteral{})+ , ("time" , field -> TimeLiteral{})+ ] <- List.sortOn fst (Map.toList m) -> rendered+ | [ ("time" , field -> TimeLiteral{})+ , ("timeZone", field -> TimeZoneLiteral{})+ ] <- List.sortOn fst (Map.toList m) -> rendered+ DateLiteral{} -> rendered+ TimeLiteral{} -> rendered+ TimeZoneLiteral{} -> rendered+ _ -> Nothing+ where+ field = Dhall.Syntax.shallowDenote . recordFieldValue++ rendered = Just (prettyToStrictText e)++prettyBase16 :: ByteString -> Text+prettyBase16 bytes =+ case Encoding.decodeUtf8' (Base16.encode bytes) of+ Left exception ->+ Operations.internalError+ ("prettyBase16: base16-encoded bytes could not be decoded as UTF-8 text: " <> Text.pack (Exception.displayException exception))+ Right text ->+ Text.toUpper text {- $setup >>> import Test.QuickCheck (Fun(..))
@@ -1,12 +1,28 @@ module Dhall.Pretty.Internal where -import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty, Doc)-import Dhall.Src (Src)+import Control.DeepSeq (NFData)+import Data.Data (Data)+import Data.Text (Text)+import Dhall.Src (Src)+import Language.Haskell.TH.Syntax (Lift)+import Prettyprinter (Doc, Pretty) -import {-# SOURCE #-} Dhall.Syntax+import Dhall.Syntax.Const+import {-# SOURCE #-} Dhall.Syntax.Expr+import Dhall.Syntax.Var data Ann++data CharacterSet = ASCII | Unicode++instance Eq CharacterSet+instance Ord CharacterSet+instance Show CharacterSet+instance Data CharacterSet+instance Lift CharacterSet+instance NFData CharacterSet+instance Semigroup CharacterSet+instance Monoid CharacterSet prettyVar :: Var -> Doc Ann
@@ -18,15 +18,13 @@ , displayException , throwIO )-import Control.Monad (forM_)+import Control.Monad (forM_) #if !(MIN_VERSION_base(4,13,0))-import Control.Monad.Fail (MonadFail)+import Control.Monad.Fail (MonadFail) #endif-import Control.Monad.IO.Class (MonadIO, liftIO)-import Control.Monad.State.Class (MonadState, get, modify)-import Control.Monad.State.Strict (evalStateT)--- For the MonadFail instance for StateT.-import Control.Monad.Trans.Instances ()+import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.State.Class (MonadState, get, modify)+import Control.Monad.State.Strict (evalStateT) import Data.Char (isSpace) import Data.List ( dropWhileEnd@@ -47,35 +45,36 @@ import System.Directory (getDirectoryContents) import System.Environment (getEnvironment) -import qualified Control.Monad.Fail as Fail-import qualified Control.Monad.Trans.State.Strict as State+import qualified Control.Monad.Fail as Fail+import qualified Control.Monad.Trans.State.Strict as State import qualified Data.HashSet-import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty (renderIO)+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO import qualified Dhall import qualified Dhall.Context import qualified Dhall.Core-import qualified Dhall.Core as Dhall+import qualified Dhall.Core as Dhall ( Expr , Var (V) , normalize )-import qualified Dhall.Core as Expr (Expr (..))-import qualified Dhall.Import as Dhall-import qualified Dhall.Map as Map-import qualified Dhall.Parser as Dhall-import qualified Dhall.Parser.Token as Parser.Token+import qualified Dhall.Core as Expr (Expr (..))+import qualified Dhall.Import as Dhall+import qualified Dhall.Map as Map+import qualified Dhall.Parser as Dhall+import qualified Dhall.Parser.Expression as Parser.Expression import qualified Dhall.Pretty import qualified Dhall.Pretty.Internal-import qualified Dhall.TypeCheck as Dhall-import qualified Dhall.Version as Meta+import qualified Dhall.Syntax as Syntax+import qualified Dhall.TypeCheck as Dhall+import qualified Dhall.Version as Meta+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty (renderIO) import qualified System.Console.ANSI-import qualified System.Console.Haskeline.Completion as Haskeline-import qualified System.Console.Repline as Repline+import qualified System.Console.Haskeline.Completion as Haskeline+import qualified System.Console.Repline as Repline import qualified System.IO-import qualified Text.Megaparsec as Megaparsec+import qualified Text.Megaparsec as Megaparsec #if MIN_VERSION_haskeline(0,8,0) import qualified Control.Monad.Catch@@ -236,31 +235,51 @@ | otherwise = Left (trim str) -addBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => Either String (String, String) -> m ()-addBinding (Right (k, src)) = do- varName <- case Megaparsec.parse (unParser Parser.Token.label) "(input)" (Text.pack k) of- Left _ -> Fail.fail "Invalid variable name"- Right varName -> return varName+addBinding :: ( MonadFail m, MonadIO m, MonadState Env m ) => String -> m ()+addBinding string = do+ let parseBinding =+ Parser.Expression.letBinding+ (Parser.Expression.parsers+ (Megaparsec.try Parser.Expression.import_)+ ) - loaded <- parseAndLoad src+ let input = "let " <> Text.pack string - t <- typeCheck loaded+ Syntax.Binding{ variable, annotation, value } <- case Megaparsec.parse (unParser parseBinding) "(input)" input of+ Left _ -> Fail.fail ":let should be of the form `:let x [: T] = y`"+ Right binding -> return binding - expr <- normalize loaded+ (resolved, bindingType) <- case annotation of+ Just (_, unresolvedType) -> do+ let annotated = Syntax.Annot value unresolvedType + resolved <- liftIO (Dhall.load annotated)++ _ <- typeCheck resolved++ bindingType <- liftIO (Dhall.load unresolvedType)++ return (resolved, bindingType)+ _ -> do+ resolved <- liftIO (Dhall.load value)++ bindingType <- typeCheck resolved++ return (resolved, bindingType)++ bindingExpr <- normalize resolved+ modify ( \e -> e { envBindings = Dhall.Context.insert- varName- Binding { bindingType = t, bindingExpr = expr }+ variable+ Binding{ bindingType, bindingExpr } ( envBindings e ) } ) - output ( Expr.Annot ( Expr.Var ( Dhall.V varName 0 ) ) t )--addBinding _ = Fail.fail ":let should be of the form `:let x = y`"+ output (Expr.Annot (Expr.Var (Dhall.V variable 0)) bindingType) clearBindings :: (MonadFail m, MonadState Env m) => String -> m () clearBindings _ = modify adapt@@ -275,7 +294,8 @@ normalizedExpression <- normalize loadedExpression - writeOutputHandle $ hashExpressionToCode normalizedExpression+ writeOutputHandle+ (hashExpressionToCode (Dhall.Core.alphaNormalize normalizedExpression)) saveFilePrefix :: FilePath saveFilePrefix = ".dhall-repl"@@ -478,7 +498,7 @@ "let" "IDENTIFIER = EXPRESSION" "Assign an expression to a variable"- (dontCrash . addBinding . parseAssignment)+ (dontCrash . addBinding) , HelpOption "clear" ""
@@ -1,5 +1,4 @@ {-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -17,62 +16,65 @@ import Control.Applicative (empty) import Control.Exception (Exception)+import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Void (Void) import Dhall.Crypto (SHA256Digest) import Dhall.Map (Map)-import Dhall.Pretty (CharacterSet (..))+import Dhall.Pretty (CharacterSet (..), detectCharacterSet) import Dhall.Src (Src) import Dhall.Syntax (Expr (..), Import, Var (..)) import Dhall.Util ( Censor (..)- , CheckFailed (..) , Header (..) , Input (..)+ , MultipleCheckFailed (..) , OutputMode (..) ) -import qualified Control.Exception as Exception+import qualified Control.Exception as Exception import qualified Data.Map-import qualified Data.Maybe as Maybe-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text-import qualified Data.Void as Void-import qualified Dhall.Core as Core-import qualified Dhall.Import as Import-import qualified Dhall.Map as Map-import qualified Dhall.Normalize as Normalize-import qualified Dhall.Optics as Optics-import qualified Dhall.Parser as Parser+import qualified Data.Maybe as Maybe+import qualified Data.Text.IO as Text.IO+import qualified Data.Void as Void+import qualified Dhall.Core as Core+import qualified Dhall.Import as Import+import qualified Dhall.Map as Map+import qualified Dhall.Normalize as Normalize+import qualified Dhall.Parser as Parser import qualified Dhall.Pretty-import qualified Dhall.Substitution as Substitution-import qualified Dhall.Syntax as Syntax-import qualified Dhall.TypeCheck as TypeCheck-import qualified Dhall.Util as Util-import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite-import qualified System.Console.ANSI as ANSI-import qualified System.IO as IO+import qualified Dhall.Substitution as Substitution+import qualified Dhall.Syntax as Syntax+import qualified Dhall.TypeCheck as TypeCheck+import qualified Dhall.Util as Util+import qualified Lens.Micro as Lens+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty.Terminal+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified System.AtomicWrite.Writer.LazyText as AtomicWrite+import qualified System.Console.ANSI as ANSI+import qualified System.IO as IO -- | Arguments to the @rewrite-with-schemas@ subcommand data Schemas = Schemas- { characterSet :: CharacterSet- , censor :: Censor- , input :: Input- , outputMode :: OutputMode- , schemas :: Text+ { chosenCharacterSet :: Maybe CharacterSet+ , censor :: Censor+ , input :: Input+ , outputMode :: OutputMode+ , schemas :: Text } -- | Implementation of the @dhall rewrite-with-schemas@ subcommand schemasCommand :: Schemas -> IO () schemasCommand Schemas{..} = do- originalText <- case input of- InputFile file -> Text.IO.readFile file- StandardInput -> Text.IO.getContents+ (inputName, originalText) <- case input of+ InputFile file -> (,) file <$> Text.IO.readFile file+ StandardInput -> (,) "(input)" <$> Text.IO.getContents - (Header header, expression) <- Util.getExpressionAndHeaderFromStdinText censor originalText+ (Header header, expression) <- Util.getExpressionAndHeaderFromStdinText censor inputName originalText + let characterSet = fromMaybe (detectCharacterSet expression) chosenCharacterSet+ schemasRecord <- Core.throws (Parser.exprFromText "(schemas)" schemas) schemasExpression <- rewriteWithSchemas schemasRecord expression@@ -112,8 +114,10 @@ let modified = "rewritten" - Exception.throwIO CheckFailed{..}+ let inputs = pure input + Exception.throwIO MultipleCheckFailed{..}+ decodeSchema :: Expr s Void -> Maybe (Expr s Void, Map Text (Expr s Void)) decodeSchema (RecordLit m) | Just _Type <- Core.recordFieldValue <$> Map.lookup "Type" m@@ -191,7 +195,7 @@ let rewrittenExpression :: Expr Src Import rewrittenExpression =- fmap Void.absurd (Optics.transformOf Syntax.subExpressions schemasRewrite normalizedExpression)+ fmap Void.absurd (Lens.transformOf Syntax.subExpressions schemasRewrite normalizedExpression) if Normalize.freeIn (V "schemas" 0) rewrittenExpression then return (Let (Syntax.makeBinding "schemas" _schemas) rewrittenExpression)
@@ -15,10 +15,10 @@ import Control.DeepSeq (NFData) import Data.Data (Data) import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty (..)) import GHC.Generics (Generic) import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift (..))+import Prettyprinter (Pretty (..)) import Text.Megaparsec (SourcePos (SourcePos), mkPos, unPos) import {-# SOURCE #-} qualified Dhall.Util
@@ -1,1448 +1,31 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveLift #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedLists #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE UnicodeSyntax #-}--{-| This module contains the core syntax types and optics for them.--'reservedIdentifiers', 'denote' and friends are included because they are-involved in a dependency circle with "Dhall.Pretty.Internal".--}--module Dhall.Syntax (- -- * 'Expr'- Const(..)- , Var(..)- , Binding(..)- , makeBinding- , Chunks(..)- , DhallDouble(..)- , PreferAnnotation(..)- , Expr(..)- , RecordField(..)- , makeRecordField- , FunctionBinding(..)- , makeFunctionBinding- , FieldSelection(..)- , makeFieldSelection-- -- ** 'Let'-blocks- , MultiLet(..)- , multiLet- , wrapInLets-- -- ** Optics- , subExpressions- , unsafeSubExpressions- , chunkExprs- , bindingExprs- , recordFieldExprs- , functionBindingExprs-- -- ** Handling 'Note's- , denote- , renote- , shallowDenote-- -- * 'Import'- , Directory(..)- , File(..)- , FilePrefix(..)- , Import(..)- , ImportHashed(..)- , ImportMode(..)- , ImportType(..)- , URL(..)- , Scheme(..)- , pathCharacter-- -- * Reserved identifiers- , reservedIdentifiers- , reservedKeywords-- -- * `Data.Text.Text` manipulation- , toDoubleQuoted- , longestSharedWhitespacePrefix- , linesLiteral- , unlinesLiteral-- -- * Desugaring- , desugarWith-- -- * Utilities- , internalError- -- `shift` should really be in `Dhall.Normalize`, but it's here to avoid a- -- module cycle- , shift- ) where--import Control.DeepSeq (NFData)-import Data.Bifunctor (Bifunctor (..))-import Data.Bits (xor)-import Data.Data (Data)-import Data.Foldable-import Data.HashSet (HashSet)-import Data.List.NonEmpty (NonEmpty (..))-import Data.Sequence (Seq)-import Data.String (IsString (..))-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Data.Traversable ()-import Data.Void (Void)-import Dhall.Map (Map)-import {-# SOURCE #-} Dhall.Pretty.Internal-import Dhall.Set (Set)-import Dhall.Src (Src (..))-import GHC.Generics (Generic)-import Instances.TH.Lift ()-import Language.Haskell.TH.Syntax (Lift)-import Numeric.Natural (Natural)-import Unsafe.Coerce (unsafeCoerce)--import qualified Control.Monad-import qualified Data.HashSet-import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Dhall.Crypto-import qualified Dhall.Optics as Optics-import qualified Lens.Family as Lens-import qualified Network.URI as URI---- $setup--- >>> import Dhall.Binary () -- For the orphan instance for `Serialise (Expr Void Import)`--{-| Constants for a pure type system-- The axioms are:--> ⊦ Type : Kind-> ⊦ Kind : Sort-- ... and the valid rule pairs are:--> ⊦ Type ↝ Type : Type -- Functions from terms to terms (ordinary functions)-> ⊦ Kind ↝ Type : Type -- Functions from types to terms (type-polymorphic functions)-> ⊦ Sort ↝ Type : Type -- Functions from kinds to terms-> ⊦ Kind ↝ Kind : Kind -- Functions from types to types (type-level functions)-> ⊦ Sort ↝ Kind : Sort -- Functions from kinds to types (kind-polymorphic functions)-> ⊦ Sort ↝ Sort : Sort -- Functions from kinds to kinds (kind-level functions)-- Note that Dhall does not support functions from terms to types and therefore- Dhall is not a dependently typed language--}-data Const = Type | Kind | Sort- deriving (Show, Eq, Ord, Data, Bounded, Enum, Generic, Lift, NFData)--instance Pretty Const where- pretty = Pretty.unAnnotate . prettyConst--{-| Label for a bound variable-- The `Data.Text.Text` field is the variable's name (i.e. \"@x@\").-- The `Int` field disambiguates variables with the same name if there are- multiple bound variables of the same name in scope. Zero refers to the- nearest bound variable and the index increases by one for each bound- variable of the same name going outward. The following diagram may help:--> ┌──refers to──┐-> │ │-> v │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0->-> ┌─────────────────refers to─────────────────┐-> │ │-> v │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1-- This `Int` behaves like a De Bruijn index in the special case where all- variables have the same name.-- You can optionally omit the index if it is @0@:--> ┌─refers to─┐-> │ │-> v │-> λ(x : Type) → λ(y : Type) → λ(x : Type) → x-- Zero indices are omitted when pretty-printing @Var@s and non-zero indices- appear as a numeric suffix.--}-data Var = V Text !Int- deriving (Data, Generic, Eq, Ord, Show, Lift, NFData)--instance IsString Var where- fromString str = V (fromString str) 0--instance Pretty Var where- pretty = Pretty.unAnnotate . prettyVar--{- | Record the binding part of a @let@ expression.--For example,--> let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x--will be instantiated as follows:--* @bindingSrc0@ corresponds to the @A@ comment.-* @variable@ is @"x"@-* @bindingSrc1@ corresponds to the @B@ comment.-* @annotation@ is 'Just' a pair, corresponding to the @C@ comment and @Bool@.-* @bindingSrc2@ corresponds to the @D@ comment.-* @value@ corresponds to @True@.--}-data Binding s a = Binding- { bindingSrc0 :: Maybe s- , variable :: Text- , bindingSrc1 :: Maybe s- , annotation :: Maybe (Maybe s, Expr s a)- , bindingSrc2 :: Maybe s- , value :: Expr s a- } deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)--instance Bifunctor Binding where- first k (Binding src0 a src1 b src2 c) =- Binding (fmap k src0) a (fmap k src1) (fmap adapt0 b) (fmap k src2) (first k c)- where- adapt0 (src3, d) = (fmap k src3, first k d)-- second = fmap--{-| Construct a 'Binding' with no source information and no type annotation.--}-makeBinding :: Text -> Expr s a -> Binding s a-makeBinding name = Binding Nothing name Nothing Nothing Nothing---- | This wrapper around 'Prelude.Double' exists for its 'Eq' instance which is--- defined via the binary encoding of Dhall @Double@s.-newtype DhallDouble = DhallDouble { getDhallDouble :: Double }- deriving (Show, Data, Lift, NFData, Generic)---- | This instance satisfies all the customary 'Eq' laws except substitutivity.------ In particular:------ >>> nan = DhallDouble (0/0)--- >>> nan == nan--- True------ This instance is also consistent with with the binary encoding of Dhall @Double@s:------ >>> toBytes n = Dhall.Binary.encodeExpression (DoubleLit n :: Expr Void Import)------ prop> \a b -> (a == b) == (toBytes a == toBytes b)-instance Eq DhallDouble where- DhallDouble a == DhallDouble b- | isNaN a && isNaN b = True- | isNegativeZero a `xor` isNegativeZero b = False- | otherwise = a == b---- | This instance relies on the 'Eq' instance for 'DhallDouble' but cannot--- satisfy the customary 'Ord' laws when @NaN@ is involved.-instance Ord DhallDouble where- compare a@(DhallDouble a') b@(DhallDouble b') =- if a == b- then EQ- else compare a' b'---- | The body of an interpolated @Text@ literal-data Chunks s a = Chunks [(Text, Expr s a)] Text- deriving (Functor, Foldable, Generic, Traversable, Show, Eq, Ord, Data, Lift, NFData)--instance Semigroup (Chunks s a) where- Chunks xysL zL <> Chunks [] zR =- Chunks xysL (zL <> zR)- Chunks xysL zL <> Chunks ((x, y):xysR) zR =- Chunks (xysL ++ (zL <> x, y):xysR) zR--instance Monoid (Chunks s a) where- mempty = Chunks [] mempty--instance IsString (Chunks s a) where- fromString str = Chunks [] (fromString str)---- | Used to record the origin of a @//@ operator (i.e. from source code or a--- product of desugaring)-data PreferAnnotation s a- = PreferFromSource- | PreferFromWith (Expr s a)- -- ^ Stores the original @with@ expression- | PreferFromCompletion- deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)--instance Bifunctor PreferAnnotation where- first _ PreferFromSource = PreferFromSource- first f (PreferFromWith e ) = PreferFromWith (first f e)- first _ PreferFromCompletion = PreferFromCompletion-- second = fmap--{-| Record the field of a record-type and record-literal expression.- The reason why we use the same ADT for both of them is because they store- the same information.--For example,--> { {- A -} x {- B -} : {- C -} T }--... or--> { {- A -} x {- B -} = {- C -} T }--will be instantiated as follows:--* @recordFieldSrc0@ corresponds to the @A@ comment.-* @recordFieldValue@ is @"T"@-* @recordFieldSrc1@ corresponds to the @B@ comment.-* @recordFieldSrc2@ corresponds to the @C@ comment.--Although the @A@ comment isn't annotating the @"T"@ Record Field,-this is the best place to keep these comments.--Note that @recordFieldSrc2@ is always 'Nothing' when the 'RecordField' is for-a punned entry, because there is no @=@ sign. For example,--> { {- A -} x {- B -} }--will be instantiated as follows:--* @recordFieldSrc0@ corresponds to the @A@ comment.-* @recordFieldValue@ corresponds to @(Var "x")@-* @recordFieldSrc1@ corresponds to the @B@ comment.-* @recordFieldSrc2@ will be 'Nothing'--The labels involved in a record using dot-syntax like in this example:--> { {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }--will be instantiated as follows:--* For both the @a@ and @b@ field, @recordfieldSrc2@ is 'Nothing'-* For the @a@ field:- * @recordFieldSrc0@ corresponds to the @A@ comment- * @recordFieldSrc1@ corresponds to the @B@ comment-* For the @b@ field:- * @recordFieldSrc0@ corresponds to the @C@ comment- * @recordFieldSrc1@ corresponds to the @D@ comment-* For the @c@ field:- * @recordFieldSrc0@ corresponds to the @E@ comment- * @recordFieldSrc1@ corresponds to the @F@ comment- * @recordFieldSrc2@ corresponds to the @G@ comment--That is, for every label except the last one the semantics of @recordFieldSrc0@-and @recordFieldSrc1@ are the same from a regular record label but-@recordFieldSrc2@ is always 'Nothing'. For the last keyword, all srcs are 'Just'--}-data RecordField s a = RecordField- { recordFieldSrc0 :: Maybe s- , recordFieldValue :: Expr s a- , recordFieldSrc1 :: Maybe s- , recordFieldSrc2 :: Maybe s- } deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)---- | Construct a 'RecordField' with no src information-makeRecordField :: Expr s a -> RecordField s a-makeRecordField e = RecordField Nothing e Nothing Nothing---instance Bifunctor RecordField where- first k (RecordField s0 value s1 s2) =- RecordField (k <$> s0) (first k value) (k <$> s1) (k <$> s2)- second = fmap--{-| Record the label of a function or a function-type expression--For example,--> λ({- A -} a {- B -} : {- C -} T) -> e--will be instantiated as follows:-* @functionBindingSrc0@ corresponds to the @A@ comment-* @functionBindingVariable@ is @a@-* @functionBindingSrc1@ corresponds to the @B@ comment-* @functionBindingSrc2@ corresponds to the @C@ comment-* @functionBindingAnnotation@ is @T@--}-data FunctionBinding s a = FunctionBinding- { functionBindingSrc0 :: Maybe s- , functionBindingVariable :: Text- , functionBindingSrc1 :: Maybe s- , functionBindingSrc2 :: Maybe s- , functionBindingAnnotation :: Expr s a- } deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)---- | Smart constructor for 'FunctionBinding' with no src information-makeFunctionBinding :: Text -> Expr s a -> FunctionBinding s a-makeFunctionBinding l t = FunctionBinding Nothing l Nothing Nothing t--instance Bifunctor FunctionBinding where- first k (FunctionBinding src0 label src1 src2 type_) =- FunctionBinding (k <$> src0) label (k <$> src1) (k <$> src2) (first k type_)-- second = fmap--{-| Record the field on a selector-expression--For example,--> e . {- A -} x {- B -}--will be instantiated as follows:-* @fieldSelectionSrc0@ corresponds to the @A@ comment-* @fieldSelectionLabel@ corresponds to @x@-* @fieldSelectionSrc1@ corresponds to the @B@ comment--Given our limitation that not all expressions recover their whitespaces, the-purpose of @fieldSelectionSrc1@ is to save the 'Text.Megaparsec.SourcePos' where-the @fieldSelectionLabel@ ends, but we /still/ use a 'Maybe Src' (@s = 'Src'@)-to be consistent with similar data types such as 'Binding', for example.--}-data FieldSelection s = FieldSelection- { fieldSelectionSrc0 :: Maybe s- , fieldSelectionLabel :: !Text- , fieldSelectionSrc1 :: Maybe s- } deriving (Data, Eq, Foldable, Functor, Generic, Lift, NFData, Ord, Show, Traversable)---- | Smart constructor for 'FieldSelection' with no src information-makeFieldSelection :: Text -> FieldSelection s-makeFieldSelection t = FieldSelection Nothing t Nothing--{-| Syntax tree for expressions-- The @s@ type parameter is used to track the presence or absence of `Src`- spans:-- * If @s = `Src`@ then the code may contains `Src` spans (either in a `Note`- constructor or inline within another constructor, like `Let`)- * If @s = `Void`@ then the code has no `Src` spans-- The @a@ type parameter is used to track the presence or absence of imports-- * If @a = `Import`@ then the code may contain unresolved `Import`s- * If @a = `Void`@ then the code has no `Import`s--}-data Expr s a- -- | > Const c ~ c- = Const Const- -- | > Var (V x 0) ~ x- -- > Var (V x n) ~ x@n- | Var Var- -- | > Lam (FunctionBinding _ "x" _ _ A) b ~ λ(x : A) -> b- | Lam (FunctionBinding s a) (Expr s a)- -- | > Pi "_" A B ~ A -> B- -- > Pi x A B ~ ∀(x : A) -> B- | Pi Text (Expr s a) (Expr s a)- -- | > App f a ~ f a- | App (Expr s a) (Expr s a)- -- | > Let (Binding _ x _ Nothing _ r) e ~ let x = r in e- -- > Let (Binding _ x _ (Just t ) _ r) e ~ let x : t = r in e- --- -- The difference between- --- -- > let x = a let y = b in e- --- -- and- --- -- > let x = a in let y = b in e- --- -- is only an additional 'Note' around @'Let' "y" …@ in the second- -- example.- --- -- See 'MultiLet' for a representation of let-blocks that mirrors the- -- source code more closely.- | Let (Binding s a) (Expr s a)- -- | > Annot x t ~ x : t- | Annot (Expr s a) (Expr s a)- -- | > Bool ~ Bool- | Bool- -- | > BoolLit b ~ b- | BoolLit Bool- -- | > BoolAnd x y ~ x && y- | BoolAnd (Expr s a) (Expr s a)- -- | > BoolOr x y ~ x || y- | BoolOr (Expr s a) (Expr s a)- -- | > BoolEQ x y ~ x == y- | BoolEQ (Expr s a) (Expr s a)- -- | > BoolNE x y ~ x != y- | BoolNE (Expr s a) (Expr s a)- -- | > BoolIf x y z ~ if x then y else z- | BoolIf (Expr s a) (Expr s a) (Expr s a)- -- | > Natural ~ Natural- | Natural- -- | > NaturalLit n ~ n- | NaturalLit Natural- -- | > NaturalFold ~ Natural/fold- | NaturalFold- -- | > NaturalBuild ~ Natural/build- | NaturalBuild- -- | > NaturalIsZero ~ Natural/isZero- | NaturalIsZero- -- | > NaturalEven ~ Natural/even- | NaturalEven- -- | > NaturalOdd ~ Natural/odd- | NaturalOdd- -- | > NaturalToInteger ~ Natural/toInteger- | NaturalToInteger- -- | > NaturalShow ~ Natural/show- | NaturalShow- -- | > NaturalSubtract ~ Natural/subtract- | NaturalSubtract- -- | > NaturalPlus x y ~ x + y- | NaturalPlus (Expr s a) (Expr s a)- -- | > NaturalTimes x y ~ x * y- | NaturalTimes (Expr s a) (Expr s a)- -- | > Integer ~ Integer- | Integer- -- | > IntegerLit n ~ ±n- | IntegerLit Integer- -- | > IntegerClamp ~ Integer/clamp- | IntegerClamp- -- | > IntegerNegate ~ Integer/negate- | IntegerNegate- -- | > IntegerShow ~ Integer/show- | IntegerShow- -- | > IntegerToDouble ~ Integer/toDouble- | IntegerToDouble- -- | > Double ~ Double- | Double- -- | > DoubleLit n ~ n- | DoubleLit DhallDouble- -- | > DoubleShow ~ Double/show- | DoubleShow- -- | > Text ~ Text- | Text- -- | > TextLit (Chunks [(t1, e1), (t2, e2)] t3) ~ "t1${e1}t2${e2}t3"- | TextLit (Chunks s a)- -- | > TextAppend x y ~ x ++ y- | TextAppend (Expr s a) (Expr s a)- -- | > TextReplace ~ Text/replace- | TextReplace- -- | > TextShow ~ Text/show- | TextShow- -- | > List ~ List- | List- -- | > ListLit (Just t ) [] ~ [] : t- -- > ListLit Nothing [x, y, z] ~ [x, y, z]- --- -- Invariant: A non-empty list literal is always represented as- -- @ListLit Nothing xs@.- --- -- When an annotated, non-empty list literal is parsed, it is represented- -- as- --- -- > Annot (ListLit Nothing [x, y, z]) t ~ [x, y, z] : t-- -- Eventually we should have separate constructors for empty and non-empty- -- list literals. For now it's easier to check the invariant in @infer@.- -- See https://github.com/dhall-lang/dhall-haskell/issues/1359#issuecomment-537087234.- | ListLit (Maybe (Expr s a)) (Seq (Expr s a))- -- | > ListAppend x y ~ x # y- | ListAppend (Expr s a) (Expr s a)- -- | > ListBuild ~ List/build- | ListBuild- -- | > ListFold ~ List/fold- | ListFold- -- | > ListLength ~ List/length- | ListLength- -- | > ListHead ~ List/head- | ListHead- -- | > ListLast ~ List/last- | ListLast- -- | > ListIndexed ~ List/indexed- | ListIndexed- -- | > ListReverse ~ List/reverse- | ListReverse- -- | > Optional ~ Optional- | Optional- -- | > Some e ~ Some e- | Some (Expr s a)- -- | > None ~ None- | None- -- | > Record [ (k1, RecordField _ t1) ~ { k1 : t1, k2 : t1 }- -- > , (k2, RecordField _ t2)- -- > ]- | Record (Map Text (RecordField s a))- -- | > RecordLit [ (k1, RecordField _ v1) ~ { k1 = v1, k2 = v2 }- -- > , (k2, RecordField _ v2)- -- > ]- | RecordLit (Map Text (RecordField s a))- -- | > Union [(k1, Just t1), (k2, Nothing)] ~ < k1 : t1 | k2 >- | Union (Map Text (Maybe (Expr s a)))- -- | > Combine Nothing x y ~ x ∧ y- --- -- The first field is a `Just` when the `Combine` operator is introduced- -- as a result of desugaring duplicate record fields:- --- -- > RecordLit [ ( k ~ { k = x, k = y }- -- > , RecordField- -- > _- -- > (Combine (Just k) x y)- -- > )]- | Combine (Maybe Text) (Expr s a) (Expr s a)- -- | > CombineTypes x y ~ x ⩓ y- | CombineTypes (Expr s a) (Expr s a)- -- | > Prefer False x y ~ x ⫽ y- --- -- The first field is a `True` when the `Prefer` operator is introduced as a- -- result of desugaring a @with@ expression- | Prefer (PreferAnnotation s a) (Expr s a) (Expr s a)- -- | > RecordCompletion x y ~ x::y- | RecordCompletion (Expr s a) (Expr s a)- -- | > Merge x y (Just t ) ~ merge x y : t- -- > Merge x y Nothing ~ merge x y- | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))- -- | > ToMap x (Just t) ~ toMap x : t- -- > ToMap x Nothing ~ toMap x- | ToMap (Expr s a) (Maybe (Expr s a))- -- | > Field e (FieldSelection _ x _) ~ e.x- | Field (Expr s a) (FieldSelection s)- -- | > Project e (Left xs) ~ e.{ xs }- -- > Project e (Right t) ~ e.(t)- | Project (Expr s a) (Either (Set Text) (Expr s a))- -- | > Assert e ~ assert : e- | Assert (Expr s a)- -- | > Equivalent x y ~ x ≡ y- | Equivalent (Expr s a) (Expr s a)- -- | > With x y e ~ x with y = e- | With (Expr s a) (NonEmpty Text) (Expr s a)- -- | > Note s x ~ e- | Note s (Expr s a)- -- | > ImportAlt ~ e1 ? e2- | ImportAlt (Expr s a) (Expr s a)- -- | > Embed import ~ import- | Embed a- deriving (Foldable, Generic, Traversable, Show, Data, Lift, NFData)--- NB: If you add a constructor to Expr, please also update the Arbitrary--- instance in Dhall.Test.QuickCheck.---- | This instance encodes what the Dhall standard calls an \"exact match\"--- between two expressions.------ Note that------ >>> nan = DhallDouble (0/0)--- >>> DoubleLit nan == DoubleLit nan--- True-deriving instance (Eq s, Eq a) => Eq (Expr s a)---- | Note that this 'Ord' instance inherits `DhallDouble`'s defects.-deriving instance (Ord s, Ord a) => Ord (Expr s a)---- This instance is hand-written due to the fact that deriving--- it does not give us an INLINABLE pragma. We annotate this fmap--- implementation with this pragma below to allow GHC to, possibly,--- inline the implementation for performance improvements.-instance Functor (Expr s) where- fmap f (Embed a) = Embed (f a)- fmap f (Let b e2) = Let (fmap f b) (fmap f e2)- fmap f (Note s e1) = Note s (fmap f e1)- fmap f (Record a) = Record $ fmap f <$> a- fmap f (RecordLit a) = RecordLit $ fmap f <$> a- fmap f (Lam fb e) = Lam (f <$> fb) (f <$> e)- fmap f (Field a b) = Field (f <$> a) b- fmap f expression = Lens.over unsafeSubExpressions (fmap f) expression- {-# INLINABLE fmap #-}--instance Applicative (Expr s) where- pure = Embed-- (<*>) = Control.Monad.ap--instance Monad (Expr s) where- return = pure-- expression >>= k = case expression of- Embed a -> k a- Let a b -> Let (adaptBinding a) (b >>= k)- Note a b -> Note a (b >>= k)- Record a -> Record $ bindRecordKeyValues <$> a- RecordLit a -> RecordLit $ bindRecordKeyValues <$> a- Lam a b -> Lam (adaptFunctionBinding a) (b >>= k)- Field a b -> Field (a >>= k) b- _ -> Lens.over unsafeSubExpressions (>>= k) expression- where- bindRecordKeyValues (RecordField s0 e s1 s2) =- RecordField s0 (e >>= k) s1 s2-- adaptBinding (Binding src0 c src1 d src2 e) =- Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e >>= k)-- adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =- FunctionBinding src0 label src1 src2 (type_ >>= k)-- adaptBindingAnnotation (src3, f) = (src3, f >>= k)--instance Bifunctor Expr where- first k (Note a b ) = Note (k a) (first k b)- first _ (Embed a ) = Embed a- first k (Let a b ) = Let (first k a) (first k b)- first k (Record a ) = Record $ first k <$> a- first k (RecordLit a) = RecordLit $ first k <$> a- first k (Lam a b ) = Lam (first k a) (first k b)- first k (Field a b ) = Field (first k a) (k <$> b)- first k expression = Lens.over unsafeSubExpressions (first k) expression-- second = fmap--instance IsString (Expr s a) where- fromString str = Var (fromString str)---- | Generates a syntactically valid Dhall program-instance Pretty a => Pretty (Expr s a) where- pretty = Pretty.unAnnotate . prettyExpr--{--Instead of converting explicitly between 'Expr's and 'MultiLet', it might-be nicer to use a pattern synonym:--> pattern MultiLet' :: NonEmpty (Binding s a) -> Expr s a -> Expr s a-> pattern MultiLet' as b <- (multiLetFromExpr -> Just (MultiLet as b)) where-> MultiLet' as b = wrapInLets as b->-> multiLetFromExpr :: Expr s a -> Maybe (MultiLet s a)-> multiLetFromExpr = \case-> Let x mA a b -> Just (multiLet x mA a b)-> _ -> Nothing--This works in principle, but GHC as of v8.8.1 doesn't handle it well:-https://gitlab.haskell.org/ghc/ghc/issues/17096--This should be fixed by GHC-8.10, so it might be worth revisiting then.--}--{-| Generate a 'MultiLet' from the contents of a 'Let'.-- In the resulting @'MultiLet' bs e@, @e@ is guaranteed not to be a 'Let',- but it might be a @('Note' … ('Let' …))@.-- Given parser output, 'multiLet' consolidates @let@s that formed a- let-block in the original source.--}-multiLet :: Binding s a -> Expr s a -> MultiLet s a-multiLet b0 = \case- Let b1 e1 ->- let MultiLet bs e = multiLet b1 e1- in MultiLet (NonEmpty.cons b0 bs) e- e -> MultiLet (b0 :| []) e--{-| Wrap let-'Binding's around an 'Expr'.--'wrapInLets' can be understood as an inverse for 'multiLet':--> let MultiLet bs e1 = multiLet b e0->-> wrapInLets bs e1 == Let b e0--}-wrapInLets :: Foldable f => f (Binding s a) -> Expr s a -> Expr s a-wrapInLets bs e = foldr Let e bs--{-| This type represents 1 or more nested `Let` bindings that have been- coalesced together for ease of manipulation--}-data MultiLet s a = MultiLet (NonEmpty (Binding s a)) (Expr s a)---- | A traversal over the immediate sub-expressions of an expression.-subExpressions- :: Applicative f => (Expr s a -> f (Expr s a)) -> Expr s a -> f (Expr s a)-subExpressions _ (Embed a) = pure (Embed a)-subExpressions f (Note a b) = Note a <$> f b-subExpressions f (Let a b) = Let <$> bindingExprs f a <*> f b-subExpressions f (Record a) = Record <$> traverse (recordFieldExprs f) a-subExpressions f (RecordLit a) = RecordLit <$> traverse (recordFieldExprs f) a-subExpressions f (Lam fb e) = Lam <$> functionBindingExprs f fb <*> f e-subExpressions f (Field a b) = Field <$> f a <*> pure b-subExpressions f expression = unsafeSubExpressions f expression-{-# INLINABLE subExpressions #-}--{-| An internal utility used to implement transformations that require changing- one of the type variables of the `Expr` type-- This utility only works because the implementation is partial, not- handling the `Let`, `Note`, or `Embed` cases, which need to be handled by- the caller.--}-unsafeSubExpressions- :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)-unsafeSubExpressions _ (Const c) = pure (Const c)-unsafeSubExpressions _ (Var v) = pure (Var v)-unsafeSubExpressions f (Pi a b c) = Pi a <$> f b <*> f c-unsafeSubExpressions f (App a b) = App <$> f a <*> f b-unsafeSubExpressions f (Annot a b) = Annot <$> f a <*> f b-unsafeSubExpressions _ Bool = pure Bool-unsafeSubExpressions _ (BoolLit b) = pure (BoolLit b)-unsafeSubExpressions f (BoolAnd a b) = BoolAnd <$> f a <*> f b-unsafeSubExpressions f (BoolOr a b) = BoolOr <$> f a <*> f b-unsafeSubExpressions f (BoolEQ a b) = BoolEQ <$> f a <*> f b-unsafeSubExpressions f (BoolNE a b) = BoolNE <$> f a <*> f b-unsafeSubExpressions f (BoolIf a b c) = BoolIf <$> f a <*> f b <*> f c-unsafeSubExpressions _ Natural = pure Natural-unsafeSubExpressions _ (NaturalLit n) = pure (NaturalLit n)-unsafeSubExpressions _ NaturalFold = pure NaturalFold-unsafeSubExpressions _ NaturalBuild = pure NaturalBuild-unsafeSubExpressions _ NaturalIsZero = pure NaturalIsZero-unsafeSubExpressions _ NaturalEven = pure NaturalEven-unsafeSubExpressions _ NaturalOdd = pure NaturalOdd-unsafeSubExpressions _ NaturalToInteger = pure NaturalToInteger-unsafeSubExpressions _ NaturalShow = pure NaturalShow-unsafeSubExpressions _ NaturalSubtract = pure NaturalSubtract-unsafeSubExpressions f (NaturalPlus a b) = NaturalPlus <$> f a <*> f b-unsafeSubExpressions f (NaturalTimes a b) = NaturalTimes <$> f a <*> f b-unsafeSubExpressions _ Integer = pure Integer-unsafeSubExpressions _ (IntegerLit n) = pure (IntegerLit n)-unsafeSubExpressions _ IntegerClamp = pure IntegerClamp-unsafeSubExpressions _ IntegerNegate = pure IntegerNegate-unsafeSubExpressions _ IntegerShow = pure IntegerShow-unsafeSubExpressions _ IntegerToDouble = pure IntegerToDouble-unsafeSubExpressions _ Double = pure Double-unsafeSubExpressions _ (DoubleLit n) = pure (DoubleLit n)-unsafeSubExpressions _ DoubleShow = pure DoubleShow-unsafeSubExpressions _ Text = pure Text-unsafeSubExpressions f (TextLit chunks) =- TextLit <$> chunkExprs f chunks-unsafeSubExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b-unsafeSubExpressions _ TextReplace = pure TextReplace-unsafeSubExpressions _ TextShow = pure TextShow-unsafeSubExpressions _ List = pure List-unsafeSubExpressions f (ListLit a b) = ListLit <$> traverse f a <*> traverse f b-unsafeSubExpressions f (ListAppend a b) = ListAppend <$> f a <*> f b-unsafeSubExpressions _ ListBuild = pure ListBuild-unsafeSubExpressions _ ListFold = pure ListFold-unsafeSubExpressions _ ListLength = pure ListLength-unsafeSubExpressions _ ListHead = pure ListHead-unsafeSubExpressions _ ListLast = pure ListLast-unsafeSubExpressions _ ListIndexed = pure ListIndexed-unsafeSubExpressions _ ListReverse = pure ListReverse-unsafeSubExpressions _ Optional = pure Optional-unsafeSubExpressions f (Some a) = Some <$> f a-unsafeSubExpressions _ None = pure None-unsafeSubExpressions f (Union a) = Union <$> traverse (traverse f) a-unsafeSubExpressions f (Combine a b c) = Combine a <$> f b <*> f c-unsafeSubExpressions f (CombineTypes a b) = CombineTypes <$> f a <*> f b-unsafeSubExpressions f (Prefer a b c) = Prefer <$> a' <*> f b <*> f c- where- a' = case a of- PreferFromSource -> pure PreferFromSource- PreferFromWith d -> PreferFromWith <$> f d- PreferFromCompletion -> pure PreferFromCompletion-unsafeSubExpressions f (RecordCompletion a b) = RecordCompletion <$> f a <*> f b-unsafeSubExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t-unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t-unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b-unsafeSubExpressions f (Assert a) = Assert <$> f a-unsafeSubExpressions f (Equivalent a b) = Equivalent <$> f a <*> f b-unsafeSubExpressions f (With a b c) = With <$> f a <*> pure b <*> f c-unsafeSubExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r-unsafeSubExpressions _ (Let {}) = unhandledConstructor "Let"-unsafeSubExpressions _ (Note {}) = unhandledConstructor "Note"-unsafeSubExpressions _ (Embed {}) = unhandledConstructor "Embed"-unsafeSubExpressions _ (Record {}) = unhandledConstructor "Record"-unsafeSubExpressions _ (RecordLit {}) = unhandledConstructor "RecordLit"-unsafeSubExpressions _ (Lam {}) = unhandledConstructor "Lam"-unsafeSubExpressions _ (Field {}) = unhandledConstructor "Field"-{-# INLINABLE unsafeSubExpressions #-}--unhandledConstructor :: Text -> a-unhandledConstructor constructor =- internalError- ( "Dhall.Syntax.unsafeSubExpressions: Unhandled "- <> constructor- <> " construtor"- )--{-| Traverse over the immediate 'Expr' children in a 'Binding'.--}-bindingExprs- :: (Applicative f)- => (Expr s a -> f (Expr s b))- -> Binding s a -> f (Binding s b)-bindingExprs f (Binding s0 n s1 t s2 v) =- Binding- <$> pure s0- <*> pure n- <*> pure s1- <*> traverse (traverse f) t- <*> pure s2- <*> f v-{-# INLINABLE bindingExprs #-}--{-| Traverse over the immediate 'Expr' children in a 'RecordField'.--}-recordFieldExprs- :: Applicative f- => (Expr s a -> f (Expr s b))- -> RecordField s a -> f (RecordField s b)-recordFieldExprs f (RecordField s0 e s1 s2) =- RecordField- <$> pure s0- <*> f e- <*> pure s1- <*> pure s2--{-| Traverse over the immediate 'Expr' children in a 'FunctionBinding'.--}-functionBindingExprs- :: Applicative f- => (Expr s a -> f (Expr s b))- -> FunctionBinding s a -> f (FunctionBinding s b)-functionBindingExprs f (FunctionBinding s0 label s1 s2 type_) =- FunctionBinding- <$> pure s0- <*> pure label- <*> pure s1- <*> pure s2- <*> f type_---- | A traversal over the immediate sub-expressions in 'Chunks'.-chunkExprs- :: Applicative f- => (Expr s a -> f (Expr t b))- -> Chunks s a -> f (Chunks t b)-chunkExprs f (Chunks chunks final) =- flip Chunks final <$> traverse (traverse f) chunks-{-# INLINABLE chunkExprs #-}--{-| Internal representation of a directory that stores the path components in- reverse order-- In other words, the directory @\/foo\/bar\/baz@ is encoded as- @Directory { components = [ "baz", "bar", "foo" ] }@--}-newtype Directory = Directory { components :: [Text] }- deriving (Eq, Generic, Ord, Show, NFData)--instance Semigroup Directory where- Directory components₀ <> Directory components₁ =- Directory (components₁ <> components₀)--instance Pretty Directory where- pretty (Directory {..}) = foldMap prettyPathComponent (reverse components)--prettyPathComponent :: Text -> Doc ann-prettyPathComponent text- | Data.Text.all pathCharacter text =- "/" <> Pretty.pretty text- | otherwise =- "/\"" <> Pretty.pretty text <> "\""--{-| A `File` is a `directory` followed by one additional path component- representing the `file` name--}-data File = File- { directory :: Directory- , file :: Text- } deriving (Eq, Generic, Ord, Show, NFData)--instance Pretty File where- pretty (File {..}) =- Pretty.pretty directory- <> prettyPathComponent file--instance Semigroup File where- File directory₀ _ <> File directory₁ file =- File (directory₀ <> directory₁) file---- | The beginning of a file path which anchors subsequent path components-data FilePrefix- = Absolute- -- ^ Absolute path- | Here- -- ^ Path relative to @.@- | Parent- -- ^ Path relative to @..@- | Home- -- ^ Path relative to @~@- deriving (Eq, Generic, Ord, Show, NFData)--instance Pretty FilePrefix where- pretty Absolute = ""- pretty Here = "."- pretty Parent = ".."- pretty Home = "~"---- | The URI scheme-data Scheme = HTTP | HTTPS deriving (Eq, Generic, Ord, Show, NFData)---- | This type stores all of the components of a remote import-data URL = URL- { scheme :: Scheme- , authority :: Text- , path :: File- , query :: Maybe Text- , headers :: Maybe (Expr Src Import)- } deriving (Eq, Generic, Ord, Show, NFData)--instance Pretty URL where- pretty (URL {..}) =- schemeDoc- <> "://"- <> Pretty.pretty authority- <> pathDoc- <> queryDoc- <> foldMap prettyHeaders headers- where- prettyHeaders h =- " using " <> Pretty.unAnnotate (prettyImportExpression h)-- File {..} = path-- Directory {..} = directory-- pathDoc =- foldMap prettyURIComponent (reverse components)- <> prettyURIComponent file-- schemeDoc = case scheme of- HTTP -> "http"- HTTPS -> "https"-- queryDoc = case query of- Nothing -> ""- Just q -> "?" <> Pretty.pretty q--prettyURIComponent :: Text -> Doc ann-prettyURIComponent text =- Pretty.pretty $ URI.normalizeCase $ URI.normalizeEscape $ "/" <> Data.Text.unpack text---- | The type of import (i.e. local vs. remote vs. environment)-data ImportType- = Local FilePrefix File- -- ^ Local path- | Remote URL- -- ^ URL of remote resource and optional headers stored in an import- | Env Text- -- ^ Environment variable- | Missing- deriving (Eq, Generic, Ord, Show, NFData)--parent :: File-parent = File { directory = Directory { components = [ ".." ] }, file = "" }--instance Semigroup ImportType where- Local prefix file₀ <> Local Here file₁ = Local prefix (file₀ <> file₁)-- Remote (URL { path = path₀, ..}) <> Local Here path₁ =- Remote (URL { path = path₀ <> path₁, ..})-- Local prefix file₀ <> Local Parent file₁ =- Local prefix (file₀ <> parent <> file₁)-- Remote (URL { path = path₀, .. }) <> Local Parent path₁ =- Remote (URL { path = path₀ <> parent <> path₁, .. })-- import₀ <> Remote (URL { headers = headers₀, .. }) =- Remote (URL { headers = headers₁, .. })- where- importHashed₀ = Import (ImportHashed Nothing import₀) Code-- headers₁ = fmap (fmap (importHashed₀ <>)) headers₀-- _ <> import₁ =- import₁--instance Pretty ImportType where- pretty (Local prefix file) =- Pretty.pretty prefix <> Pretty.pretty file-- pretty (Remote url) = Pretty.pretty url-- pretty (Env env) = "env:" <> prettyEnvironmentVariable env-- pretty Missing = "missing"---- | How to interpret the import's contents (i.e. as Dhall code or raw text)-data ImportMode = Code | RawText | Location- deriving (Eq, Generic, Ord, Show, NFData)---- | A `ImportType` extended with an optional hash for semantic integrity checks-data ImportHashed = ImportHashed- { hash :: Maybe Dhall.Crypto.SHA256Digest- , importType :: ImportType- } deriving (Eq, Generic, Ord, Show, NFData)--instance Semigroup ImportHashed where- ImportHashed _ importType₀ <> ImportHashed hash importType₁ =- ImportHashed hash (importType₀ <> importType₁)--instance Pretty ImportHashed where- pretty (ImportHashed Nothing p) =- Pretty.pretty p- pretty (ImportHashed (Just h) p) =- Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)---- | Reference to an external resource-data Import = Import- { importHashed :: ImportHashed- , importMode :: ImportMode- } deriving (Eq, Generic, Ord, Show, NFData)--instance Semigroup Import where- Import importHashed₀ _ <> Import importHashed₁ code =- Import (importHashed₀ <> importHashed₁) code--instance Pretty Import where- pretty (Import {..}) = Pretty.pretty importHashed <> Pretty.pretty suffix- where- suffix :: Text- suffix = case importMode of- RawText -> " as Text"- Location -> " as Location"- Code -> ""--{-| Returns `True` if the given `Char` is valid within an unquoted path- component-- This is exported for reuse within the @"Dhall.Parser.Token"@ module--}-pathCharacter :: Char -> Bool-pathCharacter c =- '\x21' == c- || ('\x24' <= c && c <= '\x27')- || ('\x2A' <= c && c <= '\x2B')- || ('\x2D' <= c && c <= '\x2E')- || ('\x30' <= c && c <= '\x3B')- || c == '\x3D'- || ('\x40' <= c && c <= '\x5A')- || ('\x5E' <= c && c <= '\x7A')- || c == '\x7C'- || c == '\x7E'---- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)-denote :: Expr s a -> Expr t a-denote = \case- Note _ b -> denote b- Let a b -> Let (denoteBinding a) (denote b)- Embed a -> Embed a- Combine _ b c -> Combine Nothing (denote b) (denote c)- Record a -> Record $ denoteRecordField <$> a- RecordLit a -> RecordLit $ denoteRecordField <$> a- Lam a b -> Lam (denoteFunctionBinding a) (denote b)- Field a (FieldSelection _ b _) -> Field (denote a) (FieldSelection Nothing b Nothing)- expression -> Lens.over unsafeSubExpressions denote expression- where- denoteRecordField (RecordField _ e _ _) = RecordField Nothing (denote e) Nothing Nothing- denoteBinding (Binding _ c _ d _ e) =- Binding Nothing c Nothing (fmap denoteBindingAnnotation d) Nothing (denote e)-- denoteBindingAnnotation (_, f) = (Nothing, denote f)-- denoteFunctionBinding (FunctionBinding _ l _ _ t) =- FunctionBinding Nothing l Nothing Nothing (denote t)---- | The \"opposite\" of `denote`, like @first absurd@ but faster-renote :: Expr Void a -> Expr s a-renote = unsafeCoerce-{-# INLINE renote #-}--{-| Remove any outermost `Note` constructors-- This is typically used when you want to get the outermost non-`Note`- constructor without removing internal `Note` constructors--}-shallowDenote :: Expr s a -> Expr s a-shallowDenote (Note _ e) = shallowDenote e-shallowDenote e = e---- | The set of reserved keywords according to the @keyword@ rule in the grammar-reservedKeywords :: HashSet Text-reservedKeywords =- Data.HashSet.fromList- [- "if"- , "then"- , "else"- , "let"- , "in"- , "using"- , "missing"- , "as"- , "Infinity"- , "NaN"- , "merge"- , "Some"- , "toMap"- , "assert"- , "forall"- , "with"- ]---- | The set of reserved identifiers for the Dhall language--- | Contains also all keywords from "reservedKeywords"-reservedIdentifiers :: HashSet Text-reservedIdentifiers = reservedKeywords <>- Data.HashSet.fromList- [ -- Builtins according to the `builtin` rule in the grammar- "Natural/fold"- , "Natural/build"- , "Natural/isZero"- , "Natural/even"- , "Natural/odd"- , "Natural/toInteger"- , "Natural/show"- , "Natural/subtract"- , "Integer"- , "Integer/clamp"- , "Integer/negate"- , "Integer/show"- , "Integer/toDouble"- , "Integer/show"- , "Natural/subtract"- , "Double/show"- , "List/build"- , "List/fold"- , "List/length"- , "List/head"- , "List/last"- , "List/indexed"- , "List/reverse"- , "Text/replace"- , "Text/show"- , "Bool"- , "True"- , "False"- , "Optional"- , "None"- , "Natural"- , "Integer"- , "Double"- , "Text"- , "List"- , "Type"- , "Kind"- , "Sort"- ]---- | Same as @Data.Text.splitOn@, except always returning a `NonEmpty` result-splitOn :: Text -> Text -> NonEmpty Text-splitOn needle haystack =- case Data.Text.splitOn needle haystack of- [] -> "" :| []- t : ts -> t :| ts---- | Split `Chunks` by lines-linesLiteral :: Chunks s a -> NonEmpty (Chunks s a)-linesLiteral (Chunks [] suffix) =- fmap (Chunks []) (splitOn "\n" suffix)-linesLiteral (Chunks ((prefix, interpolation) : pairs₀) suffix₀) =- foldr- NonEmpty.cons- (Chunks ((lastLine, interpolation) : pairs₁) suffix₁ :| chunks)- (fmap (Chunks []) initLines)- where- splitLines = splitOn "\n" prefix-- initLines = NonEmpty.init splitLines- lastLine = NonEmpty.last splitLines-- Chunks pairs₁ suffix₁ :| chunks = linesLiteral (Chunks pairs₀ suffix₀)---- | Flatten several `Chunks` back into a single `Chunks` by inserting newlines-unlinesLiteral :: NonEmpty (Chunks s a) -> Chunks s a-unlinesLiteral chunks =- Data.Foldable.fold (NonEmpty.intersperse "\n" chunks)---- | Returns `True` if the `Chunks` represents a blank line-emptyLine :: Chunks s a -> Bool-emptyLine (Chunks [] "" ) = True-emptyLine (Chunks [] "\r") = True -- So that `\r\n` is treated as a blank line-emptyLine _ = False---- | Return the leading whitespace for a `Chunks` literal-leadingSpaces :: Chunks s a -> Text-leadingSpaces chunks = Data.Text.takeWhile isSpace firstText- where- isSpace c = c == ' ' || c == '\t'-- firstText =- case chunks of- Chunks [] suffix -> suffix- Chunks ((prefix, _) : _ ) _ -> prefix--{-| Compute the longest shared whitespace prefix for the purposes of stripping- leading indentation--}-longestSharedWhitespacePrefix :: NonEmpty (Chunks s a) -> Text-longestSharedWhitespacePrefix literals =- case fmap leadingSpaces filteredLines of- l : ls -> Data.Foldable.foldl' sharedPrefix l ls- [] -> ""- where- sharedPrefix ab ac =- case Data.Text.commonPrefixes ab ac of- Just (a, _b, _c) -> a- Nothing -> ""-- -- The standard specifies to filter out blank lines for all lines *except*- -- for the last line- filteredLines = newInit <> pure oldLast- where- oldInit = NonEmpty.init literals-- oldLast = NonEmpty.last literals-- newInit = filter (not . emptyLine) oldInit---- | Drop the first @n@ characters for a `Chunks` literal-dropLiteral :: Int -> Chunks s a -> Chunks s a-dropLiteral n (Chunks [] suffix) =- Chunks [] (Data.Text.drop n suffix)-dropLiteral n (Chunks ((prefix, interpolation) : rest) suffix) =- Chunks ((Data.Text.drop n prefix, interpolation) : rest) suffix--{-| Convert a single-quoted `Chunks` literal to the equivalent double-quoted- `Chunks` literal--}-toDoubleQuoted :: Chunks Src a -> Chunks Src a-toDoubleQuoted literal =- unlinesLiteral (fmap (dropLiteral indent) literals)- where- literals = linesLiteral literal-- longestSharedPrefix = longestSharedWhitespacePrefix literals-- indent = Data.Text.length longestSharedPrefix--{-| `shift` is used by both normalization and type-checking to avoid variable- capture by shifting variable indices-- For example, suppose that you were to normalize the following expression:--> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x-- If you were to substitute @y@ with @x@ without shifting any variable- indices, then you would get the following incorrect result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x -- Incorrect normalized form-- In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in- order to avoid being misinterpreted as the @x@ bound by the innermost- lambda. If we perform that `shift` then we get the correct result:--> λ(a : Type) → λ(x : a) → λ(x : a) → x@1-- As a more worked example, suppose that you were to normalize the following- expression:--> λ(a : Type)-> → λ(f : a → a → a)-> → λ(x : a)-> → λ(x : a)-> → (λ(x : a) → f x x@1) x@1-- The correct normalized result would be:--> λ(a : Type)-> → λ(f : a → a → a)-> → λ(x : a)-> → λ(x : a)-> → f x@1 x-- The above example illustrates how we need to both increase and decrease- variable indices as part of substitution:-- * We need to increase the index of the outer @x\@1@ to @x\@2@ before we- substitute it into the body of the innermost lambda expression in order- to avoid variable capture. This substitution changes the body of the- lambda expression to @(f x\@2 x\@1)@-- * We then remove the innermost lambda and therefore decrease the indices of- both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one- less @x@ variable is now bound within that scope-- Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to- the indices of all variables named @x@ whose indices are greater than- @(n + m)@, where @m@ is the number of bound variables of the same name- within that scope-- In practice, @d@ is always @1@ or @-1@ because we either:-- * increment variables by @1@ to avoid variable capture during substitution- * decrement variables by @1@ when deleting lambdas after substitution-- @n@ starts off at @0@ when substitution begins and increments every time we- descend into a lambda or let expression that binds a variable of the same- name in order to avoid shifting the bound variables by mistake.--}-shift :: Int -> Var -> Expr s a -> Expr s a-shift d (V x n) (Var (V x' n')) = Var (V x' n'')- where- n'' = if x == x' && n <= n' then n' + d else n'-shift d (V x n) (Lam (FunctionBinding src0 x' src1 src2 _A) b) =- Lam (FunctionBinding src0 x' src1 src2 _A') b'- where- _A' = shift d (V x n ) _A- b' = shift d (V x n') b- where- n' = if x == x' then n + 1 else n-shift d (V x n) (Pi x' _A _B) = Pi x' _A' _B'- where- _A' = shift d (V x n ) _A- _B' = shift d (V x n') _B- where- n' = if x == x' then n + 1 else n-shift d (V x n) (Let (Binding src0 f src1 mt src2 r) e) =- Let (Binding src0 f src1 mt' src2 r') e'- where- e' = shift d (V x n') e- where- n' = if x == f then n + 1 else n-- mt' = fmap (fmap (shift d (V x n))) mt- r' = shift d (V x n) r-shift d v expression = Lens.over subExpressions (shift d v) expression---- | Desugar all @with@ expressions-desugarWith :: Expr s a -> Expr s a-desugarWith = Optics.rewriteOf subExpressions rewrite- where- rewrite e@(With record (key :| []) value) =- Just- (Prefer- (PreferFromWith e)- record- (RecordLit [ (key, makeRecordField value) ])- )- rewrite e@(With record (key0 :| key1 : keys) value) =- Just- (Let- (makeBinding "_" record)- (Prefer (PreferFromWith e) "_"- (RecordLit- [ (key0, makeRecordField $ With (Field "_" (FieldSelection Nothing key0 Nothing)) (key1 :| keys) (shift 1 "_" value)) ]- )- )- )- rewrite _ = Nothing--_ERROR :: String-_ERROR = "\ESC[1;31mError\ESC[0m"--{-| Utility function used to throw internal errors that should never happen- (in theory) but that are not enforced by the type system--}-internalError :: Data.Text.Text -> forall b . b-internalError text = error (unlines- [ _ERROR <> ": Compiler bug "- , " "- , "Explanation: This error message means that there is a bug in the Dhall compiler."- , "You didn't do anything wrong, but if you would like to see this problem fixed "- , "then you should report the bug at: "- , " "- , "https://github.com/dhall-lang/dhall-haskell/issues "- , " "- , "Please include the following text in your bug report: "- , " "- , "``` "- , Data.Text.unpack text <> " "- , "``` "- ] )+module Dhall.Syntax+ ( module Export+ ) where++import {-# SOURCE #-} Dhall.Pretty.Internal as Export+ ( CharacterSet (..)+ )+import Dhall.Syntax.Binding as Export+import Dhall.Syntax.Chunks as Export+import Dhall.Syntax.Const as Export+import Dhall.Syntax.Expr as Export+import Dhall.Syntax.FunctionBinding as Export+import Dhall.Syntax.Import as Export+import Dhall.Syntax.Instances.Applicative as Export ()+import Dhall.Syntax.Instances.Bifunctor as Export ()+import Dhall.Syntax.Instances.Data as Export ()+import Dhall.Syntax.Instances.Eq as Export ()+import Dhall.Syntax.Instances.Foldable as Export ()+import Dhall.Syntax.Instances.Functor as Export ()+import Dhall.Syntax.Instances.Lift as Export ()+import Dhall.Syntax.Instances.Monad as Export ()+import Dhall.Syntax.Instances.NFData as Export ()+import Dhall.Syntax.Instances.Ord as Export ()+import Dhall.Syntax.Instances.Pretty as Export+import Dhall.Syntax.Instances.Show as Export ()+import Dhall.Syntax.Instances.Traversable as Export ()+import Dhall.Syntax.MultiLet as Export+import Dhall.Syntax.Operations as Export+import Dhall.Syntax.RecordField as Export+import Dhall.Syntax.Types as Export+import Dhall.Syntax.Var as Export
@@ -1,7 +0,0 @@-module Dhall.Syntax where--data Var--data Const--data Expr s a
@@ -0,0 +1,57 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Binding+ ( Binding(..)+ , makeBinding++ -- * Optics+ , bindingExprs+ ) where++import Data.Text (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import GHC.Generics (Generic)++-- | Record the binding part of a @let@ expression.+--+-- For example,+--+-- > let {- A -} x {- B -} : {- C -} Bool = {- D -} True in x+--+-- … will be instantiated as follows:+--+-- * @bindingSrc0@ corresponds to the @A@ comment.+-- * @variable@ is @"x"@+-- * @bindingSrc1@ corresponds to the @B@ comment.+-- * @annotation@ is 'Just' a pair, corresponding to the @C@ comment and @Bool@.+-- * @bindingSrc2@ corresponds to the @D@ comment.+-- * @value@ corresponds to @True@.+data Binding s a = Binding+ { bindingSrc0 :: Maybe s+ , variable :: Text+ , bindingSrc1 :: Maybe s+ , annotation :: Maybe (Maybe s, Expr s a)+ , bindingSrc2 :: Maybe s+ , value :: Expr s a+ } deriving Generic++{-| Construct a 'Binding' with no source information and no type annotation.+-}+makeBinding :: Text -> Expr s a -> Binding s a+makeBinding name = Binding Nothing name Nothing Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'Binding'.+-}+bindingExprs+ :: (Applicative f)+ => (Expr s a -> f (Expr s b))+ -> Binding s a -> f (Binding s b)+bindingExprs f (Binding s0 n s1 t s2 v) =+ Binding+ <$> pure s0+ <*> pure n+ <*> pure s1+ <*> traverse (traverse f) t+ <*> pure s2+ <*> f v+{-# INLINABLE bindingExprs #-}
@@ -0,0 +1,141 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Syntax.Chunks+ ( Chunks(..)++ -- * Optics+ , chunkExprs++ -- * `Data.Text.Text` manipulation+ , toDoubleQuoted+ , longestSharedWhitespacePrefix+ , linesLiteral+ , unlinesLiteral+ ) where++import Data.List.NonEmpty (NonEmpty (..))+import Data.String (IsString (..))+import Data.Text (Text)+import Dhall.Src (Src)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import GHC.Generics (Generic)++import qualified Data.Foldable+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text++-- | The body of an interpolated @Text@ literal+data Chunks s a = Chunks [(Text, Expr s a)] Text+ deriving Generic++instance IsString (Chunks s a) where+ fromString str = Chunks [] (fromString str)++instance Semigroup (Chunks s a) where+ Chunks xysL zL <> Chunks [] zR =+ Chunks xysL (zL <> zR)+ Chunks xysL zL <> Chunks ((x, y):xysR) zR =+ Chunks (xysL ++ (zL <> x, y):xysR) zR++instance Monoid (Chunks s a) where+ mempty = Chunks [] mempty++-- | A traversal over the immediate sub-expressions in 'Chunks'.+chunkExprs+ :: Applicative f+ => (Expr s a -> f (Expr t b))+ -> Chunks s a -> f (Chunks t b)+chunkExprs f (Chunks chunks final) =+ flip Chunks final <$> traverse (traverse f) chunks+{-# INLINABLE chunkExprs #-}++-- | Same as @Data.Text.splitOn@, except always returning a `NonEmpty` result+splitOn :: Text -> Text -> NonEmpty Text+splitOn needle haystack =+ case Data.Text.splitOn needle haystack of+ [] -> "" :| []+ t : ts -> t :| ts++-- | Split `Chunks` by lines+linesLiteral :: Chunks s a -> NonEmpty (Chunks s a)+linesLiteral (Chunks [] suffix) =+ fmap (Chunks []) (splitOn "\n" suffix)+linesLiteral (Chunks ((prefix, interpolation) : pairs₀) suffix₀) =+ foldr+ NonEmpty.cons+ (Chunks ((lastLine, interpolation) : pairs₁) suffix₁ :| chunks)+ (fmap (Chunks []) initLines)+ where+ splitLines = splitOn "\n" prefix++ initLines = NonEmpty.init splitLines+ lastLine = NonEmpty.last splitLines++ Chunks pairs₁ suffix₁ :| chunks = linesLiteral (Chunks pairs₀ suffix₀)++-- | Flatten several `Chunks` back into a single `Chunks` by inserting newlines+unlinesLiteral :: NonEmpty (Chunks s a) -> Chunks s a+unlinesLiteral chunks =+ Data.Foldable.fold (NonEmpty.intersperse "\n" chunks)++-- | Returns `True` if the `Chunks` represents a blank line+emptyLine :: Chunks s a -> Bool+emptyLine (Chunks [] "" ) = True+emptyLine (Chunks [] "\r") = True -- So that `\r\n` is treated as a blank line+emptyLine _ = False++-- | Return the leading whitespace for a `Chunks` literal+leadingSpaces :: Chunks s a -> Text+leadingSpaces chunks = Data.Text.takeWhile isSpace firstText+ where+ isSpace c = c == ' ' || c == '\t'++ firstText =+ case chunks of+ Chunks [] suffix -> suffix+ Chunks ((prefix, _) : _ ) _ -> prefix++{-| Compute the longest shared whitespace prefix for the purposes of stripping+ leading indentation+-}+longestSharedWhitespacePrefix :: NonEmpty (Chunks s a) -> Text+longestSharedWhitespacePrefix literals =+ case fmap leadingSpaces filteredLines of+ l : ls -> Data.Foldable.foldl' sharedPrefix l ls+ [] -> ""+ where+ sharedPrefix ab ac =+ case Data.Text.commonPrefixes ab ac of+ Just (a, _b, _c) -> a+ Nothing -> ""++ -- The standard specifies to filter out blank lines for all lines *except*+ -- for the last line+ filteredLines = newInit <> pure oldLast+ where+ oldInit = NonEmpty.init literals++ oldLast = NonEmpty.last literals++ newInit = filter (not . emptyLine) oldInit++-- | Drop the first @n@ characters for a `Chunks` literal+dropLiteral :: Int -> Chunks s a -> Chunks s a+dropLiteral n (Chunks [] suffix) =+ Chunks [] (Data.Text.drop n suffix)+dropLiteral n (Chunks ((prefix, interpolation) : rest) suffix) =+ Chunks ((Data.Text.drop n prefix, interpolation) : rest) suffix++{-| Convert a single-quoted `Chunks` literal to the equivalent double-quoted+ `Chunks` literal+-}+toDoubleQuoted :: Chunks Src a -> Chunks Src a+toDoubleQuoted literal =+ unlinesLiteral (fmap (dropLiteral indent) literals)+ where+ literals = linesLiteral literal++ longestSharedPrefix = longestSharedWhitespacePrefix literals++ indent = Data.Text.length longestSharedPrefix
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Chunks where++import Data.Kind (Type)++type Chunks :: Type -> Type -> Type+data Chunks s a
@@ -0,0 +1,29 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Const+ ( Const(..)+ ) where++import GHC.Generics (Generic)++{-| Constants for a pure type system++ The axioms are:++> ⊦ Type : Kind+> ⊦ Kind : Sort++ ... and the valid rule pairs are:++> ⊦ Type ↝ Type : Type -- Functions from terms to terms (ordinary functions)+> ⊦ Kind ↝ Type : Type -- Functions from types to terms (type-polymorphic functions)+> ⊦ Sort ↝ Type : Type -- Functions from kinds to terms+> ⊦ Kind ↝ Kind : Kind -- Functions from types to types (type-level functions)+> ⊦ Sort ↝ Kind : Sort -- Functions from kinds to types (kind-polymorphic functions)+> ⊦ Sort ↝ Sort : Sort -- Functions from kinds to kinds (kind-level functions)++ Note that Dhall does not support functions from terms to types and therefore+ Dhall is not a dependently typed language+-}+data Const = Type | Kind | Sort+ deriving (Bounded, Enum, Generic)
@@ -0,0 +1,267 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr+ ( Expr(..)+ ) where++import Data.ByteString (ByteString)+import Data.Kind (Type)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Sequence (Seq)+import Data.String (IsString (..))+import Data.Text (Text)+import Data.Traversable ()+import Dhall.Map (Map)+import {-# SOURCE #-} Dhall.Pretty.Internal (CharacterSet (..))+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import GHC.Generics (Generic)+import Numeric.Natural (Natural)++import qualified Data.Time as Time++{-| Syntax tree for expressions++ The @s@ type parameter is used to track the presence or absence of+ `Dhall.Src.Src` spans:++ * If @s = `Dhall.Src.Src`@ then the code may contains `Dhall.Src.Src` spans+ (either in a `Note` constructor or inline within another constructor, like+ `Let`)+ * If @s = `Data.Void.Void`@ then the code has no `Dhall.Src.Src` spans++ The @a@ type parameter is used to track the presence or absence of imports++ * If @a = `Dhall.Syntax.Import.Import`@ then the code may contain unresolved+ `Dhall.Syntax.Import.Import`s+ * If @a = `Data.Void.Void`@ then the code has no+ `Dhall.Syntax.Import.Import`s+-}+type Expr :: Type -> Type -> Type+data Expr s a+ -- | > Const c ~ c+ = Const Const+ -- | > Var (V x 0) ~ x+ -- > Var (V x n) ~ x@n+ | Var Var+ -- | > Lam _ (FunctionBinding _ "x" _ _ A) b ~ λ(x : A) -> b+ | Lam (Maybe CharacterSet) (FunctionBinding s a) (Expr s a)+ -- | > Pi _ "_" A B ~ A -> B+ -- > Pi _ x A B ~ ∀(x : A) -> B+ | Pi (Maybe CharacterSet) Text (Expr s a) (Expr s a)+ -- | > App f a ~ f a+ | App (Expr s a) (Expr s a)+ -- | > Let (Binding _ x _ Nothing _ r) e ~ let x = r in e+ -- > Let (Binding _ x _ (Just t ) _ r) e ~ let x : t = r in e+ --+ -- The difference between+ --+ -- > let x = a let y = b in e+ --+ -- and+ --+ -- > let x = a in let y = b in e+ --+ -- is only an additional 'Note' around @'Let' "y" …@ in the second+ -- example.+ --+ -- See `Dhall.Syntax.MultiLet.MultiLet` for a representation of let-blocks+ -- that mirrors the source code more closely.+ | Let (Binding s a) (Expr s a)+ -- | > Annot x t ~ x : t+ | Annot (Expr s a) (Expr s a)+ -- | > Bool ~ Bool+ | Bool+ -- | > BoolLit b ~ b+ | BoolLit Bool+ -- | > BoolAnd x y ~ x && y+ | BoolAnd (Expr s a) (Expr s a)+ -- | > BoolOr x y ~ x || y+ | BoolOr (Expr s a) (Expr s a)+ -- | > BoolEQ x y ~ x == y+ | BoolEQ (Expr s a) (Expr s a)+ -- | > BoolNE x y ~ x != y+ | BoolNE (Expr s a) (Expr s a)+ -- | > BoolIf x y z ~ if x then y else z+ | BoolIf (Expr s a) (Expr s a) (Expr s a)+ -- | > Bytes ~ Bytes+ | Bytes+ -- | > BytesLit "\x00\xFF" ~ 0x"00FF"+ | BytesLit ByteString+ -- | > Natural ~ Natural+ | Natural+ -- | > NaturalLit n ~ n+ | NaturalLit Natural+ -- | > NaturalFold ~ Natural/fold+ | NaturalFold+ -- | > NaturalBuild ~ Natural/build+ | NaturalBuild+ -- | > NaturalIsZero ~ Natural/isZero+ | NaturalIsZero+ -- | > NaturalEven ~ Natural/even+ | NaturalEven+ -- | > NaturalOdd ~ Natural/odd+ | NaturalOdd+ -- | > NaturalToInteger ~ Natural/toInteger+ | NaturalToInteger+ -- | > NaturalShow ~ Natural/show+ | NaturalShow+ -- | > NaturalSubtract ~ Natural/subtract+ | NaturalSubtract+ -- | > NaturalPlus x y ~ x + y+ | NaturalPlus (Expr s a) (Expr s a)+ -- | > NaturalTimes x y ~ x * y+ | NaturalTimes (Expr s a) (Expr s a)+ -- | > Integer ~ Integer+ | Integer+ -- | > IntegerLit n ~ ±n+ | IntegerLit Integer+ -- | > IntegerClamp ~ Integer/clamp+ | IntegerClamp+ -- | > IntegerNegate ~ Integer/negate+ | IntegerNegate+ -- | > IntegerShow ~ Integer/show+ | IntegerShow+ -- | > IntegerToDouble ~ Integer/toDouble+ | IntegerToDouble+ -- | > Double ~ Double+ | Double+ -- | > DoubleLit n ~ n+ | DoubleLit DhallDouble+ -- | > DoubleShow ~ Double/show+ | DoubleShow+ -- | > Text ~ Text+ | Text+ -- | > TextLit (Chunks [(t1, e1), (t2, e2)] t3) ~ "t1${e1}t2${e2}t3"+ | TextLit (Chunks s a)+ -- | > TextAppend x y ~ x ++ y+ | TextAppend (Expr s a) (Expr s a)+ -- | > TextReplace ~ Text/replace+ | TextReplace+ -- | > TextShow ~ Text/show+ | TextShow+ -- | > Date ~ Date+ | Date+ -- | > DateLiteral (fromGregorian _YYYY _MM _DD) ~ YYYY-MM-DD+ | DateLiteral Time.Day+ -- | > DateShow ~ Date/show+ | DateShow+ -- | > Time ~ Time+ | Time+ -- | > TimeLiteral (TimeOfDay hh mm ss) _ ~ hh:mm:ss+ | TimeLiteral+ Time.TimeOfDay+ Word+ -- ^ Precision+ -- | > TimeShow ~ Time/show+ | TimeShow+ -- | > TimeZone ~ TimeZone+ | TimeZone+ -- | > TimeZoneLiteral (TimeZone ( 60 * _HH + _MM) _ _) ~ +HH:MM+ -- | > TimeZoneLiteral (TimeZone (-60 * _HH + _MM) _ _) ~ -HH:MM+ | TimeZoneLiteral Time.TimeZone+ -- | > TimeZoneShow ~ TimeZone/Show+ | TimeZoneShow+ -- | > List ~ List+ | List+ -- | > ListLit (Just t ) [] ~ [] : t+ -- > ListLit Nothing [x, y, z] ~ [x, y, z]+ --+ -- Invariant: A non-empty list literal is always represented as+ -- @ListLit Nothing xs@.+ --+ -- When an annotated, non-empty list literal is parsed, it is represented+ -- as+ --+ -- > Annot (ListLit Nothing [x, y, z]) t ~ [x, y, z] : t++ -- Eventually we should have separate constructors for empty and non-empty+ -- list literals. For now it's easier to check the invariant in @infer@.+ -- See https://github.com/dhall-lang/dhall-haskell/issues/1359#issuecomment-537087234.+ | ListLit (Maybe (Expr s a)) (Seq (Expr s a))+ -- | > ListAppend x y ~ x # y+ | ListAppend (Expr s a) (Expr s a)+ -- | > ListBuild ~ List/build+ | ListBuild+ -- | > ListFold ~ List/fold+ | ListFold+ -- | > ListLength ~ List/length+ | ListLength+ -- | > ListHead ~ List/head+ | ListHead+ -- | > ListLast ~ List/last+ | ListLast+ -- | > ListIndexed ~ List/indexed+ | ListIndexed+ -- | > ListReverse ~ List/reverse+ | ListReverse+ -- | > Optional ~ Optional+ | Optional+ -- | > Some e ~ Some e+ | Some (Expr s a)+ -- | > None ~ None+ | None+ -- | > Record [ (k1, RecordField _ t1) ~ { k1 : t1, k2 : t1 }+ -- > , (k2, RecordField _ t2)+ -- > ]+ | Record (Map Text (RecordField s a))+ -- | > RecordLit [ (k1, RecordField _ v1) ~ { k1 = v1, k2 = v2 }+ -- > , (k2, RecordField _ v2)+ -- > ]+ | RecordLit (Map Text (RecordField s a))+ -- | > Union [(k1, Just t1), (k2, Nothing)] ~ < k1 : t1 | k2 >+ | Union (Map Text (Maybe (Expr s a)))+ -- | > Combine _ Nothing x y ~ x ∧ y+ --+ -- The first field is a `Just` when the `Combine` operator is introduced+ -- as a result of desugaring duplicate record fields:+ --+ -- > RecordLit [ ( k ~ { k = x, k = y }+ -- > , RecordField+ -- > _+ -- > (Combine (Just k) x y)+ -- > )]+ | Combine (Maybe CharacterSet) (Maybe Text) (Expr s a) (Expr s a)+ -- | > CombineTypes _ x y ~ x ⩓ y+ | CombineTypes (Maybe CharacterSet) (Expr s a) (Expr s a)+ -- | > Prefer _ _ x y ~ x ⫽ y+ | Prefer (Maybe CharacterSet) PreferAnnotation (Expr s a) (Expr s a)+ -- | > RecordCompletion x y ~ x::y+ | RecordCompletion (Expr s a) (Expr s a)+ -- | > Merge x y (Just t ) ~ merge x y : t+ -- > Merge x y Nothing ~ merge x y+ | Merge (Expr s a) (Expr s a) (Maybe (Expr s a))+ -- | > ToMap x (Just t) ~ toMap x : t+ -- > ToMap x Nothing ~ toMap x+ | ToMap (Expr s a) (Maybe (Expr s a))+ -- | > ShowConstructor x ~ showConstructor x+ | ShowConstructor (Expr s a)+ -- | > Field e (FieldSelection _ x _) ~ e.x+ | Field (Expr s a) (FieldSelection s)+ -- | > Project e (Left xs) ~ e.{ xs }+ -- > Project e (Right t) ~ e.(t)+ | Project (Expr s a) (Either [Text] (Expr s a))+ -- | > Assert e ~ assert : e+ | Assert (Expr s a)+ -- | > Equivalent _ x y ~ x ≡ y+ | Equivalent (Maybe CharacterSet) (Expr s a) (Expr s a)+ -- | > With x y e ~ x with y = e+ | With (Expr s a) (NonEmpty WithComponent) (Expr s a)+ -- | > Note s x ~ e+ | Note s (Expr s a)+ -- | > ImportAlt ~ e1 ? e2+ | ImportAlt (Expr s a) (Expr s a)+ -- | > Embed import ~ import+ | Embed a+ deriving (Generic)+-- NB: If you add a constructor to Expr, please also update the Arbitrary+-- instance in Dhall.Test.QuickCheck.++instance IsString (Expr s a) where+ fromString str = Var (fromString str)
@@ -0,0 +1,8 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Expr where++import Data.Kind (Type)++type Expr :: Type -> Type -> Type+data Expr s a
@@ -0,0 +1,53 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.FunctionBinding+ ( FunctionBinding(..)+ , makeFunctionBinding++ -- * Optics+ , functionBindingExprs+ ) where++import Data.Text (Text)+import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import GHC.Generics (Generic)++-- | Record the label of a function or a function-type expression+--+-- For example,+--+-- > λ({- A -} a {- B -} : {- C -} T) -> e+--+-- … will be instantiated as follows:+--+-- * @functionBindingSrc0@ corresponds to the @A@ comment+-- * @functionBindingVariable@ is @a@+-- * @functionBindingSrc1@ corresponds to the @B@ comment+-- * @functionBindingSrc2@ corresponds to the @C@ comment+-- * @functionBindingAnnotation@ is @T@+data FunctionBinding s a = FunctionBinding+ { functionBindingSrc0 :: Maybe s+ , functionBindingVariable :: Text+ , functionBindingSrc1 :: Maybe s+ , functionBindingSrc2 :: Maybe s+ , functionBindingAnnotation :: Expr s a+ } deriving Generic++-- | Smart constructor for 'FunctionBinding' with no src information+makeFunctionBinding :: Text -> Expr s a -> FunctionBinding s a+makeFunctionBinding l t = FunctionBinding Nothing l Nothing Nothing t++{-| Traverse over the immediate 'Expr' children in a 'FunctionBinding'.+-}+functionBindingExprs+ :: Applicative f+ => (Expr s a -> f (Expr s b))+ -> FunctionBinding s a -> f (FunctionBinding s b)+functionBindingExprs f (FunctionBinding s0 label s1 s2 type_) =+ FunctionBinding+ <$> pure s0+ <*> pure label+ <*> pure s1+ <*> pure s2+ <*> f type_+{-# INLINABLE functionBindingExprs #-}
@@ -0,0 +1,139 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Dhall.Syntax.Import+ ( Directory(..)+ , File(..)+ , FilePrefix(..)+ , Import(..)+ , ImportHashed(..)+ , ImportMode(..)+ , ImportType(..)+ , URL(..)+ , Scheme(..)+ ) where++import Data.Data (Data)+import Data.Text (Text)+import Dhall.Src (Src (..))+import Dhall.Syntax.Expr (Expr (..))+import Dhall.Syntax.Instances.Data ()+import Dhall.Syntax.Instances.Functor ()+import GHC.Generics (Generic)++import qualified Dhall.Crypto++{-| Internal representation of a directory that stores the path components in+ reverse order++ In other words, the directory @\/foo\/bar\/baz@ is encoded as+ @Directory { components = [ "baz", "bar", "foo" ] }@+-}+newtype Directory = Directory { components :: [Text] }+ deriving (Data, Generic)++{-| A `File` is a `directory` followed by one additional path component+ representing the `file` name+-}+data File = File+ { directory :: Directory+ , file :: Text+ } deriving (Data, Generic)++-- | The beginning of a file path which anchors subsequent path components+data FilePrefix+ = Absolute+ -- ^ Absolute path+ | Here+ -- ^ Path relative to @.@+ | Parent+ -- ^ Path relative to @..@+ | Home+ -- ^ Path relative to @~@+ deriving (Data, Generic)++-- | The URI scheme+data Scheme = HTTP | HTTPS+ deriving (Data, Generic)++-- | This type stores all of the components of a remote import+data URL = URL+ { scheme :: Scheme+ , authority :: Text+ , path :: File+ , query :: Maybe Text+ , headers :: Maybe (Expr Src Import)+ } deriving (Data, Generic)++-- | The type of import (i.e. local vs. remote vs. environment)+data ImportType+ = Local FilePrefix File+ -- ^ Local path+ | Remote URL+ -- ^ URL of remote resource and optional headers stored in an import+ | Env Text+ -- ^ Environment variable+ | Missing+ deriving (Data, Generic)++-- | How to interpret the import's contents (i.e. as Dhall code or raw text)+data ImportMode = Code | RawText | Location | RawBytes+ deriving (Data, Generic)++-- | A `ImportType` extended with an optional hash for semantic integrity checks+data ImportHashed = ImportHashed+ { hash :: Maybe Dhall.Crypto.SHA256Digest+ , importType :: ImportType+ } deriving (Data, Generic)++-- | Reference to an external resource+data Import = Import+ { importHashed :: ImportHashed+ , importMode :: ImportMode+ } deriving (Data, Generic)+++++instance Semigroup Directory where+ Directory components0 <> Directory components1 =+ Directory (components1 <> components0)++instance Semigroup File where+ File directory0 _ <> File directory1 file =+ File (directory0 <> directory1) file++instance Semigroup ImportType where+ Local prefix file0 <> Local Here file1 = Local prefix (file0 <> file1)++ Remote (URL { path = path0, ..}) <> Local Here path1 =+ Remote (URL { path = path0 <> path1, ..})++ Local prefix file0 <> Local Parent file1 =+ Local prefix (file0 <> parent <> file1)++ Remote (URL { path = path0, .. }) <> Local Parent path1 =+ Remote (URL { path = path0 <> parent <> path1, .. })++ import0 <> Remote (URL { headers = headers0, .. }) =+ Remote (URL { headers = headers1, .. })+ where+ importHashed0 = Import (ImportHashed Nothing import0) Code++ headers1 = fmap (fmap (importHashed0 <>)) headers0++ _ <> import1 =+ import1++instance Semigroup ImportHashed where+ ImportHashed _ importType0 <> ImportHashed hash importType1 =+ ImportHashed hash (importType0 <> importType1)++instance Semigroup Import where+ Import importHashed0 _ <> Import importHashed1 code =+ Import (importHashed0 <> importHashed1) code++parent :: File+parent = File { directory = Directory { components = [ ".." ] }, file = "" }
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Applicative () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Applicative (Expr s) where+ pure = Embed++ expression <*> k = case expression of+ Embed a -> a <$> k+ Let a b -> Let (adaptBinding a) (b <*> k)+ Note a b -> Note a (b <*> k)+ Record a -> Record $ adaptRecordField <$> a+ RecordLit a -> RecordLit $ adaptRecordField <$> a+ Lam cs a b -> Lam cs (adaptFunctionBinding a) (b <*> k)+ Field a b -> Field (a <*> k) b+ _ -> Lens.over unsafeSubExpressions (<*> k) expression+ where+ adaptRecordField (RecordField s0 e s1 s2) =+ RecordField s0 (e <*> k) s1 s2++ adaptBinding (Binding src0 c src1 d src2 e) =+ Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e <*> k)++ adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+ FunctionBinding src0 label src1 src2 (type_ <*> k)++ adaptBindingAnnotation (src3, f) = (src3, f <*> k)
@@ -0,0 +1,44 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Bifunctor () where++import Data.Bifunctor (Bifunctor (..))+import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Bifunctor Binding where+ first k (Binding src0 a src1 b src2 c) =+ Binding (fmap k src0) a (fmap k src1) (fmap adapt0 b) (fmap k src2) (first k c)+ where+ adapt0 (src3, d) = (fmap k src3, first k d)++ second = fmap++instance Bifunctor RecordField where+ first k (RecordField s0 value' s1 s2) =+ RecordField (k <$> s0) (first k value') (k <$> s1) (k <$> s2)+ second = fmap++instance Bifunctor FunctionBinding where+ first k (FunctionBinding src0 label src1 src2 type_) =+ FunctionBinding (k <$> src0) label (k <$> src1) (k <$> src2) (first k type_)++ second = fmap++instance Bifunctor Expr where+ first k (Note a b ) = Note (k a) (first k b)+ first _ (Embed a ) = Embed a+ first k (Let a b ) = Let (first k a) (first k b)+ first k (Record a ) = Record $ first k <$> a+ first k (RecordLit a) = RecordLit $ first k <$> a+ first k (Lam cs a b ) = Lam cs (first k a) (first k b)+ first k (Field a b ) = Field (first k a) (k <$> b)+ first k expression = Lens.over unsafeSubExpressions (first k) expression++ second = fmap
@@ -0,0 +1,28 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Data () where++import Data.Data (Data)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Data Const+deriving instance Data Var+deriving instance (Data a, Data s) => Data (Binding s a)+deriving instance Data DhallDouble+deriving instance (Data a, Data s) => Data (Chunks s a)+deriving instance Data PreferAnnotation+deriving instance (Data a, Data s) => Data (RecordField s a)+deriving instance (Data a, Data s) => Data (FunctionBinding s a)+deriving instance Data s => Data (FieldSelection s)+deriving instance Data WithComponent+deriving instance (Data a, Data s) => Data (Expr s a)
@@ -0,0 +1,67 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Eq () where++import Data.Bits (xor)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++-- $setup+-- >>> import Data.Void (Void)+-- >>> import Dhall.Binary () -- For the orphan instance for `Serialise (Expr Void Import)`++deriving instance Eq Const+deriving instance Eq Var+deriving instance (Eq s, Eq a) => Eq (Binding s a)+deriving instance (Eq s, Eq a) => Eq (Chunks s a)+deriving instance Eq PreferAnnotation+deriving instance (Eq s, Eq a) => Eq (RecordField s a)+deriving instance (Eq s, Eq a) => Eq (FunctionBinding s a)+deriving instance Eq s => Eq (FieldSelection s)+deriving instance Eq WithComponent+-- | This instance encodes what the Dhall standard calls an \"exact match\"+-- between two expressions.+--+-- Note that+--+-- >>> nan = DhallDouble (0/0)+-- >>> DoubleLit nan == DoubleLit nan+-- True+deriving instance (Eq s, Eq a) => Eq (Expr s a)+deriving instance Eq Directory+deriving instance Eq File+deriving instance Eq FilePrefix+deriving instance Eq Scheme+deriving instance Eq URL+deriving instance Eq ImportType+deriving instance Eq ImportMode+deriving instance Eq ImportHashed+deriving instance Eq Import++-- | This instance satisfies all the customary 'Eq' laws except substitutivity.+--+-- In particular:+--+-- >>> nan = DhallDouble (0/0)+-- >>> nan == nan+-- True+--+-- This instance is also consistent with with the binary encoding of Dhall @Double@s:+--+-- >>> toBytes n = Dhall.Binary.encodeExpression (DoubleLit n :: Expr Void Import)+--+-- prop> \a b -> (a == b) == (toBytes a == toBytes b)+instance Eq DhallDouble where+ DhallDouble a == DhallDouble b+ | isNaN a && isNaN b = True+ | isNegativeZero a `xor` isNegativeZero b = False+ | otherwise = a == b
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Foldable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Foldable (Binding s)+deriving instance Foldable (Chunks s)+deriving instance Foldable (RecordField s)+deriving instance Foldable (FunctionBinding s)+deriving instance Foldable FieldSelection+deriving instance Foldable (Expr s)
@@ -0,0 +1,37 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Functor () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import {-# SOURCE #-} Dhall.Syntax.Operations (unsafeSubExpressions)+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++import qualified Lens.Micro as Lens++deriving instance Functor (Binding s)+deriving instance Functor (Chunks s)+deriving instance Functor (RecordField s)+deriving instance Functor (FunctionBinding s)+deriving instance Functor FieldSelection++-- This instance is hand-written due to the fact that deriving+-- it does not give us an INLINABLE pragma. We annotate this fmap+-- implementation with this pragma below to allow GHC to, possibly,+-- inline the implementation for performance improvements.+instance Functor (Expr s) where+ fmap f (Embed a) = Embed (f a)+ fmap f (Let b e2) = Let (fmap f b) (fmap f e2)+ fmap f (Note s e1) = Note s (fmap f e1)+ fmap f (Record a) = Record $ fmap f <$> a+ fmap f (RecordLit a) = RecordLit $ fmap f <$> a+ fmap f (Lam cs fb e) = Lam cs (f <$> fb) (f <$> e)+ fmap f (Field a b) = Field (f <$> a) b+ fmap f expression = Lens.over unsafeSubExpressions (fmap f) expression+ {-# INLINABLE fmap #-}
@@ -0,0 +1,42 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Lift () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Language.Haskell.TH.Syntax (Lift)++#if !MIN_VERSION_template_haskell(2,21,0)+import qualified Data.Fixed as Fixed+#endif+import qualified Data.Time as Time++#if !MIN_VERSION_time(1,14,0)+deriving instance Lift Time.Day+#endif+deriving instance Lift Time.TimeOfDay+deriving instance Lift Time.TimeZone+#if !MIN_VERSION_template_haskell(2,21,0)+deriving instance Lift (Fixed.Fixed a)+#endif+deriving instance Lift Const+deriving instance Lift Var+deriving instance (Lift s, Lift a) => Lift (Binding s a)+deriving instance Lift DhallDouble+deriving instance (Lift s, Lift a) => Lift (Chunks s a)+deriving instance Lift PreferAnnotation+deriving instance (Lift s, Lift a) => Lift (RecordField s a)+deriving instance (Lift s, Lift a) => Lift (FunctionBinding s a)+deriving instance Lift s => Lift (FieldSelection s)+deriving instance Lift WithComponent+deriving instance (Lift s, Lift a) => Lift (Expr s a)
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Monad () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Applicative ()+import Dhall.Syntax.Operations+import Dhall.Syntax.RecordField++import qualified Lens.Micro as Lens++instance Monad (Expr s) where+ return = pure++ expression >>= k = case expression of+ Embed a -> k a+ Let a b -> Let (adaptBinding a) (b >>= k)+ Note a b -> Note a (b >>= k)+ Record a -> Record $ bindRecordKeyValues <$> a+ RecordLit a -> RecordLit $ bindRecordKeyValues <$> a+ Lam cs a b -> Lam cs (adaptFunctionBinding a) (b >>= k)+ Field a b -> Field (a >>= k) b+ _ -> Lens.over unsafeSubExpressions (>>= k) expression+ where+ bindRecordKeyValues (RecordField s0 e s1 s2) =+ RecordField s0 (e >>= k) s1 s2++ adaptBinding (Binding src0 c src1 d src2 e) =+ Binding src0 c src1 (fmap adaptBindingAnnotation d) src2 (e >>= k)++ adaptFunctionBinding (FunctionBinding src0 label src1 src2 type_) =+ FunctionBinding src0 label src1 src2 (type_ >>= k)++ adaptBindingAnnotation (src3, f) = (src3, f >>= k)
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.NFData () where++import Control.DeepSeq (NFData)+import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++instance NFData Const+instance NFData Var+instance (NFData s, NFData a) => NFData (Binding s a)+instance NFData DhallDouble+instance (NFData s, NFData a) => NFData (Chunks s a)+instance NFData PreferAnnotation+instance (NFData s, NFData a) => NFData (RecordField s a)+instance (NFData s, NFData a) => NFData (FunctionBinding s a)+instance NFData s => NFData (FieldSelection s)+instance NFData WithComponent+instance (NFData s, NFData a) => NFData (Expr s a)+instance NFData Directory+instance NFData File+instance NFData FilePrefix+instance NFData Scheme+instance NFData URL+instance NFData ImportType+instance NFData ImportMode+instance NFData ImportHashed+instance NFData Import
@@ -0,0 +1,45 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Ord () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.Instances.Eq ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Ord Const+deriving instance Ord Var+deriving instance (Ord s, Ord a) => Ord (Binding s a)+deriving instance (Ord s, Ord a) => Ord (Chunks s a)+deriving instance Ord PreferAnnotation+deriving instance (Ord s, Ord a) => Ord (RecordField s a)+deriving instance (Ord s, Ord a) => Ord (FunctionBinding s a)+deriving instance Ord s => Ord (FieldSelection s)+deriving instance Ord WithComponent+-- | Note that this 'Ord' instance inherits `DhallDouble`'s defects.+deriving instance (Ord s, Ord a) => Ord (Expr s a)+deriving instance Ord Directory+deriving instance Ord File+deriving instance Ord FilePrefix+deriving instance Ord Scheme+deriving instance Ord URL+deriving instance Ord ImportType+deriving instance Ord ImportMode+deriving instance Ord ImportHashed+deriving instance Ord Import++-- | This instance relies on the 'Eq' instance for 'DhallDouble' but cannot+-- satisfy the customary 'Ord' laws when @NaN@ is involved.+instance Ord DhallDouble where+ compare a@(DhallDouble a') b@(DhallDouble b') =+ if a == b+ then EQ+ else compare a' b'
@@ -0,0 +1,135 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty+ ( pathCharacter+ ) where++import Data.Text (Text)+import {-# SOURCE #-} Dhall.Pretty.Internal+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.Import+import Dhall.Syntax.Var+import Prettyprinter (Doc, Pretty)++import qualified Data.Text+import qualified Network.URI as URI+import qualified Prettyprinter as Pretty++instance Pretty Const where+ pretty = Pretty.unAnnotate . prettyConst++instance Pretty Var where+ pretty = Pretty.unAnnotate . prettyVar++-- | Generates a syntactically valid Dhall program+instance Pretty a => Pretty (Expr s a) where+ pretty = Pretty.unAnnotate . prettyExpr++instance Pretty Directory where+ pretty (Directory {..}) = foldMap prettyPathComponent (reverse components)++prettyPathComponent :: Text -> Doc ann+prettyPathComponent text+ | Data.Text.all pathCharacter text =+ "/" <> Pretty.pretty text+ | otherwise =+ "/\"" <> Pretty.pretty text <> "\""++instance Pretty File where+ pretty (File {..}) =+ Pretty.pretty directory+ <> prettyPathComponent file++instance Pretty FilePrefix where+ pretty Absolute = ""+ pretty Here = "."+ pretty Parent = ".."+ pretty Home = "~"++instance Pretty URL where+ pretty (URL {..}) =+ schemeDoc+ <> "://"+ <> Pretty.pretty authority+ <> pathDoc+ <> queryDoc+ <> foldMap prettyHeaders headers+ where+ prettyHeaders h =+ " using (" <> Pretty.unAnnotate (Pretty.pretty h) <> ")"++ File {..} = path++ Directory {..} = directory++ pathDoc =+ foldMap prettyURIComponent (reverse components)+ <> prettyURIComponent file++ schemeDoc = case scheme of+ HTTP -> "http"+ HTTPS -> "https"++ queryDoc = case query of+ Nothing -> ""+ Just q -> "?" <> Pretty.pretty q++prettyURIComponent :: Text -> Doc ann+prettyURIComponent text =+ Pretty.pretty $ URI.normalizeCase $ URI.normalizeEscape $ "/" <> Data.Text.unpack text++instance Pretty ImportType where+ pretty (Local prefix file) =+ Pretty.pretty prefix <> Pretty.pretty file++ pretty (Remote url) = Pretty.pretty url++ pretty (Env env) = "env:" <> prettyEnvironmentVariable env++ pretty Missing = "missing"++instance Pretty ImportHashed where+ pretty (ImportHashed Nothing p) =+ Pretty.pretty p+ pretty (ImportHashed (Just h) p) =+ Pretty.group (Pretty.flatAlt long short)+ where+ long =+ Pretty.align+ ( Pretty.pretty p <> Pretty.hardline+ <> " sha256:" <> Pretty.pretty (show h)+ )++ short = Pretty.pretty p <> " sha256:" <> Pretty.pretty (show h)++instance Pretty Import where+ pretty (Import {..}) = Pretty.pretty importHashed <> Pretty.pretty suffix+ where+ suffix :: Text+ suffix = case importMode of+ RawText -> " as Text"+ Location -> " as Location"+ Code -> ""+ RawBytes -> " as Bytes"++{-| Returns `True` if the given `Char` is valid within an unquoted path+ component++ This is exported for reuse within the @"Dhall.Parser.Token"@ module+-}+pathCharacter :: Char -> Bool+pathCharacter c =+ '\x21' == c+ || ('\x24' <= c && c <= '\x27')+ || ('\x2A' <= c && c <= '\x2B')+ || ('\x2D' <= c && c <= '\x2E')+ || ('\x30' <= c && c <= '\x3B')+ || c == '\x3D'+ || ('\x40' <= c && c <= '\x5A')+ || ('\x5E' <= c && c <= '\x7A')+ || c == '\x7C'+ || c == '\x7E'
@@ -0,0 +1,8 @@+{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Pretty where++import Dhall.Syntax.Expr (Expr)+import Prettyprinter (Pretty)++instance Pretty a => Pretty (Expr s a)
@@ -0,0 +1,36 @@+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Show () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Const+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Import+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types+import Dhall.Syntax.Var++deriving instance Show Const+deriving instance Show Var+deriving instance (Show s, Show a) => Show (Binding s a)+deriving instance Show DhallDouble+deriving instance (Show s, Show a) => Show (Chunks s a)+deriving instance Show PreferAnnotation+deriving instance (Show s, Show a) => Show (RecordField s a)+deriving instance (Show s, Show a) => Show (FunctionBinding s a)+deriving instance Show s => Show (FieldSelection s)+deriving instance Show WithComponent+deriving instance (Show s, Show a) => Show (Expr s a)+deriving instance Show Directory+deriving instance Show File+deriving instance Show FilePrefix+deriving instance Show Scheme+deriving instance Show URL+deriving instance Show ImportType+deriving instance Show ImportMode+deriving instance Show ImportHashed+deriving instance Show Import
@@ -0,0 +1,22 @@+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE StandaloneDeriving #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Dhall.Syntax.Instances.Traversable () where++import Dhall.Syntax.Binding+import Dhall.Syntax.Chunks+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.Instances.Foldable ()+import Dhall.Syntax.Instances.Functor ()+import Dhall.Syntax.RecordField+import Dhall.Syntax.Types++deriving instance Traversable (Binding s)+deriving instance Traversable (Chunks s)+deriving instance Traversable (RecordField s)+deriving instance Traversable (FunctionBinding s)+deriving instance Traversable FieldSelection+deriving instance Traversable (Expr s)
@@ -0,0 +1,62 @@+{-# LANGUAGE LambdaCase #-}++{- | Instead of converting explicitly between 'Expr's and 'MultiLet', it might+be nicer to use a pattern synonym:++> pattern MultiLet' :: NonEmpty (Binding s a) -> Expr s a -> Expr s a+> pattern MultiLet' as b <- (multiLetFromExpr -> Just (MultiLet as b)) where+> MultiLet' as b = wrapInLets as b+>+> multiLetFromExpr :: Expr s a -> Maybe (MultiLet s a)+> multiLetFromExpr = \case+> Let x mA a b -> Just (multiLet x mA a b)+> _ -> Nothing++This works in principle, but GHC as of v8.8.1 doesn't handle it well:+https://gitlab.haskell.org/ghc/ghc/issues/17096++This should be fixed by GHC-8.10, so it might be worth revisiting then.+-}++module Dhall.Syntax.MultiLet+ ( MultiLet(..)+ , multiLet+ , wrapInLets+ ) where++import Data.List.NonEmpty (NonEmpty (..))+import Dhall.Syntax.Binding (Binding)+import Dhall.Syntax.Expr (Expr (..))++import qualified Data.List.NonEmpty as NonEmpty++{-| Generate a 'MultiLet' from the contents of a 'Let'.++ In the resulting @'MultiLet' bs e@, @e@ is guaranteed not to be a 'Let',+ but it might be a @('Note' … ('Let' …))@.++ Given parser output, 'multiLet' consolidates @let@s that formed a+ let-block in the original source.+-}+multiLet :: Binding s a -> Expr s a -> MultiLet s a+multiLet b0 = \case+ Let b1 e1 ->+ let MultiLet bs e = multiLet b1 e1+ in MultiLet (NonEmpty.cons b0 bs) e+ e -> MultiLet (b0 :| []) e++{-| Wrap let-'Binding's around an 'Expr'.++'wrapInLets' can be understood as an inverse for 'multiLet':++> let MultiLet bs e1 = multiLet b e0+>+> wrapInLets bs e1 == Let b e0+-}+wrapInLets :: Foldable f => f (Binding s a) -> Expr s a -> Expr s a+wrapInLets bs e = foldr Let e bs++{-| This type represents 1 or more nested `Let` bindings that have been+ coalesced together for ease of manipulation+-}+data MultiLet s a = MultiLet (NonEmpty (Binding s a)) (Expr s a)
@@ -0,0 +1,394 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++module Dhall.Syntax.Operations+ ( -- * Optics+ subExpressions+ , subExpressionsWith+ , unsafeSubExpressions++ -- * Handling 'Note's+ , denote+ , renote+ , shallowDenote++ -- * Reserved identifiers+ , reservedIdentifiers+ , reservedKeywords++ -- * Utilities+ , internalError+ -- `shift` should really be in `Dhall.Normalize`, but it's here to avoid a+ -- module cycle+ , shift+ ) where++import Data.HashSet (HashSet)+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Syntax.Binding (Binding (..), bindingExprs)+import Dhall.Syntax.Chunks (chunkExprs)+import Dhall.Syntax.Expr+import Dhall.Syntax.FunctionBinding+import Dhall.Syntax.RecordField (RecordField (..), recordFieldExprs)+import Dhall.Syntax.Types+import Dhall.Syntax.Var+import Unsafe.Coerce (unsafeCoerce)++import qualified Data.HashSet+import qualified Data.Text+import qualified Lens.Micro as Lens+++-- | A traversal over the immediate sub-expressions of an expression.+subExpressions+ :: Applicative f => (Expr s a -> f (Expr s a)) -> Expr s a -> f (Expr s a)+subExpressions = subExpressionsWith (pure . Embed)+{-# INLINABLE subExpressions #-}++{-| A traversal over the immediate sub-expressions of an expression which+ allows mapping embedded values+-}+subExpressionsWith+ :: Applicative f => (a -> f (Expr s b)) -> (Expr s a -> f (Expr s b)) -> Expr s a -> f (Expr s b)+subExpressionsWith h _ (Embed a) = h a+subExpressionsWith _ f (Note a b) = Note a <$> f b+subExpressionsWith _ f (Let a b) = Let <$> bindingExprs f a <*> f b+subExpressionsWith _ f (Record a) = Record <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (RecordLit a) = RecordLit <$> traverse (recordFieldExprs f) a+subExpressionsWith _ f (Lam cs fb e) = Lam cs <$> functionBindingExprs f fb <*> f e+subExpressionsWith _ f (Field a b) = Field <$> f a <*> pure b+subExpressionsWith _ f expression = unsafeSubExpressions f expression+{-# INLINABLE subExpressionsWith #-}++{-| An internal utility used to implement transformations that require changing+ one of the type variables of the `Expr` type++ This utility only works because the implementation is partial, not+ handling the `Let`, `Note`, or `Embed` cases, which need to be handled by+ the caller.+-}+unsafeSubExpressions+ :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)+unsafeSubExpressions _ (Const c) = pure (Const c)+unsafeSubExpressions _ (Var v) = pure (Var v)+unsafeSubExpressions f (Pi cs a b c) = Pi cs a <$> f b <*> f c+unsafeSubExpressions f (App a b) = App <$> f a <*> f b+unsafeSubExpressions f (Annot a b) = Annot <$> f a <*> f b+unsafeSubExpressions _ Bool = pure Bool+unsafeSubExpressions _ (BoolLit b) = pure (BoolLit b)+unsafeSubExpressions f (BoolAnd a b) = BoolAnd <$> f a <*> f b+unsafeSubExpressions f (BoolOr a b) = BoolOr <$> f a <*> f b+unsafeSubExpressions f (BoolEQ a b) = BoolEQ <$> f a <*> f b+unsafeSubExpressions f (BoolNE a b) = BoolNE <$> f a <*> f b+unsafeSubExpressions f (BoolIf a b c) = BoolIf <$> f a <*> f b <*> f c+unsafeSubExpressions _ Bytes = pure Bytes+unsafeSubExpressions _ (BytesLit a) = pure (BytesLit a)+unsafeSubExpressions _ Natural = pure Natural+unsafeSubExpressions _ (NaturalLit n) = pure (NaturalLit n)+unsafeSubExpressions _ NaturalFold = pure NaturalFold+unsafeSubExpressions _ NaturalBuild = pure NaturalBuild+unsafeSubExpressions _ NaturalIsZero = pure NaturalIsZero+unsafeSubExpressions _ NaturalEven = pure NaturalEven+unsafeSubExpressions _ NaturalOdd = pure NaturalOdd+unsafeSubExpressions _ NaturalToInteger = pure NaturalToInteger+unsafeSubExpressions _ NaturalShow = pure NaturalShow+unsafeSubExpressions _ NaturalSubtract = pure NaturalSubtract+unsafeSubExpressions f (NaturalPlus a b) = NaturalPlus <$> f a <*> f b+unsafeSubExpressions f (NaturalTimes a b) = NaturalTimes <$> f a <*> f b+unsafeSubExpressions _ Integer = pure Integer+unsafeSubExpressions _ (IntegerLit n) = pure (IntegerLit n)+unsafeSubExpressions _ IntegerClamp = pure IntegerClamp+unsafeSubExpressions _ IntegerNegate = pure IntegerNegate+unsafeSubExpressions _ IntegerShow = pure IntegerShow+unsafeSubExpressions _ IntegerToDouble = pure IntegerToDouble+unsafeSubExpressions _ Double = pure Double+unsafeSubExpressions _ (DoubleLit n) = pure (DoubleLit n)+unsafeSubExpressions _ DoubleShow = pure DoubleShow+unsafeSubExpressions _ Text = pure Text+unsafeSubExpressions f (TextLit chunks) = TextLit <$> chunkExprs f chunks+unsafeSubExpressions f (TextAppend a b) = TextAppend <$> f a <*> f b+unsafeSubExpressions _ TextReplace = pure TextReplace+unsafeSubExpressions _ TextShow = pure TextShow+unsafeSubExpressions _ Date = pure Date+unsafeSubExpressions _ (DateLiteral a) = pure (DateLiteral a)+unsafeSubExpressions _ DateShow = pure DateShow+unsafeSubExpressions _ Time = pure Time+unsafeSubExpressions _ (TimeLiteral a b) = pure (TimeLiteral a b)+unsafeSubExpressions _ TimeShow = pure TimeShow+unsafeSubExpressions _ TimeZone = pure TimeZone+unsafeSubExpressions _ (TimeZoneLiteral a) = pure (TimeZoneLiteral a)+unsafeSubExpressions _ TimeZoneShow = pure TimeZoneShow+unsafeSubExpressions _ List = pure List+unsafeSubExpressions f (ListLit a b) = ListLit <$> traverse f a <*> traverse f b+unsafeSubExpressions f (ListAppend a b) = ListAppend <$> f a <*> f b+unsafeSubExpressions _ ListBuild = pure ListBuild+unsafeSubExpressions _ ListFold = pure ListFold+unsafeSubExpressions _ ListLength = pure ListLength+unsafeSubExpressions _ ListHead = pure ListHead+unsafeSubExpressions _ ListLast = pure ListLast+unsafeSubExpressions _ ListIndexed = pure ListIndexed+unsafeSubExpressions _ ListReverse = pure ListReverse+unsafeSubExpressions _ Optional = pure Optional+unsafeSubExpressions f (Some a) = Some <$> f a+unsafeSubExpressions _ None = pure None+unsafeSubExpressions f (Union a) = Union <$> traverse (traverse f) a+unsafeSubExpressions f (Combine cs a b c) = Combine cs a <$> f b <*> f c+unsafeSubExpressions f (CombineTypes cs a b) = CombineTypes cs <$> f a <*> f b+unsafeSubExpressions f (Prefer cs a b c) = Prefer cs <$> pure a <*> f b <*> f c+unsafeSubExpressions f (RecordCompletion a b) = RecordCompletion <$> f a <*> f b+unsafeSubExpressions f (Merge a b t) = Merge <$> f a <*> f b <*> traverse f t+unsafeSubExpressions f (ToMap a t) = ToMap <$> f a <*> traverse f t+unsafeSubExpressions f (ShowConstructor a) = ShowConstructor <$> f a+unsafeSubExpressions f (Project a b) = Project <$> f a <*> traverse f b+unsafeSubExpressions f (Assert a) = Assert <$> f a+unsafeSubExpressions f (Equivalent cs a b) = Equivalent cs <$> f a <*> f b+unsafeSubExpressions f (With a b c) = With <$> f a <*> pure b <*> f c+unsafeSubExpressions f (ImportAlt l r) = ImportAlt <$> f l <*> f r+unsafeSubExpressions _ (Let {}) = unhandledConstructor "Let"+unsafeSubExpressions _ (Note {}) = unhandledConstructor "Note"+unsafeSubExpressions _ (Embed {}) = unhandledConstructor "Embed"+unsafeSubExpressions _ (Record {}) = unhandledConstructor "Record"+unsafeSubExpressions _ (RecordLit {}) = unhandledConstructor "RecordLit"+unsafeSubExpressions _ (Lam {}) = unhandledConstructor "Lam"+unsafeSubExpressions _ (Field {}) = unhandledConstructor "Field"+{-# INLINABLE unsafeSubExpressions #-}++unhandledConstructor :: Text -> a+unhandledConstructor constructor =+ internalError+ ( "Dhall.Syntax.unsafeSubExpressions: Unhandled "+ <> constructor+ <> " construtor"+ )++-- | Remove all `Note` constructors from an `Expr` (i.e. de-`Note`)+--+-- This also remove CharacterSet annotations.+denote :: Expr s a -> Expr t a+denote = \case+ Note _ b -> denote b+ Let a b -> Let (denoteBinding a) (denote b)+ Embed a -> Embed a+ Combine _ _ b c -> Combine Nothing Nothing (denote b) (denote c)+ CombineTypes _ b c -> CombineTypes Nothing (denote b) (denote c)+ Prefer _ a b c -> Lens.over unsafeSubExpressions denote $ Prefer Nothing a b c+ Record a -> Record $ denoteRecordField <$> a+ RecordLit a -> RecordLit $ denoteRecordField <$> a+ Lam _ a b -> Lam Nothing (denoteFunctionBinding a) (denote b)+ Pi _ t a b -> Pi Nothing t (denote a) (denote b)+ Field a (FieldSelection _ b _) -> Field (denote a) (FieldSelection Nothing b Nothing)+ Equivalent _ a b -> Equivalent Nothing (denote a) (denote b)+ expression -> Lens.over unsafeSubExpressions denote expression+ where+ denoteRecordField (RecordField _ e _ _) = RecordField Nothing (denote e) Nothing Nothing++ denoteBinding (Binding _ c _ d _ e) =+ Binding Nothing c Nothing (fmap denoteBindingAnnotation d) Nothing (denote e)++ denoteBindingAnnotation (_, f) = (Nothing, denote f)++ denoteFunctionBinding (FunctionBinding _ l _ _ t) =+ FunctionBinding Nothing l Nothing Nothing (denote t)++-- | The \"opposite\" of `denote`, like @first absurd@ but faster+renote :: Expr Void a -> Expr s a+renote = unsafeCoerce+{-# INLINE renote #-}++{-| Remove any outermost `Note` constructors++ This is typically used when you want to get the outermost non-`Note`+ constructor without removing internal `Note` constructors+-}+shallowDenote :: Expr s a -> Expr s a+shallowDenote (Note _ e) = shallowDenote e+shallowDenote e = e++-- | The set of reserved keywords according to the @keyword@ rule in the grammar+reservedKeywords :: HashSet Text+reservedKeywords =+ Data.HashSet.fromList+ [ "if"+ , "then"+ , "else"+ , "let"+ , "in"+ , "using"+ , "missing"+ , "as"+ , "Infinity"+ , "NaN"+ , "merge"+ , "Some"+ , "toMap"+ , "assert"+ , "forall"+ , "with"+ ]++-- | The set of reserved identifiers for the Dhall language+-- | Contains also all keywords from "reservedKeywords"+reservedIdentifiers :: HashSet Text+reservedIdentifiers = reservedKeywords <>+ Data.HashSet.fromList+ [ -- Builtins according to the `builtin` rule in the grammar+ "Natural/fold"+ , "Natural/build"+ , "Natural/isZero"+ , "Natural/even"+ , "Natural/odd"+ , "Natural/toInteger"+ , "Natural/show"+ , "Natural/subtract"+ , "Integer"+ , "Integer/clamp"+ , "Integer/negate"+ , "Integer/show"+ , "Integer/toDouble"+ , "Integer/show"+ , "Natural/subtract"+ , "Double/show"+ , "List/build"+ , "List/fold"+ , "List/length"+ , "List/head"+ , "List/last"+ , "List/indexed"+ , "List/reverse"+ , "Text/replace"+ , "Text/show"+ , "Date/show"+ , "Time/show"+ , "TimeZone/show"+ , "Bool"+ , "Bytes"+ , "True"+ , "False"+ , "Optional"+ , "None"+ , "Natural"+ , "Integer"+ , "Double"+ , "Text"+ , "Date"+ , "Time"+ , "TimeZone"+ , "List"+ , "Type"+ , "Kind"+ , "Sort"+ ]++{-| `shift` is used by both normalization and type-checking to avoid variable+ capture by shifting variable indices++ For example, suppose that you were to normalize the following expression:++> λ(a : Type) → λ(x : a) → (λ(y : a) → λ(x : a) → y) x++ If you were to substitute @y@ with @x@ without shifting any variable+ indices, then you would get the following incorrect result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x -- Incorrect normalized form++ In order to substitute @x@ in place of @y@ we need to `shift` @x@ by @1@ in+ order to avoid being misinterpreted as the @x@ bound by the innermost+ lambda. If we perform that `shift` then we get the correct result:++> λ(a : Type) → λ(x : a) → λ(x : a) → x@1++ As a more worked example, suppose that you were to normalize the following+ expression:++> λ(a : Type)+> → λ(f : a → a → a)+> → λ(x : a)+> → λ(x : a)+> → (λ(x : a) → f x x@1) x@1++ The correct normalized result would be:++> λ(a : Type)+> → λ(f : a → a → a)+> → λ(x : a)+> → λ(x : a)+> → f x@1 x++ The above example illustrates how we need to both increase and decrease+ variable indices as part of substitution:++ * We need to increase the index of the outer @x\@1@ to @x\@2@ before we+ substitute it into the body of the innermost lambda expression in order+ to avoid variable capture. This substitution changes the body of the+ lambda expression to @(f x\@2 x\@1)@++ * We then remove the innermost lambda and therefore decrease the indices of+ both @x@s in @(f x\@2 x\@1)@ to @(f x\@1 x)@ in order to reflect that one+ less @x@ variable is now bound within that scope++ Formally, @(shift d (V x n) e)@ modifies the expression @e@ by adding @d@ to+ the indices of all variables named @x@ whose indices are greater than+ @(n + m)@, where @m@ is the number of bound variables of the same name+ within that scope++ In practice, @d@ is always @1@ or @-1@ because we either:++ * increment variables by @1@ to avoid variable capture during substitution+ * decrement variables by @1@ when deleting lambdas after substitution++ @n@ starts off at @0@ when substitution begins and increments every time we+ descend into a lambda or let expression that binds a variable of the same+ name in order to avoid shifting the bound variables by mistake.+-}+shift :: Int -> Var -> Expr s a -> Expr s a+shift d (V x n) (Var (V x' n')) = Var (V x' n'')+ where+ n'' = if x == x' && n <= n' then n' + d else n'+shift d (V x n) (Lam cs (FunctionBinding src0 x' src1 src2 _A) b) =+ Lam cs (FunctionBinding src0 x' src1 src2 _A') b'+ where+ _A' = shift d (V x n ) _A+ b' = shift d (V x n') b+ where+ n' = if x == x' then n + 1 else n+shift d (V x n) (Pi cs x' _A _B) = Pi cs x' _A' _B'+ where+ _A' = shift d (V x n ) _A+ _B' = shift d (V x n') _B+ where+ n' = if x == x' then n + 1 else n+shift d (V x n) (Let (Binding src0 f src1 mt src2 r) e) =+ Let (Binding src0 f src1 mt' src2 r') e'+ where+ e' = shift d (V x n') e+ where+ n' = if x == f then n + 1 else n++ mt' = fmap (fmap (shift d (V x n))) mt+ r' = shift d (V x n) r+shift d v expression = Lens.over subExpressions (shift d v) expression++_ERROR :: String+_ERROR = "\ESC[1;31mError\ESC[0m"++{-| Utility function used to throw internal errors that should never happen+ (in theory) but that are not enforced by the type system+-}+internalError :: Data.Text.Text -> forall b . b+internalError text = error (unlines+ [ _ERROR <> ": Compiler bug "+ , " "+ , "Explanation: This error message means that there is a bug in the Dhall compiler."+ , "You didn't do anything wrong, but if you would like to see this problem fixed "+ , "then you should report the bug at: "+ , " "+ , "https://github.com/dhall-lang/dhall-haskell/issues "+ , " "+ , "Please include the following text in your bug report: "+ , " "+ , "``` "+ , Data.Text.unpack text <> " "+ , "``` "+ ] )
@@ -0,0 +1,5 @@+module Dhall.Syntax.Operations where++import Dhall.Syntax.Expr (Expr)++unsafeSubExpressions :: Applicative f => (Expr s a -> f (Expr t b)) -> Expr s a -> f (Expr t b)
@@ -0,0 +1,93 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.RecordField+ ( RecordField(..)+ , makeRecordField++ -- * Optics+ , recordFieldExprs+ ) where++import {-# SOURCE #-} Dhall.Syntax.Expr (Expr)+import GHC.Generics (Generic)++-- | Record the field of a record-type and record-literal expression.+-- The reason why we use the same ADT for both of them is because they store+-- the same information.+--+-- For example,+--+-- > { {- A -} x {- B -} : {- C -} T }+--+-- ... or+--+-- > { {- A -} x {- B -} = {- C -} T }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ is @"T"@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ corresponds to the @C@ comment.+--+-- Although the @A@ comment isn't annotating the @"T"@ Record Field,+-- this is the best place to keep these comments.+--+-- Note that @recordFieldSrc2@ is always 'Nothing' when the 'RecordField' is for+-- a punned entry, because there is no @=@ sign. For example,+--+-- > { {- A -} x {- B -} }+--+-- will be instantiated as follows:+--+-- * @recordFieldSrc0@ corresponds to the @A@ comment.+-- * @recordFieldValue@ corresponds to @(Var "x")@+-- * @recordFieldSrc1@ corresponds to the @B@ comment.+-- * @recordFieldSrc2@ will be 'Nothing'+--+-- The labels involved in a record using dot-syntax like in this example:+--+-- > { {- A -} a {- B -} . {- C -} b {- D -} . {- E -} c {- F -} = {- G -} e }+--+-- will be instantiated as follows:+--+-- * For both the @a@ and @b@ field, @recordfieldSrc2@ is 'Nothing'+-- * For the @a@ field:+-- * @recordFieldSrc0@ corresponds to the @A@ comment+-- * @recordFieldSrc1@ corresponds to the @B@ comment+-- * For the @b@ field:+-- * @recordFieldSrc0@ corresponds to the @C@ comment+-- * @recordFieldSrc1@ corresponds to the @D@ comment+-- * For the @c@ field:+-- * @recordFieldSrc0@ corresponds to the @E@ comment+-- * @recordFieldSrc1@ corresponds to the @F@ comment+-- * @recordFieldSrc2@ corresponds to the @G@ comment+--+-- That is, for every label except the last one the semantics of+-- @recordFieldSrc0@ and @recordFieldSrc1@ are the same from a regular record+-- label but @recordFieldSrc2@ is always 'Nothing'. For the last keyword, all+-- srcs are 'Just'+data RecordField s a = RecordField+ { recordFieldSrc0 :: Maybe s+ , recordFieldValue :: Expr s a+ , recordFieldSrc1 :: Maybe s+ , recordFieldSrc2 :: Maybe s+ } deriving Generic++-- | Construct a 'RecordField' with no src information+makeRecordField :: Expr s a -> RecordField s a+makeRecordField e = RecordField Nothing e Nothing Nothing++{-| Traverse over the immediate 'Expr' children in a 'RecordField'.+-}+recordFieldExprs+ :: Applicative f+ => (Expr s a -> f (Expr s b))+ -> RecordField s a -> f (RecordField s b)+recordFieldExprs f (RecordField s0 e s1 s2) =+ RecordField+ <$> pure s0+ <*> f e+ <*> pure s1+ <*> pure s2+{-# INLINABLE recordFieldExprs #-}
@@ -0,0 +1,55 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Types+ ( DhallDouble(..)+ , PreferAnnotation(..)+ , FieldSelection(..)+ , makeFieldSelection+ , WithComponent(..)+ ) where++import Data.Text (Text)+import GHC.Generics (Generic)++-- | This wrapper around 'Prelude.Double' exists for its 'Eq' instance which is+-- defined via the binary encoding of Dhall @Double@s.+newtype DhallDouble = DhallDouble { getDhallDouble :: Double }+ deriving Generic++-- | Used to record the origin of a @//@ operator (i.e. from source code or a+-- product of desugaring)+data PreferAnnotation+ = PreferFromSource+ | PreferFromCompletion+ deriving Generic++-- | Record the field on a selector-expression+--+-- For example,+--+-- > e . {- A -} x {- B -}+--+-- … will be instantiated as follows:+--+-- * @fieldSelectionSrc0@ corresponds to the @A@ comment+-- * @fieldSelectionLabel@ corresponds to @x@+-- * @fieldSelectionSrc1@ corresponds to the @B@ comment+--+-- Given our limitation that not all expressions recover their whitespaces, the+-- purpose of @fieldSelectionSrc1@ is to save the 'Text.Megaparsec.SourcePos'+-- where the @fieldSelectionLabel@ ends, but we /still/ use a+-- 'Maybe Dhall.Src.Src' (@s = 'Dhall.Src.Src'@) to be consistent with similar+-- data types such as 'Dhall.Syntax.Binding.Binding', for example.+data FieldSelection s = FieldSelection+ { fieldSelectionSrc0 :: Maybe s+ , fieldSelectionLabel :: !Text+ , fieldSelectionSrc1 :: Maybe s+ } deriving Generic++-- | Smart constructor for 'FieldSelection' with no src information+makeFieldSelection :: Text -> FieldSelection s+makeFieldSelection t = FieldSelection Nothing t Nothing++-- | A path component for a @with@ expression+data WithComponent = WithLabel Text | WithQuestion+ deriving Generic
@@ -0,0 +1,14 @@+{-# LANGUAGE StandaloneKindSignatures #-}++module Dhall.Syntax.Types where++import Data.Kind (Type)++data DhallDouble++data PreferAnnotation++type FieldSelection :: Type -> Type+data FieldSelection s++data WithComponent
@@ -0,0 +1,47 @@+{-# LANGUAGE DeriveGeneric #-}++module Dhall.Syntax.Var+ ( Var(..)+ ) where++import Data.String (IsString (..))+import Data.Text (Text)+import GHC.Generics (Generic)++{-| Label for a bound variable++ The `Data.Text.Text` field is the variable's name (i.e. \"@x@\").++ The `Int` field disambiguates variables with the same name if there are+ multiple bound variables of the same name in scope. Zero refers to the+ nearest bound variable and the index increases by one for each bound+ variable of the same name going outward. The following diagram may help:++> ┌──refers to──┐+> │ │+> v │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@0+>+> ┌─────────────────refers to─────────────────┐+> │ │+> v │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x@1++ This `Int` behaves like a De Bruijn index in the special case where all+ variables have the same name.++ You can optionally omit the index if it is @0@:++> ┌─refers to─┐+> │ │+> v │+> λ(x : Type) → λ(y : Type) → λ(x : Type) → x++ Zero indices are omitted when pretty-printing @Var@s and non-zero indices+ appear as a numeric suffix.+-}+data Var = V Text !Int+ deriving Generic++instance IsString Var where+ fromString str = V (fromString str) 0
@@ -1,4 +1,6 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE RecordWildCards #-}@@ -6,25 +8,36 @@ -- | Template Haskell utilities module Dhall.TH- ( -- * Template Haskell+ ( -- * Embedding Dhall in Haskell staticDhallExpression+ , dhall+ -- * Generating Haskell from Dhall expressions , makeHaskellTypeFromUnion , makeHaskellTypes+ , makeHaskellTypesWith , HaskellType(..)+ , GenerateOptions(..)+ , defaultGenerateOptions ) where +import Control.Monad (forM_)+import Data.Bifunctor (first) import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Pretty) import Dhall (FromDhall, ToDhall)-import Dhall.Syntax (Expr (..))+import Dhall.Syntax (Expr (..), FunctionBinding (..), Var (..)) import GHC.Generics (Generic)-import Language.Haskell.TH.Quote (dataToExpQ)+import Language.Haskell.TH.Quote (QuasiQuoter (..), dataToExpQ)+import Lens.Micro.Extras (view)+import Prettyprinter (Pretty) import Language.Haskell.TH.Syntax ( Bang (..)+ , Body (..) , Con (..) , Dec (..) , Exp (..)+ , Match (..)+ , Pat (..) , Q , SourceStrictness (..) , SourceUnpackedness (..)@@ -33,20 +46,25 @@ import Language.Haskell.TH.Syntax (DerivClause (..), DerivStrategy (..)) -import qualified Data.List as List-import qualified Data.Text as Text-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty-import qualified Data.Typeable as Typeable+import qualified Data.List as List+import qualified Data.Map as Map+import qualified Data.Set as Set+import qualified Data.Text as Text+import qualified Data.Time as Time+import qualified Data.Typeable as Typeable import qualified Dhall-import qualified Dhall.Core as Core+import qualified Dhall.Core as Core+import qualified Dhall.Import import qualified Dhall.Map import qualified Dhall.Pretty import qualified Dhall.Util import qualified GHC.IO.Encoding-import qualified Language.Haskell.TH.Syntax as Syntax+import qualified Language.Haskell.TH.Syntax as TH import qualified Numeric.Natural+import qualified Prettyprinter.Render.String as Pretty import qualified System.IO + {-| This fully resolves, type checks, and normalizes the expression, so the resulting AST is self-contained. @@ -73,23 +91,61 @@ -} staticDhallExpression :: Text -> Q Exp staticDhallExpression text = do- Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)+ TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8) - expression <- Syntax.runIO (Dhall.inputExpr text)+ (expression, status) <- TH.runIO $ do+ parsed <- Dhall.parseWithSettings Dhall.defaultInputSettings text + (resolved, status) <- Dhall.resolveAndStatusWithSettings Dhall.defaultInputSettings parsed++ _ <- Dhall.typecheckWithSettings Dhall.defaultInputSettings resolved++ let normalized = Dhall.normalizeWithSettings Dhall.defaultInputSettings resolved++ pure (normalized, status)++ forM_ (Dhall.Map.keys (view Dhall.Import.cache status)) $ \chained ->+ case Dhall.Import.chainedImport chained of+ Core.Import+ { importHashed = Core.ImportHashed+ { importType = Core.Local prefix file+ }+ } -> do+ fp <- Dhall.Import.localToPath prefix file+ TH.addDependentFile fp+ _ -> return ()+ dataToExpQ (fmap liftText . Typeable.cast) expression where -- A workaround for a problem in TemplateHaskell (see -- https://stackoverflow.com/questions/38143464/cant-find-inerface-file-declaration-for-variable)- liftText = fmap (AppE (VarE 'Text.pack)) . Syntax.lift . Text.unpack+ liftText = fmap (AppE (VarE 'Text.pack)) . TH.lift . Text.unpack +{-| A quasi-quoter for Dhall expressions.++ This quoter is build on top of 'staticDhallExpression'. Therefore consult the+ documentation of that function for further information.++ This quoter is meant to be used in expression context only; Other contexts+ like pattern contexts or declaration contexts are not supported and will+ result in an error.+-}+dhall :: QuasiQuoter+dhall = QuasiQuoter+ { quoteExp = staticDhallExpression . Text.pack+ , quotePat = const $ error "dhall quasi-quoter: Quoting patterns is not supported!"+ , quoteType = const $ error "dhall quasi-quoter: Quoting types is not supported!"+ , quoteDec = const $ error "dhall quasi-quoter: Quoting declarations is not supported!"+ }+ {-| Convert a Dhall type to a Haskell type that does not require any new data declarations beyond the data declarations supplied as the first argument -} toNestedHaskellType :: (Eq a, Pretty a)- => [HaskellType (Expr s a)]+ => [Var]+ -> [HaskellType (Expr s a)] -- ^ All Dhall-derived data declarations -- -- Used to replace complex types with references to one of these@@ -97,8 +153,40 @@ -> Expr s a -- ^ Dhall expression to convert to a simple Haskell type -> Q Type-toNestedHaskellType haskellTypes = loop+toNestedHaskellType typeParams haskellTypes = loop where+ predicate dhallType haskellType = Core.judgmentallyEqual (code haskellType) dhallType++ document dhallType =+ mconcat+ [ "Unsupported nested type\n"+ , " \n"+ , "Explanation: Not all Dhall types can be nested within Haskell datatype \n"+ , "declarations. Specifically, only the following simple Dhall types are supported\n"+ , "as a nested type inside of a data declaration: \n"+ , " \n"+ , "• ❰Bool❱ \n"+ , "• ❰Double❱ \n"+ , "• ❰Integer❱ \n"+ , "• ❰Natural❱ \n"+ , "• ❰Text❱ \n"+ , "• ❰Date❱ \n"+ , "• ❰TimeOfDay❱ \n"+ , "• ❰TimeZone❱ \n"+ , "• ❰List a❱ (where ❰a❱ is also a valid nested type) \n"+ , "• ❰Optional a❱ (where ❰a❱ is also a valid nested type) \n"+ , "• Another matching datatype declaration \n"+ , "• A bound type variable \n"+ , " \n"+ , "The Haskell datatype generation logic encountered the following Dhall type: \n"+ , " \n"+ , " " <> Dhall.Util.insert dhallType <> "\n"+ , " \n"+ , "... which did not fit any of the above criteria."+ ]++ message dhallType = Pretty.renderString (Dhall.Pretty.layout (document dhallType))+ loop dhallType = case dhallType of Bool -> return (ConT ''Bool)@@ -115,6 +203,15 @@ Text -> return (ConT ''Text) + Date ->+ return (ConT ''Time.Day)++ Time ->+ return (ConT ''Time.TimeOfDay)++ TimeZone ->+ return (ConT ''Time.TimeZone)+ App List dhallElementType -> do haskellElementType <- loop dhallElementType @@ -125,126 +222,168 @@ return (AppT (ConT ''Maybe) haskellElementType) - _ | Just haskellType <- List.find predicate haskellTypes -> do- let name = Syntax.mkName (Text.unpack (typeName haskellType))+ App dhallAppType dhallElementType -> do+ haskellAppType <- loop dhallAppType+ haskellElementType <- loop dhallElementType - return (ConT name) - | otherwise -> do- let document =- mconcat- [ "Unsupported nested type\n"- , " \n"- , "Explanation: Not all Dhall types can be nested within Haskell datatype \n"- , "declarations. Specifically, only the following simple Dhall types are supported\n"- , "as a nested type inside of a data declaration: \n"- , " \n"- , "• ❰Bool❱ \n"- , "• ❰Double❱ \n"- , "• ❰Integer❱ \n"- , "• ❰Natural❱ \n"- , "• ❰Text❱ \n"- , "• ❰List a❱ (where ❰a❱ is also a valid nested type) \n"- , "• ❰Optional a❱ (where ❰a❱ is also a valid nested type) \n"- , "• Another matching datatype declaration \n"- , " \n"- , "The Haskell datatype generation logic encountered the following Dhall type: \n"- , " \n"- , " " <> Dhall.Util.insert dhallType <> "\n"- , " \n"- , "... which did not fit any of the above criteria."- ]+ return (AppT haskellAppType haskellElementType) - let message = Pretty.renderString (Dhall.Pretty.layout document)+ Var v+ | Just (V param index) <- List.find (v ==) typeParams -> do+ let name = TH.mkName $ (Text.unpack param) ++ (show index) - fail message- where- predicate haskellType =- Core.judgmentallyEqual (code haskellType) dhallType+ return (VarT name) -derivingClauses :: [DerivClause]-derivingClauses =- [ DerivClause (Just StockStrategy) [ ConT ''Generic ]- , DerivClause (Just AnyclassStrategy) [ ConT ''FromDhall, ConT ''ToDhall ]- ]+ | otherwise -> fail $ message v + _ | Just haskellType <- List.find (predicate dhallType) haskellTypes -> do+ let name = TH.mkName (Text.unpack (typeName haskellType))++ return (ConT name)+ | otherwise -> fail $ message dhallType++-- | A deriving clause for `Generic`.+derivingGenericClause :: DerivClause+derivingGenericClause = DerivClause (Just StockStrategy) [ ConT ''Generic ]++-- | Generates a `FromDhall` instances.+fromDhallInstance+ :: TH.Name -- ^ The name of the type the instances is for+ -> Q Exp -- ^ A TH splice generating some `Dhall.InterpretOptions`+ -> Q [Dec]+fromDhallInstance n interpretOptions = [d|+ instance FromDhall $(pure $ ConT n) where+ autoWith = Dhall.genericAutoWithInputNormalizer $(interpretOptions)+ |]++-- | Generates a `ToDhall` instances.+toDhallInstance+ :: TH.Name -- ^ The name of the type the instances is for+ -> Q Exp -- ^ A TH splice generating some `Dhall.InterpretOptions`+ -> Q [Dec]+toDhallInstance n interpretOptions = [d|+ instance ToDhall $(pure $ ConT n) where+ injectWith = Dhall.genericToDhallWithInputNormalizer $(interpretOptions)+ |]+ -- | Convert a Dhall type to the corresponding Haskell datatype declaration toDeclaration :: (Eq a, Pretty a)- => [HaskellType (Expr s a)]+ => GenerateOptions+ -> [HaskellType (Expr s a)] -> HaskellType (Expr s a)- -> Q Dec-toDeclaration haskellTypes MultipleConstructors{..} =- case code of- Union kts -> do- let name = Syntax.mkName (Text.unpack typeName)+ -> Q [Dec]+toDeclaration generateOptions@GenerateOptions{..} haskellTypes typ =+ case typ of+ SingleConstructor{..} -> uncurry (fromSingle typeName constructorName) $ getTypeParams code+ MultipleConstructors{..} -> uncurry (fromMulti typeName) $ getTypeParams code+ where+ getTypeParams = first numberConsecutive . getTypeParams_ [] - constructors <- traverse (toConstructor haskellTypes typeName) (Dhall.Map.toList kts )+ getTypeParams_ acc (Lam _ (FunctionBinding _ v _ _ _) rest) = getTypeParams_ (v:acc) rest+ getTypeParams_ acc rest = (acc, rest) - return (DataD [] name [] Nothing constructors derivingClauses)+ derivingClauses = [ derivingGenericClause | generateFromDhallInstance || generateToDhallInstance ] - _ -> do- let document =- mconcat- [ "Dhall.TH.makeHaskellTypes: Not a union type\n"- , " \n"- , "Explanation: This function expects the ❰code❱ field of ❰MultipleConstructors❱ to\n"- , "evaluate to a union type. \n"- , " \n"- , "For example, this is a valid Dhall union type that this function would accept: \n"- , " \n"- , " \n"- , " ┌──────────────────────────────────────────────────────────────────┐ \n"- , " │ Dhall.TH.makeHaskellTypes (MultipleConstructors \"T\" \"< A | B >\") │ \n"- , " └──────────────────────────────────────────────────────────────────┘ \n"- , " \n"- , " \n"- , "... which corresponds to this Haskell type declaration: \n"- , " \n"- , " \n"- , " ┌────────────────┐ \n"- , " │ data T = A | B │ \n"- , " └────────────────┘ \n"- , " \n"- , " \n"- , "... but the following Dhall type is rejected due to being a bare record type: \n"- , " \n"- , " \n"- , " ┌──────────────────────────────────────────────┐ \n"- , " │ Dhall.TH.makeHaskellTypes \"T\" \"{ x : Bool }\" │ Not valid \n"- , " └──────────────────────────────────────────────┘ \n"- , " \n"- , " \n"- , "The Haskell datatype generation logic encountered the following Dhall type: \n"- , " \n"- , " " <> Dhall.Util.insert code <> "\n"- , " \n"- , "... which is not a union type."- ]+ interpretOptions = generateToInterpretOptions generateOptions typ - let message = Pretty.renderString (Dhall.Pretty.layout document)+#if MIN_VERSION_template_haskell(2,21,0)+ toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) TH.BndrReq+#elif MIN_VERSION_template_haskell(2,17,0)+ toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i)) ()+#else+ toTypeVar (V n i) = TH.PlainTV (TH.mkName (Text.unpack n ++ show i))+#endif - fail message-toDeclaration haskellTypes SingleConstructor{..} = do- let name = Syntax.mkName (Text.unpack typeName)+ toDataD typeName typeParams constructors = do+ let name = TH.mkName (Text.unpack typeName) - constructor <- toConstructor haskellTypes typeName (constructorName, Just code)+ let params = fmap toTypeVar typeParams - return (DataD [] name [] Nothing [constructor] derivingClauses)+ fmap concat . sequence $+ [pure [DataD [] name params Nothing constructors derivingClauses]] <>+ [ fromDhallInstance name interpretOptions | generateFromDhallInstance ] <>+ [ toDhallInstance name interpretOptions | generateToDhallInstance ] + fromSingle typeName constructorName typeParams dhallType = do+ constructor <- toConstructor typeParams generateOptions haskellTypes typeName (constructorName, Just dhallType)++ toDataD typeName typeParams [constructor]++ fromMulti typeName typeParams dhallType = case dhallType of+ Union kts -> do+ constructors <- traverse (toConstructor typeParams generateOptions haskellTypes typeName) (Dhall.Map.toList kts)++ toDataD typeName typeParams constructors++ _ -> fail $ message dhallType++ message dhallType = Pretty.renderString (Dhall.Pretty.layout $ document dhallType)++ document dhallType =+ mconcat+ [ "Dhall.TH.makeHaskellTypes: Not a union type\n"+ , " \n"+ , "Explanation: This function expects the ❰code❱ field of ❰MultipleConstructors❱ to\n"+ , "evaluate to a union type. \n"+ , " \n"+ , "For example, this is a valid Dhall union type that this function would accept: \n"+ , " \n"+ , " \n"+ , " ┌──────────────────────────────────────────────────────────────────┐ \n"+ , " │ Dhall.TH.makeHaskellTypes (MultipleConstructors \"T\" \"< A | B >\") │ \n"+ , " └──────────────────────────────────────────────────────────────────┘ \n"+ , " \n"+ , " \n"+ , "... which corresponds to this Haskell type declaration: \n"+ , " \n"+ , " \n"+ , " ┌────────────────┐ \n"+ , " │ data T = A | B │ \n"+ , " └────────────────┘ \n"+ , " \n"+ , " \n"+ , "... but the following Dhall type is rejected due to being a bare record type: \n"+ , " \n"+ , " \n"+ , " ┌──────────────────────────────────────────────┐ \n"+ , " │ Dhall.TH.makeHaskellTypes \"T\" \"{ x : Bool }\" │ Not valid \n"+ , " └──────────────────────────────────────────────┘ \n"+ , " \n"+ , " \n"+ , "The Haskell datatype generation logic encountered the following Dhall type: \n"+ , " \n"+ , " " <> Dhall.Util.insert dhallType <> "\n"+ , " \n"+ , "... which is not a union type."+ ]++-- | Number each variable, starting at 0+numberConsecutive :: [Text.Text] -> [Var]+numberConsecutive = snd . List.mapAccumR go Map.empty . reverse+ where+ go m k =+ let (i, m') = Map.updateLookupWithKey (\_ j -> Just $ j + 1) k m+ in maybe ((Map.insert k 0 m'), (V k 0)) (\i' -> (m', (V k i'))) i+ -- | Convert a Dhall type to the corresponding Haskell constructor toConstructor :: (Eq a, Pretty a)- => [HaskellType (Expr s a)]+ => [Var]+ -> GenerateOptions+ -> [HaskellType (Expr s a)] -> Text -- ^ typeName -> (Text, Maybe (Expr s a)) -- ^ @(constructorName, fieldType)@ -> Q Con-toConstructor haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do- let name = Syntax.mkName (Text.unpack constructorName)+toConstructor typeParams GenerateOptions{..} haskellTypes outerTypeName (constructorName, maybeAlternativeType) = do+ let name = TH.mkName (Text.unpack $ constructorModifier constructorName) - let bang = Bang NoSourceUnpackedness NoSourceStrictness+ let strictness = if makeStrict then SourceStrict else NoSourceStrictness + let bang = Bang NoSourceUnpackedness strictness+ case maybeAlternativeType of Just dhallType | let predicate haskellType =@@ -252,22 +391,22 @@ && typeName haskellType /= outerTypeName , Just haskellType <- List.find predicate haskellTypes -> do let innerName =- Syntax.mkName (Text.unpack (typeName haskellType))+ TH.mkName (Text.unpack (typeName haskellType)) return (NormalC name [ (bang, ConT innerName) ]) Just (Record kts) -> do let process (key, dhallFieldType) = do- haskellFieldType <- toNestedHaskellType haskellTypes dhallFieldType+ haskellFieldType <- toNestedHaskellType typeParams haskellTypes dhallFieldType - return (Syntax.mkName (Text.unpack key), bang, haskellFieldType)+ return (TH.mkName (Text.unpack $ fieldModifier key), bang, haskellFieldType) varBangTypes <- traverse process (Dhall.Map.toList $ Core.recordFieldValue <$> kts) return (RecC name varBangTypes) Just dhallAlternativeType -> do- haskellAlternativeType <- toNestedHaskellType haskellTypes dhallAlternativeType+ haskellAlternativeType <- toNestedHaskellType typeParams haskellTypes dhallAlternativeType return (NormalC name [ (bang, haskellAlternativeType) ]) @@ -298,17 +437,18 @@ makeHaskellTypeFromUnion typeName code = makeHaskellTypes [ MultipleConstructors{..} ] --- | Used by `makeHaskellTypes` to specify how to generate Haskell types+-- | Used by `makeHaskellTypes` and `makeHaskellTypesWith` to specify how to+-- generate Haskell types. data HaskellType code -- | Generate a Haskell type with more than one constructor from a Dhall- -- union type+ -- union type. = MultipleConstructors { typeName :: Text -- ^ Name of the generated Haskell type , code :: code -- ^ Dhall code that evaluates to a union type }- -- | Generate a Haskell type with one constructor from any Dhall type+ -- | Generate a Haskell type with one constructor from any Dhall type. -- -- To generate a constructor with multiple named fields, supply a Dhall -- record type. This does not support more than one anonymous field.@@ -322,8 +462,88 @@ } deriving (Functor, Foldable, Traversable) +-- | This data type holds various options that let you control several aspects+-- how Haskell code is generated. In particular you can+--+-- * disable the generation of `FromDhall`/`ToDhall` instances.+-- * modify how a Dhall union field translates to a Haskell data constructor.+data GenerateOptions = GenerateOptions+ { constructorModifier :: Text -> Text+ -- ^ How to map a Dhall union field name to a Haskell constructor.+ -- Note: The `constructorName` of `SingleConstructor` will be passed to this function, too.+ , fieldModifier :: Text -> Text+ -- ^ How to map a Dhall record field names to a Haskell record field names.+ , generateFromDhallInstance :: Bool+ -- ^ Generate a `FromDhall` instance for the Haskell type+ , generateToDhallInstance :: Bool+ -- ^ Generate a `ToDhall` instance for the Haskell type+ , makeStrict :: Bool+ -- ^ Make all fields strict.+ }++-- | A default set of options used by `makeHaskellTypes`. That means:+--+-- * Constructors and fields are passed unmodified.+-- * Both `FromDhall` and `ToDhall` instances are generated.+--+-- Note: `From/ToDhall` should be `False` if importing higher-kinded types.+-- In these cases one should use a standalone declaration.+defaultGenerateOptions :: GenerateOptions+defaultGenerateOptions = GenerateOptions+ { constructorModifier = id+ , fieldModifier = id+ , generateFromDhallInstance = True+ , generateToDhallInstance = True+ , makeStrict = False+ }++-- | This function generates `Dhall.InterpretOptions` that can be used for the+-- marshalling of the Haskell type generated according to the `GenerateOptions`.+-- I.e. those `Dhall.InterpretOptions` reflect the mapping done by+-- `constructorModifier` and `fieldModifier` on the value level.+generateToInterpretOptions :: GenerateOptions -> HaskellType (Expr s a) -> Q Exp+generateToInterpretOptions GenerateOptions{..} haskellType = [| Dhall.InterpretOptions+ { Dhall.fieldModifier = \ $(pure nameP) ->+ $(toCases fieldModifier $ fields haskellType)+ , Dhall.constructorModifier = \ $(pure nameP) ->+ $(toCases constructorModifier $ constructors haskellType)+ , Dhall.singletonConstructors = Dhall.singletonConstructors Dhall.defaultInterpretOptions+ }|]+ where+ constructors :: HaskellType (Expr s a) -> [Text]+ constructors SingleConstructor{..} = [constructorName]+ constructors MultipleConstructors{..} | Union kts <- code = Dhall.Map.keys kts+ constructors _ = []++ fields :: HaskellType (Expr s a) -> [Text]+ fields SingleConstructor{..} | Record kts <- code = Dhall.Map.keys kts+ fields MultipleConstructors{..} | Union kts <- code = Set.toList $ mconcat+ [ Dhall.Map.keysSet kts'+ | (_, Just (Record kts')) <- Dhall.Map.toList kts+ ]+ fields _ = []++ toCases :: (Text -> Text) -> [Text] -> Q Exp+ toCases f xs = do+ err <- [| Core.internalError $ "Unmatched " <> Text.pack (show $(pure nameE)) |]+ pure $ CaseE nameE $ map mkMatch xs <> [Match WildP (NormalB err) []]+ where+ mkMatch n = Match (textToPat $ f n) (NormalB $ textToExp n) []++ nameE :: Exp+ nameE = TH.VarE $ TH.mkName "n"++ nameP :: Pat+ nameP = TH.VarP $ TH.mkName "n"++ textToExp :: Text -> Exp+ textToExp = TH.LitE . TH.StringL . Text.unpack++ textToPat :: Text -> Pat+ textToPat = TH.LitP . TH.StringL . Text.unpack+ -- | Generate a Haskell datatype declaration with one constructor from a Dhall--- type+-- type. -- -- This comes in handy if you need to keep Dhall types and Haskell types in -- sync. You make the Dhall types the source of truth and use Template Haskell@@ -398,9 +618,18 @@ -- > deriving instance Ord Employee -- > deriving instance Show Employee makeHaskellTypes :: [HaskellType Text] -> Q [Dec]-makeHaskellTypes haskellTypes = do- Syntax.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8)+makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions - haskellTypes' <- traverse (traverse (Syntax.runIO . Dhall.inputExpr)) haskellTypes+-- | Like `makeHaskellTypes`, but with the ability to customize the generated+-- Haskell code by passing `GenerateOptions`.+--+-- For instance, `makeHaskellTypes` is implemented using this function:+--+-- > makeHaskellTypes = makeHaskellTypesWith defaultGenerateOptions+makeHaskellTypesWith :: GenerateOptions -> [HaskellType Text] -> Q [Dec]+makeHaskellTypesWith generateOptions haskellTypes = do+ TH.runIO (GHC.IO.Encoding.setLocaleEncoding System.IO.utf8) - traverse (toDeclaration haskellTypes') haskellTypes'+ haskellTypes' <- traverse (traverse (TH.runIO . Dhall.inputExpr)) haskellTypes++ concat <$> traverse (toDeclaration generateOptions haskellTypes') haskellTypes'
@@ -1,4 +1,5 @@ {-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# LANGUAGE CPP #-} {-| Dhall is a programming language specialized for configuration files. This module contains a tutorial explaining how to author configuration files@@ -375,13 +376,23 @@ -- -- ... and you can reference that expression either directly: --+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS) -- >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool -- True+#else+-- > >>> input auto "https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > True+#endif -- -- ... or inside of a larger expression: --+#if defined(WITH_HTTP) && defined(USE_HTTP_CLIENT_TLS) && defined(NETWORK_TESTS) -- >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool -- False+#else+-- > >>> input auto "False == https://raw.githubusercontent.com/dhall-lang/dhall-haskell/18e4e9a18dc53271146df3ccf5b4177c3552236b/examples/True" :: IO Bool+-- > False+#endif -- -- You're not limited to hosting Dhall expressions on GitHub. You can host a -- Dhall expression anywhere that you can host UTF8-encoded text on the web,@@ -1619,7 +1630,7 @@ -- > let replicate = https://prelude.dhall-lang.org/List/replicate -- > in replicate 5 -- > $--- > $ dhall freeze --inplace ./foo.dhall+-- > $ dhall freeze ./foo.dhall -- > $ cat ./foo.dhall -- > let replicate = -- > https://prelude.dhall-lang.org/List/replicate sha256:d4250b45278f2d692302489ac3e78280acb238d27541c837ce46911ff3baa347@@ -1633,7 +1644,7 @@ -- record might be the contents of a software license: -- -- > { package = "dhall"--- > , author = "Gabriel Gonzalez"+-- > , author = "Gabriella Gonzalez" -- > , license = ./LICENSE -- > } --@@ -1642,7 +1653,7 @@ -- -- > $ cat LICENSE -- > ''--- > Copyright (c) 2017 Gabriel Gonzalez+-- > Copyright (c) 2017 Gabriella Gonzalez -- > All rights reserved. -- > -- > ...@@ -1657,14 +1668,14 @@ -- end of the import, like this: -- -- > { package = "dhall"--- > , author = "Gabriel Gonzalez"+-- > , author = "Gabriella Gonzalez" -- > , license = ./LICENSE as Text -- > } -- -- ... and then you can use the original text file unmodified: -- -- > $ cat LICENSE--- > Copyright (c) 2017 Gabriel Gonzalez+-- > Copyright (c) 2017 Gabriella Gonzalez -- > All rights reserved. -- > -- > ...@@ -1744,10 +1755,9 @@ -- > (List (List Natural)) -- > (replicate 5 (List Natural) (replicate 5 Natural 1)) ----- You can also use the formatter to modify files in place using the--- @--inplace@ flag (i.e. for formatting source code):+-- You can also use the formatter to modify files in place: ----- > $ dhall format --inplace ./unformatted+-- > $ dhall format ./unformatted -- -- Carefully note that the code formatter does not preserve all comments. -- Currently, the formatter only preserves two types of comments:@@ -1847,7 +1857,7 @@ -- You can find an up-to-date list of available built-in functions and operators -- here: ----- <https://github.com/dhall-lang/dhall-lang/wiki/Built-in-types%2C-functions%2C-and-operators Built-in types, functions, and operators>+-- <https://docs.dhall-lang.org/references/Built-in-types.html> -- $caveats --@@ -1872,9 +1882,13 @@ -- > -- > (input):1:1 ----- In fact, there are no built-in functions for @Integer@s (or @Double@s) other--- than @Integer/show@ and @Double/show@. As far as the language is concerned--- they are opaque values that can only be shuffled around but not used in any+-- There are no built-in functions for @Integer@ arithmetic; however, conversion+-- to and from @Natural@s is possible usinng @Integer/clamp@, @Integer/negate@+-- and @Natural/toInteger@.+--+-- For @Double@s the situation is even more extreme: there are no built-in+-- functions other than @Double/show@. As far as the language is concerned they+-- are opaque values that can only be shuffled around but not used in any -- meaningful way until they have been loaded into Haskell. -- -- Second, the equality @(==)@ and inequality @(!=)@ operators only work on@@ -1969,6 +1983,7 @@ -- $substitutions -- -- Substitutions are another way to extend the language.+-- -- Suppose we have the following Haskell datatype: -- -- > data Result = Failure Integer | Success String@@ -1980,28 +1995,15 @@ -- -- > -- example.dhall -- >--- > let Result = < Failure : Integer | Success Text >--- > in Result.Failure 1+-- > let Result = < Failure : Integer | Success : Text >+-- > in Result.Failure +1 -- -- Right now it is quite easy to keep these two definitions (the one in Haskell source and the one in the Dhall file) synchronized: -- If we implement a new feature in the Haskell source we update the corresponding type in the Dhall file. -- But what happens if our application is growing and our Result type contains e.g. 10 unions with possible types embedded in it?--- Maintaining the code will get tedious. Luckily we can extract the correct Dhall type from the Haskell definition: ----- > resultDecoder :: Dhall.Decoder Result--- > resultDecoder = Dhall.auto--- >--- > resultType :: Expr Src Void--- > resultType = Dhall.expected resultDecoder--- >--- > resultTypeString :: String--- > resultTypeString = show $ pretty resultType------ Now we just have to inject that type into the Dhall code and we are done. One common way to do that is to wrap the import of example.dhall in a let expression:------ > Dhall.input (Dhall.auto :: Dhall.Decoder Result) ("let Result = " ++ Data.Text.pack resultTypeString ++ " in ./example.dhall")------ Now we can omit the definition of Result in our example.dhall file. While this will work perfectly Dhall provides a cleaner solution for our \"injection problem\":+-- We can override the interpreter's @evaluateSettings@ with a custom set of+-- substitutions, like this: -- -- > {-# LANGUAGE OverloadedStrings #-} -- >@@ -2314,4 +2316,4 @@ -- $faq ----- <https://github.com/dhall-lang/dhall-lang/wiki/Frequently-Asked-Questions-(FAQ) Frequently Asked Questions (FAQ)>+-- <https://docs.dhall-lang.org/howtos/FAQ.html>
@@ -35,10 +35,9 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.Monoid (Endo (..)) import Data.Semigroup (Max (..))-import Data.Sequence (Seq, ViewL (..))+import Data.Sequence (ViewL (..)) import Data.Set (Set) import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty (..)) import Data.Typeable (Typeable) import Data.Void (Void, absurd) import Dhall.Context (Context)@@ -48,9 +47,10 @@ , Val (..) , (~>) )-import Dhall.Pretty (Ann)+import Dhall.Pretty (Ann, UnescapedLabel (..)) import Dhall.Src (Src)-import Lens.Family (over)+import Lens.Micro (anyOf, over)+import Prettyprinter (Doc, Pretty (..), vsep) import Dhall.Syntax ( Binding (..)@@ -61,28 +61,28 @@ , PreferAnnotation (..) , RecordField (..) , Var (..)+ , WithComponent (..) ) -import qualified Data.Foldable as Foldable-import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Foldable as Foldable+import qualified Data.Foldable.WithIndex as Foldable.WithIndex+import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Map import qualified Data.Sequence import qualified Data.Set-import qualified Data.Text as Text-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.String as Pretty+import qualified Data.Text as Text import qualified Data.Traversable import qualified Dhall.Context import qualified Dhall.Core import qualified Dhall.Diff-import qualified Dhall.Eval as Eval+import qualified Dhall.Eval as Eval import qualified Dhall.Map import qualified Dhall.Pretty import qualified Dhall.Pretty.Internal-import qualified Dhall.Set-import qualified Dhall.Syntax as Syntax+import qualified Dhall.Syntax as Syntax import qualified Dhall.Util-import qualified Lens.Family+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.String as Pretty {-| A type synonym for `Void` @@ -93,9 +93,6 @@ type X = Void {-# DEPRECATED X "Use Data.Void.Void instead" #-} -traverseWithIndex_ :: Applicative f => (Int -> a -> f b) -> Seq a -> f ()-traverseWithIndex_ k xs = Foldable.sequenceA_ (Data.Sequence.mapWithIndex k xs)- axiom :: Const -> Either (TypeError s a) Const axiom Type = return Kind axiom Kind = return Sort@@ -189,7 +186,7 @@ {-| `typeWithA` is implemented internally in terms of @infer@ in order to speed up equivalence checking. - Specifically, we extend the `Context` to become a @Ctx@, which can store + Specifically, we extend the `Context` to become a @Ctx@, which can store the entire contents of a `let` expression (i.e. the type *and* the value of the bound variable). By storing this extra information in the @Ctx@ we no longer need to substitute `let` expressions at all (which is very@@ -229,7 +226,7 @@ go types n0 - Lam (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b -> do+ Lam _ (FunctionBinding { functionBindingVariable = x, functionBindingAnnotation = _A}) b -> do tA' <- loop ctx _A case tA' of@@ -252,7 +249,7 @@ return (VHPi x _A' (\u -> Eval.eval (Extend values x u) _B'')) - Pi x _A _B -> do+ Pi _ x _A _B -> do tA' <- loop ctx _A kA <- case tA' of@@ -417,34 +414,26 @@ _R' <- loop ctx r - tL' <- loop ctx (quote names _L')+ _ <- loop ctx (quote names _L') let _L'' = quote names _L' - case tL' of- VConst Type ->- return ()- _ -> do- let tL'' = quote names tL'- die (IfBranchMustBeTerm True l _L'' tL'')-- tR' <- loop ctx (quote names _R')+ _ <- loop ctx (quote names _R') let _R'' = quote names _R' - case tR' of- VConst Type ->- return ()- _ -> do- let tR'' = quote names tR'- die (IfBranchMustBeTerm True r _R'' tR'')- if Eval.conv values _L' _R' then return () else die (IfBranchMismatch l r _L'' _R'') return _L' + Bytes ->+ return (VConst Type)++ BytesLit _ ->+ return VBytes+ Natural -> return (VConst Type) @@ -593,6 +582,33 @@ TextShow -> return (VText ~> VText) + Date ->+ return (VConst Type)++ DateLiteral _ ->+ return VDate++ DateShow ->+ return (VDate ~> VText)++ Time ->+ return (VConst Type)++ TimeLiteral _ _ ->+ return VTime++ TimeShow ->+ return (VTime ~> VText)++ TimeZone ->+ return (VConst Type)++ TimeZoneLiteral _ ->+ return VTimeZone++ TimeZoneShow ->+ return (VTimeZone ~> VText)+ List -> return (VConst Type ~> VConst Type) @@ -627,7 +643,7 @@ Left (TypeError context t₁ err) - traverseWithIndex_ process ts₁+ Foldable.WithIndex.itraverse_ process ts₁ return (VList _T₀') @@ -782,14 +798,14 @@ Max c <- fmap Foldable.fold (Dhall.Map.unorderedTraverseWithKey process xTs) return (VConst c)- Combine mk l r -> do+ Combine _ mk l r -> do _L' <- loop ctx l let l'' = quote names (eval values l) _R' <- loop ctx r - let r'' = quote names (eval values l)+ let r'' = quote names (eval values r) xLs' <- case _L' of VRecord xLs' ->@@ -831,7 +847,7 @@ combineTypes [] xLs' xRs' - CombineTypes l r -> do+ CombineTypes _ l r -> do _L' <- loop ctx l let l' = eval values l@@ -878,7 +894,7 @@ return (VConst c) - Prefer a l r -> do+ Prefer _ _ l r -> do _L' <- loop ctx l _R' <- loop ctx r@@ -891,11 +907,7 @@ let l'' = quote names (eval values l) - case a of- PreferFromWith withExpression ->- die (MustUpdateARecord withExpression l'' _L'')- _ ->- die (MustCombineARecord '⫽' l'' _L'')+ die (MustCombineARecord '⫽' l'' _L'') xRs' <- case _R' of VRecord xRs' -> return xRs'@@ -913,13 +925,13 @@ _L' <- loop ctx l case _L' of- VRecord xLs' + VRecord xLs' | not (Dhall.Map.member "default" xLs') -> die (InvalidRecordCompletion "default" l) | not (Dhall.Map.member "Type" xLs') -> die (InvalidRecordCompletion "Type" l) | otherwise- -> loop ctx (Annot (Prefer PreferFromCompletion (Field l def) r) (Field l typ))+ -> loop ctx (Annot (Prefer mempty PreferFromCompletion (Field l def) r) (Field l typ)) _ -> die (CompletionSchemaMustBeARecord l (quote names _L')) where@@ -991,7 +1003,7 @@ n < 0 containsBadVar e =- Lens.Family.anyOf+ anyOf Dhall.Core.subExpressions containsBadVar e@@ -1127,6 +1139,14 @@ die (MapTypeMismatch (quote names (mapType _T')) _T₁'') + ShowConstructor e -> do+ _E' <- loop ctx e+ case _E' of+ VUnion _ -> pure VText+ VOptional _ -> pure VText++ _ -> die ShowConstructorNotOnUnion+ Field e (Syntax.fieldSelectionLabel -> x) -> do _E' <- loop ctx e @@ -1154,6 +1174,12 @@ die (CantAccess text e'' _E'') Project e (Left xs) -> do+ case duplicateElement xs of+ Just x -> do+ die (DuplicateProjectionLabel x)+ Nothing -> do+ return ()+ _E' <- loop ctx e let _E'' = quote names _E'@@ -1167,7 +1193,7 @@ let adapt = VRecord . Dhall.Map.unorderedFromList - fmap adapt (traverse process (Dhall.Set.toAscList xs))+ fmap adapt (traverse process xs) _ -> do let text =@@ -1234,7 +1260,7 @@ _ -> die (NotAnEquivalence _T) - Equivalent x y -> do+ Equivalent _ x y -> do _A₀' <- loop ctx x let _A₀'' = quote names _A₀'@@ -1261,28 +1287,54 @@ return (VConst Type) - With e ks v -> do- tE' <- loop ctx e+ With e₀ ks₀ v₀ -> do+ tE₀' <- loop ctx e₀ - kTs' <- case tE' of- VRecord kTs' -> return kTs'- _ -> die (NotWithARecord e (quote names tE'))+ -- The purpose of this inner loop is to ensure that we only need to+ -- typecheck the record once - case ks of- k :| [] -> do- tV' <- loop ctx v+ let with tE' ks v = case tE' of+ VRecord kTs' ->+ case ks of+ WithLabel k :| [] -> do+ tV' <- loop ctx v - return (VRecord (Dhall.Map.insert k tV' kTs'))- k₀ :| k₁ : ks' -> do- let e₁ =- if Dhall.Map.member k₀ kTs'- then Field e (Syntax.makeFieldSelection k₀)- else RecordLit mempty+ return (VRecord (Dhall.Map.insert k tV' kTs'))+ WithLabel k₀ :| k₁ : ks' -> do+ let _T =+ case Dhall.Map.lookup k₀ kTs' of+ Just _T' -> _T'+ Nothing -> VRecord mempty - tV' <- loop ctx (With e₁ (k₁ :| ks') v)+ tV' <- with _T (k₁ :| ks') v - return (VRecord (Dhall.Map.insert k₀ tV' kTs'))+ return (VRecord (Dhall.Map.insert k₀ tV' kTs'))+ WithQuestion :| _ -> do+ die NotALabelPath + VOptional _O' -> do+ case ks of++ -- (Some x) with ? = v is valid iff the type of x is the same as the type of v.+ WithQuestion :| [] -> do+ tV' <- loop ctx v+ if Eval.conv values _O' tV'+ then return (VOptional _O')+ else die OptionalWithTypeMismatch++ -- (Some x) with ?.a.b = v is valid iff the type of x.a.b is the same as the type of v.+ WithQuestion :| k₁ : ks' -> do+ tV' <- with _O' (k₁ :| ks') v+ if Eval.conv values _O' tV'+ then return (VOptional _O')+ else die OptionalWithTypeMismatch++ WithLabel k :| _ -> die (NotAQuestionPath k)++ _ -> die (NotWithARecord e₀ (quote names tE')) -- TODO: NotWithARecordOrOptional++ with tE₀' ks₀ v₀+ Note s e -> case loop ctx e of Left (TypeError ctx' (Note s' e') m) ->@@ -1326,23 +1378,19 @@ | Untyped | MissingListType | MismatchedListElements Int (Expr s a) (Expr s a) (Expr s a)- | InvalidListElement Int (Expr s a) (Expr s a) (Expr s a) | InvalidListType (Expr s a) | ListLitInvariant | InvalidSome (Expr s a) (Expr s a) (Expr s a) | InvalidPredicate (Expr s a) (Expr s a) | IfBranchMismatch (Expr s a) (Expr s a) (Expr s a) (Expr s a)- | IfBranchMustBeTerm Bool (Expr s a) (Expr s a) (Expr s a) | InvalidFieldType Text (Expr s a) | InvalidAlternativeType Text (Expr s a) | ListAppendMismatch (Expr s a) (Expr s a)- | MustUpdateARecord (Expr s a) (Expr s a) (Expr s a) | MustCombineARecord Char (Expr s a) (Expr s a) | InvalidDuplicateField Text (Expr s a) (Expr s a) | InvalidRecordCompletion Text (Expr s a) | CompletionSchemaMustBeARecord (Expr s a) (Expr s a) | CombineTypesRequiresRecordType (Expr s a) (Expr s a)- | RecordTypeMismatch Const Const (Expr s a) (Expr s a) | DuplicateFieldCannotBeMerged (NonEmpty Text) | FieldCollision (NonEmpty Text) | FieldTypeCollision (NonEmpty Text)@@ -1359,12 +1407,12 @@ | HandlerInputTypeMismatch Text (Expr s a) (Expr s a) | DisallowedHandlerType Text (Expr s a) (Expr s a) Text | HandlerOutputTypeMismatch Text (Expr s a) Text (Expr s a)- | InvalidHandlerOutputType Text (Expr s a) (Expr s a) | MissingMergeType | HandlerNotAFunction Text (Expr s a) | CantAccess Text (Expr s a) (Expr s a) | CantProject Text (Expr s a) (Expr s a) | CantProjectByExpression (Expr s a)+ | DuplicateProjectionLabel Text | MissingField Text (Expr s a) | MissingConstructor Text (Expr s a) | ProjectionTypeMismatch Text (Expr s a) (Expr s a) (Expr s a) (Expr s a)@@ -1382,17 +1430,26 @@ | CantListAppend (Expr s a) (Expr s a) | CantAdd (Expr s a) (Expr s a) | CantMultiply (Expr s a) (Expr s a)+ | OptionalWithTypeMismatch+ | NotALabelPath+ | NotAQuestionPath Text+ | ShowConstructorNotOnUnion deriving (Show) +formatHints :: [Doc Ann] -> Doc Ann+formatHints hints = vsep (map format hints)+ where+ format hint = "\n\n\ESC[1;33mHint\ESC[0m: " <> hint+ shortTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann shortTypeMessage msg =- "\ESC[1;31mError\ESC[0m: " <> short <> "\n"+ "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n" where ErrorMessages {..} = prettyTypeMessage msg longTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> Doc Ann longTypeMessage msg =- "\ESC[1;31mError\ESC[0m: " <> short <> "\n"+ "\ESC[1;31mError\ESC[0m: " <> short <> formatHints hints <> "\n" <> "\n" <> long where@@ -1404,6 +1461,8 @@ data ErrorMessages = ErrorMessages { short :: Doc Ann -- ^ Default succinct 1-line explanation of what went wrong+ , hints :: [Doc Ann]+ -- ^ Possibly-empty hints based on specific types involved in the error , long :: Doc Ann -- ^ Longer and more detailed explanation of the error }@@ -1414,6 +1473,12 @@ insert :: Pretty a => a -> Doc Ann insert = Dhall.Util.insert +emptyRecordTypeHint :: (Eq a, Pretty a) => Expr s a -> [Doc Ann]+emptyRecordTypeHint expr =+ if Eval.judgmentallyEqual expr (Record mempty) then+ ["{} is the empty record type, use {=} for the empty record value"]+ else []+ -- | Convert a `TypeMessage` to short- and long-form `ErrorMessages` prettyTypeMessage :: (Eq a, Pretty a) => TypeMessage s a -> ErrorMessages prettyTypeMessage (UnboundVariable x) = ErrorMessages {..}@@ -1422,6 +1487,8 @@ where short = "Unbound variable: " <> Pretty.pretty x + hints = []+ long = "Explanation: Expressions can only reference previously introduced (i.e. “bound”)\n\ \variables that are still “in scope” \n\@@ -1535,6 +1602,8 @@ where short = "Invalid function input" + hints = []+ long = "Explanation: A function can accept an input “term” that has a given “type”, like\n\ \this: \n\@@ -1604,6 +1673,8 @@ where short = "Invalid function output" + hints = []+ long = "Explanation: A function can return an output “term” that has a given “type”, \n\ \like this: \n\@@ -1683,6 +1754,8 @@ where short = "Not a function" + hints = []+ long = "Explanation: Expressions separated by whitespace denote function application, \n\ \like this: \n\@@ -1823,6 +1896,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3) + hints = emptyRecordTypeHint expr2+ long = "Explanation: Every function declares what type or kind of argument to accept \n\ \ \n\@@ -1956,6 +2031,9 @@ short = "Expression doesn't match annotation\n" <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)++ hints = []+ long = "Explanation: You can annotate an expression with its type or kind using the \n\ \❰:❱ symbol, like this: \n\@@ -2052,6 +2130,8 @@ where short = "❰Sort❱ has no type, kind, or sort" + hints = []+ long = "Explanation: There are five levels of expressions that form a hierarchy: \n\ \ \n\@@ -2090,6 +2170,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized Bool expr1) + hints = []+ long = "Explanation: Every ❰if❱ expression begins with a predicate which must have type \n\ \❰Bool❱ \n\@@ -2148,93 +2230,6 @@ txt0 = insert expr0 txt1 = insert expr1 -prettyTypeMessage (IfBranchMustBeTerm b expr0 expr1 expr2) =- ErrorMessages {..}- where- short = "❰if❱ branch is not a term"-- long =- "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\- \is an expression: \n\- \ \n\- \ \n\- \ Expression for ❰then❱ branch \n\- \ ⇩ \n\- \ ┌────────────────────────────────┐ \n\- \ │ if True then \"Hello, world!\" │ \n\- \ │ else \"Goodbye, world!\" │ \n\- \ └────────────────────────────────┘ \n\- \ ⇧ \n\- \ Expression for ❰else❱ branch \n\- \ \n\- \ \n\- \These expressions must be a “term”, where a “term” is defined as an expression \n\- \that has a type thas has kind ❰Type❱ \n\- \ \n\- \For example, the following expressions are all valid “terms”: \n\- \ \n\- \ \n\- \ ┌────────────────────┐ \n\- \ │ 1 : Natural : Type │ ❰1❱ is a term with a type (❰Natural❱) of kind ❰Type❱\n\- \ └────────────────────┘ \n\- \ ⇧ \n\- \ term \n\- \ \n\- \ \n\- \ ┌─────────────────────────────────────┐ \n\- \ │ Natural/odd : Natural → Bool : Type │ ❰Natural/odd❱ is a term with a type\n\- \ └─────────────────────────────────────┘ (❰Natural → Bool❱) of kind ❰Type❱ \n\- \ ⇧ \n\- \ term \n\- \ \n\- \ \n\- \However, the following expressions are " <> _NOT <> " valid terms: \n\- \ \n\- \ \n\- \ ┌────────────────────┐ \n\- \ │ Text : Type : Kind │ ❰Text❱ has kind (❰Type❱) of sort ❰Kind❱ and is \n\- \ └────────────────────┘ therefore not a term \n\- \ ⇧ \n\- \ type \n\- \ \n\- \ \n\- \ ┌───────────────────────────┐ \n\- \ │ List : Type → Type : Kind │ ❰List❱ has kind (❰Type → Type❱) of sort \n\- \ └───────────────────────────┘ ❰Kind❱ and is therefore not a term \n\- \ ⇧ \n\- \ type-level function \n\- \ \n\- \ \n\- \This means that you cannot define an ❰if❱ expression that returns a type. For \n\- \example, the following ❰if❱ expression is " <> _NOT <> " valid: \n\- \ \n\- \ \n\- \ ┌─────────────────────────────┐ \n\- \ │ if True then Text else Bool │ Invalid ❰if❱ expression \n\- \ └─────────────────────────────┘ \n\- \ ⇧ ⇧ \n\- \ type type \n\- \ \n\- \ \n\- \Your ❰" <> txt0 <> "❱ branch of your ❰if❱ expression is: \n\- \ \n\- \" <> txt1 <> "\n\- \ \n\- \... which has kind: \n\- \ \n\- \" <> txt2 <> "\n\- \ \n\- \... of sort: \n\- \ \n\- \" <> txt3 <> "\n\- \ \n\- \... and is not a term. Therefore your ❰if❱ expression is not valid \n"- where- txt0 = if b then "then" else "else"- txt1 = insert expr0- txt2 = insert expr1- txt3 = insert expr2- prettyTypeMessage (IfBranchMismatch expr0 expr1 expr2 expr3) = ErrorMessages {..} where@@ -2242,6 +2237,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr3) + hints = []+ long = "Explanation: Every ❰if❱ expression has a ❰then❱ and ❰else❱ branch, each of which\n\ \is an expression: \n\@@ -2316,6 +2313,8 @@ where short = "Internal error: A non-empty list literal violated an internal invariant" + hints = []+ long = "Explanation: Internal error: A non-empty list literal violated an internal \n\ \invariant. \n\@@ -2331,6 +2330,8 @@ where short = "Invalid type for ❰List❱" + hints = []+ long = "Explanation: ❰List❱s can optionally document their type with a type annotation, \n\ \like this: \n\@@ -2393,6 +2394,8 @@ where short = "An empty list requires a type annotation" + hints = []+ long = "Explanation: Lists do not require a type annotation if they have at least one \n\ \element: \n\@@ -2420,6 +2423,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr2) + hints = []+ long = "Explanation: Every element in a list must have the same type \n\ \ \n\@@ -2451,49 +2456,12 @@ txt1 = pretty i txt3 = insert expr2 -prettyTypeMessage (InvalidListElement i expr0 _expr1 expr2) =- ErrorMessages {..}- where- short = "List element has the wrong type\n"- <> "\n"- <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr2)-- long =- "Explanation: Every element in the list must have a type matching the type \n\- \annotation at the end of the list \n\- \ \n\- \For example, this is a valid ❰List❱: \n\- \ \n\- \ \n\- \ ┌──────────────────────────┐ \n\- \ │ [1, 2, 3] : List Natural │ Every element in this ❰List❱ is an ❰Natural❱ \n\- \ └──────────────────────────┘ \n\- \ \n\- \ \n\- \.. but this is " <> _NOT <> " a valid ❰List❱: \n\- \ \n\- \ \n\- \ ┌──────────────────────────────┐ \n\- \ │ [1, \"ABC\", 3] : List Natural │ The second element is not an ❰Natural❱ \n\- \ └──────────────────────────────┘ \n\- \ \n\- \ \n\- \Your ❰List❱ elements should have this type: \n\- \ \n\- \" <> txt0 <> "\n\- \ \n\- \... but the element at index #" <> txt1 <> " has this type instead: \n\- \ \n\- \" <> txt3 <> "\n"- where- txt0 = insert expr0- txt1 = pretty i- txt3 = insert expr2- prettyTypeMessage (InvalidSome expr0 expr1 expr2) = ErrorMessages {..} where short = "❰Some❱ argument has the wrong type" + hints = []+ long = "Explanation: The ❰Some❱ constructor expects an argument that is a term, where \n\ \the type of the type of a term must be ❰Type❱ \n\@@ -2536,6 +2504,8 @@ where short = "Invalid field type" + hints = []+ long = "Explanation: Every record type annotates each field with a ❰Type❱, a ❰Kind❱, or \n\ \a ❰Sort❱ like this: \n\@@ -2579,6 +2549,8 @@ where short = "Invalid alternative type" + hints = []+ long = "Explanation: Every union type specifies the type of each alternative, like this:\n\ \ \n\@@ -2636,6 +2608,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1) + hints = []+ long = "Explanation: You can append two ❰List❱s using the ❰#❱ operator, like this: \n\ \ \n\@@ -2673,11 +2647,13 @@ txt0 = insert expr0 txt1 = insert expr1 -prettyTypeMessage (CompletionSchemaMustBeARecord expr0 expr1) = ErrorMessages {..} - where- short = "The completion schema must be a record" +prettyTypeMessage (CompletionSchemaMustBeARecord expr0 expr1) = ErrorMessages {..}+ where+ short = "The completion schema must be a record" - long = + hints = []++ long = "Explanation: You can complete records using the ❰::❱ operator: \n\ \ \n\ \ ┌─────────────────────────────────────────────────────────────────────────┐ \n\@@ -2697,11 +2673,13 @@ txt0 = insert expr0 txt1 = insert expr1 -prettyTypeMessage (InvalidRecordCompletion fieldName expr0) = ErrorMessages {..} - where- short = "Completion schema is missing a field: " <> pretty fieldName+prettyTypeMessage (InvalidRecordCompletion fieldName expr0) = ErrorMessages {..}+ where+ short = "Completion schema is missing a field: " <> pretty fieldName - long = + hints = []++ long = "Explanation: You can complete records using the ❰::❱ operator like this:\n\ \ \n\ \ ┌─────────────────────────────────────────────────────────────────────────┐ \n\@@ -2722,55 +2700,6 @@ txt0 = insert expr0 txt1 = pretty fieldName -prettyTypeMessage (MustUpdateARecord withExpression expression typeExpression) =- ErrorMessages {..}- where- short = "You can only update records"-- long =- "Explanation: You can update records using the ❰with❱ keyword, like this: \n\- \ \n\- \ \n\- \ ┌────────────────────────────────┐ \n\- \ │ { x = { y = 1 } } with x.y = 2 │ \n\- \ └────────────────────────────────┘ \n\- \ \n\- \ \n\- \ ┌────────────────────────────────────────────────────────────┐ \n\- \ │ λ(r : { foo : { bar : Bool } }) → r with foo.bar = False } │ \n\- \ └────────────────────────────────────────────────────────────┘ \n\- \ \n\- \ \n\- \... but you cannot update values that are not records. \n\- \ \n\- \For example, the following expression is " <> _NOT <> " valid: \n\- \ \n\- \ \n\- \ ┌─────────────────┐ \n\- \ │ 1 with x = True │ \n\- \ └─────────────────┘ \n\- \ ⇧ \n\- \ Invalid: Not a record \n\- \ \n\- \ \n\- \────────────────────────────────────────────────────────────────────────────────\n\- \ \n\- \The following expression is not permitted: \n\- \ \n\- \" <> insert withExpression' <> "\n\- \ \n\- \... because the left argument to ❰with❱: \n\- \ \n\- \" <> insert expression <> "\n\- \ \n\- \... is not a record, but is actually a: \n\- \ \n\- \" <> insert typeExpression <> "\n"- where- withExpression' = case withExpression of- With record keys value -> With (Dhall.Core.normalize record) keys value- _ -> withExpression- prettyTypeMessage (MustCombineARecord c expression typeExpression) = ErrorMessages {..} where@@ -2780,6 +2709,8 @@ short = "You can only " <> action <> " records" + hints = emptyRecordTypeHint expression+ long = "Explanation: You can " <> action <> " records using the ❰" <> op <> "❱ operator, like this:\n\ \ \n\@@ -2837,6 +2768,8 @@ where short = "Invalid duplicate field: " <> Dhall.Pretty.Internal.prettyLabel k + hints = []+ long = "Explanation: You can specify a field twice if both fields are themselves \n\ \records, like this: \n\@@ -2894,7 +2827,7 @@ \ \n\ \... which is not a record type \n" where- txt0 = insert (Dhall.Pretty.Internal.escapeLabel True k)+ txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome k) txt1 = insert expr0 txt2 = insert expr1 @@ -2903,6 +2836,8 @@ where short = "❰⩓❱ requires arguments that are record types" + hints = []+ long = "Explanation: You can only use the ❰⩓❱ operator on arguments that are record type\n\ \literals, like this: \n\@@ -2937,61 +2872,12 @@ txt0 = insert expr0 txt1 = insert expr1 -prettyTypeMessage (RecordTypeMismatch const0 const1 expr0 expr1) =- ErrorMessages {..}- where- short = "Record type mismatch"-- long =- "Explanation: You can only use the ❰⩓❱ operator on record types if they are both \n\- \ ❰Type❱s or ❰Kind❱s: \n\- \ \n\- \ \n\- \ ┌─────────────────────────────────────┐ \n\- \ │ { age : Natural } ⩓ { name : Text } │ Valid: Both arguments are ❰Type❱s \n\- \ └─────────────────────────────────────┘ \n\- \ \n\- \ \n\- \ ┌──────────────────────────────────────┐ \n\- \ │ { Input : Type } ⩓ { Output : Type } │ Valid: Both arguments are ❰Kind❱s \n\- \ └──────────────────────────────────────┘ \n\- \ \n\- \ \n\- \... but you cannot combine a ❰Type❱ and a ❰Kind❱: \n\- \ \n\- \ \n\- \ ┌────────────────────────────────────┐ \n\- \ │ { Input : Type } ⩓ { name : Text } │ Invalid: The arguments do not match \n\- \ └────────────────────────────────────┘ \n\- \ \n\- \ \n\- \────────────────────────────────────────────────────────────────────────────────\n\- \ \n\- \You tried to combine the following record type: \n\- \ \n\- \" <> txt0 <> "\n\- \ \n\- \... with this record types: \n\- \ \n\- \" <> txt1 <> "\n\- \ \n\- \... but the former record type is a: \n\- \ \n\- \" <> txt2 <> "\n\- \ \n\- \... but the latter record type is a: \n\- \ \n\- \" <> txt3 <> "\n"- where- txt0 = insert expr0- txt1 = insert expr1- txt2 = insert const0- txt3 = insert const1- prettyTypeMessage (DuplicateFieldCannotBeMerged ks) = ErrorMessages {..} where short = "Duplicate field cannot be merged: " <> pretty (toPath ks) + hints = []+ long = "Explanation: Duplicate fields are only allowed if they are both records and if \n\ \the two records can be recursively merged without collisions. \n\@@ -3046,7 +2932,7 @@ \ \n\ \" <> txt1 <> "\n" where- txt0 = insert (Dhall.Pretty.Internal.escapeLabel True (NonEmpty.head ks))+ txt0 = insert (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome (NonEmpty.head ks)) txt1 = insert (toPath ks) @@ -3054,6 +2940,8 @@ where short = "Field collision on: " <> pretty (toPath ks) + hints = []+ long = "Explanation: You can recursively merge records using the ❰∧❱ operator: \n\ \ \n\@@ -3118,6 +3006,8 @@ where short = "Field type collision on: " <> pretty (toPath ks) + hints = []+ long = "Explanation: You can recursively merge record types using the ❰⩓❱ operator, like\n\ \this: \n\@@ -3159,6 +3049,8 @@ where short = "❰merge❱ expects a record of handlers" + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3214,6 +3106,8 @@ where short = "❰merge❱ expects a union or an ❰Optional❱" + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3264,6 +3158,8 @@ where short = "Unused handler" + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3304,9 +3200,11 @@ where short = case Data.Set.toList ks of [] -> "Missing handler: " <> Dhall.Pretty.Internal.prettyLabel exemplar- xs@(_:_) -> "Missing handlers: " <> (Pretty.hsep . Pretty.punctuate Pretty.comma + xs@(_:_) -> "Missing handlers: " <> (Pretty.hsep . Pretty.punctuate Pretty.comma . map Dhall.Pretty.Internal.prettyLabel $ exemplar:xs) + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3348,6 +3246,8 @@ where short = "An empty ❰merge❱ requires a type annotation" + hints = []+ long = "Explanation: A ❰merge❱ does not require a type annotation if the union has at \n\ \least one alternative, like this \n\@@ -3380,6 +3280,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2) + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3440,6 +3342,8 @@ where short = "Disallowed handler type" + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3481,70 +3385,6 @@ \ \n\ \" <> insert variable <> "\n" -prettyTypeMessage (InvalidHandlerOutputType expr0 expr1 expr2) =- ErrorMessages {..}- where- short = "Wrong handler output type\n"- <> "\n"- <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr1 expr2)-- long =- "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\- \a record with one handler per alternative, like this: \n\- \ \n\- \ \n\- \ ┌─────────────────────────────────────────────────────────────────┐ \n\- \ │ let union = < Left : Natural | Right : Bool >.Left 2 │ \n\- \ │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │ \n\- \ │ in merge handlers union : Bool │ \n\- \ └─────────────────────────────────────────────────────────────────┘ \n\- \ \n\- \ \n\- \... as long as the output type of each handler function matches the declared \n\- \type of the result: \n\- \ \n\- \ \n\- \ ┌───────────────────────────────────────────────────────────┐ \n\- \ │ handlers : { Left : Natural → Bool, Right : Bool → Bool } │ \n\- \ └───────────────────────────────────────────────────────────┘ \n\- \ ⇧ ⇧ \n\- \ These output types ... \n\- \ \n\- \ ... must match the declared type of the ❰merge❱ \n\- \ ⇩ \n\- \ ┌─────────────────────────────┐ \n\- \ │ merge handlers union : Bool │ \n\- \ └─────────────────────────────┘ \n\- \ \n\- \ \n\- \For example, the following expression is " <> _NOT <> " valid: \n\- \ \n\- \ \n\- \ ┌──────────────────────────────────────────────────────────────────┐ \n\- \ │ let union = < Left : Natural | Right : Bool >.Left 2 │ \n\- \ │ let handlers = { Left = Natural/even, Right = λ(x : Bool) → x } │ \n\- \ │ in merge handlers union : Text │ \n\- \ └──────────────────────────────────────────────────────────────────┘ \n\- \ ⇧ \n\- \ Invalid: Doesn't match output of either handler\n\- \ \n\- \ \n\- \Your handler for the following alternative: \n\- \ \n\- \" <> txt0 <> "\n\- \ \n\- \... needs to return an output value of type: \n\- \ \n\- \" <> txt1 <> "\n\- \ \n\- \... but actually returns an output value of a different type: \n\- \ \n\- \" <> txt2 <> "\n"- where- txt0 = insert expr0- txt1 = insert expr1- txt2 = insert expr2- prettyTypeMessage (HandlerOutputTypeMismatch key0 expr0 key1 expr1) = ErrorMessages {..} where@@ -3552,6 +3392,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1) + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3606,6 +3448,8 @@ where short = "Handler for "<> Dhall.Pretty.Internal.prettyLabel k <> " is not a function" + hints = []+ long = "Explanation: You can ❰merge❱ the alternatives of a union or an ❰Optional❱ using \n\ \a record with one handler per alternative, like this: \n\@@ -3643,10 +3487,12 @@ txt0 = insert k txt1 = insert expr0 -prettyTypeMessage (MustMapARecord _expr0 _expr1) = ErrorMessages {..}+prettyTypeMessage (MustMapARecord provided _providedType) = ErrorMessages {..} where short = "❰toMap❱ expects a record value" + hints = emptyRecordTypeHint provided+ long = "Explanation: You can apply ❰toMap❱ to any homogenous record, like this: \n\ \ \n\@@ -3675,6 +3521,8 @@ where short = "❰toMap❱ expects a record of kind ❰Type❱" + hints = []+ long = "Explanation: You can apply ❰toMap❱ to any homogenous record of kind ❰Type❱, like\n\ \ this: \n\@@ -3701,6 +3549,8 @@ where short = "❰toMap❱ expects a homogenous record" + hints = []+ long = "Explanation: You can apply ❰toMap❱ to any homogenous record, like this: \n\ \ \n\@@ -3728,6 +3578,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1) + hints = []+ long = "Explanation: a ❰toMap❱ application has been annotated with a type that doesn't \n\ \match its inferred type. \n"@@ -3739,6 +3591,8 @@ <> "\n" <> insert expr + hints = []+ long = "Explanation: A ❰toMap❱ applied to an empty record must have a type annotation: \n\ \that matches a list of key-value pairs, like this \n\@@ -3756,6 +3610,8 @@ where short = "An empty ❰toMap❱ requires a type annotation" + hints = []+ long = "Explanation: A ❰toMap❱ does not require a type annotation if the record has at \n\ \least one field, like this \n\@@ -3779,6 +3635,8 @@ where short = "Not a record or a union" + hints = []+ long = "Explanation: You can only access fields on records or unions, like this: \n\ \ \n\@@ -3837,6 +3695,8 @@ where short = "Not a record" + hints = []+ long = "Explanation: You can only project fields on records, like this: \n\ \ \n\@@ -3898,6 +3758,8 @@ where short = "Selector is not a record type" + hints = []+ long = "Explanation: You can project by an expression if that expression is a record \n\ \type: \n\@@ -3953,10 +3815,44 @@ where txt = insert expr +prettyTypeMessage (DuplicateProjectionLabel k) = ErrorMessages {..}+ where+ short = "Duplicate projection label: " <> Dhall.Pretty.Internal.prettyLabel k++ hints = []++ long =+ "Explanation: You can only specify a label once when projecting a record's fields\n\+ \by label. For example, this is valid: \n\+ \ \n\+ \ \n\+ \ ┌─────────────────────────────────────────┐ \n\+ \ │ { x = 1.1, y = 2.4, z = -0.3 }.{ x, y } │ \n\+ \ └─────────────────────────────────────────┘ \n\+ \ \n\+ \ \n\+ \... but this is not valid: \n\+ \ \n\+ \ \n\+ \ ┌─────────────────────────────────────────┐ \n\+ \ │ { x = 1.1, y = 2.4, z = -0.3 }.{ y, y } │ \n\+ \ └─────────────────────────────────────────┘ \n\+ \ ⇧ \n\+ \ Invalid: the label ❰y❱ appears twice \n\+ \ \n\+ \ \n\+ \You tried to project the following field twice: \n\+ \ \n\+ \" <> txt0 <> "\n"+ where+ txt0 = insert k+ prettyTypeMessage (MissingField k expr0) = ErrorMessages {..} where short = "Missing record field: " <> Dhall.Pretty.Internal.prettyLabel k + hints = []+ long = "Explanation: You can only access fields on records, like this: \n\ \ \n\@@ -3999,6 +3895,8 @@ where short = "Missing constructor: " <> Dhall.Pretty.Internal.prettyLabel k + hints = []+ long = "Explanation: You can access constructors from unions, like this: \n\ \ \n\@@ -4039,6 +3937,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr2 expr3) + hints = []+ long = "Explanation: You can project a subset of fields from a record by specifying the \n\ \desired type of the final record, like this: \n\@@ -4086,6 +3986,8 @@ <> "\n" <> Dhall.Diff.doc (Dhall.Diff.diffNormalized expr0 expr1) + hints = []+ long = "Explanation: You can assert at type-checking time that two terms are equal if \n\ \they have the same normal form, like this: \n\@@ -4149,6 +4051,8 @@ where short = "Not an equivalence\n" + hints = []+ long = "Explanation: The type annotation for an ❰assert❱ must evaluate to an equivalence\n\ \of the form ❰x ≡ y❱, like this: \n\@@ -4202,6 +4106,8 @@ where short = "Incomparable expression\n" + hints = []+ long = "Explanation: You can use an ❰assert❱ to compare two terms for equivalence, like \n\ \this: \n\@@ -4233,6 +4139,8 @@ where short = "The two sides of the equivalence have different types" + hints = []+ long = "Explanation: You can use ❰≡❱ to compare two terms of the same type for \n\ \equivalence, like this: \n\@@ -4272,6 +4180,8 @@ where short = "❰with❱ only works on records" + hints = []+ long = "Explanation: You can use ❰with❱ to update a record, like this: \n\ \ \n\@@ -4323,6 +4233,8 @@ where short = "You can only interpolate ❰Text❱" + hints = []+ long = "Explanation: Text interpolation only works on expressions of type ❰Text❱ \n\ \ \n\@@ -4385,6 +4297,8 @@ where short = "❰++❱ only works on ❰Text❱" + hints = []+ long = "Explanation: The ❰++❱ operator expects two arguments that have type ❰Text❱ \n\ \ \n\@@ -4431,6 +4345,8 @@ where short = "❰#❱ only works on ❰List❱s" + hints = []+ long = "Explanation: The ❰#❱ operator expects two arguments that are both ❰List❱s \n\ \ \n\@@ -4461,11 +4377,133 @@ prettyTypeMessage (CantMultiply expr0 expr1) = buildNaturalOperator "*" expr0 expr1 +prettyTypeMessage OptionalWithTypeMismatch = ErrorMessages {..}+ where+ short = "❰with❱ cannot change the type of an ❰Optional❱ value"+ hints = []+ long =+ "Explanation: The ❰with❱ keyword cannot change the type of a value stored inside \n\+ \of a ❰Some❱ constructor \n\+ \ \n\+ \For example, this is a valid use of ❰with❱: \n\+ \ \n\+ \ \n\+ \ The old value has type ❰Natural❱ \n\+ \ ⇩ \n\+ \ ┌───────────────────┐ \n\+ \ │ Some 1 with ? = 2 │ \n\+ \ └───────────────────┘ \n\+ \ ⇧ \n\+ \ ... which matches the type of the new value, which is also\n\+ \ ❰Natural❱ \n\+ \ \n\+ \ \n\+ \... but the following example is not valid: \n\+ \ \n\+ \ \n\+ \ The old value has type ❰Natural❱ \n\+ \ ⇩ \n\+ \ ┌──────────────────────┐ \n\+ \ │ Some 1 with ? = True │ \n\+ \ └──────────────────────┘ \n\+ \ ⇧ \n\+ \ ... but the new value has type ❰Bool❱, which does not \n\+ \ match \n"++prettyTypeMessage NotALabelPath = ErrorMessages {..}+ where+ short = "Use a label to update a record"+ hints = []+ long =+ "Explanation: The ❰with❱ keyword supports updating records by naming the field(s)\n\+ \to update, but you provided a path component of ❰?❱, which only works on \n\+ \❰Optional❱ values and not records. \n\+ \ \n\+ \For example, these are valid uses of ❰with❱ to update a record: \n\+ \ \n\+ \ \n\+ \ ┌──────────────────────┐ \n\+ \ │ { x = 1 } with x = 2 │ \n\+ \ └──────────────────────┘ \n\+ \ \n\+ \ \n\+ \ ┌────────────────────────────────┐ \n\+ \ │ { x = { y = 1 } } with x.y = 2 │ \n\+ \ └────────────────────────────────┘ \n\+ \ \n\+ \ \n\+ \... but the following example is not valid: \n\+ \ \n\+ \ \n\+ \ ┌──────────────────────┐ \n\+ \ │ { x = 1 } with ? = 2 │ \n\+ \ └──────────────────────┘ \n\+ \ ⇧ \n\+ \ This path component is reserved for updating ❰Optional❱ \n\+ \ values and not records \n\+ \ \n\+ \Note that you can update a field named ❰?❱ if you escape the path component, \n\+ \though: \n\+ \ \n\+ \ \n\+ \ ┌────────────────────────┐ \n\+ \ │ { ? = 1 } with `?` = 2 │ \n\+ \ └────────────────────────┘ \n"++prettyTypeMessage (NotAQuestionPath k) = ErrorMessages {..}+ where+ short = "Use ❰?❱ to update an ❰Optional❱ value"+ hints = []+ long =+ "Explanation: The ❰with❱ keyword supports updating ❰Optional❱ values using a path\n\+ \component of ❰?❱, but you provided a path component other than ❰?❱. \n\+ \ \n\+ \For example, these are valid uses of ❰with❱ to update an ❰Optional❱ value: \n\+ \ \n\+ \ \n\+ \ ┌───────────────────┐ \n\+ \ │ Some 1 with ? = 2 │ \n\+ \ └───────────────────┘ \n\+ \ \n\+ \ \n\+ \ ┌─────────────────────────────┐ \n\+ \ │ { x = Some 1 } with x.? = 2 │ \n\+ \ └─────────────────────────────┘ \n\+ \ \n\+ \ \n\+ \... but the following example is not valid: \n\+ \ \n\+ \ \n\+ \ ┌──────────────────────┐ \n\+ \ │ Some 1 with x = True │ \n\+ \ └──────────────────────┘ \n\+ \ ⇧ \n\+ \ This path component should have been ❰?❱ \n\+ \ \n\+ \ \n\+ \────────────────────────────────────────────────────────────────────────────────\n\+ \ \n\+ \You provided this path component: \n\+ \ \n\+ \" <> txt0 <> "\n\+ \ \n\+ \... which perhaps should have been ❰?❱. \n"+ where+ txt0 = insert k++prettyTypeMessage ShowConstructorNotOnUnion = ErrorMessages {..}+ where+ short = "ShowConstructorNotOnUnion"+ hints = []+ long = ""+ buildBooleanOperator :: Pretty a => Text -> Expr s a -> Expr s a -> ErrorMessages buildBooleanOperator operator expr0 expr1 = ErrorMessages {..} where short = "❰" <> txt2 <> "❱ only works on ❰Bool❱s" + hints = []+ long = "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Bool❱\n\ \ \n\@@ -4495,6 +4533,8 @@ where short = "❰" <> txt2 <> "❱ only works on ❰Natural❱s" + hints = []+ long = "Explanation: The ❰" <> txt2 <> "❱ operator expects two arguments that have type ❰Natural❱\n\ \ \n\@@ -4626,8 +4666,6 @@ pure MissingListType MismatchedListElements a b c d -> MismatchedListElements <$> pure a <*> f b <*> f c <*> f d- InvalidListElement a b c d ->- InvalidListElement <$> pure a <*> f b <*> f c <*> f d InvalidListType a -> InvalidListType <$> f a ListLitInvariant ->@@ -4638,8 +4676,6 @@ InvalidPredicate <$> f a <*> f b IfBranchMismatch a b c d -> IfBranchMismatch <$> f a <*> f b <*> f c <*> f d- IfBranchMustBeTerm a b c d ->- IfBranchMustBeTerm <$> pure a <*> f b <*> f c <*> f d InvalidFieldType a b -> InvalidFieldType <$> pure a <*> f b InvalidAlternativeType a b ->@@ -4648,18 +4684,14 @@ ListAppendMismatch <$> f a <*> f b InvalidDuplicateField a b c -> InvalidDuplicateField a <$> f b <*> f c- MustUpdateARecord a b c ->- MustUpdateARecord <$> f a <*> f b <*> f c MustCombineARecord a b c -> MustCombineARecord <$> pure a <*> f b <*> f c- InvalidRecordCompletion a l -> + InvalidRecordCompletion a l -> InvalidRecordCompletion a <$> f l- CompletionSchemaMustBeARecord l r -> + CompletionSchemaMustBeARecord l r -> CompletionSchemaMustBeARecord <$> f l <*> f r CombineTypesRequiresRecordType a b -> CombineTypesRequiresRecordType <$> f a <*> f b- RecordTypeMismatch a b c d ->- RecordTypeMismatch <$> pure a <*> pure b <*> f c <*> f d DuplicateFieldCannotBeMerged a -> pure (DuplicateFieldCannotBeMerged a) FieldCollision a ->@@ -4692,8 +4724,6 @@ DisallowedHandlerType <$> pure a <*> f b <*> f c <*> pure d HandlerOutputTypeMismatch a b c d -> HandlerOutputTypeMismatch <$> pure a <*> f b <*> pure c <*> f d- InvalidHandlerOutputType a b c ->- InvalidHandlerOutputType <$> pure a <*> f b <*> f c MissingMergeType -> pure MissingMergeType HandlerNotAFunction a b ->@@ -4704,6 +4734,8 @@ CantProject <$> pure a <*> f b <*> f c CantProjectByExpression a -> CantProjectByExpression <$> f a+ DuplicateProjectionLabel a ->+ pure (DuplicateProjectionLabel a) MissingField a b -> MissingField <$> pure a <*> f b MissingConstructor a b ->@@ -4738,6 +4770,14 @@ CantAdd <$> f a <*> f b CantMultiply a b -> CantMultiply <$> f a <*> f b+ OptionalWithTypeMismatch ->+ pure OptionalWithTypeMismatch+ NotALabelPath ->+ pure NotALabelPath+ NotAQuestionPath k ->+ pure (NotAQuestionPath k)+ ShowConstructorNotOnUnion ->+ pure ShowConstructorNotOnUnion {-| Newtype used to wrap error messages so that they render with a more detailed explanation of what went wrong@@ -4800,4 +4840,12 @@ toPath :: (Functor list, Foldable list) => list Text -> Text toPath ks = Text.intercalate "."- (Foldable.toList (fmap (Dhall.Pretty.Internal.escapeLabel True) ks))+ (Foldable.toList (fmap (Dhall.Pretty.Internal.escapeLabel AnyLabelOrSome) ks))++duplicateElement :: Ord a => [a] -> Maybe a+duplicateElement = go Data.Set.empty+ where+ go _ [] = Nothing+ go found (x : xs)+ | Data.Set.member x found = Just x+ | otherwise = go (Data.Set.insert x found) xs
@@ -3,14 +3,12 @@ module Dhall.URL where -import Data.Text (Text)+import Data.Text (Text) import Dhall.Syntax (Directory (..), File (..), Scheme (..), URL (..)) -import qualified Network.URI.Encode as URI.Encode- renderComponent :: Text -> Text-renderComponent component = "/" <> URI.Encode.encodeText component+renderComponent component = "/" <> component renderQuery :: Text -> Text renderQuery query = "?" <> query
@@ -1,3 +1,4 @@+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -8,9 +9,10 @@ , snipDoc , insert , _ERROR+ , _WARNING+ , printWarning , Censor(..) , Input(..)- , PossiblyTransitiveInput(..) , Transitivity(..) , OutputMode(..) , Output(..)@@ -19,26 +21,35 @@ , getExpressionAndHeaderFromStdinText , Header(..) , CheckFailed(..)+ , MultipleCheckFailed(..)+ , handleMultipleChecksFailed+ , renderExpression ) where -import Control.Exception (Exception (..))-import Control.Monad.IO.Class (MonadIO (..))-import Data.Bifunctor (first)-import Data.String (IsString)-import Data.Text (Text)-import Data.Text.Prettyprint.Doc (Doc, Pretty)-import Dhall.Parser (Header (..), ParseError)-import Dhall.Pretty (Ann)-import Dhall.Src (Src)-import Dhall.Syntax (Expr, Import)+import Control.Exception (Exception (..))+import Control.Monad.IO.Class (MonadIO (..))+import Data.Bifunctor (first)+import Data.Either (lefts)+import Data.Foldable (toList)+import Data.List.NonEmpty (NonEmpty (..))+import Data.String (IsString)+import Data.Text (Text)+import Dhall.Parser (Header (..), ParseError)+import Dhall.Pretty (Ann, CharacterSet)+import Dhall.Src (Src)+import Dhall.Syntax (Expr, Import)+import Prettyprinter (Doc, Pretty) import qualified Control.Exception import qualified Data.Text import qualified Data.Text.IO-import qualified Data.Text.Prettyprint.Doc as Pretty-import qualified Data.Text.Prettyprint.Doc.Render.Terminal as Pretty.Terminal import qualified Dhall.Parser import qualified Dhall.Pretty+import qualified Prettyprinter as Pretty+import qualified Prettyprinter.Render.Terminal as Pretty.Terminal+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified System.Console.ANSI as ANSI+import qualified System.IO as IO -- | Utility function to cut out the interior of a large text block snip :: Text -> Text@@ -102,6 +113,21 @@ _ERROR :: IsString string => string _ERROR = "\ESC[1;31mError\ESC[0m" +-- | Prefix used for error messages+_WARNING :: IsString string => string+_WARNING = "\ESC[1;33mWarning\ESC[0m"++-- | Output a warning message on stderr.+printWarning :: (MonadIO m) => String -> m ()+printWarning message = do+ let warning =+ "\n"+ <> _WARNING+ <> ": "+ <> message++ liftIO $ IO.hPutStrLn IO.stderr warning+ get :: (String -> Text -> Either ParseError a) -> Censor@@ -112,13 +138,13 @@ case input of Input_ (InputFile file) -> Data.Text.IO.readFile file Input_ StandardInput -> Data.Text.IO.getContents- StdinText text -> pure text+ StdinText _ text -> pure text let name = case input of Input_ (InputFile file) -> file Input_ StandardInput -> "(input)"- StdinText _ -> "(input)"+ StdinText inputName _ -> inputName let result = parser name inText @@ -140,17 +166,14 @@ data Censor = NoCensor | Censor -- | Path to input-data Input = StandardInput | InputFile FilePath+data Input = StandardInput | InputFile FilePath deriving (Eq) -- | Path to input or raw input text, necessary since we can't read STDIN twice-data InputOrTextFromStdin = Input_ Input | StdinText Text--{-| For utilities that may want to process transitive dependencies, like- @dhall freeze@--}-data PossiblyTransitiveInput- = NonTransitiveStandardInput- | PossiblyTransitiveInputFile FilePath Transitivity+data InputOrTextFromStdin+ = Input_ Input+ | StdinText String Text+ -- ^ @StdinText name text@ where name is a user-friendly name describing the+ -- input expression, used in parsing error messages {-| Specifies whether or not an input's transitive dependencies should also be processed. Transitive dependencies are restricted to relative file imports.@@ -170,15 +193,25 @@ -} data OutputMode = Write | Check +-- | A check failure corresponding to a single input.+-- This type is intended to be used with 'MultipleCheckFailed' for error+-- reporting.+newtype CheckFailed = CheckFailed { input :: Input }+ -- | Exception thrown when the @--check@ flag to a command-line subcommand fails-data CheckFailed = CheckFailed { command :: Text, modified :: Text }+data MultipleCheckFailed = MultipleCheckFailed+ { command :: Text+ , modified :: Text+ , inputs :: NonEmpty Input+ } -instance Exception CheckFailed+instance Exception MultipleCheckFailed -instance Show CheckFailed where- show CheckFailed{..} =- _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed\n\- \\n\+instance Show MultipleCheckFailed where+ show MultipleCheckFailed{..} =+ _ERROR <> ": ❰dhall " <> command_ <> " --check❱ failed on:\n\+ \\n" <> files <>+ "\n\ \You ran ❰dhall " <> command_ <> " --check❱, but the input appears to have not\n\ \been " <> modified_ <> " before, or was changed since the last time the input\n\ \was " <> modified_ <> ".\n"@@ -187,6 +220,32 @@ command_ = Data.Text.unpack command + files = unlines . map format $ toList inputs++ format input = case input of+ StandardInput -> "↳ (stdin)"+ InputFile file -> "↳ " <> file++-- | Run IO for multiple inputs, then collate all the check failures before+-- throwing if there was any failure+handleMultipleChecksFailed+ :: (Foldable t, Traversable t)+ => Text+ -> Text+ -> (a -> IO (Either CheckFailed ()))+ -> t a+ -> IO ()+handleMultipleChecksFailed command modified f xs = post =<< mapM f xs+ where+ post results =+ case lefts (toList results) of+ [] -> pure ()+ cf:cfs -> Control.Exception.throwIO $ MultipleCheckFailed+ { command+ , modified+ , inputs = fmap input (cf:|cfs)+ }+ -- | Convenient utility for retrieving an expression getExpression :: Censor -> Input -> IO (Expr Src Import) getExpression censor = get Dhall.Parser.exprFromText censor . Input_@@ -199,6 +258,34 @@ -- | Convenient utility for retrieving an expression along with its header from -- | text already read from STDIN (so it's not re-read) getExpressionAndHeaderFromStdinText- :: Censor -> Text -> IO (Header, Expr Src Import)-getExpressionAndHeaderFromStdinText censor =- get Dhall.Parser.exprAndHeaderFromText censor . StdinText+ :: Censor -> String -> Text -> IO (Header, Expr Src Import)+getExpressionAndHeaderFromStdinText censor inputName =+ get Dhall.Parser.exprAndHeaderFromText censor . StdinText inputName++{-| Convenient utility to output an expression either to a file+ or to stdout.+-}+renderExpression :: Pretty a => CharacterSet -> Bool -> Maybe FilePath -> Expr Src a -> IO ()+renderExpression characterSet plain output expression = do+ let document = Dhall.Pretty.prettyCharacterSet characterSet expression++ let stream = Dhall.Pretty.layout document++ case output of+ Nothing -> do+ supportsANSI <- ANSI.hSupportsANSI IO.stdout++ let ansiStream =+ if supportsANSI && not plain+ then fmap Dhall.Pretty.annToAnsiStyle stream+ else Pretty.unAnnotateS stream++ Pretty.Terminal.renderIO IO.stdout ansiStream++ Data.Text.IO.putStrLn ""++ Just file_ ->+ IO.withFile file_ IO.WriteMode $ \h -> do+ Pretty.Text.renderIO h stream++ Data.Text.IO.hPutStrLn h ""
@@ -13,21 +13,22 @@ module Dhall.Test.Dhall where -import Control.Exception (SomeException, try)-import Data.Fix (Fix (..))-import Data.Functor.Classes (Eq1(..), Show1(..))-import Data.List.NonEmpty (NonEmpty (..))-import Data.Maybe (isJust)-import Data.Scientific (Scientific)-import Data.Sequence (Seq)-import Data.Text (Text)-import Data.Vector (Vector)-import Data.Void (Void)-import Dhall (FromDhall, ToDhall)-import Dhall.Core (Expr (..))-import GHC.Generics (Generic, Rep)-import Numeric.Natural (Natural)-import System.Timeout (timeout)+import Control.Exception (SomeException, throwIO, try)+import Data.Either.Validation (validationToEither)+import Data.Fix (Fix (..))+import Data.Functor.Classes (Eq1 (..), Show1 (..))+import Data.List.NonEmpty (NonEmpty (..))+import Data.Maybe (isJust)+import Data.Scientific (Scientific)+import Data.Sequence (Seq)+import Data.Text (Text)+import Data.Vector (Vector)+import Data.Void (Void)+import Dhall (FromDhall, ToDhall)+import Dhall.Core (Expr (..))+import GHC.Generics (Generic, Rep)+import Numeric.Natural (Natural)+import System.Timeout (timeout) import Test.Tasty import Test.Tasty.HUnit @@ -43,7 +44,7 @@ = LitF Natural | AddF expr expr | MulF expr expr- deriving (Eq, Functor, Generic, FromDhall, Show)+ deriving (Eq, Functor, Generic, FromDhall, ToDhall, Show) instance Eq1 ExprF where liftEq _ (LitF aL) (LitF aR) = aL == aR@@ -91,14 +92,15 @@ let expectedMsg = "\ESC[1;31mError\ESC[0m: Invalid Dhall.Decoder \n\ \ \n\- \Every Decoder must provide an extract function that succeeds if an expression \n\- \matches the expected type. You provided a Decoder that disobeys this contract \n\+ \Every Decoder must provide an extract function that does not fail with a type \n\+ \error if an expression matches the expected type. You provided a Decoder that \n\+ \disobeys this contract \n\ \ \n\ \The Decoder provided has the expected dhall type: \n\ \ \n\ \↳ { bar : Natural, foo : Text }\n\ \ \n\- \and it couldn't extract a value from the well-typed expression: \n\+ \and it threw a type error during extraction from the well-typed expression: \n\ \ \n\ \↳ { bar = 0, foo = \"foo\" }\n\ \ \n"@@ -141,6 +143,11 @@ shouldHaveWorkingRecursiveFromDhall = testGroup "recursive FromDhall instance" [ testCase "works for a recursive expression" $ do actual <- Dhall.input Dhall.auto "./tests/recursive/expr0.dhall"++ expected @=? actual+ , testCase "roundtrips (one-way)" $ do+ let expr = Dhall.embed Dhall.inject expected+ actual <- either throwIO pure . validationToEither . Dhall.extract Dhall.auto $ expr expected @=? actual , testCase "passes a shadowing sanity check" $ do
@@ -2,21 +2,19 @@ module Dhall.Test.Diff where -import Data.Text (Text)-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+import Data.Text (Text)+import Test.Tasty (TestTree) -import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc.Render.Text as Pretty.Text-import qualified Dhall.Core as Core-import qualified Dhall.Diff as Diff-import qualified Dhall.Parser as Parser+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO+import qualified Dhall.Core as Core+import qualified Dhall.Diff as Diff+import qualified Dhall.Parser as Parser import qualified Dhall.Pretty-import qualified Dhall.Test.Util as Test.Util-import qualified Test.Tasty as Tasty-import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Dhall.Test.Util as Test.Util+import qualified Prettyprinter.Render.Text as Pretty.Text+import qualified Test.Tasty as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle diffDirectory :: FilePath
@@ -0,0 +1,149 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedLists #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.DirectoryTree (tests) where++import Control.Monad+import Data.Either (partitionEithers)+import Data.Either.Validation+import Dhall.DirectoryTree+import Lens.Micro (set)+import System.FilePath ((</>))+import Test.Tasty+import Test.Tasty.HUnit++import qualified Data.List+import qualified Data.Text.IO+import qualified Dhall+import qualified Dhall.Core+import qualified System.Directory as Directory+import qualified System.FilePath as FilePath+import qualified System.PosixCompat.Files as Files++tests :: TestTree+tests = testGroup "to-directory-tree"+ [ testGroup "fixpointed"+ [ fixpointedType+ , fixpointedEmpty+ , fixpointedSimple+ , fixpointedAllowPathSeparators+#ifndef mingw32_HOST_OS+ , fixpointedPermissions+ , fixpointedUserGroup+#endif+ ]+ ]++fixpointedType :: TestTree+fixpointedType = testCase "Type is as expected" $ do+ let file = "./tests/to-directory-tree/type.dhall"+ ref <- Dhall.inputExpr file+ expected' <- case directoryTreeType of+ Failure e -> assertFailure $ show e+ Success expr -> return expr+ assertBool "Type mismatch" $ expected' `Dhall.Core.judgmentallyEqual` ref++fixpointedEmpty :: TestTree+fixpointedEmpty = testCase "empty" $ do+ let outDir = "./tests/to-directory-tree/fixpoint-empty.out"+ path = "./tests/to-directory-tree/fixpoint-empty.dhall"+ entries <- runDirectoryTree False outDir path+ entries @?= [Directory outDir]++fixpointedSimple :: TestTree+fixpointedSimple = testCase "simple" $ do+ let outDir = "./tests/to-directory-tree/fixpoint-simple.out"+ path = "./tests/to-directory-tree/fixpoint-simple.dhall"+ entries <- runDirectoryTree False outDir path+ entries @?= Data.List.sort+ [ Directory outDir+ , File $ outDir </> "file"+ , Directory $ outDir </> "directory"+ ]++fixpointedAllowPathSeparators :: TestTree+fixpointedAllowPathSeparators = testCase "allow-path-separators" $ do+ let outDir = "./tests/to-directory-tree/fixpoint-allow-path-separators.out"+ path = "./tests/to-directory-tree/fixpoint-allow-path-separators.dhall"+ entries <- runDirectoryTree True outDir path+ entries @?= Data.List.sort+ [ Directory outDir+ , Directory $ outDir </> "non-existent-1"+ , File $ outDir </> "non-existent-1" </> "file"+ , Directory $ outDir </> "non-existent-2"+ , Directory $ outDir </> "non-existent-2" </> "directory"+ ]++{-+This test is disabled on Windows as it fails due to limitations of the :+ expected: 448+ but got: 438+-}+fixpointedPermissions :: TestTree+fixpointedPermissions = testCase "permissions" $ do+ let outDir = "./tests/to-directory-tree/fixpoint-permissions.out"+ path = "./tests/to-directory-tree/fixpoint-permissions.dhall"+ entries <- runDirectoryTree False outDir path+ entries @?=+ [ Directory outDir+ , File $ outDir </> "file"+ ]+ s <- Files.getFileStatus $ outDir </> "file"+ let mode = Files.fileMode s `Files.intersectFileModes` Files.accessModes+ prettyFileMode mode @?= prettyFileMode Files.ownerModes++fixpointedUserGroup :: TestTree+fixpointedUserGroup = testCase "user and group" $ do+ let file = "./tests/to-directory-tree/fixpoint-usergroup.dhall"+ expr <- Dhall.inputExpr file+ entries <- decodeDirectoryTree expr+ entries @?=+ [ TextFileEntry $ Entry+ { entryName = "ids"+ , entryContent = ""+ , entryUser = Just (UserId 0)+ , entryGroup = Just (GroupId 0)+ , entryMode = Nothing+ }+ , TextFileEntry $ Entry+ { entryName = "names"+ , entryContent = ""+ , entryUser = Just (UserName "user")+ , entryGroup = Just (GroupName "group")+ , entryMode = Nothing+ }+ ]++runDirectoryTree :: Bool -> FilePath -> FilePath -> IO [WalkEntry]+runDirectoryTree allowSeparators outDir path = do+ doesOutDirExist <- Directory.doesDirectoryExist outDir+ when doesOutDirExist $+ Directory.removeDirectoryRecursive outDir+ Directory.createDirectoryIfMissing True outDir++ text <- Data.Text.IO.readFile path+ let inputSettings+ = set Dhall.rootDirectory (FilePath.takeDirectory path)+ . set Dhall.sourceName path+ $ Dhall.defaultInputSettings+ expr <- Dhall.inputExprWithSettings inputSettings text++ toDirectoryTree allowSeparators outDir $ Dhall.Core.denote expr++ Data.List.sort <$> walkFsTree outDir++data WalkEntry+ = Directory FilePath+ | File FilePath+ deriving (Eq, Ord, Show)++walkFsTree :: FilePath -> IO [WalkEntry]+walkFsTree dir = do+ entries <- Directory.listDirectory dir+ (ds, fs) <- fmap partitionEithers $ forM entries $ \path -> do+ let path' = dir </> path+ isDirectory <- Directory.doesDirectoryExist path'+ return $ if isDirectory then Left path' else Right (File path')+ entries' <- traverse walkFsTree ds+ return $ Directory dir : fs <> concat entries'
@@ -7,17 +7,16 @@ import Dhall.Pretty (CharacterSet (..)) import Test.Tasty (TestTree) -import qualified Control.Monad as Monad-import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text as Doc.Render.Text-import qualified Dhall.Core as Core-import qualified Dhall.Parser as Parser-import qualified Dhall.Pretty as Pretty-import qualified Dhall.Test.Util as Test.Util-import qualified Test.Tasty as Tasty-import qualified Test.Tasty.Silver as Tasty.Silver+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO+import qualified Dhall.Core as Core+import qualified Dhall.Parser as Parser+import qualified Dhall.Pretty as Pretty+import qualified Dhall.Test.Util as Test.Util+import qualified Prettyprinter as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty as Tasty+import qualified Test.Tasty.Silver as Tasty.Silver import qualified Turtle getTests :: IO TestTree@@ -27,7 +26,7 @@ let skip = [ "./tests/format/asciiA.dhall" ] - Monad.guard (path `notElem` skip)+ path `Test.Util.pathNotIn` skip return path
@@ -4,9 +4,7 @@ import Data.Text (Text) import Dhall.Freeze (Intent (..), Scope (..))-import Prelude hiding (FilePath) import Test.Tasty (TestTree)-import Turtle (FilePath) import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO@@ -18,19 +16,30 @@ import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle -freezeDirectory :: FilePath-freezeDirectory = "./tests/freeze"+freezeDirectoryCached :: FilePath+freezeDirectoryCached = "./tests/freeze/cached" +freezeDirectorySecure :: FilePath+freezeDirectorySecure = "./tests/freeze/secure"+ getTests :: IO TestTree getTests = do- freezeTests <- Test.Util.discover (Turtle.chars <* "A.dhall") freezeTest (Turtle.lstree freezeDirectory)+ freezeCachedTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+ (freezeTest freezeDirectoryCached Cache)+ (Turtle.lstree freezeDirectoryCached)+ freezeSecureTests <- Test.Util.discover (Turtle.chars <* "A.dhall")+ (freezeTest freezeDirectorySecure Secure)+ (Turtle.lstree freezeDirectorySecure) - let testTree = Tasty.testGroup "freeze tests" [ freezeTests ]+ let testTree = Tasty.testGroup "freeze tests"+ [ Tasty.testGroup "cached" [freezeCachedTests]+ , Tasty.testGroup "secure" [freezeSecureTests]+ ] return testTree -freezeTest :: Text -> TestTree-freezeTest prefix =+freezeTest :: FilePath -> Intent -> Text -> TestTree+freezeTest dir intent prefix = Tasty.HUnit.testCase (Text.unpack prefix) $ do let inputFile = Text.unpack (prefix <> "A.dhall") let outputFile = Text.unpack (prefix <> "B.dhall")@@ -39,7 +48,7 @@ parsedInput <- Core.throws (Parser.exprFromText mempty inputText) - actualExpression <- Freeze.freezeExpression (Turtle.encodeString freezeDirectory) AllImports Cache parsedInput+ actualExpression <- Freeze.freezeExpression dir AllImports intent parsedInput let actualText = Core.pretty actualExpression <> "\n"
@@ -1,17 +1,16 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-} module Dhall.Test.Import where import Control.Exception (SomeException) import Data.Text (Text)-import Dhall.Import (MissingImports (..))-import Dhall.Parser (SourcedException (..))-import Prelude hiding (FilePath)+import Data.Void (Void)+import System.FilePath ((</>)) import Test.Tasty (TestTree)-import Turtle (FilePath, (</>)) import qualified Control.Exception as Exception-import qualified Control.Monad as Monad import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO@@ -19,13 +18,18 @@ import qualified Dhall.Import as Import import qualified Dhall.Parser as Parser import qualified Dhall.Test.Util as Test.Util-import qualified Network.HTTP.Client as HTTP-import qualified Network.HTTP.Client.TLS as HTTP import qualified System.FilePath as FilePath+import qualified System.IO.Temp as Temp import qualified Test.Tasty as Tasty import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle +#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Network.HTTP.Client as HTTP+import qualified Network.HTTP.Client.TLS as HTTP+#endif++ importDirectory :: FilePath importDirectory = "./dhall-lang/tests/import" @@ -44,17 +48,58 @@ , importDirectory </> "success/unit/asLocation/RemoteChain2A.dhall" , importDirectory </> "success/unit/asLocation/RemoteChain3A.dhall" , importDirectory </> "success/unit/asLocation/RemoteChainMissingA.dhall"++ -- Skip all tests that reference httpbin.org to avoid clobbering+ -- their servers. These should eventually be replaced by tests+ -- that depend on an equivalent endpoint on test.dhall-lang.org+ -- instead of httpbin.org.+ , importDirectory </> "failure/customHeadersUsingBoundVariable.dhall"+ , importDirectory </> "failure/originHeadersFromRemote.dhall"+ , importDirectory </> "failure/originHeadersFromRemoteENV.dhall"+ , importDirectory </> "success/customHeadersA.dhall"+ , importDirectory </> "success/noHeaderForwardingA.dhall"+ , importDirectory </> "success/success/originHeadersA.dhall"+ , importDirectory </> "success/originHeadersENV.dhall"+ , importDirectory </> "success/originHeadersImportA.dhall"+ , importDirectory </> "success/originHeadersImportENV.dhall"+ , importDirectory </> "success/originHeadersImportFromEnvA.dhall"+ , importDirectory </> "success/originHeadersImportFromEnvENV.dhall"+ , importDirectory </> "success/originHeadersOverrideA.dhall"+ , importDirectory </> "success/originHeadersOverrideENV.dhall" ] - successTests <- Test.Util.discover (Turtle.chars <> "A.dhall") successTest (do+ successTests <- Test.Util.discover (Turtle.chars <* "A.dhall") successTest (do path <- Turtle.lstree (importDirectory </> "success") - Monad.guard (path `notElem` flakyTests)+ path `Test.Util.pathNotIn` flakyTests return path ) - failureTests <- Test.Util.discover (Turtle.chars <> ".dhall") failureTest (Turtle.lstree (importDirectory </> "failure"))+ failureTests <- Test.Util.discover (Turtle.chars <* ".dhall") failureTest (do+ path <- Turtle.lstree (importDirectory </> "failure") + let expectedSuccesses =+ [ importDirectory </> "failure/unit/DontRecoverCycle.dhall"+ , importDirectory </> "failure/unit/DontRecoverTypeError.dhall"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+ -- We attempt to simulate test.dhall-lang.org, but even so+ -- some tests unexpectedly succeed due to the inadequacy of+ -- the simulation+ , importDirectory </> "failure/unit/cors/OnlySelf.dhall"+ , importDirectory </> "failure/unit/cors/OnlyOther.dhall"+ , importDirectory </> "failure/unit/cors/Null.dhall"+ , importDirectory </> "failure/unit/cors/TwoHops.dhall"+ , importDirectory </> "failure/unit/cors/Empty.dhall"+ , importDirectory </> "failure/unit/cors/NoCORS.dhall"+ , importDirectory </> "failure/originHeadersFromRemote.dhall"+#endif+ ]++ path `Test.Util.pathNotIn` expectedSuccesses+ "ENV.dhall" `Test.Util.pathNotSuffixOf` path++ return path )+ let testTree = Tasty.testGroup "import tests" [ successTests@@ -64,74 +109,131 @@ return testTree successTest :: Text -> TestTree-successTest path = do- let pathString = Text.unpack path+successTest prefix = do+ let inputPath = Text.unpack (prefix <> "A.dhall") - let directoryString = FilePath.takeDirectory pathString+ let expectedPath = Text.unpack (prefix <> "B.dhall") - let expectedFailures = []+ let directoryString = FilePath.takeDirectory inputPath - Test.Util.testCase path expectedFailures (do+ let expectedFailures =+ [+ -- Importing relative to the home directory works, but I'm too+ -- lazy to mock the home directory for testing purposes+ importDirectory </> "success/unit/ImportRelativeToHome"+#if !(defined(WITH_HTTP) && defined(NETWORK_TESTS))+ , importDirectory </> "success/originHeadersImportFromEnv"+ , importDirectory </> "success/originHeadersImport"+ , importDirectory </> "success/originHeadersOverride"+ , importDirectory </> "success/unit/asLocation/RemoteChainEnv"+#endif+ ] - text <- Text.IO.readFile pathString+ Test.Util.testCase prefix expectedFailures (do - actualExpr <- Core.throws (Parser.exprFromText mempty text)+ text <- Text.IO.readFile inputPath - let originalCache = "dhall-lang/tests/import/cache"+ expectedText <- Text.IO.readFile expectedPath - let setCache = Turtle.export "XDG_CACHE_HOME"+ actualExpr <- Core.throws (Parser.exprFromText mempty text) - let unsetCache = Turtle.unset "XDG_CACHE_HOME"+ expectedExpr <- Core.throws (Parser.exprFromText mempty expectedText) + let originalCache = "dhall-lang/tests/import/cache"++#if defined(WITH_HTTP) && defined(NETWORK_TESTS) let httpManager = HTTP.newManager HTTP.tlsManagerSettings { HTTP.managerResponseTimeout = HTTP.responseTimeoutMicro (120 * 1000 * 1000) }++ let status =+ Import.makeEmptyStatus+ httpManager+ (pure Import.envOriginHeaders)+ directoryString+#else+ let status = Import.emptyStatus directoryString+#endif+ let load = State.evalStateT (Test.Util.loadWith actualExpr)- (Import.emptyStatusWithManager httpManager directoryString)+ status - let usesCache = [ "hashFromCacheA.dhall"- , "unit/asLocation/HashA.dhall"- , "unit/IgnorePoisonedCacheA.dhall"]+ let usesCache = [ "hashFromCache"+ , "unit/asLocation/Hash"+ , "unit/IgnorePoisonedCache"+ , "unit/DontCacheIfHash"+ ] - let endsIn path' = not $ null $ Turtle.match (Turtle.ends path') path+ let endsIn path' =+ not (null (Turtle.match (Turtle.ends path') (Test.Util.toDhallPath prefix))) let buildNewCache = do- tempdir <- Turtle.mktempdir "/tmp" "dhall-cache"- Turtle.liftIO $ Turtle.cptree originalCache tempdir- return tempdir+ tempdir <- Turtle.managed (Temp.withSystemTempDirectory "dhall-cache")+ Turtle.liftIO (Turtle.cptree originalCache tempdir)+ return tempdir - let runTest =+ let cacheSetup = if any endsIn usesCache- then Turtle.runManaged $ do+ then do cacheDir <- buildNewCache- setCache $ Turtle.format Turtle.fp cacheDir- _ <- Turtle.liftIO load- unsetCache- else do- _ <- load++ let set = do+ m <- Turtle.need "XDG_CACHE_HOME"++ Turtle.export "XDG_CACHE_HOME" (Turtle.format Turtle.fp cacheDir)++ return m++ let reset Nothing = do+ Turtle.unset "XDG_CACHE_HOME"+ reset (Just x) = do+ Turtle.export "XDG_CACHE_HOME" x++ _ <- Turtle.managed (Exception.bracket set reset) return ()+ else pure () - let handler :: SomeException -> IO ()+ let setup = cacheSetup >> Test.Util.managedTestEnvironment prefix++ let resolve = Turtle.with setup (const load)++ let handler :: SomeException -> IO (Core.Expr Parser.Src Void) handler exception = Tasty.HUnit.assertFailure (show exception) - Exception.handle handler runTest+ actualResolved <- Exception.handle handler resolve - return () )+ expectedResolved <- Import.assertNoImports expectedExpr + let actual = Core.normalize actualResolved :: Core.Expr Void Void++ let expected = Core.normalize expectedResolved :: Core.Expr Void Void++ let message =+ "The imported expression did not match the expected output"++ Tasty.HUnit.assertEqual message expected actual)+ failureTest :: Text -> TestTree-failureTest path = do+failureTest prefix = do+ let path = prefix <> ".dhall"+ let pathString = Text.unpack path Tasty.HUnit.testCase pathString (do- text <- Text.IO.readFile pathString+ actualExpr <- do+ Core.throws (Parser.exprFromText mempty (Test.Util.toDhallPath path)) - actualExpr <- Core.throws (Parser.exprFromText mempty text)+ let setup = Test.Util.managedTestEnvironment prefix - Exception.catch- (do _ <- Test.Util.load actualExpr+ let run = Exception.catch @SomeException+ (Test.Util.load actualExpr >> return True)+ (\_ -> return False) - fail "Import should have failed, but it succeeds")- (\(SourcedException _ (MissingImports _)) -> pure ()) )+ succeeded <- Turtle.with setup (const run)++ if succeeded+ then fail "Import should have failed, but it succeeds"+ else return () )
@@ -4,21 +4,19 @@ import Data.Text (Text) import Dhall.Parser (Header (..))-import Prelude hiding (FilePath) import Test.Tasty (TestTree)-import Turtle (FilePath) -import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text as Doc.Render.Text-import qualified Dhall.Core as Core-import qualified Dhall.Lint as Lint-import qualified Dhall.Parser as Parser-import qualified Dhall.Pretty as Pretty-import qualified Dhall.Test.Util as Test.Util-import qualified Test.Tasty as Tasty-import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO+import qualified Dhall.Core as Core+import qualified Dhall.Lint as Lint+import qualified Dhall.Parser as Parser+import qualified Dhall.Pretty as Pretty+import qualified Dhall.Test.Util as Test.Util+import qualified Prettyprinter as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle lintDirectory :: FilePath
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} module Main where import System.FilePath ((</>))@@ -5,18 +6,22 @@ import qualified Dhall.Test.Dhall import qualified Dhall.Test.Diff+import qualified Dhall.Test.DirectoryTree import qualified Dhall.Test.Format import qualified Dhall.Test.Freeze import qualified Dhall.Test.Import import qualified Dhall.Test.Lint import qualified Dhall.Test.Normalization+import qualified Dhall.Test.Package import qualified Dhall.Test.Parser import qualified Dhall.Test.QuickCheck import qualified Dhall.Test.Regression import qualified Dhall.Test.Schemas import qualified Dhall.Test.SemanticHash-import qualified Dhall.Test.Tags+#ifndef CROSS import qualified Dhall.Test.TH+#endif+import qualified Dhall.Test.Tags import qualified Dhall.Test.Tutorial import qualified Dhall.Test.TypeInference import qualified GHC.IO.Encoding@@ -62,11 +67,15 @@ , tagsTests , freezeTests , schemaTests+ , Dhall.Test.DirectoryTree.tests , Dhall.Test.Regression.tests , Dhall.Test.Tutorial.tests , Dhall.Test.QuickCheck.tests , Dhall.Test.Dhall.tests+#ifndef CROSS , Dhall.Test.TH.tests+#endif+ , Dhall.Test.Package.tests ] return testTree
@@ -2,12 +2,11 @@ module Dhall.Test.Normalization where -import Data.Text (Text)-import Data.Void (Void)-import Dhall.Core (Expr (..), Var (..), throws)-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Core (Expr (..), Var (..), throws)+import System.FilePath ((</>))+import Test.Tasty (TestTree) import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO@@ -17,6 +16,7 @@ import qualified Dhall.Parser as Parser import qualified Dhall.Test.Util as Test.Util import qualified Dhall.TypeCheck as TypeCheck+import qualified System.FilePath as FilePath import qualified Test.Tasty as Tasty import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle@@ -24,32 +24,41 @@ normalizationDirectory :: FilePath normalizationDirectory = "./dhall-lang/tests/normalization/success" +unitDirectory :: FilePath+unitDirectory = normalizationDirectory </> "unit/"+ getTests :: IO TestTree getTests = do let pattern = Turtle.chars <* "A.dhall" let normalizationFiles = do- path <- Turtle.lstree normalizationDirectory+ path <- FilePath.normalise <$> Turtle.lstree normalizationDirectory - Nothing <- return (Turtle.stripPrefix (normalizationDirectory </> "unit/") path)+ unitDirectory `Test.Util.pathNotPrefixOf` path return path betaNormalizationTests <- Test.Util.discover pattern betaNormalizationTest normalizationFiles - alphaNormalizationTests <- do+ alphaNormalizationTests <- Test.Util.discover pattern alphaNormalizationTest (Turtle.lstree "./dhall-lang/tests/alpha-normalization/success/") - let unitTestFiles = Turtle.lstree (normalizationDirectory </> "unit/")+ let unitTestFiles = Turtle.lstree unitDirectory unitTests <- Test.Util.discover pattern unitTest unitTestFiles let testTree = Tasty.testGroup "normalization"- [ betaNormalizationTests- , unitTests- , alphaNormalizationTests+ [ Tasty.testGroup "beta-normalization"+ [ betaNormalizationTests+ ]+ , Tasty.testGroup "unit tests"+ [ unitTests+ ]+ , Tasty.testGroup "alpha-normalization"+ [ alphaNormalizationTests+ ] , customization ] @@ -67,7 +76,7 @@ let tyCtx = Context.insert "min"- (Pi "_" Natural (Pi "_" Natural Natural))+ (Pi mempty "_" Natural (Pi mempty "_" Natural Natural)) Context.empty valCtx e =@@ -128,7 +137,7 @@ let expectedNormalized = Core.denote expectedResolved :: Expr Void Void let message =- "The normalized expression did not match the expected output"+ "The alpha-normalized expression did not match the expected output" Tasty.HUnit.assertEqual message expectedNormalized actualNormalized @@ -200,6 +209,6 @@ Core.alphaNormalize (Core.denote expectedResolved) let message =- "The normalized expression did not match the expected output"+ "The beta-normalized expression did not match the expected output" Tasty.HUnit.assertEqual message expectedNormalized actualNormalized
@@ -0,0 +1,270 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++module Dhall.Test.Package where++import Control.Exception (Exception, displayException, finally, try)+import Data.List.NonEmpty (NonEmpty (..))+import Data.Void (Void)+import Dhall.Core+ ( Directory (..)+ , Expr (..)+ , File (..)+ , FilePrefix (..)+ , Import (..)+ , ImportHashed (..)+ , ImportMode (..)+ , ImportType (..)+ , makeRecordField+ )+import qualified Dhall.Map as Map+import Dhall.Package+import Lens.Micro (set)+import qualified System.Directory as Directory+import System.FilePath ((</>))+import Test.Tasty+import Test.Tasty.HUnit++tests :: TestTree+tests = testGroup "Package"+ [ packagePackageFile+ , packageCustomPackageFile+ , packageSingleFile+ , packageEmptyDirectory+ , packageSingleDirectory+ , packageNested+ , packageRecursive+ , packageMissingFile+ , packageFilesDifferentDirs+ , packageIncompatibleFiles+ ]++packagePackageFile :: TestTree+packagePackageFile = testCase "package file" $ do+ let path = "./tests/package" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit Map.empty++ (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/package.dhall" :| [])+ assertEqual "path" path output+ assertEqual "content" package expr++packageCustomPackageFile :: TestTree+packageCustomPackageFile = testCase "custom package file" $ do+ let path = "./tests/package" </> "custom.dhall"++ let package :: Expr Void Import+ package = RecordLit $+ Map.singleton "package" $ makeRecordField $ Embed packageDhall++ let options :: Options+ options = set packageFileName "custom.dhall" defaultOptions++ (output, expr) <- getPackagePathAndContent options ("./tests/package/package.dhall" :| [])+ assertEqual "path" path output+ assertEqual "content" package expr++packageSingleFile :: TestTree+packageSingleFile = testCase "single file" $ do+ let path = "./tests/package/dir" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit $+ Map.singleton "test" $ makeRecordField $ Embed testDhall++ (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/dir/test.dhall" :| [])+ assertEqual "path" path output+ assertEqual "content" package expr++packageEmptyDirectory :: TestTree+packageEmptyDirectory = testCase "empty directory" $ do+ let path = "./tests/package/empty" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit Map.empty++ (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/empty" :| [])+ assertEqual "path" path output+ assertEqual "content" package expr++packageSingleDirectory :: TestTree+packageSingleDirectory = testCase "single directory" $ do+ let path = "./tests/package/dir" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit $ Map.singleton "test" $+ makeRecordField $ Embed testDhall++ (output, expr) <- getPackagePathAndContent defaultOptions ("./tests/package/dir" :| [])+ assertEqual "path" path output+ assertEqual "content" package expr++packageNested :: TestTree+packageNested = testCase "nested files" $ do+ let path = "./tests/package" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit $ Map.fromList+ [ ("dir", makeRecordField $ RecordLit $ Map.fromList+ [ ("test", makeRecordField $ Embed dirTestDhall)+ ]+ )+ , ("other", makeRecordField $ Embed otherPackageDhall)+ , ("test", makeRecordField $ Embed testDhall)+ ]++ (output, expr) <- getPackagePathAndContent defaultOptions+ ( "./tests/package/test.dhall" :|+ [ "./tests/package/dir/test.dhall"+ , "./tests/package/other/package.dhall"+ ])+ assertEqual "path" path output+ assertEqual "content" package expr++packageRecursive :: TestTree+packageRecursive = testCase "recursively create subpackages" $ removePackagesAfter $ do+ let path = "./tests/package/dir" </> "package.dhall"++ let package :: Expr Void Import+ package = RecordLit $ Map.fromList+ [ ("subdirectory1", makeRecordField $ Embed subdirectoryPackageDhall1)+ , ("subdirectory2", makeRecordField $ Embed subdirectoryPackageDhall2)+ , ("test", makeRecordField $ Embed testDhall)+ ]++ let options :: Options+ options = set packagingMode RecursiveSubpackages defaultOptions++ (output, expr) <- getPackagePathAndContent options+ ( "./tests/package/dir" :| [] )+ assertEqual "path" path output+ assertEqual "content" package expr+ where+ removePackagesAfter :: IO a -> IO a+ removePackagesAfter action = action `finally` do+ Directory.removePathForcibly "./tests/package/dir/subdirectory1/package.dhall"+ Directory.removePathForcibly "./tests/package/dir/subdirectory2/package.dhall"++packageMissingFile :: TestTree+packageMissingFile = testCase "missing file" $ do+ let action :: IO (FilePath, Expr Void Import)+ action = getPackagePathAndContent defaultOptions ("./tests/package/missing.dhall" :| [])++ assertThrow action $ \case+ InvalidPath "./tests/package/missing.dhall" -> True+ _ -> False++packageFilesDifferentDirs :: TestTree+packageFilesDifferentDirs = testCase "files from different directories" $ do+ let action :: IO (FilePath, Expr Void Import)+ action = getPackagePathAndContent defaultOptions+ ( "./tests/package/dir/test.dhall" :|+ [ "./tests/package/test/test.dhall"+ ])++ assertThrow action $ \case+ AmbiguousOutputDirectory "./tests/package/dir" "./tests/package/test" -> True+ _ -> False++packageIncompatibleFiles :: TestTree+packageIncompatibleFiles = testCase "files that are incompatible" $ do+ let action :: IO (FilePath, Expr Void Import)+ action = getPackagePathAndContent defaultOptions+ ( "./tests/package/test.dhall" :|+ [ "./tests/package/test/test.dhall"+ ])++ assertThrow action $ \case+ IncompatiblePaths xs -> xs == [ testDhall , testTestDhall ]+ _ -> False++packageDhall :: Import+packageDhall = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here File+ { directory = Directory []+ , file = "package.dhall"+ }+ }+ , importMode = Code+ }++testDhall :: Import+testDhall = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here File+ { directory = Directory []+ , file = "test.dhall"+ }+ }+ , importMode = Code+ }++dirTestDhall :: Import+dirTestDhall = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here $ File+ { directory = Directory {components = ["dir"]}+ , file = "test.dhall"+ }+ }+ , importMode = Code+ }++otherPackageDhall :: Import+otherPackageDhall = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here $ File+ { directory = Directory {components = ["other"]}+ , file = "package.dhall"+ }+ }+ , importMode = Code+ }++subdirectoryPackageDhall1 :: Import+subdirectoryPackageDhall1 = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here $ File+ { directory = Directory {components = ["subdirectory1"]}+ , file = "package.dhall"}+ }+ , importMode = Code+ }++subdirectoryPackageDhall2 :: Import+subdirectoryPackageDhall2 = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here $ File+ { directory = Directory {components = ["subdirectory2"]}+ , file = "package.dhall"}+ }+ , importMode = Code+ }++testTestDhall :: Import+testTestDhall = Import+ { importHashed = ImportHashed+ { hash = Nothing+ , importType = Local Here (File+ { directory = Directory {components = ["test"]}+ , file = "test.dhall"+ })+ }+ , importMode = Code+ }++assertThrow :: (Exception e, Show a) => IO a -> (e -> Bool) -> IO ()+assertThrow k p = do+ result <- try k+ case result of+ Left e | p e -> return ()+ Left e -> assertFailure $ "Predicate did not match: " <> displayException e+ Right result' -> assertFailure $ "Expected exception, but got: " <> show result'
@@ -2,12 +2,11 @@ module Dhall.Test.Parser where -import Data.Text (Text)-import Data.Void (Void)-import Dhall.Core (Binding (..), Expr (..), Import, Var (..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath, (</>))+import Data.Text (Text)+import Data.Void (Void)+import Dhall.Core (Binding (..), Expr (..), Import, Var (..))+import System.FilePath ((</>))+import Test.Tasty (TestTree) import qualified Control.Monad as Monad import qualified Data.Bifunctor as Bifunctor@@ -152,7 +151,9 @@ shouldNotParse :: Text -> TestTree shouldNotParse path = do- let expectedFailures = []+ let expectedFailures =+ [ parseDirectory </> "failure/spacing/LetNoSpace4.dhall"+ ] let pathString = Text.unpack path
@@ -1,3 +1,5 @@+-- TODO: update because we added ShowConstructor constructor to Expr in Dhall.Syntax+ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-}@@ -50,6 +52,7 @@ , Scheme (..) , URL (..) , Var (..)+ , WithComponent (..) ) import Dhall.Map (Map) @@ -62,7 +65,7 @@ import Dhall.Src (Src (..)) import Dhall.Test.Format (format) import Dhall.TypeCheck (TypeError, Typer)-import Generic.Random ((:+) (..), ConstrGen (..), W, Weights, (%))+import Generic.Random (ConstrGen (..), W, Weights, (%), (:+) (..)) import Test.QuickCheck ( Arbitrary (..) , Gen@@ -90,6 +93,7 @@ import qualified Data.Set import qualified Data.SpecialValues import qualified Data.Text as Text+import qualified Data.Time as Time import qualified Dhall.Binary import qualified Dhall.Context import qualified Dhall.Core@@ -99,7 +103,7 @@ import qualified Dhall.Set import qualified Dhall.TypeCheck import qualified Generic.Random-import qualified Lens.Family as Lens+import qualified Lens.Micro as Lens import qualified Numeric.Natural as Nat import qualified Test.QuickCheck import qualified Test.Tasty@@ -270,14 +274,14 @@ shrink = genericShrink -instance (Arbitrary s, Arbitrary a) => Arbitrary (PreferAnnotation s a) where- arbitrary =- Test.QuickCheck.oneof- [ pure PreferFromSource- , PreferFromWith <$> arbitrary- , pure PreferFromCompletion- ]+instance Arbitrary PreferAnnotation where+ arbitrary = Test.QuickCheck.oneof+ [ pure PreferFromSource+ , pure PreferFromCompletion+ ] + shrink = genericShrink+ instance (Arbitrary s, Arbitrary a) => Arbitrary (RecordField s a) where arbitrary = lift4 RecordField @@ -295,6 +299,10 @@ arbitrary = FieldSelection <$> pure Nothing <*> label <*> pure Nothing shrink = genericShrink +instance Arbitrary WithComponent where+ arbitrary =+ Test.QuickCheck.oneof [ pure WithQuestion, WithLabel <$> arbitrary ]+ instance (Arbitrary s, Arbitrary a) => Arbitrary (Expr s a) where arbitrary = Test.QuickCheck.suchThat@@ -305,10 +313,10 @@ standardizedExpression where customGens- :: ConstrGen "Lam" 0 (FunctionBinding s a)- :+ ConstrGen "Pi" 0 Text+ :: ConstrGen "Lam" 1 (FunctionBinding s a)+ :+ ConstrGen "Pi" 1 Text :+ ConstrGen "Field" 1 (FieldSelection s)- :+ ConstrGen "Project" 1 (Either (Set Text) (Expr s a))+ :+ ConstrGen "Project" 1 (Either [Text] (Expr s a)) :+ Gen Integer -- Generates all Integer fields in Expr :+ Gen Text -- Generates all Text fields in Expr :+ ()@@ -326,7 +334,7 @@ projection = Test.QuickCheck.oneof- [ fmap (Left . Dhall.Set.fromList) (Test.QuickCheck.listOf label)+ [ fmap Left (Test.QuickCheck.listOf label) , arbitrary ] @@ -350,6 +358,8 @@ % (1 :: W "BoolEQ") % (1 :: W "BoolNE") % (1 :: W "BoolIf")+ % (1 :: W "Bytes")+ % (1 :: W "BytesLit") % (1 :: W "Natural") % (7 :: W "NaturalLit") % (1 :: W "NaturalFold")@@ -376,6 +386,15 @@ % (1 :: W "TextAppend") % (1 :: W "TextReplace") % (1 :: W "TextShow")+ % (1 :: W "Date")+ % (1 :: W "DateLiteral")+ % (1 :: W "DateShow")+ % (1 :: W "Time")+ % (1 :: W "TimeLiteral")+ % (1 :: W "TimeShow")+ % (1 :: W "TimeZone")+ % (1 :: W "TimeZoneLiteral")+ % (1 :: W "TimeZoneShow") % (1 :: W "List") % (1 :: W "ListLit") % (1 :: W "ListAppend")@@ -398,6 +417,7 @@ % (7 :: W "RecordCompletion") % (1 :: W "Merge") % (1 :: W "ToMap")+ % (1 :: W "ShowConstructor") % (7 :: W "Field") % (7 :: W "Project") % (1 :: W "Assert")@@ -417,13 +437,11 @@ Data.Sequence.null xs standardizedExpression (Note _ _) = False-standardizedExpression (Combine (Just _) _ _) =+standardizedExpression (Combine _ (Just _) _ _) = False standardizedExpression With{} = False-standardizedExpression (Prefer PreferFromCompletion _ _) =- False-standardizedExpression (Prefer (PreferFromWith _) _ _) =+standardizedExpression (Prefer _ PreferFromCompletion _ _) = False -- The following three expressions are valid ASTs, but they can never be parsed, -- because the annotation will associate with `Merge`/`ListLit`/`ToMap` with@@ -434,16 +452,19 @@ False standardizedExpression (Annot (ToMap _ Nothing) _) = False+standardizedExpression (TimeZoneLiteral (Time.TimeZone _ b t)) =+ not b && null t+standardizedExpression (TimeLiteral (Time.TimeOfDay _ _ ss) precision) =+ isInteger (ss * magnitude)+ where+ magnitude = 10 ^ precision++ isInteger x = x == fromInteger (round x) standardizedExpression _ = True chooseCharacter :: (Char, Char) -> Gen Char-chooseCharacter =-#if MIN_VERSION_QuickCheck(2,14,0)- Test.QuickCheck.chooseEnum-#else- Test.QuickCheck.choose-#endif+chooseCharacter = Test.QuickCheck.chooseEnum instance Arbitrary File where arbitrary = lift2 File@@ -508,7 +529,7 @@ -- The standard does not yet specify how to encode `as Text`, so don't test it -- yet instance Arbitrary ImportMode where- arbitrary = Test.QuickCheck.elements [ Code, RawText, Location ]+ arbitrary = Test.QuickCheck.elements [ Code, RawText, Location, RawBytes ] shrink = genericShrink
@@ -7,6 +7,7 @@ import Data.Either.Validation (Validation (..)) import Data.Void (Void)+import Dhall.Core (Expr (..), ReifiedNormalizer (..)) import Dhall.Import (Imported, MissingImports (..)) import Dhall.Parser (SourcedException (..), Src) import Dhall.TypeCheck (TypeError)@@ -16,16 +17,17 @@ import qualified Control.Exception import qualified Data.Text.IO import qualified Data.Text.Lazy.IO-import qualified Data.Text.Prettyprint.Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text import qualified Dhall-import qualified Dhall.Context+import qualified Dhall.Context as Context import qualified Dhall.Core import qualified Dhall.Map import qualified Dhall.Parser import qualified Dhall.Pretty-import qualified Dhall.Test.Util as Util+import qualified Dhall.Test.Util as Util import qualified Dhall.TypeCheck+import qualified Lens.Micro as Lens+import qualified Prettyprinter+import qualified Prettyprinter.Render.Text import qualified System.Timeout import qualified Test.Tasty import qualified Test.Tasty.HUnit@@ -46,6 +48,9 @@ , issue1584 , issue1646 , issue1732+ , issue1884+ , issue2088+ , issue2463 , parsing0 , typeChecking0 , typeChecking1@@ -160,9 +165,9 @@ -- Verify that pretty-printing preserves string interpolation source <- Data.Text.IO.readFile "./tests/regression/issue216b.dhall" e <- Util.code source- let doc = Data.Text.Prettyprint.Doc.pretty e+ let doc = Prettyprinter.pretty e let docStream = Dhall.Pretty.layout doc- let text0 = Data.Text.Prettyprint.Doc.Render.Text.renderLazy docStream+ let text0 = Prettyprinter.Render.Text.renderLazy docStream text1 <- Data.Text.Lazy.IO.readFile "./tests/regression/issue216b.dhall" @@ -171,7 +176,7 @@ issue253 :: TestTree issue253 = Test.Tasty.HUnit.testCase "Issue #253" (do -- Verify that type-checking rejects ill-formed custom contexts- let context = Dhall.Context.insert "x" "x" Dhall.Context.empty+ let context = Context.insert "x" "x" Context.empty let result = Dhall.TypeCheck.typeWith context "x" -- If the context is not validated correctly then type-checking will@@ -221,6 +226,31 @@ -- expression as the first argument to a with expression _ <- Util.code "./tests/regression/issue1884.dhall" return () )++issue2088 :: TestTree+issue2088 = Test.Tasty.HUnit.testCase "Issue #2088" (do+ -- This test ensures that the parser for projection by labels doesn't+ -- accidentally swallow trailing commas OUTSIDE of the projection+ _ <- Util.code "./tests/regression/issue2088.dhall"+ return () )++issue2463 :: TestTree+issue2463 = Test.Tasty.HUnit.testCase "Issue #2463" (do+ let startingContext = Context.insert "foo" Integer Context.empty++ let normalizer (Var "foo") = Just (IntegerLit 0)+ normalizer _ = Nothing++ let inputSettings = transform Dhall.defaultInputSettings+ where+ transform =+ Lens.set Dhall.normalizer+ (Just (ReifiedNormalizer (pure . normalizer)))+ . Lens.set Dhall.startingContext startingContext++ x <- Dhall.inputWithSettings inputSettings Dhall.auto "foo"++ Test.Tasty.HUnit.assertEqual "" (0 :: Integer) x ) parsing0 :: TestTree parsing0 = Test.Tasty.HUnit.testCase "Parsing regression #0" (
@@ -4,21 +4,19 @@ import Data.Text (Text) import Dhall.Parser (Header (..))-import Prelude hiding (FilePath) import Test.Tasty (TestTree)-import Turtle (FilePath) -import qualified Data.Text as Text-import qualified Data.Text.IO as Text.IO-import qualified Data.Text.Prettyprint.Doc as Doc-import qualified Data.Text.Prettyprint.Doc.Render.Text as Doc.Render.Text-import qualified Dhall.Core as Core-import qualified Dhall.Parser as Parser-import qualified Dhall.Pretty as Pretty-import qualified Dhall.Schemas as Schemas-import qualified Dhall.Test.Util as Test.Util-import qualified Test.Tasty as Tasty-import qualified Test.Tasty.HUnit as Tasty.HUnit+import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO+import qualified Dhall.Core as Core+import qualified Dhall.Parser as Parser+import qualified Dhall.Pretty as Pretty+import qualified Dhall.Schemas as Schemas+import qualified Dhall.Test.Util as Test.Util+import qualified Prettyprinter as Doc+import qualified Prettyprinter.Render.Text as Doc.Render.Text+import qualified Test.Tasty as Tasty+import qualified Test.Tasty.HUnit as Tasty.HUnit import qualified Turtle schemasDirectory :: FilePath
@@ -2,10 +2,8 @@ module Dhall.Test.SemanticHash where -import Data.Text (Text)-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+import Data.Text (Text)+import Test.Tasty (TestTree) import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO
@@ -11,7 +11,7 @@ import qualified Data.Either.Validation import qualified Dhall import qualified Dhall.Map-import qualified Lens.Family as Lens+import qualified Lens.Micro as Lens data Result = Failure Integer | Success String deriving (Eq, Dhall.Generic, Show)
@@ -1,15 +1,20 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} module Dhall.Test.TH where -import Dhall.TH (HaskellType (..))-import Test.Tasty (TestTree)+import Control.Exception (throwIO)+import Data.Either.Validation (Validation (..))+import Data.Time (TimeOfDay (..), TimeZone (..), fromGregorian)+import Dhall.TH (HaskellType (..))+import Test.Tasty (TestTree) +import qualified Data.Text import qualified Dhall import qualified Dhall.TH import qualified Test.Tasty as Tasty@@ -23,6 +28,7 @@ Dhall.TH.makeHaskellTypes [ MultipleConstructors "Department" "./tests/th/Department.dhall" , SingleConstructor "Employee" "MakeEmployee" "./tests/th/Employee.dhall"+ , SingleConstructor "TimeExample" "TimeExample" "./tests/th/Time.dhall" ] deriving instance Eq Department@@ -31,6 +37,9 @@ deriving instance Eq Employee deriving instance Show Employee +deriving instance Eq TimeExample+deriving instance Show TimeExample+ Dhall.TH.makeHaskellTypes [ SingleConstructor "Bar" "MakeBar" "(./tests/th/issue2066.dhall).Bar" , SingleConstructor "Foo" "MakeFoo" "(./tests/th/issue2066.dhall).Foo"@@ -70,3 +79,141 @@ qux <- Dhall.input Dhall.auto "let T = ./tests/th/issue2066.dhall in T.Qux.Foo { foo = +2, bar = { baz = +3 } }" Tasty.HUnit.assertEqual "" qux (Foo MakeFoo{ foo = 2, bar = MakeBar{ baz = 3 } })++ timex <- Dhall.input Dhall.auto "let T = ./tests/th/Time.dhall in { txTime = 21:12:00, txDate = 1976-04-01, txTimeZone = +05:00 } : T"++ Tasty.HUnit.assertEqual "" timex TimeExample { txTime = tod, txDate = day, txTimeZone = tz}++ where+ tod = TimeOfDay { todHour = 21, todMin = 12, todSec = 0 }+ day = fromGregorian 1976 4 1+ tz = TimeZone { timeZoneMinutes = 300, timeZoneSummerOnly = False, timeZoneName = "" }+ ++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("My" <>)+ , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+ })+ [ MultipleConstructors "MyT" "./tests/th/example.dhall"+ , MultipleConstructors "MyDepartment" "./tests/th/Department.dhall"+ , SingleConstructor "MyEmployee" "Employee" "./tests/th/Employee.dhall"+ ]++ +deriving instance Eq MyT+deriving instance Eq MyDepartment+deriving instance Eq MyEmployee+deriving instance Show MyT+deriving instance Show MyDepartment+deriving instance Show MyEmployee++ +Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("My" <>)+ , Dhall.TH.fieldModifier = ("my" <>) . Data.Text.toTitle+ , Dhall.TH.generateFromDhallInstance = False+ , Dhall.TH.generateToDhallInstance = False+ })+ [ SingleConstructor "MyHKSingle" "HKSingle" "./tests/th/HigherKindSingle.dhall"+ , MultipleConstructors "MyHKUnion" "./tests/th/HigherKindUnion.dhall"+ ]++type MyHKSingle_ = MyHKSingle Maybe Int+type MyHKUnion_ = MyHKUnion Bool Int++deriving instance Eq MyHKSingle_+deriving instance Show MyHKSingle_+deriving instance Dhall.Generic MyHKSingle_+instance Dhall.FromDhall MyHKSingle_+instance Dhall.ToDhall MyHKSingle_++deriving instance Eq MyHKUnion_+deriving instance Show MyHKUnion_+deriving instance Dhall.Generic MyHKUnion_+instance Dhall.FromDhall MyHKUnion_+instance Dhall.ToDhall MyHKUnion_++testMakeHaskellTypesWith :: TestTree+testMakeHaskellTypesWith = Tasty.HUnit.testCase "makeHaskellTypesWith" $ do+ let text0 = "let T = ./tests/th/example.dhall in T.A { x = True, y = [] : List Text }"+ ref0 = MyA{ myX = True, myY = [] }+ myTest text0 ref0++ let text1 = "let T = ./tests/th/example.dhall in T.B (None (List Natural))"+ ref1 = MyB Nothing+ myTest text1 ref1++ let text2 = "let T = ./tests/th/example.dhall in T.C"+ ref2 = MyC+ myTest text2 ref2++ let textDepartment = "let T = ./tests/th/Department.dhall in T.Sales"+ refDepartment = MySales+ myTest textDepartment refDepartment++ let textEmployee = "let T = ./tests/th/Department.dhall in T.Sales"+ refEmployee = MyEmployee{ myName = "", myDepartment = MySales }+ myTest textEmployee refEmployee++ let textHKSingle = "let T = (./tests/th/HigherKindSingle.dhall) Optional Int in T { foo = +1, bar = Some +2, bam = \"\" }"+ refHKSingle = MyHKSingle { myFoo = 1, myBar = Just 2, myBam = "" } :: MyHKSingle_+ myTest textHKSingle refHKSingle++ let textHKUnion0 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Foo True"+ refHKUnion0 = MyFoo True :: MyHKUnion_+ myTest textHKUnion0 refHKUnion0++ let textHKUnion1 = "let T = (./tests/th/HigherKindUnion.dhall) Bool Int in T.Bar +1"+ refHKUnion1 = MyBar 1 :: MyHKUnion_+ myTest textHKUnion1 refHKUnion1++ where+ myTest text ref = do+ expr <- Dhall.inputExpr text+ t <- case Dhall.extract Dhall.auto expr of+ Failure e -> throwIO e+ Success t -> return t++ Tasty.HUnit.assertEqual "" t ref+ Tasty.HUnit.assertEqual "" expr $ Dhall.embed Dhall.inject ref++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("NoFromDhall" <>)+ , Dhall.TH.fieldModifier = ("noFromDhall" <>) . Data.Text.toTitle+ , Dhall.TH.generateFromDhallInstance = False+ })+ [ MultipleConstructors "NoFromDhallT" "./tests/th/example.dhall"+ ]++instance Dhall.FromDhall NoFromDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("NoToDhall" <>)+ , Dhall.TH.fieldModifier = ("noToDhall" <>) . Data.Text.toTitle+ , Dhall.TH.generateToDhallInstance = False+ })+ [ MultipleConstructors "NoToDhallT" "./tests/th/example.dhall"+ ]++instance Dhall.ToDhall NoToDhallT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("NoInstances" <>)+ , Dhall.TH.fieldModifier = ("noInstances" <>) . Data.Text.toTitle+ , Dhall.TH.generateFromDhallInstance = False+ , Dhall.TH.generateToDhallInstance = False+ })+ [ MultipleConstructors "NoInstancesT" "./tests/th/example.dhall"+ ]++deriving instance Dhall.Generic NoInstancesT+instance Dhall.FromDhall NoInstancesT+instance Dhall.ToDhall NoInstancesT++Dhall.TH.makeHaskellTypesWith (Dhall.TH.defaultGenerateOptions+ { Dhall.TH.constructorModifier = ("Strict" <>)+ , Dhall.TH.fieldModifier = ("strict" <>) . Data.Text.toTitle+ , Dhall.TH.makeStrict = True+ })+ [ MultipleConstructors "StrictFields" "./tests/th/example.dhall"+ ]
@@ -2,11 +2,10 @@ module Dhall.Test.Tags where -import Data.Text (Text)-import Dhall.Util (Input (..))-import Prelude hiding (FilePath)-import Test.Tasty (TestTree)-import Turtle (FilePath)+import Data.Text (Text)+import Dhall.Util (Input (..))+import System.FilePath ((</>))+import Test.Tasty (TestTree) import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO@@ -30,7 +29,9 @@ tagsTest :: Text -> TestTree tagsTest prefix = Tasty.HUnit.testCase (Text.unpack prefix) $ do- let inputFile = Text.unpack (prefix <> ".dhall")+ -- The use of toDhallPah is a hack to ensure we always get the same file+ -- paths, i.e. ones with a '.' prefixed and UNIX path separators.+ let inputFile = Text.unpack (Test.Util.toDhallPath prefix <> ".dhall") let outputFile = Text.unpack (prefix <> ".tags") actualTags <- fixPathSeparators <$> Tags.generate (InputFile inputFile) Nothing False@@ -44,7 +45,7 @@ tagsDirTest :: TestTree tagsDirTest = Tasty.HUnit.testCase "all" $ do- let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory Turtle.</> "all.tags"+ let outputFile = Text.unpack . Turtle.format Turtle.fp $ tagsDirectory </> "all.tags" actualTags <- fmap fixPathSeparators (Tags.generate
@@ -5,12 +5,10 @@ import Control.Exception (SomeException (..)) import Data.Text (Text)-import Prelude hiding (FilePath)+import System.FilePath ((</>)) import Test.Tasty (TestTree)-import Turtle (FilePath, (</>)) import qualified Control.Exception as Exception-import qualified Control.Monad as Monad import qualified Data.Text as Text import qualified Data.Text.IO as Text.IO import qualified Dhall.Core as Core@@ -38,7 +36,7 @@ , typeInferenceDirectory </> "success/CacheImportsCanonicalizeA.dhall" ] - Monad.guard (path `notElem` skip)+ path `Test.Util.pathNotIn` skip return path @@ -59,7 +57,7 @@ successTest prefix = do let expectedFailures = []-#ifdef WITH_HTTP+#if defined(WITH_HTTP) && defined(NETWORK_TESTS) #else ++ [ typeInferenceDirectory </> "success/CacheImports" ]@@ -97,14 +95,18 @@ Tasty.HUnit.assertEqual message resolvedExpectedType inferredType + -- We also add this to exercise the `Dhall.Eval.conv` code path, since+ -- it's easy to forget to update it when adding new syntax+ _ <- Core.throws (TypeCheck.typeOf (Core.Annot resolvedExpr resolvedExpectedType))+ return ()+ failureTest :: Text -> TestTree failureTest prefix = do let expectedFailures = [ -- Duplicate fields are incorrectly caught during parsing: -- https://github.com/dhall-lang/dhall-haskell/issues/772- typeInferenceDirectory </> "failure/unit/RecordProjectionDuplicateFields"- , typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields"+ typeInferenceDirectory </> "failure/unit/RecordTypeDuplicateFields" , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants1" , typeInferenceDirectory </> "failure/unit/UnionTypeDuplicateVariants2" ]
@@ -1,6 +1,8 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ViewPatterns #-} module Dhall.Test.Util ( code@@ -18,35 +20,47 @@ , assertDoesntTypeCheck , discover , Dhall.Test.Util.testCase+ , pathIn+ , pathNotIn+ , pathNotPrefixOf+ , pathNotSuffixOf , toDhallPath+ , managedTestEnvironment ) where +import Control.Applicative (Alternative, liftA2, (<|>))+import Control.Exception (tryJust)+import Control.Monad (guard) import Control.Monad.Trans.State.Strict (StateT) import Data.Bifunctor (first) import Data.Text (Text) import Data.Void (Void) import Dhall.Context (Context) import Dhall.Core- ( Expr+ ( Chunks (..)+ , Expr (..) , Import , Normalizer , ReifiedNormalizer (..) ) import Dhall.Import (SemanticCacheMode (..), Status (..)) import Dhall.Parser (Src)-import Prelude hiding (FilePath)+import System.IO.Error (isDoesNotExistError) import Test.Tasty (TestTree) import Test.Tasty.HUnit-import Turtle (FilePath, Pattern, Shell, fp)+import Turtle (Pattern, Shell, fp) import qualified Control.Exception import qualified Control.Foldl as Foldl import qualified Control.Monad.Trans.State.Strict as State import qualified Data.Functor+import qualified Data.List as List import qualified Data.Text as Text+import qualified Data.Text.IO as Text.IO import qualified Dhall.Context import qualified Dhall.Core import qualified Dhall.Import+import qualified Dhall.Map import qualified Dhall.Parser import qualified Dhall.TypeCheck import qualified System.FilePath as FilePath@@ -54,10 +68,12 @@ import qualified Test.Tasty.ExpectedFailure as Tasty.ExpectedFailure import qualified Turtle -#ifndef WITH_HTTP-import Control.Monad.IO.Class (MonadIO (..))-import Dhall.Core (URL (..))-import Lens.Family.State.Strict (zoom)+#if defined(WITH_HTTP) && defined(NETWORK_TESTS)+import qualified Data.Foldable+#else+import Control.Monad.IO.Class (MonadIO (..))+import Dhall.Core (Directory (..), File (..), URL (..))+import Lens.Micro.Mtl (zoom) import qualified Data.Foldable import qualified Data.Text.Encoding@@ -94,62 +110,85 @@ (loadWith expression) (Dhall.Import.emptyStatus rootDirectory) { _semanticCacheMode = semanticCacheMode } -#ifdef WITH_HTTP+#if defined(WITH_HTTP) && defined(NETWORK_TESTS) loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void) loadWith = Dhall.Import.loadWith #else loadWith :: Expr Src Import -> StateT Status IO (Expr Src Void) loadWith expr = do- let mockRemote' url = do- liftIO . putStrLn $ "\nTesting without real HTTP support --"- ++ " using mock HTTP client to resolve remote import."- mockRemote url- zoom Dhall.Import.remote (State.put mockRemote')+ zoom Dhall.Import.remote (State.put mockRemote) Dhall.Import.loadWith expr mockRemote :: Dhall.Core.URL -> StateT Status IO Data.Text.Text--- Matches anything pointing to--- `https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/`-mockRemote (URL { authority = "raw.githubusercontent.com"- , path = Dhall.Core.File (Dhall.Core.Directory components) file })- | take 3 (reverse components) == ["dhall-lang", "dhall-lang", "master"] = do- let dropEnd n ls = take (length ls - n) ls- let localDir = dropEnd 3 components ++ ["dhall-lang"]+mockRemote+ url@URL+ { authority = "raw.githubusercontent.com"+ , path = File (Directory components) file+ } = do+ let localDir = case reverse components of+ "dhall-lang" : "dhall-lang" : _ : rest ->+ reverse ("dhall-lang" : rest)+ "Nadrieril" : "dhall-rust" : _ : "dhall" : rest ->+ reverse ("dhall-lang" : rest)+ _ -> do+ fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url)) - localPath <- Dhall.Import.localToPath Dhall.Core.Here (Dhall.Core.File (Dhall.Core.Directory localDir) file)- liftIO $ Data.Text.IO.readFile localPath+ localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file) --- Matches anything pointing to--- `https://test.dhall-lang.org/Bool/package.dhall`; checks that a `test` header--- is present and redirects to the local copy of the prelude.-mockRemote (URL { authority = "test.dhall-lang.org"- , path = Dhall.Core.File (Dhall.Core.Directory components) file- , headers = Just headersExpr }) =- case Data.Foldable.find ((== "test") . fst) hs of- Nothing -> fail $ "(mock http) Tried to load an import from "- ++"\"test.dhall-lang.org\""- ++ "without setting the \"test\" header field."- Just (_, _) -> do- let localDir = components ++ ["Prelude", "dhall-lang"]- localPath <- Dhall.Import.localToPath Dhall.Core.Here (Dhall.Core.File (Dhall.Core.Directory localDir) file)- liftIO $ Data.Text.IO.readFile localPath- where- hs = Dhall.Import.toHeaders headersExpr+ liftIO (Data.Text.IO.readFile localPath) --- Emulates `https://httpbin.org/user-agent`-mockRemote (URL { authority = "httpbin.org"- , path = Dhall.Core.File (Dhall.Core.Directory []) "user-agent"- , headers = Just headersExpr }) =- case Data.Foldable.find ((== "user-agent") . fst) hs of- Nothing -> fail $ "(mock http) Tried to read the user agent via "- ++ "\"httpbin.com/user-agent\" without supplying one "- ++ "in the header!"- Just (_, userAgent) -> do+mockRemote+ URL { authority = "prelude.dhall-lang.org"+ , path = File (Directory components) file+ } = do+ let localDir = components ++ [ "Prelude", "dhall-lang" ]++ localPath <- Dhall.Import.localToPath Dhall.Core.Here (File (Directory localDir) file)++ liftIO (Data.Text.IO.readFile localPath)++mockRemote url@URL{ authority = "test.dhall-lang.org", path, headers } =+ case (path, fmap Dhall.Import.toHeaders headers) of+ (File (Directory []) "foo", Just [("test", _)]) ->+ return "./bar"+ (File (Directory []) "bar", Just [("test", _)]) ->+ return "True"+ (File (Directory ["cors"]) "AllowedAll.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "OnlyGithub.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "OnlySelf.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "OnlyOther.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "Empty.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "NoCORS.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "Null.dhall", _) ->+ return "42"+ (File (Directory ["cors"]) "SelfImportAbsolute.dhall", _) ->+ return "https://test.dhall-lang.org/cors/NoCORS.dhall"+ (File (Directory ["cors"]) "SelfImportRelative.dhall", _) ->+ return "./NoCORS.dhall"+ (File (Directory ["cors"]) "TwoHopsFail.dhall", _) ->+ return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlySelf.dhall"+ (File (Directory ["cors"]) "TwoHopsSuccess.dhall", _) ->+ return "https://raw.githubusercontent.com/dhall-lang/dhall-lang/5ff7ecd2411894dd9ce307dc23020987361d2d43/tests/import/data/cors/OnlyGithub.dhall"+ _ -> do+ fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url))++mockRemote url@URL{ authority = "httpbin.org", path, headers } =+ case (path, fmap Dhall.Import.toHeaders headers) of+ (File (Directory []) "user-agent", Just [("user-agent", userAgent)]) -> do let agentText = Data.Text.Encoding.decodeUtf8 userAgent+ return ("{\n \"user-agent\": \"" <> agentText <> "\"\n}\n")- where- hs = Dhall.Import.toHeaders headersExpr+ (File (Directory []) "user-agent", Nothing) -> do+ return ("{\n \"user-agent\": \"Dhall\"\n}\n")+ _ -> do+ fail ("Unable to mock URL: " <> Text.unpack (Dhall.Core.pretty url)) mockRemote url = do let urlString = Text.unpack (Dhall.Core.pretty url)@@ -157,6 +196,57 @@ <> urlString) #endif +{- Given a test prefix, returns a managed resource+ which sets / reverts relevant environment variables based+ on `prefix <> "ENV.dhall"` (if present)+ -}+managedTestEnvironment :: Text -> Turtle.Managed [(Text, Maybe Text)]+managedTestEnvironment prefix = Turtle.managed (Control.Exception.bracket setup cleanup)+ where+ envPath = Text.unpack (prefix <> "ENV.dhall")++ setup :: IO [(Text, Maybe Text)]+ setup = do+ envFileContents <-+ tryJust (guard . isDoesNotExistError) (Text.IO.readFile envPath)++ testEnv <- case envFileContents of+ Right contents -> do+ resolved <- code contents+ return (convertEnvExpr (Dhall.Core.normalize resolved))+ Left _ -> return []++ traverse setEnv testEnv++ cleanup :: [(Text, Maybe Text)] -> IO ()+ cleanup = Data.Foldable.traverse_ restoreEnv++ convertEnvExpr :: Expr Src Void -> [(Text, Text)]+ convertEnvExpr (ListLit _ hs) = Data.Foldable.toList (Data.Foldable.fold maybePairs)+ where+ maybePairs = mapM toPair hs++ toPair :: Expr s a -> Maybe (Text, Text)+ toPair (RecordLit m) = do+ (Dhall.Core.recordFieldValue -> TextLit (Chunks [] key), Dhall.Core.recordFieldValue -> TextLit (Chunks [] value))+ <- lookupHeader <|> lookupMapKey+ return (key, value)+ where+ lookupHeader = liftA2 (,) (Dhall.Map.lookup "header" m) (Dhall.Map.lookup "value" m)+ lookupMapKey = liftA2 (,) (Dhall.Map.lookup "mapKey" m) (Dhall.Map.lookup "mapValue" m)+ toPair _ = Nothing+ convertEnvExpr _ = []++ setEnv :: (Text, Text) -> IO (Text, Maybe Text)+ setEnv (k, v) = do+ old <- Turtle.need k+ Turtle.export k v+ return (k, old)++ restoreEnv :: (Text, Maybe Text) -> IO ()+ restoreEnv (k, Just old) = Turtle.export k old+ restoreEnv (k, Nothing) = Turtle.unset k+ equivalent :: Text -> Text -> IO () equivalent text0 text1 = do expr0 <- fmap Dhall.Core.normalize (code text0) :: IO (Expr Void Void)@@ -203,7 +293,7 @@ let shell = do path_ <- paths - let pathText = Turtle.format fp path_+ let pathText = Turtle.format fp (FilePath.normalise path_) prefix : _ <- return (Turtle.match pattern pathText) @@ -215,15 +305,29 @@ testCase :: Text -> [ FilePath ] -> Assertion -> TestTree testCase prefix expectedFailures assertion =- if prefix `elem` map (Turtle.format fp) expectedFailures+ if prefix `elem` map (Turtle.format fp . FilePath.normalise) expectedFailures then Tasty.ExpectedFailure.expectFail test else test where test = Test.Tasty.HUnit.testCase (Text.unpack prefix) assertion +pathIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathIn this = guard . any (FilePath.equalFilePath this)++pathNotIn :: Alternative f => FilePath -> [FilePath] -> f ()+pathNotIn this = guard . not . any (FilePath.equalFilePath this)++pathNotPrefixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotPrefixOf this =+ guard . not . List.isPrefixOf (FilePath.normalise this) . FilePath.normalise++pathNotSuffixOf :: Alternative f => FilePath -> FilePath -> f ()+pathNotSuffixOf this =+ guard . not . List.isSuffixOf (FilePath.normalise this) . FilePath.normalise+ {-| Path names on Windows are not valid Dhall paths due to using backslashes instead of forwardslashes to separate path components. This utility fixes them if necessary -} toDhallPath :: Text -> Text-toDhallPath = Text.replace "\\" "/"+toDhallPath = ("./" <>) . Text.replace "\\" "/"
@@ -11,7 +11,8 @@ labels.{ `app.kubernetes.io/name`, `app.kubernetes.io/instance` } let k8s =- https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd+ https://raw.githubusercontent.com/dhall-lang/dhall-kubernetes/4ab28225a150498aef67c226d3c5f026c95b5a1e/package.dhall+ sha256:2c7ac35494f16b1f39afcf3467b2f3b0ab579edb0c711cddd2c93f1cbed358bd let serviceName = "ipfs"
@@ -3,7 +3,8 @@ = λ(a : Type) → { field : Text , nesting :- ./Nesting sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335+ ./Nesting+ sha256:6284802edd41d5d725aa1ec7687e614e21ad1be7e14dd10996bfa9625105c335 ? ./Nesting , contents : a }
@@ -0,0 +1,1 @@+"'\${x}'\n"
@@ -0,0 +1,3 @@+''+${"'"}''${x}'+''
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+ : T+ = T.`Some`++let x+ : T+ = T.Type++in True
@@ -0,0 +1,11 @@+let T = < Some | Type >++let t+ : T+ = T.`Some`++let x+ : T+ = T.Type++in True
@@ -0,0 +1,1 @@+let empty : ∀(a : Type) → List a = λ(a : Type) → [] : List a in empty
@@ -0,0 +1,5 @@+let empty+ : ∀(a : Type) → List a+ = λ(a : Type) → [] : List a++in empty
@@ -0,0 +1,1 @@+04:00:00-04:00
@@ -0,0 +1,1 @@+04:00:00-04:00
@@ -1,1 +1,1 @@-{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20 }+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
@@ -1,1 +1,1 @@-{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20 }+{ example0 = 0x42, example1 = +0x42, example2 = 1.2e20, example3 = -0b0111 }
@@ -0,0 +1,6 @@+-- https://github.com/dhall-lang/dhall-haskell/issues/2273+let MyPackage =+ https://server.test/package.dhall using (./headers.dhall)+ sha256:03a6e298ff140d430cea8b387fad886ce9f5bee24622c7d1102115cc08ed9cf8++in MyPackage
@@ -0,0 +1,6 @@+-- https://github.com/dhall-lang/dhall-haskell/issues/2273+let MyPackage =+ https://server.test/package.dhall using (./headers.dhall)+ sha256:03a6e298ff140d430cea8b387fad886ce9f5bee24622c7d1102115cc08ed9cf8++in MyPackage
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"Hello, world!"
@@ -0,0 +1,2 @@+#!/usr/bin/env -S dhall text --file+"Hello, world!"
@@ -1,4 +1,5 @@ let replicate =- https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c+ https://raw.githubusercontent.com/dhall-lang/Prelude/c79c2bc3c46f129cc5b6d594ce298a381bcae92c/List/replicate+ sha256:cc856d59b63f7699881bdb8e4b1036ca4c0013827268040a50c1e1405f646a2c in replicate 5
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
@@ -0,0 +1,3 @@+-- This test ensures that we don't strip leading zeros from the fractional+-- component of seconds when pretty-printing them+00:00:00.01
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
@@ -0,0 +1,1 @@+λ(x : Optional Natural) → x with ? = 2
@@ -1,1 +0,0 @@-True
@@ -0,0 +1,1 @@+True
@@ -0,0 +1,2 @@+ ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,3 @@+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,5 @@+-- The purpose of this test is to verify that `dhall freeze --cached` is+-- idempotent and doesn't attempt to resolve the `missing` import+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,3 @@+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,3 @@+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -0,0 +1,3 @@+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,1 @@+./True.dhall
@@ -0,0 +1,3 @@+ missing+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -1,2 +0,0 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
@@ -1,2 +0,0 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
@@ -1,1 +0,0 @@-./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
@@ -1,2 +0,0 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
@@ -1,1 +0,0 @@-./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -1,2 +0,0 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
@@ -0,0 +1,1 @@+True
@@ -0,0 +1,2 @@+ ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70+? ./True.dhall
@@ -0,0 +1,2 @@+./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -0,0 +1,1 @@+./True.dhall sha256:0000000000000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,2 @@+./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -0,0 +1,1 @@+./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -0,0 +1,2 @@+./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -0,0 +1,1 @@+./True.dhall
@@ -0,0 +1,2 @@+./True.dhall+ sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70
@@ -1,1 +0,0 @@-./True.dhall
@@ -1,2 +0,0 @@- ./True.dhall sha256:27abdeddfe8503496adeb623466caa47da5f63abd2bc6fa19f6cfcb73ecfed70-? ./True.dhall
@@ -0,0 +1,1 @@+[ { x = 1 }.{ x }, { x = 1 } ]
@@ -0,0 +1,1 @@+\(a : Type -> Type) -> \(a : Type) -> { foo : a, bar : a@1 a, bam : Text }
@@ -0,0 +1,1 @@+\(a : Type) -> \(b : Type) -> < Foo : a | Bar : b >
@@ -0,0 +1,1 @@+{ txTime : Time, txDate : Date, txTimeZone : TimeZone }
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in \(r : Type) ->+ \(make : Make r) ->+ [ make.file+ { name = "non-existent-1/file"+ , content = ""+ , user = None User+ , group = None Group+ , mode = None Mode+ }+ , make.directory+ { name = "non-existent-2/directory"+ , content = [] : List r+ , user = None User+ , group = None Group+ , mode = None Mode+ }+ ]
@@ -0,0 +1,3 @@+let Make = (./fixpoint-helper.dhall).Make++in \(r : Type) -> \(make : Make r) -> [] : List r
@@ -0,0 +1,30 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+ { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+ { user : Optional Access+ , group : Optional Access+ , other : Optional Access+ }++let Entry =+ \(content : Type) ->+ { name : Text+ , content : content+ , user : Optional User+ , group : Optional Group+ , mode : Optional Mode+ }++let Make =+ \(r : Type) ->+ { directory : Entry (List r) -> r+ , binary-file : Entry Bytes -> r+ , file : Entry Text -> r+ }++in { User, Group, Access, Mode, Entry, Make }
@@ -0,0 +1,24 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Make = (./fixpoint-helper.dhall).Make++let no-access = { execute = Some False, read = Some False, write = Some False }++let full-access = { execute = Some True, read = Some True, write = Some True }++in \(r : Type) ->+ \(make : Make r) ->+ [ make.file+ { name = "file"+ , content = ""+ , user = None User+ , group = None Group+ , mode = Some+ { user = Some full-access+ , group = Some no-access+ , other = Some no-access+ }+ }+ ]
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in \(r : Type) ->+ \(make : Make r) ->+ [ make.file+ { name = "file"+ , content = ""+ , user = None User+ , group = None Group+ , mode = None Mode+ }+ , make.directory+ { name = "directory"+ , content = [] : List r+ , user = None User+ , group = None Group+ , mode = None Mode+ }+ ]
@@ -0,0 +1,25 @@+let User = (./fixpoint-helper.dhall).User++let Group = (./fixpoint-helper.dhall).Group++let Mode = (./fixpoint-helper.dhall).Mode++let Make = (./fixpoint-helper.dhall).Make++in \(r : Type) ->+ \(make : Make r) ->+ [ make.file+ { name = "ids"+ , content = ""+ , user = Some (User.UserId 0)+ , group = Some (Group.GroupId 0)+ , mode = None Mode+ }+ , make.file+ { name = "names"+ , content = ""+ , user = Some (User.UserName "user")+ , group = Some (Group.GroupName "group")+ , mode = None Mode+ }+ ]
@@ -0,0 +1,36 @@+let User = < UserId : Natural | UserName : Text >++let Group = < GroupId : Natural | GroupName : Text >++let Access =+ { execute : Optional Bool, read : Optional Bool, write : Optional Bool }++let Mode =+ { user : Optional Access+ , group : Optional Access+ , other : Optional Access+ }++let Entry =+ \(content : Type) ->+ { name : Text+ , content : content+ , user : Optional User+ , group : Optional Group+ , mode : Optional Mode+ }++in forall (result : Type) ->+ let DirectoryEntry = Entry (List result)++ let BinaryFileEntry = Entry Bytes++ let TextFileEntry = Entry Text++ let Make =+ { directory : DirectoryEntry -> result+ , binary-file : BinaryFileEntry -> result+ , file : TextFileEntry -> result+ }++ in forall (make : Make) -> List result