CurryInfo: verify-non-fail-2.0.0

categories:
Programming Analysis Verification
dependencies:
[Dependency "base" [[VGte "3.2.0",VLt "4.0.0"]],Dependency "abstract-curry" [[VGte "4.0.0",VLt "5.0.0"]],Dependency "cass" [[VGte "4.0.0",VLt "5.0.0"]],Dependency "cass-analysis" [[VGte "4.0.0",VLt "5.0.0"]],Dependency "containers" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "contracts" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "csv" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "currypath" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "directory" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "execpath" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "extra" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "filepath" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "flatcurry" [[VGte "3.0.0",VLt "5.0.0"]],Dependency "flatcurry-smt" [[VMajCompatible "2.0.0"]],Dependency "io-extra" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "json" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "process" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "profiling" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "rw-data" [[VGte "1.0.0"]],Dependency "scc" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "time" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "transformers" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "wl-pprint" [[VGte "3.0.0",VLt "4.0.0"]],Dependency "xml" [[VGte "3.0.0",VLt "4.0.0"]]]
documentation:
A tool to verify Curry operations as non-failing
================================================

This package contains a tool to verify that all operations
in a given Curry module are non-failing, i.e., their evaluation does
not result in a failure, if they are called with appropriate
arguments. The tool automatically infers abstract call types
and non-fail conditions specifying supersets of appropriate arguments.

As an example, consider the following operation to compute the last element
of a given list:

    last :: [a] -> a
    last [x]            = x
    last (_ : xs@(_:_)) = last xs

In the default mode (where types are abstracted into a set
of allowed top-level constructors), the inferred call type is

    last: {:}

specifying that `last` does not fail if the argument is a
non-empty list, i.e., evaluable to some data term rooted by
the list constructor "`:`".

When an operation with such a restricted call type is used,
the tool checks whether it is used in a context which
ensures its call type. For instance, the operations

    head (x:xs) = x

and

    tail (x:xs) = xs

have the inferred call types

    head: {:}
    tail: {:}

When these operations are applied, it should be ensured
(in a top-level functional computation) that the actual arguments
are non-empty lists, as in the following operation:

    readCommand :: IO ()
    readCommand = do
      putStr "Input a command:"
      s <- getLine
      let ws = words s
      case null ws of True  -> readCommand
                      False -> processCommand (head ws) (tail ws)

The tool automatically verifies that the operation `readCommand`
is non-failing.

The ideas of the implementation of this tool are described in:

> M. Hanus: Inferring Non-Failure Conditions for Declarative Programs,
> Proc. of the 17th International Symposium on Functional and Logic Programming
> (FLOPS 2024), Springer LNCS 14659, pp. 167-187, 2024,
> DOI: [10.1007/978-981-97-2300-3\_10](http://dx.doi.org/10.1007/978-981-97-2300-3\_10),


Arithmetic non-fail conditions
------------------------------

If the SMT solver [Z3](https://github.com/Z3Prover/z3.git) is
installed and the executable `z3` can be found in the path,
the tool can also infer and verify arithmetic non-fail conditions.
For instance, it infers for the factorial function defined by

    fac :: Int -> Int
    fac n | n == 0 = 1
          | n > 0  = n * fac (n - 1)

the non-fail condition

    fac'nonfail :: Int -> Bool
    fac'nonfail v1 = (v1 == 0) || (v1 > 0)

specifying that the argument must be non-negative in order to ensure
that `fac` does not fail.
With this information, it also proves that the following
I/O operation does not fail (where the operation `readInt`
reads a line until it is an integer):

    printFac :: IO ()
    printFac = do
      putStr "Factorial computation for: "
      n <- readInt
      if n<0 then putStrLn "Negative number, try again" >> printFac
             else print (fac n)

The ideas of the verification of arithmetic non-fail conditions
are described in:

> M. Hanus: Hybrid Verification of Declarative Programs with
> Arithmetic Non-fail Conditions,
> Proc. of the 22nd Asian Symposium on Programming Languages and Systems
> (APLAS 2024), Springer LNCS 15194, pp. 109-129, 2024,
> DOI: [10.1007/978-981-97-8943-6\_6](http://dx.doi.org/10.1007/978-981-97-8943-6\_6),

------------------------------------------------------------------------------

Installation
------------

If you downloaded the sources of this package, then the tool can be
installed via the command

    > cypm install

in the main directory of this package. Otherwise, the tool can
also be downloaded and installed by the command

    > cypm install verify-non-fail

This installs the executable `curry-calltypes` in the bin-directory of CPM.

If one uses KiCS2 to install this tool, one should use version 3.1.0
of April 11, 2024 (or newer) due to a memory leak in an older version of KiCS2.

------------------------------------------------------------------------------

Web Demo Installation
---------------------

If you want to try this tool on simple programs via a web interface,
you can use a
[Web Demo Installation](https://cpm.curry-lang.org/webapps/failfree/)
of this tool.

------------------------------------------------------------------------------

Files
-----

In order to support a modular analysis of applications consisting
of several modules, the tool caches already computed analysis results
of modules in under the directory `~/.curry_verify_cache`.
This path is defined in `Verify.Files.getVerifyCacheDirectory`.
To store the analysis results for different Curry systems and
abstract domains separately, the analysis results for a Curry module
which is stored in a file with path `MODULEPATH.curry` are contained in

    ~/.curry_verify_cache/CURRYSYSTEMID/DOMAINID/MODULEPATH-*

For instance, the call types of the prelude for KiCS2 Version 3.1.0
w.r.t. the abstract domain `Values` are stored in

    ~/.curry_verify_cache/kics2-3.1.0/Values/opt/kics2/lib/Prelude-CALLTYPES

provided that KiCS2 is installed at `/opt/kics2` so that the prelude
is contained in the file `/opt/kics2/lib/Prelude.curry`.

All cache files (for the Curry system used to install this tool)
can be deleted by the command

    curry-calltypes --delete

------------------------------------------------------------------------------
exportedmodules:
PackageConfig Main FlatCurry.AddTypes FlatCurry.Names FlatCurry.Simplify FlatCurry.NormalizeLet FlatCurry.Print FlatCurry.Build Verify.ESMT Verify.NonFailConditions Verify.WithSMT Verify.Files Verify.Statistics Verify.IOTypes Verify.CallTypes Verify.Helpers Verify.ProgInfo Verify.Options
modules:
PackageConfig Main FlatCurry.AddTypes FlatCurry.Names FlatCurry.Simplify FlatCurry.NormalizeLet FlatCurry.Print FlatCurry.Build Verify.ESMT Verify.NonFailConditions Verify.WithSMT Verify.Files Verify.Statistics Verify.IOTypes Verify.CallTypes Verify.Helpers Verify.ProgInfo Verify.Options
version:
2.0.0