diff --git a/.circleci/config.yml b/.circleci/config.yml index f33699cb69..31327853ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,6 @@ commands: default: "cabal v2-update" ghc_version: type: string - default: "8.10.7" project_file: type: string default: "cabal.project" @@ -69,7 +68,7 @@ commands: echo 'export PATH=~/.ghcup/bin:$PATH' >> $BASH_ENV << parameters.cabal_update_command >> cabal v2-clean - cabal v2-build --project-file << parameters.project_file >> --flag include --flag devel -j --enable-tests liquid liquidhaskell-parser synthesis liquid-base liquid-prelude liquid-bytestring liquid-containers liquid-ghc-prim liquid-parallel liquid-vector liquid-platform test-driver + cabal v2-build --project-file << parameters.project_file >> --flag devel -j --enable-tests liquidhaskell-parser liquid-base liquid-prelude liquid-bytestring liquid-containers liquid-ghc-prim liquid-parallel liquid-vector liquid-platform test-driver - save_cache: key: cabal-cache-v3-{{ checksum "liquidhaskell.cabal" }}-{{ checksum "<< parameters.project_file >>" }}-{{ checksum "liquid-fixpoint-commit" }} paths: @@ -81,12 +80,22 @@ commands: command: | mkdir -p /tmp/junit/cabal << parameters.setup_test_extra_steps >> + - run: + name: Test Relational + command: | + LIQUID_CABAL_PROJECT_FILE=<> cabal v2-run --project-file << parameters.project_file >> tests:test-driver -- relational-pos relational-neg || (<>) + no_output_timeout: 30m + - run: + name: Test Translations + command: | + LIQUID_CABAL_PROJECT_FILE=<> cabal v2-run --project-file << parameters.project_file >> tests:test-driver -- relational-pos relational-neg || (<>) + no_output_timeout: 30m - run: name: Test command: | LIQUID_CABAL_PROJECT_FILE=<> cabal v2-run --project-file << parameters.project_file >> test-driver || (<>) cabal v2-test --project-file << parameters.project_file >> tests:tasty || (<>) - (liquidhaskell_datadir=$PWD cabal v2-test -j1 --project-file << parameters.project_file >> liquidhaskell:liquidhaskell-parser --flag include --flag devel --test-show-details=streaming --test-options="--xml=/tmp/junit/cabal/parser-test-results.xml") || (<>) + (liquidhaskell_datadir=$PWD cabal v2-test -j1 --project-file << parameters.project_file >> liquidhaskell:liquidhaskell-parser --flag devel --test-show-details=streaming --test-options="--xml=/tmp/junit/cabal/parser-test-results.xml") || (<>) no_output_timeout: 30m stack_build_and_test: @@ -125,9 +134,20 @@ commands: - ~/.stack - ./.stack-work - run: - name: Test + name: Test Relational + command: | + stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> clean + stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> run test-driver -- relational-pos relational-neg + no_output_timeout: 30m + - run: + name: Test Translation command: | stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> clean + stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> run test-driver -- relational-pos relational-neg + no_output_timeout: 30m + - run: + name: Test + command: | mkdir -p /tmp/junit/stack stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> run test-driver stack --no-terminal --stack-yaml << parameters.stack_yaml_file >> test tests:tasty @@ -147,7 +167,7 @@ commands: jobs: - stack_810: + stack_900: machine: image: ubuntu-2004:202107-02 steps: @@ -155,31 +175,19 @@ jobs: stack_yaml_file: "stack.yaml" extra_build_flags: "--flag liquidhaskell:devel" extra_test_flags: " liquid-platform:liquidhaskell " - - cabal_810: + cabal_900: machine: image: ubuntu-2004:202107-02 steps: - cabal_build_and_test: + ghc_version: "9.2.5" liquid_runner: "--liquid-runner=cabal -v0 v2-exec liquidhaskell -- -v0 \ -package-env=$(./scripts/generate_testing_ghc_env) \ -package=liquidhaskell -package=Cabal " - cabal_900: - machine: - image: ubuntu-2004:202107-02 - steps: - - cabal_build_and_test: - ghc_version: "9.0.1" - project_file: "cabal.ghc9.project" - liquid_runner: "--liquid-runner=cabal -v0 v2-exec --project-file cabal.ghc9.project liquidhaskell -- -v0 \ - -package-env=$(./scripts/generate_testing_ghc_env cabal.ghc9.project) \ - -package=liquidhaskell -package=Cabal " - workflows: version: 2 build_stack_and_cabal: jobs: - - stack_810 - - cabal_810 + - stack_900 - cabal_900 diff --git a/.github/workflows/haskell.yml b/.github/workflows/haskell.yml deleted file mode 100644 index e7507034a4..0000000000 --- a/.github/workflows/haskell.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: stack install & run examples - -on: - push: - branches: '**' - pull_request: - branches: '**' - -permissions: - contents: read - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - uses: freckle/stack-cache-action@main - - uses: actions/setup-haskell@v1 - with: - ghc-version: '8.10.3' - enable-stack: true - stack-version: 'latest' - - - name: Install Z3 - run: | - wget https://github.com/Z3Prover/z3/releases/download/z3-4.9.1/z3-4.9.1-x64-glibc-2.31.zip - unzip z3-4.9.1-x64-glibc-2.31.zip - rm -f z3-4.9.1-x64-glibc-2.31.zip - sudo cp z3-4.9.1-x64-glibc-2.31/bin/libz3.a /usr/local/lib - sudo cp z3-4.9.1-x64-glibc-2.31/bin/z3 /usr/local/bin - sudo cp z3-4.9.1-x64-glibc-2.31/include/* /usr/local/include - rm -rf z3-4.9.1-x64-glibc-2.31 - z3 --version - - name: Build - run: stack setup && stack install - - name: Test Relational - run: | - chmod +x ./tests/relational/rtest - ./tests/relational/rtest - shell: bash - - name: Test Non-Relational - run: | - stack --no-terminal --stack-yaml stack.yaml run test-driver - stack --no-terminal --stack-yaml stack.yaml test tests:tasty - stack --no-terminal --stack-yaml stack.yaml test -j1 liquidhaskell:liquidhaskell-parser --flag liquidhaskell:devel - diff --git a/.github/workflows/hlint.yml b/.github/workflows/hlint.yml index f815a094ae..7e198862fe 100644 --- a/.github/workflows/hlint.yml +++ b/.github/workflows/hlint.yml @@ -7,12 +7,9 @@ on: jobs: build: name: hlint - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - - name: fix ncurses version - run: sudo apt-get install libncurses5 - - uses: actions/checkout@v3 with: submodules: true @@ -20,7 +17,7 @@ jobs: - uses: haskell/actions/hlint-setup@v2 name: Set up HLint with: - version: "3.4" + version: "3.4" - uses: haskell/actions/hlint-run@v2 name: hlint diff --git a/.gitignore b/.gitignore index 6e06898f63..f4181ce334 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,5 @@ tests/**/*.o-boot .idea *.iml -.DS_Store \ No newline at end of file +.DS_Store +docs/mkDocs/site diff --git a/README.md b/README.md index f12a7db862..ae46926e8a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ ![LiquidHaskell](/resources/logo.png) - [![Hackage](https://img.shields.io/hackage/v/liquidhaskell.svg)](https://hackage.haskell.org/package/liquidhaskell) [![Hackage-Deps](https://img.shields.io/hackage-deps/v/liquidhaskell.svg)](http://packdeps.haskellers.com/feed?needle=liquidhaskell) [![Build Status](https://img.shields.io/circleci/project/ucsd-progsys/liquidhaskell/master.svg)](https://circleci.com/gh/ucsd-progsys/liquidhaskell) [![Windows build status](https://ci.appveyor.com/api/projects/status/78y7uusjcgor5p16/branch/develop?svg=true)](https://ci.appveyor.com/project/varosi/liquidhaskell-nlhra/branch/develop) @@ -22,8 +21,7 @@ to let us know. If possible, try to: * State as clearly as possible what is the problem you are facing; * Provide a small Haskell file producing the issue; * Write down the expected behaviour vs the actual behaviour; -* If possible, let us know if you have used the [plugin](install.md) or the [executable](legacy.md) and - which _GHC version_ you are using. +* Please, let us know which liquidhaskell version you are using. ## Your first Pull Request @@ -109,28 +107,21 @@ For documentation on the `test-driver` executable itself, please refer to the `README.md` in `tests/` or run `cabal run tests:test-driver -- --help` or `stack run test-driver -- --help` -_For a way of running the test suite for multiple GHC versions, consult the General Development FAQs. below_ - -There are particular scripts for running LH in the different modes, e.g. for different -compiler versions. These scripts are in: - - $ ./scripts/test - -So you can run *all* the tests for say the ghc-8.10 version by +You can run *all* the tests by - $ ./scripts/test/test_810_plugin.sh + $ ./scripts/test/test_plugin.sh You can run a bunch of particular test-groups instead by - $ LIQUID_DEV_MODE=true ./scripts/test/test_810_plugin.sh ... + $ LIQUID_DEV_MODE=true ./scripts/test/test_plugin.sh ... and you can list all the possible test options with - $ LIQUID_DEV_MODE=true ./scripts/test/test_810_plugin.sh --help + $ LIQUID_DEV_MODE=true ./scripts/test/test_plugin.sh --help or get a list of just the test groups, one per line, with - $ LIQUID_DEV_MODE=true ./scripts/tests/test_810_plugin.sh --show-all + $ LIQUID_DEV_MODE=true ./scripts/test/test_plugin.sh --show-all To pass in specific parameters and run a subset of the tests, you can invoke cabal directly with @@ -148,15 +139,13 @@ You can directly extend and run the tests by modifying the files in ### Parallelism in Tests -Most tests run in parallel, with a few module dependencies built sequentially in -advance. Benchmarks are run sequentially after all other tests have finished. -For details on adding tests, see note [Parallel_Tests] in `tests/test.hs`. +Tests run in parallel, unless the flag `--measure-timings` is specified to `test_plugin.sh`. ## How to create performance comparison charts When `liquidhaskell` tests run, we can collect timing information with - $ ./scripts/tests/test_810_plugin.sh --measure-timings + $ ./scripts/test/test_plugin.sh --measure-timings Measures will be collected in `.dump-timings` files. These can be converted to json data with @@ -185,110 +174,23 @@ current directory. The current formatting is optimized for comparing the outputs of running the benchmarks alone. - $ scripts/test/test_810_plugin.sh + $ scripts/test/test_plugin.sh \ benchmark-stitch-lh \ benchmark-bytestring \ - benchmark-vector-algorithms + benchmark-vector-algorithms \ benchmark-cse230 \ benchmark-esop2013 \ benchmark-icfp15-pos \ - benchmark-icfp15-ne - -## How to Profile - -1. Build with profiling on - - ``` - $ stack build liquidhaskell --fast --profile - ``` - -2. Run with profiling - - ``` - $ stack exec -- liquid range.hs +RTS -hc -p - $ stack exec -- liquid range.hs +RTS -hy -p - ``` - - Followed by this which shows the stats file - - ``` - $ more liquid.prof - ``` - - or by this to see the graph - - ``` - $ hp2ps -e8in -c liquid.hp - $ gv liquid.ps - ``` + benchmark-icfp15-neg - etc. +## Miscelaneous tasks -## How to Get Stack Traces On Exceptions +* **Profiling** See the instructions in [scripts/ProfilingDriver.hs][]. +* **Getting stack traces on exceptions** See `-xc` flag in the [GHC user's guide][ghc-users-guide]. +* **Working with submodules** See `man gitsubmodules` or the [git documentation site][git-documentation]. -1. Build with profiling on - - ``` - $ stack build liquidhaskell --fast --profile - ``` - -2. Run with backtraces - - ``` - $ liquid +RTS -xc -RTS foo.hs - ``` - - ``` - stack exec -- liquid List00.hs +RTS -p -xc -RTS - ``` - -## Working With Submodules - -To update the `liquid-fixpoint` submodule, run: - -``` -cd ./liquid-fixpoint -git fetch --all -git checkout / -cd .. -``` - -This will update `liquid-fixpoint` to the latest version on `` (usually `master`) -from `` (usually `origin`). After updating `liquid-fixpoint`, make sure to include this change in a -commit! Running: - -``` -git add ./liquid-fixpoint -``` - -will save the current commit hash of `liquid-fixpoint` in your next commit to the `liquidhaskell` repository. -For the best experience, **don't** make changes directly to the `./liquid-fixpoint` submodule, or else git -may get confused. Do any `liquid-fixpoint` development inside a separate clone/copy elsewhere. If something -goes wrong, run: - -``` -rm -r ./liquid-fixpoint -git submodule update --init -``` - -to blow away your copy of the `liquid-fixpoint` submodule and revert to the last saved commit hash. - -Want to work fully offline? `git` lets you add a local directory as a remote. Run: - -``` -cd ./liquid-fixpoint -git remote add local /path/to/your/fixpoint/clone -cd .. -``` - -Then to update the submodule from your local clone, you can run: - -``` -cd ./liquid-fixpoint -git fetch local -git checkout local/ -cd .. -``` +[ghc-users-guide]: https://downloads.haskell.org/ghc/latest/docs/users_guide/ +[git-documentation]: https://git-scm.com/doc ## Releasing on Hackage @@ -301,10 +203,22 @@ Bash script. The script doesn't accept any argument and it tries to determine th to upload by scanning the `$PWD` for packages named appropriately. It will ask the user for confirmation before proceeding, and `stack upload` will be used under the hood. +## GHC support policy + +LH supports only one version of GHC at any given time. This is because LH depends heavily on the `ghc` library +and there is currently no distinction between public API's and API's internal to GHC. There are currently no +release notes for the `ghc` library and breaking changes happen without notice and without deprecation +periods. Supporting only one GHC version saves developer time because it obviates the need for `#ifdef`'s +throughout the codebase, or for an compatibility layer that becomes increasingly difficult to write as we +attempt to support more GHC versions. Porting to newer GHC versions takes less time, the code is easier to +read and there is less code duplication. + +Users of older versions of GHC can still use older versions of LH. + ## The GHC.API module -In order to allow LH to work with multiple GHC versions, we need a way to abstract over all the breaking -changes of the `ghc` library, which might change substantially with every major GHC release. This is +In order to minimize the effort in porting LH to new releases of GHC, we need a way to abstract over breaking +changes in the `ghc` library, which might change substantially with every major GHC release. This is accomplished by the [GHC.API][] module. The idea is that **rather than importing multiple `ghc` modules, LH developers must import this single module in order to write future-proof code**. This is especially important for versions of the compiler greater than 9, where the module hierarchy changed substantially, @@ -345,8 +259,7 @@ the code provided as part of the `release/0.8.10.2` branch, commit `9a2f8284c5fe The module [GHC.Plugin][] is the main entrypoint for all the plugin functionalities. Whenever possible, this module is reusing common functionalities from the [GHC.Interface][], which is the original module used to interface LH with the old executable. Generally speaking, the [GHC.Interface][] module is considered "legacy" -and it's rarely what one wants to modify. It will probably be removed once the old executable stops being -supported, with the functions now in use by the [GHC.Plugin][] being moved into the latter. +and it's rarely what one wants to modify. It will probably be removed at some point. ## The GhcMonadLike shim @@ -428,39 +341,17 @@ compilation might fail with an error, typically because some `ghc` API function The way to fix it is to modify the [GHC.API][] shim module and perform any required change, likely by conditionally compiling some code in a `CPP` block. For minor changes, it's usually enough to perform small changes, but for more tricky migrations it might be necessary to backport some GHC code, or create some -patter synonym to deal with changes in type constructors. You can see an example of this technique in -action by looking at the pattern synonym for [FunTy][]. +patter synonym to deal with changes in type constructors. ## Is there a way to run the testsuite for different versions of GHC? -Yes. The easiest way is to run one of the scripts inside the `scripts/test` directory. We provide scripts -to run the testsuite for a variety of GHC versions, mostly using `stack` but also with `cabal` (e.g. -`test_810_plugin.sh`). If run without arguments, the script will run the _full_ testsuite. If an argument -is given, only a particular pattern/test will be run. Running - -``` -./scripts/test/test_810_plugin.sh BST -``` - -will run all the tests which name matches "BST". In case the "fast recompilation" is desired, it's totally -possibly to pass `LIQUID_DEV_MODE` to the script, for example: - -``` -LIQUID_DEV_MODE=true ./scripts/test/test_810_plugin.sh -``` +Currently, no. Only one version of GHC is supported and that is the one +that can be tested with `./scripts/test/test_plugin.sh`. -[GHC.API]: https://github.com/ucsd-progsys/liquidhaskell/blob/develop/src/Language/Haskell/Liquid/GHC/API.hs -[FunTy]: https://github.com/ucsd-progsys/liquidhaskell/blob/develop/src/Language/Haskell/Liquid/GHC/API.hs#L224 +[GHC.API]: src-ghc/Liquid/GHC/API.hs # GHC Plugin Development FAQs -## Is it possible that the behaviour of the old executable and the new / the plugin differ? - -It might happen, yes, but the surface area is fairly small. Both modules work by producing a [TargetSrc][] -that is passed to the internal LH API, which is shared by _both_ modules. Therefore, any difference in -behaviour has to be researched in the code path that produces such [TargetSrc][]. For the [GHC.Plugin][] this -happens in the `makeTargetSrc`, whereas for the [GHC.Interface][] this happens inside the [makeGhcSrc][] function. - ## Why is the GHC.Interface using slightly different types than the GHC.Plugin module? Mostly for backward-compatibility and for historical reasons. Types like [BareSpec][] used to be type alias @@ -471,23 +362,23 @@ to map back and forth (sometimes in a partial way) between old and new data stru using**. -[Plugin]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin.hs -[GHC.Plugin]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin.hs -[GHC.Interface]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Interface.hs -[SpecFinder]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs -[BareSpec]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/Types/Specs.hs#L301 -[LiftedSpec]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/Types/Specs.hs#L476 -[TargetSrc]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/Types/Specs.hs#L160 +[Plugin]: src/Language/Haskell/Liquid/GHC/Plugin.hs +[GHC.Plugin]: src/Language/Haskell/Liquid/GHC/Plugin.hs +[GHC.Interface]: src-ghc/Liquid/GHC/Interface.hs +[SpecFinder]: src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs +[BareSpec]: src/Language/Haskell/Liquid/Types/Specs.hs#L361 +[LiftedSpec]: src/Language/Haskell/Liquid/Types/Specs.hs#L554 +[TargetSrc]: src/Language/Haskell/Liquid/Types/Specs.hs#L157 [Ghc monad]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:Ghc [HscEnv]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:HscEnv [DynFlags]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:DynFlags [GhcMonad]: https://hackage.haskell.org/package/ghc-8.10.1/docs/GHC.html#t:GhcMonad -[GhcMonadLike]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/GhcMonadLike.hs -[typechecking phase]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin.hs#L196-L224 +[GhcMonadLike]: src-ghc/Liquid/GHC/GhcMonadLike.hs +[typechecking phase]: src/Language/Haskell/Liquid/GHC/Plugin.hs#L206-L222 [ghcide]: https://github.com/haskell/ghcide -[findRelevantSpecs]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs#L61 +[findRelevantSpecs]: src/Language/Haskell/Liquid/GHC/Plugin/SpecFinder.hs#L61 [core binds]: https://hackage.haskell.org/package/ghc-8.10.1/docs/CoreSyn.html#t:CoreBind -[configureGhcTargets]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Interface.hs#L268 -[processTargetModule]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Interface.hs#L468 -[processModule]: https://github.com/ucsd-progsys/liquidhaskell/blob/9a2f8284c5fe5b18ed0410e842acd3329a629a6b/src/Language/Haskell/Liquid/GHC/Plugin.hs#L393 +[configureGhcTargets]: src-ghc/Liquid/GHC/Interface.hs#L252 +[processTargetModule]: src-ghc/Liquid/GHC/Interface.hs#L481 +[processModule]: src/Language/Haskell/Liquid/GHC/Plugin.hs#L393 diff --git a/TODO.EASY.md b/TODO.EASY.md index b3f5c6516c..3051e92b83 100644 --- a/TODO.EASY.md +++ b/TODO.EASY.md @@ -1,22 +1,15 @@ -- Verification of Libraries +- Verification of Libraries - [zlib](https://hackage.haskell.org/package/zlib) - [probability](https://github.com/nikivazou/probability) - + - fix parser error message - - Parse Errors [#241](https://github.com/ucsd-progsys/liquidhaskell/issues/241) - - Liquid Haskell doesn't accept Haskell names containing ' (single-quote) [#273](https://github.com/ucsd-progsys/liquidhaskell/issues/273) - - Error messages [#400](https://github.com/ucsd-progsys/liquidhaskell/issues/400) - Add list of reserved tokens -- Parse Propositional Variables in Refinements [#338](https://github.com/ucsd-progsys/liquidhaskell/issues/338) - -- Combine GHC and Liquid Type Aliases [#381](https://github.com/ucsd-progsys/liquidhaskell/issues/381) - - Applying data type with wrong number of abstract refinement params could give better errors [#297](https://github.com/ucsd-progsys/liquidhaskell/issues/297) - Export qualifiers from measure types [#302](https://github.com/ucsd-progsys/liquidhaskell/issues/302) -- systematically remove all error calls +- systematically remove all error calls NV: Not sure how easy this is, as it requires deep understanding of the code to distinguish dead code from our errors. diff --git a/appveyor.yml b/appveyor.yml index 5d1ffd3632..265e0b3254 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -31,28 +31,15 @@ install: build_script: -# Build LiquidHaskell (the legacy executable) -# until https://gitlab.haskell.org/ghc/ghc/issues/17236 is fixed. - echo "" | rm -rf .stack-work -- echo "" | stack --no-terminal build --ghc-options="-fexternal-interpreter" liquidhaskell:lib --flag liquidhaskell:no-plugin --copy-bins --local-bin-path . -- echo "" | stack --no-terminal build liquid-fixpoint:exe:fixpoint liquidhaskell:exe:liquid --flag liquidhaskell:no-plugin --copy-bins --local-bin-path . +- echo "" | stack --no-terminal build --flag liquidhaskell:devel liquidhaskell # Copy runtime DLLs - call appveyor-copy.bat -# Test if they are working -- fixpoint --version -- liquid --version +# ZIP executable +# - 7z a liquidhaskell.zip liquid.exe fixpoint.exe .\include\CoreToLogic.lg LICENSE LICENSE_Z3 libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll -# ZIP execturable -- 7z a liquidhaskell.zip liquid.exe fixpoint.exe .\include\CoreToLogic.lg LICENSE LICENSE_Z3 libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll - -# Run the tests (using the legacy executable) +# Run the tests test_script: -- echo "" | stack --no-terminal test liquidhaskell:liquidhaskell-parser --fast --flag liquidhaskell:no-plugin -# XXX(matt.walker): Can this whole file be removed? -# - echo "" | stack --no-terminal test liquidhaskell:test --fast --flag liquidhaskell:no-plugin --ta="--liquid-runner \"stack --compiler=ghc-8.10.7 --silent exec -- liquid\"" --test-arguments "-p Micro" - -artifacts: -- path: liquidhaskell.zip - name: LiquidHaskell +- echo "" | stack --no-terminal test --flag liquidhaskell:devel liquidhaskell:liquidhaskell-parser diff --git a/benchmark-timings/benchmark-timings.cabal b/benchmark-timings/benchmark-timings.cabal index f7e9373c30..39d086e70d 100644 --- a/benchmark-timings/benchmark-timings.cabal +++ b/benchmark-timings/benchmark-timings.cabal @@ -34,10 +34,10 @@ executable benchmark-timings -- LANGUAGE extensions used by modules in this package. -- other-extensions: build-depends: base - , aeson ^>=1.5.6 + , aeson >= 1.5.6 && < 2.1 , cassava ^>=0.5.2 - , bytestring ^>=0.10.12 - , optparse-applicative ^>=0.16.1 + , bytestring >=0.10.12 && <0.12 + , optparse-applicative >=0.16.1 && <0.18 ghc-options: -Wall hs-source-dirs: app default-language: Haskell2010 diff --git a/cabal.ghc9.project b/cabal.ghc9.project deleted file mode 100644 index b1847f3909..0000000000 --- a/cabal.ghc9.project +++ /dev/null @@ -1,143 +0,0 @@ -packages: . - ./liquid-bytestring - ./liquid-containers - ./liquid-fixpoint - ./liquid-parallel - ./liquid-prelude - ./liquid-vector - ./liquid-platform - ./tests - ./tests/benchmarks/popl18/lib - ./benchmark-timings - -package liquid-fixpoint - flags: +devel - -package liquid-platform - flags: +devel - -tests: True - -with-compiler: ghc-9.0.1 - -source-repository-package - type: git - location: https://github.com/liquidhaskell/liquid-ghc-prim.git - tag: v0.7.0 - -source-repository-package - type: git - location: https://github.com/facundominguez/liquid-base.git - tag: 8ad2378cee5ccf7937d9e08aacd5c5b7128318e8 - -source-repository-package - type: git - location: https://github.com/qnikst/ghc-timings-report - tag: 45ef3498e35897712bde8e002ce18df6d55f8b15 - -constraints: - any.Cabal ==3.4.0.0, - Decimal ==0.5.1, - EdisonAPI ==1.3.1, - EdisonCore ==1.3.2.1, - FPretty ==1.1, - HTTP ==4000.3.15, - ListLike ==4.7.2, - QuickCheck ==2.14.2, - active ==0.2.0.14, - aivika ==5.9, - aivika-transformers ==5.9, - alex ==3.2.5, - arith-encode ==1.0.2, - basement ==0.0.11, - cassava ==0.5.2.0, - chaselev-deque ==0.5.0.5, - combinat ==0.2.9.0, - commonmark ==0.1.0.2, - conduit ==1.3.4.2, - cql ==4.0.2, - critbit ==0.2.0.0, - cryptonite ==0.27, - data-r-tree ==0.6.0, - diagrams-lib ==1.4.3, - doctest ==0.16.3 || ==0.17, - drinkery ==0.4, - emacs-module ==0.1.1, - enumeration ==0.2.0, - fclabels ==2.0.5, - foundation ==0.0.25, - free ==5.1.7, - recursion-schemes ==5.2.2, - free-algebras ==0.1.0.0, - generic-deriving ==1.14.1, - generic-lens ==2.0.0.0, - generic-lens-core ==2.0.0.0, - generics-sop ==0.5.1.0, - haskeline ==0.8.2, - haskell-src-meta ==0.8.5, - heterocephalus ==1.0.5.4, - hgeometry ==0.11.0.0, - hgeometry-ipe ==0.11.0.0, - hmatrix ==0.20.0.0, - hslua ==1.2.0, - hxt ==9.3.1.18, - hxt-regex-xmlschema ==9.2.0.3, - inspection-testing ==0.4.2.4, - io-choice ==0.0.7, - io-streams ==1.5.2.0, - iproute ==1.7.9, - kind-generics-th ==0.2.2.1, - language-haskell-extract ==0.2.4, - lens ==4.19.2, - lens-family ==2.1.1, - lens-family-th ==0.5.2.1, - memory ==0.15.0, - microlens ==0.4.11.2, - microlens-th ==0.4.3.6, - monadplus ==1.4.2, - mustache ==2.3.1, - network-uri ==2.6.3.0, - obdd ==0.8.2, - optics-extra ==0.4, - optics-th ==0.4, - packman ==0.5.0, - pandoc ==2.11, - parameterized-utils ==2.1.1, - partial-isomorphisms ==0.2.2.1, - persistent-template ==2.8.2.3, - pipes ==4.3.14, - pipes-bytestring ==2.1.6, - pipes-parse ==3.0.8, - pipes-safe ==2.3.2, - plots ==0.1.1.2, - pretty-types ==0.3.0.1, - proto3-wire ==1.2.0, - ral-lens ==0.1, - regex-base ==0.94.0.0, - regex-compat ==0.95.2.0, - row-types ==1.0.0.0, - scheduler ==1.4.2.3, - semirings ==0.5.4, - shake ==0.19.1, - singletons ==2.6 || ==2.7, - store ==0.7.12, - store-core ==0.4.4.4, - streaming-bytestring ==0.1.6, - syb ==0.7.2.1, - texmath ==0.12.0.3, - text-show ==3.9.6, - th-abstraction ==0.4.2.0, - th-desugar ==1.10 || ==1.11, - th-expand-syns ==0.4.8.0, - th-lift-instances ==0.1.18, - th-utilities ==0.2.4.3, - tpdb ==2.2.0, - trivial-constraint ==0.6.0.0, - true-name ==0.1.0.3, - typenums ==0.1.2.1, - uniplate ==1.6.12, - unique ==0, - vec-lens ==0.3, - vinyl ==0.13.0, - xlsx ==0.8.1, - yesod-core ==1.6.18.4 diff --git a/cabal.project b/cabal.project index e9af472858..7d370bd034 100644 --- a/cabal.project +++ b/cabal.project @@ -1,3 +1,5 @@ +with-compiler: ghc-9.2.5 + packages: . ./liquid-base ./liquid-bytestring @@ -17,8 +19,13 @@ source-repository-package location: https://github.com/qnikst/ghc-timings-report tag: 45ef3498e35897712bde8e002ce18df6d55f8b15 +allow-newer: ghc-timings:base, rest-rewrite:time + package liquid-fixpoint flags: +devel +package liquidhaskell + ghc-options: -j + package liquid-platform flags: +devel diff --git a/devel/Paths_liquidhaskell.hs b/devel/Paths_liquidhaskell.hs deleted file mode 100644 index d00d95ffbd..0000000000 --- a/devel/Paths_liquidhaskell.hs +++ /dev/null @@ -1,18 +0,0 @@ -{-# LANGUAGE TemplateHaskell #-} - -module Paths_liquidhaskell where - -import Language.Haskell.TH -import System.Directory -import System.FilePath -import Data.Version (Version, makeVersion) - -getDataFileName :: FilePath -> IO FilePath -getDataFileName fp = do - let loc' = $(do { loc <- location; f <- runIO (canonicalizePath (loc_filename loc)); litE (stringL f); }) - let root = takeDirectory (takeDirectory loc') - return (root fp) - --- | dummy version (devel only) -version :: Version -version = makeVersion [0,0,0,0] diff --git a/docs/blog/2013-01-01-refinement-types-101.lhs b/docs/blog/2013-01-01-refinement-types-101.lhs index 2646210ae9..e9066d1487 100644 --- a/docs/blog/2013-01-01-refinement-types-101.lhs +++ b/docs/blog/2013-01-01-refinement-types-101.lhs @@ -180,7 +180,7 @@ How *does* LiquidHaskell verify the above function? The key step is that LiquidHaskell deduces that the expression `"divide by zero"` is not merely of type `String`, but in fact -has the the refined type `{v:String | false}` *in the context* +has the refined type `{v:String | false}` *in the context* in which the call to `error'` occurs. LiquidHaskell arrives at this conclusion by using the fact that diff --git a/docs/blog/2013-01-27-refinements101-reax.lhs b/docs/blog/2013-01-27-refinements101-reax.lhs index 317632342c..d13a7f76f9 100644 --- a/docs/blog/2013-01-27-refinements101-reax.lhs +++ b/docs/blog/2013-01-27-refinements101-reax.lhs @@ -155,7 +155,7 @@ non-negative `n` guarantee holds trivially. **Reason 2: The Specification is a Fib** If you run the above in the demo, you will see that LiquidHaskell still -doth protest loudly, and frankly, one might start getting a little +does protest loudly, and frankly, one might start getting a little frustrated at the stubbornness and petulance of the checker. \begin{code} However, if you stare at the implementation, you will see that it in fact, *does not* meet the specification, as @@ -194,7 +194,7 @@ recursive calls --- we get the above by plugging the parameters \end{code} \begin{code} Finally, to check the output guarantee is met, LiquidHaskell asks the SMT solver to prove that -(b >= 2n - 2) => (b >= n) +(b >= 2n - 3) => (b >= n) \end{code} The SMT solver will refuse, of course, since the above implication is @@ -258,5 +258,5 @@ There are several things to take away. [concolic]: http://en.wikipedia.org/wiki/Concolic_testing [icse04]: http://goto.ucsd.edu/~rjhala/papers/generating_tests_from_counterexamples.html [dsd]: http://dl.acm.org/citation.cfm?doid=1348250.1348254 -[mlton]: http://www.cs.purdue.edu/homes/zhu103/pubs/vmcai13.pdf +[mlton]: https://www.cs.purdue.edu/homes/suresh/papers/vmcai13.pdf diff --git a/docs/mkDocs/docs/blogposts/2013-01-01-refinement-types-101.lhs.md b/docs/mkDocs/docs/blogposts/2013-01-01-refinement-types-101.lhs.md index 193169350b..736f319e95 100644 --- a/docs/mkDocs/docs/blogposts/2013-01-01-refinement-types-101.lhs.md +++ b/docs/mkDocs/docs/blogposts/2013-01-01-refinement-types-101.lhs.md @@ -239,7 +239,7 @@ deducing that `n` is trivially non-negative when `0 < n` and that in the `otherwise` case, i.e. when `not (0 < n)` the value `0 - n` is indeed non-negative (lets not worry about underflows for the moment.) LiquidHaskell is able to automatically make these arithmetic deductions -by using an [SMT solver](http://rise4fun.com/Z3/) which has decision +by using an [SMT solver](https://github.com/Z3Prover/z3) which has decision built-in procedures for arithmetic, to reason about the logical refinements. @@ -310,8 +310,8 @@ Modular Verification -------------------- Incidentally, note the `import` statement at the top. Rather than rolling -our own `lAssert` we can import and use a pre-defined version `liquidAssert` -defined in an external [module](https://github.com/ucsd-progsys/liquidhaskell/blob/master/include/Language/Haskell/Liquid/Prelude.hs) +our own `lAssert` we can import and use a pre-defined version `liquidAssert` +defined in an external [module](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs)
286: {-@ truncate'' :: Int -> Int -> Int @-}
diff --git a/docs/mkDocs/docs/blogposts/2013-01-31-safely-catching-a-list-by-its-tail.lhs.md b/docs/mkDocs/docs/blogposts/2013-01-31-safely-catching-a-list-by-its-tail.lhs.md
index ad7ee2c702..63257d6589 100644
--- a/docs/mkDocs/docs/blogposts/2013-01-31-safely-catching-a-list-by-its-tail.lhs.md
+++ b/docs/mkDocs/docs/blogposts/2013-01-31-safely-catching-a-list-by-its-tail.lhs.md
@@ -44,7 +44,7 @@ That is, measures will appear in specifications but *never* inside code.
 
 
 
- Let's reuse this mechanism, this time, providing a [definition](https://github.com/ucsd-progsys/liquidhaskell/blob/master/include/GHC/Base.spec) for the measure
+ Let's reuse this mechanism, this time, providing a [definition](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/liquid-base/src/GHC/Base.spec) for the measure
 
48: measure len :: forall a. [a] -> GHC.Types.Int
 49: len ([])     = 0
 50: len (y:ys)   = 1 + (len ys) 
diff --git a/docs/mkDocs/docs/blogposts/2020-04-12-polymorphic-perplexion.lhs.md b/docs/mkDocs/docs/blogposts/2020-04-12-polymorphic-perplexion.lhs.md
index 097bfef796..46eb09de34 100644
--- a/docs/mkDocs/docs/blogposts/2020-04-12-polymorphic-perplexion.lhs.md
+++ b/docs/mkDocs/docs/blogposts/2020-04-12-polymorphic-perplexion.lhs.md
@@ -28,8 +28,8 @@ that has puzzled me and other users several times.
 A Type for Ordered Lists
 ------------------------
 
-[Previously](2013-07-29-putting-things-in-order.lhs/) 
-we have seen how you can use LH to define a type of lists whose values are in increasing 
+[Previously](2013-07-29-putting-things-in-order.lhs.md)
+we have seen how you can use LH to define a type of lists whose values are in increasing
 (ok, non-decreasing!) order.
 
 First, we define an `IncList a` type, with `Emp` ("empty") 
diff --git a/docs/mkDocs/docs/blogposts/2020-08-20-lh-as-a-ghc-plugin.lhs.md b/docs/mkDocs/docs/blogposts/2020-08-20-lh-as-a-ghc-plugin.lhs.md
index 6a681db3ec..0e435d15cb 100644
--- a/docs/mkDocs/docs/blogposts/2020-08-20-lh-as-a-ghc-plugin.lhs.md
+++ b/docs/mkDocs/docs/blogposts/2020-08-20-lh-as-a-ghc-plugin.lhs.md
@@ -110,9 +110,9 @@ run LH on the changed modules! If you use `stack` you may have to specify
 a few more dependencies, as the various packages are not (yet) on stackage, 
 as shown in the [demo `stack.yaml`](https://github.com/ucsd-progsys/lh-plugin-demo/blob/main/stack.yaml).
 No extra dependencies are needede if you use `cabal-v2`. In both cases,
-you can use the respective files [`stack.yaml`](https://github.com/ucsd-progsys/lh-plugin-demo/blob/main/stack.yaml.github) 
-and [`cabal.project`](https://github.com/ucsd-progsys/lh-plugin-demo/blob/main/cabal.project.github) 
-point to specific git snapshots if you want to use the most recent versions. 
+you can use the respective files [`stack.yaml`](https://github.com/ucsd-progsys/lh-plugin-demo/blob/main/stack.yaml)
+and [`cabal.project`](https://github.com/ucsd-progsys/lh-plugin-demo/blob/main/cabal.project)
+point to specific git snapshots if you want to use the most recent versions.
 If you clone the repo and run, e.g. `cabal v2-build` or `stack build` you'll get the following result, after the relevant dependencies 
 are downloaded and built of course...
 
diff --git a/docs/mkDocs/docs/index.md b/docs/mkDocs/docs/index.md
index ec1621e586..9b7c24709b 100644
--- a/docs/mkDocs/docs/index.md
+++ b/docs/mkDocs/docs/index.md
@@ -8,7 +8,7 @@ LiquidHaskell _(LH)_ refines Haskell's types with logical predicates that let yo
 

LH warns you that head is not total as it is missing the case for [] and checks that it is total on NonEmpty lists. -(more...) +(more...)

@@ -25,7 +25,7 @@ The input contract propagates to uses of head which are verified by

LH lets you avoid off-by-one errors that can lead to crashes or buffer overflows. -(more...) +(more...)

@@ -59,7 +59,7 @@ LH checks that functions terminate and so warns about the infinite recursion due

Write correctness requirements, for example a list is ordered, as refinements. LH makes illegal values be unrepresentable. -(more...) +(more...)

diff --git a/docs/mkDocs/docs/install.md b/docs/mkDocs/docs/install.md index df2d4608dd..7f620a7eb7 100644 --- a/docs/mkDocs/docs/install.md +++ b/docs/mkDocs/docs/install.md @@ -7,7 +7,7 @@ This sections documents how to install LH and its dependencies. In order to use LiquidHaskell, you will need a [SMT solver](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories) installed on your system. Download and install at least one of: -* [Z3](https://github.com/Z3Prover/z3) or [Microsoft official binary](https://www.microsoft.com/en-us/download/details.aspx?id=52270) +* [Z3](https://github.com/Z3Prover/z3) or [Microsoft official binary](https://github.com/Z3Prover/z3/releases) * [CVC4](https://cvc4.github.io/) * [MathSat](https://mathsat.fbk.eu/) @@ -54,5 +54,3 @@ You may also want to delete the `.liquid` directories placed alongside your sour ## Other Options **Online Demo**: For small projects without a `.cabal` file, you can paste your code into the [online demo](http://goto.ucsd.edu:8090/index.html). - -**Legacy Executable**: A [stanadalone executable](legacy.md) is also provided, although it is **deprecated** and will be removed in the future. diff --git a/docs/mkDocs/docs/legacy.md b/docs/mkDocs/docs/legacy.md deleted file mode 100644 index cd5f819b3c..0000000000 --- a/docs/mkDocs/docs/legacy.md +++ /dev/null @@ -1,65 +0,0 @@ -# Installing the Legacy LiquidHaskell Executable - -**We strongly recommend** that you use the [GHC Plugin](install.md) -available in version 0.8.10 onwards, as the legacy executable is deprecated and has been -kept around for backwards compatibility. It will eventually be removed from future LH releases. - -## External software requirements - -Make sure all the required [external software](install.md) software is installed before proceeding. - -## Installation options - -You can install the `liquid` binary via package manager *or* source. - -### Via Package Manager - -Simply do: - - cabal install liquidhaskell - -We are working to put `liquid` on `stackage`. - -You can designate a specific version of LiquidHaskell to -ensure that the correct GHC version is in the environment. -For example: - - cabal install liquidhaskell-0.8.10.1 - -### Build from Source - -If you want the most recent version, you can build from source as follows, -either using `stack` (recommended) or `cabal`. In either case: - -1. *recursively* `clone` the repo: - - ```git clone --recursive https://github.com/ucsd-progsys/liquidhaskell.git``` - -2. Go inside the `liquidhaskell` directory: - - ``` - cd liquidhaskell - ``` - -3. Build the package: - - a. with [stack][stack]: - - stack install liquidhaskell - - b. or with [cabal][cabal]: - - cabal v2-build liquidhaskell - -## Running in GHCi - -To run inside `ghci` e.g. when developing do: - -```bash -$ stack ghci liquidhaskell -ghci> :m +Language.Haskell.Liquid.Liquid -ghci> liquid ["tests/pos/Abs.hs"] -``` - -[stack]: https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md -[cabal]: https://www.haskell.org/cabal/ diff --git a/docs/mkDocs/docs/options.md b/docs/mkDocs/docs/options.md index f50ed8e9d8..9fad924f0b 100644 --- a/docs/mkDocs/docs/options.md +++ b/docs/mkDocs/docs/options.md @@ -192,11 +192,6 @@ Currently, LiquidHaskell supports To use these solvers, you must install the corresponding binaries from the above web-pages into your `PATH`. -You can also build and link against the Z3 API (faster but requires more -dependencies). If you do so, you can use that interface with: - - $ liquid --smtsolver=z3mem foo.hs - ## Short Error Messages **Options:** `short-errors` diff --git a/docs/mkDocs/docs/papers.md b/docs/mkDocs/docs/papers.md index 437fc846d5..9877e85652 100644 --- a/docs/mkDocs/docs/papers.md +++ b/docs/mkDocs/docs/papers.md @@ -12,11 +12,14 @@ you could curl up with: ### Haskell +- [REST: Integrating Term Rewriting with Program Verification, ECOOP 2022](https://drops.dagstuhl.de/opus/volltexte/2022/16210/) +- [Refinement Reflection: Complete Verification with SMT, POPL 2018](https://ranjitjhala.github.io/static/refinement_reflection.pdf) +- [Local Refinement Typing, ICFP 2017](https://ranjitjhala.github.io/static/local_refinement_typing.pdf) +- [Bounded Refinement Types, ICFP 2015](http://goto.ucsd.edu/~nvazou/icfp15/main.pdf) - [Refinement Types For Haskell, ICFP 2014](http://goto.ucsd.edu/~rjhala/papers/refinement_types_for_haskell.pdf) - [LiquidHaskell in the Real World, Haskell 2014](http://goto.ucsd.edu/~rjhala/papers/real_world_liquid.pdf) - [Abstract Refinement Types, ESOP 2013](http://goto.ucsd.edu/~rjhala/papers/abstract_refinement_types.pdf) - ### ML - [Liquid Types, PLDI 2008](http://goto.ucsd.edu/~rjhala/liquid/liquid_types.pdf) @@ -33,11 +36,21 @@ you could curl up with: ## Talks +- [Resource Analysis with Refinement Types, YOW! Lambda Jam 2021](https://skillsmatter.com/skillscasts/16729-resource-analysis-with-refinement-types) +- [Liquid Haskell: Theorem Proving for All, Haskell Exchange 2018](https://skillsmatter.com/skillscasts/11068-keynote-looking-forward-to-niki-vazou-s-keynote-at-haskellx-2018) +- [Scrap your Bounds Checks with Liquid Haskell, Haskell Exchange 2017](https://skillsmatter.com/skillscasts/10690-keynote-scrap-your-bounds-checks-with-liquid-haskell) [(slides)](https://github.com/Gabriella439/slides/blob/main/liquidhaskell/slides.md) + The following talks are good tutorial introductions to the techniques. - [Tutorial at VMCAI](http://goto.ucsd.edu/~rjhala/talks/liquid_types_VMCAI.pptx) - [Tutorial at CAV](http://goto.ucsd.edu/~rjhala/talks/liquid_types_CAV2011.pptx) +## Other articles + +- [A Dialog with Liquid Haskell, Tweag blog 2022](https://www.tweag.io/blog/2022-07-21-lh-introspection/) +- [Why Liquid Haskell Matters, Tweag blog 2022](https://www.tweag.io/blog/2022-01-19-why-liquid-haskell/) +- [Compile-time memory safety using Liquid Haskell, Haskell for all blog 2015](https://www.haskellforall.com/2015/12/compile-time-memory-safety-using-liquid.html) + ## People Liquid Types have been developed in the UCSD Programming Systems group by diff --git a/docs/mkDocs/docs/specifications.md b/docs/mkDocs/docs/specifications.md index 9bff194388..74b05704b3 100644 --- a/docs/mkDocs/docs/specifications.md +++ b/docs/mkDocs/docs/specifications.md @@ -44,42 +44,13 @@ The following sections detail more variety for the uses of the above annotations ## Modules WITHOUT code -The following section is slightly different depending on whether you are using the plugin (which you should!) -or the legacy executable. - -### (Plugin) Adding refinements for external modules - See the [installation](install.md) section, which cointains a link to a walkthrough document that describes how to add refinements for external packages (cfr. **"Providing Specifications for Existing Packages"**) -### (Legacy executable) Adding refinements for external modules - -When checking a file `target.hs`, you can specify an _include_ directory by - - liquid -i /path/to/include/ target.hs - -Now, to write specifications for some **external module** `Foo.Bar.Baz` for which -you **do not have the code**, you can create a `.spec` file at: - - /path/to/include/Foo/Bar/Baz.spec - -See, for example, the contents of: - -+ [include/Prelude.spec](https://github.com/ucsd-progsys/liquidhaskell/blob/master/include/Prelude.spec) -+ [include/Data/List.spec](https://github.com/ucsd-progsys/liquidhaskell/blob/master/include/Data/List.spec) -+ [include/Data/Vector.spec](https://github.com/ucsd-progsys/liquidhaskell/blob/master/include/Data/Vector.spec) - -**Note**: - -+ The above directories are part of the LH prelude, and included by - default when running `liquid`. -+ The `.spec` mechanism is *only for external modules** without code, - see below for standalone specifications for **internal** or **home** modules. - ## Modules WITH code: Data Write the specification directly into the .hs or .lhs file, -above the data definition. See, for example, [tests/pos/Map.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Map.hs): +above the data definition. See, for example, [tests/pos/Map.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Map.hs): ```haskell {-@ @@ -96,7 +67,7 @@ data Map k a = Tip ``` You can also write invariants for data type definitions -together with the types. For example, see [tests/pos/record0.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/record0.hs): +together with the types. For example, see [tests/pos/record0.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Record0.hs): ```haskell {-@ @@ -126,7 +97,7 @@ as `data size (M1 a, M2 a) msize`. Finally you can specify the variance of type variables for data types. -For example, see [tests/pos/Variance.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Variance.hs), where data type `Foo` has four +For example, see [tests/pos/Variance.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Variance.hs), where data type `Foo` has four type variables `a`, `b`, `c`, `d`, specified as invariant, bivariant, covariant and contravariant, respectively. @@ -138,7 +109,7 @@ data Foo a b c d ## Modules WITH code: Functions Write the specification directly into the .hs or .lhs file, -above the function definition. [For example](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/spec0.hs): +above the function definition. [For example](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Spec0.hs): ```haskell {-@ incr :: x:{v: Int | v > 0} -> {v: Int | v > x} @-} @@ -148,7 +119,7 @@ incr x = x + 1 ## Modules WITH code: Type Classes -Write the specification directly into the .hs or .lhs file. The constrained variable must match the one from the class definition. A class must have at least one refinement signature (even if it's a trivial one) to be lifted to the refinement logic. [For example](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Class.hs): +Write the specification directly into the .hs or .lhs file. The constrained variable must match the one from the class definition. A class must have at least one refinement signature (even if it's a trivial one) to be lifted to the refinement logic. [For example](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Class.hs): ```haskell class Semigroup a where {-@ mappend :: a -> a -> a @-} @@ -180,7 +151,7 @@ The example above inlines the proofs directly into the instance definition. This ## Modules WITH code: Type Classes (Legacy) Write the specification directly into the .hs or .lhs file, -above the type class definition. [For example](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Class.hs): +above the type class definition. [For example](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Class.hs): ```haskell {-@ class Sized s where @@ -194,7 +165,7 @@ Any measures used in the refined class definition will need to be *generic* (see [Specifying Measures](#specifying-measures)). As an alternative, you can refine class instances. -[For example](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/classes/pos/Inst00.hs): +[For example](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/classes/pos/Inst00.hs): ```haskell instance Compare Int where @@ -327,7 +298,7 @@ following examples for details: **Status:** `experimental` -There is experimental support for implicit arguments, solved for with congruence closure. For example, consider [Implicit1.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Implicit1.hs): +There is experimental support for implicit arguments, solved for with congruence closure. For example, consider [Implicit1.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/implicit/pos/Implicit1.hs): ```haskell {-@ type IntN N = {v:Int | v = N} @-} @@ -354,7 +325,7 @@ verbose. You can write predicate aliases like so: {-@ predicate Ge X Y = not (Lt X Y) @-} ``` -and then use the aliases inside refinements, [for example](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/pred.hs) +and then use the aliases inside refinements, [for example](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Pred.hs) ```haskell {-@ incr :: x:{v:Int | (Pos v)} -> { v:Int | ((Pos v) && (Ge v x))} @-} @@ -362,7 +333,7 @@ incr :: Int -> Int incr x = x + 1 ``` -See [Data.Map](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/benchmarks/esop2013-submission/Base.hs) for a more substantial +See [Data.Map](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/benchmarks/esop2013-submission/Base.hs) for a more substantial and compelling example. **Syntax:** The key requirements for type aliases are: @@ -417,13 +388,13 @@ and: {-@ assert insert :: (Ord a) => a -> SortedList a -> SortedList a @-} -see [tests/pos/ListSort.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/ListSort.hs) +see [tests/pos/ListSort.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/ListSort.hs) and: {-@ assert insert :: (Ord k) => k -> a -> OMap k a -> OMap k a @-} -see [tests/pos/Map.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Map.hs) +see [tests/pos/Map.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Map.hs) **Syntax:** The key requirements for type aliases are: @@ -439,7 +410,7 @@ For example, if `(+++)` is defined as a measure or reflected function, you can u Note: infix operators cannot contain the dot character `.`. -If `(==>)` is a Haskell infix type ([see](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/T1567.hs)) +If `(==>)` is a Haskell infix type ([see](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/T1567.hs)) infixr 1 ==> @@ -452,13 +423,13 @@ then to use it as infix in the refinements types you need to add the refinement They can be placed in a `.spec` file or in a .hs/.lhs file wrapped around `{-@ @-}`. -Value measures: [GHC/Base.spec](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/liquid-base/src/GHC/Base.spec) +Value measures: [GHC/Base.spec](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/liquid-base/src/GHC/Base.spec) measure len :: forall a. [a] -> GHC.Types.Int len ([]) = 0 len (y:ys) = 1 + len(ys) -Propositional measures: [tests/pos/LambdaEval.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/LambdaEval.hs) +Propositional measures: [tests/pos/LambdaEval.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/LambdaEval.hs) ```haskell {-@ @@ -474,7 +445,7 @@ isValue (Pair e1 e2) = ((? (isValue(e1))) && (? (isValue(e2)))) @-} ``` -Raw measures: [tests/pos/meas8.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/meas8.hs) +Raw measures: [tests/pos/meas8.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Meas8.hs) ```haskell {-@ measure rlen :: [a] -> Int @@ -483,7 +454,7 @@ rlen (y:ys) = {v | v = (1 + rlen(ys))} @-} ``` -Generic measures: [tests/pos/Class.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Class.hs) +Generic measures: [tests/pos/Class.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Class.hs) ```haskell {-@ class measure size :: a -> Int @-} @@ -499,9 +470,9 @@ Generic measures: [tests/pos/Class.hs](https://github.com/ucsd-progsys/liquidhas **Note:** Measure names **do not** have to be the same as field name, e.g. we could call the measure `sz` in the above -as shown in [tests/pos/Class2.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Class2.hs). +as shown in [tests/pos/Class2.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Class2.hs). -Haskell Functions as Measures (beta): [tests/pos/HaskellMeasure.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/HaskellMeasure.hs) +Haskell Functions as Measures (beta): [tests/pos/HaskellMeasure.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/HaskellMeasure.hs) Inductive Haskell Functions from Data Types to some type can be lifted to logic @@ -564,7 +535,7 @@ states that the *inner* `a` enjoys the property that the *outer* container is definitely a `Just` and furthermore, the inner value is exactly the same as the `fromJust` property of the outer container. -As another example, suppose we have a [measure](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/liquid-containers/src/Data/Set.spec): +As another example, suppose we have a [measure](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/liquid-containers/src/Data/Set.spec): measure listElts :: [a] -> (Set a) listElts([]) = {v | (? Set_emp(v))} @@ -579,16 +550,16 @@ set of the elements belonging to the entire list. One often needs these *circular* or *self* invariants to connect different levels (or rather, to *reify* the connections between the two levels.) See -[this test](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/maybe4.hs) for a simple example and `hedgeUnion` and -[Data.Map.Base](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/benchmarks/esop2013-submission/Base.hs) for a complex one. +[this test](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Maybe4.hs) for a simple example and `hedgeUnion` and +[Data.Map.Base](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/benchmarks/esop2013-submission/Base.hs) for a complex one. # Abstract and Bounded Refinements This is probably the best example of the abstract refinement syntax: -+ [Abstract Refinements](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/Map.hs) -+ [Bounded Refinements](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/benchmarks/icfp15/pos/Overview.lhs) ++ [Abstract Refinements](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Map.hs) ++ [Bounded Refinements](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/benchmarks/icfp15/pos/Overview.lhs) Unfortunately, the best documentation for these two advanced features is the relevant papers at: @@ -616,7 +587,7 @@ Invariants LH lets you locally associate invariants with specific data types. -For example, in [tests/measure/pos/Using00.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/measure/pos/Using00.hs) every +For example, in [tests/measure/pos/Using00.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/measure/pos/Using00.hs) every list is treated as a `Stream`. To establish this local invariant one can use the `using` declaration @@ -629,9 +600,9 @@ calls* to List's constructors (ie., `:` and `[]`) satisfy it, and will assume that each list element that is created satisfies this invariant. -With this, at the [above](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/measure/neg/Using00.hs) test LiquidHaskell +With this, at the [above](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/measure/neg/Using00.hs) test LiquidHaskell proves that taking the `head` of a list is safe. -But, at [tests/measure/neg/Using00.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/measure/neg/Using00.hs) the usage of +But, at [tests/measure/neg/Using00.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/measure/neg/Using00.hs) the usage of `[]` falsifies this local invariant resulting in an "Invariant Check" error. **WARNING:** There is an older _global_ invariant mechanism that @@ -682,7 +653,7 @@ You can also annotate a function as being a global rewrite rule by using the ## Limitations Currently, rewriting does not work if the equality that uses the rewrite rule -includes parameters that contain inner refinements ([test](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/errors/ReWrite5.hs)). +includes parameters that contain inner refinements ([test](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/errors/ReWrite5.hs)). Rewriting works by pattern-matching expressions to determine if there is a variable substitution that would allow it to match against either side of a @@ -691,7 +662,7 @@ corresponding equality is generated. If one side of the equality contains any parameters that are not bound on the other side, it will not be possible to generate a rewrite in that direction, because those variables cannot be instantiated. Likewise, if there are free variables on both sides of an -equality, no rewrite can be generated at all ([test](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/errors/ReWrite7.hs)). +equality, no rewrite can be generated at all ([test](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/errors/ReWrite7.hs)). It's possible in theory for rewriting rules to diverge. We have a simple check to ensure that rewriting rules that will always diverge do not get instantiated. @@ -744,7 +715,7 @@ There are several ways to specify qualifiers. ## By Separate `.hquals` Files -You can write qualifier files e.g. [Prelude.hquals](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/include/Prelude.hquals).. +You can write qualifier files e.g. [Prelude.hquals](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/include/Prelude.hquals).. If a module is called or imports @@ -760,13 +731,13 @@ Additional qualifiers may be used by adding lines of the form: {-@ include @-} -to the Haskell source. See, [this](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/meas5.hs) for example. +to the Haskell source. See, [this](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Meas5.hs) for example. ## In Haskell Source or Spec Files Finally, you can specifiers directly inside source (.hs or .lhs) or spec (.spec) -files by writing as shown [here](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/qualTest.hs) +files by writing as shown [here](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/QualTest.hs) {-@ qualif Foo(v:Int, a: Int) : (v = a + 100) @-} @@ -899,7 +870,7 @@ isOdd n = not $ isEven n thus recovering a decreasing measure for the pair of functions, the pair of arguments. This can be encoded with the lexicographic termination annotation as shown above. -See [tests/pos/mutrec.hs](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/pos/mutrec.hs) +See [tests/pos/mutrec.hs](https://github.com/ucsd-progsys/liquidhaskell/blob/develop/tests/pos/Mutrec.hs) for the full example. ## Automatic Termination Metrics @@ -945,57 +916,6 @@ you can write {-@ lazy foo @-} ``` -# Synthesis - -**Status:** `experimental` - -LH has some very preliminary support for program synthesis. - -### How to use it - -Activate the flag for typed holes in LiquidHaskell. E.g. -from command line: - - liquid --typedholes - -In a Haskell source file: - - {-@ LIQUID --typed-holes @-} - -Using the flag for typed holes, two more flags can be used: - -- **max-match-depth**: Maximum number of pattern match expressions used during synthesis (default value: 4). - -- **max-app-depth**: Maximum number of same function applications used during synthesis (default value: 2). - -Having the program specified in a Haskell source file, use -GHC' s hole variables, e.g.: - -```haskell -{-@ myMap :: (a -> b) -> xs:[a] -> {v:[b] | len v == len xs} @-} -myMap :: (a -> b) -> [a] -> [b] -myMap = _goal -``` - -## Limitations - -This is an experimental feature, so potential users could only -expect to synthesize programs, like [these](https://github.com/ucsd-progsys/liquidhaskell/tree/develop/tests/synthesis). - -Current limitations include: - -- No boolean conditionals are synthesized. -- Holes can only appear at top level, e.g.: - - {-@ f :: x: [a] -> { v: [a] | v == x } @-} - f :: [a] -> [a] - -- This works - f = _hole - -- This does not work - f x = _hole - -- Only one hole can appear in each module. - # Relational Types **Status:** `experimental` @@ -1014,24 +934,25 @@ incr = (+ 1) Monotonicity states that for any `x1, x2 :: Int` such that `x1 < x2`, inequality `incr x1 < incr x2` holds. This can be expressed as a comparison property on `incr`. ```haskell -{-@ relational incr ~ incr - :: x1:Int -> Int ~ x2:Int -> Int ~~ x1 < x2 => r1 x1 < r2 x2 @-} +{-@ relational incr ~ incr :: { x1:Int -> Int + ~ x2:Int -> Int + | x1 < x2 :=> r1 x1 < r2 x2 } @-} ``` Relational signature starts with the keyword `relational`. Next, it contains two functions being compared `incr ~ incr`. To prove monotonicity, we compare `incr` to itself. In the general case, it is possible to compare two different functions. -Related expressions are followed by their type signatures `x1:Int -> Int` and `x2:Int -> Int` separated with a tilde. The last component of the signature is a predicate `x1 < x2 => r1 x1 < r2 x2`. +Related expressions are followed by their type signatures `x1:Int -> Int` and `x2:Int -> Int` separated with a tilde. The last component of the signature is a predicate `x1 < x2 :=> r1 x1 < r2 x2`. -Binders `x1` and `x2` refer to the functions' arguments. Keywords `r1` and `r2` are aliases for lhs `incr` and rhs `incr` respectively. +Binders `x1` and `x2` refer to the functions' arguments. Keywords `r1` and `r2` are aliases for lhs `incr` and rhs `incr` respectively. The predicate is logically equivalent to `x1 < x2 => r1 x1 < r2 x2`. Implication symbol `:=>` separates the precondition on the arguments from the postcondition on the return values. ### Relational Predicate Syntax -A relational predicate is a sequence of clauses separated by top-level implication connectives `=>`: +A relational predicate is a sequence of clauses separated by top-level implication connectives `:=>` (logically equivalent to `=>`): ``` -x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 -^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^ - 1st 2nd 3rd clause +x1 < x2 :=> y1 < y2 :=> r1 x1 y1 < r2 x2 y2 +^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^ + 1st 2nd 3rd clause ``` * Number of Clauses @@ -1044,16 +965,15 @@ x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 -- clauses == arguments + 1 - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 @-} - ^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^ + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | x1 < x2 :=> y1 < y2 :=> r1 x1 y1 < r2 x2 y2 } @-} + ^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ``` - For example, function `incr` has 1 argument. Its relational predicate has 1 implication that separates the precondition from the postcondition: `x1 < x2 => r1 x1 < r2 x2`. + For example, function `incr` has 1 argument. Its relational predicate has 1 implication that separates the precondition from the postcondition: `x1 < x2 :=> r1 x1 < r2 x2`. - Nested, non-top-level implications are allowed, e.g. `(true => x1 < x2) => (r1 x1 < r2 x2)`. + Nested, non-top-level implications are allowed, e.g. `(true => x1 < x2) :=> (r1 x1 < r2 x2)`. * Argument Scopes @@ -1063,43 +983,38 @@ x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 ```haskell -- ERROR: clauses < arguments + 1 - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ x1 < x2 && y1 < y2 => r1 x1 y1 < r2 x2 y2 @-} + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | x1 < x2 && y1 < y2 :=> r1 x1 y1 < r2 x2 y2 } @-} -- ERROR: y1 and y2 used before their introduction - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ y1 < y2 => x1 < x2 => r1 x1 y1 < r2 x2 y2 @-} + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | y1 < y2 :=> x1 < x2 :=> r1 x1 y1 < r2 x2 y2 } @-} ``` Correct versions could look like this: ```haskell - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 @-} - - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ true => x1 < x2 && y1 < y2 => r1 x1 y1 < r2 x2 y2 @-} - - {-@ relational plus ~ plus - :: x1:Int -> y1:Int -> Int - ~ x2:Int -> y2:Int -> Int - ~~ true => true => (x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2) @-} + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | x1 < x2 :=> y1 < y2 :=> r1 x1 y1 < r2 x2 y2 } @-} + + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | true :=> x1 < x2 && y1 < y2 :=> r1 x1 y1 < r2 x2 y2 } @-} + + {-@ relational plus ~ plus :: { x1:Int -> y1:Int -> Int + ~ x2:Int -> y2:Int -> Int + | true :=> true :=> x1 < x2 => y1 < y2 => r1 x1 y1 < r2 x2 y2 } @-} ``` ### Provided Guarantees -For all possible inputs of the two compared functions, it is guaranteed that the relational predicate holds. +For all possible inputs of the two compared functions, it is guaranteed that the relational predicate holds. ### Running Relational Checks @@ -1115,6 +1030,6 @@ Or in a Haskell source file: ### Current limitations -- No support for abstract refinements. Notably, means no support for the standard list `[a]` and tuple `(a, b)` types which have implicit abstract refinements. Please use user-defined lists and tuples instead. +- No support for abstract refinements. All abstract refinements are erased before relational typechecking. Notably, this happens for the standard list `[a]` and tuple `(a, b)` types! -- Limited support for higher-order relational signatures. +- Limited support for higher-order relational signatures. Use `!=>` instead of `:=>` after the function arguments to enable higher-order checking. diff --git a/exe/Liquid.hs b/exe/Liquid.hs deleted file mode 100644 index b6c4c39755..0000000000 --- a/exe/Liquid.hs +++ /dev/null @@ -1,6 +0,0 @@ -import Language.Haskell.Liquid.Liquid (liquid) -import System.Environment (getArgs) --- import GhcTest - -main :: IO a -main = liquid =<< getArgs diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 8ead923564..0000000000 --- a/flake.lock +++ /dev/null @@ -1,68 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "locked": { - "lastModified": 1652776076, - "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "liquid-fixpoint": { - "inputs": { - "flake-utils": [ - "flake-utils" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1653693908, - "narHash": "sha256-IYrQB9M/XdDaDzQ1576iUNvbehJ4fUlKvPtg5l/Z5xU=", - "owner": "plredmond", - "repo": "liquid-fixpoint", - "rev": "8ce7686045c49b25b46ea3024e9c0dd2979d8488", - "type": "github" - }, - "original": { - "owner": "plredmond", - "ref": "nix-flake", - "repo": "liquid-fixpoint", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1653504306, - "narHash": "sha256-bqjEskV+/tqOQqSEaCu4e6uWZ0F7ekBiMR16xpn4V0k=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "6efc186e6079ff3f328a2497ff3d36741ac60f6e", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-22.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "liquid-fixpoint": "liquid-fixpoint", - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 0d5bffe08b..0000000000 --- a/flake.nix +++ /dev/null @@ -1,131 +0,0 @@ -{ - - description = "LiquidHaskell packages"; - - inputs = { - nixpkgs.url = github:NixOS/nixpkgs/nixos-22.05; - flake-utils.url = github:numtide/flake-utils; - - liquid-fixpoint.url = github:plredmond/liquid-fixpoint/nix-flake; # TODO change to official repo after merge - liquid-fixpoint.inputs.nixpkgs.follows = "nixpkgs"; - liquid-fixpoint.inputs.flake-utils.follows = "flake-utils"; - }; - - outputs = { self, nixpkgs, flake-utils, liquid-fixpoint }: - let - composeOverlays = funs: builtins.foldl' nixpkgs.lib.composeExtensions (self: super: { }) funs; - haskellOverlay = compiler: final: prev: new: - let new-overrides = new.overrides or (a: b: { }); in - { - haskell = prev.haskell // { - packages = prev.haskell.packages // { - ${compiler} = prev.haskell.packages.${compiler}.override - (old: old // new // { - overrides = self: super: old.overrides self super // new-overrides self super; - }); - }; - }; - }; - haskellPackagesOverlay = compiler: final: prev: cur-packages-overlay: - haskellOverlay compiler final prev { overrides = cur-packages-overlay; }; - ghc = "ghc8107"; # Based on https://github.com/ucsd-progsys/liquid-fixpoint/blob/develop/stack.yaml#L3 - beComponent = pkgs: pkg: pkgs.haskell.lib.overrideCabal pkg (old: { - enableLibraryProfiling = false; - buildTools = (old.buildTools or [ ]) ++ [ pkgs.z3 ]; - }); - mkOutputs = system: - let - # do not use when defining the overlays - pkgs = import nixpkgs { - inherit system; - overlays = [ self.overlay.${system} ]; - }; - in - { - - packages = { - # Group 1: LH without tests - liquidhaskell = pkgs.haskell.packages.${ghc}.liquidhaskell; - # Group 2: Depends on LH - liquid-ghc-prim = pkgs.haskell.packages.${ghc}.liquid-ghc-prim; - # Group 3: Depends on liquid-ghc-prim - liquid-base = pkgs.haskell.packages.${ghc}.liquid-base; - # Group 4: Depends on liquid-base - liquid-bytestring = pkgs.haskell.packages.${ghc}.liquid-bytestring; - liquid-containers = pkgs.haskell.packages.${ghc}.liquid-containers; - liquid-parallel = pkgs.haskell.packages.${ghc}.liquid-parallel; - liquid-platform = pkgs.haskell.packages.${ghc}.liquid-platform; - liquid-prelude = pkgs.haskell.packages.${ghc}.liquid-prelude; - liquid-vector = pkgs.haskell.packages.${ghc}.liquid-vector; - # Group 5: Depends on all of the above - liquidhaskell_with_tests = pkgs.haskell.packages.${ghc}.liquidhaskell_with_tests; - }; - - defaultPackage = pkgs.haskell.packages.${ghc}.liquidhaskell_with_tests; - - devShell = self.defaultPackage.${system}.env; - - overlay = composeOverlays [ - liquid-fixpoint.overlay.${system} - self.overlays.${system}.updateAllCabalHashes - self.overlays.${system}.addLiquidHaskellWithoutTests - self.overlays.${system}.addLiquidGHCPrim - self.overlays.${system}.addLiquidBase - self.overlays.${system}.addLiquidHaskellPackages - self.overlays.${system}.addLiquidHaskellWithTests - ]; - - overlays = { - updateAllCabalHashes = final: prev: - { - all-cabal-hashes = final.fetchurl { - # fetch latest cabal hashes https://github.com/commercialhaskell/all-cabal-hashes/commits/hackage as of Fri May 27 06:40:19 PM UTC 2022 - url = "https://github.com/commercialhaskell/all-cabal-hashes/archive/91cbef8524376834839ea2814010a0258a06e37e.tar.gz"; - sha256 = "01h8cd2b1w4060dyyh4zz604gpjyzhvvc0mb1aj18b1z2bcgfakj"; - }; - }; - addLiquidHaskellWithoutTests = final: prev: haskellPackagesOverlay ghc final prev (selfH: superH: - let callCabal2nix = final.haskell.packages.${ghc}.callCabal2nix; in - with final.haskell.lib; { - liquidhaskell = - let src = final.nix-gitignore.gitignoreSource [ ".swp" "*.nix" "result" "liquid-*" ] ./.; - in - dontHaddock # src/Language/Haskell/Liquid/Types/RefType.hs:651:3: error: parse error on input ‘-- | _meetable t1 t2’ - (doJailbreak # LH requires slightly old versions of recursion-schemes and optparse-applicative - (dontCheck (beComponent final (callCabal2nix "liquidhaskell" src { })))); - }); - addLiquidGHCPrim = final: prev: haskellPackagesOverlay ghc final prev (selfH: superH: - let callCabal2nix = final.haskell.packages.${ghc}.callCabal2nix; in - with final.haskell.lib; { - liquid-ghc-prim = dontHaddock (beComponent final (callCabal2nix "liquid-ghc-prim" ./liquid-ghc-prim { })); - }); - addLiquidBase = final: prev: haskellPackagesOverlay ghc final prev (selfH: superH: - let callCabal2nix = final.haskell.packages.${ghc}.callCabal2nix; in - with final.haskell.lib; { - liquid-base = dontHaddock (beComponent final (callCabal2nix "liquid-base" ./liquid-base { })); - }); - addLiquidHaskellPackages = final: prev: haskellPackagesOverlay ghc final prev (selfH: superH: - let callCabal2nix = final.haskell.packages.${ghc}.callCabal2nix; in - with final.haskell.lib; { - liquid-bytestring = (beComponent final (callCabal2nix "liquid-bytestring" ./liquid-bytestring { })); - liquid-containers = (beComponent final (callCabal2nix "liquid-containers" ./liquid-containers { })); - liquid-parallel = (beComponent final (callCabal2nix "liquid-parallel" ./liquid-parallel { })); - liquid-platform = (beComponent final (callCabal2nix "liquid-platform" ./liquid-platform { })); - liquid-prelude = (beComponent final (callCabal2nix "liquid-prelude" ./liquid-prelude { })); - liquid-vector = (beComponent final (callCabal2nix "liquid-vector" ./liquid-vector { })); - }); - addLiquidHaskellWithTests = final: prev: haskellPackagesOverlay ghc final prev (selfH: superH: - with final.haskell.lib; { - liquidhaskell_with_tests = overrideCabal selfH.liquidhaskell (old: { - doCheck = true; # change the value set above - testDepends = old.testDepends or [ ] ++ [ final.hostname ]; - testHaskellDepends = old.testHaskellDepends ++ builtins.attrValues (builtins.removeAttrs self.packages.${system} [ "liquidhaskell_with_tests" ]); - preCheck = ''export TASTY_LIQUID_RUNNER="liquidhaskell -v0"''; - }); - }); - }; - - }; - in - flake-utils.lib.eachDefaultSystem mkOutputs; -} diff --git a/include/710/Data/Traversable.spec b/include/710/Data/Traversable.spec deleted file mode 100644 index c47696d147..0000000000 --- a/include/710/Data/Traversable.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec Data.Traversable where - -Data.Traversable.sequence :: Data.Traversable.Traversable t => forall m a. GHC.Base.Monad m => xs:t (m a) -> m ({v:t a | len v = len xs}) diff --git a/include/Bot.hquals b/include/Bot.hquals deleted file mode 100644 index 0382d0c64e..0000000000 --- a/include/Bot.hquals +++ /dev/null @@ -1,8 +0,0 @@ -//BOT: Do not delete EVER! - -qualif Bot(v:@(0)) : 0 = 1 -qualif Bot(v:obj) : 0 = 1 -qualif Bot(v:a) : 0 = 1 -qualif Bot(v:bool) : 0 = 1 -qualif Bot(v:int) : 0 = 1 - diff --git a/include/Control/Exception.spec b/include/Control/Exception.spec deleted file mode 100644 index 5e68bf44ca..0000000000 --- a/include/Control/Exception.spec +++ /dev/null @@ -1,5 +0,0 @@ -module spec Control.Exception where - -// Useless as compiled into GHC primitive, which is ignored -assume assert :: {v:Bool | v } -> a -> a - diff --git a/include/Control/Parallel/Strategies.spec b/include/Control/Parallel/Strategies.spec deleted file mode 100644 index a0fd3a197c..0000000000 --- a/include/Control/Parallel/Strategies.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec Control.Parallel.Strategies where - -assume withStrategy :: Control.Parallel.Strategies.Strategy a -> x:a -> {v:a | v == x} diff --git a/include/CoreToLogic.lg b/include/CoreToLogic.lg index efb2e0d5aa..6fe3124087 100644 --- a/include/CoreToLogic.lg +++ b/include/CoreToLogic.lg @@ -23,6 +23,7 @@ define GHC.Real.fromIntegral x = (x) define GHC.Types.True = (true) define GHC.Real.div x y = (x / y) define GHC.Real.mod x y = (x mod y) +define GHC.Classes.not x = (~ x) define GHC.Base.$ f x = (f x) define Language.Haskell.Liquid.Bag.get k m = (Map_select m k) diff --git a/include/Data/Bits.spec b/include/Data/Bits.spec deleted file mode 100644 index 2ab553b565..0000000000 --- a/include/Data/Bits.spec +++ /dev/null @@ -1,6 +0,0 @@ -module spec Data.Bits where - -// TODO: cannot use this because `Bits` is not a `Num` -// Data.Bits.shiftR :: (Data.Bits.Bits a) => x:a -> d:Nat -// -> {v:a | ((d=1) => (x <= 2*v + 1 && 2*v <= x)) } - diff --git a/include/Data/ByteString.spec b/include/Data/ByteString.spec deleted file mode 100644 index 89cc03fbec..0000000000 --- a/include/Data/ByteString.spec +++ /dev/null @@ -1,375 +0,0 @@ -module spec Data.ByteString where - -import Data.String - -measure bslen :: Data.ByteString.ByteString -> { n : Int | 0 <= n } - -invariant { bs : Data.ByteString.ByteString | 0 <= bslen bs } - -invariant { bs : Data.ByteString.ByteString | bslen bs == stringlen bs } - -empty :: { bs : Data.ByteString.ByteString | bslen bs == 0 } - -singleton :: _ -> { bs : Data.ByteString.ByteString | bslen bs == 1 } - -pack :: w8s : [_] - -> { bs : Data.ByteString.ByteString | bslen bs == len w8s } - -unpack :: bs : Data.ByteString.ByteString - -> { w8s : [_] | len w8s == bslen bs } - -cons :: _ - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i + 1 } - -snoc :: i : Data.ByteString.ByteString - -> _ - -> { o : Data.ByteString.ByteString | bslen o == bslen i + 1 } - -append :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen l + bslen r } - -head :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -unsnoc :: i:Data.ByteString.ByteString - -> (Maybe ({ o : Data.ByteString.ByteString | bslen o == bslen i - 1 }, _)) - -last :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -tail :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -init - :: {i:Data.ByteString.ByteString | 1 <= bslen i } - -> {o:Data.ByteString.ByteString | bslen o == bslen i - 1 } - -null - :: bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | b <=> bslen bs == 0 } - -length :: bs : Data.ByteString.ByteString -> { n : Int | bslen bs == n } - -map - :: (_ -> _) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -reverse - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -intersperse - :: _ - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (bslen i == 0 <=> bslen o == 0) && (1 <= bslen i <=> bslen o == 2 * bslen i - 1) } - -intercalate - :: l : Data.ByteString.ByteString - -> rs : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | len rs == 0 ==> bslen o == 0 } - -transpose - :: is : [Data.ByteString.ByteString] - -> { os : [{ bs : Data.ByteString.ByteString | bslen bs <= len is }] | len is == 0 ==> len os == 0} - -foldl1 - :: (_ -> _ -> _) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> _ - -foldl1' - :: (_ -> _ -> _) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> _ - -foldr1 - :: (_ -> _ -> _) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> _ - -foldr1' - :: (_ -> _ -> _) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> _ - -concat - :: is : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | (len is == 0) ==> (bslen o == 0) } - -concatMap - :: (_ -> Data.ByteString.ByteString) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen i == 0 ==> bslen o == 0 } - -any - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> not b } - -all - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> b } - -maximum :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -minimum :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -scanl :: (_ -> _ -> _) - -> _ - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -scanl1 :: (_ -> _ -> _) - -> i : { i : Data.ByteString.ByteString | 1 <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -scanr - :: (_ -> _ -> _) - -> _ - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -scanr1 - :: (_ -> _ -> _) - -> i : { i : Data.ByteString.ByteString | 1 <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -mapAccumL - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.ByteString.ByteString - -> (acc, { o : Data.ByteString.ByteString | bslen o == bslen i }) - -mapAccumR - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.ByteString.ByteString - -> (acc, { o : Data.ByteString.ByteString | bslen o == bslen i }) - -replicate - :: n : Int - -> _ - -> { bs : Data.ByteString.ByteString | bslen bs == n } - -unfoldrN - :: n : Int - -> (a -> Maybe (_, a)) - -> a - -> ({ bs : Data.ByteString.ByteString | bslen bs <= n }, Maybe a) - -take - :: n : Int - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (n <= 0 <=> bslen o == 0) && - ((0 <= n && n <= bslen i) <=> bslen o == n) && - (bslen i <= n <=> bslen o = bslen i) } - -drop - :: n : Int - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (n <= 0 <=> bslen o == bslen i) && - ((0 <= n && n <= bslen i) <=> bslen o == bslen i - n) && - (bslen i <= n <=> bslen o == 0) } - -splitAt - :: n : Int - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | (n <= 0 <=> bslen l == 0) && - ((0 <= n && n <= bslen i) <=> bslen l == n) && - (bslen i <= n <=> bslen l == bslen i) } - , { r : Data.ByteString.ByteString | (n <= 0 <=> bslen r == bslen i) && - ((0 <= n && n <= bslen i) <=> bslen r == bslen i - n) && - (bslen i <= n <=> bslen r == 0) } - ) - -takeWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -dropWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -span - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -spanEnd - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -break - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -breakEnd - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -group - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | 1 <= bslen o && bslen o <= bslen i }] - -groupBy - :: (_ -> _ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | 1 <= bslen o && bslen o <= bslen i }] - -inits - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -tails - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -split - :: _ - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -splitWith - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -isPrefixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l >= bslen r ==> not b } - -isSuffixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l > bslen r ==> not b } - -isInfixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l > bslen r ==> not b } - -breakSubstring - :: il : Data.ByteString.ByteString - -> ir : Data.ByteString.ByteString - -> ( { ol : Data.ByteString.ByteString | bslen ol <= bslen ir && (bslen il > bslen ir ==> bslen ol == bslen ir)} - , { or : Data.ByteString.ByteString | bslen or <= bslen ir && (bslen il > bslen ir ==> bslen or == 0) } - ) - -elem - :: _ - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> not b } - -notElem - :: _ - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> b } - -find - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> (Maybe { w8 : _ | bslen bs /= 0 }) - -filter - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -partition - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -index :: bs : Data.ByteString.ByteString -> { n : Int | 0 <= n && n < bslen bs } -> _ - -elemIndex - :: _ - -> bs : Data.ByteString.ByteString - -> (Maybe { n : Int | 0 <= n && n < bslen bs }) - -elemIndices - :: _ - -> bs : Data.ByteString.ByteString - -> [{ n : Int | 0 <= n && n < bslen bs }] - -elemIndexEnd - :: _ - -> bs : Data.ByteString.ByteString - -> (Maybe { n : Int | 0 <= n && n < bslen bs }) - -findIndex - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> (Maybe { n : Int | 0 <= n && n < bslen bs }) - -findIndices - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> [{ n : Int | 0 <= n && n < bslen bs }] - -count - :: _ - -> bs : Data.ByteString.ByteString - -> { n : Int | 0 <= n && n < bslen bs } - -zip - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : [(_, _)] | len o <= bslen l && len o <= bslen r } - -zipWith - :: (_ -> _ -> a) - -> l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : [a] | len o <= bslen l && len o <= bslen r } - -unzip - :: i : [(_, _)] - -> ( { l : Data.ByteString.ByteString | bslen l == len i } - , { r : Data.ByteString.ByteString | bslen r == len i } - ) - -sort - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -copy - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -hGet - :: _ - -> n : { n : Int | 0 <= n } - -> (IO { bs : Data.ByteString.ByteString | bslen bs == n || bslen bs == 0 }) - -hGetSome - :: _ - -> n : { n : Int | 0 <= n } - -> (IO { bs : Data.ByteString.ByteString | bslen bs <= n }) - -hGetNonBlocking - :: _ - -> n : { n : Int | 0 <= n } - -> (IO { bs : Data.ByteString.ByteString | bslen bs <= n }) - -uncons - :: i : Data.ByteString.ByteString - -> (Maybe (_, { o : Data.ByteString.ByteString | bslen o == bslen i - 1 })) - diff --git a/include/Data/ByteString/Char8.spec b/include/Data/ByteString/Char8.spec deleted file mode 100644 index a9c96565fc..0000000000 --- a/include/Data/ByteString/Char8.spec +++ /dev/null @@ -1,402 +0,0 @@ -module spec Data.ByteString.Char8 where - -import Data.ByteString - -assume empty :: { bs : Data.ByteString.ByteString | bslen bs == 0 } - -assume singleton - :: Char -> { bs : Data.ByteString.ByteString | bslen bs == 1 } - -assume pack - :: w8s : [Char] - -> { bs : Data.ByteString.ByteString | bslen bs == len w8s } - -assume unpack - :: bs : Data.ByteString.ByteString - -> { w8s : [Char] | len w8s == bslen bs } - -assume cons - :: Char - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i + 1 } - -assume snoc - :: i : Data.ByteString.ByteString - -> Char - -> { o : Data.ByteString.ByteString | bslen o == bslen i + 1 } - -assume append - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen l + bslen r } - -head :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -assume uncons - :: i : Data.ByteString.ByteString - -> Maybe (Char, { o : Data.ByteString.ByteString | bslen o == bslen i - 1 }) - -assume unsnoc - :: i : Data.ByteString.ByteString - -> Maybe ({ o : Data.ByteString.ByteString | bslen o == bslen i - 1 }, Char) - -assume last :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -assume tail :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -assume init :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -assume null - :: bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | b <=> bslen bs == 0 } - -assume length :: bs : Data.ByteString.ByteString -> { n : Int | bslen bs == n } - -assume map - :: (Char -> Char) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume reverse - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume intersperse - :: Char - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (bslen i == 0 <=> bslen o == 0) && (1 <= bslen i <=> bslen o == 2 * bslen i - 1) } - -assume intercalate - :: l : Data.ByteString.ByteString - -> rs : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | len rs == 0 ==> bslen o == 0 } - -assume transpose - :: is : [Data.ByteString.ByteString] - -> { os : [{ bs : Data.ByteString.ByteString | bslen bs <= len is }] | len is == 0 ==> len os == 0} - -foldl1 - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> Char - -foldl1' - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> Char - -foldr1 - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> Char - -foldr1' - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.ByteString | 1 <= bslen bs } - -> Char - -assume concat - :: is : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | len is == 0 ==> bslen o } - -assume concatMap - :: (Char -> Data.ByteString.ByteString) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen i == 0 ==> bslen o == 0 } - -assume any :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> not b } - -assume all :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> b } - -maximum - :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -minimum - :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> Char - -assume scanl - :: (Char -> Char -> Char) - -> Char - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume scanl1 - :: (Char -> Char -> Char) - -> i : { i : Data.ByteString.ByteString | 1 <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume scanr - :: (Char -> Char -> Char) - -> Char - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume scanr1 - :: (Char -> Char -> Char) - -> i : { i : Data.ByteString.ByteString | 1 <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume mapAccumL - :: (acc -> Char -> (acc, Char)) - -> acc - -> i : Data.ByteString.ByteString - -> (acc, { o : Data.ByteString.ByteString | bslen o == bslen i }) - -assume mapAccumR - :: (acc -> Char -> (acc, Char)) - -> acc - -> i : Data.ByteString.ByteString - -> (acc, { o : Data.ByteString.ByteString | bslen o == bslen i }) - -assume replicate - :: n : Int - -> Char - -> { bs : Data.ByteString.ByteString | bslen bs == n } - -assume unfoldrN - :: n : Int - -> (a -> Maybe (Char, a)) - -> a - -> ({ bs : Data.ByteString.ByteString | bslen bs <= n }, Maybe a) - -assume take - :: n : Int - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (n <= 0 <=> bslen o == 0) && - ((0 <= n && n <= bslen i) <=> bslen o == n) && - (bslen i <= n <=> bslen o = bslen i) } - -assume drop - :: n : Int - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | (n <= 0 <=> bslen o == bslen i) && - ((0 <= n && n <= bslen i) <=> bslen o == bslen i - n) && - (bslen i <= n <=> bslen o == 0) } - -assume splitAt - :: n : Int - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | (n <= 0 <=> bslen l == 0) && - ((0 <= n && n <= bslen i) <=> bslen l == n) && - (bslen i <= n <=> bslen l == bslen i) } - , { r : Data.ByteString.ByteString | (n <= 0 <=> bslen r == bslen i) && - ((0 <= n && n <= bslen i) <=> bslen r == bslen i - n) && - (bslen i <= n <=> bslen r == 0) } - ) - -assume takeWhile - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -assume dropWhile - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -assume span - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -assume spanEnd - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -assume break - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -assume breakEnd - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - , { r : Data.ByteString.ByteString | bslen r <= bslen i } - ) - -assume group - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | 1 <= bslen o && bslen o <= bslen i }] - -assume groupBy - :: (Char -> Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | 1 <= bslen o && bslen o <= bslen i }] - -assume inits - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume tails - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume split - :: Char - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume splitWith - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume lines - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume words - :: i : Data.ByteString.ByteString - -> [{ o : Data.ByteString.ByteString | bslen o <= bslen i }] - -assume unlines - :: is : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | (len is == 0 <=> bslen o == 0) && bslen o >= len is } - -assume unwords - :: is : [Data.ByteString.ByteString] - -> { o : Data.ByteString.ByteString | (len is == 0 ==> bslen o == 0) && (1 <= len is ==> bslen o >= len is - 1) } - -assume isPrefixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l >= bslen r ==> not b } - -assume isSuffixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l > bslen r ==> not b } - -assume isInfixOf - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen l > bslen r ==> not b } - -assume breakSubstring - :: il : Data.ByteString.ByteString - -> ir : Data.ByteString.ByteString - -> ( { ol : Data.ByteString.ByteString | bslen ol <= bslen ir && (bslen il > bslen ir ==> bslen ol == bslen ir)} - , { or : Data.ByteString.ByteString | bslen or <= bslen ir && (bslen il > bslen ir ==> bslen or == 0) } - ) - -assume elem - :: Char - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> not b } - -assume notElem - :: Char - -> bs : Data.ByteString.ByteString - -> { b : GHC.Types.Bool | bslen bs == 0 ==> b } - -assume find - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> Maybe { w8 : Char | bslen bs /= 0 } - -assume filter - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o <= bslen i } - -index - :: bs : Data.ByteString.ByteString - -> { n : Int | 0 <= n && n < bslen bs } - -> Char - -assume elemIndex - :: Char - -> bs : Data.ByteString.ByteString - -> Maybe { n : Int | 0 <= n && n < bslen bs } - -assume elemIndices - :: Char - -> bs : Data.ByteString.ByteString - -> [{ n : Int | 0 <= n && n < bslen bs }] - -assume elemIndexEnd - :: Char - -> bs : Data.ByteString.ByteString - -> Maybe { n : Int | 0 <= n && n < bslen bs } - -assume findIndex - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> Maybe { n : Int | 0 <= n && n < bslen bs } - -assume findIndices - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.ByteString - -> [{ n : Int | 0 <= n && n < bslen bs }] - -assume count - :: Char - -> bs : Data.ByteString.ByteString - -> { n : Int | 0 <= n && n < bslen bs } - -assume zip - :: l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : [(Char, Char)] | len o <= bslen l && len o <= bslen r } - -assume zipWith - :: (Char -> Char -> a) - -> l : Data.ByteString.ByteString - -> r : Data.ByteString.ByteString - -> { o : [a] | len o <= bslen l && len o <= bslen r } - -assume unzip - :: i : [(Char, Char)] - -> ( { l : Data.ByteString.ByteString | bslen l == len i } - , { r : Data.ByteString.ByteString | bslen r == len i } - ) - -assume sort - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume readInt - :: i : Data.ByteString.ByteString - -> Maybe { p : (Int, { o : Data.ByteString.ByteString | bslen o < bslen i}) | bslen i /= 0 } - -assume readInteger - :: i : Data.ByteString.ByteString - -> Maybe { p : (Integer, { o : Data.ByteString.ByteString | bslen o < bslen i}) | bslen i /= 0 } - -assume copy - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bslen i } - -assume hGet - :: System.IO.Handle - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.ByteString | bslen bs == n || bslen bs == 0 } - -assume hGetSome - :: System.IO.Handle - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.ByteString | bslen bs <= n } - -assume hGetNonBlocking - :: System.IO.Handle - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.ByteString | bslen bs <= n } - -// assume partition - // :: (Char -> GHC.Types.Bool) - // -> i : Data.ByteString.ByteString - // -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } - // , { r : Data.ByteString.ByteString | bslen r <= bslen i } - // ) diff --git a/include/Data/ByteString/Lazy.spec b/include/Data/ByteString/Lazy.spec deleted file mode 100644 index 63b2b3da1c..0000000000 --- a/include/Data/ByteString/Lazy.spec +++ /dev/null @@ -1,338 +0,0 @@ -module spec Data.ByteString.Lazy where - -import Data.String -import Data.ByteString - -measure bllen :: Data.ByteString.Lazy.ByteString -> { n : GHC.Int.Int64 | 0 <= n } - -invariant { bs : Data.ByteString.Lazy.ByteString | 0 <= bllen bs } - -invariant { bs : Data.ByteString.Lazy.ByteString | bllen bs == stringlen bs } - -assume empty :: { bs : Data.ByteString.Lazy.ByteString | bllen bs == 0 } - -assume singleton - :: _ -> { bs : Data.ByteString.Lazy.ByteString | bllen bs == 1 } - -assume pack - :: w8s : [_] - -> { bs : _ | bllen bs == len w8s } - -assume unpack - :: bs : Data.ByteString.Lazy.ByteString - -> { w8s : [_] | len w8s == bllen bs } - -assume fromStrict - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bslen i } - -assume toStrict - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bllen i } - -assume fromChunks - :: i : [Data.ByteString.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | len i == 0 <=> bllen o == 0 } - -assume toChunks - :: i : Data.ByteString.Lazy.ByteString - -> { os : [{ o : Data.ByteString.ByteString | bslen o <= bllen i}] | len os == 0 <=> bllen i == 0 } - -assume cons - :: _ - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i + 1 } - -assume snoc - :: i : Data.ByteString.Lazy.ByteString - -> _ - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i + 1 } - -assume append - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen l + bllen r } - -assume head - :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> _ - -assume uncons - :: i : Data.ByteString.Lazy.ByteString - -> Maybe (_, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i - 1 }) - -assume unsnoc - :: i : Data.ByteString.Lazy.ByteString - -> Maybe ({ o : Data.ByteString.Lazy.ByteString | bllen o == bllen i - 1 }, _) - -assume last :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> _ - -assume tail :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> _ - -assume init :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> _ - -assume null :: bs : Data.ByteString.Lazy.ByteString -> { b : GHC.Types.Bool | b <=> bllen bs == 0 } - -assume length - :: bs : Data.ByteString.Lazy.ByteString -> { n : GHC.Int.Int64 | bllen bs == n } - -assume map - :: (_ -> _) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume reverse - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume intersperse - :: _ - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (bllen i == 0 <=> bllen o == 0) && (1 <= bllen i <=> bllen o == 2 * bllen i - 1) } - -assume intercalate - :: l : Data.ByteString.Lazy.ByteString - -> rs : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | len rs == 0 ==> bllen o == 0 } - -assume transpose - :: is : [Data.ByteString.Lazy.ByteString] - -> { os : [{ bs : Data.ByteString.Lazy.ByteString | bllen bs <= len is }] | len is == 0 ==> len os == 0} - -assume foldl1 - :: (_ -> _ -> _) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> _ - -assume foldl1' - :: (_ -> _ -> _) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> _ - -assume foldr1 - :: (_ -> _ -> _) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> _ - -assume concat - :: is : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | (len is == 0) ==> (bllen o == 0) } - -assume concatMap - :: (_ -> Data.ByteString.Lazy.ByteString) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen i == 0 ==> bllen o == 0 } - -assume any :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen bs == 0 ==> not b } - -assume all :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen bs == 0 ==> b } - -assume maximum :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> _ - -assume minimum :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> _ - -assume scanl - :: (_ -> _ -> _) - -> _ - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume mapAccumL - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.ByteString.Lazy.ByteString - -> (acc, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i }) - -assume mapAccumR - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.ByteString.Lazy.ByteString - -> (acc, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i }) - -assume replicate - :: n : GHC.Int.Int64 - -> _ - -> { bs : Data.ByteString.Lazy.ByteString | bllen bs == n } - -assume take - :: n : GHC.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (n <= 0 ==> bllen o == 0) && - ((0 <= n && n <= bllen i) <=> bllen o == n) && - (bllen i <= n <=> bllen o = bllen i) } - -assume drop - :: n : GHC.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen o == bllen i) && - ((0 <= n && n <= bllen i) <=> bllen o == bllen i - n) && - (bllen i <= n <=> bllen o == 0) } - -assume splitAt - :: n : GHC.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen l == 0) && - ((0 <= n && n <= bllen i) <=> bllen l == n) && - (bllen i <= n <=> bllen l == bllen i) } - , { r : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen r == bllen i) && - ((0 <= n && n <= bllen i) <=> bllen r == bllen i - n) && - (bllen i <= n <=> bllen r == 0) } - ) - -assume takeWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume dropWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume span - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume break - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume group - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | 1 <= bllen o && bllen o <= bllen i }] - -assume groupBy - :: (_ -> _ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | 1 <= bllen o && bllen o <= bllen i }] - -assume inits - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume tails - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume split - :: _ - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume splitWith - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume isPrefixOf - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen l >= bllen r ==> not b } - -assume isSuffixOf - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen l >= bllen r ==> not b } - -assume elem - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | (bllen bs == 0) ==> not b } - -assume notElem - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | (bllen bs == 0) ==> b } - -assume find - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { w8 : _ | bllen bs /= 0 } - -assume filter - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume partition - :: (_ -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume index - :: bs : Data.ByteString.Lazy.ByteString - -> { n : GHC.Int.Int64 | 0 <= n && n < bllen bs } - -> _ - -assume elemIndex - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : GHC.Int.Int64 | 0 <= n && n < bllen bs } - -assume elemIndices - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> [{ n : GHC.Int.Int64 | 0 <= n && n < bllen bs }] - -assume elemIndexEnd - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : GHC.Int.Int64 | 0 <= n && n < bllen bs } - -assume findIndex - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : GHC.Int.Int64 | 0 <= n && n < bllen bs } - -assume findIndices - :: (_ -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> [{ n : GHC.Int.Int64 | 0 <= n && n < bllen bs }] - -assume count - :: _ - -> bs : Data.ByteString.Lazy.ByteString - -> { n : GHC.Int.Int64 | 0 <= n && n < bllen bs } - -assume zip - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : [(_, _)] | len o <= bllen l && len o <= bllen r } - -assume zipWith - :: (_ -> _ -> a) - -> l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : [a] | len o <= bllen l && len o <= bllen r } - -assume unzip - :: i : [(_, _)] - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l == len i } - , { r : Data.ByteString.Lazy.ByteString | bllen r == len i } - ) - -assume copy - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume hGet - :: _ - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.Lazy.ByteString | bllen bs == n || bllen bs == 0 } - -assume hGetNonBlocking - :: _ - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.Lazy.ByteString | bllen bs <= n } diff --git a/include/Data/ByteString/Lazy/Char8.spec b/include/Data/ByteString/Lazy/Char8.spec deleted file mode 100644 index 7207795496..0000000000 --- a/include/Data/ByteString/Lazy/Char8.spec +++ /dev/null @@ -1,417 +0,0 @@ -module spec Data.ByteString.Lazy where - -assume empty :: { bs : Data.ByteString.Lazy.ByteString | bllen bs == 0 } - -assume singleton - :: Char -> { bs : Data.ByteString.Lazy.ByteString | bllen bs == 1 } - -assume pack - :: w8s : [Char] - -> { bs : Data.ByteString.ByteString | bllen bs == len w8s } - -assume unpack - :: bs : Data.ByteString.Lazy.ByteString - -> { w8s : [Char] | len w8s == bllen bs } - -assume fromStrict - :: i : Data.ByteString.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bslen i } - -assume toStrict - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.ByteString | bslen o == bllen i } - -assume fromChunks - :: i : [Data.ByteString.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | len i == 0 <=> bllen o == 0 } - -assume toChunks - :: i : Data.ByteString.Lazy.ByteString - -> { os : [{ o : Data.ByteString.ByteString | bslen o <= bllen i}] | len os == 0 <=> bllen i == 0 } - -assume cons - :: Char - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i + 1 } - -assume snoc - :: i : Data.ByteString.Lazy.ByteString - -> Char - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i + 1 } - -assume append - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen l + bllen r } - -head - :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -assume uncons - :: i : Data.ByteString.Lazy.ByteString - -> Maybe (Char, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i - 1 }) - -assume unsnoc - :: i : Data.ByteString.Lazy.ByteString - -> Maybe ({ o : Data.ByteString.Lazy.ByteString | bllen o == bllen i - 1 }, Char) - -last - :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -tail - :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -init - :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -assume null - :: bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | b <=> bllen bs == 0 } - -assume length - :: bs : Data.ByteString.Lazy.ByteString -> { n : Data.Int.Int64 | bllen bs == n } - -assume map - :: (Char -> Char) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume reverse - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume intersperse - :: Char - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (bllen i == 0 <=> bllen o == 0) && (1 <= bllen i <=> bllen o == 2 * bllen i - 1) } - -assume intercalate - :: l : Data.ByteString.Lazy.ByteString - -> rs : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | len rs == 0 ==> bllen o == 0 } - -assume transpose - :: is : [Data.ByteString.Lazy.ByteString] - -> { os : [{ bs : Data.ByteString.Lazy.ByteString | bllen bs <= len is }] | len is == 0 ==> len os == 0} - -foldl1 - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -foldl1' - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -foldr1 - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -foldr1' - :: (Char -> Char -> Char) - -> { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } - -> Char - -assume concat - :: is : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | len is == 0 ==> bllen o } - -assume concatMap - :: (Char -> Data.ByteString.Lazy.ByteString) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen i == 0 ==> bllen o == 0 } - -assume any :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen bs == 0 ==> not b } - -assume all :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen bs == 0 ==> b } - -maximum :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> Char - -minimum :: { bs : Data.ByteString.Lazy.ByteString | 1 <= bllen bs } -> Char - -assume scanl - :: (Char -> Char -> Char) - -> Char - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume scanl1 - :: (Char -> Char -> Char) - -> i : { i : Data.ByteString.Lazy.ByteString | 1 <= bllen i } - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume scanr - :: (Char -> Char -> Char) - -> Char - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume scanr1 - :: (Char -> Char -> Char) - -> i : { i : Data.ByteString.Lazy.ByteString | 1 <= bllen i } - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume mapAccumL - :: (acc -> Char -> (acc, Char)) - -> acc - -> i : Data.ByteString.Lazy.ByteString - -> (acc, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i }) - -assume mapAccumR - :: (acc -> Char -> (acc, Char)) - -> acc - -> i : Data.ByteString.Lazy.ByteString - -> (acc, { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i }) - -assume replicate - :: n : Data.Int.Int64 - -> Char - -> { bs : Data.ByteString.Lazy.ByteString | bllen bs == n } - -assume unfoldrN - :: n : Int - -> (a -> Maybe (Char, a)) - -> a - -> ({ bs : Data.ByteString.Lazy.ByteString | bllen bs <= n }, Maybe a) - -assume take - :: n : Data.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (n <= 0 ==> bllen o == 0) && - ((0 <= n && n <= bllen i) <=> bllen o == n) && - (bllen i <= n <=> bllen o = bllen i) } - -assume drop - :: n : Data.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen o == bllen i) && - ((0 <= n && n <= bllen i) <=> bllen o == bllen i - n) && - (bllen i <= n <=> bllen o == 0) } - -assume splitAt - :: n : Data.Int.Int64 - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen l == 0) && - ((0 <= n && n <= bllen i) <=> bllen l == n) && - (bllen i <= n <=> bllen l == bllen i) } - , { r : Data.ByteString.Lazy.ByteString | (n <= 0 <=> bllen r == bllen i) && - ((0 <= n && n <= bllen i) <=> bllen r == bllen i - n) && - (bllen i <= n <=> bllen r == 0) } - ) - -assume takeWhile - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume dropWhile - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume span - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume spanEnd - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume break - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -assume breakEnd - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) -assume group - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | 1 <= bllen o && bllen o <= bllen i }] - -assume groupBy - :: (Char -> Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | 1 <= bllen o && bllen o <= bllen i }] - -assume inits - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume tails - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume split - :: Char - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume splitWith - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume lines - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume words - :: i : Data.ByteString.Lazy.ByteString - -> [{ o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i }] - -assume unlines - :: is : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | (len is == 0 <=> bllen o == 0) && bllen o >= len is } - -assume unwords - :: is : [Data.ByteString.Lazy.ByteString] - -> { o : Data.ByteString.Lazy.ByteString | (len is == 0 ==> bllen o == 0) && (1 <= len is ==> bllen o >= len is - 1) } - -assume isPrefixOf - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen l >= bllen r ==> not b } - -assume isSuffixOf - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen l >= bllen r ==> not b } - -assume isInfixOf - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen l >= bllen r ==> not b } - -assume breakSubstring - :: il : Data.ByteString.Lazy.ByteString - -> ir : Data.ByteString.Lazy.ByteString - -> ( { ol : Data.ByteString.Lazy.ByteString | bllen ol <= bllen ir && (bllen il > bllen ir ==> bllen ol == bllen ir)} - , { or : Data.ByteString.Lazy.ByteString | bllen or <= bllen ir && (bllen il > bllen ir ==> bllen or == 0) } - ) - -assume elem - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen b == 0 ==> not b } - -assume notElem - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> { b : GHC.Types.Bool | bllen b == 0 ==> b } - -assume find - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { w8 : Char | bllen bs /= 0 } - -assume filter - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o <= bllen i } - -assume partition - :: (Char -> GHC.Types.Bool) - -> i : Data.ByteString.Lazy.ByteString - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l <= bllen i } - , { r : Data.ByteString.Lazy.ByteString | bllen r <= bllen i } - ) - -index - :: bs : Data.ByteString.Lazy.ByteString - -> { n : Data.Int.Int64 | 0 <= n && n < bllen bs } - -> Char - -assume elemIndex - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : Data.Int.Int64 | 0 <= n && n < bllen bs } - -assume elemIndices - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> [{ n : Data.Int.Int64 | 0 <= n && n < bllen bs }] - -assume elemIndexEnd - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : Data.Int.Int64 | 0 <= n && n < bllen bs } - -assume findIndex - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> Maybe { n : Data.Int.Int64 | 0 <= n && n < bllen bs } - -assume findIndices - :: (Char -> GHC.Types.Bool) - -> bs : Data.ByteString.Lazy.ByteString - -> [{ n : Data.Int.Int64 | 0 <= n && n < bllen bs }] - -assume count - :: Char - -> bs : Data.ByteString.Lazy.ByteString - -> { n : Data.Int.Int64 | 0 <= n && n < bllen bs } - -assume zip - :: l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : [(Char, Char)] | len o <= bllen l && len o <= bllen r } - -assume zipWith - :: (Char -> Char -> a) - -> l : Data.ByteString.Lazy.ByteString - -> r : Data.ByteString.Lazy.ByteString - -> { o : [a] | len o <= bllen l && len o <= bllen r } - -assume unzip - :: i : [(Char, Char)] - -> ( { l : Data.ByteString.Lazy.ByteString | bllen l == len i } - , { r : Data.ByteString.Lazy.ByteString | bllen r == len i } - ) - -assume sort - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume readInt - :: i : Data.ByteString.Lazy.ByteString - -> Maybe { p : (Int, { o : Data.ByteString.Lazy.ByteString | bllen o < bllen i}) | bllen i /= 0 } - -assume readInteger - :: i : Data.ByteString.Lazy.ByteString - -> Maybe { p : (Integer, { o : Data.ByteString.Lazy.ByteString | bllen o < bllen i}) | bllen i /= 0 } - -assume copy - :: i : Data.ByteString.Lazy.ByteString - -> { o : Data.ByteString.Lazy.ByteString | bllen o == bllen i } - -assume hGet - :: System.IO.Handle - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.Lazy.ByteString | bllen bs == n || bllen bs == 0 } - -assume hGetNonBlocking - :: System.IO.Handle - -> n : { n : Int | 0 <= n } - -> IO { bs : Data.ByteString.Lazy.ByteString | bllen bs <= n } diff --git a/include/Data/ByteString/Short.spec b/include/Data/ByteString/Short.spec deleted file mode 100644 index 3b254a3aa9..0000000000 --- a/include/Data/ByteString/Short.spec +++ /dev/null @@ -1,25 +0,0 @@ -module spec Data.ByteString.Short where - -import Data.String - -measure sbslen :: Data.ByteString.Short.ShortByteString -> { n : Int | 0 <= n } - -invariant { bs : Data.ByteString.Short.ShortByteString | 0 <= sbslen bs } - -invariant { bs : Data.ByteString.Short.ShortByteString | sbslen bs == stringlen bs } - -toShort :: i : Data.ByteString.ByteString -> { o : Data.ByteString.Short.ShortByteString | sbslen o == bslen i } - -fromShort :: o : Data.ByteString.Short.ShortByteString -> { i : Data.ByteString.ByteString | bslen i == sbslen o } - -pack :: w8s : [Data.Word.Word8] -> { bs : Data.ByteString.Short.ShortByteString | sbslen bs == len w8s } - -unpack :: bs : Data.ByteString.Short.ShortByteString -> { w8s : [Data.Word.Word8] | len w8s == sbslen bs } - -empty :: { bs : Data.ByteString.Short.ShortByteString | sbslen bs == 0 } - -null :: bs : Data.ByteString.Short.ShortByteString -> { b : GHC.Types.Bool | b <=> sbslen bs == 0 } - -length :: bs : Data.ByteString.Short.ShortByteString -> { n : Int | sbslen bs == n } - -index :: bs : Data.ByteString.Short.ShortByteString -> { n : Int | 0 <= n && n < sbslen bs } -> Data.Word.Word8 diff --git a/include/Data/ByteString/Unsafe.spec b/include/Data/ByteString/Unsafe.spec deleted file mode 100644 index 775a4bb913..0000000000 --- a/include/Data/ByteString/Unsafe.spec +++ /dev/null @@ -1,29 +0,0 @@ -module spec Data.ByteString.Unsafe where - -unsafeHead - :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -unsafeTail - :: bs : { v : Data.ByteString.ByteString | bslen v > 0 } - -> { v : Data.ByteString.ByteString | bslen v = bslen bs - 1 } - -unsafeInit - :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -unsafeLast - :: { bs : Data.ByteString.ByteString | 1 <= bslen bs } -> _ - -unsafeIndex - :: bs : Data.ByteString.ByteString - -> { n : Int | 0 <= n && n < bslen bs } - -> _ - -unsafeTake - :: n : { n : Int | 0 <= n } - -> i : { i : Data.ByteString.ByteString | n <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == n } - -unsafeDrop - :: n : { n : Int | 0 <= n } - -> i : { i : Data.ByteString.ByteString | n <= bslen i } - -> { o : Data.ByteString.ByteString | bslen o == bslen i - n } diff --git a/include/Data/Char.spec b/include/Data/Char.spec deleted file mode 100644 index 2c53389917..0000000000 --- a/include/Data/Char.spec +++ /dev/null @@ -1 +0,0 @@ -module spec Data.Chare where diff --git a/include/Data/Either.spec b/include/Data/Either.spec deleted file mode 100644 index 607b58eecf..0000000000 --- a/include/Data/Either.spec +++ /dev/null @@ -1,5 +0,0 @@ -module spec Data.Either where - -measure isLeft :: Data.Either.Either a b -> Bool - isLeft (Left x) = true - isLeft (Right x) = false diff --git a/include/Data/Foldable.spec b/include/Data/Foldable.spec deleted file mode 100644 index c4d72d09d9..0000000000 --- a/include/Data/Foldable.spec +++ /dev/null @@ -1,6 +0,0 @@ -module spec Data.Foldable where - -import GHC.Base - -length :: Data.Foldable.Foldable f => forall a. xs:f a -> {v:Nat | v = len xs} -null :: v:_ -> {b:Bool | (b <=> len v = 0) && (not b <=> len v > 0)} diff --git a/include/Data/Int.spec b/include/Data/Int.spec deleted file mode 100644 index 7b418181e5..0000000000 --- a/include/Data/Int.spec +++ /dev/null @@ -1,8 +0,0 @@ -module spec Data.Int where - -embed Data.Int.Int8 as int -embed Data.Int.Int16 as int -embed Data.Int.Int32 as int -embed Data.Int.Int64 as int - -// type Nat64 = {v:Data.Int.Int64 | v >= 0} diff --git a/include/Data/Map.hiddenspec b/include/Data/Map.hiddenspec deleted file mode 100644 index 5e98059389..0000000000 --- a/include/Data/Map.hiddenspec +++ /dev/null @@ -1,27 +0,0 @@ -module spec Data.Map where - -embed Data.Map.Map as Map_t - ---------------------------------------------------------------------------------------- --- | Logical Map Operators: Interpreted "natively" by the SMT solver ------------------ ---------------------------------------------------------------------------------------- - -measure Map_select :: forall k v. Data.Map.Map k v -> k -> v - -measure Map_store :: forall k v. Data.Map.Map k v -> k -> v -> Data.Map.Map k v - - -insert :: Ord k => k:k -> v:v -> m:Data.Map.Map k v -> {n:Data.Map.Map k v | n = Map_store m k v} - -lookup :: Ord k => k:k -> m:Data.Map.Map k v -> Maybe {v:v | v = Map_select m k} - -(!) :: Ord k => m:Data.Map.Map k v -> k:k -> {v:v | v = Map_select m k} - - - - - - - - - diff --git a/include/Data/Maybe.spec b/include/Data/Maybe.spec deleted file mode 100644 index 4f40670a82..0000000000 --- a/include/Data/Maybe.spec +++ /dev/null @@ -1,7 +0,0 @@ -module spec Data.Maybe where - -maybe :: v:b -> (a -> b) -> u:(Maybe a) -> {w:b | not (isJust u) => w == v} -isJust :: v:(Maybe a) -> {b:Bool | b == isJust v} -isNothing :: v:(Maybe a) -> {b:Bool | not (isJust v) == b} -fromJust :: {v:(Maybe a) | isJust v} -> a -fromMaybe :: v:a -> u:(Maybe a) -> {x:a | not (isJust u) => x == v} diff --git a/include/Data/OldList.spec b/include/Data/OldList.spec deleted file mode 100644 index b82274ecce..0000000000 --- a/include/Data/OldList.spec +++ /dev/null @@ -1,11 +0,0 @@ -module spec Data.OldList where - -import GHC.Base -import GHC.List -import GHC.Types - -assume groupBy :: (a -> a -> GHC.Types.Bool) -> [a] -> [{v:[a] | len(v) > 0}] - -assume transpose :: [[a]] -> [{v:[a] | (len v) > 0}] - - diff --git a/include/Data/Set.spec b/include/Data/Set.spec deleted file mode 100644 index 2ea2f18ef6..0000000000 --- a/include/Data/Set.spec +++ /dev/null @@ -1,59 +0,0 @@ -module spec Data.Set where - -embed Data.Set.Internal.Set as Set_Set - -// ---------------------------------------------------------------------------------------------- -// -- | Logical Set Operators: Interpreted "natively" by the SMT solver ------------------------- -// ---------------------------------------------------------------------------------------------- - - -// union -measure Set_cup :: (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) - -// intersection -measure Set_cap :: (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) - -// difference -measure Set_dif :: (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) - -// singleton -measure Set_sng :: a -> (Data.Set.Internal.Set a) - -// emptiness test -measure Set_emp :: (Data.Set.Internal.Set a) -> GHC.Types.Bool - -// empty set -measure Set_empty :: forall a. GHC.Types.Int -> (Data.Set.Internal.Set a) - -// membership test -measure Set_mem :: a -> (Data.Set.Internal.Set a) -> GHC.Types.Bool - -// inclusion test -measure Set_sub :: (Data.Set.Internal.Set a) -> (Data.Set.Internal.Set a) -> GHC.Types.Bool - -// --------------------------------------------------------------------------------------------- -// -- | Refined Types for Data.Set Operations -------------------------------------------------- -// --------------------------------------------------------------------------------------------- - -isSubsetOf :: (GHC.Classes.Ord a) => x:(Data.Set.Internal.Set a) -> y:(Data.Set.Internal.Set a) -> {v:GHC.Types.Bool | v <=> Set_sub x y} -member :: (GHC.Classes.Ord a) => x:a -> xs:(Data.Set.Internal.Set a) -> {v:GHC.Types.Bool | v <=> Set_mem x xs} -null :: xs:(Data.Set.Internal.Set a) -> {v:GHC.Types.Bool | v <=> Set_emp xs} - -empty :: {v:(Data.Set.Internal.Set a) | Set_emp v} -singleton :: x:a -> {v:(Data.Set.Internal.Set a) | v = (Set_sng x)} -insert :: (GHC.Classes.Ord a) => x:a -> xs:(Data.Set.Internal.Set a) -> {v:(Data.Set.Internal.Set a) | v = Set_cup xs (Set_sng x)} -delete :: (GHC.Classes.Ord a) => x:a -> xs:(Data.Set.Internal.Set a) -> {v:(Data.Set.Internal.Set a) | v = Set_dif xs (Set_sng x)} - -union :: GHC.Classes.Ord a => xs:(Data.Set.Internal.Set a) -> ys:(Data.Set.Internal.Set a) -> {v:(Data.Set.Internal.Set a) | v = Set_cup xs ys} -intersection :: GHC.Classes.Ord a => xs:(Data.Set.Internal.Set a) -> ys:(Data.Set.Internal.Set a) -> {v:(Data.Set.Internal.Set a) | v = Set_cap xs ys} -difference :: GHC.Classes.Ord a => xs:(Data.Set.Internal.Set a) -> ys:(Data.Set.Internal.Set a) -> {v:(Data.Set.Internal.Set a) | v = Set_dif xs ys} - -fromList :: GHC.Classes.Ord a => xs:[a] -> {v:Data.Set.Internal.Set a | v = listElts xs} - -// --------------------------------------------------------------------------------------------- -// -- | The set of elements in a list ---------------------------------------------------------- -// --------------------------------------------------------------------------------------------- - -measure listElts :: [a] -> (Data.Set.Internal.Set a) - listElts [] = {v | (Set_emp v)} - listElts (x:xs) = {v | v = Set_cup (Set_sng x) (listElts xs) } diff --git a/include/Data/String.spec b/include/Data/String.spec deleted file mode 100644 index 48da15f724..0000000000 --- a/include/Data/String.spec +++ /dev/null @@ -1,8 +0,0 @@ -module spec Data.String where - -measure stringlen :: a -> GHC.Types.Int - -Data.String.fromString - :: forall a. Data.String.IsString a - => i : [GHC.Types.Char] - -> { o : a | i ~~ o && len i == stringlen o } diff --git a/include/Data/Text.spec b/include/Data/Text.spec deleted file mode 100644 index 16716a3de4..0000000000 --- a/include/Data/Text.spec +++ /dev/null @@ -1,289 +0,0 @@ -module spec Data.Text where - -import Data.String - -measure tlen :: Data.Text.Text -> { n : Int | 0 <= n } - -invariant { t : Data.Text.Text | 0 <= tlen t } - -invariant { t : Data.Text.Text | tlen t == stringlen t } - -empty :: { t : Data.Text.Text | tlen t == 0 } - -singleton :: _ -> { t : Data.Text.Text | tlen t == 1 } - -pack :: str : [_] - -> { t : Data.Text.Text | tlen t == len str } - -unpack :: t : Data.Text.Text - -> { str : [_] | len str == tlen t } - -cons :: _ - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i + 1 } - -snoc :: i : Data.Text.Text - -> _ - -> { o : Data.Text.Text | tlen o == tlen i + 1 } - -append :: l : Data.Text.Text - -> r : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen l + tlen r } - -head :: { t : Data.Text.Text | 1 <= tlen t } -> _ - -unsnoc :: i:Data.Text.Text - -> (Maybe ({ o : Data.Text.Text | tlen o == tlen i - 1 }, _)) - -last :: { t : Data.Text.Text | 1 <= tlen t } -> _ - -tail :: { t : Data.Text.Text | 1 <= tlen t } -> _ - -init - :: {i:Data.Text.Text | 1 <= tlen i } - -> {o:Data.Text.Text | tlen o == tlen i - 1 } - -null - :: t : Data.Text.Text - -> { b : GHC.Types.Bool | b <=> tlen t == 0 } - -length :: t : Data.Text.Text -> { n : Int | tlen t == n } - -map - :: (_ -> _) - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i } - -reverse - :: i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i } - -intersperse - :: _ - -> i : Data.Text.Text - -> { o : Data.Text.Text | (tlen i == 0 <=> tlen o == 0) && (1 <= tlen i <=> tlen o == 2 * tlen i - 1) } - -intercalate - :: l : Data.Text.Text - -> rs : [Data.Text.Text] - -> { o : Data.Text.Text | len rs == 0 ==> tlen o == 0 } - -transpose - :: is : [Data.Text.Text] - -> { os : [{ t : Data.Text.Text | tlen t <= len is }] | len is == 0 ==> len os == 0} - -foldl1 - :: (_ -> _ -> _) - -> { t : Data.Text.Text | 1 <= tlen t } - -> _ - -foldl1' - :: (_ -> _ -> _) - -> { t : Data.Text.Text | 1 <= tlen t } - -> _ - -foldr1 - :: (_ -> _ -> _) - -> { t : Data.Text.Text | 1 <= tlen t } - -> _ - -concat - :: is : [Data.Text.Text] - -> { o : Data.Text.Text | (len is == 0) ==> (tlen o == 0) } - -concatMap - :: (_ -> Data.Text.Text) - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen i == 0 ==> tlen o == 0 } - -any - :: (_ -> GHC.Types.Bool) - -> t : Data.Text.Text - -> { b : GHC.Types.Bool | tlen t == 0 ==> not b } - -all - :: (_ -> GHC.Types.Bool) - -> t : Data.Text.Text - -> { b : GHC.Types.Bool | tlen t == 0 ==> b } - -maximum :: { t : Data.Text.Text | 1 <= tlen t } -> _ - -minimum :: { t : Data.Text.Text | 1 <= tlen t } -> _ - -scanl :: (_ -> _ -> _) - -> _ - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i } - -scanl1 :: (_ -> _ -> _) - -> i : { i : Data.Text.Text | 1 <= tlen i } - -> { o : Data.Text.Text | tlen o == tlen i } - -scanr - :: (_ -> _ -> _) - -> _ - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i } - -scanr1 - :: (_ -> _ -> _) - -> i : { i : Data.Text.Text | 1 <= tlen i } - -> { o : Data.Text.Text | tlen o == tlen i } - -mapAccumL - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.Text.Text - -> (acc, { o : Data.Text.Text | tlen o == tlen i }) - -mapAccumR - :: (acc -> _ -> (acc, _)) - -> acc - -> i : Data.Text.Text - -> (acc, { o : Data.Text.Text | tlen o == tlen i }) - -replicate - :: n : Int - -> _ - -> { t : Data.Text.Text | tlen t == n } - -unfoldrN - :: n : Int - -> (a -> Maybe (_, a)) - -> a - -> { t : Data.Text.Text | tlen t <= n } - -take - :: n : Int - -> i : Data.Text.Text - -> { o : Data.Text.Text | (n <= 0 <=> tlen o == 0) && - ((0 <= n && n <= tlen i) <=> tlen o == n) && - (tlen i <= n <=> tlen o = tlen i) } - -drop - :: n : Int - -> i : Data.Text.Text - -> { o : Data.Text.Text | (n <= 0 <=> tlen o == tlen i) && - ((0 <= n && n <= tlen i) <=> tlen o == tlen i - n) && - (tlen i <= n <=> tlen o == 0) } - -splitAt - :: n : Int - -> i : Data.Text.Text - -> ( { l : Data.Text.Text | (n <= 0 <=> tlen l == 0) && - ((0 <= n && n <= tlen i) <=> tlen l == n) && - (tlen i <= n <=> tlen l == tlen i) } - , { r : Data.Text.Text | (n <= 0 <=> tlen r == tlen i) && - ((0 <= n && n <= tlen i) <=> tlen r == tlen i - n) && - (tlen i <= n <=> tlen r == 0) } - ) - -takeWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o <= tlen i } - -dropWhile - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o <= tlen i } - -span - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> ( { l : Data.Text.Text | tlen l <= tlen i } - , { r : Data.Text.Text | tlen r <= tlen i } - ) - -break - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> ( { l : Data.Text.Text | tlen l <= tlen i } - , { r : Data.Text.Text | tlen r <= tlen i } - ) - -group - :: i : Data.Text.Text - -> [{ o : Data.Text.Text | 1 <= tlen o && tlen o <= tlen i }] - -groupBy - :: (_ -> _ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> [{ o : Data.Text.Text | 1 <= tlen o && tlen o <= tlen i }] - -inits - :: i : Data.Text.Text - -> [{ o : Data.Text.Text | tlen o <= tlen i }] - -tails - :: i : Data.Text.Text - -> [{ o : Data.Text.Text | tlen o <= tlen i }] - -split - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> [{ o : Data.Text.Text | tlen o <= tlen i }] - -isPrefixOf - :: l : Data.Text.Text - -> r : Data.Text.Text - -> { b : GHC.Types.Bool | tlen l >= tlen r ==> not b } - -isSuffixOf - :: l : Data.Text.Text - -> r : Data.Text.Text - -> { b : GHC.Types.Bool | tlen l > tlen r ==> not b } - -isInfixOf - :: l : Data.Text.Text - -> r : Data.Text.Text - -> { b : GHC.Types.Bool | tlen l > tlen r ==> not b } - -find - :: (_ -> GHC.Types.Bool) - -> t : Data.Text.Text - -> (Maybe { char : _ | tlen t /= 0 }) - -filter - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> { o : Data.Text.Text | tlen o <= tlen i } - -partition - :: (_ -> GHC.Types.Bool) - -> i : Data.Text.Text - -> ( { l : Data.Text.Text | tlen l <= tlen i } - , { r : Data.Text.Text | tlen r <= tlen i } - ) - -index :: t : Data.Text.Text -> { n : Int | 0 <= n && n < tlen t } -> _ - -findIndex - :: (_ -> GHC.Types.Bool) - -> t : Data.Text.Text - -> (Maybe { n : Int | 0 <= n && n < tlen t }) - -count - :: _ - -> t : Data.Text.Text - -> { n : Int | 0 <= n && n < tlen t } - -zip - :: l : Data.Text.Text - -> r : Data.Text.Text - -> { o : [(_, _)] | len o <= tlen l && len o <= tlen r } - -zipWith - :: (_ -> _ -> Char) - -> l : Data.Text.Text - -> r : Data.Text.Text - -> { o : Text | tlen o <= tlen l && tlen o <= tlen r } - -copy - :: i : Data.Text.Text - -> { o : Data.Text.Text | tlen o == tlen i } - -uncons - :: i : Data.Text.Text - -> (Maybe (_, { o : Data.Text.Text | tlen o == tlen i - 1 })) - diff --git a/include/Data/Text/Fusion.spec b/include/Data/Text/Fusion.spec deleted file mode 100644 index 7655e1a55d..0000000000 --- a/include/Data/Text/Fusion.spec +++ /dev/null @@ -1,25 +0,0 @@ -module spec Data.Text.Fusion where - -import Data.Text.Fusion.Common - -stream :: t:Data.Text.Internal.Text - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (tlength t)} -reverseStream :: t:Data.Text.Internal.Text - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (tlength t)} -unstream :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Internal.Text | (tlength v) = (slen s)} - -findIndex :: (GHC.Types.Char -> GHC.Types.Bool) - -> s:Data.Text.Fusion.Internal.Stream Char - -> (Data.Maybe.Maybe {v:Nat | v < (slen s)}) - -mapAccumL :: (a -> GHC.Types.Char -> (a,GHC.Types.Char)) - -> a - -> s:Data.Text.Fusion.Internal.Stream Char - -> (a, {v:Data.Text.Internal.Text | (tlength v) = (slen s)}) - - -length :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:GHC.Types.Int | v = (slen s)} -reverse :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Internal.Text | (tlength v) = (slen s)} diff --git a/include/Data/Text/Fusion/Common.spec b/include/Data/Text/Fusion/Common.spec deleted file mode 100644 index 17037b50cc..0000000000 --- a/include/Data/Text/Fusion/Common.spec +++ /dev/null @@ -1,52 +0,0 @@ -module spec Data.Text.Fusion.Common where - -measure slen :: Data.Text.Fusion.Internal.Stream a - -> GHC.Types.Int - -cons :: GHC.Types.Char - -> s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (1 + (slen s))} - -snoc :: s:Data.Text.Fusion.Internal.Stream Char - -> GHC.Types.Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (1 + (slen s))} - -compareLengthI :: s:Data.Text.Fusion.Internal.Stream Char - -> l:GHC.Types.Int - -> {v:GHC.Types.Ordering | ((v = GHC.Types.EQ) <=> ((slen s) = l))} - -isSingleton :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:GHC.Types.Bool | (v <=> ((slen s) = 1))} - -singleton :: GHC.Types.Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = 1} - -streamList :: l:[a] - -> {v:Data.Text.Fusion.Internal.Stream a | (slen v) = (len l)} - -unstreamList :: s:Data.Text.Fusion.Internal.Stream a - -> {v:[a] | (len v) = (slen s)} - -map :: (GHC.Types.Char -> GHC.Types.Char) - -> s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (slen s)} - -filter :: (GHC.Types.Char -> GHC.Types.Bool) - -> s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) <= (slen s)} - -intersperse :: GHC.Types.Char - -> s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) > (slen s)} - -replicateCharI :: l:GHC.Types.Int - -> GHC.Types.Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = l} - -toCaseFold :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) >= (slen s)} - -toUpper :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) >= (slen s)} -toLower :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) >= (slen s)} diff --git a/include/Data/Text/Lazy/Fusion.spec b/include/Data/Text/Lazy/Fusion.spec deleted file mode 100644 index a4525a1ec7..0000000000 --- a/include/Data/Text/Lazy/Fusion.spec +++ /dev/null @@ -1,8 +0,0 @@ -module spec Data.Text.Lazy.Fusion where - -stream :: t:Data.Text.Lazy.Internal.Text - -> {v:Data.Text.Fusion.Internal.Stream Char | (slen v) = (ltlength t)} -unstream :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:Data.Text.Lazy.Internal.Text | (ltlength v) = (slen s)} -length :: s:Data.Text.Fusion.Internal.Stream Char - -> {v:GHC.Int.Int64 | v = (slen s)} diff --git a/include/Data/Time.spec b/include/Data/Time.spec deleted file mode 100644 index 2fdd747a08..0000000000 --- a/include/Data/Time.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec Data.Time where - -import Data.Time.Calendar diff --git a/include/Data/Time/Calendar.spec b/include/Data/Time/Calendar.spec deleted file mode 100644 index 8cb3fe3bcc..0000000000 --- a/include/Data/Time/Calendar.spec +++ /dev/null @@ -1,11 +0,0 @@ -module spec Data.Time.Calendar where - -type NumericMonth = { x:Nat | 0 < x && x <= 12 } - -type NumericDayOfMonth = { x:Nat | 0 < x && x <= 31 } - -fromGregorian :: Integer -> NumericMonth -> NumericDayOfMonth -> Day - -toGregorian :: Day -> (Integer,NumericMonth,NumericDayOfMonth) - -gregorianMonthLength :: Integer -> NumericMonth -> { x:Nat | 28 <= x && x <= 31 } diff --git a/include/Data/Tuple.spec b/include/Data/Tuple.spec deleted file mode 100644 index 030c794b0d..0000000000 --- a/include/Data/Tuple.spec +++ /dev/null @@ -1,4 +0,0 @@ -module spec Data.Tuple where - -fst :: {f:(x:(a,b) -> {v:a | v = (fst x)}) | f == fst } -snd :: {f:(x:(a,b) -> {v:b | v = (snd x)}) | f == snd } \ No newline at end of file diff --git a/include/Data/Vector.hquals b/include/Data/Vector.hquals deleted file mode 100644 index 11cd038798..0000000000 --- a/include/Data/Vector.hquals +++ /dev/null @@ -1,13 +0,0 @@ -qualif VecEmpty(v: Data.Vector.Vector a) : (vlen v) = 0 -qualif VecEmpty(v: Data.Vector.Vector a) : (vlen v) > 0 -qualif VecEmpty(v: Data.Vector.Vector a) : (vlen v) >= 0 - -qualif Vlen(v:int, x: Data.Vector.Vector a) : (v = vlen x) -qualif Vlen(v:int, x: Data.Vector.Vector a) : (v <= vlen x) -qualif Vlen(v:int, x: Data.Vector.Vector a) : (v < vlen x) - -qualif CmpVlen(v:Data.Vector.Vector a, x:Data.Vector.Vector b) : (vlen v < vlen x) -qualif CmpVlen(v:Data.Vector.Vector a, x:Data.Vector.Vector b) : (vlen v <= vlen x) -qualif CmpVlen(v:Data.Vector.Vector a, x:Data.Vector.Vector b) : (vlen v > vlen x) -qualif CmpVlen(v:Data.Vector.Vector a, x:Data.Vector.Vector b) : (vlen v >= vlen x) -qualif CmpVlen(v:Data.Vector.Vector a, x:Data.Vector.Vector b) : (vlen v = vlen x) \ No newline at end of file diff --git a/include/Data/Vector.spec b/include/Data/Vector.spec deleted file mode 100644 index 78faf38b70..0000000000 --- a/include/Data/Vector.spec +++ /dev/null @@ -1,26 +0,0 @@ -module spec Data.Vector where - -import GHC.Base - -data variance Data.Vector.Vector covariant - - -measure vlen :: forall a. (Data.Vector.Vector a) -> Int - -invariant {v: Data.Vector.Vector a | 0 <= vlen v } - -! :: forall a. x:(Data.Vector.Vector a) -> vec:{v:Nat | v < vlen x } -> a - -unsafeIndex :: forall a. x:(Data.Vector.Vector a) -> vec:{v:Nat | v < vlen x } -> a - -fromList :: forall a. x:[a] -> {v: Data.Vector.Vector a | vlen v = len x } - -length :: forall a. x:(Data.Vector.Vector a) -> {v : Nat | v = vlen x } - -replicate :: n:Nat -> a -> {v:Data.Vector.Vector a | vlen v = n} - -imap :: (Nat -> a -> b) -> x:(Data.Vector.Vector a) -> {y:Data.Vector.Vector b | vlen y = vlen x } - -map :: (a -> b) -> x:(Data.Vector.Vector a) -> {y:Data.Vector.Vector b | vlen y = vlen x } - -head :: forall a. {xs: Data.Vector.Vector a | vlen xs > 0} -> a diff --git a/include/Data/Word.spec b/include/Data/Word.spec deleted file mode 100644 index dc7d3bce01..0000000000 --- a/include/Data/Word.spec +++ /dev/null @@ -1,10 +0,0 @@ -module spec Data.Word where - -embed Data.Word.Word as int -embed Data.Word.Word8 as int -embed Data.Word.Word16 as int -embed Data.Word.Word32 as int -embed Data.Word.Word64 as int - -invariant {v : Data.Word.Word32 | 0 <= v } -invariant {v : Data.Word.Word16 | 0 <= v } diff --git a/include/Data/Word8.spec b/include/Data/Word8.spec deleted file mode 100644 index 76bf4190fb..0000000000 --- a/include/Data/Word8.spec +++ /dev/null @@ -1,5 +0,0 @@ -module spec Data.Word8 where - -import GHC.Word - -invariant {v:GHC.Word.Word8 | 0 <= v } \ No newline at end of file diff --git a/include/Foreign/C/String.spec b/include/Foreign/C/String.spec deleted file mode 100644 index 607c436d46..0000000000 --- a/include/Foreign/C/String.spec +++ /dev/null @@ -1,11 +0,0 @@ -module spec Foreign.C.String where - -import Foreign.Ptr - -type CStringLen = ((GHC.Ptr.Ptr Foreign.C.Types.CChar), Nat)<{\p v -> (v <= (plen p))}> -type CStringLenN N = ((GHC.Ptr.Ptr Foreign.C.Types.CChar), {v:Nat | v = N})<{\p v -> (v <= (plen p))}> - -// measure cStringLen :: Foreign.C.String.CStringLen -> GHC.Types.Int - -measure cStringLen :: ((GHC.Ptr.Ptr Foreign.C.Types.CChar), GHC.Types.Int) -> GHC.Types.Int - cStringLen (c, n) = n diff --git a/include/Foreign/C/Types.spec b/include/Foreign/C/Types.spec deleted file mode 100644 index f77f5868fd..0000000000 --- a/include/Foreign/C/Types.spec +++ /dev/null @@ -1,7 +0,0 @@ -module spec Foreign.C.Types where - -import GHC.Word - -embed Foreign.C.Types.CInt as int -embed Foreign.C.Types.CSize as int -embed Foreign.C.Types.CULong as int diff --git a/include/Foreign/ForeignPtr.spec b/include/Foreign/ForeignPtr.spec deleted file mode 100644 index 5c1bd76ba9..0000000000 --- a/include/Foreign/ForeignPtr.spec +++ /dev/null @@ -1,16 +0,0 @@ -module spec Foreign.ForeignPtr where - -import GHC.ForeignPtr -import Foreign.Ptr - -Foreign.ForeignPtr.withForeignPtr :: forall a b. fp:(GHC.ForeignPtr.ForeignPtr a) - -> ((PtrN a (fplen fp)) -> GHC.Types.IO b) - -> (GHC.Types.IO b) - -GHC.ForeignPtr.newForeignPtr_ :: p:(GHC.Ptr.Ptr a) -> (GHC.Types.IO (ForeignPtrN a (plen p))) -Foreign.Concurrent.newForeignPtr :: p:(PtrV a) -> GHC.Types.IO () -> (GHC.Types.IO (ForeignPtrN a (plen p))) -Foreign.ForeignPtr.newForeignPtr :: _ -> p:(PtrV a) -> (GHC.Types.IO (ForeignPtrN a (plen p))) - - -// this uses `sizeOf (undefined :: a)`, so the ForeignPtr does not necessarily have length `n` -// Foreign.ForeignPtr.Imp.mallocForeignPtrArray :: (Foreign.Storable.Storable a) => n:Nat -> IO (ForeignPtrN a n) diff --git a/include/Foreign/Marshal/Alloc.spec b/include/Foreign/Marshal/Alloc.spec deleted file mode 100644 index c7d8a31e82..0000000000 --- a/include/Foreign/Marshal/Alloc.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec Foreign.Marshal.Alloc where - -Foreign.Marshal.Alloc.allocaBytes :: n:Nat -> (PtrN a n -> IO b) -> IO b diff --git a/include/Foreign/Marshal/Array.spec b/include/Foreign/Marshal/Array.spec deleted file mode 100644 index a492f87da0..0000000000 --- a/include/Foreign/Marshal/Array.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec Foreign.Marshal.Array where - -Foreign.Marshal.Array.allocaArray :: Foreign.Storable.Storable a => n:Int -> ((PtrN a n) -> IO b) -> IO b diff --git a/include/Foreign/Ptr.spec b/include/Foreign/Ptr.spec deleted file mode 100644 index 0fe190159a..0000000000 --- a/include/Foreign/Ptr.spec +++ /dev/null @@ -1,5 +0,0 @@ -module spec Foreign.Ptr where - -import GHC.Ptr - - diff --git a/include/Foreign/Storable.spec b/include/Foreign/Storable.spec deleted file mode 100644 index ed85c4a7d3..0000000000 --- a/include/Foreign/Storable.spec +++ /dev/null @@ -1,30 +0,0 @@ -module spec Foreign.Storable where - -import Foreign.Ptr - -// DON'T do this, we can't import HS files from SPEC files -// import Language.Haskell.Liquid.Foreign - -predicate PValid P N = ((0 <= N) && (N < (plen P))) - -Foreign.Storable.poke :: (Foreign.Storable.Storable a) - => {v: (GHC.Ptr.Ptr a) | 0 < (plen v)} - -> a - -> (GHC.Types.IO ()) - -Foreign.Storable.peek :: (Foreign.Storable.Storable a) - => p:{v: (GHC.Ptr.Ptr a) | 0 < (plen v)} - -> (GHC.Types.IO {v:a | v = (deref p)}) - -Foreign.Storable.peekByteOff :: (Foreign.Storable.Storable a) - => forall b. p:(GHC.Ptr.Ptr b) - -> {v:GHC.Types.Int | (PValid p v)} - -> (GHC.Types.IO a) - -Foreign.Storable.pokeByteOff :: (Foreign.Storable.Storable a) - => forall b. p:(GHC.Ptr.Ptr b) - -> {v:GHC.Types.Int | (PValid p v)} - -> a - -> GHC.Types.IO () - - diff --git a/include/GHC/Base.hquals b/include/GHC/Base.hquals deleted file mode 100644 index 4a282c6773..0000000000 --- a/include/GHC/Base.hquals +++ /dev/null @@ -1,30 +0,0 @@ -//qualif NonNull(v: [a]) : (? (nonnull([v]))) -//qualif Null(v: [a]) : (~ (? (nonnull([v])))) -//qualif EqNull(v:Bool, ~A: [a]): (v <=> (? (nonnull([~A])))) - -// qualif IsEmp(v:GHC.Types.Bool, ~A: [a]) : ((v) <=> len([~A]) [ > ; = ] 0) -// qualif ListZ(v: [a]) : len([v]) [ = ; >= ; > ] 0 -// qualif CmpLen(v:[a], ~A:[b]) : len([v]) [= ; >=; >; <=; <] len([~A]) -// qualif EqLen(v:int, ~A: [a]) : v = len([~A]) -// qualif LenEq(v:[a], ~A: int) : ~A = len([v]) -// qualif LenAcc(v:int, ~A:[a], ~B: int): v = len([~A]) + ~B -// qualif LenDiff(v:[a], ~A:int): len([v]) = (~A [ +; - ] 1) - -qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (v <=> (len xs > 0)) -qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (v <=> (len xs = 0)) - -qualif ListZ(v: [a]) : (len([v]) = 0) -qualif ListZ(v: [a]) : (len([v]) >= 0) -qualif ListZ(v: [a]) : (len([v]) > 0) - -qualif CmpLen(v:[a], xs:[b]) : (len([v]) = len([xs])) -qualif CmpLen(v:[a], xs:[b]) : (len([v]) >= len([xs])) -qualif CmpLen(v:[a], xs:[b]) : (len([v]) > len([xs])) -qualif CmpLen(v:[a], xs:[b]) : (len([v]) <= len([xs])) -qualif CmpLen(v:[a], xs:[b]) : (len([v]) < len([xs])) - -qualif EqLen(v:int, xs: [a]) : (v = len([xs])) -qualif LenEq(v:[a], x: int) : (x = len([v])) -qualif LenDiff(v:[a], x:int) : (len([v]) = x + 1) -qualif LenDiff(v:[a], x:int) : (len([v]) = x - 1) -qualif LenAcc(v:int, xs:[a], n: int): (v = len([xs]) + n) diff --git a/include/GHC/Base.spec b/include/GHC/Base.spec deleted file mode 100644 index 438850d12c..0000000000 --- a/include/GHC/Base.spec +++ /dev/null @@ -1,79 +0,0 @@ -module spec GHC.Base where - -import GHC.CString -import GHC.Prim -import GHC.Classes -import GHC.Types - -embed GHC.Types.Int as int -embed GHC.Types.Bool as bool - -measure autolen :: forall a. a -> GHC.Types.Int -class measure len :: forall f a. f a -> GHC.Types.Int -instance measure len :: forall a. [a] -> GHC.Types.Int - len [] = 0 - len (y:ys) = 1 + len ys - -// measure null :: [a] -> Bool -// null [] = true -// null (y:ys) = false - -measure fst :: (a, b) -> a - fst (a, b) = a - -measure snd :: (a, b) -> b - snd (a, b) = b - -qualif Fst(__v:a, __y:b): (__v = (fst __y)) -qualif Snd(__v:a, __y:b): (__v = (snd __y)) - -measure isJust :: Maybe a -> Bool - isJust (Just x) = true - isJust (Nothing) = false - -measure fromJust :: Maybe a -> a - fromJust (Just x) = x - - -invariant {v: [a] | len v >= 0 } -map :: (a -> b) -> xs:[a] -> {v: [b] | len v == len xs} -(++) :: xs:[a] -> ys:[a] -> {v:[a] | len v == len xs + len ys} - -($) :: (a -> b) -> a -> b -id :: x:a -> {v:a | v = x} - -// data variance Text.ParserCombinators.ReadPrec.ReadPrec contravariant - -// qualif NonNull(v: [a]) : (? (nonnull v )) -// qualif Null(v: [a]) : (~ (? (nonnull v ))) -// qualif EqNull(v:Bool, ~A: [a]): (v <=> (? (nonnull([~A])))) - -// qualif IsEmp(v:GHC.Types.Bool, ~A: [a]) : ((v) <=> len([~A]) [ > ; = ] 0) -// qualif ListZ(v: [a]) : len v [ = ; >= ; > ] 0 -// qualif CmpLen(v:[a], ~A:[b]) : len v [= ; >=; >; <=; <] len([~A]) -// qualif EqLen(v:int, ~A: [a]) : v = len([~A]) -// qualif LenEq(v:[a], ~A: int) : ~A = len v -// qualif LenAcc(v:int, ~A:[a], ~B: int): v = len([~A]) + ~B -// qualif LenDiff(v:[a], ~A:int): len v = (~A [ +; - ] 1) - -qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (v <=> (len xs > 0)) -qualif IsEmp(v:GHC.Types.Bool, xs: [a]) : (v <=> (len xs = 0)) - -qualif ListZ(v: [a]) : (len v = 0) -qualif ListZ(v: [a]) : (len v >= 0) -qualif ListZ(v: [a]) : (len v > 0) - -qualif CmpLen(v:[a], xs:[b]) : (len v = len xs ) -qualif CmpLen(v:[a], xs:[b]) : (len v >= len xs ) -qualif CmpLen(v:[a], xs:[b]) : (len v > len xs ) -qualif CmpLen(v:[a], xs:[b]) : (len v <= len xs ) -qualif CmpLen(v:[a], xs:[b]) : (len v < len xs ) - -qualif EqLen(v:int, xs: [a]) : (v = len xs ) -qualif LenEq(v:[a], x: int) : (x = len v ) - -qualif LenDiff(v:[a], x:int) : (len v = x + 1) -qualif LenDiff(v:[a], x:int) : (len v = x - 1) -qualif LenAcc(v:int, xs:[a], n: int): (v = len xs + n) - - diff --git a/include/GHC/CString.spec b/include/GHC/CString.spec deleted file mode 100644 index 1f903d319d..0000000000 --- a/include/GHC/CString.spec +++ /dev/null @@ -1,11 +0,0 @@ -module spec GHC.CString where - -import GHC.Prim - -measure strLen :: GHC.Base.String -> GHC.Types.Int - -embed GHC.Types.Char as Char - -GHC.CString.unpackCString# - :: x:GHC.Prim.Addr# - -> {v:[Char] | v ~~ x && len v == strLen x} diff --git a/include/GHC/Classes.spec b/include/GHC/Classes.spec deleted file mode 100644 index 4031995e06..0000000000 --- a/include/GHC/Classes.spec +++ /dev/null @@ -1,29 +0,0 @@ -module spec GHC.Classes where - -import GHC.Types - -not :: x:GHC.Types.Bool -> {v:GHC.Types.Bool | ((v) <=> ~(x))} -(&&) :: x:GHC.Types.Bool -> y:GHC.Types.Bool - -> {v:GHC.Types.Bool | ((v) <=> ((x) && (y)))} -(||) :: x:GHC.Types.Bool -> y:GHC.Types.Bool - -> {v:GHC.Types.Bool | ((v) <=> ((x) || (y)))} -(==) :: (GHC.Classes.Eq a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x = y)} -(/=) :: (GHC.Classes.Eq a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x != y)} -(>) :: (GHC.Classes.Ord a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x > y)} -(>=) :: (GHC.Classes.Ord a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x >= y)} -(<) :: (GHC.Classes.Ord a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x < y)} -(<=) :: (GHC.Classes.Ord a) => x:a -> y:a - -> {v:GHC.Types.Bool | ((v) <=> x <= y)} - -compare :: (GHC.Classes.Ord a) => x:a -> y:a - -> {v:GHC.Types.Ordering | (((v = GHC.Types.EQ) <=> (x = y)) && - ((v = GHC.Types.LT) <=> (x < y)) && - ((v = GHC.Types.GT) <=> (x > y))) } - -max :: (GHC.Classes.Ord a) => x:a -> y:a -> {v:a | v = (if x > y then x else y) } -min :: (GHC.Classes.Ord a) => x:a -> y:a -> {v:a | v = (if x < y then x else y) } diff --git a/include/GHC/Exts.spec b/include/GHC/Exts.spec deleted file mode 100644 index 538ef92706..0000000000 --- a/include/GHC/Exts.spec +++ /dev/null @@ -1,10 +0,0 @@ -module spec GHC.Exts where - -// embed GHC.Exts.Int# as int -// embed GHC.Exts.Word# as int -// embed GHC.Exts.Addr# as Str -// embed GHC.Exts.Double# as real -// embed GHC.Exts.Char# as Char - - - diff --git a/include/GHC/ForeignPtr.spec b/include/GHC/ForeignPtr.spec deleted file mode 100644 index 794cd0338b..0000000000 --- a/include/GHC/ForeignPtr.spec +++ /dev/null @@ -1,9 +0,0 @@ -module spec GHC.ForeignPtr where - -measure fplen :: GHC.ForeignPtr.ForeignPtr a -> GHC.Types.Int - -type ForeignPtrV a = {v: GHC.ForeignPtr.ForeignPtr a | 0 <= fplen v} -type ForeignPtrN a N = {v: GHC.ForeignPtr.ForeignPtr a | 0 <= fplen v && fplen v == N } - -mallocPlainForeignPtrBytes :: n:{v:GHC.Types.Int | v >= 0 } -> (GHC.Types.IO (ForeignPtrN a n)) - diff --git a/include/GHC/IO/Handle.spec b/include/GHC/IO/Handle.spec deleted file mode 100644 index dac988eb77..0000000000 --- a/include/GHC/IO/Handle.spec +++ /dev/null @@ -1,10 +0,0 @@ -module spec GHC.IO.Handle where - -hGetBuf :: GHC.IO.Handle.Handle -> GHC.Ptr.Ptr a -> n:Nat - -> (GHC.Types.IO {v:Nat | v <= n}) - -hGetBufNonBlocking :: GHC.IO.Handle.Handle -> GHC.Ptr.Ptr a -> n:Nat - -> (GHC.Types.IO {v:Nat | v <= n}) - -hFileSize :: GHC.IO.Handle.Handle - -> (GHC.Types.IO {v:GHC.Integer.Type.Integer | v >= 0}) diff --git a/include/GHC/Int.spec b/include/GHC/Int.spec deleted file mode 100644 index e7a8cd5578..0000000000 --- a/include/GHC/Int.spec +++ /dev/null @@ -1,8 +0,0 @@ -module spec GHC.Int where - -embed GHC.Int.Int8 as int -embed GHC.Int.Int16 as int -embed GHC.Int.Int32 as int -embed GHC.Int.Int64 as int - -type Nat64 = {v:GHC.Int.Int64 | v >= 0} diff --git a/include/GHC/List.spec b/include/GHC/List.spec deleted file mode 100644 index 9e62f65a0b..0000000000 --- a/include/GHC/List.spec +++ /dev/null @@ -1,60 +0,0 @@ -module spec GHC.List where - -head :: xs:{v: [a] | len v > 0} -> {v:a | v = head xs} -tail :: xs:{v: [a] | len v > 0} -> {v: [a] | len(v) = (len(xs) - 1) && v = tail xs} - -last :: xs:{v: [a] | len v > 0} -> a -init :: xs:{v: [a] | len v > 0} -> {v: [a] | len(v) = len(xs) - 1} -null :: xs:[a] -> {v: GHC.Types.Bool | ((v) <=> len(xs) = 0) } -length :: xs:[a] -> {v: GHC.Types.Int | v = len(xs)} -filter :: (a -> GHC.Types.Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} -scanl :: (a -> b -> a) -> a -> xs:[b] -> {v: [a] | len(v) = 1 + len(xs) } -scanl1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = len(xs) } -foldr1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> a -scanr :: (a -> b -> b) -> b -> xs:[a] -> {v: [b] | len(v) = 1 + len(xs) } -scanr1 :: (a -> a -> a) -> xs:{v: [a] | len(v) > 0} -> {v: [a] | len(v) = len(xs) } - -lazy GHC.List.iterate -iterate :: (a -> a) -> a -> [a] - -repeat :: a -> [a] -lazy GHC.List.repeat - -replicate :: n:Nat -> x:a -> {v: [{v:a | v = x}] | len(v) = n} - -cycle :: {v: [a] | len(v) > 0 } -> [a] -lazy cycle - -takeWhile :: (a -> GHC.Types.Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} -dropWhile :: (a -> GHC.Types.Bool) -> xs:[a] -> {v: [a] | len(v) <= len(xs)} - -take :: n:GHC.Types.Int - -> xs:[a] - -> {v:[a] | if n >= 0 then (len v = (if (len xs) < n then (len xs) else n)) else (len v = 0)} -drop :: n:GHC.Types.Int - -> xs:[a] - -> {v:[a] | (if (n >= 0) then (len(v) = (if (len(xs) < n) then 0 else len(xs) - n)) else ((len v) = (len xs)))} - -splitAt :: n:_ -> x:[a] -> ({v:[a] | (if (n >= 0) then (if (len x) < n then (len v) = (len x) else (len v) = n) else ((len v) = 0))},[a])<{\x1 x2 -> (len x2) = (len x) - (len x1)}> -span :: (a -> GHC.Types.Bool) - -> xs:[a] - -> ({v:[a]|((len v)<=(len xs))}, {v:[a]|((len v)<=(len xs))}) - -break :: (a -> GHC.Types.Bool) -> xs:[a] -> ([a],[a])<{\x y -> (len xs) = (len x) + (len y)}> - -reverse :: xs:[a] -> {v: [a] | len(v) = len(xs)} - -include - -GHC.List.!! :: xs:[a] -> {v: _ | ((0 <= v) && (v < len(xs)))} -> a - - -zip :: xs : [a] -> ys:[b] - -> {v : [(a, b)] | ((((len v) <= (len xs)) && ((len v) <= (len ys))) - && (((len xs) = (len ys)) => ((len v) = (len xs))) )} - -zipWith :: (a -> b -> c) - -> xs : [a] -> ys:[b] - -> {v : [c] | (((len v) <= (len xs)) && ((len v) <= (len ys)))} - -errorEmptyList :: {v: _ | false} -> a diff --git a/include/GHC/Num.spec b/include/GHC/Num.spec deleted file mode 100644 index 984687e0e3..0000000000 --- a/include/GHC/Num.spec +++ /dev/null @@ -1,9 +0,0 @@ -module spec GHC.Num where - -embed GHC.Integer.Type.Integer as int - -GHC.Num.fromInteger :: (GHC.Num.Num a) => x:GHC.Integer.Type.Integer -> {v:a | v = x } - -GHC.Num.negate :: (GHC.Num.Num a) - => x:a - -> {v:a | v = -x} diff --git a/include/GHC/Prim.spec b/include/GHC/Prim.spec deleted file mode 100644 index ab672c9589..0000000000 --- a/include/GHC/Prim.spec +++ /dev/null @@ -1,8 +0,0 @@ -module spec GHC.Prim where - -embed GHC.Prim.Int# as int -embed GHC.Prim.Addr# as Str -embed GHC.Prim.Char# as Char -embed GHC.Prim.Double# as real -embed GHC.Prim.Float# as real -embed GHC.Prim.Word# as int diff --git a/include/GHC/Ptr.spec b/include/GHC/Ptr.spec deleted file mode 100644 index ce0d796043..0000000000 --- a/include/GHC/Ptr.spec +++ /dev/null @@ -1,24 +0,0 @@ -module spec GHC.Ptr where - -measure pbase :: GHC.Ptr.Ptr a -> GHC.Types.Int -measure plen :: GHC.Ptr.Ptr a -> GHC.Types.Int -measure isNullPtr :: GHC.Ptr.Ptr a -> Bool - -invariant {v:Foreign.Ptr.Ptr a | 0 <= plen v } -invariant {v:Foreign.Ptr.Ptr a | 0 <= pbase v } - -type PtrN a N = {v: PtrV a | plen v == N } -type PtrV a = {v: GHC.Ptr.Ptr a | 0 <= plen v } - -GHC.Ptr.castPtr :: p:(PtrV a) -> (PtrN b (plen p)) - -GHC.Ptr.plusPtr :: base:(PtrV a) - -> off:{v:GHC.Types.Int | v <= plen base } - -> {v:(PtrV b) | pbase v = pbase base && plen v = plen base - off} - -GHC.Ptr.minusPtr :: q:(PtrV a) - -> p:{v:(PtrV b) | pbase v == pbase q && plen v >= plen q} - -> {v:Nat | v == plen p - plen q} - -measure deref :: GHC.Ptr.Ptr a -> a - diff --git a/include/GHC/Read.spec b/include/GHC/Read.spec deleted file mode 100644 index 8314ac74b6..0000000000 --- a/include/GHC/Read.spec +++ /dev/null @@ -1,5 +0,0 @@ -module spec GHC.Read where - -type ParsedString XS = {v:_ | (if ((len XS) > 0) then ((len v) < (len XS)) else ((len v) = 0))} - -GHC.Read.lex :: xs:_ -> [((ParsedString xs), (ParsedString xs))] diff --git a/include/GHC/Real.spec b/include/GHC/Real.spec deleted file mode 100644 index edf1b10f3a..0000000000 --- a/include/GHC/Real.spec +++ /dev/null @@ -1,37 +0,0 @@ -module spec GHC.Real where - -(GHC.Real.^) :: (GHC.Num.Num a, GHC.Real.Integral b) => a:a -> n:b -> {v:a | v == 0 <=> a == 0 } - -GHC.Real.fromIntegral :: (GHC.Real.Integral a, GHC.Num.Num b) => x:a -> {v:b|v=x} - -class (GHC.Num.Num a) => GHC.Real.Fractional a where - (GHC.Real./) :: x:a -> y:{v:a | v /= 0} -> {v:a | v == x / y} - GHC.Real.recip :: a -> a - GHC.Real.fromRational :: GHC.Real.Ratio Integer -> a - -class (GHC.Real.Real a, GHC.Enum.Enum a) => GHC.Real.Integral a where - GHC.Real.quot :: x:a -> y:{v:a | v /= 0} -> {v:a | (v = (x / y)) && - ((x >= 0 && y >= 0) => v >= 0) && - ((x >= 0 && y >= 1) => v <= x) } - GHC.Real.rem :: x:a -> y:{v:a | v /= 0} -> {v:a | ((v >= 0) && (v < y))} - GHC.Real.mod :: x:a -> y:{v:a | v /= 0} -> {v:a | v = x mod y && ((0 <= x && 0 < y) => (0 <= v && v < y))} - - GHC.Real.div :: x:a -> y:{v:a | v /= 0} -> {v:a | (v = (x / y)) && - ((x >= 0 && y >= 0) => v >= 0) && - ((x >= 0 && y >= 1) => v <= x) && - ((1 < y) => v < x ) && - ((y >= 1) => v <= x) - } - GHC.Real.quotRem :: x:a -> y:{v:a | v /= 0} -> ( {v:a | (v = (x / y)) && - ((x >= 0 && y >= 0) => v >= 0) && - ((x >= 0 && y >= 1) => v <= x)} - , {v:a | ((v >= 0) && (v < y))}) - GHC.Real.divMod :: x:a -> y:{v:a | v /= 0} -> ( {v:a | (v = (x / y)) && - ((x >= 0 && y >= 0) => v >= 0) && - ((x >= 0 && y >= 1) => v <= x) } - , {v:a | v = x mod y && ((0 <= x && 0 < y) => (0 <= v && v < y))} - ) - GHC.Real.toInteger :: x:a -> {v:GHC.Integer.Type.Integer | v = x} - -// fixpoint can't handle (x mod y), only (x mod c) so we need to be more clever here -// mod :: x:a -> y:a -> {v:a | v = (x mod y) } diff --git a/include/GHC/Types.spec b/include/GHC/Types.spec deleted file mode 100644 index fe1278fda4..0000000000 --- a/include/GHC/Types.spec +++ /dev/null @@ -1,41 +0,0 @@ -module spec GHC.Types where - -embed GHC.Prim.Int# as int -embed GHC.Prim.Addr# as Str -embed GHC.Prim.Char# as Char -embed GHC.Types.Double# as real -embed GHC.Types.Float# as real -embed GHC.Types.Word as int - -// TODO: Drop prefix below -// GHC.Types.EQ :: {v:GHC.Types.Ordering | v = (cmp v) } -// GHC.Types.LT :: {v:GHC.Types.Ordering | v = (cmp v) } -// GHC.Types.GT :: {v:GHC.Types.Ordering | v = (cmp v) } - -// measure cmp :: GHC.Types.Ordering -> GHC.Types.Ordering -// cmp GHC.Types.EQ = { v | v = GHC.Types.EQ } -// cmp GHC.Types.LT = { v | v = GHC.Types.LT } -// cmp GHC.Types.GT = { v | v = GHC.Types.GT } - - -GHC.Types.True :: {v:GHC.Types.Bool | v } -GHC.Types.False :: {v:GHC.Types.Bool | (~ v) } - -GHC.Types.isTrue# :: n:_ -> {v:GHC.Types.Bool | (n = 1 <=> v)} - -GHC.Types.W# :: w:_ -> {v:GHC.Types.Word | v == w } - -assume GHC.Types.D# :: x:GHC.Prim.Double# -> {v: GHC.Types.Double | v = (x :: real) } -assume GHC.Types.F# :: x:GHC.Prim.Float# -> {v: GHC.Types.Float | v = (x :: real) } -assume GHC.Types.I# :: x:GHC.Prim.Int# -> {v: GHC.Types.Int | v = (x :: int) } -assume GHC.Types.C# :: x:GHC.Prim.Char# -> {v: GHC.Types.Char | v = (x :: Char) } - -assume GHC.Prim.+# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v: GHC.Prim.Int# | v = x + y} -assume GHC.Prim.-# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v: GHC.Prim.Int# | v = x - y} -assume GHC.Prim.==# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v:GHC.Prim.Int# | v = 1 <=> x = y} -assume GHC.Prim.>=# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v:GHC.Prim.Int# | v = 1 <=> x >= y} -assume GHC.Prim.<=# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v:GHC.Prim.Int# | v = 1 <=> x <= y} -assume GHC.Prim.<# :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v:GHC.Prim.Int# | v = 1 <=> x < y} -assume GHC.Prim.># :: x:GHC.Prim.Int# -> y:GHC.Prim.Int# -> {v:GHC.Prim.Int# | v = 1 <=> x > y} - -measure addrLen :: GHC.Prim.Addr# -> GHC.Types.Int diff --git a/include/GHC/Word.spec b/include/GHC/Word.spec deleted file mode 100644 index ff48403fe5..0000000000 --- a/include/GHC/Word.spec +++ /dev/null @@ -1,7 +0,0 @@ -module spec GHC.Word where - -embed GHC.Word.Word as int -embed GHC.Word.Word8 as int -embed GHC.Word.Word16 as int -embed GHC.Word.Word32 as int -embed GHC.Word.Word64 as int diff --git a/include/KMeansHelper.hs b/include/KMeansHelper.hs deleted file mode 100644 index e531ad4bff..0000000000 --- a/include/KMeansHelper.hs +++ /dev/null @@ -1,78 +0,0 @@ -module KMeansHelper where - -import Prelude hiding (zipWith) -import Data.List (sort, span, minimumBy) -import Data.Function (on) -import Data.Ord (comparing) -import Language.Haskell.Liquid.Prelude (liquidAssert, liquidError) - - --- | Fixed-Length Lists - -{-@ type List a N = {v : [a] | (len v) = N} @-} - - --- | N Dimensional Points - -{-@ type Point N = List Double N @-} - -{-@ type NonEmptyList a = {v : [a] | (len v) > 0} @-} - --- | Clustering - -{-@ type Clustering a = [(NonEmptyList a)] @-} - ------------------------------------------------------------------- --- | Grouping By a Predicate ------------------------------------- ------------------------------------------------------------------- - -{-@ groupBy :: (a -> a -> Bool) -> [a] -> (Clustering a) @-} -groupBy _ [] = [] -groupBy eq (x:xs) = (x:ys) : groupBy eq zs - where (ys,zs) = span (eq x) xs - ------------------------------------------------------------------- --- | Partitioning By a Size -------------------------------------- ------------------------------------------------------------------- - -{-@ type PosInt = {v: Int | v > 0 } @-} - -{-@ partition :: size:PosInt -> xs:[a] -> (Clustering a) / [len xs] @-} - -partition size [] = [] -partition size ys@(_:_) = zs : partition size zs' - where - zs = take size ys - zs' = drop size ys - ------------------------------------------------------------------------ --- | Safe Zipping ----------------------------------------------------- ------------------------------------------------------------------------ - -{-@ zipWith :: (a -> b -> c) -> xs:[a] -> (List b (len xs)) -> (List c (len xs)) @-} -zipWith f (a:as) (b:bs) = f a b : zipWith f as bs -zipWith _ [] [] = [] - --- Other cases only for exposition -zipWith _ (_:_) [] = liquidError "Dead Code" -zipWith _ [] (_:_) = liquidError "Dead Code" - ------------------------------------------------------------------------ --- | "Matrix" Transposition ------------------------------------------- ------------------------------------------------------------------------ - -{-@ type Matrix a Rows Cols = (List (List a Cols) Rows) @-} - -{-@ transpose :: c:Int -> r:PosInt -> Matrix a r c -> Matrix a c r @-} - -transpose :: Int -> Int -> [[a]] -> [[a]] -transpose 0 _ _ = [] -transpose c r ((x:xs) : xss) = (x : map head xss) : transpose (c-1) r (xs : map tail xss) - --- Or, with comprehensions --- transpose c r ((x:xs):xss) = (x : [ xs' | (x':_) <- xss ]) : transpose (c-1) r (xs : [xs' | (_ : xs') <- xss]) - --- Not needed, just for exposition -transpose c r ([] : _) = liquidError "dead code" -transpose c r [] = liquidError "dead code" - diff --git a/include/Language/Haskell/Liquid/Bag.hs b/include/Language/Haskell/Liquid/Bag.hs deleted file mode 100644 index a2fe10cd34..0000000000 --- a/include/Language/Haskell/Liquid/Bag.hs +++ /dev/null @@ -1,53 +0,0 @@ -module Language.Haskell.Liquid.Bag where - -import qualified Data.Map as M - -{-@ embed Data.Map.Map as Map_t @-} - -{-@ measure Map_default :: Int -> Bag a @-} -{-@ measure Map_union :: Bag a -> Bag a -> Bag a @-} -{-@ measure Map_select :: Data.Map.Map k v -> k -> v @-} -{-@ measure Map_store :: Data.Map.Map k v -> k -> v -> Data.Map.Map k v @-} -{-@ measure bagSize :: Bag k -> Int @-} - --- if I just write measure fromList the measure definition is not imported -{-@ measure fromList :: [k] -> Bag k - fromList [] = Map_default 0 - fromList (x:xs) = Map_store (fromList xs) x (1 + (Map_select (fromList xs) x)) - @-} - - -type Bag a = M.Map a Int - -{-@ assume empty :: {v:Bag k | v = Map_default 0} @-} -empty :: Bag k -empty = M.empty - -{-@ assume bagSize :: b:Bag k -> {i:Nat | i == bagSize b} @-} -bagSize :: Bag k -> Int -bagSize b = sum (M.elems b) - -{-@ fromList :: (Ord k) => xs:[k] -> {v:Bag k | v == fromList xs } @-} -fromList :: (Ord k) => [k] -> Bag k -fromList [] = empty -fromList (x:xs) = put x (fromList xs) - -{-@ assume get :: (Ord k) => k:k -> b:Bag k -> {v:Nat | v = Map_select b k} @-} -get :: (Ord k) => k -> Bag k -> Int -get k m = M.findWithDefault 0 k m - -{-@ assume put :: (Ord k) => k:k -> b:Bag k -> {v:Bag k | v = Map_store b k (1 + (Map_select b k))} @-} -put :: (Ord k) => k -> Bag k -> Bag k -put k m = M.insert k (1 + get k m) m - -{-@ assume union :: (Ord k) => m1:Bag k -> m2:Bag k -> {v:Bag k | v = Map_union m1 m2} @-} -union :: (Ord k) => Bag k -> Bag k -> Bag k -union m1 m2 = M.union m1 m2 - -{-@ thm_emp :: x:k -> xs:Bag k -> { Language.Haskell.Liquid.Bag.empty /= put x xs } @-} -thm_emp :: (Ord k) => k -> Bag k -> () -thm_emp x xs = const () (get x xs) - -{-@ assume thm_size :: xs:[k] -> { bagSize (fromList xs) == len xs } @-} -thm_size :: (Ord k) => [k] -> () -thm_size _ = () diff --git a/include/Language/Haskell/Liquid/Equational.hs b/include/Language/Haskell/Liquid/Equational.hs deleted file mode 100644 index 11ba1aad7e..0000000000 --- a/include/Language/Haskell/Liquid/Equational.hs +++ /dev/null @@ -1,55 +0,0 @@ -module Language.Haskell.Liquid.Equational where - -------------------------------------------------------------------------------- --- | Proof is just unit -------------------------------------------------------------------------------- - -type Proof = () - -------------------------------------------------------------------------------- --- | Casting expressions to Proof using the "postfix" `*** QED` -------------------------------------------------------------------------------- - -data QED = QED - -infixl 2 *** -(***) :: a -> QED -> Proof -_ *** QED = () - -------------------------------------------------------------------------------- --- | Equational Reasoning operators --- | The `eq` operator is inlined in the logic, so can be used in reflected --- | functions while ignoring the equality steps. -------------------------------------------------------------------------------- - -infixl 3 ==., `eq` - - -{-@ (==.) :: x:a -> y:{a | x == y} -> {v:a | v == y && v == x} @-} -(==.) :: a -> a -> a -_ ==. x = x -{-# INLINE (==.) #-} - - -{-@ eq :: x:a -> y:{a | x == y} -> {v:a | v == y && v == x} @-} -eq :: a -> a -> a -_ `eq` x = x -{-# INLINE eq #-} - -------------------------------------------------------------------------------- --- | Explanations -------------------------------------------------------------------------------- - -infixl 3 ? - -{-@ (?) :: forall a b Bool>. a -> b -> a @-} -(?) :: a -> b -> a -x ? _ = x -{-# INLINE (?) #-} - -------------------------------------------------------------------------------- --- | Using proofs as theorems -------------------------------------------------------------------------------- - -withTheorem :: a -> Proof -> a -withTheorem z _ = z diff --git a/include/Language/Haskell/Liquid/Foreign.hs b/include/Language/Haskell/Liquid/Foreign.hs deleted file mode 100644 index c89a59e34d..0000000000 --- a/include/Language/Haskell/Liquid/Foreign.hs +++ /dev/null @@ -1,64 +0,0 @@ -{-# OPTIONS_GHC -fno-warn-unused-imports #-} -{-# LANGUAGE MagicHash #-} - -{- OPTIONS_GHC -cpp #-} -{- OPTIONS_GHC -cpp -fglasgow-exts -} - -module Language.Haskell.Liquid.Foreign where - -import Foreign.C.Types (CSize(..)) -import Foreign.Ptr -import Foreign.ForeignPtr -import GHC.Base - -import Data.Word (Word64) -- Necessary to bring in scope the evidence that Word64 = int - --- TODO: shouldn't have to re-import these (tests/pos/imp0.hs) -{- import Foreign.C.Types -} -{- import Foreign.Ptr -} -{- import Foreign.ForeignPtr -} -{- import GHC.Base -} - - - ------------------------------------------------------------------------------------------------ - -{-# NOINLINE intCSize #-} -{-@ assume intCSize :: x:Int -> {v: CSize | v = x } @-} -intCSize :: Int -> CSize -intCSize = fromIntegral - -{-# NOINLINE cSizeInt #-} -{-@ assume cSizeInt :: x:CSize -> {v: Int | v = x } @-} -cSizeInt :: CSize -> Int -cSizeInt = fromIntegral - - -{-@ assume mkPtr :: x:GHC.Prim.Addr# -> {v: (Ptr b) | ((plen v) = (addrLen x) && ((plen v) >= 0)) } @-} -mkPtr :: Addr# -> Ptr b -mkPtr = undefined -- Ptr x - - -{-@ assume isNullPtr :: p:(Ptr a) -> {v:Bool | (v <=> (isNullPtr p)) } @-} -isNullPtr :: Ptr a -> Bool -isNullPtr p = (p == nullPtr) -{-# INLINE isNullPtr #-} - -{-@ fpLen :: p:(ForeignPtr a) -> {v:Int | v = (fplen p) } @-} -fpLen :: ForeignPtr a -> Int -fpLen = undefined - -{-@ pLen :: p:(Ptr a) -> {v:Int | v = (plen p) } @-} -pLen :: Ptr a -> Int -pLen = undefined - -{-@ deref :: p:Ptr a -> {v:a | v = (deref p)} @-} -deref :: Ptr a -> a -deref = undefined - -{-@ eqPtr :: p:PtrV a - -> q:{v:PtrV a | (((pbase v) = (pbase p)) && ((plen v) <= (plen p)))} - -> {v:Bool | (v <=> ((plen p) = (plen q)))} - @-} -eqPtr :: Ptr a -> Ptr a -> Bool -eqPtr = undefined diff --git a/include/Language/Haskell/Liquid/List.hs b/include/Language/Haskell/Liquid/List.hs deleted file mode 100644 index b111ba693e..0000000000 --- a/include/Language/Haskell/Liquid/List.hs +++ /dev/null @@ -1,7 +0,0 @@ -module Language.Haskell.Liquid.List (transpose) where - -{-@ lazy transpose @-} -transpose :: Int -> [[a]] -> [[a]] -transpose _ [] = [] -transpose n ([] : xss) = transpose n xss -transpose n ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (n - 1) (xs : [ t | (_:t) <- xss]) diff --git a/include/Language/Haskell/Liquid/Prelude.hs b/include/Language/Haskell/Liquid/Prelude.hs deleted file mode 100644 index 7a4be44aaf..0000000000 --- a/include/Language/Haskell/Liquid/Prelude.hs +++ /dev/null @@ -1,142 +0,0 @@ -{-# LANGUAGE MagicHash #-} - -module Language.Haskell.Liquid.Prelude where - -------------------------------------------------------------------- ---------------------------- Arithmetic ---------------------------- -------------------------------------------------------------------- - -{-@ assume plus :: x:{v:Int | true } -> y:{v:Int | true} -> {v:Int | v = x + y} @-} -{-@ assume minus :: x:{v:Int | true } -> y:{v:Int | true} -> {v:Int | v = x - y} @-} -{-@ assume times :: x:Int -> y:Int -> Int @-} -{-@ assume eq :: x:Int -> y:Int -> {v:Bool | ((v) <=> x = y)} @-} -{-@ assume neq :: x:Int -> y:Int -> {v:Bool | ((v) <=> x != y)} @-} -{-@ assume leq :: x:Int -> y:Int -> {v:Bool | ((v) <=> x <= y)} @-} -{-@ assume geq :: x:Int -> y:Int -> {v:Bool | ((v) <=> x >= y)} @-} -{-@ assume lt :: x:Int -> y:Int -> {v:Bool | ((v) <=> x < y)} @-} -{-@ assume gt :: x:Int -> y:Int -> {v:Bool | ((v) <=> x > y)} @-} - -{-# NOINLINE plus #-} -plus :: Int -> Int -> Int -plus x y = x + y - -{-# NOINLINE minus #-} -minus :: Int -> Int -> Int -minus x y = x - y - -{-# NOINLINE times #-} -times :: Int -> Int -> Int -times x y = x * y - -------------------------------------------------------------------- ---------------------------- Comparisons --------------------------- -------------------------------------------------------------------- - -{-# NOINLINE eq #-} -eq :: Int -> Int -> Bool -eq x y = x == y - -{-# NOINLINE neq #-} -neq :: Int -> Int -> Bool -neq x y = not (x == y) - -{-# NOINLINE leq #-} -leq :: Int -> Int -> Bool -leq x y = x <= y - -{-# NOINLINE geq #-} -geq :: Int -> Int -> Bool -geq x y = x >= y - -{-# NOINLINE lt #-} -lt :: Int -> Int -> Bool -lt x y = x < y - -{-# NOINLINE gt #-} -gt :: Int -> Int -> Bool -gt x y = x > y - -------------------------------------------------------------------- ------------------------- Specifications --------------------------- -------------------------------------------------------------------- - - -{-@ ignore liquidAssertB @-} -{-@ assume liquidAssertB :: x:{v:Bool | v} -> {v: Bool | v} @-} -{-# NOINLINE liquidAssertB #-} -liquidAssertB :: Bool -> Bool -liquidAssertB b = b - -{-@ assume liquidAssert :: {v:Bool | v} -> a -> a @-} -{-# NOINLINE liquidAssert #-} -liquidAssert :: Bool -> a -> a -liquidAssert _ x = x - -{-@ ignore liquidAssume @-} -{-@ assume liquidAssume :: b:Bool -> a -> {v: a | b} @-} -{-# NOINLINE liquidAssume #-} -liquidAssume :: Bool -> a -> a -liquidAssume b x = if b then x else error "liquidAssume fails" - -{-@ ignore liquidAssumeB @-} -{-@ assume liquidAssumeB :: forall

Bool>. (a

-> {v:Bool| v}) -> a -> a

@-} -liquidAssumeB :: (a -> Bool) -> a -> a -liquidAssumeB p x | p x = x - | otherwise = error "liquidAssumeB fails" - - -{-@ ignore unsafeError @-} -{-# NOINLINE unsafeError #-} -unsafeError :: String -> a -unsafeError = error - - -{-@ liquidError :: {v:String | 0 = 1} -> a @-} -{-# NOINLINE liquidError #-} -liquidError :: String -> a -liquidError = error - -{-@ assume crash :: forall a . x:{v:Bool | v} -> a @-} -{-# NOINLINE crash #-} -crash :: Bool -> a -crash = undefined - -{-# NOINLINE force #-} -force :: Bool -force = True - -{-# NOINLINE choose #-} -choose :: Int -> Int -choose = undefined - -------------------------------------------------------------------- ------------ Modular Arithmetic Wrappers --------------------------- -------------------------------------------------------------------- - --- tedium because fixpoint doesn't want to deal with (x mod y) only (x mod c) -{-@ assume isEven :: x:Int -> {v:Bool | ((v) <=> ((x mod 2) = 0))} @-} -{-# NOINLINE isEven #-} -isEven :: Int -> Bool -isEven x = x `mod` 2 == 0 - -{-@ assume isOdd :: x:Int -> {v:Bool | ((v) <=> ((x mod 2) = 1))} @-} -{-# NOINLINE isOdd #-} -isOdd :: Int -> Bool -isOdd x = x `mod` 2 == 1 - ------------------------------------------------------------------------------------------------ - -{-@ safeZipWith :: (a -> b -> c) -> xs : [a] -> ys:{v:[b] | len v = len xs} - -> {v : [c] | len v = len xs } @-} -safeZipWith :: (a->b->c) -> [a]->[b]->[c] -safeZipWith f (a:as) (b:bs) = f a b : safeZipWith f as bs -safeZipWith _ [] [] = [] -safeZipWith _ _ _ = error "safeZipWith: cannot happen!" - -{-@ (==>) :: p:Bool -> q:Bool -> {v:Bool | v <=> (p => q)} @-} -infixr 8 ==> -(==>) :: Bool -> Bool -> Bool -False ==> False = True -False ==> True = True -True ==> True = True -True ==> False = False diff --git a/include/Language/Haskell/Liquid/Prelude.pred b/include/Language/Haskell/Liquid/Prelude.pred deleted file mode 100644 index a6c5c9663a..0000000000 --- a/include/Language/Haskell/Liquid/Prelude.pred +++ /dev/null @@ -1,22 +0,0 @@ -assume (>) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> Bool -assume (<) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> Bool -assume (>=) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> Bool -assume (<=) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> Bool -assume (==) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> Bool -assume (+) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> a^True -assume (*) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> a^True -assume (-) :: forall a. forAll p1:a p2:a. (Ord a^True) => a^p1 -> a^p2 -> a^True -assume ($) :: forall a b. forAll q1:a q2:b. (a^q1 -> b^q2) -> a^q1 -> b^q2 -assume (.) :: forall b c a. forAll q1:a q2:b q3:c. (b^q2 -> c^q3) -> (a^q1 -> b^q2) -> a^q1 -> c^q3 -assume filter :: forall a. forAll p1:a. (a^p1 -> Bool) -> [a^p1]-> [a^p1] -assume snd :: forall a b. forAll p1:a p2:b. (a^p1, b^p2)-> b^p2 -assume map :: forall a b. forAll q1:a q2:b. (a^q1 -> b^q2) -> [a^q1]-> [b^q2] -assume (++) :: forall a. forAll q:a. [a^q]-> [a^q]-> [a^q] -assume concat :: forall a. forAll q:a. [[a^q]]-> [a^q] -assume foldl :: forall a b. forAll q1:a q2:b. (a^q1 -> b^q2 -> a^q1) -> a^q1 -> [b^q2]-> a^q1 -assume foldr :: forall a b. forAll q1:a q2:b. (a^q1 -> b^q2 -> b^q2) -> b^q2 -> [a^q1]-> b^q2 -assume (,) :: forall a b. forAll q1:a q2:b. a^q1 -> b^q2 ->(a^q1, b^q2) -assume Prelude.error :: forall a. forAll q2:a. [Char]-> a^q2 -assume Prelude.head :: forall a. forAll q:a. [a^q]-> a^q -assume Prelude.tail :: forall a. forAll q:a. [a^q]-> [a^q] -assume Prelude.enumFromTo :: forall a. forAll q:a. (Enum a^ True) => a^q -> a^q -> [a^q] diff --git a/include/Language/Haskell/Liquid/ProofCombinators.hs b/include/Language/Haskell/Liquid/ProofCombinators.hs deleted file mode 100644 index 3360eb7ad5..0000000000 --- a/include/Language/Haskell/Liquid/ProofCombinators.hs +++ /dev/null @@ -1,183 +0,0 @@ -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE IncoherentInstances #-} - -module Language.Haskell.Liquid.ProofCombinators ( - - -- ATTENTION! `Admit` and `(==!)` are UNSAFE: they should not belong the final proof term - - -- * Proof is just a () alias - Proof - , toProof - - -- * Proof constructors - , trivial, unreachable, (***), QED(..) - - -- * Proof certificate constructors - , (?) - - -- * These two operators check all intermediate equalities - , (===) -- proof of equality is implicit eg. x === y - , (=<=) -- proof of equality is implicit eg. x <= y - , (=>=) -- proof of equality is implicit eg. x =>= y - - -- * This operator does not check intermediate equalities - , (==.) - - -- Uncheck operator used only for proof debugging - , (==!) -- x ==! y always succeeds - - -- * Combining Proofs - , (&&&) - , withProof - , impossible - - -) where - -------------------------------------------------------------------------------- --- | Proof is just a () alias ------------------------------------------------- -------------------------------------------------------------------------------- - -type Proof = () - -toProof :: a -> Proof -toProof _ = () - -------------------------------------------------------------------------------- --- | Proof Construction ------------------------------------------------------- -------------------------------------------------------------------------------- - --- | trivial is proof by SMT - -trivial :: Proof -trivial = () - --- {-@ unreachable :: {v : Proof | False } @-} -unreachable :: Proof -unreachable = () - --- All proof terms are deleted at runtime. -{- RULE "proofs are irrelevant" forall (p :: Proof). p = () #-} - --- | proof casting --- | `x *** QED`: x is a proof certificate* strong enough for SMT to prove your theorem --- | `x *** Admit`: x is an unfinished proof - -infixl 3 *** -{-@ assume (***) :: a -> p:QED -> { if (isAdmit p) then false else true } @-} -(***) :: a -> QED -> Proof -_ *** _ = () - -data QED = Admit | QED - -{-@ measure isAdmit :: QED -> Bool @-} -{-@ Admit :: {v:QED | isAdmit v } @-} - - -------------------------------------------------------------------------------- --- | * Checked Proof Certificates --------------------------------------------- -------------------------------------------------------------------------------- - --- Any (refined) carries proof certificates. --- For example 42 :: {v:Int | v == 42} is a certificate that --- the value 42 is equal to 42. --- But, this certificate will not really be used to proof any fancy theorems. - --- Below we provide a number of equational operations --- that constuct proof certificates. - --- | Implicit equality - --- x === y returns the proof certificate that --- result value is equal to both x and y --- when y == x (as assumed by the operator's precondition) - -infixl 3 === -{-@ (===) :: x:a -> y:{a | y == x} -> {v:a | v == x && v == y} @-} -(===) :: a -> a -> a -_ === y = y - -infixl 3 =<= -{-@ (=<=) :: x:a -> y:{a | x <= y} -> {v:a | v == y} @-} -(=<=) :: a -> a -> a -_ =<= y = y - -infixl 3 =>= -{-@ (=>=) :: x:a -> y:{a | x >= y} -> {v:a | v == y} @-} -(=>=) :: a -> a -> a -_ =>= y = y - -------------------------------------------------------------------------------- --- | `?` is basically Haskell's $ and is used for the right precedence --- | `?` lets you "add" some fact into a proof term -------------------------------------------------------------------------------- - -infixl 3 ? - -{-@ (?) :: forall a b Bool, pb :: b -> Bool>. a -> b -> a @-} -(?) :: a -> b -> a -x ? _ = x -{-# INLINE (?) #-} - -------------------------------------------------------------------------------- --- | Assumed equality --- `x ==! y ` --- returns the admitted proof certificate that result value is equals x and y -------------------------------------------------------------------------------- - -infixl 3 ==! -{-@ assume (==!) :: x:a -> y:a -> {v:a | v == x && v == y} @-} -(==!) :: a -> a -> a -(==!) _ y = y - - --- | To summarize: --- --- - (==!) is *only* for proof debugging --- - (===) does not require explicit proof term --- - (?) lets you insert "lemmas" as other `Proof` values - -------------------------------------------------------------------------------- --- | * Unchecked Proof Certificates ------------------------------------------- -------------------------------------------------------------------------------- - --- | The above operators check each intermediate proof step. --- The operator `==.` below accepts an optional proof term --- argument, but does not check intermediate steps. --- TODO: What is it USEFUL FOR? - -infixl 3 ==. - -{-# DEPRECATED (==.) "Use (===) instead" #-} - -{-# INLINE (==.) #-} -(==.) :: a -> a -> a -_ ==. x = x - -------------------------------------------------------------------------------- --- | * Combining Proof Certificates ------------------------------------------- -------------------------------------------------------------------------------- - -(&&&) :: Proof -> Proof -> Proof -x &&& _ = x - - -{-@ withProof :: x:a -> b -> {v:a | v = x} @-} -withProof :: a -> b -> a -withProof x _ = x - -{-@ impossible :: {v:a | false} -> b @-} -impossible :: a -> b -impossible _ = undefined - -------------------------------------------------------------------------------- --- | Convenient Syntax for Inductive Propositions -------------------------------------------------------------------------------- - -{-@ measure prop :: a -> b @-} -{-@ type Prop E = {v:_ | prop v = E} @-} - - - diff --git a/include/Language/Haskell/Liquid/RTick/Combinators.hs b/include/Language/Haskell/Liquid/RTick/Combinators.hs deleted file mode 100644 index 00da9a0c4c..0000000000 --- a/include/Language/Haskell/Liquid/RTick/Combinators.hs +++ /dev/null @@ -1,366 +0,0 @@ - --- --- Liquidate your assets: reasoning about resource usage in Liquid Haskell. --- - -{-@ LIQUID "--reflection" @-} - -module Language.Haskell.Liquid.RTick.Combinators - ( - - -- Basic: - Proof -- Simply the unit type. - , QED(..) -- 'ASS': Signify the end of an /unfinished/ proof. - -- 'QED': Signify the end of a /complete/ proof. - , (&&&) -- Combine proofs. - , (***) -- Discard final result at the end of a proof. - , (?) -- Appeal to an external theorem. - , isAss -- Check whether a proof is complete. - , toProof -- Cast to proof. - , trivial -- Trivial proof. - , withTheorem -- Appeal to an external theorem. - -- Equational: - , (==.) -- Equality. - , (==?) -- Equality (assumption). - , eq -- Equality. Note: 'eq' is inlined in the logic. - -- Inequational: - , (<.) -- Less than. - , (.) -- Greater than. - , (>?) -- Greater than (assumption). - , (>=.) -- Greater than or equal. - , (>=?) -- Greater than or equal (assumption). - , (<=>.) -- Cost equivalence. - , (<=>?) -- Cost equivalence (assumption) - , (>~>.) -- Improvement. - , (>~>?) -- Improvement (assumption). - , (.>==) -- Quantified improvement. - , (?>==) -- Quantified improvement (assumption). - , (<~<.) -- Diminishment. - , (<~.) -- Quantified improvement. - , (==>?) -- Quantified improvement (assumption). - , (==<.) -- Quantified diminishment. - , (== {b} @-} -assert :: Bool -> Proof -assert _ = () - --- unchecked -(==!) :: a -> a -> a -_ ==! x = x - - -type Proof = () -data QED = QED | ASS - -{-@ toProof :: a -> Proof @-} -toProof :: a -> Proof -toProof _ = () -{-# INLINE toProof #-} - -{-@ trivial :: Proof @-} -trivial :: Proof -trivial = () -{-# INLINE trivial #-} - -{-@ measure isAss @-} -isAss :: QED -> Bool -isAss ASS = True -isAss QED = False - -{-@ assume (***) :: a -> qed:QED -> { if (isAss qed) then false else true } @-} -infixl 1 *** -(***) :: a -> QED -> Proof -_ *** _ = () -{-# INLINE (***) #-} - -{-@ (?) :: x:a -> Proof -> { v:a | x == v } @-} -infixl 3 ? -(?) :: a -> Proof -> a -x ? _ = x -{-# INLINE (?) #-} - -{-@ (&&&) :: Proof -> Proof -> Proof @-} -infixl 3 &&& -(&&&) :: Proof -> Proof -> Proof -x &&& _ = x -{-# INLINE (&&&) #-} - -{-@ withTheorem :: x:a -> Proof -> { v:a | x == v } @-} -withTheorem :: a -> Proof -> a -withTheorem x _ = x -{-# INLINE withTheorem #-} - -------------------------------------------------------------------------------- --- | Equational: -------------------------------------------------------------------------------- - --- --- Equality. --- -{-@ (==.) :: x:a -> { y:a | x == y } -> { v:a | x == v && y == v } @-} -infixl 3 ==. -(==.) :: a -> a -> a -_ ==. x = x -{-# INLINE (==.) #-} - -{-@ assume (==?) :: x:a -> y:a -> { v:a | x == v && y == v } @-} -infixl 3 ==? -(==?) :: a -> a -> a -_ ==? x = x -{-# INLINE (==?) #-} - --- --- Equality. Note: 'eq' is inlined in the logic, so can be used in --- reflected functions. --- -{-@ eq :: x:a -> { y:a | x == y } -> { v:a | x == v && y == v } @-} -eq :: a -> a -> a -_ `eq` x = x -{-# INLINE eq #-} - -------------------------------------------------------------------------------- --- | Inequational: -------------------------------------------------------------------------------- - --- --- Less than. --- -{-@ (<.) :: m:a -> { n:a | m < n } -> { o:a | o == n } @-} -infixl 3 <. -(<.) :: a -> a -> a -_ <. n = n -{-# INLINE (<.) #-} - -{-@ assume ( n:a -> { o:a | o == n && m < n } @-} -infixl 3 a -> a -_ { n:a | m <= n } -> { o:a | o == n } @-} -infixl 3 <=. -(<=.) :: a -> a -> a -_ <=. n = n -{-# INLINE (<=.) #-} - -{-@ assume (<=?) :: m:a -> n:a -> { o:a | o == n && m <= n } @-} -infixl 3 <=? -(<=?) :: a -> a -> a -_ <=? n = n -{-# INLINE (<=?) #-} - --- --- Greater than. --- -{-@ (>.) :: m:a -> { n:a | m > n } -> { o:a | o == n } @-} -infixl 3 >. -(>.) :: a -> a -> a -_ >. y = y -{-# INLINE (>.) #-} - -{-@ assume (>?) :: m:a -> n:a -> { o:a | o == n && m > n } @-} -infixl 3 >? -(>?) :: a -> a -> a -_ >? y = y -{-# INLINE (>?) #-} - --- --- Greater than or equal. --- -{-@ (>=.) :: m:a -> { n:a | m >= n } -> { o:a | o == n } @-} -infixl 3 >=. -(>=.) :: a -> a -> a -_ >=. n = n -{-# INLINE (>=.) #-} - -{-@ assume (>=?) :: m:a -> n:a -> { o:a | o == n && m >= n } @-} -infixl 3 >=? -(>=?) :: a -> a -> a -_ >=? n = n -{-# INLINE (>=?) #-} - --- --- Cost equivalence. --- -{-@ predicate COSTEQ T1 T2 = tval T1 == tval T2 && tcost T1 == tcost T2 @-} - -{-@ (<=>.) - :: t1:Tick a - -> { t2:Tick a | COSTEQ t1 t2 } - -> { t3:Tick a | COSTEQ t1 t2 && COSTEQ t1 t3 && COSTEQ t2 t3 } -@-} -infixl 3 <=>. -(<=>.) :: Tick a -> Tick a -> Tick a -(<=>.) _ t2 = t2 -{-# INLINE (<=>.) #-} - -{-@ assume (<=>?) - :: t1:Tick a -> t2:Tick a - -> { t3:Tick a | COSTEQ t1 t2 && COSTEQ t1 t3 && t2 == t3 } -@-} -infixl 3 <=>? -(<=>?) :: Tick a -> Tick a -> Tick a -(<=>?) _ t2 = t2 -{-# INLINE (<=>?) #-} - --- --- Improvement. --- -{-@ predicate IMP T1 T2 = tval T1 == tval T2 && tcost T1 >= tcost T2 @-} - -{-@ (>~>.) - :: t1:Tick a - -> { t2:Tick a | IMP t1 t2 } - -> { t3:Tick a | IMP t1 t2 && IMP t1 t3 && t2 == t3 } -@-} -infixl 3 >~>. -(>~>.) :: Tick a -> Tick a -> Tick a -(>~>.) _ t2 = t2 -{-# INLINE (>~>.) #-} - -{-@ assume (>~>?) - :: t1:Tick a -> t2:Tick a - -> { t3:Tick a | IMP t1 t2 && IMP t1 t3 && t2 == t3 } -@-} -infixl 3 >~>? -(>~>?) :: Tick a -> Tick a -> Tick a -(>~>?) _ t2 = t2 -{-# INLINE (>~>?) #-} - --- --- Quantified improvement. --- -{-@ predicate QIMP T1 N T2 = tval T1 == tval T2 && tcost T1 == tcost T2 + N @-} - -{-@ (.>==) - :: t1:Tick a - -> n:Int - -> { t2:Tick a | QIMP t1 n t2 } - -> { t3:Tick a | QIMP t1 n t2 && QIMP t1 n t3 && t2 == t3 } -@-} -infixl 3 .>== -(.>==) :: Tick a -> Int -> Tick a -> Tick a -(.>==) _ _ t2 = t2 -{-# INLINE (.>==) #-} - -{-@ assume (?>==) - :: t1:Tick a -> n:Nat -> t2:Tick a - -> { t3:Tick a | QIMP t1 n t2 && QIMP t1 n t3 && t2 == t3 } -@-} -infixl 3 ?>== -(?>==) :: Tick a -> Int -> Tick a -> Tick a -(?>==) _ _ t2 = t2 -{-# INLINE (?>==) #-} - --- --- Diminishment. --- -{-@ predicate DIM T1 T2 = tval T1 == tval T2 && tcost T1 <= tcost T2 @-} - -{-@ (<~<.) - :: t1:Tick a - -> { t2:Tick a | DIM t1 t2 } - -> { t3:Tick a | DIM t1 t2 && DIM t1 t3 && t2 == t3 } -@-} -infixl 3 <~<. -(<~<.) :: Tick a -> Tick a -> Tick a -(<~<.) _ t2 = t2 -{-# INLINE (<~<.) #-} - -{-@ assume (<~ t2:Tick a - -> { t3:Tick a | DIM t1 t2 && DIM t1 t3 && t2 == t3 } -@-} -infixl 3 <~ Tick a -> Tick a -(<~ n:Nat - -> { t2:Tick a | QDIM t1 n t2 } - -> { t3:Tick a | QDIM t1 n t2 && QDIM t1 n t3 && t2 == t3 } -@-} -infixl 3 .<== -(.<==) :: Tick a -> Int -> Tick a -> Tick a -(.<==) _ _ t2 = t2 -{-# INLINE (.<==) #-} - -{-@ assume (?<==) - :: t1:Tick a -> n:Nat -> t2:Tick a - -> { t3:Tick a | QDIM t1 n t2 && QDIM t1 n t3 && t2 == t3 } -@-} -infixl 3 ?<== -(?<==) :: Tick a -> Int -> Tick a -> Tick a -(?<==) _ _ t2 = t2 -{-# INLINE (?<==) #-} - -------------------------------------------------------------------------------- --- | Cost separators: -------------------------------------------------------------------------------- - --- --- Quantified improvement. --- -{-@ (==>.) :: (a -> b) -> a -> b @-} -infixl 3 ==>. -(==>.) :: (a -> b) -> a -> b -f ==>. a = f a -{-# INLINE (==>.) #-} - --- --- Quantified improvement (assumption). --- -{-@ (==>?) :: (a -> b) -> a -> b @-} -infixl 3 ==>? -(==>?) :: (a -> b) -> a -> b -f ==>? a = f a -{-# INLINE (==>?) #-} - --- --- Quantified diminishment. --- -{-@ (==<.) :: (a -> b) -> a -> b @-} -infixl 3 ==<. -(==<.) :: (a -> b) -> a -> b -f ==<. a = f a -{-# INLINE (==<.) #-} - --- --- Quantified diminishment (assumption). --- -{-@ (== b) -> a -> b @-} -infixl 3 == b) -> a -> b -f == Int @-} -{-@ measure subString :: SMTString -> Int -> Int -> SMTString @-} -{-@ measure concatString :: SMTString -> SMTString -> SMTString @-} -{-@ measure fromString :: String -> SMTString @-} -{-@ measure takeString :: Int -> SMTString -> SMTString @-} -{-@ measure dropString :: Int -> SMTString -> SMTString @-} - ----------------------------------- - -{-@ assume concatString :: x:SMTString -> y:SMTString - -> {v:SMTString | v == concatString x y && stringLen v == stringLen x + stringLen y } @-} -concatString :: SMTString -> SMTString -> SMTString -concatString (S s1) (S s2) = S (s1 `BS.append` s2) - -{-@ assume stringEmp :: {v:SMTString | v == stringEmp && stringLen v == 0 } @-} -stringEmp :: SMTString -stringEmp = S (BS.empty) - -stringLen :: SMTString -> Int -{-@ assume stringLen :: x:SMTString -> {v:Nat | v == stringLen x} @-} -stringLen (S s) = BS.length s - - -{-@ assume subString :: s:SMTString -> offset:Int -> ln:Int -> {v:SMTString | v == subString s offset ln } @-} -subString :: SMTString -> Int -> Int -> SMTString -subString (S s) o l = S (BS.take l $ BS.drop o s) - - -{-@ assume takeString :: i:Nat -> xs:{SMTString | i <= stringLen xs } -> {v:SMTString | stringLen v == i && v == takeString i xs } @-} -takeString :: Int -> SMTString -> SMTString -takeString i (S s) = S (BS.take i s) - -{-@ assume dropString :: i:Nat -> xs:{SMTString | i <= stringLen xs } -> {v:SMTString | stringLen v == stringLen xs - i && v == dropString i xs } @-} -dropString :: Int -> SMTString -> SMTString -dropString i (S s) = S (BS.drop i s) - - -{-@ assume fromString :: i:String -> {o:SMTString | i == o && o == fromString i} @-} -fromString :: String -> SMTString -fromString = S . ST.fromString - - -{-@ assume isNullString :: i:SMTString -> {b:Bool | b <=> stringLen i == 0 } @-} -isNullString :: SMTString -> Bool -isNullString (S s) = BS.length s == 0 diff --git a/include/Language/Haskell/Liquid/Synthesize/Error.hs b/include/Language/Haskell/Liquid/Synthesize/Error.hs deleted file mode 100644 index 41af9bf08d..0000000000 --- a/include/Language/Haskell/Liquid/Synthesize/Error.hs +++ /dev/null @@ -1,5 +0,0 @@ -module Language.Haskell.Liquid.Synthesize.Error where - -{-@ err :: { v: Int | false } -> a @-} -err :: Int -> a -err s = undefined \ No newline at end of file diff --git a/include/NotReal.spec b/include/NotReal.spec deleted file mode 100644 index fd347cb3d3..0000000000 --- a/include/NotReal.spec +++ /dev/null @@ -1,11 +0,0 @@ -module spec Prelude where - -import GHC.Num -assume GHC.Num.* :: (GHC.Num.Num a) => x:a -> y:a - -> {v:a | ((((((x = 0) || (y = 0)) => (v = 0))) - && (((x > 0) && (y > 0)) => ((v >= x) && (v >= y)))) - && (((x > 1) && (y > 1)) => ((v > x) && (v > y)))) - } - - -GHC.Real./ :: (GHC.Real.Fractional a) => x:a -> y:{v:a | v != 0.0} -> a diff --git a/include/PatErr.spec b/include/PatErr.spec deleted file mode 100644 index 14d4f69b25..0000000000 --- a/include/PatErr.spec +++ /dev/null @@ -1,15 +0,0 @@ -module spec Prelude where - - -measure totalityError :: a -> Bool - - -assume Control.Exception.Base.patError :: {v:GHC.Prim.Addr# | totalityError "Pattern match(es) are non-exhaustive"} -> a - -assume Control.Exception.Base.recSelError :: {v:GHC.Prim.Addr# | totalityError "Use of partial record field selector"} -> a - -assume Control.Exception.Base.nonExhaustiveGuardsError :: {v:GHC.Prim.Addr# | totalityError "Guards are non-exhaustive"} -> a - -assume Control.Exception.Base.noMethodBindingError :: {v:GHC.Prim.Addr# | totalityError "Missing method(s) on instance declaration"} -> a - -assume Control.Exception.Base.recConError :: {v:GHC.Prim.Addr# | totalityError "Missing field in record construction"} -> a \ No newline at end of file diff --git a/include/Prelude.hquals b/include/Prelude.hquals deleted file mode 100644 index 66d1337c30..0000000000 --- a/include/Prelude.hquals +++ /dev/null @@ -1,44 +0,0 @@ -//BOT: Do not delete EVER! - -qualif Bot(v:@(0)) : (0 = 1) -qualif Bot(v:obj) : (0 = 1) -qualif Bot(v:a) : (0 = 1) -qualif Bot(v:bool) : (0 = 1) -qualif Bot(v:int) : (0 = 1) - -qualif CmpZ(v:a) : (v < 0) -qualif CmpZ(v:a) : (v <= 0) -qualif CmpZ(v:a) : (v > 0) -qualif CmpZ(v:a) : (v >= 0) -qualif CmpZ(v:a) : (v = 0) -qualif CmpZ(v:a) : (v != 0) - -qualif Cmp(v:a, x:a) : (v < x) -qualif Cmp(v:a, x:a) : (v <= x) -qualif Cmp(v:a, x:a) : (v > x) -qualif Cmp(v:a, x:a) : (v >= x) -qualif Cmp(v:a, x:a) : (v = x) -qualif Cmp(v:a, x:a) : (v != x) - -// qualif CmpZ(v:a) : v [ < ; <= ; > ; >= ; = ; != ] 0 -// qualif Cmp(v:a,x:a) : v [ < ; <= ; > ; >= ; = ; != ] x -// qualif Cmp(v:int,x:int) : v [ < ; <= ; > ; >= ; = ; != ] x - - -qualif One(v:int) : v = 1 -qualif True1(v:GHC.Types.Bool) : (v) -qualif False1(v:GHC.Types.Bool) : (~ v) - -constant papp1 : func(1, [Pred @(0); @(0); bool]) -qualif Papp(v:a,p:Pred a) : (papp1(p, v)) - -constant papp2 : func(4, [Pred @(0) @(1); @(2); @(3); bool]) -qualif Papp2(v:a,x:b,p:Pred a b) : (papp2(p, v, x)) - -qualif Papp3(v:a,x:b, y:c, p:Pred a b c) : (papp3(p, v, x, y)) -constant papp3 : func(6, [Pred @(0) @(1) @(2); @(3); @(4); @(5); bool]) - -// qualif Papp4(v:a,x:b, y:c, z:d, p:Pred a b c d) : papp4(p, v, x, y, z) -constant papp4 : func(8, [Pred @(0) @(1) @(2) @(6); @(3); @(4); @(5); @(7); bool]) - -constant runFun : func(2, [Arrow @(0) @(1); @(0); @(1)]) diff --git a/include/Prelude.spec b/include/Prelude.spec deleted file mode 100644 index bffeaa9f5f..0000000000 --- a/include/Prelude.spec +++ /dev/null @@ -1,88 +0,0 @@ -module spec Prelude where - -import GHC.Base -import GHC.Int -import GHC.List -import GHC.Num -import GHC.Real -import GHC.Word - -import Data.Foldable -import Data.Maybe -import Data.Tuple -import GHC.Exts -import GHC.Err - - -// GHC.Types.D# :: x:_ -> {v:_ | v = x} - -GHC.Err.error :: {v:_ | false} -> a - -assume GHC.Base.. :: forall

c -> Bool, q :: a -> b -> Bool, r :: a -> c -> Bool>. - {xcmp::a, wcmp::b |- c

<: c} - (ycmp:b -> c

) - -> (zcmp:a -> b) - -> xcmp:a -> c -assume GHC.Integer.smallInteger :: x:GHC.Prim.Int# -> { v:GHC.Integer.Type | v = (x :: int) } - -assume GHC.Num.+ :: (GHC.Num.Num a) => x:a -> y:a -> {v:a | v = x + y } -assume GHC.Num.- :: (GHC.Num.Num a) => x:a -> y:a -> {v:a | v = x - y } - -embed GHC.Types.Double as real -embed GHC.Types.Float as real -embed Integer as int - -type GeInt N = {v: GHC.Types.Int | v >= N } -type LeInt N = {v: GHC.Types.Int | v <= N } -type Nat = {v: GHC.Types.Int | v >= 0 } -type Even = {v: GHC.Types.Int | (v mod 2) = 0 } -type Odd = {v: GHC.Types.Int | (v mod 2) = 1 } -type BNat N = {v: Nat | v <= N } -type TT = {v: GHC.Types.Bool | v} -type FF = {v: GHC.Types.Bool | not v} -type String = [GHC.Types.Char] - -predicate Max V X Y = if X > Y then V = X else V = Y -predicate Min V X Y = if X < Y then V = X else V = Y - -type IncrListD a = [a]<{\x y -> (x+D) <= y}> - -// BOT: Do not delete EVER! - -qualif Bot(v:@(0)) : (0 = 1) -qualif Bot(v:obj) : (0 = 1) -qualif Bot(v:a) : (0 = 1) -qualif Bot(v:bool) : (0 = 1) -qualif Bot(v:int) : (0 = 1) - -qualif CmpZ(v:a) : (v < 0) -qualif CmpZ(v:a) : (v <= 0) -qualif CmpZ(v:a) : (v > 0) -qualif CmpZ(v:a) : (v >= 0) -qualif CmpZ(v:a) : (v = 0) -qualif CmpZ(v:a) : (v != 0) - -qualif Cmp(v:a, x:a) : (v < x) -qualif Cmp(v:a, x:a) : (v <= x) -qualif Cmp(v:a, x:a) : (v > x) -qualif Cmp(v:a, x:a) : (v >= x) -qualif Cmp(v:a, x:a) : (v = x) -qualif Cmp(v:a, x:a) : (v != x) - -qualif One(v:int) : v = 1 -qualif True1(v:GHC.Types.Bool) : (v) -qualif False1(v:GHC.Types.Bool) : (~ v) - -// REBARE constant papp1 : func(1, [Pred @(0); @(0); bool]) -qualif Papp(v:a, p:Pred a) : (papp1 p v) - -// REBARE constant papp2 : func(4, [Pred @(0) @(1); @(2); @(3); bool]) -qualif Papp2(v:a, x:b, p:Pred a b) : (papp2 p v x) - -// REBARE constant papp3 : func(6, [Pred @(0) @(1) @(2); @(3); @(4); @(5); bool]) -qualif Papp3(v:a, x:b, y:c, p:Pred a b c) : (papp3 p v x y) - -// qualif Papp4(v:a,x:b, y:c, z:d, p:Pred a b c d) : papp4(p, v, x, y, z) -// REBARE constant papp4 : func(8, [Pred @(0) @(1) @(2) @(6); @(3); @(4); @(5); @(7); bool]) - -// REBARE constant runFun : func(2, [Arrow @(0) @(1); @(0); @(1)]) diff --git a/include/Real.spec b/include/Real.spec deleted file mode 100644 index 978c83533d..0000000000 --- a/include/Real.spec +++ /dev/null @@ -1,9 +0,0 @@ -module spec Prelude where - -import GHC.Num - -assume GHC.Num.* :: (GHC.Num.Num a) => x:a -> y:a -> {v:a | v = x * y} - - - -// GHC.Real./ :: forall a. (GHC.Real.Fractional a) => x:a -> y:{v:a | v != 0.0} -> {v: a | v = (x / y) } diff --git a/include/System/IO.spec b/include/System/IO.spec deleted file mode 100644 index d044ab3c62..0000000000 --- a/include/System/IO.spec +++ /dev/null @@ -1,3 +0,0 @@ -module spec System.IO where - -import GHC.IO.Handle diff --git a/include/len.hquals b/include/len.hquals deleted file mode 100644 index dd7ecc6724..0000000000 --- a/include/len.hquals +++ /dev/null @@ -1,7 +0,0 @@ - -// Qualifiers about complex length relationships -// qualif LenSum(v:[a], ~A:[b], ~B:[c]): len([v]) = (len([~A]) [ +; - ] len([~B])) - -qualif LenSum(v:[a], xs:[b], ys:[c]): len([v]) = (len([xs]) + len([ys])) -qualif LenSum(v:[a], xs:[b], ys:[c]): len([v]) = (len([xs]) - len([ys])) - diff --git a/liquid-base/liquid-base.cabal b/liquid-base/liquid-base.cabal index 30087528f9..9f15ec22f5 100644 --- a/liquid-base/liquid-base.cabal +++ b/liquid-base/liquid-base.cabal @@ -1,6 +1,6 @@ -cabal-version: 1.24 +cabal-version: 2.0 name: liquid-base -version: 4.14.3.0 +version: 4.15.1.0 synopsis: Drop-in base replacement for LiquidHaskell description: Drop-in base replacement for LiquidHaskell. license: BSD3 @@ -23,7 +23,7 @@ data-files: src/Data/*.spec src/Control/*.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Control.Applicative @@ -244,17 +244,11 @@ library Liquid.Prelude.Totality hs-source-dirs: src - build-depends: - liquid-ghc-prim - , liquidhaskell >= 0.8.10.1 - if impl(ghc < 9) - build-depends: integer-gmp < 1.0.4.0 - , base == 4.14.3.0 - else - build-depends: base == 4.15.0.0 + build-depends: base ^>= 4.16.0.0 + , liquid-ghc-prim + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports NoImplicitPrelude if impl(ghc >= 8.10) ghc-options: -fplugin=LiquidHaskell -fplugin-opt=LiquidHaskell:--no-positivity-check - \ No newline at end of file diff --git a/liquid-base/src/Foreign/ForeignPtr.spec b/liquid-base/src/Foreign/ForeignPtr.spec index 5c1bd76ba9..f9ff6e5f07 100644 --- a/liquid-base/src/Foreign/ForeignPtr.spec +++ b/liquid-base/src/Foreign/ForeignPtr.spec @@ -3,7 +3,7 @@ module spec Foreign.ForeignPtr where import GHC.ForeignPtr import Foreign.Ptr -Foreign.ForeignPtr.withForeignPtr :: forall a b. fp:(GHC.ForeignPtr.ForeignPtr a) +GHC.ForeignPtr.withForeignPtr :: forall a b. fp:(GHC.ForeignPtr.ForeignPtr a) -> ((PtrN a (fplen fp)) -> GHC.Types.IO b) -> (GHC.Types.IO b) diff --git a/liquid-base/src/GHC/Num.spec b/liquid-base/src/GHC/Num.spec index 3809a3e3ea..7f1755bfd2 100644 --- a/liquid-base/src/GHC/Num.spec +++ b/liquid-base/src/GHC/Num.spec @@ -9,5 +9,7 @@ GHC.Num.negate :: (GHC.Num.Num a) => x:a -> {v:a | v = -x} +GHC.Num.abs :: (GHC.Num.Num a) => x:a -> {y:a | (x >= 0 ==> y = x) && (x < 0 ==> y = -x) } + GHC.Num.+ :: (GHC.Num.Num a) => x:a -> y:a -> {v:a | v = x + y } GHC.Num.- :: (GHC.Num.Num a) => x:a -> y:a -> {v:a | v = x - y } diff --git a/liquid-base/src/GHC/Real.spec b/liquid-base/src/GHC/Real.spec index 830ec4fbb8..b67039f25c 100644 --- a/liquid-base/src/GHC/Real.spec +++ b/liquid-base/src/GHC/Real.spec @@ -2,7 +2,7 @@ module spec GHC.Real where import GHC.Types -(GHC.Real.^) :: (GHC.Num.Num a, GHC.Real.Integral b) => a:a -> n:b -> {v:a | v == 0 <=> a == 0 } +(GHC.Real.^) :: (GHC.Num.Num a, GHC.Real.Integral b) => x:a -> y:{n:b | n >= 0} -> {z:a | (y == 0 => z == 1) && ((x == 0 && y /= 0) <=> z == 0)} GHC.Real.fromIntegral :: (GHC.Real.Integral a, GHC.Num.Num b) => x:a -> {v:b|v=x} diff --git a/liquid-bytestring/liquid-bytestring.cabal b/liquid-bytestring/liquid-bytestring.cabal index 94400d4dd4..b63ec39a8c 100644 --- a/liquid-bytestring/liquid-bytestring.cabal +++ b/liquid-bytestring/liquid-bytestring.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: liquid-bytestring -version: 0.10.10.0 +version: 0.11.3.1 synopsis: LiquidHaskell specs for the bytestring package description: LiquidHaskell specs for the bytestring package. license: BSD3 @@ -20,7 +20,7 @@ data-files: src/Data/ByteString.spec src/Data/ByteString/Lazy/Char8.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Data.ByteString @@ -38,9 +38,6 @@ library Data.ByteString.Builder.Internal Data.ByteString.Builder.Prim.Internal - Data.ByteString.Lazy.Builder - Data.ByteString.Lazy.Builder.Extras - Data.ByteString.Lazy.Builder.ASCII -- FIXME: This is commented out as unfortunately it doesn't refine -- correctly with modern versions of bytestring. @@ -48,10 +45,9 @@ library hs-source-dirs: src build-depends: liquid-base < 5 - , bytestring >= 0.10.10.0 && < 0.11 - , liquidhaskell >= 0.8.10.1 + , bytestring >= 0.11 && < 0.12 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports if impl(ghc >= 8.10) ghc-options: -fplugin=LiquidHaskell - \ No newline at end of file diff --git a/liquid-bytestring/src/Data/ByteString.spec b/liquid-bytestring/src/Data/ByteString.spec index 89cc03fbec..e13a85dc0e 100644 --- a/liquid-bytestring/src/Data/ByteString.spec +++ b/liquid-bytestring/src/Data/ByteString.spec @@ -291,7 +291,7 @@ filter -> { o : Data.ByteString.ByteString | bslen o <= bslen i } partition - :: (_ -> GHC.Types.Bool) + :: (Word8 -> GHC.Types.Bool) -> i : Data.ByteString.ByteString -> ( { l : Data.ByteString.ByteString | bslen l <= bslen i } , { r : Data.ByteString.ByteString | bslen r <= bslen i } diff --git a/liquid-bytestring/src/Data/ByteString/Char8.hs b/liquid-bytestring/src/Data/ByteString/Char8.hs index 121247fb45..3dbfc5ccd3 100644 --- a/liquid-bytestring/src/Data/ByteString/Char8.hs +++ b/liquid-bytestring/src/Data/ByteString/Char8.hs @@ -6,7 +6,7 @@ import Data.Int import GHC.IO.Handle -#ifdef MIN_VERSION_GLASGOW_HASKELL +#ifdef MIN_VERSION_bytestring #if MIN_VERSION_bytestring(0,10,12) -- bytestring >= 0.10.12.0 is now exporting 'partition' as part of 'Data.ByteString.Char8', which means diff --git a/liquid-bytestring/src/Data/ByteString/Lazy/Builder.hs b/liquid-bytestring/src/Data/ByteString/Lazy/Builder.hs deleted file mode 100644 index 451e224a33..0000000000 --- a/liquid-bytestring/src/Data/ByteString/Lazy/Builder.hs +++ /dev/null @@ -1,3 +0,0 @@ -module Data.ByteString.Lazy.Builder (module Exports) where - -import "bytestring" Data.ByteString.Lazy.Builder as Exports diff --git a/liquid-bytestring/src/Data/ByteString/Lazy/Builder/ASCII.hs b/liquid-bytestring/src/Data/ByteString/Lazy/Builder/ASCII.hs deleted file mode 100644 index ed271554e9..0000000000 --- a/liquid-bytestring/src/Data/ByteString/Lazy/Builder/ASCII.hs +++ /dev/null @@ -1,3 +0,0 @@ -module Data.ByteString.Lazy.Builder.ASCII (module Exports) where - -import "bytestring" Data.ByteString.Lazy.Builder.ASCII as Exports diff --git a/liquid-bytestring/src/Data/ByteString/Lazy/Builder/Extras.hs b/liquid-bytestring/src/Data/ByteString/Lazy/Builder/Extras.hs deleted file mode 100644 index 71b47ea203..0000000000 --- a/liquid-bytestring/src/Data/ByteString/Lazy/Builder/Extras.hs +++ /dev/null @@ -1,3 +0,0 @@ -module Data.ByteString.Lazy.Builder.Extras (module Exports) where - -import "bytestring" Data.ByteString.Lazy.Builder.Extras as Exports diff --git a/liquid-containers/liquid-containers.cabal b/liquid-containers/liquid-containers.cabal index a7f6da4c32..785d2d89ae 100644 --- a/liquid-containers/liquid-containers.cabal +++ b/liquid-containers/liquid-containers.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: liquid-containers -version: 0.6.2.1 +version: 0.6.4.1 synopsis: LiquidHaskell specs for the containers package description: LiquidHaskell specs for the containers package. license: BSD3 @@ -15,7 +15,7 @@ build-type: Custom data-files: src/Data/Set.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Data.Containers.ListUtils @@ -49,8 +49,8 @@ library Utils.Containers.Internal.StrictPair hs-source-dirs: src build-depends: liquid-base < 5 - , containers >= 0.6.2.1 && < 0.7 - , liquidhaskell >= 0.8.10.1 + , containers >= 0.6.4.1 && < 0.7 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports if impl(ghc >= 8.10) diff --git a/liquid-fixpoint b/liquid-fixpoint index e378d2ee86..0d08484369 160000 --- a/liquid-fixpoint +++ b/liquid-fixpoint @@ -1 +1 @@ -Subproject commit e378d2ee8656da929e41c2d593a88a81e9620391 +Subproject commit 0d08484369589bc92b9f3817c1a7e415ebe66431 diff --git a/liquid-ghc-prim/liquid-ghc-prim.cabal b/liquid-ghc-prim/liquid-ghc-prim.cabal index fe6db2cbfe..75783aeff3 100644 --- a/liquid-ghc-prim/liquid-ghc-prim.cabal +++ b/liquid-ghc-prim/liquid-ghc-prim.cabal @@ -1,6 +1,6 @@ -cabal-version: 1.24 +cabal-version: 2.0 name: liquid-ghc-prim -version: 0.6.1 +version: 0.7.0.1 synopsis: Drop-in ghc-prim replacement for LiquidHaskell description: Drop-in ghc-prim replacement for LiquidHaskell. license: BSD3 @@ -16,7 +16,7 @@ data-files: src/GHC/*.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: @@ -28,20 +28,19 @@ library GHC.CString GHC.Classes GHC.Debug - GHC.IntWord64 GHC.Magic + GHC.Prim.Exception GHC.Prim.Ext - GHC.PrimopWrappers + GHC.Prim.Panic GHC.Tuple GHC.Types hs-source-dirs: src - build-depends: ghc-prim == 0.6.1 - , liquidhaskell >= 0.8.10.1 + build-depends: ghc-prim ^>= 0.8 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports NoImplicitPrelude MagicHash if impl(ghc >= 8.10) ghc-options: -fplugin=LiquidHaskell - \ No newline at end of file diff --git a/liquid-ghc-prim/src/GHC/IntWord64.hs b/liquid-ghc-prim/src/GHC/IntWord64.hs deleted file mode 100644 index 2084efbedc..0000000000 --- a/liquid-ghc-prim/src/GHC/IntWord64.hs +++ /dev/null @@ -1,3 +0,0 @@ -module GHC.IntWord64 (module Exports) where - -import "ghc-prim" GHC.IntWord64 as Exports diff --git a/liquid-ghc-prim/src/GHC/Prim/Exception.hs b/liquid-ghc-prim/src/GHC/Prim/Exception.hs new file mode 100644 index 0000000000..a4be753435 --- /dev/null +++ b/liquid-ghc-prim/src/GHC/Prim/Exception.hs @@ -0,0 +1,3 @@ +module GHC.Prim.Exception (module Exports) where + +import "ghc-prim" GHC.Prim.Exception as Exports diff --git a/liquid-ghc-prim/src/GHC/Prim/Panic.hs b/liquid-ghc-prim/src/GHC/Prim/Panic.hs new file mode 100644 index 0000000000..082676cb35 --- /dev/null +++ b/liquid-ghc-prim/src/GHC/Prim/Panic.hs @@ -0,0 +1,3 @@ +module GHC.Prim.Panic (module Exports) where + +import "ghc-prim" GHC.Prim.Panic as Exports diff --git a/liquid-ghc-prim/src/GHC/PrimopWrappers.hs b/liquid-ghc-prim/src/GHC/PrimopWrappers.hs deleted file mode 100644 index 86e0664bf7..0000000000 --- a/liquid-ghc-prim/src/GHC/PrimopWrappers.hs +++ /dev/null @@ -1,3 +0,0 @@ -module GHC.PrimopWrappers (module Exports) where - -import "ghc-prim" GHC.PrimopWrappers as Exports diff --git a/liquid-ghc-prim/src/GHC/Types.hs b/liquid-ghc-prim/src/GHC/Types.hs index ef2787f7e9..8ddd44ce81 100644 --- a/liquid-ghc-prim/src/GHC/Types.hs +++ b/liquid-ghc-prim/src/GHC/Types.hs @@ -1,10 +1,3 @@ module GHC.Types (module Exports) where import "ghc-prim" GHC.Types as Exports - -{-@ embed GHC.Prim.Int# as int @-} -{-@ embed GHC.Prim.Addr# as Str @-} -{-@ embed GHC.Prim.Char# as Char @-} -{-@ embed GHC.Prim.Double# as real @-} -{-@ embed GHC.Prim.Float# as real @-} -{-@ embed GHC.Prim.Word# as int @-} diff --git a/liquid-ghc-prim/src/GHC/Types.spec b/liquid-ghc-prim/src/GHC/Types.spec index 8cdd28bad9..e8dde2f98d 100644 --- a/liquid-ghc-prim/src/GHC/Types.spec +++ b/liquid-ghc-prim/src/GHC/Types.spec @@ -2,11 +2,17 @@ module spec GHC.Types where // Boxed types embed GHC.Types.Double as real +embed GHC.Prim.Double# as real embed GHC.Types.Float as real +embed GHC.Prim.Float# as real embed GHC.Types.Word as int +embed GHC.Prim.Word# as int embed GHC.Types.Int as int +embed GHC.Prim.Int# as int embed GHC.Types.Bool as bool embed GHC.Types.Char as Char +embed GHC.Prim.Char# as Char +embed GHC.Prim.Addr# as Str embed GHC.Integer.Type.Integer as int embed GHC.Num.Integer as int diff --git a/liquid-parallel/liquid-parallel.cabal b/liquid-parallel/liquid-parallel.cabal index d14ca60cd3..778c6175fd 100644 --- a/liquid-parallel/liquid-parallel.cabal +++ b/liquid-parallel/liquid-parallel.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: liquid-parallel -version: 3.2.2.0 +version: 3.2.2.0.1 synopsis: LiquidHaskell specs for the parallel package description: LiquidHaskell specs for the parallel package. license: BSD3 @@ -15,7 +15,7 @@ build-type: Custom data-files: src/Control/Parallel/Strategies.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Control.Seq @@ -23,10 +23,9 @@ library Control.Parallel.Strategies hs-source-dirs: src build-depends: liquid-base < 4.16 - , parallel >= 3.2.0.0 && < 3.3 - , liquidhaskell >= 0.8.10.1 + , parallel >= 3.2.2.0 && < 3.3 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports if impl(ghc >= 8.10) ghc-options: -fplugin=LiquidHaskell - \ No newline at end of file diff --git a/liquid-platform/liquid-platform.cabal b/liquid-platform/liquid-platform.cabal index 214facca6b..16b427dc2c 100644 --- a/liquid-platform/liquid-platform.cabal +++ b/liquid-platform/liquid-platform.cabal @@ -1,6 +1,6 @@ cabal-version: 1.22 name: liquid-platform -version: 0.8.10.2 +version: 0.9.0.2 synopsis: A battery-included platform for LiquidHaskell description: A battery-included platform for LiquidHaskell. license: BSD3 @@ -25,38 +25,37 @@ executable liquidhaskell buildable: False else buildable: True - build-depends: liquid-base >= 4.14.1.0 && < 5 - , liquid-containers >= 0.6.2.1 && < 0.7 - , liquid-prelude >= 0.8.10.2 - , liquid-vector >= 0.12.1.2 && < 0.13 - , liquid-bytestring >= 0.10.0.0 && < 0.11 - , liquidhaskell >= 0.8.10.2 + build-depends: liquid-base >= 4.15.1.0 && < 5 + , liquid-containers >= 0.6.4.1 && < 0.7 + , liquid-prelude >= 0.9.0.2 + , liquid-vector >= 0.12.3.1 && < 0.13 + , liquid-bytestring >= 0.11.3.1 && < 0.12 + , liquidhaskell >= 0.9.0.2 , filepath , process >= 1.6.0.0 && < 1.7 , cmdargs >= 0.10 && < 0.11 if flag(devel) ghc-options: -Werror - + executable gradual main-is: src/Gradual.hs - build-depends: base >= 4.8.1.0 && < 5 + build-depends: base >= 4.15.1.0 && < 5 , cmdargs , hscolour - , liquid-fixpoint >= 0.7.0.5 - , liquidhaskell >= 0.8.10.1 + , liquid-fixpoint >= 0.9.0.2 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 buildable: False ghc-options: -W -threaded if flag(devel) ghc-options: -Werror - + executable target main-is: src/Target.hs build-depends: base >= 4.8.1.0 && < 5, hint, liquidhaskell >= 0.8.10.2 default-language: Haskell2010 buildable: False - diff --git a/liquid-prelude/liquid-prelude.cabal b/liquid-prelude/liquid-prelude.cabal index f4e9a130d5..0e5c36ed4b 100644 --- a/liquid-prelude/liquid-prelude.cabal +++ b/liquid-prelude/liquid-prelude.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: liquid-prelude -version: 0.8.10.2 +version: 0.9.0.2 synopsis: General utility modules for LiquidHaskell description: General utility modules for LiquidHaskell. license: BSD3 @@ -13,7 +13,7 @@ homepage: https://github.com/ucsd-progsys/liquidhaskell build-type: Custom custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Language.Haskell.Liquid.RTick @@ -25,14 +25,13 @@ library Language.Haskell.Liquid.Equational Language.Haskell.Liquid.Bag Language.Haskell.Liquid.ProofCombinators - Language.Haskell.Liquid.Synthesize.Error KMeansHelper hs-source-dirs: src build-depends: liquid-base < 5 - , bytestring >= 0.10.0.0 && < 0.11 - , containers >= 0.6.0.0 && < 0.7 - , liquidhaskell >= 0.8.10.2 + , liquid-ghc-prim + , bytestring >= 0.10.12.1 && < 0.12 + , containers >= 0.6.4.1 && < 0.7 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 if impl(ghc >= 8.10) ghc-options: -fplugin=LiquidHaskell - diff --git a/liquid-prelude/src/Language/Haskell/Liquid/Bag.hs b/liquid-prelude/src/Language/Haskell/Liquid/Bag.hs index 93f2da5197..5d7aa53a21 100644 --- a/liquid-prelude/src/Language/Haskell/Liquid/Bag.hs +++ b/liquid-prelude/src/Language/Haskell/Liquid/Bag.hs @@ -44,7 +44,7 @@ put k m = M.insert k (1 + get k m) m union :: (Ord k) => Bag k -> Bag k -> Bag k union m1 m2 = M.union m1 m2 -{-@ thm_emp :: x:k -> xs:Bag k -> { Language.Haskell.Liquid.Bag.empty /= put x xs } @-} +{-@ thm_emp :: x:k -> xs:Bag k -> { Map_select xs x >= 0 => Language.Haskell.Liquid.Bag.empty /= put x xs } @-} thm_emp :: (Ord k) => k -> Bag k -> () thm_emp x xs = const () (get x xs) diff --git a/liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs b/liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs index 7a4be44aaf..0a839374f9 100644 --- a/liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs +++ b/liquid-prelude/src/Language/Haskell/Liquid/Prelude.hs @@ -2,6 +2,8 @@ module Language.Haskell.Liquid.Prelude where +import GHC.Types() -- import specs + ------------------------------------------------------------------- --------------------------- Arithmetic ---------------------------- ------------------------------------------------------------------- diff --git a/liquid-prelude/src/Language/Haskell/Liquid/Synthesize/Error.hs b/liquid-prelude/src/Language/Haskell/Liquid/Synthesize/Error.hs deleted file mode 100644 index 41af9bf08d..0000000000 --- a/liquid-prelude/src/Language/Haskell/Liquid/Synthesize/Error.hs +++ /dev/null @@ -1,5 +0,0 @@ -module Language.Haskell.Liquid.Synthesize.Error where - -{-@ err :: { v: Int | false } -> a @-} -err :: Int -> a -err s = undefined \ No newline at end of file diff --git a/liquid-vector/liquid-vector.cabal b/liquid-vector/liquid-vector.cabal index d64d7c5a28..249b584060 100644 --- a/liquid-vector/liquid-vector.cabal +++ b/liquid-vector/liquid-vector.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: liquid-vector -version: 0.12.1.2 +version: 0.12.3.1 synopsis: LiquidHaskell specs for the vector package description: LiquidHaskell specs for the vector package. license: BSD3 @@ -15,7 +15,7 @@ build-type: Custom data-files: src/Data/Vector.spec custom-setup - setup-depends: Cabal, base, liquidhaskell + setup-depends: Cabal<4, base<5, liquidhaskell library exposed-modules: Data.Vector.Internal.Check @@ -46,8 +46,8 @@ library Data.Vector hs-source-dirs: src build-depends: liquid-base < 4.16 - , vector >= 0.12.1.2 && < 0.13 - , liquidhaskell >= 0.8.10.1 + , vector >= 0.12.3.1 && < 0.13 + , liquidhaskell >= 0.9.0.2 default-language: Haskell2010 default-extensions: PackageImports if impl(ghc >= 8.10) diff --git a/liquidhaskell.cabal b/liquidhaskell.cabal index bae66745d6..0008374495 100644 --- a/liquidhaskell.cabal +++ b/liquidhaskell.cabal @@ -1,6 +1,6 @@ cabal-version: 2.4 name: liquidhaskell -version: 0.8.10.7.1 +version: 0.9.2.5.0 synopsis: Liquid Types for Haskell description: Liquid Types for Haskell. license: BSD-3-Clause @@ -11,51 +11,11 @@ maintainer: Ranjit Jhala category: Language homepage: https://github.com/ucsd-progsys/liquidhaskell build-type: Simple -tested-with: GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.1, GHC == 8.10.7, GHC == 9.0.1 +tested-with: GHC == 9.2.5 extra-source-files: CHANGES.md README.md - devel/Paths_liquidhaskell.hs - tests/pos/*.hs - tests/neg/*.hs - tests/import/lib/*.hs - tests/import/client/*.hs - tests/errors/*.hs - tests/pos/*.hquals - tests/ffi-include/foo.c - tests/ffi-include/foo.h - --- The legacy executable requires a set of hardcoded specifications --- provided by the files in the 'include' directory. This --- directory is now deprecated and you should never edit it, unless you --- are specifically fixing a bug in the legacy executable. --- Remove these lines below once we stop supporting the legacy plugin. -data-files: include/*.hquals - include/*.hs - include/*.spec - include/CoreToLogic.lg - include/Control/*.spec - include/Control/Parallel/*.spec - include/Data/*.hquals - include/Data/*.spec - include/Data/Text/*.spec - include/Data/Text/Fusion/*.spec - include/Data/Text/Lazy/*.spec - include/Data/ByteString/*.spec - include/Foreign/*.spec - include/Foreign/C/*.spec - include/Foreign/Marshal/*.spec - include/GHC/*.hquals - include/GHC/*.spec - include/GHC/IO/*.spec - include/Language/Haskell/Liquid/*.hs - include/Language/Haskell/Liquid/Synthesize/*.hs - include/Language/Haskell/Liquid/*.pred - include/System/*.spec - include/710/Data/*.spec - include/*.hs - include/Language/Haskell/Liquid/*.hs - include/Language/Haskell/Liquid/*.pred +data-files: include/CoreToLogic.lg syntax/liquid.css -- Needed for the mirror-modules helper @@ -67,23 +27,15 @@ source-repository head flag devel default: False + manual: True description: Enable more warnings and fail compilation when warnings occur. Turn this flag on in CI. -flag include - default: False - description: use in-tree include directory - flag deterministic-profiling default: False description: Support building against GHC with backported -flag no-plugin - default: False - manual: True - description: Use the legacy executable for testing. - flag mirror-modules-helper default: False manual: True @@ -130,6 +82,8 @@ library Liquid.GHC.SpanStack Liquid.GHC.Types Liquid.GHC.TypeRep + Language.Haskell.Liquid.GHC.Plugin + Language.Haskell.Liquid.GHC.Plugin.Tutorial Language.Haskell.Liquid.Interactive.Handler Language.Haskell.Liquid.Interactive.Types Language.Haskell.Liquid.LawInstances @@ -137,13 +91,6 @@ library Language.Haskell.Liquid.Measure Language.Haskell.Liquid.Misc Language.Haskell.Liquid.Parse - Language.Haskell.Liquid.Synthesize.GHC - Language.Haskell.Liquid.Synthesize.Termination - Language.Haskell.Liquid.Synthesize.Monad - Language.Haskell.Liquid.Synthesize.Misc - Language.Haskell.Liquid.Synthesize.Generate - Language.Haskell.Liquid.Synthesize.Check - Language.Haskell.Liquid.Synthesize.Env Language.Haskell.Liquid.Termination.Structural Language.Haskell.Liquid.Transforms.ANF Language.Haskell.Liquid.Transforms.CoreToLogic @@ -169,7 +116,6 @@ library Language.Haskell.Liquid.Types.Types Language.Haskell.Liquid.Types.Variance Language.Haskell.Liquid.Types.Visitors - Language.Haskell.Liquid.Synthesize Language.Haskell.Liquid.UX.ACSS Language.Haskell.Liquid.UX.Annotate Language.Haskell.Liquid.UX.CTags @@ -183,39 +129,18 @@ library Language.Haskell.Liquid.WiredIn LiquidHaskell Paths_liquidhaskell - - -- FIXME: Temporary measure to ensure that if the source plugin is available, then: - -- 1. we compile it; - -- 2. We don't rely on the \"liquid-prelude\" Haskell files previously shipped as part of LH itself. - -- Once the source plugin is out, we should also removed the duplicate \"liquid-prelude\" files from - -- the \"include\" directory. - - if impl(ghc >= 8.10) - exposed-modules: Language.Haskell.Liquid.GHC.Plugin - Language.Haskell.Liquid.GHC.Plugin.Tutorial - other-modules: Language.Haskell.Liquid.GHC.Plugin.SpecFinder - Language.Haskell.Liquid.GHC.Plugin.Types - Language.Haskell.Liquid.GHC.Plugin.Util - hs-source-dirs: src src-ghc - else - hs-source-dirs: src src-ghc include - exposed-modules: Language.Haskell.Liquid.RTick - Language.Haskell.Liquid.Prelude - Language.Haskell.Liquid.Foreign - Language.Haskell.Liquid.RTick.Combinators - Language.Haskell.Liquid.String - Language.Haskell.Liquid.List - Language.Haskell.Liquid.Equational - Language.Haskell.Liquid.Bag - Language.Haskell.Liquid.ProofCombinators - KMeansHelper + other-modules: Language.Haskell.Liquid.GHC.Plugin.SpecFinder + Language.Haskell.Liquid.GHC.Plugin.Types + Language.Haskell.Liquid.GHC.Plugin.Util + Language.Haskell.Liquid.Synthesize.GHC + hs-source-dirs: src src-ghc build-depends: base >= 4.11.1.0 && < 5 , Diff >= 0.3 && < 0.5 , aeson , binary , bytestring >= 0.10 - , Cabal < 3.5 + , Cabal < 3.7 , cereal , cmdargs >= 0.10 , containers >= 0.5 @@ -225,17 +150,18 @@ library , filepath >= 1.3 , fingertree >= 0.1 , exceptions < 0.11 - , ghc + , ghc ^>= 9.2 , ghc-boot , ghc-paths >= 0.1 , ghc-prim , gitrev , hashable >= 1.3 && < 1.4 , hscolour >= 1.22 - , liquid-fixpoint >= 0.8.10.2.1 && < 0.9 + , liquid-fixpoint == 0.9.0.2.1 , mtl >= 2.1 , optics >= 0.2 - , optparse-applicative < 0.17 + , optparse-applicative < 0.18 + , ormolu , githash , megaparsec >= 8 , pretty >= 1.1 @@ -255,31 +181,14 @@ library , extra default-language: Haskell98 default-extensions: PatternGuards, RecordWildCards, DoAndIfThenElse - ghc-options: -W -fwarn-missing-signatures -j + ghc-options: -W -fwarn-missing-signatures if flag(devel) ghc-options: -Wall -Werror - if flag(include) - hs-source-dirs: devel - if flag(deterministic-profiling) cpp-options: -DDETERMINISTIC_PROFILING - if impl(ghc < 8.10) || flag(no-plugin) - cpp-options: -DLIQUID_NO_PLUGIN - --- This is the (legacy) 'liquid' executable which uses the old GHC Interface. -executable liquid - main-is: exe/Liquid.hs - build-depends: base >= 4.9.1.0 && < 5, liquidhaskell - default-language: Haskell98 - default-extensions: PatternGuards - ghc-options: -W -threaded - - if flag(devel) - ghc-options: -Wall -Wno-name-shadowing -Werror - test-suite liquidhaskell-parser type: exitcode-stdio-1.0 main-is: Parser.hs @@ -288,7 +197,7 @@ test-suite liquidhaskell-parser build-depends: base >= 4.8.1.0 && < 5 , directory >= 1.2.5 && < 1.4 , filepath - , liquid-fixpoint >= 0.8.10.1 + , liquid-fixpoint , liquidhaskell , megaparsec , syb @@ -301,28 +210,6 @@ test-suite liquidhaskell-parser if flag(devel) ghc-options: -Wall -Wno-name-shadowing -Werror -test-suite synthesis - type: exitcode-stdio-1.0 - main-is: Synthesis.hs - other-modules: Paths_liquidhaskell - hs-source-dirs: tests - build-depends: base >= 4.8.1.0 && < 5 - , liquid-fixpoint >= 0.8.10.1 - , liquidhaskell - , tasty >= 0.7 - , tasty-hunit - , process - , filepath - , text - , directory - , ghc - , extra - default-language: Haskell2010 - ghc-options: -W - - if flag(devel) - ghc-options: -Wall -Wno-name-shadowing -Werror - -- This executable can be used to generate modules for mirror-packages. executable mirror-modules main-is: Main.hs diff --git a/nixpkgs.nix b/nixpkgs.nix new file mode 100644 index 0000000000..c5f229f06d --- /dev/null +++ b/nixpkgs.nix @@ -0,0 +1,9 @@ +let + # NixOS/Nixpkgs master 2022-11-27 + rev = "a115bb9bd56831941be3776c8a94005867f316a7"; + sha256 = "1501jzl4661qwr45b9ip7c7bpmbl94816draybhh60s9wgxn068d"; +in +import (fetchTarball { + inherit sha256; + url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; +}) diff --git a/scripts/CountBinders.hs b/scripts/CountBinders.hs deleted file mode 100755 index 3bc7292e12..0000000000 --- a/scripts/CountBinders.hs +++ /dev/null @@ -1,93 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE TypeSynonymInstances #-} -module Main where - - -import Control.Applicative -import Data.Function -import Data.Generics -import Data.List -import System.Environment -import Text.Printf - -import CoreMonad -import CoreSyn -import DynFlags -import GHC -import GHC.Paths -import HscTypes -import qualified Outputable as Out -import Type -import Var - -import Language.Haskell.Liquid.GhcMisc -import Language.Haskell.Liquid.Misc - -getCoreBinds :: FilePath -> IO [CoreBind] -getCoreBinds target = runGhc (Just libdir) $ do - addTarget =<< guessTarget target Nothing - flags <- getSessionDynFlags - inc <- liftIO getIncludeDir - setSessionDynFlags $ updateDynFlags flags [inc] - load LoadAllTargets - modGraph <- getModuleGraph - case find ((== target) . msHsFilePath) modGraph of - Just modSummary -> do - mod_guts <- coreModule <$> (desugarModule =<< typecheckModule =<< parseModule modSummary) - return $! mg_binds mod_guts - Nothing -> error "Ghc Interface: Unable to get GhcModGuts" - - -updateDynFlags :: DynFlags -> [FilePath] -> DynFlags -updateDynFlags df ps - = df { importPaths = ps ++ importPaths df - , libraryPaths = ps ++ libraryPaths df - , profAuto = ProfAutoCalls - , ghcLink = NoLink - , hscTarget = HscInterpreted - , ghcMode = CompManager - } `xopt_set` Opt_MagicHash - `dopt_set` Opt_ImplicitImportQualified - - -allBinders :: [CoreBind] -> [CoreBind] -allBinders cbs = cbs ++ map bind (concatMap (listify isBinder) cbs) - where - bind (Let x _) = x - isBinder (Let _ _) = True - isBinder _ = False - - -recsAndFuns :: [CoreBind] -> ([Var],[Var],[Var]) -recsAndFuns binds = (recs,recfuns,funs) - where - recs = [v | Rec bs <- binds, (v,_) <- bs] - recfuns = filter isFun recs - -- GHC does transforms recursive functions (at least with tyvars) - -- into a let binding that quantifies over the tyvar followed by a - -- letrec that defines the function, e.g. - -- let foo = \ @a -> { letrec foo = ... in foo } - -- but we don't want to count foo as rec and nonrec - funs = nubBy ((==) `on` getOccName) - $ [v | NonRec v _ <- binds, isFun v] - ++ recfuns - isFun = isFunTy . snd . splitForAllTys . varType - - -main :: IO () -main = do - target <- head <$> getArgs - binds <- allBinders <$> getCoreBinds target - - let (recs,recfuns,funs) = recsAndFuns binds - - printf "funs: %d\n" (length funs) - printf "recs: %d\n" (length recs) - printf "recsFuns: %d\n" (length recfuns) - - -instance Show CoreBind where - show = showPpr - -instance Show (Expr CoreBndr) where - show = showPpr diff --git a/scripts/ProfilingDriver.hs b/scripts/ProfilingDriver.hs new file mode 100644 index 0000000000..557d95a96d --- /dev/null +++ b/scripts/ProfilingDriver.hs @@ -0,0 +1,40 @@ +-- | This program calls ghc using the provided command line arguments. +-- Use it to profile the liquidhaskell plugin. +-- +-- Build liquid-platform first with profiling enabled. +-- +-- > cabal build --enable-profiling liquid-platform +-- +-- Then build this program. +-- +-- > cabal exec --enable-profiling -- ghc -prof scripts/ProfilingDriver.hs +-- +-- Then run the liquidhaskell executable pointing it to this driver with +-- the LIQUID_GHC_PATH env var. +-- +-- > LIQUID_GHC_PATH=scripts/ProfilingDriver liquidhaskell_datadir=$PWD \ +-- > cabal exec -- liquidhaskell +RTS -p -RTS tests/pos/Bag.hs +-- +module Main where + +import GHC as G +import GHC.Driver.Session as G + +import Control.Monad +import Control.Monad.IO.Class +import System.Environment +import GHC.Paths (libdir) +import GHC.Utils.Logger as G + +main :: IO () +main = do + xs <- getArgs + runGhc (Just libdir) $ do + df1 <- getSessionDynFlags + let cmdOpts = ["-fforce-recomp"] ++ filter ("--make" /=) xs + logger <- liftIO G.initLogger + (df2, leftovers, warns) <- G.parseDynamicFlags logger df1 (map G.noLoc cmdOpts) + setSessionDynFlags df2 + ts <- mapM (flip G.guessTarget Nothing) $ map unLoc leftovers + setTargets ts + void $ G.load LoadAllTargets diff --git a/scripts/plot-performance/README.md b/scripts/plot-performance/README.md index 5356ae8743..b2967190c9 100644 --- a/scripts/plot-performance/README.md +++ b/scripts/plot-performance/README.md @@ -5,27 +5,4 @@ produced by LH's testuite. It will produce something like this: ![perf-min](https://user-images.githubusercontent.com/442035/78143687-e3f4a480-742e-11ea-9a47-6b1800914a15.png) -### Usage - -In order to measure, say, regression between two LH branches, it's first necessary to acquire two `.csv` -files to compare. For example, suppose you want to measure the performance changes between `develop` and -a `new-feature` branch. The easiest way is to do something like this: - -``` -git checkout develop -stack build -stack test -j1 liquidhaskell:test --flag liquidhaskell:include --flag liquidhaskell:devel --test-arguments="-p Micro" -git checkout new-feature -stack build -stack test -j1 liquidhaskell:test --flag liquidhaskell:include --flag liquidhaskell:devel --test-arguments="-p Micro" -``` - -After doing so, inside `tests/logs` you will find a bunch of folders named after your hostname, with some -timestamps. At that point you can simply do: - -``` -./chart_perf.sh ../path/to/develop.csv ../path/to/new_feature.csv -``` - -The order is _chronological_, i.e. the first csv should be the "before" and the second the "after". After -you do that, you should hopefully have a `perf.png` image on your filesystem to inspect. +See the main [README](../../README.md#how-to-create-performance-comparison-charts) for usage information. diff --git a/scripts/test/test_901_plugin.sh b/scripts/test/test_901_plugin.sh deleted file mode 100755 index 8dd029ccb8..0000000000 --- a/scripts/test/test_901_plugin.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -TEST_GROUPS="$@" - -LIQUID_CABAL_PROJECT_FILE=cabal.ghc9.project liquidhaskell_datadir=$PWD cabal v2-run --project-file cabal.ghc9.project tests:test-driver -- "$TEST_GROUPS" diff --git a/scripts/test/test_810_plugin.sh b/scripts/test/test_plugin.sh similarity index 100% rename from scripts/test/test_810_plugin.sh rename to scripts/test/test_plugin.sh diff --git a/src-ghc/Liquid/GHC/API.hs b/src-ghc/Liquid/GHC/API.hs index 98c20a5791..ce19399bcf 100644 --- a/src-ghc/Liquid/GHC/API.hs +++ b/src-ghc/Liquid/GHC/API.hs @@ -5,7 +5,6 @@ The intended use of this module is to shelter LiquidHaskell from changes to the --} -{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-} @@ -18,102 +17,16 @@ The intended use of this module is to shelter LiquidHaskell from changes to the module Liquid.GHC.API ( module Ghc , module StableModule - --- Specific exports for 8.6.5 -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) - , pattern Bndr - , pattern LitString - , pattern LitFloat - , pattern LitDouble - , pattern LitChar - , VarBndr -#endif -#endif - --- Specific exports for 8.6.5 and 8.8.x -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - , AnonArgFlag(..) - , pattern FunTy - , pattern AnonTCB - , ft_af, ft_mult, ft_arg, ft_res - , bytesFS - , mkFunTy - , isEvVarType - , isEqPrimPred - , noExtField - , Mult - , pattern Many -#endif -#endif - , tyConRealArity , dataConExTyVars - --- Specific exports for 8.8.x -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - , isEqPred -#endif -#endif - --- Specific exports for 8.10.x -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) && !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - , Mult - , pattern Many - , pattern FunTy - , mkFunTy - , ft_af, ft_mult, ft_arg, ft_res -#endif -#endif - --- Shared exports for GHC < 9 -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - , pattern RealSrcSpan - , pattern UnhelpfulSpan - , UnhelpfulSpanReason(..) - , scaledThing - , Scaled(..) - , mkScaled - , irrelevantMult - , dataConInstArgTys - , dataConOrigArgTys - , dataConRepArgTys - , mkLocalVar - , DataConAppContext(..) - , deepSplitProductType_maybe - , splitFunTys - , mkUserLocal - , dataConWrapperType - , apiAnnComments - , getDependenciesModuleNames - , GenWithIsBoot(..) - , ModuleNameWithIsBoot - , IsBootInterface - , isBootSummary - , mkIntExprInt - , dataConFullSig -#endif -#endif - --- Specific exports for 9.x -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) , fsToUnitId , moduleUnitId , thisPackage , renderWithStyle - , mkUserStyle , pattern LitNumber , dataConSig , getDependenciesModuleNames , gcatch -#endif -#endif - ) where import Liquid.GHC.API.StableModule as StableModule @@ -122,183 +35,6 @@ import GHC as Ghc hiding , exprType ) --- Shared imports for GHC < 9 -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - -import CoreFVs as Ghc (exprFreeVarsList) -import OccurAnal as Ghc (occurAnalysePgm) -import Annotations as Ghc -import ApiAnnotation as Ghc -import Avail as Ghc -import Bag as Ghc -import BasicTypes as Ghc -import Class as Ghc -import CoAxiom as Ghc -import Coercion as Ghc -import ConLike as Ghc -import CoreLint as Ghc hiding (dumpIfSet) -import CoreMonad as Ghc (CoreToDo(..)) -import CoreSubst as Ghc (deShadowBinds, substExpr, emptySubst, extendCvSubst) -import CoreSyn as Ghc hiding (AnnExpr, AnnExpr' (..), AnnRec, AnnCase) -import CoreUtils as Ghc (exprType) -import CostCentre as Ghc -import Data.Map.Strict (Map) -import DataCon as Ghc hiding (dataConInstArgTys, dataConOrigArgTys, dataConRepArgTys, dataConFullSig) -import qualified DataCon as Ghc -import Digraph as Ghc -import DriverPhases as Ghc (Phase(StopLn)) -import DriverPipeline as Ghc hiding (P, getLocation) -import DsMonad as Ghc -import DynFlags as Ghc -import ErrUtils as Ghc -import FamInst as Ghc -import FamInstEnv as Ghc hiding (pprFamInst) -import Finder as Ghc -import ForeignCall (CType) -import GHC as Ghc (SrcSpan) -import GhcMonad as Ghc (withSession) -import GhcPlugins as Ghc (deserializeWithData , fromSerialized , toSerialized, extendIdSubst) -import HscMain as Ghc -import HscTypes as Ghc hiding (IsBootInterface, isBootSummary) -import Id as Ghc hiding (lazySetIdInfo, setIdExported, setIdNotExported, mkUserLocal) -import IdInfo as Ghc -import IfaceSyn as Ghc -import InstEnv as Ghc -import Literal as Ghc -import MkCore as Ghc hiding (mkIntExprInt) -import MkId (mkDataConWorkId) -import Module as Ghc -import Name as Ghc hiding (varName) -import NameEnv (lookupNameEnv_NF) -import NameSet as Ghc -import Outputable as Ghc hiding ((<>)) -import Pair as Ghc -import Panic as Ghc -import Plugins as Ghc (defaultPlugin, Plugin(..), CommandLineOption, purePlugin) -import PrelInfo as Ghc -import PrelNames as Ghc hiding (wildCardName) -import RdrName as Ghc -import SrcLoc as Ghc hiding (RealSrcSpan, SrcSpan(UnhelpfulSpan)) -import TcRnDriver as Ghc -import TcRnMonad as Ghc hiding (getGHCiMonad) -import TysPrim as Ghc -import TysWiredIn as Ghc -import Unify as Ghc -import UniqDFM as Ghc -import UniqFM as Ghc -import UniqSet as Ghc -import UniqSupply as Ghc -import Unique as Ghc -import Var as Ghc hiding (mkLocalVar) -import VarEnv as Ghc -import VarSet as Ghc -import qualified SrcLoc -import qualified Data.Bifunctor as Bi -import qualified Data.Data as Data -import qualified GhcMake -import qualified HscTypes as Ghc -import qualified Id as Ghc -import qualified MkCore as Ghc -import qualified Var as Ghc -import qualified WwLib as Ghc -import RnExpr as Ghc (rnLExpr) -import TcExpr as Ghc (tcInferSigma) -import TcBinds as Ghc (tcValBinds) -import Inst as Ghc (deeplyInstantiate) -import TcSimplify as Ghc ( simplifyInfer, simplifyInteractive - , InferMode (..)) -import TcHsSyn as Ghc (zonkTopLExpr) -import TcEvidence as Ghc ( TcEvBinds (EvBinds)) -import DsExpr as Ghc (dsLExpr) -#endif -#endif - --- --- Compatibility layer for different GHC versions. --- - --- --- Specific imports for GHC 8.6.5 --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) - -import qualified Literal as Lit -import FastString as Ghc hiding (bytesFS, LitString) -import TcType as Ghc hiding (typeKind, mkFunTy) -import Type as Ghc hiding (typeKind, mkFunTy, splitFunTys, extendCvSubst) -import qualified Type as Ghc -import qualified Var as Var -import qualified GHC.Real --- import PrelNames (eqPrimTyConKey, eqReprPrimTyConKey, gHC_REAL, varQual_RDR) -#endif -#endif - --- --- Specific imports for GHC 8.6.5 & 8.8.x --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - -import Binary -import Data.ByteString (ByteString) -import Data.Data (Data) -import Kind as Ghc -import TyCoRep as Ghc hiding (Type (FunTy), mkFunTy, extendCvSubst) -import TyCon as Ghc hiding (mkAnonTyConBinders, TyConBndrVis(AnonTCB)) -import qualified TyCoRep as Ty hiding (extendCvSubst) -import qualified TyCon as Ty -import Platform as Ghc -import qualified HsExtension --- import PrelNames (eqPrimTyConKey, eqReprPrimTyConKey, gHC_REAL, varQual_RDR) - -#endif -#endif - --- --- Specific imports for 8.8.x --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - -import FastString as Ghc hiding (bytesFS) -import TcType as Ghc hiding (typeKind, mkFunTy, isEqPred) -import Type as Ghc hiding (typeKind, mkFunTy, isEvVarType, isEqPred, splitFunTys, extendCvSubst) -import qualified Type as Ghc -import qualified Type as Ghc (isEvVarType) -import qualified PrelNames as Ghc -import Data.Foldable (asum) --- import PrelNames (eqPrimTyConKey, eqReprPrimTyConKey, gHC_REAL, varQual_RDR) -#endif -#endif - --- --- Specific imports for GHC 8.10 --- -#ifdef MIN_VERSION_GLASGOW_HASKELL - -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) && !MIN_VERSION_GLASGOW_HASKELL (9,0,0,0) -import GHC.Platform as Ghc (Platform) -import Type as Ghc hiding (mapType, typeKind, isPredTy, splitFunTys, extendCvSubst) -import qualified Type as Ghc hiding (extendCvSubst) -import TyCon as Ghc -import qualified TyCoRep as Ty -import TcType as Ghc -import TyCoRep as Ghc hiding (Type (FunTy), mkFunTy, ft_arg, ft_res, ft_af) -import FastString as Ghc -import Predicate as Ghc (getClassPredTys_maybe, isEvVarType, getClassPredTys, isDictId) -import TcOrigin as Ghc (lexprCtOrigin) -import Data.Foldable (asum) -#endif -#endif - --- --- Specific imports for GHC 9 --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) && !MIN_VERSION_GLASGOW_HASKELL (9,1,0,0) - import Optics import qualified Control.Monad.Catch as Ex @@ -308,7 +44,7 @@ import GHC.Builtin.Types as Ghc import GHC.Builtin.Types.Prim as Ghc import GHC.Builtin.Utils as Ghc import GHC.Core as Ghc hiding (AnnExpr, AnnExpr' (..), AnnRec, AnnCase) -import GHC.Core.Class as Ghc +import GHC.Core.Class as Ghc hiding (FunDep) import GHC.Core.Coercion as Ghc import GHC.Core.Coercion.Axiom as Ghc import GHC.Core.ConLike as Ghc @@ -319,7 +55,7 @@ import GHC.Core.Lint as Ghc hiding (dumpIfSet) import GHC.Core.Make as Ghc import GHC.Core.Opt.Monad as Ghc (CoreToDo(..)) import GHC.Core.Opt.WorkWrap.Utils as Ghc -import GHC.Core.Predicate as Ghc (getClassPredTys_maybe, getClassPredTys, isEvVarType, isEqPrimPred, isEqPred, isClassPred, isDictId) +import GHC.Core.Predicate as Ghc (getClassPredTys_maybe, getClassPredTys, isEvVarType, isEqPrimPred, isEqPred, isClassPred, isDictId, mkClassPred) import GHC.Core.Subst as Ghc (deShadowBinds, emptySubst, extendCvSubst) import GHC.Core.TyCo.Rep as Ghc import GHC.Core.TyCon as Ghc @@ -330,12 +66,10 @@ import GHC.Data.Bag as Ghc import GHC.Data.FastString as Ghc import GHC.Data.Graph.Directed as Ghc import GHC.Data.Pair as Ghc -import GHC.Driver.Finder as Ghc import GHC.Driver.Main as Ghc import GHC.Driver.Phases as Ghc (Phase(StopLn)) import GHC.Driver.Pipeline as Ghc (compileFile) -import GHC.Driver.Session as Ghc hiding (isHomeModule) -import GHC.Driver.Types as Ghc +import GHC.Driver.Session as Ghc import GHC.Driver.Monad as Ghc (withSession) import GHC.HsToCore.Monad as Ghc import GHC.Iface.Syntax as Ghc @@ -349,22 +83,44 @@ import GHC.Plugins as Ghc ( deserializeWithData , extendIdSubst , substExpr ) +import GHC.Core.FVs as Ghc (exprFreeVarsList) +import GHC.Core.Opt.OccurAnal as Ghc +import GHC.Driver.Env as Ghc +import GHC.Driver.Ppr as Ghc +import GHC.HsToCore.Expr as Ghc +import GHC.Iface.Load as Ghc +import GHC.Rename.Expr as Ghc (rnLExpr) +import GHC.Runtime.Context as Ghc +import GHC.Tc.Gen.App as Ghc (tcInferSigma) +import GHC.Tc.Gen.Bind as Ghc (tcValBinds) +import GHC.Tc.Gen.Expr as Ghc (tcInferRho) import GHC.Tc.Instance.Family as Ghc import GHC.Tc.Module as Ghc +import GHC.Tc.Solver as Ghc import GHC.Tc.Types as Ghc +import GHC.Tc.Types.Evidence as Ghc +import GHC.Tc.Types.Origin as Ghc (lexprCtOrigin) import GHC.Tc.Utils.Monad as Ghc hiding (getGHCiMonad) import GHC.Tc.Utils.TcType as Ghc (tcSplitDFunTy, tcSplitMethodTy) +import GHC.Tc.Utils.Zonk as Ghc import GHC.Types.Annotations as Ghc import GHC.Types.Avail as Ghc import GHC.Types.Basic as Ghc import GHC.Types.CostCentre as Ghc +import GHC.Types.Error as Ghc +import GHC.Types.Fixity as Ghc import GHC.Types.Id as Ghc hiding (lazySetIdInfo, setIdExported, setIdNotExported) import GHC.Types.Id.Info as Ghc import GHC.Types.Literal as Ghc hiding (LitNumber) +import qualified GHC.Types.Literal as Ghc import GHC.Types.Name as Ghc hiding (varName, isWiredIn) import GHC.Types.Name.Reader as Ghc import GHC.Types.Name.Set as Ghc +import GHC.Types.SourceError as Ghc +import GHC.Types.SourceText as Ghc import GHC.Types.SrcLoc as Ghc +import GHC.Types.Tickish as Ghc +import GHC.Types.TypeEnv as Ghc import GHC.Types.Unique as Ghc import GHC.Types.Unique.DFM as Ghc import GHC.Types.Unique.FM as Ghc @@ -373,436 +129,21 @@ import GHC.Types.Unique.Supply as Ghc import GHC.Types.Var as Ghc import GHC.Types.Var.Env as Ghc import GHC.Types.Var.Set as Ghc +import GHC.Unit.External as Ghc +import GHC.Unit.Finder as Ghc +import GHC.Unit.Home.ModInfo as Ghc import GHC.Unit.Module as Ghc +import GHC.Unit.Module.Deps as Ghc +import GHC.Unit.Module.Graph as Ghc +import GHC.Unit.Module.ModDetails as Ghc +import GHC.Unit.Module.ModGuts as Ghc +import GHC.Unit.Module.ModSummary as Ghc import GHC.Utils.Error as Ghc -import GHC.Utils.Outputable as Ghc hiding ((<>), integer, renderWithStyle, mkUserStyle) +import GHC.Utils.Logger as Ghc +import GHC.Utils.Misc as Ghc (zipEqual) +import GHC.Utils.Outputable as Ghc (mkUserStyle) +import GHC.Utils.Outputable as Ghc hiding ((<>), integer, mkUserStyle) import GHC.Utils.Panic as Ghc -import qualified GHC.Types.Literal as Ghc -import qualified GHC.Utils.Outputable as Ghc -import GHC.Tc.Types.Origin as Ghc (lexprCtOrigin) -import GHC.Rename.Expr as Ghc (rnLExpr) -import GHC.Tc.Gen.Expr as Ghc (tcInferSigma, tcInferRho) -import GHC.Tc.Gen.Bind as Ghc (tcValBinds) -import GHC.Tc.Solver as Ghc -import GHC.Tc.Utils.Zonk as Ghc -import GHC.Core.FVs as Ghc (exprFreeVarsList) -import GHC.Tc.Types.Evidence as Ghc -import GHC.HsToCore.Expr as Ghc -import GHC.Core.Predicate as Ghc (mkClassPred) -import GHC.Core.Opt.OccurAnal as Ghc -#endif -#endif - --- --- Compat shim for GHC < 9 (shared parts) --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - -data BufSpan - -pattern RealSrcSpan :: SrcLoc.RealSrcSpan -> Maybe BufSpan -> SrcLoc.SrcSpan -pattern RealSrcSpan rss mbSpan <- ((,Nothing) -> (SrcLoc.RealSrcSpan rss, mbSpan)) - where - RealSrcSpan rss _mbSpan = SrcLoc.RealSrcSpan rss - -data UnhelpfulSpanReason - = UnhelpfulNoLocationInfo - | UnhelpfulWiredIn - | UnhelpfulInteractive - | UnhelpfulGenerated - | UnhelpfulOther !FastString - deriving (Eq, Show) - -pattern UnhelpfulSpan :: UnhelpfulSpanReason -> SrcLoc.SrcSpan -pattern UnhelpfulSpan reason <- (toUnhelpfulReason -> Just reason) - where - UnhelpfulSpan reason = SrcLoc.UnhelpfulSpan (fromUnhelpfulReason reason) - -fromUnhelpfulReason :: UnhelpfulSpanReason -> FastString -fromUnhelpfulReason = \case - UnhelpfulNoLocationInfo -> fsLit "UnhelpfulNoLocationInfo" - UnhelpfulWiredIn -> fsLit "UnhelpfulWiredIn" - UnhelpfulInteractive -> fsLit "UnhelpfulInteractive" - UnhelpfulGenerated -> fsLit "UnhelpfulGenerated" - UnhelpfulOther fs -> fs - -toUnhelpfulReason :: SrcLoc.SrcSpan -> Maybe UnhelpfulSpanReason -toUnhelpfulReason (SrcLoc.RealSrcSpan _) = Nothing -toUnhelpfulReason (SrcLoc.UnhelpfulSpan fs) = Just $ case unpackFS fs of - "UnhelpfulNoLocationInfo" -> UnhelpfulNoLocationInfo - "UnhelpfulWiredIn" -> UnhelpfulWiredIn - "UnhelpfulInteractive" -> UnhelpfulInteractive - "UnhelpfulGenerated" -> UnhelpfulGenerated - _ -> UnhelpfulOther fs - --- Backporting multiplicity - -data Scaled a = Scaled Mult a - deriving (Data.Data) - -instance (Outputable a) => Outputable (Scaled a) where - ppr (Scaled _cnt t) = ppr t - -irrelevantMult :: Scaled a -> a -irrelevantMult = scaledThing - -mkScaled :: Mult -> a -> Scaled a -mkScaled = Scaled - -scaledThing :: Scaled a -> a -scaledThing (Scaled _ t) = t - -type Mult = Type - -pcDataCon :: Name -> [TyVar] -> [Type] -> TyCon -> DataCon -pcDataCon n univs tys tycon = data_con - where - data_con = mkDataCon n - False - (mkPrelTyConRepName n) - (map (const (HsSrcBang NoSourceText NoSrcUnpack NoSrcStrict)) tys) - [] - univs - [] - (error "[TyVarBinder]") - [] - [] - tys - (mkTyConApp tycon (mkTyVarTys univs)) - NoRRI - tycon - (lookupNameEnv_NF (mkTyConTagMap tycon) n) - [] - (mkDataConWorkId (mkDataConWorkerName data_con (dataConWorkerUnique (nameUnique n))) data_con) - NoDataConRep - - -mkDataConWorkerName :: DataCon -> Unique -> Name -mkDataConWorkerName data_con wrk_key = - mkWiredInName modu wrk_occ wrk_key - (AnId (dataConWorkId data_con)) UserSyntax - where - modu = nameModule dc_name - dc_name = dataConName data_con - dc_occ = nameOccName dc_name - wrk_occ = mkDataConWorkerOcc dc_occ - -pcTyCon :: Name -> Maybe CType -> [TyVar] -> [DataCon] -> TyCon -pcTyCon name cType tyvars cons - = mkAlgTyCon name - (mkAnonTyConBinders VisArg tyvars) - liftedTypeKind - (map (const Representational) tyvars) - cType - [] -- No stupid theta - (mkDataTyConRhs cons) - (VanillaAlgTyCon (mkPrelTyConRepName name)) - False -- Not in GADT syntax - - -mkWiredInDataConName :: BuiltInSyntax -> Module -> FastString -> Unique -> DataCon -> Name -mkWiredInDataConName built_in modu fs unique datacon - = mkWiredInName modu (mkDataOccFS fs) unique - (AConLike (RealDataCon datacon)) -- Relevant DataCon - built_in - -multiplicityTyConKey :: Unique -multiplicityTyConKey = mkPreludeTyConUnique 192 - -multiplicityTyConName :: Name -multiplicityTyConName = mkWiredInTyConName UserSyntax gHC_TYPES (fsLit "Multiplicity") - multiplicityTyConKey multiplicityTyCon - -manyDataConName :: Name -manyDataConName = mkWiredInDataConName BuiltInSyntax gHC_TYPES (fsLit "Many") manyDataConKey manyDataCon - -multiplicityTyCon :: TyCon -multiplicityTyCon = pcTyCon multiplicityTyConName Nothing [] [manyDataCon] - -manyDataCon :: DataCon -manyDataCon = pcDataCon manyDataConName [] [] multiplicityTyCon - -manyDataConKey :: Unique -manyDataConKey = mkPreludeDataConUnique 116 - -manyDataConTy :: Type -manyDataConTy = mkTyConTy manyDataConTyCon - -manyDataConTyCon :: TyCon -manyDataConTyCon = promoteDataCon manyDataCon - -pattern Many :: Mult -pattern Many <- (isManyDataConTy -> True) - where Many = manyDataConTy - -isManyDataConTy :: Mult -> Bool -isManyDataConTy ty - | Just tc <- tyConAppTyCon_maybe ty - = tc `hasKey` manyDataConKey -isManyDataConTy _ = False - --- --- Dependencies and Boot --- -type IsBootInterface = GhcMake.IsBoot - --- | This data type just pairs a value 'mod' with an IsBootInterface flag. In --- practice, 'mod' is usually a @Module@ or @ModuleName@'. -data GenWithIsBoot mod = GWIB - { gwib_mod :: mod - , gwib_isBoot :: IsBootInterface - } deriving ( Eq, Ord, Show - , Functor, Foldable, Traversable - ) - -type ModuleNameWithIsBoot = GenWithIsBoot ModuleName - -isBootSummary :: ModSummary -> IsBootInterface -isBootSummary ms = case Ghc.isBootSummary ms of - True -> GhcMake.IsBoot - False -> GhcMake.NotBoot - -getDependenciesModuleNames :: Dependencies -> [ModuleNameWithIsBoot] -getDependenciesModuleNames = map f . dep_mods - where - f :: (ModuleName, Bool) -> ModuleNameWithIsBoot - f (modName, b) = let isBoot = if b then GhcMake.IsBoot else GhcMake.NotBoot in GWIB modName isBoot - -dataConInstArgTys :: DataCon -> [Type] -> [Scaled Type] -dataConInstArgTys dc tys = map (mkScaled Many) (Ghc.dataConInstArgTys dc tys) - -dataConOrigArgTys :: DataCon -> [Scaled Type] -dataConOrigArgTys dc = map (mkScaled Many) (Ghc.dataConOrigArgTys dc) - -dataConRepArgTys :: DataCon -> [Scaled Type] -dataConRepArgTys dc = map (mkScaled Many) (Ghc.dataConRepArgTys dc) - -mkLocalVar :: IdDetails -> Name -> Mult -> Type -> IdInfo -> Id -mkLocalVar idDetails' name _ ty info = Ghc.mkLocalVar idDetails' name ty info - -mkUserLocal :: OccName -> Unique -> Mult -> Type -> SrcSpan -> Id -mkUserLocal occName' u _mult ty srcSpan = Ghc.mkUserLocal occName' u ty srcSpan - -dataConWrapperType :: DataCon -> Type -dataConWrapperType = dataConUserType - --- WWlib - -data DataConAppContext - = DataConAppContext - { dcac_dc :: !DataCon - , dcac_tys :: ![Type] - , dcac_arg_tys :: ![(Scaled Type, StrictnessMark)] - , dcac_co :: !Coercion - } - -deepSplitProductType_maybe :: FamInstEnvs -> Type -> Maybe DataConAppContext -deepSplitProductType_maybe famInstEnv ty = do - (dc, tys, tysWithStricts, co) <- Ghc.deepSplitProductType_maybe famInstEnv ty - pure $ DataConAppContext dc tys (map (Bi.first (mkScaled Many)) tysWithStricts) co - -splitFunTys :: Type -> ([Scaled Type], Type) -splitFunTys ty = Bi.first (map (mkScaled Many)) $ Ghc.splitFunTys ty - -apiAnnComments :: (Map ApiAnnKey [SrcSpan], Map SrcSpan [Located AnnotationComment]) - -> Map SrcSpan [Located AnnotationComment] -apiAnnComments = snd - -mkIntExprInt :: Platform -> Int -> CoreExpr -mkIntExprInt _ = Ghc.mkIntExprInt unsafeGlobalDynFlags - -dataConFullSig :: DataCon -> ([TyVar], [TyCoVar], [EqSpec], ThetaType, [Scaled Type], Type) -dataConFullSig dc = - let (tyvars, tycovars, eqspecs, theta, tys, ty) = Ghc.dataConFullSig dc - in (tyvars, tycovars, eqspecs, theta, map (mkScaled Many) tys, ty) - - -#endif -#endif - --- --- Compat shim for GHC 8.6.5 - -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) - -pattern LitString :: ByteString -> Lit.Literal -pattern LitString bs <- Lit.MachStr bs where - LitString bs = Lit.MachStr bs - -pattern LitFloat :: GHC.Real.Ratio Integer -> Lit.Literal -pattern LitFloat f <- Lit.MachFloat f where - LitFloat f = Lit.MachFloat f - -pattern LitDouble :: GHC.Real.Ratio Integer -> Lit.Literal -pattern LitDouble d <- Lit.MachDouble d where - LitDouble d = Lit.MachDouble d - -pattern LitChar :: Char -> Lit.Literal -pattern LitChar c <- Lit.MachChar c where - LitChar c = Lit.MachChar c - -pattern Bndr :: var -> argf -> Var.TyVarBndr var argf -pattern Bndr var argf <- TvBndr var argf where - Bndr var argf = TvBndr var argf - -type VarBndr = TyVarBndr - -isEqPrimPred :: Type -> Bool -isEqPrimPred = Ghc.isPredTy - --- See NOTE [isEvVarType]. -isEvVarType :: Type -> Bool -isEvVarType = Ghc.isPredTy - -tyConRealArity :: TyCon -> Int -tyConRealArity = tyConArity - -#endif -#endif - --- --- Compat shim for GHC-8.6.5 and GHC-8.8.x --- -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - --- | The non-dependent version of 'ArgFlag'. - --- Appears here partly so that it's together with its friend ArgFlag, --- but also because it is used in IfaceType, rather early in the --- compilation chain --- See Note [AnonArgFlag vs. ForallVisFlag] -data AnonArgFlag - = VisArg -- ^ Used for @(->)@: an ordinary non-dependent arrow. - -- The argument is visible in source code. - | InvisArg -- ^ Used for @(=>)@: a non-dependent predicate arrow. - -- The argument is invisible in source code. - deriving (Eq, Ord, Data) - -instance Outputable AnonArgFlag where - ppr VisArg = text "[vis]" - ppr InvisArg = text "[invis]" - -instance Binary AnonArgFlag where - put_ bh VisArg = putByte bh 0 - put_ bh InvisArg = putByte bh 1 - - get bh = do - h <- getByte bh - case h of - 0 -> return VisArg - _ -> return InvisArg - -mkAnonTyConBinders :: AnonArgFlag -> [TyVar] -> [TyConBinder] -mkAnonTyConBinders _ = Ty.mkAnonTyConBinders - -bytesFS :: FastString -> ByteString -bytesFS = fastStringToByteString - -mkFunTy :: AnonArgFlag -> Mult -> Type -> Type -> Type -mkFunTy _ _ = Ty.FunTy - -pattern FunTy :: AnonArgFlag -> Mult -> Type -> Type -> Type -pattern FunTy { ft_af, ft_mult, ft_arg, ft_res } <- ((VisArg,Many,) -> (ft_af, ft_mult, Ty.FunTy ft_arg ft_res)) where - FunTy _ft_af _ft_mult ft_arg ft_res = Ty.FunTy ft_arg ft_res - -pattern AnonTCB :: AnonArgFlag -> Ty.TyConBndrVis -pattern AnonTCB af <- ((VisArg,) -> (af, Ty.AnonTCB)) where - AnonTCB _af = Ty.AnonTCB - -noExtField :: NoExt -noExtField = NoExt - -#endif - --- Compat shim for GHC 8.8.x - -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) && !MIN_VERSION_GLASGOW_HASKELL(8,10,1,0) - -isEqPrimPred :: Type -> Bool -isEqPrimPred ty - | Just tc <- tyConAppTyCon_maybe ty - = tc `hasKey` Ghc.eqPrimTyConKey || tc `hasKey` Ghc.eqReprPrimTyConKey - | otherwise - = False - -isEqPred :: Type -> Bool -isEqPred ty - | Just tc <- tyConAppTyCon_maybe ty - , Just cls <- tyConClass_maybe tc - = cls `hasKey` Ghc.eqTyConKey || cls `hasKey` Ghc.heqTyConKey - | otherwise - = False - --- See NOTE [isEvVarType]. -isEvVarType :: Type -> Bool -isEvVarType = Ghc.isEvVarType - -#endif -#endif - -{- | [NOTE:tyConRealArity] - -The semantics of 'tyConArity' changed between GHC 8.6.5 and GHC 8.10, mostly due to the -Visible Dependent Quantification (VDQ). As a result, given the following: - -data family EntityField record :: * -> * - -Calling `tyConArity` on this would yield @2@ for 8.6.5 but @1@ an 8.10, so we try to backport -the old behaviour in 8.10 by \"looking\" at the 'Kind' of the input 'TyCon' and trying to recursively -split the type apart with either 'splitFunTy_maybe' or 'splitForAllTy_maybe'. - --} - -{- | [NOTE:isEvVarType] - -For GHC < 8.8.1 'isPredTy' is effectively the same as the new 'isEvVarType', which covers the cases -for coercion types and \"normal\" type coercions. The 8.6.5 version of 'isPredTy' had a special case to -handle a 'TyConApp' in the case of type equality (i.e. ~ ) which was removed in the implementation -for 8.8.1, which essentially calls 'tcIsConstraintKind' straight away. --} - --- --- Support for GHC >= 8.8 --- - -#if MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) && !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - --- See NOTE [tyConRealArity]. -tyConRealArity :: TyCon -> Int -tyConRealArity tc = go 0 (tyConKind tc) - where - go :: Int -> Kind -> Int - go !acc k = - case asum [fmap snd (splitFunTy_maybe k), fmap snd (splitForAllTy_maybe k)] of - Nothing -> acc - Just ks -> go (acc + 1) ks - -dataConExTyVars :: DataCon -> [TyVar] -dataConExTyVars = dataConExTyCoVars - -#endif - --- --- Compat shim for 8.10.x --- - -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) && !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -pattern FunTy :: AnonArgFlag -> Mult -> Type -> Type -> Type -pattern FunTy { ft_af, ft_mult, ft_arg, ft_res } <- ((Many,) -> (ft_mult, Ty.FunTy ft_af ft_arg ft_res)) where - FunTy ft_af' _ft_mult' ft_arg' ft_res' = Ty.FunTy ft_af' ft_arg' ft_res' - -mkFunTy :: AnonArgFlag -> Mult -> Type -> Type -> Type -mkFunTy af _ arg res = Ty.FunTy af arg res -#endif - --- --- Compat shim for 9.0.x - -#if MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -- 'fsToUnitId' is gone in GHC 9, but we can bring code it in terms of 'fsToUnit' and 'toUnitId'. fsToUnitId :: FastString -> UnitId @@ -812,7 +153,7 @@ moduleUnitId :: Module -> UnitId moduleUnitId = toUnitId . moduleUnit thisPackage :: DynFlags -> UnitId -thisPackage = toUnitId . homeUnit +thisPackage = homeUnitId_ -- See NOTE [tyConRealArity]. tyConRealArity :: TyCon -> Int @@ -820,7 +161,7 @@ tyConRealArity tc = go 0 (tyConKind tc) where go :: Int -> Kind -> Int go !acc k = - case asum [fmap (view _3) (splitFunTy_maybe k), fmap snd (splitForAllTy_maybe k)] of + case asum [fmap (view _3) (splitFunTy_maybe k), fmap snd (splitForAllTyCoVar_maybe k)] of Nothing -> acc Just ks -> go (acc + 1) ks @@ -831,10 +172,7 @@ getDependenciesModuleNames :: Dependencies -> [ModuleNameWithIsBoot] getDependenciesModuleNames = dep_mods renderWithStyle :: DynFlags -> SDoc -> PprStyle -> String -renderWithStyle dynflags sdoc style = Ghc.renderWithStyle (Ghc.initSDocContext dynflags style) sdoc - -mkUserStyle :: DynFlags -> PrintUnqualified -> Depth -> PprStyle -mkUserStyle _ = Ghc.mkUserStyle +renderWithStyle dynflags sdoc style = Ghc.renderWithContext (Ghc.initSDocContext dynflags style) sdoc -- -- Literal @@ -854,10 +192,3 @@ dataConSig dc gcatch :: (Ex.MonadCatch m, Exception e) => m a -> (e -> m a) -> m a gcatch = Ex.catch - -#endif - --- --- End of compatibility shim. --- -#endif diff --git a/src-ghc/Liquid/GHC/API/StableModule.hs b/src-ghc/Liquid/GHC/API/StableModule.hs index 57c131c4bc..72568af491 100644 --- a/src-ghc/Liquid/GHC/API/StableModule.hs +++ b/src-ghc/Liquid/GHC/API/StableModule.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveGeneric #-} {-# OPTIONS_GHC -Wno-orphans #-} @@ -15,16 +14,8 @@ module Liquid.GHC.API.StableModule ( ) where import qualified GHC - -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -import qualified Module as GHC -#else import qualified GHC.Unit.Types as GHC import qualified GHC.Unit.Module as GHC -#endif -#endif - import Data.Hashable import GHC.Generics hiding (to, moduleName) import Data.Binary @@ -43,25 +34,16 @@ toStableModule :: GHC.Module -> StableModule toStableModule = StableModule moduleUnitId :: GHC.Module -> GHC.UnitId -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -moduleUnitId = GHC.moduleUnitId -#else moduleUnitId = GHC.toUnitId . GHC.moduleUnit -#endif -#endif renderModule :: GHC.Module -> String renderModule m = "Module { unitId = " <> (GHC.unitIdString . moduleUnitId $ m) - <> ", name = " <> show (GHC.moduleName m) + <> ", name = " <> GHC.moduleNameString (GHC.moduleName m) <> " }" -- These two orphans originally lived inside module 'Language.Haskell.Liquid.Types.Types'. instance Hashable GHC.ModuleName where - hashWithSalt i = hashWithSalt i . show - -instance Show GHC.ModuleName where - show = GHC.moduleNameString + hashWithSalt i = hashWithSalt i . GHC.moduleNameString instance Hashable StableModule where hashWithSalt s (StableModule mdl) = hashWithSalt s (GHC.moduleStableString mdl) @@ -91,13 +73,6 @@ instance Binary StableModule where -- | Creates a new 'StableModule' out of a 'ModuleName' and a 'UnitId'. mkStableModule :: GHC.UnitId -> GHC.ModuleName -> StableModule -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -mkStableModule uid modName = StableModule (GHC.mkModule uid modName) -#else mkStableModule uid modName = let realUnit = GHC.RealUnit $ GHC.Definite uid in StableModule (GHC.Module realUnit modName) -#endif -#endif - diff --git a/src-ghc/Liquid/GHC/GhcMonadLike.hs b/src-ghc/Liquid/GHC/GhcMonadLike.hs index 26547938a2..234850b9d9 100644 --- a/src-ghc/Liquid/GHC/GhcMonadLike.hs +++ b/src-ghc/Liquid/GHC/GhcMonadLike.hs @@ -1,7 +1,9 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE RankNTypes #-} -- | This module introduces a \"lighter\" "GhcMonad" typeclass which doesn't require an instance of -- 'ExceptionMonad', and can therefore be used for both 'CoreM' and 'Ghc'. -- @@ -29,14 +31,16 @@ module Liquid.GHC.GhcMonadLike ( , findModule , lookupModule , isBootInterface + , ApiComment(..) , apiComments ) where import Control.Monad.IO.Class import Control.Exception (throwIO) -import Data.IORef (readIORef) - +import Data.Data (Data, gmapQr) +import Data.Generics (extQ) +import qualified Data.List import qualified Liquid.GHC.API as Ghc import Liquid.GHC.API hiding ( ModuleInfo , findModule @@ -54,24 +58,12 @@ import Liquid.GHC.API hiding ( ModuleInfo , tm_renamed_source ) --- Shared imports for GHC < 9 -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -import qualified CoreMonad -import qualified EnumSet -import Maybes -import GhcMake -import Exception (ExceptionMonad) -#else import GHC.Data.Maybe import GHC.Driver.Make import GHC.Utils.Exception (ExceptionMonad) import qualified GHC.Core.Opt.Monad as CoreMonad import qualified GHC.Data.EnumSet as EnumSet -#endif -#endif -import qualified Data.Map.Strict as M import Optics class HasHscEnv m where @@ -119,10 +111,10 @@ getModSummary mdl = do , not (isBootInterface . isBootSummary $ ms) ] case mods_by_name of [] -> do dflags <- getDynFlags - liftIO $ throwIO $ mkApiErr dflags (text "Module not part of module graph") + liftIO $ throwIO $ GhcApiError (showSDoc dflags (text "Module not part of module graph")) [ms] -> return ms multiple -> do dflags <- getDynFlags - liftIO $ throwIO $ mkApiErr dflags (text "getModSummary is ambiguous: " <+> ppr multiple) + liftIO $ throwIO $ GhcApiError (showSDoc dflags (text "getModSummary is ambiguous: " <+> ppr multiple)) -- Converts a 'IsBootInterface' into a 'Bool'. @@ -144,7 +136,7 @@ lookupModSummary mdl = do lookupGlobalName :: GhcMonadLike m => Name -> m (Maybe TyThing) lookupGlobalName name = do hsc_env <- askHscEnv - liftIO $ lookupTypeHscEnv hsc_env name + liftIO $ lookupType hsc_env name -- NOTE(adn) Taken from the GHC API, adapted to work for a 'GhcMonadLike' monad. lookupName :: GhcMonadLike m => Name -> m (Maybe TyThing) @@ -155,17 +147,7 @@ lookupName name = do -- | Our own simplified version of 'ModuleInfo' to overcome the fact we cannot construct the \"original\" -- one as the constructor is not exported, and 'getHomeModuleInfo' and 'getPackageModuleInfo' are not -- exported either, so we had to backport them as well. -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - --- For GHC < 9, UniqFM has a single parameter. -data ModuleInfo = ModuleInfo { minf_type_env :: UniqFM TyThing } -#else --- For GHC >= 9, UniqFM has two parameters. --- just fine. -data ModuleInfo = ModuleInfo { minf_type_env :: UniqFM Name TyThing } -#endif -#endif +newtype ModuleInfo = ModuleInfo { minf_type_env :: UniqFM Name TyThing } modInfoLookupName :: GhcMonadLike m => ModuleInfo @@ -175,9 +157,8 @@ modInfoLookupName minf name = do hsc_env <- askHscEnv case lookupTypeEnv (minf_type_env minf) name of Just tyThing -> return (Just tyThing) - Nothing -> do - eps <- liftIO $ readIORef (hsc_EPS hsc_env) - return $! lookupType (hsc_dflags hsc_env) (hsc_HPT hsc_env) (eps_PTE eps) name + Nothing -> liftIO $ do + lookupType hsc_env name moduleInfoTc :: GhcMonadLike m => ModSummary -> TcGblEnv -> m ModuleInfo moduleInfoTc ms tcGblEnv = do @@ -194,8 +175,7 @@ parseModule ms = do hsc_env <- askHscEnv let hsc_env_tmp = hsc_env { hsc_dflags = ms_hspp_opts ms } hpm <- liftIO $ hscParse hsc_env_tmp ms - return (ParsedModule ms (hpm_module hpm) (hpm_src_files hpm) - (hpm_annotations hpm)) + return (ParsedModule ms (hpm_module hpm) (hpm_src_files hpm)) -- | Our own simplified version of 'TypecheckedModule'. data TypecheckedModule = TypecheckedModule { @@ -216,8 +196,7 @@ typecheckModule pmod = do (tc_gbl_env, rn_info) <- liftIO $ hscTypecheckRename hsc_env_tmp ms $ HsParsedModule { hpm_module = parsedSource pmod, - hpm_src_files = pm_extra_src_files pmod, - hpm_annotations = pm_annotations pmod } + hpm_src_files = pm_extra_src_files pmod } return TypecheckedModule { tm_parsed_module = pmod , tm_renamed_source = rn_info @@ -271,13 +250,13 @@ findModule mod_name maybe_pkg = do let dflags = hsc_dflags hsc_env this_pkg = thisPackage dflags - -- + throwNoModError err = throwOneError $ noModError hsc_env noSrcSpan mod_name err case maybe_pkg of Just pkg | fsToUnitId pkg /= this_pkg && pkg /= fsLit "this" -> liftIO $ do res <- findImportedModule hsc_env mod_name maybe_pkg case res of Found _ m -> return m - err -> throwOneError $ noModError dflags noSrcSpan mod_name err + err -> throwNoModError err _otherwise -> do home <- lookupLoadedHomeModule mod_name case home of @@ -287,7 +266,7 @@ findModule mod_name maybe_pkg = do case res of Found loc m | moduleUnitId m /= this_pkg -> return m | otherwise -> modNotLoadedError dflags m loc - err -> throwOneError $ noModError dflags noSrcSpan mod_name err + err -> throwNoModError err lookupLoadedHomeModule :: GhcMonadLike m => ModuleName -> m (Maybe Module) @@ -316,24 +295,31 @@ lookupModule mod_name Nothing = do res <- findExposedPackageModule hsc_env mod_name Nothing case res of Found _ m -> return m - err -> throwOneError $ noModError (hsc_dflags hsc_env) noSrcSpan mod_name err - --- Compatibility shim to extract the comments out of an 'ApiAnns', as modern GHCs now puts the --- comments (i.e. Haskell comments) in a different field ('apiAnnRogueComments'). -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -apiComments :: ApiAnns -> [Ghc.Located AnnotationComment] -apiComments apiAnns = - let comments = concat . M.elems . apiAnnComments $ apiAnns - in - comments -#else -apiComments :: ApiAnns -> [Ghc.Located AnnotationComment] -apiComments apiAnns = - let comments = concat . M.elems . apiAnnComments $ apiAnns - in - map toRealSrc $ mappend comments (apiAnnRogueComments apiAnns) + err -> + throwOneError $ noModError hsc_env noSrcSpan mod_name err + +-- | Abstraction of 'EpaComment'. +data ApiComment + = ApiLineComment String + | ApiBlockComment String + deriving Show + +-- | Extract top-level comments from a module. +apiComments :: ParsedModule -> [Ghc.Located ApiComment] +apiComments pm = + let hs = unLoc (pm_parsed_source pm) + go :: forall a. Data a => a -> [LEpaComment] + go = gmapQr (++) [] go `extQ` (id @[LEpaComment]) + in Data.List.sortOn (spanToLineColumn . getLoc) $ + mapMaybe (tokComment . toRealSrc) $ go hs where - toRealSrc (L x e) = L (RealSrcSpan x Nothing) e -#endif -#endif + tokComment (L sp (EpaComment (EpaLineComment s) _)) = Just (L sp (ApiLineComment s)) + tokComment (L sp (EpaComment (EpaBlockComment s) _)) = Just (L sp (ApiBlockComment s)) + tokComment _ = Nothing + + -- TODO: take into account anchor_op, which only matters if the source was + -- pre-processed by an exact-print-aware tool. + toRealSrc (L a e) = L (RealSrcSpan (anchor a) Nothing) e + + spanToLineColumn = + fmap (\s -> (srcSpanStartLine s, srcSpanStartCol s)) . srcSpanToRealSrcSpan diff --git a/src-ghc/Liquid/GHC/Interface.hs b/src-ghc/Liquid/GHC/Interface.hs index 6a6394a8cc..3ec177d3c5 100644 --- a/src-ghc/Liquid/GHC/Interface.hs +++ b/src-ghc/Liquid/GHC/Interface.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TypeSynonymInstances #-} @@ -13,6 +12,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_GHC -Wwarn=deprecations #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Liquid.GHC.Interface ( @@ -123,14 +123,14 @@ import qualified Debug.Trace as Debug -------------------------------------------------------------------------------- -{- | @realTargets mE cfg targets@ uses `Interface.configureGhcTargets` to +{- | @realTargets mE cfg targets@ uses `Interface.configureGhcTargets` to return a list of files [i1, i2, ... ] ++ [f1, f2, ...] - 1. Where each file only (transitively imports) PRECEDIING ones; + 1. Where each file only (transitively imports) PRECEDIING ones; 2. `f1..` are a permutation of the original `targets`; - 3. `i1..` either don't have "fresh" .bspec files. + 3. `i1..` either don't have "fresh" .bspec files. -} -------------------------------------------------------------------------------- @@ -138,9 +138,7 @@ realTargets :: Maybe HscEnv -> Config -> [FilePath] -> IO [FilePath] realTargets mbEnv cfg tgtFs | noCheckImports cfg = return tgtFs | otherwise = do - incDir <- Misc.getIncludeDir - allFs <- orderTargets mbEnv cfg tgtFs - let srcFs = filter (not . Misc.isIncludeFile incDir) allFs + srcFs <- orderTargets mbEnv cfg tgtFs realFs <- filterM check srcFs dir <- getCurrentDirectory return (makeRelative dir <$> realFs) @@ -159,7 +157,7 @@ orderTargets mbEnv cfg tgtFiles = runLiquidGhc mbEnv cfg $ do skipTarget :: S.HashSet FilePath -> FilePath -> IO Bool skipTarget tgts f - | S.member f tgts = return False -- Always check target file + | S.member f tgts = return False -- Always check target file | otherwise = hasFreshBinSpec f -- But skip an import with fresh .bspec hasFreshBinSpec :: FilePath -> IO Bool @@ -220,11 +218,14 @@ updateIncludePaths df ps = addGlobalInclude (includePaths df) ps configureDynFlags :: Config -> FilePath -> Ghc DynFlags configureDynFlags cfg tmp = do df <- getSessionDynFlags - (df',_,_) <- parseDynamicFlags df $ map noLoc $ ghcOptions cfg + logger <- getLogger + (df',_,_) <- parseDynamicFlags logger df $ map noLoc $ ghcOptions cfg loud <- liftIO isLoud + pushLogHookM $ \_ -> + if loud then defaultLogAction else \_ _ _ _ _ -> return () let df'' = df' { importPaths = nub $ idirs cfg ++ importPaths df' , libraryPaths = nub $ idirs cfg ++ libraryPaths df' - , includePaths = updateIncludePaths df' (idirs cfg) -- addGlobalInclude (includePaths df') (idirs cfg) + , includePaths = updateIncludePaths df' (idirs cfg) -- addGlobalInclude (includePaths df') (idirs cfg) , packageFlags = ExposePackage "" (PackageArg "ghc-prim") (ModRenaming True []) @@ -233,20 +234,8 @@ configureDynFlags cfg tmp = do , debugLevel = 1 -- insert SourceNotes -- , profAuto = ProfAutoCalls , ghcLink = LinkInMemory - , hscTarget = HscInterpreted + , backend = Interpreter , ghcMode = CompManager - -- prevent GHC from printing anything, unless in Loud mode -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - , log_action = if loud - then defaultLogAction - else \_ _ _ _ _ _ -> return () -#else - , log_action = if loud - then defaultLogAction - else \_ _ _ _ _ -> return () -#endif -#endif -- redirect .hi/.o/etc files to temp directory , objectDir = Just tmp , hiDir = Just tmp @@ -267,11 +256,12 @@ configureGhcTargets tgtFiles = do moduleGraph <- depanal [] False -- see [NOTE:DROP-BOOT-FILES] let homeModules = filter (not . isBootInterface . isBootSummary) $ - flattenSCCs $ topSortModuleGraph False moduleGraph Nothing + flattenSCCs $ filterToposortToModules $ + topSortModuleGraph False moduleGraph Nothing let homeNames = moduleName . ms_mod <$> homeModules _ <- setTargetModules homeNames liftIO $ whenLoud $ print ("Module Dependencies" :: String, homeNames) - return $ mkModuleGraph homeModules + return $ mkModuleGraph (map Ghc.extendModSummaryNoDeps homeModules) setTargetModules :: [ModuleName] -> Ghc () setTargetModules modNames = setTargets $ mkTarget <$> modNames @@ -298,9 +288,9 @@ compileCFiles cfg = do Bar.hs --> Foo.hs --> Bar.hs-boot we'll get - + [Bar.hs, Foo.hs] - + which is backwards.. -} -------------------------------------------------------------------------------- @@ -343,7 +333,7 @@ importDeclModule fromMod (mpkgQual, locModName) = do dflags <- getDynFlags liftIO $ throwGhcExceptionIO $ ProgramError $ O.showPpr dflags (moduleName fromMod) ++ ": " ++ - O.showSDoc dflags (cannotFindModule dflags modName res) + O.showSDoc dflags (cannotFindModule hscEnv modName res) -------------------------------------------------------------------------------- -- | Extract Ids --------------------------------------------------------------- @@ -417,7 +407,7 @@ processModule cfg logicMap tgtFiles depGraph specEnv modSummary = do let isTarget' = file `S.member` tgtFiles _ <- loadDependenciesOf $ moduleName mod' parsed <- parseModule $ keepRawTokenStream modSummary - let specComments = extractSpecComments (pm_annotations parsed) + let specComments = extractSpecComments parsed typechecked <- typecheckModule $ ignoreInline parsed let specQuotes = extractSpecQuotes typechecked _ <- loadModule' typechecked @@ -454,7 +444,7 @@ loadModule' tm = loadModule tm' pm = tm_parsed_module tm ms = pm_mod_summary pm df = ms_hspp_opts ms - df' = df { hscTarget = HscNothing, ghcLink = NoLink } + df' = df { backend = NoBackend, ghcLink = NoLink } ms' = ms { ms_hspp_opts = df' } pm' = pm { pm_mod_summary = ms' } tm' = tm { tm_parsed_module = pm' } @@ -484,10 +474,10 @@ loadModule' tm = loadModule tm' -- Ghc.execOptions -- void $ Ghc.execStmt -- "let {infixl 7 /; (/) :: Num a => a -> a -> a; _ / _ = undefined}" - -- Ghc.execOptions + -- Ghc.execOptions -- void $ Ghc.execStmt -- "let {len :: [a] -> Int; len _ = undefined}" - -- Ghc.execOptions + -- Ghc.execOptions processTargetModule :: Config -> LogicMap -> DepGraph -> SpecEnv -> FilePath -> TypecheckedModule -> Ms.BareSpec -> Ghc TargetInfo processTargetModule cfg0 logicMap depGraph specEnv file typechecked bareSpec = do @@ -504,14 +494,21 @@ processTargetModule cfg0 logicMap depGraph specEnv file typechecked bareSpec = d (msgs, specM) <- Ghc.withSession $ \hsc_env -> liftIO $ runTcInteractive hsc_env (makeTargetSpec cfg logicMap targetSrc (view bareSpecIso bareSpec) dependencies) case specM of - Nothing -> panic Nothing $ O.showSDoc dynFlags $ O.sep (Ghc.pprErrMsgBagWithLoc (snd msgs)) - Just spec -> + Nothing -> + panic Nothing $ + O.showSDoc dynFlags $ + O.sep $ + Ghc.pprMsgEnvelopeBagWithLoc + -- TODO use getMessages from GHC 9.4 onwards. + (Ghc.getErrorMessages msgs `Ghc.unionBags` Ghc.getWarningMessages msgs) + Just spec -> do + logger <- getLogger case spec of Left diagnostics -> do - mapM_ (liftIO . printWarning dynFlags) (allWarnings diagnostics) + mapM_ (liftIO . printWarning logger dynFlags) (allWarnings diagnostics) throw (allErrors diagnostics) Right (warns, targetSpec, liftedSpec) -> do - mapM_ (liftIO . printWarning dynFlags) warns + mapM_ (liftIO . printWarning logger dynFlags) warns -- The call below is temporary, we should really load & save directly 'LiftedSpec's. _ <- liftIO $ saveLiftedSpec (_giTarget ghcSrc) (unsafeFromLiftedSpec liftedSpec) return $ TargetInfo targetSrc targetSpec @@ -569,7 +566,7 @@ loadContext bareSpec dependencies targetSrc = do legacyBareSpec = review bareSpecIso bareSpec --------------------------------------------------------------------------------------- --- | @makeGhcSrc@ builds all the source-related information needed for consgen +-- | @makeGhcSrc@ builds all the source-related information needed for consgen --------------------------------------------------------------------------------------- makeGhcSrc :: Config -> FilePath -> TypecheckedModule -> ModSummary -> Ghc GhcSrc @@ -587,7 +584,6 @@ makeGhcSrc cfg file typechecked modSum = do availableTcs <- availableTyCons hscEnv modSum (fst $ tm_internals_ typechecked) (mg_exports modGuts') let impVars = importVars coreBinds ++ classCons (mgi_cls_inst modGuts) - incDir <- liftIO Misc.getIncludeDir --liftIO $ do -- print $ "_gsTcs => " ++ show (nub $ (mgi_tcs modGuts) ++ availableTcs) @@ -597,8 +593,7 @@ makeGhcSrc cfg file typechecked modSum = do -- print $ "defVars => " ++ show (dataCons ++ (letVars coreBinds)) return $ Src - { _giIncDir = incDir - , _giTarget = file + { _giTarget = file , _giTargetMod = ModName Target (moduleName (ms_mod modSum)) , _giCbs = coreBinds , _giImpVars = impVars @@ -646,16 +641,16 @@ qImports qns = QImports --------------------------------------------------------------------------------------- --- | @lookupTyThings@ grabs all the @Name@s and associated @TyThing@ known to GHC --- for this module; we will use this to create our name-resolution environment --- (see `Bare.Resolve`) +-- | @lookupTyThings@ grabs all the @Name@s and associated @TyThing@ known to GHC +-- for this module; we will use this to create our name-resolution environment +-- (see `Bare.Resolve`) --------------------------------------------------------------------------------------- lookupTyThings :: GhcMonadLike m => HscEnv -> ModSummary -> TcGblEnv -> m [(Name, Maybe TyThing)] lookupTyThings hscEnv modSum tcGblEnv = forM names (lookupTyThing hscEnv modSum tcGblEnv) where names :: [Ghc.Name] names = liftM2 (++) - (fmap Ghc.gre_name . Ghc.globalRdrEnvElts . tcg_rdr_env) + (fmap Ghc.greMangledName . Ghc.globalRdrEnvElts . tcg_rdr_env) (fmap is_dfun_name . tcg_insts) tcGblEnv -- | Lookup a single 'Name' in the GHC environment, yielding back the 'Name' alongside the 'TyThing', -- if one is found. @@ -671,8 +666,11 @@ lookupTyThing hscEnv modSum tcGblEnv n = do availableTyThings :: GhcMonadLike m => HscEnv -> ModSummary -> TcGblEnv -> [AvailInfo] -> m [TyThing] availableTyThings hscEnv modSum tcGblEnv avails = fmap (catMaybes . mconcat) $ forM avails $ \a -> do results <- case a of - Avail n -> pure <$> lookupTyThing hscEnv modSum tcGblEnv n - AvailTC n ns _ -> forM (n : ns) $ lookupTyThing hscEnv modSum tcGblEnv + Avail n -> + pure <$> lookupTyThing hscEnv modSum tcGblEnv (Ghc.greNameMangledName n) + AvailTC n ns -> + forM (n : map Ghc.greNameMangledName ns) $ + lookupTyThing hscEnv modSum tcGblEnv pure . map snd $ results -- | Returns all the available (i.e. exported) 'TyCon's (type constructors) for the input 'Module'. @@ -685,22 +683,22 @@ availableVars :: GhcMonadLike m => HscEnv -> ModSummary -> TcGblEnv -> [AvailInf availableVars hscEnv modSum tcGblEnv avails = fmap (\things -> [var | (AnId var) <- things]) (availableTyThings hscEnv modSum tcGblEnv avails) --- lookupTyThings :: HscEnv -> TypecheckedModule -> MGIModGuts -> Ghc [(Name, Maybe TyThing)] +-- lookupTyThings :: HscEnv -> TypecheckedModule -> MGIModGuts -> Ghc [(Name, Maybe TyThing)] -- lookupTyThings hscEnv tcm mg = --- forM (mgNames mg ++ instNames mg) $ \n -> do --- tt1 <- lookupName n --- tt2 <- liftIO $ Ghc.hscTcRcLookupName hscEnv n --- tt3 <- modInfoLookupName mi n --- tt4 <- lookupGlobalName n +-- forM (mgNames mg ++ instNames mg) $ \n -> do +-- tt1 <- lookupName n +-- tt2 <- liftIO $ Ghc.hscTcRcLookupName hscEnv n +-- tt3 <- modInfoLookupName mi n +-- tt4 <- lookupGlobalName n -- return (n, Misc.firstMaybes [tt1, tt2, tt3, tt4]) --- where +-- where -- mi = tm_checked_module_info tcm --- lookupName :: GhcMonad m => Name -> m (Maybe TyThing) +-- lookupName :: GhcMonad m => Name -> m (Maybe TyThing) -- hscTcRcLookupName :: HscEnv -> Name -> IO (Maybe TyThing) --- modInfoLookupName :: GhcMonad m => ModuleInfo -> Name -> m (Maybe TyThing) --- lookupGlobalName :: GhcMonad m => Name -> m (Maybe TyThing) +-- modInfoLookupName :: GhcMonad m => ModuleInfo -> Name -> m (Maybe TyThing) +-- lookupGlobalName :: GhcMonad m => Name -> m (Maybe TyThing) _dumpTypeEnv :: TypecheckedModule -> IO () _dumpTypeEnv tm = do @@ -710,8 +708,8 @@ _dumpTypeEnv tm = do tcmTyThings :: TypecheckedModule -> Maybe [Name] tcmTyThings = - -- typeEnvElts - -- . tcg_type_env . fst + -- typeEnvElts + -- . tcg_type_env . fst -- . md_types . snd -- . tm_internals_ modInfoTopLevelScope @@ -722,18 +720,18 @@ _dumpRdrEnv :: HscEnv -> MGIModGuts -> IO () _dumpRdrEnv _hscEnv modGuts = do print ("DUMP-RDR-ENV" :: String) print (mgNames modGuts) - -- print (hscNames hscEnv) - -- print (mgDeps modGuts) + -- print (hscNames hscEnv) + -- print (mgDeps modGuts) where _mgDeps = Ghc.dep_mods . mgi_deps _hscNames = fmap showPpr . Ghc.ic_tythings . Ghc.hsc_IC mgNames :: MGIModGuts -> [Ghc.Name] -mgNames = fmap Ghc.gre_name . Ghc.globalRdrEnvElts . mgi_rdr_env +mgNames = fmap Ghc.greMangledName . Ghc.globalRdrEnvElts . mgi_rdr_env --------------------------------------------------------------------------------------- --- | @makeDependencies@ loads BareSpec for target and imported modules --- /IMPORTANT(adn)/: We \"cheat\" a bit by creating a 'Module' out the 'ModuleName' we +-- | @makeDependencies@ loads BareSpec for target and imported modules +-- /IMPORTANT(adn)/: We \"cheat\" a bit by creating a 'Module' out the 'ModuleName' we -- parse from the spec, and convert the former into a 'StableModule' for the purpose -- of dependency tracking. This means, in practice, that all the \"wired-in-prelude\" -- specs will share the same `UnitId`, which for the sake of the executable is an @@ -813,7 +811,7 @@ getFamInstances env = do -------------------------------------------------------------------------------- -- | Extract Specifications from GHC ------------------------------------------- -------------------------------------------------------------------------------- -extractSpecComments :: ApiAnns -> [(SourcePos, String)] +extractSpecComments :: ParsedModule -> [(SourcePos, String)] extractSpecComments = mapMaybe extractSpecComment . GhcMonadLike.apiComments -- | 'extractSpecComment' pulls out the specification part from a full comment @@ -822,8 +820,8 @@ extractSpecComments = mapMaybe extractSpecComment . GhcMonadLike.apiComments -- 2. '{-@ ... -}' then it throws a malformed SPECIFICATION ERROR, and -- 3. Otherwise it is just treated as a plain comment so we return Nothing. -extractSpecComment :: Ghc.Located AnnotationComment -> Maybe (SourcePos, String) -extractSpecComment (Ghc.L sp (AnnBlockComment txt)) +extractSpecComment :: Ghc.Located GhcMonadLike.ApiComment -> Maybe (SourcePos, String) +extractSpecComment (Ghc.L sp (GhcMonadLike.ApiBlockComment txt)) | isPrefixOf "{-@" txt && isSuffixOf "@-}" txt -- valid specification = Just (offsetPos, take (length txt - 6) $ drop 3 txt) | isPrefixOf "{-@" txt -- invalid specification @@ -1039,7 +1037,7 @@ instance PPrint TargetInfo where pprintCBs :: [CoreBind] -> Doc pprintCBs = pprDoc . tidyCBs - -- To print verbosely + -- To print verbosely -- = text . O.showSDocDebug unsafeGlobalDynFlags . O.ppr . tidyCBs instance Show TargetInfo where @@ -1054,4 +1052,4 @@ instance PPrint TargetVars where ------------------------------------------------------------------------ instance Result SourceError where - result = (`Crash` "Invalid Source") . sourceErrors "" + result e = Crash ((, Nothing) <$> sourceErrors "" e) "Invalid Source" diff --git a/src-ghc/Liquid/GHC/Logging.hs b/src-ghc/Liquid/GHC/Logging.hs index ba4bdedf44..e64b9b2b4a 100644 --- a/src-ghc/Liquid/GHC/Logging.hs +++ b/src-ghc/Liquid/GHC/Logging.hs @@ -9,8 +9,6 @@ to pay the price of a pretty-printing \"roundtrip\". -} -{-# LANGUAGE CPP #-} - module Liquid.GHC.Logging ( fromPJDoc , putWarnMsg @@ -29,47 +27,28 @@ fromPJDoc = GHC.text . PJ.render -- | Like the original 'putLogMsg', but internally converts the input 'Doc' (from the \"pretty\" library) -- into GHC's internal 'SDoc'. -putLogMsg :: GHC.DynFlags +putLogMsg :: GHC.Logger + -> GHC.DynFlags -> GHC.WarnReason -> GHC.Severity -> GHC.SrcSpan -> Maybe GHC.PprStyle -> PJ.Doc -> IO () -putLogMsg dynFlags reason sev srcSpan _mbStyle = -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - GHC.putLogMsg dynFlags reason sev srcSpan style' . GHC.text . PJ.render - where - style' :: GHC.PprStyle - style' = case _mbStyle of - Nothing -> defaultErrStyle dynFlags - Just sty -> sty -#else - GHC.putLogMsg dynFlags reason sev srcSpan . GHC.text . PJ.render -#endif -#endif - +putLogMsg logger dynFlags reason sev srcSpan _mbStyle = + GHC.putLogMsg logger dynFlags reason sev srcSpan . GHC.text . PJ.render -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -defaultErrStyle :: GHC.DynFlags -> GHC.PprStyle -defaultErrStyle _dynFlags = GHC.defaultErrStyle _dynFlags -#else defaultErrStyle :: GHC.DynFlags -> GHC.PprStyle defaultErrStyle _dynFlags = GHC.defaultErrStyle -#endif -#else - #error MIN_VERSION_GLASGOW_HASKELL is not defined -#endif -putWarnMsg :: GHC.DynFlags -> GHC.SrcSpan -> PJ.Doc -> IO () -putWarnMsg dynFlags srcSpan doc = - putLogMsg dynFlags GHC.NoReason GHC.SevWarning srcSpan (Just $ defaultErrStyle dynFlags) doc +putWarnMsg :: GHC.Logger -> GHC.DynFlags -> GHC.SrcSpan -> PJ.Doc -> IO () +putWarnMsg logger dynFlags srcSpan doc = + putLogMsg logger dynFlags GHC.NoReason GHC.SevWarning srcSpan (Just $ defaultErrStyle dynFlags) doc -putErrMsg :: GHC.DynFlags -> GHC.SrcSpan -> PJ.Doc -> IO () -putErrMsg dynFlags srcSpan doc = putLogMsg dynFlags GHC.NoReason GHC.SevError srcSpan Nothing doc +putErrMsg :: GHC.Logger -> GHC.DynFlags -> GHC.SrcSpan -> PJ.Doc -> IO () +putErrMsg logger dynFlags srcSpan doc = + putLogMsg logger dynFlags GHC.NoReason GHC.SevError srcSpan Nothing doc -- | Like GHC's 'mkLongErrAt', but it builds the final 'ErrMsg' out of two \"HughesPJ\"'s 'Doc's. -mkLongErrAt :: GHC.SrcSpan -> PJ.Doc -> PJ.Doc -> GHC.TcRn GHC.ErrMsg +mkLongErrAt :: GHC.SrcSpan -> PJ.Doc -> PJ.Doc -> GHC.TcRn (GHC.MsgEnvelope GHC.DecoratedSDoc) mkLongErrAt srcSpan msg extra = GHC.mkLongErrAt srcSpan (fromPJDoc msg) (fromPJDoc extra) diff --git a/src-ghc/Liquid/GHC/Misc.hs b/src-ghc/Liquid/GHC/Misc.hs index 460c56985f..2f3f7c52d0 100644 --- a/src-ghc/Liquid/GHC/Misc.hs +++ b/src-ghc/Liquid/GHC/Misc.hs @@ -71,10 +71,10 @@ mkAlive x -------------------------------------------------------------------------------- -- | Encoding and Decoding Location -------------------------------------------- -------------------------------------------------------------------------------- -srcSpanTick :: Module -> SrcSpan -> Tickish a +srcSpanTick :: Module -> SrcSpan -> CoreTickish srcSpanTick m sp = ProfNote (AllCafsCC m sp) False True -tickSrcSpan :: Outputable a => Tickish a -> SrcSpan +tickSrcSpan :: CoreTickish -> SrcSpan tickSrcSpan (ProfNote cc _ _) = cc_loc cc tickSrcSpan (SourceNote ss _) = RealSrcSpan ss Nothing tickSrcSpan _ = noSrcSpan @@ -97,20 +97,6 @@ stringVar s t = mkLocalVar VanillaId name Many t vanillaIdInfo name = mkInternalName (mkUnique 'x' 25) occ noSrcSpan occ = mkVarOcc s -mkLocVar :: Int -> String -> Type -> Var -mkLocVar i s t = mkLocalVar VanillaId name Many t vanillaIdInfo - where - name = mkInternalName unique occ noSrcSpan - unique = mkLocalUnique i - occ = mkVarOcc s - -{- -Taken from GHC.Types.Unique -url: https://hackage.haskell.org/package/ghc-9.4.4/docs/src/GHC.Types.Unique.html#Unique --} -mkLocalUnique :: Int -> Unique -mkLocalUnique i = mkUnique 'X' i - -- FIXME: plugging in dummy type like this is really dangerous maybeAuxVar :: Symbol -> Maybe Var maybeAuxVar s @@ -170,7 +156,7 @@ unTickExpr (App e a) = App (unTickExpr e) (unTickExpr a) unTickExpr (Lam b e) = Lam b (unTickExpr e) unTickExpr (Let b e) = Let (unTick b) (unTickExpr e) unTickExpr (Case e b t as) = Case (unTickExpr e) b t (map unTickAlt as) - where unTickAlt (a, b', e') = (a, b', unTickExpr e') + where unTickAlt (Alt a b' e') = Alt a b' (unTickExpr e') unTickExpr (Cast e c) = Cast (unTickExpr e) c unTickExpr (Tick _ e) = unTickExpr e unTickExpr x = x @@ -210,14 +196,17 @@ showPpr = showSDoc . ppr -- FIXME: somewhere we depend on this printing out all GHC entities with -- fully-qualified names... showSDoc :: Ghc.SDoc -> String -showSDoc sdoc = Ghc.renderWithStyle unsafeGlobalDynFlags sdoc (Ghc.mkUserStyle unsafeGlobalDynFlags myQualify {- Ghc.alwaysQualify -} Ghc.AllTheWay) +showSDoc = Ghc.renderWithContext ctx + where + style = Ghc.mkUserStyle myQualify Ghc.AllTheWay + ctx = Ghc.defaultSDocContext { sdocStyle = style } myQualify :: Ghc.PrintUnqualified myQualify = Ghc.neverQualify { Ghc.queryQualifyName = Ghc.alwaysQualifyNames } -- { Ghc.queryQualifyName = \_ _ -> Ghc.NameNotInScope1 } showSDocDump :: Ghc.SDoc -> String -showSDocDump = Ghc.showSDocDump unsafeGlobalDynFlags +showSDocDump = Ghc.showSDocDump Ghc.defaultSDocContext instance Outputable a => Outputable (S.HashSet a) where ppr = ppr . S.toList @@ -262,7 +251,7 @@ srcSpanFSrcSpan sp = F.SS p p' p' = srcSpanSourcePosE sp sourcePos2SrcSpan :: SourcePos -> SourcePos -> SrcSpan -sourcePos2SrcSpan p p' = RealSrcSpan (realSrcSpan f (unPos l) (unPos c) (unPos l') (unPos c')) Nothing +sourcePos2SrcSpan p p' = RealSrcSpan (packRealSrcSpan f (unPos l) (unPos c) (unPos l') (unPos c')) Nothing where (f, l, c) = F.sourcePosElts p (_, l', c') = F.sourcePosElts p' @@ -445,11 +434,11 @@ lookupRdrName hsc_env mod_name rdr_name = do Nothing -> mkGlobalRdrEnv (gresFromAvails provenance (mi_exports iface)) Just e -> e case lookupGRE_RdrName rdr_name env of - [gre] -> return (Just (gre_name gre)) +-- XXX [gre] -> return (Just (gre_name gre)) [] -> return Nothing _ -> Ghc.panic "lookupRdrNameInModule" Nothing -> throwCmdLineErrorS dflags $ Ghc.hsep [Ghc.ptext (sLit "Could not determine the exports of the module"), ppr mod_name] - err' -> throwCmdLineErrorS dflags $ cannotFindModule dflags mod_name err' + err' -> throwCmdLineErrorS dflags $ cannotFindModule hsc_env mod_name err' where dflags = hsc_dflags hsc_env throwCmdLineErrorS dflags' = throwCmdLineError . Ghc.showSDoc dflags' throwCmdLineError = throwGhcException . CmdLineError @@ -738,20 +727,22 @@ gHC_VERSION = show (__GLASGOW_HASKELL__ :: Int) symbolFastString :: Symbol -> FastString symbolFastString = mkFastStringByteString . T.encodeUtf8 . symbolText -lintCoreBindings :: [Var] -> CoreProgram -> (Bag MsgDoc, Bag MsgDoc) +lintCoreBindings :: [Var] -> CoreProgram -> (Bag SDoc, Bag SDoc) lintCoreBindings = Ghc.lintCoreBindings (defaultDynFlags undefined (undefined ("LlvmTargets" :: String))) CoreDoNothing synTyConRhs_maybe :: TyCon -> Maybe Type synTyConRhs_maybe = Ghc.synTyConRhs_maybe -tcRnLookupRdrName :: HscEnv -> Ghc.Located RdrName -> IO (Messages, Maybe [Name]) +tcRnLookupRdrName :: HscEnv -> Ghc.LocatedN RdrName -> IO (Messages DecoratedSDoc, Maybe [Name]) tcRnLookupRdrName = Ghc.tcRnLookupRdrName showCBs :: Bool -> [CoreBind] -> String showCBs untidy - | untidy = Ghc.showSDocDebug unsafeGlobalDynFlags . ppr . tidyCBs + | untidy = + Ghc.renderWithContext ctx . ppr . tidyCBs | otherwise = showPpr - + where + ctx = Ghc.defaultSDocContext { sdocPprDebug = True } ignoreCoreBinds :: S.HashSet Var -> [CoreBind] -> [CoreBind] ignoreCoreBinds vs cbs @@ -918,73 +909,32 @@ isEvVar x = isPredVar x || isTyVar x || isCoVar x -- hsc_env <- Ghc.getHscEnv -- liftIO $ elabRnExpr hsc_env mode expr -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -elabRnExpr - :: TcRnExprMode -> LHsExpr GhcPs -> TcRn CoreExpr -elabRnExpr mode rdr_expr = do - (rn_expr, _fvs) <- rnLExpr rdr_expr - failIfErrsM - uniq <- newUnique - let fresh_it = itName uniq (getLoc rdr_expr) - orig = Ghc.lexprCtOrigin rn_expr - (tclvl, lie, (tc_expr, res_ty)) <- pushLevelAndCaptureConstraints $ do - (_tc_expr, expr_ty) <- tcInferSigma rn_expr - expr_ty' <- if inst - then snd <$> deeplyInstantiate orig expr_ty - else return expr_ty - return (_tc_expr, expr_ty') - (_, _, evbs, residual, _) <- simplifyInfer tclvl - infer_mode - [] {- No sig vars -} - [(fresh_it, res_ty)] - lie - evbs' <- perhaps_disable_default_warnings $ simplifyInteractive residual - full_expr <- zonkTopLExpr (mkHsDictLet (EvBinds evbs') (mkHsDictLet evbs tc_expr)) - initDsTc $ dsLExpr full_expr - where - (inst, infer_mode, perhaps_disable_default_warnings) = case mode of - TM_Inst -> (True, NoRestrictions, id) - TM_NoInst -> (False, NoRestrictions, id) - TM_Default -> (True, EagerDefaulting, unsetWOptM Opt_WarnTypeDefaults) -#else -elabRnExpr - :: TcRnExprMode -> LHsExpr GhcPs -> TcRn CoreExpr -elabRnExpr mode rdr_expr = do +elabRnExpr :: LHsExpr GhcPs -> TcRn CoreExpr +elabRnExpr rdr_expr = do (rn_expr, _fvs) <- rnLExpr rdr_expr failIfErrsM - -- Now typecheck the expression, and generalise its type - -- it might have a rank-2 type (e.g. :t runST) - uniq <- newUnique ; - let fresh_it = itName uniq (getLoc rdr_expr) + -- Typecheck the expression ((tclvl, (tc_expr, res_ty)), lie) <- captureTopConstraints $ pushTcLevelM $ - tc_infer rn_expr + tcInferRho rn_expr -- Generalise - (_qtvs, _dicts, evbs, residual, _) - <- simplifyInfer tclvl infer_mode + uniq <- newUnique + let { fresh_it = itName uniq (getLocA rdr_expr) } + ((_qtvs, _dicts, evbs, _), residual) + <- captureConstraints $ + simplifyInfer tclvl NoRestrictions [] {- No sig vars -} [(fresh_it, res_ty)] lie -- Ignore the dictionary bindings - evbs' <- perhaps_disable_default_warnings $ - simplifyInteractive residual + evbs' <- simplifyInteractive residual full_expr <- zonkTopLExpr (mkHsDictLet (EvBinds evbs') (mkHsDictLet evbs tc_expr)) initDsTc $ dsLExpr full_expr - where - tc_infer expr' | inst = tcInferRho expr' - | otherwise = tcInferSigma expr' - -- tcInferSigma: see Note [Implementing :type] - - -- See Note [TcRnExprMode] - (inst, infer_mode, perhaps_disable_default_warnings) = case mode of - TM_Inst -> (True, NoRestrictions, id) - TM_NoInst -> (False, NoRestrictions, id) - TM_Default -> (True, EagerDefaulting, unsetWOptM Opt_WarnTypeDefaults) -#endif + newtype HashableType = HashableType {getHType :: Type} instance Eq HashableType where @@ -1067,28 +1017,17 @@ withWiredIn m = discardConstraints $ do -- (Ghc.NonRecursive, unitBag (Ghc.L locSpan b)) -- ) wiredIns - sigsExt ext wiredIns = concatMap (\w -> - let inf = maybeToList $ (\(fPrec, fDir) -> Ghc.L locSpan $ FixSig Ghc.noExtField $ FixitySig Ghc.noExtField [Ghc.L locSpan (tcWiredInName w)] $ Ghc.Fixity Ghc.NoSourceText fPrec fDir) <$> tcWiredInFixity w in + sigs wiredIns = concatMap (\w -> + let inf = maybeToList $ (\(fPrec, fDir) -> Ghc.L locSpanAnn $ Ghc.FixSig Ghc.noAnn $ Ghc.FixitySig Ghc.noExtField [Ghc.L locSpanAnn (tcWiredInName w)] $ Ghc.Fixity Ghc.NoSourceText fPrec fDir) <$> tcWiredInFixity w in let t = let ext' = [] in - [Ghc.L locSpan $ TypeSig Ghc.noExtField [Ghc.L locSpan (tcWiredInName w)] $ HsWC ext' $ HsIB ext $ tcWiredInType w] + [Ghc.L locSpanAnn $ TypeSig Ghc.noAnn [Ghc.L locSpanAnn (tcWiredInName w)] $ HsWC ext' $ Ghc.L locSpanAnn $ HsSig Ghc.noExtField (HsOuterImplicit ext') $ tcWiredInType w] in inf <> t ) wiredIns - sigs = sigsExt cppExt - -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) - cppExt = HsIBRn {hsib_vars = [], hsib_closed = True} in -- TODO: What goes here? XXX -#else - cppExt = [] -#endif -#else - cppExt = [] -#endif - locSpan = UnhelpfulSpan (UnhelpfulOther "Liquid.GHC.Misc: WiredIn") + locSpanAnn = noAnnSrcSpan locSpan mkHsFunTy :: LHsType GhcRn -> LHsType GhcRn -> LHsType GhcRn mkHsFunTy a b = nlHsFunTy a b @@ -1099,8 +1038,8 @@ withWiredIn m = discardConstraints $ do u <- getUniqueM return $ Ghc.mkInternalName u (Ghc.mkVarOcc s) locSpan - toLoc = Ghc.L locSpan - nameToTy = Ghc.L locSpan . HsTyVar Ghc.noExtField Ghc.NotPromoted + toLoc = Ghc.L locSpanAnn + nameToTy = Ghc.L locSpanAnn . HsTyVar Ghc.noAnn Ghc.NotPromoted boolTy' :: LHsType GhcRn boolTy' = nameToTy $ toLoc boolTyConName @@ -1124,39 +1063,21 @@ withWiredIn m = discardConstraints $ do -- infix 4 == :: forall a . a -> a -> Bool eq = do n <- toName "==" - aName <- Ghc.L locSpan <$> toName "a" + aName <- toLoc <$> toName "a" let aTy = nameToTy aName - let ty = noLoc $ HsForAllTy Ghc.noExtField -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) - ForallInvis -#endif - [Ghc.L locSpan $ UserTyVar Ghc.noExtField aName] $ mkHsFunTy aTy (mkHsFunTy aTy boolTy') -#else - (mkHsForAllInvisTele [Ghc.L locSpan $ UserTyVar Ghc.noExtField SpecifiedSpec aName]) $ mkHsFunTy aTy (mkHsFunTy aTy boolTy') -#endif + let ty = toLoc $ HsForAllTy Ghc.noExtField + (mkHsForAllInvisTele Ghc.noAnn [toLoc $ UserTyVar Ghc.noAnn SpecifiedSpec aName]) $ mkHsFunTy aTy (mkHsFunTy aTy boolTy') return $ TcWiredIn n (Just (4, Ghc.InfixN)) ty -- TODO: This is defined as a measure in liquid-base GHC.Base. We probably want to insert all measures to the environment. -- len :: forall a. [a] -> Int len = do n <- toName "len" - aName <- Ghc.L locSpan <$> toName "a" + aName <- toLoc <$> toName "a" let aTy = nameToTy aName - let ty = - noLoc $ HsForAllTy Ghc.noExtField -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) - ForallInvis -#endif - [Ghc.L locSpan $ UserTyVar Ghc.noExtField aName] $ mkHsFunTy (listTy aTy) intTy' - return $ TcWiredIn n Nothing ty -#else - (mkHsForAllInvisTele [Ghc.L locSpan $ UserTyVar Ghc.noExtField SpecifiedSpec aName]) $ mkHsFunTy (listTy aTy) intTy' + let ty = toLoc $ HsForAllTy Ghc.noExtField + (mkHsForAllInvisTele Ghc.noAnn [toLoc $ UserTyVar Ghc.noAnn SpecifiedSpec aName]) $ mkHsFunTy (listTy aTy) intTy' return $ TcWiredIn n Nothing ty -#endif - - prependGHCRealQual :: FastString -> RdrName prependGHCRealQual = varQual_RDR gHC_REAL diff --git a/src-ghc/Liquid/GHC/Play.hs b/src-ghc/Liquid/GHC/Play.hs index 1194703c98..747a1e0861 100644 --- a/src-ghc/Liquid/GHC/Play.hs +++ b/src-ghc/Liquid/GHC/Play.hs @@ -144,9 +144,6 @@ isRecursivenewTyCon c go _ = False -isHoleVar :: Var -> Bool -isHoleVar x = L.isPrefixOf "_" (show x) - dataConImplicitIds :: DataCon -> [Id] dataConImplicitIds dc = [ x | AnId x <- dataConImplicitTyThings dc] @@ -187,8 +184,8 @@ instance Subable Coercion where subTy _ _ = panic Nothing "subTy Coercion" instance Subable (Alt Var) where - sub s (a, b, e) = (a, map (sub s) b, sub s e) - subTy s (a, b, e) = (a, map (subTy s) b, subTy s e) + sub s (Alt a b e) = Alt a (map (sub s) b) (sub s e) + subTy s (Alt a b e) = Alt a (map (subTy s) b) (subTy s e) instance Subable Var where sub s v | M.member v s = subVar $ s M.! v @@ -230,7 +227,7 @@ substExpr s = go go (Lam x e) = Lam (subsVar x) (go e) go (Let (NonRec x ex) e) = Let (NonRec (subsVar x) (go ex)) (go e) go (Let (Rec xes) e) = Let (Rec [(subsVar x', go e') | (x',e') <- xes]) (go e) - go (Case e b t alts) = Case (go e) (subsVar b) t [(c, subsVar <$> xs, go e') | (c, xs, e') <- alts] + go (Case e b t alts) = Case (go e) (subsVar b) t [Alt c (subsVar <$> xs) (go e') | Alt c xs e' <- alts] go (Cast e c) = Cast (go e) c go (Tick t e) = Tick t (go e) go (Type t) = Type t diff --git a/src-ghc/Liquid/GHC/Resugar.hs b/src-ghc/Liquid/GHC/Resugar.hs index 4a0aa408ec..7e3ad4580f 100644 --- a/src-ghc/Liquid/GHC/Resugar.hs +++ b/src-ghc/Liquid/GHC/Resugar.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -105,7 +104,7 @@ exprArgs _e (Var op, [Type m, d, Type a, Type b, e1, Lam x e2]) | op `is` Ghc.bindMName = Just (PatBind e1 x e2 m d a b op) -exprArgs (Case (Var xe) x t [(DataAlt c, ys, Var y)]) _ +exprArgs (Case (Var xe) x t [Alt (DataAlt c) ys (Var y)]) _ | Just i <- y `L.elemIndex` ys = Just (PatProject xe x t c ys i) @@ -154,7 +153,7 @@ lower (PatReturn e m d t op) = Ghc.mkCoreApps (Var op) [Type m, d, Type t, e] lower (PatProject xe x t c ys i) - = Case (Var xe) x t [(DataAlt c, ys, Var yi)] where yi = ys !! i + = Case (Var xe) x t [Alt (DataAlt c) ys (Var yi)] where yi = ys !! i lower (PatSelfBind x e) = Let (NonRec x e) (Var x) diff --git a/src-ghc/Liquid/GHC/SpanStack.hs b/src-ghc/Liquid/GHC/SpanStack.hs index 021c8ed484..2767ca2f0f 100644 --- a/src-ghc/Liquid/GHC/SpanStack.hs +++ b/src-ghc/Liquid/GHC/SpanStack.hs @@ -43,8 +43,8 @@ push !s stk -- @(SpanStack stk) -- | A single span data Span - = Var !Ghc.Var -- ^ binder for whom we are generating constraint - | Tick !(Ghc.Tickish Ghc.Var) -- ^ nearest known Source Span + = Var !Ghc.Var -- ^ binder for whom we are generating constraint + | Tick !Ghc.CoreTickish -- ^ nearest known Source Span | Span SrcSpan instance Show Span where diff --git a/src-ghc/Liquid/GHC/TypeRep.hs b/src-ghc/Liquid/GHC/TypeRep.hs index e3cd30e2ac..64e3b89047 100644 --- a/src-ghc/Liquid/GHC/TypeRep.hs +++ b/src-ghc/Liquid/GHC/TypeRep.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -116,15 +115,8 @@ substCoercion x tx (TyConAppCo r c cs) = TyConAppCo (subst x tx r) c (subst x tx <$> cs) substCoercion x tx (AppCo c1 c2) = AppCo (subst x tx c1) (subst x tx c2) -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -substCoercion x tx (FunCo r c1 c2) - = FunCo r (subst x tx c1) (subst x tx c2) -#else substCoercion x tx (FunCo r cN c1 c2) = FunCo r cN (subst x tx c1) (subst x tx c2) -- TODO(adinapoli) Is this the correct substitution? -#endif -#endif substCoercion x tx (ForAllCo y c1 c2) | symbol x == symbol y = ForAllCo y c1 c2 @@ -152,22 +144,6 @@ substCoercion x tx (KindCo c) = KindCo (subst x tx c) substCoercion x tx (SubCo c) = SubCo (subst x tx c) -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) -substCoercion x tx (Refl r t) - = Refl (subst x tx r) (subst x tx t) -substCoercion x tx (CoherenceCo c1 c2) - = CoherenceCo (subst x tx c1) (subst x tx c2) -#endif -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) -substCoercion x tx (Refl t) - = Refl (subst x tx t) -substCoercion x tx (GRefl r t co) -- FIXME(adn) Is this a correct substitution? - = GRefl r (subst x tx t) co -- FIXME(adn) Is this a correct substitution? -substCoercion _x _tx (HoleCo cH) - = HoleCo cH -- FIXME(adn) Is this a correct substitution? -#endif -#endif instance SubstTy Role where instance SubstTy (CoAxiom Branched) where diff --git a/src/Language/Haskell/Liquid/Bare/Axiom.hs b/src/Language/Haskell/Liquid/Bare/Axiom.hs index e5e4f1c66d..4412425a2f 100644 --- a/src/Language/Haskell/Liquid/Bare/Axiom.hs +++ b/src/Language/Haskell/Liquid/Bare/Axiom.hs @@ -2,6 +2,8 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} + -- | This module contains the code that DOES reflection; i.e. converts Haskell -- definitions into refinements. @@ -175,7 +177,7 @@ instance Subable Ghc.CoreExpr where = e instance Subable Ghc.CoreAlt where - subst su (c, xs, e) = (c, xs, subst su e) + subst su (Ghc.Alt c xs e) = Ghc.Alt c xs (subst su e) data AxiomType = AT { aty :: SpecType, aargs :: [(F.Symbol, SpecType)], ares :: SpecType } diff --git a/src/Language/Haskell/Liquid/Bare/Check.hs b/src/Language/Haskell/Liquid/Bare/Check.hs index ef79934baf..e7410e16e5 100644 --- a/src/Language/Haskell/Liquid/Bare/Check.hs +++ b/src/Language/Haskell/Liquid/Bare/Check.hs @@ -187,10 +187,10 @@ checkTargetSpec specs src env cbs tsp checkPlugged :: PPrint v => [(v, LocSpecType)] -> Diagnostics -checkPlugged xs = mkDiagnostics mempty (map mkErr (filter (hasHoleTy . val . snd) xs)) +checkPlugged xs = mkDiagnostics mempty (map mkError (filter (hasHoleTy . val . snd) xs)) where - mkErr (x,t) = ErrBadData (GM.sourcePosSrcSpan $ loc t) (pprint x) msg - msg = "Cannot resolve type hole `_`. Use explicit type instead." + mkError (x,t) = ErrBadData (GM.sourcePosSrcSpan $ loc t) (pprint x) msg + msg = "Cannot resolve type hole `_`. Use explicit type instead." -------------------------------------------------------------------------------- @@ -294,9 +294,9 @@ _checkDuplicateFieldNames :: [(DataCon, DataConP)] -> [Error] _checkDuplicateFieldNames = mapMaybe go where go (d, dts) = checkNoDups (dcpLoc dts) d (fst <$> dcpTyArgs dts) - checkNoDups l d xs = mkErr l d <$> _firstDuplicate xs + checkNoDups l d xs = mkError l d <$> _firstDuplicate xs - mkErr l d x = ErrBadData (GM.sourcePosSrcSpan l) + mkError l d x = ErrBadData (GM.sourcePosSrcSpan l) (pprint d) (text "Multiple declarations of record selector" <+> pprintSymbol x) @@ -373,12 +373,12 @@ checkTerminationExpr :: (Eq v, PPrint v) -> (v, LocSpecType, [F.Located F.Expr]) -> Diagnostics checkTerminationExpr emb env (v, Loc l _ st, les) - = mkErr "ill-sorted" (go les) <> mkErr "non-numeric" (go' les) + = mkError "ill-sorted" (go les) <> mkError "non-numeric" (go' les) where -- es = val <$> les - mkErr :: Doc -> Maybe (F.Expr, Doc) -> Diagnostics - mkErr _ Nothing = emptyDiagnostics - mkErr k (Just expr') = + mkError :: Doc -> Maybe (F.Expr, Doc) -> Diagnostics + mkError _ Nothing = emptyDiagnostics + mkError k (Just expr') = mkDiagnostics mempty [(\ (e, d) -> ErrTermSpec (GM.sourcePosSrcSpan l) (pprint v) k e st d) expr'] -- mkErr = uncurry (\ e d -> ErrTermSpec (GM.sourcePosSrcSpan l) (pprint v) (text "ill-sorted" ) e t d) -- mkErr' = uncurry (\ e d -> ErrTermSpec (GM.sourcePosSrcSpan l) (pprint v) (text "non-numeric") e t d) @@ -440,13 +440,13 @@ checkClassMethods (Just clsis) cms xts = cls = F.notracepp "CLS" cms checkDuplicateRTAlias :: String -> [Located (RTAlias s a)] -> Diagnostics -checkDuplicateRTAlias s tas = mkDiagnostics mempty (map mkErr dups) +checkDuplicateRTAlias s tas = mkDiagnostics mempty (map mkError dups) where - mkErr xs@(x:_) = ErrDupAlias (GM.fSrcSpan x) + mkError xs@(x:_) = ErrDupAlias (GM.fSrcSpan x) (text s) (pprint . rtName . val $ x) (GM.fSrcSpan <$> xs) - mkErr [] = panic Nothing "mkError: called on empty list" + mkError [] = panic Nothing "mkError: called on empty list" dups = [z | z@(_:_:_) <- L.groupBy ((==) `on` (rtName . val)) tas] diff --git a/src/Language/Haskell/Liquid/Bare/Class.hs b/src/Language/Haskell/Liquid/Bare/Class.hs index e25fe050f1..796f7c8272 100644 --- a/src/Language/Haskell/Liquid/Bare/Class.hs +++ b/src/Language/Haskell/Liquid/Bare/Class.hs @@ -3,6 +3,8 @@ {-# LANGUAGE ParallelListComp #-} {-# LANGUAGE TupleSections #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} + module Language.Haskell.Liquid.Bare.Class ( makeClasses , makeCLaws diff --git a/src/Language/Haskell/Liquid/Bare/DataType.hs b/src/Language/Haskell/Liquid/Bare/DataType.hs index 49891c8157..f743558951 100644 --- a/src/Language/Haskell/Liquid/Bare/DataType.hs +++ b/src/Language/Haskell/Liquid/Bare/DataType.hs @@ -359,10 +359,11 @@ meetDataConSpec :: Bool -> F.TCEmb Ghc.TyCon -> [(Ghc.Var, SpecType)] -> [DataCo -------------------------------------------------------------------------------- meetDataConSpec allowTC emb xts dcs = M.toList $ snd <$> L.foldl' upd dcm0 xts where - dcm0 = M.fromList (dataConSpec' allowTC dcs) + dcm0 = M.fromListWith meetM (dataConSpec' allowTC dcs) upd dcm (x, t) = M.insert x (Ghc.getSrcSpan x, tx') dcm where tx' = maybe t (meetX x t) (M.lookup x dcm) + meetM (l,t) (_,t') = (l, t `F.meet` t') meetX x t (sp', t') = F.notracepp (_msg x t t') $ meetVarTypes emb (pprint x) (Ghc.getSrcSpan x, t) (sp', t') _msg x t t' = "MEET-VAR-TYPES: " ++ showpp (x, t, t') diff --git a/src/Language/Haskell/Liquid/Bare/Elaborate.hs b/src/Language/Haskell/Liquid/Bare/Elaborate.hs index d2cd729159..5a4802f63e 100644 --- a/src/Language/Haskell/Liquid/Bare/Elaborate.hs +++ b/src/Language/Haskell/Liquid/Bare/Elaborate.hs @@ -42,33 +42,12 @@ import Data.Functor.Foldable hiding (Fix) import Data.Functor.Foldable #endif --- import TcRnMonad (TcRn) import Data.Char ( isUpper ) -#if MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) import GHC.Types.Name.Occurrence -#else -import OccName -#endif --- import GHC --- import GhcPlugins ( isDFunId --- ) - --- import FastString --- import CoreSyn --- import PrelNames import qualified Liquid.GHC.API as Ghc (noExtField) - --- import qualified Outputable as O --- import TysWiredIn ( boolTyCon --- , true_RDR --- ) --- import RdrName --- import BasicTypes import Data.Default ( def ) import qualified Data.Maybe as Mb --- import qualified CoreUtils as Utils - -- TODO: make elaboration monadic so typeclass names are unified to something -- that is generated in advance. This can greatly simplify the implementation @@ -535,21 +514,11 @@ elaborateSpecType' partialTp coreToLogic simplify t = hsExpr = buildHsExpr (fixExprToHsExpr (S.fromList origBinders) e) querySpecType :: LHsExpr GhcPs -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,6,5,0) && !MIN_VERSION_GLASGOW_HASKELL(8,8,1,0) - exprWithTySigs = noLoc $ ExprWithTySig - (mkLHsSigWcType (specTypeToLHsType querySpecType)) - hsExpr -#else - exprWithTySigs = noLoc $ ExprWithTySig - Ghc.noExtField + exprWithTySigs = noLocA $ ExprWithTySig + noAnn hsExpr - (mkLHsSigWcType (specTypeToLHsType querySpecType)) -#endif -#else - exprWithTySigs = noLoc ExprWithTySig -#endif - eeWithLamsCore <- GM.elabRnExpr TM_Inst exprWithTySigs + (hsTypeToHsSigWcType (specTypeToLHsType querySpecType)) + eeWithLamsCore <- GM.elabRnExpr exprWithTySigs eeWithLamsCore' <- simplify eeWithLamsCore let (_, tyBinders) = @@ -637,12 +606,8 @@ renameBinderSort f = rename rename ( F.FApp t0 t1 ) = F.FApp (rename t0) (rename t1) -mkHsTyConApp :: IdP (GhcPass p) -> [LHsType (GhcPass p)] -> LHsType (GhcPass p) -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -mkHsTyConApp = nlHsTyConApp -#else +mkHsTyConApp :: IdP GhcPs -> [LHsType GhcPs] -> LHsType GhcPs mkHsTyConApp tyconId tyargs = nlHsTyConApp Prefix tyconId (map HsValArg tyargs) -#endif -- | Embed fixpoint expressions into parsed haskell expressions. -- It allows us to bypass the GHC parser and use arbitrary symbols @@ -702,15 +667,15 @@ fixExprToHsExpr _ e = constantToHsExpr :: F.Constant -> LHsExpr GhcPs -- constantToHsExpr (F.I c) = noLoc (HsLit NoExt (HsInt NoExt (mkIntegralLit c))) constantToHsExpr (F.I i) = - noLoc (HsOverLit Ghc.noExtField (mkHsIntegral (mkIntegralLit i))) + noLocA (HsOverLit noAnn (mkHsIntegral (mkIntegralLit i))) constantToHsExpr (F.R d) = - noLoc (HsOverLit Ghc.noExtField (mkHsFractional (mkFractionalLit d))) + noLocA (HsOverLit noAnn (mkHsFractional (mkTHFractionalLit (toRational d)))) constantToHsExpr _ = todo Nothing "constantToHsExpr: Not sure how to handle constructor L" -- This probably won't work because of the qualifiers bopToHsExpr :: F.Bop -> LHsExpr GhcPs -bopToHsExpr bop = noLoc (HsVar Ghc.noExtField (noLoc (f bop))) +bopToHsExpr bop = noLocA (HsVar Ghc.noExtField (noLocA (f bop))) where f F.Plus = plus_RDR f F.Minus = minus_RDR @@ -721,7 +686,7 @@ bopToHsExpr bop = noLoc (HsVar Ghc.noExtField (noLoc (f bop))) f F.RDiv = GM.prependGHCRealQual (fsLit "/") brelToHsExpr :: F.Brel -> LHsExpr GhcPs -brelToHsExpr brel = noLoc (HsVar Ghc.noExtField (noLoc (f brel))) +brelToHsExpr brel = noLocA (HsVar Ghc.noExtField (noLocA (f brel))) where f F.Eq = mkVarUnqual (mkFastString "==") f F.Gt = gt_RDR @@ -765,19 +730,12 @@ specTypeToLHsType = -- (GM.notracePpr ("varRdr" ++ F.showpp (F.symbol tv)) $ getRdrName tv) (symbolToRdrNameNs tvName (F.symbol tv)) RFunF _ _ (tin, tin') (_, tout) _ - | isClassType tin -> noLoc $ HsQualTy Ghc.noExtField (noLoc [tin']) tout + | isClassType tin -> noLocA $ HsQualTy Ghc.noExtField (Just (noLocA [tin'])) tout | otherwise -> nlHsFunTy tin' tout RImpFF _ _ (_, tin) (_, tout) _ -> nlHsFunTy tin tout - RAllTF (ty_var_value -> (RTV tv)) (_, t) _ -> noLoc $ HsForAllTy + RAllTF (ty_var_value -> (RTV tv)) (_, t) _ -> noLocA $ HsForAllTy Ghc.noExtField -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) - ForallInvis -#endif - [noLoc $ UserTyVar Ghc.noExtField (noLoc $ symbolToRdrNameNs tvName (F.symbol tv))] -#else - (mkHsForAllInvisTele [noLoc $ UserTyVar Ghc.noExtField SpecifiedSpec (noLoc $ symbolToRdrNameNs tvName (F.symbol tv))]) -#endif + (mkHsForAllInvisTele noAnn [noLocA $ UserTyVar noAnn SpecifiedSpec (noLocA $ symbolToRdrNameNs tvName (F.symbol tv))]) t RAllPF _ (_, ty) -> ty RAppF RTyCon { rtc_tc = tc } ts _ _ -> mkHsTyConApp @@ -794,6 +752,6 @@ specTypeToLHsType = RAppTyF (_, t) (_, t') _ -> nlHsAppTy t t' -- YL: todo.. RRTyF _ _ _ (_, t) -> t - RHoleF _ -> noLoc $ HsWildCardTy Ghc.noExtField + RHoleF _ -> noLocA $ HsWildCardTy Ghc.noExtField RExprArgF _ -> todo Nothing "Oops, specTypeToLHsType doesn't know how to handle RExprArg" diff --git a/src/Language/Haskell/Liquid/Bare/Expand.hs b/src/Language/Haskell/Liquid/Bare/Expand.hs index 22f0e67a38..0a4fc9b2ac 100644 --- a/src/Language/Haskell/Liquid/Bare/Expand.hs +++ b/src/Language/Haskell/Liquid/Bare/Expand.hs @@ -6,8 +6,6 @@ {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE OverloadedStrings #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Bare.Expand ( -- * Create alias expansion environment makeRTEnv @@ -58,7 +56,7 @@ import qualified Language.Haskell.Liquid.Bare.Plugged as Bare makeRTEnv :: Bare.Env -> ModName -> Ms.BareSpec -> Bare.ModSpecs -> LogicMap -> BareRTEnv -------------------------------------------------------------------------------- -makeRTEnv env m mySpec iSpecs lmap +makeRTEnv env modName mySpec iSpecs lmap = renameRTArgs $ makeRTAliases tAs $ makeREAliases eAs where tAs = [ t | (_, s) <- specs, t <- Ms.aliases s ] @@ -68,9 +66,9 @@ makeRTEnv env m mySpec iSpecs lmap -- this clearly breaks things if a signature -- contains lmap functions but never gets -- elaborated - else [ specREAlias env m e | (_, xl) <- M.toList (lmSymDefs lmap) + else [ specREAlias env modName e | (_, xl) <- M.toList (lmSymDefs lmap) , let e = lmapEAlias xl ] - specs = (m, mySpec) : M.toList iSpecs + specs = (modName, mySpec) : M.toList iSpecs -- | We apply @renameRTArgs@ *after* expanding each alias-definition, to -- ensure that the substitutions work properly (i.e. don't miss expressions @@ -90,11 +88,11 @@ makeREAliases = graphExpand buildExprEdges f mempty -- | @renameTys@ ensures that @RTAlias@ type parameters have distinct names -- to avoid variable capture e.g. as in T1556.hs renameTys :: RTAlias F.Symbol BareType -> RTAlias F.Symbol BareType -renameTys rt = rt { rtTArgs = ys, rtBody = subts (rtBody rt) (zip xs ys) } +renameTys rt = rt { rtTArgs = ys, rtBody = sbts (rtBody rt) (zip xs ys) } where xs = rtTArgs rt ys = (`F.suffixSymbol` rtName rt) <$> xs - subts = foldl (flip subt) + sbts = foldl (flip subt) renameVV :: RTAlias F.Symbol BareType -> RTAlias F.Symbol BareType @@ -187,8 +185,8 @@ checkCyclicAliases table graph cycleAliasErr :: AliasTable x t -> [F.Symbol] -> Error cycleAliasErr _ [] = panic Nothing "checkCyclicAliases: No type aliases in reported cycle" -cycleAliasErr t scc@(rta:_) = ErrAliasCycle { pos = fst (locate rta) - , acycle = map locate scc } +cycleAliasErr t symList@(rta:_) = ErrAliasCycle { pos = fst (locate rta) + , acycle = map locate symList } where locate sym = ( GM.fSrcSpan $ fromAliasSymbol t sym , pprint sym ) @@ -534,10 +532,10 @@ generalizeVar :: Ghc.Var -> SpecType -> SpecType generalizeVar v t = mkUnivs (zip as (repeat mempty)) [] t where as = filter isGen (freeTyVars t) - (vas,_) = Ghc.splitForAllTys (GM.expandVarType v) + (vas,_) = Ghc.splitForAllTyCoVars (GM.expandVarType v) isGen (RTVar (RTV a) _) = a `elem` vas --- splitForAllTys :: Type -> ([TyVar], Type) +-- splitForAllTyCoVars :: Type -> ([TyVar], Type) -- -- generalize :: (Eq tv) => RType c tv r -> RType c tv r -- generalize t = mkUnivs (freeTyVars t) [] [] t diff --git a/src/Language/Haskell/Liquid/Bare/Measure.hs b/src/Language/Haskell/Liquid/Bare/Measure.hs index d64195de37..8c2121e408 100644 --- a/src/Language/Haskell/Liquid/Bare/Measure.hs +++ b/src/Language/Haskell/Liquid/Bare/Measure.hs @@ -2,8 +2,6 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TupleSections #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -- | This module contains (most of) the code needed to lift Haskell entitites, -- . code- (CoreBind), and data- (Tycon) definitions into the spec level. @@ -65,21 +63,21 @@ makeMeasureDefinition :: Bool -> Bare.TycEnv -> LogicMap -> [Ghc.CoreBind] -> Lo -> Measure LocSpecType Ghc.DataCon makeMeasureDefinition allowTC tycEnv lmap cbs x = case GM.findVarDef (val x) cbs of - Nothing -> Ex.throw $ errHMeas x "Cannot extract measure from haskell function" - Just (v, def) -> Ms.mkM vx vinfo mdef MsLifted (makeUnSorted allowTC (Ghc.varType v) mdef) + Nothing -> Ex.throw $ errHMeas x "Cannot extract measure from haskell function" + Just (v, cexp) -> Ms.mkM vx vinfo mdef MsLifted (makeUnSorted allowTC (Ghc.varType v) mdef) where vx = F.atLoc x (F.symbol v) - mdef = coreToDef' allowTC tycEnv lmap vx v def + mdef = coreToDef' allowTC tycEnv lmap vx v cexp vinfo = GM.varLocInfo (logicType allowTC) v makeUnSorted :: Bool -> Ghc.Type -> [Def LocSpecType Ghc.DataCon] -> UnSortedExprs -makeUnSorted allowTC t defs +makeUnSorted allowTC ty defs | isMeasureType ta = mempty | otherwise = map defToUnSortedExpr defs where - ta = go $ Ghc.expandTypeSynonyms t + ta = go $ Ghc.expandTypeSynonyms ty go (Ghc.ForAllTy _ t) = go t go Ghc.FunTy{ Ghc.ft_arg = p, Ghc.ft_res = t} | isErasable p = go t @@ -89,16 +87,16 @@ makeUnSorted allowTC t defs isMeasureType (Ghc.TyConApp _ ts) = all Ghc.isTyVarTy ts isMeasureType _ = False - defToUnSortedExpr def = (xx:(fst <$> binds def), - Ms.bodyPred (F.mkEApp (measure def) [F.expr xx]) (body def)) + defToUnSortedExpr defn = (xx:(fst <$> binds defn), + Ms.bodyPred (F.mkEApp (measure defn) [F.expr xx]) (body defn)) xx = F.vv $ Just 10000 isErasable = if allowTC then GM.isEmbeddedDictType else Ghc.isClassPred coreToDef' :: Bool -> Bare.TycEnv -> LogicMap -> LocSymbol -> Ghc.Var -> Ghc.CoreExpr -> [Def LocSpecType Ghc.DataCon] -coreToDef' allowTC tycEnv lmap vx v def = - case runToLogic embs lmap dm (errHMeas vx) (coreToDef allowTC vx v def) of +coreToDef' allowTC tycEnv lmap vx v defn = + case runToLogic embs lmap dm (errHMeas vx) (coreToDef allowTC vx v defn) of Right l -> l Left e -> Ex.throw e where @@ -122,8 +120,8 @@ makeMeasureInline :: Bool -> F.TCEmb Ghc.TyCon -> LogicMap -> [Ghc.CoreBind] -> -> (LocSymbol, LMap) makeMeasureInline allowTC embs lmap cbs x = case GM.findVarDef (val x) cbs of - Nothing -> Ex.throw $ errHMeas x "Cannot inline haskell function" - Just (v, def) -> (vx, coreToFun' allowTC embs Nothing lmap vx v def ok) + Nothing -> Ex.throw $ errHMeas x "Cannot inline haskell function" + Just (v, defn) -> (vx, coreToFun' allowTC embs Nothing lmap vx v defn ok) where vx = F.atLoc x (F.symbol v) ok (xs, e) = LMap vx (F.symbol <$> xs) (either id id e) @@ -135,10 +133,10 @@ makeMeasureInline allowTC embs lmap cbs x = coreToFun' :: Bool -> F.TCEmb Ghc.TyCon -> Maybe Bare.DataConMap -> LogicMap -> LocSymbol -> Ghc.Var -> Ghc.CoreExpr -> (([Ghc.Var], Either F.Expr F.Expr) -> a) -> a -coreToFun' allowTC embs dmMb lmap x v def ok = either Ex.throw ok act +coreToFun' allowTC embs dmMb lmap x v defn ok = either Ex.throw ok act where act = runToLogic embs lmap dm err xFun - xFun = coreToFun allowTC x v def + xFun = coreToFun allowTC x v defn err = errHMeas x dm = Mb.fromMaybe mempty dmMb @@ -186,20 +184,20 @@ zipMapMaybe :: (a -> Maybe b) -> [a] -> [(a, b)] zipMapMaybe f = Mb.mapMaybe (\x -> (x, ) <$> f x) hasDataDecl :: ModName -> Ms.BareSpec -> Ghc.TyCon -> HasDataDecl -hasDataDecl mod spec - = \tc -> F.notracepp (msg tc) $ M.lookupDefault def (tcName tc) decls +hasDataDecl modName spec + = \tc -> F.notracepp (msg tc) $ M.lookupDefault defn (tcName tc) decls where msg tc = "hasDataDecl " ++ show (tcName tc) - def = NoDecl Nothing - tcName = fmap (qualifiedDataName mod) . tyConDataName True - dcName = qualifiedDataName mod . tycName + defn = NoDecl Nothing + tcName = fmap (qualifiedDataName modName) . tyConDataName True + dcName = qualifiedDataName modName . tycName decls = M.fromList [ (Just dn, hasDecl d) | d <- Ms.dataDecls spec , let dn = dcName d] qualifiedDataName :: ModName -> DataName -> DataName -qualifiedDataName mod (DnName lx) = DnName (qualifyModName mod <$> lx) -qualifiedDataName mod (DnCon lx) = DnCon (qualifyModName mod <$> lx) +qualifiedDataName modName (DnName lx) = DnName (qualifyModName modName <$> lx) +qualifiedDataName modName (DnCon lx) = DnCon (qualifyModName modName <$> lx) {-tyConDataDecl :: {tc:TyCon | isAlgTyCon tc} -> Maybe DataDecl @-} tyConDataDecl :: ((Ghc.TyCon, DataName), HasDataDecl) -> Maybe DataDecl @@ -236,11 +234,11 @@ dataConDecl d = {- F.notracepp msg $ -} DataCtor dx (F.symbol <$> as) [] xts xts = [(Bare.makeDataConSelector Nothing d i, RT.bareOfType t) | (i, t) <- its ] dx = F.symbol <$> GM.locNamedThing d its = zip [1..] ts - (as,_ps,ts,t) = Ghc.dataConSig d - outT = Just (RT.bareOfType t :: BareType) + (as,_ps,ts,ty) = Ghc.dataConSig d + outT = Just (RT.bareOfType ty :: BareType) _outT :: Maybe BareType _outT - | isGadt = Just (RT.bareOfType t) + | isGadt = Just (RT.bareOfType ty) | otherwise = Nothing @@ -295,18 +293,18 @@ dataConSel permitTC dc n (Proj i) = mkArrow (zip as (repeat mempty)) [] [] [xt] -- bkDataCon :: DataCon -> Int -> ([RTVar RTyVar RSort], [SpecType], (Symbol, SpecType, RReft)) bkDataCon :: (F.Reftable (RTProp RTyCon RTyVar r), PPrint r, F.Reftable r) => Bool -> Ghc.DataCon -> Int -> ([RTVar RTyVar RSort], [RRType r], (F.Symbol, RFInfo, RRType r, r)) -bkDataCon permitTC dc nFlds = (as, ts, (F.dummySymbol, classRFInfo permitTC, t, mempty)) +bkDataCon permitTC dcn nFlds = (as, ts, (F.dummySymbol, classRFInfo permitTC, t, mempty)) where ts = RT.ofType <$> Misc.takeLast nFlds (map Ghc.irrelevantMult _ts) t = -- Misc.traceShow ("bkDataConResult" ++ GM.showPpr (dc, _t, _t0)) $ RT.ofType $ Ghc.mkTyConApp tc tArgs' as = makeRTVar . RT.rTyVar <$> (αs ++ αs') - ((αs,αs',_,_,_ts,_t), _t0) = hammer dc + ((αs,αs',_,_,_ts,_t), _t0) = hammer dcn tArgs' = take (nArgs - nVars) tArgs ++ (Ghc.mkTyVarTy <$> αs) nVars = length αs nArgs = length tArgs (tc, tArgs) = Mb.fromMaybe err (Ghc.splitTyConApp_maybe _t) - err = GM.namedPanic dc ("Cannot split result type of DataCon " ++ show dc) + err = GM.namedPanic dcn ("Cannot split result type of DataCon " ++ show dcn) hammer dc = (Ghc.dataConFullSig dc, Ghc.varType . Ghc.dataConWorkId $ dc) data DataConSel = Check | Proj Int @@ -490,7 +488,7 @@ toBound v x (vs, Left p) = (x', Bound x' fvs ps xs p) (ps , xs) = (txp <$> ps', txx <$> xs') txp v = (dummyLoc $ simpleSymbolVar v, RT.ofType $ varType v) txx v = (dummyLoc $ symbol v, RT.ofType $ varType v) - fvs = (((`RVar` mempty) . RTV) <$> fst (splitForAllTys $ varType v)) :: [RSort] + fvs = (((`RVar` mempty) . RTV) <$> fst (splitForAllTyCoVars $ varType v)) :: [RSort] toBound v x (vs, Right e) = toBound v x (vs, Left e) diff --git a/src/Language/Haskell/Liquid/Bare/Misc.hs b/src/Language/Haskell/Liquid/Bare/Misc.hs index b44e4f17a3..d6998e8468 100644 --- a/src/Language/Haskell/Liquid/Bare/Misc.hs +++ b/src/Language/Haskell/Liquid/Bare/Misc.hs @@ -1,6 +1,5 @@ {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Bare.Misc ( joinVar @@ -167,7 +166,7 @@ mapTyRVar α a s@(MTVST αas err) Nothing -> return $ MTVST ((α,a):αas) err matchKindArgs' :: [Type] -> [SpecType] -> [SpecType] -matchKindArgs' ts1 ts2 = reverse $ go (reverse ts1) (reverse ts2) +matchKindArgs' ts1' = reverse . go (reverse ts1') . reverse where go (_:ts1) (t2:ts2) = t2:go ts1 ts2 go ts [] | all isKind ts @@ -176,7 +175,7 @@ matchKindArgs' ts1 ts2 = reverse $ go (reverse ts1) (reverse ts2) matchKindArgs :: [SpecType] -> [SpecType] -> [SpecType] -matchKindArgs ts1 ts2 = reverse $ go (reverse ts1) (reverse ts2) +matchKindArgs ts1' = reverse . go (reverse ts1') . reverse where go (_:ts1) (t2:ts2) = t2:go ts1 ts2 go ts [] = ts @@ -193,7 +192,7 @@ varFunSymbol = dummyLoc . F.symbol . idDataCon isFunVar :: Id -> Bool isFunVar v = isDataConId v && not (null αs) && Mb.isNothing tf where - (αs, t) = splitForAllTys $ varType v + (αs, t) = splitForAllTyCoVars $ varType v tf = splitFunTy_maybe t -- the Vars we lookup in GHC don't always have the same tyvars as the Vars diff --git a/src/Language/Haskell/Liquid/Bare/Plugged.hs b/src/Language/Haskell/Liquid/Bare/Plugged.hs index 8a1f0ad56f..1d2f73820f 100644 --- a/src/Language/Haskell/Liquid/Bare/Plugged.hs +++ b/src/Language/Haskell/Liquid/Bare/Plugged.hs @@ -1,7 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PartialTypeSignatures #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-record-updates #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.Bare.Plugged ( makePluggedSig @@ -159,7 +160,7 @@ plugHolesOld, plugHolesNew -> LocSpecType -- NOTE: this use of toType is safe as rt' is derived from t. -plugHolesOld allowTC tce tyi x f t0 zz@(Loc l l' st0) +plugHolesOld allowTC tce tyi xx f t0 zz@(Loc l l' st0) = Loc l l' . mkArrow (zip (updateRTVar <$> αs') rs) ps' [] [] . makeCls cs' @@ -175,22 +176,22 @@ plugHolesOld allowTC tce tyi x f t0 zz@(Loc l l' st0) su' = [(y, RVar (rTyVar x) ()) | (x, y) <- tyvsmap] :: [(RTyVar, RSort)] coSub = M.fromList [(F.symbol y, F.FObj (F.symbol x)) | (y, x) <- su] ps' = fmap (subts su') <$> ps - cs' = [(F.dummySymbol, RApp c ts [] mempty) | (c, ts) <- cs ] + cs' = [(F.dummySymbol, RApp c ts [] mempty) | (c, ts) <- cs2 ] (αs', rs) = unzip αs - (αs,_,cs,rt) = bkUnivClass (F.notracepp "hs-spec" $ ofType (Ghc.expandTypeSynonyms t0) :: SpecType) + (αs,_,cs2,rt) = bkUnivClass (F.notracepp "hs-spec" $ ofType (Ghc.expandTypeSynonyms t0) :: SpecType) (_,ps,_ ,st) = bkUnivClass (F.notracepp "lq-spec" st0) makeCls cs t = foldr (uncurry (rFun' (classRFInfo allowTC))) t cs - err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint x) + err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint xx) (text "Plugged Init types old") (pprint $ Ghc.expandTypeSynonyms t0) (pprint $ toRSort st0) (Just (hsT, lqT)) - (Ghc.getSrcSpan x) + (Ghc.getSrcSpan xx) -plugHolesNew allowTC@False tce tyi x f t0 zz@(Loc l l' st0) +plugHolesNew allowTC@False tce tyi xx f t0 zz@(Loc l l' st0) = Loc l l' . mkArrow (zip (updateRTVar <$> as'') rs) ps [] [] . makeCls cs' @@ -200,24 +201,24 @@ plugHolesNew allowTC@False tce tyi x f t0 zz@(Loc l l' st0) rt' = tx rt as'' = subRTVar su <$> as' (as',rs) = unzip as - cs' = [ (F.dummySymbol, ct) | (c, t) <- cs, let ct = tx (RApp c t [] mempty) ] + cs' = [ (F.dummySymbol, ct) | (c, t) <- tyCons, let ct = tx (RApp c t [] mempty) ] tx = subts su su = case Bare.runMapTyVars allowTC (toType False rt) st err of Left e -> Ex.throw e Right s -> [ (rTyVar x, y) | (x, y) <- Bare.vmap s] - (as,_,cs,rt) = bkUnivClass (ofType (Ghc.expandTypeSynonyms t0) :: SpecType) + (as,_,tyCons,rt) = bkUnivClass (ofType (Ghc.expandTypeSynonyms t0) :: SpecType) (_,ps,_ ,st) = bkUnivClass st0 makeCls cs t = foldr (uncurry (rFun' (classRFInfo allowTC))) t cs - err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint x) + err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint xx) (text "Plugged Init types new") (pprint $ Ghc.expandTypeSynonyms t0) (pprint $ toRSort st0) (Just (hsT, lqT)) - (Ghc.getSrcSpan x) + (Ghc.getSrcSpan xx) -plugHolesNew allowTC@True tce tyi x f t0 zz@(Loc l l' st0) +plugHolesNew allowTC@True tce tyi a f t0 zz@(Loc l l' st0) = Loc l l' . mkArrow (zip (updateRTVar <$> as'') rs) ps [] (if length cs > length cs' then cs else cs') -- . makeCls cs' @@ -237,12 +238,12 @@ plugHolesNew allowTC@True tce tyi x f t0 zz@(Loc l l' st0) cs = [ (x, classRFInfo allowTC, t, r) | (x,t,r)<-cs0] cs' = [ (x, classRFInfo allowTC, t, r) | (x,t,r)<-cs0'] - err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint x) + err hsT lqT = ErrMismatch (GM.fSrcSpan zz) (pprint a) (text "Plugged Init types new") (pprint $ Ghc.expandTypeSynonyms t0) (pprint $ toRSort st0) (Just (hsT, lqT)) - (Ghc.getSrcSpan x) + (Ghc.getSrcSpan a) subRTVar :: [(RTyVar, RTyVar)] -> SpecRTVar -> SpecRTVar subRTVar su a@(RTVar v i) = Mb.maybe a (`RTVar` i) (lookup v su) @@ -251,9 +252,9 @@ goPlug :: F.TCEmb Ghc.TyCon -> Bare.TyConMap -> (Doc -> Doc -> Error) -> (SpecTy -> SpecType goPlug tce tyi err f = go where - go t (RHole r) = (addHoles t') { rt_reft = f t r } + go st (RHole r) = (addHoles t') { rt_reft = f st r } where - t' = everywhere (mkT $ addRefs tce tyi) t + t' = everywhere (mkT $ addRefs tce tyi) st addHoles = everywhere (mkT addHole) -- NOTE: make sure we only add holes to RVar and RApp (NOT RFun) addHole :: SpecType -> SpecType diff --git a/src/Language/Haskell/Liquid/Bare/Resolve.hs b/src/Language/Haskell/Liquid/Bare/Resolve.hs index 35f9892b18..03d4c5d853 100644 --- a/src/Language/Haskell/Liquid/Bare/Resolve.hs +++ b/src/Language/Haskell/Liquid/Bare/Resolve.hs @@ -11,8 +11,6 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TupleSections #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Bare.Resolve ( -- * Creating the Environment makeEnv @@ -63,7 +61,6 @@ import qualified Data.HashMap.Strict as M import qualified Data.Text as T import qualified Text.PrettyPrint.HughesPJ as PJ -import qualified Language.Fixpoint.Utils.Files as F import qualified Language.Fixpoint.Types as F import qualified Language.Fixpoint.Types.Visitor as F import qualified Language.Fixpoint.Misc as Misc @@ -71,7 +68,6 @@ import qualified Liquid.GHC.API as Ghc import qualified Liquid.GHC.Misc as GM import qualified Language.Haskell.Liquid.Misc as Misc import qualified Language.Haskell.Liquid.Types.RefType as RT -import qualified Language.Haskell.Liquid.Types.Errors as Errors import Language.Haskell.Liquid.Types.Types import Language.Haskell.Liquid.Measure (BareSpec) import Language.Haskell.Liquid.Types.Specs hiding (BareSpec) @@ -125,8 +121,8 @@ localBinds = concatMap (bgo S.empty) where add x g = maybe g (`S.insert` g) (localKey x) adds b g = foldr add g (Ghc.bindersOf b) - take x g = maybe [] (\k -> [x | not (S.member k g)]) (localKey x) - pgo g (x, e) = take x g ++ go (add x g) e + take' x g = maybe [] (\k -> [x | not (S.member k g)]) (localKey x) + pgo g (x, e) = take' x g ++ go (add x g) e bgo g (Ghc.NonRec x e) = pgo g (x, e) bgo g (Ghc.Rec xes) = concatMap (pgo g) xes go g (Ghc.App e a) = concatMap (go g) [e, a] @@ -134,7 +130,7 @@ localBinds = concatMap (bgo S.empty) go g (Ghc.Let b e) = bgo g b ++ go (adds b g) e go g (Ghc.Tick _ e) = go g e go g (Ghc.Cast e _) = go g e - go g (Ghc.Case e _ _ cs) = go g e ++ concatMap (go g . Misc.thd3) cs + go g (Ghc.Case e _ _ cs) = go g e ++ concatMap (go g . (\(Ghc.Alt _ _ e') -> e')) cs go _ (Ghc.Var _) = [] go _ _ = [] @@ -640,37 +636,18 @@ rankedThings f ias = case Misc.sortOn fst (Misc.groupList ibs) of ------------------------------------------------------------------------------- lookupTyThing :: Env -> ModName -> LocSymbol -> [((Int, F.Symbol), Ghc.TyThing)] ------------------------------------------------------------------------------- -lookupTyThing env name lsym = [ (k, t) | (k, ts) <- ordMatches, t <- ts] +lookupTyThing env mdname lsym = [ (k, t) | (k, ts) <- ordMatches, t <- ts] where ordMatches = Misc.sortOn fst (Misc.groupList matches) matches = myTracepp ("matches-" ++ msg) [ ((k, m), t) | (m, t) <- lookupThings env x - , k <- myTracepp msg $ mm nameSym m mods ] - msg = "lookupTyThing: " ++ F.showpp (lsym, x, mods) - (x, mods) = symbolModules env (F.val lsym) - nameSym = F.symbol name - allowExt = allowExtResolution env lsym - mm name m mods = myTracepp ("matchMod: " ++ F.showpp (lsym, name, m, mods, allowExt)) $ - matchMod env name m allowExt mods - --- | [NOTE:External-Resolution] @allowExtResolution@ determines whether a @LocSymbol@ --- can be resolved by a @TyThing@ that is _outside_ the module corresponding to @LocSymbol@. --- We need to allow this, e.g. to resolve names like @Data.Set.Set@ with @Data.Set.Internal.Set@, --- but should do so ONLY when the LocSymbol comes from a "hand-written" .spec file or --- something from the LH prelude. Other names, e.g. from "machine-generated" .bspec files --- should already be FULLY-qualified to to their actual definition (e.g. Data.Set.Internal.Set) --- and so we should DISALLOW external-resolution in such cases. - -allowExtResolution :: Env -> LocSymbol -> Bool -allowExtResolution env lx = case fileMb of - Nothing -> True - Just f -> myTracepp ("allowExt: " ++ show (f, tgtFile)) - $ f == tgtFile || Misc.isIncludeFile incDir f || F.isExtFile F.Spec f - where - tgtFile = _giTarget (reSrc env) - incDir = _giIncDir (reSrc env) - fileMb = Errors.srcSpanFileMb (GM.fSrcSpan lx) + , k <- myTracepp msg $ mm nameSym m mds ] + msg = "lookupTyThing: " ++ F.showpp (lsym, x, mds) + (x, mds) = symbolModules env (F.val lsym) + nameSym = F.symbol mdname + mm name m mods = myTracepp ("matchMod: " ++ F.showpp (lsym, name, m, mods)) $ + matchMod env name m mods lookupThings :: Env -> F.Symbol -> [(F.Symbol, Ghc.TyThing)] lookupThings env x = myTracepp ("lookupThings: " ++ F.showpp x) @@ -678,8 +655,8 @@ lookupThings env x = myTracepp ("lookupThings: " ++ F.showpp x) where get z = M.lookup z (_reTyThings env) -matchMod :: Env -> F.Symbol -> F.Symbol -> Bool -> Maybe [F.Symbol] -> [Int] -matchMod env tgtName defName allowExt = go +matchMod :: Env -> F.Symbol -> F.Symbol -> Maybe [F.Symbol] -> [Int] +matchMod env tgtName defName = go where go Nothing -- Score UNQUALIFIED names | defName == tgtName = [0] -- prioritize names defined in *this* module @@ -690,7 +667,7 @@ matchMod env tgtName defName allowExt = go | isEmptySymbol defName && ms == [tgtName] = [0] -- local variable, see tests-names-pos-local00.hs | ms == [defName] = [1] - | allowExt && isExt = [matchImp env defName 2] -- to allow matching re-exported names e.g. Data.Set.union for Data.Set.Internal.union + | isExt = [matchImp env defName 2] -- to allow matching re-exported names e.g. Data.Set.union for Data.Set.Internal.union | otherwise = [] where isExt = any (`isParentModuleOf` defName) ms @@ -776,9 +753,9 @@ maybeResolveSym env name kind x = case resolveLocSym env name kind x of -- | @ofBareType@ and @ofBareTypeE@ should be the _only_ @SpecType@ constructors ------------------------------------------------------------------------------- ofBareType :: Env -> ModName -> F.SourcePos -> Maybe [PVar BSort] -> BareType -> SpecType -ofBareType env name l ps t = either fail id (ofBareTypeE env name l ps t) +ofBareType env name l ps t = either fail' id (ofBareTypeE env name l ps t) where - fail = Ex.throw + fail' = Ex.throw -- fail = Misc.errorP "error-ofBareType" . F.showpp ofBareTypeE :: Env -> ModName -> F.SourcePos -> Maybe [PVar BSort] -> BareType -> Lookup SpecType @@ -845,7 +822,7 @@ type Expandable r = ( PPrint r ofBRType :: (Expandable r) => Env -> ModName -> ([F.Symbol] -> r -> r) -> F.SourcePos -> BRType r -> Lookup (RRType r) -ofBRType env name f l t = go [] t +ofBRType env name f l = go [] where goReft bs r = return (f bs r) goRImpF bs x i t1 t2 r = RImpF x i <$> (rebind x <$> go bs t1) <*> go (x:bs) t2 <*> goReft bs r @@ -967,13 +944,13 @@ txRefSort :: TyConMap -> F.TCEmb Ghc.TyCon -> LocSpecType -> LocSpecType txRefSort tyi tce t = F.atLoc t $ mapBot (addSymSort (GM.fSrcSpan t) tce tyi) (val t) addSymSort :: Ghc.SrcSpan -> F.TCEmb Ghc.TyCon -> TyConMap -> SpecType -> SpecType -addSymSort sp tce tyi (RApp rc@RTyCon{} ts rs r) - = RApp rc ts (zipWith3 (addSymSortRef sp rc) pvs rargs [1..]) r' +addSymSort sp tce tyi (RApp rc@RTyCon{} ts rs rr) + = RApp rc ts (zipWith3 (addSymSortRef sp rc) pvs rargs [1..]) r2 where (_, pvs) = RT.appRTyCon tce tyi rc ts -- pvs = rTyConPVs rc' (rargs, rrest) = splitAt (length pvs) rs - r' = L.foldl' go r rrest + r2 = L.foldl' go rr rrest go r (RProp _ (RHole r')) = r' `F.meet` r go r (RProp _ t' ) = let r' = Mb.fromMaybe mempty (stripRTypeBase t') in r `F.meet` r' @@ -1014,7 +991,7 @@ addSymSortRef' _ _ _ p (RProp s t) xs = spliceArgs "addSymSortRef 2" s p spliceArgs :: String -> [(F.Symbol, b)] -> PVar t -> [(F.Symbol, t)] -spliceArgs msg s p = go (fst <$> s) (pargs p) +spliceArgs msg syms p = go (fst <$> syms) (pargs p) where go [] [] = [] go [] ((s,x,_):as) = (x, s):go [] as diff --git a/src/Language/Haskell/Liquid/Bare/ToBare.hs b/src/Language/Haskell/Liquid/Bare/ToBare.hs index 5e1f846f08..a34b1f0eba 100644 --- a/src/Language/Haskell/Liquid/Bare/ToBare.hs +++ b/src/Language/Haskell/Liquid/Bare/ToBare.hs @@ -1,8 +1,6 @@ -- | This module contains functions that convert things -- to their `Bare` versions, e.g. SpecType -> BareType etc. -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Bare.ToBare ( -- * Types specToBare @@ -85,7 +83,7 @@ txRTV :: (c1 -> c2) -> (tv1 -> tv2) -> RTVU c1 tv1 -> RTVU c2 tv2 txRTV cF vF (RTVar α z) = RTVar (vF α) (txRType cF vF <$> z) txPV :: (c1 -> c2) -> (tv1 -> tv2) -> PVU c1 tv1 -> PVU c2 tv2 -txPV cF vF (PV x k y txes) = PV x k' y txes' +txPV cF vF (PV sym k y txes) = PV sym k' y txes' where txes' = [ (tx t, x, e) | (t, x, e) <- txes] k' = tx <$> k diff --git a/src/Language/Haskell/Liquid/Bare/Typeclass.hs b/src/Language/Haskell/Liquid/Bare/Typeclass.hs index 7d485d2213..08d37d0c1a 100644 --- a/src/Language/Haskell/Liquid/Bare/Typeclass.hs +++ b/src/Language/Haskell/Liquid/Bare/Typeclass.hs @@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.Bare.Typeclass ( compileClasses @@ -48,7 +48,7 @@ compileClasses -> [(ModName, Ms.BareSpec)] -> (Ms.BareSpec, [(Ghc.ClsInst, [Ghc.Var])]) compileClasses src env (name, spec) rest = - (spec { sigs = sigs' } <> clsSpec, instmethods) + (spec { sigs = sigsNew } <> clsSpec, instmethods) where clsSpec = mempty { dataDecls = clsDecls @@ -65,13 +65,13 @@ compileClasses src env (name, spec) rest = } clsDecls = makeClassDataDecl (M.toList refinedMethods) -- class methods - (refinedMethods, sigs') = foldr grabClassSig (mempty, mempty) (sigs spec) + (refinedMethods, sigsNew) = foldr grabClassSig (mempty, mempty) (sigs spec) grabClassSig :: (F.LocSymbol, ty) -> (M.HashMap Ghc.Class [(Ghc.Id, ty)], [(F.LocSymbol, ty)]) -> (M.HashMap Ghc.Class [(Ghc.Id, ty)], [(F.LocSymbol, ty)]) - grabClassSig sig@(lsym, ref) (refs, sigs') = case clsOp of - Nothing -> (refs, sig : sigs') + grabClassSig sigPair@(lsym, ref) (refs, sigs') = case clsOp of + Nothing -> (refs, sigPair : sigs') Just (cls, sig) -> (M.alter (merge sig) cls refs, sigs') where clsOp = do @@ -234,19 +234,19 @@ elaborateClassDcp coreToLg simplifier dcp = do t -- YL: is this redundant if we already have strengthenClassSel? strengthenTy :: F.Symbol -> SpecType -> SpecType - strengthenTy x t = mkUnivs tvs pvs (RFun z i cls (t' `RT.strengthen` mt) r) + strengthenTy x t = mkUnivs tvs pvs (RFun z i clas (t' `RT.strengthen` mt) r) where - (tvs, pvs, RFun z i cls t' r) = bkUniv t + (tvs, pvs, RFun z i clas t' r) = bkUniv t vv = rTypeValueVar t' mt = RT.uReft (vv, F.PAtom F.Eq (F.EVar vv) (F.EApp (F.EVar x) (F.EVar z))) elaborateMethod :: F.Symbol -> S.HashSet F.Symbol -> SpecType -> SpecType -elaborateMethod dc methods t = mapExprReft - (\_ -> substClassOpBinding tcbind dc methods) - t +elaborateMethod dc methods st = mapExprReft + (\_ -> substClassOpBinding tcbindSym dc methods) + st where - tcbind = grabtcbind t + tcbindSym = grabtcbind st grabtcbind :: SpecType -> F.Symbol grabtcbind t = F.notracepp "grabtcbind" @@ -263,7 +263,7 @@ elaborateMethod dc methods t = mapExprReft -- After: Funcctor.fmap ($p1Applicative##GHC.Base.Applicative) substClassOpBinding :: F.Symbol -> F.Symbol -> S.HashSet F.Symbol -> F.Expr -> F.Expr -substClassOpBinding tcbind dc methods e = go e +substClassOpBinding tcbind dc methods = go where go :: F.Expr -> F.Expr go (F.EApp e0 e1) @@ -404,7 +404,7 @@ makeClassAuxTypesOne elab (ldcp, inst, methods) = subst ((a, ta):su) t = subsTyVarMeet' (a, ta) (subst su t) substAuxMethod :: F.Symbol -> M.HashMap F.Symbol F.Symbol -> F.Expr -> F.Expr -substAuxMethod dfun methods e = F.notracepp "substAuxMethod" $ go e +substAuxMethod dfun methods = F.notracepp "substAuxMethod" . go where go :: F.Expr -> F.Expr go (F.EApp e0 e1) | F.EVar x <- F.notracepp "e0" e0 diff --git a/src/Language/Haskell/Liquid/Constraint/Constraint.hs b/src/Language/Haskell/Liquid/Constraint/Constraint.hs index e839a6d2a9..0e3e9f6dbf 100644 --- a/src/Language/Haskell/Liquid/Constraint/Constraint.hs +++ b/src/Language/Haskell/Liquid/Constraint/Constraint.hs @@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleInstances #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- TODO: what exactly is the purpose of this module? What do these functions do? @@ -37,18 +37,18 @@ constraintToLogicOne γ binds (last (fst <$> xts), r)) | xts <- xss] where - xts = init binds - (xs, ts) = unzip xts + symRts = init binds + (xs, ts) = unzip symRts r = snd $ last binds xss = combinations ((\t -> [(x, t) | x <- localBindsOfType t γ]) <$> ts) subConstraintToLogicOne :: (Foldable t, Reftable r, Reftable r1) => t (Symbol, (Symbol, RType t1 t2 r)) -> (Symbol, (Symbol, RType t3 t4 r1)) -> Expr -subConstraintToLogicOne xts (x', (x, t)) = PImp (pAnd rs) r +subConstraintToLogicOne xts (sym', (sym, rt)) = PImp (pAnd rs) r where - (rs , su) = foldl go ([], []) xts - ([r], _ ) = go ([], su) (x', (x, t)) + (rs , symExprs) = foldl go ([], []) xts + ([r], _ ) = go ([], symExprs) (sym', (sym, rt)) go (acc, su) (x', (x, t)) = let (Reft(v, p)) = toReft (fromMaybe mempty (stripRTypeBase t)) su' = (x', EVar x):(v, EVar x) : su in diff --git a/src/Language/Haskell/Liquid/Constraint/Env.hs b/src/Language/Haskell/Liquid/Constraint/Env.hs index 02a9c60748..71fb21fa54 100644 --- a/src/Language/Haskell/Liquid/Constraint/Env.hs +++ b/src/Language/Haskell/Liquid/Constraint/Env.hs @@ -7,8 +7,6 @@ {-# LANGUAGE ImplicitParams #-} {-# LANGUAGE PartialTypeSignatures #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -- | This module defines the representation for Environments needed -- during constraint generation. @@ -151,7 +149,7 @@ addBinders γ0 x' cbs = foldM (++=) (γ0 -= x') [("addBinders", x, t) | (x, t) addBind :: SrcSpan -> F.Symbol -> F.SortedReft -> CG ((F.Symbol, F.Sort), F.BindId) addBind l x r = do st <- get - let (i, bs') = F.insertBindEnv x r (binds st) + let (i, bs') = F.insertBindEnv x r (Ci l Nothing Nothing) (binds st) put $ st { binds = bs' } { bindSpans = M.insert i l (bindSpans st) } return ((x, F.sr_sort r), {- traceShow ("addBind: " ++ showpp x) -} i) @@ -165,8 +163,8 @@ addCGEnv tx γ (eMsg, x, REx y tyy tyx) = do γ' <- addCGEnv tx γ (eMsg, y', tyy) addCGEnv tx γ' (eMsg, x, tyx `F.subst1` (y, F.EVar y')) -addCGEnv tx γ (eMsg, x, RAllE yy tyy tyx) - = addCGEnv tx γ (eMsg, x, t) +addCGEnv tx γ (eMsg, sym, RAllE yy tyy tyx) + = addCGEnv tx γ (eMsg, sym, t) where xs = localBindsOfType tyy (renv γ) t = L.foldl' F.meet ttrue [ tyx' `F.subst1` (yy, F.EVar x) | x <- xs] diff --git a/src/Language/Haskell/Liquid/Constraint/Generate.hs b/src/Language/Haskell/Liquid/Constraint/Generate.hs index b6effde86a..9a205382c4 100644 --- a/src/Language/Haskell/Liquid/Constraint/Generate.hs +++ b/src/Language/Haskell/Liquid/Constraint/Generate.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE StandaloneDeriving #-} @@ -13,17 +12,13 @@ {-# LANGUAGE ImplicitParams #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- | This module defines the representation of Subtyping and WF Constraints, -- and the code for syntax-directed constraint generation. module Language.Haskell.Liquid.Constraint.Generate ( generateConstraints, generateConstraintsWithEnv, caseEnv, consE ) where -#if !MIN_VERSION_base(4,14,0) -import Control.Monad.Fail -#endif - import Prelude hiding (error) import GHC.Stack import Liquid.GHC.API as Ghc hiding ( panic @@ -54,7 +49,6 @@ import Language.Haskell.Liquid.Constraint.Monad import Language.Haskell.Liquid.Constraint.Split import Language.Haskell.Liquid.Constraint.Relational (consAssmRel, consRelTop) import Language.Haskell.Liquid.Types.Dictionaries -import Liquid.GHC.Play (isHoleVar) import qualified Liquid.GHC.Resugar as Rs import qualified Liquid.GHC.SpanStack as Sp import qualified Liquid.GHC.Misc as GM -- ( isInternal, collectArguments, tickSrcSpan, showPpr ) @@ -90,9 +84,11 @@ consAct γ cfg info = do let gSrc = giSrc info when (gradual cfg) (mapM_ (addW . WfC γ . val . snd) (gsTySigs sSpc ++ gsAsmSigs sSpc)) γ' <- foldM (consCBTop cfg info) γ (giCbs gSrc) + -- Relational Checking: the following only runs when the list of relational specs is not empty (ψ, γ'') <- foldM (consAssmRel cfg info) ([], γ') (gsAsmRel sSpc ++ gsRelation sSpc) relErrs <- gets relWf mapM_ (consRelTop cfg info cconsE consE γ'' ψ) (if null relErrs then gsRelation sSpc else []) + -- End: Relational Checking mapM_ (consClass γ) (gsMethods $ gsSig $ giSpec info) hcs <- gets hsCs hws <- gets hsWfs @@ -135,7 +131,7 @@ makeDecrIndex (x, Asserted t, args) makeDecrIndex _ = return [] makeDecrIndexTy :: Var -> SpecType -> [Var] -> CG (Either (TError t) [Int]) -makeDecrIndexTy x t args +makeDecrIndexTy x st args = do spDecr <- gets specDecr autosz <- gets autoSize hint <- checkHint' autosz (L.lookup x spDecr) @@ -147,7 +143,7 @@ makeDecrIndexTy x t args tvs = zip ts args msg = ErrTermin (getSrcSpan x) [F.pprint x] (text "No decreasing parameter") cenv = makeNumEnv ts - trep = toRTypeRep $ unOCons t + trep = toRTypeRep $ unOCons st p autosz (t, v) = isDecreasing autosz cenv t && not (isIdTRecBound v) checkHint' autosz = checkHint x ts (isDecreasing autosz cenv) @@ -259,9 +255,9 @@ consCBLet γ cb = do -------------------------------------------------------------------------------- consCBTop :: Config -> TargetInfo -> CGEnv -> CoreBind -> CG CGEnv -------------------------------------------------------------------------------- -consCBTop cfg info γ cb +consCBTop cfg info cgenv cb | all (trustVar cfg info) xs - = foldM addB γ xs + = foldM addB cgenv xs where xs = bindersOf cb tt = trueTy (typeclass cfg) . varType @@ -307,32 +303,32 @@ consCBSizedTys γ xes = do xets <- forM xes $ \(x, e) -> fmap (x, e,) (varTemplate γ (x, Just e)) autoenv <- gets autoSize ts <- mapM (T.mapM refreshArgs) (thd3 <$> xets) - let vs = zipWith collectArgs ts es - is <- mapM makeDecrIndex (zip3 xs ts vs) >>= checkSameLens - let xeets = (\vis -> [(vis, x) | x <- zip3 xs is $ map unTemplate ts]) <$> zip vs is - _ <- mapM checkIndex (zip4 xs vs ts is) >>= checkEqTypes . L.transpose + let vs = zipWith collectArgs' ts es + is <- mapM makeDecrIndex (zip3 vars ts vs) >>= checkSameLens + let xeets = (\vis -> [(vis, x) | x <- zip3 vars is $ map unTemplate ts]) <$> zip vs is + _ <- mapM checkIndex (zip4 vars vs ts is) >>= checkEqTypes . L.transpose let rts = (recType autoenv <$>) <$> xeets - let xts = zip xs ts + let xts = zip vars ts γ' <- foldM extender γ xts - let γs = zipWith makeRecInvariants [γ' `setTRec` zip xs rts' | rts' <- rts] (filter (not . noMakeRec) <$> vs) - let xets' = zip3 xs es ts + let γs = zipWith makeRecInvariants [γ' `setTRec` zip vars rts' | rts' <- rts] (filter (not . noMakeRec) <$> vs) + let xets' = zip3 vars es ts mapM_ (uncurry $ consBind True) (zip γs xets') return γ' where noMakeRec = if allowTC then GM.isEmbeddedDictVar else GM.isPredVar allowTC = typeclass (getConfig γ) - (xs, es) = unzip xes - dxs = F.pprint <$> xs - collectArgs = GM.collectArguments . length . ty_binds . toRTypeRep . unOCons . unTemplate + (vars, es) = unzip xes + dxs = F.pprint <$> vars + collectArgs' = GM.collectArguments . length . ty_binds . toRTypeRep . unOCons . unTemplate checkEqTypes :: [[Maybe SpecType]] -> CG [[SpecType]] - checkEqTypes x = mapM (checkAll err1 toRSort) (catMaybes <$> x) - checkSameLens = checkAll err2 length + checkEqTypes x = mapM (checkAll' err1 toRSort) (catMaybes <$> x) + checkSameLens = checkAll' err2 length err1 = ErrTermin loc dxs $ text "The decreasing parameters should be of same type" err2 = ErrTermin loc dxs $ text "All Recursive functions should have the same number of decreasing parameters" - loc = getSrcSpan (head xs) + loc = getSrcSpan (head vars) - checkAll _ _ [] = return [] - checkAll err f (x:xs) + checkAll' _ _ [] = return [] + checkAll' err f (x:xs) | all (== f x) (f <$> xs) = return (x:xs) | otherwise = addWarning err >> return [] @@ -340,7 +336,7 @@ consCBWithExprs :: CGEnv -> [(Var, CoreExpr)] -> CG CGEnv consCBWithExprs γ xes = do xets <- forM xes $ \(x, e) -> fmap (x, e,) (varTemplate γ (x, Just e)) texprs <- gets termExprs - let xtes = mapMaybe (`lookup` texprs) xs + let xtes = mapMaybe (`lookup'` texprs) xs let ts = safeFromAsserted err . thd3 <$> xets ts' <- mapM refreshArgs ts let xts = zip xs (Asserted <$> ts') @@ -350,8 +346,8 @@ consCBWithExprs γ xes mapM_ (uncurry $ consBind True) (zip γs xets') return γ' where (xs, es) = unzip xes - lookup k m | Just x <- M.lookup k m = Just (k, x) - | otherwise = Nothing + lookup' k m | Just x <- M.lookup k m = Just (k, x) + | otherwise = Nothing err = "Constant: consCBWithExprs" makeTermEnvs :: CGEnv -> [(Var, [F.Located F.Expr])] -> [(Var, CoreExpr)] @@ -359,19 +355,19 @@ makeTermEnvs :: CGEnv -> [(Var, [F.Located F.Expr])] -> [(Var, CoreExpr)] -> [CGEnv] makeTermEnvs γ xtes xes ts ts' = setTRec γ . zip xs <$> rts where - vs = zipWith collectArgs ts es - ys = fst5 . bkArrowDeep <$> ts - ys' = fst5 . bkArrowDeep <$> ts' - sus' = zipWith mkSub ys ys' - sus = zipWith mkSub ys ((F.symbol <$>) <$> vs) + vs = zipWith collectArgs' ts ces + syms = fst5 . bkArrowDeep <$> ts + syms' = fst5 . bkArrowDeep <$> ts' + sus' = zipWith mkSub syms syms' + sus = zipWith mkSub syms ((F.symbol <$>) <$> vs) ess = (\x -> safeFromJust (err x) (x `L.lookup` xtes)) <$> xs tes = zipWith (\su es -> F.subst su <$> es) sus ess tes' = zipWith (\su es -> F.subst su <$> es) sus' ess rss = zipWith makeLexRefa tes' <$> (repeat <$> tes) rts = zipWith (addObligation OTerm) ts' <$> rss - (xs, es) = unzip xes + (xs, ces) = unzip xes mkSub ys ys' = F.mkSubst [(x, F.EVar y) | (x, y) <- zip ys ys'] - collectArgs = GM.collectArguments . length . ty_binds . toRTypeRep + collectArgs' = GM.collectArguments . length . ty_binds . toRTypeRep err x = "Constant: makeTermEnvs: no terminating expression for " ++ GM.showPpr x addObligation :: Oblig -> SpecType -> RReft -> SpecType @@ -389,7 +385,7 @@ consCB :: Bool -> Bool -> CGEnv -> CoreBind -> CG CGEnv consCB True _ γ (Rec xes) = do texprs <- gets termExprs modify $ \i -> i { recCount = recCount i + length xes } - let xxes = mapMaybe (`lookup` texprs) xs + let xxes = mapMaybe (`lookup'` texprs) xs if null xxes then consCBSizedTys γ xes else check xxes <$> consCBWithExprs γ xes @@ -399,7 +395,7 @@ consCB True _ γ (Rec xes) | otherwise = panic (Just loc) msg msg = "Termination expressions must be provided for all mutually recursive binders" loc = getSrcSpan (head xs) - lookup k m = (k,) <$> M.lookup k m + lookup' k m = (k,) <$> M.lookup k m -- don't do termination checking, but some strata checks? consCB _ False γ (Rec xes) @@ -427,16 +423,12 @@ consCB _ _ γ (NonRec x _) | isDictionary x where isDictionary = isJust . dlookup (denv γ) - -consCB _ _ γ (NonRec x _ ) | isHoleVar x && typedHoles (getConfig γ) - = return γ - consCB _ _ γ (NonRec x def) | Just (w, τ) <- grepDictionary def , Just d <- dlookup (denv γ) w - = do t <- mapM (trueTy (typeclass (getConfig γ))) τ - mapM_ addW (WfC γ <$> t) - let xts = dmap (fmap (f t)) d + = do st <- mapM (trueTy (typeclass (getConfig γ))) τ + mapM_ addW (WfC γ <$> st) + let xts = dmap (fmap (f st)) d let γ' = γ { denv = dinsert (denv γ) x xts } t <- trueTy (typeclass (getConfig γ)) (varType x) extender γ' (x, Assumed t) @@ -466,24 +458,24 @@ consBind _ _ (x, _, Assumed t) | RecSelId {} <- idDetails x -- don't check record selectors with assumed specs = return $ F.notracepp ("TYPE FOR SELECTOR " ++ show x) $ Assumed t -consBind isRec γ (x, e, Asserted spect) +consBind isRec' γ (x, e, Asserted spect) = do let γ' = γ `setBind` x (_,πs,_) = bkUniv spect - γπ <- foldM addPToEnv γ' πs + cgenv <- foldM addPToEnv γ' πs -- take implcits out of the function's SpecType and into the env let tyr = toRTypeRep spect let spect' = fromRTypeRep (tyr { ty_ebinds = [], ty_einfo = [], ty_eargs = [], ty_erefts = [] }) - γπ <- foldM (+=) γπ $ (\(y,t)->("implicitError",y,t)) <$> zip (ty_ebinds tyr) (ty_eargs tyr) + γπ <- foldM (+=) cgenv $ (\(y,t)->("implicitError",y,t)) <$> zip (ty_ebinds tyr) (ty_eargs tyr) cconsE γπ e (weakenResult (typeclass (getConfig γ)) x spect') when (F.symbol x `elemHEnv` holes γ) $ -- have to add the wf constraint here for HOLEs so we have the proper env addW $ WfC γπ $ fmap killSubst spect - addIdA x (defAnn isRec spect) + addIdA x (defAnn isRec' spect) return $ Asserted spect -consBind isRec γ (x, e, Internal spect) +consBind isRec' γ (x, e, Internal spect) = do let γ' = γ `setBind` x (_,πs,_) = bkUniv spect γπ <- foldM addPToEnv γ' πs @@ -492,23 +484,23 @@ consBind isRec γ (x, e, Internal spect) when (F.symbol x `elemHEnv` holes γ) $ -- have to add the wf constraint here for HOLEs so we have the proper env addW $ WfC γπ $ fmap killSubst spect - addIdA x (defAnn isRec spect) + addIdA x (defAnn isRec' spect) return $ Internal spect where explanation = "Cannot give singleton type to the function definition." -consBind isRec γ (x, e, Assumed spect) +consBind isRec' γ (x, e, Assumed spect) = do let γ' = γ `setBind` x γπ <- foldM addPToEnv γ' πs cconsE γπ e =<< true (typeclass (getConfig γ)) spect - addIdA x (defAnn isRec spect) + addIdA x (defAnn isRec' spect) return $ Asserted spect where πs = ty_preds $ toRTypeRep spect -consBind isRec γ (x, e, Unknown) +consBind isRec' γ (x, e, Unknown) = do t' <- consE (γ `setBind` x) e t <- topSpecType x t' - addIdA x (defAnn isRec t) + addIdA x (defAnn isRec' t) when (GM.isExternalId x) (addKuts x t) return $ Asserted t @@ -649,7 +641,7 @@ cconsE' γ (Case e x _ cases) t = do γ' <- consCBLet γ (NonRec x e) forM_ cases $ cconsCase γ' x t nonDefAlts where - nonDefAlts = [a | (a, _, _) <- cases, a /= DEFAULT] + nonDefAlts = [a | Alt a _ _ <- cases, a /= DEFAULT] _msg = "cconsE' #nonDefAlts = " ++ show (length nonDefAlts) cconsE' γ (Lam α e) (RAllT α' t r) | isTyVar α @@ -680,9 +672,6 @@ cconsE' γ e@(Cast e' c) t = do t' <- castTy γ (exprType e) e' c addC (SubC γ (F.notracepp ("Casted Type for " ++ GM.showPpr e ++ "\n init type " ++ showpp t) t') t) ("cconsE Cast: " ++ GM.showPpr e) -cconsE' γ (Var x) t | isHoleVar x && typedHoles (getConfig γ) - = addHole x t γ - cconsE' γ e t = do te <- consE γ e te' <- instantiatePreds γ e te >>= addPost γ @@ -700,13 +689,13 @@ lambdaSingleton _ _ _ _ = return mempty addForAllConstraint :: CGEnv -> Var -> CoreExpr -> SpecType -> CG () -addForAllConstraint γ _ _ (RAllT a t r) - | F.isTauto r +addForAllConstraint γ _ _ (RAllT rtv rt rr) + | F.isTauto rr = return () | otherwise - = do t' <- true (typeclass (getConfig γ)) t - let truet = RAllT a $ unRAllP t' - addC (SubC γ (truet mempty) $ truet r) "forall constraint true" + = do t' <- true (typeclass (getConfig γ)) rt + let truet = RAllT rtv $ unRAllP t' + addC (SubC γ (truet mempty) $ truet rr) "forall constraint true" where unRAllP (RAllT a t r) = RAllT a (unRAllP t) r unRAllP (RAllP _ t) = unRAllP t unRAllP t = t @@ -866,12 +855,12 @@ consE γ e'@(App e a) | Just aDict <- getExprDict γ a consE γ e'@(App e a) = do ([], πs, te) <- bkUniv <$> consE γ {- GM.tracePpr ("APP-EXPR: " ++ GM.showPpr (exprType e)) -} e - te' <- instantiatePreds γ e' $ foldr RAllP te πs - (γ', te''') <- dropExists γ te' - te'' <- dropConstraints γ te''' - updateLocA (exprLoc e) te'' - (hasGhost, γ'', te''') <- instantiateGhosts γ' te'' - let RFun x _ tx t _ = checkFun ("Non-fun App with caller ", e') γ te''' + te1 <- instantiatePreds γ e' $ foldr RAllP te πs + (γ', te2) <- dropExists γ te1 + te3 <- dropConstraints γ te2 + updateLocA (exprLoc e) te3 + (hasGhost, γ'', te4) <- instantiateGhosts γ' te3 + let RFun x _ tx t _ = checkFun ("Non-fun App with caller ", e') γ te4 cconsE γ'' a tx tout <- makeSingleton γ'' (simplify e') <$> addPost γ'' (maybe (checkUnbound γ'' e' x t a) (F.subst1 t . (x,)) (argExpr γ $ simplify a)) if hasGhost @@ -929,7 +918,7 @@ consE _ e@(Type t) = panic Nothing $ "consE cannot handle type " ++ GM.showPpr (e, t) caseKVKind ::[Alt Var] -> KVKind -caseKVKind [(DataAlt _, _, Var _)] = ProjectE +caseKVKind [Alt (DataAlt _) _ (Var _)] = ProjectE caseKVKind cs = CaseE (length cs) updateEnvironment :: CGEnv -> TyVar -> CG CGEnv @@ -1058,9 +1047,9 @@ castTy γ t e _ castTy' γ τ (Var x) - = do t <- trueTy (typeclass (getConfig γ)) τ - -- tx <- varRefType γ x -- NV HERE: the refinements of the var x do not get into the - -- -- environment. Check + = do t0 <- trueTy (typeclass (getConfig γ)) τ + tx <- varRefType γ x + let t = mergeCastTys t0 tx let ce = if typeclass (getConfig γ) && noADT (getConfig γ) then F.expr x else eCoerc (typeSort (emb γ) $ Ghc.expandTypeSynonyms $ varType x) (typeSort (emb γ) τ) @@ -1076,6 +1065,24 @@ castTy' γ t (Tick _ e) castTy' _ _ e = panic Nothing $ "castTy cannot handle expr " ++ GM.showPpr e + +{- +mergeCastTys tcorrect trefined + tcorrect has the correct GHC skeleton, + trefined has the correct refinements (before coercion) + mergeCastTys keeps the trefined when the two GHC types match +-} + +mergeCastTys :: SpecType -> SpecType -> SpecType +mergeCastTys t1 t2 + | toType False t1 == toType False t2 + = t2 +mergeCastTys (RApp c1 ts1 ps1 r1) (RApp c2 ts2 _ _) + | c1 == c2 + = RApp c1 (zipWith mergeCastTys ts1 ts2) ps1 r1 +mergeCastTys t _ + = t + {- showCoercion :: Coercion -> String showCoercion (AxiomInstCo co1 co2 co3) @@ -1156,23 +1163,23 @@ dropExists γ (REx x tx t) = (, t) <$> γ += ("dropExists", x, tx) dropExists γ t = return (γ, t) dropConstraints :: CGEnv -> SpecType -> CG SpecType -dropConstraints γ (RFun x i tx@(RApp c _ _ _) t r) | isErasable c - = flip (RFun x i tx) r <$> dropConstraints γ t +dropConstraints cgenv (RFun x i tx@(RApp c _ _ _) t r) | isErasable c + = flip (RFun x i tx) r <$> dropConstraints cgenv t where - isErasable = if typeclass (getConfig γ) then isEmbeddedDict else isClass -dropConstraints γ (RRTy cts _ OCons t) - = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) γ xts + isErasable = if typeclass (getConfig cgenv) then isEmbeddedDict else isClass +dropConstraints cgenv (RRTy cts _ OCons rt) + = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) cgenv xts addC (SubC γ' t1 t2) "dropConstraints" - dropConstraints γ t + dropConstraints cgenv rt where (xts, t1, t2) = envToSub cts dropConstraints _ t = return t ------------------------------------------------------------------------------------- -cconsCase :: CGEnv -> Var -> SpecType -> [AltCon] -> (AltCon, [Var], CoreExpr) -> CG () +cconsCase :: CGEnv -> Var -> SpecType -> [AltCon] -> CoreAlt -> CG () ------------------------------------------------------------------------------------- -cconsCase γ x t acs (ac, ys, ce) +cconsCase γ x t acs (Alt ac ys ce) = do cγ <- caseEnv γ x acs ac ys mempty cconsE cγ ce t @@ -1193,9 +1200,9 @@ caseEnv γ x _ (DataAlt c) ys pIs = do let (x' : ys') = F.symbol <$> (x:ys) xt0 <- checkTyCon ("checkTycon cconsCase", x) γ <$> γ ??= x - let xt = shiftVV xt0 x' + let rt = shiftVV xt0 x' tdc <- γ ??= dataConWorkId c >>= refreshVV - let (rtd,yts',_) = unfoldR tdc xt ys + let (rtd,yts',_) = unfoldR tdc rt ys yts <- projectTypes (typeclass (getConfig γ)) pIs yts' let ys'' = F.symbol <$> filter (not . if allowTC then GM.isEmbeddedDictVar else GM.isEvVar) ys let r1 = dataConReft c ys'' @@ -1234,7 +1241,7 @@ ignoreSelf = F.mapExpr (\r -> if selfSymbol `elem` F.syms r then F.PTrue else r) -------------------------------------------------------------------------------- projectTypes :: Bool -> Maybe [Int] -> [SpecType] -> CG [SpecType] projectTypes _ Nothing ts = return ts -projectTypes allowTC (Just is) ts = mapM (projT is) (zip [0..] ts) +projectTypes allowTC (Just ints) ts = mapM (projT ints) (zip [0..] ts) where projT is (j, t) | j `elem` is = return t @@ -1305,8 +1312,8 @@ varAnn γ x t -- | Helpers: Creating Fresh Refinement ------------------------------- ----------------------------------------------------------------------- freshPredRef :: CGEnv -> CoreExpr -> PVar RSort -> CG SpecProp -freshPredRef γ e (PV _ (PVProp τ) _ as) - = do t <- freshTyType (typeclass (getConfig γ)) PredInstE e (toType False τ) +freshPredRef γ e (PV _ (PVProp rsort) _ as) + = do t <- freshTyType (typeclass (getConfig γ)) PredInstE e (toType False rsort) args <- mapM (const fresh) as let targs = [(x, s) | (x, (s, y, z)) <- zip args as, F.EVar y == z ] γ' <- foldM (+=) γ [("freshPredRef", x, ofRSort τ) | (x, τ) <- targs] @@ -1372,13 +1379,13 @@ varRefType γ x = varRefType' :: CGEnv -> Var -> SpecType -> SpecType varRefType' γ x t' | Just tys <- trec γ, Just tr <- M.lookup x' tys - = strengthen tr xr + = strengthen' tr xr | otherwise - = strengthen t' xr + = strengthen' t' xr where xr = singletonReft x x' = F.symbol x - strengthen + strengthen' | higherOrderFlag γ = strengthenMeet | otherwise @@ -1386,8 +1393,8 @@ varRefType' γ x t' -- | create singleton types for function application makeSingleton :: CGEnv -> CoreExpr -> SpecType -> SpecType -makeSingleton γ e t - | higherOrderFlag γ, App f x <- simplify e +makeSingleton γ cexpr t + | higherOrderFlag γ, App f x <- simplify cexpr = case (funExpr γ f, argForAllExpr x) of (Just f', Just x') | not (if typeclass (getConfig γ) then GM.isEmbeddedDictExpr x else GM.isPredExpr x) -- (isClassPred $ exprType x) @@ -1396,7 +1403,7 @@ makeSingleton γ e t -> strengthenMeet t (uTop $ F.exprReft f') _ -> t | rankNTypes (getConfig γ) - = case argExpr γ (simplify e) of + = case argExpr γ (simplify cexpr) of Just e' -> strengthenMeet t $ uTop (F.exprReft e') _ -> t | otherwise @@ -1475,7 +1482,7 @@ isType a = eqType (exprType a) predType -- | @isGenericVar@ determines whether the @RTyVar@ has no class constraints isGenericVar :: RTyVar -> SpecType -> Bool -isGenericVar α t = all (\(c, α') -> (α'/=α) || isGenericClass c ) (classConstrs t) +isGenericVar α st = all (\(c, α') -> (α'/=α) || isGenericClass c ) (classConstrs st) where classConstrs t = [(c, ty_var_value α') | (c, ts) <- tyClasses t @@ -1487,4 +1494,4 @@ isGenericVar α t = all (\(c, α') -> (α'/=α) || isGenericClass c ) (classCon -- fail msg = panic Nothing msg instance MonadFail Data.Functor.Identity.Identity where - fail msg = panic Nothing msg \ No newline at end of file + fail msg = panic Nothing msg diff --git a/src/Language/Haskell/Liquid/Constraint/Init.hs b/src/Language/Haskell/Liquid/Constraint/Init.hs index e0f9760620..2ba59e698a 100644 --- a/src/Language/Haskell/Liquid/Constraint/Init.hs +++ b/src/Language/Haskell/Liquid/Constraint/Init.hs @@ -6,8 +6,6 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -- | This module defines the representation of Subtyping and WF Constraints, -- and the code for syntax-directed constraint generation. @@ -85,7 +83,6 @@ initEnv info is autoinv = mkRTyConInv (gsInvariants (gsData sp) ++ ((Nothing,) <$> autoinv)) addPolyInfo' = if reflection (getConfig info) then map (mapSnd addPolyInfo) else id - mapSndM f (x,y) = (x,) <$> f y makeExactDc dcs = if exactDCFlag info then map strengthenDataConType dcs else dcs addPolyInfo :: SpecType -> SpecType @@ -102,9 +99,9 @@ makeDataConTypes allowTC x = (x,) <$> trueTy allowTC (varType x) makeAutoDecrDataCons :: [(Id, SpecType)] -> S.HashSet TyCon -> [Id] -> ([LocSpecType], [(Id, SpecType)]) makeAutoDecrDataCons dcts specenv dcs - = (simplify invs, tys) + = (simplify rsorts, tys) where - (invs, tys) = unzip $ concatMap go tycons + (rsorts, tys) = unzip $ concatMap go tycons tycons = L.nub $ mapMaybe idTyCon dcs go tycon @@ -125,8 +122,8 @@ makeSizedDataCons :: [(Id, SpecType)] -> DataCon -> Integer -> (RSort, (Id, Spec makeSizedDataCons dcts x' n = (toRSort $ ty_res trep, (x, fromRTypeRep trep{ty_res = tres})) where x = dataConWorkId x' - t = fromMaybe (impossible Nothing "makeSizedDataCons: this should never happen") $ L.lookup x dcts - trep = toRTypeRep t + st = fromMaybe (impossible Nothing "makeSizedDataCons: this should never happen") $ L.lookup x dcts + trep = toRTypeRep st tres = ty_res trep `strengthen` MkUReft (F.Reft (F.vv_, F.PAtom F.Eq (lenOf F.vv_) computelen)) mempty recarguments = filter (\(t,_) -> toRSort t == toRSort tres) (zip (ty_args trep) (ty_binds trep)) @@ -261,7 +258,6 @@ initCGI cfg info = CGInfo { , binds = F.emptyBindEnv , ebinds = [] , annotMap = AI M.empty - , holesMap = M.empty , relHints = Doc.empty , relWf = [] , newTyEnv = M.fromList (mapSnd val <$> gsNewTypes (gsSig spc)) diff --git a/src/Language/Haskell/Liquid/Constraint/Monad.hs b/src/Language/Haskell/Liquid/Constraint/Monad.hs index 5da6107ebb..f5e4d0930f 100644 --- a/src/Language/Haskell/Liquid/Constraint/Monad.hs +++ b/src/Language/Haskell/Liquid/Constraint/Monad.hs @@ -4,21 +4,18 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Constraint.Monad where import qualified Data.HashMap.Strict as M import qualified Data.Text as T import Control.Monad -import Control.Monad.State (get, gets, modify) +import Control.Monad.State (gets, modify) import Language.Haskell.Liquid.Types hiding (loc) import Language.Haskell.Liquid.Constraint.Types import Language.Haskell.Liquid.Constraint.Env import Language.Fixpoint.Misc hiding (errorstar) import Liquid.GHC.Misc -- (concatMapM) -import Liquid.GHC.SpanStack (srcSpan) import Liquid.GHC.API as Ghc hiding (panic, showPpr) -------------------------------------------------------------------------------- @@ -41,18 +38,18 @@ addC c _msg -------------------------------------------------------------------------------- addPost :: CGEnv -> SpecType -> CG SpecType -------------------------------------------------------------------------------- -addPost γ (RRTy e r OInv t) - = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("addPost", x,t)) γ e - addC (SubR γ' OInv r) "precondition-oinv" >> return t +addPost cgenv (RRTy e r OInv rt) + = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("addPost", x,t)) cgenv e + addC (SubR γ' OInv r) "precondition-oinv" >> return rt -addPost γ (RRTy e r OTerm t) - = do γ' <- foldM (\γ (x, t) -> γ += ("addPost", x, t)) γ e - addC (SubR γ' OTerm r) "precondition-oterm" >> return t +addPost cgenv (RRTy e r OTerm rt) + = do γ' <- foldM (\γ (x, t) -> γ += ("addPost", x, t)) cgenv e + addC (SubR γ' OTerm r) "precondition-oterm" >> return rt -addPost γ (RRTy cts _ OCons t) - = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) γ xts +addPost cgenv (RRTy cts _ OCons rt) + = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) cgenv xts addC (SubC γ' t1 t2) "precondition-ocons" - addPost γ t + addPost cgenv rt where (xts, t1, t2) = envToSub cts addPost _ t @@ -89,21 +86,6 @@ addLocA :: Maybe Var -> SrcSpan -> Annot SpecType -> CG () addLocA !xo !l !t = modify $ \s -> s { annotMap = addA l xo t $ annotMap s } - --- | Used for annotating holes - -addHole :: Var -> SpecType -> CGEnv -> CG () -addHole x t γ - | typedHoles (getConfig γ) = - do st <- get - modify $ \s -> s {holesMap = M.insert x (hinfo (st, γ)) $ holesMap s} - -- addWarning $ ErrHole loc ("hole found") (reGlobal env <> reLocal env) x' t - | otherwise = return () - where - hinfo = HoleInfo t loc env - loc = srcSpan $ cgLoc γ - env = mconcat [renv γ, grtys γ, assms γ, intys γ] - -------------------------------------------------------------------------------- -- | Update annotations for a location, due to (ghost) predicate applications -------------------------------------------------------------------------------- diff --git a/src/Language/Haskell/Liquid/Constraint/Qualifier.hs b/src/Language/Haskell/Liquid/Constraint/Qualifier.hs index 6a8d264e94..e343bafebf 100644 --- a/src/Language/Haskell/Liquid/Constraint/Qualifier.hs +++ b/src/Language/Haskell/Liquid/Constraint/Qualifier.hs @@ -2,8 +2,6 @@ {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Constraint.Qualifier ( giQuals , useSpcQuals @@ -172,8 +170,8 @@ refTypeQuals lEnv l tce t0 = go emptySEnv t0 go _ _ = [] goRefs c g rs = concat $ zipWith (goRef g) rs (rTyConPVs c) goRef _ (RProp _ (RHole _)) _ = [] - goRef g (RProp s t) _ = go (insertsSEnv g s) t - insertsSEnv = foldr (\(x, t) γ -> insertSEnv x (rTypeSort tce t) γ) + goRef g (RProp s t) _ = go (insertsSEnv' g s) t + insertsSEnv' = foldr (\(x, t) γ -> insertSEnv x (rTypeSort tce t) γ) refTopQuals :: (PPrint t, Reftable t, SubsTy RTyVar RSort t, Reftable (RTProp RTyCon RTyVar (UReft t))) @@ -184,8 +182,8 @@ refTopQuals :: (PPrint t, Reftable t, SubsTy RTyVar RSort t, Reftable (RTProp RT -> SEnv Sort -> RRType (UReft t) -> [Qualifier] -refTopQuals lEnv l tce t0 γ t - = [ mkQ v so pa | let (RR so (Reft (v, ra))) = rTypeSortedReft tce t +refTopQuals lEnv l tce t0 γ rrt + = [ mkQ' v so pa | let (RR so (Reft (v, ra))) = rTypeSortedReft tce rrt , pa <- conjuncts ra , not $ isHole pa , not $ isGradual pa @@ -193,12 +191,12 @@ refTopQuals lEnv l tce t0 γ t $ isNothing $ checkSorted (srcSpan l) (insertSEnv v so γ') pa ] ++ - [ mkP s e | let (MkUReft _ (Pr ps)) = fromMaybe (msg t) $ stripRTypeBase t + [ mkP s e | let (MkUReft _ (Pr ps)) = fromMaybe (msg rrt) $ stripRTypeBase rrt , p <- findPVar (ty_preds $ toRTypeRep t0) <$> ps , (s, _, e) <- pargs p ] where - mkQ = mkQual lEnv l t0 γ + mkQ' = mkQual lEnv l t0 γ mkP = mkPQual lEnv l tce t0 γ msg t = panic Nothing $ "Qualifier.refTopQuals: no typebase" ++ showpp t γ' = unionSEnv' γ lEnv diff --git a/src/Language/Haskell/Liquid/Constraint/Relational.hs b/src/Language/Haskell/Liquid/Constraint/Relational.hs index c96b4b7cfb..550602011f 100644 --- a/src/Language/Haskell/Liquid/Constraint/Relational.hs +++ b/src/Language/Haskell/Liquid/Constraint/Relational.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} @@ -7,17 +6,13 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} + -- | This module defines the representation of Subtyping and WF Constraints, -- and the code for syntax-directed constraint generation. module Language.Haskell.Liquid.Constraint.Relational (consAssmRel, consRelTop) where - -#if !MIN_VERSION_base(4,14,0) -import Control.Monad.Fail -#endif - - import Control.Monad.State import Data.Bifunctor as B import qualified Data.HashMap.Strict as M @@ -27,7 +22,6 @@ import Data.Monoid ( Any(..) ) import Data.String ( IsString(..) ) import Data.Char ( toUpper ) import Data.Default ( def ) --- import qualified Debug.Trace as D import qualified Language.Fixpoint.Types as F import qualified Language.Fixpoint.Types.Visitor as F @@ -38,8 +32,9 @@ import Language.Haskell.Liquid.Constraint.Types import Language.Haskell.Liquid.Synthesize.GHC ( coreToHs , fromAnf - , pprintBody' + , pprintBody , handleVar + , RenVars ) import Liquid.GHC.API ( Alt @@ -123,16 +118,25 @@ consRelTop cfg ti chk syn γ ψ (x, y, t, s, ra, rp) = traceChk "Init" e d t s p consRelCheckBind (UnaryTyping chk (\γγ ee -> removeAbsRef <$> syn γγ ee)) γ' ψ e d t' s' ra rp when (relationalHints cfg) $ modify $ \cgi -> cgi - { relHints = relHint - (relSigToUnSig (toExpr x) (toExpr y) t' s' rp) - hintName - (relTermToUnTerm argNames x y hintName (toCoreExpr e) (toCoreExpr d)) + { relHints = relHint (renVars argNames) + (relSigToUnSig (toExpr x) (toExpr y) t' s' rp) + hintName + (relTermToUnTerm argNames x y hintName + (toCoreExpr e) (toCoreExpr d)) $+$ relHints cgi } where argNames = (fst $ vargs t', fst $ vargs s') - toExpr = F.EVar . F.symbol - toCoreExpr = GM.unTickExpr . binderToExpr + toExpr = F.EVar . F.symbol + + {- cleanUnTerms in toCoreExpr generates: + Expression: patError () + Type: forall a. Addr# -> a + Args: [()] + -} + toCoreExpr = fromAnf . GM.unTickExpr . binderToExpr +-- fst . cleanUnTerms renVars +-- . fromAnf . GM.unTickExpr . binderToExpr p = fromRelExpr rp γ' = γ `setLocation` Sp.Span (GM.fSrcSpan (F.loc t)) cbs = giCbs $ giSrc ti @@ -298,7 +302,12 @@ isCommonArg x | Type{} <- GM.unTickExpr x = False isCommonArg x | Var v <- GM.unTickExpr x = not (GM.isEmbeddedDictVar v) isCommonArg _ = True -relTermToUnTerm' :: ArgMapping -> [((Var, Var), CoreExpr)] -> CoreExpr -> CoreExpr -> CoreExpr +renVars :: ArgMapping -> RenVars +renVars (lvars, rvars) = map F.symbolSafeString $ lvars ++ rvars + +type TranslationEnv = [((Var, Var), CoreExpr)] + +relTermToUnTerm' :: ArgMapping -> TranslationEnv -> CoreExpr -> CoreExpr -> CoreExpr relTermToUnTerm' _ relTerms (Var x1) (Var x2) | Just relX <- lookup (x1, x2) relTerms = relX @@ -315,28 +324,20 @@ relTermToUnTerm' m relTerms (App f1 v1) (App f2 v2) , GM.isEmbeddedDictVar x2 , areCompatible f1 f2 = relTermToUnTerm' m relTerms f1 f2 -relTermToUnTerm' m relTerms _e1@(App f1 v1) _e2@(App f2 v2) - | Var x1 <- GM.unTickExpr v1 - , Var x2 <- GM.unTickExpr v2 - , areCompatible f1 f2 - , areCompatible v1 v2 - , Just relX <- lookup (x1, x2) relTerms - = traceWhenLoud - ("relTermToUnTerm App lookup " ++ show x1 ++ " ~ " ++ show x2 ++ " ~> " ++ show relX) $ - App (App (App (relTermToUnTerm' m relTerms f1 f2) v1) v2) relX - -- `addLemma` cle1 `addLemma` cle2 - -- where - -- (cle1, _) = cleanUnTerms e1 - -- (cle2, _) = cleanUnTerms e2 -relTermToUnTerm' m relTerms (App f1 x1) (App f2 x2) +relTermToUnTerm' m relTerms (App f1 x1) (App f2 x2) | isCommonArg x1 , isCommonArg x2 , areCompatible f1 f2 , areCompatible x1 x2 = traceWhenLoud - ("relTermToUnTerm App common arg " ++ show x1 ++ " " ++ show x2) $ - App (App (App (relTermToUnTerm' m relTerms f1 f2) x1) x2) relX - where relX = mkLambdaUnit x1 x2 (Ghc.exprType x1) (Ghc.exprType x2) + ("relTermToUnTerm App common arg " ++ show x1 ++ " ~ " ++ show x2) $ + App (App (App relF x1') x2') relX + where + relF = relTermToUnTerm' m relTerms f1 f2 + relX = relTermToUnTerm' m relTerms x1 x2 + rvs = renVars m + (x1', _) = cleanUnTerms rvs x1 + (x2', _) = cleanUnTerms rvs x2 relTermToUnTerm' m relTerms (Lam α1 e1) (Lam α2 e2) | Ghc.isTyVar α1, Ghc.isTyVar α2 = relTermToUnTerm' m relTerms e1 e2 @@ -350,13 +351,18 @@ relTermToUnTerm' m relTerms (Lam x1 e1) (Lam x2 e2) (e1l, e2r) = subRelCopiesWithMapping m e1 x1 e2 x2 relTermToUnTerm' m relTerms (Let (NonRec x1 d1) e1) (Let (NonRec x2 d2) e2) | areCompatible d1 d2 - = Let (NonRec x1l d1) $ Let (NonRec x2r d2) $ Let (NonRec relX relD) $ - relTermToUnTerm' m (((x1l, x2r), Var relX) : relTerms) e1l e2r + , not b1 + , not b2 + = Let (NonRec x1l d1') $ Let (NonRec x2r d2') $ Let (NonRec relX relD) $ + relTermToUnTerm' m (((x1l, x2r), Var relX) : relTerms) e1l e2r `addLemma` Var relX where - relX = mkRelLemmaVar x1 x2 + relX = mkRelLemmaVar x1l x2r relD = relTermToUnTerm' m relTerms d1 d2 (x1l, x2r) = mkRelCopies x1 x2 (e1l, e2r) = subRelCopies e1 x1 e2 x2 + rvs = renVars m + (d1', b1) = cleanUnTerms rvs d1 + (d2', b2) = cleanUnTerms rvs d2 -- TODO: test recursive and mutually recursive lets relTermToUnTerm' m relTerms (Let (Rec bs1) e1) (Let (Rec bs2) e2) | length bs1 == length bs2 @@ -370,47 +376,56 @@ relTermToUnTerm' m relTerms (Let (Rec bs1) e1) (Let (Rec bs2) e2) relTermsBs = zipWith (\(x1, d1) (x2, d2) -> ((x1, x2), relTermToUnTerm' m relTerms d1 d2)) bs1 bs2 relTerms' = relTermsBs ++ relTerms relBs = zipWith (\(x1, d1) (x2, d2) -> (mkRelLemmaVar x1 x2, relTermToUnTerm' m relTerms' d1 d2)) bs1 bs2 -relTermToUnTerm' m relTerms (Case d1 x1 t1 as1) (Case d2 x2 t2 as2) = - Case d1 x1l t1 $ map - (\(c1, bs1, e1) -> +relTermToUnTerm' m relTerms (Case d1 x1 t1 as1) (Case d2 x2 t2 as2) + | not b1, not b2 = + Case d1' x1l t1 $ map + (\(Ghc.Alt c1 bs1 e1) -> let bs1l = map (mkCopyWithSuffix relSuffixL) bs1 in - ( c1 - , bs1l - , Case d2 x2r t2 $ map - (\(c2, bs2, e2) -> + ( Ghc.Alt c1 bs1l $ + Case d2' x2r t2 $ map + (\(Ghc.Alt c2 bs2 e2) -> let bs2r = map (mkCopyWithSuffix relSuffixR) bs2 e1l = subVarAndTys ((x1, x1l) : zip bs1 bs1l) e1 e2r = subVarAndTys ((x2, x2r) : zip bs2 bs2r) e2 - in (c2, bs2r, relTermToUnTerm' m relTerms e1l e2r) + in (Ghc.Alt c2 bs2r $ relTermToUnTerm' m relTerms e1l e2r) ) as2 )) as1 - where (x1l, x2r) = mkRelCopies x1 x2 -relTermToUnTerm' _ _ e1 e2 + where + (x1l, x2r) = mkRelCopies x1 x2 + rvs = renVars m + (d1', b1) = cleanUnTerms rvs d1 + (d2', b2) = cleanUnTerms rvs d2 +relTermToUnTerm' m _ e1 e2 = traceWhenLoud ("relTermToUnTerm': can't proceed proof generation on e1:\n" ++ F.showpp e1 ++ "\ne2:\n" ++ F.showpp e2) $ Tick (Ghc.SourceNote realSpan info) $ - mkLambdaUnit e1 e2 (Ghc.exprType e1) (Ghc.exprType e2) + mkLambdaUnit m e1 e2 (Ghc.exprType e1) (Ghc.exprType e2) Ghc.unitExpr 1 where realLoc = Ghc.mkRealSrcLoc (Ghc.mkFastString "") 0 0 realSpan = Ghc.mkRealSrcSpan realLoc realLoc - left = coreToGoal True e1 - right = coreToGoal True e2 + rvs = renVars m + left = coreToGoal rvs True e1 + right = coreToGoal rvs True e2 info = "GOAL: " ++ left ++ " ~ " ++ right +-- guardLemma :: Bool -> CoreExpr -> CoreExpr +-- guardLemma True _ = Ghc.unitExpr +-- guardLemma False e = e + {- function to print CoreExpr as strings in order to insert them as goal comments on the output of the proof. when the boolean argument short is true, if the goal is bigger then 20 chars then the string is trimed. -} -coreToGoal :: Bool -> CoreExpr -> String -coreToGoal short e +coreToGoal :: RenVars -> Bool -> CoreExpr -> String +coreToGoal rvs short e | bool = "()" | short && length goal <= 20 = goal | short = take 20 goal ++ " (...) " | otherwise = goal where - goal = unwords $ words $ concat $ splitOn "\n" $ pprintBody' expr - (expr, bool) = cleanUnTerms $ fromAnf e + goal = unwords $ words $ concat $ splitOn "\n" $ pprintBody rvs expr + (expr, bool) = cleanUnTerms rvs $ fromAnf e areCompatible :: CoreExpr -> CoreExpr -> Bool areCompatible e1 e2 = areCompatibleTy (Ghc.exprType e1) (Ghc.exprType e2) @@ -432,78 +447,84 @@ areCompatibleTy t1 (Ghc.ForAllTy _ t2) = areCompatibleTy t1 t2 areCompatibleTy _ _ = False -mkLambdaUnit :: CoreExpr -> CoreExpr -> Type -> Type -> CoreExpr -mkLambdaUnit e1 e2 (Ghc.ForAllTy _ t1) (Ghc.ForAllTy _ t2) = mkLambdaUnit e1 e2 t1 t2 -mkLambdaUnit e1 e2 (Ghc.FunTy Ghc.InvisArg _ _ t1) (Ghc.FunTy Ghc.InvisArg _ _ t2) = mkLambdaUnit e1 e2 t1 t2 -mkLambdaUnit e1 e2 (Ghc.FunTy Ghc.VisArg _ _ t1) (Ghc.FunTy Ghc.VisArg _ _ t2) - = Lam (GM.stringVar "_" Ghc.unitTy) $ - Lam (GM.stringVar "_" Ghc.unitTy) $ - Lam (GM.stringVar "_" Ghc.unitTy) $ mkLambdaUnit e1 e2 t1 t2 -mkLambdaUnit _ _ t1@Ghc.FunTy{} t2 = F.panic $ "relTermToUnTerm: asked to relate unmatching types " ++ F.showpp t1 ++ " " ++ F.showpp t2 -mkLambdaUnit _ _ t1 t2@Ghc.FunTy{} = F.panic $ "relTermToUnTerm: asked to relate unmatching types " ++ F.showpp t1 ++ " " ++ F.showpp t2 - -mkLambdaUnit e1 e2 _ _ - | Ghc.FunTy {} <- Ghc.exprType e1 - , Ghc.FunTy {} <- Ghc.exprType e2 = Ghc.unitExpr - | Ghc.ForAllTy {} <- Ghc.exprType e1 - , Ghc.ForAllTy {} <- Ghc.exprType e2 = Ghc.unitExpr - | patError1 || patError2 = Ghc.unitExpr - | otherwise = Ghc.unitExpr `addLemma` cle1 `addLemma` cle2 +mkLambdaUnit :: ArgMapping -> CoreExpr -> CoreExpr -> Type -> Type -> CoreExpr -> Int -> CoreExpr +mkLambdaUnit m e1 e2 (Ghc.ForAllTy _ t1) (Ghc.ForAllTy _ t2) acc i + = mkLambdaUnit m e1 e2 t1 t2 acc i +mkLambdaUnit m e1 e2 (Ghc.FunTy Ghc.InvisArg _ _ t1) (Ghc.FunTy Ghc.InvisArg _ _ t2) acc i + = mkLambdaUnit m e1 e2 t1 t2 acc i +mkLambdaUnit m e1 e2 (Ghc.FunTy Ghc.VisArg _ _ t1) (Ghc.FunTy Ghc.VisArg _ _ t2) acc i + = Lam v1 $ Lam v2 $ Lam relV $ mkLambdaUnit m (App e1 (Var v1)) (App e2 (Var v2)) t1 t2 + (acc `addLemma` Var relV) (i + 2) + where + v1 = GM.stringVar ("x" ++ show i) Ghc.unitTy + v2 = GM.stringVar ("x" ++ show (i + 1)) Ghc.unitTy + relV = mkRelLemmaVar v1 v2 +mkLambdaUnit _ _ _ t1@Ghc.FunTy{} t2 _ _ = F.panic $ "relTermToUnTerm: asked to relate unmatching types " ++ F.showpp t1 ++ " " ++ F.showpp t2 +mkLambdaUnit _ _ _ t1 t2@Ghc.FunTy{} _ _ = F.panic $ "relTermToUnTerm: asked to relate unmatching types " ++ F.showpp t1 ++ " " ++ F.showpp t2 + +mkLambdaUnit m e1 e2 _ _ acc _ + | patError1 || patError2 = acc + | otherwise = acc `addLemma` cle1 `addLemma` cle2 where - (cle1, patError1) = cleanUnTerms e1 - (cle2, patError2) = cleanUnTerms e2 + rvs = renVars m + (cle1, patError1) = cleanUnTerms rvs e1 + (cle2, patError2) = cleanUnTerms rvs e2 -- Generates proof: e ? lm addLemma :: CoreExpr -> CoreExpr -> CoreExpr -addLemma e lm = App (App cnst e) lm - where - cnst = Var $ GM.stringVar "const" Ghc.unitTy - -- q = Var $ GM.stringVar "?" Ghc.unitTy - -cleanUnTerms :: CoreExpr -> (CoreExpr, Bool) -{- Maybe have to do some cleaning to the vars here -} -cleanUnTerms var@(Var v) - | handleVar v == "patError" = (var, True) +addLemma e lm = App (App q e) lm + where q = Var $ GM.stringVar "?" Ghc.unitTy + +cleanUnTerms :: RenVars -> CoreExpr -> (CoreExpr, Bool) +cleanUnTerms rvs var@(Var v) + | handleVar rvs v == "patError" = (var, True) | otherwise = (var, False) -cleanUnTerms l@Lit{} = (l, False) -cleanUnTerms (App f e) - | Type{} <- GM.unTickExpr e = cleanUnTerms f -cleanUnTerms (App f (Var v)) - | GM.isEmbeddedDictVar v = cleanUnTerms f -cleanUnTerms (App f e) = (App core1 core2, bool1 || bool2) + +cleanUnTerms _ (Lit (Ghc.LitString _)) = (Ghc.unitExpr, False) +cleanUnTerms _ l@Lit{} = (l, False) + +cleanUnTerms rvs (App f e) + | Type{} <- GM.unTickExpr e = cleanUnTerms rvs f +cleanUnTerms rvs (App f (Var v)) + | GM.isEmbeddedDictVar v = cleanUnTerms rvs f +cleanUnTerms rvs (App f e) = (App core1 core2, bool1 || bool2) where - (core1, bool1) = cleanUnTerms f - (core2, bool2) = cleanUnTerms e -cleanUnTerms (Lam α e) - | Ghc.isTyVar α = cleanUnTerms e + (core1, bool1) = cleanUnTerms rvs f + (core2, bool2) = cleanUnTerms rvs e +cleanUnTerms rvs (Lam α e) + | Ghc.isTyVar α = cleanUnTerms rvs e | otherwise = (Lam α core, bool) where - (core, bool) = cleanUnTerms e + (core, bool) = cleanUnTerms rvs e -cleanUnTerms (Let (NonRec v e1) e2) = +cleanUnTerms rvs (Let (NonRec v e1) e2) = (Let (NonRec v core1) core2, bool1 || bool2) where - (core1, bool1) = cleanUnTerms e1 - (core2, bool2) = cleanUnTerms e2 + (core1, bool1) = cleanUnTerms rvs e1 + (core2, bool2) = cleanUnTerms rvs e2 -cleanUnTerms (Let r e) = (Let r core, bool) +cleanUnTerms rvs (Let r e) = (Let r core, bool) -- TODO: cleanUnTerms <$> r where - (core, bool) = cleanUnTerms e + (core, bool) = cleanUnTerms rvs e -cleanUnTerms (Case e v t alts) = (Case core v t clAlts, bool1 || bool2) +cleanUnTerms rvs (Case e v t alts) = + (Case core v t clAlts, bool1 || bool2) where - (core, bool1) = cleanUnTerms e - (clAlts, bool2) = cleanCase alts + (core, bool1) = cleanUnTerms rvs e + (clAlts, bool2) = cleanCase rvs alts -cleanUnTerms e = error ("cleanUnTerms: " ++ F.showpp e) +cleanUnTerms _ e = error ("cleanUnTerms: " ++ F.showpp e) -cleanCase :: [(a, b, CoreExpr)] -> ([(a, b, CoreExpr)], Bool) -cleanCase alts = (zip3 altcs vss cores, bool) +cleanCase :: RenVars -> [Ghc.Alt CoreBndr] -> ([Ghc.Alt CoreBndr], Bool) +cleanCase rvs alts = ( map (\(a, b, c) -> Ghc.Alt a b c) $ zip3 altcs vss cores + , bool) where (altcs, vss, altesBools) = unzip3 $ - map (\(altc, vs, alte) -> - (altc, vs, cleanUnTerms alte)) alts + map (\(Ghc.Alt altc vs alte) -> + (altc + , vs + , cleanUnTerms rvs alte)) alts (cores, bool) = or <$> unzip altesBools @@ -586,14 +607,13 @@ consRelCheckBind _ _ _ (Rec [(_, e1)]) (Rec [(_, e2)]) t1 t2 _ rp consRelCheckBind _ _ _ b1 b2 _ _ _ _ = F.panic $ "consRelCheckBind Rec: mutually recursive binders are not supported " ++ F.showpp (b1, b2) --- Definition of CoreExpr: https://hackage.haskell.org/package/ghc-8.10.1/docs/CoreSyn.html consRelCheck :: UnaryTyping -> CGEnv -> RelEnv -> CoreExpr -> CoreExpr -> SpecType -> SpecType -> F.Expr -> CG () consRelCheck unary γ ψ (Tick tt e) d t s p = - {- traceChk "Left Tick" e d t s p $ -} consRelCheck unary (γ `setLocation` Sp.Tick tt) ψ e d t s p + consRelCheck unary (γ `setLocation` Sp.Tick tt) ψ e d t s p consRelCheck unary γ ψ e (Tick tt d) t s p = - {- traceChk "Right Tick" e d t s p $ -} consRelCheck unary (γ `setLocation` Sp.Tick tt) ψ e d t s p + consRelCheck unary (γ `setLocation` Sp.Tick tt) ψ e d t s p consRelCheck unary γ ψ l1@(Lam α1 e1) e2 rt1@(RAllT s1 t1 r1) t2 p | Ghc.isTyVar α1 @@ -639,7 +659,8 @@ consRelCheck unary γ ψ l1@(Let (NonRec x1 d1) e1) l2@(Let (NonRec x2 d2) e2) t let binders = vs1 ++ vs2 ++ concatMap (fst . vargs) ts1 ++ concatMap (fst . vargs) ts2 let qs' = traceWhenLoud ("Let qs: " ++ F.showpp qs) qs let (ho, fo) = L.partition (containsVars binders) qs' - γ''' <- γ'' `addPreds` map (F.subst rs2xs) fo + let fo' = map (F.subst rs2xs) fo + γ''' <- γ'' `addPreds` traceWhenLoud ("Let fos: " ++ F.showpp fo') fo' let ψ' = ψ ++ map (\qq -> toRel (evar1, evar2, s1, s2, qq)) ho consRelCheck unary γ''' ψ' e1' e2' t1 t2 p where @@ -713,16 +734,6 @@ consRelCheck unary γ ψ e d t1 t2 p = addC (SubC γ s1 t1) ("consRelCheck (Synth): s1 = " ++ F.showpp s1 ++ " t1 = " ++ F.showpp t1) addC (SubC γ s2 t2) ("consRelCheck (Synth): s2 = " ++ F.showpp s2 ++ " t2 = " ++ F.showpp t2) --- consSameCtors :: CGEnv -> RelEnv -> F.Symbol -> F.Symbol -> SpecType -> SpecType -> [AltCon] -> AltCon -> CG () --- consSameCtors γ _ x1 x2 _ _ _ (DataAlt c) | isBoolDataCon c --- = entl γ (F.PIff (F.EVar x1) (F.EVar x2)) "consSameCtors DataAlt Bool" --- consSameCtors γ _ x1 x2 _ _ _ (DataAlt c) --- = entl γ (F.PIff (isCtor c $ F.EVar x1) (isCtor c $ F.EVar x2)) "consSameCtors DataAlt" --- consSameCtors _ _ _ _ _ _ _ (LitAlt _) --- = F.panic "consSameCtors undefined for literals" --- consSameCtors _ _ _ _ _ _ _ DEFAULT --- = F.panic "consSameCtors undefined for default" - consExtAltEnv :: CGEnv -> F.Symbol -> SpecType -> AltCon -> [Var] -> CoreExpr -> String -> CG (CGEnv, CoreExpr) consExtAltEnv γ x s c bs e suf = do ct <- ctorTy γ c s @@ -730,17 +741,17 @@ consExtAltEnv γ x s c bs e suf = do consRelCheckAltAsyncL :: UnaryTyping -> CGEnv -> RelEnv -> SpecType -> SpecType -> F.Expr -> Var -> Var -> SpecType -> CoreExpr -> Alt CoreBndr -> CG () -consRelCheckAltAsyncL unary γ ψ t1 t2 p x1 x1' s1 e2 (c, bs1, e1) = do +consRelCheckAltAsyncL unary γ ψ t1 t2 p x1 x1' s1 e2 (Ghc.Alt c bs1 e1) = do (γ', e1') <- consExtAltEnv γ (F.symbol x1') s1 c bs1 e1 relSuffixL consRelCheck unary γ' ψ (subVarAndTy x1 x1' e1') e2 t1 t2 p consRelCheckAltAsyncR :: UnaryTyping -> CGEnv -> RelEnv -> SpecType -> SpecType -> F.Expr -> CoreExpr -> Var -> Var -> SpecType -> Alt CoreBndr -> CG () -consRelCheckAltAsyncR unary γ ψ t1 t2 p e1 x2 x2' s2 (c, bs2, e2) = do +consRelCheckAltAsyncR unary γ ψ t1 t2 p e1 x2 x2' s2 (Ghc.Alt c bs2 e2) = do (γ', e2') <- consExtAltEnv γ (F.symbol x2') s2 c bs2 e2 relSuffixR consRelCheck unary γ' ψ e1 (subVarAndTy x2 x2' e2') t1 t2 p --- consRelCheckAltSync :: CGEnv -> RelEnv -> SpecType -> SpecType -> F.Expr -> +-- consRelCheckAltSync :: CGEnv -> PrEnv -> SpecType -> SpecType -> F.Expr -> -- F.Symbol -> F.Symbol -> SpecType -> SpecType -> RelAlt -> CG () -- consRelCheckAltSync γ ψ t1 t2 p x1 x2 s1 s2 (c, bs1, bs2, e1, e2) = do -- (γ', e1') <- consExtAltEnv γ x1 s1 c bs1 e1 relSuffixL @@ -765,7 +776,6 @@ unapply γ y yt (z : zs) (RFun x _ s t _) e suffix = do z' = mkCopyWithSuffix suffix z evar = F.symbol z' e' = subVarAndTy z z' e --- unapply γ y yt l@(_ : _) (RAllP p ty) e suffix = unapply γ y yt l (forgetRAllP p ty) e suffix unapply _ _ _ (_ : _) t _ _ = F.panic $ "can't unapply type " ++ F.showpp t unapply γ y yt [] t e _ = do let yt' = t `F.meet` yt @@ -785,10 +795,10 @@ instantiateTys = L.foldl' go consRelSynth :: UnaryTyping -> CGEnv -> RelEnv -> CoreExpr -> CoreExpr -> CG (SpecType, SpecType, [F.Expr]) consRelSynth unary γ ψ (Tick tt e) d = - {- traceSyn "Left Tick" e d -} consRelSynth unary (γ `setLocation` Sp.Tick tt) ψ e d + consRelSynth unary (γ `setLocation` Sp.Tick tt) ψ e d consRelSynth unary γ ψ e (Tick tt d) = - {- traceSyn "Right Tick" e d -} consRelSynth unary (γ `setLocation` Sp.Tick tt) ψ e d + consRelSynth unary (γ `setLocation` Sp.Tick tt) ψ e d consRelSynth unary γ ψ a1@(App e1 d1) e2 | Type t1 <- GM.unTickExpr d1 = traceSyn "App Ty L" a1 e2 $ do @@ -807,7 +817,6 @@ consRelSynth unary γ ψ e1 a2@(App e2 d2) | Type t2 <- GM.unTickExpr d2 = consRelSynth unary γ ψ a1@(App e1 d1) a2@(App e2 d2) = traceSyn "App Exp Exp" a1 a2 $ do (ft1, ft2, fps) <- consRelSynth unary γ ψ e1 e2 (t1, t2, ps) <- consRelSynthApp unary γ ψ ft1 ft2 fps d1 d2 - -- qs <- instantiateApp a1 a2 γ ψ return (t1, t2, ps) consRelSynth unary γ ψ e d = traceSyn "Unary" e d $ do @@ -837,10 +846,9 @@ consRelSynthApp :: UnaryTyping -> CGEnv -> RelEnv -> SpecType -> SpecType -> consRelSynthApp unary γ ψ ft1 ft2 ps e1 (Tick _ e2) = consRelSynthApp unary γ ψ ft1 ft2 ps e1 e2 consRelSynthApp unary γ ψ ft1 ft2 ps (Tick t1 e1) e2 = - -- TODO: create span consRelSynthApp unary (γ `setLocation` Sp.Tick t1) ψ ft1 ft2 ps e1 e2 -consRelSynthApp unary γ ψ ft1@(RFun v1 _ s1{- @RFun{} -} t1 r1) ft2@(RFun v2 _ s2{- @RFun{} -} t2 r2) ps@[F.PImp q p] d1@(Var x1) d2@(Var x2) +consRelSynthApp unary γ ψ ft1@(RFun v1 _ s1 t1 r1) ft2@(RFun v2 _ s2 t2 r2) ps@[F.PImp q p] d1@(Var x1) d2@(Var x2) = traceSynApp ft1 ft2 ps d1 d2 $ do entlFunRefts γ r1 r2 "consRelSynthApp HO" let qsubst = F.subst $ F.mkSubst [(v1, F.EVar resL), (v2, F.EVar resR)] @@ -857,18 +865,8 @@ consRelSynthApp unary γ ψ ft1@(RFun v1 _ s1 t1 r1) ft2@(RFun v2 _ s2 t2 r2) ps F.subst $ F.mkSubst [(v1, F.EVar $ F.symbol x1), (v2, F.EVar $ F.symbol x2)] return (subst t1, subst t2, map subst qs) -consRelSynthApp _ _ _ RFun{} RFun{} ps d1@(Var _) d2@(Var _) - = F.panic $ "consRelSynthApp: multiple rel sigs not supported " ++ F.showpp (ps, d1, d2) --- do --- entlFunRefts γ r1 r2 "consRelSynthApp FO" --- consUnaryCheck γ d1 s1 --- consUnaryCheck γ d2 s2 --- let qsubst = F.subst $ F.mkSubst [(v1, F.EVar resL), (v2, F.EVar resR)] --- (_, _, qs) <- consRelSynth γ ψ d1 d2 --- let subst = --- F.subst $ F.mkSubst --- [(v1, F.EVar $ F.symbol x1), (v2, F.EVar $ F.symbol x2)] --- return (subst t1, subst t2, map (subst . unapplyRelArgs v1 v2) (qsubst qs ++ ps)) +consRelSynthApp _ _ _ ft1@RFun{} ft2@RFun{} ps d1@(Var _) d2@(Var _) + = F.panic $ "consRelSynthApp: multiple rel sigs not supported " ++ F.showpp (ft1, ft2, ps, d1, d2) consRelSynthApp _ _ _ RFun{} RFun{} _ d1 d2 = F.panic $ "consRelSynthApp: expected application to variables, got" ++ F.showpp (d1, d2) consRelSynthApp _ _ _ t1 t2 p d1 d2 = @@ -965,13 +963,11 @@ partitionArgs :: [Var] -> [Var] -> [SpecType] -> [SpecType] -> [F.Expr] -> (RelE partitionArgs xs1 xs2 ts1 ts2 qs = (map toRel ho, map toUnary fo) where (ho, fo) = L.partition (isFuncPred . toUnary) (zip5 xs1 xs2 ts1 ts2 qs) - -- unapp = L.foldl' (\p (v1, v2) -> unapplyRelArgs v1 v2 p) toRel (f1, f2, t1, t2, q) = let (vs1, ts1') = vargs t1 in let (vs2, ts2') = vargs t2 in let bs1 = zip vs1 (fst . vargs <$> ts1') in let bs2 = zip vs2 (fst . vargs <$> ts2') - -- TODO: add symmetric RelPred in let rp = RelPred f1 f2 bs1 bs2 $ ERBasic q in traceWhenLoud ("partitionArgs toRel: " ++ F.showpp (f1, f2, bs1, bs2, q)) rp toUnary (_, _, _, _, q) = q @@ -983,18 +979,6 @@ unRAllT t msg = F.panic $ msg ++ ": expected RAllT, got: " ++ F.showpp t forgetRAllP :: PVU RTyCon RTyVar -> SpecType -> SpecType forgetRAllP _ t = t --- isCtor :: Ghc.DataCon -> F.Expr -> F.Expr --- isCtor d = F.EApp (F.EVar $ makeDataConChecker d) - --- isAltCon :: AltCon -> F.Symbol -> F.Expr --- isAltCon (DataAlt c) x | c == Ghc.trueDataCon = F.EVar x --- isAltCon (DataAlt c) x | c == Ghc.falseDataCon = F.PNot $ F.EVar x --- isAltCon (DataAlt c) x = isCtor c (F.EVar x) --- isAltCon _ _ = F.PTrue - --- isBoolDataCon :: DataCon -> Bool --- isBoolDataCon c = c == Ghc.trueDataCon || c == Ghc.falseDataCon - args :: CoreExpr -> CoreExpr -> SpecType -> SpecType -> F.Expr -> Maybe ([Var], [Var], [F.Symbol], [F.Symbol], [SpecType], [SpecType], [F.Expr]) args e1 e2 t1 t2 ps @@ -1040,102 +1024,10 @@ prems :: F.Expr -> [F.Expr] prems (F.PImp q p) = q : prems p prems _ = [] --- conclRel :: RelExpr -> F.Expr --- conclRel (ERBasic e ) = e --- conclRel (ERChecked _ b) = conclRel b --- conclRel (ERUnChecked _ b) = conclRel b - concl :: F.Expr -> F.Expr concl (F.PImp _ p) = concl p concl p = p --- unpackApp :: CoreExpr -> Maybe [Var] --- unpackApp = fmap reverse . unpack' . GM.unTickExpr --- where --- unpack' :: CoreExpr -> Maybe [Var] --- unpack' (Tick _ e) = unpack' e --- unpack' (Var f ) = Just [f] --- unpack' (App e (Var α)) | Ghc.isTyVar α = unpack' e --- unpack' (App e (Type _)) = unpack' e --- unpack' (App e (Var x)) = (x :) <$> unpack' e --- unpack' e = traceWhenLoud ("can't unpackApp APP " ++ show e) Nothing - --- instantiateApp :: CoreExpr -> CoreExpr -> CGEnv -> RelEnv -> CG [F.Expr] --- instantiateApp e1 e2 γ ψ = traceWhenLoud --- ("instantiateApp " ++ F.showpp e1 ++ " " ++ F.showpp e2 ++ " " ++ (concatMap ((++ "\n"). show) ψ)) --- concatMapM (inst (unpackApp e1) (unpackApp e2)) ψ --- where --- inst :: Maybe [Var] -> Maybe [Var] -> RelPred -> CG [F.Expr] --- inst (Just (f1:xs1)) (Just (f2:xs2)) qpr --- | fun1 qpr == f1 --- , fun2 qpr == f2 --- , length (args1 qpr) == length xs1 --- , length (args2 qpr) == length xs2 --- = do --- p <- traceWhenLoud ("instantiateApp qpr pred: " ++ F.showpp (fromRelExpr (prop qpr))) --- consTotalHOPred xs1 xs2 (args1 qpr) (args2 qpr) (prop qpr) [] --- return $ --- traceWhenLoud ("instantiateApp: " ++ F.showpp p) --- [p] --- inst _ _ _ = return [] --- consTotalHOPred :: [Var] -> [Var] -> [(F.Symbol, [F.Symbol])] -> [(F.Symbol, [F.Symbol])] -> RelExpr -> [F.Expr] -> CG F.Expr --- consTotalHOPred [] [] [] [] rps qs = return $ if null p then F.PTrue else L.foldr1 F.PImp p --- where --- ps = fromRelExpr rps --- p = reverse qs ++ (prems ps ++ [concl ps]) --- consTotalHOPred (x1:xs1) (x2:xs2) ((b1, bs1@(_:_)):vs1) ((b2, bs2@(_:_)):vs2) ps' qs --- | Just (q, ps) <- traceWhenLoud ("consTotalHOPred ps' (chk) " ++ F.showpp (fromRelExpr ps')) unImp ps' = do --- (tf1, tf2, _) <- consRelSynth γ ψ (Var x1) (Var x2) --- case (tf1, tf2) of --- (RFun x1' _ _ _ _, RFun x2' _ _ _ _) -> do --- fqs <- instantiateApp (App (Var x1) (Var evar1)) (App (Var x2) (Var evar2)) γ ψ --- let fqsub = F.mkSubst [(F.symbol evar1, F.EVar x1'), (F.symbol evar2, F.EVar x2')] --- let bs2args = zip (bs1 ++ bs2) (F.EVar <$> fst (vargs tf1) ++ fst (vargs tf2)) --- let qsub = F.mkSubst (traceWhenLoud ("subst qpr prem " ++ show bs2args) bs2args) --- let p = F.subst fqsub $ F.PAnd (unapplyRelArgs (F.symbol x1) (F.symbol x2) <$> fqs) --- let q' = F.subst qsub q --- consRelSub γ tf1 tf2 (traceWhenLoud ("consTotalHOPred fqs for (" ++ F.showpp evar1 ++ " " ++ F.showpp evar2 ++ "): " --- ++ F.showpp fqs ++ " consTotalHOPred p: " ++ F.showpp p) p) --- (traceWhenLoud ("consTotalHOPred q: " ++ F.showpp q') q') --- let bs2fs = F.mkSubst [(b1, F.EVar (F.symbol x1)), (b2, F.EVar (F.symbol x2))] --- consTotalHOPred xs1 xs2 vs1 vs2 --- (substR bs2fs $ unapplyRelArgsR (F.symbol x1) (F.symbol x2) ps) qs --- _ -> F.panic "consTotalHOPred: bs " --- where --- (evar1, evar2) = mkRelCopies x1 x2 --- -- f1 = symbolType γ x1 "consTotalHOPred funArg L" --- -- f2 = symbolType γ x2 "consTotalHOPred funArg R" --- consTotalHOPred (x1:xs1) (x2:xs2) ((b1, _):vs1) ((b2, _):vs2) (ERChecked q ps) qs --- = do --- (tf1, tf2, _) <- consRelSynth γ ψ (Var x1) (Var x2) --- fqs <- instantiateApp (Var x1) (Var x2) γ ψ --- let bs2rs = [(b1, F.EVar resL), (b2, F.EVar resR)] --- let qsub = F.mkSubst bs2rs --- let p = F.PAnd (unapplyRelArgs (F.symbol x1) (F.symbol x2) <$> fqs) --- let q' = F.subst qsub q --- consRelSub γ tf1 tf2 (traceWhenLoud ("consTotalHOPred fqs: " ++ F.showpp fqs ++ " consTotalHOPred p: " ++ F.showpp p) p) --- (traceWhenLoud ("consTotalHOPred q: " ++ F.showpp q') q') --- let bs2args = F.mkSubst [(b1, F.EVar (F.symbol x1)), (b2, F.EVar (F.symbol x2))] --- consTotalHOPred xs1 xs2 vs1 vs2 --- (substR bs2args $ unapplyRelArgsR (F.symbol x1) (F.symbol x2) ps) qs --- consTotalHOPred (x1:xs1) (x2:xs2) ((v1, _):vs1) ((v2, _):vs2) (ERUnChecked q ps) qs --- = consTotalHOPred xs1 xs2 vs1 vs2 (substR sb $ unapplyRelArgsR (F.symbol x1) (F.symbol x2) ps) (F.subst sb <$> q : qs) --- where --- sb = F.mkSubst [(v1, F.EVar $ F.symbol x1), (v2, F.EVar $ F.symbol x2)] --- -- TODO: change the parser to prioritise ERUnChecked q ps --- consTotalHOPred (x1:xs1) (x2:xs2) ((v1, _):vs1) ((v2, _):vs2) (ERBasic (F.PImp q ps)) qs --- = consTotalHOPred xs1 xs2 vs1 vs2 (substR sb $ unapplyRelArgsR (F.symbol x1) (F.symbol x2) (ERBasic ps)) (F.subst sb <$> q : qs) --- where --- sb = F.mkSubst [(v1, F.EVar $ F.symbol x1), (v2, F.EVar $ F.symbol x2)] --- consTotalHOPred xs1 xs2 vs1 vs2 ps qs = F.panic $ "consTotalHOPred: number of premises should be >= length of arg list" ++ --- F.showpp xs1 ++ " " ++ F.showpp xs2 ++ " " ++ F.showpp vs1 ++ " " ++ F.showpp vs2 ++ --- " " ++ F.showpp (fromRelExpr ps) ++ " " ++ F.showpp qs - --- substR :: F.Subst -> RelExpr -> RelExpr --- substR sb (ERChecked p rp) = ERChecked (F.subst sb p) (substR sb rp) --- substR sb (ERUnChecked p rp) = ERUnChecked (F.subst sb p) (substR sb rp) --- substR sb (ERBasic p) = ERBasic (F.subst sb p) - extendWithTyVar :: CGEnv -> TyVar -> CG CGEnv extendWithTyVar γ a | isValKind (Ghc.tyVarKind a) @@ -1143,15 +1035,6 @@ extendWithTyVar γ a | otherwise = return γ --- unifyAlts :: CoreBndr -> CoreBndr -> [Alt CoreBndr] -> [Alt CoreBndr] -> Maybe [RelAlt] --- unifyAlts x1 x2 alts1 alts2 = mapM subRelCopiesAlts (zip alts1 alts2) --- where --- subRelCopiesAlts ((a1, bs1, e1), (a2, bs2, e2)) --- | a1 /= a2 = Nothing --- | otherwise = let (e1', e2') = L.foldl' sb (subRelCopies e1 x1 e2 x2) (zip bs1 bs2) --- in Just (a1, mkLCopies bs1, mkRCopies bs2, e1', e2') --- sb (e1, e2) (x1', x2') = subRelCopies e1 x1' e2 x2' - matchFunArgs :: SpecType -> SpecType -> F.Symbol -> F.Expr matchFunArgs (RAllT _ t1 _) t2 x = matchFunArgs t1 t2 x matchFunArgs t1 (RAllT _ t2 _) x = matchFunArgs t1 t2 x @@ -1213,12 +1096,6 @@ mkRelCopiesWithMapping m x1 x2 = getMapping m x1 x2 mkRelCopies :: Var -> Var -> (Var, Var) mkRelCopies x1 x2 = (mkCopyWithSuffix relSuffixL x1, mkCopyWithSuffix relSuffixR x2) --- mkLCopies :: [Var] -> [Var] --- mkLCopies = (mkCopyWithSuffix relSuffixL <$>) - --- mkRCopies :: [Var] -> [Var] --- mkRCopies = (mkCopyWithSuffix relSuffixR <$>) - mkCopyWithName :: String -> Var -> Var mkCopyWithName s v = traceWhenLoud ("mkCopyWithName: produced an occ name " ++ Ghc.getOccString (varName v')) v' -- where v' = GM.stringVar s (Ghc.exprType (Var v)) @@ -1293,25 +1170,6 @@ fromRelExpr (ERBasic e) = e fromRelExpr (ERChecked a b) = F.PImp (fromRelExpr a) (fromRelExpr b) fromRelExpr (ERUnChecked a b) = F.PImp a (fromRelExpr b) --- toRelExpr :: F.Expr -> RelExpr --- toRelExpr (F.PImp a b) = ERUnChecked a (toRelExpr b) --- toRelExpr p = ERBasic p - --- unImp :: RelExpr -> Maybe (F.Expr, RelExpr) --- unImp (ERBasic (F.PImp a b)) = Just (a, ERBasic b) --- unImp (ERChecked a b) = Just (a, b) --- unImp (ERUnChecked a b) = Just (a, b) --- unImp _ = Nothing - --- toBasic :: RelExpr -> Maybe F.Expr --- toBasic (ERBasic e) = Just e --- toBasic (ERChecked _ _) = Nothing --- toBasic (ERUnChecked a b) = F.PImp a <$> toBasic b - --- toBasicOr :: F.Expr -> RelExpr -> F.Expr --- toBasicOr t = MB.fromMaybe t . toBasic - - -------------------------------------------------------------- -- Pretty Printing Errors ------------------------------------ -------------------------------------------------------------- @@ -1331,20 +1189,17 @@ relWfError loc e1 e2 t1 t2 p msg -- Pretty Printing Unary Proofs ------------------------------ -------------------------------------------------------------- -relHint :: SpecType -> Ghc.Var -> CoreExpr -> Doc -relHint t v e = text "{- HLINT ignore \"Use camelCase\" -}" - $+$ text ("{-@ " ++ name - ++ " :: " - ++ F.showpp t - ++ " @-}") - $+$ text (name - ++ " :: " - ++ removeIdent (toType False t)) - $+$ text (coreToHs t v (fromAnf e)) - $+$ text "" - $+$ text "{- BARE CORE" - $+$ text (show e) - $+$ text "-}" +relHint :: RenVars -> SpecType -> Ghc.Var -> CoreExpr -> Doc +relHint rvs t v e = text "{- HLINT ignore \"Use camelCase\" -}" + $+$ text "{- HLINT ignore \"Use if\" -}" + $+$ text "{- HLINT ignore \"Use section\" -}" + $+$ text ("{-@ " ++ name ++ " :: " ++ F.showpp t ++ " @-}") + $+$ text (name ++ " :: " ++ removeIdent (toType False t)) + $+$ text (coreToHs rvs t v e) + -- $+$ text "" + -- $+$ text "{- BARE CORE" + -- $+$ text (show e) + -- $+$ text "-}" where name = Ghc.occNameString $ Ghc.getOccName v removeIdent :: Type -> String @@ -1373,48 +1228,6 @@ noIdent = Style { mode = OneLineMode -- Debug ----------------------------------------------------- -------------------------------------------------------------- --- showType :: SpecType -> String --- showType (RAllP _ t ) = "RAllP " ++ showType t --- showType (RAllT _ t _) = "RAllT " ++ showType t --- showType (RImpF _ _ t t' _) = --- "RImpF(" ++ showType t ++ ", " ++ showType t' ++ ") " --- showType (RFun _ _ t t' _) = "RFun(" ++ showType t ++ ", " ++ showType t' ++ ") " --- showType (RAllE _ t t' ) = "RAllE(" ++ showType t ++ ", " ++ showType t' ++ ") " --- showType (REx _ t t' ) = "REx(" ++ showType t ++ ", " ++ showType t' ++ ") " --- showType (RAppTy t t' _) = --- "RAppTy(" ++ showType t ++ ", " ++ showType t' ++ ") " --- showType (RApp _ ts _ _) = "RApp" ++ show (showType <$> ts) --- showType (RRTy xts _ _ t) = --- "RRTy(" --- ++ show (map (\(_, s) -> showType s) xts) --- ++ ", " --- ++ showType t --- ++ ") " --- showType v@(RVar _ _ ) = "RVar " ++ F.showpp v --- showType v@(RExprArg _) = "RExprArg " ++ F.showpp v --- showType v@(RHole _) = "RHole" ++ F.showpp v - --- traceUnapply :: (PPrint x1, PPrint x2, PPrint e1, PPrint e2) => x1 -> x2 -> e1 -> e2 -> e2 --- traceUnapply x1 x2 e1 e2 = traceWhenLoud ("Unapply\n" --- ++ "x1: " ++ F.showpp x1 ++ "\n\n" --- ++ "x2: " ++ F.showpp x2 ++ "\n\n" --- ++ "e1: " ++ F.showpp e1 ++ "\n\n" --- ++ "e2: " ++ F.showpp e2) e2 - --- traceHsCs :: CG a -> CG a --- traceHsCs m = do --- hcs <- gets hsCs --- traceWhenLoud ("NEW SUBTYPING CS\n" ++ F.showpp hcs) m - --- traceHsCsSyn :: UnarySynthesis -> UnarySynthesis --- traceHsCsSyn syn γ e = do --- hcs <- gets hsCs --- modify $ \s -> s { hsCs = [] } --- t <- syn γ e --- hcs' <- gets hsCs --- traceWhenLoud ("NEW SUBTYPING CS\n" ++ F.showpp hcs') $ --- modify $ \s -> s { hsCs = hcs' ++ hcs } --- return t traceSub :: (PPrint t, PPrint s, PPrint p, PPrint q) => String -> t -> s -> p -> q -> a -> a traceSub msg t s p q = traceWhenLoud (msg ++ " RelSub\n" diff --git a/src/Language/Haskell/Liquid/Constraint/Split.hs b/src/Language/Haskell/Liquid/Constraint/Split.hs index 52b7fc8548..6d5b47841c 100644 --- a/src/Language/Haskell/Liquid/Constraint/Split.hs +++ b/src/Language/Haskell/Liquid/Constraint/Split.hs @@ -2,7 +2,7 @@ {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -------------------------------------------------------------------------------- -- | Constraint Splitting ------------------------------------------------------ @@ -185,18 +185,18 @@ splitC allowTC (SubC γ t1 (RAllE x tx t2)) γ' <- γ += ("addAllBind 2", y, forallExprRefType γ tx) splitC allowTC (SubC γ' t1 (F.subst1 t2 (x, F.EVar y))) -splitC allowTC (SubC γ (RRTy env _ OCons t1) t2) - = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) γ xts +splitC allowTC (SubC cgenv (RRTy env _ OCons t1) t2) + = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) cgenv xts c1 <- splitC allowTC (SubC γ' t1' t2') - c2 <- splitC allowTC (SubC γ t1 t2 ) + c2 <- splitC allowTC (SubC cgenv t1 t2 ) return $ c1 ++ c2 where (xts, t1', t2') = envToSub env -splitC allowTC (SubC γ (RRTy e r o t1) t2) - = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) γ e +splitC allowTC (SubC cgenv (RRTy e r o t1) t2) + = do γ' <- foldM (\γ (x, t) -> γ `addSEnv` ("splitS", x,t)) cgenv e c1 <- splitC allowTC (SubR γ' o r) - c2 <- splitC allowTC (SubC γ t1 t2) + c2 <- splitC allowTC (SubC cgenv t1 t2) return $ c1 ++ c2 splitC allowTC (SubC γ (RFun x1 i1 t1 t1' r1) (RFun x2 i2 t2 t2' r2)) @@ -451,10 +451,10 @@ forallExprReft_ _ _ forallExprReftLookup :: CGEnv -> F.Symbol -> Maybe ([F.Symbol], [RFInfo], [SpecType], [RReft], SpecType) -forallExprReftLookup γ x = snap <$> F.lookupSEnv x (syenv γ) +forallExprReftLookup γ sym = snap <$> F.lookupSEnv sym (syenv γ) where - snap = mapFifth5 ignoreOblig . (\(_,(x,a,b,c),t)->(x,a,b,c,t)) . bkArrow . thd3 . bkUniv . lookup - lookup z = fromMaybe (panicUnbound γ z) (γ ?= F.symbol z) + snap = mapFifth5 ignoreOblig . (\(_,(x,a,b,c),t)->(x,a,b,c,t)) . bkArrow . thd3 . bkUniv . lookup' + lookup' z = fromMaybe (panicUnbound γ z) (γ ?= F.symbol z) -------------------------------------------------------------------------------- diff --git a/src/Language/Haskell/Liquid/Constraint/ToFixpoint.hs b/src/Language/Haskell/Liquid/Constraint/ToFixpoint.hs index 4af01fad8a..b11dff81fe 100644 --- a/src/Language/Haskell/Liquid/Constraint/ToFixpoint.hs +++ b/src/Language/Haskell/Liquid/Constraint/ToFixpoint.hs @@ -1,6 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.Constraint.ToFixpoint ( cgInfoFInfo @@ -148,13 +148,13 @@ makeRewrites info sub = concatMap (makeRewriteOne tce) $ filter ((`S.member` rws canRewrite :: S.HashSet F.Symbol -> F.Expr -> F.Expr -> Bool -canRewrite freeVars from to = noFreeSyms && doesNotDiverge +canRewrite freeVars' from to = noFreeSyms && doesNotDiverge where - fromSyms = S.intersection freeVars (S.fromList $ F.syms from) - toSyms = S.intersection freeVars (S.fromList $ F.syms to) + fromSyms = S.intersection freeVars' (S.fromList $ F.syms from) + toSyms = S.intersection freeVars' (S.fromList $ F.syms to) noFreeSyms = S.null $ S.difference toSyms fromSyms - doesNotDiverge = Mb.isNothing (unify (S.toList freeVars) from to) - || Mb.isJust (unify (S.toList freeVars) to from) + doesNotDiverge = Mb.isNothing (unify (S.toList freeVars') from to) + || Mb.isJust (unify (S.toList freeVars') to from) refinementEQs :: LocSpecType -> [(F.Expr, F.Expr)] refinementEQs t = @@ -174,10 +174,10 @@ makeRewriteOne tce (_, t) rewrites :: F.Expr -> F.Expr -> [F.AutoRewrite] rewrites lhs rhs = - (guard (canRewrite freeVars lhs rhs) >> [F.AutoRewrite xs lhs rhs]) - ++ (guard (canRewrite freeVars rhs lhs) >> [F.AutoRewrite xs rhs lhs]) + (guard (canRewrite freeVars' lhs rhs) >> [F.AutoRewrite xs lhs rhs]) + ++ (guard (canRewrite freeVars' rhs lhs) >> [F.AutoRewrite xs rhs lhs]) - freeVars = S.fromList (ty_binds tRep) + freeVars' = S.fromList (ty_binds tRep) xs = do (sym, arg) <- zip (ty_binds tRep) (ty_args tRep) @@ -193,7 +193,7 @@ hasClassArg :: Id -> Bool hasClassArg x = F.tracepp msg (GM.isDataConId x && any Ghc.isClassPred (t:ts')) where msg = "hasClassArg: " ++ showpp (x, t:ts') - (ts, t) = Ghc.splitFunTys . snd . Ghc.splitForAllTys . Ghc.varType $ x + (ts, t) = Ghc.splitFunTys . snd . Ghc.splitForAllTyCoVars . Ghc.varType $ x ts' = map Ghc.irrelevantMult ts @@ -219,36 +219,36 @@ specTypeEq emb f t = F.mkEquation (F.symbol f) xts body tOut bExp = F.eApps (F.eVar f) (F.EVar <$> xs) makeSimplify :: (Var, SpecType) -> [F.Rewrite] -makeSimplify (x, t) - | not (GM.isDataConId x) +makeSimplify (var, t) + | not (GM.isDataConId var) = [] | otherwise - = go $ specTypeToResultRef (F.eApps (F.EVar $ F.symbol x) (F.EVar <$> ty_binds (toRTypeRep t))) t + = go $ specTypeToResultRef (F.eApps (F.EVar $ F.symbol var) (F.EVar <$> ty_binds (toRTypeRep t))) t where go (F.PAnd es) = concatMap go es - go (F.PAtom eq (F.EApp (F.EVar f) dc) bd) + go (F.PAtom eq (F.EApp (F.EVar f) expr) bd) | eq `elem` [F.Eq, F.Ueq] - , (F.EVar dc, xs) <- F.splitEApp dc - , dc == F.symbol x + , (F.EVar dc, xs) <- F.splitEApp expr + , dc == F.symbol var , all isEVar xs = [F.SMeasure f dc (fromEVar <$> xs) bd] - go (F.PIff (F.EApp (F.EVar f) dc) bd) - | (F.EVar dc, xs) <- F.splitEApp dc - , dc == F.symbol x + go (F.PIff (F.EApp (F.EVar f) expr) bd) + | (F.EVar dc, xs) <- F.splitEApp expr + , dc == F.symbol var , all isEVar xs = [F.SMeasure f dc (fromEVar <$> xs) bd] - go (F.EApp (F.EVar f) dc) - | (F.EVar dc, xs) <- F.splitEApp dc - , dc == F.symbol x + go (F.EApp (F.EVar f) expr) + | (F.EVar dc, xs) <- F.splitEApp expr + , dc == F.symbol var , all isEVar xs = [F.SMeasure f dc (fromEVar <$> xs) F.PTrue] - go (F.PNot (F.EApp (F.EVar f) dc)) - | (F.EVar dc, xs) <- F.splitEApp dc - , dc == F.symbol x + go (F.PNot (F.EApp (F.EVar f) expr)) + | (F.EVar dc, xs) <- F.splitEApp expr + , dc == F.symbol var , all isEVar xs = [F.SMeasure f dc (fromEVar <$> xs) F.PFalse] @@ -282,11 +282,11 @@ equationBody allowTC f xArgs e mbT -- NV Move this to types? -- sound but imprecise approximation of a type in the logic specTypeToLogic :: Bool -> [F.Expr] -> F.Expr -> SpecType -> F.Expr -specTypeToLogic allowTC es e t +specTypeToLogic allowTC es expr st | ok = F.subst su (F.PImp (F.pAnd args) res) | otherwise = F.PTrue where - res = specTypeToResultRef e t + res = specTypeToResultRef expr st args = zipWith mkExpr (mkReft <$> ts) es mkReft t = F.toReft $ Mb.fromMaybe mempty (stripRTypeBase t) mkExpr (F.Reft (v, ev)) e = F.subst1 ev (v, e) @@ -307,7 +307,7 @@ specTypeToLogic allowTC es e t :: ([(F.Symbol, SpecType)], [(F.Symbol, SpecType)]) (xs, ts) = unzip nocls :: ([F.Symbol], [SpecType]) - trep = toRTypeRep t + trep = toRTypeRep st specTypeToResultRef :: F.Expr -> SpecType -> F.Expr diff --git a/src/Language/Haskell/Liquid/Constraint/Types.hs b/src/Language/Haskell/Liquid/Constraint/Types.hs index a64bc33508..dcf1660499 100644 --- a/src/Language/Haskell/Liquid/Constraint/Types.hs +++ b/src/Language/Haskell/Liquid/Constraint/Types.hs @@ -3,8 +3,6 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE FlexibleInstances #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Constraint.Types ( -- * Constraint Generation Monad CG @@ -103,7 +101,7 @@ data CGEnv = CGE , tgKey :: !(Maybe Tg.TagKey) -- ^ Current top-level binder , trec :: !(Maybe (M.HashMap F.Symbol SpecType)) -- ^ Type of recursive function with decreasing constraints , lcb :: !(M.HashMap F.Symbol CoreExpr) -- ^ Let binding that have not been checked (c.f. LAZYVARs) - , forallcb :: !(M.HashMap Var F.Expr) -- ^ Polymorhic let bindings + , forallcb :: !(M.HashMap Var F.Expr) -- ^ Polymorhic let bindings , holes :: !HEnv -- ^ Types with holes, will need refreshing , lcs :: !LConstraint -- ^ Logical Constraints , cerr :: !(Maybe (TError SpecType)) -- ^ error that should be reported at the user @@ -150,15 +148,15 @@ data SubC = SubC { senv :: !CGEnv data WfC = WfC !CGEnv !SpecType -- deriving (Data, Typeable) -type FixSubC = F.SubC Cinfo -type FixWfC = F.WfC Cinfo - +type FixSubC = F.SubC Cinfo +type FixWfC = F.WfC Cinfo +type FixBindEnv = F.BindEnv Cinfo subVar :: FixSubC -> Maybe Var subVar = ci_var . F.sinfo instance PPrint SubC where - pprintTidy k c@(SubC {}) = + pprintTidy k c@SubC {} = "The environment:" $+$ "" @@ -177,7 +175,7 @@ instance PPrint SubC where , "<:" , pprintTidy k (rhs c) ] - pprintTidy k c@(SubR {}) = + pprintTidy k c@SubR {} = "The environment:" $+$ "" @@ -209,19 +207,18 @@ data CGInfo = CGInfo , fixCs :: ![FixSubC] -- ^ subtyping over Sort (post-splitting) , fixWfs :: ![FixWfC] -- ^ wellformedness constraints over Sort (post-splitting) , freshIndex :: !Integer -- ^ counter for generating fresh KVars - , binds :: !F.BindEnv -- ^ set of environment binders + , binds :: !FixBindEnv -- ^ set of environment binders , ebinds :: ![F.BindId] -- ^ existentials , annotMap :: !(AnnInfo (Annot SpecType)) -- ^ source-position annotation map - , holesMap :: !(M.HashMap Var (HoleInfo (CGInfo, CGEnv) SpecType)) -- ^ information for ghc hole expressions , relHints :: !Doc -- ^ Unary proofs generated for relational specs , relWf :: ![Error] -- ^ Relational well-formedness errors , tyConInfo :: !TyConMap -- ^ information about type-constructors - , specDecr :: ![(Var, [Int])] -- ^ ^ Lexicographic order of decreasing args (DEPRECATED) + , specDecr :: ![(Var, [Int])] -- ^ ^ Lexicographic order of decreasing args (DEPRECATED) , newTyEnv :: !(M.HashMap Ghc.TyCon SpecType) -- ^ Mapping of new type type constructors with their refined types. , termExprs :: !(M.HashMap Var [F.Located F.Expr]) -- ^ Terminating Metrics for Recursive functions , specLVars :: !(S.HashSet Var) -- ^ Set of variables to ignore for termination checking , specLazy :: !(S.HashSet Var) -- ^ "Lazy binders", skip termination checking - , specTmVars :: !(S.HashSet Var) -- ^ Binders that FAILED struct termination check that MUST be checked + , specTmVars :: !(S.HashSet Var) -- ^ Binders that FAILED struct termination check that MUST be checked , autoSize :: !(S.HashSet Ghc.TyCon) -- ^ ? FIX THIS , tyConEmbed :: !(F.TCEmb Ghc.TyCon) -- ^ primitive Sorts into which TyCons should be embedded , kuts :: !F.Kuts -- ^ Fixpoint Kut variables (denoting "back-edges"/recursive KVars) @@ -300,7 +297,7 @@ type RTyConIAl = M.HashMap RTyCon [RInv] -------------------------------------------------------------------------------- mkRTyConInv :: [(Maybe Var, F.Located SpecType)] -> RTyConInv -------------------------------------------------------------------------------- -mkRTyConInv ts = group [ (c, RInv (go ts) t v) | (v, t@(RApp c ts _ _)) <- strip <$> ts] +mkRTyConInv tss = group [ (c, RInv (go ts) t v) | (v, t@(RApp c ts _ _)) <- strip <$> tss] where strip = mapSnd (thrd3 . bkUniv . val) go ts | generic (toRSort <$> ts) = [] @@ -346,9 +343,9 @@ addRInv m (x, t) | otherwise = (x, t) where - ids = [id | tc <- M.keys m + ids = [id' | tc <- M.keys m , dc <- Ghc.tyConDataCons $ rtc_tc tc - , AnId id <- Ghc.dataConImplicitTyThings dc] + , AnId id' <- Ghc.dataConImplicitTyThings dc] res = ty_res . toRTypeRep conjoinInvariantShift :: SpecType -> SpecType -> SpecType @@ -388,15 +385,15 @@ restoreInvariant γ is = γ {invs = is} makeRecInvariants :: CGEnv -> [Var] -> CGEnv makeRecInvariants γ [x] = γ {invs = M.unionWith (++) (invs γ) is} where - is = M.map (map f . filter (isJust . (varType x `tcUnifyTy`) . toType False . _rinv_type)) (rinvs γ) - f i = i{_rinv_type = guard $ _rinv_type i} + is = M.map (map g . filter (isJust . (varType x `tcUnifyTy`) . toType False . _rinv_type)) (rinvs γ) + g i = i{_rinv_type = guard' $ _rinv_type i} - guard (RApp c ts rs r) + guard' (RApp c ts rs r) | Just f <- szFun <$> sizeFunction (rtc_info c) = RApp c ts rs (MkUReft (ref f $ F.toReft r) mempty) | otherwise = RApp c ts rs mempty - guard t + guard' t = t ref f (F.Reft(v, rr)) diff --git a/src/Language/Haskell/Liquid/GHC/Plugin.hs b/src/Language/Haskell/Liquid/GHC/Plugin.hs index 92be3eab7a..8c486c9cef 100644 --- a/src/Language/Haskell/Liquid/GHC/Plugin.hs +++ b/src/Language/Haskell/Liquid/GHC/Plugin.hs @@ -114,7 +114,7 @@ debugLog msg = when debugLogs $ liftIO (putStrLn msg) plugin :: GHC.Plugin plugin = GHC.defaultPlugin { typeCheckResultAction = liquidPlugin - , dynflagsPlugin = customDynFlags + , driverPlugin = customDynFlags , pluginRecompile = purePlugin } where @@ -126,8 +126,9 @@ plugin = GHC.defaultPlugin { -- for a post-mortem. liquidPlugin :: [CommandLineOption] -> ModSummary -> TcGblEnv -> TcM TcGblEnv liquidPlugin opts summary gblEnv = do + logger <- getLogger dynFlags <- getDynFlags - withTiming dynFlags (text "LiquidHaskell" <+> brackets (ppr $ ms_mod_name summary)) (const ()) $ do + withTiming logger dynFlags (text "LiquidHaskell" <+> brackets (ppr $ ms_mod_name summary)) (const ()) $ do if gopt Opt_Haddock dynFlags then do -- Warn the user @@ -136,7 +137,7 @@ plugin = GHC.defaultPlugin { ] let srcLoc = mkSrcLoc (mkFastString $ ms_hspp_file summary) 1 1 let warning = mkWarning (mkSrcSpan srcLoc srcLoc) msg - liftIO $ printWarning dynFlags warning + liftIO $ printWarning logger dynFlags warning pure gblEnv else do newGblEnv <- typecheckHook opts summary gblEnv @@ -157,21 +158,21 @@ plugin = GHC.defaultPlugin { -- | Overrides the default 'DynFlags' options. Specifically, we need the GHC -- lexer not to throw away block comments, as this is where the LH spec comments -- would live. This is why we set the 'Opt_KeepRawTokenStream' option. -customDynFlags :: [CommandLineOption] -> DynFlags -> IO DynFlags -customDynFlags opts dflags = do +customDynFlags :: [CommandLineOption] -> HscEnv -> IO HscEnv +customDynFlags opts hscEnv = do cfg <- liftIO $ LH.getOpts opts writeIORef cfgRef cfg - configureDynFlags dflags + return (hscEnv { hsc_dflags = configureDynFlags (hsc_dflags hscEnv) }) where - configureDynFlags :: DynFlags -> IO DynFlags + configureDynFlags :: DynFlags -> DynFlags configureDynFlags df = - pure $ df `gopt_set` Opt_ImplicitImportQualified - `gopt_set` Opt_PIC - `gopt_set` Opt_DeferTypedHoles - `gopt_set` Opt_KeepRawTokenStream - `xopt_set` MagicHash - `xopt_set` DeriveGeneric - `xopt_set` StandaloneDeriving + df `gopt_set` Opt_ImplicitImportQualified + `gopt_set` Opt_PIC + `gopt_set` Opt_DeferTypedHoles + `gopt_set` Opt_KeepRawTokenStream + `xopt_set` MagicHash + `xopt_set` DeriveGeneric + `xopt_set` StandaloneDeriving -------------------------------------------------------------------------------- -- | \"Unoptimising\" things ---------------------------------------------------- @@ -190,7 +191,7 @@ instance Unoptimise DynFlags where unoptimise df = updOptLevel 0 df { debugLevel = 1 , ghcLink = LinkInMemory - , hscTarget = HscInterpreted + , backend = Interpreter , ghcMode = CompManager } @@ -222,9 +223,12 @@ typecheckHook :: [CommandLineOption] -> ModSummary -> TcGblEnv -> TcM (Either Li typecheckHook _ (unoptimise -> modSummary) tcGblEnv = do debugLog $ "We are in module: " <> show (toStableModule thisModule) - parsed <- GhcMonadLike.parseModule (LH.keepRawTokenStream cleanedSummary) - let comments = LH.extractSpecComments (pm_annotations parsed) - typechecked <- GhcMonadLike.typecheckModule (LH.ignoreInline parsed) + parsed <- GhcMonadLike.parseModule (LH.keepRawTokenStream modSummary) + let comments = LH.extractSpecComments parsed + -- The LH plugin itself calls the type checker (see following line). This + -- would lead to a loop if we didn't remove the plugin when calling the type + -- checker. + typechecked <- updTopEnv dropPlugins $ GhcMonadLike.typecheckModule (LH.ignoreInline parsed) env <- askHscEnv resolvedNames <- LH.lookupTyThings env modSummary tcGblEnv availTyCons <- LH.availableTyCons env modSummary tcGblEnv (tcg_exports tcGblEnv) @@ -241,12 +245,7 @@ typecheckHook _ (unoptimise -> modSummary) tcGblEnv = do thisModule :: Module thisModule = tcg_mod tcGblEnv - cleanedSummary :: ModSummary - cleanedSummary = - modSummary { ms_hspp_opts = (ms_hspp_opts modSummary) { cachedPlugins = [] - , staticPlugins = [] - } - } + dropPlugins hsc_env = hsc_env { hsc_plugins = [], hsc_static_plugins = [] } serialiseSpec :: Module -> TcGblEnv -> LiquidLib -> TcM TcGblEnv serialiseSpec thisModule tcGblEnv liquidLib = do @@ -370,6 +369,8 @@ checkLiquidHaskellContext lhContext = do -- If there are unmatched filters or errors, and we are not reporting with -- json, we don't make it to this part of the code because errorLogger -- will throw an exception. + -- + -- F.Crash is also handled by reportResult and errorLogger case o_result out of F.Safe _ -> return $ Right pmrClientLib _ | json moduleCfg -> failM @@ -383,7 +384,7 @@ errorLogger file filters outputResult = do , failure = GHC.failM , continue = pure () , pprinter = \(spn, e) -> mkLongErrAt spn (LH.fromPJDoc e) O.empty - , matchingFilters = LH.reduceFilters (PJ.render . snd) filters + , matchingFilters = LH.reduceFilters (\(src, doc) -> PJ.render doc ++ " at " ++ LH.showPpr src) filters , filters = filters } (LH.orMessages outputResult) @@ -531,6 +532,7 @@ processModule LiquidHaskellContext{..} = do debugLog $ "mg_tcs => " ++ O.showSDocUnsafe (O.ppr $ mg_tcs modGuts) targetSrc <- makeTargetSrc moduleCfg file lhModuleTcData modGuts hscEnv + logger <- getLogger dynFlags <- getDynFlags -- See https://github.com/ucsd-progsys/liquidhaskell/issues/1711 @@ -548,10 +550,10 @@ processModule LiquidHaskellContext{..} = do (case result of -- Print warnings and errors, aborting the compilation. Left diagnostics -> do - liftIO $ mapM_ (printWarning dynFlags) (allWarnings diagnostics) + liftIO $ mapM_ (printWarning logger dynFlags) (allWarnings diagnostics) reportErrs $ allErrors diagnostics Right (warnings, targetSpec, liftedSpec) -> do - liftIO $ mapM_ (printWarning dynFlags) warnings + liftIO $ mapM_ (printWarning logger dynFlags) warnings let targetInfo = TargetInfo targetSrc targetSpec debugLog $ "bareSpec ==> " ++ show bareSpec @@ -618,8 +620,7 @@ makeTargetSrc cfg file tcData modGuts hscEnv = do debugLog $ "qualImports => " ++ show (tcQualifiedImports tcData) return $ TargetSrc - { giIncDir = mempty - , giTarget = file + { giTarget = file , giTargetMod = ModName Target (moduleName (mg_module modGuts)) , giCbs = coreBinds , giImpVars = impVars diff --git a/src/Language/Haskell/Liquid/Liquid.hs b/src/Language/Haskell/Liquid/Liquid.hs index c42e025607..acb2de07a5 100644 --- a/src/Language/Haskell/Liquid/Liquid.hs +++ b/src/Language/Haskell/Liquid/Liquid.hs @@ -3,11 +3,8 @@ {-@ LIQUID "--diff" @-} module Language.Haskell.Liquid.Liquid ( - -- * Executable command - liquid - -- * Single query - , runLiquid + runLiquid -- * Ghci State , MbEnv @@ -29,6 +26,8 @@ import System.Console.CmdArgs.Verbosity (whenLoud, whenNormal) import Control.Monad (when, unless) import qualified Data.Maybe as Mb import qualified Data.List as L +import qualified Data.Text as T +import Ormolu (ormolu, defaultConfig, OrmoluException) import qualified Control.Exception as Ex import qualified Language.Haskell.Liquid.UX.DiffCheck as DC import Language.Haskell.Liquid.Misc @@ -36,7 +35,6 @@ import Language.Fixpoint.Misc import Language.Fixpoint.Solver import qualified Language.Fixpoint.Types as F import Language.Haskell.Liquid.Types -import Language.Haskell.Liquid.Synthesize (synthesize) import Language.Haskell.Liquid.UX.Errors import Language.Haskell.Liquid.UX.CmdLine import Language.Haskell.Liquid.UX.Tidy @@ -52,16 +50,6 @@ import Liquid.GHC.API as GHC hiding (text, vcat, ($+$), getOpts, (<+>) type MbEnv = Maybe HscEnv - --------------------------------------------------------------------------------- -liquid :: [String] -> IO b --------------------------------------------------------------------------------- -liquid args = do - cfg <- getOpts args - printLiquidHaskellBanner - (ec, _) <- runLiquid Nothing cfg - exitWith ec - -------------------------------------------------------------------------------- liquidConstraints :: Config -> IO (Either [CGInfo] ExitCode) -------------------------------------------------------------------------------- @@ -267,22 +255,17 @@ solveCs cfg tgt cgi info names = do `addErrors` makeFailErrors (S.toList failBs) rf `addErrors` makeFailUseErrors (S.toList failBs) (giCbs $ giSrc info) let lErrors = applySolution sol <$> logErrors cgi - hErrors <- if typedHoles cfg - then synthesize tgt fcfg (cgi{holesMap = applySolution sol <$> holesMap cgi}) - else return [] when (relationalHints cfg) $ do let hintName = takeBaseName tgt ++ "_relToUn" let hintFile = replaceBaseName tgt hintName - let flags = "{-@ LIQUID \"--reflection\" @-}\n{-@ LIQUID \"--ple\" @-}\n\n" - let moduleFile = "module " ++ hintName ++ " ( module " ++ hintName ++ ") where\n" - ++ "import " ++ takeBaseName tgt ++ "\n" - ++ "import Language.Haskell.Liquid.ProofCombinators\n" - ++ "import GHC.Types\n" - + let flags = "{-@ LIQUID \"--reflection\" @-}\n" + ++ "{-@ LIQUID \"--ple\" @-}\n" + ++ "{-@ LIQUID \"--no-adt\" @-}\n\n" + let moduleFile = "module " ++ hintName ++ " ( module " ++ hintName ++ ") where\n" let listOfImps = map (\imp -> F.symbolicString imp) - (S.toList $ gsAllImps $ giSrc info) - let imports = - L.intercalate "\n" $ map ("import " ++) listOfImps + (S.toList $ gsAllImps $ giSrc info) + ++ [takeBaseName tgt, "GHC.Types", "GHC.Classes", "Language.Haskell.Liquid.ProofCombinators"] + let imports = L.intercalate "\n" $ map ("import " ++) listOfImps {- Modules that have the form of: "import moduleName (function)", @@ -296,14 +279,20 @@ solveCs cfg tgt cgi info names = do -} let hints = render (relHints cgi) unless (null hints) $ do - writeFile hintFile (flags ++ moduleFile ++ imports ++ "\n" ++ hints) + let hintRaw = flags ++ moduleFile ++ imports ++ "\n" ++ hints + hintOrmolu <- try (ormolu defaultConfig hintFile hintRaw) :: IO (Either OrmoluException T.Text) + case hintOrmolu of + Left ex -> do writeFile hintFile hintRaw + whenLoud $ print ex + Right hintFormatted -> writeFile hintFile (T.unpack hintFormatted) putStrLn "****** Relational Hints ********************************************************" putStrLn $ "Saved to file: " ++ hintFile - let resModel = resModel' `addErrors` (e2u cfg sol <$> (lErrors ++ hErrors ++ relWf cgi)) + let resModel = resModel' `addErrors` (e2u cfg sol <$> (lErrors ++ relWf cgi)) let out0 = mkOutput cfg resModel sol (annotMap cgi) return $ out0 { o_vars = names } { o_result = resModel } + e2u :: Config -> F.FixSolution -> Error -> UserError e2u cfg s = fmap F.pprint . tidyError cfg s diff --git a/src/Language/Haskell/Liquid/Measure.hs b/src/Language/Haskell/Liquid/Measure.hs index d19ccb3926..fdaa50e5c4 100644 --- a/src/Language/Haskell/Liquid/Measure.hs +++ b/src/Language/Haskell/Liquid/Measure.hs @@ -71,11 +71,11 @@ checkDuplicateMeasure :: [Measure ty ctor] -> [Measure ty ctor] checkDuplicateMeasure measures = case M.toList dups of [] -> measures - (m,ms):_ -> uError $ mkErr m (msName <$> ms) + (m,ms):_ -> uError $ mkError m (msName <$> ms) where gms = group [(msName m , m) | m <- measures] dups = M.filter ((1 <) . length) gms - mkErr m ms = ErrDupMeas (fSrcSpan m) (pprint (val m)) (fSrcSpan <$> ms) + mkError m ms = ErrDupMeas (fSrcSpan m) (pprint (val m)) (fSrcSpan <$> ms) dataConTypes :: Bool -> MSpec (RRType Reft) DataCon -> ([(Var, RRType Reft)], [(LocSymbol, RRType Reft)]) @@ -119,7 +119,7 @@ makeDataConType allowTC ds | any Mb.isNothing (snd <$> binds def) = True | otherwise - = length (binds def) == length (fst $ splitFunTys $ snd $ splitForAllTys wot) + = length (binds def) == length (fst $ splitFunTys $ snd $ splitForAllTyCoVars wot) extend :: Bool @@ -194,7 +194,7 @@ defRefType allowTC tdc (Def f dc mt xs body) splitType :: Type -> ([TyVar],[Type], Type) splitType t = (αs, map irrelevantMult ts, tr) where - (αs, tb) = splitForAllTys t + (αs, tb) = splitForAllTyCoVars t (ts, tr) = splitFunTys tb stitchArgs :: (Monoid t1, PPrint a) diff --git a/src/Language/Haskell/Liquid/Misc.hs b/src/Language/Haskell/Liquid/Misc.hs index c31c8d3442..81bddb27e9 100644 --- a/src/Language/Haskell/Liquid/Misc.hs +++ b/src/Language/Haskell/Liquid/Misc.hs @@ -159,16 +159,6 @@ unzip4 = go [] [] [] [] go a1 a2 a3 a4 [] = (reverse a1, reverse a2, reverse a3, reverse a4) -isIncludeFile :: FilePath -> FilePath -> Bool -isIncludeFile incDir src = -- do - -- incDir <- getIncludeDir - -- return - incDir `L.isPrefixOf` src - -getIncludeDir :: IO FilePath -getIncludeDir = dropFileName <$> getDataFileName ("include" "Prelude.spec") -{-# DEPRECATED getIncludeDir "getIncludeDir is deprecated. The hardcoded include folder will be removed in the future." #-} - getCssPath :: IO FilePath getCssPath = getDataFileName $ "syntax" "liquid.css" @@ -184,8 +174,7 @@ getCoreToLogicPath = do if exists then return atExe else - fmap ( fileName) getIncludeDir - + getDataFileName ("include" fileName) {-@ type ListN a N = {v:[a] | len v = N} @-} {-@ type ListL a L = ListN a (len L) @-} diff --git a/src/Language/Haskell/Liquid/Parse.hs b/src/Language/Haskell/Liquid/Parse.hs index 6f807f6dd6..9faff4945f 100644 --- a/src/Language/Haskell/Liquid/Parse.hs +++ b/src/Language/Haskell/Liquid/Parse.hs @@ -57,7 +57,7 @@ hsSpecificationP :: ModuleName -> [BPspec] -> Either [Error] (ModName, Measure.BareSpec) hsSpecificationP modName specComments specQuotes = - case go ([], []) initPStateWithList $ reverse specComments of + case go ([], []) initPStateWithList specComments of ([], specs) -> Right $ mkSpec (ModName SrcImport modName) (specs ++ specQuotes) (errors, _) -> @@ -198,7 +198,7 @@ toLogicOneP = do reserved "define" (x:xs) <- some locSymbolP reservedOp "=" - e <- exprP + e <- exprP <|> predP return (x, val <$> xs, e) diff --git a/src/Language/Haskell/Liquid/Synthesize.hs b/src/Language/Haskell/Liquid/Synthesize.hs deleted file mode 100644 index 8f03c605cc..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize.hs +++ /dev/null @@ -1,180 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE TupleSections #-} -{-# LANGUAGE FlexibleContexts #-} - -module Language.Haskell.Liquid.Synthesize ( - synthesize - ) where - -import Language.Haskell.Liquid.Types -import Language.Haskell.Liquid.Constraint.Types -import Language.Haskell.Liquid.Constraint.Generate -import qualified Language.Haskell.Liquid.Types.RefType as R -import Language.Haskell.Liquid.Synthesize.Termination -import Language.Haskell.Liquid.Synthesize.Generate -import Language.Haskell.Liquid.Synthesize.GHC hiding (SSEnv) -import Language.Haskell.Liquid.Synthesize.Monad -import Language.Haskell.Liquid.Synthesize.Misc hiding (notrace) -import Language.Haskell.Liquid.Constraint.Fresh (trueTy) -import qualified Language.Fixpoint.Smt.Interface as SMT -import Language.Fixpoint.Types hiding (SEnv, SVar, Error) -import qualified Language.Fixpoint.Types as F -import qualified Language.Fixpoint.Types.Config as F -import Language.Haskell.Liquid.Synthesize.Env -import Liquid.GHC.API as GHC hiding (text, ($+$)) - -import Text.PrettyPrint.HughesPJ (text, ($+$)) -import Control.Monad.State.Lazy -import qualified Data.HashMap.Strict as M -import Data.Maybe - -synthesize :: FilePath -> F.Config -> CGInfo -> IO [Error] -synthesize tgt fcfg cginfo = - mapM go (M.toList $ holesMap cginfo) - where - measures = map (val . msName) ((gsMeasures . gsData . giSpec . ghcI) cginfo) - go (x, HoleInfo _ loc env (cgi,cge)) = do - let topLvlBndr = fromMaybe (error "Top-level binder not found") (cgVar cge) - typeOfTopLvlBnd = fromMaybe (error "Type: Top-level symbol not found") (M.lookup (symbol topLvlBndr) (reGlobal env)) - coreProgram = giCbs $ giSrc $ ghcI cgi - (uniVars, _) = getUniVars coreProgram topLvlBndr - fromREnv' = filterREnv (reLocal env) - fromREnv'' = M.fromList (filter (rmClassVars . toType False . snd) (M.toList fromREnv')) - rmClassVars t = case t of { TyConApp c _ -> not . isClassTyCon $ c; _ -> True } - fromREnv = M.fromList (rmMeasures measures (M.toList fromREnv'')) - isForall t = case t of { ForAllTy{} -> True; _ -> False} - rEnvForalls = M.fromList (filter (isForall . toType False . snd) (M.toList fromREnv)) - fs = map (snd . snd) $ M.toList (symbolToVar coreProgram topLvlBndr rEnvForalls) - - ssenv0 = symbolToVar coreProgram topLvlBndr fromREnv - (senv1, foralls') = initSSEnv typeOfTopLvlBnd cginfo ssenv0 - - ctx <- SMT.makeContext fcfg tgt - state0 <- initState ctx fcfg cgi cge env topLvlBndr (reverse uniVars) M.empty - let foralls = foralls' ++ fs - fills <- synthesize' ctx cgi senv1 typeOfTopLvlBnd topLvlBndr typeOfTopLvlBnd foralls state0 - - return $ ErrHole loc ( - if not (null fills) - then text "\n Hole Fills:" $+$ pprintMany (map (coreToHs typeOfTopLvlBnd topLvlBndr . fromAnf) fills) - else mempty) mempty (symbol x) typeOfTopLvlBnd - - -synthesize' :: SMT.Context -> CGInfo -> SSEnv -> SpecType -> Var -> SpecType -> [Var] -> SState -> IO [CoreExpr] -synthesize' ctx cgi ssenv tx xtop ttop foralls st2 - = evalSM (go tx) ctx ssenv st2 - where - - go :: SpecType -> SM [CoreExpr] - - -- Type Abstraction - go (RAllT a t _x) = GHC.Lam (tyVarVar a) <$$> go t - - go t@(RApp c _ts _ _r) = do - let coreProgram = giCbs $ giSrc $ ghcI cgi - args = drop 1 (argsP coreProgram xtop) - (_, (xs, _, txs, _), _) = bkArrow ttop - addEnv xtop $ decrType xtop ttop args (zip xs txs) - - if R.isNumeric (tyConEmbed cgi) c - then error " [ Numeric in synthesize ] Update liquid fixpoint. " - else do let ts = unifyWith (toType False t) - if null ts then modify (\s -> s { sUGoalTy = Nothing } ) - else modify (\s -> s { sUGoalTy = Just ts } ) - modify (\s -> s {sForalls = (foralls, [])}) - emem0 <- insEMem0 ssenv - modify (\s -> s { sExprMem = emem0 }) - synthesizeBasic t - - go (RAllP _ t) = go t - - go (RRTy _env _ref _obl t) = go t - - go t@RFun{} - = do ys <- mapM freshVar txs - let su = F.mkSubst $ zip xs (EVar . symbol <$> ys) - mapM_ (uncurry addEnv) (zip ys (subst su<$> txs)) - let dt = decrType xtop ttop ys (zip xs txs) - addEnv xtop dt - mapM_ (uncurry addEmem) (zip ys (subst su <$> txs)) - addEmem xtop dt - senv1 <- getSEnv - let goalType' = subst su to - hsGoalTy = toType False goalType' - ts = unifyWith hsGoalTy - if null ts then modify (\s -> s { sUGoalTy = Nothing } ) - else modify (\s -> s { sUGoalTy = Just ts } ) - modify (\s -> s { sForalls = (foralls, []) } ) - emem0 <- insEMem0 senv1 - modify (\s -> s { sExprMem = emem0 }) - mapM_ (`addDecrTerm` []) ys - scruts <- synthesizeScrut ys - modify (\s -> s { scrutinees = scruts }) - GHC.mkLams ys <$$> synthesizeBasic goalType' - where (_, (xs, _,txs, _), to) = bkArrow t - - go t = error (" Unmatched t = " ++ show t) - -synthesizeBasic :: SpecType -> SM [CoreExpr] -synthesizeBasic t = do - let ts = unifyWith (toType False t) -- All the types that are used for instantiation. - if null ts then modify (\s -> s { sUGoalTy = Nothing } ) - else modify (\s -> s { sUGoalTy = Just ts } ) - modify (\s -> s { sGoalTys = [] }) - fixEMem t - es <- genTerms t - if null es then synthesizeMatch t - else return es - -synthesizeMatch :: SpecType -> SM [CoreExpr] -synthesizeMatch t = do - scruts <- scrutinees <$> get - i <- incrCase - case safeIxScruts i scruts of - Nothing -> return [] - Just id' -> if null scruts - then return [] - else withIncrDepth (matchOnExpr t (scruts !! id')) - -synthesizeScrut :: [Var] -> SM [(CoreExpr, Type, TyCon)] -synthesizeScrut vs = do - exprs <- synthesizeScrutinee vs - let exprs' = map (\e -> (exprType e, e)) exprs - isDataCon v = case varType v of { TyConApp c _ -> not . isClassTyCon $ c; _ -> False } - vs0 = filter isDataCon vs - es0 = map GHC.Var vs0 - es1 = map (\e -> (exprType e, e)) es0 - es2 = [(e, t, c) | (t@(TyConApp c _), e) <- es1] - return (es2 ++ [(e, t, c) | (t@(TyConApp c _), e) <- exprs']) - -matchOnExpr :: SpecType -> (CoreExpr, Type, TyCon) -> SM [CoreExpr] -matchOnExpr t (GHC.Var v, tx, c) - = matchOn t (v, tx, c) -matchOnExpr t (e, tx, c) - = do freshV <- freshVarType tx - freshSpecTy <- liftCG $ trueTy False tx - -- use consE - addEnv freshV freshSpecTy - es <- matchOn t (freshV, tx, c) - return $ GHC.Let (GHC.NonRec freshV e) <$> es - -matchOn :: SpecType -> (Var, Type, TyCon) -> SM [CoreExpr] -matchOn t (v, tx, c) = - (GHC.Case (GHC.Var v) v tx <$$> sequence) <$> mapM (makeAlt t (v, tx)) (tyConDataCons c) - - -makeAlt :: SpecType -> (Var, Type) -> DataCon -> SM [GHC.CoreAlt] -makeAlt t (x, TyConApp _ kts) c = locally $ do - ts <- liftCG $ mapM (trueTy False) τs - xs <- mapM freshVar ts - newScruts <- synthesizeScrut xs - modify (\s -> s { scrutinees = scrutinees s ++ newScruts } ) - addsEnv $ zip xs ts - addsEmem $ zip xs ts - addDecrTerm x xs - liftCG0 (\γ -> caseEnv γ x mempty (GHC.DataAlt c) xs Nothing) - es <- synthesizeBasic t - return $ (GHC.DataAlt c, xs, ) <$> es - where - (_, _, τs) = dataConInstSig c kts -makeAlt _ _ _ = error "makeAlt.bad argument " diff --git a/src/Language/Haskell/Liquid/Synthesize/Check.hs b/src/Language/Haskell/Liquid/Synthesize/Check.hs deleted file mode 100644 index 1bbf75953b..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Check.hs +++ /dev/null @@ -1,99 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE BangPatterns #-} - -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -module Language.Haskell.Liquid.Synthesize.Check (check, hasType, isWellTyped, checkError) where - - -import Language.Fixpoint.Types.Constraints -import qualified Language.Fixpoint.Types.Config - as F -import qualified Language.Fixpoint.Types as F -import Language.Fixpoint.Solver -import Language.Haskell.Liquid.Types.Types -import Language.Haskell.Liquid.Types.Specs -import Language.Haskell.Liquid.Constraint.Env -import Language.Haskell.Liquid.Constraint.Generate -import Language.Haskell.Liquid.Constraint.Types -import Language.Haskell.Liquid.Constraint.Fresh - ( trueTy ) -import Language.Haskell.Liquid.Constraint.ToFixpoint -import Language.Haskell.Liquid.Synthesize.Monad -import Language.Haskell.Liquid.Synthesize.GHC -import Liquid.GHC.API as Ghc -import Language.Haskell.Liquid.Misc ( mapThd3 ) -import Control.Monad.State.Lazy -import System.Console.CmdArgs.Verbosity -import Liquid.GHC.TypeRep -import Language.Haskell.Liquid.Types - -hasType :: SpecType -> CoreExpr -> SM Bool -hasType t !e' = notrace (" [ Check ] " ++ show e') $ do - x <- freshVar t - st <- get - let tpOfE = exprType e' - ht = toType False t - if tpOfE == ht - then liftIO $ quietly $ check (sCGI st) (sCGEnv st) (sFCfg st) x e (Just t) - else error $ " [ hasType ] Expression = " ++ show e' ++ " with type " ++ showTy tpOfE ++ " , specType = " ++ show t - where e = tx e' - --- Returns true if the expression is well-typed. -isWellTyped :: CoreExpr -> SM Bool -isWellTyped e = do - t <- liftCG $ trueTy False $ exprType e - hasType t e - - -tx :: CoreExpr -> CoreExpr -tx (Case e b t alts) = Case e b t (mapThd3 tx <$> alts) -tx e@(Let _ _) = let (bs,e') = unbind e in foldr Let e' bs -tx e = e - -unbind :: CoreExpr -> ([CoreBind], CoreExpr) -unbind (Let (NonRec x ex) e) = let (bs,e') = unbind ex in (bs ++ [NonRec x e'],e) -unbind e = ([], e) - - -check :: CGInfo -> CGEnv -> F.Config -> Var -> CoreExpr -> Maybe SpecType -> IO Bool -check cgi γ cfg x e t = do - finfo <- cgInfoFInfo info' cs - isSafe <$> solve cfg{F.srcFile = "SCheck" <> F.srcFile cfg} finfo - where - cs = generateConstraintsWithEnv info' (cgi{hsCs = []}) (γ{grtys = insertREnv' (F.symbol x) t (grtys γ)}) - info' = info {giSrc = giSrc', giSpec = giSpec'} - giSrc' = (giSrc info) {giCbs = [Rec [(x, e)]]} - giSpec' = giSpecOld{gsSig = gsSig'} - giSpecOld = giSpec info - gsSigOld = gsSig giSpecOld - gsSig' = gsSigOld {gsTySigs = addTySig x t (gsTySigs gsSigOld)} - info = ghcI cgi - - insertREnv' _ Nothing g = g - insertREnv' x (Just t) g = insertREnv x t g - - addTySig _ Nothing ts = ts - addTySig x (Just t) ts = (x,dummyLoc t):ts - -checkError :: SpecType -> SM (Maybe CoreExpr) -checkError t = do - errVar <- varError - let errorExpr = App (App (Var errVar) (Type (toType False t))) errorInt - globalFlags = unsafeGlobalDynFlags - platform = targetPlatform globalFlags - errorInt = mkIntExprInt platform 42 - b <- hasType t errorExpr - if b - then return $ Just errorExpr - else return Nothing - -quietly :: IO a -> IO a -quietly act = do - vb <- getVerbosity - setVerbosity Quiet - r <- act - setVerbosity vb - return r - - diff --git a/src/Language/Haskell/Liquid/Synthesize/Env.hs b/src/Language/Haskell/Liquid/Synthesize/Env.hs deleted file mode 100644 index c51ed7c04c..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Env.hs +++ /dev/null @@ -1,47 +0,0 @@ -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -module Language.Haskell.Liquid.Synthesize.Env where - -import Language.Fixpoint.Types -import Liquid.GHC.API as GHC -import Language.Haskell.Liquid.Constraint.Types -import Language.Haskell.Liquid.Types -import Language.Haskell.Liquid.Synthesize.Monad -import qualified Data.HashMap.Strict as M -import qualified Data.HashSet as S -import Data.List - -initSSEnv :: SpecType -> CGInfo -> SSEnv -> (SSEnv, [Var]) -initSSEnv rt info senv = (M.union senv (M.fromList foralls), vs) - where foralls = filter iNeedIt (mkElem <$> prims) - vs = map (snd . snd) foralls - dataCons = typeToCons rt - mkElem (v, lt) = (symbol v, (val lt, v)) - prims = gsCtors $ gsData $ giSpec $ ghcI info - iNeedIt (_, (_, v)) = v `elem` (dataConWorkId <$> dataCons) - --- | For algebraic datatypes: Find (in the refinement type) --- all the datatypes that are used and --- get their constructors. -tpToCons :: SpecType -> [DataCon] -tpToCons (RAllT _a t _x) - = tpToCons t -tpToCons (RApp c args _ _r) - = tyConDataCons (rtc_tc c) ++ concatMap tpToCons args -tpToCons (RFun _sym _ rt0 rt1 _reft) - = tpToCons rt0 ++ tpToCons rt1 -tpToCons RVar{} - = [] -tpToCons (RAllP _ t) - = tpToCons t -tpToCons (RRTy _ _ _ t) - = tpToCons t -tpToCons _ - = [] - -typeToCons :: SpecType -> [DataCon] -typeToCons rt = S.toList $ S.fromList (tpToCons rt) - -rmMeasures :: [Symbol] -> [(Symbol, SpecType)] -> [(Symbol, SpecType)] -rmMeasures meas = filter (\(s,_) -> case find (== s) meas of Nothing -> True - Just _ -> False) diff --git a/src/Language/Haskell/Liquid/Synthesize/GHC.hs b/src/Language/Haskell/Liquid/Synthesize/GHC.hs index bebb934519..08e3384e0c 100644 --- a/src/Language/Haskell/Liquid/Synthesize/GHC.hs +++ b/src/Language/Haskell/Liquid/Synthesize/GHC.hs @@ -10,7 +10,6 @@ module Language.Haskell.Liquid.Synthesize.GHC where import qualified Language.Fixpoint.Types as F import Language.Haskell.Liquid.Types - import Data.Default import Data.Maybe ( fromMaybe ) import Liquid.GHC.TypeRep @@ -89,13 +88,13 @@ fromAnf' (Lam b e) bnds in (Lam b e', bnds') fromAnf' (Let (NonRec rb lb) e) bnds - | elem '#' (show rb) = let (lb', bnds') = fromAnf' lb bnds - in fromAnf' e ((rb, lb') : bnds') - - | otherwise = (Let (NonRec rb lb') e', binds'') + | "lq_anf" == take 6 (show rb) + = fromAnf' e ((rb, lb') : bnds') + | otherwise + = (Let (NonRec rb lb') e', bnds'') where - (lb', bnds') = fromAnf' lb bnds - (e', binds'') = fromAnf' e ((rb, lb') : bnds') + (lb', bnds') = fromAnf' lb bnds + (e', bnds'') = fromAnf' e bnds' fromAnf' (Let (Rec {}) _) _ = error " By construction, no recursive bindings in let expression. " @@ -103,10 +102,20 @@ fromAnf' (Let (Rec {}) _) _ = fromAnf' (Var var) bnds = (fromMaybe (Var var) (lookup var bnds), bnds) +fromAnf' (Case scr bnd _ [GHC.Alt (GHC.DataAlt c) [x] e]) bnds + | c == GHC.intDataCon + = fromAnf' e $ (x, scr'):bnds'' + where + bnds'' = (bnd, scr'):bnds' + (scr', bnds') = fromAnf' scr bnds + fromAnf' (Case scr bnd tp alts) bnds - = (Case scr bnd tp ( - map (\(altc, xs, e) -> - (altc, xs, fst $ fromAnf' e bnds)) alts), bnds) + = (Case scr' bnd tp + (map (\(GHC.Alt altc xs e) -> + GHC.Alt altc xs (fst $ fromAnf' e bnds'')) alts), bnds'') + where + bnds'' = (bnd, scr'):bnds' + (scr', bnds') = fromAnf' scr bnds fromAnf' (App e1 e2) bnds = let (e1', bnds') = fromAnf' e1 bnds @@ -115,8 +124,6 @@ fromAnf' (App e1 e2) bnds fromAnf' t@Type{} bnds = (t, bnds) -fromAnf' (Lit (GHC.LitString _)) bnds = (GHC.unitExpr, bnds) - fromAnf' l@Lit{} bnds = (l, bnds) fromAnf' (Tick s e) bnds = (Tick s e', bnds') @@ -128,10 +135,14 @@ fromAnf' e _ = error $ "fromAnf: unsupported core expression " -- | Function used for pretty printing core as Haskell source. -- Input does not contain let bindings. -coreToHs :: SpecType -> Var -> CoreExpr -> String -coreToHs _ v e = pprintSymbols (handleVar v - ++ " " - ++ pprintFormals caseIndent e) +coreToHs :: RenVars -> SpecType -> Var -> CoreExpr -> String +coreToHs rvs _ v e = pprintSymbols (handleVar (getOccString v:rvs) v + ++ " " + ++ pprintFormals + (getOccString v:rvs) + caseIndent e) + +type RenVars = [String] caseIndent :: Int caseIndent = 2 @@ -158,18 +169,18 @@ pprintSym symbols s prefix = takeWhile (== ' ') s suffix = dropWhile (== ' ') s -pprintFormals :: Int -> CoreExpr -> String -pprintFormals i e = handleLam "= " i e +pprintFormals :: RenVars -> Int -> CoreExpr -> String +pprintFormals rvs i e = handleLam rvs "= " i e -handleLam :: String -> Int -> CoreExpr -> String -handleLam char i (Lam v e) - | isTyVar v = " {- tyVar -}" ++ handleLam char i e - | isTcTyVar v = " {- isTcTyVar -}" ++ handleLam char i e - | isTyCoVar v = " {- isTyCoVar -}" ++ handleLam char i e - | isCoVar v = " {- isCoVar -}" ++ handleLam char i e - | isId v = handleVar v ++ " " ++ handleLam char i e - | otherwise = handleVar v ++ " " ++ handleLam char i e -handleLam char i e = char ++ pprintBody i e +handleLam :: RenVars -> String -> Int -> CoreExpr -> String +handleLam rvs char i (Lam v e) + | isTyVar v = " {- tyVar -}" ++ handleLam rvs char i e + | isTcTyVar v = " {- isTcTyVar -}" ++ handleLam rvs char i e + | isTyCoVar v = " {- isTyCoVar -}" ++ handleLam rvs char i e + | isCoVar v = " {- isCoVar -}" ++ handleLam rvs char i e + | isId v = handleVar rvs v ++ " " ++ handleLam rvs char i e + | otherwise = handleVar rvs v ++ " " ++ handleLam rvs char i e +handleLam rvs char i e = char ++ pprintBody' rvs i e {- If a specific function is built-in into haskell it will still @@ -196,28 +207,36 @@ getExternalName n = mod ++ outName {- Handle the multiple types of variables one might encounter in Haskell. -} -handleVar :: Var -> String -handleVar v +handleVar :: RenVars -> Var -> String +handleVar vars v | isTyConName name = "{- TyConName -}" | isTyVarName name = "{- TyVar -}" - | isSystemName name = getSysName name --- ++ "{- SysName -}" + | isSystemName name = getSysName vars v + -- ++ "{- SysName -}" | isWiredInName name = getLocalName name --- ++ "{- WiredInName -}" - | isInternalName name = getOccString name --- ++ "{- Internal -}" + -- ++ "{- WiredInName -}" + | isInternalName name = getSysName vars v + -- ++ "{- Internal -}" | isExternalName name = getExternalName name --- ++ "{- external name -}" + -- ++ "{- external name -}" | otherwise = "{- Not properly handled -}" - ++ show name + ++ show (getOccString name) where name :: Name name = varName v +occStr :: Var -> String +occStr = getOccString . varName -getSysName :: Name -> String -getSysName n = filter (not . (`elem` "$#")) occ - where occ = getOccString n +getSysName :: RenVars -> Var -> String +getSysName vars v + | occ `elem` vars = occ + -- | "Lemma" == drop (length occ - 5) occ = occ + -- ++ "{- in renvars -}" + | otherwise = filter (`notElem` "$#") $ show v + -- ++ "{- not in renvars -}" + where + occ = getOccString (varName v) {- Should not be done here, but function used to check if is an undesirable variable or not (I#) -} @@ -233,64 +252,77 @@ checkUnit (Var v) | otherwise = False checkUnit _ = False ---------------------------------------------------------------------- -pprintBody' :: CoreExpr -> String -pprintBody' = pprintBody 0 +pprintBody :: RenVars -> CoreExpr -> String +pprintBody rvs = pprintBody' rvs 0 -pprintBody :: Int -> CoreExpr -> String -pprintBody i e@Lam{} = "(\\" ++ handleLam " -> " i e ++ ")" +pprintBody' :: RenVars -> Int -> CoreExpr -> String +pprintBody' rvs i e@Lam{} = "(\\" ++ handleLam rvs " -> " i e ++ ")" -pprintBody _ var@(Var v) +pprintBody' rvs _ var@(Var v) | undesirableVar var = "" - | otherwise = handleVar v + | otherwise = handleVar rvs v -pprintBody i (App e Type{}) = pprintBody i e +pprintBody' rvs i (App e Type{}) = pprintBody' rvs i e -pprintBody i (App e1 e2) - | undesirableVar e1 = pprintBody i e2 - | undesirableVar e2 = pprintBody i e1 - | checkUnit e2 = pprintBody i e1 - ++ " " - ++ pprintBody i e2 - | otherwise = "(" ++ left ++ ")\n" - ++ indent (i + 1) - ++ "(" ++ right ++ ")" - where - left = pprintBody i e1 - right = pprintBody (i+1) e2 - -pprintBody _ l@(Lit literal) = +pprintBody' rvs i (App e1 e2) + | undesirableVar e1 = pprintBody' rvs i e2 + | undesirableVar e2 = pprintBody' rvs i e1 + | isOperator e1 = paren e2 False right ++ " " ++ paren e1 False left + | otherwise = paren e1 True left ++ " " ++ paren e2 False right + where + left = pprintBody' rvs i e1 + right = pprintBody' rvs (i+1) e2 + +pprintBody' _ _ l@(Lit literal) = case isLitValue_maybe literal of Just i -> show i Nothing -> show l -pprintBody i (Case e _ _ alts) - = "case " ++ pprintBody i e ++ " of" - ++ concatMap (pprintAlts (i + caseIndent)) alts +pprintBody' rvs i (Case e _ _ alts) + = "case " ++ pprintBody' rvs i e ++ " of" + ++ concatMap (pprintAlts rvs (i + caseIndent)) alts -pprintBody _ Type{} = "{- Type -}" +pprintBody' _ _ Type{} = "{- Type -}" -pprintBody i (Let (NonRec x e1) e2) = +pprintBody' rvs i (Let (NonRec x e1) e2) = letExp ++ eqlExp ++ - indent i ++ pprintBody (i+1) e2 + indent i ++ pprintBody' rvs (i+1) e2 where - letExp = "let " ++ handleVar x ++ " = " - eqlExp = pprintBody firstIdent e1 ++ " in\n" + letExp = "let " ++ handleVar rvs x ++ " = " + eqlExp = pprintBody' rvs firstIdent e1 ++ " in\n" firstIdent = i + caseIndent*2 + length letExp -pprintBody _ (Let Rec{} _) = "{- let rec -}" +pprintBody' _ _ (Let Rec{} _) = "{- let rec -}" -pprintBody i (Tick (SourceNote _ s) e) +pprintBody' rvs i (Tick (SourceNote _ s) e) | expr == "()" = "{- " ++ s ++ " -} " ++ expr | otherwise = "{- " ++ s ++ " -}" ++ "\n" ++ indent i ++ expr where - expr = pprintBody i e + expr = pprintBody' rvs i e + +pprintBody' rvs i (Tick _ e) = pprintBody' rvs i e + +pprintBody' _ _ e = error (" Not yet implemented for e = " ++ show e) + +noParenVars :: [String] +noParenVars = ["()"] -pprintBody i (Tick _ e) = pprintBody i e +letters :: String +letters = ['a'..'z'] ++ ['A'..'Z'] -pprintBody _ e = error (" Not yet implemented for e = " ++ show e) +isOperator :: CoreExpr -> Bool +isOperator (Var v) | head (occStr v) `notElem` letters = True +isOperator _ = False + +paren :: CoreExpr -> Bool -> String -> String +paren (Var _) _ res = res +paren (App _ _) True res = res +paren (App (Var i) _) _ res | occStr i == "I#" = res +paren Lit{} _ res = res +paren _ _ res = "(" ++ res ++ ")" {- data Alt Var = Alt AltCon [Var] (Expr Var) @@ -299,19 +331,37 @@ data AltCon = DataAlt DataCon | LitAlt Literal | DEFAULT -} -pprintAlts :: Int -> Alt Var -> String -pprintAlts i (DataAlt dataCon, vs, e) +pprintAlts :: RenVars -> Int -> Alt Var -> String +pprintAlts rvs i (GHC.Alt (DataAlt dataCon) vs e) = "\n" ++ indent i ++ elCase - ++ pprintBody (i + newIndent) e + ++ pprintBody' rvs (i + newIndent) e where elCase = getOccString (getName dataCon) - ++ concatMap (\v -> " " ++ handleVar v) vs + ++ concatMap (\v -> " " ++ handleVar rvs v) vs ++ " -> " newIndent = length elCase -pprintAlts _ _ = - error " Pretty printing for pattern match on datatypes. " +pprintAlts rvs i (GHC.Alt (LitAlt literal) vs e) + = "\n" ++ indent i + ++ elCase + ++ pprintBody' rvs (i + newIndent) e + where + elCase = showSDocUnsafe (ppr literal) + ++ concatMap (\v -> " " ++ handleVar rvs v) vs + ++ " -> " + newIndent = length elCase + +pprintAlts rvs i (GHC.Alt DEFAULT vs e) + = "\n" ++ indent i + ++ elCase + ++ pprintBody' rvs (i + newIndent) e + where + elCase = "_" + ++ concatMap (\v -> " " ++ handleVar rvs v) vs + ++ " -> " + newIndent = length elCase + @@ -412,14 +462,14 @@ varsCB (GHC.Rec _) _ = notrace " [ symbolToVarCB ] Rec " [] varsE :: GHC.CoreExpr -> [Var] varsE (GHC.Lam a e) = a : varsE e varsE (GHC.Let (GHC.NonRec b _) e) = b : varsE e -varsE (GHC.Case _ b _ alts) = foldr (\(_, vars, e) res -> vars ++ varsE e ++ res) [b] alts +varsE (GHC.Case _ b _ alts) = foldr (\(GHC.Alt _ vars e) res -> vars ++ varsE e ++ res) [b] alts varsE (GHC.Tick _ e) = varsE e varsE _ = [] caseVarsE :: GHC.CoreExpr -> [Var] caseVarsE (GHC.Lam _ e) = caseVarsE e caseVarsE (GHC.Let (GHC.NonRec _ _) e) = caseVarsE e -caseVarsE (GHC.Case _ b _ alts) = foldr (\(_, _, e) res -> caseVarsE e ++ res) [b] alts +caseVarsE (GHC.Case _ b _ alts) = foldr (\(GHC.Alt _ _ e) res -> caseVarsE e ++ res) [b] alts caseVarsE (GHC.Tick _ e) = caseVarsE e caseVarsE _ = [] diff --git a/src/Language/Haskell/Liquid/Synthesize/Generate.hs b/src/Language/Haskell/Liquid/Synthesize/Generate.hs deleted file mode 100644 index d62ba7fef5..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Generate.hs +++ /dev/null @@ -1,252 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE TupleSections #-} -{-# LANGUAGE BangPatterns #-} - -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -module Language.Haskell.Liquid.Synthesize.Generate where - -import Liquid.GHC.API as GHC hiding (Depth) -import Language.Haskell.Liquid.Types -import Language.Haskell.Liquid.Synthesize.GHC - hiding ( SSEnv ) -import Language.Haskell.Liquid.Synthesize.Monad -import Language.Haskell.Liquid.Synthesize.Misc - hiding ( notrace ) -import Language.Haskell.Liquid.Synthesize.Check -import Data.Maybe -import Control.Monad.State.Lazy -import Language.Haskell.Liquid.Constraint.Fresh - ( trueTy ) -import Data.List -import Data.Tuple.Extra -import Language.Fixpoint.Types.PrettyPrint (tracepp) - --- Generate terms that have type t: This changes the @ExprMemory@ in @SM@ state. --- Return expressions type checked against type @specTy@. -genTerms :: SpecType -> SM [CoreExpr] -genTerms = genTerms' ResultMode - - -data SearchMode - = ArgsMode -- ^ searching for arguments of functions that can eventually - -- produce the top level hole fill - | ResultMode -- ^ searching for the hole fill - deriving (Eq, Show) - -genTerms' :: SearchMode -> SpecType -> SM [CoreExpr] -genTerms' i specTy = - do goalTys <- sGoalTys <$> get - case find (== toType False specTy) goalTys of - Nothing -> modify (\s -> s { sGoalTys = toType False specTy : sGoalTys s }) - Just _ -> return () - fixEMem specTy - fnTys <- functionCands (toType False specTy) - es <- withTypeEs specTy - es0 <- structuralCheck es - - err <- checkError specTy - case err of - Nothing -> - filterElseM (hasType specTy) es0 $ - withDepthFill i specTy 0 fnTys - Just e -> return [e] - -genArgs :: SpecType -> SM [CoreExpr] -genArgs t = - do goalTys <- sGoalTys <$> get - case find (== toType False t) goalTys of - Nothing -> do modify (\s -> s { sGoalTys = toType False t : sGoalTys s }) - fixEMem t - fnTys <- functionCands (toType False t) - es <- withDepthFillArgs t 0 fnTys - if null es - then return [] - else do -- modify (\s -> s {sExprId = sExprId s + 1}) - return es - Just _ -> return [] - -withDepthFillArgs :: SpecType -> Int -> [(Type, CoreExpr, Int)] -> SM [CoreExpr] -withDepthFillArgs t depth cs = do - thisEm <- sExprMem <$> get - es <- argsFill thisEm cs [] - argsDepth <- localMaxArgsDepth - - filterElseM (hasType t) es $ - if depth < argsDepth - then trace (" [ withDepthFillArgs ] argsDepth = " ++ show argsDepth) $ withDepthFillArgs t (depth + 1) cs - else return [] - -argsFill :: ExprMemory -> [(Type, CoreExpr, Int)] -> [CoreExpr] -> SM [CoreExpr] -argsFill _ [] es0 = return es0 -argsFill em0 (c:cs) es0 = - case subgoals (fst3 c) of - Nothing -> return [] - Just (resTy, subGs) -> - do let argCands = map (withSubgoal em0) subGs - toGen = foldr (\x b -> (not . null) x && b) True (tracepp (" [ argsFill ] for c = " ++ show (snd3 c) ++ " argCands ") argCands) - es <- do curExprId <- sExprId <$> get - if toGen then - prune curExprId c argCands - else return [] - curExprId <- sExprId <$> get - let nextEm = map (resTy, , curExprId + 1) es - modify (\s -> s {sExprMem = nextEm ++ sExprMem s }) - argsFill em0 cs (es ++ es0) - -withDepthFill :: SearchMode -> SpecType -> Int -> [(Type, GHC.CoreExpr, Int)] -> SM [CoreExpr] -withDepthFill i t depth tmp = do - exprs <- fill i depth tmp [] - appDepth <- localMaxAppDepth - - filterElseM (hasType t) exprs $ - if depth < appDepth - then do modify (\s -> s { sExprId = sExprId s + 1 }) - withDepthFill i t (depth + 1) tmp - else return [] - -fill :: SearchMode -> Int -> [(Type, GHC.CoreExpr, Int)] -> [CoreExpr] -> SM [CoreExpr] -fill _ _ [] accExprs - = return accExprs -fill i depth (c : cs) accExprs - = case subgoals (fst3 c) of - Nothing -> return [] -- Not a function type - Just (resTy, subGs) -> - do specSubGs <- liftCG $ mapM (trueTy False) (filter (not . isFunction) subGs) - mapM_ genArgs specSubGs - em <- sExprMem <$> get - let argCands = map (withSubgoal em) subGs - toGen = foldr (\x b -> (not . null) x && b) True argCands - newExprs <- do curExprId <- sExprId <$> get - if toGen - then prune curExprId c (tracepp (" [ fill " ++ show curExprId ++ " ] For c = " ++ show (snd3 c) ++ " argCands ") argCands) - else return [] - curExprId <- sExprId <$> get - let nextEm = map (resTy, , curExprId + 1) newExprs - modify (\s -> s {sExprMem = nextEm ++ sExprMem s }) - let accExprs' = newExprs ++ accExprs - fill i depth cs accExprs' - -------------------------------------------------------------------------------------------- --- | Pruning terms for function application | -- -------------------------------------------------------------------------------------------- -type Depth = Int - -feasible :: Depth -> (CoreExpr, Int) -> Bool -feasible d c = snd c >= d - -feasibles :: Depth -> Int -> [(CoreExpr, Int)] -> [Int] -feasibles _ _ [] - = [] -feasibles d i (c:cs) - = if feasible d c - then i : feasibles d (i+1) cs - else feasibles d (i+1) cs - -isFeasible :: Depth -> [[(CoreExpr, Int)]] -> [[Int]] -isFeasible d = map (feasibles d 0) - -findFeasibles :: Depth -> [[(CoreExpr, Int)]] -> ([[Int]], [Int]) -findFeasibles d cs = (fs, ixs) - where fs = isFeasible d cs - ixs = [i | (i, f) <- zip [0..] fs, not (null f)] - -toExpr :: [Int] -> -- Produced from @isFeasible@. - -- Assumed in increasing order. - [(GHC.CoreExpr, Int)] -> -- The candidate expressions. - ([(GHC.CoreExpr, Int)], -- Expressions from 2nd argument. - [(GHC.CoreExpr, Int)]) -- The rest of the expressions -toExpr ixs args = ( [ args !! i | (ix, i) <- is, ix == i ], - [ args !! i | (ix, i) <- is, ix /= i ]) - where is = zip [0..] ixs - -fixCands :: Int -> [Int] -> [[(CoreExpr, Int)]] -> ([[(CoreExpr, Int)]], [[(CoreExpr, Int)]]) -fixCands i ixs args - = let cs = args !! i - (cur, next) = toExpr ixs cs - (args0, args1) = (replace (i+1) cur args, replace (i+1) next args) - in (args0, args1) - --- | The first argument should be an 1-based index. -replace :: Int -> a -> [a] -> [a] -replace i x l - = left ++ [x] ++ right - where left = take (i-1) l - right = drop i l - -repeatFix :: [Int] -> [[Int]] -> (Type, CoreExpr, Int) -> [[(CoreExpr, Int)]] -> [CoreExpr] -> SM [CoreExpr] -repeatFix [ ] _ _ _ es - = return es -repeatFix (i:is) ixs toFill args es - = do let (args0, args1) = fixCands i (ixs !! i) args - es0 <- fillOne toFill args0 - es1 <- structuralCheck es0 - es2 <- (++ es) <$> filterM isWellTyped es1 - repeatFix is ixs toFill args1 es2 - -prune :: Depth -> (Type, CoreExpr, Int) -> [[(CoreExpr, Int)]] -> SM [CoreExpr] -prune d toFill args - = do let (ixs, is) = findFeasibles d args - repeatFix is ixs toFill args [] - - ----------------------------------------------------------------------------- --- | Term generation: Perform type and term application for functions. | -- ----------------------------------------------------------------------------- - -fillOne :: (Type, GHC.CoreExpr, Int) -> [[(CoreExpr, Int)]] -> SM [CoreExpr] -fillOne _ [] - = return [] -fillOne (t, e, _) cs - = applyTerms [e] cs ((snd . fromJust . subgoals) t) - -applyTerm :: [GHC.CoreExpr] -> [(CoreExpr, Int)] -> Type -> SM [CoreExpr] -applyTerm es args t = do - es1 <- mapM (\x -> applyArg es x t) args - return (concat es1) - -applyArg :: [GHC.CoreExpr] -> (CoreExpr, Int) -> Type -> SM [CoreExpr] -applyArg es (arg, _) t - = do !idx <- incrSM - return [ case arg of GHC.Var _ -> GHC.App e arg - _ -> let letv = mkVar (Just ("x" ++ show idx)) idx t - in GHC.Let (GHC.NonRec letv arg) (GHC.App e (GHC.Var letv)) - | e <- es - ] - -applyTerms :: [GHC.CoreExpr] -> [[(CoreExpr, Int)]] -> [Type] -> SM [CoreExpr] -applyTerms es [] [] - = return es -applyTerms es0 (c:cs) (t:ts) - = do es1 <- applyTerm es0 c t - applyTerms es1 cs ts -applyTerms _es _cs _ts - = error "[ applyTerms ] Wildcard. " - --------------------------------------------------------------------------------------- -prodScrutinees :: [(Type, CoreExpr, Int)] -> [[[(CoreExpr, Int)]]] -> SM [CoreExpr] -prodScrutinees [] [] = return [] -prodScrutinees (c:cs) (a:as) = do - es <- fillOne c a - (++ es) <$> prodScrutinees cs as -prodScrutinees _ _ = error " prodScrutinees " - -synthesizeScrutinee :: [Var] -> SM [CoreExpr] -synthesizeScrutinee vars = do - s <- get - let foralls = (fst . sForalls) s - insVs = sUniVars s - fix = sFix s - -- Assign higher priority to function candidates that return tuples - fnCs0 = filter returnsTuple foralls - fnCs = if returnsTuple fix then fix : fnCs0 else fnCs0 - - fnEs = map GHC.Var fnCs - fnCs' = map (\e -> instantiate e (Just insVs)) fnEs - sGs = map ((snd . fromJust) . subgoals . exprType) fnCs' - argCands = map (map (withSubgoal vs)) sGs - fnCs'' = map (\e -> (exprType e, e, 0)) fnCs' - - vs' = filter ((not . isFunction) . varType) vars - vs = map (\v -> (varType v, GHC.Var v, 0)) vs' - prodScrutinees fnCs'' argCands diff --git a/src/Language/Haskell/Liquid/Synthesize/Misc.hs b/src/Language/Haskell/Liquid/Synthesize/Misc.hs deleted file mode 100644 index d2475d41cc..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Misc.hs +++ /dev/null @@ -1,94 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} - -{-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -module Language.Haskell.Liquid.Synthesize.Misc where - -import qualified Language.Fixpoint.Types as F -import Control.Monad.State.Lazy -import Text.PrettyPrint.HughesPJ (text, Doc, vcat, ($+$)) -import Language.Haskell.Liquid.Synthesize.GHC -import Liquid.GHC.TypeRep -import Liquid.GHC.API hiding (text, ($+$), vcat) -import Language.Fixpoint.Types - - -isFunction :: Type -> Bool -isFunction FunTy{} = True -isFunction ForAllTy{} = True -isFunction _ = False - -(<$$>) :: (Functor m, Functor n) => (a -> b) -> m (n a) -> m (n b) -(<$$>) = fmap . fmap - -filterElseM :: Monad m => (a -> m Bool) -> [a] -> m [a] -> m [a] -filterElseM f as ms = do - rs <- filterM f as - if null rs then - ms - else - return rs - --- Replaces | old w | new | symbol name in expr. -substInFExpr :: F.Symbol -> F.Symbol -> F.Expr -> F.Expr -substInFExpr pn nn e = F.subst1 e (pn, F.EVar nn) - - -findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a) -findM _ [] = return Nothing -findM p (x:xs) = do b <- p x ; if b then return (Just x) else findM p xs - - -composeM :: Monad m => (a -> m b) -> (b -> c) -> a -> m c -composeM f g x = do - mx <- f x - return (g mx) - ----------------------------------------------------------------------------- -----------------------------Printing---------------------------------------- ----------------------------------------------------------------------------- -solDelim :: String -solDelim = "*********************************************" - --- pprintMany :: (F.PPrint a) => [a] -> Doc --- pprintMany xs = vcat [ F.pprint x $+$ text solDelim | x <- xs ] - -pprintMany :: [String] -> Doc -pprintMany xs = vcat [ text x $+$ text solDelim | x <- xs ] - -showGoals :: [[String]] -> String -showGoals [] = "" -showGoals (goal : goals) = - show goal ++ - "\n" ++ - replicate 12 ' ' ++ - showGoals goals - -showEmem :: (Show a1, Show a2) => [(Type, a1, a2)] -> String -showEmem emem = show $ showEmem' emem - -showEmem' :: (Show a1, Show a2) => [(Type, a1, a2)] -> [(String, String, String)] -showEmem' emem = map (\(t, e, i) -> (show e, showTy t, show i)) emem - -exprmemToExpr :: [(a2, CoreExpr, Int)] -> String -exprmemToExpr em = show $ map (\(_, e, i) -> show (fromAnf e, i) ++ " * ") em - -showCand :: (a, (Type, b)) -> (String, b) -showCand (_, (t, v)) = (showTy t, v) - -showCands :: [(a, (Type, b))] -> [(String, b)] -showCands = map showCand - -notrace :: String -> a -> a -notrace _ a = a - -instance PPrint AltCon - -showCoreAlt :: CoreAlt -> String -showCoreAlt (DataAlt altCon, vars, expr) = - " For " ++ show altCon ++ " vars " ++ show vars ++ " expr " ++ show expr -showCoreAlt _ = " No! " - -showCoreAlts :: [CoreAlt] -> String -showCoreAlts alts = concatMap showCoreAlt alts diff --git a/src/Language/Haskell/Liquid/Synthesize/Monad.hs b/src/Language/Haskell/Liquid/Synthesize/Monad.hs deleted file mode 100644 index dedd46d0dd..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Monad.hs +++ /dev/null @@ -1,423 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FlexibleContexts #-} - -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -module Language.Haskell.Liquid.Synthesize.Monad where - - -import Liquid.GHC.API as GHC -import Language.Haskell.Liquid.Bare.Resolve - as B -import Language.Haskell.Liquid.Types -import Language.Haskell.Liquid.Constraint.Types -import Language.Haskell.Liquid.Constraint.Env -import Language.Haskell.Liquid.Synthesize.GHC - hiding ( SSEnv ) -import Language.Haskell.Liquid.Synthesize.Misc - hiding ( notrace ) -import qualified Language.Fixpoint.Smt.Interface - as SMT -import Language.Fixpoint.Types hiding ( SEnv - , SVar - , Error - ) -import qualified Language.Fixpoint.Types as F -import qualified Language.Fixpoint.Types.Config - as F -import Control.Monad.State.Lazy -import qualified Data.HashMap.Strict as M -import Data.Maybe -import Data.List -import Data.Tuple.Extra - -localMaxMatchDepth :: SM Int -localMaxMatchDepth = maxMatchDepth . getConfig . sCGEnv <$> get - -------------------------------------------------------------------------------- --- | Synthesis Monad ---------------------------------------------------------- -------------------------------------------------------------------------------- - --- The state keeps a unique index for generation of fresh variables --- and the environment of variables to types that is expanded on lambda terms -type SSEnv = M.HashMap Symbol (SpecType, Var) -type SSDecrTerm = [(Var, [Var])] - -type ExprMemory = [(Type, CoreExpr, Int)] -type T = M.HashMap Type (CoreExpr, Int) -data SState - = SState { rEnv :: !REnv - , ssEnv :: !SSEnv -- Local Binders Generated during Synthesis - , ssIdx :: !Int - , ssDecrTerm :: !SSDecrTerm - , sContext :: !SMT.Context - , sCGI :: !CGInfo - , sCGEnv :: !CGEnv - , sFCfg :: !F.Config - , sDepth :: !Int - , sExprMem :: !ExprMemory - , sExprId :: !Int - , sArgsId :: !Int - , sArgsDepth :: !Int - , sUniVars :: ![Var] - , sFix :: !Var - , sGoalTys :: ![Type] - , sGoalTyVar :: !(Maybe [TyVar]) - , sUGoalTy :: !(Maybe [Type]) -- Types used for instantiation. - -- Produced by @withUnify@. - , sForalls :: !([Var], [[Type]]) -- [Var] are the parametric functions (except for the fixpoint) - -- e.g. Constructors, top-level functions. - -- [[Type]]: all the types that have instantiated [Var] so far. - , caseIdx :: !Int -- [ Temporary ] Index in list of scrutinees. - , scrutinees :: ![(CoreExpr, Type, TyCon)] - } - -type SM = StateT SState IO - -localMaxAppDepth :: SM Int -localMaxAppDepth = maxAppDepth . getConfig . sCGEnv <$> get - -localMaxArgsDepth :: SM Int -localMaxArgsDepth = maxArgsDepth . getConfig . sCGEnv <$> get - -locally :: SM a -> SM a -locally act = do - st <- get - r <- act - modify $ \s -> s{sCGEnv = sCGEnv st, sCGI = sCGI st, sExprMem = sExprMem st, scrutinees = scrutinees st} - return r - - -evalSM :: SM a -> SMT.Context -> SSEnv -> SState -> IO a -evalSM act ctx env st = do - let st' = st {ssEnv = env} - r <- evalStateT act st' - _ <- SMT.cleanupContext ctx - return r - -initState :: SMT.Context -> F.Config -> CGInfo -> CGEnv -> REnv -> Var -> [Var] -> SSEnv -> IO SState -initState ctx fcfg cgi cgenv renv xtop uniVars env = - return $ SState renv env 0 [] ctx cgi cgenv fcfg 0 exprMem0 0 0 0 uniVars xtop [] Nothing Nothing ([], []) 0 [] - where exprMem0 = initExprMem env - -getSEnv :: SM SSEnv -getSEnv = ssEnv <$> get - -getSEMem :: SM ExprMemory -getSEMem = sExprMem <$> get - -getSFix :: SM Var -getSFix = sFix <$> get - -getSUniVars :: SM [Var] -getSUniVars = sUniVars <$> get - -getSDecrTerms :: SM SSDecrTerm -getSDecrTerms = ssDecrTerm <$> get - -addsEnv :: [(Var, SpecType)] -> SM () -addsEnv xts = - mapM_ (\(x,t) -> modify (\s -> s {ssEnv = M.insert (symbol x) (t,x) (ssEnv s)})) xts - -addsEmem :: [(Var, SpecType)] -> SM () -addsEmem xts = do - curAppDepth <- sExprId <$> get - mapM_ (\(x,t) -> modify (\s -> s {sExprMem = (toType False t, GHC.Var x, curAppDepth+1) : sExprMem s})) xts - - -addEnv :: Var -> SpecType -> SM () -addEnv x t = do - liftCG0 (\γ -> γ += ("arg", symbol x, t)) - modify (\s -> s {ssEnv = M.insert (symbol x) (t,x) (ssEnv s)}) - -addEmem :: Var -> SpecType -> SM () -addEmem x t = do - let ht0 = toType False t - curAppDepth <- sExprId <$> get - xtop <- getSFix - (ht1, _) <- instantiateTL - let ht = if x == xtop then ht1 else ht0 - modify (\s -> s {sExprMem = (ht, GHC.Var x, curAppDepth) : sExprMem s}) - ---------------------------------------------------------------------------------------------- --- Handle structural termination checking -- ---------------------------------------------------------------------------------------------- -addDecrTerm :: Var -> [Var] -> SM () -addDecrTerm x vars = do - decrTerms <- getSDecrTerms - case lookup x decrTerms of - Nothing -> lookupAll x vars decrTerms - Just vars' -> do - let ix = elemIndex (x, vars') decrTerms - newDecrs = thisReplace (fromMaybe (error " [ addDecrTerm ] Index ") ix) (x, vars ++ vars') decrTerms - modify (\s -> s { ssDecrTerm = newDecrs }) - --- -lookupAll :: Var -> [Var] -> SSDecrTerm -> SM () -lookupAll x vars [] = modify (\s -> s {ssDecrTerm = (x, vars) : ssDecrTerm s}) -lookupAll x vars ((xl, vs):decrs) = - case find (== x) vs of - Nothing -> lookupAll x vars decrs - Just _ -> do - sDecrs <- ssDecrTerm <$> get - let newDecr = (xl, vars ++ [x] ++ vs) - i = fromMaybe (error " Write sth ") (elemIndex (xl, vs) sDecrs) - newDecrs = thisReplace i newDecr decrs - modify (\s -> s { ssDecrTerm = newDecrs }) - -thisReplace :: Int -> a -> [a] -> [a] -thisReplace i x l - = left ++ [x] ++ right - where left = take (i-1) l - right = drop i l - --- | Entry point. -structuralCheck :: [CoreExpr] -> SM [CoreExpr] -structuralCheck es - = do decr <- ssDecrTerm <$> get - fix <- sFix <$> get - return (filter (notStructural decr fix) es) - -structCheck :: Var -> CoreExpr -> (Maybe Var, [CoreExpr]) -structCheck xtop var@(GHC.Var v) - = if v == xtop - then (Just xtop, []) - else (Nothing, [var]) -structCheck xtop (GHC.App e1 (GHC.Type _)) - = structCheck xtop e1 -structCheck xtop (GHC.App e1 e2) - = (mbVar, e2:es) - where (mbVar, es) = structCheck xtop e1 -structCheck xtop (GHC.Let _ e) - = structCheck xtop e -structCheck _ e - = error (" StructCheck " ++ show e) - -notStructural :: SSDecrTerm -> Var -> CoreExpr -> Bool -notStructural decr xtop e - = case v of - Nothing -> True - Just _ -> foldr (\x b -> isDecreasing' x decr || b) False args - where (v, args) = structCheck xtop e - -isDecreasing' :: CoreExpr -> SSDecrTerm -> Bool -isDecreasing' (GHC.Var v) decr - = v `notElem` map fst decr -isDecreasing' _e _decr - = True ---------------------------------------------------------------------------------------------- --- END OF STRUCTURAL CHECK -- ---------------------------------------------------------------------------------------------- - -liftCG0 :: (CGEnv -> CG CGEnv) -> SM () -liftCG0 act = do - st <- get - let (cgenv, cgi) = runState (act (sCGEnv st)) (sCGI st) - modify (\s -> s {sCGI = cgi, sCGEnv = cgenv}) - - -liftCG :: CG a -> SM a -liftCG act = do - st <- get - let (x, cgi) = runState act (sCGI st) - modify (\s -> s {sCGI = cgi}) - return x - - -freshVarType :: Type -> SM Var -freshVarType t = (\i -> mkVar (Just "x") i t) <$> incrSM - - -freshVar :: SpecType -> SM Var -freshVar = freshVarType . toType False - -withIncrDepth :: Monoid a => SM a -> SM a -withIncrDepth m = do - s <- get - matchBound <- localMaxMatchDepth - let d = sDepth s - if d + 1 > matchBound - then return mempty - else do put s{sDepth = d + 1} - r <- m - modify $ \s -> s{sDepth = d} - return r - - -incrSM :: SM Int -incrSM = do s <- get - put s{ssIdx = ssIdx s + 1} - return (ssIdx s) - -incrCase :: SM Int -incrCase - = do s <- get - put s { caseIdx = caseIdx s + 1 } - return (caseIdx s) - -safeIxScruts :: Int -> [a] -> Maybe Int -safeIxScruts i l - | i >= length l = Nothing - | otherwise = Just i - -symbolExpr :: Type -> F.Symbol -> SM CoreExpr -symbolExpr τ x = incrSM >>= (\i -> return $ F.notracepp ("symExpr for " ++ F.showpp x) $ GHC.Var $ mkVar (Just $ F.symbolString x) i τ) - - -------------------------------------------------------------------------------------------------------- ------------------------------------------ Handle ExprMemory ------------------------------------------- -------------------------------------------------------------------------------------------------------- - --- | Initializes @ExprMemory@ structure. --- 1. Transforms refinement types to conventional (Haskell) types. --- 2. All @Depth@s are initialized to 0. -initExprMem :: SSEnv -> ExprMemory -initExprMem sEnv = map (\(_, (t, v)) -> (toType False t, GHC.Var v, 0)) (M.toList sEnv) - - --------------- Init @ExprMemory@ with instantiated functions with the right type (sUGoalTy) ----------- -insEMem0 :: SSEnv -> SM ExprMemory -insEMem0 senv = do - xtop <- getSFix - (ttop, _) <- instantiateTL - mbUTy <- sUGoalTy <$> get - uniVs <- sUniVars <$> get - - let ts = fromMaybe [] mbUTy - ts0 <- snd . sForalls <$> get - fs0 <- fst . sForalls <$> get - modify ( \s -> s { sForalls = (fs0, ts : ts0) } ) - - let handleIt e = case e of GHC.Var v -> if xtop == v - then (instantiate e (Just uniVs), ttop) - else change e - _ -> change e - change e = let { e' = instantiateTy e mbUTy; t' = exprType e' } - in (e', t') - - em0 = initExprMem senv - return $ map (\(_, e, i) -> let (e', t') = handleIt e - in (t', e', i)) em0 - -instantiateTy :: CoreExpr -> Maybe [Type] -> CoreExpr -instantiateTy e mbTy = - case mbTy of - Nothing -> e - Just tys -> fromMaybe e (applyTy tys e) - --- | Used for instantiation: Applies types to an expression. --- > The result does not have @forall@. --- Nothing as a result suggests that there are more types than foralls in the expression. -applyTy :: [Type] -> GHC.CoreExpr -> Maybe GHC.CoreExpr -applyTy [] e = case exprType e of - ForAllTy{} -> Nothing - _ -> Just e -applyTy (t:ts) e = case exprType e of - ForAllTy{} -> applyTy ts (GHC.App e (GHC.Type t)) - _ -> Nothing - --- | Instantiation based on current goal-type. -fixEMem :: SpecType -> SM () -fixEMem t - = do (fs, ts) <- sForalls <$> get - let uTys = unifyWith (toType False t) - needsFix <- case find (== uTys) ts of - Nothing -> return True -- not yet instantiated - Just _ -> return False -- already instantiated - - when needsFix $ - do modify (\s -> s { sForalls = (fs, uTys : ts)}) - let notForall e = case exprType e of {ForAllTy{} -> False; _ -> True} - es = map (\v -> instantiateTy (GHC.Var v) (Just uTys)) fs - fixEs = filter notForall es - thisDepth <- sDepth <$> get - let fixedEMem = map (\e -> (exprType e, e, thisDepth + 1)) fixEs - modify (\s -> s {sExprMem = fixedEMem ++ sExprMem s}) - ------------------------------------------------------------------------------------------------- ------------------------------- Special handle for the current fixpoint ------------------------- ------------------------------------------------------------------------------------------------- - --- | Instantiate the top-level variable. -instantiateTL :: SM (Type, GHC.CoreExpr) -instantiateTL = do - uniVars <- getSUniVars - xtop <- getSFix - let e = fromJust $ apply uniVars (GHC.Var xtop) - return (exprType e, e) - --- | Applies type variables (1st argument) to an expression. --- The expression is guaranteed to have the same level of --- parametricity (same number of @forall@) as the length of the 1st argument. --- > The result has zero @forall@. -apply :: [Var] -> GHC.CoreExpr -> Maybe GHC.CoreExpr -apply [] e = - case exprType e of - ForAllTy {} -> Nothing - _ -> Just e -apply (v:vs) e - = case exprType e of - ForAllTy{} -> apply vs (GHC.App e (GHC.Type (TyVarTy v))) - _ -> Nothing - -instantiate :: CoreExpr -> Maybe [Var] -> CoreExpr -instantiate e mbt = - case mbt of - Nothing -> e - Just tyVars -> fromMaybe e (apply tyVars e) - ------------------------------------------------------------------------------------------------------ - -withTypeEs :: SpecType -> SM [CoreExpr] -withTypeEs t = do - em <- sExprMem <$> get - return (map snd3 (filter (\x -> fst3 x == toType False t) em)) - -findCandidates :: Type -> -- Goal type: Find all candidate expressions of this type, - -- or that produce this type (i.e. functions). - SM ExprMemory -findCandidates goalTy = do - sEMem <- sExprMem <$> get - return (filter (goalType goalTy . fst3) sEMem) - -functionCands :: Type -> SM [(Type, GHC.CoreExpr, Int)] -functionCands goalTy = do - all <- findCandidates goalTy - return (filter (isFunction . fst3) all) - - ---------------------------------------------------------------------------------- ---------------------------- Generate error expression --------------------------- ---------------------------------------------------------------------------------- - -varError :: SM Var -varError = do - info <- ghcI . sCGI <$> get - let env = B.makeEnv (gsConfig $ giSpec info) (toGhcSrc $ giSrc info) mempty mempty - let name = giTargetMod $ giSrc info - let errSym = dummyLoc $ symbol "Language.Haskell.Liquid.Synthesize.Error.err" - case B.lookupGhcVar env name "Var" errSym of - Right v -> return v - Left e -> error (show e) - - -toGhcSrc :: TargetSrc -> GhcSrc -toGhcSrc a = Src - { _giIncDir = giIncDir a - , _giTarget = giTarget a - , _giTargetMod = giTargetMod a - , _giCbs = giCbs a - , _gsTcs = gsTcs a - , _gsCls = gsCls a - , _giDerVars = giDerVars a - , _giImpVars = giImpVars a - , _giDefVars = giDefVars a - , _giUseVars = giUseVars a - , _gsExports = gsExports a - , _gsFiTcs = gsFiTcs a - , _gsFiDcs = gsFiDcs a - , _gsPrimTcs = gsPrimTcs a - , _gsQualImps = gsQualImps a - , _gsAllImps = gsAllImps a - , _gsTyThings = gsTyThings a - } diff --git a/src/Language/Haskell/Liquid/Synthesize/Termination.hs b/src/Language/Haskell/Liquid/Synthesize/Termination.hs deleted file mode 100644 index 4fbf173acb..0000000000 --- a/src/Language/Haskell/Liquid/Synthesize/Termination.hs +++ /dev/null @@ -1,22 +0,0 @@ -{-# LANGUAGE FlexibleInstances #-} - -module Language.Haskell.Liquid.Synthesize.Termination ( - decrType - ) where - -import Language.Haskell.Liquid.Types -import qualified Language.Haskell.Liquid.Types.RefType - as R -import qualified Language.Fixpoint.Types as F -import Liquid.GHC.API - -decrType :: Var -> SpecType -> [Var] -> [(F.Symbol, SpecType)] -> SpecType -decrType _x ti xs _xts = - go xs ti - where - go (v:_) (RFun x i tx t r) - | isDecreasing mempty mempty tx = let Left (x', tx') = R.makeDecrType mempty [(v,(x,tx))] - in RFun x' i tx' t r - go (_:vs) (RFun x i tx t r) = RFun x i tx (go vs t) r - go vs (RAllT a t x) = RAllT a (go vs t) x - go _ t = t diff --git a/src/Language/Haskell/Liquid/Termination/Structural.hs b/src/Language/Haskell/Liquid/Termination/Structural.hs index 5b4d6fb7b2..31296fad32 100644 --- a/src/Language/Haskell/Liquid/Termination/Structural.hs +++ b/src/Language/Haskell/Liquid/Termination/Structural.hs @@ -2,8 +2,6 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Termination.Structural (terminationVars) where import Language.Haskell.Liquid.Types hiding (isDecreasing) @@ -62,7 +60,7 @@ nextBinds = \case App e a -> nextBinds e ++ nextBinds a Lam _ e -> nextBinds e Let b e -> b : nextBinds e - Case scrut _ _ alts -> nextBinds scrut ++ ([body | (_, _, body) <- alts] >>= nextBinds) + Case scrut _ _ alts -> nextBinds scrut ++ ([body | Alt _ _ body <- alts] >>= nextBinds) Cast e _ -> nextBinds e Tick _ e -> nextBinds e Var{} -> [] @@ -176,12 +174,12 @@ addParam param env = case envCurrentFun env of | otherwise = fun addSynonym :: Var -> Var -> Env -> Env -addSynonym oldName newName env = env { envCheckedFuns = updateFun <$> envCheckedFuns env } +addSynonym oldName newName' env = env { envCheckedFuns = updateFun <$> envCheckedFuns env } where updateFun fun = fun { funParams = updateParam <$> funParams fun } updateParam param - | oldName `elemVarSet` paramNames param = param { paramNames = paramNames param `extendVarSet` newName } - | oldName `elemVarSet` paramSubterms param = param { paramSubterms = paramSubterms param `extendVarSet` newName } + | oldName `elemVarSet` paramNames param = param { paramNames = paramNames param `extendVarSet` newName' } + | oldName `elemVarSet` paramSubterms param = param { paramSubterms = paramSubterms param `extendVarSet` newName' } | otherwise = param addSubterms :: Var -> [Var] -> Env -> Env @@ -269,12 +267,12 @@ getCallInfoExpr env = \case Case (toVar -> Just var) bndr _ alts -> foldMap getCallInfoAlt alts where - getCallInfoAlt (_, subterms, body) = getCallInfoExpr (branchEnv subterms) body + getCallInfoAlt (Alt _ subterms body) = getCallInfoExpr (branchEnv subterms) body branchEnv subterms = addSubterms var subterms . addSynonym var bndr $ env Case scrut _ _ alts -> getCallInfoExpr env scrut <> foldMap getCallInfoAlt alts where - getCallInfoAlt (_, _, body) = getCallInfoExpr env body + getCallInfoAlt (Alt _ _ body) = getCallInfoExpr env body Cast e _ -> getCallInfoExpr env e Tick _ e -> getCallInfoExpr env e diff --git a/src/Language/Haskell/Liquid/Transforms/ANF.hs b/src/Language/Haskell/Liquid/Transforms/ANF.hs index 32a46545be..2f0c5e11e3 100644 --- a/src/Language/Haskell/Liquid/Transforms/ANF.hs +++ b/src/Language/Haskell/Liquid/Transforms/ANF.hs @@ -3,13 +3,12 @@ -------------------------------------------------------------------------------- {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NoMonomorphismRestriction #-} -{-# LANGUAGE TupleSections #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-} - module Language.Haskell.Liquid.Transforms.ANF (anormalize) where import Prelude hiding (error) @@ -21,7 +20,6 @@ import Liquid.GHC.API as Ghc hiding ( mkTyArg import qualified Liquid.GHC.API as Ghc import Control.Monad.State.Lazy import System.Console.CmdArgs.Verbosity (whenLoud) -import qualified Language.Fixpoint.Misc as F import qualified Language.Fixpoint.Types as F import Language.Haskell.Liquid.UX.Config as UX @@ -36,7 +34,6 @@ import qualified Liquid.GHC.SpanStack as Sp import qualified Liquid.GHC.Resugar as Rs import Data.Maybe (fromMaybe) import Data.List (sortBy, (\\)) -import Data.Function (on) import qualified Text.Printf as Printf import Data.Hashable import Data.HashMap.Strict (HashMap) @@ -99,12 +96,12 @@ normalizeTyVars (NonRec x e) = NonRec (setVarType x t') $ normalizeForAllTys e where t' = subst msg as as' bt msg = "WARNING: unable to renameVars on " ++ GM.showPpr x - as' = fst $ splitForAllTys $ exprType e - (as, bt) = splitForAllTys (varType x) + as' = fst $ splitForAllTyCoVars $ exprType e + (as, bt) = splitForAllTyCoVars (varType x) normalizeTyVars (Rec xes) = Rec xes' where nrec = normalizeTyVars <$> (uncurry NonRec <$> xes) - xes' = (\(NonRec x e) -> (x, e)) <$> nrec + xes' = (\case NonRec x e -> (x, e); _ -> impossible Nothing "This cannot happen") <$> nrec subst :: String -> [TyVar] -> [TyVar] -> Type -> Type subst msg as as' bt @@ -121,7 +118,7 @@ normalizeForAllTys e = case e of -> e _ -> mkLams tvs (mkTyApps e (map mkTyVarTy tvs)) where - (tvs, _) = splitForAllTys (exprType e) + (tvs, _) = splitForAllTyCoVars (exprType e) newtype DsM a = DsM {runDsM :: Ghc.DsM a} @@ -220,7 +217,7 @@ normalize γ (Case e x t as) = do n <- normalizeName γ e x' <- lift $ freshNormalVar γ τx -- rename "wild" to avoid shadowing let γ' = extendAnfEnv γ x x' - as' <- forM as $ \(c, xs, e') -> fmap (c, xs,) (stitch (incrCaseDepth c γ') e') + as' <- forM as $ \(Alt c xs e') -> fmap (Alt c xs) (stitch (incrCaseDepth c γ') e') as'' <- lift $ expandDefaultCase γ τx as' return $ Case n x' t as'' where τx = GM.expandVarType x @@ -303,15 +300,15 @@ expandDefault γ = aeCaseDepth γ <= maxCaseExpand γ -------------------------------------------------------------------------------- expandDefaultCase :: AnfEnv -> Type - -> [(AltCon, [Id], CoreExpr)] - -> DsM [(AltCon, [Id], CoreExpr)] + -> [CoreAlt] + -> DsM [CoreAlt] -------------------------------------------------------------------------------- -expandDefaultCase γ tyapp zs@((DEFAULT, _ ,_) : _) | expandDefault γ +expandDefaultCase γ tyapp zs@(Alt DEFAULT _ _ : _) | expandDefault γ = expandDefaultCase' γ tyapp zs -expandDefaultCase γ tyapp@(TyConApp tc _) z@((DEFAULT, _ ,_):dcs) +expandDefaultCase γ tyapp@(TyConApp tc _) z@(Alt DEFAULT _ _:dcs) = case tyConDataCons_maybe tc of - Just ds -> do let ds' = ds \\ [ d | (DataAlt d, _ , _) <- dcs] + Just ds -> do let ds' = ds \\ [ d | Alt (DataAlt d) _ _ <- dcs] let n = length ds' if n == 1 then expandDefaultCase' γ tyapp z @@ -324,21 +321,21 @@ expandDefaultCase _ _ z = return z expandDefaultCase' - :: AnfEnv -> Type -> [(AltCon, [Id], c)] -> DsM [(AltCon, [Id], c)] -expandDefaultCase' γ t ((DEFAULT, _, e) : dcs) - | Just dtss <- GM.defaultDataCons t (F.fst3 <$> dcs) = do + :: AnfEnv -> Type -> [CoreAlt] -> DsM [CoreAlt] +expandDefaultCase' γ t (Alt DEFAULT _ e : dcs) + | Just dtss <- GM.defaultDataCons t ((\(Alt dc _ _) -> dc) <$> dcs) = do dcs' <- warnCaseExpand γ <$> forM dtss (cloneCase γ e) return $ sortCases (dcs' ++ dcs) expandDefaultCase' _ _ z = return z -cloneCase :: AnfEnv -> e -> (DataCon, [TyVar], [Type]) -> DsM (AltCon, [Id], e) +cloneCase :: AnfEnv -> CoreExpr -> (DataCon, [TyVar], [Type]) -> DsM CoreAlt cloneCase γ e (d, as, ts) = do xs <- mapM (freshNormalVar γ) ts - return (DataAlt d, as ++ xs, e) + return (Alt (DataAlt d) (as ++ xs) e) -sortCases :: [(AltCon, b, c)] -> [(AltCon, b, c)] -sortCases = sortBy (cmpAltCon `on` F.fst3) +sortCases :: [CoreAlt] -> [CoreAlt] +sortCases = sortBy Ghc.cmpAlt warnCaseExpand :: AnfEnv -> [a] -> [a] warnCaseExpand γ xs @@ -430,5 +427,5 @@ incrCaseDepth :: AltCon -> AnfEnv -> AnfEnv incrCaseDepth DEFAULT γ = γ { aeCaseDepth = 1 + aeCaseDepth γ } incrCaseDepth _ γ = γ -at :: AnfEnv -> Tickish Id -> AnfEnv +at :: AnfEnv -> CoreTickish -> AnfEnv at γ tt = γ { aeSrcSpan = Sp.push (Sp.Tick tt) (aeSrcSpan γ)} diff --git a/src/Language/Haskell/Liquid/Transforms/CoreToLogic.hs b/src/Language/Haskell/Liquid/Transforms/CoreToLogic.hs index 8d888410ec..9d93059c6e 100644 --- a/src/Language/Haskell/Liquid/Transforms/CoreToLogic.hs +++ b/src/Language/Haskell/Liquid/Transforms/CoreToLogic.hs @@ -1,12 +1,10 @@ {-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Transforms.CoreToLogic ( coreToDef @@ -58,8 +56,8 @@ logicType :: (Reftable r) => Bool -> Type -> RRType r logicType allowTC τ = fromRTypeRep $ t { ty_binds = bs, ty_info = is, ty_args = as, ty_refts = rs} where t = toRTypeRep $ ofType τ - (bs, is, as, rs) = Misc.unzip4 $ dropWhile (isErasable . Misc.thd4) $ Misc.zip4 (ty_binds t) (ty_info t) (ty_args t) (ty_refts t) - isErasable = if allowTC then isEmbeddedClass else isClassType + (bs, is, as, rs) = Misc.unzip4 $ dropWhile (isErasable' . Misc.thd4) $ Misc.zip4 (ty_binds t) (ty_info t) (ty_args t) (ty_refts t) + isErasable' = if allowTC then isEmbeddedClass else isClassType {- | [NOTE:inlineSpecType type]: the refinement depends on whether the result type is a Bool or not: CASE1: measure f@logic :: X -> Bool <=> f@haskell :: x:X -> {v:Bool | v <=> (f@logic x)} @@ -69,16 +67,16 @@ logicType allowTC τ = fromRTypeRep $ t { ty_binds = bs, ty_info = is, ty_a inlineSpecType :: Bool -> Var -> SpecType inlineSpecType allowTC v = fromRTypeRep $ rep {ty_res = res `strengthen` r , ty_binds = xs} where - r = MkUReft (mkR (mkEApp f (mkA <$> vxs))) mempty + r = MkUReft (mkReft (mkEApp f (mkA <$> vxs))) mempty rep = toRTypeRep t res = ty_res rep xs = intSymbol (symbol ("x" :: String)) <$> [1..length $ ty_binds rep] - vxs = dropWhile (isErasable . snd) $ zip xs (ty_args rep) - isErasable = if allowTC then isEmbeddedClass else isClassType + vxs = dropWhile (isErasable' . snd) $ zip xs (ty_args rep) + isErasable' = if allowTC then isEmbeddedClass else isClassType f = dummyLoc (symbol v) t = ofType (GM.expandVarType v) :: SpecType mkA = EVar . fst - mkR = if isBool res then propReft else exprReft + mkReft = if isBool res then propReft else exprReft -- | Refine types of measures: keep going until you find the last data con! -- this code is a hack! we refine the last data constructor, @@ -89,14 +87,14 @@ inlineSpecType allowTC v = fromRTypeRep $ rep {ty_res = res `strengthen` r , ty -- formerly: strengthenResult' measureSpecType :: Bool -> Var -> SpecType -measureSpecType allowTC v = go mkT [] [(1::Int)..] t +measureSpecType allowTC v = go mkT [] [(1::Int)..] st where - mkR | boolRes = propReft - | otherwise = exprReft - mkT xs = MkUReft (mkR $ mkEApp f (EVar <$> reverse xs)) mempty - f = dummyLoc (symbol v) - t = ofType (GM.expandVarType v) :: SpecType - boolRes = isBool $ ty_res $ toRTypeRep t + mkReft | boolRes = propReft + | otherwise = exprReft + mkT xs = MkUReft (mkReft $ mkEApp locSym (EVar <$> reverse xs)) mempty + locSym = dummyLoc (symbol v) + st = ofType (GM.expandVarType v) :: SpecType + boolRes = isBool $ ty_res $ toRTypeRep st go f args i (RAllT a t r) = RAllT a (go f args i t) r go f args i (RAllP p t) = RAllP p $ go f args i t @@ -165,22 +163,22 @@ runToLogicWithBoolBinds xs tce lmap dm ferror m coreAltToDef :: (Reftable r) => Bool -> LocSymbol -> Var -> [Var] -> Var -> Type -> [C.CoreAlt] -> LogicM [Def (Located (RRType r)) DataCon] -coreAltToDef allowTC x z zs y t alts - | not (null litAlts) = measureFail x "Cannot lift definition with literal alternatives" +coreAltToDef allowTC locSym z zs y t alts + | not (null litAlts) = measureFail locSym "Cannot lift definition with literal alternatives" | otherwise = do - d1s <- F.notracepp "coreAltDefs-1" <$> mapM (mkAlt x cc myArgs z) dataAlts - d2s <- F.notracepp "coreAltDefs-2" <$> mkDef x cc myArgs z defAlts defExpr + d1s <- F.notracepp "coreAltDefs-1" <$> mapM (mkAlt locSym cc myArgs z) dataAlts + d2s <- F.notracepp "coreAltDefs-2" <$> mkDef locSym cc myArgs z defAlts defExpr return (d1s ++ d2s) where myArgs = reverse zs cc = if eqType t boolTy then P else E - defAlts = GM.defaultDataCons (GM.expandVarType y) (Misc.fst3 <$> alts) - defExpr = listToMaybe [ e | (C.DEFAULT , _, e) <- alts ] - dataAlts = [ a | a@(C.DataAlt _, _, _) <- alts ] - litAlts = [ a | a@(C.LitAlt _, _, _) <- alts ] + defAlts = GM.defaultDataCons (GM.expandVarType y) ((\(Alt c _ _) -> c) <$> alts) + defExpr = listToMaybe [ e | (Alt C.DEFAULT _ e) <- alts ] + dataAlts = [ a | a@(Alt (C.DataAlt _) _ _) <- alts ] + litAlts = [ a | a@(Alt (C.LitAlt _) _ _) <- alts ] -- mkAlt :: LocSymbol -> (Expr -> Body) -> [Var] -> Var -> (C.AltCon, [Var], C.CoreExpr) - mkAlt x ctor _args dx (C.DataAlt d, xs, e) + mkAlt x ctor _args dx (Alt (C.DataAlt d) xs e) = Def x {- (toArgs id args) -} d (Just $ varRType dx) (toArgs Just xs') . ctor . (`subst1` (F.symbol dx, F.mkEApp (GM.namedLocSymbol d) (F.eVar <$> xs'))) @@ -209,14 +207,14 @@ defArgs x = zipWith (\i t -> (defArg i, defRTyp t)) [0..] coreToDef :: Reftable r => Bool -> LocSymbol -> Var -> C.CoreExpr -> LogicM [Def (Located (RRType r)) DataCon] -coreToDef allowTC x _ e = go [] $ inlinePreds $ simplify allowTC e +coreToDef allowTC locSym _ = go [] . inlinePreds . simplify allowTC where go args (C.Lam x e) = go (x:args) e go args (C.Tick _ e) = go args e - go (z:zs) (C.Case _ y t alts) = coreAltToDef allowTC x z zs y t alts + go (z:zs) (C.Case _ y t alts) = coreAltToDef allowTC locSym z zs y t alts go (z:zs) e - | Just t <- isMeasureArg z = coreAltToDef allowTC x z zs z t [(C.DEFAULT, [], e)] - go _ _ = measureFail x "Does not have a case-of at the top-level" + | Just t <- isMeasureArg z = coreAltToDef allowTC locSym z zs z t [Alt C.DEFAULT [] e] + go _ _ = measureFail locSym "Does not have a case-of at the top-level" inlinePreds = inline (eqType boolTy . GM.expandVarType) @@ -242,7 +240,7 @@ varRType :: (Reftable r) => Var -> Located (RRType r) varRType = GM.varLocInfo ofType coreToFun :: Bool -> LocSymbol -> Var -> C.CoreExpr -> LogicM ([Var], Either Expr Expr) -coreToFun allowTC _ _v e = go [] $ normalize allowTC e +coreToFun allowTC _ _v = go [] . normalize allowTC where isE = if allowTC then GM.isEmbeddedDictVar else isErasable go acc (C.Lam x e) | isTyVar x = go acc e @@ -261,11 +259,7 @@ coreToLogic allowTC cb = coreToLg allowTC (normalize allowTC cb) coreToLg :: Bool -> C.CoreExpr -> LogicM Expr coreToLg allowTC (C.Let (C.NonRec x (C.Coercion c)) e) - = coreToLg allowTC (C.substExpr -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - C.empty -#endif - (C.extendCvSubst C.emptySubst x c) e) + = coreToLg allowTC (C.substExpr (C.extendCvSubst C.emptySubst x c) e) coreToLg allowTC (C.Let b e) = subst1 <$> coreToLg allowTC e <*> makesub allowTC b coreToLg allowTC (C.Tick _ e) = coreToLg allowTC e @@ -317,11 +311,11 @@ typeEqToLg (s, t) = do return $ F.notracepp "TYPE-EQ-TO-LOGIC" (tx s, tx t) checkBoolAlts :: [C.CoreAlt] -> LogicM (C.CoreExpr, C.CoreExpr) -checkBoolAlts [(C.DataAlt false, [], efalse), (C.DataAlt true, [], etrue)] +checkBoolAlts [Alt (C.DataAlt false) [] efalse, Alt (C.DataAlt true) [] etrue] | false == falseDataCon, true == trueDataCon = return (efalse, etrue) -checkBoolAlts [(C.DataAlt true, [], etrue), (C.DataAlt false, [], efalse)] +checkBoolAlts [Alt (C.DataAlt true) [] etrue, Alt (C.DataAlt false) [] efalse] | false == falseDataCon, true == trueDataCon = return (efalse, etrue) checkBoolAlts alts @@ -336,7 +330,7 @@ casesToLg allowTC v e alts = mapM (altToLg allowTC e) normAlts >>= go go ((d,p):dps) = do c <- checkDataAlt d e e' <- go dps return (EIte c p e' `subst1` su) - go [] = panic (Just (getSrcSpan v)) "Unexpected empty cases in casesToLg" + go [] = panic (Just (getSrcSpan v)) $ "Unexpected empty cases in casesToLg: " ++ show e su = (symbol v, e) checkDataAlt :: C.AltCon -> Expr -> LogicM Expr @@ -351,16 +345,16 @@ normalizeAlts :: [C.CoreAlt] -> [C.CoreAlt] normalizeAlts alts = ctorAlts ++ defAlts where (defAlts, ctorAlts) = L.partition isDefault alts - isDefault (c,_,_) = c == C.DEFAULT + isDefault (Alt c _ _) = c == C.DEFAULT altToLg :: Bool -> Expr -> C.CoreAlt -> LogicM (C.AltCon, Expr) -altToLg allowTC de (a@(C.DataAlt d), xs, e) = do +altToLg allowTC de (Alt a@(C.DataAlt d) xs e) = do p <- coreToLg allowTC e dm <- gets lsDCMap let su = mkSubst $ concat [ dataConProj dm de d x i | (x, i) <- zip (filter (not . if allowTC then GM.isEmbeddedDictVar else GM.isEvVar) xs) [1..]] return (a, subst su p) -altToLg allowTC _ (a, _, e) +altToLg allowTC _ (Alt a _ e) = (a, ) <$> coreToLg allowTC e dataConProj :: DataConMap -> Expr -> DataCon -> Var -> Int -> [(Symbol, Expr)] @@ -503,9 +497,9 @@ bops = M.fromList [ (numSymbol "+", Plus) realSymbol = symbol . (++) "GHC.Real." splitArgs :: Bool -> C.Expr t -> (C.Expr t, [C.Arg t]) -splitArgs allowTC e = (f, reverse es) +splitArgs allowTC exprt = (exprt', reverse args) where - (f, es) = go e + (exprt', args) = go exprt go (C.App (C.Var i) e) | ignoreVar i = go e go (C.App f (C.Var v)) | if allowTC then GM.isEmbeddedDictVar v else isErasable v = go f @@ -563,7 +557,7 @@ ignoreVar i = simpleSymbolVar i `elem` ["I#", "D#"] -- We need the disjuction for GHC >= 9, where the Integer now comes from the \"ghc-bignum\" package, -- and it has different names for the constructors. isBangInteger :: [C.CoreAlt] -> Bool -isBangInteger [(C.DataAlt s, _, _), (C.DataAlt jp,_,_), (C.DataAlt jn,_,_)] +isBangInteger [Alt (C.DataAlt s) _ _, Alt (C.DataAlt jp) _ _, Alt (C.DataAlt jn) _ _] = (symbol s == "GHC.Integer.Type.S#" || symbol s == "GHC.Num.Integer.IS") && (symbol jp == "GHC.Integer.Type.Jp#" || symbol jp == "GHC.Num.Integer.IP") && (symbol jn == "GHC.Integer.Type.Jn#" || symbol jn == "GHC.Num.Integer.IN") @@ -624,7 +618,7 @@ instance Simplify C.CoreExpr where = simplify allowTC e simplify allowTC (C.Let xes e) = C.Let (simplify allowTC xes) (simplify allowTC e) - simplify allowTC (C.Case e x _t alts@[(_,_,ee),_,_]) | isBangInteger alts + simplify allowTC (C.Case e x _t alts@[Alt _ _ ee,_,_]) | isBangInteger alts -- XXX(matt): seems to be for debugging? = -- Misc.traceShow ("To simplify allowTC case") $ sub (M.singleton x (simplify allowTC e)) (simplify allowTC ee) @@ -652,11 +646,18 @@ instance Simplify C.CoreExpr where inline _ (C.Coercion c) = C.Coercion c inline _ (C.Type t) = C.Type t -isUndefined :: (t, t1, C.Expr t2) -> Bool -isUndefined (_, _, e) = isUndefinedExpr e +isUndefined :: CoreAlt -> Bool +isUndefined (Alt _ _ exprCoreBndr) = isUndefinedExpr exprCoreBndr where - -- auto generated undefined case: (\_ -> (patError @type "error message")) void - isUndefinedExpr (C.App (C.Var x) _) | show x `elem` perrors = True + isUndefinedExpr :: C.CoreExpr -> Bool + -- auto generated undefined case: (\_ -> (patError @levity @type "error message")) void + -- Type arguments are erased before calling isUndefined + isUndefinedExpr (C.App (C.Var x) _) + | show x `elem` perrors = True + -- another auto generated undefined case: + -- let lqanf_... = patError "error message") in case lqanf_... of {} + isUndefinedExpr (C.Let (C.NonRec x e) (C.Case (C.Var v) _ _ [])) + | x == v = isUndefinedExpr e isUndefinedExpr (C.Let _ e) = isUndefinedExpr e -- otherwise isUndefinedExpr _ = False @@ -672,7 +673,7 @@ instance Simplify C.CoreBind where inline p (C.Rec xes) = C.Rec (Misc.mapSnd (inline p) <$> xes) instance Simplify C.CoreAlt where - simplify allowTC (c, xs, e) = (c, xs, simplify allowTC e) + simplify allowTC (Alt c xs e) = Alt c xs (simplify allowTC e) -- where xs = F.tracepp _msg xs0 -- _msg = "isCoVars? " ++ F.showpp [(x, isCoVar x, varType x) | x <- xs0] - inline p (c, xs, e) = (c, xs, inline p e) + inline p (Alt c xs e) = Alt c xs (inline p e) diff --git a/src/Language/Haskell/Liquid/Transforms/InlineAux.hs b/src/Language/Haskell/Liquid/Transforms/InlineAux.hs index 3c503d654e..d55be8b042 100644 --- a/src/Language/Haskell/Liquid/Transforms/InlineAux.hs +++ b/src/Language/Haskell/Liquid/Transforms/InlineAux.hs @@ -1,8 +1,5 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Transforms.InlineAux ( inlineAux ) @@ -18,18 +15,18 @@ inlineAux :: UX.Config -> Module -> CoreProgram -> CoreProgram inlineAux cfg m cbs = if UX.auxInline cfg then occurAnalysePgm m (const False) (const False) [] (map f cbs) else cbs where f :: CoreBind -> CoreBind - f all@(NonRec x e) + f all'@(NonRec x e) | Just (dfunId, methodToAux) <- M.lookup x auxToMethodToAux = NonRec x (inlineAuxExpr dfunId methodToAux e) - | otherwise = all + | otherwise = all' f (Rec bs) = Rec (fmap g bs) where - g all@(x, e) + g all'@(x, e) | Just (dfunId, methodToAux) <- M.lookup x auxToMethodToAux = (x, inlineAuxExpr dfunId methodToAux e) | otherwise - = all + = all' auxToMethodToAux = mconcat $ fmap (uncurry dfunIdSubst) (grepDFunIds cbs) @@ -73,17 +70,13 @@ dfunIdSubst dfunId e = M.fromList $ zip auxIds (repeat (dfunId, methodToAux)) methods = classAllSelIds cls inlineAuxExpr :: DFunId -> M.HashMap Id Id -> CoreExpr -> CoreExpr -inlineAuxExpr dfunId methodToAux e = go e +inlineAuxExpr dfunId methodToAux = go where go :: CoreExpr -> CoreExpr go (Lam b body) = Lam b (go body) go (Let b body) - | NonRec x e <- b, isDictId x = go - $ substExpr -#if !MIN_VERSION_GLASGOW_HASKELL(9,0,0,0) - empty -#endif - (extendIdSubst emptySubst x e) body + | NonRec x e <- b, isDictId x = + go $ substExpr (extendIdSubst emptySubst x e) body | otherwise = Let (mapBnd go b) (go body) go (Case e x t alts) = Case (go e) x t (fmap (mapAlt go) alts) go (Cast e c ) = Cast (go e) c @@ -105,5 +98,5 @@ mapBnd :: (Expr b -> Expr b) -> Bind b -> Bind b mapBnd f (NonRec b e) = NonRec b (f e) mapBnd f (Rec bs ) = Rec (map (second f) bs) -mapAlt :: (Expr b -> Expr b) -> (t, t1, Expr b) -> (t, t1, Expr b) -mapAlt f (d, bs, e) = (d, bs, f e) +mapAlt :: (Expr b -> Expr b) -> Alt b -> Alt b +mapAlt f (Alt d bs e) = Alt d bs (f e) diff --git a/src/Language/Haskell/Liquid/Transforms/Rec.hs b/src/Language/Haskell/Liquid/Transforms/Rec.hs index f13ab69ff3..2f4f1340a4 100644 --- a/src/Language/Haskell/Liquid/Transforms/Rec.hs +++ b/src/Language/Haskell/Liquid/Transforms/Rec.hs @@ -3,8 +3,6 @@ {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Transforms.Rec ( transformRecExpr, transformScope , outerScTr , innerScTr @@ -73,7 +71,7 @@ inlineFailCases = (go [] <$>) go' su (Tick t e) = Tick t (go' su e) go' _ e = e - goalt su (c, xs, e) = (c, xs, go' su e) + goalt su (Alt c xs e) = Alt c xs (go' su e) isFailId x = isLocalId x && isSystemName (varName x) && L.isPrefixOf "fail" (show x) getFailExpr = L.lookup @@ -103,8 +101,8 @@ innerScTr :: Functor f => f (Bind Id) -> f (Bind Id) innerScTr = (mapBnd scTrans <$>) scTrans :: Id -> Expr Id -> Expr Id -scTrans x e = mapExpr scTrans $ foldr Let e0 bs - where (bs, e0) = go [] x e +scTrans id' expr = mapExpr scTrans $ foldr Let e0 bindIds + where (bindIds, e0) = go [] id' expr go bs x (Let b e) | isCaseArg x b = go (b:bs) x e go bs x (Tick t e) = second (Tick t) $ go bs x e go bs _ e = (bs, e) @@ -142,7 +140,7 @@ isNonPolyRec (Let (Rec xes) _) = any nonPoly (snd <$> xes) isNonPolyRec _ = False nonPoly :: CoreExpr -> Bool -nonPoly = null . fst . splitForAllTys . exprType +nonPoly = null . fst . splitForAllTyCoVars . exprType collectNonRecLets :: Expr t -> ([Bind t], Expr t) collectNonRecLets = go [] @@ -158,13 +156,13 @@ trans :: Foldable t -> t (Bind Id) -> Expr Var -> State TrEnv (Expr Id) -trans vs ids bs (Let (Rec xes) e) - = fmap (mkLam . mkLet) (makeTrans vs liveIds e') +trans vs ids bs (Let (Rec xes) expr) + = fmap (mkLam . mkLet') (makeTrans vs liveIds e') where liveIds = mkAlive <$> ids - mkLet e = foldr Let e bs + mkLet' e = foldr Let e bs mkLam e = foldr Lam e $ vs ++ liveIds - e' = Let (Rec xes') e - xes' = second mkLet <$> xes + e' = Let (Rec xes') expr + xes' = second mkLet' <$> xes trans _ _ _ _ = panic Nothing "TransformRec.trans called with invalid input" @@ -190,7 +188,7 @@ makeTrans vs ids (Let (Rec xes) e) makeTrans _ _ _ = panic Nothing "TransformRec.makeTrans called with invalid input" mkRecBinds :: [(b, Expr b)] -> Bind b -> Expr b -> Expr b -mkRecBinds xes rs e = Let rs (L.foldl' f e xes) +mkRecBinds xes rs expr = Let rs (L.foldl' f expr xes) where f e (x, xe) = Let (NonRec x xe) e mkSubs :: (Eq k, Hashable k) @@ -203,11 +201,11 @@ mkFreshIds :: [TyVar] -> [Var] -> Var -> State TrEnv ([Var], Id) -mkFreshIds tvs ids x - = do ids' <- mapM fresh ids +mkFreshIds tvs origIds var + = do ids' <- mapM fresh origIds let ids'' = map setIdTRecBound ids' - let t = mkForAllTys ((`Bndr` Required) <$> tvs) $ mkType (reverse ids'') $ varType x - let x' = setVarType x t + let t = mkForAllTys ((`Bndr` Required) <$> tvs) $ mkType (reverse ids'') $ varType var + let x' = setVarType var t return (ids'', x') where mkType ids ty = foldl (\t x -> FunTy VisArg Many (varType x) t) ty ids -- FIXME(adinapoli): Is 'VisArg' OK here? @@ -275,8 +273,8 @@ mapExpr f (Case e b t alt) = Case e b t (map (mapAlt f) alt) mapExpr f (Tick t e) = Tick t (mapExpr f e) mapExpr _ e = e -mapAlt :: (b -> Expr b -> Expr b) -> (t, t1, Expr b) -> (t, t1, Expr b) -mapAlt f (d, bs, e) = (d, bs, mapExpr f e) +mapAlt :: (b -> Expr b -> Expr b) -> Alt b -> Alt b +mapAlt f (Alt d bs e) = Alt d bs (mapExpr f e) -- Do not apply transformations to inner code diff --git a/src/Language/Haskell/Liquid/Transforms/RefSplit.hs b/src/Language/Haskell/Liquid/Transforms/RefSplit.hs index cb68c4e0ae..102a9f421c 100644 --- a/src/Language/Haskell/Liquid/Transforms/RefSplit.hs +++ b/src/Language/Haskell/Liquid/Transforms/RefSplit.hs @@ -2,7 +2,6 @@ {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Transforms.RefSplit ( @@ -68,11 +67,11 @@ splitRType f (RAppTy tx t r) = (RAppTy tx1 t1 r1, RAppTy tx2 t2 r2) (tx1, tx2) = splitRType f tx (t1, t2) = splitRType f t (r1, r2) = splitRef f r -splitRType f (RRTy xs r o t) = (RRTy xs1 r1 o t1, RRTy xs2 r2 o t2) +splitRType f (RRTy xs r o rt) = (RRTy xs1 r1 o rt1, RRTy xs2 r2 o rt2) where (xs1, xs2) = unzip (go <$> xs) (r1, r2) = splitRef f r - (t1, t2) = splitRType f t + (rt1, rt2) = splitRType f rt go (x, t) = let (t1, t2) = splitRType f t in ((x,t1), (x, t2)) splitRType f (RHole r) = (RHole r1, RHole r2) diff --git a/src/Language/Haskell/Liquid/Transforms/Rewrite.hs b/src/Language/Haskell/Liquid/Transforms/Rewrite.hs index b685cecde3..f34093e4e7 100644 --- a/src/Language/Haskell/Liquid/Transforms/Rewrite.hs +++ b/src/Language/Haskell/Liquid/Transforms/Rewrite.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -8,7 +7,7 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleContexts #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- | This module contains functions for recursively "rewriting" -- GHC core using "rules". @@ -31,7 +30,7 @@ import Data.Maybe (fromMaybe) import Control.Monad.State hiding (lift) import Language.Fixpoint.Misc ({- mapFst, -} mapSnd) import qualified Language.Fixpoint.Types as F -import Language.Haskell.Liquid.Misc (safeZipWithError, mapThd3, Nat) +import Language.Haskell.Liquid.Misc (safeZipWithError, Nat) import Liquid.GHC.Play (substExpr) import Liquid.GHC.Resugar import Liquid.GHC.Misc (unTickExpr, isTupleId, showPpr, mkAlive) -- , showPpr, tracePpr) @@ -45,15 +44,66 @@ import qualified Data.HashMap.Strict as M rewriteBinds :: Config -> [CoreBind] -> [CoreBind] rewriteBinds cfg | simplifyCore cfg - = fmap (normalizeTuples . rewriteBindWith tidyTuples . rewriteBindWith simplifyPatTuple) + = fmap (normalizeTuples + . rewriteBindWith undollar + . rewriteBindWith tidyTuples + . rewriteBindWith simplifyPatTuple) | otherwise = id simplifyCore :: Config -> Bool simplifyCore = not . noSimplifyCore +undollar :: RewriteRule +undollar = go + where + go e + -- matches `$ t1 t2 t3 f a` + | App e1 a <- untick e + , App e2 f <- untick e1 + , App e3 t3 <- untick e2 + , App e4 t2 <- untick e3 + , App d t1 <- untick e4 + , Var v <- untick d + , v `hasKey` dollarIdKey + , Type _ <- untick t1 + , Type _ <- untick t2 + , Type _ <- untick t3 + = Just $ App f a + go (Tick t e) + = Tick t <$> go e + go (Let (NonRec x ex) e) + = do ex' <- go ex + e' <- go e + return $ Let (NonRec x ex') e' + go (Let (Rec bes) e) + = Let <$> (Rec <$> mapM goRec bes) <*> go e + go (Case e x t alts) + = Case e x t <$> mapM goAlt alts + go (App e1 e2) + = App <$> go e1 <*> go e2 + go (Lam x e) + = Lam x <$> go e + go (Cast e c) + = (`Cast` c) <$> go e + go e + = return e + + goRec (x, e) + = (x,) <$> go e + + goAlt (Alt c bs e) + = Alt c bs <$> go e + + + + +untick :: CoreExpr -> CoreExpr +untick (Tick _ e) = untick e +untick e = e + tidyTuples :: RewriteRule -tidyTuples e = Just $ evalState (go e) [] +tidyTuples ce = Just $ evalState (go ce) [] where go (Tick t e) = Tick t <$> go e @@ -79,30 +129,30 @@ tidyTuples e = Just $ evalState (go e) [] goRec (x, e) = (x,) <$> go e - goAlt (c, bs, e) - = (c, bs,) <$> go e + goAlt (Alt c bs e) + = Alt c bs <$> go e - goAltR v (c, bs, e) + goAltR v (Alt c bs e) = do m <- get case L.lookup (c,v) m of - Just bs' -> return (c, bs', substTuple bs' bs e) + Just bs' -> return (Alt c bs' (substTuple bs' bs e)) Nothing -> do let bs' = mkAlive <$> bs modify (((c,v),bs'):) - return (c, bs', e) + return (Alt c bs' e) normalizeTuples :: CoreBind -> CoreBind -normalizeTuples b - | NonRec x e <- b +normalizeTuples cb + | NonRec x e <- cb = NonRec x $ go e - | Rec xes <- b + | Rec xes <- cb = let (xs,es) = unzip xes in Rec $ zip xs (go <$> es) where go (Let (NonRec x ex) e) | Case _ _ _ alts <- unTickExpr ex - , [(_, vs, Var z)] <- alts + , [Alt _ vs (Var z)] <- alts , z `elem` vs = Let (NonRec z (go ex)) (substTuple [z] [x] (go e)) go (Let (NonRec x ex) e) @@ -114,7 +164,7 @@ normalizeTuples b go (Lam x e) = Lam x (go e) go (Case e b t alt) - = Case (go e) b t (mapThd3 go <$> alt) + = Case (go e) b t ((\(Alt c bs e') -> Alt c bs (go e')) <$> alt) go (Cast e c) = Cast (go e) c go (Tick t e) @@ -155,7 +205,7 @@ rewriteWith tx = go step (Lam x e) = Lam x (go e) step (Cast e c) = Cast (go e) c step (Tick t e) = Tick t (go e) - step (Case e x t cs) = Case (go e) x t (mapThd3 go <$> cs) + step (Case e x t cs) = Case (go e) x t ((\(Alt c bs e') -> Alt c bs (go e')) <$> cs) step e@(Type _) = e step e@(Lit _) = e step e@(Var _) = e @@ -249,9 +299,9 @@ simplifyPatTuple :: RewriteRule _tidyAlt :: Int -> Maybe CoreExpr -> Maybe CoreExpr -_tidyAlt n (Just (Let (NonRec x e) rest)) +_tidyAlt n (Just (Let (NonRec cb expr) rest)) | Just (yes, e') <- takeBinds n rest - = Just $ Let (NonRec x e) $ foldl (\e (x, ex) -> Let (NonRec x ex) e) e' (reverse $ go $ reverse yes) + = Just $ Let (NonRec cb expr) $ foldl (\e (x, ex) -> Let (NonRec x ex) e) e' (reverse $ go $ reverse yes) where go xes@((_, e):_) = let bs = grapBinds e in mapSnd (replaceBinds bs) <$> xes @@ -259,13 +309,13 @@ _tidyAlt n (Just (Let (NonRec x e) rest)) replaceBinds bs (Case c x t alt) = Case c x t (replaceBindsAlt bs <$> alt) replaceBinds bs (Tick t e) = Tick t (replaceBinds bs e) replaceBinds _ e = e - replaceBindsAlt bs (c, _, e) = (c, bs, e) + replaceBindsAlt bs (Alt c _ e) = Alt c bs e grapBinds (Case _ _ _ alt) = grapBinds' alt grapBinds (Tick _ e) = grapBinds e grapBinds _ = [] grapBinds' [] = [] - grapBinds' ((_,bs,_):_) = bs + grapBinds' (Alt _ bs _ : _) = bs _tidyAlt _ e = e @@ -291,9 +341,9 @@ varTuple x = Nothing takeBinds :: Nat -> CoreExpr -> Maybe ([(Var, CoreExpr)], CoreExpr) -takeBinds n e - | n < 2 = Nothing - | otherwise = {- mapFst reverse <$> -} go n e +takeBinds nat ce + | nat < 2 = Nothing + | otherwise = {- mapFst reverse <$> -} go nat ce where go 0 e = Just ([], e) go n (Let (NonRec x e) e') = do (xes, e'') <- go (n-1) e' @@ -326,8 +376,8 @@ hasTuple ys = stepE stepE e | Just xs <- isVarTup ys e = Just xs | otherwise = go e - stepA (DEFAULT,_,_) = Nothing - stepA (_, _, e) = stepE e + stepA (Alt DEFAULT _ _) = Nothing + stepA (Alt _ _ e) = stepE e go (Let _ e) = stepE e go (Case _ _ _ cs) = msum (stepA <$> cs) go _ = Nothing @@ -337,20 +387,20 @@ hasTuple ys = stepE -------------------------------------------------------------------------------- replaceTuple :: [Var] -> CoreExpr -> CoreExpr -> Maybe CoreExpr -replaceTuple ys e e' = stepE e +replaceTuple ys ce ce' = stepE ce where - t' = Ghc.exprType e' + t' = Ghc.exprType ce' stepE e - | Just xs <- isVarTup ys e = Just $ substTuple xs ys e' + | Just xs <- isVarTup ys e = Just $ substTuple xs ys ce' | otherwise = go e - stepA (DEFAULT, xs, err) = Just (DEFAULT, xs, replaceIrrefutPat t' err) - stepA (c, xs, e) = (c, xs,) <$> stepE e + stepA (Alt DEFAULT xs err) = Just (Alt DEFAULT xs (replaceIrrefutPat t' err)) + stepA (Alt c xs e) = Alt c xs <$> stepE e go (Let b e) = Let b <$> stepE e go (Case e x t cs) = fixCase e x t <$> mapM stepA cs go _ = Nothing _showExpr :: CoreExpr -> String -_showExpr e = show' e +_showExpr = show' where show' (App e1 e2) = show' e1 ++ " " ++ show' e2 show' (Var x) = _showVar x @@ -359,7 +409,7 @@ _showExpr e = show' e show' (Case e x _ alt) = "Case " ++ _showVar x ++ " = " ++ show' e ++ " OF " ++ unlines (showAlt' <$> alt) show' e = showPpr e - showAlt' (c, bs, e) = showPpr c ++ unwords (_showVar <$> bs) ++ " -> " ++ show' e + showAlt' (Alt c bs e) = showPpr c ++ unwords (_showVar <$> bs) ++ " -> " ++ show' e _showVar :: Var -> String _showVar = show . F.symbol @@ -383,7 +433,7 @@ fixCase :: CoreExpr -> Var -> Type -> ListNE (Alt Var) -> CoreExpr fixCase e x _t cs' = Case e x t' cs' where t' = Ghc.exprType body - (_,_,body) = c + Alt _ _ body = c c:_ = cs' {-@ type ListNE a = {v:[a] | len v > 0} @-} diff --git a/src/Language/Haskell/Liquid/Types/Bounds.hs b/src/Language/Haskell/Liquid/Types/Bounds.hs index 11910d0b43..c8b26d9aa9 100644 --- a/src/Language/Haskell/Liquid/Types/Bounds.hs +++ b/src/Language/Haskell/Liquid/Types/Bounds.hs @@ -4,7 +4,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.Types.Bounds ( @@ -62,13 +62,13 @@ instance (PPrint e, PPrint t) => (Show (Bound t e)) where instance (PPrint e, PPrint t) => (PPrint (Bound t e)) where - pprintTidy k (Bound s vs ps xs e) = "bound" <+> pprintTidy k s <+> + pprintTidy k (Bound s vs ps ys e) = "bound" <+> pprintTidy k s <+> "forall" <+> pprintTidy k vs <+> "." <+> pprintTidy k (fst <$> ps) <+> "=" <+> - ppBsyms k (fst <$> xs) <+> pprintTidy k e + ppBsyms k (fst <$> ys) <+> pprintTidy k e where ppBsyms _ [] = "" - ppBsyms k xs = "\\" <+> pprintTidy k xs <+> "->" + ppBsyms k' xs = "\\" <+> pprintTidy k' xs <+> "->" instance Bifunctor Bound where first f (Bound s vs ps xs e) = Bound s (f <$> vs) (Misc.mapSnd f <$> ps) (Misc.mapSnd f <$> xs) e @@ -76,7 +76,7 @@ instance Bifunctor Bound where makeBound :: (PPrint r, UReftable r, SubsTy RTyVar (RType RTyCon RTyVar ()) r) => RRBound RSort -> [RRType r] -> [F.Symbol] -> RRType r -> RRType r -makeBound (Bound _ vs ps xs p) ts qs +makeBound (Bound _ vs ps xs expr) ts qs = RRTy cts mempty OCons where cts = (\(x, t) -> (x, foldr subsTyVarMeet t su)) <$> cts' @@ -84,7 +84,7 @@ makeBound (Bound _ vs ps xs p) ts qs cts' = makeBoundType penv rs xs penv = zip (val . fst <$> ps) qs - rs = bkImp [] p + rs = bkImp [] expr bkImp acc (F.PImp p q) = bkImp (p:acc) q bkImp acc p = p:acc @@ -128,10 +128,10 @@ isPApp penv (F.EApp e _) = isPApp penv e isPApp _ _ = False toUsedPVars :: [(F.Symbol, F.Symbol)] -> F.Expr -> (F.Symbol, [PVar ()]) -toUsedPVars penv q@(F.EApp _ e) = (x, [toUsedPVar penv q]) +toUsedPVars penv q@(F.EApp _ expr) = (sym, [toUsedPVar penv q]) where -- NV : TODO make this a better error - x = case {- unProp -} e of {F.EVar x -> x; e -> todo Nothing ("Bound fails in " ++ show e) } + sym = case {- unProp -} expr of {F.EVar x -> x; e -> todo Nothing ("Bound fails in " ++ show e) } toUsedPVars _ _ = impossible Nothing "This cannot happen" toUsedPVar :: [(F.Symbol, F.Symbol)] -> F.Expr -> PVar () diff --git a/src/Language/Haskell/Liquid/Types/Equality.hs b/src/Language/Haskell/Liquid/Types/Equality.hs index 688eb9697a..aa3eaa83cb 100644 --- a/src/Language/Haskell/Liquid/Types/Equality.hs +++ b/src/Language/Haskell/Liquid/Types/Equality.hs @@ -1,7 +1,5 @@ {-# LANGUAGE FlexibleInstances #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -- Syntactic Equality of Types up tp forall type renaming module Language.Haskell.Liquid.Types.Equality where @@ -18,14 +16,14 @@ instance REq SpecType where t1 =*= t2 = compareRType t1 t2 compareRType :: SpecType -> SpecType -> Bool -compareRType i1 i2 = res && unify vs +compareRType i1 i2 = res && unify ys where unify vs = and (sndEq <$> L.groupBy (\(x1,_) (x2,_) -> x1 == x2) vs) sndEq [] = True sndEq [_] = True sndEq ((_,y):xs) = all (==y) (snd <$> xs) - (res, vs) = runWriter (go i1 i2) + (res, ys) = runWriter (go i1 i2) go :: SpecType -> SpecType -> Writer [(RTyVar, RTyVar)] Bool go (RAllT x1 t1 r1) (RAllT x2 t2 r2) | RTV v1 <- ty_var_value x1 diff --git a/src/Language/Haskell/Liquid/Types/Errors.hs b/src/Language/Haskell/Liquid/Types/Errors.hs index 1930a247a9..757de269a4 100644 --- a/src/Language/Haskell/Liquid/Types/Errors.hs +++ b/src/Language/Haskell/Liquid/Types/Errors.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} @@ -44,7 +45,7 @@ module Language.Haskell.Liquid.Types.Errors ( , ppTicks -- * SrcSpan Helpers - , realSrcSpan + , packRealSrcSpan , unpackRealSrcSpan , srcSpanFileMb ) where @@ -710,15 +711,17 @@ unpackRealSrcSpan rsp = (f, l1, c1, l2, c2) instance FromJSON RealSrcSpan where - parseJSON (Object v) = realSrcSpan <$> v .: "filename" - <*> v .: "startLine" - <*> v .: "startCol" - <*> v .: "endLine" - <*> v .: "endCol" + parseJSON (Object v) = + packRealSrcSpan + <$> v .: "filename" + <*> v .: "startLine" + <*> v .: "startCol" + <*> v .: "endLine" + <*> v .: "endCol" parseJSON _ = mempty -realSrcSpan :: FilePath -> Int -> Int -> Int -> Int -> RealSrcSpan -realSrcSpan f l1 c1 l2 c2 = mkRealSrcSpan loc1 loc2 +packRealSrcSpan :: FilePath -> Int -> Int -> Int -> Int -> RealSrcSpan +packRealSrcSpan f l1 c1 l2 c2 = mkRealSrcSpan loc1 loc2 where loc1 = mkRealSrcLoc (fsLit f) l1 c1 loc2 = mkRealSrcLoc (fsLit f) l2 c2 @@ -754,9 +757,7 @@ instance FromJSON (TError a) where parseJSON _ = mempty errSaved :: SrcSpan -> String -> TError a -errSaved sp body = ErrSaved sp (text n) (text $ unlines m) - where - n : m = lines body +errSaved sp body | n : m <- lines body = ErrSaved sp (text n) (text $ unlines m) totalityType :: PPrint a => Tidy -> a -> Bool totalityType td tE = pprintTidy td tE == text "{VV : Addr# | 5 < 4}" @@ -1103,10 +1104,9 @@ ppList d ls -- | Convert a GHC error into a list of our errors. sourceErrors :: String -> SourceError -> [TError t] -sourceErrors s = concatMap (errMsgErrors s) . bagToList . srcErrorMessages - -errMsgErrors :: String -> ErrMsg -> [TError t] -errMsgErrors s e = [ ErrGhc (errMsgSpan e) msg ] - where - msg = text s - $+$ nest 4 (text (show e)) +sourceErrors s = + concatMap errMsgErrors . bagToList . srcErrorMessages + where + errMsgErrors e = [ ErrGhc (errMsgSpan e) msg ] + where + msg = text s $+$ nest 4 (text (show e)) diff --git a/src/Language/Haskell/Liquid/Types/Fresh.hs b/src/Language/Haskell/Liquid/Types/Fresh.hs index ba8797abe5..40fd3515e0 100644 --- a/src/Language/Haskell/Liquid/Types/Fresh.hs +++ b/src/Language/Haskell/Liquid/Types/Fresh.hs @@ -7,8 +7,6 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ConstraintKinds #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.Types.Fresh ( Freshable(..) , refreshTy @@ -137,13 +135,13 @@ refreshRefType allowTC (RAllT α t r) refreshRefType allowTC (RAllP π t) = RAllP π <$> refresh allowTC t -refreshRefType allowTC (RImpF b i t t' _) - | b == F.dummySymbol = (\b t1 t2 -> RImpF b i t1 t2 mempty) <$> fresh <*> refresh allowTC t <*> refresh allowTC t' - | otherwise = (\t1 t2 -> RImpF b i t1 t2 mempty) <$> refresh allowTC t <*> refresh allowTC t' +refreshRefType allowTC (RImpF sym i t t' _) + | sym == F.dummySymbol = (\b t1 t2 -> RImpF b i t1 t2 mempty) <$> fresh <*> refresh allowTC t <*> refresh allowTC t' + | otherwise = (\t1 t2 -> RImpF sym i t1 t2 mempty) <$> refresh allowTC t <*> refresh allowTC t' -refreshRefType allowTC (RFun b i t t' _) - | b == F.dummySymbol = (\b t1 t2 -> RFun b i t1 t2 mempty) <$> fresh <*> refresh allowTC t <*> refresh allowTC t' - | otherwise = (\t1 t2 -> RFun b i t1 t2 mempty) <$> refresh allowTC t <*> refresh allowTC t' +refreshRefType allowTC (RFun sym i t t' _) + | sym == F.dummySymbol = (\b t1 t2 -> RFun b i t1 t2 mempty) <$> fresh <*> refresh allowTC t <*> refresh allowTC t' + | otherwise = (\t1 t2 -> RFun sym i t1 t2 mempty) <$> refresh allowTC t <*> refresh allowTC t' refreshRefType _ (RApp rc ts _ _) | isClass rc = return $ rRCls rc ts @@ -261,8 +259,8 @@ refreshArgsSub t refreshPs :: (FreshM m) => SpecType -> m SpecType refreshPs = mapPropM go where - go (RProp s t) = do - t' <- refreshPs t + go (RProp s st) = do + t' <- refreshPs st xs <- mapM (const fresh) s let su = F.mkSubst [(y, F.EVar x) | (x, (y, _)) <- zip xs s] return $ RProp [(x, t) | (x, (_, t)) <- zip xs s] $ F.subst su t' diff --git a/src/Language/Haskell/Liquid/Types/PredType.hs b/src/Language/Haskell/Liquid/Types/PredType.hs index b1d8b9e2c7..1961170d68 100644 --- a/src/Language/Haskell/Liquid/Types/PredType.hs +++ b/src/Language/Haskell/Liquid/Types/PredType.hs @@ -5,7 +5,7 @@ {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.Types.PredType ( PrType @@ -154,7 +154,7 @@ dataConResultTy dc αs t = mkFamilyTyConApp tc tArgs' meetWorkWrapRep :: DataCon -> SpecRep -> SpecRep -> SpecRep meetWorkWrapRep c workR wrapR - | 0 <= pad + | 0 <= pad' = workR { ty_binds = xs ++ ty_binds wrapR , ty_args = ts ++ zipWith F.meet ts' (ty_args wrapR) , ty_res = strengthenRType (ty_res workR) (ty_res wrapR) @@ -163,9 +163,9 @@ meetWorkWrapRep c workR wrapR | otherwise = panic (Just (getSrcSpan c)) errMsg where - pad = {- F.tracepp ("MEETWKRAP: " ++ show (ty_vars workR)) $ -} workN - wrapN - (xs, _) = splitAt pad (ty_binds workR) - (ts, ts') = splitAt pad (ty_args workR) + pad' = {- F.tracepp ("MEETWKRAP: " ++ show (ty_vars workR)) $ -} workN - wrapN + (xs, _) = splitAt pad' (ty_binds workR) + (ts, ts') = splitAt pad' (ty_args workR) workN = length (ty_args workR) wrapN = length (ty_args wrapR) errMsg = "Unsupported Work/Wrap types for Data Constructor " ++ showPpr c @@ -182,18 +182,18 @@ dcWrapSpecType allowTC dc (DataConP _ _ vs ps cs yts rt _ _ _) mkArrow makeVars' ps [] ts' rt' where isCls = Ghc.isClassTyCon $ Ghc.dataConTyCon dc - (xs, ts) = unzip (reverse yts) + (as, sts) = unzip (reverse yts) mkDSym z = F.symbol z `F.suffixSymbol` F.symbol dc - ys = mkDSym <$> xs + bs = mkDSym <$> as tx _ [] [] [] = [] tx su (x:xs) (y:ys) (t:ts) = (y, classRFInfo allowTC , if allowTC && isCls then t else F.subst (F.mkSubst su) t, mempty) : tx ((x, F.EVar y):su) xs ys ts tx _ _ _ _ = panic Nothing "PredType.dataConPSpecType.tx called on invalid inputs" - yts' = tx [] xs ys ts + yts' = tx [] as bs sts ts' = map ("" , classRFInfo allowTC , , mempty) cs ++ yts' - su = F.mkSubst [(x, F.EVar y) | (x, y) <- zip xs ys] - rt' = F.subst su rt - makeVars = zipWith (\v a -> RTVar v (rTVarInfo a :: RTVInfo RSort)) vs (fst $ splitForAllTys $ dataConRepType dc) + subst = F.mkSubst [(x, F.EVar y) | (x, y) <- zip as bs] + rt' = F.subst subst rt + makeVars = zipWith (\v a -> RTVar v (rTVarInfo a :: RTVInfo RSort)) vs (fst $ splitForAllTyCoVars $ dataConRepType dc) makeVars' = zip makeVars (repeat mempty) instance PPrint TyConP where @@ -336,7 +336,7 @@ substPVar src dst = go go (RImpF x i t t' r) = RImpF x i (go t) (go t') (goRR r) go (RAllE x t t') = RAllE x (go t) (go t') go (REx x t t') = REx x (go t) (go t') - go (RRTy e r o t) = RRTy e' (goRR r) o (go t) where e' = [(x, go t) | (x, t) <- e] + go (RRTy e r o rt) = RRTy e' (goRR r) o (go rt) where e' = [(x, go t) | (x, t) <- e] go (RAppTy t1 t2 r) = RAppTy (go t1) (go t2) (goRR r) go (RHole r) = RHole (goRR r) go t@(RExprArg _) = t @@ -355,12 +355,12 @@ substPVar src dst = go substPred :: String -> (RPVar, SpecProp) -> SpecType -> SpecType ------------------------------------------------------------------------------- -substPred _ (π, RProp ss (RVar a1 r1)) t@(RVar a2 r2) +substPred _ (rp, RProp ss (RVar a1 r1)) t@(RVar a2 r2) | isPredInReft && a1 == a2 = RVar a1 $ meetListWithPSubs πs ss r1 r2' | isPredInReft = panic Nothing ("substPred RVar Var Mismatch" ++ show (a1, a2)) | otherwise = t where - (r2', πs) = splitRPvar π r2 + (r2', πs) = splitRPvar rp r2 isPredInReft = not $ null πs substPred msg su@(π, _ ) (RApp c ts rs r) @@ -376,22 +376,22 @@ substPred msg (p, tp) (RAllP q@PV{} t) substPred msg su (RAllT a t r) = RAllT a (substPred msg su t) r -substPred msg su@(π,prop) (RFun x i t t' r) +substPred msg su@(rp,prop) (RFun x i rt rt' r) -- = RFun x (substPred msg su t) (substPred msg su t') r - | null πs = RFun x i (substPred msg su t) (substPred msg su t') r + | null πs = RFun x i (substPred msg su rt) (substPred msg su rt') r | otherwise = let sus = (\π -> F.mkSubst (zip (fst <$> rf_args prop) (thd3 <$> pargs π))) <$> πs in - foldl (\t su -> t `F.meet` F.subst su (rf_body prop)) (RFun x i (substPred msg su t) (substPred msg su t') r') sus - where (r', πs) = splitRPvar π r + foldl (\t subst -> t `F.meet` F.subst subst (rf_body prop)) (RFun x i (substPred msg su rt) (substPred msg su rt') r') sus + where (r', πs) = splitRPvar rp r -- ps has , pargs :: ![(t, Symbol, Expr)] -- AT: just a copy of the other case, mutatis mutandi. (is there a less hacky way?) -substPred msg su@(π,prop) (RImpF x i t t' r) - | null πs = RImpF x i (substPred msg su t) (substPred msg su t') r +substPred msg su@(rp,prop) (RImpF x i rt rt' r) + | null πs = RImpF x i (substPred msg su rt) (substPred msg su rt') r | otherwise = let sus = (\π -> F.mkSubst (zip (fst <$> rf_args prop) (thd3 <$> pargs π))) <$> πs in - foldl (\t su -> t `F.meet` F.subst su (rf_body prop)) (RImpF x i (substPred msg su t) (substPred msg su t') r') sus - where (r', πs) = splitRPvar π r + foldl (\t subst -> t `F.meet` F.subst subst (rf_body prop)) (RImpF x i (substPred msg su rt) (substPred msg su rt') r') sus + where (r', πs) = splitRPvar rp r @@ -426,8 +426,8 @@ substRCon msg (_, RProp ss t1@(RApp c1 ts1 rs1 r1)) t2@(RApp c2 ts2 rs2 _) πs r ts = F.subst su $ safeZipWith (msg ++ ": substRCon") strSub ts1 ts2 rs = F.subst su $ safeZipWith (msg ++ ": substRCon2") strSubR rs1' rs2' (rs1', rs2') = pad "substRCon" F.top rs1 rs2 - strSub r1 r2 = meetListWithPSubs πs ss r1 r2 - strSubR r1 r2 = meetListWithPSubsRef πs ss r1 r2 + strSub x r2 = meetListWithPSubs πs ss x r2 + strSubR x r2 = meetListWithPSubsRef πs ss x r2 su = F.mkSubst $ zipWith (\s1 s2 -> (s1, F.EVar s2)) (rvs t1) (rvs t2) diff --git a/src/Language/Haskell/Liquid/Types/PrettyPrint.hs b/src/Language/Haskell/Liquid/Types/PrettyPrint.hs index 6d29ef2fe2..712628475c 100644 --- a/src/Language/Haskell/Liquid/Types/PrettyPrint.hs +++ b/src/Language/Haskell/Liquid/Types/PrettyPrint.hs @@ -12,7 +12,6 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Types.PrettyPrint ( -- * Printable RTypes @@ -58,7 +57,6 @@ import Liquid.GHC.API as Ghc ( Class , Type , Var , Name - , ErrMsg , SourceError , TyCon , topPrec @@ -73,6 +71,7 @@ import Language.Haskell.Liquid.Types.Types import Prelude hiding (error) import Text.PrettyPrint.HughesPJ hiding ((<>)) + -- | `Filter`s match errors. They are used to ignore classes of errors they -- match. `AnyFilter` matches all errors. `StringFilter` matches any error whose -- \"representation\" contains the given `String`. A \"representation\" is @@ -101,7 +100,7 @@ pprintSymbol x = char '‘' <-> pprint x <-> char '’' -------------------------------------------------------------------------------- -- | A whole bunch of PPrint instances follow ---------------------------------- -------------------------------------------------------------------------------- -instance PPrint ErrMsg where +instance PPrint (Ghc.MsgEnvelope Ghc.DecoratedSDoc) where pprintTidy _ = text . show instance PPrint SourceError where @@ -258,8 +257,8 @@ pprRtype bb p (RAppTy t t' r) = F.ppTy r $ pprRtype bb p t <+> pprRtype bb p t' pprRtype bb p (RRTy e _ OCons t) = sep [braces (pprRsubtype bb p e) <+> "=>", pprRtype bb p t] -pprRtype bb p (RRTy e r o t) - = sep [ppp (pprint o <+> ppe <+> pprint r), pprRtype bb p t] +pprRtype bb p (RRTy e r o rt) + = sep [ppp (pprint o <+> ppe <+> pprint r), pprRtype bb p rt] where ppe = hsep (punctuate comma (ppxt <$> e)) <+> dcolon ppp doc = text "<<" <+> doc <+> text ">>" @@ -299,19 +298,19 @@ ppExists PPrint (RType c tv ()), F.Reftable (RTProp c tv r), F.Reftable (RTProp c tv ())) => PPEnv -> Prec -> RType c tv r -> Doc -ppExists bb p t - = text "exists" <+> brackets (intersperse comma [pprDbind bb topPrec x t | (x, t) <- zs]) <-> dot <-> pprRtype bb p t' - where (zs, t') = split [] t +ppExists bb p rt + = text "exists" <+> brackets (intersperse comma [pprDbind bb topPrec x t | (x, t) <- ws]) <-> dot <-> pprRtype bb p rt' + where (ws, rt') = split [] rt split zs (REx x t t') = split ((x,t):zs) t' split zs t = (reverse zs, t) ppAllExpr :: (OkRT c tv r, PPrint (RType c tv r), PPrint (RType c tv ())) => PPEnv -> Prec -> RType c tv r -> Doc -ppAllExpr bb p t - = text "forall" <+> brackets (intersperse comma [pprDbind bb topPrec x t | (x, t) <- zs]) <-> dot <-> pprRtype bb p t' +ppAllExpr bb p rt + = text "forall" <+> brackets (intersperse comma [pprDbind bb topPrec x t | (x, t) <- ws]) <-> dot <-> pprRtype bb p rt' where - (zs, t') = split [] t + (ws, rt') = split [] rt split zs (RAllE x t t') = split ((x,t):zs) t' split zs t = (reverse zs, t) @@ -338,14 +337,14 @@ pprDbind bb p x t pprRtyFun :: ( OkRT c tv r, PPrint (RType c tv r), PPrint (RType c tv ())) => PPEnv -> Doc -> RType c tv r -> Doc -pprRtyFun bb prefix t = hsep (prefix : dArgs ++ [dOut]) +pprRtyFun bb prefix rt = hsep (prefix : dArgs ++ [dOut]) where dArgs = concatMap ppArg args dOut = pprRtype bb topPrec out ppArg (b, t, a) = [pprDbind bb funPrec b t, a] - (args, out) = brkFun t + (args, out) = brkFun rt -{- +{- pprRtyFun bb prefix t = prefix <+> pprRtyFun' bb t @@ -452,8 +451,8 @@ instance (PPrint r, F.Reftable r) => PPrint (UReft r) where -- | Pretty-printing errors ---------------------------------------------------- -------------------------------------------------------------------------------- -printError :: (Show e, F.PPrint e) => F.Tidy -> DynFlags -> TError e -> IO () -printError k dyn err = putErrMsg dyn (pos err) (ppError k empty err) +printError :: (Show e, F.PPrint e) => Ghc.Logger -> F.Tidy -> DynFlags -> TError e -> IO () +printError logger k dyn err = putErrMsg logger dyn (pos err) (ppError k empty err) -- | Similar in spirit to 'reportErrors' from the GHC API, but it uses our -- pretty-printer and shim functions under the hood. Also filters the errors @@ -475,8 +474,8 @@ filterReportErrors path failure continue filters k = , filters = filters } where - renderer :: TError e' -> String - renderer = render . ppError k empty + renderer e = render (ppError k empty e $+$ pprint (pos e)) + -- | Retrieve the `Filter`s from the Config. getFilters :: Config -> [Filter] @@ -487,12 +486,15 @@ getFilters cfg = anyFilter <> stringFilters -- | Return the list of @filters@ that matched the @err@ , given a @renderer@ -- for the @err@ and some @filters@ -reduceFilters :: forall e. (e -> String) -> [Filter] -> e -> [Filter] -reduceFilters renderer fs err = filter (filterDoesMatchErr err) fs - where - filterDoesMatchErr :: e -> Filter -> Bool - filterDoesMatchErr _ AnyFilter = True - filterDoesMatchErr e (StringFilter filter) = filter `L.isInfixOf` renderer e +reduceFilters :: (e -> String) -> [Filter] -> e -> [Filter] +reduceFilters renderer fs err = filter (filterDoesMatchErr renderer err) fs + +filterDoesMatchErr :: (e -> String) -> e -> Filter -> Bool +filterDoesMatchErr _ _ AnyFilter = True +filterDoesMatchErr renderer e (StringFilter filter') = stringMatch filter' (renderer e) + +stringMatch :: String -> String -> Bool +stringMatch filter' str = filter' `L.isInfixOf` str -- | Used in `filterReportErrorsWith'` data FilterReportErrorsArgs m filter msg e a = diff --git a/src/Language/Haskell/Liquid/Types/RefType.hs b/src/Language/Haskell/Liquid/Types/RefType.hs index ec72c1baa9..3277d50c21 100644 --- a/src/Language/Haskell/Liquid/Types/RefType.hs +++ b/src/Language/Haskell/Liquid/Types/RefType.hs @@ -15,7 +15,7 @@ {-# OPTIONS_GHC -Wno-incomplete-patterns #-} -- TODO(#1918): Only needed for GHC <9.0.1. {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-record-updates #-} -- | Refinement Types. Mostly mirroring the GHC Type definition, but with -- room for refinements of various sorts. @@ -96,7 +96,6 @@ module Language.Haskell.Liquid.Types.RefType ( import Prelude hiding (error) -- import qualified Prelude import Data.Maybe (fromMaybe, isJust) -import Data.Bifunctor (first) import Data.Monoid (First(..)) import Data.Hashable import qualified Data.HashMap.Strict as M @@ -145,14 +144,14 @@ import Data.List (foldl') strengthenDataConType :: (Var, SpecType) -> (Var, SpecType) strengthenDataConType (x, t) = (x, fromRTypeRep trep {ty_res = tres}) where - tres = F.notracepp _msg $ ty_res trep `strengthen` MkUReft (exprReft expr) mempty + tres = F.notracepp _msg $ ty_res trep `strengthen` MkUReft (exprReft expr') mempty trep = toRTypeRep t _msg = "STRENGTHEN-DATACONTYPE x = " ++ F.showpp (x, zip xs ts) (xs, ts) = dataConArgs trep as = ty_vars trep x' = symbol x - expr | null xs && null as = EVar x' - | otherwise = mkEApp (dummyLoc x') (EVar <$> xs) + expr' | null xs && null as = EVar x' + | otherwise = mkEApp (dummyLoc x') (EVar <$> xs) dataConArgs :: SpecRep -> ([Symbol], [SpecType]) @@ -167,9 +166,9 @@ pdVar :: PVar t -> Predicate pdVar v = Pr [uPVar v] findPVar :: [PVar (RType c tv ())] -> UsedPVar -> PVar (RType c tv ()) -findPVar ps p = PV name ty v (zipWith (\(_, _, e) (t, s, _) -> (t, s, e)) (pargs p) args) +findPVar ps upv = PV name ty v (zipWith (\(_, _, e) (t, s, _) -> (t, s, e)) (pargs upv) args) where - PV name ty v args = fromMaybe (msg p) $ L.find ((== pname p) . pname) ps + PV name ty v args = fromMaybe (msg upv) $ L.find ((== pname upv) . pname) ps msg p = panic Nothing $ "RefType.findPVar" ++ showpp p ++ "not found" -- | Various functions for converting vanilla `Reft` to `Spec` @@ -221,7 +220,6 @@ instance ( SubsTy tv (RType c tv ()) (RType c tv ()) ) => Monoid (RType c tv r) where mempty = panic Nothing "mempty: RType" - mappend = strengthenRefType -- MOVE TO TYPES instance ( SubsTy tv (RType c tv ()) c @@ -506,15 +504,17 @@ kindToBRType :: Monoid r => Type -> BRType r kindToBRType = kindToRType_ bareOfType kindToRType_ :: (Type -> z) -> Type -> z -kindToRType_ ofType = ofType . go +kindToRType_ ofType' = ofType' . go where go t | t == typeSymbolKind = stringTy - | t == typeNatKind = intTy + | t == naturalTy = intTy | otherwise = t isValKind :: Kind -> Bool -isValKind x = x == typeNatKind || x == typeSymbolKind +isValKind x0 = + let x = expandTypeSynonyms x0 + in x == naturalTy || x == typeSymbolKind bTyVar :: Symbol -> BTyVar bTyVar = BTV @@ -535,7 +535,7 @@ rPred = RAllP rEx :: Foldable t => t (Symbol, RType c tv r) -> RType c tv r -> RType c tv r -rEx xts t = foldr (\(x, tx) t -> REx x tx t) t xts +rEx xts rt = foldr (\(x, tx) t -> REx x tx t) rt xts rApp :: TyCon -> [RType RTyCon tv r] @@ -625,7 +625,7 @@ strengthenRefType_ :: ) => (RType c tv r -> RType c tv r -> RType c tv r) -> RType c tv r -> RType c tv r -> RType c tv r -strengthenRefTypeGen t1 t2 = strengthenRefType_ f t1 t2 +strengthenRefTypeGen = strengthenRefType_ f where f (RVar v1 r1) t = RVar v1 (r1 `meet` fromMaybe mempty (stripRTypeBase t)) f t (RVar _ r1) = t `strengthen` r1 @@ -701,11 +701,18 @@ strengthenRefType_ f (RImpF x1 i t1 t1' r1) (RImpF x2 _ t2 t2' r2) -- YL: Evidence that we need a Monoid instance for RFInfo? strengthenRefType_ f (RFun x1 i1 t1 t1' r1) (RFun x2 i2 t2 t2' r2) + | x2 /= F.dummySymbol = RFun x2 i1{permitTC = getFirst b} t t' (r1 `meet` r2) where t = strengthenRefType_ f t1 t2 t' = strengthenRefType_ f (subst1 t1' (x1, EVar x2)) t2' b = First (permitTC i1) <> First (permitTC i2) +strengthenRefType_ f (RFun x1 i1 t1 t1' r1) (RFun x2 i2 t2 t2' r2) + = RFun x1 i1{permitTC = getFirst b} t t' (r1 `meet` r2) + where t = strengthenRefType_ f t1 t2 + t' = strengthenRefType_ f t1' (subst1 t2' (x2, EVar x1)) + b = First (permitTC i1) <> First (permitTC i2) + strengthenRefType_ f (RApp tid t1s rs1 r1) (RApp _ t2s rs2 r2) = RApp tid ts rs (r1 `meet` r2) where ts = zipWith (strengthenRefType_ f) t1s t2s @@ -1033,7 +1040,7 @@ subsTyVars -> t (tv, RType c tv (), RType c tv r) -> RType c tv r -> RType c tv r -subsTyVars meet ats t = foldl' (flip (subsTyVar meet)) t ats +subsTyVars meet' ats t = foldl' (flip (subsTyVar meet')) t ats subsTyVar :: (Eq tv, Hashable tv, Reftable r, TyConable c, @@ -1045,7 +1052,7 @@ subsTyVar -> (tv, RType c tv (), RType c tv r) -> RType c tv r -> RType c tv r -subsTyVar meet = subsFree meet S.empty +subsTyVar meet' = subsFree meet' S.empty subsFree :: (Eq tv, Hashable tv, Reftable r, TyConable c, @@ -1071,9 +1078,9 @@ subsFree m s z@(α, τ, _) (RApp c ts rs r) = RApp c' (subsFree m s z <$> ts) (subsFreeRef m s z <$> rs) (subt (α, τ) r) where z' = (α, τ) -- UNIFY: why instantiating INSIDE parameters? c' = if α `S.member` s then c else subt z' c -subsFree meet s (α', τ, t') (RVar α r) +subsFree meet' s (α', τ, t') (RVar α r) | α == α' && not (α `S.member` s) - = if meet then t' `strengthen` subt (α, τ) r else t' + = if meet' then t' `strengthen` subt (α, τ) r else t' | otherwise = RVar (subt (α', τ) α) r subsFree m s z (RAllE x t t') @@ -1318,7 +1325,7 @@ instance (SubsTy tv ty ty) => SubsTy tv ty (PVKind ty) where subt _ PVHProp = PVHProp instance (SubsTy tv ty ty) => SubsTy tv ty (PVar ty) where - subt su (PV n t v xts) = PV n (subt su t) v [(subt su t, x, y) | (t,x,y) <- xts] + subt su (PV n pvk v xts) = PV n (subt su pvk) v [(subt su t, x, y) | (t,x,y) <- xts] instance SubsTy RTyVar RSort RTyCon where subt z c = RTyCon tc ps' i @@ -1574,9 +1581,9 @@ rTypeSort tce = typeSort tce . toType True -------------------------------------------------------------------------------- applySolution :: (Functor f) => FixSolution -> f SpecType -> f SpecType -------------------------------------------------------------------------------- -applySolution = fmap . fmap . mapReft . appSolRefa +applySolution = fmap . fmap . mapReft' . appSolRefa where - mapReft f (MkUReft (Reft (x, z)) p) = MkUReft (Reft (x, f z)) p + mapReft' f (MkUReft (Reft (x, z)) p) = MkUReft (Reft (x, f z)) p appSolRefa :: Visitable t => M.HashMap KVar Expr -> t -> t @@ -1664,7 +1671,7 @@ typeSortForAll tce τ = F.notracepp ("typeSortForall " ++ showpp τ) $ genSort where sbody = typeSort tce tbody genSort t = foldl' (flip FAbs) (sortSubst su t) [i..n+i-1] - (as, tbody) = F.notracepp ("splitForallTys" ++ GM.showPpr τ) (splitForAllTys τ) + (as, tbody) = F.notracepp ("splitForallTys" ++ GM.showPpr τ) (splitForAllTyCoVars τ) su = M.fromList $ zip sas (FVar <$> [i..]) sas = symbol <$> as n = length as @@ -1701,28 +1708,57 @@ grabArgs τs τ expandProductType :: (PPrint r, Reftable r, SubsTy RTyVar (RType RTyCon RTyVar ()) r, Reftable (RTProp RTyCon RTyVar r)) => Var -> RType RTyCon RTyVar r -> RType RTyCon RTyVar r expandProductType x t - | isTrivial = t + | isTrivial' = t | otherwise = fromRTypeRep $ trep {ty_binds = xs', ty_info=is', ty_args = ts', ty_refts = rs'} where - isTrivial = ofType (varType x) == toRSort t - τs = map irrelevantMult $ fst $ splitFunTys $ snd $ splitForAllTys $ toType False t + isTrivial' = ofType (varType x) == toRSort t + τs = map irrelevantMult $ fst $ splitFunTys $ snd $ splitForAllTyCoVars $ toType False t trep = toRTypeRep t (xs',is',ts',rs') = unzip4 $ concatMap mkProductTy $ zip5 τs (ty_binds trep) (ty_info trep) (ty_args trep) (ty_refts trep) -- splitFunTys :: Type -> ([Type], Type) +data DataConAppContext + = DataConAppContext + { dcac_dc :: !DataCon + , dcac_tys :: ![Type] + , dcac_arg_tys :: ![(Type, StrictnessMark)] + , dcac_co :: !Coercion + } mkProductTy :: forall t r. (Monoid t, Monoid r) => (Type, Symbol, RFInfo, RType RTyCon RTyVar r, t) -> [(Symbol, RFInfo, RType RTyCon RTyVar r, t)] -mkProductTy (τ, x, i, t, r) = maybe [(x, i, t, r)] f $ do - DataConAppContext{..} <- deepSplitProductType_maybe menv τ - pure (dcac_dc, dcac_tys, map (first irrelevantMult) dcac_arg_tys, dcac_co) +mkProductTy (τ, x, i, t, r) = maybe [(x, i, t, r)] f (deepSplitProductType menv τ) where - f :: (DataCon, [Type], [(Type, StrictnessMark)], Coercion) -> [(Symbol, RFInfo, RType RTyCon RTyVar r, t)] - f = map ((dummySymbol, defRFInfo, , mempty) . ofType . fst) . third4 + f :: DataConAppContext -> [(Symbol, RFInfo, RType RTyCon RTyVar r, t)] + f DataConAppContext{..} = map ((dummySymbol, defRFInfo, , mempty) . ofType . fst) dcac_arg_tys menv = (emptyFamInstEnv, emptyFamInstEnv) +-- Copied from GHC 9.0.2. +orElse :: Maybe a -> a -> a +orElse = flip fromMaybe + +-- Copied from GHC 9.0.2. +deepSplitProductType :: FamInstEnvs -> Type -> Maybe DataConAppContext +-- If deepSplitProductType_maybe ty = Just (dc, tys, arg_tys, co) +-- then dc @ tys (args::arg_tys) :: rep_ty +-- co :: ty ~ rep_ty +-- Why do we return the strictness of the data-con arguments? +-- Answer: see Note [Record evaluated-ness in worker/wrapper] +deepSplitProductType fam_envs ty + | let (co, ty1) = topNormaliseType_maybe fam_envs ty + `orElse` (mkRepReflCo ty, ty) + , Just (tc, tc_args) <- splitTyConApp_maybe ty1 + , Just con <- tyConSingleDataCon_maybe tc + , let arg_tys = dataConInstArgTys con tc_args + strict_marks = dataConRepStrictness con + = Just DataConAppContext { dcac_dc = con + , dcac_tys = tc_args + , dcac_arg_tys = zipEqual "dspt" (map irrelevantMult arg_tys) strict_marks + , dcac_co = co } +deepSplitProductType _ _ = Nothing + ----------------------------------------------------------------------------------------- -- | Binders generated by class predicates, typically for constraining tyvars (e.g. FNum) ----------------------------------------------------------------------------------------- @@ -1781,11 +1817,11 @@ mkDType :: Symbolic a mkDType autoenv xvs acc [(v, (x, t))] = Left ((x, ) $ t `strengthen` tr) where - tr = uTop $ Reft (vv, pOr (r:acc)) - r = cmpLexRef xvs (v', vv, f) - v' = symbol v - f = mkDecrFun autoenv t - vv = "vvRec" + tr = uTop $ Reft (vv', pOr (r:acc)) + r = cmpLexRef xvs (v', vv', f) + v' = symbol v + f = mkDecrFun autoenv t + vv' = "vvRec" mkDType autoenv xvs acc ((v, (x, t)):vxts) = mkDType autoenv ((v', x, f):xvs) (r:acc) vxts @@ -1822,10 +1858,10 @@ cmpLexRef vxs (v, x, g) where zero = ECon $ I 0 makeLexRefa :: [Located Expr] -> [Located Expr] -> UReft Reft -makeLexRefa es' es = uTop $ Reft (vv, PIff (EVar vv) $ pOr rs) +makeLexRefa es' es = uTop $ Reft (vv', PIff (EVar vv') $ pOr rs) where - rs = makeLexReft [] [] (val <$> es) (val <$> es') - vv = "vvRec" + rs = makeLexReft [] [] (val <$> es) (val <$> es') + vv' = "vvRec" makeLexReft :: [(Expr, Expr)] -> [Expr] -> [Expr] -> [Expr] -> [Expr] makeLexReft _ acc [] [] @@ -1882,7 +1918,7 @@ ppVars :: (PPrint a) => Tidy -> [a] -> Doc ppVars k as = "forall" <+> hcat (punctuate " " (F.pprintTidy k <$> as)) <+> "." ppFields :: (PPrint k, PPrint v) => Tidy -> Doc -> [(k, v)] -> Doc -ppFields k sep kvs = hcat $ punctuate sep (F.pprintTidy k <$> kvs) +ppFields k sep' kvs = hcat $ punctuate sep' (F.pprintTidy k <$> kvs) ppMbSizeFun :: Maybe SizeFun -> Doc ppMbSizeFun Nothing = "" @@ -1912,8 +1948,8 @@ tyVarsPosition :: RType RTyCon tv r -> Positions tv tyVarsPosition = go (Just True) where go p (RVar t _) = report p t - go p (RFun _ _ t1 t2 _) = go (flip p) t1 <> go p t2 - go p (RImpF _ _ t1 t2 _) = go (flip p) t1 <> go p t2 + go p (RFun _ _ t1 t2 _) = go (flip' p) t1 <> go p t2 + go p (RImpF _ _ t1 t2 _) = go (flip' p) t1 <> go p t2 go p (RAllT _ t _) = go p t go p (RAllP _ t) = go p t go p (RApp c ts _ _) = mconcat (zipWith go (getPosition p <$> varianceTyArgs (rtc_info c)) ts) @@ -1931,7 +1967,7 @@ tyVarsPosition = go (Just True) report Nothing v = Pos [] [] [v] report (Just True) v = Pos [v] [] [] report (Just False) v = Pos [] [v] [] - flip = fmap not + flip' = fmap not data Positions a = Pos {ppos :: [a], pneg :: [a], punknown :: [a]} diff --git a/src/Language/Haskell/Liquid/Types/Specs.hs b/src/Language/Haskell/Liquid/Types/Specs.hs index 9ca12b19af..8c7f0ae698 100644 --- a/src/Language/Haskell/Liquid/Types/Specs.hs +++ b/src/Language/Haskell/Liquid/Types/Specs.hs @@ -155,8 +155,7 @@ instance HasConfig TargetInfo where -- information (for example, 'giDefVars' are populated with datacons from the module plus the -- let vars derived from the A-normalisation). data TargetSrc = TargetSrc - { giIncDir :: !FilePath -- ^ Path for LH include/prelude directory - , giTarget :: !FilePath -- ^ Source file for module + { giTarget :: !FilePath -- ^ Source file for module , giTargetMod :: !ModName -- ^ Name for module , giCbs :: ![CoreBind] -- ^ Source Code , gsTcs :: ![TyCon] -- ^ All used Type constructors @@ -694,8 +693,7 @@ data GhcInfo = GI -} data GhcSrc = Src - { _giIncDir :: !FilePath -- ^ Path for LH include/prelude directory - , _giTarget :: !FilePath -- ^ Source file for module + { _giTarget :: !FilePath -- ^ Source file for module , _giTargetMod :: !ModName -- ^ Name for module , _giCbs :: ![CoreBind] -- ^ Source Code , _gsTcs :: ![TyCon] -- ^ All used Type constructors @@ -741,8 +739,7 @@ targetSrcIso :: Iso' GhcSrc TargetSrc targetSrcIso = iso toTargetSrc fromTargetSrc where toTargetSrc a = TargetSrc - { giIncDir = _giIncDir a - , giTarget = _giTarget a + { giTarget = _giTarget a , giTargetMod = _giTargetMod a , giCbs = _giCbs a , gsTcs = _gsTcs a @@ -761,8 +758,7 @@ targetSrcIso = iso toTargetSrc fromTargetSrc } fromTargetSrc a = Src - { _giIncDir = giIncDir a - , _giTarget = giTarget a + { _giTarget = giTarget a , _giTargetMod = giTargetMod a , _giCbs = giCbs a , _gsTcs = gsTcs a diff --git a/src/Language/Haskell/Liquid/Types/Types.hs b/src/Language/Haskell/Liquid/Types/Types.hs index 601bc4eb71..4a54c34132 100644 --- a/src/Language/Haskell/Liquid/Types/Types.hs +++ b/src/Language/Haskell/Liquid/Types/Types.hs @@ -12,7 +12,6 @@ {-# LANGUAGE DerivingVia #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} -- | This module should contain all the global type definitions and basic instances. @@ -143,7 +142,7 @@ module Language.Haskell.Liquid.Types.Types ( , AnnInfo (..) , Annot (..) - -- * Hole Information + -- * Hole Information , HoleInfo(..) -- * Overall Output @@ -238,7 +237,7 @@ module Language.Haskell.Liquid.Types.Types ( -- , rtyVarUniqueSymbol, tyVarUniqueSymbol , rtyVarType, tyVarVar - -- * Refined Function Info + -- * Refined Function Info , RFInfo(..), defRFInfo, mkRFInfo, classRFInfo, classRFInfoType , ordSrcSpan @@ -248,7 +247,6 @@ module Language.Haskell.Liquid.Types.Types ( import Liquid.GHC.API as Ghc hiding ( Expr , Target , isFunTy - , LM , ($+$) , nest , text @@ -321,9 +319,9 @@ type BScope = Bool -- | Information about Type Constructors ----------------------------------------------------------------------------- data TyConMap = TyConMap - { tcmTyRTy :: M.HashMap TyCon RTyCon -- ^ Map from GHC TyCon to RTyCon + { tcmTyRTy :: M.HashMap TyCon RTyCon -- ^ Map from GHC TyCon to RTyCon , tcmFIRTy :: M.HashMap (TyCon, [F.Sort]) RTyCon -- ^ Map from GHC Family-Instances to RTyCon - , tcmFtcArity :: M.HashMap TyCon Int -- ^ Arity of each Family-Tycon + , tcmFtcArity :: M.HashMap TyCon Int -- ^ Arity of each Family-Tycon } @@ -353,9 +351,9 @@ instance B.Binary RFInfo ----------------------------------------------------------------------------- data PPEnv = PP - { ppPs :: Bool -- ^ print abstract-predicates + { ppPs :: Bool -- ^ print abstract-predicates , ppTyVar :: Bool -- ^ print the unique suffix for each tyvar - , ppShort :: Bool -- ^ print the tycons without qualification + , ppShort :: Bool -- ^ print the tycons without qualification , ppDebug :: Bool -- ^ gross with full info } deriving (Show) @@ -419,7 +417,7 @@ toLogicMap ls = mempty {lmSymDefs = M.fromList $ map toLMap ls} toLMap (x, ys, e) = (F.val x, LMap {lmVar = x, lmArgs = ys, lmExpr = e}) eAppWithMap :: LogicMap -> F.Located Symbol -> [Expr] -> Expr -> Expr -eAppWithMap lmap f es def +eAppWithMap lmap f es expr | Just (LMap _ xs e) <- M.lookup (F.val f) (lmSymDefs lmap) , length xs == length es = F.subst (F.mkSubst $ zip xs es) e @@ -427,7 +425,7 @@ eAppWithMap lmap f es def , isApp e = F.subst (F.mkSubst $ zip xs es) $ dropApp e (length xs - length es) | otherwise - = def + = expr dropApp :: Expr -> Int -> Expr dropApp e i | i <= 0 = e @@ -456,7 +454,7 @@ instance F.Loc TyConP where -- TODO: just use Located instead of dc_loc, dc_locE data DataConP = DataConP { dcpLoc :: !F.SourcePos - , dcpCon :: !DataCon -- ^ Corresponding GHC DataCon + , dcpCon :: !DataCon -- ^ Corresponding GHC DataCon , dcpFreeTyVars :: ![RTyVar] -- ^ Type parameters , dcpFreePred :: ![PVar RSort] -- ^ Abstract Refinement parameters , dcpTyConstrs :: ![SpecType] -- ^ ? Class constraints (via `dataConStupidTheta`) @@ -882,9 +880,9 @@ data RTVInfo s | RTVInfo { rtv_name :: Symbol , rtv_kind :: s , rtv_is_val :: Bool - , rtv_is_pol :: Bool -- true iff the type variable gets instantiated with - -- any refinement (ie is polymorphic on refinements), - -- false iff instantiation is with true refinement + , rtv_is_pol :: Bool -- true iff the type variable gets instantiated with + -- any refinement (ie is polymorphic on refinements), + -- false iff instantiation is with true refinement } deriving (Generic, Data, Typeable, Functor) deriving Hashable via Generically (RTVInfo s) @@ -1231,7 +1229,7 @@ data DataCtor = DataCtor { dcName :: F.LocSymbol -- ^ DataCon name , dcTyVars :: [F.Symbol] -- ^ Type parameters , dcTheta :: [BareType] -- ^ The GHC ThetaType corresponding to DataCon.dataConSig - , dcFields :: [(Symbol, BareType)] -- ^ field-name and field-Type pairs + , dcFields :: [(Symbol, BareType)] -- ^ field-name and field-Type pairs , dcResult :: Maybe BareType -- ^ Possible output (if in GADT form) } deriving (Data, Typeable, Generic) deriving Hashable via Generically DataCtor @@ -1399,7 +1397,7 @@ mkArrow :: [(RTVar tv (RType c tv ()), r)] -> [(Symbol, RFInfo, RType c tv r, r)] -> RType c tv r -> RType c tv r -mkArrow αs πs yts xts = mkUnivs αs πs . mkArrs RImpF yts. mkArrs RFun xts +mkArrow αs πs yts zts = mkUnivs αs πs . mkArrs RImpF yts . mkArrs RFun zts where mkArrs f xts t = foldr (\(b,i,t1,r) t2 -> f b i t1 t2 r) t xts @@ -1441,7 +1439,7 @@ mkUnivs :: (Foldable t, Foldable t1) -> t1 (PVar (RType c tv ())) -> RType c tv r -> RType c tv r -mkUnivs αs πs t = foldr (\(a,r) t -> RAllT a t r) (foldr RAllP t πs) αs +mkUnivs αs πs rt = foldr (\(a,r) t -> RAllT a t r) (foldr RAllP rt πs) αs bkUnivClass :: SpecType -> ([(SpecRTVar, RReft)],[PVar RSort], [(RTyCon, [SpecType])], SpecType ) bkUnivClass t = (as, ps, cs, t2) @@ -2071,8 +2069,8 @@ allErrors = dErrors -- | Printing Warnings --------------------------------------------------------- -------------------------------------------------------------------------------- -printWarning :: DynFlags -> Warning -> IO () -printWarning dyn (Warning span doc) = GHC.putWarnMsg dyn span doc +printWarning :: Logger -> DynFlags -> Warning -> IO () +printWarning logger dyn (Warning srcSpan doc) = GHC.putWarnMsg logger dyn srcSpan doc -------------------------------------------------------------------------------- -- | Error Data Type ----------------------------------------------------------- @@ -2088,11 +2086,12 @@ instance NFData a => NFData (TError a) -- | Source Information Associated With Constraints ---------------------------- -------------------------------------------------------------------------------- -data Cinfo = Ci { ci_loc :: !SrcSpan - , ci_err :: !(Maybe Error) - , ci_var :: !(Maybe Var) - } - deriving (Eq, Generic) +data Cinfo = Ci + { ci_loc :: !SrcSpan + , ci_err :: !(Maybe Error) + , ci_var :: !(Maybe Var) + } + deriving (Eq, Generic) instance F.Loc Cinfo where srcSpan = srcSpanFSrcSpan . ci_loc @@ -2109,8 +2108,8 @@ data ModName = ModName !ModType !ModuleName data ModType = Target | SrcImport | SpecImport deriving (Eq, Ord, Show, Generic, Data, Typeable) --- instance B.Binary ModType --- instance B.Binary ModName +-- instance B.Binary ModType +-- instance B.Binary ModName instance Hashable ModType @@ -2166,7 +2165,7 @@ instance Monoid (RTEnv tv t) where instance Semigroup (RTEnv tv t) where RTE x y <> RTE x' y' = RTE (x `M.union` x') (y `M.union` y') --- mapRT :: (M.HashMap Symbol (RTAlias tv t) -> M.HashMap Symbol (RTAlias tv t)) +-- mapRT :: (M.HashMap Symbol (RTAlias tv t) -> M.HashMap Symbol (RTAlias tv t)) -- -> RTEnv tv t -> RTEnv tv t -- mapRT f e = e { typeAliases = f (typeAliases e) } @@ -2208,13 +2207,13 @@ type UnSortedExprs = [UnSortedExpr] -- mempty = [] type UnSortedExpr = ([F.Symbol], F.Expr) data MeasureKind - = MsReflect -- ^ due to `reflect foo` + = MsReflect -- ^ due to `reflect foo` | MsMeasure -- ^ due to `measure foo` with old-style (non-haskell) equations | MsLifted -- ^ due to `measure foo` with new-style haskell equations - | MsClass -- ^ due to `class measure` definition + | MsClass -- ^ due to `class measure` definition | MsAbsMeasure -- ^ due to `measure foo` without equations c.f. tests/pos/T1223.hs - | MsSelector -- ^ due to selector-fields e.g. `data Foo = Foo { fld :: Int }` - | MsChecker -- ^ due to checkers e.g. `is-F` for `data Foo = F ... | G ...` + | MsSelector -- ^ due to selector-fields e.g. `data Foo = Foo { fld :: Int }` + | MsChecker -- ^ due to checkers e.g. `is-F` for `data Foo = F ... | G ...` deriving (Eq, Ord, Show, Data, Typeable, Generic) deriving Hashable via Generically MeasureKind @@ -2326,7 +2325,7 @@ instance F.PPrint t => F.PPrint (RClass t) where = ppMethods k ("class" <+> supers ts) n as [(m, RISig t) | (m, t) <- mts] where supers [] = "" - supers ts = tuplify (F.pprintTidy k <$> ts) <+> "=>" + supers xs = tuplify (F.pprintTidy k <$> xs) <+> "=>" tuplify = parens . hcat . punctuate ", " @@ -2334,7 +2333,7 @@ instance F.PPrint t => F.PPrint (RILaws t) where pprintTidy k (RIL n ss ts mts _) = ppEqs k ("instance laws" <+> supers ss) n ts mts where supers [] = "" - supers ts = tuplify (F.pprintTidy k <$> ts) <+> "=>" + supers xs = tuplify (F.pprintTidy k <$> xs) <+> "=>" tuplify = parens . hcat . punctuate ", " @@ -2358,7 +2357,7 @@ ppMethods k hdr name args mts dName = parens (F.pprintTidy k name <+> dArgs) dArgs = gaps (F.pprintTidy k <$> args) gaps = hcat . punctuate " " - bind m t = ppRISig k m t -- F.pprintTidy k m <+> "::" <+> F.pprintTidy k t + bind m t = ppRISig k m t -- F.pprintTidy k m <+> "::" <+> F.pprintTidy k t instance B.Binary ty => B.Binary (RClass ty) @@ -2508,8 +2507,8 @@ instance F.PPrint TyThing where instance Show DataCon where show = F.showpp --- instance F.Symbolic TyThing where --- symbol = tyThingSymbol +-- instance F.Symbolic TyThing where +-- symbol = tyThingSymbol liquidBegin :: String liquidBegin = ['{', '-', '@'] diff --git a/src/Language/Haskell/Liquid/Types/Variance.hs b/src/Language/Haskell/Liquid/Types/Variance.hs index 0ad27550b3..991aef0bd8 100644 --- a/src/Language/Haskell/Liquid/Types/Variance.hs +++ b/src/Language/Haskell/Liquid/Types/Variance.hs @@ -4,7 +4,6 @@ {-# OPTIONS_GHC -Wno-incomplete-patterns #-} -- TODO(#1918): Only needed for GHC <9.0.1. {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Types.Variance ( Variance(..), VarianceInfo, makeTyConVariance, flipVariance @@ -60,13 +59,13 @@ instance F.PPrint Variance where makeTyConVariance :: TyCon -> VarianceInfo -makeTyConVariance c = varSignToVariance <$> tvs +makeTyConVariance tyCon = varSignToVariance <$> tvs where - tvs = GM.tyConTyVarsDef c + tvs = GM.tyConTyVarsDef tyCon - varsigns = if Ghc.isTypeSynonymTyCon c - then go True (fromJust $ Ghc.synTyConRhs_maybe c) - else L.nub $ concatMap goDCon $ Ghc.tyConDataCons c + varsigns = if Ghc.isTypeSynonymTyCon tyCon + then go True (fromJust $ Ghc.synTyConRhs_maybe tyCon) + else L.nub $ concatMap goDCon $ Ghc.tyConDataCons tyCon varSignToVariance v = case filter (\p -> GM.showPpr (fst p) == GM.showPpr v) varsigns of [] -> Invariant @@ -81,13 +80,13 @@ makeTyConVariance c = varSignToVariance <$> tvs go pos (TyVarTy v) = [(v, pos)] go pos (AppTy t1 t2) = go pos t1 ++ go pos t2 go pos (TyConApp c' ts) - | c == c' + | tyCon == c' = [] -- NV fix that: what happens if we have mutually recursive data types? -- now just provide "default" Bivariant for mutually rec types. -- but there should be a finer solution - | mutuallyRecursive c c' + | mutuallyRecursive tyCon c' = concatMap (goTyConApp pos Bivariant) ts | otherwise = concat $ zipWith (goTyConApp pos) (makeTyConVariance c') ts diff --git a/src/Language/Haskell/Liquid/Types/Visitors.hs b/src/Language/Haskell/Liquid/Types/Visitors.hs index ba6cf419ac..5055661824 100644 --- a/src/Language/Haskell/Liquid/Types/Visitors.hs +++ b/src/Language/Haskell/Liquid/Types/Visitors.hs @@ -2,7 +2,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} module Language.Haskell.Liquid.Types.Visitors ( @@ -123,16 +122,17 @@ exprLiterals = go go' _ = [] + tyLitToLit (CharTyLit c) = LitChar c tyLitToLit (StrTyLit fs) = LitString (bytesFS fs) tyLitToLit (NumTyLit i) = LitNumber LitNumInt (fromIntegral i) intPrimTy instance CBVisitable (Alt Var) where - freeVars env (a, xs, e) = freeVars env a ++ freeVars (extendEnv env xs) e - readVars (_,_, e) = readVars e - letVars (_,xs,e) = xs ++ letVars e - literals (c,_, e) = literals c ++ literals e + freeVars env (Alt a xs e) = freeVars env a ++ freeVars (extendEnv env xs) e + readVars (Alt _ _ e) = readVars e + letVars (Alt _ xs e) = xs ++ letVars e + literals (Alt c _ e) = literals c ++ literals e instance CBVisitable AltCon where freeVars _ (DataAlt dc) = [ x | AnId x <- dataConImplicitTyThings dc] @@ -159,7 +159,7 @@ data CoreVisitor env acc = CoreVisitor } coreVisitor :: CoreVisitor env acc -> env -> acc -> [CoreBind] -> acc -coreVisitor vis env acc cbs = snd (foldl' step (env, acc) cbs) +coreVisitor vis cenv cacc cbs = snd (foldl' step (cenv, cacc) cbs) where stepXE (env, acc) (x,e) = (env', stepE env' acc' e) where @@ -189,7 +189,7 @@ coreVisitor vis env acc cbs = snd (foldl' step (env, acc) cbs) goE env acc (Case e _ _ cs) = foldl' (goC env) (stepE env acc e) cs goE _ acc _ = acc - goC env acc (_, xs, e) = stepE env' acc' e + goC env acc (Alt _ xs e) = stepE env' acc' e where env' = foldl' (envF vis) env xs acc' = foldl' (bindF vis env) acc xs diff --git a/src/Language/Haskell/Liquid/UX/ACSS.hs b/src/Language/Haskell/Liquid/UX/ACSS.hs index 000292644a..c2e54c810e 100644 --- a/src/Language/Haskell/Liquid/UX/ACSS.hs +++ b/src/Language/Haskell/Liquid/UX/ACSS.hs @@ -1,4 +1,4 @@ -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- | Formats Haskell source code as HTML with CSS and Mouseover Type Annotations module Language.Haskell.Liquid.UX.ACSS ( @@ -97,11 +97,11 @@ annotTokenise baseLoc tx (src, annm) = zipWith (\(x,y) z -> (x,y,z)) toks annots linWidth = length $ show $ length $ lines src spanAnnot :: Int -> AnnMap -> Loc -> Annotation -spanAnnot w (Ann ts es _ _) span = A t e b +spanAnnot w (Ann ts es _ _) loc = A t e b where - t = fmap snd (M.lookup span ts) - e = "ERROR" <$ find (span `inRange`) [(x,y) | (x,y,_) <- es] - b = spanLine w span + t = fmap snd (M.lookup loc ts) + e = "ERROR" <$ find (loc `inRange`) [(x,y) | (x,y,_) <- es] + b = spanLine w loc spanLine :: t -> Loc -> Maybe (Int, t) spanLine w (L (l, c)) @@ -114,7 +114,7 @@ inRange (L (l0, c0)) (L (l, c), L (l', c')) tokeniseWithCommentTransform :: Maybe (String -> [(TokenType, String)]) -> String -> [(TokenType, String)] tokeniseWithCommentTransform Nothing = tokenise -tokeniseWithCommentTransform (Just f) = concatMap (expand f) . tokenise +tokeniseWithCommentTransform (Just g) = concatMap (expand g) . tokenise where expand f (Comment, s) = f s expand _ z = [z] @@ -261,7 +261,7 @@ data Lit = Code {unL :: String} | Lit {unL :: String} deriving (Show) -- Also, importantly, accepts non-standard DOS and Mac line ending characters. -- And retains the trailing '\n' character in each resultant string. inlines :: String -> [String] -inlines s = lines' s id +inlines str = lines' str id where lines' [] acc = [acc []] lines' ('\^M':'\n':s) acc = acc ['\n'] : lines' s id -- DOS @@ -296,4 +296,4 @@ joinL :: [Lit] -> [Lit] joinL [] = [] joinL (Code c:Code c2:xs) = joinL (Code (c++c2):xs) joinL (Lit c :Lit c2 :xs) = joinL (Lit (c++c2):xs) -joinL (any:xs) = any: joinL xs +joinL (lit:xs) = lit: joinL xs diff --git a/src/Language/Haskell/Liquid/UX/Annotate.hs b/src/Language/Haskell/Liquid/UX/Annotate.hs index 725d8def32..f08639d2c7 100644 --- a/src/Language/Haskell/Liquid/UX/Annotate.hs +++ b/src/Language/Haskell/Liquid/UX/Annotate.hs @@ -4,7 +4,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} --------------------------------------------------------------------------- -- | This module contains the code that uses the inferred types to generate @@ -51,7 +50,7 @@ import qualified Data.Vector as V import qualified Data.ByteString.Lazy as B import qualified Data.Text as T import qualified Data.HashMap.Strict as M -import qualified Language.Haskell.Liquid.Misc as Misc +import qualified Language.Haskell.Liquid.Misc as Misc import qualified Language.Haskell.Liquid.UX.ACSS as ACSS import Language.Haskell.HsColour.Classify import Language.Fixpoint.Utils.Files @@ -112,7 +111,7 @@ doGenerate cfg tplAnnMap typAnnMap annTyp srcF writeFile vimF $ vimAnnot cfg annTyp B.writeFile jsonF $ encode typAnnMap where - pandocF = pandocHtml cfg + pandocF = pandocHtml cfg tyHtmlF = extFileName Html srcF tpHtmlF = extFileName Html $ extFileName Cst srcF _annF = extFileName Annot srcF @@ -123,7 +122,7 @@ mkBots :: Reftable r => AnnInfo (RType c tv r) -> [GHC.SrcSpan] mkBots (AI m) = [ src | (src, (Just _, t) : _) <- sortBy (ordSrcSpan `on` fst) $ M.toList m , isFalse (rTypeReft t) ] --- | Like 'copyFile' from 'System.Directory', but ensure that the parent /temporary/ directory +-- | Like 'copyFile' from 'System.Directory', but ensure that the parent /temporary/ directory -- (i.e. \".liquid\") exists on disk, creating it if necessary. copyFileCreateParentDirIfMissing :: FilePath -> FilePath -> IO () copyFileCreateParentDirIfMissing src tgt = do @@ -134,7 +133,7 @@ writeFilesOrStrings :: FilePath -> [Either FilePath String] -> IO () writeFilesOrStrings tgtFile = mapM_ $ either (`copyFileCreateParentDirIfMissing` tgtFile) (tgtFile `appendFile`) generateHtml :: Bool -> FilePath -> FilePath -> ACSS.AnnMap -> IO () -generateHtml pandocF srcF htmlF annm = do +generateHtml pandocF srcF htmlF annm = do src <- Misc.sayReadFile srcF let lhs = isExtFile LHs srcF let body = {-# SCC "hsannot" #-} ACSS.hsannot False (Just tokAnnot) lhs (src, annm) @@ -237,10 +236,10 @@ cssHTML css = unlines -- annotations. mkAnnMap :: Config -> ErrorResult -> AnnInfo Doc -> ACSS.AnnMap -mkAnnMap cfg res ann = ACSS.Ann - { ACSS.types = mkAnnMapTyp cfg ann - , ACSS.errors = mkAnnMapErr res - , ACSS.status = mkStatus res +mkAnnMap cfg res ann = ACSS.Ann + { ACSS.types = mkAnnMapTyp cfg ann + , ACSS.errors = mkAnnMapErr res + , ACSS.status = mkStatus res , ACSS.sptypes = mkAnnMapBinders cfg ann } @@ -254,7 +253,7 @@ mkStatus (Crash _ _) = ACSS.Error mkAnnMapErr :: PPrint (TError t) => FixResult (TError t) -> [(Loc, Loc, String)] mkAnnMapErr (Unsafe _ ls) = mapMaybe cinfoErr ls -mkAnnMapErr (Crash ls _) = mapMaybe cinfoErr ls +mkAnnMapErr (Crash ls _) = mapMaybe (cinfoErr . fst) ls mkAnnMapErr _ = [] cinfoErr :: PPrint (TError t) => TError t -> Maybe (Loc, Loc, String) @@ -427,7 +426,7 @@ instance ToJSON Loc where , "column" .= toJSON c ] instance ToJSON AnnErrors where - toJSON (AnnErrors errs) = Array $ V.fromList (toJ <$> errs) + toJSON (AnnErrors errors) = Array $ V.fromList (toJ <$> errors) where toJ (l,l',s) = object [ "start" .= toJSON l , "stop" .= toJSON l' @@ -445,32 +444,32 @@ dropErrorLoc msg (_, msg') = break (' ' ==) msg instance (Show k, ToJSON a) => ToJSON (Assoc k a) where - toJSON (Asc kas) = object [ tshow k .= toJSON a | (k, a) <- M.toList kas ] + toJSON (Asc kas) = object [ tshow' k .= toJSON a | (k, a) <- M.toList kas ] where - tshow = fromString . show + tshow' = fromString . show instance ToJSON ACSS.AnnMap where toJSON a = object [ "types" .= toJSON (annTypes a) , "errors" .= toJSON (annErrors a) , "status" .= toJSON (ACSS.status a) - , "sptypes" .= (toJ <$> ACSS.sptypes a) + , "sptypes" .= (toJ <$> ACSS.sptypes a) ] - where - toJ (sp, (x,t)) = object [ "start" .= toJSON (srcSpanStartLoc sp) - , "stop" .= toJSON (srcSpanEndLoc sp) - , "ident" .= toJSON x - , "ann" .= toJSON t - ] - + where + toJ (sp, (x,t)) = object [ "start" .= toJSON (srcSpanStartLoc sp) + , "stop" .= toJSON (srcSpanEndLoc sp) + , "ident" .= toJSON x + , "ann" .= toJSON t + ] + annErrors :: ACSS.AnnMap -> AnnErrors annErrors = AnnErrors . ACSS.errors annTypes :: ACSS.AnnMap -> AnnTypes -annTypes a = grp [(l, c, ann1 l c x s) | (l, c, x, s) <- binders] +annTypes a = grp [(l, c, ann1 l c x s) | (l, c, x, s) <- binders'] where ann1 l c x s = A1 x s l c grp = L.foldl' (\m (r,c,x) -> ins r c x m) (Asc M.empty) - binders = [(l, c, x, s) | (L (l, c), (x, s)) <- M.toList $ ACSS.types a] + binders' = [(l, c, x, s) | (L (l, c), (x, s)) <- M.toList $ ACSS.types a] ins :: (Eq k, Eq k1, Hashable k, Hashable k1) => k -> k1 -> a -> Assoc k (Assoc k1 a) -> Assoc k (Assoc k1 a) @@ -499,25 +498,29 @@ tokeniseWithLoc = ACSS.tokeniseWithLoc (Just tokAnnot) -------------------------------------------------------------------------------- _anns :: AnnTypes -_anns = i [(5, i [( 14, A1 { ident = "foo" - , ann = "int -> int" - , row = 5 - , col = 14 - }) - ] - ) - ,(9, i [( 22, A1 { ident = "map" - , ann = "(a -> b) -> [a] -> [b]" - , row = 9 - , col = 22 - }) - ,( 28, A1 { ident = "xs" - , ann = "[b]" - , row = 9 - , col = 28 - }) - ]) - ] - -i :: (Eq k, Hashable k) => [(k, a)] -> Assoc k a -i = Asc . M.fromList +_anns = + mkAssoc + [ (5, mkAssoc + [ ( 14, A1 { ident = "foo" + , ann = "int -> int" + , row = 5 + , col = 14 + }) + ] + ) + , (9, mkAssoc + [ ( 22, A1 { ident = "map" + , ann = "(a -> b) -> [a] -> [b]" + , row = 9 + , col = 22 + }) + , ( 28, A1 { ident = "xs" + , ann = "[b]" + , row = 9 + , col = 28 + }) + ]) + ] + +mkAssoc :: (Eq k, Hashable k) => [(k, a)] -> Assoc k a +mkAssoc = Asc . M.fromList diff --git a/src/Language/Haskell/Liquid/UX/CmdLine.hs b/src/Language/Haskell/Liquid/UX/CmdLine.hs index b3ddff9c5f..c3310eab01 100644 --- a/src/Language/Haskell/Liquid/UX/CmdLine.hs +++ b/src/Language/Haskell/Liquid/UX/CmdLine.hs @@ -9,7 +9,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_GHC -Wwarn=deprecations #-} {-# OPTIONS_GHC -fno-cse #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# LANGUAGE FlexibleContexts #-} -- | This module contains all the code needed to output the result which -- is either: `SAFE` or `WARNING` with some reasonable error message when @@ -78,7 +78,6 @@ import Language.Haskell.Liquid.UX.Annotate import Language.Haskell.Liquid.UX.Config import Language.Haskell.Liquid.UX.SimpleVersion (simpleVersion) import Liquid.GHC.Misc -import Language.Haskell.Liquid.Misc import Language.Haskell.Liquid.Types.PrettyPrint () import Language.Haskell.Liquid.Types hiding (typ) import qualified Language.Haskell.Liquid.UX.ACSS as ACSS @@ -410,10 +409,6 @@ config = cmdArgsMode $ Config { &= name "no-check-imports" &= help "Do not check the transitive imports; only check the target files." - , typedHoles - = def - &= name "typed-holes" - &= help "Use (refinement) typed-holes [currently warns on '_x' variables]" , relationalHints = def &= name "relational-hints" @@ -426,16 +421,6 @@ config = cmdArgsMode $ Config { = def &= help "Enable inlining of class methods" &= name "aux-inline" - , maxMatchDepth - = def - &= name "max-match-depth" - &= help "Define the number of expressions to pattern match on (typed-holes must be on to use this flag)." - , maxAppDepth - = def - &= name "max-app-depth" - , maxArgsDepth - = def - &= name "max-args-depth" , rwTerminationCheck = def @@ -544,9 +529,9 @@ findSmtSolver :: FC.SMTSolver -> IO (Maybe FC.SMTSolver) findSmtSolver smt = maybe Nothing (const $ Just smt) <$> findExecutable (show smt) fixConfig :: Config -> IO Config -fixConfig cfg = do +fixConfig config' = do pwd <- getCurrentDirectory - cfg <- canonicalizePaths pwd cfg + cfg <- canonicalizePaths pwd config' return $ canonConfig cfg -- | Attempt to canonicalize all `FilePath's in the `Config' so we don't have @@ -622,11 +607,8 @@ gitMsg gi = concat mkOpts :: Config -> IO Config mkOpts cfg = do let files' = sortNub $ files cfg - id0 <- getIncludeDir return $ cfg { files = files' -- See NOTE [searchpath] - , idirs = [id0 gHC_VERSION, id0] - ++ idirs cfg } -------------------------------------------------------------------------------- @@ -737,13 +719,9 @@ defConfig = Config , nopolyinfer = False , compileSpec = False , noCheckImports = False - , typedHoles = False , relationalHints = False , typeclass = False , auxInline = False - , maxMatchDepth = 4 - , maxAppDepth = 2 - , maxArgsDepth = 1 , rwTerminationCheck = False , skipModule = False , noLazyPLE = False @@ -796,8 +774,14 @@ reportResultJson annm = do resultWithContext :: F.FixResult UserError -> IO (FixResult CError) resultWithContext (F.Unsafe s es) = F.Unsafe s <$> errorsWithContext es -resultWithContext (F.Crash es s) = (`F.Crash` s) <$> errorsWithContext es resultWithContext (F.Safe stats) = return (F.Safe stats) +resultWithContext (F.Crash es s) = do + let (userErrs, msgs) = unzip es + errs' <- errorsWithContext userErrs + return (F.Crash (zip errs' msgs) s) + + + instance Show (CtxError Doc) where show = showpp @@ -847,7 +831,7 @@ resDocs _k (F.Crash [] s) = } resDocs k (F.Crash xs s) = OutputResult { - orHeader = text "LIQUID: ERROR" <+> text s + orHeader = text "LIQUID: ERROR:" <+> text s , orMessages = map (cErrToSpanned k . errToFCrash) xs } resDocs k (F.Unsafe _ xs) = @@ -860,21 +844,25 @@ resDocs k (F.Unsafe _ xs) = cErrToSpanned :: F.Tidy -> CError -> (GHC.SrcSpan, Doc) cErrToSpanned k CtxError{ctErr} = (pos ctErr, pprintTidy k ctErr) -errToFCrash :: CtxError a -> CtxError a -errToFCrash ce = ce { ctErr = tx $ ctErr ce} +errToFCrash :: (CError, Maybe String) -> CError +errToFCrash (ce, Just msg) = ce { ctErr = ErrOther (pos (ctErr ce)) (fixMessageDoc msg) } +errToFCrash (ce, Nothing) = ce { ctErr = tx $ ctErr ce} where tx (ErrSubType l m _ g t t') = ErrFCrash l m g t t' - tx e = e + tx e = F.notracepp "errToFCrash?" e + +fixMessageDoc :: String -> Doc +fixMessageDoc msg = vcat (text <$> lines msg) {- TODO: Never used, do I need to exist? reportUrl = text "Please submit a bug report at: https://github.com/ucsd-progsys/liquidhaskell" -} addErrors :: FixResult a -> [a] -> FixResult a -addErrors r [] = r -addErrors (Safe s) errs = Unsafe s errs -addErrors (Unsafe s xs) errs = Unsafe s (xs ++ errs) -addErrors r _ = r +addErrors r [] = r +addErrors (Safe s) errors = Unsafe s errors +addErrors (Unsafe s xs) errors = Unsafe s (xs ++ errors) +addErrors r _ = r instance Fixpoint (F.FixResult CError) where toFix = vcat . map snd . orMessages . resDocs F.Full diff --git a/src/Language/Haskell/Liquid/UX/Config.hs b/src/Language/Haskell/Liquid/UX/Config.hs index 87a55c9469..1d8f134d05 100644 --- a/src/Language/Haskell/Liquid/UX/Config.hs +++ b/src/Language/Haskell/Liquid/UX/Config.hs @@ -96,13 +96,9 @@ data Config = Config , reflection :: Bool -- ^ Allow "reflection"; switches on "--higherorder" and "--exactdc" , compileSpec :: Bool -- ^ Only "compile" the spec -- into .bspec file -- don't do any checking. , noCheckImports :: Bool -- ^ Do not check the transitive imports - , typedHoles :: Bool -- ^ Warn about "typed-holes" , relationalHints :: Bool -- ^ Generate unary proofs for relational specs. , typeclass :: Bool -- ^ enable typeclass support. , auxInline :: Bool -- ^ - , maxMatchDepth :: Int - , maxAppDepth :: Int - , maxArgsDepth :: Int , rwTerminationCheck :: Bool -- ^ Enable termination checking for rewriting , skipModule :: Bool -- ^ Skip this module entirely (don't even compile any specs in it) , noLazyPLE :: Bool diff --git a/src/Language/Haskell/Liquid/UX/DiffCheck.hs b/src/Language/Haskell/Liquid/UX/DiffCheck.hs index b338806332..f332c9c606 100644 --- a/src/Language/Haskell/Liquid/UX/DiffCheck.hs +++ b/src/Language/Haskell/Liquid/UX/DiffCheck.hs @@ -6,9 +6,10 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wno-orphans #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Language.Haskell.Liquid.UX.DiffCheck ( @@ -50,7 +51,7 @@ import System.Directory (copyFile, doesFileExist import Language.Fixpoint.Types (atLoc, FixResult (..), SourcePos(..), safeSourcePos, unPos) -- import qualified Language.Fixpoint.Misc as Misc import Language.Fixpoint.Utils.Files -import Language.Fixpoint.Solver.Stats () +import Language.Fixpoint.Solver.Stats () import Language.Haskell.Liquid.Misc (mkGraph) import Liquid.GHC.Misc import Liquid.GHC.API as Ghc hiding ( Located @@ -61,7 +62,7 @@ import Liquid.GHC.API as Ghc hiding ( Located ) import Text.PrettyPrint.HughesPJ (text, render, Doc) import qualified Data.ByteString as B -import qualified Data.ByteString.Lazy as LB +import qualified Data.ByteString.Lazy as LB import Language.Haskell.Liquid.Types hiding (Def, LMap) @@ -70,7 +71,7 @@ import Language.Haskell.Liquid.Types hiding (Def, LMap) -------------------------------------------------------------------------------- -- | Main type of value returned for diff-check. -data DiffCheck = DC +data DiffCheck = DC { newBinds :: [CoreBind] , oldOutput :: !(Output Doc) , newSpec :: !TargetSpec @@ -81,7 +82,7 @@ instance PPrint DiffCheck where -- | Variable definitions -data Def = D +data Def = D { start :: Int -- ^ line at which binder definition starts , end :: Int -- ^ line at which binder definition ends , binder :: Var -- ^ name of binder @@ -116,10 +117,10 @@ checkedVars = concatMap names . newBinds -------------------------------------------------------------------------------- slice :: FilePath -> [CoreBind] -> TargetSpec -> IO (Maybe DiffCheck) -------------------------------------------------------------------------------- -slice target cbs sp = do +slice target cbs sp = do ex <- doesFileExist savedFile - if ex - then doDiffCheck + if ex + then doDiffCheck else return Nothing where savedFile = extFileName Saved target @@ -151,7 +152,7 @@ sliceSaved' srcF is lm (DC coreBinds result spec) assumeSpec :: M.HashMap Var LocSpecType -> TargetSpec -> TargetSpec assumeSpec sigm sp = sp { gsSig = gsig { gsAsmSigs = M.toList $ M.union sigm assm } } where - assm = M.fromList (gsAsmSigs gsig) + assm = M.fromList (gsAsmSigs gsig) gsig = gsSig sp diffVars :: [Int] -> [Def] -> [Var] @@ -211,7 +212,7 @@ thinWith :: S.HashSet Var -> [CoreBind] -> [Var] -> [CoreBind] thinWith sigs cbs xs = filterBinds cbs calls where calls = txClosure cbDeps sigs (S.fromList xs) - cbDeps = coreDeps cbs + cbDeps = coreDeps cbs coreDeps :: [CoreBind] -> Deps coreDeps bs = mkGraph $ calls ++ calls' @@ -220,7 +221,7 @@ coreDeps bs = mkGraph $ calls ++ calls' calls' = [(y, x) | (x, y) <- calls] deps b = [(x, y) | x <- bindersOf b , y <- freeVars S.empty b - , S.member y defVars + , S.member y defVars ] defVars = S.fromList (letVars bs) @@ -268,8 +269,8 @@ specDefs srcF = map def . filter sameFile . specSigs sameFile = (srcF ==) . file . snd specSigs :: TargetSpec -> [(Var, LocSpecType)] -specSigs sp = gsTySigs (gsSig sp) - ++ gsAsmSigs (gsSig sp) +specSigs sp = gsTySigs (gsSig sp) + ++ gsAsmSigs (gsSig sp) ++ gsCtors (gsData sp) instance PPrint Def where @@ -285,9 +286,9 @@ coreDefs cbs = coreExprDefs xm xes xm = varBounds xes coreExprDefs :: M.HashMap Var (Int, Int) -> [(Var, CoreExpr)]-> [Def] -coreExprDefs xm xes = - L.sort - [ D l l' x +coreExprDefs xm xes = + L.sort + [ D l l' x | (x, e) <- xes , (l, l') <- maybeToList $ coreExprDef xm (x, e) ] @@ -302,43 +303,43 @@ coreExprDef m (x, e) = meetSpans eSp vSp coreVarExprs :: [CoreBind] -> [(Var, CoreExpr)] coreVarExprs = filter ok . concatMap varExprs where - ok = isGoodSrcSpan . getSrcSpan . fst + ok = isGoodSrcSpan . getSrcSpan . fst varExprs :: Bind a -> [(a, Expr a)] varExprs (NonRec x e) = [(x, e)] varExprs (Rec xes) = xes --- | varBounds computes upper and lower bounds on where each top-level binder's +-- | varBounds computes upper and lower bounds on where each top-level binder's -- definition can be by using ONLY the lines where the binder is defined. varBounds :: [(Var, CoreExpr)] -> M.HashMap Var (Int, Int) -varBounds = M.fromList . defBounds . varDefs +varBounds = M.fromList . defBounds . varDefs varDefs :: [(Var, CoreExpr)] -> [(Int, Var)] -varDefs xes = +varDefs xes = L.sort [ (l, x) | (x,_) <- xes, let Just (l, _) = lineSpan x (getSrcSpan x) ] defBounds :: [(Int, Var)] -> [(Var, (Int, Int) )] defBounds ((l, x) : lxs@((l', _) : _ )) = (x, (l, l' - 1)) : defBounds lxs defBounds _ = [] -{- +{- -------------------------------------------------------------------------------- coreDefs :: [CoreBind] -> [Def] -------------------------------------------------------------------------------- -coreDefs cbs = tracepp "coreDefs" $ +coreDefs cbs = tracepp "coreDefs" $ L.sort [D l l' x | b <- cbs , x <- bindersOf b , isGoodSrcSpan (getSrcSpan x) , (l, l') <- coreDef b] coreDef :: CoreBind -> [(Int, Int)] -coreDef b +coreDef b | True = tracepp ("coreDef: " ++ showpp (vs, vSp)) $ maybeToList vSp | False = tracepp ("coreDef: " ++ showpp (b, eSp, vSp)) $ meetSpans b eSp vSp where eSp = lineSpan b $ catSpans b $ bindSpans b vSp = lineSpan b $ catSpans b $ getSrcSpan <$> vs - vs = bindersOf b + vs = bindersOf b meetSpans :: Maybe (Int, Int) -> Maybe (Int, Int) -> Maybe (Int, Int) meetSpans Nothing _ @@ -420,8 +421,8 @@ exprSpans (Cast e _) = exprSpans e exprSpans (Case e x _ cs) = getSrcSpan x : exprSpans e ++ concatMap altSpans cs exprSpans _ = [] -altSpans :: (NamedThing a, NamedThing a1) => (t, [a], Expr a1) -> [SrcSpan] -altSpans (_, xs, e) = map getSrcSpan xs ++ exprSpans e +altSpans :: (NamedThing b) => Alt b -> [SrcSpan] +altSpans (Alt _ xs e) = map getSrcSpan xs ++ exprSpans e isJunkSpan :: SrcSpan -> Bool isJunkSpan RealSrcSpan{} = False @@ -478,7 +479,7 @@ diffShifts = go 1 1 -------------------------------------------------------------------------------- saveResult :: FilePath -> Output Doc -> IO () -------------------------------------------------------------------------------- -saveResult target res = do +saveResult target res = do copyFile target saveF B.writeFile errF $ LB.toStrict $ encode res where @@ -488,13 +489,13 @@ saveResult target res = do -------------------------------------------------------------------------------- loadResult :: FilePath -> IO (Output Doc) -------------------------------------------------------------------------------- -loadResult f = do +loadResult f = do ex <- doesFileExist jsonF - if ex + if ex then convert <$> B.readFile jsonF else return mempty where - convert = fromMaybe mempty . decode . LB.fromStrict + convert = fromMaybe mempty . decode . LB.fromStrict jsonF = extFileName Cache f -------------------------------------------------------------------------------- @@ -509,20 +510,18 @@ adjustTypes lm cm (AI m) = AI $ if True then mempty else M.fromList -- , Just sp' <- [adjustSrcSpan lm cm sp]] adjustResult :: LMap -> ChkItv -> ErrorResult -> ErrorResult -adjustResult lm cm (Unsafe s es) = errorsResult (Unsafe s) $ adjustErrors lm cm es -adjustResult lm cm (Crash es z) = errorsResult (`Crash` z) $ adjustErrors lm cm es +adjustResult lm cm (Unsafe s es) = errorsResult (Unsafe s) $ mapMaybe (adjustError lm cm) es +adjustResult lm cm (Crash es z) = errorsResult (`Crash` z) $ (, Nothing) <$>mapMaybe (adjustError lm cm . fst) es adjustResult _ _ r = r errorsResult :: ([a] -> FixResult b) -> [a] -> FixResult b errorsResult _ [] = Safe mempty errorsResult f es = f es -adjustErrors :: (PPrint (TError a)) => LMap -> ChkItv -> [TError a] -> [TError a] -adjustErrors lm cm = mapMaybe adjustError - where - adjustError e = case adjustSrcSpan lm cm (pos e) of - Just sp' -> Just (e {pos = sp'}) - Nothing -> Nothing +adjustError :: (PPrint (TError a)) => LMap -> ChkItv -> TError a -> Maybe (TError a) +adjustError lm cm e = case adjustSrcSpan lm cm (pos e) of + Just sp' -> Just (e {pos = sp'}) + Nothing -> Nothing -------------------------------------------------------------------------------- adjustSrcSpan :: LMap -> ChkItv -> SrcSpan -> Maybe SrcSpan @@ -546,7 +545,7 @@ adjustSpan _ sp = Just sp adjustReal :: LMap -> RealSrcSpan -> Maybe RealSrcSpan adjustReal lm rsp - | Just δ <- sh = Just $ realSrcSpan f (l1 + δ) c1 (l2 + δ) c2 + | Just δ <- sh = Just $ packRealSrcSpan f (l1 + δ) c1 (l2 + δ) c2 | otherwise = Nothing where (f, l1, c1, l2, c2) = unpackRealSrcSpan rsp diff --git a/src/Language/Haskell/Liquid/UX/Errors.hs b/src/Language/Haskell/Liquid/UX/Errors.hs index 5b0a82ba20..b5d30d2386 100644 --- a/src/Language/Haskell/Liquid/UX/Errors.hs +++ b/src/Language/Haskell/Liquid/UX/Errors.hs @@ -3,8 +3,6 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE BangPatterns #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - -- | This module contains the functions related to @Error@ type, -- in particular, to @tidyError@ using a solution, and @pprint@ errors. diff --git a/src/Language/Haskell/Liquid/UX/QuasiQuoter.hs b/src/Language/Haskell/Liquid/UX/QuasiQuoter.hs index f8ed5da868..1f4f74079f 100644 --- a/src/Language/Haskell/Liquid/UX/QuasiQuoter.hs +++ b/src/Language/Haskell/Liquid/UX/QuasiQuoter.hs @@ -1,12 +1,9 @@ -{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE OverloadedStrings #-} -{-# OPTIONS_GHC -Wno-name-shadowing #-} - module Language.Haskell.Liquid.UX.QuasiQuoter -- ( -- -- * LiquidHaskell Specification QuasiQuoter @@ -63,14 +60,14 @@ lqDec src = do prg <- pragAnnD ModuleAnnotation $ conE 'LiquidQuote `appE` dataToExpQ' spec case mkSpecDecs spec of - Left err -> - throwErrorInQ err + Left uerr -> + throwErrorInQ uerr Right decs -> return $ prg : decs throwErrorInQ :: UserError -> Q a -throwErrorInQ err = - fail . showpp =<< runIO (errorsWithContext [err]) +throwErrorInQ uerr = + fail . showpp =<< runIO (errorsWithContext [uerr]) -------------------------------------------------------------------------------- -- Liquid Haskell to Template Haskell ------------------------------------------ @@ -94,11 +91,7 @@ mkSpecDecs (Alias rta) = lsym = F.atLoc rta n name = symbolName n n = rtName (val rta) -#if MIN_VERSION_template_haskell(2,17,0) tvs = (\a -> PlainTV (symbolName a) ()) <$> rtTArgs (val rta) -#else - tvs = PlainTV . symbolName <$> rtTArgs (val rta) -#endif mkSpecDecs _ = Right [] @@ -159,14 +152,10 @@ simplifyBareType'' (tvs, cls) (RFun _ _ i o _) simplifyBareType'' (tvs, cls) (RAllT tv t _) = simplifyBareType'' (ty_var_value tv : tvs, cls) t -simplifyBareType'' (tvs, cls) t = -#if MIN_VERSION_template_haskell(2,17,0) +simplifyBareType'' (tvs, cls) bt = ForallT ((\t -> PlainTV (symbolName t) SpecifiedSpec) <$> reverse tvs) -#else - ForallT (PlainTV . symbolName <$> reverse tvs) -#endif <$> mapM simplifyBareType' (reverse cls) - <*> simplifyBareType' t + <*> simplifyBareType' bt data Simpl a = Simplified a @@ -184,8 +173,6 @@ instance Applicative Simpl where FoundHole <*> _ = FoundHole instance Monad Simpl where - return = Simplified - Simplified x >>= f = f x FoundExprArg l >>= _ = FoundExprArg l FoundHole >>= _ = FoundHole diff --git a/src/Language/Haskell/Liquid/UX/Tidy.hs b/src/Language/Haskell/Liquid/UX/Tidy.hs index 27acfcc4b9..e16192240f 100644 --- a/src/Language/Haskell/Liquid/UX/Tidy.hs +++ b/src/Language/Haskell/Liquid/UX/Tidy.hs @@ -36,7 +36,7 @@ import qualified Data.HashSet as S import qualified Data.List as L import qualified Data.Text as T import qualified Control.Exception as Ex -import qualified Liquid.GHC.Misc as GM +import qualified Liquid.GHC.Misc as GM -- (dropModuleNames, showPpr, stringTyVar) import Language.Fixpoint.Types hiding (Result, SrcSpan, Error) import Language.Haskell.Liquid.Types.Types @@ -54,10 +54,10 @@ class Result a where result :: a -> FixResult UserError instance Result UserError where - result e = Crash [e] "" + result e = Crash [(e, Nothing)] "" instance Result [Error] where - result es = Crash (errorToUserError <$> es) "" + result es = Crash ([ (errorToUserError e, Nothing) | e <- es]) "" instance Result Error where result e = result [e] -- Crash [pprint e] "" @@ -71,16 +71,16 @@ errorToUserError = fmap ppSpecTypeErr -- TODO: move to Types.hs cinfoError :: Cinfo -> Error cinfoError (Ci _ (Just e) _) = e -cinfoError (Ci l _ _) = ErrOther l (text $ "Cinfo:" ++ GM.showPpr l) +cinfoError (Ci l _ _) = ErrOther l (text $ "Cinfo: " ++ GM.showPpr l) ------------------------------------------------------------------------- tidySpecType :: Tidy -> SpecType -> SpecType ------------------------------------------------------------------------- -tidySpecType k - = tidyEqual +tidySpecType k + = tidyEqual . tidyValueVars . tidyDSymbols - . tidySymbols k + . tidySymbols k . tidyInternalRefas . tidyLocalRefas k . tidyFunBinds @@ -105,9 +105,9 @@ tidySymbols k t = substa (shortSymbol k . tidySymbol) $ mapBind dropBind t xs = S.fromList (syms t) dropBind x = if x `S.member` xs then tidySymbol x else nonSymbol -shortSymbol :: Tidy -> Symbol -> Symbol -shortSymbol Lossy = GM.dropModuleNames -shortSymbol _ = id +shortSymbol :: Tidy -> Symbol -> Symbol +shortSymbol Lossy = GM.dropModuleNames +shortSymbol _ = id tidyLocalRefas :: Tidy -> SpecType -> SpecType tidyLocalRefas k = mapReft (txReft' k) @@ -120,7 +120,7 @@ tidyLocalRefas k = mapReft (txReft' k) tidyEqual :: SpecType -> SpecType tidyEqual = mapReft txReft - where + where txReft u = u { ur_reft = mapPredReft dropInternals $ ur_reft u } dropInternals = pAnd . L.nub . conjuncts @@ -230,7 +230,7 @@ instance PPrint (CtxError SpecType) where instance PPrint Error where pprintTidy k = ppError k empty . fmap ppSpecTypeErr - + ppSpecTypeErr :: SpecType -> Doc ppSpecTypeErr = ppSpecType Lossy diff --git a/src/Language/Haskell/Liquid/WiredIn.hs b/src/Language/Haskell/Liquid/WiredIn.hs index 696049a8d7..2f2ccde96d 100644 --- a/src/Language/Haskell/Liquid/WiredIn.hs +++ b/src/Language/Haskell/Liquid/WiredIn.hs @@ -1,5 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} +{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} + module Language.Haskell.Liquid.WiredIn ( wiredTyCons , wiredDataCons @@ -213,6 +215,7 @@ derivingClasses = S.fromList , "GHC.Base.Functor" , "Data.Foldable.Foldable" , "Data.Traversable.Traversable" + , "GHC.Real.Fractional" -- , "GHC.Enum.Bounded" -- , "GHC.Base.Monoid" ] diff --git a/src/LiquidHaskell.hs b/src/LiquidHaskell.hs index 6b3e46df70..ae600702c6 100644 --- a/src/LiquidHaskell.hs +++ b/src/LiquidHaskell.hs @@ -1,20 +1,9 @@ -{-# LANGUAGE CPP #-} - module LiquidHaskell ( -- * LiquidHaskell Specification QuasiQuoter lq -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) -- * LiquidHaskell as a compiler plugin , plugin -#endif -#endif ) where import Language.Haskell.Liquid.UX.QuasiQuoter - -#ifdef MIN_VERSION_GLASGOW_HASKELL -#if MIN_VERSION_GLASGOW_HASKELL(8,10,0,0) import Language.Haskell.Liquid.GHC.Plugin (plugin) -#endif -#endif diff --git a/stack.yaml b/stack.yaml index 3c9bf83aa8..c87d6bc063 100644 --- a/stack.yaml +++ b/stack.yaml @@ -8,6 +8,7 @@ flags: extra-package-dbs: [] ghc-options: hscolour: -w + liquidhaskell: -j packages: - liquid-fixpoint - liquid-ghc-prim @@ -23,16 +24,18 @@ packages: - benchmark-timings - . extra-deps: -- blaze-colonnade-1.2.2.1@sha256:b27601f0366b006e86ee33297a722fe33c94ac058e61d4eace387d132e656a21,1394 -- colonnade-1.2.0.2@sha256:e0b43a1fe4f87072f3f7cd9eaccdb790f7df8ceff5f73c3a4e242aba9337485f,2099 - hashable-1.3.5.0 -- rest-rewrite-0.3.0 +- rest-rewrite-0.4.0 +- smtlib-backends-0.3 +- smtlib-backends-process-0.3 - git: https://github.com/qnikst/ghc-timings-report commit: 45ef3498e35897712bde8e002ce18df6d55f8b15 # for tests - strip-ansi-escape-0.1.0.0@sha256:08f2ed93b16086a837ec46eab7ce8d27cf39d47783caaeb818878ea33c2ff75f,1628 -resolver: lts-18.27 +resolver: lts-20.1 +allow-newer: true nix: packages: [cacert, git, hostname, z3] + path: [nixpkgs=./nixpkgs.nix] diff --git a/stack.yaml.lock b/stack.yaml.lock index f6705bb519..ef98059d77 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -5,54 +5,54 @@ packages: - completed: - hackage: blaze-colonnade-1.2.2.1@sha256:b27601f0366b006e86ee33297a722fe33c94ac058e61d4eace387d132e656a21,1394 + hackage: hashable-1.3.5.0@sha256:3a2beeafb220f9de706568a7e4a5b3c762cc4c9f25c94d7ef795b8c2d6a691d7,4240 pantry-tree: - size: 279 - sha256: e1a52f56ec0cab647ec7af0d75bfbb45f09cccea4a8127996cb7b132bd73bd2c + sha256: 4df2f6b536a0fcc5f7d562cb29e373f27dc4a2747452ac5cc74c1599cab22fc5 + size: 1248 original: - hackage: blaze-colonnade-1.2.2.1@sha256:b27601f0366b006e86ee33297a722fe33c94ac058e61d4eace387d132e656a21,1394 + hackage: hashable-1.3.5.0 - completed: - hackage: colonnade-1.2.0.2@sha256:e0b43a1fe4f87072f3f7cd9eaccdb790f7df8ceff5f73c3a4e242aba9337485f,2099 + hackage: rest-rewrite-0.4.0@sha256:be93d899f7dece33f2a7613eb3dabd24d139f9cb2fc09f9efedfdce4ba6eb276,3923 pantry-tree: - size: 327 - sha256: 2010fda4c4af2dd9da64786d9e902f387b6a9cb034eb6573d678e752deecc319 + sha256: ad19ccb2185ac0b58ddfd2eede69e6444986e687232e1504eb04ce7bb6e39368 + size: 4018 original: - hackage: colonnade-1.2.0.2@sha256:e0b43a1fe4f87072f3f7cd9eaccdb790f7df8ceff5f73c3a4e242aba9337485f,2099 + hackage: rest-rewrite-0.4.0 - completed: - hackage: hashable-1.3.5.0@sha256:3a2beeafb220f9de706568a7e4a5b3c762cc4c9f25c94d7ef795b8c2d6a691d7,4240 + hackage: smtlib-backends-0.3@sha256:917d88540a9ede7beedbe2ed13b492acddbce394d30ccf5d0ef4f4fba9aa2c12,1157 pantry-tree: - size: 1248 - sha256: 4df2f6b536a0fcc5f7d562cb29e373f27dc4a2747452ac5cc74c1599cab22fc5 + sha256: 59b578ae7df155a6c73a513358370747e3cc6229ebb44adaba9e0935f811539c + size: 275 original: - hackage: hashable-1.3.5.0 + hackage: smtlib-backends-0.3 - completed: - hackage: rest-rewrite-0.3.0@sha256:398f937a5faf6bd3329650ee9aed31bbfe7ed1c23252710908ad7295e3252c94,3890 + hackage: smtlib-backends-process-0.3@sha256:d4d7d02859383e0a43db2d8ce7ef01deffe1bcd356b2ff8626925c3a1c8db922,1600 pantry-tree: - size: 3943 - sha256: 6e42cf85257cbc2abf50a9c8f3bac8777920f1b970e6f2cae9358690e1186e99 + sha256: d7d8ec52d07f4a59614000fd93d77b109d085d58f2d96e2c4b972f541c4e8287 + size: 461 original: - hackage: rest-rewrite-0.3.0 + hackage: smtlib-backends-process-0.3 - completed: - name: ghc-timings - version: '0.1' + commit: 45ef3498e35897712bde8e002ce18df6d55f8b15 git: https://github.com/qnikst/ghc-timings-report + name: ghc-timings pantry-tree: - size: 7544 sha256: 72622264696c78cda23cf96382dee7a3d14e3eafdb8977486338f113681dcec4 - commit: 45ef3498e35897712bde8e002ce18df6d55f8b15 + size: 7544 + version: '0.1' original: - git: https://github.com/qnikst/ghc-timings-report commit: 45ef3498e35897712bde8e002ce18df6d55f8b15 + git: https://github.com/qnikst/ghc-timings-report - completed: hackage: strip-ansi-escape-0.1.0.0@sha256:08f2ed93b16086a837ec46eab7ce8d27cf39d47783caaeb818878ea33c2ff75f,1628 pantry-tree: - size: 671 sha256: cf7712453587e8ea69b96f33e2e8015c22d3b448259d4cace663cc15657309d7 + size: 671 original: hackage: strip-ansi-escape-0.1.0.0@sha256:08f2ed93b16086a837ec46eab7ce8d27cf39d47783caaeb818878ea33c2ff75f,1628 snapshots: - completed: - size: 590102 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/27.yaml - sha256: 79a786674930a89301b0e908fad2822a48882f3d01486117693c377b8edffdbe - original: lts-18.27 + sha256: b73b2b116143aea728c70e65c3239188998bac5bc3be56465813dacd74215dc5 + size: 648424 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/1.yaml + original: lts-20.1 diff --git a/tests/README.md b/tests/README.md index e71a907340..23750c159b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -14,6 +14,7 @@ containing `pos` and `neg` subfolders for positive and negative tests respectively. + ## `test-driver` Executable See the code for comments and documentation that is likely more up to date than @@ -22,6 +23,22 @@ invoke either stack or cabal to compile specific test groups, kept in `tests.cabal` as separate executables. The rest of this file describes how to modify the test suite by adding new tests. +### Running a Particular Test Suite + +With `stack` you can do (you may have to set certain flags to `True` in `tests.cabal`) + +``` +$ cd tests +$ stack test tests:exe:errors --fast +``` + +and with `cabal` you could try + +``` +$ cd tests +$ cabal v2-run tests:errors +``` + ### Adding a New Test to an Existing Test Group Create a new file in the source directory specified in the cabal file for that diff --git a/tests/Synthesis.hs b/tests/Synthesis.hs deleted file mode 100644 index 3f68d80bd5..0000000000 --- a/tests/Synthesis.hs +++ /dev/null @@ -1,153 +0,0 @@ -{-# LANGUAGE TupleSections #-} - -module Main where - -import Test.Tasty -import Test.Tasty.HUnit - -import qualified Data.Text as T -import qualified Data.Text.IO as T -import System.FilePath -import System.Process -import System.IO -import System.Directory -import System.Exit -import System.IO.Unsafe -import Data.Tuple.Extra - -------------------------------------------------------------- --- | Contains the input files -------------------------------------------------------------- -synthesisTestsDir :: FilePath -synthesisTestsDir = "tests/synthesis/tests" -------------------------------------------------------------- - -------------------------------------------------------------- --- | Contains the results of the synthesis on the inputs -------------------------------------------------------------- -logDir :: FilePath -logDir = "tests/synthesis/logs" -------------------------------------------------------------- - -------------------------------------------------------------- --- | Contains the outputs that we need to check logs against -------------------------------------------------------------- -outputsDir :: FilePath -outputsDir = "tests/synthesis/static" -------------------------------------------------------------- - -main :: IO () -main = do - print " Synthesis test suite " - result <- fromInput - defaultMain (tests result) - -fromInput :: IO [(FilePath, T.Text, [[T.Text]])] -fromInput = do - res <- createLogs -- Get the filename from here - logs <- handleLogs (map thd3 res) - let filenames = map fst3 res - programNames = map (head . T.words . head . head) logs - result = zip3 filenames programNames logs - return result - -handleLogs :: [T.Text] -> IO [[[T.Text]]] -handleLogs texts - = return (map handleLog texts) - -keyword :: T.Text -keyword = T.pack " Hole Fills:" - -startsWith :: T.Text -> T.Text -> Bool -startsWith kw line = T.isPrefixOf kw line - --- | @walkFile@ returns empty means that there is no solution produced --- for given specification (needs to be checked) - -walkFile :: T.Text -> [T.Text] -walkFile text = dropWhile (not . startsWith keyword) ls - where ls = T.lines text - --- | Lines from the solution in the log file (without trailing characters) -handleLog :: T.Text -> [[T.Text]] -handleLog text = - let toBeParsed = walkFile text - sols = T.splitOn (T.pack delim) (T.unlines (tail toBeParsed)) - noTrailing = map (filter (not . T.null)) (map (map T.strip) (map T.lines sols)) - in noTrailing - - -delim :: String -delim = "*********************************************" - - -createLogs :: IO [(FilePath, ExitCode, T.Text)] -createLogs = do - files <- listDirectory synthesisTestsDir - let testFiles = filter (\x -> takeExtension x == ".hs") files - res <- mapM runLiquid testFiles - let (ecs, ts) = unzip res - fs = map dropExtension testFiles - return (zip3 fs ecs ts) - -runLiquid :: FilePath -> IO (ExitCode, T.Text) -runLiquid tgt = do - let inFile = synthesisTestsDir tgt - log = logDir (dropExtension tgt <.> ".log") - -- use `liquid` if its on the path, otherwise use stack to call it - bin <- maybe "stack exec -- liquid" - ( <> " --ghc-option=-hide-package=base" - <> " --ghc-option=-hide-package=containers" - ) <$> findExecutable "liquid" - withFile log WriteMode $ \h -> do - (_, _, _, ph) <- createProcess $ (shell (bin ++ ' ' : inFile)) { std_out = UseHandle h, std_err = UseHandle h } - exitCode <- waitForProcess ph - (exitCode, ) <$> T.readFile log - - -getSolutions :: FilePath -> IO T.Text -getSolutions tgt = do - let file = outputsDir tgt - T.readFile file - -mkTgt :: FilePath -> FilePath -mkTgt t = addExtension t ".hs" - - - --- | Get solution from outputs line by line in order to compare -lineFile :: T.Text -> T.Text -> [T.Text] -lineFile progName file = - dropWhile (\x -> not (startsWith (progName `T.append` (T.pack " ")) x) || - startsWith (progName `T.append` (T.pack " ::")) x) (T.lines file) - -clean :: [T.Text] -> [T.Text] -clean ls = filter (not . T.null) (map T.strip ls) - -processAnswers :: [(FilePath, T.Text, [[T.Text]])] -> [(FilePath, [[T.Text]], [T.Text])] -processAnswers = map processAnswer - -processAnswer :: (FilePath, T.Text, [[T.Text]]) -> (FilePath, [[T.Text]], [T.Text]) -processAnswer (fp, prog, ts) = - let file = unsafePerformIO (getSolutions (mkTgt fp)) - fileLines = lineFile prog file - cleanLines = clean fileLines - in (fp, ts, cleanLines) - -compareLines :: [T.Text] -> [T.Text] -> Bool -compareLines [] [] = True -compareLines (t:ts) (l:ls) = t == l && compareLines ts ls -compareLines _ _ = False - -buildTestCase :: (FilePath, [[T.Text]], [T.Text]) -> TestTree -buildTestCase (fp, ls, ts) - = testCase - fp - ((foldr (\l b -> compareLines ts l || b) False ls) @?= True) - -tests :: [(FilePath, T.Text, [[T.Text]])] -> TestTree -tests inputs = - let answers = processAnswers inputs - units = map buildTestCase answers - in testGroup " Tests for synthesis " units - diff --git a/tests/benchmarks/bytestring-0.9.2.1/Data/ByteString.hs b/tests/benchmarks/bytestring-0.9.2.1/Data/ByteString.hs index 0779c2ef12..a59d5f78a4 100644 --- a/tests/benchmarks/bytestring-0.9.2.1/Data/ByteString.hs +++ b/tests/benchmarks/bytestring-0.9.2.1/Data/ByteString.hs @@ -271,7 +271,7 @@ import System.IO (hGetBufNonBlocking) import System.IO.Error (isEOFError) -- import GHC.Handle -import GHC.Exts (Word#, (+#), writeWord8OffAddr#) +import GHC.Exts (Word8#, (+#), writeWord8OffAddr#) import GHC.Base (build) import GHC.Word hiding (Word8) import GHC.Ptr (Ptr(..)) @@ -1225,7 +1225,7 @@ splitWith pred_ (PS fp off lenAAA) = splitWith0 pred# off lenAAA fp splitWith0 pred' off' len' fp' = withPtr fp $ \p -> splitLoop pred' p 0 off' len' fp' - splitLoop :: (Word# -> Bool) + splitLoop :: (Word8# -> Bool) -> Ptr Word8 -> Int -> Int -> Int -> ForeignPtr Word8 diff --git a/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Map.hs b/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Map.hs deleted file mode 100644 index 45c2eac945..0000000000 --- a/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Map.hs +++ /dev/null @@ -1,92 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# OPTIONS_GHC -fenable-rewrite-rules -Wno-inline-rule-shadowing #-} - ------------------------------------------------------------------------------ --- | --- Module : Language.Stitch.LH.Data.Map --- Copyright : (C) 2021 Facundo Domínguez --- License : BSD-style (see LICENSE) --- Stability : experimental --- --- An interface of maps that can be used in reflected definitions --- with LH. It is not currently used in the rest of stitch-lh, but --- I'm keeping it for now, just for the record. --- --- The ability to reflect operations on Maps comes into play when --- trying to reflect the typechecker. ----------------------------------------------------------------------------- - -module Language.Stitch.LH.Data.Map - ( module Language.Stitch.LH.Data.Map - , Map - ) - where - -import Data.Map (Map) -import qualified Data.Map as Map -import Data.Set (Set) -import qualified Data.Set as Set -import Prelude hiding (lookup) - --- XXX: put lookup in the logic and use rewrite rules to give it --- an implementation --- XXX: GHC only seems to fire rules if the definitions are eta expanded. -{-@ -reflect lookup -lazy lookup -lookup - :: forall

Bool>. - Ord a - => k : a - -> m : Map a b

- -> { r : Maybe b

- | not (Set.member k (mapKeys m)) <=> r = Nothing - } -@-} -lookup :: Ord a => a -> Map a b -> Maybe b -lookup a m = lookup a m - where - _ = Set.empty :: Set () -- quiet warning about unused imports - -{-# RULES "lookupImpl" lookup = Map.lookup #-} - -{-@ -reflect insert -lazy insert -insert - :: forall

Bool>. - Ord a - => a - -> b

- - -> Map a b

- -> Map a b

-@-} -insert :: Ord a => a -> b -> Map a b -> Map a b -insert a b m = insert a b m - -{-# RULES "insertImpl" insert = Map.insert #-} - -{-@ -reflect empty -lazy empty -empty :: forall

Bool>. Map a b

-@-} -empty :: Map a b -empty = goEmpty () - --- XXX: Making goEmpty local to empty, causes LH to crash when --- building Check.hs. -{-@ reflect goEmpty @-} -{-@ lazy goEmpty @-} -- With PR 2069 a termination error appears --- XXX: For some reason, GHC aggrees to fire emptyImpl only if --- empty appears in an auxiliar definition like this one. -goEmpty :: () -> Map a b -goEmpty () = goEmpty () - -{-# RULES "emptyImpl" goEmpty () = Map.empty #-} - - -{-@ -measure mapKeys :: Map a b -> Set a -@-} diff --git a/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Nat.hs b/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Nat.hs index e101348458..98e050fb82 100644 --- a/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Nat.hs +++ b/tests/benchmarks/stitch-lh/src/Language/Stitch/LH/Data/Nat.hs @@ -2,7 +2,6 @@ module Language.Stitch.LH.Data.Nat where import Prelude hiding (max) -{-@ type Nat = { v : Int | v >= 0 } @-} type Nat = Int {-@ inline max @-} diff --git a/tests/benchmarks/stitch-lh/stitch-lh.cabal b/tests/benchmarks/stitch-lh/stitch-lh.cabal index 2291983876..0a37c98d97 100644 --- a/tests/benchmarks/stitch-lh/stitch-lh.cabal +++ b/tests/benchmarks/stitch-lh/stitch-lh.cabal @@ -42,7 +42,6 @@ library Language.Stitch.LH.Check -- Language.Stitch.LH.CSE Language.Stitch.LH.Data.List - Language.Stitch.LH.Data.Map Language.Stitch.LH.Eval Language.Stitch.LH.Lex Language.Stitch.LH.Monad diff --git a/tests/errors/ElabLocation.hs b/tests/errors/ElabLocation.hs index 5f48c087ea..06d2348a3c 100644 --- a/tests/errors/ElabLocation.hs +++ b/tests/errors/ElabLocation.hs @@ -1,13 +1,15 @@ --- | This file tests that LH correctly localizes the elaboration error +-- | This file tests that LH correctly localizes the elaboration error -- to the '10 / x' term (where we get a sort-error as the 'Ratio Int' -- is compared against '0' which appears in the refinement for '/'.) --- You can fix this by `embed Ratio * as Int` +-- You can fix this by `embed Ratio * as Int` + +{-@ LIQUID "--expect-error-containing=ElabLocation.hs:15:14" @-} module ElabLocation where -import Data.Ratio +import Data.Ratio foo :: Ratio Int -> Bool -foo x = y == y - where +foo x = y == y + where y = 10 / x diff --git a/tests/errors/ElabLocation2.hs b/tests/errors/ElabLocation2.hs new file mode 100644 index 0000000000..7f5ee37d27 --- /dev/null +++ b/tests/errors/ElabLocation2.hs @@ -0,0 +1,18 @@ +{-@ LIQUID "--expect-error-containing=ElabLocation2.hs:18:54-66" @-} +module ElabLocation2 where +type Range = (Int,Int) + +{-@ measure start @-} +start :: Range -> Int +start (a,b) = a + +{-@ measure end @-} +end :: Range -> Int +end (a,b) = b + +{-@ using (Range) as {r:Range | start r <= end r} @-} + +-- seemed to work earlier, now fails +{-@ intsToRanges :: Int -> Int -> Int -> Int -> Maybe (Range,Range) @-} +intsToRanges :: Int -> Int -> Int -> Int -> Maybe (Range,Range) +intsToRanges a b c d = if a <= b && c <= d then Just ((a,b),(c,d)) else Nothing diff --git a/tests/errors/ElabLocation3.hs b/tests/errors/ElabLocation3.hs new file mode 100644 index 0000000000..d92c6705d1 --- /dev/null +++ b/tests/errors/ElabLocation3.hs @@ -0,0 +1,210 @@ +module ElabLocation3 where +{-@ LIQUID "--expect-error-containing=ElabLocation3.hs:174:1-5" @-} +{-@ LIQUID "--reflection" @-} + +import Language.Haskell.Liquid.ProofCombinators +import Prelude hiding (id) + +{-@ type Pos = {v:Int | 0 < v} @-} + +{-@ incr :: Pos -> Pos @-} +incr :: Int -> Int +incr x = x + 2 + + + +{-@ +data Monkey = + M { number :: Nat, + items :: [Int], + operation :: Int -> Int, + testMod :: {n:Int | n > 0 }, + ifTrue :: Nat, + ifFalse :: Nat, + count :: Nat + } +@-} +data Monkey = + M { number :: Int, + items :: [Int], + operation :: Int -> Int, + testMod :: Int, + ifTrue :: Int, + ifFalse :: Int, + count :: Int } + +{-@ myCount :: _ -> Nat @-} +myCount :: Monkey -> Int +myCount M { count = k} = k + + +showMonkey :: Monkey -> String +showMonkey (M n i o m ifT ifF count) = + "#" ++ (show n) ++ " items " ++ (show i) ++ " examined " ++ (show count) ++ "\n" + +instance Show Monkey where show = showMonkey + +{-@ type MonkeyIR X = {m:Monkey | number m < X && ifTrue m < X && ifFalse m < X } @-} + +-- fst = item +-- snd = destination +{-@ type MonkeyItem X = (Int, {n:Nat | n < X}) @-} + +{-@ turn :: x:Int -> {worry:Int | worry /= 0 } -> {modulus:Int | modulus /= 0} -> m:MonkeyIR x -> {d:[MonkeyItem x] | len d = len (items m)} @-} +turn :: Int -> Int -> Int -> Monkey -> [(Int, Int)] +turn _ worry modulus (M _ oldItems op m dTrue dFalse _) = + map toDestination oldItems where + toDestination i = let newWorry = (( op i ) `div` worry) `mod` modulus in + (newWorry, if newWorry `mod` m == 0 then dTrue else dFalse) + +-- What I would like to do: +-- measure countOfItems :: [Monkey] -> Int +-- countOfItems [] = 0 +-- countOfItems (m:ms) = len (items m) + countOfItems ms +-- +-- -> {m2:[MonkeyIR x] | len m2 = len m && countOfItems m2 = countOfItems m + len mi} +-- +-- But this measure gets applied to all lists, which doesn't work + +{-@ data MonkeyList = Empty | MCons { headMonkey :: MonkeyIR 8, barrel :: MonkeyList } @-} +data MonkeyList = + Empty | + MCons Monkey MonkeyList + +{-@ measure mLen :: MonkeyList -> Int + mLen Empty = 0 + mLen (MCons m ms) = 1 + mLen ms + @-} + +{-@ measure countOfItems :: MonkeyList -> Int + countOfItems Empty = 0 + countOfItems (MCons m ms) = len (items m) + countOfItems ms @-} + +{- +{-@ distribute2 :: m:MonkeyList -> {mi:[MonkeyItem 8] | len mi <= mLen m} + -> {m2:MonkeyList | mLen m2 = mLen m && countOfItems m2 = countOfItems m + len mi} @-} +distribute2 :: MonkeyList -> [(Int,Int)] -> MonkeyList +distribute2 Empty [] = Empty +distribute2 Empty _ = error "Shouldn't happen" +distribute2 (MCons m ms) destinations = + MCons (m {items = (items m) ++ newItems}) (distribute2 ms (filter (notP toMe) destinations)) where + newItems = map fst (filter toMe destinations) + toMe (_,d) = d == number m +-} + +{-@ distribute :: x:Int -> m:[MonkeyIR x] -> mi:[MonkeyItem x] + -> {m2:[MonkeyIR x] | len m2 = len m} @-} +distribute :: Int -> [Monkey] -> [(Int,Int)] -> [Monkey] +distribute _ [] _ = [] +distribute x (m:ms) destinations = + (m {items = (items m) ++ newItems}):(distribute x ms destinations) where + newItems = map fst (filter toMe destinations) + toMe (_,d) = d == number m + +-- Monkey N's turn in the round +{-@ roundN :: x:Int -> + {worry:Int | worry /= 0 } -> + {modulus:Int | modulus /= 0} -> + {before:[MonkeyIR x] | len before = x} -> + {n:Nat | n < x } -> + {after:[m:MonkeyIR x] | len after = x} @-} +roundN :: Int -> Int -> Int -> [Monkey] -> Int -> [Monkey] +roundN x worry modulus monkeys n = + let m = (monkeys !! n) + destinations = turn x worry modulus m + newCount = (myCount m) + length (items m) + afterRemoval = (take n monkeys) ++ [(m {items = [], count = newCount} )] ++ (drop (n+1) monkeys) in + distribute x afterRemoval destinations + +-- One round of all monkeys +-- Complicated by the need to prove termination. +{-@ round :: x:Int -> {worry:Int | worry /= 0} -> {modulus:Int | modulus /= 0 } -> + {before:[MonkeyIR x] | len before = x} -> + {after:[MonkeyIR x] | len after = x} @-} +round :: Int -> Int -> Int -> [Monkey] -> [Monkey] +round x worry modulus monkeys = go 0 monkeys where + {-@ go :: {n:Int | n >= 0 && n <= x} -> {m:[MonkeyIR x] | len m = x} -> {m2:[MonkeyIR x] | len m2 = x} / [ x - n ] @-} + go n ms = if n == x then ms + else go (n+1) (roundN x worry modulus ms n) + + +{-@ m0 :: MonkeyIR 4 @-} +m0 = M { number=0, items=[79,98], operation=(\o -> o * 19), testMod=23, ifTrue=2, ifFalse=3, count=0 } +{-@ m1 :: MonkeyIR 4 @-} +m1 = M { number=1, items=[54,65,75,74], operation=(\o -> o + 6), testMod=19, ifTrue=2, ifFalse=0, count=0 } +{-@ m2 :: MonkeyIR 4 @-} +m2 = M { number=2, items=[79,60,97], operation=(\o -> o * o), testMod=13, ifTrue=1, ifFalse=3, count=0 } +{-@ m3 :: MonkeyIR 4 @-} +m3 = M { number=3, items=[74], operation=(\o -> o + 3), testMod=17, ifTrue=0, ifFalse=1, count=0 } + +{-@ example :: {m:[MonkeyIR 4] | len m = 4} @-} +example :: [Monkey] +example = [ m0, m1, m2, m3 ] + +{-@ i0 :: MonkeyIR 8 @-} +i0 = M { number=0, items=[59,74,65,86], operation=(\o -> o * 19), testMod=7, ifTrue=6, ifFalse=2, count=0 } +{-@ i1 :: MonkeyIR 8 @-} +i1 = M { number=1, items=[62,84,72,91,68,78,51], operation=(\o -> o + 1), testMod=2, ifTrue=2, ifFalse=0, count=0 } +{-@ i2 :: MonkeyIR 8 @-} +i2 = M { number=2, items=[78,84,96], operation=(\o -> o + 8), testMod=19, ifTrue=6, ifFalse=5, count=0 } +{-@ i3 :: MonkeyIR 8 @-} +i3 = M { number=3, items=[97,86], operation=(\o -> o * o), testMod=3, ifTrue=1, ifFalse=0, count=0 } +{-@ i4 :: MonkeyIR 8 @-} +i4 = M { number=4, items=[50], operation=(\o -> o + 6), testMod=13, ifTrue=3, ifFalse=1, count=0 } +{-@ i5 :: MonkeyIR 8 @-} +i5 = M { number=5, items=[73,65,69,65,51], operation=(\o -> o * 17), testMod=11, ifTrue=4, ifFalse=7, count=0 } +{-@ i6 :: MonkeyIR 8 @-} +i6 = M { number=6, items=[69, 82, 97, 93, 82, 84, 58, 63], operation=(\o -> o + 5), testMod=5, ifTrue=5, ifFalse=7, count=0 } +{-@ i7 :: MonkeyIR 8 @-} +i7 = M { number=7, items=[81, 78, 82, 76, 79, 80], operation=(\o -> o + 3), testMod=17, ifTrue=3, ifFalse=4, count=0 } + +{-@ input :: {m:[MonkeyIR 8] | len m = 8} @-} +input :: [Monkey] +input = [ i0, i1, i2, i3, i4, i5, i6, i7 ] + +{-@ assume iterate :: (a -> a) -> a -> {l:[a] | len l >= 1000000 } @-} + +computeModulus :: [Monkey] -> Int +computeModulus ms = foldl1 (*) (map testMod ms) + + +id z = z + +part1 :: () -> IO () +part1 _ = do + putStrLn "Part 1" + let m1 = computeModulus example in do + putStrLn $ "Working mod " ++ show m1 + let allRounds = iterate {- (Main.round 4 3 m1) -} id example in + print $ allRounds !! 20 + + let m2 = computeModulus input in do + putStrLn $ "Working mod " ++ show m2 + let allRounds2 = iterate {- (Main.round 8 3 m2) -} id input in + print $ allRounds2 !! 20 + +part2 :: () -> IO () +part2 _ = do + putStrLn "Part 2" + let m1 = computeModulus example in do + putStrLn $ "Working mod " ++ show m1 + let allRounds = iterate {- (Main.round 4 1 m1) -} id example in do + print $ allRounds !! 1000 + print $ allRounds !! 2000 + print $ allRounds !! 3000 + print $ allRounds !! 4000 + print $ allRounds !! 5000 + print $ allRounds !! 6000 + print $ allRounds !! 7000 + print $ allRounds !! 8000 + print $ allRounds !! 9000 + print $ allRounds !! 10000 + + let m2 = computeModulus input in do + putStrLn $ "Working mod " ++ show m2 + let allRounds2 = iterate {- (Main.round 8 1 m2) -} id input in + print $ allRounds2 !! 10000 + +mymain :: IO () +mymain = part1 () >> part2 () + diff --git a/tests/errors/ErrLocation2.hs b/tests/errors/ErrLocation2.hs index a0323315ca..0cfbfc5f79 100644 --- a/tests/errors/ErrLocation2.hs +++ b/tests/errors/ErrLocation2.hs @@ -1,4 +1,4 @@ -{-@ LIQUID "--expect-error-containing=ErrLocation2.hs:12:20: error" @-} +{-@ LIQUID "--expect-error-containing=ErrLocation2.hs:12:20" @-} module ErrLocation2 where diff --git a/tests/import/client/C.hs b/tests/import/client/C.hs new file mode 100644 index 0000000000..0e5fc50400 --- /dev/null +++ b/tests/import/client/C.hs @@ -0,0 +1,9 @@ +{-@ LIQUID "--reflection" @-} + +module C where +import Language +import B + +{-@ getVal :: {e:Expr l st r | isEFalse e } -> {v:Int | false} @-} +getVal :: Expr l st r -> Int +getVal (EFalse v) = v \ No newline at end of file diff --git a/tests/import/lib/B.hs b/tests/import/lib/B.hs new file mode 100644 index 0000000000..9257ed03ef --- /dev/null +++ b/tests/import/lib/B.hs @@ -0,0 +1,8 @@ +{-@ LIQUID "--reflection" @-} +module B where +import Language + +{-@ reflect subst @-} +subst :: Expr l st r -> Expr l st r +subst EUnit = EUnit +subst e = e \ No newline at end of file diff --git a/tests/import/lib/Language.hs b/tests/import/lib/Language.hs new file mode 100644 index 0000000000..c156334d39 --- /dev/null +++ b/tests/import/lib/Language.hs @@ -0,0 +1,10 @@ +module Language where + +data Expr l st r = EUnit | EFalse Int +{-@ data Expr l st r = EUnit | EFalse { elb1 :: {xxx:Int | false}} @-} + + +{-@ measure isEFalse @-} +isEFalse :: Expr l st r -> Bool +isEFalse (EFalse _ ) = True +isEFalse _ = False \ No newline at end of file diff --git a/tests/neg/AbsNegTest.hs b/tests/neg/AbsNegTest.hs new file mode 100644 index 0000000000..3a77120fde --- /dev/null +++ b/tests/neg/AbsNegTest.hs @@ -0,0 +1,6 @@ +{-@ LIQUID "--expect-error-containing=AbsNegTest.hs:6:1" @-} +module AbsNegTest where + +{-@ f :: Int -> {n:Int | n < 0} @-} +f :: Int -> Int +f x = abs x diff --git a/tests/neg/Exponential1NegTest.hs b/tests/neg/Exponential1NegTest.hs new file mode 100644 index 0000000000..bbf6082559 --- /dev/null +++ b/tests/neg/Exponential1NegTest.hs @@ -0,0 +1,5 @@ +{-@ LIQUID "--expect-error-containing=Exponential1NegTest.hs:5:1" @-} +module Exponential1NegTest where + +ex5 :: Float -> Int -> Float +ex5 x y = x ^ y diff --git a/tests/neg/Exponential2NegTest.hs b/tests/neg/Exponential2NegTest.hs new file mode 100644 index 0000000000..8aaf9ca837 --- /dev/null +++ b/tests/neg/Exponential2NegTest.hs @@ -0,0 +1,6 @@ +{-@ LIQUID "--expect-error-containing=Exponential2NegTest.hs:6:20" @-} +module Exponential2NegTest where + +{-@ ex6 :: {n:Float | n /= 0} -> Int -> Float @-} +ex6 :: Float -> Int -> Float +ex6 x y = 1 / (x ^ y) diff --git a/tests/ple/pos/Permutations.hs b/tests/ple/pos/Permutations.hs new file mode 100644 index 0000000000..b349a1e0e2 --- /dev/null +++ b/tests/ple/pos/Permutations.hs @@ -0,0 +1,831 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +-- | This module proves that unoptimized implementations of +-- 'Data.List.permutations' are equivalent to the optimized +-- implementation in [1]. +-- +-- Additionally, this module offers a proof of an approximation of the +-- laziness requirement on permutations. See 'lemmaPermutationsDecomposition'. +-- +-- [1] https://gitlab.haskell.org/ghc/ghc/-/blob/aec5a443bc45ca99cfeedc1777edb0aceca142cf/libraries/base/Data/OldList.hs#L1263 +-- +module Permutations where + +import Language.Haskell.Liquid.ProofCombinators ((===), (***), QED(Admit, QED), (?), pleUnfold) + +-- We need to redefine operations from the base package in order to +-- have PLE reason with them. PLE is one of the algorithms in +-- liquid-fixpoint that unfolds definitions automatically in proofs. +-- +-- Therefore, we hide here the definitions comming from the Prelude. +-- In an ideal world, we would be able to use the original definitions +-- from base, and still would be able to use PLE. +-- +import Prelude hiding ((!!), (++), asTypeOf, concat, const, drop, foldr, id, map, take, reverse) + +-- The following infixr directives are processed by Liquid Haskell. +-- +-- They instruct the parser about the fixity and associativity of +-- operators when reading specifications. +-- +{-@ infixr 5 ++ @-} +{-@ infixr 5 : @-} +{-@ infixl 9 !! @-} + + +-- We write first the definition of the optimized permutations. +-- +-- The implementation in base uses local definitions in where clauses. +-- We split it here in top-level functions to better reason about +-- them in isolation. But it is possible to give Liquid Haskell +-- specifications to local functions as well. + +-- Liquid Haskell requires functions to be terminating, in order +-- to ensure soundness of the verified specifications. +-- +-- We disable the termination checker with the lazy directive though. +-- The termination checker is a bit tricky to convince once we start +-- adding lemmas that refer to permutations calls in their parameters. +-- +-- The termination of permutations is checked +-- [here](https://github.com/ucsd-progsys/liquidhaskell/blob/d20d80d53949efbb7d2ac6eb1509a0ec822d3bea/tests/pos/Permutation.hs) +-- though. +-- +{-@ lazy permutations @-} +{-@ reflect permutations @-} +{-@ permutations :: ts:[a] -> [[a]] / [(len ts), 1, 0] @-} +permutations :: [a] -> [[a]] +permutations xs0 = xs0 : perms xs0 [] + +-- @permutations xs0@ is equivalent to the following expressions +-- +-- > xs0 : concat [ interleave (ts!!n) (drop (n+1) xs0) xs [] | n <- [0..len xs0 - 1], xs <- permutations (reverse (take n xs0)) ] +-- > [ insertAt m (xs0!!n) xs ++ (drop (n+1) xs0) | n <- [0..len xs0 - 1], xs <- permutations (reverse (take n xs0)), m <- [0..len xs - 1] ] +-- + + +-- | @perms ts is@ is equivalent to the following expressions +-- +-- > concat [ interleave (ts!!n) (drop (n+1) ts) xs [] | n <- [0..len ts - 1], xs <- permutations (reverse (take n ts) ++ is) ] +-- > [ insertAt m (ts!!n) xs ++ (drop (n+1) ts) | n <- [0..len ts - 1], xs <- permutations (reverse (take n ts) ++ is), m <- [0..len xs - 1] ] +-- +-- The specification differs from this expressions in a few syntactic +-- aspects. +-- +-- 1) List ranges are not allowed in formulas. Therefore, we use the +-- function 'fromTo'. +-- 2) List comprehensions are not allowed in formulas. Therefore, we +-- use functions 'concat' and 'map' instead. +-- 3) Lambda expressions do not work well in formulas. Therefore, we +-- use top-level functions 'aux1' and 'aux2' instead. + +{-@ +reflect perms +perms + :: ts:[a] + -> is:[a] + -> { v:[[a]] + | v = concat (map (aux2 ts is) (fromTo 0 (len ts - 1))) + } / [((len ts)+(len is)), 0, (len ts)] +@-} +perms :: [a] -> [a] -> [[a]] +perms [] _ = [] +perms (t0:ts0) is = + mapInterleave t0 ts0 (permutations is) (perms ts0 (t0:is)) + `const` + lemmaMapAux2 t0 ts0 is 0 (length ts0 - 1) + `const` + lemmaAppendAssoc + (concat (map (aux1 t0 ts0 []) (permutations is))) + [] + (concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1)))) + `const` + mapInterleave t0 ts0 (permutations is) [] + +-- For efficiency of the verification process, proofs are given in +-- condensed form as above. The form starts from an expressions that +-- is the result of the function, with multiple lemma applications +-- appended with 'const'. +-- +-- Discovering which lemma applications are needed is done by writing +-- a longer step-by-step proof, where the need for each lemma can be +-- observed between steps. +-- +-- We start by writing the step-by-step proof, testing each new addition +-- with Liquid Haskell. When we are finished, we comment out the +-- step-by-step proof, and collect the lemmas into the condensed proof. +-- + +{- + `asTypeOf` + const (concat (map (aux1 t0 ts0 []) (permutations is)) ++ perms ts0 (t0:is)) + (mapInterleave t0 ts0 (permutations is) (perms ts0 (t0:is))) + `asTypeOf` + const (concat (map (aux1 t0 ts0 []) (permutations is)) ++ concat (map (aux2 ts0 (t0:is)) (fromTo 0 (length ts0 - 1)))) + (perms ts0 (t0:is)) + `asTypeOf` + const (concat (map (aux1 t0 ts0 []) (permutations is)) ++ concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1)))) + (lemmaMapAux2 t0 ts0 is 0 (length ts0 - 1)) + `asTypeOf` + (concat (map (aux1 t0 ts0 []) (permutations is)) ++ ([] ++ concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1))))) + `asTypeOf` + const ((concat (map (aux1 t0 ts0 []) (permutations is)) ++ []) ++ concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1)))) + (lemmaAppendAssoc + (concat (map (aux1 t0 ts0 []) (permutations is))) + [] + (concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1)))) + ) + `asTypeOf` + (mapInterleave t0 ts0 (permutations is) [] ++ concat (map (aux2 (t0:ts0) is) (fromTo 1 (length (t0:ts0) - 1)))) + `asTypeOf` + concat (map (aux2 (t0:ts0) is) (fromTo 0 (len (t0:ts0) - 1))) +-} + +{-@ +reflect aux2 +aux2 :: ts:[a] -> [a] -> { n:Int | n < len ts && n >= 0 } -> [[a]] +@-} +aux2 :: [a] -> [a] -> Int -> [[a]] +aux2 ts is n = + mapInterleave (ts!!n) (drop (n+1) ts) (permutations (reverse (take n ts) ++ is)) [] + +{-@ reflect aux0 @-} +aux0 :: a -> ([a] -> b) -> [a] -> [a] -> Int -> b +aux0 t f ys ts n = f (insertAt n t ys ++ ts) + +{-@ reflect aux1 @-} +aux1 :: a -> [a] -> [[a]] -> [a] -> [[a]] +aux1 t ts r p = interleave t ts p r + +-- | 'mapInterleave' is not part of the optimized definition of +-- permutations. We factor it out from 'perms' to break down a +-- bit the complexity of the verification. +-- +-- @mapInterleave t ts ps r@ is equivalent to the expressions +-- +-- > concat [ interleave t ts xs [] | xs <- ps ] ++ r +-- > [ insertAt n t xs ++ ts | xs <- ps, n <- [0..len xs - 1] ] ++ r +-- + +{-@ +reflect mapInterleave +mapInterleave + :: t:a + -> ts:[a] + -> ps:[[a]] + -> r:[[a]] + -> { v:[[a]] | v == concat (map (aux1 t ts []) ps) ++ r } +@-} +mapInterleave :: a -> [a] -> [[a]] -> [[a]] -> [[a]] +mapInterleave t ts ps r = foldr (interleave t ts) r ps `const` lemmaFoldrInterleave t ts ps r + +-- | @interleave t ts xs r@ is equivalent to the expression +-- +-- > [ insertAt n t xs ++ ts | n <- [0..len xs - 1] ] ++ r +-- + +{-@ +reflect interleave +interleave + :: t:a + -> ts:[a] + -> xs:[a] + -> r:[[a]] + -> { v:[[a]] | v == map (aux0 t id xs ts) (fromTo 0 (len xs - 1)) ++ r } +@-} +interleave :: a -> [a] -> [a] -> [[a]] -> [[a]] +interleave t ts xs r = + let (_,zs) = interleave' t ts id xs r in zs + +-- | @interleave' t ts f ys r@ is equivalent to the expression +-- +-- > (ys ++ ts, [ f (insertAt n t ys ++ ts) | n <- [0..len ys - 1] ] ++ r) +-- + +{-@ +reflect interleave' +interleave' + :: t:a + -> ts:[a] + -> f:([a] -> b) + -> ys:[a] + -> r:[b] + -> ( { v:[a] | v == ys ++ ts } + , { v:[b] | v == map (aux0 t f ys ts) (fromTo 0 (len ys-1)) ++ r } + ) +@-} +interleave' :: a -> [a] -> ([a] -> b) -> [a] -> [b] -> ([a], [b]) +interleave' t ts _ [] r = (ts, r) +interleave' t ts f (y:ys) r = + let (us, zs) = interleave' t ts (snoc f y) ys r + in (y:us, f (t:y:us) : zs `const` (lemmaMapAux0 t f y ys ts 0 (length ys - 1))) + + +--------------------------------- +-- Laziness requirement +--------------------------------- + +-- | The documentation of 'Data.List.permutations' states the laziness +-- requirement as follows +-- +-- > map (take n) (take (factorial n) $ permutations ([1..n] ++ undefined)) +-- > = +-- > permutations [1..n] +-- +-- This property cannot be proved with Liquid Haskell as partially +-- defined lists are not representable in formulas. Therefore, we +-- would have to content ourselves with the weaker +-- +-- > map (take n) (take (factorial n) $ permutations ([1..n] ++ r)) +-- > = +-- > permutations [1..n] +-- +-- where @r@ stands for any list. +-- +-- Now, when working out the proof, I didn't feel in the mood of +-- computing the lengths of the lists returned by all of the functions +-- implementing permutations, and therefore I aimed to rephrase the +-- property without calls to 'take'. I arrived first to +-- +-- > take (factorial n) (permutations ([1..n] ++ r)) +-- > = +-- > map (++ r) (permutations [1..n]) +-- +-- and then to +-- +-- > permutations ([1..n] ++ r) +-- > = +-- > map (++ r) (permutations [1..n]) ++ residue n r +-- +-- where 'residue' is some expression that we really don't care about +-- when considering the laziness requirement. Below are two +-- formulations of it. +-- +-- > residue n sfx = concat (map (aux2 ([1..n] ++ sfx) []) (fromTo n (n + len sfx - 1))) +-- > residue n sfx = +-- > concat +-- > [ concat [ interleave (sfx!!m) (drop (m+1) sfx) xs [] +-- > | xs <- permutations (reverse ([1..n] ++ take m sfx)) +-- > ] +-- > | m <- [0 .. length sfx - 1] +-- > ] +-- + +{-@ +lemmaPermutationsDecomposition + :: { n:Int | n >= 0 } + -> r:[Int] + -> { permutations (fromTo 1 n ++ r) + == + map (flipAppend r) (permutations (fromTo 1 n)) ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + len r - 1))) + } +@-} +lemmaPermutationsDecomposition :: Int -> [Int] -> () +lemmaPermutationsDecomposition n r = lemmaPermsDecomposition n r + + +{-@ +lemmaPermsDecomposition + :: { n:Int | n >= 0 } + -> r:[Int] + -> { perms (fromTo 1 n ++ r) [] + == + map (flipAppend r) (perms (fromTo 1 n) []) ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + len r - 1))) + } +@-} +lemmaPermsDecomposition :: Int -> [Int] -> () +lemmaPermsDecomposition n r = + () + `const` perms (fromTo 1 n ++ r) [] + `const` lemmaLengthAppend (fromTo 1 n) r + `const` lemmaLengthFromTo 1 n + `const` lemmaFromToSplit 0 (n - 1) (n + length r - 1) + `const` lemmaMapAppend (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1)) (fromTo n (n + length r - 1)) + `const` lemmaConcatAppend + (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1))) + (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1))) + `const` lemmaConcatMapInterleave (fromTo 1 n) r 0 (n - 1) + `const` perms (fromTo 1 n) [] +{- + perms (fromTo 1 n ++ r) [] + `asTypeOf` + concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (length (fromTo 1 n ++ r) - 1))) + `asTypeOf` case lemmaLengthAppend (fromTo 1 n) r of { () -> + concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (length (fromTo 1 n) + length r - 1))) + `asTypeOf` case lemmaLengthFromTo 1 n of { () -> + concat (map (aux2 ((fromTo 1 n ++ r)) []) (fromTo 0 (n + length r - 1))) + `asTypeOf` + const (concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1) ++ fromTo n (n + length r - 1)))) + (lemmaFromToSplit 0 (n - 1) (n + length r - 1)) + `asTypeOf` + const ( + const (concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1))) + ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1))) + ) + (lemmaMapAppend (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1)) (fromTo n (n + length r - 1))) + ) + (lemmaConcatAppend + (map (aux2 (fromTo 1 n ++ r) []) (fromTo 0 (n - 1))) + (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1))) + ) + `asTypeOf` + const (map (flipAppend r) (concat (map (aux2 (fromTo 1 n) []) (fromTo 0 (n - 1)))) + ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1)))) + (lemmaConcatMapInterleave (fromTo 1 n) r 0 (n - 1)) + `asTypeOf` + (map (flipAppend r) (concat (map (aux2 (fromTo 1 n) []) (fromTo 0 (length (fromTo 1 n) - 1)))) + ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1)))) + `asTypeOf` + (map (flipAppend r) (perms (fromTo 1 n) []) + ++ concat (map (aux2 (fromTo 1 n ++ r) []) (fromTo n (n + length r - 1)))) + }} + *** + QED +-} + + +------------------------------ +-- Auxiliary functions +------------------------------ + +infixr 5 ++ + +{-@ reflect id @-} +id :: a -> a +id x = x + +{-@ inline const @-} +const :: a -> b -> a +const x _ = x + +{-@ +inline asTypeOf +asTypeOf :: x:a -> { y:a | x = y } -> { v:a | v = x } +@-} +asTypeOf :: a -> a -> a +asTypeOf x _ = x + +{-@ reflect concat @-} +concat :: [[a]] -> [a] +concat [] = [] +concat (x:xs) = x ++ concat xs + +{-@ +reflect !! +(!!) :: xs:[a] -> { n:Int | n < len xs && n >= 0 } -> a +@-} +(!!) :: [a] -> Int -> a +(x:xs) !! 0 = x +(x:xs) !! n = xs !! (n - 1) + +{-@ reflect take @-} +take :: Int -> [a] -> [a] +take n xs + | n > 0 = + case xs of + [] -> [] + x:xs -> x : take (n-1) xs + | otherwise = + [] + +{-@ reflect drop @-} +drop :: Int -> [a] -> [a] +drop n xs + | n > 0 = + case xs of + [] -> [] + _:xs -> drop (n-1) xs + | otherwise = + xs + +{-@ reflect ++ @-} +(++) :: [a] -> [a] -> [a] +[] ++ ys = ys +(x:xs) ++ ys = x : xs ++ ys + +{-@ reflect flipAppend @-} +flipAppend :: [a] -> [a] -> [a] +flipAppend xs ys = ys ++ xs + +{-@ reflect insertAt @-} +insertAt :: Int -> a -> [a] -> [a] +insertAt n y xs = take n xs ++ y : drop n xs + +{-@ reflect map @-} +map :: (a -> b) -> [a] -> [b] +map f [] = [] +map f (x:xs) = f x : map f xs + +{-@ reflect foldr @-} +foldr :: (a -> b -> b) -> b -> [a] -> b +foldr f z [] = z +foldr f z (x:xs) = f x (foldr f z xs) + +{-@ reflect fromTo @-} +{-@ +fromTo + :: a:Int + -> b:Int + -> [{c:Int | a <= c && c <= b}] + / [b-a+1] +@-} +fromTo :: Int -> Int -> [Int] +fromTo a b = if a <= b then a : fromTo (a + 1) b + else [] + +{-@ reflect reverse @-} +reverse :: [a] -> [a] +reverse [] = [] +reverse (x:xs) = reverse xs ++ [x] + +{-@ +lemmaElemAtAppend + :: xs:[a] + -> ys:[a] + -> { i:Int | 0 <= i && i < len xs } + -> { (xs ++ ys) !! i == xs !! i } +@-} +lemmaElemAtAppend :: [a] -> [a] -> Int -> () +lemmaElemAtAppend [] _ _ = () +lemmaElemAtAppend (_:xs) ys i = + if i > 0 then lemmaElemAtAppend xs ys (i - 1) else () + +{-@ +lemmaDropAppend + :: xs:[a] + -> ys:[a] + -> { i:Int | 0 <= i && i <= len xs } + -> { drop i (xs ++ ys) == drop i xs ++ ys } +@-} +lemmaDropAppend :: [a] -> [a] -> Int -> () +lemmaDropAppend [] _ _ = () +lemmaDropAppend (_:xs) ys i = + if i > 0 then lemmaDropAppend xs ys (i - 1) else () + +{-@ +lemmaTakeAppend + :: xs:[a] + -> ys:[a] + -> { i:Int | 0 <= i && i <= len xs } + -> { take i (xs ++ ys) == take i xs } +@-} +lemmaTakeAppend :: [a] -> [a] -> Int -> () +lemmaTakeAppend [] _ _ = () +lemmaTakeAppend (_:xs) ys i = + if i > 0 then lemmaTakeAppend xs ys (i - 1) else () + +{-@ +lemmaMapAppend + :: f:(a -> b) + -> xs:[a] + -> ys:[a] + -> { map f xs ++ map f ys == map f (xs ++ ys) } +@-} +lemmaMapAppend :: (a -> b) -> [a] -> [a] -> () +lemmaMapAppend f [] ys = () +lemmaMapAppend f (_:xs) ys = lemmaMapAppend f xs ys + +{-@ +lemmaConcatAppend + :: xs:[[a]] + -> ys:[[a]] + -> { concat (xs ++ ys) = concat xs ++ concat ys } +@-} +lemmaConcatAppend :: [[a]] -> [[a]] -> () +lemmaConcatAppend [] _ = () +lemmaConcatAppend (x:xs) ys = + lemmaConcatAppend xs ys + `const` lemmaAppendAssoc x (concat xs) (concat ys) + +{-@ +lemmaLengthFromTo + :: i:Int + -> { j:Int | i <= j + 1 } + -> { len (fromTo i j) == j - i + 1 } / [j - i + 1] +@-} +lemmaLengthFromTo :: Int -> Int -> () +lemmaLengthFromTo i j = if i <= j then lemmaLengthFromTo (i + 1) j else () + +{-@ +lemmaLengthAppend + :: xs:[a] + -> ys:[a] + -> { len (xs ++ ys) == len xs + len ys } +@-} +lemmaLengthAppend :: [a] -> [a] -> () +lemmaLengthAppend [] _ = () +lemmaLengthAppend (_:xs) ys = lemmaLengthAppend xs ys + +{-@ +lemmaFromToSplit + :: a:Int + -> { b:Int | a <= b + 1 } + -> { c:Int | b <= c } + -> { fromTo a b ++ fromTo (b + 1) c == fromTo a c } / [ b - a + 1 ] +@-} +lemmaFromToSplit :: Int -> Int -> Int -> () +lemmaFromToSplit a b c = + if a + 1 <= b then lemmaFromToSplit (a+1) b c else if a <= b then () else () + +{- + if a + 1 <= b then + (fromTo a b ++ fromTo (b + 1) c) + `asTypeOf` + (a:fromTo (a+1) b ++ fromTo (b + 1) c) + `asTypeOf` + const (a:fromTo (a+1) c) + (lemmaFromToSplit (a+1) b c) + `asTypeOf` + fromTo a c + *** + QED + else + () +-} + +{-@ lemmaAppendId :: xs:[a] -> { xs = xs ++ [] } @-} +lemmaAppendId :: [a] -> () +lemmaAppendId [] = () +lemmaAppendId (_:xs) = lemmaAppendId xs + +-- | The refinement predicate in the return type is equivalent to +-- +-- > [ f (y : insertAt n t ys ts) | n <- [i..j] ] +-- > = +-- > [ f (insertAt n t (y:ys) ts) | n <- [i+1 .. j+1] ] +-- + +{-@ +lemmaMapAux0 + :: t:a + -> f:([a] -> b) + -> y:a + -> ys:[a] + -> ts:[a] + -> { i:Int | 0 <= i } + -> j:Int + -> { map (aux0 t (snoc f y) ys ts) (fromTo i j) + == map (aux0 t f (y:ys) ts) (fromTo (i+1) (j+1)) + } / [j-i+1] +@-} +lemmaMapAux0 :: a -> ([a] -> b) -> a -> [a] -> [a] -> Int -> Int -> () +lemmaMapAux0 t f y ys ts i j = + if i <= j then lemmaMapAux0 t f y ys ts (i+1) j else () + +{-@ reflect snoc @-} +snoc :: ([a] -> b) -> a -> [a] -> b +snoc f y xs = f (y : xs) + +{-@ +lemmaInterleaveAppend + :: t:a + -> ts:[a] + -> p:[a] + -> r:[[a]] + -> { interleave t ts p r == interleave t ts p [] ++ r } +@-} +lemmaInterleaveAppend :: a -> [a] -> [a] -> [[a]] -> () +lemmaInterleaveAppend t ts p r = + () + ? interleave t ts p r + ? interleave t ts p [] + ? lemmaAppendAssoc (map (aux0 t id p ts) (fromTo 0 (length p - 1))) [] r + + +--------------------------------- + +-- Doesn't work: +-- rewriteWith lemmaInterleaveAppend [lemmaAppendAssoc] + +{-@ +lemmaFoldrInterleave + :: t:a + -> ts:[a] + -> ps:[[a]] + -> r:[[a]] + -> { foldr (interleave t ts) r ps == concat (map (aux1 t ts []) ps) ++ r } +@-} +lemmaFoldrInterleave :: a -> [a] -> [[a]] -> [[a]] -> () +lemmaFoldrInterleave t ts [] r = () +lemmaFoldrInterleave t ts (p:ps) r = + lemmaFoldrInterleave t ts ps r + ? lemmaInterleaveAppend t ts p (concat (map (aux1 t ts []) ps) ++ r) + ? lemmaAppendAssoc (interleave t ts p []) (concat (map (aux1 t ts []) ps)) r + +{-@ +lemmaAppendAssoc :: xs:[a] -> ys:[a] -> zs:[a] -> { xs ++ ys ++ zs = (xs ++ ys) ++ zs } +@-} +lemmaAppendAssoc :: [a] -> [a] -> [a] -> () +lemmaAppendAssoc [] _ _ = () +lemmaAppendAssoc (_:xs) ys zs = lemmaAppendAssoc xs ys zs + +{-@ +lemmaConcatMapInterleave + :: ts:[a] + -> r:[a] + -> { i:Int | i >= 0 } + -> { j:Int | j < len ts } + -> { concat (map (aux2 (ts ++ r) []) (fromTo i j)) + == map (flipAppend r) (concat (map (aux2 ts []) (fromTo i j))) } / [j - i + 1] +@-} +lemmaConcatMapInterleave :: [a] -> [a] -> Int -> Int -> () +lemmaConcatMapInterleave ts r i j = + if i <= j then + lemmaConcatMapInterleave ts r (i + 1) j + `const` lemmaLengthAppend ts r + `const` lemmaTakeAppend ts r i + `const` lemmaElemAtAppend ts r i + `const` lemmaDropAppend ts r (i + 1) + `const` lemmaAppendInterleave (ts !! i) (drop (i + 1) ts) r (permutations (reverse (take i ts) ++ [])) + `const` lemmaMapAppend (flipAppend r) (aux2 ts [] i) (concat (map (aux2 ts []) (fromTo (i + 1) j))) + else + () +{- + if i <= j then + case lemmaLengthAppend ts r of { () -> + concat (map (aux2 (ts ++ r) []) (fromTo i j)) + `asTypeOf` + concat (map (aux2 (ts ++ r) []) (i : fromTo (i + 1) j)) + `asTypeOf` + (aux2 (ts ++ r) [] i ++ concat (map (aux2 (ts ++ r) []) (fromTo (i + 1) j))) + `asTypeOf` + const (aux2 (ts ++ r) [] i ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaConcatMapInterleave ts r (i + 1) j) + `asTypeOf` + (mapInterleave ((ts ++ r) !! i) (drop (i + 1) (ts ++ r)) (permutations (reverse (take i (ts ++ r)) ++ [])) [] + ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + `asTypeOf` + const (mapInterleave ((ts ++ r) !! i) (drop (i + 1) (ts ++ r)) (permutations (reverse (take i ts) ++ [])) [] + ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaTakeAppend ts r i) + `asTypeOf` + const (mapInterleave (ts !! i) (drop (i + 1) (ts ++ r)) (permutations (reverse (take i ts) ++ [])) [] + ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaElemAtAppend ts r i) + `asTypeOf` + const (mapInterleave (ts !! i) (drop (i + 1) ts ++ r) (permutations (reverse (take i ts) ++ [])) [] + ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaDropAppend ts r (i + 1)) + `asTypeOf` + const (map (flipAppend r) (aux2 ts [] i) ++ map (flipAppend r) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaAppendInterleave (ts !! i) (drop (i + 1) ts) r (permutations (reverse (take i ts) ++ []))) + `asTypeOf` + const (map (flipAppend r) (aux2 ts [] i ++ concat (map (aux2 ts []) (fromTo (i + 1) j)))) + (lemmaMapAppend (flipAppend r) (aux2 ts [] i) (concat (map (aux2 ts []) (fromTo (i + 1) j)))) + `asTypeOf` + map (flipAppend r) (concat (map (aux2 ts []) (fromTo i j))) + } + *** + QED + else + () +-} + +{-@ +lemmaAppendInterleave + :: t:a + -> ts:[a] + -> r:[a] + -> ps:[[a]] + -> { mapInterleave t (ts ++ r) ps [] == map (flipAppend r) (mapInterleave t ts ps []) } +@-} +lemmaAppendInterleave :: a -> [a] -> [a] -> [[a]] -> () +lemmaAppendInterleave t ts r [] = () + ? mapInterleave t (ts ++ r) [] [] + ? mapInterleave t ts [] [] +lemmaAppendInterleave t ts r (p:ps) = + lemmaAppendInterleave t ts r ps + `const` mapInterleave t (ts ++ r) (p:ps) [] + `const` mapInterleave t ts (p:ps) [] + `const` mapInterleave t (ts ++ r) ps [] + `const` mapInterleave t ts ps [] + `const` lemmaAppendAssoc (aux1 t (ts ++ r) [] p) (concat (map (aux1 t (ts ++ r) []) ps)) [] + `const` interleave t (ts ++ r) p [] + `const` lemmaAppendAux0 t p ts r (fromTo 0 (length p - 1)) + `const` lemmaAppendId (map (aux0 t id p ts) (fromTo 0 (length p - 1))) + `const` lemmaAppendId (map (flipAppend r) (interleave t ts p [])) + `const` lemmaMapAppend (flipAppend r) (aux1 t ts [] p) (mapInterleave t ts ps []) + `const` lemmaAppendAssoc (aux1 t ts [] p) (concat (map (aux1 t ts []) ps)) [] + +{- + mapInterleave t (ts ++ r) (p:ps) [] + `asTypeOf` + const (concat (map (aux1 t (ts ++ r) []) (p:ps)) ++ []) + (mapInterleave t (ts ++ r) (p:ps) []) + `asTypeOf` + ((aux1 t (ts ++ r) [] p ++ concat (map (aux1 t (ts ++ r) []) ps)) ++ []) + `asTypeOf` + const (aux1 t (ts ++ r) [] p ++ concat (map (aux1 t (ts ++ r) []) ps) ++ []) + (lemmaAppendAssoc (aux1 t (ts ++ r) [] p) (concat (map (aux1 t (ts ++ r) []) ps)) []) + `asTypeOf` + const (aux1 t (ts ++ r) [] p ++ mapInterleave t (ts ++ r) ps []) + (mapInterleave t (ts ++ r) ps []) + `asTypeOf` + const (aux1 t (ts ++ r) [] p ++ map (flipAppend r) (mapInterleave t ts ps [])) + (lemmaAppendInterleave t ts r ps) + `asTypeOf` + const ((map (aux0 t id p (ts ++ r)) (fromTo 0 (length p - 1)) ++ []) ++ map (flipAppend r) (mapInterleave t ts ps [])) + (interleave t (ts ++ r) p []) + `asTypeOf` + const ((map (flipAppend r) (map (aux0 t id p ts) (fromTo 0 (length p - 1))) ++ []) ++ map (flipAppend r) (mapInterleave t ts ps [])) + (lemmaAppendAux0 t p ts r (fromTo 0 (length p - 1))) + `asTypeOf` + const ((map (flipAppend r) (interleave t ts p []) ++ []) ++ map (flipAppend r) (mapInterleave t ts ps [])) + (lemmaAppendId (map (aux0 t id p ts) (fromTo 0 (length p - 1)))) + `asTypeOf` + const (map (flipAppend r) (aux1 t ts [] p) ++ map (flipAppend r) (mapInterleave t ts ps [])) + (lemmaAppendId (map (flipAppend r) (interleave t ts p []))) + `asTypeOf` + const (map (flipAppend r) (aux1 t ts [] p ++ mapInterleave t ts ps [])) + (lemmaMapAppend (flipAppend r) (aux1 t ts [] p) (mapInterleave t ts ps [])) + `asTypeOf` + const (map (flipAppend r) (aux1 t ts [] p ++ concat (map (aux1 t ts []) ps) ++ [])) + (mapInterleave t ts ps []) + `asTypeOf` + const (map (flipAppend r) ((aux1 t ts [] p ++ concat (map (aux1 t ts []) ps)) ++ [])) + (lemmaAppendAssoc (aux1 t ts [] p) (concat (map (aux1 t ts []) ps)) []) + `asTypeOf` + map (flipAppend r) (mapInterleave t ts (p:ps) []) + *** + QED +-} + +{-@ +lemmaAppendAux0 + :: t:a + -> p:[a] + -> ts:[a] + -> r:[a] + -> xs:[Int] + -> { map (aux0 t id p (ts ++ r)) xs == map (flipAppend r) (map (aux0 t id p ts) xs) } +@-} +lemmaAppendAux0 :: a -> [a] -> [a] -> [a] -> [Int] -> () +lemmaAppendAux0 t p ts r [] = () +lemmaAppendAux0 t p ts r (x:xs) = + lemmaAppendAux0 t p ts r xs + ? lemmaAppendAssoc (insertAt x t p) ts r + +-- | The refinement predicate in the return type is equivalent to +-- +-- > [ interleave (ts!!n) (drop (n+1) ts) xs [] +-- > | n <- [i..j] +-- > , xs <- permutations (reverse (take n ts) ++ t:is) +-- > ] +-- > +-- > = +-- > +-- > [ interleave ((t:ts)!!n) (drop (n+1) (t:ts)) xs [] +-- > | n <- [i+1..j+1] +-- > , xs <- permutations (reverse (take n (t:ts)) ++ is) +-- > ] +-- + +{-@ +lemmaMapAux2 + :: t:a + -> ts:[a] + -> is:[a] + -> { i:Int | 0 <= i } + -> { j:Int | j < len ts } + -> { map (aux2 ts (t:is)) (fromTo i j) + == map (aux2 (t:ts) is) (fromTo (i+1) (j+1)) + } / [j-i+1] +@-} +lemmaMapAux2 :: a -> [a] -> [a] -> Int -> Int -> () +lemmaMapAux2 t ts is i j = + if i<=j then + lemmaMapAux2 t ts is (i+1) j + `const` lemmaAppendAssoc (reverse (take i ts)) [t] is + +{- + map (aux2 ts (t:is)) (fromTo i j) + === + aux2 ts (t:is) i : map (aux2 ts (t:is)) (fromTo (i+1) j) + === + const (aux2 ts (t:is) i : map (aux2 (t:ts) is) (fromTo (i+2) (j+1))) + (lemmaMapAux2 t ts is (i+1) j) + === + (mapInterleave (ts!!i) (drop (i+1) ts) (permutations (reverse (take i ts) ++ (t:is))) [] + : map (aux2 (t:ts) is) (fromTo (i+2) (j+1)) + ) + === + (mapInterleave (ts!!i) (drop (i+1) ts) (permutations (reverse (take i ts) ++ [t] ++ is)) [] + : map (aux2 (t:ts) is) (fromTo (i+2) (j+1)) + ) + === + const (mapInterleave (ts!!i) (drop (i+1) ts) (permutations ((reverse (take i ts) ++ [t]) ++ is)) [] + : map (aux2 (t:ts) is) (fromTo (i+2) (j+1)) + ) + (lemmaAppendAssoc (reverse (take i ts)) [t] is) + === + (mapInterleave ((t:ts)!!(i+1)) (drop (i+2) (t:ts)) (permutations (reverse (take (i+1) (t:ts)) ++ is)) [] + : map (aux2 (t:ts) is) (fromTo (i+2) (j+1)) + ) + === + (aux2 (t:ts) is (i+1) : map (aux2 (t:ts) is) (fromTo (i+2) (j+1)) + *** + QED + -} + else + () diff --git a/tests/pos/AbsPosTest.hs b/tests/pos/AbsPosTest.hs new file mode 100644 index 0000000000..8d0320193d --- /dev/null +++ b/tests/pos/AbsPosTest.hs @@ -0,0 +1,17 @@ +module AbsPosTest where + +{-@ f :: Int -> {n:Int | n >= 0} @-} +f :: Int -> Int +f x = abs x + +{-@ g :: {n:Int | n >= 0} -> {m:Int | m = n} @-} +g :: Int -> Int +g x = abs x + +{-@ h :: {n:Int | n < 0} -> {m:Int | m = -n} @-} +h :: Int -> Int +h x = abs x + +{-@ f2 :: Int -> {n:Int | n >= 0} @-} +f2 :: Int -> Int +f2 x = abs x diff --git a/tests/pos/Elim_ex_let.hs b/tests/pos/Elim_ex_let.hs index c554d8b787..dad884bcf2 100644 --- a/tests/pos/Elim_ex_let.hs +++ b/tests/pos/Elim_ex_let.hs @@ -5,9 +5,9 @@ module Elim_ex_let (prop) where import LiquidHaskell -[lq| type Nat = {v:Int | 0 <= v} |] +[lq| type MyNat = {v:Int | 0 <= v} |] -[lq| prop :: a -> Nat |] +[lq| prop :: a -> MyNat |] prop _ = let x _ = let y = 0 in y - 1 diff --git a/tests/pos/ExponentialPosTest.hs b/tests/pos/ExponentialPosTest.hs new file mode 100644 index 0000000000..066bf3ccb8 --- /dev/null +++ b/tests/pos/ExponentialPosTest.hs @@ -0,0 +1,17 @@ +module ExponentialPosTest where + +{-@ ex1 :: Float -> Nat -> Float @-} +ex1 :: Float -> Int -> Float +ex1 x y = x ^ y + +{-@ ex2 :: {n:Float | n /= 0} -> Nat -> Float @-} +ex2 :: Float -> Int -> Float +ex2 x y = 5 / (x ^ y) + +{-@ ex3 :: Float -> {n:Nat | n == 0} -> {v:Float | v == 1} @-} +ex3 :: Float -> Int -> Float +ex3 x y = 1 / (x ^ y) + +{-@ ex4 :: {b:Float | b == 0} -> {n:Nat | n /= 0} -> {v:Float | v == 0} @-} +ex4 :: Float -> Int -> Float +ex4 x y = x ^ y diff --git a/tests/pos/LNot.hs b/tests/pos/LNot.hs new file mode 100644 index 0000000000..729eff0a0f --- /dev/null +++ b/tests/pos/LNot.hs @@ -0,0 +1,30 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +module LNot where +import Prelude hiding (any, all, filter, nub, foldr, flip) + + + +{-@ lemma_all_ex_not :: f:(a->Bool) -> ls:[a] -> { (bnot (any f ls)) == all (bnot . f) ls} @-} +lemma_all_ex_not :: (a->Bool) -> [a] -> () +lemma_all_ex_not f [] = () +lemma_all_ex_not f (x:xs) + | f x = lemma_all_ex_not f xs +lemma_all_ex_not f (x:xs) + | (bnot . f) x = lemma_all_ex_not f xs + +{-@ reflect any @-} +any :: (a -> Bool) -> [a] -> Bool +any _ [] = False +any p (x:xs) = if p x then True else any p xs + +{-@ reflect all @-} +all :: (a -> Bool) -> [a] -> Bool +all _ [] = True +all p (x:xs) = if p x then all p xs else False + +{-@ reflect bnot @-} +{-@ bnot :: x:Bool -> {v:Bool | v = not x} @-} +bnot :: Bool -> Bool +bnot True = False +bnot False = True \ No newline at end of file diff --git a/tests/pos/Permutation.hs b/tests/pos/Permutation.hs index 92356113a7..c78679cd58 100644 --- a/tests/pos/Permutation.hs +++ b/tests/pos/Permutation.hs @@ -1,3 +1,8 @@ +-- | This module contains a termination proof of Data.List.permutations. +-- +-- See tests/ple/pos/Permutations.hs for a proof of the laziness +-- requirement. +-- module Permutation () where {-@ permutations :: ts:[a] -> [[a]] / [(len ts), 1, 0] @-} @@ -13,4 +18,3 @@ perms (t:ts) is = foldr interleave (perms ts (t:is)) (permutations is) interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r in (y:us, f (t:y:us) : zs) - diff --git a/tests/pos/T2091.hs b/tests/pos/T2091.hs new file mode 100644 index 0000000000..4f2e99266a --- /dev/null +++ b/tests/pos/T2091.hs @@ -0,0 +1,23 @@ +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE GADTs #-} + +module T2091 where + +import Prelude (Bool(..)) +import GHC.TypeLits + +data Vec (n :: Nat) a where + VCons :: a -> Vec n a -> Vec (1 + n) a + VNil :: Vec 0 a + +{-@ ys0 :: Vec _ Bool @-} +ys0 :: Vec 0 Bool +ys0 = VNil + +type Vec1 = Vec 1 +{-@ type T = {v:Bool | v } @-} +{-@ ys1 :: Vec _ T @-} +ys1 :: Vec 1 Bool +ys1 = VCons True VNil diff --git a/tests/pos/T2093.hs b/tests/pos/T2093.hs new file mode 100644 index 0000000000..6273cf5f97 --- /dev/null +++ b/tests/pos/T2093.hs @@ -0,0 +1,26 @@ +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE GADTs #-} +{-@ embed GHC.Natural.Natural as int @-} +{-@ embed GHC.Num.Natural.Natural as int @-} +{-@ LIQUID "--no-totality" @-} + +module T2093 where + +import Prelude +import GHC.TypeLits +import GHC.Natural + +newtype Unsigned (n :: Nat) = U Natural +instance KnownNat n => Num (Unsigned n) + +instance Ord (Unsigned n) +instance Eq (Unsigned n) + +type Hex = Unsigned 4 +{-@ type Digit = {v : Hex | v <= 9 } @-} + +{-@ x :: Digit @-} +x :: Hex +x = 3 \ No newline at end of file diff --git a/tests/pos/T2096.hs b/tests/pos/T2096.hs new file mode 100644 index 0000000000..e501b133ed --- /dev/null +++ b/tests/pos/T2096.hs @@ -0,0 +1,29 @@ +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE GADTs #-} +{-@ embed GHC.Natural.Natural as int @-} +{-@ LIQUID "--no-totality" @-} + +module T2096 where + +import Prelude +import GHC.TypeLits +import GHC.Natural +import Unsafe.Coerce + +-- See https://github.com/ucsd-progsys/liquidhaskell/issues/2095 +workaround :: (n1 + 1) ~ (n2 + 1) => Vec n1 a -> Vec n2 a +workaround = unsafeCoerce + +data Vec (n :: Nat) a where + Nil :: Vec 0 a + Cons :: a -> Vec n a -> Vec (n + 1) a + +foo :: Vec n a -> Vec n a -> Vec n a +foo Nil Nil = Nil +foo (Cons x xs) (Cons y ys) = Cons x zs + where + zs = foo xs $ workaround ys +foo _ _ = undefined + diff --git a/tests/pos/T716.hs b/tests/pos/T716.hs index 1fcd6aa2c1..2a199151eb 100644 --- a/tests/pos/T716.hs +++ b/tests/pos/T716.hs @@ -24,8 +24,8 @@ import GHC.Word {-@ data Word = W# {w :: {v:Word# | undefinedOffset v >= 64}} @-} -grabWord16_SAFE (Ptr ip#) = let x = byteSwap16# (indexWord16OffAddr# ip# 0#) in W# (narrow16Word# x) +grabWord16_SAFE (Ptr ip#) = let x = byteSwap16# (indexWordOffAddr# ip# 0#) in W# (narrow16Word# x) -grabWord16_UNSAFE (Ptr ip#) = W# (narrow16Word# (byteSwap16# (indexWord16OffAddr# ip# 0#))) +grabWord16_UNSAFE (Ptr ip#) = W# (narrow16Word# (byteSwap16# (indexWordOffAddr# ip# 0#))) diff --git a/tests/pos/UnboxedTuples.hs b/tests/pos/UnboxedTuples.hs index 2ea0b7787e..d9afad484b 100644 --- a/tests/pos/UnboxedTuples.hs +++ b/tests/pos/UnboxedTuples.hs @@ -4,5 +4,5 @@ module UnboxedTuples where import GHC.Int -foo = let (# x, y #) = (# 1#, 1# #) in I8# x +foo = let (# x, y #) = (# 1#, 1# #) in I# x diff --git a/tests/pos/UnboxedTuplesAndTH.hs b/tests/pos/UnboxedTuplesAndTH.hs index 4c3a2a7013..07d82cfbd2 100644 --- a/tests/pos/UnboxedTuplesAndTH.hs +++ b/tests/pos/UnboxedTuplesAndTH.hs @@ -7,7 +7,7 @@ module UnboxedTuplesAndTH where import GHC.Int import Language.Haskell.TH.Syntax -foo = let (# x, y #) = (# 1#, 1# #) in I8# x +foo = let (# x, y #) = (# 1#, 1# #) in I# x bar :: Q Exp bar = [| 1 + 2|] diff --git a/tests/relational/neg/AppNull.hs b/tests/relational/neg/AppNull.hs index c2ab7eb201..ba8485f82a 100644 --- a/tests/relational/neg/AppNull.hs +++ b/tests/relational/neg/AppNull.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module AppNull where import Prelude hiding ( null ) diff --git a/tests/relational/neg/Fib.hs b/tests/relational/neg/Fib.hs index 3291a9aed6..c4cde44381 100644 --- a/tests/relational/neg/Fib.hs +++ b/tests/relational/neg/Fib.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module Fib where data N = Z | S N @@ -16,7 +16,7 @@ leq _ Z = False leq (S n) (S m) = leq n m {-@ relational fib ~ fib :: {n1:_ -> _ ~ n2:_ -> _ - | Fixme.leq n1 n2 :=> r1 < r2 }@-} + | Fib.leq n1 n2 :=> r1 < r2 }@-} diff --git a/tests/relational/neg/FunReft.hs b/tests/relational/neg/FunReft.hs index 978498282c..288cc2c800 100644 --- a/tests/relational/neg/FunReft.hs +++ b/tests/relational/neg/FunReft.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module FunReft where {-@ foo :: { v:(x1:Int -> Int) | x1 /= x1 } @-} foo :: Int -> Int diff --git a/tests/relational/neg/IncrLet.hs b/tests/relational/neg/IncrLet.hs index 5f69c561b7..ef78ee19d4 100644 --- a/tests/relational/neg/IncrLet.hs +++ b/tests/relational/neg/IncrLet.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module IncrLet where incr :: Int -> Int incr = let one = 1 in (+ one) diff --git a/tests/relational/neg/Null.hs b/tests/relational/neg/Null.hs index 78c74f8f29..fc02fdd3c7 100644 --- a/tests/relational/neg/Null.hs +++ b/tests/relational/neg/Null.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module Null where import Prelude hiding ( null ) diff --git a/tests/relational/neg/PolyNull.hs b/tests/relational/neg/PolyNull.hs index c04172a824..289ada15d5 100644 --- a/tests/relational/neg/PolyNull.hs +++ b/tests/relational/neg/PolyNull.hs @@ -1,12 +1,12 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module PolyNull where import Prelude hiding ( null ) data List a = Nil | Cons a (List a) {-@ measure size @-} -{-@ size :: l:List a -> {v:Nat | ((v == 0) <=> (is$Fixme.Nil l)) } @-} +{-@ size :: l:List a -> {v:Nat | ((v == 0) <=> (is$PolyNull.Nil l)) } @-} size :: List a -> Int size Nil = 0 size (Cons _ xs) = 1 + size xs diff --git a/tests/relational/neg/Prims.hs b/tests/relational/neg/Prims.hs index 9b2785b534..a574ce9114 100644 --- a/tests/relational/neg/Prims.hs +++ b/tests/relational/neg/Prims.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module Prims where i :: Int i = 0 diff --git a/tests/relational/neg/Rec.hs b/tests/relational/neg/Rec.hs index dc67d607c2..22b14eca0b 100644 --- a/tests/relational/neg/Rec.hs +++ b/tests/relational/neg/Rec.hs @@ -1,5 +1,5 @@ {-@ LIQUID "--expect-any-error" @-} -module Fixme where +module Rec where f :: Int -> Int f x = if x <= 0 then 0 else 1 + f (x - 1) diff --git a/tests/relational/pos/Abs_relToUn.hs b/tests/relational/pos/Abs_relToUn.hs new file mode 100644 index 0000000000..9ff2b651a5 --- /dev/null +++ b/tests/relational/pos/Abs_relToUn.hs @@ -0,0 +1,9 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module Abs_relToUn (module Abs_relToUn) where + +import Abs +import GHC.Classes +import GHC.Types +import Prelude diff --git a/tests/relational/pos/ApSum.hs b/tests/relational/pos/ApSum.hs index 6d2c78431e..a7e2b94bad 100644 --- a/tests/relational/pos/ApSum.hs +++ b/tests/relational/pos/ApSum.hs @@ -1,4 +1,4 @@ -module Fixme where +module ApSum where apsum :: Int -> Int -> Int apsum n a = if n <= 0 then a else a + n + apsum (n - 1) a diff --git a/tests/relational/pos/AppNull.hs b/tests/relational/pos/AppNull.hs index 690be9748d..13559f6134 100644 --- a/tests/relational/pos/AppNull.hs +++ b/tests/relational/pos/AppNull.hs @@ -1,4 +1,6 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} + +module AppNull where import Prelude hiding ( null ) diff --git a/tests/relational/pos/BuiltInFib.hs b/tests/relational/pos/BuiltInFib.hs index 105f5b70d7..becd8eaba4 100644 --- a/tests/relational/pos/BuiltInFib.hs +++ b/tests/relational/pos/BuiltInFib.hs @@ -1,4 +1,4 @@ -module Fixme where +module BuiltInFib where fib :: Int -> Int fib x | x <= 1 = 1 diff --git a/tests/relational/pos/BuiltInNull.hs b/tests/relational/pos/BuiltInNull.hs index 2060e3af3d..d6648a9309 100644 --- a/tests/relational/pos/BuiltInNull.hs +++ b/tests/relational/pos/BuiltInNull.hs @@ -1,4 +1,7 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module BuiltInNull where {-@ reflect null' @-} null' :: [Int] -> Bool @@ -6,5 +9,5 @@ null' [] = True null' _ = False {-@ relational null' ~ null' :: { l1:_ -> _ - ~ l2:_ -> _ - | len l1 = len l2 :=> Fixme.null' l1 = Fixme.null' l2 }@-} + ~ l2:_ -> _ + | len l1 = len l2 :=> BuiltInNull.null' l1 = BuiltInNull.null' l2 } @-} diff --git a/tests/relational/pos/Erasure.hs b/tests/relational/pos/Erasure.hs new file mode 100644 index 0000000000..0a6f85dc2c --- /dev/null +++ b/tests/relational/pos/Erasure.hs @@ -0,0 +1,509 @@ +-- +-- Liquidate your assets: reasoning about resource usage in Liquid Haskell. +-- + +{-@ LIQUID "--reflection" @-} + +{-@ infix <*> @-} +{-@ infix @-} +{-@ infix @-} +{-@ infix <\> @-} +{-@ infix <\\> @-} +{-@ infix >>= @-} +{-@ infix =<< @-} +{-@ infix >/= @-} +{-@ infix =/< @-} +{-@ infix >//= @-} +{-@ infix =//< @-} +{-@ infix >\= @-} +{-@ infix =\< @-} +{-@ infix >\\= @-} +{-@ infix =\\< @-} + +module Erasure (module Erasure) where + +import RTick +import Language.Haskell.Liquid.ProofCombinators + +-- +-- Erasing all the library's cost annotations. In practice, we define the +-- erase function, ⟨·⟩, as a set of inference rules. +-- + +-- +-- ⟨t⟩ == x +-- ----------------- +-- ⟨step m t⟩ == x +-- +{-@ assume erase_step :: m:Int -> x:a -> { t:Tick a | erase t == x } -> { erase (step m t) == x } @-} +erase_step :: Int -> a -> Tick a -> Proof +erase_step _ _ _ = () + +-- +-- +-- ----------------- +-- ⟨wait x⟩ == x +-- +{-@ assume erase_wait :: x:a -> { erase (wait x) == x } @-} +erase_wait :: a -> Proof +erase_wait _ = () + +-- +-- +-- ------------------ +-- ⟨waitN n x⟩ == x +-- +{-@ assume erase_waitN :: n:Int -> x:a -> { erase (waitN n x) == x } @-} +erase_waitN :: Int -> a -> Proof +erase_waitN _ _ = () + +-- +-- +-- ------------- +-- ⟨go x⟩ == x +-- +{-@ assume erase_go :: x:a -> { erase (go x) == x } @-} +erase_go :: a -> Proof +erase_go _ = () + +-- +-- +-- ---------------- +-- ⟨goN n x⟩ == x +-- +{-@ assume erase_goN :: n:Int -> x:a -> { erase (goN n x) == x } @-} +erase_goN :: Int -> a -> Proof +erase_goN _ _ = () + +-- +-- ⟨t⟩ == x +-- --------------------- +-- ⟨fmap f t⟩ == f x +-- +{-@ assume erase_fmap :: f:(a -> b) -> x:a -> { t:Tick a | erase t == x } -> { erase (fmap f t) == f x } @-} +erase_fmap :: (a -> b) -> a -> Tick a -> Proof +erase_fmap _ _ _ = () + +-- +-- ⟨t⟩ == x +-- --------------------- +-- ⟨wmap f t⟩ == f x +-- +{-@ assume erase_wmap :: f:(a -> b) -> x:a -> { t:Tick a | erase t == x } -> { erase (wmap f t) == f x } @-} +erase_wmap :: (a -> b) -> a -> Tick a -> Proof +erase_wmap _ _ _ = () + +-- +-- ⟨t⟩ == x +-- ----------------------- +-- ⟨wmapN n f t⟩ == f x +-- +{-@ assume erase_wmapN + :: m:Int + -> f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { erase (wmapN m f t) == f x } +@-} +erase_wmapN :: Int -> (a -> b) -> a -> Tick a -> Proof +erase_wmapN _ _ _ _ = () + +-- +-- ⟨t⟩ == x +-- --------------------- +-- ⟨gmap f t⟩ == f x +-- +{-@ assume erase_gmap + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { erase (gmap f t) == f x } +@-} +erase_gmap :: (a -> b) -> a -> Tick a -> Proof +erase_gmap _ _ _ = () + +-- +-- ⟨t⟩ == x +-- ---------------------- +-- ⟨gmap n f t⟩ == f x +-- +{-@ assume erase_gmapN + :: m:Int + -> f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { erase (gmapN m f t) == f x } +@-} +erase_gmapN :: Int -> (a -> b) -> a -> Tick a -> Proof +erase_gmapN _ _ _ _ = () + +-- +-- +-- ---------------- +-- ⟨pure x⟩ == x +-- +{-@ assume erase_pure :: x:a -> { erase (pure x) == x } @-} +erase_pure :: a -> Proof +erase_pure _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------- +-- ⟨tf <*> tx⟩ == f x +-- +{-@ assume erase_app + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (tf <*> tx) == f x } +@-} +erase_app :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_app _ _ _ _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------- +-- ⟨tf tx⟩ == f x +-- +{-@ assume erase_wapp + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (tf tx) == f x } +@-} +erase_wapp :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_wapp _ _ _ _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------- +-- ⟨tf tx⟩ == f x +-- +{-@ assume erase_wwapp + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (tf tx) == f x } +@-} +erase_wwapp :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_wwapp _ _ _ _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------- +-- ⟨tf <\> tx⟩ == f x +-- +{-@ assume erase_gapp + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (tf <\> tx) == f x } +@-} +erase_gapp :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_gapp _ _ _ _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------- +-- ⟨tf <\\> tx⟩ == f x +-- +{-@ assume erase_ggapp + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (tf <\\> tx) == f x } +@-} +erase_ggapp :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_ggapp _ _ _ _ = () + +-- +-- ⟨tx⟩ == x ⟨ty⟩ == y +-- ------------------------------- +-- ⟨liftA2 f tx ty⟩ == f x y +-- +{-@ assume erase_liftA2 + :: f:(a -> b -> c) + -> x:a + -> y:b + -> { tx:Tick a | erase tx == x } + -> { ty:Tick b | erase ty == y } + -> { erase (liftA2 f tx ty) == f x y } +@-} +erase_liftA2 :: (a -> b -> c) -> a -> b -> Tick a -> Tick b -> Proof +erase_liftA2 _ _ _ _ _ = () + +-- +-- +-- ------------------ +-- ⟨return x⟩ == x +-- +{-@ assume erase_return :: x:a -> { erase (return x) == x } @-} +erase_return :: a -> Proof +erase_return _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t >>= g⟩ == f x +-- +{-@ assume erase_bind + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (t >>= g) == f x } +@-} +erase_bind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_bind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t =<< g⟩ == f x +-- +{-@ assume erase_flipped_bind + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (g =<< t) == f x } +@-} +erase_flipped_bind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_flipped_bind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨eqBind n t g⟩ == f x +-- +{-@ assume erase_eqBind + :: n:Int + -> f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (eqBind n t g) == f x } +@-} +erase_eqBind :: Int -> (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_eqBind _ _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨leqBind n t g⟩ == f x +-- +{-@ assume erase_leqBind + :: n:Int + -> f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (leqBind n t g) == f x } +@-} +erase_leqBind :: Int -> (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_leqBind _ _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨geqBind n t g⟩ == f x +-- +{-@ assume erase_geqBind + :: n:Int + -> f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (geqBind n t g) == f x } +@-} +erase_geqBind :: Int -> (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_geqBind _ _ _ _ _ = () + +-- +-- ⟨tf⟩ == f ⟨tx⟩ == x +-- ------------------------ +-- ⟨ap tf tx⟩ == f x +-- +{-@ assume erase_ap + :: f:(a -> b) + -> x:a + -> { tf:Tick (a -> b) | erase tf == f } + -> { tx:Tick a | erase tx == x } + -> { erase (ap tf tx) == f x } +@-} +erase_ap :: (a -> b) -> a -> Tick (a -> b) -> Tick a -> Proof +erase_ap _ _ _ _ = () + +-- +-- ⟨t⟩ == x +-- --------------------- +-- ⟨liftM f t⟩ == f x +-- +{-@ assume erase_liftM + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { erase (liftM f t) == f x } +@-} +erase_liftM :: (a -> b) -> a -> Tick a -> Proof +erase_liftM _ _ _ = () + +-- +-- ⟨tx⟩ == x ⟨ty⟩ == y +-- ------------------------------- +-- ⟨liftM2 f tx ty⟩ == f x y +-- +{-@ assume erase_liftM2 + :: f:(a -> b -> c) + -> x:a + -> y:b + -> { tx:Tick a | erase tx == x } + -> { ty:Tick b | erase ty == y } + -> { erase (liftM2 f tx ty) == f x y } +@-} +erase_liftM2 :: (a -> b -> c) -> a -> b -> Tick a -> Tick b -> Proof +erase_liftM2 _ _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t >/= g⟩ == f x +-- +{-@ assume erase_wbind + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (t >/= g) == f x } +@-} +erase_wbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_wbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t =/< g⟩ == f x +-- +{-@ assume erase_flipped_wbind + :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (g =/< t) == f x } +@-} +erase_flipped_wbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_flipped_wbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t >//= g⟩ == f x +-- +{-@ assume erase_wwbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (t >//= g) == f x } +@-} +erase_wwbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_wwbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t =//< g⟩ == f x +-- +{-@ assume erase_flipped_wwbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (g =//< t) == f x } +@-} +erase_flipped_wwbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_flipped_wwbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t >\= g⟩ == f x +-- +{-@ assume erase_gbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (t >\= g) == f x } +@-} +erase_gbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_gbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t =\< g⟩ == f x +-- +{-@ assume erase_flipped_gbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (g =\< t) == f x } +@-} +erase_flipped_gbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_flipped_gbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t >\\= g⟩ == f x +-- +{-@ assume erase_ggbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (t >\\= g) == f x } +@-} +erase_ggbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_ggbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x ⟨g x⟩ == f x +-- ---------------------------- +-- ⟨t =\\< g⟩ == f x +-- +{-@ assume erase_flipped_ggbind :: f:(a -> b) + -> x:a + -> { t:Tick a | erase t == x } + -> { g:(a -> Tick b) | erase (g x) == f x } + -> { erase (g =\\< t) == f x } +@-} +erase_flipped_ggbind :: (a -> b) -> a -> Tick a -> (a -> Tick b) -> Proof +erase_flipped_ggbind _ _ _ _ = () + +-- +-- ⟨t⟩ == x +-- -------------------- +-- ⟨⟨pay n t⟩⟩ == x +-- +{-@ assume erase_pay :: n:Int + -> x:a + -> { t:Tick a | n <= tcost t && erase t == x } + -> { erase (erase (pay n t)) == x } +@-} +erase_pay :: Int -> a -> Tick a -> Proof +erase_pay _ _ _ = () + +------------------------------------------------------------------------------- +-- | Helper functions: +------------------------------------------------------------------------------- + +-- +-- Inference rules without any premises are clearly equivalent to 'tval'. +-- +{-@ reflect erase @-} +{-@ erase :: Tick a -> a @-} +erase :: Tick a -> a +erase (Tick _ x) = x diff --git a/tests/relational/pos/Fib.hs b/tests/relational/pos/Fib.hs index 94284161b5..eec8161ab1 100644 --- a/tests/relational/pos/Fib.hs +++ b/tests/relational/pos/Fib.hs @@ -1,4 +1,6 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} + +module Fib where data N = Z | S N diff --git a/tests/relational/pos/FunReft.hs b/tests/relational/pos/FunReft.hs index d63128d599..0a3dbecaf8 100644 --- a/tests/relational/pos/FunReft.hs +++ b/tests/relational/pos/FunReft.hs @@ -1,4 +1,4 @@ -module Fixme where +module FunReft where {-@ foo :: { v:(x1:Int -> Int) | x1 == x1 } @-} foo :: Int -> Int diff --git a/tests/relational/pos/IncrF.hs b/tests/relational/pos/IncrF.hs index b3877a858e..2e50da85eb 100644 --- a/tests/relational/pos/IncrF.hs +++ b/tests/relational/pos/IncrF.hs @@ -1,5 +1,5 @@ -module Fixme where +module IncrF where {-@ add :: x:Int -> y:Int -> {v:Int|v = x + y} @-} add :: Int -> Int -> Int diff --git a/tests/relational/pos/IncrLet.hs b/tests/relational/pos/IncrLet.hs index 1312c95fa4..073508c617 100644 --- a/tests/relational/pos/IncrLet.hs +++ b/tests/relational/pos/IncrLet.hs @@ -1,4 +1,6 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} + +module IncrLet where import GHC.Types @@ -14,7 +16,7 @@ incr = plus 1 ~ x2:Int -> Int | x1 < x2 :=> r1 x1 < r2 x2 } @-} --- {-@ relIncrIncr_rtt :: x1:GHC.Types.Int -> x2:{VV : GHC.Types.Int | x1 < x2} -> {VV : () | Fixme.incr x1 < Fixme.incr x2} @-} +-- {-@ relIncrIncr_rtt :: x1:GHC.Types.Int -> x2:{VV : GHC.Types.Int | x1 < x2} -> {VV : () | IncrLet.incr x1 < IncrLet.incr x2} @-} -- relIncrIncr_rtt :: GHC.Types.Int -> GHC.Types.Int -> () -- relIncrIncr_rtt = () (() () ()) (() () ()) diff --git a/tests/relational/pos/Lists.hs b/tests/relational/pos/Lists.hs new file mode 100644 index 0000000000..7c9bfdd0aa --- /dev/null +++ b/tests/relational/pos/Lists.hs @@ -0,0 +1,197 @@ + +-- +-- Liquidate your assets: reasoning about resource usage in Liquid Haskell. +-- + +{-@ LIQUID "--reflection" @-} + +module Lists (module Lists) where + +import Prelude hiding + ( Functor(..) + , Applicative(..) + , Monad(..) + , drop + , length + , take + ) + +import RTick +import Language.Haskell.Liquid.ProofCombinators +import Erasure + +{-@ type OList a = [a]<{\h x -> h <= x }> @-} +{-@ type List a = [a] @-} + +-- +-- Some functions on lists. Throughout this file the cost model is the number +-- of recursive calls. +-- + +------------------------------------------------------------------------------- +-- | Measures: +------------------------------------------------------------------------------- + +{-@ measure length @-} +{-@ length :: [a] -> Nat @-} +length :: [a] -> Int +length [] = 0 +length (_ : xs) = 1 + length xs + +------------------------------------------------------------------------------- +-- | Functions: +------------------------------------------------------------------------------- + +-- +-- Constructing lists: +-- + +-- +-- We redefine ':' because Liquid Haskell doesn't like @(x:)@ in some +-- proofs. +-- +{-@ reflect cons @-} +{-@ cons :: forall

a -> Bool>. x:a -> xs:[a

]

+ -> { zs:[a]

| 1 + length xs == length zs } +@-} +cons :: a -> [a] -> [a] +cons x xs = x : xs + +-- +-- Taking and dropping: +-- + +{-@ reflect takeLE @-} +{-@ takeLE :: n:Nat -> { xs:[a] | n <= length xs } + -> { t:Tick { zs:[a] | n == length zs } | tcost t == n } +@-} +takeLE :: Int -> [a] -> Tick [a] +takeLE _ [] = pure [] +takeLE 0 _ = pure [] +takeLE n (x : xs) = pure (cons x) takeLE (n - 1) xs + +{-@ reflect dropLE @-} +{-@ dropLE :: n:Nat -> { xs:[a] | n <= length xs } + -> { t:Tick { zs:[a] | length xs - n == length zs } | tcost t == n } +@-} +dropLE :: Int -> [a] -> Tick [a] +dropLE _ [] = pure [] +dropLE 0 xs = pure xs +dropLE n (_ : xs) = step 1 (dropLE (n - 1) xs) + +------------------------------------------------------------------------------- +-- | Erasure proofs: +------------------------------------------------------------------------------- +-- +-- We prove that erasing the annotations from 'takeLE' and 'dropLE' +-- returns the standard 'take' and 'drop' functions. +-- + +-- Functions: ----------------------------------------------------------------- + +{-@ reflect take @-} +{-@ take :: n:Nat -> { xs:[a] | n <= length xs } -> {o:[a] | length o == n } @-} +take :: Int -> [a] -> [a] +take _ [] = [] +take 0 _ = [] +take n (x : xs) = x : take (n - 1) xs + +{-@ reflect drop @-} +{-@ drop :: n:Nat -> { xs:[a] | n <= length xs } -> {o:[a] | length o == length xs - n }@-} +drop :: Int -> [a] -> [a] +drop _ [] = [] +drop 0 xs = xs +drop n (_ : xs) = drop (n - 1) xs + +-- Proofs: -------------------------------------------------------------------- + +{-@ takeLE_erase :: n:Nat -> { xs:[a] | n <= length xs } + -> { erase (takeLE n xs) == take n xs } +@-} +takeLE_erase :: Int -> [a] -> Proof +takeLE_erase n [] + = erase (takeLE n []) + -- { defn. of takeLE } + === erase (pure []) + ? erase_pure [] + === [] + -- { defn. of take } + === take n [] + *** QED +takeLE_erase 0 xs + = erase (takeLE 0 xs) + -- { defn. of takeLE } + === erase (pure []) + ? erase_pure [] + === [] + -- { defn. of take } + === take 0 xs + *** QED +takeLE_erase n (x : xs) + = erase (takeLE n (x : xs)) + -- { defn. of takeLE } + === tval (pure (cons x) takeLE (n - 1) xs) + ? takeLE_erase (n - 1) xs + ? erase_pure (cons x) + ? erase_wapp (cons x) (take (n - 1) xs) (pure (cons x)) (takeLE (n - 1) xs) + === cons x (take (n - 1) xs) + -- { defn. of cons } + === x : take (n - 1) xs + -- { defn. of take } + === take n (x : xs) + *** QED + +{-@ dropLE_erase :: n:Nat -> { xs:[a] | n <= length xs } + -> { erase (dropLE n xs) == drop n xs } +@-} +dropLE_erase :: Int -> [a] -> Proof +dropLE_erase n [] + = erase (dropLE n []) + -- { defn. of dropLE } + === erase (pure []) + ? erase_pure [] + === [] + -- { defn. of drop } + === drop n [] + *** QED +dropLE_erase 0 xs + = erase (dropLE 0 xs) + -- { defn. of dropLE } + === erase (pure xs) + ? erase_pure xs + === xs + -- { defn. of drop } + === drop 0 xs + *** QED +dropLE_erase n (x : xs) + = erase (dropLE n (x : xs)) + -- { defn. of dropLE } + === erase (step 1 (dropLE (n - 1) xs)) + ? dropLE_erase (n - 1) xs + ? erase_step 1 (drop (n - 1) xs) (dropLE (n - 1) xs) + === drop n (x : xs) + *** QED + + +data P a b = P { left :: a, right :: b} +{-@ data P a b

b -> Bool> = P {left :: a, right :: b

}@-} +{-@ reflect split @-} +split :: [a] -> P [a] [a] +{- split + :: x:[a] + -> P <{\l r -> (2 + <= length x => + (length l < length x && length r < length x)) + && length l + length r + == length x && (((length x) mod 2 == 0 ) + => (length l == length x / 2 && length r + == length x / 2))}> [a] [a] +@-} +{-@ split :: x:[a] + -> {p:P [a] [a] + | (2 <= length x => (length (left p) < length x && length (right p) < length x)) + && length (left p) + length (right p) == length x + && (((length x) mod 2 == 0 ) + => (length (left p) == length x / 2 && length (right p) == length x / 2))} @-} +split xs = P (take n xs) (drop n xs) + where n = length xs `div` 2 \ No newline at end of file diff --git a/tests/relational/pos/Log2.hs b/tests/relational/pos/Log2.hs new file mode 100644 index 0000000000..3c452207c3 --- /dev/null +++ b/tests/relational/pos/Log2.hs @@ -0,0 +1,66 @@ +module Log2 (module Log2) where + +import Language.Haskell.Liquid.ProofCombinators (Proof) + +assumption :: Proof +assumption = () +-- +-- Define an abstract measure called 'log' +-- LH knows nothing about its implementation +-- +{-@ measure log :: a -> a @-} + +-- +-- log_2 rounded to the nearest integer +-- +{-@ assume log :: x:Int -> {v:Int | v == log x } @-} +log :: Int -> Int +log x = round (logBase 2 (fromIntegral x :: Double)) + + +-- +-- Assume that log_2 1 == 0 +-- +{-@ assume logOne :: { log 1 == 0 } @-} +logOne :: Proof +logOne = assumption +-- +-- Assume that log_2 == 1 +-- +{-@ assume logTwo :: { log 2 == 1 } @-} +logTwo :: Proof +logTwo = assumption + + +{-@ assume logNat :: x:{ Int | 0 <= x } -> { 0 <= log x } @-} +logNat :: Int -> Proof +logNat _ = assumption + +{-@ assume logPos :: x:{ Int | 1 < x } -> { 0 < log x } @-} +logPos :: Int -> Proof +logPos _ = assumption + +-- +-- Log ratio law: log_b (x / y) == log_b x - log_b y +-- +{-@ assume logDiv :: x:Int -> y:Int -> {log (x / y) = log x - log y } @-} +logDiv :: Int -> Int -> Proof +logDiv _ _ = assumption + +-- +-- Log ratio law: log_b (x + y) == log_b x + log_b (1+y/x) +-- +{-@ assume logPlus :: x:Int -> y:Int -> {log (x + y) = log x + log (1 + y/x) } @-} +logPlus :: Int -> Int -> Proof +logPlus _ _ = assumption + +plusLog :: Int -> Int -> Int -> Proof +{-@ assume plusLog :: d1:Int -> d2:Int -> d:{Int | 0 < d && d == d1 + d2 } + -> { log d1 + log d2 <= 2 * (log d)} @-} +plusLog _ _ _ = () +{- + log d1 + log d2 +== log (d - d2) + log (d - d1) +== 2 * log d + log (1 - d2/d) + log (1 - d1/d) +<= 2 * log d +-} \ No newline at end of file diff --git a/tests/relational/pos/Map.hs b/tests/relational/pos/Map.hs index fb3bea7d7f..c08472f5a7 100644 --- a/tests/relational/pos/Map.hs +++ b/tests/relational/pos/Map.hs @@ -1,4 +1,5 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +module Map where import Prelude hiding ( map ) diff --git a/tests/relational/pos/Max.hs b/tests/relational/pos/Max.hs index 80da7d9a07..88a0c4445e 100644 --- a/tests/relational/pos/Max.hs +++ b/tests/relational/pos/Max.hs @@ -1,4 +1,4 @@ -module Fixme where +module Max where max :: Int -> Int -> Int max a b = if a < b then b else a diff --git a/tests/relational/pos/Null.hs b/tests/relational/pos/Null.hs index 296f5ef0a1..68d7774bbf 100644 --- a/tests/relational/pos/Null.hs +++ b/tests/relational/pos/Null.hs @@ -1,4 +1,7 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module Null where import Prelude hiding ( null ) diff --git a/tests/relational/pos/PMonad.hs b/tests/relational/pos/PMonad.hs index 99f0f4c681..6613ab49d8 100644 --- a/tests/relational/pos/PMonad.hs +++ b/tests/relational/pos/PMonad.hs @@ -1,3 +1,4 @@ +{-@ LIQUID "--reflection" @-} {-@ LIQUID "--no-totality" @-} module PMonad where diff --git a/tests/relational/pos/PolyNull.hs b/tests/relational/pos/PolyNull.hs index 64e7063b6a..5767458134 100644 --- a/tests/relational/pos/PolyNull.hs +++ b/tests/relational/pos/PolyNull.hs @@ -1,11 +1,12 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +module PolyNull where import Prelude hiding ( null ) data List a = Nil | Cons a (List a) {-@ measure size @-} -{-@ size :: l:List a -> {v:Nat | ((v == 0) <=> (is$Fixme.Nil l)) } @-} +{-@ size :: l:List a -> {v:Nat | ((v == 0) <=> (is$PolyNull.Nil l)) } @-} size :: List a -> Int size Nil = 0 size (Cons _ xs) = 1 + size xs @@ -17,4 +18,4 @@ null _ = False {-@ relational null ~ null :: { l1:List a -> Bool ~ l2:List b -> Bool - | Fixme.size l1 == Fixme.size l2 :=> r1 l1 == r2 l2 } @-} + | PolyNull.size l1 == PolyNull.size l2 :=> r1 l1 == r2 l2 } @-} diff --git a/tests/relational/pos/PowerOf2.hs b/tests/relational/pos/PowerOf2.hs new file mode 100644 index 0000000000..39db01166d --- /dev/null +++ b/tests/relational/pos/PowerOf2.hs @@ -0,0 +1,61 @@ + +{-@ LIQUID "--reflection" @-} + +module PowerOf2 where + +import Language.Haskell.Liquid.ProofCombinators (Proof) + +assumption :: Proof +assumption = () + +-- +-- Define an abstract measure called 'powerOf2' +-- LH knows nothing about its implementation +-- +{-@ measure powerOf2 :: Int -> Bool @-} + +-- +-- Multiplication/division identity law: 2 * (x / 2) == x +-- +{-@ assume timesDiv :: x:{ Int | powerOf2 x } -> { 2 * (x / 2) == x } @-} +timesDiv :: Int -> Proof +timesDiv _ = assumption + +-- +-- Assume that if x is a power of 2 then x / 2 is a power of 2 +-- +{-@ assume powerOf2Div2 :: x:{ Int | powerOf2 x } -> { powerOf2 (x / 2) } @-} +powerOf2Div2 :: Int -> Proof +powerOf2Div2 _ = assumption + +-- +-- Assume that if x is a power of 2 then (x - x / 2) is a power of 2 +-- +{-@ assume powerOf2Div2' :: x:{ Int | powerOf2 x } -> { powerOf2 (x - (x / 2)) } @-} +powerOf2Div2' :: Int -> Proof +powerOf2Div2' _ = assumption + + + +{-@ assume powerOfIsEven :: x:{ Int | powerOf2 x } -> { (x mod 2 == 0) && (2 <= x => (x / 2 < x) && powerOf2 (x / 2)) } @-} +powerOfIsEven :: Int -> Proof +powerOfIsEven _ = assumption +------------------------------------------------------------------------------- + +-- +-- 2^x +-- +{-@ reflect twoToPower @-} +{-@ twoToPower :: Nat -> Nat @-} +twoToPower :: Int -> Int +twoToPower 0 = 1 +twoToPower n = 2 * twoToPower (n - 1) + + +-- Some math assumptions +distributeDiv :: Int -> Int -> Int -> Proof +{-@ assume distributeDiv + :: n:{Int | powerOf2 n} + -> x:Int -> y:Int + -> {(n/2 * (x + 2 * y)) == n * (x/2 + y )} @-} +distributeDiv _ _ _ = () \ No newline at end of file diff --git a/tests/relational/pos/Prims.hs b/tests/relational/pos/Prims.hs index 4e075be2c8..268b846472 100644 --- a/tests/relational/pos/Prims.hs +++ b/tests/relational/pos/Prims.hs @@ -1,4 +1,4 @@ -module Fixme where +module Prims where s :: Int s = 0 diff --git a/tests/relational/pos/ProofCombinators.hs b/tests/relational/pos/ProofCombinators.hs new file mode 100644 index 0000000000..6045b9f903 --- /dev/null +++ b/tests/relational/pos/ProofCombinators.hs @@ -0,0 +1,19 @@ +module ProofCombinators where + +assert :: Bool -> () +{-@ assert :: b:{Bool | b} -> {b} @-} +assert _ = () + +assume :: Bool -> () +{-@ assume assume :: b:Bool -> {b} @-} +assume _ = () + +infixl 3 =*= +{-@ (=*=) :: x:Int -> y:{Int | y == x} -> {v:Int | v == x && v == y} @-} +(=*=) :: Int -> Int -> Int +_ =*= y = y + +infixl 3 =<*= +{-@ (=<*=) :: x:Int -> y:{Int | x <= y } -> {v:Int | v == y} @-} +(=<*=) :: Int -> Int -> Int +_ =<*= y = y diff --git a/tests/relational/pos/R2Dcounting.hs b/tests/relational/pos/R2Dcounting.hs new file mode 100644 index 0000000000..4fb576ef05 --- /dev/null +++ b/tests/relational/pos/R2Dcounting.hs @@ -0,0 +1,71 @@ +{- 2DCount 16/3/24 | Changed on Nov 22 2022 -} +{-# LANGUAGE FlexibleContexts #-} +{-@ LIQUID "--relational-hints" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module R2Dcounting + ( module R2Dcounting ) where + +{-@ infix <*> @-} +{-@ infix : @-} + +import RTick +import Language.Haskell.Liquid.ProofCombinators +import Prelude hiding (return, (>>=), pure, length, (<*>), fmap) + +--- Proof --- +{-@ relational count2Df1 ~ count2Df2 + :: { p1:([Int] -> Bool) -> e1:Int -> l1:[[Int]] -> RTick.Tick Int + ~ p2:([Int] -> Bool) -> e2:Int -> l2:[[Int]] -> RTick.Tick Int + | !(true :=> true) + :=> !(e1 = e2 && p1 = p2) + :=> !(l1 = l2) + :=> RTick.tcost (r1 p1 e1 l1) + <= RTick.tcost (r2 p2 e2 l2) } @-} +--- End --- + +{-@ reflect count2D @-} +count2D :: (Int -> [Int] -> Tick Int) -> ([Int] -> Bool) -> Int -> [[Int]] -> Tick Int +count2D _ _ _ [] = return 0 +count2D find p x (l:m) = + count2D find p x m >>= count2D' (p l) (find x l) + +{-@ reflect count2Df1 @-} +count2Df1 :: ([Int] -> Bool) -> Int -> [[Int]] -> Tick Int +count2Df1 _ _ _ = return 0 +count2Df1 p x (l:m) = count2Df1 p x m >>= count2D' (p l) (find1 x l) + +{-@ reflect count2Df2 @-} +count2Df2 :: ([Int] -> Bool) -> Int -> [[Int]] -> Tick Int +count2Df2 _ _ _ = return 0 +count2Df2 p x (l:m) = count2Df2 p x m >>= count2D' (p l) (find2 x l) + +{-@ reflect count2D' @-} +count2D' :: Bool -> Tick Int -> Int -> Tick Int +count2D' b c r = if b then fmap (plus r) c else return r + +{-@ reflect plus @-} +{-@ plus :: Int -> Int -> Int @-} +plus :: Int -> Int -> Int +plus x y = x + y + +{-@ reflect find1 @-} +find1 :: Int -> [Int] -> Tick Int +{-@ find1 :: Int -> [Int] -> {t:RTick.Tick Int | 0 <= tcost t} @-} +find1 _ [] = return 0 +find1 x (y:ys) + | x == y = return 1 + | otherwise = step 1 (find1 x ys) + +{-@ reflect find2 @-} +{-@ find2 :: Int -> [Int] -> {t:RTick.Tick Int | 0 <= tcost t} @-} +find2 :: Int -> [Int] -> Tick Int +find2 _ [] = return 0 +find2 x (y:ys) = step 1 (eqBind 0 (find2 x ys) (find2Cond (if x == y then 1 else 0))) + +{-@ reflect find2Cond @-} +{-@ find2Cond :: Int -> Int -> {t:RTick.Tick Int | 0 == tcost t} @-} +find2Cond :: Int -> Int -> Tick Int +find2Cond _ 1 = return 1 +find2Cond d _ = return d diff --git a/tests/relational/pos/R2Dcounting_relToUn.hs b/tests/relational/pos/R2Dcounting_relToUn.hs new file mode 100644 index 0000000000..67cda7e690 --- /dev/null +++ b/tests/relational/pos/R2Dcounting_relToUn.hs @@ -0,0 +1,57 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module R2Dcounting_relToUn (module R2Dcounting_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import R2Dcounting +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ count2Df1Count2Df2Theorem :: p1:(lq_tmp$db##0:[GHC.Types.Int] -> GHC.Types.Bool) -> p2:(lq_tmp$db##6:[GHC.Types.Int] -> GHC.Types.Bool) -> p1p2Lemma:(lq_tmp$db##0:[GHC.Types.Int] -> lq_tmp$db##6:[GHC.Types.Int] -> lq_tmp$db##0lq_tmp$db##6Lemma:() -> ()) -> e1:GHC.Types.Int -> e2:GHC.Types.Int -> e1e2Lemma:{VV : () | e1 == e2 + && p1 == p2} -> l1:[[GHC.Types.Int]] -> l2:[[GHC.Types.Int]] -> l1l2Lemma:{VV : () | l1 == l2} -> {VV : () | RTick.tcost (R2Dcounting.count2Df1 p1 e1 l1) <= RTick.tcost (R2Dcounting.count2Df2 p2 e2 l2)} @-} +count2Df1Count2Df2Theorem :: ([GHC.Types.Int] -> GHC.Types.Bool) -> ([GHC.Types.Int] -> GHC.Types.Bool) -> ([GHC.Types.Int] -> [GHC.Types.Int] -> () -> ()) -> GHC.Types.Int -> GHC.Types.Int -> () -> [[GHC.Types.Int]] -> [[GHC.Types.Int]] -> () -> () +count2Df1Count2Df2Theorem p1 p2 p1p2Lemma e1 e2 e1e2Lemma l1 l2 l1l2Lemma = + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (RTick.return x1)) ? (RTick.return x2)) + ) + 0 + 0 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? x1) ? x2) + ) + 0 + 0 + ( {- GOAL: 0 ~ 0 -} + (() ? 0) ? 0 + ) + ) + +{- BARE CORE +\ _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] + _ [Occ=Dead] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (RTick.return x1)) + (RTick.return x2)) + (GHC.Types.I# 0#) + (GHC.Types.I# 0#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 0# 0# (src<.:0:0> ? (? GHC.Tuple.() 0#) 0#)) +-} diff --git a/tests/relational/pos/RBinaryCounters.hs b/tests/relational/pos/RBinaryCounters.hs new file mode 100644 index 0000000000..c1e7e0c70c --- /dev/null +++ b/tests/relational/pos/RBinaryCounters.hs @@ -0,0 +1,109 @@ +{- Counters 26/21/21 -} + +-- +-- Liquidate your assets: reasoning about resource usage in Liquid Haskell.s +-- + +{-@ LIQUID "--relational-hints" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module RBinaryCounters (module RBinaryCounters) where + +import Prelude hiding (return, (>>=), pure, length) +import RTick +import Language.Haskell.Liquid.ProofCombinators +import Lists + +-- +-- Comparing bit flips using relational cost analysis. +-- + +{-@ reflect tt @-} +{-@ tt :: n:Nat -> { zs:[{ v:Bool | v == True }] | n == Lists.length zs } @-} +tt :: Int -> [Bool] +tt 0 = [] +tt n = True : tt (n - 1) + +{-@ reflect ff @-} +{-@ ff :: n:Nat -> { zs:[{ v:Bool | v == False }] | n == Lists.length zs } @-} +ff :: Int -> [Bool] +ff 0 = [] +ff n = False : ff (n - 1) + +dualTTFF :: Int -> Proof +{-@ dualTTFF :: l:Nat -> { dual (ff l) (tt l) } @-} +dualTTFF 0 = () +dualTTFF i = dualTTFF (i - 1) + +{-@ reflect dual @-} +{-@ dual + :: xs:[Bool] + -> { ys:[Bool] | Lists.length xs == Lists.length ys } + -> Bool +@-} +dual :: [Bool] -> [Bool] -> Bool +dual [] [] = True +dual (x : xs) (y : ys) = x /= y && dual xs ys +dual _ _ = True + +{-@ reflect incrN @-} +{-@ incrN :: Nat -> [Bool] -> Tick [Bool] @-} +incrN :: Int -> [Bool] -> Tick [Bool] +incrN 0 xs = return xs +incrN n xs = incr xs >>= incrN (n - 1) + +--- Proof --- +{- relational incr ~ decr :: { xs1:[Bool] -> Tick [Bool] + ~ xs2:[Bool] -> Tick [Bool] + | Lists.length xs1 = Lists.length xs2 && RBinaryCounters.dual xs1 xs2 + :=> RTick.tcost (r1 xs1) = RTick.tcost (r2 xs2) + && RBinaryCounters.dual (RTick.tval (r1 xs1)) (RTick.tval (r2 xs2)) } @-} + +{- relational incrN ~ decrN :: { n1:Nat -> xs1:[Bool] -> Tick [Bool] + ~ n2:Nat -> xs2:[Bool] -> Tick [Bool] + | n1 = n2 :=> Lists.length xs1 = Lists.length xs2 && RBinaryCounters.dual xs1 xs2 + :=> RTick.tcost (r1 n1 xs1) = RTick.tcost (r2 n2 xs2) + && RBinaryCounters.dual (RTick.tval (r1 n1 xs1)) (RTick.tval (r2 n2 xs2)) } @-} + +{- relational incrNff ~ decrNtt + :: { n1: Nat -> m1: Nat -> Tick [Bool] + ~ n2: Nat -> m2: Nat -> Tick [Bool] + | n1 = n2 :=> m1 = m2 :=> RTick.tcost (r1 n1 m1) == RTick.tcost (r2 n2 m2) } @-} +--- End --- + +{-@ reflect decrNtt @-} +{-@ decrNtt :: Nat -> Nat -> Tick [Bool] @-} +decrNtt :: Int -> Int -> Tick [Bool] +decrNtt n m = decrN n (tt m) + +{-@ reflect incrNff @-} +{-@ incrNff :: Nat -> Nat -> Tick [Bool] @-} +incrNff :: Int -> Int -> Tick [Bool] +incrNff n m = incrN n (ff m) + +{-@ reflect incr @-} +{-@ incr + :: xs:[Bool] + -> Tick { zs:[Bool] | Lists.length zs == Lists.length xs } +@-} +incr :: [Bool] -> Tick [Bool] +incr [] = return [] +incr (False:xs) = pure (cons True) pure xs +incr (True:xs) = pure (cons False) incr xs + +{-@ reflect decrN @-} +{-@ decrN :: Nat -> [Bool] -> Tick [Bool] @-} +decrN :: Int -> [Bool] -> Tick [Bool] +decrN 0 xs = return xs +decrN n xs = decr xs >>= decrN (n - 1) + +{-@ reflect decr @-} +{-@ decr + :: xs:[Bool] + -> Tick { zs:[Bool] | Lists.length xs == Lists.length zs } +@-} +decr :: [Bool] -> Tick [Bool] +decr [] = return [] +decr (False : xs) = pure (cons True) decr xs +decr (True : xs) = pure (cons False) pure xs diff --git a/tests/relational/pos/RBinaryCounters_relToUn_completed.hs b/tests/relational/pos/RBinaryCounters_relToUn_completed.hs new file mode 100644 index 0000000000..6dc76b6730 --- /dev/null +++ b/tests/relational/pos/RBinaryCounters_relToUn_completed.hs @@ -0,0 +1,104 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RBinaryCounters_relToUn_completed where +import RTick +import Lists +import Prelude +import Language.Haskell.Liquid.ProofCombinators +import RBinaryCounters +import GHC.Types +import GHC.Classes +import Language.Haskell.Liquid.ProofCombinators +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ incrNffDecrNttTheorem :: n1:{VV0 : GHC.Types.Int | VV0 >= 0} -> n2:{VV0 : GHC.Types.Int | VV0 >= 0} -> n1n2Lemma:{VV : () | n1 == n2} -> m1:{VV0 : GHC.Types.Int | VV0 >= 0} -> m2:{VV0 : GHC.Types.Int | VV0 >= 0} -> m1m2Lemma:{VV : () | m1 == m2} -> {VV : () | RTick.tcost (RBinaryCounters.incrNff n1 m1) == RTick.tcost (RBinaryCounters.decrNtt n2 m2)} @-} +incrNffDecrNttTheorem + :: GHC.Types.Int + -> GHC.Types.Int + -> () + -> GHC.Types.Int + -> GHC.Types.Int + -> () + -> () +incrNffDecrNttTheorem n1 n2 n1n2Lemma_a1g2 m1 m2 m1m2Lemma_a1g3 = + incrNDecrNTheorem n1 n2 n1n2Lemma_a1g2 (ff m1) (tt m2) (dualTTFF m1 ? m1m2Lemma_a1g3) + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ incrNDecrNTheorem :: n1:{VV0 : GHC.Types.Int | VV0 >= 0} -> n2:{VV0 : GHC.Types.Int | VV0 >= 0} -> n1n2Lemma:{VV : () | n1 == n2} -> xs1:[GHC.Types.Bool] -> xs2:[GHC.Types.Bool] -> xs1xs2Lemma:{VV : () | RBinaryCounters.dual xs1 xs2 + && Lists.length xs1 == Lists.length xs2} -> {VV : () | RBinaryCounters.dual (RTick.tval (RBinaryCounters.incrN n1 xs1)) (RTick.tval (RBinaryCounters.decrN n2 xs2)) + && RTick.tcost (RBinaryCounters.incrN n1 xs1) == RTick.tcost (RBinaryCounters.decrN n2 xs2)} @-} +incrNDecrNTheorem :: GHC.Types.Int -> GHC.Types.Int -> () -> [GHC.Types.Bool] -> [GHC.Types.Bool] -> () -> () +incrNDecrNTheorem n1 n2 n1n2Lemma_d21P xs1 xs2 xs1xs2Lemma_a1fX = case n1 of + 0 -> case n2 of + 0 -> ({- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2))) xs1 xs2 xs1xs2Lemma_a1fX + _ -> {- GOAL: RTick.return xs1_a1f (...) ~ (RBinaryCounters.dec (...) -} + (() ? (RTick.return xs1)) ? ((RBinaryCounters.decr xs2) RTick.>>= (RBinaryCounters.decrN (n2 - 1))) + + _ -> case n2 of + 0 -> {- GOAL: (RBinaryCounters.inc (...) ~ RTick.return xs2_a1g (...) -} + (() ? ((RBinaryCounters.incr xs1) RTick.>>= (RBinaryCounters.incrN (n1 - 1)))) ? (RTick.return xs2) + _ -> incrNDecrNTheorem (n1 - 1) (n2 - 1) n1n2Lemma_d21P (tval (incr xs1)) (tval (decr xs2)) (incrDecrTheorem xs1 xs2 xs1xs2Lemma_a1fX) + ? ({- GOAL: RTick.>>= ~ RTick.>>= -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick.>>= x3)) ? (x2 RTick.>>= x4))) (RBinaryCounters.incr xs1) (RBinaryCounters.decr xs2) (({- GOAL: RBinaryCounters.incr ~ RBinaryCounters.decr -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RBinaryCounters.incr x1)) ? (RBinaryCounters.decr x2) ? incrDecrTheorem x1 x2 x1x2Lemma_xp)) xs1 xs2 xs1xs2Lemma_a1fX) (RBinaryCounters.incrN (n1 - 1)) (RBinaryCounters.decrN (n2 - 1)) (incrNDecrNTheorem (n1 - 1) (n2 - 1) (({- GOAL: - ~ - -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 - x3)) ? (x2 - x4))) n1 n2 n1n2Lemma_d21P 1 1 (({- GOAL: ~ -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? x1) ? x2)) 1 1 ({- GOAL: 1 ~ 1 -} + (() ? 1) ? 1)))) + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ incrDecrTheorem :: xs1:[GHC.Types.Bool] -> xs2:[GHC.Types.Bool] -> xs1xs2Lemma:{VV : () | RBinaryCounters.dual xs1 xs2 + && Lists.length xs1 == Lists.length xs2} -> {VV : () | RBinaryCounters.dual (RTick.tval (RBinaryCounters.incr xs1)) (RTick.tval (RBinaryCounters.decr xs2)) + && RTick.tcost (RBinaryCounters.incr xs1) == RTick.tcost (RBinaryCounters.decr xs2)} @-} +incrDecrTheorem :: [GHC.Types.Bool] -> [GHC.Types.Bool] -> () -> () +incrDecrTheorem xs1 xs2 xs1xs2Lemma_d21J = case xs1 of + [] -> case xs2 of + [] -> ({- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2))) [] [] ({- GOAL: [] ~ [] -} + (() ? []) ? []) + (:) ds2_d21C xs2 -> {- GOAL: RTick.return [] ~ case ds2_d21C of Fal (...) -} + (() ? (RTick.return [])) ? (case ds2_d21C of + False -> (RTick.pure (Lists.cons True)) RTick. (RBinaryCounters.decr xs2) + True -> (RTick.pure (Lists.cons False)) RTick. (RTick.pure xs2)) + (:) ds1_d21O xs1 -> case xs2 of + [] -> {- GOAL: case ds1_d21O of Fal (...) ~ RTick.return [] -} + (() ? (case ds1_d21O of + False -> (RTick.pure (Lists.cons True)) RTick. (RTick.pure xs1) + True -> (RTick.pure (Lists.cons False)) RTick. (RBinaryCounters.incr xs1))) ? (RTick.return []) + (:) ds2_d21C xs2 -> case ds1_d21O of + False -> case ds2_d21C of + False -> ({- GOAL: RTick. ~ RTick. -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick. x3)) ? (x2 RTick. x4))) (RTick.pure (Lists.cons True)) (RTick.pure (Lists.cons True)) (({- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2))) (Lists.cons True) (Lists.cons True) (({- GOAL: Lists.cons ~ Lists.cons -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (Lists.cons x1 x3)) ? (Lists.cons x2 x4))) True True ({- GOAL: True ~ True -} + (() ? True) ? True))) (RTick.pure xs1) (RBinaryCounters.decr xs2) (({- GOAL: RTick.pure ~ RBinaryCounters.decr -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RBinaryCounters.decr x2))) xs1 xs2 ({- GOAL: xs1_a1g4 ~ xs2_a1g9 -} + (() ? xs1) ? xs2)) + True -> ({- GOAL: RTick. ~ RTick. -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick. x3)) ? (x2 RTick. x4))) (RTick.pure (Lists.cons True)) (RTick.pure (Lists.cons False)) (({- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2))) (Lists.cons True) (Lists.cons False) (({- GOAL: Lists.cons ~ Lists.cons -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (Lists.cons x1 x3)) ? (Lists.cons x2 x4))) True False ({- GOAL: True ~ False -} + (() ? True) ? False))) (RTick.pure xs1) (RTick.pure xs2) (({- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2))) xs1 xs2 ({- GOAL: xs1_a1g4 ~ xs2_a1g9 -} + (() ? xs1) ? xs2)) + True -> case ds2_d21C of + False -> ({- GOAL: RTick. ~ RTick. -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick. x3)) ? (x2 RTick. x4))) (RTick.pure (Lists.cons False)) (RTick.pure (Lists.cons True)) (({- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2))) (Lists.cons False) (Lists.cons True) (({- GOAL: Lists.cons ~ Lists.cons -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (Lists.cons x1 x3)) ? (Lists.cons x2 x4))) False True ({- GOAL: False ~ True -} + (() ? False) ? True))) (RBinaryCounters.incr xs1) (RBinaryCounters.decr xs2) (incrDecrTheorem xs1 xs2 ({- GOAL: xs1_a1g4 ~ xs2_a1g9 -} + (() ? xs1) ? xs2)) + True -> ({- GOAL: RTick. ~ RTick. -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick. x3)) ? (x2 RTick. x4))) (RTick.pure (Lists.cons False)) (RTick.pure (Lists.cons False)) (({- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2))) (Lists.cons False) (Lists.cons False) (({- GOAL: Lists.cons ~ Lists.cons -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (Lists.cons x1 x3)) ? (Lists.cons x2 x4))) False False ({- GOAL: False ~ False -} + (() ? False) ? False))) (RBinaryCounters.incr xs1) (RTick.pure xs2) (({- GOAL: RBinaryCounters.incr ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RBinaryCounters.incr x1)) ? (RTick.pure x2))) xs1 xs2 ({- GOAL: xs1_a1g4 ~ xs2_a1g9 -} + (() ? xs1) ? xs2)) diff --git a/tests/relational/pos/RConstantTimeComparison.hs b/tests/relational/pos/RConstantTimeComparison.hs index 6f3535a656..af1053d6b4 100644 --- a/tests/relational/pos/RConstantTimeComparison.hs +++ b/tests/relational/pos/RConstantTimeComparison.hs @@ -2,21 +2,18 @@ -- -- Liquidate your assets: reasoning about resource usage in Liquid Haskell. -- - -{-@ LIQUID "--reflection" @-} -{-@ LIQUID "--ple" @-} +{-@ LIQUID "--relational-hints" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} module RConstantTimeComparison (module RConstantTimeComparison) where -import Prelude hiding ( pure, return, and, fmap, Functor(..), Applicative(..), Monad(..), (=<<) ) - -import qualified Control.Applicative as A -import qualified Control.Monad as M -import qualified Data.Functor as F - +import Prelude hiding ( pure, return, and, fmap, length ) +import RTick import Language.Haskell.Liquid.ProofCombinators +import Lists -- -- Proving a password comparisons function adheres to the @@ -36,14 +33,15 @@ comp [] _ = return True comp (x : xs) (y : ys) = let Tick m v = comp xs ys in Tick (m + 1) (and (x == y) v) +--- Proof --- {-@ relational comp ~ comp :: { xs1:[Bit] -> ys1:[Bit] -> t:Tick Bool - ~ xs2:[Bit] -> ys2:[Bit] -> t:Tick Bool - | xs1 = xs2 - :=> len xs1 == len ys1 && len xs1 == len ys2 - :=> RConstantTimeComparison.tcost (RConstantTimeComparison.comp xs1 ys1) - == RConstantTimeComparison.tcost (RConstantTimeComparison.comp xs1 ys2) } -@-} + ~ xs2:[Bit] -> ys2:[Bit] -> t:Tick Bool + | !(xs1 = xs2) + :=> !(len xs1 == len ys1 && len xs1 == len ys2) + :=> RTick.tcost (r1 xs1 ys1) + == RTick.tcost (r2 xs2 ys2) } @-} +--- End --- {- Previous comp: @@ -62,309 +60,3 @@ Tick m f Tick n x = Tick (1 + m + n) (f x) {-@ and :: Bool -> Bool -> Bool @-} and :: Bool -> Bool -> Bool and x y = x && y - - -------------------------------------------------------------------------------- --- | 'Tick' datatype for recording resource usage: -------------------------------------------------------------------------------- - -{-@ data Tick a = Tick { tcost :: Int, tval :: a } @-} -data Tick a = Tick { tcost :: Int, tval :: a } - -{-@ measure ttcost @-} -ttcost :: Tick a -> Int -ttcost (Tick c _) = c - -------------------------------------------------------------------------------- --- | Primitive resource operators: -------------------------------------------------------------------------------- - -instance F.Functor Tick where - fmap = fmap - -{-@ reflect fmap @-} -{-@ fmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1) (f (tval t1)) == t } @-} -fmap :: (a -> b) -> Tick a -> Tick b -fmap f (Tick m x) = Tick m (f x) - -instance A.Applicative Tick where - pure = pure - (<*>) = (<*>) - -{-@ reflect pure @-} -{-@ pure :: x:a -> { t:Tick a | x == tval t && 0 == tcost t } @-} -pure :: a -> Tick a -pure x = Tick 0 x - -{-@ reflect <*> @-} -{-@ (<*>) :: t1:Tick (a -> b) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} -infixl 4 <*> -(<*>) :: Tick (a -> b) -> Tick a -> Tick b -Tick m f <*> Tick n x = Tick (m + n) (f x) - -{-@ reflect liftA2 @-} -{-@ liftA2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b -> { t:Tick c | f (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} -liftA2 :: (a -> b -> c) -> Tick a -> Tick b -> Tick c -liftA2 f (Tick m x) (Tick n y) = Tick (m + n) (f x y) - -instance M.Monad Tick where - return = return - (>>=) = (>>=) - -{-@ reflect return @-} -{-@ return :: x:a -> { t:Tick a | x == tval t && 0 == tcost t } @-} -return :: a -> Tick a -return x = Tick 0 x - -{-@ reflect >>= @-} -{-@ (>>=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) == tcost t } @-} -infixl 4 >>= -(>>=) :: Tick a -> (a -> Tick b) -> Tick b -Tick m x >>= f = let Tick n y = f x in Tick (m + n) y - -{-@ reflect =<< @-} -{-@ (=<<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) == tcost t } @-} -infixl 4 =<< -(=<<) :: (a -> Tick b) -> Tick a -> Tick b -f =<< Tick m x = let Tick n y = f x in Tick (m + n) y - -{-@ reflect ap @-} -{-@ ap :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} -ap :: Tick (a -> b) -> Tick a -> Tick b -ap (Tick m f) (Tick n x) = Tick (m + n) (f x) - -{-@ reflect liftM @-} -{-@ liftM :: f:(a -> b) -> t1:Tick a -> { t:Tick b | tcost t1 == tcost t } @-} -liftM :: (a -> b) -> Tick a -> Tick b -liftM f (Tick m x) = Tick m (f x) - -{-@ reflect liftM2 @-} -{-@ liftM2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b -> { t:Tick c | f (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} -liftM2 :: (a -> b -> c) -> Tick a -> Tick b -> Tick c -liftM2 f (Tick m x) (Tick n y) = Tick (m + n) (f x y) - -------------------------------------------------------------------------------- - -{-@ reflect eqBind @-} -{-@ eqBind - :: n:Int - -> t1:Tick a - -> f:(a -> { tf:Tick b | n == tcost tf }) - -> { t:Tick b | tval (f (tval t1)) - == tval t && tcost t1 + n == tcost t } -@-} -eqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b -eqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y - -{-@ reflect leqBind @-} -{-@ leqBind :: n:Int -> t1:Tick a -> f:(a -> { tf:Tick b | n >= tcost tf }) -> { t:Tick b | tcost t1 + n >= tcost t } @-} -leqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b -leqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y - -{-@ reflect geqBind @-} -{-@ geqBind :: n:Int -> t1:Tick a -> f:(a -> { tf:Tick b | n <= tcost tf }) -> { t2:Tick b | tcost t1 + n <= tcost t2 } @-} -geqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b -geqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y - -------------------------------------------------------------------------------- --- | Resource modifiers: -------------------------------------------------------------------------------- - -{-@ reflect step @-} -{-@ step :: m:Int -> t1:Tick a -> { t:Tick a | tval t1 == tval t && m + tcost t1 == tcost t } @-} -step :: Int -> Tick a -> Tick a -step m (Tick n x) = Tick (m + n) x - --- --- @wait := step 1 . return@. --- -{-@ reflect wait @-} -{-@ wait :: x:a -> { t:Tick a | x == tval t && 1 == tcost t } @-} -wait :: a -> Tick a -wait x = Tick 1 x - --- --- @waitN (n > 0) := step n . return@. --- -{-@ reflect waitN @-} -{-@ waitN :: n:Nat -> x:a -> { t:Tick a | x == tval t && n == tcost t } @-} -waitN :: Int -> a -> Tick a -waitN n x = Tick n x - --- --- @go := step (-1) . return@. --- -{-@ reflect go @-} -{-@ go :: x:a -> { t:Tick a | x == tval t && (-1) == tcost t } @-} -go :: a -> Tick a -go x = Tick (-1) x - --- --- @goN (n > 0) := step (-n) . return@. --- -{-@ reflect goN @-} -{-@ goN :: { n:Nat | n > 0 } -> x:a -> { t:Tick a | x == tval t && (-n) == tcost t } @-} -goN :: Int -> a -> Tick a -goN n x = Tick (-n) x - --- --- @wmap f := step 1 . fmap f@. --- -{-@ reflect wmap @-} -{-@ wmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (1 + tcost t1) (f (tval t1)) == t } @-} -wmap :: (a -> b) -> Tick a -> Tick b -wmap f (Tick m x) = Tick (1 + m) (f x) - --- --- @wmapN (n > 0) f := step n . fmap f@. --- -{-@ reflect wmapN @-} -{-@ wmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (m + tcost t1) (f (tval t1)) == t } @-} -wmapN :: Int -> (a -> b) -> Tick a -> Tick b -wmapN m f (Tick n x) = Tick (m + n) (f x) - --- --- @gmap f := step (-1) . fmap f@. --- -{-@ reflect gmap @-} -{-@ gmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1 - 1) (f (tval t1)) == t } @-} -gmap :: (a -> b) -> Tick a -> Tick b -gmap f (Tick m x) = Tick (m - 1) (f x) - --- --- @gmapN (n > 0) f := step (-n) . fmap f@. --- -{-@ reflect gmapN @-} -{-@ gmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1 - m) (f (tval t1)) == t } @-} -gmapN :: Int -> (a -> b) -> Tick a -> Tick b -gmapN m f (Tick n x) = Tick (n - m) (f x) - --- --- \"wapp\": @(f ) := step 1 . (f <*>)@. --- -{-@ reflect @-} -{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && 1 + tcost t1 + tcost t2 == tcost t } @-} -infixl 4 -() :: Tick (a -> b) -> Tick a -> Tick b -Tick m f Tick n x = Tick (1 + m + n) (f x) - --- --- \"wwapp\": @(f ) := step 2 . (f <*>)@. --- -{-@ reflect @-} -{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && 2 + tcost t1 + tcost t2 == tcost t } @-} -infixl 4 -() :: Tick (a -> b) -> Tick a -> Tick b -Tick m f Tick n x = Tick (2 + m + n) (f x) - --- --- \"gapp\": @(f <\>) := step (-1) . (f <*>)@. --- -{-@ reflect <\> @-} -{-@ (<\>) :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 - 1 == tcost t } @-} -infixl 4 <\> -(<\>) :: Tick (a -> b) -> Tick a -> Tick b -Tick m f <\> Tick n x = Tick (m + n - 1) (f x) - --- --- \"ggapp\": @(f <\\>) := step (-2) . (f <*>)@. --- -{-@ reflect <\\> @-} -{-@ (<\\>) :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 - 2 == tcost t } @-} -infixl 4 <\\> -(<\\>) :: Tick (a -> b) -> Tick a -> Tick b -Tick m f <\\> Tick n x = Tick (m + n - 2) (f x) - --- --- \"wbind\": @(>/= f) := step 1 . (>>= f)@. --- -{-@ reflect >/= @-} -{-@ (>/=) - :: t1:Tick a - -> f:(a -> Tick b) - -> { t:Tick b | (tval (f (tval t1)) == tval t) - && (1 + tcost t1 + tcost (f (tval t1))) == tcost t } -@-} -infixl 4 >/= -(>/=) :: Tick a -> (a -> Tick b) -> Tick b -Tick m x >/= f = let Tick n y = f x in Tick (1 + m + n) y - --- --- \"wbind\": @(f =/<) := step 1 . (f =<<)@. --- -{-@ reflect =/< @-} -{-@ (=/<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && 1 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} -infixl 4 =/< -(=/<) :: (a -> Tick b) -> Tick a -> Tick b -f =/< Tick m x = let Tick n y = f x in Tick (1 + m + n) y - --- --- \"wwbind\": @(>//= f) := step 2 . (>>= f)@. --- -{-@ reflect >//= @-} -{-@ (>//=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && 2 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} -infixl 4 >//= -(>//=) :: Tick a -> (a -> Tick b) -> Tick b -Tick m x >//= f = let Tick n y = f x in Tick (2 + m + n) y - --- --- \"wwbind\": @(f =//<) := step 2 . (f =<<)@. --- -{-@ reflect =//< @-} -{-@ (=//<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && 2 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} -infixl 4 =//< -(=//<) :: (a -> Tick b) -> Tick a -> Tick b -f =//< Tick m x = let Tick n y = f x in Tick (2 + m + n) y - --- --- \"gbind\": @(>\= f) := step (-1) . (>>= f)@. --- -{-@ reflect >\= @-} -{-@ (>\=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 1 == tcost t } @-} -infixl 4 >\= -(>\=) :: Tick a -> (a -> Tick b) -> Tick b -Tick m x >\= f = let Tick n y = f x in Tick (m + n - 1) y - --- --- \"gbind\": @(f =\<) := step (-1) . (f =<<)@. --- -{-@ reflect =\< @-} -{-@ (=\<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 1 == tcost t } @-} -infixl 4 =\< -(=\<) :: (a -> Tick b) -> Tick a -> Tick b -f =\< Tick m x = let Tick n y = f x in Tick (m + n - 1) y - --- --- \"ggbind\": @(>\= f) := step (-2) . (>>= f)@. --- -{-@ reflect >\\= @-} -{-@ (>\\=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 2 == tcost t } @-} -infixl 4 >\\= -(>\\=) :: Tick a -> (a -> Tick b) -> Tick b -Tick m x >\\= f = let Tick n y = f x in Tick (m + n - 2) y - --- --- \"ggbind\": @(f =\\<) := step (-2) . (f =<<)@. --- -{-@ reflect =\\< @-} -{-@ (=\\<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 2 == tcost t } @-} -infixl 4 =\\< -(=\\<) :: (a -> Tick b) -> Tick a -> Tick b -f =\\< Tick m x = let Tick n y = f x in Tick (m + n - 2) y - -------------------------------------------------------------------------------- --- | Memoisation: -------------------------------------------------------------------------------- - -{-@ reflect pay @-} -{-@ pay :: m:Int -> { t1:Tick a | m <= tcost t1 } -> { t:Tick ({ t2 : Tick a | tcost t1 - m == tcost t2 }) | m == tcost t } @-} -pay :: Int -> Tick a -> Tick (Tick a) -pay m (Tick n x) = Tick m (Tick (n - m) x) - - -{-@ reflect zipWithM @-} -{-@ zipWithM :: f:(a -> b -> Tick c) -> x:Tick a -> y:Tick b - -> {t:Tick c | tcost t == tcost x + tcost y + tcost (f (tval x) (tval y)) - && tval t == tval (f (tval x) (tval y)) } @-} -zipWithM :: (a -> b -> Tick c) -> Tick a -> Tick b -> Tick c -zipWithM f (Tick c1 x1) (Tick c2 x2) = let Tick c x = f x1 x2 in Tick (c + c1 + c2) x diff --git a/tests/relational/pos/RConstantTimeComparison_relToUn.hs b/tests/relational/pos/RConstantTimeComparison_relToUn.hs new file mode 100644 index 0000000000..53289fe2e6 --- /dev/null +++ b/tests/relational/pos/RConstantTimeComparison_relToUn.hs @@ -0,0 +1,374 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RConstantTimeComparison_relToUn (module RConstantTimeComparison_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import Lists +import RConstantTimeComparison +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ compCompTheorem :: xs1:[RConstantTimeComparison.Bit] -> xs2:[RConstantTimeComparison.Bit] -> xs1xs2Lemma:{VV : () | xs1 == xs2} -> ys1:[RConstantTimeComparison.Bit] -> ys2:[RConstantTimeComparison.Bit] -> ys1ys2Lemma:{VV : () | len xs1 == len ys1 + && len xs1 == len ys2} -> {VV : () | RTick.tcost (RConstantTimeComparison.comp xs1 ys1) == RTick.tcost (RConstantTimeComparison.comp xs2 ys2)} @-} +compCompTheorem :: [RConstantTimeComparison.Bit] -> [RConstantTimeComparison.Bit] -> () -> [RConstantTimeComparison.Bit] -> [RConstantTimeComparison.Bit] -> () -> () +compCompTheorem xs1 xs2 xs1xs2Lemma ys1 ys2 ys1ys2Lemma = case xs1 of + [] -> case xs2 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (RTick.return x1)) ? (RTick.return x2)) + ) + True + True + ( {- GOAL: True ~ True -} + (() ? True) ? True + ) + (:) x2 xs2 -> {- GOAL: RTick.return True ~ () -} () + (:) x1 xs1 -> case xs2 of + [] -> {- GOAL: () ~ RTick.return True -} () + (:) x2 xs2 -> case ys1 of + [] -> case ys2 of + [] -> {- GOAL: () ~ () -} () + (:) y2 ys2 -> {- GOAL: () ~ let ds = RConstantTi (...) -} () + (:) y1 ys1 -> case ys2 of + [] -> {- GOAL: let ds = RConstantTi (...) ~ () -} () + (:) y2 ys2 -> + let ds1 = RConstantTimeComparison.comp xs1 ys1 + in let ds2 = RConstantTimeComparison.comp xs2 ys2 + in let ds1ds2Lemma = + compCompTheorem + xs1 + xs2 + ( {- GOAL: xs1 ~ xs2 -} + (() ? xs1) ? xs2 + ) + ys1 + ys2 + ( {- GOAL: ys1 ~ ys2 -} + (() ? ys1) ? ys2 + ) + in ( let m1 = case RConstantTimeComparison.comp xs1 ys1 of + Tick m v -> m + in let m2 = case RConstantTimeComparison.comp xs2 ys2 of + Tick m v -> m + in let m1m2Lemma = case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v1 -> case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v2 -> + {- GOAL: m1 ~ m2 -} + (() ? m1) ? m2 + in ( let v1 = case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v -> v + in let v2 = case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v -> v + in let v1v2Lemma = case RConstantTimeComparison.comp xs1 ys1 of + Tick m11 v1 -> case RConstantTimeComparison.comp xs2 ys2 of + Tick m22 v2 -> + {- GOAL: v1 ~ v2 -} + (() ? v1) ? v2 + in ( ( {- GOAL: RTick.Tick ~ RTick.Tick -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (RTick.Tick x1 x3)) ? (RTick.Tick x2 x4)) + ) + ( ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v1 -> m1 + ) + + 1 + ) + ( ( case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v2 -> m2 + ) + + 1 + ) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 + x3)) ? (x2 + x4)) + ) + ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v1 -> m1 + ) + ( case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v2 -> m2 + ) + ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m11 v11 -> case RConstantTimeComparison.comp xs2 ys2 of + Tick m22 v22 -> m1m2Lemma + ) + 1 + 1 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? x1) ? x2) + ) + 1 + 1 + ( {- GOAL: 1 ~ 1 -} + (() ? 1) ? 1 + ) + ) + ) + ( RConstantTimeComparison.and + (x1 GHC.Classes.== y1) + ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v1 -> v1 + ) + ) + ( RConstantTimeComparison.and + (x2 GHC.Classes.== y2) + ( case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v2 -> v2 + ) + ) + ( ( {- GOAL: RConstantTimeCompari (...) ~ RConstantTimeCompari (...) -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (RConstantTimeComparison.and x1 x3)) ? (RConstantTimeComparison.and x2 x4)) + ) + (x1 GHC.Classes.== y1) + (x2 GHC.Classes.== y2) + ( ( {- GOAL: GHC.Classes.== ~ GHC.Classes.== -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 GHC.Classes.== x3)) ? (x2 GHC.Classes.== x4)) + ) + x1 + x2 + ( {- GOAL: x1 ~ x2 -} + (() ? x1) ? x2 + ) + y1 + y2 + ( {- GOAL: y1 ~ y2 -} + (() ? y1) ? y2 + ) + ) + ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m1 v1 -> v1 + ) + ( case RConstantTimeComparison.comp xs2 ys2 of + Tick m2 v2 -> v2 + ) + ( case RConstantTimeComparison.comp xs1 ys1 of + Tick m11 v11 -> case RConstantTimeComparison.comp xs2 ys2 of + Tick m22 v22 -> v1v2Lemma + ) + ) + ) + ? v1v2Lemma + ) + ? m1m2Lemma + ) + ? ds1ds2Lemma + +{- BARE CORE +\ (xs1 :: [RConstantTimeComparison.Bit]) + (xs2 :: [RConstantTimeComparison.Bit]) + (xs1xs2Lemma :: [RConstantTimeComparison.Bit]) + (ys1 :: [RConstantTimeComparison.Bit]) + (ys2 :: [RConstantTimeComparison.Bit]) + (ys1ys2Lemma :: [RConstantTimeComparison.Bit]) -> + case xs1 of lq_anf$##72057594037927948741 { + [] -> + case xs2 of lq_anf$##72057594037927948742 { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (RTick.return x1)) + (RTick.return x2)) + GHC.Types.True + GHC.Types.True + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.True) GHC.Types.True); + : x2 xs2 -> src<.:0:0> GHC.Tuple.() + }; + : x1 xs1 -> + case xs2 of lq_anf$##72057594037927948742 { + [] -> src<.:0:0> GHC.Tuple.(); + : x2 xs2 -> + case ys1 of lq_anf$##72057594037927948751 { + [] -> + case ys2 of lq_anf$##72057594037927948752 { + [] -> src<.:0:0> GHC.Tuple.(); + : y2 ys2 -> src<.:0:0> GHC.Tuple.() + }; + : y1 ys1 -> + case ys2 of lq_anf$##72057594037927948752 { + [] -> src<.:0:0> GHC.Tuple.(); + : y2 ys2 -> + let { + ds1 :: RTick.Tick GHC.Types.Bool + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] + ds1 = RConstantTimeComparison.comp xs1 ys1 } in + let { + ds2 :: RTick.Tick GHC.Types.Bool + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] + ds2 = RConstantTimeComparison.comp xs2 ys2 } in + let { + ds1ds2Lemma :: RTick.Tick GHC.Types.Bool + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}] + ds1ds2Lemma + = compCompTheorem + xs1 + xs2 + (src<.:0:0> ? (? GHC.Tuple.() xs1) xs2) + ys1 + ys2 + (src<.:0:0> ? (? GHC.Tuple.() ys1) ys2) } in + ? (let { + m1 :: GHC.Types.Int + [LclId] + m1 + = case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m v -> + m + } } in + let { + m2 :: GHC.Types.Int + [LclId] + m2 + = case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m v -> + m + } } in + let { + m1m2Lemma :: GHC.Types.Int + [LclId] + m1m2Lemma + = case RConstantTimeComparison.comp xs1 ys1 of + { RTick.Tick m1 v1 -> + case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v2 -> + src<.:0:0> ? (? GHC.Tuple.() m1) m2 + } + } } in + ? (let { + v1 :: GHC.Types.Bool + [LclId] + v1 + = case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m1 v -> + v + } } in + let { + v2 :: GHC.Types.Bool + [LclId] + v2 + = case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v -> + v + } } in + let { + v1v2Lemma :: GHC.Types.Bool + [LclId] + v1v2Lemma + = case RConstantTimeComparison.comp xs1 ys1 of + { RTick.Tick m11 v1 -> + case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m22 v2 -> + src<.:0:0> ? (? GHC.Tuple.() v1) v2 + } + } } in + ? ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) (RTick.Tick x1 x3)) + (RTick.Tick x2 x4)) + (GHC.Num.+ + (case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m1 v1 -> + m1 + }) + (GHC.Types.I# 1#)) + (GHC.Num.+ + (case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v2 -> + m2 + }) + (GHC.Types.I# 1#)) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + (case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m1 v1 -> + m1 + }) + (case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v2 -> + m2 + }) + (case RConstantTimeComparison.comp xs1 ys1 of + { RTick.Tick m11 v11 -> + case RConstantTimeComparison.comp xs2 ys2 of + { RTick.Tick m22 v22 -> + m1m2Lemma + } + }) + (GHC.Types.I# 1#) + (GHC.Types.I# 1#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 1# 1# (src<.:0:0> ? (? GHC.Tuple.() 1#) 1#))) + (RConstantTimeComparison.and + (GHC.Classes.== x1 y1) + (case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m1 v1 -> + v1 + })) + (RConstantTimeComparison.and + (GHC.Classes.== x2 y2) + (case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v2 -> + v2 + })) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (RConstantTimeComparison.and x1 x3)) + (RConstantTimeComparison.and x2 x4)) + (GHC.Classes.== x1 y1) + (GHC.Classes.== x2 y2) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (GHC.Classes.== x1 x3)) + (GHC.Classes.== x2 x4)) + x1 + x2 + (src<.:0:0> ? (? GHC.Tuple.() x1) x2) + y1 + y2 + (src<.:0:0> ? (? GHC.Tuple.() y1) y2)) + (case RConstantTimeComparison.comp xs1 ys1 of { RTick.Tick m1 v1 -> + v1 + }) + (case RConstantTimeComparison.comp xs2 ys2 of { RTick.Tick m2 v2 -> + v2 + }) + (case RConstantTimeComparison.comp xs1 ys1 of + { RTick.Tick m11 v11 -> + case RConstantTimeComparison.comp xs2 ys2 of + { RTick.Tick m22 v22 -> + v1v2Lemma + } + }))) + v1v2Lemma) + m1m2Lemma) + ds1ds2Lemma + } + } + } + } +-} diff --git a/tests/relational/pos/RIncr.hs b/tests/relational/pos/RIncr.hs index 32a08411ca..4beb67684a 100644 --- a/tests/relational/pos/RIncr.hs +++ b/tests/relational/pos/RIncr.hs @@ -1,11 +1,15 @@ +{-@ LIQUID "--relational-hint" @-} {-@ LIQUID "--reflection" @-} {-@ LIQUID "--ple" @-} -module RIncr () where +module RIncr where +{-@ reflect incr @-} incr :: Int -> Int incr x = x + 1 +--- Proof --- {-@ relational incr ~ incr :: { xl : Int -> Int ~ xr : Int -> Int - | xl < xr :=> r1 xl < r2 xr } @-} + | !(xl < xr) :=> r1 xl < r2 xr } @-} +--- End --- \ No newline at end of file diff --git a/tests/relational/pos/RIncr_relToUn.hs b/tests/relational/pos/RIncr_relToUn.hs new file mode 100644 index 0000000000..3867d633da --- /dev/null +++ b/tests/relational/pos/RIncr_relToUn.hs @@ -0,0 +1,60 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RIncr_relToUn (module RIncr_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import RIncr +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ incrIncrTheorem :: xl:GHC.Types.Int -> xr:GHC.Types.Int -> xlxrLemma:{VV : () | xl < xr} -> {VV : () | RIncr.incr xl < RIncr.incr xr} @-} +incrIncrTheorem :: GHC.Types.Int -> GHC.Types.Int -> () -> () +incrIncrTheorem xl xr xlxrLemma = + ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 + x3)) ? (x2 + x4)) + ) + xl + xr + xlxrLemma + 1 + 1 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? x1) ? x2) + ) + 1 + 1 + ( {- GOAL: 1 ~ 1 -} + (() ? 1) ? 1 + ) + ) + +{- BARE CORE +\ (xl :: GHC.Types.Int) + (xr :: GHC.Types.Int) + (xlxrLemma :: GHC.Types.Int) -> + (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + xl + xr + xlxrLemma + (GHC.Types.I# 1#) + (GHC.Types.I# 1#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 1# 1# (src<.:0:0> ? (? GHC.Tuple.() 1#) 1#)) +-} diff --git a/tests/relational/pos/RMap.hs b/tests/relational/pos/RMap.hs new file mode 100644 index 0000000000..56cfe939bc --- /dev/null +++ b/tests/relational/pos/RMap.hs @@ -0,0 +1,22 @@ +{-@ LIQUID "--relational-hint" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module RMap where +import Prelude hiding (map) + +type List a = [a] + +{-@ reflect map @-} +map :: (Int -> Int) -> List Int -> List Int +map _ [] = [] +map f (x:xs) = f x:map f xs + +--- Proof --- +{-@ relational map ~ map :: + { f1:(x1:Int -> Int) -> xs1:List Int -> List Int + ~ f2:(x2:Int -> Int) -> xs2:List Int -> List Int + | !(true :=> true) + :=> !(len xs1 = len xs2) + :=> len (r1 f1 xs1) = len (r2 f2 xs2) } @-} +--- End --- \ No newline at end of file diff --git a/tests/relational/pos/RMap_relToUn.hs b/tests/relational/pos/RMap_relToUn.hs new file mode 100644 index 0000000000..fb7a4a4cc4 --- /dev/null +++ b/tests/relational/pos/RMap_relToUn.hs @@ -0,0 +1,97 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RMap_relToUn (module RMap_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import RMap +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ mapMapTheorem :: f1:(x1:GHC.Types.Int -> GHC.Types.Int) -> f2:(x2:GHC.Types.Int -> GHC.Types.Int) -> f1f2Lemma:(x1:GHC.Types.Int -> x2:GHC.Types.Int -> x1x2Lemma:() -> ()) -> xs1:[GHC.Types.Int] -> xs2:[GHC.Types.Int] -> xs1xs2Lemma:{VV : () | len xs1 == len xs2} -> {VV : () | len (RMap.map f1 xs1) == len (RMap.map f2 xs2)} @-} +mapMapTheorem :: (GHC.Types.Int -> GHC.Types.Int) -> (GHC.Types.Int -> GHC.Types.Int) -> (GHC.Types.Int -> GHC.Types.Int -> () -> ()) -> [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +mapMapTheorem f1 f2 f1f2Lemma xs1 xs2 xs1xs2Lemma = case xs1 of + [] -> case xs2 of + [] -> + {- GOAL: [] ~ [] -} + (() ? []) ? [] + (:) x2 xs2 -> + {- GOAL: [] ~ (f2 x2) : (RMap.map (...) -} + (() ? []) ? ((f2 x2) : (RMap.map f2 xs2)) + (:) x1 xs1 -> case xs2 of + [] -> + {- GOAL: (f1 x1) : (RMap.map (...) ~ [] -} + (() ? ((f1 x1) : (RMap.map f1 xs1))) ? [] + (:) x2 xs2 -> + ( {- GOAL: : ~ : -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 : x3)) ? (x2 : x4)) + ) + (f1 x1) + (f2 x2) + ( f1f2Lemma + x1 + x2 + ( {- GOAL: x1 ~ x2 -} + (() ? x1) ? x2 + ) + ) + (RMap.map f1 xs1) + (RMap.map f2 xs2) + ( mapMapTheorem + f1 + f2 + f1f2Lemma + xs1 + xs2 + ( {- GOAL: xs1 ~ xs2 -} + (() ? xs1) ? xs2 + ) + ) + +{- BARE CORE +\ (f1 :: GHC.Types.Int -> GHC.Types.Int) + (f2 :: GHC.Types.Int -> GHC.Types.Int) + (f1f2Lemma :: GHC.Types.Int -> GHC.Types.Int) + (xs1 :: [GHC.Types.Int]) + (xs2 :: [GHC.Types.Int]) + (xs1xs2Lemma :: [GHC.Types.Int]) -> + case xs1 of lq_anf$##72057594037927940271 { + [] -> + case xs2 of lq_anf$##72057594037927940272 { + [] -> src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[]; + : x2 xs2 -> + src<.:0:0> + ? (? GHC.Tuple.() GHC.Types.[]) + (GHC.Types.: (f2 x2) (RMap.map f2 xs2)) + }; + : x1 xs1 -> + case xs2 of lq_anf$##72057594037927940272 { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() (GHC.Types.: (f1 x1) (RMap.map f1 xs1))) + GHC.Types.[]; + : x2 xs2 -> + (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) (GHC.Types.: x1 x3)) + (GHC.Types.: x2 x4)) + (f1 x1) + (f2 x2) + (f1f2Lemma x1 x2 (src<.:0:0> ? (? GHC.Tuple.() x1) x2)) + (RMap.map f1 xs1) + (RMap.map f2 xs2) + (mapMapTheorem + f1 f2 f1f2Lemma xs1 xs2 (src<.:0:0> ? (? GHC.Tuple.() xs1) xs2)) + } + } +-} diff --git a/tests/relational/pos/RMemAlloc.hs b/tests/relational/pos/RMemAlloc.hs new file mode 100644 index 0000000000..91485f082f --- /dev/null +++ b/tests/relational/pos/RMemAlloc.hs @@ -0,0 +1,44 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--relational-hints" @-} +module RMemAlloc where + +import RTick +import Prelude hiding (pure, foldl) +import Language.Haskell.Liquid.ProofCombinators + +{-@ reflect foldl @-} +{-@ foldl :: (Int -> Int -> Int) -> Int -> xs:[Int] -> { t:Tick Int | tcost t == len xs } @-} +foldl :: (Int -> Int -> Int) -> Int -> [Int] -> Tick Int +foldl _ z [] = pure z +foldl f z (x : xs) = let w = f z x in 1 `step` foldl f w xs + +{-@ reflect foldl' @-} +{-@ foldl' :: (Int -> Int -> Int) -> Int -> xs:[Int] -> { t:Tick Int | tcost t == 0 } @-} +foldl' :: (Int -> Int -> Int) -> Int -> [Int] -> Tick Int +foldl' _ z [] = pure z +foldl' f z (x : xs) = let w = f z x in w `seq` foldl' f w xs + +{-@ reflect length1 @-} +length1 :: [Int] -> Tick Int +length1 xs = foldl' upd 0 xs + +{-@ reflect upd @-} +upd :: Int -> Int -> Int +upd x _ = x + 1 + +{-@ reflect length2 @-} +length2 :: [Int] -> Tick Int +length2 xs = foldl upd 0 xs + +{-@ relational length1 ~ length2 :: { xs1:[Int] -> Tick Int + ~ xs2:[Int] -> Tick Int + | xs1 = xs2 + :=> RTick.tcost (RMemAlloc.length2 xs1) + - RTick.tcost (RMemAlloc.length1 xs1) = len xs1} @-} + +{-@ reflect len @-} +{-@ len :: [a] -> Nat @-} +len :: [a] -> Int +len [] = 0 +len (_:xs) = 1 + len xs diff --git a/tests/relational/pos/RMemAlloc_relToUn.hs b/tests/relational/pos/RMemAlloc_relToUn.hs new file mode 100644 index 0000000000..5d3eee5e7d --- /dev/null +++ b/tests/relational/pos/RMemAlloc_relToUn.hs @@ -0,0 +1,82 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RMemAlloc_relToUn (module RMemAlloc_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import RMemAlloc +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ length1Length2Theorem :: xs1:[GHC.Types.Int] -> xs2:[GHC.Types.Int] -> xs1xs2Lemma:{VV : () | xs1 == xs2} -> {VV : () | RTick.tcost (RMemAlloc.length2 xs1) - RTick.tcost (RMemAlloc.length1 xs1) == len xs1} @-} +length1Length2Theorem :: [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +length1Length2Theorem xs1 xs2 xs1xs2Lemma = + ( {- GOAL: RMemAlloc.foldl' ~ RMemAlloc.foldl -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma x5 x6 x5x6Lemma -> ((((() ? x1x2Lemma) ? x3x4Lemma) ? x5x6Lemma) ? (RMemAlloc.foldl' x1 x3 x5)) ? (RMemAlloc.foldl x2 x4 x6)) + ) + RMemAlloc.upd + RMemAlloc.upd + ( {- GOAL: RMemAlloc.upd ~ RMemAlloc.upd -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (RMemAlloc.upd x1 x3)) ? (RMemAlloc.upd x2 x4)) + ) + 0 + 0 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? x1) ? x2) + ) + 0 + 0 + ( {- GOAL: 0 ~ 0 -} + (() ? 0) ? 0 + ) + ) + xs1 + xs2 + xs1xs2Lemma + +{- BARE CORE +\ (xs1 :: [GHC.Types.Int]) + (xs2 :: [GHC.Types.Int]) + (xs1xs2Lemma :: [GHC.Types.Int]) -> + (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) + (x5 :: ()) + (x6 :: ()) + (x5x6Lemma :: ()) -> + ? (? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) x5x6Lemma) + (RMemAlloc.foldl' x1 x3 x5)) + (RMemAlloc.foldl x2 x4 x6)) + RMemAlloc.upd + RMemAlloc.upd + (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (RMemAlloc.upd x1 x3)) + (RMemAlloc.upd x2 x4)) + (GHC.Types.I# 0#) + (GHC.Types.I# 0#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 0# 0# (src<.:0:0> ? (? GHC.Tuple.() 0#) 0#)) + xs1 + xs2 + xs1xs2Lemma +-} diff --git a/tests/relational/pos/RPatError.hs b/tests/relational/pos/RPatError.hs new file mode 100644 index 0000000000..d415d1d9d6 --- /dev/null +++ b/tests/relational/pos/RPatError.hs @@ -0,0 +1,22 @@ +{- LIQUID "--relational-hints" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +module RPatError where + +import Prelude hiding (zip) + +{-@ measure len @-} +{-@ len :: [a] -> Nat @-} +len :: [a] -> Int +len [] = 0 +len (_:xs) = 1 + len xs + +{-@ reflect zip @-} +{-@ zip :: xs:[Int] -> {ys:[Int]|ys = xs} -> () @-} +zip :: [Int] -> [Int] -> () +zip [] [] = () +zip (_:xs) (_:ys) = zip xs ys + +{-@ relational zip ~ zip :: { xs1:[Int] -> ys1:[Int] -> () + ~ xs2:[Int] -> ys2:[Int] -> () + | true :=> ys1 = xs1 && ys2 = xs2 :=> true } @-} \ No newline at end of file diff --git a/tests/relational/pos/RRelationalISort.hs b/tests/relational/pos/RRelationalISort.hs new file mode 100644 index 0000000000..013c99858a --- /dev/null +++ b/tests/relational/pos/RRelationalISort.hs @@ -0,0 +1,176 @@ +{- POPL'17 Radicek et al. -} +{- ISort 16/11/69 -} + +{-@ LIQUID "--relational-hints" @-} +{- LIQUID "--relational" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module RRelationalISort where +import Prelude hiding (return, (>>=), pure, (<*>), length) +import Lists +{-@ infix : @-} +{-@ infix @-} +import RTick +import Language.Haskell.Liquid.ProofCombinators +import Language.Haskell.Liquid.Bag + +--- Proof --- +{-@ assume relational isort ~ isort + :: { l1:[Int] -> Tick [Int] + ~ l2:[Int] -> Tick [Int] + | !(Lists.length l1 = Lists.length l2) + :=> RTick.tcost (r1 l1) - RTick.tcost (r2 l2) + <= RRelationalISort.unsortedDiff l1 l2 } +@-} + +{- assume relational isort ~ isort by translation isortIsortTheorem @-} + +{- relational insert ~ insert :: { x1:Int -> xs1:[Int] -> Tick [Int] + ~ x2:Int -> xs2:[Int] -> Tick [Int] + | !(true) + :=> !(true) + :=> RTick.tcost (r1 x1 xs1) - RTick.tcost (r2 x2 xs2) + <= RRelationalISort.largerThan x1 xs1 - RRelationalISort.largerThan x2 xs2 } +@-} +--- End --- +--- Proof --- +{-@ ple theorem @-} +theorem :: [Int] -> [Int] -> Proof +{-@ theorem :: l1:[Int] -> l2:{[Int] | length l1 == length l2} + -> { tcost (isort l1) - tcost (isort l2) <= unsortedDiff l1 l2 } @-} +theorem [] [] + = () +theorem (x1:xs1) (x2:xs2) + = theorem xs1 xs2 + ? lemma x1 (getISortVal xs1) + ? lemma_preservation x1 xs1 + ? lemma x2 (getISortVal xs2) + ? lemma_preservation x2 xs2 + +{-@ ple lemma @-} +lemma :: Ord a => a -> [a] -> Proof +{-@ lemma + :: Ord a => x:a + -> xs:(OList a) + -> { tcost (insert x xs) == largerThan x xs } +@-} +lemma _ [] = () +lemma x (y:ys) + | x <= y + = lemma1 x (castLEqCons x y ys) + | otherwise + = lemma x ys + +castLEqCons :: a -> a -> [a] -> [a] +{-@ castLEqCons :: x:a -> y':{a | x <= y'} -> ys':(OList {v:a | y' <= v }) -> {o:OList {v:a | x <= v } | o == y':ys'} @-} +castLEqCons _ y' ys' = y':ys' + +getISortVal :: [Int] -> [Int] +{-@ getISortVal :: xs:[Int] -> {o:OList Int | length o == length xs && o == tval (isort xs)} @-} +getISortVal xs = tval (isort xs) + +{-@ ple lemma1 @-} +lemma1 :: Ord a => a -> [a] -> Proof +{-@ lemma1 :: Ord a => x:a -> xs:(OList {v:a | x <= v}) -> {largerThan x xs == 0 } @-} +lemma1 _ [] = () +lemma1 x (_:xs) = lemma1 x xs + +{-@ ple lemma_preservation @-} +lemma_preservation :: Int -> [Int] -> Proof +{-@ lemma_preservation + :: x:Int + -> xs:[Int] + -> {largerThan x xs == largerThan x (tval (isort xs))} + / [length xs] +@-} +lemma_preservation _ [] = () +lemma_preservation x (y:ys) + | x <= y = preservation_insert x y (getISortVal ys) + ? lemma_preservation x ys + +lemma_preservation x (y:ys) + = preservation_insert x y (getISortVal ys) ? lemma_preservation x ys + + +{-@ ple preservation_insert @-} +preservation_insert :: Ord a => a -> a -> [a] -> Proof +{-@ preservation_insert :: Ord a => x:a -> y:a -> ys:(OList a) + -> { largerThan x (y:ys) == largerThan x (tval (insert y ys)) } @-} +preservation_insert _ _ [] = () +preservation_insert x y (z:zs) + | y <= z + = largerThan x (tval (insert y (z:zs))) + === largerThan x (tval (return (y:z:zs))) + === largerThan x (y:z:zs) + *** QED +preservation_insert x y (z:zs) + | not (y <= z) && (x <= z) + = largerThan x (tval (insert y (z:zs))) + ==! largerThan x (tval ((pure (z:)) insert y zs)) + ==! largerThan x ((tval (pure (z:))) (tval (insert y zs))) + ==! largerThan x (z:(tval (insert y zs))) + ==! largerThan x (tval (insert y zs)) + ? preservation_insert x y zs + ==! largerThan x (y:zs) + ==! (if x <= y then largerThan x zs else 1 + largerThan x zs) + ==! (if x <= y then largerThan x (z:zs) else 1 + largerThan x (z:zs)) + ==! largerThan x (y:z:zs) + *** QED + | otherwise + = largerThan x (tval (insert y (z:zs))) + ==! largerThan x (tval ((pure (z:)) insert y zs)) + ==! largerThan x ((tval (pure (z:))) (tval (insert y zs))) + ==! largerThan x (z:(tval (insert y zs))) + ==! 1 + largerThan x (tval (insert y zs)) + ? preservation_insert x y zs + ==! 1 + largerThan x (y:zs) + ==! 1 + (if x <= y then largerThan x zs else 1 + largerThan x zs) + ==! (if x <= y then largerThan x (z:zs) else 1 + largerThan x (z:zs)) + ==! largerThan x (y:z:zs) + *** QED + +--- End --- + +{-@ reflect isort @-} +isort :: [Int] -> Tick [Int] +{-@ isort + :: xs:[Int] + -> Tick {os:(OList Int) | length os == length xs } +@-} +isort [] = return [] +isort (x:xs) = isort xs >/= insert x + + +{-@ reflect insert @-} +insert :: Ord a => a -> [a] -> Tick [a] +{-@ insert + :: Ord a => x:a -> xs:(OList a) + -> Tick { os:(OList a) | length os == 1 + length xs } +@-} +insert x [] = return [x] +insert x (y:ys) + | x <= y = return (x:y:ys) + | otherwise = let Tick m f = Tick 0 (cons y) in + let Tick n v = insert x ys + in Tick (1 + n + m) (f v) + +{-@ reflect unsortedDiff @-} +unsortedDiff :: Ord a => [a] -> [a] -> Int +unsortedDiff l1 l2 = unsorted l1 - unsorted l2 + +{-@ reflect sorted @-} +sorted :: Ord a => [a] -> Bool +sorted xs = unsorted xs == 0 + +{-@ reflect unsorted @-} +unsorted :: Ord a => [a] -> Int +unsorted [] = 0 +unsorted (x:xs) = largerThan x xs + unsorted xs + +{-@ reflect largerThan @-} +largerThan :: Ord a => a -> [a] -> Int +largerThan _ [] = 0 +largerThan x (y:ys) + | x <= y = largerThan x ys + | otherwise = 1 + largerThan x ys diff --git a/tests/relational/pos/RRelationalISort_relToUn_completed.hs b/tests/relational/pos/RRelationalISort_relToUn_completed.hs new file mode 100644 index 0000000000..cb167a0949 --- /dev/null +++ b/tests/relational/pos/RRelationalISort_relToUn_completed.hs @@ -0,0 +1,139 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{- LIQUID "--fast" @-} +{-@ LIQUID "--no-adt" @-} + +module RRelationalISort_relToUn_completed where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.Bag +import Language.Haskell.Liquid.ProofCombinators +import Lists +import RRelationalISort +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ isortIsortTheorem :: l1:[GHC.Types.Int] -> l2:[GHC.Types.Int] -> l1l2Lemma:{VV : () | Lists.length l1 == Lists.length l2} -> {VV : () | RTick.tcost (RRelationalISort.isort l1) - RTick.tcost (RRelationalISort.isort l2) <= RRelationalISort.unsortedDiff l1 l2} @-} +isortIsortTheorem :: [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +isortIsortTheorem l1 l2 l1l2Lemma_d2et = case l1 of + [] -> case l2 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2)) + ) + [] + [] + ( {- GOAL: [] ~ [] -} + (() ? []) ? [] + ) + (:) x2_a1cV xs2_a1cW -> + {- GOAL: RTick.return [] ~ (RRelationalISort.is (...) -} + (() ? (RTick.return [])) ? ((RRelationalISort.isort xs2_a1cW) RTick.>/= (RRelationalISort.insert x2_a1cV)) + (:) x1_a1cV xs1_a1cW -> case l2 of + [] -> + {- GOAL: (RRelationalISort.is (...) ~ RTick.return [] -} + (() ? ((RRelationalISort.isort xs1_a1cW) RTick.>/= (RRelationalISort.insert x1_a1cV))) ? (RTick.return []) + (:) x2_a1cV xs2_a1cW -> + + + let ds1_d1Ul = RRelationalISort.isort xs1_a1cW + in + ( {- GOAL: RTick.>/= ~ RTick.>/= -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick.>/= x3)) ? (x2 RTick.>/= x4) + ? let x1 = x1_a1cV + xs1 = xs1_a1cW + x2 = x2_a1cV + xs2 = xs2_a1cW in (lemma x1 (getISortVal xs1) + ? lemma_preservation x1 xs1 + ? lemma x2 (getISortVal xs2) + ? lemma_preservation x2 xs2)) + ) + (RRelationalISort.isort xs1_a1cW) + (RRelationalISort.isort xs2_a1cW) + ( isortIsortTheorem + xs1_a1cW + xs2_a1cW + ( {- GOAL: xs1_a1cW ~ xs2_a1cW -} + (() ? xs1_a1cW) ? xs2_a1cW + ) + ) + (RRelationalISort.insert x1_a1cV) + (RRelationalISort.insert x2_a1cV) + ( ( {- GOAL: RRelationalISort.ins (...) ~ RRelationalISort.ins (...) -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (RRelationalISort.insert x1 x3)) ? (RRelationalISort.insert x2 x4)) + ) + x1_a1cV + x2_a1cV + ( {- GOAL: x1_a1cV ~ x2_a1cV -} + (() ? x1_a1cV) ? x2_a1cV + ) + ) + +{- BARE CORE +\ (l1_d2et :: [GHC.Types.Int]) + (l2_d2et :: [GHC.Types.Int]) + (l1l2Lemma_d2et :: [GHC.Types.Int]) -> + case l1_d2et of lq_anf$##72057594037927937761_d2Q { + [] -> + case l2_d2et of lq_anf$##72057594037927937762_d2Q { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.return x1)) + (RTick.return x2)) + GHC.Types.[] + GHC.Types.[] + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[]); + : x2_a1cV xs2_a1cW -> + src<.:0:0> + ? (? GHC.Tuple.() (RTick.return GHC.Types.[])) + (RTick.>/= + (RRelationalISort.isort xs2_a1cW) + (RRelationalISort.insert x2_a1cV)) + }; + : x1_a1cV xs1_a1cW -> + case l2_d2et of lq_anf$##72057594037927937762_d2Q { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (RTick.>/= + (RRelationalISort.isort xs1_a1cW) + (RRelationalISort.insert x1_a1cV))) + (RTick.return GHC.Types.[]); + : x2_a1cV xs2_a1cW -> + (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RTick.>/= x1 x3)) + (RTick.>/= x2 x4)) + (RRelationalISort.isort xs1_a1cW) + (RRelationalISort.isort xs2_a1cW) + (isortIsortTheorem_rEF + xs1_a1cW + xs2_a1cW + (src<.:0:0> ? (? GHC.Tuple.() xs1_a1cW) xs2_a1cW)) + (RRelationalISort.insert x1_a1cV) + (RRelationalISort.insert x2_a1cV) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RRelationalISort.insert x1 x3)) + (RRelationalISort.insert x2 x4)) + x1_a1cV x2_a1cV (src<.:0:0> ? (? GHC.Tuple.() x1_a1cV) x2_a1cV)) + } + } +-} diff --git a/tests/relational/pos/RRelationalMSort.hs b/tests/relational/pos/RRelationalMSort.hs new file mode 100644 index 0000000000..2127bf0d0d --- /dev/null +++ b/tests/relational/pos/RRelationalMSort.hs @@ -0,0 +1,73 @@ +{- Relational MSort 23/25/59 -} + +{-# LANGUAGE FlexibleContexts #-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--relational-hints" @-} +{- LIQUID "--smttimeout=20000" @-} + +module RRelationalMSort where + +{-@ infix <*> @-} +{-@ infix : @-} + +import RTick +import Language.Haskell.Liquid.ProofCombinators +import ProofCombinators +import Lists +import Log2 (log, logNat, plusLog) +import PowerOf2 +import Prelude hiding (return, (>>=), pure, length, (<*>), log, take, drop, min, fst, snd) + +--- Proof --- + +{- relational msort ~ msort :: { xs1:[Int] -> Tick [Int] + ~ xs2:[Int] -> Tick [Int] + | !(Lists.length xs1 = Lists.length xs2 && powerOf2 (Lists.length xs1)) + :=> RTick.tcost (r1 xs1) - RTick.tcost (r2 xs2) + <= Lists.length xs1 * (1 + log (RRelationalMSort.differ xs1 xs2)) } @-} + + +--- End -- + +{-@ reflect differ @-} +{-@ differ :: xs:[Int] -> { ys:[Int] | length xs == length ys } -> Nat @-} +differ :: [Int] -> [Int] -> Int +differ [] [] = 0 +differ (x:xs) (y:ys) + | x == y = differ xs ys + | otherwise = 1 + differ xs ys + +{-@ reflect msort @-} +{- msort :: xs:[Int] -> Tick ({o:List Int | length o == length xs }) / [length xs] @-} +{-@ msort :: xs:[Int] -> { t:Tick (List Int) | length (tval t) == length xs } / [length xs] @-} +msort :: [Int] -> Tick [Int] +msort [] = return [] +msort [x] = return [x] +-- msort xs = step 2 (zipWithM merge (msort ls) (msort rs)) +msort xs = step (2 + tcost l + tcost r) (merge (tval l) (tval r)) + where + l = msort (left s) + r = msort (right s) + s = split xs + +{-@ reflect merge @-} +{- merge :: xs:(List Int) -> ys:(List Int) + -> {t:Tick ({o:List Int | length o == length xs + length ys }) | tcost t <= length xs + length ys && min (length xs) (length ys) <= tcost t } + / [length xs + length ys] @-} +{-@ merge :: xs:(List Int) -> ys:(List Int) + -> {t:Tick (List Int) | length (tval t) == length xs + length ys + && tcost t <= length xs + length ys + && min (length xs) (length ys) <= tcost t } + / [length xs + length ys] @-} +merge :: [Int] -> [Int] -> Tick [Int] +merge [] ys = return ys +merge xs [] = return xs +merge (x:xs) (y:ys) | x <= y = Tick (t + 1) (cons x m) + where Tick t m = merge xs (y:ys) +merge (x:xs) (y:ys) = Tick (t + 1) (cons y m) + where Tick t m = merge (x:xs) ys + +{-@ inline min @-} +min :: Int -> Int -> Int +min x y = if x <= y then x else y \ No newline at end of file diff --git a/tests/relational/pos/RRelationalMSort_relToUn.hs b/tests/relational/pos/RRelationalMSort_relToUn.hs new file mode 100644 index 0000000000..de0641cd82 --- /dev/null +++ b/tests/relational/pos/RRelationalMSort_relToUn.hs @@ -0,0 +1,1197 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RRelationalMSort_relToUn (module RRelationalMSort_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import Lists +import Log2 +import PowerOf2 +import ProofCombinators +import RRelationalMSort +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ msortMsortTheorem :: xs1:[GHC.Types.Int] -> xs2:[GHC.Types.Int] -> xs1xs2Lemma:{VV : () | powerOf2 (Lists.length xs1) + && Lists.length xs1 == Lists.length xs2} -> {VV : () | Lists.length xs1 == Lists.length (RTick.tval (RRelationalMSort.msort xs1)) + && Lists.length xs2 == Lists.length (RTick.tval (RRelationalMSort.msort xs2)) + && RTick.tcost (RRelationalMSort.msort xs1) - RTick.tcost (RRelationalMSort.msort xs2) <= Lists.length xs1 * (1 + log (RRelationalMSort.differ xs1 xs2))} @-} +msortMsortTheorem :: [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +msortMsortTheorem xs1 xs2 xs1xs2Lemma = case xs1 of + [] -> case xs2 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (RTick.return x1)) ? (RTick.return x2)) + ) + [] + [] + ( {- GOAL: [] ~ [] -} + (() ? []) ? [] + ) + (:) x2 ds2 -> + {- GOAL: RTick.return [] ~ case ds2 of [] -> RT (...) -} + (() ? (RTick.return [])) + ? ( case ds2 of + [] -> RTick.return (x2 : []) + (:) lq_anf7205759403792793662 lq_anf7205759403792793663 -> + let s = Lists.split xs2 + in let ds = RRelationalMSort.msort (Lists.right (Lists.split xs2)) + in let rt = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rt + in let rs' = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rs' + in let ds = RRelationalMSort.msort (Lists.left (Lists.split xs2)) + in let lt = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> lt + in let ls' = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> ls' + in RTick.step + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> lt + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rt + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> ls' + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rs' + ) + ) + ) + (:) x1 ds1 -> case xs2 of + [] -> + {- GOAL: case ds1 of [] -> RT (...) ~ RTick.return [] -} + ( () + ? ( case ds1 of + [] -> RTick.return (x1 : []) + (:) lq_anf7205759403792793662 lq_anf7205759403792793663 -> + let s = Lists.split xs1 + in let ds = RRelationalMSort.msort (Lists.right (Lists.split xs1)) + in let rt = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rt + in let rs' = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rs' + in let ds = RRelationalMSort.msort (Lists.left (Lists.split xs1)) + in let lt = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> lt + in let ls' = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> ls' + in RTick.step + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> lt + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rt + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> ls' + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rs' + ) + ) + ) + ) + ? (RTick.return []) + (:) x2 ds2 -> case ds1 of + [] -> case ds2 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (RTick.return x1)) ? (RTick.return x2)) + ) + (x1 : []) + (x2 : []) + ( ( {- GOAL: : ~ : -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 : x3)) ? (x2 : x4)) + ) + x1 + x2 + ( {- GOAL: x1 ~ x2 -} + (() ? x1) ? x2 + ) + [] + [] + ( {- GOAL: [] ~ [] -} + (() ? []) ? [] + ) + ) + (:) lq_anf72057594037927936622 lq_anf72057594037927936632 -> + {- GOAL: RTick.return (x1 : [ (...) ~ let s = Lists.split (...) -} + (() ? (RTick.return (x1 : []))) + ? ( let s = Lists.split xs2 + in let ds = RRelationalMSort.msort (Lists.right (Lists.split xs2)) + in let rt = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rt + in let rs' = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rs' + in let ds = RRelationalMSort.msort (Lists.left (Lists.split xs2)) + in let lt = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> lt + in let ls' = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> ls' + in RTick.step + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> lt + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rt + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> ls' + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rs' + ) + ) + ) + (:) lq_anf72057594037927936621 lq_anf72057594037927936631 -> case ds2 of + [] -> + {- GOAL: let s = Lists.split (...) ~ RTick.return (x2 : [ (...) -} + ( () + ? ( let s = Lists.split xs1 + in let ds = RRelationalMSort.msort (Lists.right (Lists.split xs1)) + in let rt = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rt + in let rs' = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rs' + in let ds = RRelationalMSort.msort (Lists.left (Lists.split xs1)) + in let lt = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> lt + in let ls' = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> ls' + in RTick.step + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> lt + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rt + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> ls' + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rs' + ) + ) + ) + ) + ? (RTick.return (x2 : [])) + (:) lq_anf72057594037927936622 lq_anf72057594037927936632 -> + let s1 = Lists.split xs1 + in let s2 = Lists.split xs2 + in let s1s2Lemma = + ( {- GOAL: Lists.split ~ Lists.split -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (Lists.split x1)) ? (Lists.split x2)) + ) + xs1 + xs2 + xs1xs2Lemma + in ( let ds1 = RRelationalMSort.msort (Lists.right (Lists.split xs1)) + in let ds2 = RRelationalMSort.msort (Lists.right (Lists.split xs2)) + in let ds1ds2Lemma = + msortMsortTheorem + (Lists.right (Lists.split xs1)) + (Lists.right (Lists.split xs2)) + ( ( {- GOAL: Lists.right ~ Lists.right -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (Lists.right x1)) ? (Lists.right x2)) + ) + (Lists.split xs1) + (Lists.split xs2) + ( ( {- GOAL: Lists.split ~ Lists.split -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (Lists.split x1)) ? (Lists.split x2)) + ) + xs1 + xs2 + xs1xs2Lemma + ) + ) + in ( let rt1 = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt rs' -> rt + in let rt2 = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt rs' -> rt + in let rt1rt2Lemma = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs'1 -> case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs'2 -> + {- GOAL: rt1 ~ rt2 -} + (() ? rt1) ? rt2 + in ( let rs'1 = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs' -> rs' + in let rs'2 = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs' -> rs' + in let rs'1rs'2Lemma = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt11 rs'1 -> case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt22 rs'2 -> + {- GOAL: rs'1 ~ rs'2 -} + (() ? rs'1) ? rs'2 + in ( let ds1 = RRelationalMSort.msort (Lists.left (Lists.split xs1)) + in let ds2 = RRelationalMSort.msort (Lists.left (Lists.split xs2)) + in let ds1ds2Lemma = + msortMsortTheorem + (Lists.left (Lists.split xs1)) + (Lists.left (Lists.split xs2)) + ( ( {- GOAL: Lists.left ~ Lists.left -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (Lists.left x1)) ? (Lists.left x2)) + ) + (Lists.split xs1) + (Lists.split xs2) + ( ( {- GOAL: Lists.split ~ Lists.split -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? (Lists.split x1)) ? (Lists.split x2)) + ) + xs1 + xs2 + xs1xs2Lemma + ) + ) + in ( let lt1 = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt ls' -> lt + in let lt2 = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt ls' -> lt + in let lt1lt2Lemma = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> + {- GOAL: lt1 ~ lt2 -} + (() ? lt1) ? lt2 + in ( let ls'1 = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls' -> ls' + in let ls'2 = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls' -> ls' + in let ls'1ls'2Lemma = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt11 ls'1 -> case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt22 ls'2 -> + {- GOAL: ls'1 ~ ls'2 -} + (() ? ls'1) ? ls'2 + in ( ( {- GOAL: RTick.step ~ RTick.step -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (RTick.step x1 x3)) ? (RTick.step x2 x4)) + ) + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> lt1 + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs'1 -> rt1 + ) + ) + ( ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> lt2 + ) + ) + + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs'2 -> rt2 + ) + ) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 + x3)) ? (x2 + x4)) + ) + ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> lt1 + ) + ) + ( 2 + + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> lt2 + ) + ) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (x1 + x3)) ? (x2 + x4)) + ) + 2 + 2 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma -> ((() ? x1x2Lemma) ? x1) ? x2) + ) + 2 + 2 + ( {- GOAL: 2 ~ 2 -} + (() ? 2) ? 2 + ) + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> lt1 + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> lt2 + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt11 ls'11 -> case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt22 ls'22 -> lt1lt2Lemma + ) + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs'1 -> rt1 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs'2 -> rt2 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt11 rs'11 -> case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt22 rs'22 -> rt1rt2Lemma + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> ls'1 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs'1 -> rs'1 + ) + ) + ( RRelationalMSort.merge + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> ls'2 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs'2 -> rs'2 + ) + ) + ( ( {- GOAL: RRelationalMSort.mer (...) ~ RRelationalMSort.mer (...) -} + (\x1 x2 x1x2Lemma x3 x4 x3x4Lemma -> (((() ? x1x2Lemma) ? x3x4Lemma) ? (RRelationalMSort.merge x1 x3)) ? (RRelationalMSort.merge x2 x4)) + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt1 ls'1 -> ls'1 + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt2 ls'2 -> ls'2 + ) + ( case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + Tick lt11 ls'11 -> case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + Tick lt22 ls'22 -> ls'1ls'2Lemma + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt1 rs'1 -> rs'1 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt2 rs'2 -> rs'2 + ) + ( case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + Tick rt11 rs'11 -> case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + Tick rt22 rs'22 -> rs'1rs'2Lemma + ) + ) + ) + ? ls'1ls'2Lemma + ) + ? lt1lt2Lemma + ) + ? ds1ds2Lemma + ) + ? rs'1rs'2Lemma + ) + ? rt1rt2Lemma + ) + ? ds1ds2Lemma + ) + ? s1s2Lemma + +{- BARE CORE +\ (xs1 :: [GHC.Types.Int]) + (xs2 :: [GHC.Types.Int]) + (xs1xs2Lemma :: [GHC.Types.Int]) -> + case xs1 of lq_anf$##72057594037927936501 { + [] -> + case xs2 of lq_anf$##72057594037927936502 { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (RTick.return x1)) + (RTick.return x2)) + GHC.Types.[] + GHC.Types.[] + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[]); + : x2 ds2 -> + src<.:0:0> + ? (? GHC.Tuple.() (RTick.return GHC.Types.[])) + (case ds2 of lq_anf$##7205759403792793652 { + [] -> RTick.return (GHC.Types.: x2 GHC.Types.[]); + : lq_anf$##7205759403792793662 lq_anf$##7205759403792793663 -> + let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs2 } in + let { + ds_d1U5 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U5 + = RRelationalMSort.msort (Lists.right (Lists.split xs2)) } in + let { + rt :: GHC.Types.Int + [LclId] + rt + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rs' :: [GHC.Types.Int] + [LclId] + rs' + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rs' + } } in + let { + ds_d1U4 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U4 + = RRelationalMSort.msort (Lists.left (Lists.split xs2)) } in + let { + lt :: GHC.Types.Int + [LclId] + lt + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + ls' :: [GHC.Types.Int] + [LclId] + ls' + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + ls' + } } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + lt + })) + (case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rt + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + ls' + }) + (case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rs' + })) + }) + }; + : x1 ds1 -> + case xs2 of lq_anf$##72057594037927936502 { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (case ds1 of lq_anf$##7205759403792793652 { + [] -> RTick.return (GHC.Types.: x1 GHC.Types.[]); + : lq_anf$##7205759403792793662 lq_anf$##7205759403792793663 -> + let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs1 } in + let { + ds_d1U5 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U5 + = RRelationalMSort.msort (Lists.right (Lists.split xs1)) } in + let { + rt :: GHC.Types.Int + [LclId] + rt + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rs' :: [GHC.Types.Int] + [LclId] + rs' + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rs' + } } in + let { + ds_d1U4 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U4 + = RRelationalMSort.msort (Lists.left (Lists.split xs1)) } in + let { + lt :: GHC.Types.Int + [LclId] + lt + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + ls' :: [GHC.Types.Int] + [LclId] + ls' + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + ls' + } } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + lt + })) + (case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rt + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + ls' + }) + (case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rs' + })) + })) + (RTick.return GHC.Types.[]); + : x2 ds2 -> + case ds1 of lq_anf$##72057594037927936521 { + [] -> + case ds2 of lq_anf$##72057594037927936522 { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (RTick.return x1)) + (RTick.return x2)) + (GHC.Types.: x1 GHC.Types.[]) + (GHC.Types.: x2 GHC.Types.[]) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) (GHC.Types.: x1 x3)) + (GHC.Types.: x2 x4)) + x1 + x2 + (src<.:0:0> ? (? GHC.Tuple.() x1) x2) + GHC.Types.[] + GHC.Types.[] + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[])); + : lq_anf$##72057594037927936622 lq_anf$##72057594037927936632 -> + src<.:0:0> + ? (? GHC.Tuple.() (RTick.return (GHC.Types.: x1 GHC.Types.[]))) + (let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs2 } in + let { + ds_d1U5 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U5 + = RRelationalMSort.msort (Lists.right (Lists.split xs2)) } in + let { + rt :: GHC.Types.Int + [LclId] + rt + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rs' :: [GHC.Types.Int] + [LclId] + rs' + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rs' + } } in + let { + ds_d1U4 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U4 + = RRelationalMSort.msort (Lists.left (Lists.split xs2)) } in + let { + lt :: GHC.Types.Int + [LclId] + lt + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + ls' :: [GHC.Types.Int] + [LclId] + ls' + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + ls' + } } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + lt + })) + (case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rt + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + ls' + }) + (case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rs' + }))) + }; + : lq_anf$##72057594037927936621 lq_anf$##72057594037927936631 -> + case ds2 of lq_anf$##72057594037927936522 { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs1 } in + let { + ds_d1U5 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U5 + = RRelationalMSort.msort (Lists.right (Lists.split xs1)) } in + let { + rt :: GHC.Types.Int + [LclId] + rt + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rs' :: [GHC.Types.Int] + [LclId] + rs' + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rs' + } } in + let { + ds_d1U4 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U4 + = RRelationalMSort.msort (Lists.left (Lists.split xs1)) } in + let { + lt :: GHC.Types.Int + [LclId] + lt + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + ls' :: [GHC.Types.Int] + [LclId] + ls' + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + ls' + } } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + lt + })) + (case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rt + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + ls' + }) + (case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rs' + })))) + (RTick.return (GHC.Types.: x2 GHC.Types.[])); + : lq_anf$##72057594037927936622 lq_anf$##72057594037927936632 -> + let { + s1 :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s1 = Lists.split xs1 } in + let { + s2 :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s2 = Lists.split xs2 } in + let { + s1s2Lemma :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s1s2Lemma + = (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (Lists.split x1)) (Lists.split x2)) + xs1 xs2 xs1xs2Lemma } in + ? (let { + ds1 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1 = RRelationalMSort.msort (Lists.right (Lists.split xs1)) } in + let { + ds2 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds2 = RRelationalMSort.msort (Lists.right (Lists.split xs2)) } in + let { + ds1ds2Lemma :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma + = msortMsortTheorem + (Lists.right (Lists.split xs1)) + (Lists.right (Lists.split xs2)) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (Lists.right x1)) (Lists.right x2)) + (Lists.split xs1) + (Lists.split xs2) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (Lists.split x1)) + (Lists.split x2)) + xs1 xs2 xs1xs2Lemma)) } in + ? (let { + rt1 :: GHC.Types.Int + [LclId] + rt1 + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rt2 :: GHC.Types.Int + [LclId] + rt2 + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt rs' -> + rt + } } in + let { + rt1rt2Lemma :: GHC.Types.Int + [LclId] + rt1rt2Lemma + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt1 rs'1 -> + case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt2 rs'2 -> + src<.:0:0> ? (? GHC.Tuple.() rt1) rt2 + } + } } in + ? (let { + rs'1 :: [GHC.Types.Int] + [LclId] + rs'1 + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt1 rs' -> + rs' + } } in + let { + rs'2 :: [GHC.Types.Int] + [LclId] + rs'2 + = case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt2 rs' -> + rs' + } } in + let { + rs'1rs'2Lemma :: [GHC.Types.Int] + [LclId] + rs'1rs'2Lemma + = case RRelationalMSort.msort (Lists.right (Lists.split xs1)) of + { RTick.Tick rt11 rs'1 -> + case RRelationalMSort.msort (Lists.right (Lists.split xs2)) of + { RTick.Tick rt22 rs'2 -> + src<.:0:0> ? (? GHC.Tuple.() rs'1) rs'2 + } + } } in + ? (let { + ds1 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds1 = RRelationalMSort.msort (Lists.left (Lists.split xs1)) } in + let { + ds2 :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds2 = RRelationalMSort.msort (Lists.left (Lists.split xs2)) } in + let { + ds1ds2Lemma :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma + = msortMsortTheorem + (Lists.left (Lists.split xs1)) + (Lists.left (Lists.split xs2)) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (Lists.left x1)) + (Lists.left x2)) + (Lists.split xs1) + (Lists.split xs2) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) (Lists.split x1)) + (Lists.split x2)) + xs1 xs2 xs1xs2Lemma)) } in + ? (let { + lt1 :: GHC.Types.Int + [LclId] + lt1 + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + lt2 :: GHC.Types.Int + [LclId] + lt2 + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt ls' -> + lt + } } in + let { + lt1lt2Lemma :: GHC.Types.Int + [LclId] + lt1lt2Lemma + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) of + { RTick.Tick lt1 ls'1 -> + case RRelationalMSort.msort (Lists.left (Lists.split xs2)) of + { RTick.Tick lt2 ls'2 -> + src<.:0:0> ? (? GHC.Tuple.() lt1) lt2 + } + } } in + ? (let { + ls'1 :: [GHC.Types.Int] + [LclId] + ls'1 + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls' -> + ls' + } } in + let { + ls'2 :: [GHC.Types.Int] + [LclId] + ls'2 + = case RRelationalMSort.msort (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls' -> + ls' + } } in + let { + ls'1ls'2Lemma :: [GHC.Types.Int] + [LclId] + ls'1ls'2Lemma + = case RRelationalMSort.msort (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt11 ls'1 -> + case RRelationalMSort.msort (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt22 ls'2 -> + src<.:0:0> ? (? GHC.Tuple.() ls'1) ls'2 + } + } } in + ? ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (RTick.step x1 x3)) + (RTick.step x2 x4)) + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls'1 -> + lt1 + })) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt1 rs'1 -> + rt1 + })) + (GHC.Num.+ + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls'2 -> + lt2 + })) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt2 rs'2 -> + rt2 + })) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls'1 -> + lt1 + })) + (GHC.Num.+ + (GHC.Types.I# 2#) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls'2 -> + lt2 + })) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + (GHC.Types.I# 2#) + (GHC.Types.I# 2#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma) + (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 2# 2# (src<.:0:0> ? (? GHC.Tuple.() 2#) 2#)) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls'1 -> + lt1 + }) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls'2 -> + lt2 + }) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt11 ls'11 -> + case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt22 ls'22 -> + lt1lt2Lemma + } + })) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt1 rs'1 -> + rt1 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt2 rs'2 -> + rt2 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt11 rs'11 -> + case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt22 rs'22 -> + rt1rt2Lemma + } + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls'1 -> + ls'1 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt1 rs'1 -> + rs'1 + })) + (RRelationalMSort.merge + (case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls'2 -> + ls'2 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt2 rs'2 -> + rs'2 + })) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma) x3x4Lemma) + (RRelationalMSort.merge x1 x3)) + (RRelationalMSort.merge x2 x4)) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt1 ls'1 -> + ls'1 + }) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt2 ls'2 -> + ls'2 + }) + (case RRelationalMSort.msort + (Lists.left (Lists.split xs1)) + of + { RTick.Tick lt11 ls'11 -> + case RRelationalMSort.msort + (Lists.left (Lists.split xs2)) + of + { RTick.Tick lt22 ls'22 -> + ls'1ls'2Lemma + } + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt1 rs'1 -> + rs'1 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt2 rs'2 -> + rs'2 + }) + (case RRelationalMSort.msort + (Lists.right (Lists.split xs1)) + of + { RTick.Tick rt11 rs'11 -> + case RRelationalMSort.msort + (Lists.right (Lists.split xs2)) + of + { RTick.Tick rt22 rs'22 -> + rs'1rs'2Lemma + } + }))) + ls'1ls'2Lemma) + lt1lt2Lemma) + ds1ds2Lemma) + rs'1rs'2Lemma) + rt1rt2Lemma) + ds1ds2Lemma) + s1s2Lemma + } + } + } + } +-} diff --git a/tests/relational/pos/RRelationalMSort_relToUn_completed.hs b/tests/relational/pos/RRelationalMSort_relToUn_completed.hs new file mode 100644 index 0000000000..9767e57a8b --- /dev/null +++ b/tests/relational/pos/RRelationalMSort_relToUn_completed.hs @@ -0,0 +1,587 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} +{-@ LIQUID "--fast" @-} +module RRelationalMSort_relToUn_completed where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import Lists +import Log2 +import PowerOf2 +import ProofCombinators +import RRelationalMSort +import RTick +import Prelude hiding (length, take, drop, log) + + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ msortMsortTheorem :: xs1:[GHC.Types.Int] -> xs2:[GHC.Types.Int] -> xs1xs2Lemma:{VV : () | powerOf2 (Lists.length xs1) + && Lists.length xs1 == Lists.length xs2} -> {VV : () | RTick.tcost (RRelationalMSort.msort xs1) - RTick.tcost (RRelationalMSort.msort xs2) <= Lists.length xs1 * (1 + log (RRelationalMSort.differ xs1 xs2))} / [length xs1] @-} +msortMsortTheorem :: [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +msortMsortTheorem xs1 xs2 xs1xs2Lemma_d1TS = case xs1 of + [] -> case xs2 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2)) + ) + [] + [] + ( {- GOAL: [] ~ [] -} + (() ? []) ? [] + ) + (:) x2_a10c ds2_d1U1 -> + {- GOAL: RTick.return [] ~ case ds2_d1U1 of [] (...) -} + (() ? (RTick.return [])) + ? ( case ds2_d1U1 of + [] -> RTick.return (x2_a10c : []) + (:) lq_anf7205759403792793666 lq_anf7205759403792793667 -> + let s = Lists.split xs2 + in let r = RRelationalMSort.msort (Lists.right s) + in let l = RRelationalMSort.msort (Lists.left s) + in RTick.step ((2 + (RTick.tcost l)) + (RTick.tcost r)) (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + ) + (:) x1_a10c ds1_d1U1 -> case xs2 of + [] -> + {- GOAL: case ds1_d1U1 of [] (...) ~ RTick.return [] -} + ( () + ? ( case ds1_d1U1 of + [] -> RTick.return (x1_a10c : []) + (:) lq_anf7205759403792793666 lq_anf7205759403792793667 -> + let s = Lists.split xs1 + in let r = RRelationalMSort.msort (Lists.right s) + in let l = RRelationalMSort.msort (Lists.left s) + in RTick.step ((2 + (RTick.tcost l)) + (RTick.tcost r)) (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + ) + ) + ? (RTick.return []) + (:) x2_a10c ds2_d1U1 -> case ds1_d1U1 of + [] -> case ds2_d1U1 of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2)) + ) + (x1_a10c : []) + (x2_a10c : []) + ( ( {- GOAL: : ~ : -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 : x3)) ? (x2 : x4)) + ) + x1_a10c + x2_a10c + ( {- GOAL: x1_a10c ~ x2_a10c -} + (() ? x1_a10c) ? x2_a10c + ) + [] + [] + ( {- GOAL: [] ~ [] -} + (() ? []) ? [] + ) + ) ? logNat (differ [x1_a10c] [x2_a10c]) + (:) lq_anf72057594037927936662_d14 lq_anf72057594037927936672_d15 -> + {- GOAL: RTick.return (x1_a10 (...) ~ let s = Lists.split (...) -} + (() ? (RTick.return (x1_a10c : []))) + ? ( let s = Lists.split xs2 + in let r = RRelationalMSort.msort (Lists.right s) + in let l = RRelationalMSort.msort (Lists.left s) + in RTick.step ((2 + (RTick.tcost l)) + (RTick.tcost r)) (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + ) + (:) lq_anf72057594037927936661_d14 lq_anf72057594037927936671_d15 -> case ds2_d1U1 of + [] -> + {- GOAL: let s = Lists.split (...) ~ RTick.return (x2_a10 (...) -} + ( () + ? ( let s = Lists.split xs1 + in let r = RRelationalMSort.msort (Lists.right s) + in let l = RRelationalMSort.msort (Lists.left s) + in RTick.step ((2 + (RTick.tcost l)) + (RTick.tcost r)) (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + ) + ) + ? (RTick.return (x2_a10c : [])) + (:) lq_anf72057594037927936662_d14 lq_anf72057594037927936672_d15 -> if 0 == differ xs1 xs2 then theoremSameLists xs1 xs2 else + let s1_a10g = Lists.split xs1 + in let s2_a10g = Lists.split xs2 + in let s1s2Lemma_a10g = + ( {- GOAL: Lists.split ~ Lists.split -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (Lists.split x1)) ? (Lists.split x2)) + ) + xs1 + xs2 + xs1xs2Lemma_d1TS + in ( let r1_a10f = RRelationalMSort.msort (Lists.right s1_a10g) + in let r2_a10f = RRelationalMSort.msort (Lists.right s2_a10g) + lxs1 = (Lists.left s1_a10g) + rxs1 = (Lists.right s1_a10g) + lxs2 = (Lists.left s2_a10g) + rxs2 = (Lists.right s2_a10g) + in let r1r2Lemma_a10f = + assert (length xs1 >= 2) + ? assert (length xs2 >= 2) + ? powerOfIsEven n + ? assert (length (Lists.right s1_a10g) == length xs1 `div` 2) + ? assert (length (Lists.right s2_a10g) == length xs2 `div` 2) + ? msortMsortTheorem + (Lists.right s1_a10g) + (Lists.right s2_a10g) + ( ( {- GOAL: Lists.right ~ Lists.right -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (Lists.right x1)) ? (Lists.right x2)) + ) + s1_a10g + s2_a10g + s1s2Lemma_a10g + ) + ? splitDiffer n2 xs1 xs2 + ? plusLog (differ lxs1 lxs2) (differ rxs1 rxs2) (differ xs1 xs2) + in ( let l1_a10e = RRelationalMSort.msort (Lists.left s1_a10g) + in let l2_a10e = RRelationalMSort.msort (Lists.left s2_a10g) + in let l1l2Lemma_a10e = + msortMsortTheorem + (Lists.left s1_a10g) + (Lists.left s2_a10g) + ( ( {- GOAL: Lists.left ~ Lists.left -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (Lists.left x1)) ? (Lists.left x2)) + ) + s1_a10g + s2_a10g + s1s2Lemma_a10g + ) + in ( ( {- GOAL: RTick.step ~ RTick.step -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (RTick.step x1 x3)) ? (RTick.step x2 x4)) + ) + ((2 + (RTick.tcost l1_a10e)) + (RTick.tcost r1_a10f)) + ((2 + (RTick.tcost l2_a10e)) + (RTick.tcost r2_a10f)) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 + x3)) ? (x2 + x4)) + ) + (2 + (RTick.tcost l1_a10e)) + (2 + (RTick.tcost l2_a10e)) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 + x3)) ? (x2 + x4)) + ) + 2 + 2 + ( ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? x1) ? x2) + ) + 2 + 2 + ( {- GOAL: 2 ~ 2 -} + (() ? 2) ? 2 + ) + ) + (RTick.tcost l1_a10e) + (RTick.tcost l2_a10e) + ( ( {- GOAL: RTick.tcost ~ RTick.tcost -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.tcost x1)) ? (RTick.tcost x2)) + ) + l1_a10e + l2_a10e + l1l2Lemma_a10e + ) + ) + (RTick.tcost r1_a10f) + (RTick.tcost r2_a10f) + ( ( {- GOAL: RTick.tcost ~ RTick.tcost -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.tcost x1)) ? (RTick.tcost x2)) + ) + r1_a10f + r2_a10f + r1r2Lemma_a10f + ) + ) + (RRelationalMSort.merge (RTick.tval l1_a10e) (RTick.tval r1_a10f)) + (RRelationalMSort.merge (RTick.tval l2_a10e) (RTick.tval r2_a10f)) + ( ( {- GOAL: RRelationalMSort.mer (...) ~ RRelationalMSort.mer (...) -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (RRelationalMSort.merge x1 x3)) ? (RRelationalMSort.merge x2 x4)) + ) + (RTick.tval l1_a10e) + (RTick.tval l2_a10e) + ( ( {- GOAL: RTick.tval ~ RTick.tval -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.tval x1)) ? (RTick.tval x2)) + ) + l1_a10e + l2_a10e + l1l2Lemma_a10e + ) + (RTick.tval r1_a10f) + (RTick.tval r2_a10f) + ( ( {- GOAL: RTick.tval ~ RTick.tval -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.tval x1)) ? (RTick.tval x2)) + ) + r1_a10f + r2_a10f + r1r2Lemma_a10f + ) + ) + ) + ? l1l2Lemma_a10e + ) + ? r1r2Lemma_a10f + ) + ? s1s2Lemma_a10g + ? distributeDiv n 3 (log (differ xs1 xs2)) + where + n = length xs1 + n2 = length xs1 `div` 2 + +{-@ assume theoremSameLists + :: xs:[Int] + -> ys:{[Int] | length xs = length ys && powerOf2 (length xs) + && (differ xs ys == 0) } + -> { tcost (msort xs) - tcost (msort ys) + <= length xs * (1 + log (differ xs ys))} + @-} +theoremSameLists :: [Int] -> [Int] -> Proof +theoremSameLists _ _ = () + +{-@ ple splitDiffer @-} +splitDiffer :: Int -> [Int] -> [Int] -> Proof +{-@ splitDiffer :: n:Nat + -> xs:{[Int] | n <= length xs } + -> ys:{[Int] | n <= length ys && length xs == length ys } + -> { differ xs ys == differ (take n xs) (take n ys) + + differ (drop n xs) (drop n ys) } +@-} +splitDiffer _ [] [] = () +splitDiffer _ [] (_:_) = () +splitDiffer _ (_:_) [] = () +splitDiffer 0 _ _ = () -- NV: based on the definitions of take drop take 0 = [] and drop 0 xs = xs only when you are not in the list empty case +splitDiffer n (x:xs) (y:ys) + = differ (x:xs) (y:ys) + ? splitDiffer (n-1) xs ys + === differ (take n (x:xs)) (take n (y:ys)) + differ (drop n (x:xs)) (drop n (y:ys)) + *** QED + + +{- BARE CORE +\ (xs1_d1TS :: [GHC.Types.Int]) + (xs2_d1TS :: [GHC.Types.Int]) + (xs1xs2Lemma_d1TS :: [GHC.Types.Int]) -> + case xs1_d1TS of lq_anf$##72057594037927936501_dO { + [] -> + case xs2_d1TS of lq_anf$##72057594037927936502_dO { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.return x1)) + (RTick.return x2)) + GHC.Types.[] + GHC.Types.[] + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[]); + : x2_a10c ds2_d1U1 -> + src<.:0:0> + ? (? GHC.Tuple.() (RTick.return GHC.Types.[])) + (case ds2_d1U1 of lq_anf$##7205759403792793652 { + [] -> RTick.return (GHC.Types.: x2_a10c GHC.Types.[]); + : lq_anf$##7205759403792793666 lq_anf$##7205759403792793667 -> + let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs2_d1TS } in + let { + r :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r = RRelationalMSort.msort (Lists.right s) } in + let { + l :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l = RRelationalMSort.msort (Lists.left s) } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l)) (RTick.tcost r)) + (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + }) + }; + : x1_a10c ds1_d1U1 -> + case xs2_d1TS of lq_anf$##72057594037927936502_dO { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (case ds1_d1U1 of lq_anf$##7205759403792793652 { + [] -> RTick.return (GHC.Types.: x1_a10c GHC.Types.[]); + : lq_anf$##7205759403792793666 lq_anf$##7205759403792793667 -> + let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs1_d1TS } in + let { + r :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r = RRelationalMSort.msort (Lists.right s) } in + let { + l :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l = RRelationalMSort.msort (Lists.left s) } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l)) (RTick.tcost r)) + (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)) + })) + (RTick.return GHC.Types.[]); + : x2_a10c ds2_d1U1 -> + case ds1_d1U1 of lq_anf$##72057594037927936521_dQ { + [] -> + case ds2_d1U1 of lq_anf$##72057594037927936522_dQ { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.return x1)) + (RTick.return x2)) + (GHC.Types.: x1_a10c GHC.Types.[]) + (GHC.Types.: x2_a10c GHC.Types.[]) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (GHC.Types.: x1 x3)) + (GHC.Types.: x2 x4)) + x1_a10c + x2_a10c + (src<.:0:0> ? (? GHC.Tuple.() x1_a10c) x2_a10c) + GHC.Types.[] + GHC.Types.[] + (src<.:0:0> ? (? GHC.Tuple.() GHC.Types.[]) GHC.Types.[])); + : lq_anf$##72057594037927936662_d14 + lq_anf$##72057594037927936672_d15 -> + src<.:0:0> + ? (? GHC.Tuple.() + (RTick.return (GHC.Types.: x1_a10c GHC.Types.[]))) + (let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs2_d1TS } in + let { + r :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r = RRelationalMSort.msort (Lists.right s) } in + let { + l :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l = RRelationalMSort.msort (Lists.left s) } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l)) (RTick.tcost r)) + (RRelationalMSort.merge (RTick.tval l) (RTick.tval r))) + }; + : lq_anf$##72057594037927936661_d14 + lq_anf$##72057594037927936671_d15 -> + case ds2_d1U1 of lq_anf$##72057594037927936522_dQ { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (let { + s :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s = Lists.split xs1_d1TS } in + let { + r :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r = RRelationalMSort.msort (Lists.right s) } in + let { + l :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l = RRelationalMSort.msort (Lists.left s) } in + RTick.step + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l)) (RTick.tcost r)) + (RRelationalMSort.merge (RTick.tval l) (RTick.tval r)))) + (RTick.return (GHC.Types.: x2_a10c GHC.Types.[])); + : lq_anf$##72057594037927936662_d14 + lq_anf$##72057594037927936672_d15 -> + let { + s1_a10g :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s1_a10g = Lists.split xs1_d1TS } in + let { + s2_a10g :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s2_a10g = Lists.split xs2_d1TS } in + let { + s1s2Lemma_a10g :: Lists.P [GHC.Types.Int] [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}] + s1s2Lemma_a10g + = (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (Lists.split x1)) + (Lists.split x2)) + xs1_d1TS xs2_d1TS xs1xs2Lemma_d1TS } in + ? (let { + r1_a10f :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r1_a10f = RRelationalMSort.msort (Lists.right s1_a10g) } in + let { + r2_a10f :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r2_a10f = RRelationalMSort.msort (Lists.right s2_a10g) } in + let { + r1r2Lemma_a10f :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + r1r2Lemma_a10f + = msortMsortTheorem_rKO + (Lists.right s1_a10g) + (Lists.right s2_a10g) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (Lists.right x1)) + (Lists.right x2)) + s1_a10g s2_a10g s1s2Lemma_a10g) } in + ? (let { + l1_a10e :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l1_a10e = RRelationalMSort.msort (Lists.left s1_a10g) } in + let { + l2_a10e :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l2_a10e = RRelationalMSort.msort (Lists.left s2_a10g) } in + let { + l1l2Lemma_a10e :: RTick.Tick [GHC.Types.Int] + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + l1l2Lemma_a10e + = msortMsortTheorem_rKO + (Lists.left s1_a10g) + (Lists.left s2_a10g) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (Lists.left x1)) + (Lists.left x2)) + s1_a10g s2_a10g s1s2Lemma_a10g) } in + ? ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RTick.step x1 x3)) + (RTick.step x2 x4)) + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l1_a10e)) + (RTick.tcost r1_a10f)) + (GHC.Num.+ + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l2_a10e)) + (RTick.tcost r2_a10f)) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l1_a10e)) + (GHC.Num.+ (GHC.Types.I# 2#) (RTick.tcost l2_a10e)) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + (GHC.Types.I# 2#) + (GHC.Types.I# 2#) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 2# 2# (src<.:0:0> ? (? GHC.Tuple.() 2#) 2#)) + (RTick.tcost l1_a10e) + (RTick.tcost l2_a10e) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.tcost x1)) + (RTick.tcost x2)) + l1_a10e l2_a10e l1l2Lemma_a10e)) + (RTick.tcost r1_a10f) + (RTick.tcost r2_a10f) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.tcost x1)) + (RTick.tcost x2)) + r1_a10f r2_a10f r1r2Lemma_a10f)) + (RRelationalMSort.merge (RTick.tval l1_a10e) (RTick.tval r1_a10f)) + (RRelationalMSort.merge (RTick.tval l2_a10e) (RTick.tval r2_a10f)) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RRelationalMSort.merge x1 x3)) + (RRelationalMSort.merge x2 x4)) + (RTick.tval l1_a10e) + (RTick.tval l2_a10e) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.tval x1)) + (RTick.tval x2)) + l1_a10e l2_a10e l1l2Lemma_a10e) + (RTick.tval r1_a10f) + (RTick.tval r2_a10f) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.tval x1)) + (RTick.tval x2)) + r1_a10f r2_a10f r1r2Lemma_a10f))) + l1l2Lemma_a10e) + r1r2Lemma_a10f) + s1s2Lemma_a10g + } + } + } + } +-} diff --git a/tests/relational/pos/RSquareAndMultiply.hs b/tests/relational/pos/RSquareAndMultiply.hs new file mode 100644 index 0000000000..53a2235c0b --- /dev/null +++ b/tests/relational/pos/RSquareAndMultiply.hs @@ -0,0 +1,78 @@ +{- Square And Multiply 13/5/4 -} + +{-@ LIQUID "--relational-hints" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +module RSquareAndMultiply where + +{-@ infix <*> @-} +{-@ infix : @-} + +import RTick +import Language.Haskell.Liquid.ProofCombinators +import Prelude hiding (return, (>>=), pure, (<*>)) + +theorem :: Int -> Int -> [Int] -> [Int] -> Proof +{-@ theorem + :: t:Nat + -> x:Int + -> l1:{[Int] | 0 < len l1} + -> l2:{[Int] | len l1 == len l2 } + -> { tcost (sam t x l1) - tcost (sam t x l2) <= t * (diff l1 l2) } + / [len l1] +@-} +theorem _ _ [_] [_] = () +theorem t x (l1:ls1@(_:_)) (l2:ls2@(_:_)) + | l1 == 0 && l2 == 0 = theorem t x ls1 ls2 + +theorem t x (l1:ls1@(_:_)) (l2:ls2@(_:_)) + | l1 /= 0 && l2 == 0 = theorem t x ls1 ls2 + +theorem t x (l1:ls1@(_:_)) (l2:ls2@(_:_)) + | l1 == 0 && l2 /= 0 = theorem t x ls1 ls2 + +theorem t x (l1:ls1@(_:_)) (l2:ls2@(_:_)) + | l1 /= 0 && l2 /= 0 = theorem t x ls1 ls2 + +{-@ reflect diff @-} +{-@ diff :: l1:[Int] -> l2:{[Int] | len l1 == len l2 } -> Int @-} +diff :: [Int] -> [Int] -> Int +diff [] [] = 0 +diff (x:xs) (y:ys) = (if x == y then 0 else 1) + diff xs ys + +{-@ reflect sam @-} +sam :: Int -> Int -> [Int] -> Tick Int +{-@ sam :: t:Nat -> Int -> bs:{[Int] | 0 < len bs } -> Tick Int @-} +sam _ x [b] = return (if b == 0 then 1 else x) +sam t x (b:bs) = if b == 0 + then let Tick m v = sam t x bs + in pure power2 <*> Tick m v + else let Tick m v = sam t x bs + Tick n u = power2Times t x v + in Tick (m + n) u + +--- Proof --- +{-@ relational sam ~ sam + :: { t1:Nat -> x1:Int -> l1:[Int] -> Tick Int + ~ t2:Nat -> x2:Int -> l2:[Int] -> Tick Int + | !(t1 = t2) + :=> !(x1 = x2) + :=> !(0 < len l1 && len l1 = len l2) + :=> RTick.tcost (r1 t1 x1 l1) + - RTick.tcost (r2 t2 x2 l2) + <= t1 * (RSquareAndMultiply.diff l1 l2) } +@-} +--- End --- + +{-@ reflect power2Times @-} +{-@ power2Times :: Nat -> Int -> Int -> Tick Int @-} +power2Times :: Int -> Int -> Int -> Tick Int +power2Times t x s = waitN t (multiply x (power2 s)) + +{-@ reflect multiply @-} +multiply :: Int -> Int -> Int +multiply x y = x * y + +{-@ reflect power2 @-} +power2 :: Int -> Int +power2 x = x * x diff --git a/tests/relational/pos/RSquareAndMultiply_relToUn.hs b/tests/relational/pos/RSquareAndMultiply_relToUn.hs new file mode 100644 index 0000000000..e326df8b39 --- /dev/null +++ b/tests/relational/pos/RSquareAndMultiply_relToUn.hs @@ -0,0 +1,1051 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RSquareAndMultiply_relToUn (module RSquareAndMultiply_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import RSquareAndMultiply +import RTick +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ samSamTheorem :: t1:{VV##0 : GHC.Types.Int | VV##0 >= 0} -> t2:{VV##0 : GHC.Types.Int | VV##0 >= 0} -> t1t2Lemma:{VV : () | t1 == t2} -> x1:GHC.Types.Int -> x2:GHC.Types.Int -> x1x2Lemma:{VV : () | x1 == x2} -> l1:[GHC.Types.Int] -> l2:[GHC.Types.Int] -> l1l2Lemma:{VV : () | len l1 == len l2 + && 0 < len l1} -> {VV : () | RTick.tcost (RSquareAndMultiply.sam t1 x1 l1) - RTick.tcost (RSquareAndMultiply.sam t2 x2 l2) <= t1 * RSquareAndMultiply.diff l1 l2} @-} +samSamTheorem :: GHC.Types.Int -> GHC.Types.Int -> () -> GHC.Types.Int -> GHC.Types.Int -> () -> [GHC.Types.Int] -> [GHC.Types.Int] -> () -> () +samSamTheorem t1 t2 t1t2Lemma_d1TX x1 x2 x1x2Lemma_aVq l1 l2 l1l2Lemma_d1TY = case l1 of + [] -> case l2 of + [] -> {- GOAL: () ~ () -} () + (:) b2_aVr ds2_d1Uc -> {- GOAL: () ~ case ds2_d1Uc of [] (...) -} () + (:) b1_aVr ds1_d1Uc -> case l2 of + [] -> {- GOAL: case ds1_d1Uc of [] (...) ~ () -} () + (:) b2_aVr ds2_d1Uc -> case ds1_d1Uc of + [] -> case ds2_d1Uc of + [] -> + ( {- GOAL: RTick.return ~ RTick.return -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.return x1)) ? (RTick.return x2)) + ) + ( case b1_aVr GHC.Classes.== 0 of + False -> x1 + True -> 1 + ) + ( case b2_aVr GHC.Classes.== 0 of + False -> x2 + True -> 1 + ) + ( case b1_aVr GHC.Classes.== 0 of + False -> case b2_aVr GHC.Classes.== 0 of + False -> x1x2Lemma_aVq + True -> + {- GOAL: x1_aVq ~ 1 -} + (() ? x1) ? 1 + True -> case b2_aVr GHC.Classes.== 0 of + False -> + {- GOAL: 1 ~ x2_aVq -} + (() ? 1) ? x2 + True -> + ( {- GOAL: ~ -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? x1) ? x2) + ) + 1 + 1 + ( {- GOAL: 1 ~ 1 -} + (() ? 1) ? 1 + ) + ) + (:) lq_anf72057594037927936832_d1l lq_anf72057594037927936842_d1m -> + {- GOAL: RTick.return (case b (...) ~ case b2_aVr GHC.Clas (...) -} + ( () + ? ( RTick.return + ( case b1_aVr GHC.Classes.== 0 of + False -> x1 + True -> 1 + ) + ) + ) + ? ( case b2_aVr GHC.Classes.== 0 of + False -> + let ds_d1Ub = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let m = case ds_d1Ub of + Tick m v -> m + in let v = case ds_d1Ub of + Tick m v -> v + in let ds_d1Ua = RSquareAndMultiply.power2Times t2 x2 v + in let n = case ds_d1Ua of + Tick n u -> n + in let u = case ds_d1Ua of + Tick n u -> u + in RTick.Tick (m + n) u + True -> + let ds_d1U7 = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let m = case ds_d1U7 of + Tick m v -> m + in let v = case ds_d1U7 of + Tick m v -> v + in (RTick.pure RSquareAndMultiply.power2) RTick.<*> (RTick.Tick m v) + ) + (:) lq_anf72057594037927936831_d1l lq_anf72057594037927936841_d1m -> case ds2_d1Uc of + [] -> + {- GOAL: case b1_aVr GHC.Clas (...) ~ RTick.return (case b (...) -} + ( () + ? ( case b1_aVr GHC.Classes.== 0 of + False -> + let ds_d1Ub = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let m = case ds_d1Ub of + Tick m v -> m + in let v = case ds_d1Ub of + Tick m v -> v + in let ds_d1Ua = RSquareAndMultiply.power2Times t1 x1 v + in let n = case ds_d1Ua of + Tick n u -> n + in let u = case ds_d1Ua of + Tick n u -> u + in RTick.Tick (m + n) u + True -> + let ds_d1U7 = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let m = case ds_d1U7 of + Tick m v -> m + in let v = case ds_d1U7 of + Tick m v -> v + in (RTick.pure RSquareAndMultiply.power2) RTick.<*> (RTick.Tick m v) + ) + ) + ? ( RTick.return + ( case b2_aVr GHC.Classes.== 0 of + False -> x2 + True -> 1 + ) + ) + (:) lq_anf72057594037927936832_d1l lq_anf72057594037927936842_d1m -> case b1_aVr GHC.Classes.== 0 of + False -> case b2_aVr GHC.Classes.== 0 of + False -> + let ds1_d1Ub = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let ds2_d1Ub = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let ds1ds2Lemma_d1Ub = + samSamTheorem + t1 + t2 + t1t2Lemma_d1TX + x1 + x2 + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + ( {- GOAL: ds1_d1Uc ~ ds2_d1Uc -} + (() ? ds1_d1Uc) ? ds2_d1Uc + ) + in ( let m1_aXk = case ds1_d1Ub of + Tick m v -> m + in let m2_aXk = case ds2_d1Ub of + Tick m v -> m + in let m1m2Lemma_aXk = case ds1_d1Ub of + Tick m1_aXk v1_aXl -> case ds2_d1Ub of + Tick m2_aXk v2_aXl -> + {- GOAL: m1_aXk ~ m2_aXk -} + (() ? m1_aXk) ? m2_aXk + in ( let v1_aXl = case ds1_d1Ub of + Tick m1_aXk v -> v + in let v2_aXl = case ds2_d1Ub of + Tick m2_aXk v -> v + in let v1v2Lemma_aXl = case ds1_d1Ub of + Tick m11_aXk v1_aXl -> case ds2_d1Ub of + Tick m22_aXk v2_aXl -> + {- GOAL: v1_aXl ~ v2_aXl -} + (() ? v1_aXl) ? v2_aXl + in ( let ds1_d1Ua = RSquareAndMultiply.power2Times t1 x1 v1_aXl + in let ds2_d1Ua = RSquareAndMultiply.power2Times t2 x2 v2_aXl + in let ds1ds2Lemma_d1Ua = + ( {- GOAL: RSquareAndMultiply.p (...) ~ RSquareAndMultiply.p (...) -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp x5 x6 x5x6Lemma_xp -> ((((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? x5x6Lemma_xp) ? (RSquareAndMultiply.power2Times x1 x3 x5)) ? (RSquareAndMultiply.power2Times x2 x4 x6)) + ) + t1 + t2 + t1t2Lemma_d1TX + x1 + x2 + x1x2Lemma_aVq + v1_aXl + v2_aXl + v1v2Lemma_aXl + in ( let n1_aXr = case ds1_d1Ua of + Tick n u -> n + in let n2_aXr = case ds2_d1Ua of + Tick n u -> n + in let n1n2Lemma_aXr = case ds1_d1Ua of + Tick n1_aXr u1_aXs -> case ds2_d1Ua of + Tick n2_aXr u2_aXs -> + {- GOAL: n1_aXr ~ n2_aXr -} + (() ? n1_aXr) ? n2_aXr + in ( let u1_aXs = case ds1_d1Ua of + Tick n1_aXr u -> u + in let u2_aXs = case ds2_d1Ua of + Tick n2_aXr u -> u + in let u1u2Lemma_aXs = case ds1_d1Ua of + Tick n11_aXr u1_aXs -> case ds2_d1Ua of + Tick n22_aXr u2_aXs -> + {- GOAL: u1_aXs ~ u2_aXs -} + (() ? u1_aXs) ? u2_aXs + in ( ( {- GOAL: RTick.Tick ~ RTick.Tick -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (RTick.Tick x1 x3)) ? (RTick.Tick x2 x4)) + ) + (m1_aXk + n1_aXr) + (m2_aXk + n2_aXr) + ( ( {- GOAL: + ~ + -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 + x3)) ? (x2 + x4)) + ) + m1_aXk + m2_aXk + m1m2Lemma_aXk + n1_aXr + n2_aXr + n1n2Lemma_aXr + ) + u1_aXs + u2_aXs + u1u2Lemma_aXs + ) + ? u1u2Lemma_aXs + ) + ? n1n2Lemma_aXr + ) + ? ds1ds2Lemma_d1Ua + ) + ? v1v2Lemma_aXl + ) + ? m1m2Lemma_aXk + ) + ? ds1ds2Lemma_d1Ub + True -> + let ds1_d1Ub = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let ds2_d1U7 = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let ds1ds2Lemma_d1Ub = + samSamTheorem + t1 + t2 + t1t2Lemma_d1TX + x1 + x2 + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + ( {- GOAL: ds1_d1Uc ~ ds2_d1Uc -} + (() ? ds1_d1Uc) ? ds2_d1Uc + ) + in ( let m1_aXk = case ds1_d1Ub of + Tick m v -> m + in let m2_aX7 = case ds2_d1U7 of + Tick m v -> m + in let m1m2Lemma_aXk = case ds1_d1Ub of + Tick m1_aXk v1_aXl -> case ds2_d1U7 of + Tick m2_aX7 v2_aX8 -> + {- GOAL: m1_aXk ~ m2_aX7 -} + (() ? m1_aXk) ? m2_aX7 + in ( let v1_aXl = case ds1_d1Ub of + Tick m1_aXk v -> v + in let v2_aX8 = case ds2_d1U7 of + Tick m2_aX7 v -> v + in let v1v2Lemma_aXl = case ds1_d1Ub of + Tick m11_aXk v1_aXl -> case ds2_d1U7 of + Tick m22_aX7 v2_aX8 -> + {- GOAL: v1_aXl ~ v2_aX8 -} + (() ? v1_aXl) ? v2_aX8 + in ( {- GOAL: let ds_d1Ua = RSquar (...) ~ (RTick.pure RSquareA (...) -} + ( () + ? ( let ds_d1Ua = RSquareAndMultiply.power2Times t1 x1 v1_aXl + in let n = case ds_d1Ua of + Tick n u -> n + in let u = case ds_d1Ua of + Tick n u -> u + in RTick.Tick (m1_aXk + n) u + ) + ) + ? ((RTick.pure RSquareAndMultiply.power2) RTick.<*> (RTick.Tick m2_aX7 v2_aX8)) + ) + ? v1v2Lemma_aXl + ) + ? m1m2Lemma_aXk + ) + ? ds1ds2Lemma_d1Ub + True -> case b2_aVr GHC.Classes.== 0 of + False -> + let ds1_d1U7 = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let ds2_d1Ub = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let ds1ds2Lemma_d1U7 = + samSamTheorem + t1 + t2 + t1t2Lemma_d1TX + x1 + x2 + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + ( {- GOAL: ds1_d1Uc ~ ds2_d1Uc -} + (() ? ds1_d1Uc) ? ds2_d1Uc + ) + in ( let m1_aX7 = case ds1_d1U7 of + Tick m v -> m + in let m2_aXk = case ds2_d1Ub of + Tick m v -> m + in let m1m2Lemma_aX7 = case ds1_d1U7 of + Tick m1_aX7 v1_aX8 -> case ds2_d1Ub of + Tick m2_aXk v2_aXl -> + {- GOAL: m1_aX7 ~ m2_aXk -} + (() ? m1_aX7) ? m2_aXk + in ( let v1_aX8 = case ds1_d1U7 of + Tick m1_aX7 v -> v + in let v2_aXl = case ds2_d1Ub of + Tick m2_aXk v -> v + in let v1v2Lemma_aX8 = case ds1_d1U7 of + Tick m11_aX7 v1_aX8 -> case ds2_d1Ub of + Tick m22_aXk v2_aXl -> + {- GOAL: v1_aX8 ~ v2_aXl -} + (() ? v1_aX8) ? v2_aXl + in ( {- GOAL: (RTick.pure RSquareA (...) ~ let ds_d1Ua = RSquar (...) -} + (() ? ((RTick.pure RSquareAndMultiply.power2) RTick.<*> (RTick.Tick m1_aX7 v1_aX8))) + ? ( let ds_d1Ua = RSquareAndMultiply.power2Times t2 x2 v2_aXl + in let n = case ds_d1Ua of + Tick n u -> n + in let u = case ds_d1Ua of + Tick n u -> u + in RTick.Tick (m2_aXk + n) u + ) + ) + ? v1v2Lemma_aX8 + ) + ? m1m2Lemma_aX7 + ) + ? ds1ds2Lemma_d1U7 + True -> + let ds1_d1U7 = RSquareAndMultiply.sam t1 x1 ds1_d1Uc + in let ds2_d1U7 = RSquareAndMultiply.sam t2 x2 ds2_d1Uc + in let ds1ds2Lemma_d1U7 = + samSamTheorem + t1 + t2 + t1t2Lemma_d1TX + x1 + x2 + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + ( {- GOAL: ds1_d1Uc ~ ds2_d1Uc -} + (() ? ds1_d1Uc) ? ds2_d1Uc + ) + in ( let m1_aX7 = case ds1_d1U7 of + Tick m v -> m + in let m2_aX7 = case ds2_d1U7 of + Tick m v -> m + in let m1m2Lemma_aX7 = case ds1_d1U7 of + Tick m1_aX7 v1_aX8 -> case ds2_d1U7 of + Tick m2_aX7 v2_aX8 -> + {- GOAL: m1_aX7 ~ m2_aX7 -} + (() ? m1_aX7) ? m2_aX7 + in ( let v1_aX8 = case ds1_d1U7 of + Tick m1_aX7 v -> v + in let v2_aX8 = case ds2_d1U7 of + Tick m2_aX7 v -> v + in let v1v2Lemma_aX8 = case ds1_d1U7 of + Tick m11_aX7 v1_aX8 -> case ds2_d1U7 of + Tick m22_aX7 v2_aX8 -> + {- GOAL: v1_aX8 ~ v2_aX8 -} + (() ? v1_aX8) ? v2_aX8 + in ( ( {- GOAL: RTick.<*> ~ RTick.<*> -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (x1 RTick.<*> x3)) ? (x2 RTick.<*> x4)) + ) + (RTick.pure RSquareAndMultiply.power2) + (RTick.pure RSquareAndMultiply.power2) + ( ( {- GOAL: RTick.pure ~ RTick.pure -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RTick.pure x1)) ? (RTick.pure x2)) + ) + RSquareAndMultiply.power2 + RSquareAndMultiply.power2 + ( {- GOAL: RSquareAndMultiply.p (...) ~ RSquareAndMultiply.p (...) -} + (\x1 x2 x1x2Lemma_xp -> ((() ? x1x2Lemma_xp) ? (RSquareAndMultiply.power2 x1)) ? (RSquareAndMultiply.power2 x2)) + ) + ) + (RTick.Tick m1_aX7 v1_aX8) + (RTick.Tick m2_aX7 v2_aX8) + ( ( {- GOAL: RTick.Tick ~ RTick.Tick -} + (\x1 x2 x1x2Lemma_xp x3 x4 x3x4Lemma_xp -> (((() ? x1x2Lemma_xp) ? x3x4Lemma_xp) ? (RTick.Tick x1 x3)) ? (RTick.Tick x2 x4)) + ) + m1_aX7 + m2_aX7 + m1m2Lemma_aX7 + v1_aX8 + v2_aX8 + v1v2Lemma_aX8 + ) + ) + ? v1v2Lemma_aX8 + ) + ? m1m2Lemma_aX7 + ) + ? ds1ds2Lemma_d1U7 + +{- BARE CORE +\ (t1_d1TX :: GHC.Types.Int) + (t2_d1TX :: GHC.Types.Int) + (t1t2Lemma_d1TX :: GHC.Types.Int) + (x1_aVq :: GHC.Types.Int) + (x2_aVq :: GHC.Types.Int) + (x1x2Lemma_aVq :: GHC.Types.Int) + (l1_d1TY :: [GHC.Types.Int]) + (l2_d1TY :: [GHC.Types.Int]) + (l1l2Lemma_d1TY :: [GHC.Types.Int]) -> + case l1_d1TY of lq_anf$##72057594037927936651_d13 { + [] -> + case l2_d1TY of lq_anf$##72057594037927936652_d13 { + [] -> src<.:0:0> GHC.Tuple.(); + : b2_aVr ds2_d1Uc -> src<.:0:0> GHC.Tuple.() + }; + : b1_aVr ds1_d1Uc -> + case l2_d1TY of lq_anf$##72057594037927936652_d13 { + [] -> src<.:0:0> GHC.Tuple.(); + : b2_aVr ds2_d1Uc -> + case ds1_d1Uc of lq_anf$##72057594037927936691_d17 { + [] -> + case ds2_d1Uc of lq_anf$##72057594037927936692_d17 { + [] -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.return x1)) + (RTick.return x2)) + (case GHC.Classes.== b1_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793680 { + GHC.Types.False -> x1_aVq; + GHC.Types.True -> GHC.Types.I# 1# + }) + (case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793680 { + GHC.Types.False -> x2_aVq; + GHC.Types.True -> GHC.Types.I# 1# + }) + (case GHC.Classes.== b1_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936801_d1i { + GHC.Types.False -> + case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936802_d1i { + GHC.Types.False -> x1x2Lemma_aVq; + GHC.Types.True -> + src<.:0:0> ? (? GHC.Tuple.() x1_aVq) (GHC.Types.I# 1#) + }; + GHC.Types.True -> + case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936802_d1i { + GHC.Types.False -> + src<.:0:0> ? (? GHC.Tuple.() (GHC.Types.I# 1#)) x2_aVq; + GHC.Types.True -> + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (GHC.Types.I# x1)) + (GHC.Types.I# x2)) + 1# 1# (src<.:0:0> ? (? GHC.Tuple.() 1#) 1#) + } + }); + : lq_anf$##72057594037927936832_d1l + lq_anf$##72057594037927936842_d1m -> + src<.:0:0> + ? (? GHC.Tuple.() + (RTick.return + (case GHC.Classes.== b1_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793680 { + GHC.Types.False -> x1_aVq; + GHC.Types.True -> GHC.Types.I# 1# + }))) + (case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793673 { + GHC.Types.False -> + let { + ds_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1Ub = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + m :: GHC.Types.Int + [LclId] + m = case ds_d1Ub of { RTick.Tick m v -> m } } in + let { + v :: GHC.Types.Int + [LclId] + v = case ds_d1Ub of { RTick.Tick m v -> v } } in + let { + ds_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1Ua = RSquareAndMultiply.power2Times t2_d1TX x2_aVq v } in + let { + n :: GHC.Types.Int + [LclId] + n = case ds_d1Ua of { RTick.Tick n u -> n } } in + let { + u :: GHC.Types.Int + [LclId] + u = case ds_d1Ua of { RTick.Tick n u -> u } } in + RTick.Tick (GHC.Num.+ m n) u; + GHC.Types.True -> + let { + ds_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U7 = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + m :: GHC.Types.Int + [LclId] + m = case ds_d1U7 of { RTick.Tick m v -> m } } in + let { + v :: GHC.Types.Int + [LclId] + v = case ds_d1U7 of { RTick.Tick m v -> v } } in + RTick.<*> (RTick.pure RSquareAndMultiply.power2) (RTick.Tick m v) + }) + }; + : lq_anf$##72057594037927936831_d1l + lq_anf$##72057594037927936841_d1m -> + case ds2_d1Uc of lq_anf$##72057594037927936692_d17 { + [] -> + src<.:0:0> + ? (? GHC.Tuple.() + (case GHC.Classes.== b1_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793673 { + GHC.Types.False -> + let { + ds_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1Ub = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + m :: GHC.Types.Int + [LclId] + m = case ds_d1Ub of { RTick.Tick m v -> m } } in + let { + v :: GHC.Types.Int + [LclId] + v = case ds_d1Ub of { RTick.Tick m v -> v } } in + let { + ds_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1Ua = RSquareAndMultiply.power2Times t1_d1TX x1_aVq v } in + let { + n :: GHC.Types.Int + [LclId] + n = case ds_d1Ua of { RTick.Tick n u -> n } } in + let { + u :: GHC.Types.Int + [LclId] + u = case ds_d1Ua of { RTick.Tick n u -> u } } in + RTick.Tick (GHC.Num.+ m n) u; + GHC.Types.True -> + let { + ds_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds_d1U7 = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + m :: GHC.Types.Int + [LclId] + m = case ds_d1U7 of { RTick.Tick m v -> m } } in + let { + v :: GHC.Types.Int + [LclId] + v = case ds_d1U7 of { RTick.Tick m v -> v } } in + RTick.<*> (RTick.pure RSquareAndMultiply.power2) (RTick.Tick m v) + })) + (RTick.return + (case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##7205759403792793680 { + GHC.Types.False -> x2_aVq; + GHC.Types.True -> GHC.Types.I# 1# + })); + : lq_anf$##72057594037927936832_d1l + lq_anf$##72057594037927936842_d1m -> + case GHC.Classes.== b1_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936731_d1b { + GHC.Types.False -> + case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936732_d1b { + GHC.Types.False -> + let { + ds1_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1_d1Ub = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + ds2_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds2_d1Ub = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + ds1ds2Lemma_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma_d1Ub + = samSamTheorem_rxR + t1_d1TX + t2_d1TX + t1t2Lemma_d1TX + x1_aVq + x2_aVq + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + (src<.:0:0> ? (? GHC.Tuple.() ds1_d1Uc) ds2_d1Uc) } in + ? (let { + m1_aXk :: GHC.Types.Int + [LclId] + m1_aXk = case ds1_d1Ub of { RTick.Tick m v -> m } } in + let { + m2_aXk :: GHC.Types.Int + [LclId] + m2_aXk = case ds2_d1Ub of { RTick.Tick m v -> m } } in + let { + m1m2Lemma_aXk :: GHC.Types.Int + [LclId] + m1m2Lemma_aXk + = case ds1_d1Ub of { RTick.Tick m1_aXk v1_aXl -> + case ds2_d1Ub of { RTick.Tick m2_aXk v2_aXl -> + src<.:0:0> ? (? GHC.Tuple.() m1_aXk) m2_aXk + } + } } in + ? (let { + v1_aXl :: GHC.Types.Int + [LclId] + v1_aXl = case ds1_d1Ub of { RTick.Tick m1_aXk v -> v } } in + let { + v2_aXl :: GHC.Types.Int + [LclId] + v2_aXl = case ds2_d1Ub of { RTick.Tick m2_aXk v -> v } } in + let { + v1v2Lemma_aXl :: GHC.Types.Int + [LclId] + v1v2Lemma_aXl + = case ds1_d1Ub of { RTick.Tick m11_aXk v1_aXl -> + case ds2_d1Ub of { RTick.Tick m22_aXk v2_aXl -> + src<.:0:0> ? (? GHC.Tuple.() v1_aXl) v2_aXl + } + } } in + ? (let { + ds1_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, + ConLike=False, WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds1_d1Ua + = RSquareAndMultiply.power2Times t1_d1TX x1_aVq v1_aXl } in + let { + ds2_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, + ConLike=False, WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds2_d1Ua + = RSquareAndMultiply.power2Times t2_d1TX x2_aVq v2_aXl } in + let { + ds1ds2Lemma_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, + ConLike=False, WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma_d1Ua + = (src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) + (x5 :: ()) + (x6 :: ()) + (x5x6Lemma_xp :: ()) -> + ? (? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + x5x6Lemma_xp) + (RSquareAndMultiply.power2Times x1 x3 x5)) + (RSquareAndMultiply.power2Times x2 x4 x6)) + t1_d1TX + t2_d1TX + t1t2Lemma_d1TX + x1_aVq + x2_aVq + x1x2Lemma_aVq + v1_aXl + v2_aXl + v1v2Lemma_aXl } in + ? (let { + n1_aXr :: GHC.Types.Int + [LclId] + n1_aXr = case ds1_d1Ua of { RTick.Tick n u -> n } } in + let { + n2_aXr :: GHC.Types.Int + [LclId] + n2_aXr = case ds2_d1Ua of { RTick.Tick n u -> n } } in + let { + n1n2Lemma_aXr :: GHC.Types.Int + [LclId] + n1n2Lemma_aXr + = case ds1_d1Ua of { RTick.Tick n1_aXr u1_aXs -> + case ds2_d1Ua of { RTick.Tick n2_aXr u2_aXs -> + src<.:0:0> ? (? GHC.Tuple.() n1_aXr) n2_aXr + } + } } in + ? (let { + u1_aXs :: GHC.Types.Int + [LclId] + u1_aXs + = case ds1_d1Ua of { RTick.Tick n1_aXr u -> u } } in + let { + u2_aXs :: GHC.Types.Int + [LclId] + u2_aXs + = case ds2_d1Ua of { RTick.Tick n2_aXr u -> u } } in + let { + u1u2Lemma_aXs :: GHC.Types.Int + [LclId] + u1u2Lemma_aXs + = case ds1_d1Ua of { RTick.Tick n11_aXr u1_aXs -> + case ds2_d1Ua of { RTick.Tick n22_aXr u2_aXs -> + src<.:0:0> ? (? GHC.Tuple.() u1_aXs) u2_aXs + } + } } in + ? ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RTick.Tick x1 x3)) + (RTick.Tick x2 x4)) + (GHC.Num.+ m1_aXk n1_aXr) + (GHC.Num.+ m2_aXk n2_aXr) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) + x3x4Lemma_xp) + (GHC.Num.+ x1 x3)) + (GHC.Num.+ x2 x4)) + m1_aXk + m2_aXk + m1m2Lemma_aXk + n1_aXr + n2_aXr + n1n2Lemma_aXr) + u1_aXs + u2_aXs + u1u2Lemma_aXs) + u1u2Lemma_aXs) + n1n2Lemma_aXr) + ds1ds2Lemma_d1Ua) + v1v2Lemma_aXl) + m1m2Lemma_aXk) + ds1ds2Lemma_d1Ub; + GHC.Types.True -> + let { + ds1_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1_d1Ub = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + ds2_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds2_d1U7 = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + ds1ds2Lemma_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma_d1Ub + = samSamTheorem_rxR + t1_d1TX + t2_d1TX + t1t2Lemma_d1TX + x1_aVq + x2_aVq + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + (src<.:0:0> ? (? GHC.Tuple.() ds1_d1Uc) ds2_d1Uc) } in + ? (let { + m1_aXk :: GHC.Types.Int + [LclId] + m1_aXk = case ds1_d1Ub of { RTick.Tick m v -> m } } in + let { + m2_aX7 :: GHC.Types.Int + [LclId] + m2_aX7 = case ds2_d1U7 of { RTick.Tick m v -> m } } in + let { + m1m2Lemma_aXk :: GHC.Types.Int + [LclId] + m1m2Lemma_aXk + = case ds1_d1Ub of { RTick.Tick m1_aXk v1_aXl -> + case ds2_d1U7 of { RTick.Tick m2_aX7 v2_aX8 -> + src<.:0:0> ? (? GHC.Tuple.() m1_aXk) m2_aX7 + } + } } in + ? (let { + v1_aXl :: GHC.Types.Int + [LclId] + v1_aXl = case ds1_d1Ub of { RTick.Tick m1_aXk v -> v } } in + let { + v2_aX8 :: GHC.Types.Int + [LclId] + v2_aX8 = case ds2_d1U7 of { RTick.Tick m2_aX7 v -> v } } in + let { + v1v2Lemma_aXl :: GHC.Types.Int + [LclId] + v1v2Lemma_aXl + = case ds1_d1Ub of { RTick.Tick m11_aXk v1_aXl -> + case ds2_d1U7 of { RTick.Tick m22_aX7 v2_aX8 -> + src<.:0:0> ? (? GHC.Tuple.() v1_aXl) v2_aX8 + } + } } in + ? (src<.:0:0> + ? (? GHC.Tuple.() + (let { + ds_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, + ConLike=False, WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds_d1Ua + = RSquareAndMultiply.power2Times + t1_d1TX x1_aVq v1_aXl } in + let { + n :: GHC.Types.Int + [LclId] + n = case ds_d1Ua of { RTick.Tick n u -> n } } in + let { + u :: GHC.Types.Int + [LclId] + u = case ds_d1Ua of { RTick.Tick n u -> u } } in + RTick.Tick (GHC.Num.+ m1_aXk n) u)) + (RTick.<*> + (RTick.pure RSquareAndMultiply.power2) + (RTick.Tick m2_aX7 v2_aX8))) + v1v2Lemma_aXl) + m1m2Lemma_aXk) + ds1ds2Lemma_d1Ub + }; + GHC.Types.True -> + case GHC.Classes.== b2_aVr (GHC.Types.I# 0#) + of lq_anf$##72057594037927936732_d1b { + GHC.Types.False -> + let { + ds1_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1_d1U7 = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + ds2_d1Ub :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds2_d1Ub = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + ds1ds2Lemma_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma_d1U7 + = samSamTheorem_rxR + t1_d1TX + t2_d1TX + t1t2Lemma_d1TX + x1_aVq + x2_aVq + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + (src<.:0:0> ? (? GHC.Tuple.() ds1_d1Uc) ds2_d1Uc) } in + ? (let { + m1_aX7 :: GHC.Types.Int + [LclId] + m1_aX7 = case ds1_d1U7 of { RTick.Tick m v -> m } } in + let { + m2_aXk :: GHC.Types.Int + [LclId] + m2_aXk = case ds2_d1Ub of { RTick.Tick m v -> m } } in + let { + m1m2Lemma_aX7 :: GHC.Types.Int + [LclId] + m1m2Lemma_aX7 + = case ds1_d1U7 of { RTick.Tick m1_aX7 v1_aX8 -> + case ds2_d1Ub of { RTick.Tick m2_aXk v2_aXl -> + src<.:0:0> ? (? GHC.Tuple.() m1_aX7) m2_aXk + } + } } in + ? (let { + v1_aX8 :: GHC.Types.Int + [LclId] + v1_aX8 = case ds1_d1U7 of { RTick.Tick m1_aX7 v -> v } } in + let { + v2_aXl :: GHC.Types.Int + [LclId] + v2_aXl = case ds2_d1Ub of { RTick.Tick m2_aXk v -> v } } in + let { + v1v2Lemma_aX8 :: GHC.Types.Int + [LclId] + v1v2Lemma_aX8 + = case ds1_d1U7 of { RTick.Tick m11_aX7 v1_aX8 -> + case ds2_d1Ub of { RTick.Tick m22_aXk v2_aXl -> + src<.:0:0> ? (? GHC.Tuple.() v1_aX8) v2_aXl + } + } } in + ? (src<.:0:0> + ? (? GHC.Tuple.() + (RTick.<*> + (RTick.pure RSquareAndMultiply.power2) + (RTick.Tick m1_aX7 v1_aX8))) + (let { + ds_d1Ua :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, + ConLike=False, WorkFree=False, Expandable=False, + Guidance=IF_ARGS [] 40 0}] + ds_d1Ua + = RSquareAndMultiply.power2Times + t2_d1TX x2_aVq v2_aXl } in + let { + n :: GHC.Types.Int + [LclId] + n = case ds_d1Ua of { RTick.Tick n u -> n } } in + let { + u :: GHC.Types.Int + [LclId] + u = case ds_d1Ua of { RTick.Tick n u -> u } } in + RTick.Tick (GHC.Num.+ m2_aXk n) u)) + v1v2Lemma_aX8) + m1m2Lemma_aX7) + ds1ds2Lemma_d1U7; + GHC.Types.True -> + let { + ds1_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1_d1U7 = RSquareAndMultiply.sam t1_d1TX x1_aVq ds1_d1Uc } in + let { + ds2_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds2_d1U7 = RSquareAndMultiply.sam t2_d1TX x2_aVq ds2_d1Uc } in + let { + ds1ds2Lemma_d1U7 :: RTick.Tick GHC.Types.Int + [LclId, + Unf=Unf{Src=, TopLvl=False, Value=False, ConLike=False, + WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 0}] + ds1ds2Lemma_d1U7 + = samSamTheorem_rxR + t1_d1TX + t2_d1TX + t1t2Lemma_d1TX + x1_aVq + x2_aVq + x1x2Lemma_aVq + ds1_d1Uc + ds2_d1Uc + (src<.:0:0> ? (? GHC.Tuple.() ds1_d1Uc) ds2_d1Uc) } in + ? (let { + m1_aX7 :: GHC.Types.Int + [LclId] + m1_aX7 = case ds1_d1U7 of { RTick.Tick m v -> m } } in + let { + m2_aX7 :: GHC.Types.Int + [LclId] + m2_aX7 = case ds2_d1U7 of { RTick.Tick m v -> m } } in + let { + m1m2Lemma_aX7 :: GHC.Types.Int + [LclId] + m1m2Lemma_aX7 + = case ds1_d1U7 of { RTick.Tick m1_aX7 v1_aX8 -> + case ds2_d1U7 of { RTick.Tick m2_aX7 v2_aX8 -> + src<.:0:0> ? (? GHC.Tuple.() m1_aX7) m2_aX7 + } + } } in + ? (let { + v1_aX8 :: GHC.Types.Int + [LclId] + v1_aX8 = case ds1_d1U7 of { RTick.Tick m1_aX7 v -> v } } in + let { + v2_aX8 :: GHC.Types.Int + [LclId] + v2_aX8 = case ds2_d1U7 of { RTick.Tick m2_aX7 v -> v } } in + let { + v1v2Lemma_aX8 :: GHC.Types.Int + [LclId] + v1v2Lemma_aX8 + = case ds1_d1U7 of { RTick.Tick m11_aX7 v1_aX8 -> + case ds2_d1U7 of { RTick.Tick m22_aX7 v2_aX8 -> + src<.:0:0> ? (? GHC.Tuple.() v1_aX8) v2_aX8 + } + } } in + ? ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RTick.<*> x1 x3)) + (RTick.<*> x2 x4)) + (RTick.pure RSquareAndMultiply.power2) + (RTick.pure RSquareAndMultiply.power2) + ((src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) (RTick.pure x1)) + (RTick.pure x2)) + RSquareAndMultiply.power2 + RSquareAndMultiply.power2 + (src<.:0:0> + \ (x1 :: ()) (x2 :: ()) (x1x2Lemma_xp :: ()) -> + ? (? (? GHC.Tuple.() x1x2Lemma_xp) + (RSquareAndMultiply.power2 x1)) + (RSquareAndMultiply.power2 x2))) + (RTick.Tick m1_aX7 v1_aX8) + (RTick.Tick m2_aX7 v2_aX8) + ((src<.:0:0> + \ (x1 :: ()) + (x2 :: ()) + (x1x2Lemma_xp :: ()) + (x3 :: ()) + (x4 :: ()) + (x3x4Lemma_xp :: ()) -> + ? (? (? (? GHC.Tuple.() x1x2Lemma_xp) x3x4Lemma_xp) + (RTick.Tick x1 x3)) + (RTick.Tick x2 x4)) + m1_aX7 m2_aX7 m1m2Lemma_aX7 v1_aX8 v2_aX8 v1v2Lemma_aX8)) + v1v2Lemma_aX8) + m1m2Lemma_aX7) + ds1ds2Lemma_d1U7 + } + } + } + } + } + } +-} diff --git a/include/Language/Haskell/Liquid/RTick.hs b/tests/relational/pos/RTick.hs similarity index 64% rename from include/Language/Haskell/Liquid/RTick.hs rename to tests/relational/pos/RTick.hs index 5e70ed0ec5..80df526c39 100644 --- a/include/Language/Haskell/Liquid/RTick.hs +++ b/tests/relational/pos/RTick.hs @@ -6,11 +6,12 @@ {-@ LIQUID "--reflection" @-} -module Language.Haskell.Liquid.RTick +module RTick ( -- Tick datatype: Tick(..) + , ttcost -- Primitive resource operators: , fmap , pure @@ -74,6 +75,10 @@ import qualified Data.Functor as F {-@ data Tick a = Tick { tcost :: Int, tval :: a } @-} data Tick a = Tick { tcost :: Int, tval :: a } +{-@ measure ttcost @-} +ttcost :: Tick a -> Int +ttcost (Tick c _) = c + ------------------------------------------------------------------------------- -- | Primitive resource operators: ------------------------------------------------------------------------------- @@ -82,9 +87,7 @@ instance F.Functor Tick where fmap = fmap {-@ reflect fmap @-} -{-@ fmap :: f:(a -> b) -> t1:Tick a - -> { t:Tick b | Tick (tcost t1) (f (tval t1)) == t } -@-} +{-@ fmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1) (f (tval t1)) == t } @-} fmap :: (a -> b) -> Tick a -> Tick b fmap f (Tick m x) = Tick m (f x) @@ -98,19 +101,13 @@ pure :: a -> Tick a pure x = Tick 0 x {-@ reflect <*> @-} -{-@ (<*>) :: t1:Tick (a -> b) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 == tcost t } -@-} +{-@ (<*>) :: t1:Tick (a -> b) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} infixl 4 <*> (<*>) :: Tick (a -> b) -> Tick a -> Tick b Tick m f <*> Tick n x = Tick (m + n) (f x) {-@ reflect liftA2 @-} -{-@ liftA2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b - -> { t:Tick c | f (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 == tcost t } -@-} +{-@ liftA2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b -> { t:Tick c | f (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} liftA2 :: (a -> b -> c) -> Tick a -> Tick b -> Tick c liftA2 f (Tick m x) (Tick n y) = Tick (m + n) (f x y) @@ -124,28 +121,19 @@ return :: a -> Tick a return x = Tick 0 x {-@ reflect >>= @-} -{-@ (>>=) :: t1:Tick a -> f:(a -> Tick b) - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) == tcost t } -@-} +{-@ (>>=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) == tcost t } @-} infixl 4 >>= (>>=) :: Tick a -> (a -> Tick b) -> Tick b Tick m x >>= f = let Tick n y = f x in Tick (m + n) y {-@ reflect =<< @-} -{-@ (=<<) :: f:(a -> Tick b) -> t1:Tick a - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) == tcost t } -@-} +{-@ (=<<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) == tcost t } @-} infixl 4 =<< (=<<) :: (a -> Tick b) -> Tick a -> Tick b f =<< Tick m x = let Tick n y = f x in Tick (m + n) y {-@ reflect ap @-} -{-@ ap :: t1:(Tick (a -> b)) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 == tcost t } -@-} +{-@ ap :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} ap :: Tick (a -> b) -> Tick a -> Tick b ap (Tick m f) (Tick n x) = Tick (m + n) (f x) @@ -155,37 +143,30 @@ liftM :: (a -> b) -> Tick a -> Tick b liftM f (Tick m x) = Tick m (f x) {-@ reflect liftM2 @-} -{-@ liftM2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b - -> { t:Tick c | f (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 == tcost t } -@-} +{-@ liftM2 :: f:(a -> b -> c) -> t1:Tick a -> t2:Tick b -> { t:Tick c | f (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 == tcost t } @-} liftM2 :: (a -> b -> c) -> Tick a -> Tick b -> Tick c liftM2 f (Tick m x) (Tick n y) = Tick (m + n) (f x y) ------------------------------------------------------------------------------- {-@ reflect eqBind @-} -{-@ eqBind :: n:Int -> t1:Tick a - -> f:(a -> { tf:Tick b | n == tcost tf }) - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + n == tcost t } +{-@ eqBind + :: n:Int + -> t1:Tick a + -> f:(a -> { tf:Tick b | n == tcost tf }) + -> { t:Tick b | tval (f (tval t1)) + == tval t && tcost t1 + n == tcost t } @-} eqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b eqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y {-@ reflect leqBind @-} -{-@ leqBind :: n:Int -> t1:Tick a - -> f:(a -> { tf:Tick b | n >= tcost tf }) - -> { t:Tick b | tcost t1 + n >= tcost t } -@-} +{-@ leqBind :: n:Int -> t1:Tick a -> f:(a -> { tf:Tick b | n >= tcost tf }) -> { t:Tick b | tcost t1 + n >= tcost t } @-} leqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b leqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y {-@ reflect geqBind @-} -{-@ geqBind :: n:Int -> t1:Tick a - -> f:(a -> { tf:Tick b | n <= tcost tf }) - -> { t2:Tick b | tcost t1 + n <= tcost t2 } -@-} +{-@ geqBind :: n:Int -> t1:Tick a -> f:(a -> { tf:Tick b | n <= tcost tf }) -> { t2:Tick b | tcost t1 + n <= tcost t2 } @-} geqBind :: Int -> Tick a -> (a -> Tick b) -> Tick b geqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y @@ -194,9 +175,7 @@ geqBind _ (Tick m x) f = let Tick n y = f x in Tick (m + n) y ------------------------------------------------------------------------------- {-@ reflect step @-} -{-@ step :: m:Int -> t1:Tick a - -> { t:Tick a | tval t1 == tval t && m + tcost t1 == tcost t } -@-} +{-@ step :: m:Int -> t1:Tick a -> { t:Tick a | tval t1 == tval t && m + tcost t1 == tcost t } @-} step :: Int -> Tick a -> Tick a step m (Tick n x) = Tick (m + n) x @@ -212,9 +191,7 @@ wait x = Tick 1 x -- @waitN (n > 0) := step n . return@. -- {-@ reflect waitN @-} -{-@ waitN :: n:Nat -> x:a - -> { t:Tick a | x == tval t && n == tcost t } -@-} +{-@ waitN :: n:Nat -> x:a -> { t:Tick a | x == tval t && n == tcost t } @-} waitN :: Int -> a -> Tick a waitN n x = Tick n x @@ -230,9 +207,7 @@ go x = Tick (-1) x -- @goN (n > 0) := step (-n) . return@. -- {-@ reflect goN @-} -{-@ goN :: { n:Nat | n > 0 } -> x:a - -> { t:Tick a | x == tval t && (-n) == tcost t } -@-} +{-@ goN :: { n:Nat | n > 0 } -> x:a -> { t:Tick a | x == tval t && (-n) == tcost t } @-} goN :: Int -> a -> Tick a goN n x = Tick (-n) x @@ -240,9 +215,7 @@ goN n x = Tick (-n) x -- @wmap f := step 1 . fmap f@. -- {-@ reflect wmap @-} -{-@ wmap :: f:(a -> b) -> t1:Tick a - -> { t:Tick b | Tick (1 + tcost t1) (f (tval t1)) == t } -@-} +{-@ wmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (1 + tcost t1) (f (tval t1)) == t } @-} wmap :: (a -> b) -> Tick a -> Tick b wmap f (Tick m x) = Tick (1 + m) (f x) @@ -250,9 +223,7 @@ wmap f (Tick m x) = Tick (1 + m) (f x) -- @wmapN (n > 0) f := step n . fmap f@. -- {-@ reflect wmapN @-} -{-@ wmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a - -> { t:Tick b | Tick (m + tcost t1) (f (tval t1)) == t } -@-} +{-@ wmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (m + tcost t1) (f (tval t1)) == t } @-} wmapN :: Int -> (a -> b) -> Tick a -> Tick b wmapN m f (Tick n x) = Tick (m + n) (f x) @@ -260,9 +231,7 @@ wmapN m f (Tick n x) = Tick (m + n) (f x) -- @gmap f := step (-1) . fmap f@. -- {-@ reflect gmap @-} -{-@ gmap :: f:(a -> b) -> t1:Tick a - -> { t:Tick b | Tick (tcost t1 - 1) (f (tval t1)) == t } -@-} +{-@ gmap :: f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1 - 1) (f (tval t1)) == t } @-} gmap :: (a -> b) -> Tick a -> Tick b gmap f (Tick m x) = Tick (m - 1) (f x) @@ -270,9 +239,7 @@ gmap f (Tick m x) = Tick (m - 1) (f x) -- @gmapN (n > 0) f := step (-n) . fmap f@. -- {-@ reflect gmapN @-} -{-@ gmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a - -> { t:Tick b | Tick (tcost t1 - m) (f (tval t1)) == t } -@-} +{-@ gmapN :: { m:Nat | m > 0 } -> f:(a -> b) -> t1:Tick a -> { t:Tick b | Tick (tcost t1 - m) (f (tval t1)) == t } @-} gmapN :: Int -> (a -> b) -> Tick a -> Tick b gmapN m f (Tick n x) = Tick (n - m) (f x) @@ -280,10 +247,7 @@ gmapN m f (Tick n x) = Tick (n - m) (f x) -- \"wapp\": @(f ) := step 1 . (f <*>)@. -- {-@ reflect @-} -{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - 1 + tcost t1 + tcost t2 == tcost t } -@-} +{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && 1 + tcost t1 + tcost t2 == tcost t } @-} infixl 4 () :: Tick (a -> b) -> Tick a -> Tick b Tick m f Tick n x = Tick (1 + m + n) (f x) @@ -292,10 +256,7 @@ Tick m f Tick n x = Tick (1 + m + n) (f x) -- \"wwapp\": @(f ) := step 2 . (f <*>)@. -- {-@ reflect @-} -{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - 2 + tcost t1 + tcost t2 == tcost t } -@-} +{-@ () :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && 2 + tcost t1 + tcost t2 == tcost t } @-} infixl 4 () :: Tick (a -> b) -> Tick a -> Tick b Tick m f Tick n x = Tick (2 + m + n) (f x) @@ -304,10 +265,7 @@ Tick m f Tick n x = Tick (2 + m + n) (f x) -- \"gapp\": @(f <\>) := step (-1) . (f <*>)@. -- {-@ reflect <\> @-} -{-@ (<\>) :: t1:(Tick (a -> b)) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 - 1 == tcost t } -@-} +{-@ (<\>) :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 - 1 == tcost t } @-} infixl 4 <\> (<\>) :: Tick (a -> b) -> Tick a -> Tick b Tick m f <\> Tick n x = Tick (m + n - 1) (f x) @@ -316,10 +274,7 @@ Tick m f <\> Tick n x = Tick (m + n - 1) (f x) -- \"ggapp\": @(f <\\>) := step (-2) . (f <*>)@. -- {-@ reflect <\\> @-} -{-@ (<\\>) :: t1:(Tick (a -> b)) -> t2:Tick a - -> { t:Tick b | (tval t1) (tval t2) == tval t && - tcost t1 + tcost t2 - 2 == tcost t } -@-} +{-@ (<\\>) :: t1:(Tick (a -> b)) -> t2:Tick a -> { t:Tick b | (tval t1) (tval t2) == tval t && tcost t1 + tcost t2 - 2 == tcost t } @-} infixl 4 <\\> (<\\>) :: Tick (a -> b) -> Tick a -> Tick b Tick m f <\\> Tick n x = Tick (m + n - 2) (f x) @@ -328,9 +283,11 @@ Tick m f <\\> Tick n x = Tick (m + n - 2) (f x) -- \"wbind\": @(>/= f) := step 1 . (>>= f)@. -- {-@ reflect >/= @-} -{-@ (>/=) :: t1:Tick a -> f:(a -> Tick b) - -> { t:Tick b | (tval (f (tval t1)) == tval t) && - (1 + tcost t1 + tcost (f (tval t1))) == tcost t } +{-@ (>/=) + :: t1:Tick a + -> f:(a -> Tick b) + -> { t:Tick b | (tval (f (tval t1)) == tval t) + && (1 + tcost t1 + tcost (f (tval t1))) == tcost t } @-} infixl 4 >/= (>/=) :: Tick a -> (a -> Tick b) -> Tick b @@ -340,10 +297,7 @@ Tick m x >/= f = let Tick n y = f x in Tick (1 + m + n) y -- \"wbind\": @(f =/<) := step 1 . (f =<<)@. -- {-@ reflect =/< @-} -{-@ (=/<) :: f:(a -> Tick b) -> t1:Tick a - -> { t:Tick b | tval (f (tval t1)) == tval t && - 1 + tcost t1 + tcost (f (tval t1)) == tcost t } -@-} +{-@ (=/<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && 1 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} infixl 4 =/< (=/<) :: (a -> Tick b) -> Tick a -> Tick b f =/< Tick m x = let Tick n y = f x in Tick (1 + m + n) y @@ -352,10 +306,7 @@ f =/< Tick m x = let Tick n y = f x in Tick (1 + m + n) y -- \"wwbind\": @(>//= f) := step 2 . (>>= f)@. -- {-@ reflect >//= @-} -{-@ (>//=) :: t1:Tick a -> f:(a -> Tick b) - -> { t:Tick b | tval (f (tval t1)) == tval t && - 2 + tcost t1 + tcost (f (tval t1)) == tcost t } -@-} +{-@ (>//=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && 2 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} infixl 4 >//= (>//=) :: Tick a -> (a -> Tick b) -> Tick b Tick m x >//= f = let Tick n y = f x in Tick (2 + m + n) y @@ -364,10 +315,7 @@ Tick m x >//= f = let Tick n y = f x in Tick (2 + m + n) y -- \"wwbind\": @(f =//<) := step 2 . (f =<<)@. -- {-@ reflect =//< @-} -{-@ (=//<) :: f:(a -> Tick b) -> t1:Tick a - -> { t:Tick b | tval (f (tval t1)) == tval t && - 2 + tcost t1 + tcost (f (tval t1)) == tcost t } -@-} +{-@ (=//<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && 2 + tcost t1 + tcost (f (tval t1)) == tcost t } @-} infixl 4 =//< (=//<) :: (a -> Tick b) -> Tick a -> Tick b f =//< Tick m x = let Tick n y = f x in Tick (2 + m + n) y @@ -376,10 +324,7 @@ f =//< Tick m x = let Tick n y = f x in Tick (2 + m + n) y -- \"gbind\": @(>\= f) := step (-1) . (>>= f)@. -- {-@ reflect >\= @-} -{-@ (>\=) :: t1:Tick a -> f:(a -> Tick b) - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) - 1 == tcost t } -@-} +{-@ (>\=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 1 == tcost t } @-} infixl 4 >\= (>\=) :: Tick a -> (a -> Tick b) -> Tick b Tick m x >\= f = let Tick n y = f x in Tick (m + n - 1) y @@ -388,10 +333,7 @@ Tick m x >\= f = let Tick n y = f x in Tick (m + n - 1) y -- \"gbind\": @(f =\<) := step (-1) . (f =<<)@. -- {-@ reflect =\< @-} -{-@ (=\<) :: f:(a -> Tick b) -> t1:Tick a - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) - 1 == tcost t } -@-} +{-@ (=\<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 1 == tcost t } @-} infixl 4 =\< (=\<) :: (a -> Tick b) -> Tick a -> Tick b f =\< Tick m x = let Tick n y = f x in Tick (m + n - 1) y @@ -400,10 +342,7 @@ f =\< Tick m x = let Tick n y = f x in Tick (m + n - 1) y -- \"ggbind\": @(>\= f) := step (-2) . (>>= f)@. -- {-@ reflect >\\= @-} -{-@ (>\\=) :: t1:Tick a -> f:(a -> Tick b) - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) - 2 == tcost t } -@-} +{-@ (>\\=) :: t1:Tick a -> f:(a -> Tick b) -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 2 == tcost t } @-} infixl 4 >\\= (>\\=) :: Tick a -> (a -> Tick b) -> Tick b Tick m x >\\= f = let Tick n y = f x in Tick (m + n - 2) y @@ -412,10 +351,7 @@ Tick m x >\\= f = let Tick n y = f x in Tick (m + n - 2) y -- \"ggbind\": @(f =\\<) := step (-2) . (f =<<)@. -- {-@ reflect =\\< @-} -{-@ (=\\<) :: f:(a -> Tick b) -> t1:Tick a - -> { t:Tick b | tval (f (tval t1)) == tval t && - tcost t1 + tcost (f (tval t1)) - 2 == tcost t } -@-} +{-@ (=\\<) :: f:(a -> Tick b) -> t1:Tick a -> { t:Tick b | tval (f (tval t1)) == tval t && tcost t1 + tcost (f (tval t1)) - 2 == tcost t } @-} infixl 4 =\\< (=\\<) :: (a -> Tick b) -> Tick a -> Tick b f =\\< Tick m x = let Tick n y = f x in Tick (m + n - 2) y @@ -425,16 +361,14 @@ f =\\< Tick m x = let Tick n y = f x in Tick (m + n - 2) y ------------------------------------------------------------------------------- {-@ reflect pay @-} -{-@ pay :: m:Int - -> { t1:Tick a | m <= tcost t1 } - -> { t:Tick ({ t2 : Tick a | tcost t1 - m == tcost t2 }) | m == tcost t } -@-} +{-@ pay :: m:Int -> { t1:Tick a | m <= tcost t1 } -> { t:Tick ({ t2 : Tick a | tcost t1 - m == tcost t2 }) | m == tcost t } @-} pay :: Int -> Tick a -> Tick (Tick a) pay m (Tick n x) = Tick m (Tick (n - m) x) {-@ reflect zipWithM @-} -{-@ zipWithM :: f:(a -> b -> Tick c) -> x:Tick a -> y:Tick b --> {t:Tick c | tcost t == tcost x + tcost y + tcost (f (tval x) (tval y))} @-} +{-@ zipWithM :: f:(a -> b -> Tick c) -> x:Tick a -> y:Tick b + -> {t:Tick c | tcost t == tcost x + tcost y + tcost (f (tval x) (tval y)) + && tval t == tval (f (tval x) (tval y)) } @-} zipWithM :: (a -> b -> Tick c) -> Tick a -> Tick b -> Tick c zipWithM f (Tick c1 x1) (Tick c2 x2) = let Tick c x = f x1 x2 in Tick (c + c1 + c2) x diff --git a/tests/relational/pos/RVar.hs b/tests/relational/pos/RVar.hs new file mode 100644 index 0000000000..761efb2abb --- /dev/null +++ b/tests/relational/pos/RVar.hs @@ -0,0 +1,25 @@ +{-@ LIQUID "--relational-hint" @-} +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module RVar where + +{-@ measure RVar.x1 :: Int @-} +{-@ measure RVar.x2 :: Int @-} +x1, x2 :: Int +x1 = 0 +x2 = 1 + +{-@ reflect y1 @-} +{-@ reflect y2 @-} +y1, y2 :: Int +y1 = x1 +y2 = x2 + +--- Proof --- +{-@ assume relX1X2 :: {x1 <= x2} @-} +relX1X2 :: () +relX1X2 = () + +{-@ relational y1 ~ y2 :: { Int ~ Int | r1 <= r2 } @-} +--- End --- \ No newline at end of file diff --git a/tests/relational/pos/RVar_relToUn.hs b/tests/relational/pos/RVar_relToUn.hs new file mode 100644 index 0000000000..db21e54a2f --- /dev/null +++ b/tests/relational/pos/RVar_relToUn.hs @@ -0,0 +1,24 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} +{-@ LIQUID "--no-adt" @-} + +module RVar_relToUn (module RVar_relToUn) where + +import GHC.Classes +import GHC.Types +import Language.Haskell.Liquid.ProofCombinators +import RVar +import Prelude + +{- HLINT ignore "Use camelCase" -} +{- HLINT ignore "Use if" -} +{- HLINT ignore "Use section" -} +{-@ y1Y2Theorem :: {VV : () | RVar.y1 <= RVar.y2} @-} +y1Y2Theorem :: () +y1Y2Theorem = + {- GOAL: RVar.x1 ~ RVar.x2 -} + (() ? RVar.x1) ? RVar.x2 + +{- BARE CORE +src<.:0:0> ? (? GHC.Tuple.() RVar.x1) RVar.x2 +-} diff --git a/tests/relational/pos/Rec.hs b/tests/relational/pos/Rec.hs index 2e6ccad8eb..a3d77ffc56 100644 --- a/tests/relational/pos/Rec.hs +++ b/tests/relational/pos/Rec.hs @@ -1,4 +1,4 @@ -module Fixme where +module Rec where f :: Int -> Int f x = if x <= 0 then 0 else 1 + f (x - 1) diff --git a/tests/relational/pos/RecNonFunc.hs b/tests/relational/pos/RecNonFunc.hs index 5af0d131e0..b8f5c7da01 100644 --- a/tests/relational/pos/RecNonFunc.hs +++ b/tests/relational/pos/RecNonFunc.hs @@ -1,6 +1,6 @@ {-@ LIQUID "--no-termination" @-} -module Fixme where +module RecNonFunc where {-@ r :: Nat @-} r :: Int diff --git a/tests/relational/pos/SumType.hs b/tests/relational/pos/SumType.hs index eaf249c04c..db86d5ff68 100644 --- a/tests/relational/pos/SumType.hs +++ b/tests/relational/pos/SumType.hs @@ -1,4 +1,7 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + +module SumType where data D = A | B | C diff --git a/tests/relational/pos/TrdOrdPredNonRel.hs b/tests/relational/pos/TrdOrdPredNonRel.hs index 7690faf024..c4a0b8c1d5 100644 --- a/tests/relational/pos/TrdOrdPredNonRel.hs +++ b/tests/relational/pos/TrdOrdPredNonRel.hs @@ -1,3 +1,5 @@ +{-@ LIQUID "--reflection" @-} + module TrdOrdPredNonRel where {-@ reflect h @-} diff --git a/tests/relational/pos/UnaryVsRelational.hs b/tests/relational/pos/UnaryVsRelational.hs index 044e2254e6..90241c33f8 100644 --- a/tests/relational/pos/UnaryVsRelational.hs +++ b/tests/relational/pos/UnaryVsRelational.hs @@ -1,4 +1,4 @@ -module Fixme where +module UnaryVsRelational where {-@ reflect abs @-} abs :: Int -> Int diff --git a/tests/relational/rtest b/tests/relational/rtest index 224c7715e3..387c2bee89 100755 --- a/tests/relational/rtest +++ b/tests/relational/rtest @@ -5,27 +5,29 @@ # $ chmod +x tests/relational/rtest # $ ./tests/relational/rtest +LH="env liquidhaskell_datadir=$PWD cabal v2-exec -- liquidhaskell -q --ple --reflection" + # Return code rc=0 # Test pos -for f in tests/relational/pos/* +for f in tests/relational/pos/*.hs do echo echo $f - if ! liquid $f --ple --reflection + if ! $LH $f -itests/relational/pos then rc=1 fi done # Test neg -for f in tests/relational/neg/* +for f in tests/relational/neg/*.hs do echo echo $f - liquid $f --reflection --ple - if ! [[ $(liquid $f --reflection --ple) =~ "LIQUID: UNSAFE" ]] + $LH $f --reflection --ple + if ! [[ $($LH $f --reflection --ple) =~ "LIQUID: UNSAFE" ]] then rc=1 fi diff --git a/tests/relational/todo/Ap.hs b/tests/relational/todo/Ap.hs index 66f079fba4..4823b1441e 100644 --- a/tests/relational/todo/Ap.hs +++ b/tests/relational/todo/Ap.hs @@ -1,4 +1,6 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} + +module Ap where {-@ reflect ap @-} ap :: (Int -> Int) -> Int -> Int diff --git a/tests/relational/todo/AssumeRelational.hs b/tests/relational/todo/AssumeRelational.hs index 8b9ad55bee..51113e3377 100644 --- a/tests/relational/todo/AssumeRelational.hs +++ b/tests/relational/todo/AssumeRelational.hs @@ -1,3 +1,5 @@ +{-@ LIQUID "--reflection" @-} + module AssumeRelational where update :: Int -> Int -> Int diff --git a/tests/relational/todo/Bsplit.hs b/tests/relational/todo/Bsplit.hs index c42c88be87..479b416835 100644 --- a/tests/relational/todo/Bsplit.hs +++ b/tests/relational/todo/Bsplit.hs @@ -1,4 +1,5 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +module Bsplit where {-@ data Tick a = T { res :: a, time :: Int} @-} data Tick a = T { res :: a, time :: Int} diff --git a/tests/relational/todo/CaseOnRec.hs b/tests/relational/todo/CaseOnRec.hs index 75ae07ce52..61d8966dba 100644 --- a/tests/relational/todo/CaseOnRec.hs +++ b/tests/relational/todo/CaseOnRec.hs @@ -1,4 +1,4 @@ -module Fixme where +module CaseOnRec where data Parity = Even | Odd diff --git a/tests/relational/todo/DeltaSort.hs b/tests/relational/todo/DeltaSort.hs index 96e377290b..73f485c57d 100644 --- a/tests/relational/todo/DeltaSort.hs +++ b/tests/relational/todo/DeltaSort.hs @@ -1,3 +1,4 @@ +{-@ LIQUID "--reflection" @-} module DeltaSort where import Prelude hiding ( abs diff --git a/tests/relational/todo/Example.hs b/tests/relational/todo/Example.hs index 206d28d5da..c626dfd2de 100644 --- a/tests/relational/todo/Example.hs +++ b/tests/relational/todo/Example.hs @@ -1,3 +1,4 @@ +module Example where foo, bar :: Bool -> Int foo a = if a then 0 else 2 bar b = if b then 1 else 3 diff --git a/tests/relational/todo/FibLet.hs b/tests/relational/todo/FibLet.hs index 5b59be780b..b201fc0282 100644 --- a/tests/relational/todo/FibLet.hs +++ b/tests/relational/todo/FibLet.hs @@ -1,3 +1,4 @@ +{-@ LIQUID "--reflection" @-} module Fixme where data N = Z | S N diff --git a/tests/relational/todo/Filter.hs b/tests/relational/todo/Filter.hs index 4fa5923f91..11aa430401 100644 --- a/tests/relational/todo/Filter.hs +++ b/tests/relational/todo/Filter.hs @@ -1,3 +1,4 @@ +{-@ LIQUID "--reflection" @-} module Filter where {-@ measure d :: a -> a -> Double @-} diff --git a/tests/relational/todo/IncrF.hs b/tests/relational/todo/IncrF.hs index b3024481cb..b73069ecb5 100644 --- a/tests/relational/todo/IncrF.hs +++ b/tests/relational/todo/IncrF.hs @@ -1,4 +1,4 @@ -module Fixme where +module IncrF where {-@ add :: x:Int -> y:Int -> {v:Int|v = x + y} @-} add :: Int -> Int -> Int diff --git a/tests/relational/todo/IncrHO.hs b/tests/relational/todo/IncrHO.hs index b541142600..5bdfc9c01c 100644 --- a/tests/relational/todo/IncrHO.hs +++ b/tests/relational/todo/IncrHO.hs @@ -1,4 +1,5 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +module IncrHO where incr :: Int -> Int incr = (+ 1) diff --git a/tests/relational/todo/IncrVeryHO.hs b/tests/relational/todo/IncrVeryHO.hs index 196c785201..14c65c9cc2 100644 --- a/tests/relational/todo/IncrVeryHO.hs +++ b/tests/relational/todo/IncrVeryHO.hs @@ -1,3 +1,4 @@ +{-@ LIQUID "--reflection" @-} module IncrVeryHO where {-@ reflect incr @-} diff --git a/tests/relational/todo/Incr_.hs b/tests/relational/todo/Incr_.hs index 55b34d6a35..16740780d4 100644 --- a/tests/relational/todo/Incr_.hs +++ b/tests/relational/todo/Incr_.hs @@ -1,4 +1,4 @@ -module Fixme where +module Incr_ where {-@ plus :: a:Int -> b:Int -> {v:Int | v == a + b} @-} plus :: Int -> Int -> Int diff --git a/tests/relational/todo/IsZero.hs b/tests/relational/todo/IsZero.hs index d84618e965..3ef33dfdfa 100644 --- a/tests/relational/todo/IsZero.hs +++ b/tests/relational/todo/IsZero.hs @@ -1,3 +1,6 @@ +{-@ LIQUID "--reflection" @-} +{-@ LIQUID "--ple" @-} + module Fixme where isZero :: Int -> Bool diff --git a/tests/relational/todo/Map.hs b/tests/relational/todo/Map.hs index 5d7465ae33..00b4815f40 100644 --- a/tests/relational/todo/Map.hs +++ b/tests/relational/todo/Map.hs @@ -1,4 +1,5 @@ -module Fixme where +{-@ LIQUID "--reflection" @-} +module Map where import Prelude hiding ( map ) diff --git a/tests/synthesis/TODO/ListConcat.hs b/tests/synthesis/TODO/ListConcat.hs deleted file mode 100644 index 4bfc57dc48..0000000000 --- a/tests/synthesis/TODO/ListConcat.hs +++ /dev/null @@ -1,30 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListConcat where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ measure length' @-} -{-@ length' :: [a] -> Nat @-} -length' :: [a] -> Int -length' [] = 0 -length' (x:xs) = 1 + length' xs - -{-@ measure sumLen @-} -{-@ sumLen :: [[a]] -> Nat @-} -sumLen :: [[a]] -> Int -sumLen [] = 0 -sumLen (x:xs) = length' x + sumLen xs - -{-@ append0 :: xs: [a] -> ys: [a] -> {v: [a] | length' v == length' xs + length' ys} @-} -append0 :: [a] -> [a] -> [a] -append0 [] ys = ys -append0 (x:xs) ys = x:append0 xs ys - -{-@ concat0 :: x: [[a]] -> { v: [a] | length' v == sumLen x } @-} -concat0 :: [[a]] -> [a] -concat0 = _goal --- concat0 x = --- case x of --- [] -> [] --- x3:x4 -> append0 x3 (concat0 x4) diff --git a/tests/synthesis/TODO/ListToBST.hs b/tests/synthesis/TODO/ListToBST.hs deleted file mode 100644 index d6b7ee1ce4..0000000000 --- a/tests/synthesis/TODO/ListToBST.hs +++ /dev/null @@ -1,44 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListToBST where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data BST [size] a = - Empty - | Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } } - @-} -data BST a = Empty | Node a (BST a) (BST a) - -{-@ measure size @-} -{-@ size :: BST a -> Nat @-} -size :: BST a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure bstElts @-} -{-@ bstElts :: BST a -> S.Set a @-} -bstElts :: Ord a => BST a -> S.Set a -bstElts Empty = S.empty -bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r)) - -{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-} -insert :: Ord a => a -> BST a -> BST a -insert x t = - case t of - Empty -> Node x Empty Empty - Node y l r -> - if x == y - then t - else if y <= x - then Node y l (insert x r) - else Node y (insert x l) r - -{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-} -toBST :: Ord a => [a] -> BST a -toBST = _goal --- toBST xs = --- case xs of --- [] -> Empty --- x:xs' -> insert x (toBST xs') diff --git a/tests/synthesis/TODO/TreeToList.hs b/tests/synthesis/TODO/TreeToList.hs deleted file mode 100644 index 8aea9a9055..0000000000 --- a/tests/synthesis/TODO/TreeToList.hs +++ /dev/null @@ -1,42 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module TreeToList where - -import qualified Data.Set as S - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data Tree [size] a = - Empty - | Node { x:: a, l:: (Tree a), r:: (Tree a) } - @-} -data Tree a = Empty | Node a (Tree a) (Tree a) - -{-@ measure size @-} -{-@ size :: Tree a -> Nat @-} -size :: Tree a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ append' :: x: [a] -> y: [a] - -> { v: [a] | len v == len x + len y && - S.union (listElts x) (listElts y) == listElts v } - @-} -append' :: [a] -> [a] -> [a] -append' [] xs = xs -append' (y:ys) xs = y : append' ys xs - -{-@ measure treeElts @-} -{-@ treeElts :: Tree a -> Set a @-} -treeElts Empty = S.empty -treeElts (Node x l r) = S.union (S.singleton x) (S.union (treeElts l) (treeElts r)) - -{-@ toList :: x: Tree a - -> { v: [a] | len v == size x && listElts v == treeElts x} - @-} -toList :: Tree a -> [a] -toList = _goal --- toList t = --- case t of --- Empty -> [] --- Node x l r -> x : (append' (toList l) (toList r)) diff --git a/tests/synthesis/TODO/User.hs b/tests/synthesis/TODO/User.hs deleted file mode 100644 index 82cea989e6..0000000000 --- a/tests/synthesis/TODO/User.hs +++ /dev/null @@ -1,48 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module User where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ measure length' @-} -{-@ length' :: [a] -> Nat @-} -length' :: [a] -> Int -length' [] = 0 -length' (x:xs) = 1 + length' xs - -data Info = Info { sa :: Int, zc :: Int, loc :: Bool } - -data Address = Address { i :: Info, priv :: Bool } - -{-@ measure isPriv @-} -{-@ isPriv :: Address -> Bool @-} -isPriv :: Address -> Bool -isPriv (Address _ priv) = priv - -{-@ getPriv :: a:Address -> { v: Bool | v == isPriv a } @-} -getPriv :: Address -> Bool -getPriv a = isPriv a - -{-@ data AddressBook [size] = AddressBook { x :: [{v: Address | isPriv v}], y :: [{v: Address | not (isPriv v)}] } - @-} -data AddressBook = AddressBook [Address] [Address] - -{-@ measure size @-} -{-@ size :: AddressBook -> Nat @-} -size :: AddressBook -> Int -size (AddressBook bs ps) = length' bs + length' ps - -{-@ append :: xs: [a] -> ys: [a] -> { v: [a] | length' v == length' xs + length' ys } - @-} -append :: [a] -> [a] -> [a] -append [] ys = ys -append (x:xs) ys = x : append xs ys - -{-@ mergeAddressBooks :: a: AddressBook -> b: AddressBook -> {v: AddressBook | size v == size a + size b} @-} -mergeAddressBooks :: AddressBook -> AddressBook -> AddressBook -mergeAddressBooks = _goal --- mergeAddressBooks a b = --- case a of --- AddressBook x2 x3 -> --- case b of --- AddressBook x6 x7 -> AddressBook (append x2 x6) (append x3 x7) diff --git a/tests/synthesis/logs/.gitkeep b/tests/synthesis/logs/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/synthesis/static/Append.hs b/tests/synthesis/static/Append.hs deleted file mode 100644 index d04881d177..0000000000 --- a/tests/synthesis/static/Append.hs +++ /dev/null @@ -1,12 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Append where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ append :: xs: [a] -> ys: [a] -> { v: [a] | len v == len xs + len ys } @-} -append :: [a] -> [a] -> [a] -append x_S0 x_S1 = - case x_S0 of - [] -> x_S1 - (:) x_So x_Sp -> append x_Sp ((:) x_So x_S1) diff --git a/tests/synthesis/static/BSTFlatten.hs b/tests/synthesis/static/BSTFlatten.hs deleted file mode 100644 index 6f15ed7773..0000000000 --- a/tests/synthesis/static/BSTFlatten.hs +++ /dev/null @@ -1,74 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BSTFlatten where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data BST [size] a = - Empty - | Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } } - @-} -data BST a = Empty | Node a (BST a) (BST a) - -{-@ measure size @-} -{-@ size :: BST a -> Nat @-} -size :: BST a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure bstElts @-} -{-@ bstElts :: BST a -> S.Set a @-} -bstElts :: Ord a => BST a -> S.Set a -bstElts Empty = S.empty -bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r)) - -{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-} -insert :: Ord a => a -> BST a -> BST a -insert x t = - case t of - Empty -> Node x Empty Empty - Node y l r -> - if x == y - then t - else if y <= x - then Node y l (insert x r) - else Node y (insert x l) r - -{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-} -toBST :: Ord a => [a] -> BST a -toBST xs = - case xs of - [] -> Empty - x:xs' -> insert x (toBST xs') - -{-@ data IList [iLen] a = N | ICons { x0 :: a, xs0 :: IList { v: a | x0 < v } } @-} -data IList a = N | ICons a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (ICons x xs) = 1 + iLen xs - -{-@ measure iElts @-} -{-@ iElts :: IList a -> S.Set a @-} -iElts N = S.empty -iElts (ICons x xs) = S.union (S.singleton x) (iElts xs) - -{-@ pivotAppend :: p: a -> xs: IList { v: a | v < p } -> ys: IList { v: a | v > p } - -> { v: IList a | iLen v == iLen xs + iLen ys + 1 && - iElts v == S.union (S.union (iElts xs) (iElts ys)) (S.singleton p) } - @-} -pivotAppend :: a -> IList a -> IList a -> IList a -pivotAppend p xs ys = - case xs of - N -> ICons p ys - ICons x5 x6 -> ICons x5 (pivotAppend p x6 ys) - -{-@ flatten :: t: BST a -> { v: IList a | iElts v == bstElts t } @-} -flatten :: BST a -> IList a -flatten x_S0 = - case x_S0 of - BSTFlatten.Empty -> N - BSTFlatten.Node x_S8 x_S9 x_Sa -> pivotAppend x_S8 (flatten x_S9) (flatten x_Sa) diff --git a/tests/synthesis/static/BSTSort.hs b/tests/synthesis/static/BSTSort.hs deleted file mode 100644 index 11e22e40c9..0000000000 --- a/tests/synthesis/static/BSTSort.hs +++ /dev/null @@ -1,82 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BSTSort where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - - -{-@ data BST [size] a = - Empty - | Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } } - @-} -data BST a = Empty | Node a (BST a) (BST a) - -{-@ measure size @-} -{-@ size :: BST a -> Nat @-} -size :: BST a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure bstElts @-} -{-@ bstElts :: BST a -> S.Set a @-} -bstElts :: Ord a => BST a -> S.Set a -bstElts Empty = S.empty -bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r)) - -{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-} -insert :: Ord a => a -> BST a -> BST a -insert x t = - case t of - Empty -> Node x Empty Empty - Node y l r -> - if x == y - then t - else if y <= x - then Node y l (insert x r) - else Node y (insert x l) r - -{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-} -toBST :: Ord a => [a] -> BST a -toBST xs = - case xs of - [] -> Empty - x:xs' -> insert x (toBST xs') - -{-@ data IList [iLen] a = N | ICons { x0 :: a, xs0 :: IList { v: a | x0 < v } } @-} -data IList a = N | ICons a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (ICons x xs) = 1 + iLen xs - -{-@ measure iElts @-} -{-@ iElts :: IList a -> S.Set a @-} -iElts N = S.empty -iElts (ICons x xs) = S.union (S.singleton x) (iElts xs) - -{-@ pivotAppend :: p: a -> xs: IList { v: a | v < p } -> ys: IList { v: a | v > p } - -> { v: IList a | iLen v == iLen xs + iLen ys + 1 && - iElts v == S.union (S.union (iElts xs) (iElts ys)) (S.singleton p) } - @-} -pivotAppend :: a -> IList a -> IList a -> IList a -pivotAppend p xs ys = - case xs of - N -> ICons p ys - ICons x5 x6 -> ICons x5 (pivotAppend p x6 ys) - -{-@ flatten :: t: BST a -> { v: IList a | iElts v == bstElts t } @-} -flatten :: BST a -> IList a -flatten t = - case t of - Empty -> N - Node x4 x5 x6 -> pivotAppend x4 (flatten x5) (flatten x6) - -{-@ sort' :: xs: [a] -> { v: IList a | iElts v == listElts xs } @-} -sort' :: Ord a => [a] -> IList a -sort' x_S1 = flatten (toBST x_S1) - - - diff --git a/tests/synthesis/static/BinHeapSingleton.hs b/tests/synthesis/static/BinHeapSingleton.hs deleted file mode 100644 index bde0275656..0000000000 --- a/tests/synthesis/static/BinHeapSingleton.hs +++ /dev/null @@ -1,24 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BinHeapSingleton where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data Heap [size] a = Empty | Node { x :: a, l :: Heap { v: a | v > x }, r :: Heap { v: a | v > x } } @-} -data Heap a = Empty | Node a (Heap a) (Heap a) - -{-@ measure size @-} -{-@ size :: Heap a -> Nat @-} -size :: Heap a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure heapElts @-} -{-@ heapElts :: Heap a -> S.Set a @-} -heapElts Empty = S.empty -heapElts (Node x l r) = S.union (S.singleton x) (S.union (heapElts l) (heapElts r)) - -{-@ singleton :: x: a -> { v: Heap a | heapElts v == S.singleton x } @-} -singleton :: a -> Heap a -singleton x_S0 = Node x_S0 Empty Empty \ No newline at end of file diff --git a/tests/synthesis/static/Data.hs b/tests/synthesis/static/Data.hs deleted file mode 100644 index d44f5c7e76..0000000000 --- a/tests/synthesis/static/Data.hs +++ /dev/null @@ -1,17 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data where - -import Language.Haskell.Liquid.Synthesize.Error - -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - -{-@ ex :: x: L a -> { v: (L a) | length' v == length' x } @-} -ex :: L a -> L a -ex x_S0 = x_S0 \ No newline at end of file diff --git a/tests/synthesis/static/Data2.hs b/tests/synthesis/static/Data2.hs deleted file mode 100644 index dd24172064..0000000000 --- a/tests/synthesis/static/Data2.hs +++ /dev/null @@ -1,23 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data2 where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data L [length'] a = N | C {x :: a, xs :: (L a)} @-} -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - -{-@ appendL :: x: L a -> y: L a -> { v: L a | length' v == length' x + length' y } @-} -appendL N y = y -appendL (C x xs) y = C x (appendL xs y) - -{-@ ex1 :: xs:(L a) -> {v: (L a) | 2 * length' xs == length' v} @-} -ex1 :: L a -> L a -ex1 x_S0 = appendL x_S0 x_S0 - diff --git a/tests/synthesis/static/Data3.hs b/tests/synthesis/static/Data3.hs deleted file mode 100644 index 596480c7c3..0000000000 --- a/tests/synthesis/static/Data3.hs +++ /dev/null @@ -1,27 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data3 where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data L [length'] a = N | C {x :: a, xs :: (L a)} @-} -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - - -{-@ appendL :: x: L a -> y: L a -> - { v: L a | length' v == length' x + length' y } - @-} -appendL N y = y -appendL (C x xs) y = C x (appendL xs y) - -{-@ append :: xs: L a -> ys: L a -> - { v: L a | length' v == length' xs + length' ys } - @-} -append :: L a -> L a -> L a -append x_S0 x_S1 = appendL x_S0 x_S1 diff --git a/tests/synthesis/static/IntSimple.hs b/tests/synthesis/static/IntSimple.hs deleted file mode 100644 index af161807c8..0000000000 --- a/tests/synthesis/static/IntSimple.hs +++ /dev/null @@ -1,27 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module IntSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ plus :: x: Int -> y: Int -> { v: Int | v == x + y } @-} -plus :: Int -> Int -> Int -plus x y = x + y - -{-@ one :: { v: Int | v == 1} @-} -one :: Int -one = 1 - -{-@ zero :: { v: Int | v == 0 } @-} -zero :: Int -zero = 0 - -{-@ measure length' @-} -{-@ length' :: [a] -> Nat @-} -length' :: [a] -> Int -length' [] = 0 -length' (x:xs) = 1 + length' xs - -{-@ next :: x: Int -> { v: Int | v == x + 1 } @-} -next :: Int -> Int -next x_S0 = plus one x_S0 diff --git a/tests/synthesis/static/ListId.hs b/tests/synthesis/static/ListId.hs deleted file mode 100644 index c1f40944b0..0000000000 --- a/tests/synthesis/static/ListId.hs +++ /dev/null @@ -1,7 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ listId :: xs:[a] -> {v:[a] | len xs == len v} @-} -listId :: [a] -> [a] -listId x_S0 = x_S0 diff --git a/tests/synthesis/static/ListInsertSort.hs b/tests/synthesis/static/ListInsertSort.hs deleted file mode 100644 index f2fe7745d4..0000000000 --- a/tests/synthesis/static/ListInsertSort.hs +++ /dev/null @@ -1,36 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListInsertSort where - -import qualified Data.Set as S - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data IList a = N | C { x :: a, xs :: (IList { v: a | x <= v}) } @-} -data IList a = N | C a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (C x xs) = 1 + iLen xs - -{-@ measure iElems @-} -{-@ iElems :: IList a -> S.Set a @-} -iElems :: Ord a => IList a -> S.Set a -iElems N = S.empty -iElems (C x xs) = S.union (S.singleton x) (iElems xs) - -{-@ insert :: x: a -> xs: IList a -> { v: IList a | iElems v == S.union (S.singleton x) (iElems xs) } - @-} -insert :: Ord a => a -> IList a -> IList a -insert x N - = C x N -insert x (C x0 xs) - = if x <= x0 then C x (C x0 xs) else C x0 (insert x xs) - -{-@ insertSort :: xs: [a] -> { v: IList a | iElems v == listElts xs } @-} -insertSort x_S1 = - case x_S1 of - [] -> N - (:) x_Sc x_Sd -> insert x_Sc (insertSort x_Sd) diff --git a/tests/synthesis/static/ListNull.hs b/tests/synthesis/static/ListNull.hs deleted file mode 100644 index 582c1df7e2..0000000000 --- a/tests/synthesis/static/ListNull.hs +++ /dev/null @@ -1,20 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListNull where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ true :: { v: Bool | v } @-} -true :: Bool -true = True - -{-@ false :: {v: Bool | not v} @-} -false :: Bool -false = False - -{-@ isNull :: xs: [a] -> { v: Bool | (len xs == 0) <=> v } @-} -isNull :: [a] -> Bool -isNull x_S0 = - case x_S0 of - [] -> true - (:) x_Sc x_Sd -> false \ No newline at end of file diff --git a/tests/synthesis/static/ListZip.hs b/tests/synthesis/static/ListZip.hs deleted file mode 100644 index 76941a055f..0000000000 --- a/tests/synthesis/static/ListZip.hs +++ /dev/null @@ -1,15 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListZip where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ zip' :: xs: [a] -> {ys:[b] | len ys == len xs} -> {v:[(a, b)] | len v == len xs} @-} -zip' :: [a] -> [b] -> [(a, b)] -zip' x_S0 x_S1 = - case x_S0 of - [] -> [], b) - (:) x_Sl x_Sm -> - case x_S1 of - [] -> error " Dead code! " - (:) x_S14 x_S15 -> (:), b) (x_Sl, x_S14) (zip' x_Sm x_S15) \ No newline at end of file diff --git a/tests/synthesis/static/ListZipWith.hs b/tests/synthesis/static/ListZipWith.hs deleted file mode 100644 index 504cbfdb00..0000000000 --- a/tests/synthesis/static/ListZipWith.hs +++ /dev/null @@ -1,19 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListZipWith where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ zipWith' :: f: (a -> b -> c) - -> xs: [a] - -> { ys: [b] | len ys == len xs} - -> {v: [c] | len v == len xs } -@-} -zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c] -zipWith' x_S0 x_S1 x_S2 = - case x_S1 of - [] -> [] - (:) x_St x_Su -> - case x_S2 of - [] -> error " Dead code! " - (:) x_S1d x_S1e -> (:) (x_S0 x_St x_S1d) (zipWith' x_S0 x_Su x_S1e) \ No newline at end of file diff --git a/tests/synthesis/static/NestedListSimple.hs b/tests/synthesis/static/NestedListSimple.hs deleted file mode 100644 index f0666614d7..0000000000 --- a/tests/synthesis/static/NestedListSimple.hs +++ /dev/null @@ -1,9 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module NestedListSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ foo :: { v: [[a]] | len v == 2} @-} -foo :: [[a]] -foo = (:) [] ((:) [] []) diff --git a/tests/synthesis/static/Stutter.hs b/tests/synthesis/static/Stutter.hs deleted file mode 100644 index 896009090e..0000000000 --- a/tests/synthesis/static/Stutter.hs +++ /dev/null @@ -1,11 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - - -{-@ stutter :: xs:[a] -> {v:[a] | 2 * len xs == len v} @-} -stutter :: [a] -> [a] -stutter x_S0 = - case x_S0 of - [] -> [] - (:) x_Sa x_Sb -> (:) x_Sa ((:) x_Sa (stutter x_Sb)) \ No newline at end of file diff --git a/tests/synthesis/static/TreeOne.hs b/tests/synthesis/static/TreeOne.hs deleted file mode 100644 index 405462bb6b..0000000000 --- a/tests/synthesis/static/TreeOne.hs +++ /dev/null @@ -1,21 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module TreeOne where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data Tree [size] a = - Empty - | Node { x:: a, l:: (Tree a), r:: (Tree a) } - @-} -data Tree a = Empty | Node a (Tree a) (Tree a) - -{-@ measure size @-} -{-@ size :: Tree a -> Nat @-} -size :: Tree a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ one :: x: a -> {v: Tree a | size v == 1} @-} -one :: a -> Tree a -one x_S0 = Node x_S0 Empty Empty \ No newline at end of file diff --git a/tests/synthesis/static/TupleListSimple.hs b/tests/synthesis/static/TupleListSimple.hs deleted file mode 100644 index b55dfd468f..0000000000 --- a/tests/synthesis/static/TupleListSimple.hs +++ /dev/null @@ -1,9 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module TupleListSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ foo :: x: a -> ( { v: [a] | len v == 1 }, { v: [a] | len v == 0 } ) @-} -foo :: a -> ([a], [a]) -foo x_S0 = ((:) x_S0 [], []) \ No newline at end of file diff --git a/tests/synthesis/static/map.hs b/tests/synthesis/static/map.hs deleted file mode 100644 index 840a10e5fc..0000000000 --- a/tests/synthesis/static/map.hs +++ /dev/null @@ -1,12 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Map where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ myMap :: (a -> b) -> xs:[a] -> {v:[b] | len v == len xs} @-} -myMap :: (a -> b) -> [a] -> [b] -myMap x_S0 x_S1 = - case x_S1 of - [] -> [] - (:) x_Sf x_Sg -> (:) (x_S0 x_Sf) (myMap x_S0 x_Sg) \ No newline at end of file diff --git a/tests/synthesis/static/single-elem-list.hs b/tests/synthesis/static/single-elem-list.hs deleted file mode 100644 index 9305951da1..0000000000 --- a/tests/synthesis/static/single-elem-list.hs +++ /dev/null @@ -1,8 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - --- This is to test `nilDataCons`. -{-@ oneElem :: xs:a -> {v:[a] | len v == 1} @-} -oneElem :: a -> [a] -oneElem x_S0 = (:) x_S0 [] diff --git a/tests/synthesis/tests/Append.hs b/tests/synthesis/tests/Append.hs deleted file mode 100644 index 2dbeb090e1..0000000000 --- a/tests/synthesis/tests/Append.hs +++ /dev/null @@ -1,9 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Append where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ append :: xs: [a] -> ys: [a] -> { v: [a] | len v == len xs + len ys } @-} -append :: [a] -> [a] -> [a] -append = _goal diff --git a/tests/synthesis/tests/BSTFlatten.hs b/tests/synthesis/tests/BSTFlatten.hs deleted file mode 100644 index 5c2c4f1c45..0000000000 --- a/tests/synthesis/tests/BSTFlatten.hs +++ /dev/null @@ -1,71 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BSTFlatten where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data BST [size] a = - Empty - | Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } } - @-} -data BST a = Empty | Node a (BST a) (BST a) - -{-@ measure size @-} -{-@ size :: BST a -> Nat @-} -size :: BST a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure bstElts @-} -{-@ bstElts :: BST a -> S.Set a @-} -bstElts :: Ord a => BST a -> S.Set a -bstElts Empty = S.empty -bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r)) - -{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-} -insert :: Ord a => a -> BST a -> BST a -insert x t = - case t of - Empty -> Node x Empty Empty - Node y l r -> - if x == y - then t - else if y <= x - then Node y l (insert x r) - else Node y (insert x l) r - -{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-} -toBST :: Ord a => [a] -> BST a -toBST xs = - case xs of - [] -> Empty - x:xs' -> insert x (toBST xs') - -{-@ data IList [iLen] a = N | ICons { x0 :: a, xs0 :: IList { v: a | x0 < v } } @-} -data IList a = N | ICons a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (ICons x xs) = 1 + iLen xs - -{-@ measure iElts @-} -{-@ iElts :: IList a -> S.Set a @-} -iElts N = S.empty -iElts (ICons x xs) = S.union (S.singleton x) (iElts xs) - -{-@ pivotAppend :: p: a -> xs: IList { v: a | v < p } -> ys: IList { v: a | v > p } - -> { v: IList a | iLen v == iLen xs + iLen ys + 1 && - iElts v == S.union (S.union (iElts xs) (iElts ys)) (S.singleton p) } - @-} -pivotAppend :: a -> IList a -> IList a -> IList a -pivotAppend p xs ys = - case xs of - N -> ICons p ys - ICons x5 x6 -> ICons x5 (pivotAppend p x6 ys) - -{-@ flatten :: t: BST a -> { v: IList a | iElts v == bstElts t } @-} -flatten :: BST a -> IList a -flatten = _goal diff --git a/tests/synthesis/tests/BSTSort.hs b/tests/synthesis/tests/BSTSort.hs deleted file mode 100644 index a236a59b0b..0000000000 --- a/tests/synthesis/tests/BSTSort.hs +++ /dev/null @@ -1,83 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BSTSort where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - - -{-@ data BST [size] a = - Empty - | Node { x :: a, l :: BST { v: a | v < x }, r :: BST { v: a | x < v } } - @-} -data BST a = Empty | Node a (BST a) (BST a) - -{-@ measure size @-} -{-@ size :: BST a -> Nat @-} -size :: BST a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure bstElts @-} -{-@ bstElts :: BST a -> S.Set a @-} -bstElts :: Ord a => BST a -> S.Set a -bstElts Empty = S.empty -bstElts (Node x l r) = S.union (S.singleton x) (S.union (bstElts l) (bstElts r)) - -{-@ insert :: x: a -> t: BST a -> { v: BST a | bstElts v == S.union (S.singleton x) (bstElts t) } @-} -insert :: Ord a => a -> BST a -> BST a -insert x t = - case t of - Empty -> Node x Empty Empty - Node y l r -> - if x == y - then t - else if y <= x - then Node y l (insert x r) - else Node y (insert x l) r - -{-@ toBST :: xs: [a] -> { v: BST a | listElts xs == bstElts v } @-} -toBST :: Ord a => [a] -> BST a -toBST xs = - case xs of - [] -> Empty - x:xs' -> insert x (toBST xs') - -{-@ data IList [iLen] a = N | ICons { x0 :: a, xs0 :: IList { v: a | x0 < v } } @-} -data IList a = N | ICons a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (ICons x xs) = 1 + iLen xs - -{-@ measure iElts @-} -{-@ iElts :: IList a -> S.Set a @-} -iElts N = S.empty -iElts (ICons x xs) = S.union (S.singleton x) (iElts xs) - -{-@ pivotAppend :: p: a -> xs: IList { v: a | v < p } -> ys: IList { v: a | v > p } - -> { v: IList a | iLen v == iLen xs + iLen ys + 1 && - iElts v == S.union (S.union (iElts xs) (iElts ys)) (S.singleton p) } - @-} -pivotAppend :: a -> IList a -> IList a -> IList a -pivotAppend p xs ys = - case xs of - N -> ICons p ys - ICons x5 x6 -> ICons x5 (pivotAppend p x6 ys) - -{-@ flatten :: t: BST a -> { v: IList a | iElts v == bstElts t } @-} -flatten :: BST a -> IList a -flatten t = - case t of - Empty -> N - Node x4 x5 x6 -> pivotAppend x4 (flatten x5) (flatten x6) - -{-@ sort' :: xs: [a] -> { v: IList a | iElts v == listElts xs } @-} -sort' :: Ord a => [a] -> IList a -sort' = _goal --- sort' xs = flatten (toBST xs) - - - diff --git a/tests/synthesis/tests/BinHeapSingleton.hs b/tests/synthesis/tests/BinHeapSingleton.hs deleted file mode 100644 index cc4c3a7a22..0000000000 --- a/tests/synthesis/tests/BinHeapSingleton.hs +++ /dev/null @@ -1,25 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module BinHeapSingleton where - -import qualified Data.Set as S -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data Heap [size] a = Empty | Node { x :: a, l :: Heap { v: a | v > x }, r :: Heap { v: a | v > x } } @-} -data Heap a = Empty | Node a (Heap a) (Heap a) - -{-@ measure size @-} -{-@ size :: Heap a -> Nat @-} -size :: Heap a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ measure heapElts @-} -{-@ heapElts :: Heap a -> S.Set a @-} -heapElts Empty = S.empty -heapElts (Node x l r) = S.union (S.singleton x) (S.union (heapElts l) (heapElts r)) - -{-@ singleton :: x: a -> { v: Heap a | heapElts v == S.singleton x } @-} -singleton :: a -> Heap a -singleton = _goal --- singleton x = Node x Empty Empty \ No newline at end of file diff --git a/tests/synthesis/tests/Data.hs b/tests/synthesis/tests/Data.hs deleted file mode 100644 index c2a20c0bdc..0000000000 --- a/tests/synthesis/tests/Data.hs +++ /dev/null @@ -1,17 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data where - -import Language.Haskell.Liquid.Synthesize.Error - -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - -{-@ ex :: x: L a -> { v: (L a) | length' v == length' x } @-} -ex :: L a -> L a -ex = _hole \ No newline at end of file diff --git a/tests/synthesis/tests/Data2.hs b/tests/synthesis/tests/Data2.hs deleted file mode 100644 index 161424a79c..0000000000 --- a/tests/synthesis/tests/Data2.hs +++ /dev/null @@ -1,23 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data2 where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data L [length'] a = N | C {x :: a, xs :: (L a)} @-} -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - -{-@ appendL :: x: L a -> y: L a -> { v: L a | length' v == length' x + length' y } @-} -appendL N y = y -appendL (C x xs) y = C x (appendL xs y) - -{-@ ex1 :: xs:(L a) -> {v: (L a) | 2 * length' xs == length' v} @-} -ex1 :: L a -> L a -ex1 = _hole - diff --git a/tests/synthesis/tests/Data3.hs b/tests/synthesis/tests/Data3.hs deleted file mode 100644 index e083560a27..0000000000 --- a/tests/synthesis/tests/Data3.hs +++ /dev/null @@ -1,27 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Data3 where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data L [length'] a = N | C {x :: a, xs :: (L a)} @-} -data L a = C a (L a) | N - -{-@ measure length' @-} -{-@ length' :: L a -> Nat @-} -length' :: L a -> Int -length' N = 0 -length' (C _ xs) = 1 + length' xs - - -{-@ appendL :: x: L a -> y: L a -> - { v: L a | length' v == length' x + length' y } - @-} -appendL N y = y -appendL (C x xs) y = C x (appendL xs y) - -{-@ append :: xs: L a -> ys: L a -> - { v: L a | length' v == length' xs + length' ys } - @-} -append :: L a -> L a -> L a -append = _goal diff --git a/tests/synthesis/tests/IntSimple.hs b/tests/synthesis/tests/IntSimple.hs deleted file mode 100644 index d68b719040..0000000000 --- a/tests/synthesis/tests/IntSimple.hs +++ /dev/null @@ -1,27 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module IntSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ plus :: x: Int -> y: Int -> { v: Int | v == x + y } @-} -plus :: Int -> Int -> Int -plus x y = x + y - -{-@ one :: { v: Int | v == 1} @-} -one :: Int -one = 1 - -{-@ zero :: { v: Int | v == 0 } @-} -zero :: Int -zero = 0 - -{-@ measure length' @-} -{-@ length' :: [a] -> Nat @-} -length' :: [a] -> Int -length' [] = 0 -length' (x:xs) = 1 + length' xs - -{-@ next :: x: Int -> { v: Int | v == x + 1 } @-} -next :: Int -> Int -next = _goal diff --git a/tests/synthesis/tests/ListId.hs b/tests/synthesis/tests/ListId.hs deleted file mode 100644 index 69c41d16b4..0000000000 --- a/tests/synthesis/tests/ListId.hs +++ /dev/null @@ -1,7 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ listId :: xs:[a] -> {v:[a] | len xs == len v} @-} -listId :: [a] -> [a] -listId = _listId diff --git a/tests/synthesis/tests/ListInsertSort.hs b/tests/synthesis/tests/ListInsertSort.hs deleted file mode 100644 index 884d6366a6..0000000000 --- a/tests/synthesis/tests/ListInsertSort.hs +++ /dev/null @@ -1,38 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListInsertSort where - -import qualified Data.Set as S - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data IList a = N | C { x :: a, xs :: (IList { v: a | x <= v}) } @-} -data IList a = N | C a (IList a) - -{-@ measure iLen @-} -{-@ iLen :: IList a -> Nat @-} -iLen :: IList a -> Int -iLen N = 0 -iLen (C x xs) = 1 + iLen xs - -{-@ measure iElems @-} -{-@ iElems :: IList a -> S.Set a @-} -iElems :: Ord a => IList a -> S.Set a -iElems N = S.empty -iElems (C x xs) = S.union (S.singleton x) (iElems xs) - -{-@ insert :: x: a -> xs: IList a -> { v: IList a | iElems v == S.union (S.singleton x) (iElems xs) } - @-} -insert :: Ord a => a -> IList a -> IList a -insert x N - = C x N -insert x (C x0 xs) - = if x <= x0 then C x (C x0 xs) else C x0 (insert x xs) - -{-@ insertSort :: xs: [a] -> { v: IList a | iElems v == listElts xs } @-} -insertSort :: Ord a => [a] -> IList a -insertSort = _goal --- insertSort xs = --- case xs of --- [] -> N --- x3:x4 -> insert x3 (insertSort x4) diff --git a/tests/synthesis/tests/ListNull.hs b/tests/synthesis/tests/ListNull.hs deleted file mode 100644 index 52091a83b7..0000000000 --- a/tests/synthesis/tests/ListNull.hs +++ /dev/null @@ -1,19 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListNull where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ true :: { v: Bool | v } @-} -true :: Bool -true = True - -{-@ false :: {v: Bool | not v} @-} -false :: Bool -false = False - -{-@ isNull :: xs: [a] -> { v: Bool | (len xs == 0) <=> v } @-} -isNull :: [a] -> Bool -isNull = _goal --- isNull [] = true --- isNull _ = false diff --git a/tests/synthesis/tests/ListZip.hs b/tests/synthesis/tests/ListZip.hs deleted file mode 100644 index 659e8f37c3..0000000000 --- a/tests/synthesis/tests/ListZip.hs +++ /dev/null @@ -1,18 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListZip where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ zip' :: xs: [a] -> {ys:[b] | len ys == len xs} -> {v:[(a, b)] | len v == len xs} @-} -zip' :: [a] -> [b] -> [(a, b)] -zip' = _goal - --- zip' xs ys = --- case xs of --- [] -> case ys of --- [] -> [] --- (x1:x2) -> error " len mismatch " --- x0:xs0 -> case ys of --- [] -> error " len mismatch " --- (y0:ys0) -> (x0, y0) : zip' xs0 ys0 diff --git a/tests/synthesis/tests/ListZipWith.hs b/tests/synthesis/tests/ListZipWith.hs deleted file mode 100644 index bbb6eebedb..0000000000 --- a/tests/synthesis/tests/ListZipWith.hs +++ /dev/null @@ -1,20 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module ListZipWith where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ zipWith' :: f: (a -> b -> c) - -> xs: [a] - -> { ys: [b] | len ys == len xs} - -> {v: [c] | len v == len xs } -@-} -zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c] -zipWith' = _goal --- zipWith' f xs ys = --- case xs of --- [] -> [] --- x3 : x4 -> --- case ys of --- [] -> error "error" --- x7 : x8 -> (f x3 x7) : (zipWith' x f x4 x8) \ No newline at end of file diff --git a/tests/synthesis/tests/NestedListSimple.hs b/tests/synthesis/tests/NestedListSimple.hs deleted file mode 100644 index 70344b3295..0000000000 --- a/tests/synthesis/tests/NestedListSimple.hs +++ /dev/null @@ -1,9 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module NestedListSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ foo :: { v: [[a]] | len v == 2} @-} -foo :: [[a]] -foo = _goal diff --git a/tests/synthesis/tests/Stutter.hs b/tests/synthesis/tests/Stutter.hs deleted file mode 100644 index a51c6be955..0000000000 --- a/tests/synthesis/tests/Stutter.hs +++ /dev/null @@ -1,11 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - - -{-@ stutter :: xs:[a] -> {v:[a] | 2 * len xs == len v} @-} -stutter :: [a] -> [a] -stutter = _x - --- stutter [] = [] --- stutter (x:xs) = x:x:stutter xs diff --git a/tests/synthesis/tests/TreeOne.hs b/tests/synthesis/tests/TreeOne.hs deleted file mode 100644 index f86c19fc85..0000000000 --- a/tests/synthesis/tests/TreeOne.hs +++ /dev/null @@ -1,21 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module TreeOne where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ data Tree [size] a = - Empty - | Node { x:: a, l:: (Tree a), r:: (Tree a) } - @-} -data Tree a = Empty | Node a (Tree a) (Tree a) - -{-@ measure size @-} -{-@ size :: Tree a -> Nat @-} -size :: Tree a -> Int -size Empty = 0 -size (Node x l r) = 1 + size l + size r - -{-@ one :: x: a -> {v: Tree a | size v == 1} @-} -one :: a -> Tree a -one = _goal \ No newline at end of file diff --git a/tests/synthesis/tests/TupleListSimple.hs b/tests/synthesis/tests/TupleListSimple.hs deleted file mode 100644 index 60d7528652..0000000000 --- a/tests/synthesis/tests/TupleListSimple.hs +++ /dev/null @@ -1,9 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module TupleListSimple where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ foo :: x: a -> ( { v: [a] | len v == 1 }, { v: [a] | len v == 0 } ) @-} -foo :: a -> ([a], [a]) -foo = _goal diff --git a/tests/synthesis/tests/map.hs b/tests/synthesis/tests/map.hs deleted file mode 100644 index dd788ae920..0000000000 --- a/tests/synthesis/tests/map.hs +++ /dev/null @@ -1,11 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -module Map where - -import Language.Haskell.Liquid.Synthesize.Error - -{-@ myMap :: (a -> b) -> xs:[a] -> {v:[b] | len v == len xs} @-} -myMap :: (a -> b) -> [a] -> [b] -myMap = _map --- map f [] = [] --- map f (x:xs) = f x : map f xs \ No newline at end of file diff --git a/tests/synthesis/tests/single-elem-list.hs b/tests/synthesis/tests/single-elem-list.hs deleted file mode 100644 index fd9c49a5fa..0000000000 --- a/tests/synthesis/tests/single-elem-list.hs +++ /dev/null @@ -1,8 +0,0 @@ -{-@ LIQUID "--typed-holes" @-} - -import Language.Haskell.Liquid.Synthesize.Error - --- This is to test `nilDataCons`. -{-@ oneElem :: xs:a -> {v:[a] | len v == 1} @-} -oneElem :: a -> [a] -oneElem = _oneElem diff --git a/tests/tests.cabal b/tests/tests.cabal index f0488f580c..5b54137b86 100644 --- a/tests/tests.cabal +++ b/tests/tests.cabal @@ -69,7 +69,6 @@ executable benchmark-stitch-lh Language.Stitch.LH.Check -- , Language.Stitch.LH.CSE , Language.Stitch.LH.Data.List - , Language.Stitch.LH.Data.Map , Language.Stitch.LH.Eval , Language.Stitch.LH.Lex , Language.Stitch.LH.Monad @@ -651,10 +650,12 @@ executable errors , DupData , DupFunSigs , DupMeasure - -- , ElabLocation + , ElabLocation + , ElabLocation2 + , ElabLocation3 , EmptyData - -- , ErrLocation2 - -- , ErrLocation + , ErrLocation + , ErrLocation2 -- , ExportMeasure0 -- , ExportReflect0 , Fractional @@ -1122,6 +1123,7 @@ executable unit-neg other-modules: AbsApp + , AbsNegTest , AdtPeano0 , AdtPeano1 , Alias00 @@ -1166,6 +1168,8 @@ executable unit-neg , ExactADT6 , ExactGADT6 , ExactGADT7 + , Exponential1NegTest + , Exponential2NegTest , Fail1 , Fail , FilterAbs @@ -1596,6 +1600,9 @@ executable unit-pos-1 , T1775 , T1812 , T1874 + , T2091 + , T2093 + , T2096 , T385 , T531 , T595a @@ -1707,6 +1714,7 @@ executable unit-pos-2 other-modules: Abs + , AbsPosTest , Absref_crash0 , Absref_crash , Ackermann @@ -1819,6 +1827,7 @@ executable unit-pos-2 , ExactGADT6 , ExactGADT , Exp0 + , ExponentialPosTest , Extype , Fail , FailName @@ -1921,6 +1930,7 @@ executable unit-pos-2 , Loo , LooLib , LooLibLib + , LNot ghc-options: -fplugin=LiquidHaskell -fkeep-going -O0 if flag(measure-timings) @@ -2020,18 +2030,69 @@ executable relational-pos buildable: False other-modules: - Abs + Abs_relToUn + , Abs + , AppNull + , ApSum , ApSumAsync , AsynchCase + , BuiltInFib + , BuiltInNull , CheckedImp + , Erasure + , Fib + , FunReft + , IncrF + , IncrLet + , Lists + , Log2 + , Map + , Max + , MutRecSame + , Null + , PMonad + , PolyNull + , PowerOf2 , PredAbs + , Prims + , ProofCombinators + , R2Dcounting_relToUn + , R2Dcounting + , RBinaryCounters_relToUn_completed + , RBinaryCounters + , RConstantTimeComparison_relToUn + , RConstantTimeComparison + , Rec + , RecNonFunc + , RIncr_relToUn + , RIncr + , RMap_relToUn + , RMap + , RMemAlloc_relToUn + , RMemAlloc + , RPatError + , RRelationalISort_relToUn_completed + , RRelationalISort + , RRelationalMSort_relToUn_completed + , RRelationalMSort + , RSquareAndMultiply_relToUn + , RSquareAndMultiply + , RTick + , RVar_relToUn + , RVar , SndOrdPredNonRel + , SubRef1 + , SubRef2 + , SumType + , TrdOrdPredNonRel + , UnaryVsRelational ghc-options: -fplugin=LiquidHaskell -fkeep-going -O0 if flag(measure-timings) ghc-options: -fforce-recomp -ddump-timings -ddump-to-file build-depends: liquid-base , liquid-prelude + , liquid-ghc-prim , liquid-vector , liquidhaskell @@ -2050,14 +2111,27 @@ executable relational-neg other-modules: Abs + , AppNull , ApSum , ApSumAsync , BasePredWf - , CheckedImp + , BuiltInFib , CaseOnRec + , CheckedImp + , Fib , FunBaseWf + , FunReft , HigherOrderWf + , IncrLet + , IndAssm + , Null + , PolyNull + , Prims + , Rec , SndOrdPred + , SndOrdPredNonRel + , SubRef + , SubRel ghc-options: -fplugin=LiquidHaskell -fkeep-going -O0 if flag(measure-timings) @@ -2220,6 +2294,9 @@ executable import-cli , T1738Lib , WrapLib , WrapLibCode + , Language + , B + , C ghc-options: -fplugin=LiquidHaskell -fkeep-going @@ -2273,6 +2350,7 @@ executable ple-pos , Ple0 , PleORM , Ple_sum + , Permutations , ReflectDefault , RegexpDerivative , RosePLEDiv