Commit b729a342 authored by Michael Hanus 's avatar Michael Hanus
Browse files

Tools updated

parent 2d501c02
......@@ -16,6 +16,7 @@ currypp/.cpm/packages/cass-analysis-0.0.4
currypp/.cpm/packages/currycheck-1.0.1
currypp/.cpm/packages/rewriting-0.0.1
currypp/.cpm/packages/verify-0.0.2
currypp/.cpm/packages/abstract-curry-1.0.0
currypp/.cpm/packages/flatcurry-1.0.0
currypp/.cpm/packages/xml-0.0.1
optimize/.cpm/packages/cass-0.0.1
......
Copyright (c) 2017, 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.
abstract-curry
==============
This package contains libraries to deal with AbstractCurry programs.
AbstractCurry is a representation of Curry programs oriented
towards the source code of Curry. Thus, it can be used
to generate readable Curry programs, e.g., by the Web framework Spicey.
The package contains the following modules:
* `AbstractCurry.Build`: This module provides some useful operations
to write programs that generate AbstractCurry programs
in a more compact and readable way.
* `AbstractCurry.Files`: This module defines operations to read and write
AbstractCurry programs.
* `AbstractCurry.Pretty`: This module provides a pretty-printer
for AbstractCurry modules.
* `AbstractCurry.Select`: This module provides some useful operations
to select components in AbstractCurry programs, i.e.,
it provides a collection of selector functions for AbstractCurry.
* `AbstractCurry.Show`: This module provides
transformation and update operations on AbstractCurry programs.
Since the transformations are defined recursively on structured types,
they are useful to construct specific transformations on AbstractCurry
programs. In particular, this library contains the transformation
`renameCurryModule` to rename an AbstractCurry module.
* `AbstractCurry.Types`: This module defines the data types to represent
AbstractCurry programs in Curry.
{
"name": "abstract-curry",
"version": "1.0.0",
"author": "Michael Hanus <mh@informatik.uni-kiel.de>",
"synopsis": "Libraries to deal with AbstractCurry programs",
"category": [ "Metaprogramming" ],
"license": "BSD-3-Clause",
"licenseFile": "LICENSE",
"dependencies": {
},
"compilerCompatibility": {
"pakcs": ">= 1.14.0, < 2.0.0",
"kics2": ">= 0.5.0, < 2.0.0"
},
"exportedModules": [ "AbstractCurry.Build", "AbstractCurry.Files",
"AbstractCurry.Pretty", "AbstractCurry.Select",
"AbstractCurry.Transform", "AbstractCurry.Types" ],
"source": {
"git": "https://git.ps.informatik.uni-kiel.de/curry-packages/abstract-curry.git",
"tag": "$version"
}
}
------------------------------------------------------------------------
--- This library provides some useful operations to write programs
--- that generate AbstractCurry programs in a more compact and readable way.
---
--- @version February 2016
--- @category meta
------------------------------------------------------------------------
module AbstractCurry.Build where
import AbstractCurry.Types
infixr 9 ~>
------------------------------------------------------------------------
-- Goodies to construct type expressions
--- A function type.
(~>) :: CTypeExpr -> CTypeExpr -> CTypeExpr
t1 ~> t2 = CFuncType t1 t2
--- A base type.
baseType :: QName -> CTypeExpr
baseType t = CTCons t []
--- Constructs a list type from an element type.
listType :: CTypeExpr -> CTypeExpr
listType a = CTCons (pre "[]") [a]
--- Constructs a tuple type from list of component types.
tupleType :: [CTypeExpr] -> CTypeExpr
tupleType ts | l==0 = baseType (pre "()")
| l==1 = head ts
| otherwise = CTCons (pre ('(' : take (l-1) (repeat ',') ++ ")"))
ts
where l = length ts
--- Constructs an IO type from a type.
ioType :: CTypeExpr -> CTypeExpr
ioType a = CTCons (pre "IO") [a]
--- Constructs a Maybe type from element type.
maybeType :: CTypeExpr -> CTypeExpr
maybeType a = CTCons (pre "Maybe") [a]
--- The type expression of the String type.
stringType :: CTypeExpr
stringType = baseType (pre "String")
--- The type expression of the Int type.
intType :: CTypeExpr
intType = baseType (pre "Int")
--- The type expression of the Float type.
floatType :: CTypeExpr
floatType = baseType (pre "Float")
--- The type expression of the Bool type.
boolType :: CTypeExpr
boolType = baseType (pre "Bool")
--- The type expression of the Char type.
charType :: CTypeExpr
charType = baseType (pre "Char")
--- The type expression of the unit type.
unitType :: CTypeExpr
unitType = baseType (pre "()")
--- The type expression of the Time.CalendarTime type.
dateType :: CTypeExpr
dateType = baseType ("Time", "CalendarTime")
------------------------------------------------------------------------
-- Goodies to construct function declarations
--- Constructs a function declaration from a given qualified function name,
--- arity, visibility, type expression and list of defining rules.
cfunc :: QName -> Int -> CVisibility -> CTypeExpr -> [CRule] -> CFuncDecl
cfunc = CFunc
--- Constructs a function declaration from a given comment,
--- qualified function name,
--- arity, visibility, type expression and list of defining rules.
cmtfunc :: String -> QName -> Int -> CVisibility -> CTypeExpr -> [CRule]
-> CFuncDecl
cmtfunc = CmtFunc
--- Constructs a simple rule with a pattern list and an
--- unconditional right-hand side.
simpleRule :: [CPattern] -> CExpr -> CRule
simpleRule pats rhs = CRule pats (CSimpleRhs rhs [])
--- Constructs a simple rule with a pattern list, an
--- unconditional right-hand side, and local declarations.
simpleRuleWithLocals :: [CPattern] -> CExpr -> [CLocalDecl] -> CRule
simpleRuleWithLocals pats rhs ldecls = CRule pats (CSimpleRhs rhs ldecls)
--- Constructs a rule with a possibly guarded right-hand side
--- and local declarations.
--- A simple right-hand side is constructed if there is only one
--- `True` condition.
guardedRule :: [CPattern] -> [(CExpr,CExpr)] -> [CLocalDecl] -> CRule
guardedRule pats gs ldecls
| length gs == 1 && fst (head gs) == CSymbol (pre "True")
= CRule pats (CSimpleRhs (snd (head gs)) ldecls)
| otherwise = CRule pats (CGuardedRhs gs ldecls)
--- Constructs a guarded expression with the trivial guard.
noGuard :: CExpr -> (CExpr, CExpr)
noGuard e = (CSymbol (pre "True"), e)
------------------------------------------------------------------------
-- Goodies to construct expressions and patterns
--- An application of a qualified function name to a list of arguments.
applyF :: QName -> [CExpr] -> CExpr
applyF f es = foldl CApply (CSymbol f) es
--- An application of an expression to a list of arguments.
applyE :: CExpr -> [CExpr] -> CExpr
applyE f args = foldl CApply f args
--- A constant, i.e., an application without arguments.
constF :: QName -> CExpr
constF f = applyF f []
--- An application of a variable to a list of arguments.
applyV :: CVarIName -> [CExpr] -> CExpr
applyV v es = foldl CApply (CVar v) es
-- Applies the Just constructor to an AbstractCurry expression.
applyJust :: CExpr -> CExpr
applyJust a = applyF (pre "Just") [a]
-- Applies the maybe function to three AbstractCurry expressions.
applyMaybe :: CExpr -> CExpr -> CExpr -> CExpr
applyMaybe a1 a2 a3 = applyF (pre "maybe") [a1,a2,a3]
--- Constructs a tuple expression from list of component expressions.
tupleExpr :: [CExpr] -> CExpr
tupleExpr es | l==0 = constF (pre "()")
| l==1 = head es
| otherwise = applyF (pre ('(' : take (l-1) (repeat ',') ++ ")"))
es
where l = length es
-- Constructs a let declaration (with possibly empty local delcarations).
letExpr :: [CLocalDecl] -> CExpr -> CExpr
letExpr locals cexp = if null locals then cexp else CLetDecl locals cexp
--- Constructs from a pattern and an expression a branch for a case expression.
cBranch :: CPattern -> CExpr -> (CPattern, CRhs)
cBranch pattern exp = (pattern, CSimpleRhs exp [])
--- Constructs a tuple pattern from list of component patterns.
tuplePattern :: [CPattern] -> CPattern
tuplePattern ps
| l==0 = CPComb (pre "()") []
| l==1 = head ps
| otherwise = CPComb (pre ('(' : take (l-1) (repeat ',') ++ ")")) ps
where l = length ps
--- Constructs, for given n, a list of n PVars starting from 0.
pVars :: Int -> [CPattern]
pVars n = [CPVar (i,"x"++show i) | i<-[0..n-1]]
--- Converts an integer into an AbstractCurry expression.
pInt :: Int -> CPattern
pInt x = CPLit (CIntc x)
--- Converts a float into an AbstractCurry expression.
pFloat :: Float -> CPattern
pFloat x = CPLit (CFloatc x)
--- Converts a character into a pattern.
pChar :: Char -> CPattern
pChar x = CPLit (CCharc x)
--- Constructs an empty list pattern.
pNil :: CPattern
pNil = CPComb (pre "[]") []
--- Constructs a list pattern from list of component patterns.
listPattern :: [CPattern] -> CPattern
listPattern [] = pNil
listPattern (p:ps) = CPComb (pre ":") [p, listPattern ps]
--- Converts a string into a pattern representing this string.
stringPattern :: String -> CPattern
stringPattern = CPLit . CStringc
--- Converts a list of AbstractCurry expressions into an
--- AbstractCurry representation of this list.
list2ac :: [CExpr] -> CExpr
list2ac [] = constF (pre "[]")
list2ac (c:cs) = applyF (pre ":") [c, list2ac cs]
--- Converts an integer into an AbstractCurry expression.
cInt :: Int -> CExpr
cInt x = CLit (CIntc x)
--- Converts a float into an AbstractCurry expression.
cFloat :: Float -> CExpr
cFloat x = CLit (CFloatc x)
--- Converts a character into an AbstractCurry expression.
cChar :: Char -> CExpr
cChar x = CLit (CCharc x)
--- Converts a string into an AbstractCurry represention of this string.
string2ac :: String -> CExpr
string2ac s = CLit (CStringc s)
--- Converts an index i into a variable named xi.
toVar :: Int -> CExpr
toVar i = CVar (1,"x"++show i)
--- Converts a string into a variable with index 1.
cvar :: String -> CExpr
cvar s = CVar (1,s)
--- Converts a string into a pattern variable with index 1.
cpvar :: String -> CPattern
cpvar s = CPVar (1,s)
--- Converts a string into a type variable with index 1.
ctvar :: String -> CTypeExpr
ctvar s = CTVar (1,s)
------------------------------------------------------------------------
-- ---------------------------------------------------------------------------
--- This library defines various I/O actions to read Curry programs and
--- transform them into the AbstractCurry representation and to write
--- AbstractCurry files.
---
--- Assumption: an abstract Curry program is stored in file with
--- extension `.acy` in the subdirectory `.curry`
---
--- @author Michael Hanus, Bjoern Peemoeller
--- @version October 2015
--- @category meta
-- ---------------------------------------------------------------------------
module AbstractCurry.Files where
import AbstractCurry.Select (imports)
import AbstractCurry.Types
import Char (isSpace)
import Directory (doesFileExist, getModificationTime)
import Distribution
import FileGoodies (getFileInPath, lookupFileInPath)
import FilePath (takeFileName, (</>), (<.>))
import Maybe (isNothing)
import ReadShowTerm
-- ---------------------------------------------------------------------------
--- I/O action which parses a Curry program and returns the corresponding
--- typed Abstract Curry program.
--- Thus, the argument is the file name without suffix ".curry"
--- or ".lcurry") and the result is a Curry term representing this
--- program.
readCurry :: String -> IO CurryProg
readCurry prog = readCurryWithParseOptions prog (setQuiet True defaultParams)
--- Read an AbstractCurry file with all its imports.
--- @param modname - Module name or file name of Curry module
--- @return a list of curry programs, having the AbstractCurry file as head.
readCurryWithImports :: String -> IO [CurryProg]
readCurryWithImports modname = collect [] [modname]
where
collect _ [] = return []
collect imported (m:ms)
| m `elem` imported = collect imported ms
| otherwise = do
p <- readCurry m
ps <- collect (m:imported) (ms ++ imports p)
return (p:ps)
tryReadCurryWithImports :: String -> IO (Either [String] [CurryProg])
tryReadCurryWithImports modname = collect [] [modname]
where
collect _ [] = return (Right [])
collect imported (m:ms)
| m `elem` imported = collect imported ms
| otherwise = do
eProg <- tryReadCurryFile m
case eProg of
Left err -> return (Left [err])
Right prog@(CurryProg _ is _ _ _) -> do
results <- collect (m:imported) (ms ++ is)
return (either Left (Right . (prog :)) results)
tryReadCurryFile :: String -> IO (Either String CurryProg)
tryReadCurryFile m = do
mbSrc <- lookupModuleSourceInLoadPath m
case mbSrc of
Nothing -> cancel $ "Source module '" ++ m ++ "' not found"
Just (_,srcFile) -> do
callFrontendWithParams ACY (setQuiet True defaultParams) m
mbFn <- getLoadPathForModule m >>=
lookupFileInPath (abstractCurryFileName m) [""]
case mbFn of
Nothing -> cancel $ "AbstractCurry module '" ++ m ++ "' not found"
Just fn -> do
ctime <- getModificationTime srcFile
ftime <- getModificationTime fn
if ctime > ftime
then cancel $ "Source file '" ++ srcFile
++ "' is newer than AbstractCurry file '" ++ fn ++ "'"
else do
mbProg <- tryParse fn
case mbProg of
Left err -> cancel err
Right p -> return (Right p)
where cancel str = return (Left str)
--- Try to parse an AbstractCurry file.
--- @param fn - file name of AbstractCurry file
tryParse :: String -> IO (Either String CurryProg)
tryParse fn = do
exists <- doesFileExist fn
if not exists
then cancel $ "AbstractCurry file '" ++ fn ++ "' does not exist"
else do
src <- readFile fn
let (line1, lines) = break (=='\n') src
if line1 /= "{- "++version++" -}"
then cancel $ "Could not parse AbstractCurry file '" ++ fn
++ "': incompatible versions"
else case readsUnqualifiedTerm ["AbstractCurry.Types","Prelude"] lines of
[(p,tl)] | all isSpace tl -> return (Right p)
_ -> cancel $ "Could not parse AbstractCurry file '" ++ fn
++ "': no parse"
where cancel str = return (Left str)
--- I/O action which parses a Curry program and returns the corresponding
--- untyped AbstractCurry program.
--- The argument is the file name without suffix ".curry"
--- or ".lcurry") and the result is a Curry term representing this
--- program.
--- In an untyped AbstractCurry program, the type signatures
--- of operations are the type signatures provided by the programmer
--- (and not the type signatures inferred by the front end).
--- If the programmer has not provided an explicit type signature,
--- the function declaration contains the type `(CTCons ("Prelude","untyped")`.
readUntypedCurry :: String -> IO CurryProg
readUntypedCurry prog =
readUntypedCurryWithParseOptions prog (setQuiet True defaultParams)
--- I/O action which reads a typed Curry program from a file (with extension
--- ".acy") with respect to some parser options.
--- This I/O action is used by the standard action 'readCurry'.
--- It is currently predefined only in Curry2Prolog.
--- @param progfile - the program file name (without suffix ".curry")
--- @param options - parameters passed to the front end
readCurryWithParseOptions :: String -> FrontendParams -> IO CurryProg
readCurryWithParseOptions progname options = do
let modname = takeFileName progname
mbsrc <- lookupModuleSourceInLoadPath progname
case mbsrc of
Nothing -> do -- no source file, try to find AbstractCurry file in load path:
loadpath <- getLoadPathForModule progname
filename <- getFileInPath (abstractCurryFileName modname) [""] loadpath
readAbstractCurryFile filename
Just (dir,_) -> do
callFrontendWithParams ACY options progname
readAbstractCurryFile (abstractCurryFileName (dir </> modname))
--- I/O action which reads an untyped Curry program from a file (with extension
--- ".uacy") with respect to some parser options. For more details
--- see function 'readCurryWithParseOptions'
--- In an untyped AbstractCurry program, the type signatures
--- of operations are the type signatures provided by the programmer
--- (and not the type signatures inferred by the front end).
--- If the programmer has not provided an explicit type signature,
--- the function declaration contains the type `(CTCons ("Prelude","untyped")`.
readUntypedCurryWithParseOptions :: String -> FrontendParams -> IO CurryProg
readUntypedCurryWithParseOptions progname options = do
let modname = takeFileName progname
mbsrc <- lookupModuleSourceInLoadPath progname
case mbsrc of
Nothing -> do -- no source file, try to find AbstractCurry file in load path:
loadpath <- getLoadPathForModule progname
filename <- getFileInPath (untypedAbstractCurryFileName modname) [""]
loadpath
readAbstractCurryFile filename
Just (dir,_) -> do
callFrontendWithParams UACY options progname
readAbstractCurryFile (untypedAbstractCurryFileName (dir </> modname))
--- Transforms a name of a Curry program (with or without suffix ".curry"
--- or ".lcurry") into the name of the file containing the
--- corresponding AbstractCurry program.
abstractCurryFileName :: String -> String
abstractCurryFileName prog = inCurrySubdir (stripCurrySuffix prog) <.> "acy"
--- Transforms a name of a Curry program (with or without suffix ".curry"
--- or ".lcurry") into the name of the file containing the
--- corresponding untyped AbstractCurry program.
untypedAbstractCurryFileName :: String -> String
untypedAbstractCurryFileName prog =
inCurrySubdir (stripCurrySuffix prog) <.> "uacy"
--- I/O action which reads an AbstractCurry program from a file in ".acy"
--- format. In contrast to <CODE>readCurry</CODE>, this action does not parse
--- a source program. Thus, the argument must be the name of an existing
--- file (with suffix ".acy") containing an AbstractCurry program in ".acy"
--- format and the result is a Curry term representing this program.
--- It is currently predefined only in Curry2Prolog.
readAbstractCurryFile :: String -> IO CurryProg
readAbstractCurryFile filename = do
exacy <- doesFileExist filename
if exacy
then readExistingACY filename
else do let subdirfilename = inCurrySubdir filename
exdiracy <- doesFileExist subdirfilename
if exdiracy
then readExistingACY subdirfilename
else error ("EXISTENCE ERROR: AbstractCurry file '"++filename++
"' does not exist")
where
readExistingACY fname = do
filecontents <- readFile fname
let (line1,lines) = break (=='\n') filecontents
if line1 == "{- "++version++" -}"
then return (readUnqualifiedTerm ["AbstractCurry.Types","Prelude"] lines)
else error $ "AbstractCurry: incompatible file found: "++fname
--- Tries to read an AbstractCurry file and returns
---
--- * Left err , where err specifies the error occurred
--- * Right prog, where prog is the AbstractCurry program
tryReadACYFile :: String -> IO (Maybe CurryProg)
tryReadACYFile fn = do
exists <- doesFileExist fn
if exists
then tryRead fn
else do
let fn' = inCurrySubdir fn
exists' <- doesFileExist fn'
if exists'
then tryRead fn'
else cancel
where
tryRead file = do
src <- readFile file
let (line1,lines) = break (=='\n') src
if line1 /= "{- "++version++" -}"
then error $ "AbstractCurry: incompatible file found: "++fn
else case readsUnqualifiedTerm ["AbstractCurry.Types","Prelude"] lines of
[] -> cancel
[(p,tl)] -> if all isSpace tl
then return $ Just p
else cancel
_ -> cancel
cancel = return Nothing
--- Writes an AbstractCurry program into a file in ".acy" format.
--- The first argument must be the name of the target file
--- (with suffix ".acy").
writeAbstractCurryFile :: String -> CurryProg -> IO ()
writeAbstractCurryFile file prog = writeFile file (showTerm prog)
------------------------------------------------------------------------------
This diff is collapsed.
------------------------------------------------------------------------
--- This library provides some useful operations to select components
--- in AbstractCurry programs, i.e., it provides a collection of
--- selector functions for AbstractCurry.
---
--- @version May 2016
--- @category meta
------------------------------------------------------------------------
module AbstractCurry.Select
( progName, imports, functions, constructors, types, publicFuncNames
, publicConsNames, publicTypeNames
, typeName, typeVis, typeCons
, consName, consVis
, isBaseType, isPolyType, isFunctionalType, isIOType, isIOReturnType
, argTypes, resultType, tvarsOfType, tconsOfType, modsOfType
, funcName, funcArity, funcComment, funcVis, funcType, funcRules
, ruleRHS, ldeclsOfRule
, varsOfPat, varsOfExp, varsOfRhs, varsOfStat, varsOfLDecl
, varsOfFDecl, varsOfRule
, funcNamesOfLDecl, funcNamesOfFDecl, funcNamesOfStat
, isPrelude
) where
import AbstractCurry.Types
import List(union)
------------------------------------------------------------------------
-- Selectors for curry programs
-- Returns the name of a given Curry program.
progName :: CurryProg -> String
progName (CurryProg modname _ _ _ _) = modname
--- Returns the imports (module names) of a given Curry program.
imports :: CurryProg -> [MName]
imports (CurryProg _ ms _ _ _) = ms
--- Returns the function declarations of a given Curry program.
functions :: CurryProg -> [CFuncDecl]
functions (CurryProg _ _ _ fs _) = fs
--- Returns all constructors of given Curry program.
constructors :: CurryProg -> [CConsDecl]
constructors = concatMap typeCons . types
--- Returns the type declarations of a given Curry program.
types :: CurryProg -> [CTypeDecl]
types (CurryProg _ _ ts _ _) = ts
--- Returns the names of all visible functions in given Curry program.
publicFuncNames :: CurryProg -> [QName]
publicFuncNames = map funcName . filter ((== Public) . funcVis) . functions
--- Returns the names of all visible constructors in given Curry program.
publicConsNames :: CurryProg -> [QName]
publicConsNames = map consName