Commit 741843ad authored by Fredrik Wieczerkowski's avatar Fredrik Wieczerkowski

Merge branch 'master' into libs_refactor

parents edbbef9f 71add747
*~
cdoc
docs/*.aux
docs/*.pdf
docs/*.toc
docs/*.log
docs/*.out
docs/*.synctex.gz
.curry
.cpm
Copyright (c) 2020, Michael Hanus
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------
A translater from Curry with Integrated Code to standard Curry
--------------------------------------------------------------
The Curry Preprocessor
======================
Authors: Max Deppert - made@informatik.uni-kiel.de
Jasper Sikorra - jsi@informatik.uni-kiel.de
This repository contains the implementation of the
Curry preprocessor `currypp` which supports some
extensions for Curry programs, like
* Integrated code, i.e., the integration of code
written in some other language into Curry programs,
like regular expressions, format specifications (`printf`),
HTML and XML code,
* default rules,
* contracts.
Details about the usage can be found in the manual.
Here is a short summary of the usage of integrated code.
General usage of the code integrator:
-------------------------------------
If the pre-processor is installed (see Makefile) as the binary `currypp`,
If the pre-processor is installed as the binary `currypp`,
Curry source files containing integrated code can be translated
by running `currypp` as follows:
......
......@@ -150,14 +150,15 @@ one can specify the desired format with foreign code marked by
similarly to the \code{printf} statement of C,
followed by a comma-separated list of arguments.
This format specification is transformed into operations
of the \CYS library \code{Format} so that it must be imported.
of the library \code{Data.Format} (of package \code{printf})
so that it must be imported.
For instance, the following program defines an operation
that formats a string, an integer (with leading sign and zeros),
and a float with leading sign and precision 3:
\begin{currynomath}
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=foreigncode #-}
import Format
import Data.Format
showSIF :: String -> Int -> Float -> String
showSIF s i f = ``format "Name: %s | %+.5i | %+6.3f",s,i,f''
......@@ -714,6 +715,20 @@ queens :: Int -> [Int]
queens n = safe (permute [1..n])
\end{curry}
\paragraph{Important note:}
The implementation of default rules is based on set functions
(implemented by the module \code{Control.SetFunctions}).
Therefore, the package \code{setfunctions} should be installed
as a dependency.
This can easily done by executing
%
\begin{curry}
> cypm add setfunctions
\end{curry}
%
before compiling a program containing default rules with the
Curry preprocessor.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Contracts}
......@@ -777,6 +792,22 @@ Postcondition of 'sort' (module Quicksort, line 27) violated for:
ERROR: Execution aborted due to contract violation!
\end{curry}
\paragraph{Important note:}
The implementation of default rules is based on set functions
(implemented by the module \code{Control.SetFunctions}) and
the auxiliary package to check contracts at run time.
Therefore, the packages \code{setfunctions} and \code{contracts}
should be installed as dependencies.
This can easily done by executing
%
\begin{curry}
> cypm add setfunctions
> cypm add contracts
\end{curry}
%
before compiling a program containing contracts with the
Curry preprocessor.
% LocalWords: preprocessor
......
......@@ -8,9 +8,11 @@ sort (xs++[x,y]++ys) | x>y = sort (xs++[y,x]++ys)
sort'default xs = xs
-- Precondition: we don't like to sort empty lists...
sort'pre :: [Int] -> Bool
sort'pre xs = length xs > 0
-- Postcondition: input and output lists should have the same length
sort'post :: [Int] -> [Int] -> Bool
sort'post xs ys = length xs == length ys
sort7 = sort [7,1,6,3,5,4,2] -=- [1..7]
......
......@@ -4,7 +4,7 @@
-- Example for using integrated code, default rules, and contracts in one
-- module
import Format
import Data.Format
import Test.Prop
showInt i = ``format "%+.3d",i''
......@@ -15,9 +15,11 @@ sort (xs++[x,y]++ys) | x>y = sort (xs++[y,x]++ys)
sort'default xs = xs
-- Precondition: we don't like to sort empty lists...
sort'pre :: (Ord a, Show a) => [a] -> Bool
sort'pre xs = length xs > 0
-- Postcondition: input and output lists should have the same length
sort'post :: (Ord a, Show a) => [a] -> [a] -> Bool
sort'post xs ys = length xs == length ys
sort7 = sort (map showInt [7,1,6,3,5,4,2]) -=- map (\d -> "+00"++show d) [1..7]
......
......@@ -3,12 +3,16 @@
-- Defining factorial numbers:
-- Specification: the usual recursive definition
fac'spec :: Int -> Int
fac'spec n = if n==0 then 1 else n * fac'spec (n-1)
-- The input should be non-negative:
fac'pre :: Int -> Bool
fac'pre n = n>=0
-- The result should be positive:
fac'post :: Int -> Int -> Bool
fac'post _ v = v>0
-- An implementation using Prelude operations:
fac :: Int -> Int
fac n = foldr (*) 1 [1..n]
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=contracts #-}
-- straight selection sort with specification
import SetFunctions
import Control.SetFunctions
perm [] = []
perm (x:xs) = insert (perm xs)
......
......@@ -16,9 +16,11 @@ sorted [_] = True
sorted (x:y:ys) = x<=y && sorted (y:ys)
-- Trivial precondition, just for testing
sort'pre :: [Int] -> Bool
sort'pre xs = length xs >= 0
-- Postcondition: input and output lists should have the same length
sort'post :: [Int] -> [Int] -> Bool
sort'post xs ys = length xs == length ys
-- Specification of sort:
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- The following task should be solved:
-- Break a Curry main expression into an expression and a where...free clause.
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import SetFunctions
import Test.Prop
import Control.SetFunctions
-- Bubble sort formulation with default rule
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- The implementation of coloring a map using a default rule
-- (by Sergio Antoy).
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Dijsktra's Dutch National Flag problem with functional patterns
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Operation to delete suffixes of the fornm ".0"
fix_int (s++".0") = s
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Example: predicate to check for float strings
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- Examples for multiple rules with guards:
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- Warning: these redefinitions work fine with KiCS2, but with PAKCS
-- they do not work on infinite lists due to restrictions on set functions.
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Lookup with default rules:
nlookup key (_ ++ [(key,value)] ++ _) = Just value
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- A simple implementation of a two-person game (here: Nim) with default rules
--
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- Parallel or with default rules:
por True _ = True
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-------------------------------------------------------------------------
-- Definition of n-queens with default rules:
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- Reverse a list if it has exactly two elements:
rev2 :: [a] -> [a]
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
{-# OPTIONS_CYMAKE -Wnone #-}
import Test.EasyCheck
import Test.Prop
-- Example: parse World Cup soccer scores (e.g., "_:_", "3:2")
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Bubble sort formulation with default rule as deterministic function
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Dijsktra's Dutch National Flag problem with functional patterns,
-- default rule declared as a deterministic function:
......
{-# OPTIONS_CYMAKE -F --pgmF=currypp --optF=defaultrules #-}
import Test.EasyCheck
import Test.Prop
-- Parallel or declared as a deterministic function:
por :: Bool -> Bool -> DET Bool
......
......@@ -8,7 +8,7 @@
--- <http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>
------------------------------------------------------------------------------
import Format -- required in the pre-processed program
import Data.Format -- required in the pre-processed program
-- Format a string and an integer:
ex1 :: String -> Int -> IO ()
......
......@@ -6,7 +6,7 @@
------------------------------------------------------------------------------
import RegExp
import Format
import Data.Format
isEmail :: String -> Bool
isEmail s = s ``regex
......
......@@ -9,8 +9,8 @@
--- <http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html>
------------------------------------------------------------------------------
import Format -- required in the pre-processed program
import Test.EasyCheck
import qualified Data.Format -- required in the pre-processed program
import Test.Prop
-- Format a string and an integer:
ex1 :: String -> Int -> String
......
......@@ -6,7 +6,7 @@
------------------------------------------------------------------------------
import HTML.Base
import Test.EasyCheck
import Test.Prop
htmlTest1 :: String -> [HtmlExp]
htmlTest1 name = ``html
......
......@@ -8,7 +8,7 @@
------------------------------------------------------------------------------
import RegExp -- from package `regexp` (required in the pre-processed program)
import Test.EasyCheck
import Test.Prop
test_abc = (match ``regex abc'' "abc") -=- True
......
......@@ -4,29 +4,35 @@
"author": "Michael Hanus <mh@informatik.uni-kiel.de>",
"synopsis": "The standard preprocessor of Curry",
"category": [ "Programming", "Analysis" ],
"license": "BSD-3-Clause",
"licenseFile": "LICENSE",
"dependencies": {
"abstract-curry": ">= 3.0.0",
"cass-analysis" : ">= 3.0.0",
"cass" : ">= 3.0.0",
"cdbi" : ">= 3.0.0",
"currycheck" : ">= 3.0.0",
"fl-parser" : ">= 1.0.0",
"html" : ">= 3.0.0",
"regexp" : ">= 2.0.0",
"wl-pprint" : ">= 2.0.0",
"xml" : ">= 3.0.0",
"base" : ">= 2.0.0"
"base" : ">= 3.0.0, < 4.0.0",
"abstract-curry": ">= 3.0.0, < 4.0.0",
"cass-analysis" : ">= 3.0.0, < 4.0.0",
"cass" : ">= 3.0.0, < 4.0.0",
"cdbi" : ">= 3.0.0, < 4.0.0",
"contracts" : ">= 3.0.0, < 4.0.0",
"currycheck" : ">= 3.0.0, < 4.0.0",
"currypath" : ">= 3.0.0, < 4.0.0",
"finite-map" : ">= 3.0.0, < 4.0.0",
"fl-parser" : ">= 3.0.0, < 4.0.0",
"flatcurry" : ">= 3.0.0, < 4.0.0",
"frontend-exec" : ">= 3.0.0, < 4.0.0",
"html" : ">= 3.0.0, < 4.0.0",
"printf" : ">= 3.0.0, < 4.0.0",
"regexp" : ">= 3.0.0, < 4.0.0",
"searchtree" : ">= 3.0.0, < 4.0.0",
"setfunctions" : ">= 3.0.0, < 4.0.0",
"wl-pprint" : ">= 3.0.0, < 4.0.0",
"xml" : ">= 3.0.0, < 4.0.0",
"easycheck" : ">= 3.0.0, < 4.0.0"
},
"compilerCompatibility": {
"pakcs": ">= 2.0.0",
"kics2": ">= 2.0.0"
},
"sourceDirs": [ "src", "src/IntegratedCode",
"sourceDirs": [ "src",
"src/IntegratedCode",
"src/IntegratedCode/Parser",
"src/IntegratedCode/Parser/ML",
"src/IntegratedCode/Parser/SQL",
"src/DefaultRules",
"src/ContractWrapper"
"src/IntegratedCode/Parser/SQL"
],
"exportedModules": [ "Main" ],
"executable": {
......@@ -34,24 +40,27 @@
"main": "Main"
},
"testsuite": [
{ "src-dir": "src/IntegratedCode/Examples",
{ "src-dir": "examples/IntegratedCode",
"modules": [ "testFormat", "testHtml", "testRegExps" ]
},
{ "src-dir": "src/IntegratedCode/ExamplesSQL",
{ "src-dir": "examples/IntegratedSQLCode",
"options": "-v",
"script" : "test.sh"
},
{ "src-dir": "src/DefaultRules/Examples",
{ "src-dir": "examples/Contracts",
"options": "--nospec --nodet --deftype=Int",
"modules": [ "BubbleSort", "BubbleSortFormat", "Coin",
"FibInfinite", "Quicksort" ]
},
{ "src-dir": "examples/DefaultRules",
"options": "-m40",
"modules": [ "BreakWhere", "BubbleSort", "ColorMap", "DutchFlag",
"FixInt", "FloatString", "Guards", "ListFuns", "Lookup",
"Nim", "ParOr", "Queens", "Rev2", "WorldCup",
"ParOrDet", "BubbleSortDet", "DutchFlagDet" ]
"Nim", "ParOr", "Queens", "Rev2", "WorldCup" ]
},
{ "src-dir": "src/ContractWrapper/Examples",
"options": "--nospec --nodet --deftype=Int",
"modules": [ "BubbleSort", "BubbleSortFormat", "Coin",
"FibInfinite", "Quicksort" ]
{ "src-dir": "examples/DeterministicOperations",
"options": "-m40",
"modules": [ "BubbleSortDet", "DutchFlagDet", "ParOrDet" ]
}
],
"documentation": {
......
------------------------------------------------------------------------------
--- Auxiliary operations to compile additionally imported modules
--- with the front end.
module CPP.CompileWithFrontend
where
import Distribution ( curryCompiler )
import System.FrontendExec
------------------------------------------------------------------------------
--- If a module is added as a new import to the transformed program,
--- we have to compile it in order to avoid a compilation error
--- of the front end, since the front end assumes,
-- if the preprocessor is called, that all imported modules are
-- already compiled.
compileImportedModule :: Int -> String -> IO ()
compileImportedModule verb modname = do
mapM (compileModuleTo verb modname) [ACY, UACY]
compileSetFunctions2Flat
where
compileSetFunctions2Flat
| curryCompiler == "kics2"
= compileModuleTo verb modname TFCY
| curryCompiler == "pakcs"
= compileModuleTo verb modname FCY
| otherwise
= error $ "compileSetFunctions: unknown Curry compiler '" ++
curryCompiler ++ "'!"
compileModuleTo :: Int -> String -> FrontendTarget -> IO ()
compileModuleTo verb modname target = do
when (verb > 2) $ putStrLn $
"Compiling '" ++ modname ++ "' to '" ++ showFrontendTarget target ++ "'..."
callFrontendWithParams target (setQuiet True defaultParams) modname
------------------------------------------------------------------------------
......@@ -11,10 +11,19 @@
--- > Declarative Languages (PADL 2012), pp. 33-47, Springer LNCS 7149, 2012
---
--- @author Michael Hanus
--- @version October 2016
--- @version April 2019
------------------------------------------------------------------------
module TransContracts(main,transContracts) where
module CPP.Contracts ( main, translateContracts )
where
import Char
import Directory
import Distribution ( installDir )
import FilePath ( takeDirectory )
import List
import Maybe ( fromJust, isNothing )
import System