curry-frontend 0.2 → 0.2.1
raw patch · 81 files changed
+8225/−9440 lines, 81 files
Files
- curry-frontend.cabal +28/−14
- src/AbstractCurry.hs +0/−282
- src/Arity.hs +4/−3
- src/Base.lhs +40/−369
- src/CaseCompletion.hs +24/−23
- src/Combined.lhs +0/−166
- src/CompilerResults.hs +0/−24
- src/Curry/AbstractCurry.hs +282/−0
- src/Curry/Base/Ident.lhs +352/−0
- src/Curry/Base/MessageMonad.hs +83/−0
- src/Curry/Base/Position.lhs +96/−0
- src/Curry/ExtendedFlat.hs +475/−0
- src/Curry/Syntax.hs +36/−0
- src/Curry/Syntax/LLParseComb.lhs +290/−0
- src/Curry/Syntax/LexComb.lhs +104/−0
- src/Curry/Syntax/Lexer.lhs +630/−0
- src/Curry/Syntax/Parser.lhs +806/−0
- src/Curry/Syntax/Pretty.lhs +367/−0
- src/Curry/Syntax/ShowModule.hs +499/−0
- src/Curry/Syntax/Type.lhs +315/−0
- src/Curry/Syntax/Unlit.hs +57/−0
- src/Curry/Syntax/Utils.hs +202/−0
- src/CurryBuilder.hs +8/−9
- src/CurryDeps.lhs +42/−298
- src/CurryEnv.hs +11/−21
- src/CurryHtml.hs +46/−15
- src/CurryLexer.lhs +0/−630
- src/CurryPP.lhs +0/−369
- src/CurryParser.lhs +0/−818
- src/CurrySyntax.lhs +0/−323
- src/Desugar.lhs +40/−114
- src/Env.lhs +0/−55
- src/Error.lhs +0/−35
- src/Eval.lhs +8/−8
- src/Exports.lhs +15/−12
- src/ExtendedFlat.hs +0/−517
- src/Frontend.hs +62/−127
- src/GenAbstractCurry.hs +84/−152
- src/GenFlatCurry.hs +103/−153
- src/IL.lhs +0/−108
- src/IL/CurryToIL.lhs +598/−0
- src/IL/Pretty.lhs +167/−0
- src/IL/Scope.hs +124/−0
- src/IL/Type.lhs +109/−0
- src/IL/XML.lhs +518/−0
- src/ILPP.lhs +0/−166
- src/ILScope.hs +0/−124
- src/ILTrans.lhs +0/−595
- src/ILxml.lhs +0/−518
- src/Ident.lhs +0/−415
- src/Imports.lhs +29/−31
- src/InterfaceCheck.hs +1/−1
- src/KindCheck.lhs +10/−13
- src/LLParseComb.lhs +0/−292
- src/LexComb.lhs +0/−102
- src/Lift.lhs +20/−31
- src/Message.hs +0/−74
- src/Modules.lhs +141/−243
- src/NestEnv.lhs +14/−10
- src/OldScopeEnv.hs +10/−15
- src/PatchPrelude.hs +1/−1
- src/PathUtils.hs +30/−3
- src/Position.lhs +0/−94
- src/PrecCheck.lhs +11/−12
- src/Pretty.lhs +0/−905
- src/PrettyCombinators.lhs +905/−0
- src/Qual.lhs +5/−6
- src/ScopeEnv.hs +21/−21
- src/ShowCurrySyntax.hs +0/−493
- src/Simplify.lhs +35/−26
- src/SyntaxCheck.lhs +26/−60
- src/SyntaxColoring.hs +98/−171
- src/TopEnv.lhs +17/−17
- src/TypeCheck.lhs +74/−90
- src/TypeSubst.lhs +2/−0
- src/Types.lhs +38/−4
- src/Typing.lhs +12/−8
- src/Unlit.lhs +0/−110
- src/Utils.lhs +5/−11
- src/WarnCheck.hs +91/−129
- src/cymake.hs +4/−4
curry-frontend.cabal view
@@ -1,5 +1,5 @@ Name: curry-frontend-Version: 0.2+Version: 0.2.1 Cabal-Version: >= 1.6 Synopsis: Compile the functional logic language Curry to several intermediate formats Description: The Curry Frontend consists of the executable program "cymake".@@ -26,20 +26,34 @@ hs-source-dirs: src Main-is: cymake.hs Build-Depends: base >= 3 && < 4, mtl, old-time, directory, filepath, containers- Other-Modules: AbstractCurry, CurryBuilder, Env, IL, Message- CurryCompilerOpts, Error, Modules, Subst, Arity- CurryDeps, Eval, ILPP, NestEnv, SyntaxCheck, Base- Exports, ILScope, SyntaxColoring, CurryEnv- ExtendedFlat, ILTrans, OldScopeEnv, CurryHtml- ILxml, PatchPrelude, TopEnv, CaseCompletion- CurryLexer, Imports, PathUtils, TypeCheck- CurryParser, InterfaceCheck, Position- Types, CurryPP, Frontend, PrecCheck+ ghc-options: -fwarn-unused-binds -fwarn-unused-imports+-- -fwarn-incomplete-patterns+ Other-Modules: Curry.Base.Position, Curry.Base.Ident, Curry.Base.MessageMonad+ Curry.Syntax.Lexer, Curry.Syntax.LexComb+ Curry.Syntax.Parser, Curry.Syntax.LLParseComb+ Curry.Syntax.ShowModule, Curry.Syntax.Pretty+ Curry.Syntax, Curry.Syntax.Type+ Curry.Syntax.Unlit, Curry.Syntax.Utils+ Curry.AbstractCurry, Curry.ExtendedFlat+ CurryBuilder, IL.Type + CurryCompilerOpts, Modules, Subst, Arity+ CurryDeps, Eval, IL.Pretty, NestEnv, SyntaxCheck, Base+ Exports, IL.Scope, SyntaxColoring, CurryEnv+ IL.CurryToIL, OldScopeEnv, CurryHtml+ IL.XML, PatchPrelude, TopEnv, CaseCompletion+ Imports, PathUtils, TypeCheck+ InterfaceCheck, + Types, Frontend, PrecCheck TypeSubst, GenAbstractCurry- Pretty, Typing, Combined, CurrySyntax- GenFlatCurry, KindCheck, Qual, Unlit, CompilerResults- LexComb, SCC, Utils, GetOpt+ PrettyCombinators, Typing+ GenFlatCurry, KindCheck, Qual+ SCC, Utils, GetOpt Lift, ScopeEnv, WarnCheck- LLParseComb, Desugar, Ident, ShowCurrySyntax+ Desugar, Curry.Base.Ident, Simplify++-- Executable pretty-ecy+-- hs-source-dirs: src+-- Main-is: pretty-ecy.hs+-- Build-Depends: base >= 3 && < 4
− src/AbstractCurry.hs
@@ -1,282 +0,0 @@----------------------------------------------------------------------------------- Library to support meta-programming in Curry.-------- This library contains a definition for representing Curry programs---- in Curry (type "CurryProg") and an I/O action to read Curry programs and---- transform them into this abstract representation (function "readCurry").-------- Note this defines a slightly new format for AbstractCurry---- in comparison to the first proposal of 2003.-------- Assumption: an abstract Curry program is stored in file prog.acy---- and translated with the parser by "parsecurry -acy prog".-------- @author Michael Hanus---- @version April 2004-------- Version for Haskell (slightly modified):---- July 2005, Martin Engelke (men@informatik.uni-kiel.de)-------------------------------------------------------------------------------------module AbstractCurry (CurryProg(..), QName, CLabel, CVisibility(..),- CTVarIName, CTypeDecl(..), CConsDecl(..), CTypeExpr(..),- COpDecl(..), CFixity(..), CVarIName,- CFuncDecl(..), CRules(..), CEvalAnnot(..),- CRule(..), CLocalDecl(..), CExpr(..), CStatement(..),- CPattern(..), CBranchExpr(..), CLiteral(..),- CField,- readCurry, writeCurry) where--import Data.List(intersperse)--import PathUtils (writeModule,readModule)------------------------------------------------------------------------------------ Definition of data types for representing abstract Curry programs:--- ==================================================================----- Data type for representing a Curry module in the intermediate form.---- A value of this data type has the form---- <CODE>---- (CProg modname imports typedecls functions opdecls)---- </CODE>---- where modname: name of this module,---- imports: list of modules names that are imported,---- typedecls, opdecls, functions: see below--data CurryProg = CurryProg String [String] [CTypeDecl] [CFuncDecl] [COpDecl]- deriving (Read, Show)----- The data type for representing qualified names.---- In AbstractCurry all names are qualified to avoid name clashes.---- The first component is the module name and the second component the---- unqualified name as it occurs in the source program.-type QName = (String,String)----- Type for representing label identifiers-type CLabel = String---- Data type to specify the visibility of various entities.--data CVisibility = Public -- exported entity- | Private -- private entity- deriving (Read, Show, Eq)------ The data type for representing type variables.---- They are represented by (i,n) where i is a type variable index---- which is unique inside a function and n is a name (if possible,---- the name written in the source program).-type CTVarIName = (Int,String)----- Data type for representing definitions of algebraic data types---- and type synonyms.---- <PRE>---- A data type definition of the form-------- data t x1...xn = ...| c t1....tkc |...-------- is represented by the Curry term-------- (CType t v [i1,...,in] [...(CCons c kc v [t1,...,tkc])...])-------- where each ij is the index of the type variable xj-------- Note: the type variable indices are unique inside each type declaration---- and are usually numbered from 0-------- Thus, a data type declaration consists of the name of the data type,---- a list of type parameters and a list of constructor declarations.---- </PRE>--data CTypeDecl = CType QName CVisibility [CTVarIName] [CConsDecl]- | CTypeSyn QName CVisibility [CTVarIName] CTypeExpr- deriving (Read, Show)------ A constructor declaration consists of the name and arity of the---- constructor and a list of the argument types of the constructor.--data CConsDecl = CCons QName Int CVisibility [CTypeExpr]- deriving (Read, Show)------ Data type for type expressions.---- A type expression is either a type variable, a function type,---- or a type constructor application.-------- Note: the names of the predefined type constructors are---- "Int", "Float", "Bool", "Char", "IO", "Success",---- "()" (unit type), "(,...,)" (tuple types), "[]" (list type)--data CTypeExpr =- CTVar CTVarIName -- type variable- | CFuncType CTypeExpr CTypeExpr -- function type t1->t2- | CTCons QName [CTypeExpr] -- type constructor application- | CRecordType [CField CTypeExpr] -- record type (extended Curry)- (Maybe CTVarIName)- deriving (Read, Show) ------ Data type for operator declarations.---- An operator declaration "fix p n" in Curry corresponds to the---- AbstractCurry term (COp n fix p).--data COpDecl = COp QName CFixity Integer deriving (Read, Show)--data CFixity = CInfixOp -- non-associative infix operator- | CInfixlOp -- left-associative infix operator- | CInfixrOp -- right-associative infix operator- deriving (Read, Show, Eq)------ Data types for representing object variables.---- Object variables occurring in expressions are represented by (Var i)---- where i is a variable index.--type CVarIName = (Int,String)------ Data type for representing function declarations.---- <PRE>---- A function declaration in FlatCurry is a term of the form-------- (CFunc name arity visibility type (CRules eval [CRule rule1,...,rulek]))-------- and represents the function "name" with definition-------- name :: type---- rule1---- ...---- rulek-------- Note: the variable indices are unique inside each rule-------- External functions are represented as (CFunc name arity type (CExternal s))---- where s is the external name associated to this function.-------- Thus, a function declaration consists of the name, arity, type, and---- a list of rules.---- </PRE>--data CFuncDecl = CFunc QName Int CVisibility CTypeExpr CRules- deriving (Read, Show)------ A rule is either a list of formal parameters together with an expression---- (i.e., a rule in flat form), a list of general program rules with---- an evaluation annotation, or it is externally defined--data CRules = CRules CEvalAnnot [CRule]- | CExternal String- deriving (Read, Show)----- Data type for classifying evaluation annotations for functions.---- They can be either flexible (default), rigid, or choice.--data CEvalAnnot = CFlex | CRigid | CChoice deriving (Read, Show, Eq)----- The most general form of a rule. It consists of a list of patterns---- (left-hand side), a list of guards ("success" if not present in the---- source text) with their corresponding right-hand sides, and---- a list of local declarations.-data CRule = CRule [CPattern] [(CExpr,CExpr)] [CLocalDecl]- deriving (Read, Show)----- Data type for representing local (let/where) declarations-data CLocalDecl =- CLocalFunc CFuncDecl -- local function declaration- | CLocalPat CPattern CExpr [CLocalDecl] -- local pattern declaration- | CLocalVar CVarIName -- local free variable declaration- deriving (Read, Show)----- Data type for representing Curry expressions.--data CExpr =- CVar CVarIName -- variable (unique index / name)- | CLit CLiteral -- literal (Integer/Float/Char constant)- | CSymbol QName -- a defined symbol with module and name- | CApply CExpr CExpr -- application (e1 e2)- | CLambda [CPattern] CExpr -- lambda abstraction- | CLetDecl [CLocalDecl] CExpr -- local let declarations- | CDoExpr [CStatement] -- do expression- | CListComp CExpr [CStatement] -- list comprehension- | CCase CExpr [CBranchExpr] -- case expression- | CRecConstr [CField CExpr] -- record construction (extended Curry)- | CRecSelect CExpr CLabel -- field selection (extended Curry)- | CRecUpdate [CField CExpr] CExpr -- record update (extended Curry)- deriving (Read, Show)----- Data type for representing statements in do expressions and---- list comprehensions.--data CStatement = CSExpr CExpr -- an expression (I/O action or boolean)- | CSPat CPattern CExpr -- a pattern definition- | CSLet [CLocalDecl] -- a local let declaration- deriving (Read, Show)----- Data type for representing pattern expressions.--data CPattern =- CPVar CVarIName -- pattern variable (unique index / name)- | CPLit CLiteral -- literal (Integer/Float/Char constant)- | CPComb QName [CPattern] -- application (m.c e1 ... en) of n-ary- -- constructor m.c (CPComb (m,c) [e1,...,en])- | CPAs CVarIName CPattern -- as-pattern (extended Curry)- | CPFuncComb QName [CPattern] -- function pattern (extended Curry)- | CPLazy CPattern -- lazy pattern (extended Curry) - | CPRecord [CField CPattern] -- record pattern (extended curry)- (Maybe CPattern)- deriving (Read, Show) ----- Data type for representing branches in case expressions.--data CBranchExpr = CBranch CPattern CExpr deriving (Read, Show)----- Data type for representing literals occurring in an expression.---- It is either an integer, a float, or a character constant.---- Note: the constructor definition of 'CIntc' differs from the original---- PAKCS definition. It uses Haskell type 'Integer' instead of 'Int'---- to provide an unlimited range of integer numbers. Furthermore---- float values are represented with Haskell type 'Double' instead of---- 'Float'.--data CLiteral = CIntc Integer- | CFloatc Double- | CCharc Char- deriving (Read, Show, Eq)----- Type for representing labeled fields--type CField a = (CLabel,a)------------------------------------------------------------------------------------------------------------------------------------------------------------------- Reads an AbstractCurry file and returns the corresponding AbstractCurry--- program term (type 'CurryProg')-readCurry :: String -> IO CurryProg-readCurry filename- = do file <- readModule filename- let prog = (read file) :: CurryProg- return prog---- Writes an AbstractCurry program term into a file-writeCurry :: String -> CurryProg -> IO ()-writeCurry filename prog - = catch (writeModule filename (showCurry prog)) (\e -> ioError e)---- Shows an AbstractCurry program in a more nicely way.-showCurry :: CurryProg -> String-showCurry (CurryProg mname imps types funcs ops) =- "CurryProg "++show mname++"\n "++- show imps ++"\n ["++- concat (intersperse ",\n " (map (\t->show t) types)) ++"]\n ["++- concat (intersperse ",\n " (map (\f->show f) funcs)) ++"]\n "++- show ops ++"\n"- ---------------------------------------------------------------------------------------------------------------------------------------------------------------
src/Arity.hs view
@@ -9,9 +9,10 @@ -- module Arity (bindArities) where -import Base-import CurrySyntax-import Ident+import Curry.Base.Ident+import Curry.Syntax++import Base(ArityEnv, bindArity) -------------------------------------------------------------------------------
src/Base.lhs view
@@ -7,34 +7,30 @@ % \nwfilename{Base.lhs} \section{Common Definitions for the Compiler}-The module \texttt{Base} provides common definitions for the various -phases of the compiler.++The module \texttt{Base} implements the anti-pattern 'God-object'.+By providing common definitions for the various phases of the+compiler, it irrevocably turns the module structure into spaghetti.+(hsi)+ \begin{verbatim} -> module Base(module Base,module Ident,module Position,module Types,-> module CurrySyntax) where+> module Base where > import Data.List > import Control.Monad > import Data.Maybe-> import qualified Data.Set as Set > import qualified Data.Map as Map -> import Ident -> import Position+> import Curry.Base.Ident +> import Curry.Base.Position > import Types-> import CurrySyntax-> import CurryPP-> import Pretty-> import ExtendedFlat hiding (SrcRef, Fixity(..), TypeExpr, Expr(..))-> import Env+> import Curry.Syntax+> import Curry.Syntax.Utils > import TopEnv-- > import Utils -> import qualified ExtendedFlat as EF \end{verbatim} \paragraph{Types}@@ -52,10 +48,10 @@ \begin{verbatim} > toQualType :: ModuleIdent -> [Ident] -> TypeExpr -> Type-> toQualType m tvs ty = qualifyType m (toType tvs ty)+> toQualType m tvs = qualifyType m . toType tvs > toQualTypes :: ModuleIdent -> [Ident] -> [TypeExpr] -> [Type]-> toQualTypes m tvs tys = map (qualifyType m) (toTypes tvs tys)+> toQualTypes m tvs = map (qualifyType m) . toTypes tvs > toType :: [Ident] -> TypeExpr -> Type > toType tvs ty = toType' (Map.fromList (zip (tvs ++ tvs') [0..])) ty@@ -85,26 +81,8 @@ > _ -> internalError ("toType " ++ show ty)) > rty) -> qualifyType :: ModuleIdent -> Type -> Type-> qualifyType m (TypeConstructor tc tys)-> | isTupleId tc' = tupleType tys'-> | tc' == unitId && n == 0 = unitType-> | tc' == listId && n == 1 = listType (head tys')-> | otherwise = TypeConstructor (qualQualify m tc) tys'-> where n = length tys'-> tc' = unqualify tc-> tys' = map (qualifyType m) tys-> qualifyType _ (TypeVariable tv) = TypeVariable tv-> qualifyType m (TypeConstrained tys tv) =-> TypeConstrained (map (qualifyType m) tys) tv-> qualifyType m (TypeArrow ty1 ty2) =-> TypeArrow (qualifyType m ty1) (qualifyType m ty2)-> qualifyType _ (TypeSkolem k) = TypeSkolem k-> qualifyType m (TypeRecord fs rty) =-> TypeRecord (map (\ (l,ty) -> (l, qualifyType m ty)) fs) rty- > fromQualType :: ModuleIdent -> Type -> TypeExpr-> fromQualType m ty = fromType (unqualifyType m ty)+> fromQualType m = fromType . unqualifyType m > fromType :: Type -> TypeExpr > fromType (TypeConstructor tc tys)@@ -113,7 +91,7 @@ > | c == unitId && null tys = TupleType [] > | otherwise = ConstructorType tc tys' > where c = unqualify tc-> tys' = map (fromType) tys+> tys' = map fromType tys > fromType (TypeVariable tv) = > VariableType (if tv >= 0 then nameSupply !! tv > else mkIdent ('_' : show (-tv)))@@ -124,28 +102,8 @@ > RecordType (map (\ (l,ty) -> ([l], fromType ty)) fs) > (maybe Nothing (Just . fromType . TypeVariable) rty) -> unqualifyType :: ModuleIdent -> Type -> Type-> unqualifyType m (TypeConstructor tc tys) =-> TypeConstructor (qualUnqualify m tc) (map (unqualifyType m) tys)-> unqualifyType _ (TypeVariable tv) = TypeVariable tv-> unqualifyType m (TypeConstrained tys tv) =-> TypeConstrained (map (unqualifyType m) tys) tv-> unqualifyType m (TypeArrow ty1 ty2) =-> TypeArrow (unqualifyType m ty1) (unqualifyType m ty2)-> unqualifyType m (TypeSkolem k) = TypeSkolem k-> unqualifyType m (TypeRecord fs rty) =-> TypeRecord (map (\ (l,ty) -> (l, unqualifyType m ty)) fs) rty -\end{verbatim}-The following functions implement pretty-printing for types.-\begin{verbatim} -> ppType :: ModuleIdent -> Type -> Doc-> ppType m = ppTypeExpr 0 . fromQualType m--> ppTypeScheme :: ModuleIdent -> TypeScheme -> Doc-> ppTypeScheme m (ForAll _ ty) = ppType m ty- \end{verbatim} \paragraph{Interfaces} The compiler maintains a global environment holding all (directly or@@ -158,85 +116,10 @@ for PAKCS. \begin{verbatim} -> type ModuleEnv = Env ModuleIdent [IDecl]--> bindModule :: Interface -> ModuleEnv -> ModuleEnv-> bindModule (Interface m ds) = bindEnv m ds--> bindFlatInterface :: Prog -> ModuleEnv -> ModuleEnv-> bindFlatInterface (Prog m imps ts fs os)-> = bindModule (Interface (mkMIdent [m])-> ((map genIImportDecl imps)-> ++ (map genITypeDecl ts')-> ++ (map genIFuncDecl fs)-> ++ (map genIOpDecl os)))-> where-> genIImportDecl :: String -> IDecl-> genIImportDecl imp = IImportDecl pos (mkMIdent [imp])->-> genITypeDecl :: TypeDecl -> IDecl-> genITypeDecl (Type qn _ is cs)-> | recordExt `isPrefixOf` localName qn-> = ITypeDecl pos-> (genQualIdent qn)-> (map (genVarIndexIdent "a") is)-> (RecordType (map genLabeledType cs) Nothing)-> | otherwise-> = IDataDecl pos -> (genQualIdent qn) -> (map (genVarIndexIdent "a") is) -> (map (Just . genConstrDecl) cs)-> genITypeDecl (TypeSyn qn _ is t)-> = ITypeDecl pos-> (genQualIdent qn)-> (map (genVarIndexIdent "a") is)-> (genTypeExpr t)->-> genIFuncDecl :: FuncDecl -> IDecl-> genIFuncDecl (Func qn a _ t _) -> = IFunctionDecl pos (genQualIdent qn) a (genTypeExpr t)->-> genIOpDecl :: OpDecl -> IDecl-> genIOpDecl (Op qn f p) = IInfixDecl pos (genInfix f) p (genQualIdent qn)->-> genConstrDecl :: ConsDecl -> ConstrDecl-> genConstrDecl (Cons qn _ _ ts)-> = ConstrDecl pos [] (mkIdent (localName qn)) (map genTypeExpr ts)->-> genLabeledType :: EF.ConsDecl -> ([Ident],CurrySyntax.TypeExpr)-> genLabeledType (Cons qn _ _ [t])-> = ([renameLabel (fromLabelExtId (mkIdent $ localName qn))], genTypeExpr t)->-> genTypeExpr :: EF.TypeExpr -> CurrySyntax.TypeExpr-> genTypeExpr (TVar i)-> = VariableType (genVarIndexIdent "a" i)-> genTypeExpr (FuncType t1 t2) -> = ArrowType (genTypeExpr t1) (genTypeExpr t2)-> genTypeExpr (TCons qn ts) -> = ConstructorType (genQualIdent qn) (map genTypeExpr ts)->-> genInfix :: EF.Fixity -> Infix-> genInfix EF.InfixOp = Infix-> genInfix EF.InfixlOp = InfixL-> genInfix EF.InfixrOp = InfixR->-> genQualIdent :: QName -> QualIdent-> genQualIdent QName{modName=mod,localName=name} = -> qualifyWith (mkMIdent [mod]) (mkIdent name)->-> genVarIndexIdent :: String -> Int -> Ident-> genVarIndexIdent v i = mkIdent (v ++ show i)->-> isSpecialPreludeType :: TypeDecl -> Bool-> isSpecialPreludeType (Type QName{modName=mod,localName=name} _ _ _) -> = (name == "[]" || name == "()") && mod == "Prelude"-> isSpecialPreludeType _ = False->-> pos = first m-> ts' = filter (not . isSpecialPreludeType) ts+> type ModuleEnv = Map.Map ModuleIdent [IDecl] > lookupModule :: ModuleIdent -> ModuleEnv -> Maybe [IDecl]-> lookupModule = lookupEnv+> lookupModule = Map.lookup \end{verbatim} The label environment is used to store information of labels.@@ -249,19 +132,19 @@ > data LabelInfo = LabelType Ident QualIdent Type deriving Show -> type LabelEnv = Env Ident [LabelInfo]+> type LabelEnv = Map.Map Ident [LabelInfo] > bindLabelType :: Ident -> QualIdent -> Type -> LabelEnv -> LabelEnv > bindLabelType l r ty lEnv =-> maybe (bindEnv l [LabelType l r ty] lEnv)-> (\ls -> bindEnv l ((LabelType l r ty):ls) lEnv)-> (lookupEnv l lEnv)+> maybe (Map.insert l [LabelType l r ty] lEnv)+> (\ls -> Map.insert l (LabelType l r ty:ls) lEnv)+> (Map.lookup l lEnv) > lookupLabelType :: Ident -> LabelEnv -> [LabelInfo]-> lookupLabelType l lEnv = fromMaybe [] (lookupEnv l lEnv)+> lookupLabelType = Map.findWithDefault [] > initLabelEnv :: LabelEnv-> initLabelEnv = emptyEnv+> initLabelEnv = Map.empty \end{verbatim}@@ -448,10 +331,10 @@ > qualLookupCons :: QualIdent -> ValueEnv -> [ValueInfo] > qualLookupCons x tyEnv-> | (maybe False ((==) preludeMIdent) mmid) && (id == consId)+> | maybe False ((==) preludeMIdent) mmid && id == consId > = qualLookupTopEnv (qualify id) tyEnv > | otherwise = []-> where (mmid, id) = splitQualIdent x+> where (mmid, id) = (qualidMod x, qualidId x) > lookupTuple :: Ident -> [ValueInfo] > lookupTuple c@@ -502,11 +385,11 @@ > qualLookupConsArity :: QualIdent -> ArityEnv -> [ArityInfo] > qualLookupConsArity qid aEnv-> | (maybe False ((==) preludeMIdent) mmid) && (id == consId)+> | maybe False ((==) preludeMIdent) mmid && id == consId > = qualLookupTopEnv (qualify id) aEnv > | otherwise > = []-> where (mmid, id) = splitQualIdent qid+> where (mmid, id) = (qualidMod qid, qualidId qid) > lookupTupleArity :: Ident -> [ArityInfo] > lookupTupleArity id @@ -519,17 +402,17 @@ \paragraph{Module alias} \begin{verbatim} -> type ImportEnv = Env ModuleIdent ModuleIdent+> type ImportEnv = Map.Map ModuleIdent ModuleIdent > bindAlias :: Decl -> ImportEnv -> ImportEnv-> bindAlias (ImportDecl _ mid _ mmid _) iEnv-> = bindEnv mid (fromMaybe mid mmid) iEnv+> bindAlias (ImportDecl _ mid _ mmid _)+> = Map.insert mid (fromMaybe mid mmid) > lookupAlias :: ModuleIdent -> ImportEnv -> Maybe ModuleIdent-> lookupAlias = lookupEnv+> lookupAlias = Map.lookup > sureLookupAlias :: ModuleIdent -> ImportEnv -> ModuleIdent-> sureLookupAlias m iEnv = fromMaybe m (lookupAlias m iEnv)+> sureLookupAlias m = fromMaybe m . lookupAlias m \end{verbatim}@@ -595,14 +478,9 @@ sufficient. \begin{verbatim} -> type EvalEnv = Env Ident EvalAnnotation+> type EvalEnv = Map.Map Ident EvalAnnotation -> bindEval :: Ident -> EvalAnnotation -> EvalEnv -> EvalEnv-> bindEval = bindEnv -> lookupEval :: Ident -> EvalEnv -> Maybe EvalAnnotation-> lookupEval f evEnv = lookupEnv f evEnv- \end{verbatim} \paragraph{Predefined types} The list and unit data types must be predefined because their@@ -627,18 +505,16 @@ > initTCEnv :: TCEnv > initTCEnv = foldr (uncurry predefTC) emptyTopEnv predefTypes-> where a = typeVar 0-> predefTC (TypeConstructor tc tys) cs =-> predefTopEnv (qualify (unqualify tc))-> (DataType tc (length tys) (map Just cs))+> where predefTC (TypeConstructor tc tys) =+> predefTopEnv (qualify (unqualify tc)) .+> DataType tc (length tys) . map Just > initDCEnv :: ValueEnv > initDCEnv = > foldr (uncurry predefDC) emptyTopEnv > [(c,constrType (polyType ty) n' tys) > | (ty,cs) <- predefTypes, Data c n' tys <- cs]-> where primTypes = map snd (moduleImports preludeMIdent initTCEnv)-> predefDC c ty = predefTopEnv c' (DataConstructor c' ty)+> where predefDC c ty = predefTopEnv c' (DataConstructor c' ty) > where c' = qualify c > constrType (ForAll n ty) n' = ForAllExist n n' . foldr TypeArrow ty @@ -646,11 +522,11 @@ > initAEnv > = foldr bindPredefArity emptyTopEnv (concatMap snd predefTypes) > where-> bindPredefArity (Data id _ ts) aEnv-> = bindArity preludeMIdent id (length ts) aEnv+> bindPredefArity (Data id _ ts)+> = bindArity preludeMIdent id (length ts) > initIEnv :: ImportEnv-> initIEnv = emptyEnv+> initIEnv = Map.empty > predefTypes :: [(Type,[Data [Type]])] > predefTypes =@@ -661,200 +537,7 @@ \end{verbatim}-\paragraph{Free and bound variables}-The compiler needs to compute the sets of free and bound variables for-various different entities. We will devote three type classes to that-purpose. The \texttt{QualExpr} class is expected to take into account-that it is possible to use a qualified name to refer to a function-defined in the current module and therefore \emph{M.x} and $x$, where-$M$ is the current module name, should be considered the same name.-However note that this is correct only after renaming all local-definitions as \emph{M.x} always denotes an entity defined at the-top-level. -The \texttt{Decl} instance of \texttt{QualExpr} returns all free-variables on the right hand side, regardless of whether they are bound-on the left hand side. This is more convenient as declarations are-usually processed in a declaration group where the set of free-variables cannot be computed independently for each declaration. Also-note that the operator in a unary minus expression is not a free-variable. This operator always refers to a global function from the-prelude.-\begin{verbatim}--> class Expr e where-> fv :: e -> [Ident]-> class QualExpr e where-> qfv :: ModuleIdent -> e -> [Ident]-> class QuantExpr e where-> bv :: e -> [Ident]--> instance Expr e => Expr [e] where-> fv = concat . map fv-> instance QualExpr e => QualExpr [e] where-> qfv m = concat . map (qfv m)-> instance QuantExpr e => QuantExpr [e] where-> bv = concat . map bv--> instance QualExpr Decl where-> qfv m (FunctionDecl _ _ eqs) = qfv m eqs-> qfv m (PatternDecl _ _ rhs) = qfv m rhs-> qfv _ _ = []--> instance QuantExpr Decl where-> bv (TypeSig _ vs _) = vs-> bv (EvalAnnot _ fs _) = fs-> bv (FunctionDecl _ f _) = [f]-> bv (ExternalDecl _ _ _ f _) = [f]-> bv (FlatExternalDecl _ fs) = fs-> bv (PatternDecl _ t _) = bv t-> bv (ExtraVariables _ vs) = vs-> bv _ = []--> instance QualExpr Equation where-> qfv m (Equation _ lhs rhs) = filterBv lhs (qfv m lhs ++ qfv m rhs)--> instance QuantExpr Lhs where-> bv = bv . snd . flatLhs--> instance QualExpr Lhs where-> qfv m lhs = qfv m (snd (flatLhs lhs))--> instance QualExpr Rhs where-> qfv m (SimpleRhs _ e ds) = filterBv ds (qfv m e ++ qfv m ds)-> qfv m (GuardedRhs es ds) = filterBv ds (qfv m es ++ qfv m ds)--> instance QualExpr CondExpr where-> qfv m (CondExpr _ g e) = qfv m g ++ qfv m e--> instance QualExpr Expression where-> qfv _ (Literal _) = []-> qfv m (Variable v) = maybe [] return (localIdent m v)-> qfv _ (Constructor _) = []-> qfv m (Paren e) = qfv m e-> qfv m (Typed e _) = qfv m e-> qfv m (Tuple _ es) = qfv m es-> qfv m (List _ es) = qfv m es-> qfv m (ListCompr _ e qs) = foldr (qfvStmt m) (qfv m e) qs-> qfv m (EnumFrom e) = qfv m e-> qfv m (EnumFromThen e1 e2) = qfv m e1 ++ qfv m e2-> qfv m (EnumFromTo e1 e2) = qfv m e1 ++ qfv m e2-> qfv m (EnumFromThenTo e1 e2 e3) = qfv m e1 ++ qfv m e2 ++ qfv m e3-> qfv m (UnaryMinus _ e) = qfv m e-> qfv m (Apply e1 e2) = qfv m e1 ++ qfv m e2-> qfv m (InfixApply e1 op e2) = qfv m op ++ qfv m e1 ++ qfv m e2-> qfv m (LeftSection e op) = qfv m op ++ qfv m e-> qfv m (RightSection op e) = qfv m op ++ qfv m e-> qfv m (Lambda _ ts e) = filterBv ts (qfv m e)-> qfv m (Let ds e) = filterBv ds (qfv m ds ++ qfv m e)-> qfv m (Do sts e) = foldr (qfvStmt m) (qfv m e) sts-> qfv m (IfThenElse _ e1 e2 e3) = qfv m e1 ++ qfv m e2 ++ qfv m e3-> qfv m (Case _ e alts) = qfv m e ++ qfv m alts-> qfv m (RecordConstr fs) = qfv m fs-> qfv m (RecordSelection e _) = qfv m e-> qfv m (RecordUpdate fs e) = qfv m e ++ qfv m fs--> qfvStmt :: ModuleIdent -> Statement -> [Ident] -> [Ident]-> qfvStmt m st fvs = qfv m st ++ filterBv st fvs--> instance QualExpr Statement where-> qfv m (StmtExpr _ e) = qfv m e-> qfv m (StmtDecl ds) = filterBv ds (qfv m ds)-> qfv m (StmtBind _ t e) = qfv m e--> instance QualExpr Alt where-> qfv m (Alt _ t rhs) = filterBv t (qfv m rhs)--> instance QuantExpr a => QuantExpr (Field a) where-> bv (Field _ _ t) = bv t--> instance QualExpr a => QualExpr (Field a) where-> qfv m (Field _ _ t) = qfv m t--> instance QuantExpr Statement where-> bv (StmtExpr _ e) = []-> bv (StmtBind _ t e) = bv t-> bv (StmtDecl ds) = bv ds--> instance QualExpr InfixOp where-> qfv m (InfixOp op) = qfv m (Variable op)-> qfv _ (InfixConstr _) = []--> instance QuantExpr ConstrTerm where-> bv (LiteralPattern _) = []-> bv (NegativePattern _ _) = []-> bv (VariablePattern v) = [v]-> bv (ConstructorPattern c ts) = bv ts-> bv (InfixPattern t1 op t2) = bv t1 ++ bv t2-> bv (ParenPattern t) = bv t-> bv (TuplePattern _ ts) = bv ts-> bv (ListPattern _ ts) = bv ts-> bv (AsPattern v t) = v : bv t-> bv (LazyPattern _ t) = bv t-> bv (FunctionPattern f ts) = bvFuncPatt (FunctionPattern f ts)-> bv (InfixFuncPattern t1 op t2) = bvFuncPatt (InfixFuncPattern t1 op t2)-> bv (RecordPattern fs r) = (maybe [] bv r) ++ bv fs--> instance QualExpr ConstrTerm where-> qfv _ (LiteralPattern _) = []-> qfv _ (NegativePattern _ _) = []-> qfv _ (VariablePattern _) = []-> qfv m (ConstructorPattern _ ts) = qfv m ts-> qfv m (InfixPattern t1 _ t2) = qfv m [t1,t2]-> qfv m (ParenPattern t) = qfv m t-> qfv m (TuplePattern _ ts) = qfv m ts-> qfv m (ListPattern _ ts) = qfv m ts-> qfv m (AsPattern _ ts) = qfv m ts-> qfv m (LazyPattern _ t) = qfv m t-> qfv m (FunctionPattern f ts) -> = (maybe [] return (localIdent m f)) ++ qfv m ts-> qfv m (InfixFuncPattern t1 op t2) -> = (maybe [] return (localIdent m op)) ++ qfv m [t1,t2]-> qfv m (RecordPattern fs r) = (maybe [] (qfv m) r) ++ qfv m fs--> instance Expr TypeExpr where-> fv (ConstructorType _ tys) = fv tys-> fv (VariableType tv)-> | tv == anonId = []-> | otherwise = [tv]-> fv (TupleType tys) = fv tys-> fv (ListType ty) = fv ty-> fv (ArrowType ty1 ty2) = fv ty1 ++ fv ty2-> fv (RecordType fs rty) = (maybe [] fv rty) ++ fv (map snd fs)--> filterBv :: QuantExpr e => e -> [Ident] -> [Ident]-> filterBv e = filter (`Set.notMember` Set.fromList (bv e))--\end{verbatim}-Since multiple variable occurrences are allowed in function patterns,-it is necessary to compute the list of bound variables in a different way:-Each variable occuring in the function pattern will be unique in the result-list.-\begin{verbatim}--> bvFuncPatt :: ConstrTerm -> [Ident]-> bvFuncPatt = bvfp []-> where-> bvfp bvs (LiteralPattern _) = bvs-> bvfp bvs (NegativePattern _ _) = bvs-> bvfp bvs (VariablePattern v)-> | elem v bvs = bvs-> | otherwise = v:bvs-> bvfp bvs (ConstructorPattern c ts) = foldl bvfp bvs ts-> bvfp bvs (InfixPattern t1 op t2) = foldl bvfp bvs [t1,t2]-> bvfp bvs (ParenPattern t) = bvfp bvs t-> bvfp bvs (TuplePattern _ ts) = foldl bvfp bvs ts-> bvfp bvs (ListPattern _ ts) = foldl bvfp bvs ts-> bvfp bvs (AsPattern v t)-> | elem v bvs = bvfp bvs t-> | otherwise = bvfp (v:bvs) t-> bvfp bvs (LazyPattern _ t) = bvfp bvs t-> bvfp bvs (FunctionPattern f ts) = foldl bvfp bvs ts-> bvfp bvs (InfixFuncPattern t1 op t2) = foldl bvfp bvs [t1, t2]-> bvfp bvs (RecordPattern fs r)-> = foldl bvfp (maybe bvs (bvfp bvs) r) (map fieldTerm fs)--\end{verbatim} \paragraph{Miscellany} Error handling \begin{verbatim}@@ -937,18 +620,6 @@ > | x `elem` xs = NonLinear x > | otherwise = linear xs > linear [] = Linear--\end{verbatim}-In order to give precise error messages on duplicate definitions of-identifiers, the compiler pairs identifiers with their position in the-source file when passing them to the function above. However, the-position must be ignored when comparing two such pairs.-\begin{verbatim}--> data PIdent = PIdent Position Ident--> instance Eq PIdent where-> PIdent _ x == PIdent _ y = x == y \end{verbatim}
src/CaseCompletion.hs view
@@ -15,13 +15,14 @@ import Data.Maybe -import qualified CurrySyntax+import Curry.Base.Position (SrcRef)+import Curry.Base.Ident+import qualified Curry.Syntax+ import Base (ModuleEnv, lookupModule)-import IL-import Ident-import Position (SrcRef)-import OldScopeEnv as ScopeEnv-import ILScope+import IL.Type+import OldScopeEnv -- as ScopeEnv+import IL.Scope @@ -66,7 +67,7 @@ visitDecl mod menv msgs senv (FunctionDecl qident params typeexpr expr) = ((FunctionDecl qident params typeexpr expr'), msgs) where- (expr', msgs',_) = visitExpr mod menv msgs (insertExprScope senv expr) expr+ (expr', _, _) = visitExpr mod menv msgs (insertExprScope senv expr) expr visitDecl mod menv msgs senv (ExternalDecl qident cconv name typeexpr) = ((ExternalDecl qident cconv name typeexpr), msgs)@@ -108,8 +109,8 @@ = intError "visitExpr" "illegal alternative list" where altR = head altsR- (expr', msgs1, senv1) = visitExpr mod menv msgs (insertExprScope senv expr) expr- (alts', msgs2, senv2) = visitListWithEnv (visitAlt mod menv) insertAltScope msgs senv1 alts+ (expr', _, senv1) = visitExpr mod menv msgs (insertExprScope senv expr) expr+ (alts', _, senv2) = visitListWithEnv (visitAlt mod menv) insertAltScope msgs senv1 alts (altsR, msgs3) = removeRedundantAlts msgs alts' (expr2, senv3) = completeConsAlts r mod menv senv2 evalannot expr' altsR @@ -127,7 +128,7 @@ visitExpr mod menv msgs senv (Let bind expr) = ((Let bind' expr'), msgs2, senv3) where- (expr', msgs1, senv2) = visitExpr mod menv msgs (insertExprScope senv expr) expr+ (expr', _, senv2) = visitExpr mod menv msgs (insertExprScope senv expr) expr (bind', msgs2, senv3) = visitBinding mod menv msgs (insertBindingScope senv2 bind) bind visitExpr mod menv msgs senv (Letrec binds expr)@@ -224,8 +225,8 @@ p_getConsAltIdent (Alt (ConstructorPattern qident _) _) = qident p_genConstrTerm (qident, arity) (cconstrs,senv3) =- let args = ScopeEnv.genIdentList arity "x" senv3- senv4 = foldr ScopeEnv.insertIdent senv3 args+ let args = OldScopeEnv.genIdentList arity "x" senv3+ senv4 = foldr OldScopeEnv.insertIdent senv3 args in (ConstructorPattern qident args : cconstrs, senv4) @@ -537,10 +538,10 @@ (lookupModule mid' menv) where cons = head constrs- (mmid', _) = splitQualIdent cons- mid' = maybe mid id mmid' + mid' = fromMaybe mid (qualidMod cons) + -- Find complementary constructors within the declarations of the -- current module getCCFromDecls :: ModuleIdent -> [QualIdent] -> [Decl] -> [(QualIdent, Int)]@@ -570,7 +571,7 @@ -- Find complementary constructors within the module environment-getCCFromIDecls :: ModuleIdent -> [QualIdent] -> [CurrySyntax.IDecl] +getCCFromIDecls :: ModuleIdent -> [QualIdent] -> [Curry.Syntax.IDecl] -> [(QualIdent, Int)] getCCFromIDecls mident constrs idecls = let@@ -583,30 +584,30 @@ where p_declaresIConstr qident idecl = case idecl of- CurrySyntax.IDataDecl _ _ _ cdecls+ Curry.Syntax.IDataDecl _ _ _ cdecls -> any (p_isIConstrDecl qident) (map fromJust (filter isJust cdecls))- CurrySyntax.INewtypeDecl _ _ _ ncdecl + Curry.Syntax.INewtypeDecl _ _ _ ncdecl -> p_isINewConstrDecl qident ncdecl _ -> False - p_isIConstrDecl qident (CurrySyntax.ConstrDecl _ _ ident _)+ p_isIConstrDecl qident (Curry.Syntax.ConstrDecl _ _ ident _) = (unqualify qident) == ident- p_isIConstrDecl qident (CurrySyntax.ConOpDecl _ _ _ ident _)+ p_isIConstrDecl qident (Curry.Syntax.ConOpDecl _ _ _ ident _) = (unqualify qident) == ident - p_isINewConstrDecl qident (CurrySyntax.NewConstrDecl _ _ ident _)+ p_isINewConstrDecl qident (Curry.Syntax.NewConstrDecl _ _ ident _) = (unqualify qident) == ident p_extractIConstrDecls idecl = case idecl of- CurrySyntax.IDataDecl _ _ _ cdecls + Curry.Syntax.IDataDecl _ _ _ cdecls -> map fromJust (filter isJust cdecls) _ -> [] - p_getIConstrDeclInfo mid (CurrySyntax.ConstrDecl _ _ ident types)+ p_getIConstrDeclInfo mid (Curry.Syntax.ConstrDecl _ _ ident types) = (qualifyWith mid ident, length types)- p_getIConstrDeclInfo mid (CurrySyntax.ConOpDecl _ _ _ ident _)+ p_getIConstrDeclInfo mid (Curry.Syntax.ConOpDecl _ _ _ ident _) = (qualifyWith mid ident, 2)
− src/Combined.lhs
@@ -1,166 +0,0 @@-% -*- LaTeX -*--% $Id: Combined.lhs,v 1.16 2003/05/07 22:38:37 wlux Exp $-%-% Copyright (c) 1998-2003, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{Combined.lhs}-\section{Combined monads}\label{sec:combined-monads}-In this section we introduce combined monads which are parameterized-by another monads. This technique has been explored-in~\cite{KingWadler93:Combining} and very extensively-in~\cite{LiangHudakJones95:ModInterp}. The monad transformers used in-this report are mostly copied from the latter. Some restrictions were-necessary because Haskell~98 does not support multi-parameter type-classes. Especially, we cannot define generic lift operations because-they have to be parameterized over two monad classes. In addition, we-cannot define generic state and environment monad classes.-\begin{verbatim}--> module Combined where--> import Control.Monad-> import Control.Monad.Identity--\end{verbatim}--\subsection{State transformers}-The state transformer monad is defined as usual, except that the-result of the state transformer function is itself a monad. The-unparameterized version is defined by using the identity monad-\texttt{Id} for the base monad.-\begin{verbatim}--> newtype StateT s m a = StateT (s -> m (a,s))-> type St s = StateT s Identity--> unStateT :: StateT s m a -> (s -> m (a,s))-> unStateT (StateT st) = st--> instance Functor f => Functor (StateT s f) where-> fmap f (StateT st) = StateT (fmap (\(x,s') -> (f x,s')) . st)--> instance Monad m => Monad (StateT s m) where-> return x = StateT (\s -> return (x,s))-> StateT st >>= f = StateT (\s -> st s >>= \(x,s') -> unStateT (f x) s')-> fail msg = StateT (const (fail msg))--> instance MonadPlus m => MonadPlus (StateT s m) where-> mzero = StateT (const mzero)-> StateT st `mplus` StateT st' = StateT (\s -> st s `mplus` st' s)--> liftSt :: Monad m => m a -> StateT s m a-> liftSt m = StateT (\s -> m >>= \x -> return (x,s))--> callSt :: Monad m => StateT s m a -> s -> m a-> callSt (StateT st) s = st s >>= return . fst--> runSt :: St s a -> s -> a-> runSt st = runIdentity . callSt st--\end{verbatim}-In addition to the standard monad functions, state monads should-provide means to fetch and change the state. With multi-parameter type-classes, one could use the following class:-\begin{verbatim}--class Monad m => StateMonad s m where- update :: (s -> s) -> m s- fetch :: m s- change :: s -> m s-- fetch = update id- change = update . const--instance Monad m => StateMonad s (StateT s m) where- update f = StateT (\s -> return (s,f s))--\end{verbatim}-Unfortunately multi-parameter type classes are not available in-Haskell~98. Therefore we define the corresponding instance functions-for each state monad class separately. Here are the functions for the-state transformers.-\begin{verbatim}--> updateSt :: Monad m => (s -> s) -> StateT s m s-> updateSt f = StateT (\s -> return (s,f s))--> updateSt_ :: Monad m => (s -> s) -> StateT s m ()-> updateSt_ f = StateT (\s -> return ((),f s))--> fetchSt :: Monad m => StateT s m s-> fetchSt = updateSt id--> changeSt :: Monad m => s -> StateT s m s-> changeSt = updateSt . const--\end{verbatim}-Currying and uncurrying for state monads has been implemented-in~\cite{Fokker95:JPEG}. Here we extend this implementation to the-parametric monad classes.-\begin{verbatim}--> stCurry :: Monad m => StateT (s,t) m a -> t -> StateT s m (t,a)-> stCurry (StateT st) t =-> StateT (\s -> st (s,t) >>= \(x,(s',t')) -> return ((t',x),s'))--> stUncurry :: Monad m => (t -> StateT s m (t,a)) -> StateT (s,t) m a-> stUncurry f =-> StateT (\(s,t) -> let (StateT st) = f t-> in st s >>= \((t',x),s') -> return (x,(s',t')))--\end{verbatim}-\subsection{Environment monad}-A variant of the state transformer monad is the environment monad-which is also known as (state) reader monad.-\begin{verbatim}--> data ReaderT r m a = ReaderT (r -> m a)-> type Rt r a = ReaderT r Identity a--> unReaderT :: ReaderT r m a -> (r -> m a)-> unReaderT (ReaderT rt) = rt--> instance Functor f => Functor (ReaderT r f) where-> fmap f (ReaderT rt) = ReaderT (fmap f . rt)--> instance Monad m => Monad (ReaderT r m) where-> return x = ReaderT (\_ -> return x)-> ReaderT rt >>= f = ReaderT (\r -> rt r >>= \x -> unReaderT (f x) r)-> fail msg = ReaderT (const (fail msg))--> instance MonadPlus m => MonadPlus (ReaderT r m) where-> mzero = ReaderT (\_ -> mzero)-> ReaderT rt `mplus` ReaderT rt' = ReaderT (\r -> rt r `mplus` rt' r)--> liftRt :: Monad m => m a -> ReaderT r m a-> liftRt m = ReaderT (\_ -> m)--> callRt :: ReaderT r m a -> r -> m a-> callRt (ReaderT rt) r = rt r--> runRt :: Rt r a -> r -> a-> runRt rt = runIdentity . callRt rt--> envRt :: Monad m => ReaderT r m r-> envRt = ReaderT return --\end{verbatim}-Currying can also be applied to state reader monads.-\begin{verbatim}--> rtCurry :: Monad m => ReaderT (r,t) m a -> t -> ReaderT r m a-> rtCurry (ReaderT rt) t = ReaderT (\r -> rt (r,t))--> rtUncurry :: Monad m => (t -> ReaderT r m a) -> ReaderT (r,t) m a-> rtUncurry f = ReaderT (\(r,t) -> let (ReaderT rt) = f t in rt r)--\end{verbatim}-A state reader transformer can be transformed trivially into a state-transformer monad. This is handled by the combinator \texttt{ro}.-\begin{verbatim}--ro :: Monad m => ReaderT r m a -> StateT r m a-ro (ReaderT rt) = StateT (\s -> rt s >>= \x -> return (x,s))--\end{verbatim}
− src/CompilerResults.hs
@@ -1,24 +0,0 @@---------------------------------------------------------------------------------------------------------------------------------------------------------------------- CompilerResult - Provides a record for dealing with compiler results.--- --- January 2006,--- Martin Engelke (men@informatik.uni-kiel.de)----module CompilerResults where---------------------------------------------------------------------------------------data CompilerResults- = CompilerResults{ unchangedIntf :: Maybe FilePath }-----defaultResults :: CompilerResults-defaultResults = CompilerResults{ unchangedIntf = Nothing }------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ src/Curry/AbstractCurry.hs view
@@ -0,0 +1,282 @@+------------------------------------------------------------------------------+--- Library to support meta-programming in Curry.+---+--- This library contains a definition for representing Curry programs+--- in Curry (type "CurryProg") and an I/O action to read Curry programs and+--- transform them into this abstract representation (function "readCurry").+---+--- Note this defines a slightly new format for AbstractCurry+--- in comparison to the first proposal of 2003.+---+--- Assumption: an abstract Curry program is stored in file prog.acy+--- and translated with the parser by "parsecurry -acy prog".+---+--- @author Michael Hanus+--- @version April 2004+---+--- Version for Haskell (slightly modified):+--- July 2005, Martin Engelke (men@informatik.uni-kiel.de)+---+------------------------------------------------------------------------------++module Curry.AbstractCurry (CurryProg(..), QName, CLabel, CVisibility(..),+ CTVarIName, CTypeDecl(..), CConsDecl(..), CTypeExpr(..),+ COpDecl(..), CFixity(..), CVarIName,+ CFuncDecl(..), CRules(..), CEvalAnnot(..),+ CRule(..), CLocalDecl(..), CExpr(..), CStatement(..),+ CPattern(..), CBranchExpr(..), CLiteral(..),+ CField,+ readCurry, writeCurry) where++import Data.List(intersperse)++import PathUtils (writeModule,readModule)+++------------------------------------------------------------------------------+-- Definition of data types for representing abstract Curry programs:+-- ==================================================================++--- Data type for representing a Curry module in the intermediate form.+--- A value of this data type has the form+--- <CODE>+--- (CProg modname imports typedecls functions opdecls)+--- </CODE>+--- where modname: name of this module,+--- imports: list of modules names that are imported,+--- typedecls, opdecls, functions: see below++data CurryProg = CurryProg String [String] [CTypeDecl] [CFuncDecl] [COpDecl]+ deriving (Read, Show)++--- The data type for representing qualified names.+--- In AbstractCurry all names are qualified to avoid name clashes.+--- The first component is the module name and the second component the+--- unqualified name as it occurs in the source program.+type QName = (String,String)++--- Type for representing label identifiers+type CLabel = String++-- Data type to specify the visibility of various entities.++data CVisibility = Public -- exported entity+ | Private -- private entity+ deriving (Read, Show, Eq)+++--- The data type for representing type variables.+--- They are represented by (i,n) where i is a type variable index+--- which is unique inside a function and n is a name (if possible,+--- the name written in the source program).+type CTVarIName = (Int,String)++--- Data type for representing definitions of algebraic data types+--- and type synonyms.+--- <PRE>+--- A data type definition of the form+---+--- data t x1...xn = ...| c t1....tkc |...+---+--- is represented by the Curry term+---+--- (CType t v [i1,...,in] [...(CCons c kc v [t1,...,tkc])...])+---+--- where each ij is the index of the type variable xj+---+--- Note: the type variable indices are unique inside each type declaration+--- and are usually numbered from 0+---+--- Thus, a data type declaration consists of the name of the data type,+--- a list of type parameters and a list of constructor declarations.+--- </PRE>++data CTypeDecl = CType QName CVisibility [CTVarIName] [CConsDecl]+ | CTypeSyn QName CVisibility [CTVarIName] CTypeExpr+ deriving (Read, Show)+++--- A constructor declaration consists of the name and arity of the+--- constructor and a list of the argument types of the constructor.++data CConsDecl = CCons QName Int CVisibility [CTypeExpr]+ deriving (Read, Show)+++--- Data type for type expressions.+--- A type expression is either a type variable, a function type,+--- or a type constructor application.+---+--- Note: the names of the predefined type constructors are+--- "Int", "Float", "Bool", "Char", "IO", "Success",+--- "()" (unit type), "(,...,)" (tuple types), "[]" (list type)++data CTypeExpr =+ CTVar CTVarIName -- type variable+ | CFuncType CTypeExpr CTypeExpr -- function type t1->t2+ | CTCons QName [CTypeExpr] -- type constructor application+ | CRecordType [CField CTypeExpr] -- record type (extended Curry)+ (Maybe CTVarIName)+ deriving (Read, Show) +++--- Data type for operator declarations.+--- An operator declaration "fix p n" in Curry corresponds to the+--- AbstractCurry term (COp n fix p).++data COpDecl = COp QName CFixity Integer deriving (Read, Show)++data CFixity = CInfixOp -- non-associative infix operator+ | CInfixlOp -- left-associative infix operator+ | CInfixrOp -- right-associative infix operator+ deriving (Read, Show, Eq)+++--- Data types for representing object variables.+--- Object variables occurring in expressions are represented by (Var i)+--- where i is a variable index.++type CVarIName = (Int,String)+++--- Data type for representing function declarations.+--- <PRE>+--- A function declaration in FlatCurry is a term of the form+---+--- (CFunc name arity visibility type (CRules eval [CRule rule1,...,rulek]))+---+--- and represents the function "name" with definition+---+--- name :: type+--- rule1+--- ...+--- rulek+---+--- Note: the variable indices are unique inside each rule+---+--- External functions are represented as (CFunc name arity type (CExternal s))+--- where s is the external name associated to this function.+---+--- Thus, a function declaration consists of the name, arity, type, and+--- a list of rules.+--- </PRE>++data CFuncDecl = CFunc QName Int CVisibility CTypeExpr CRules+ deriving (Read, Show)+++--- A rule is either a list of formal parameters together with an expression+--- (i.e., a rule in flat form), a list of general program rules with+--- an evaluation annotation, or it is externally defined++data CRules = CRules CEvalAnnot [CRule]+ | CExternal String+ deriving (Read, Show)++--- Data type for classifying evaluation annotations for functions.+--- They can be either flexible (default), rigid, or choice.++data CEvalAnnot = CFlex | CRigid | CChoice deriving (Read, Show, Eq)++--- The most general form of a rule. It consists of a list of patterns+--- (left-hand side), a list of guards ("success" if not present in the+--- source text) with their corresponding right-hand sides, and+--- a list of local declarations.+data CRule = CRule [CPattern] [(CExpr,CExpr)] [CLocalDecl]+ deriving (Read, Show)++--- Data type for representing local (let/where) declarations+data CLocalDecl =+ CLocalFunc CFuncDecl -- local function declaration+ | CLocalPat CPattern CExpr [CLocalDecl] -- local pattern declaration+ | CLocalVar CVarIName -- local free variable declaration+ deriving (Read, Show)++--- Data type for representing Curry expressions.++data CExpr =+ CVar CVarIName -- variable (unique index / name)+ | CLit CLiteral -- literal (Integer/Float/Char constant)+ | CSymbol QName -- a defined symbol with module and name+ | CApply CExpr CExpr -- application (e1 e2)+ | CLambda [CPattern] CExpr -- lambda abstraction+ | CLetDecl [CLocalDecl] CExpr -- local let declarations+ | CDoExpr [CStatement] -- do expression+ | CListComp CExpr [CStatement] -- list comprehension+ | CCase CExpr [CBranchExpr] -- case expression+ | CRecConstr [CField CExpr] -- record construction (extended Curry)+ | CRecSelect CExpr CLabel -- field selection (extended Curry)+ | CRecUpdate [CField CExpr] CExpr -- record update (extended Curry)+ deriving (Read, Show)++--- Data type for representing statements in do expressions and+--- list comprehensions.++data CStatement = CSExpr CExpr -- an expression (I/O action or boolean)+ | CSPat CPattern CExpr -- a pattern definition+ | CSLet [CLocalDecl] -- a local let declaration+ deriving (Read, Show)++--- Data type for representing pattern expressions.++data CPattern =+ CPVar CVarIName -- pattern variable (unique index / name)+ | CPLit CLiteral -- literal (Integer/Float/Char constant)+ | CPComb QName [CPattern] -- application (m.c e1 ... en) of n-ary+ -- constructor m.c (CPComb (m,c) [e1,...,en])+ | CPAs CVarIName CPattern -- as-pattern (extended Curry)+ | CPFuncComb QName [CPattern] -- function pattern (extended Curry)+ | CPLazy CPattern -- lazy pattern (extended Curry) + | CPRecord [CField CPattern] -- record pattern (extended curry)+ (Maybe CPattern)+ deriving (Read, Show) ++--- Data type for representing branches in case expressions.++data CBranchExpr = CBranch CPattern CExpr deriving (Read, Show)++--- Data type for representing literals occurring in an expression.+--- It is either an integer, a float, or a character constant.+--- Note: the constructor definition of 'CIntc' differs from the original+--- PAKCS definition. It uses Haskell type 'Integer' instead of 'Int'+--- to provide an unlimited range of integer numbers. Furthermore+--- float values are represented with Haskell type 'Double' instead of+--- 'Float'.++data CLiteral = CIntc Integer+ | CFloatc Double+ | CCharc Char+ deriving (Read, Show, Eq)++--- Type for representing labeled fields++type CField a = (CLabel,a)++------------------------------------------------------------------------------+------------------------------------------------------------------------------++-- Reads an AbstractCurry file and returns the corresponding AbstractCurry+-- program term (type 'CurryProg')+readCurry :: String -> IO CurryProg+readCurry filename+ = do file <- readModule filename+ let prog = (read file) :: CurryProg+ return prog++-- Writes an AbstractCurry program term into a file+writeCurry :: String -> CurryProg -> IO ()+writeCurry filename prog + = catch (writeModule filename (showCurry prog)) (\e -> ioError e)++-- Shows an AbstractCurry program in a more nicely way.+showCurry :: CurryProg -> String+showCurry (CurryProg mname imps types funcs ops) =+ "CurryProg "++show mname++"\n "+++ show imps ++"\n ["+++ concat (intersperse ",\n " (map (\t->show t) types)) ++"]\n ["+++ concat (intersperse ",\n " (map (\f->show f) funcs)) ++"]\n "+++ show ops ++"\n"+ ++------------------------------------------------------------------------------+------------------------------------------------------------------------------
+ src/Curry/Base/Ident.lhs view
@@ -0,0 +1,352 @@+> {-# LANGUAGE DeriveDataTypeable #-}++% $Id: Ident.lhs,v 1.21 2004/10/29 13:08:09 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+\nwfilename{Ident.lhs}+\section{Identifiers}+This module provides the implementation of identifiers and some+utility functions for identifiers, which are used at various places in+the compiler.++Identifiers comprise the name of the denoted entity and an \emph{id},+which can be used for renaming identifiers, e.g., in order to resolve+name conflicts between identifiers from different scopes. An+identifier with an \emph{id} $0$ is considered as not being renamed+and, hence, its \emph{id} will not be shown.++\ToDo{Probably we should use \texttt{Integer} for the \emph{id}s.}++Qualified identifiers may optionally be prefixed by a module+name. \textbf{The order of the cases \texttt{UnqualIdent} and+\texttt{QualIdent} is important. Some parts of the compiler rely on+the fact that all qualified identifiers are greater than any+unqualified identifier.}+\begin{verbatim}++> module Curry.Base.Ident(Ident(..), showIdent,+> QualIdent(..),ModuleIdent(..),SrcRefOf(..),+> mkIdent, qualName,+> renameIdent, unRenameIdent,+> mkMIdent, moduleName,+> isInfixOp, isQInfixOp,+> qualify, qualifyWith, qualQualify,+> isQualified, unqualify, qualUnqualify,+> localIdent, -- splitQualIdent,+> emptyMIdent, mainMIdent,preludeMIdent,+> anonId,unitId,boolId,charId,intId,floatId,listId,ioId,+> successId,trueId,falseId,nilId,consId,mainId,+> tupleId,isTupleId,tupleArity,+> minusId,fminusId,updIdentName,+> qUnitId,qBoolId,qCharId,qIntId,qFloatId,qListId,qIOId,+> qSuccessId,qTrueId,qFalseId,qNilId,qConsId,+> qTupleId,isQTupleId,qTupleArity,+> fpSelectorId,isFpSelectorId,isQualFpSelectorId,+> recSelectorId,qualRecSelectorId,+> recUpdateId, qualRecUpdateId, recordExtId, labelExtId,+> isRecordExtId, isLabelExtId, fromRecordExtId, fromLabelExtId,+> renameLabel,+> recordExt, labelExt, mkLabelIdent,-- hasPositionIdent,+> addPositionIdent, +> addPositionModuleIdent,addRef,addRefId,+> positionOfQualIdent,updQualIdent ) where++> import Control.Monad(liftM)+> import Data.Char+> import Data.List+> import Data.Maybe+> import Data.Generics+> import Data.Function(on)++> import Curry.Base.Position+++Simple identifiers++> data Ident = Ident { positionOfIdent :: Position,+> name :: String,+> uniqueId :: Int }+> deriving (Read, Data, Typeable)+>+> instance Eq Ident where+> Ident _ m i == Ident _ n j = (m,i) == (n, j)+>+> instance Ord Ident where+> Ident _ m i `compare` Ident _ n j = (m,i) `compare` (n, j)+>+> instance Show Ident where+> show = showIdent+>+> showIdent :: Ident -> String+> showIdent (Ident _ x 0) = x+> showIdent (Ident _ x n) = x ++ '.' : show n+++Qualified identifiers++> data QualIdent = QualIdent { qualidMod :: Maybe ModuleIdent,+> qualidId:: Ident }+> deriving (Eq, Ord, Read, Data,Typeable)++> qualName :: QualIdent -> String+> qualName (QualIdent Nothing x) = name x+> qualName (QualIdent (Just m) x) = moduleName m ++ "." ++ name x++> instance Show QualIdent where+> show = qualName++Module names++> data ModuleIdent = ModuleIdent { positionOfModuleIdent :: Position,+> moduleQualifiers :: [String] }+> deriving (Read, Data,Typeable)++> instance Eq ModuleIdent where+> (==) = (==) `on` moduleQualifiers++> instance Ord ModuleIdent where+> compare = compare `on` moduleQualifiers++> moduleName :: ModuleIdent -> String+> moduleName = concat . intersperse "." . moduleQualifiers++> instance Show ModuleIdent where+> show = moduleName++-- -----------------------------------------++> addPositionIdent :: Position -> Ident -> Ident+> addPositionIdent pos (Ident NoPos x n) = Ident pos x n+> addPositionIdent AST{ast=sr} (Ident pos x n)+> = Ident pos{ast=sr} x n+> addPositionIdent pos (Ident _ x n) = Ident pos x n++> addPositionModuleIdent :: Position -> ModuleIdent -> ModuleIdent+> addPositionModuleIdent pos (ModuleIdent _ x) = ModuleIdent pos x ++> positionOfQualIdent :: QualIdent -> Position+> positionOfQualIdent = positionOfIdent . qualidId++> mkIdent :: String -> Ident+> mkIdent x = Ident NoPos x 0++> renameIdent :: Ident -> Int -> Ident+> renameIdent (Ident p x _) n = Ident p x n+++> unRenameIdent :: Ident -> Ident+> unRenameIdent (Ident p x _) = Ident p x 0++> mkMIdent :: [String] -> ModuleIdent+> mkMIdent = ModuleIdent NoPos++> isInfixOp :: Ident -> Bool+> isInfixOp (Ident _ ('<':c:cs) _)=+> last (c:cs) /= '>' || not (isAlphaNum c) && c `notElem` "_(["+> isInfixOp (Ident _ (c:_) _) = not (isAlphaNum c) && c `notElem` "_(["+> isInfixOp (Ident _ _ _) = False -- error "Zero-length identifier"++> isQInfixOp :: QualIdent -> Bool+> isQInfixOp (QualIdent _ x) = isInfixOp x++\end{verbatim}+The functions \texttt{qualify} and \texttt{qualifyWith} convert an+unqualified identifier into a qualified identifier (without and with a+given module prefix, respectively).+\begin{verbatim}++> qualify :: Ident -> QualIdent+> qualify = QualIdent Nothing++> qualifyWith :: ModuleIdent -> Ident -> QualIdent+> qualifyWith = QualIdent . Just++> qualQualify :: ModuleIdent -> QualIdent -> QualIdent+> qualQualify m (QualIdent Nothing x) = QualIdent (Just m) x+> qualQualify _ x = x++> isQualified :: QualIdent -> Bool+> isQualified (QualIdent m _) = isJust m++> unqualify :: QualIdent -> Ident+> unqualify (QualIdent _ x) = x++> qualUnqualify :: ModuleIdent -> QualIdent -> QualIdent+> qualUnqualify m qid@(QualIdent Nothing x) = qid+> qualUnqualify m (QualIdent (Just m') x) = QualIdent m'' x+> where m'' | m == m' = Nothing+> | otherwise = Just m'++> localIdent :: ModuleIdent -> QualIdent -> Maybe Ident+> localIdent _ (QualIdent Nothing x) = Just x+> localIdent m (QualIdent (Just m') x)+> | m == m' = Just x+> | otherwise = Nothing++> splitQualIdent :: QualIdent -> (Maybe ModuleIdent,Ident)+> splitQualIdent (QualIdent m x) = (m,x)++> updQualIdent :: (ModuleIdent -> ModuleIdent) -> (Ident -> Ident) -> QualIdent -> QualIdent+> updQualIdent f g (QualIdent m x) = QualIdent (liftM f m) (g x)++> addRef :: SrcRef -> QualIdent -> QualIdent+> addRef r = updQualIdent id (addRefId r)++> addRefId :: SrcRef -> Ident -> Ident+> addRefId = addPositionIdent . AST++\end{verbatim}+A few identifiers a predefined here.+\begin{verbatim}++> emptyMIdent, mainMIdent, preludeMIdent :: ModuleIdent+> emptyMIdent = ModuleIdent NoPos []+> mainMIdent = ModuleIdent NoPos ["main"]+> preludeMIdent = ModuleIdent NoPos ["Prelude"]++> anonId :: Ident+> anonId = Ident NoPos "_" 0++> unitId, boolId, charId, intId, floatId, listId, ioId, successId :: Ident+> unitId = Ident NoPos "()" 0+> boolId = Ident NoPos "Bool" 0+> charId = Ident NoPos "Char" 0+> intId = Ident NoPos "Int" 0+> floatId = Ident NoPos "Float" 0+> listId = Ident NoPos "[]" 0+> ioId = Ident NoPos "IO" 0+> successId = Ident NoPos "Success" 0++> trueId, falseId, nilId, consId :: Ident+> trueId = Ident NoPos "True" 0+> falseId = Ident NoPos "False" 0+> nilId = Ident NoPos "[]" 0+> consId = Ident NoPos ":" 0++> tupleId :: Int -> Ident+> tupleId n+> | n >= 2 = Ident NoPos ("(" ++ replicate (n - 1) ',' ++ ")") 0+> | otherwise = error "internal error: tupleId"++> isTupleId :: Ident -> Bool+> isTupleId x = n > 1 && x == tupleId n+> where n = length (name x) - 1++> tupleArity :: Ident -> Int+> tupleArity x+> | n > 1 && x == tupleId n = n+> | otherwise = error "internal error: tupleArity"+> where n = length (name x) - 1++> mainId, minusId, fminusId :: Ident+> mainId = Ident NoPos "main" 0+> minusId = Ident NoPos "-" 0+> fminusId = Ident NoPos "-." 0++> qUnitId, qNilId, qConsId, qListId :: QualIdent+> qUnitId = QualIdent Nothing unitId+> qListId = QualIdent Nothing listId+> qNilId = QualIdent Nothing nilId+> qConsId = QualIdent Nothing consId++> qBoolId, qCharId, qIntId, qFloatId, qSuccessId, qIOId :: QualIdent+> qBoolId = QualIdent (Just preludeMIdent) boolId+> qCharId = QualIdent (Just preludeMIdent) charId+> qIntId = QualIdent (Just preludeMIdent) intId+> qFloatId = QualIdent (Just preludeMIdent) floatId+> qSuccessId = QualIdent (Just preludeMIdent) successId+> qIOId = QualIdent (Just preludeMIdent) ioId++> qTrueId, qFalseId :: QualIdent+> qTrueId = QualIdent (Just preludeMIdent) trueId+> qFalseId = QualIdent (Just preludeMIdent) falseId++> qTupleId :: Int -> QualIdent+> qTupleId = QualIdent Nothing . tupleId++> isQTupleId :: QualIdent -> Bool+> isQTupleId = isTupleId . unqualify++> qTupleArity :: QualIdent -> Int+> qTupleArity = tupleArity . unqualify++\end{verbatim}+Micellaneous function for generating and testing extended identifiers.+\begin{verbatim}++> fpSelectorId :: Int -> Ident+> fpSelectorId n = Ident NoPos (fpSelExt ++ show n) 0++> isFpSelectorId :: Ident -> Bool+> isFpSelectorId f = any (fpSelExt `isPrefixOf`) (tails (name f))++> isQualFpSelectorId :: QualIdent -> Bool+> isQualFpSelectorId = isFpSelectorId . unqualify++> recSelectorId :: QualIdent -> Ident -> Ident+> recSelectorId r l =+> mkIdent (recSelExt ++ name (unqualify r) ++ "." ++ name l)++> qualRecSelectorId :: ModuleIdent -> QualIdent -> Ident -> QualIdent+> qualRecSelectorId m r l = qualifyWith m' (recSelectorId r l)+> where m' = (fromMaybe m (fst (splitQualIdent r)))++> recUpdateId :: QualIdent -> Ident -> Ident+> recUpdateId r l = +> mkIdent (recUpdExt ++ name (unqualify r) ++ "." ++ name l)++> qualRecUpdateId :: ModuleIdent -> QualIdent -> Ident -> QualIdent+> qualRecUpdateId m r l = qualifyWith m' (recUpdateId r l)+> where m' = (fromMaybe m (fst (splitQualIdent r)))++> recordExtId :: Ident -> Ident+> recordExtId r = mkIdent (recordExt ++ name r)++> labelExtId :: Ident -> Ident+> labelExtId l = mkIdent (labelExt ++ name l)++> fromRecordExtId :: Ident -> Ident+> fromRecordExtId r +> | p == recordExt = mkIdent r'+> | otherwise = r+> where (p,r') = splitAt (length recordExt) (name r)++> fromLabelExtId :: Ident -> Ident+> fromLabelExtId l +> | p == labelExt = mkIdent l'+> | otherwise = l+> where (p,l') = splitAt (length labelExt) (name l)++> isRecordExtId :: Ident -> Bool+> isRecordExtId r = recordExt `isPrefixOf` name r++> isLabelExtId :: Ident -> Bool+> isLabelExtId l = labelExt `isPrefixOf` name l++> mkLabelIdent :: String -> Ident+> mkLabelIdent c = renameIdent (mkIdent c) (-1)++> renameLabel :: Ident -> Ident+> renameLabel l = renameIdent l (-1)+++> fpSelExt = "_#selFP"+> recSelExt = "_#selR@"+> recUpdExt = "_#updR@"+> recordExt = "_#Rec:"+> labelExt = "_#Lab:"+++> instance SrcRefOf Ident where+> srcRefOf = srcRefOf . positionOfIdent++> instance SrcRefOf QualIdent where+> srcRefOf = srcRefOf . unqualify++> updIdentName :: (String -> String) -> Ident -> Ident+> updIdentName f ident = let p=positionOfIdent ident+> i=uniqueId ident+> n=name ident in+> addPositionIdent p $ flip renameIdent i $ mkIdent (f n)
+ src/Curry/Base/MessageMonad.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE FlexibleContexts #-}+{-+ The \texttt{MsgMonad} type is used for describing the result of a+ computation that can fail. In contrast to the standard \texttt{Maybe}+ type, its \texttt{Error} case provides for an error message that+ describes the failure.+-}++module Curry.Base.MessageMonad where++import Control.Monad.Error+import Control.Monad.Writer+import Control.Monad.Identity++import Curry.Base.Position+++type MsgMonadT m = ErrorT WarnMsg (WriterT [WarnMsg] m)++type MsgMonad = MsgMonadT Identity++type MsgMonadIO = MsgMonadT IO++data WarnMsg = WarnMsg { warnPos :: Maybe Position,+ warnTxt :: String+ }+instance Error WarnMsg where+ noMsg = WarnMsg Nothing "Failure!"+ strMsg = WarnMsg Nothing++instance Show WarnMsg where+ show = showWarning++-- tell w = Control.Monad.Writer.tell w++showWarning w = "Warning: " ++ pos ++ warnTxt w+ where pos = case warnPos w of+ Nothing -> ""+ Just p -> show p ++": "++showError w = "Error: " ++ pos ++ warnTxt w+ where pos = case warnPos w of+ Nothing -> ""+ Just p -> show p ++": "++ok :: MsgMonad a -> a+ok = either (error . showError) id . fst . runMsg+++failWith :: (MonadError a m, Error a) => String -> m a1+failWith = throwError . strMsg+++failWithAt :: (MonadError WarnMsg m) => Position -> String -> m a+failWithAt p s = throwError (WarnMsg (Just p) s)+++warnMessage :: (MonadWriter [WarnMsg] m) => String -> m ()+warnMessage s = tell [WarnMsg Nothing s]+++warnMessageAt :: (MonadWriter [WarnMsg] m) => Position -> String -> m ()+warnMessageAt p s = tell [WarnMsg (Just p) s]++runMsg :: MsgMonad a -> (Either WarnMsg a, [WarnMsg])+runMsg = runIdentity . runWriterT . runErrorT++-- returnIO :: MsgMonad a -> MsgMonadIO a+-- returnIO x = return$ (runIdentity . runWriterT . runErrorT) x++runMsgIO :: MsgMonad a -> (a -> IO (MsgMonad b)) -> IO (MsgMonad b)+runMsgIO m f+ = case runMsg m of+ (Left e, msgs) -> return (tell msgs >> throwError e)+ (Right x, msgs) -> do m' <- f x+ case runMsg m' of+ (Left _,_) -> return m'+ (Right x', msgs') -> return (tell (msgs ++ msgs') >> return x')++dropIO :: MsgMonad a -> MsgMonadIO a+dropIO x = case runMsg x of+ (Left e, m) -> tell m >> throwError e+ (Right x, m) -> tell m >> return x
+ src/Curry/Base/Position.lhs view
@@ -0,0 +1,96 @@+> {-# LANGUAGE DeriveDataTypeable #-}++% -*- LaTeX -*-+% $Id: Position.lhs,v 1.2 2000/10/08 09:55:43 lux Exp $+%+% $Log: Position.lhs,v $+% Revision 1.2 2000/10/08 09:55:43 lux+% Column numbers now start at 1. If the column number is less than 1 it+% will not be shown.+%+% Revision 1.1 2000/07/23 11:03:37 lux+% Positions now implemented in a separate module.+%+%+\nwfilename{Position.lhs}+\section{Positions}+A source file position consists of a filename, a line number, and a+column number. A tab stop is assumed at every eighth column.+\begin{verbatim}++> module Curry.Base.Position where+> import Data.Generics++> newtype SrcRef = SrcRef [Int] deriving (Typeable,Data) -- a pointer to the origin++-- the instances for standard classes or such that SrcRefs are invisible++> instance Show SrcRef where show _ = ""+> instance Read SrcRef where readsPrec _ s = [(noRef,s)]+> instance Eq SrcRef where _ == _ = True+> instance Ord SrcRef where compare _ _ = EQ++> noRef :: SrcRef+> noRef = SrcRef []+>+> incSrcRef :: SrcRef -> Int -> SrcRef+> incSrcRef (SrcRef [i]) j = SrcRef [i+j]+> incSrcRef is _ = error $ "internal error; increment source ref: " ++ show is++> data Position +> = Position{ file :: FilePath, line :: Int, column :: Int, ast :: SrcRef }+> | AST { ast :: SrcRef }+> | NoPos+> deriving (Eq, Ord,Data,Typeable)++> incPosition :: Position -> Int -> Position+> incPosition p j = p{ast=incSrcRef (ast p) j}++> instance Read Position where+> readsPrec p s = +> [ (Position{file="",line=i,column=j,ast=noRef},s') | ((i,j),s') <- readsPrec p s]++> instance Show Position where+> showsPrec _ Position{file=fn,line=l,column=c} =+> (if null fn then id else shows fn . showString ", ") .+> showString "line " . shows l .+> (if c > 0 then showChar '.' . shows c else id)+> showsPrec _ AST{} = id+> showsPrec _ NoPos = id++> tabWidth :: Int+> tabWidth = 8++> first :: FilePath -> Position+> first fn = Position fn 1 1 noRef++> incr :: Position -> Int -> Position+> incr p@Position{column=c} n = p{column=c + n}+> incr p _ = p++> next :: Position -> Position+> next = flip incr 1++> tab :: Position -> Position+> tab p@Position{column=c} = p{column=c + tabWidth - (c - 1) `mod` tabWidth}+> tab p = p++> nl :: Position -> Position+> nl p@Position{line=l} = p{line=l + 1, column=1}+> nl p = p++> showLine :: Position -> String+> showLine NoPos = ""+> showLine AST{} = ""+> showLine Position{line=l,column=c} +> = "(line " ++ show l ++ "." ++ show c ++ ") "++\end{verbatim}++> class SrcRefOf a where+> srcRefsOf :: a -> [SrcRef]+> srcRefsOf = (:[]) . srcRefOf+> srcRefOf :: a -> SrcRef+> srcRefOf = head . srcRefsOf++> instance SrcRefOf Position where srcRefOf = ast
+ src/Curry/ExtendedFlat.hs view
@@ -0,0 +1,475 @@+------------------------------------------------------------------------------+--- Library to support meta-programming in Curry.+---+--- This library contains a definition for representing FlatCurry programs+--- in Haskell (type "Prog").+---+--- @author Michael Hanus+--- @version September 2003+---+--- Version for Haskell (slightly modified):+--- December 2004, Martin Engelke (men@informatik.uni-kiel.de)+---+--- Added part calls for constructors, Bernd Brassel, August 2005+--- Added source references, Bernd Brassel, May 2009+------------------------------------------------------------------------------++{-# LANGUAGE DeriveDataTypeable, RankNTypes #-}++module Curry.ExtendedFlat (SrcRef,Prog(..),+ QName(..), qnOf,mkQName,+ Visibility(..),+ TVarIndex, TypeDecl(..), ConsDecl(..), TypeExpr(..),+ OpDecl(..), Fixity(..),+ VarIndex(..), mkIdx,+ FuncDecl(..), Rule(..), + CaseType(..), CombType(..), Expr(..), BranchExpr(..),+ Pattern(..), Literal(..), + readFlatCurry, readFlatInterface, readFlat, + writeFlatCurry,writeExtendedFlat,gshowsPrec+ ) where++import Data.List(intersperse)+import Control.Monad (liftM)+import Data.Generics hiding (Fixity)+import Data.Function(on)+import System.FilePath++import PathUtils (writeModule, maybeReadModule)+import Filenames(flatName)+import Curry.Base.Position (SrcRef)++------------------------------------------------------------------------------+-- Definition of data types for representing FlatCurry programs:+-- =============================================================++--- Data type for representing a Curry module in the intermediate form.+--- A value of this data type has the form+--- <CODE>+--- (Prog modname imports typedecls functions opdecls translation_table)+--- </CODE>+--- where modname: name of this module,+--- imports: list of modules names that are imported,+--- typedecls, opdecls, functions, translation of type names+--- and constructor/function names: see below++data Prog = Prog String [String] [TypeDecl] [FuncDecl] [OpDecl] + deriving (Read, Show, Eq,Data,Typeable)+++-------------------------------------------------------------------------+--- The data type for representing qualified names.+--- In FlatCurry all names are qualified to avoid name clashes.+--- The first component is the module name and the second component the+--- unqualified name as it occurs in the source program.+--- The additional information about source references and types should+--- be invisible for the normal usage of QName.+-------------------------------------------------------------------------++data QName = QName {srcRef :: Maybe SrcRef,+ typeofQName :: Maybe TypeExpr,+ modName :: String,+ localName :: String} deriving (Data,Typeable)+++instance Read QName where+ readsPrec d r = + [ (mkQName nm,s) | (nm,s) <- readsPrec d r ]+ ++ [ (QName r t m n, s) | ((r, t, m, n),s) <- readsPrec d r ]++instance Show QName where+ showsPrec d (QName r t m n)+ = showsPrec d (r,t,m,n)++instance Eq QName where (==) = (==) `on` qnOf++instance Ord QName where compare = compare `on` qnOf++mkQName :: (String,String) -> QName+mkQName = uncurry (QName Nothing Nothing)++qnOf :: QName -> (String,String) +qnOf QName{modName=m,localName=n} = (m,n)+++-------------------------------------------------------------------------+--- The data type for representing variable names.+--- The additional information should+--- be invisible for the normal usage of VarIndex.+-------------------------------------------------------------------------++data VarIndex = VarIndex {+ typeofVar :: Maybe TypeExpr,+ idxOf :: Int+ } deriving (Data,Typeable)++onIndex :: (Int -> Int) -> VarIndex -> VarIndex+onIndex f (VarIndex{ typeofVar = t, idxOf = x})+ = VarIndex t (f x)++onIndexes :: (Int ->Int -> Int) -> VarIndex -> VarIndex -> VarIndex+onIndexes g x = VarIndex (typeofVar x) . (g `on` idxOf) x++mkIdx :: Int -> VarIndex+mkIdx = VarIndex Nothing+++instance Read VarIndex where+ readsPrec d r = + [ (mkIdx i,s) | (i,s) <- readsPrec d r ]+ ++ [ (VarIndex t i,s) | ((t,i),s) <- readsPrec d r ]++instance Show VarIndex where+ showsPrec d (VarIndex t i)= showsPrec d (t,i)++instance Eq VarIndex where+ (==) = (==) `on` idxOf++instance Ord VarIndex where+ compare = compare `on` idxOf++instance Num VarIndex where+ (+) = onIndexes (+)+ (*) = onIndexes (*)+ (-) = onIndexes (-)+ abs = onIndex abs+ signum = onIndex signum+ fromInteger = mkIdx . fromInteger++------------------------------------------------------------+--- Data type to specify the visibility of various entities.+------------------------------------------------------------++data Visibility = Public -- public (exported) entity+ | Private -- private entity+ deriving (Read, Show, Eq,Data,Typeable)++--- The data type for representing type variables.+--- They are represented by (TVar i) where i is a type variable index.++type TVarIndex = Int++--- Data type for representing definitions of algebraic data types.+--- <PRE>+--- A data type definition of the form+---+--- data t x1...xn = ...| c t1....tkc |...+---+--- is represented by the FlatCurry term+---+--- (Type t [i1,...,in] [...(Cons c kc [t1,...,tkc])...])+---+--- where each ij is the index of the type variable xj+---+--- Note: the type variable indices are unique inside each type declaration+--- and are usually numbered from 0+---+--- Thus, a data type declaration consists of the name of the data type,+--- a list of type parameters and a list of constructor declarations.+--- </PRE>++data TypeDecl = Type QName Visibility [TVarIndex] [ConsDecl]+ | TypeSyn QName Visibility [TVarIndex] TypeExpr+ deriving (Read, Show, Eq,Data,Typeable)++--- A constructor declaration consists of the name and arity of the+--- constructor and a list of the argument types of the constructor.++data ConsDecl = Cons QName Int Visibility [TypeExpr]+ deriving (Read, Show, Eq,Data,Typeable)+++--- Data type for type expressions.+--- A type expression is either a type variable, a function type,+--- or a type constructor application.+---+--- Note: the names of the predefined type constructors are+--- "Int", "Float", "Bool", "Char", "IO", "Success",+--- "()" (unit type), "(,...,)" (tuple types), "[]" (list type)++data TypeExpr =+ TVar TVarIndex -- type variable+ | FuncType TypeExpr TypeExpr -- function type t1->t2+ | TCons QName [TypeExpr] -- type constructor application+ deriving (Read, Show, Eq,Data,Typeable) -- TCons module name typeargs+++--- Data type for operator declarations.+--- An operator declaration "fix p n" in Curry corresponds to the+--- FlatCurry term (Op n fix p).+--- Note: the constructor definition of 'Op' differs from the original+--- PAKCS definition using Haskell type 'Integer' instead of 'Int'+--- for representing the precedence. ++data OpDecl = Op QName Fixity Integer deriving (Read, Show, Eq,Data,Typeable)++--- Data types for the different choices for the fixity of an operator.++data Fixity = InfixOp | InfixlOp | InfixrOp deriving (Read, Show, Eq,Data,Typeable)+++--- Data type for representing object variables.+--- Object variables occurring in expressions are represented by (Var i)+--- where i is a variable index.++--- Data type for representing function declarations.+--- <PRE>+--- A function declaration in FlatCurry is a term of the form+---+--- (Func name arity type (Rule [i_1,...,i_arity] e))+---+--- and represents the function "name" with definition+---+--- name :: type+--- name x_1...x_arity = e+---+--- where each i_j is the index of the variable x_j+---+--- Note: the variable indices are unique inside each function declaration+--- and are usually numbered from 0+---+--- External functions are represented as (Func name arity type (External s))+--- where s is the external name associated to this function.+---+--- Thus, a function declaration consists of the name, arity, type, and rule.+--- </PRE>++data FuncDecl = Func QName Int Visibility TypeExpr Rule+ deriving (Read, Show, Eq,Data,Typeable)+++--- A rule is either a list of formal parameters together with an expression+--- or an "External" tag.++data Rule = Rule [VarIndex] Expr+ | External String+ deriving (Read, Show, Eq,Data,Typeable)++--- Data type for classifying case expressions.+--- Case expressions can be either flexible or rigid in Curry.++data CaseType = Rigid | Flex deriving (Read, Show, Eq,Data,Typeable)++--- Data type for classifying combinations+--- (i.e., a function/constructor applied to some arguments).+--- @cons FuncCall - a call to a function all arguments are provided+--- @cons ConsCall - a call with a constructor at the top,+--- all arguments are provided+--- @cons FuncPartCall - a partial call to a function+--- (i.e., not all arguments are provided) +--- where the parameter is the number of+--- missing arguments+--- @cons ConsPartCall - a partial call to a constructor along with +--- number of missing arguments++data CombType = FuncCall + | ConsCall + | FuncPartCall Int + | ConsPartCall Int deriving (Read, Show, Eq,Data,Typeable)++--- Data type for representing expressions.+---+--- Remarks:+--- <PRE>+--- 1. if-then-else expressions are represented as function calls:+--- (if e1 then e2 else e3)+--- is represented as+--- (Comb FuncCall ("Prelude","if_then_else") [e1,e2,e3])+--- +--- 2. Higher order applications are represented as calls to the (external)+--- function "apply". For instance, the rule+--- app f x = f x+--- is represented as+--- (Rule [0,1] (Comb FuncCall ("Prelude","apply") [Var 0, Var 1]))+--- +--- 3. A conditional rule is represented as a call to an external function+--- "cond" where the first argument is the condition (a constraint).+--- For instance, the rule+--- equal2 x | x=:=2 = success+--- is represented as+--- (Rule [0]+--- (Comb FuncCall ("Prelude","cond")+--- [Comb FuncCall ("Prelude","=:=") [Var 0, Lit (Intc 2)],+--- Comb FuncCall ("Prelude","success") []]))+--- +--- 4. Functions with evaluation annotation "choice" are represented+--- by a rule whose right-hand side is enclosed in a call to the+--- external function "Prelude.commit".+--- Furthermore, all rules of the original definition must be+--- represented by conditional expressions (i.e., (cond [c,e]))+--- after pattern matching.+--- Example:+--- +--- m eval choice+--- m [] y = y+--- m x [] = x+--- +--- is translated into (note that the conditional branches can be also+--- wrapped with Free declarations in general):+--- +--- Rule [0,1]+--- (Comb FuncCall ("Prelude","commit")+--- [Or (Case Rigid (Var 0)+--- [(Pattern ("Prelude","[]") []+--- (Comb FuncCall ("Prelude","cond")+--- [Comb FuncCall ("Prelude","success") [],+--- Var 1]))] )+--- (Case Rigid (Var 1)+--- [(Pattern ("Prelude","[]") []+--- (Comb FuncCall ("Prelude","cond")+--- [Comb FuncCall ("Prelude","success") [],+--- Var 0]))] )])+--- +--- Operational meaning of (Prelude.commit e):+--- evaluate e with local search spaces and commit to the first+--- (Comb FuncCall ("Prelude","cond") [c,ge]) in e whose constraint c+--- is satisfied+--- </PRE>+--- @cons Var - variable (represented by unique index)+--- @cons Lit - literal (Integer/Float/Char constant)+--- @cons Comb - application (f e1 ... en) of function/constructor f+--- with n<=arity(f)+--- @cons Free - introduction of free local variables+--- @cons Or - disjunction of two expressions (used to translate rules+--- with overlapping left-hand sides)+--- @cons Case - case distinction (rigid or flex)++data Expr = Var VarIndex + | Lit Literal+ | Comb CombType QName [Expr]+ | Free [VarIndex] Expr+ | Let [(VarIndex,Expr)] Expr+ | Or Expr Expr+ | Case SrcRef CaseType Expr [BranchExpr]+ deriving (Read, Show, Eq,Data,Typeable)+++--- Data type for representing branches in a case expression.+--- <PRE>+--- Branches "(m.c x1...xn) -> e" in case expressions are represented as+---+--- (Branch (Pattern (m,c) [i1,...,in]) e)+---+--- where each ij is the index of the pattern variable xj, or as+---+--- (Branch (LPattern (Intc i)) e)+---+--- for integers as branch patterns (similarly for other literals+--- like float or character constants).+--- </PRE>++data BranchExpr = Branch Pattern Expr deriving (Read, Show, Eq,Data,Typeable)++--- Data type for representing patterns in case expressions.++data Pattern = Pattern QName [VarIndex]+ | LPattern Literal+ deriving (Read, Show, Eq,Data,Typeable)++--- Data type for representing literals occurring in an expression+--- or case branch. It is either an integer, a float, or a character constant.+--- Note: the constructor definition of 'Intc' differs from the original+--- PAKCS definition. It uses Haskell type 'Integer' instead of 'Int'+--- to provide an unlimited range of integer numbers. Furthermore+--- float values are represented with Haskell type 'Double' instead of+--- 'Float'.++data Literal = Intc SrcRef Integer+ | Floatc SrcRef Double+ | Charc SrcRef Char+ deriving (Read, Show, Eq,Data,Typeable)+++------------------------------------------------------------------------------+------------------------------------------------------------------------------++-- Reads a FlatCurry file (extension ".fcy") and returns the corresponding+-- FlatCurry program term (type 'Prog') as a value of type 'Maybe'.+readFlatCurry :: FilePath -> IO (Maybe Prog)+readFlatCurry fn + = do let filename = flatName fn+ readFlat filename++-- Reads a FlatInterface file (extension ".fint") and returns the+-- corresponding term (type 'Prog') as a value of type 'Maybe'.+readFlatInterface :: String -> IO (Maybe Prog)+readFlatInterface fn+ = do let filename = replaceExtension fn ".fint"+ readFlat filename++-- Reads a Flat file and returns the corresponding term (type 'Prog') as+-- a value of type 'Maybe'.+readFlat :: FilePath -> IO (Maybe Prog)+readFlat = liftM (fmap read) . maybeReadModule+ +-- Writes a FlatCurry program term into a file.+writeFlatCurry :: String -> Prog -> IO ()+writeFlatCurry filename prog+ = writeModule filename (showFlatCurry' False prog)++-- Writes a FlatCurry program term with source references into a file.+writeExtendedFlat :: String -> Prog -> IO ()+writeExtendedFlat filename prog =+ writeModule (replaceExtension filename ".efc") (showFlatCurry' True prog)+++showFlatCurry' :: Bool -> Prog -> String+showFlatCurry' b x = gshowsPrec b False x ""++gshowsPrec :: Data a => Bool -> Bool -> a -> ShowS+gshowsPrec showType d = + genericShowsPrec d `ext1Q` showsList+ `ext2Q` showsTuple+ `extQ` (const id :: SrcRef -> ShowS)+ `extQ` (const id :: [SrcRef] -> ShowS)+ `extQ` (shows :: String -> ShowS)+ `extQ` (shows :: Char -> ShowS)+ `extQ` showsQName d+ `extQ` showsVarIndex d+ + where+ showsQName :: Bool -> QName -> ShowS+ showsQName d qn@QName{modName=m,localName=n,typeofQName=t} = + if showType then showParen d (shows qn{srcRef=Nothing})+ else shows (m,n)++ showsVarIndex :: Bool -> VarIndex -> ShowS+ showsVarIndex d+ | showType = showParen d . shows+ | otherwise = shows . idxOf++ genericShowsPrec :: Data a => Bool -> a -> ShowS+ genericShowsPrec d t = let args = intersperse (showChar ' ') $+ gmapQ (gshowsPrec showType True) t in+ showParen (d && not (null args)) $+ showString (showConstr (toConstr t)) .+ (if null args then id else showChar ' ') .+ foldr (.) id args++ showsList :: Data a => [a] -> ShowS+ showsList xs = showChar '[' . + foldr (.) (showChar ']') + (intersperse (showChar ',') $ + map (gshowsPrec showType False) xs)+ ++ showsTuple :: (Data a,Data b) => (a,b) -> ShowS+ showsTuple (x,y) = showChar '(' . + gshowsPrec showType False x . + showChar ',' .+ gshowsPrec showType False y .+ showChar ')' +++newtype Q r a = Q (a -> r)+ +ext2Q :: (Data d, Typeable2 t) => (d -> q) -> + (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q+ext2Q def ext arg =+ case dataCast2 (Q ext) of+ Just (Q ext') -> ext' arg+ Nothing -> def arg++------------------------------------------------------------------------------+------------------------------------------------------------------------------+
+ src/Curry/Syntax.hs view
@@ -0,0 +1,36 @@+module Curry.Syntax(module Curry.Syntax.Type,+ parseModule, parseHeader+ ) where++import Control.Monad+import Data.List++import Curry.Base.MessageMonad+import Curry.Syntax.Type++import qualified Curry.Syntax.Parser as CSP++import Curry.Syntax.Unlit++++parseModule :: Bool -> FilePath -> String -> MsgMonad Module+parseModule likeFlat fn =+ unlitLiterate fn >=> CSP.parseSource likeFlat fn+++parseHeader :: FilePath -> String -> MsgMonad Module+parseHeader fn =+ unlitLiterate fn >=> CSP.parseHeader fn++-- Literate source files use the extension ".lcurry"+unlitLiterate :: FilePath -> String -> MsgMonad String+unlitLiterate fn s+ | isLiterateSource fn = unlit fn s+ | otherwise = return s++isLiterateSource :: FilePath -> Bool+isLiterateSource fn = litExt `isSuffixOf` fn++litExt = ".lcurry"+
+ src/Curry/Syntax/LLParseComb.lhs view
@@ -0,0 +1,290 @@+% -*- LaTeX -*-+% $Id: LLParseComb.lhs,v 1.26 2004/02/15 23:11:30 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+\nwfilename{LLParseComb.lhs}+\section{Parsing Combinators}\label{sec:ll-parsecomb}+The parsing combinators implemented in the module \texttt{LLParseComb}+are based on the LL(1) parsing combinators developed by Swierstra and+Duponcheel~\cite{SwierstraDuponcheel96:Parsers}. They have been+adapted to using continuation passing style in order to work with the+lexing combinators described in the previous section. In addition, the+facilities for error correction are omitted in this implementation.++The two functions \texttt{applyParser} and \texttt{prefixParser} use+the specified parser for parsing a string. When \texttt{applyParser}+is used, an error is reported if the parser does not consume the whole+string, whereas \texttt{prefixParser} discards the rest of the input+string in this case.+\begin{verbatim}++> module Curry.Syntax.LLParseComb(Symbol(..),Parser,+> applyParser,prefixParser, position,succeed,symbol,+> (<?>),(<|>),(<|?>),(<*>),(<\>),(<\\>),+> opt,(<$>),(<$->),(<*->),(<-*>),(<**>),(<??>),(<.>),+> many,many1, sepBy,sepBy1, chainr,chainr1,chainl,chainl1,+> bracket,ops, layoutOn,layoutOff,layoutEnd) where++> import Control.Monad+> import Data.Maybe+> import qualified Data.Set as Set+> import qualified Data.Map as Map++> import Curry.Syntax.LexComb+> import Curry.Base.MessageMonad+> import Curry.Base.Position+++> infixl 5 <\>, <\\>+> infixl 4 <*>, <$>, <$->, <*->, <-*>, <**>, <??>, <.>+> infixl 3 <|>, <|?>+> infixl 2 <?>, `opt`++\end{verbatim}+\paragraph{Parser types}+\begin{verbatim}++> class (Ord s,Show s) => Symbol s where+> isEOF :: s -> Bool++> type Empty = Bool+> type SuccessCont s a = Position -> s -> P a+> type FailureCont a = Position -> String -> P a+> type Lexer s a = SuccessCont s a -> FailureCont a -> P a+> type ParseFun s a b = (a -> SuccessCont s b) -> FailureCont b+> -> SuccessCont s b++> data Parser s a b = Parser (Maybe (ParseFun s a b))+> (Map.Map s (Lexer s b -> ParseFun s a b))++> instance Symbol s => Show (Parser s a b) where+> showsPrec p (Parser e ps) = showParen (p >= 10) $ -- $+> showString "Parser " . shows (isJust e) .+> showChar ' ' . shows (Map.keysSet ps)++> applyParser :: Symbol s => Parser s a a -> Lexer s a -> FilePath -> String+> -> MsgMonad a+> applyParser p lexer = parse (lexer (choose p lexer done failP) failP)+> where done x pos s+> | isEOF s = returnP x+> | otherwise = failP pos (unexpected s)++> prefixParser :: Symbol s => Parser s a a -> Lexer s a -> FilePath -> String+> -> MsgMonad a+> prefixParser p lexer = parse (lexer (choose p lexer discard failP) failP)+> where discard x _ _ = returnP x++> choose :: Symbol s => Parser s a b -> Lexer s b -> ParseFun s a b+> choose (Parser e ps) lexer success fail pos s =+> case Map.lookup s ps of+> Just p -> p lexer success fail pos s+> Nothing ->+> case e of+> Just p -> p success fail pos s+> Nothing -> fail pos (unexpected s)++> unexpected :: Symbol s => s -> String+> unexpected s+> | isEOF s = "Unexpected end-of-file"+> | otherwise = "Unexpected token " ++ show s++\end{verbatim}+\paragraph{Basic combinators}+\begin{verbatim}++> position :: Symbol s => Parser s Position b+> position = Parser (Just p) Map.empty+> where p success _ pos = success pos pos++> succeed :: Symbol s => a -> Parser s a b+> succeed x = Parser (Just p) Map.empty+> where p success _ = success x++> symbol :: Symbol s => s -> Parser s s a+> symbol s = Parser Nothing (Map.singleton s p)+> where p lexer success fail pos s = lexer (success s) fail++> (<?>) :: Symbol s => Parser s a b -> String -> Parser s a b+> p <?> msg = p <|> Parser (Just pfail) Map.empty+> where pfail _ fail pos _ = fail pos msg++> (<|>) :: Symbol s => Parser s a b -> Parser s a b -> Parser s a b+> Parser e1 ps1 <|> Parser e2 ps2+> | isJust e1 && isJust e2 = error "Ambiguous parser for empty word"+> | not (Set.null common) = error ("Ambiguous parser for " ++ show common)+> | otherwise = Parser (e1 `mplus` e2) (Map.union ps1 ps2)+> where common = Map.keysSet ps1 `Set.intersection` Map.keysSet ps2++\end{verbatim}+The parsing combinators presented so far require that the grammar+being parsed is LL(1). In some cases it may be difficult or even+impossible to transform a grammar into LL(1) form. As a remedy, we+include a non-deterministic version of the choice combinator in+addition to the deterministic combinator adapted from the paper. For+every symbol from the intersection of the parser's first sets, the+combinator \texttt{(<|?>)} applies both parsing functions to the input+stream and uses that one which processes the longer prefix of the+input stream irrespective of whether it succeeds or fails. If both+functions recognize the same prefix, we choose the one that succeeds+and report an ambiguous parse error if both succeed.+\begin{verbatim}++> (<|?>) :: Symbol s => Parser s a b -> Parser s a b -> Parser s a b+> Parser e1 ps1 <|?> Parser e2 ps2+> | isJust e1 && isJust e2 = error "Ambiguous parser for empty word"+> | otherwise = Parser (e1 `mplus` e2) (Map.union ps1' ps2)+> where ps1' = Map.fromList [(s,maybe p (try p) (Map.lookup s ps2))+> | (s,p) <- Map.toList ps1]+> try p1 p2 lexer success fail pos s =+> closeP1 p2s `thenP` \p2s' ->+> closeP1 p2f `thenP` \p2f' ->+> parse p1 (retry p2s') (retry p2f')+> where p2s r1 = parse p2 (select True r1) (select False r1)+> p2f r1 = parse p2 (flip (select False) r1) (select False r1)+> parse p psucc pfail =+> p lexer (successK psucc) (failK pfail) pos s+> successK k x pos s = k (pos,success x pos s)+> failK k pos msg = k (pos,fail pos msg)+> retry k (pos,p) = closeP0 p `thenP` curry k pos+> select suc (pos1,p1) (pos2,p2) =+> case pos1 `compare` pos2 of+> GT -> p1+> EQ+> | suc -> error ("Ambiguous parse before " ++ show pos1)+> | otherwise -> p1+> LT -> p2++> (<*>) :: Symbol s => Parser s (a -> b) c -> Parser s a c -> Parser s b c+> Parser (Just p1) ps1 <*> ~p2@(Parser e2 ps2) =+> Parser (fmap (seqEE p1) e2)+> (Map.union (fmap (flip seqPP p2) ps1) (fmap (seqEP p1) ps2))+> Parser Nothing ps1 <*> p2 = Parser Nothing (fmap (flip seqPP p2) ps1)++> seqEE :: Symbol s => ParseFun s (a -> b) c -> ParseFun s a c+> -> ParseFun s b c+> seqEE p1 p2 success fail = p1 (\f -> p2 (success . f) fail) fail++> seqEP :: Symbol s => ParseFun s (a -> b) c -> (Lexer s c -> ParseFun s a c)+> -> Lexer s c -> ParseFun s b c+> seqEP p1 p2 lexer success fail = p1 (\f -> p2 lexer (success . f) fail) fail++> seqPP :: Symbol s => (Lexer s c -> ParseFun s (a -> b) c) -> Parser s a c+> -> Lexer s c -> ParseFun s b c+> seqPP p1 p2 lexer success fail =+> p1 lexer (\f -> choose p2 lexer (success . f) fail) fail++\end{verbatim}+The combinators \verb|<\\>| and \verb|<\>| can be used to restrict+the first set of a parser. This is useful for combining two parsers+with an overlapping first set with the deterministic combinator <|>.+\begin{verbatim}++> (<\>) :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c+> p <\> Parser _ ps = p <\\> Map.keys ps++> (<\\>) :: Symbol s => Parser s a b -> [s] -> Parser s a b+> Parser e ps <\\> xs = Parser e (foldr Map.delete ps xs)++\end{verbatim}+\paragraph{Other combinators.}+Note that some of these combinators have not been published in the+paper, but were taken from the implementation found on the web.+\begin{verbatim}++> opt :: Symbol s => Parser s a b -> a -> Parser s a b+> p `opt` x = p <|> succeed x++> (<$>) :: Symbol s => (a -> b) -> Parser s a c -> Parser s b c+> f <$> p = succeed f <*> p++> (<$->) :: Symbol s => a -> Parser s b c -> Parser s a c+> f <$-> p = const f <$> p {-$-}++> (<*->) :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c+> p <*-> q = const <$> p <*> q {-$-}++> (<-*>) :: Symbol s => Parser s a c -> Parser s b c -> Parser s b c+> p <-*> q = const id <$> p <*> q {-$-}++> (<**>) :: Symbol s => Parser s a c -> Parser s (a -> b) c -> Parser s b c+> p <**> q = flip ($) <$> p <*> q++> (<??>) :: Symbol s => Parser s a b -> Parser s (a -> a) b -> Parser s a b+> p <??> q = p <**> (q `opt` id)++> (<.>) :: Symbol s => Parser s (a -> b) d -> Parser s (b -> c) d+> -> Parser s (a -> c) d+> p1 <.> p2 = p1 <**> ((.) <$> p2)++> many :: Symbol s => Parser s a b -> Parser s [a] b+> many p = many1 p `opt` []++> many1 :: Symbol s => Parser s a b -> Parser s [a] b+> -- many1 p = (:) <$> p <*> many p+> many1 p = (:) <$> p <*> (many1 p `opt` [])++\end{verbatim}+The first definition of \texttt{many1} is commented out because it+does not compile under nhc. This is due to a -- known -- bug in the+type checker of nhc which expects a default declaration when compiling+mutually recursive functions with class constraints. However, no such+default can be given in the above case because neither of the types+involved is a numeric type.+\begin{verbatim}++> sepBy :: Symbol s => Parser s a c -> Parser s b c -> Parser s [a] c+> p `sepBy` q = p `sepBy1` q `opt` []++> sepBy1 :: Symbol s => Parser s a c -> Parser s b c -> Parser s [a] c+> p `sepBy1` q = (:) <$> p <*> many (q <-*> p) {-$-}++> chainr :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b -> a+> -> Parser s a b+> chainr p op x = chainr1 p op `opt` x++> chainr1 :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b+> -> Parser s a b+> chainr1 p op = r+> where r = p <**> (flip <$> op <*> r `opt` id) {-$-}++> chainl :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b -> a+> -> Parser s a b+> chainl p op x = chainl1 p op `opt` x++> chainl1 :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b+> -> Parser s a b+> chainl1 p op = foldF <$> p <*> many (flip <$> op <*> p)+> where foldF x [] = x+> foldF x (f:fs) = foldF (f x) fs++> bracket :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c+> -> Parser s b c+> bracket open p close = open <-*> p <*-> close++> ops :: Symbol s => [(s,a)] -> Parser s a b+> ops [] = error "internal error: ops"+> ops [(s,x)] = x <$-> symbol s+> ops ((s,x):rest) = x <$-> symbol s <|> ops rest++\end{verbatim}+\paragraph{Layout combinators}+Note that the layout functions grab the next token (and its position).+After modifying the layout context, the continuation is called with+the same token and an undefined result.+\begin{verbatim}++> layoutOn :: Symbol s => Parser s a b+> layoutOn = Parser (Just on) Map.empty+> where on success _ pos = pushContext (column pos) . success undefined pos++> layoutOff :: Symbol s => Parser s a b+> layoutOff = Parser (Just off) Map.empty+> where off success _ pos = pushContext (-1) . success undefined pos++> layoutEnd :: Symbol s => Parser s a b+> layoutEnd = Parser (Just end) Map.empty+> where end success _ pos = popContext . success undefined pos++\end{verbatim}
+ src/Curry/Syntax/LexComb.lhs view
@@ -0,0 +1,104 @@+% -*- LaTeX -*-+% $Id: LexComb.lhs,v 1.16 2004/01/20 16:44:14 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+\nwfilename{LexComb.lhs}+\section{Lexing combinators}+The module \texttt{LexComb} provides the basic types and combinators+to implement the lexers. The combinators use continuation passing code+in a monadic style. The first argument of the continuation function is+the string to be parsed, the second is the current position, and the+third is a flag which signals the lexer that it is lexing the+beginning of a line and therefore has to check for layout tokens. The+fourth argument is a stack of indentations that is used to handle+nested layout groups.+\begin{verbatim}++> module Curry.Syntax.LexComb where++> import Data.Char++> import Curry.Base.MessageMonad+> import Curry.Base.Position++> infixl 1 `thenP`, `thenP_`++> type Indent = Int+> type Context = [Indent]+> type P a = Position -> String -> Bool -> Context -> MsgMonad a++> parse :: P a -> FilePath -> String -> MsgMonad a+> parse p fn s = p (first fn) s False []++\end{verbatim}+Monad functions for the lexer.+\begin{verbatim}++> returnP :: a -> P a+> returnP x _ _ _ _ = return x++> thenP :: P a -> (a -> P b) -> P b+> thenP lex k pos s bol ctxt = lex pos s bol ctxt >>= \x -> k x pos s bol ctxt++> thenP_ :: P a -> P b -> P b+> p1 `thenP_` p2 = p1 `thenP` \_ -> p2++> failP :: Position -> String -> P a+> failP pos msg _ _ _ _ = failWith (parseError pos msg)++> closeP0 :: P a -> P (P a)+> closeP0 lex pos s bol ctxt = return (\_ _ _ _ -> lex pos s bol ctxt)++> closeP1 :: (a -> P b) -> P (a -> P b)+> closeP1 f pos s bol ctxt = return (\x _ _ _ _ -> f x pos s bol ctxt)++> parseError :: Position -> String -> String+> parseError p what = "\n" ++ show p ++ ": " ++ what++\end{verbatim}+Combinators that handle layout.+\begin{verbatim}++> pushContext :: Int -> P a -> P a+> pushContext col cont pos s bol ctxt = cont pos s bol (col:ctxt)++> popContext :: P a -> P a+> popContext cont pos s bol (_:ctxt) = cont pos s bol ctxt+> popContext cont pos s bol [] = +> error "parse error: popping layout from empty context stack. \+> \Perhaps you have inserted too many '}'?"++\end{verbatim}+Conversions from strings into numbers.+\begin{verbatim}++> convertSignedIntegral :: Num a => a -> String -> a+> convertSignedIntegral b ('+':s) = convertIntegral b s+> convertSignedIntegral b ('-':s) = - convertIntegral b s+> convertSignedIntegral b s = convertIntegral b s++> convertIntegral :: Num a => a -> String -> a+> convertIntegral b = foldl op 0+> where m `op` n | isDigit n = b * m + fromIntegral (ord n - ord0)+> | isUpper n = b * m + fromIntegral (ord n - ordA)+> | otherwise = b * m + fromIntegral (ord n - orda)+> ord0 = ord '0'+> ordA = ord 'A' - 10+> orda = ord 'a' - 10++> convertSignedFloating :: Fractional a => String -> String -> Int -> a+> convertSignedFloating ('+':m) f e = convertFloating m f e+> convertSignedFloating ('-':m) f e = - convertFloating m f e+> convertSignedFloating m f e = convertFloating m f e++> convertFloating :: Fractional a => String -> String -> Int -> a+> convertFloating m f e+> | e' == 0 = m'+> | e' > 0 = m' * 10^e'+> | otherwise = m' / 10^(-e')+> where m' = convertIntegral 10 (m ++ f)+> e' = e - length f++\end{verbatim}
+ src/Curry/Syntax/Lexer.lhs view
@@ -0,0 +1,630 @@++% $Id: CurryLexer.lhs,v 1.40 2004/03/04 22:39:12 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{CurryLexer.lhs}+\section{A Lexer for Curry}+In this section a lexer for Curry is implemented.+\begin{verbatim}+ +> module Curry.Syntax.Lexer (lexFile,lexer, Token (..), Category(..), Attributes(..)) where++> import Data.Char +> import Data.List+> import qualified Data.Map as Map++> import Curry.Syntax.LexComb+> import Curry.Base.Position++++\end{verbatim}+\paragraph{Tokens} Note that the equality and ordering instances of+\texttt{Token} disregard the attributes.+\begin{verbatim}++> data Token = Token Category Attributes++> instance Eq Token where+> Token t1 _ == Token t2 _ = t1 == t2+> instance Ord Token where+> Token t1 _ `compare` Token t2 _ = t1 `compare` t2++> data Category =+> -- literals+> CharTok | IntTok | FloatTok | IntegerTok | StringTok+> -- identifiers+> | Id | QId | Sym | QSym+> -- punctuation symbols+> | LeftParen | RightParen | Semicolon | LeftBrace | RightBrace+> | LeftBracket | RightBracket | Comma | Underscore | Backquote+> -- turn off layout (inserted by bbr)+> | LeftBraceSemicolon+> -- virtual punctation (inserted by layout)+> | VSemicolon | VRightBrace+> -- reserved identifiers+> | KW_case | KW_choice | KW_data | KW_do | KW_else | KW_eval | KW_external+> | KW_free | KW_if | KW_import | KW_in | KW_infix | KW_infixl | KW_infixr+> | KW_let | KW_module | KW_newtype | KW_of | KW_rigid | KW_then | KW_type+> | KW_where+> -- reserved operators+> | At | Colon | DotDot | DoubleColon | Equals | Backslash | Bar+> | LeftArrow | RightArrow | Tilde | Binds+> -- special identifiers+> | Id_as | Id_ccall | Id_forall | Id_hiding | Id_interface | Id_primitive+> | Id_qualified+> -- special operators+> | Sym_Dot | Sym_Minus | Sym_MinusDot+> -- end-of-file token+> | EOF+> -- comments (only for full lexer) inserted by men & bbr+> | LineComment | NestedComment +> deriving (Eq,Ord)++\end{verbatim}+There are different kinds of attributes associated with the tokens.+Most attributes simply save the string corresponding to the token.+However, for qualified identifiers, we also record the list of module+qualifiers. The values corresponding to a literal token are properly+converted already. To simplify the creation and extraction of+attribute values we make use of records.+\begin{verbatim}++> data Attributes =+> NoAttributes+> | CharAttributes{ cval :: Char, original :: String}+> | IntAttributes{ ival :: Int , original :: String}+> | FloatAttributes{ fval :: Double, original :: String}+> | IntegerAttributes{ intval :: Integer, original :: String}+> | StringAttributes{ sval :: String, original :: String}+> | IdentAttributes{ modul :: [String], sval :: String}++> instance Show Attributes where+> showsPrec _ NoAttributes = showChar '_'+> showsPrec _ (CharAttributes cval _) = shows cval+> showsPrec _ (IntAttributes ival _) = shows ival+> showsPrec _ (FloatAttributes fval _) = shows fval+> showsPrec _ (IntegerAttributes intval _) = shows intval+> showsPrec _ (StringAttributes sval _) = shows sval+> showsPrec _ (IdentAttributes mIdent ident) =+> showString ("`" ++ concat (intersperse "." (mIdent ++ [ident])) ++ "'")++\end{verbatim}+The following functions can be used to construct tokens with+specific attributes.+\begin{verbatim}++> tok :: Category -> Token+> tok t = Token t NoAttributes++> idTok :: Category -> [String] -> String -> Token+> idTok t mIdent ident = Token t IdentAttributes{ modul = mIdent, sval = ident }++> charTok :: Char -> String -> Token+> charTok c o = Token CharTok CharAttributes{ cval = c, original = o }++> intTok :: Int -> String -> Token+> intTok base digits =+> Token IntTok IntAttributes{ ival = convertIntegral base digits,+> original = digits}++> floatTok :: String -> String -> Int -> String -> Token+> floatTok mant frac exp rest =+> Token FloatTok FloatAttributes{ fval = convertFloating mant frac exp, +> original = mant++"."++frac++rest}+ +> integerTok :: Integer -> String -> Token+> integerTok base digits =+> Token IntegerTok+> IntegerAttributes{intval = (convertIntegral base digits) :: Integer,+> original = digits}++> stringTok :: String -> String -> Token+> stringTok cs o = Token StringTok StringAttributes{ sval = cs, original = o }++> lineCommentTok :: String -> Token+> lineCommentTok s = Token LineComment StringAttributes{ sval = s, original = s}++> nestedCommentTok :: String -> Token+> nestedCommentTok s = Token NestedComment StringAttributes{ sval = s, original = s }++\end{verbatim}+The \texttt{Show} instance of \texttt{Token} is designed to display+all tokens in their source representation.+\begin{verbatim}++> instance Show Token where+> showsPrec _ (Token Id a) = showString "identifier " . shows a+> showsPrec _ (Token QId a) = showString "qualified identifier " . shows a+> showsPrec _ (Token Sym a) = showString "operator " . shows a+> showsPrec _ (Token QSym a) = showString "qualified operator " . shows a+> showsPrec _ (Token IntTok a) = showString "integer " . shows a+> showsPrec _ (Token FloatTok a) = showString "float " . shows a+> showsPrec _ (Token CharTok a) = showString "character " . shows a+> showsPrec _ (Token IntegerTok a) = showString "integer " . shows a+> showsPrec _ (Token StringTok a) = showString "string " . shows a+> showsPrec _ (Token LeftParen _) = showString "`('"+> showsPrec _ (Token RightParen _) = showString "`)'"+> showsPrec _ (Token Semicolon _) = showString "`;'"+> showsPrec _ (Token LeftBrace _) = showString "`{'"+> showsPrec _ (Token RightBrace _) = showString "`}'"+> showsPrec _ (Token LeftBracket _) = showString "`['"+> showsPrec _ (Token RightBracket _) = showString "`]'"+> showsPrec _ (Token Comma _) = showString "`,'"+> showsPrec _ (Token Underscore _) = showString "`_'"+> showsPrec _ (Token Backquote _) = showString "``'"+> showsPrec _ (Token VSemicolon _) =+> showString "`;' (inserted due to layout)"+> showsPrec _ (Token VRightBrace _) =+> showString "`}' (inserted due to layout)"+> showsPrec _ (Token At _) = showString "`@'"+> showsPrec _ (Token Colon _) = showString "`:'"+> showsPrec _ (Token DotDot _) = showString "`..'"+> showsPrec _ (Token DoubleColon _) = showString "`::'"+> showsPrec _ (Token Equals _) = showString "`='"+> showsPrec _ (Token Backslash _) = showString "`\\'"+> showsPrec _ (Token Bar _) = showString "`|'"+> showsPrec _ (Token LeftArrow _) = showString "`<-'"+> showsPrec _ (Token RightArrow _) = showString "`->'"+> showsPrec _ (Token Tilde _) = showString "`~'"+> showsPrec _ (Token Binds _) = showString "`:='"+> showsPrec _ (Token Sym_Dot _) = showString "operator `.'"+> showsPrec _ (Token Sym_Minus _) = showString "operator `-'"+> showsPrec _ (Token Sym_MinusDot _) = showString "operator `-.'"+> showsPrec _ (Token KW_case _) = showString "`case'"+> showsPrec _ (Token KW_choice _) = showString "`choice'"+> showsPrec _ (Token KW_data _) = showString "`data'"+> showsPrec _ (Token KW_do _) = showString "`do'"+> showsPrec _ (Token KW_else _) = showString "`else'"+> showsPrec _ (Token KW_eval _) = showString "`eval'"+> showsPrec _ (Token KW_external _) = showString "`external'"+> showsPrec _ (Token KW_free _) = showString "`free'"+> showsPrec _ (Token KW_if _) = showString "`if'"+> showsPrec _ (Token KW_import _) = showString "`import'"+> showsPrec _ (Token KW_in _) = showString "`in'"+> showsPrec _ (Token KW_infix _) = showString "`infix'"+> showsPrec _ (Token KW_infixl _) = showString "`infixl'"+> showsPrec _ (Token KW_infixr _) = showString "`infixr'"+> showsPrec _ (Token KW_let _) = showString "`let'"+> showsPrec _ (Token KW_module _) = showString "`module'"+> showsPrec _ (Token KW_newtype _) = showString "`newtype'"+> showsPrec _ (Token KW_of _) = showString "`of'"+> showsPrec _ (Token KW_rigid _) = showString "`rigid'"+> showsPrec _ (Token KW_then _) = showString "`then'"+> showsPrec _ (Token KW_type _) = showString "`type'"+> showsPrec _ (Token KW_where _) = showString "`where'"+> showsPrec _ (Token Id_as _) = showString "identifier `as'"+> showsPrec _ (Token Id_ccall _) = showString "identifier `ccall'"+> showsPrec _ (Token Id_forall _) = showString "identifier `forall'"+> showsPrec _ (Token Id_hiding _) = showString "identifier `hiding'"+> showsPrec _ (Token Id_interface _) = showString "identifier `interface'"+> showsPrec _ (Token Id_primitive _) = showString "identifier `primitive'"+> showsPrec _ (Token Id_qualified _) = showString "identifier `qualified'"+> showsPrec _ (Token EOF _) = showString "<end-of-file>"+> showsPrec _ (Token LineComment a) = shows a+> showsPrec _ (Token NestedComment a) = shows a++\end{verbatim}+Tables for reserved operators and identifiers+\begin{verbatim}++> reserved_ops, reserved_and_special_ops :: Map.Map String Category+> reserved_ops = Map.fromList [+> ("@", At),+> ("::", DoubleColon),+> ("..", DotDot),+> ("=", Equals),+> ("\\", Backslash),+> ("|", Bar),+> ("<-", LeftArrow),+> ("->", RightArrow),+> ("~", Tilde),+> (":=", Binds)+> ]+> reserved_and_special_ops = foldr (uncurry Map.insert) reserved_ops [+> (":", Colon),+> (".", Sym_Dot),+> ("-", Sym_Minus),+> ("-.", Sym_MinusDot)+> ]++> reserved_ids, reserved_and_special_ids :: Map.Map String Category+> reserved_ids = Map.fromList [+> ("case", KW_case),+> ("choice", KW_choice),+> ("data", KW_data),+> ("do", KW_do),+> ("else", KW_else),+> ("eval", KW_eval),+> ("external", KW_external),+> ("free", KW_free),+> ("if", KW_if),+> ("import", KW_import),+> ("in", KW_in),+> ("infix", KW_infix),+> ("infixl", KW_infixl),+> ("infixr", KW_infixr),+> ("let", KW_let),+> ("module", KW_module),+> ("newtype", KW_newtype),+> ("of", KW_of),+> ("rigid", KW_rigid),+> ("then", KW_then),+> ("type", KW_type),+> ("where", KW_where)+> ]+> reserved_and_special_ids = foldr (uncurry Map.insert) reserved_ids [+> ("as", Id_as),+> ("ccall", Id_ccall),+> ("forall", Id_forall),+> ("hiding", Id_hiding),+> ("interface", Id_interface),+> ("primitive", Id_primitive),+> ("qualified", Id_qualified)+> ]++\end{verbatim}+Character classes+\begin{verbatim}++> isIdent, isSym, isOctit, isHexit :: Char -> Bool+> isIdent c = isAlphaNum c || c `elem` "'_"+> isSym c = c `elem` "~!@#$%^&*+-=<>:?./|\\" {-$-}+> isOctit c = c >= '0' && c <= '7'+> isHexit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'++inserted for full lexing (men&bbr)++> isLineComment, isNestedComment :: String -> Bool+> isLineComment ('-':'-':_) = True+> isLineComment _ = False+> isNestedComment ('{':'-':s) = True+> isNestedComment _ = False+++\end{verbatim}+Lexing functions+\begin{verbatim}++> type SuccessP a = Position -> Token -> P a+> type FailP a = Position -> String -> P a++> lexFile :: P [(Position,Token)]+> lexFile = fullLexer tokens failP+> where tokens p t@(Token c _)+> | c == EOF = returnP [(p,t)]+> | otherwise = lexFile `thenP` returnP . ((p,t):)++> lexer :: SuccessP a -> FailP a -> P a+> lexer success fail = skipBlanks+> where -- skipBlanks moves past whitespace and comments+> skipBlanks p [] bol = success p (tok EOF) p [] bol+> skipBlanks p ('\t':s) bol = skipBlanks (tab p) s bol+> skipBlanks p ('\n':s) bol = skipBlanks (nl p) s True+> skipBlanks p ('-':'-':s) bol =+> skipBlanks (nl p) (tail' (dropWhile (/= '\n') s)) True+> skipBlanks p ('{':'-':s) bol =+> nestedComment p skipBlanks fail (incr p 2) s bol+> skipBlanks p (c:s) bol+> | isSpace c = skipBlanks (next p) s bol+> | otherwise =+> (if bol then lexBOL else lexToken) success fail p (c:s) bol+> tail' [] = []+> tail' (_:tl) = tl++> fullLexer :: SuccessP a -> FailP a -> P a+> fullLexer success fail = skipBlanks+> where -- skipBlanks moves past whitespace +> skipBlanks p [] bol = success p (tok EOF) p [] bol+> skipBlanks p ('\t':s) bol = skipBlanks (tab p) s bol+> skipBlanks p ('\n':s) bol = skipBlanks (nl p) s True+> skipBlanks p s@('-':'-':_) bol = lexLineComment success p s bol+> skipBlanks p s@('{':'-':_) bol =+> lexNestedComment 0 id p success fail p s bol+> skipBlanks p (c:s) bol+> | isSpace c = skipBlanks (next p) s bol+> | otherwise =+> (if bol then lexBOL else lexToken) success fail p (c:s) bol+> tail' [] = []+> tail' (_:tl) = tl++> lexLineComment :: SuccessP a -> P a+> lexLineComment success p s = case break (=='\n') s of+> (comment,rest) -> success p (lineCommentTok comment) (incr p (length comment)) rest+ +> lexNestedComment :: Int -> (String -> String) -> +> Position -> SuccessP a -> FailP a -> P a+> lexNestedComment 1 comment p0 success fail p ('-':'}':s) = +> success p0 (nestedCommentTok (comment "-}") ) (incr p 2) s +> lexNestedComment n comment p0 success fail p ('{':'-':s) = +> lexNestedComment (n+1) (comment . ("{-"++)) p0 success fail (incr p 2) s+> lexNestedComment n comment p0 success fail p ('-':'}':s) = +> lexNestedComment (n-1) (comment . ("-}"++)) p0 success fail (incr p 2) s+> lexNestedComment n comment p0 success fail p (c@'\t':s) = +> lexNestedComment n (comment . (c:)) p0 success fail (tab p) s+> lexNestedComment n comment p0 success fail p (c@'\n':s) = +> lexNestedComment n (comment . (c:)) p0 success fail (nl p) s+> lexNestedComment n comment p0 success fail p (c:s) = +> lexNestedComment n (comment . (c:)) p0 success fail (next p) s+> lexNestedComment n comment p0 success fail p "" = +> fail p0 "Unterminated nested comment" p []++> nestedComment :: Position -> P a -> FailP a -> P a+> nestedComment p0 success fail p ('-':'}':s) = success (incr p 2) s+> nestedComment p0 success fail p ('{':'-':s) =+> nestedComment p (nestedComment p0 success fail) fail (incr p 2) s+> nestedComment p0 success fail p ('\t':s) =+> nestedComment p0 success fail (tab p) s+> nestedComment p0 success fail p ('\n':s) =+> nestedComment p0 success fail (nl p) s+> nestedComment p0 success fail p (_:s) =+> nestedComment p0 success fail (next p) s+> nestedComment p0 success fail p [] =+> fail p0 "Unterminated nested comment at end-of-file" p []+++> lexBOL :: SuccessP a -> FailP a -> P a+> lexBOL success fail p s _ [] = lexToken success fail p s False []+> lexBOL success fail p s _ ctxt@(n:rest)+> | col < n = success p (tok VRightBrace) p s True rest+> | col == n = success p (tok VSemicolon) p s False ctxt+> | otherwise = lexToken success fail p s False ctxt+> where col = column p++> lexToken :: SuccessP a -> FailP a -> P a+> lexToken success fail p [] = success p (tok EOF) p []+> lexToken success fail p (c:s)+> | c == '(' = token LeftParen+> | c == ')' = token RightParen+> | c == ',' = token Comma+> | c == ';' = token Semicolon+> | c == '[' = token LeftBracket+> | c == ']' = token RightBracket+> | c == '_' = token Underscore+> | c == '`' = token Backquote+> | c == '{' = lexLeftBrace (token LeftBrace) (next p) (success p) s +> | c == '}' = \bol -> token RightBrace bol . drop 1+> | c == '\'' = lexChar p success fail (next p) s+> | c == '\"' = lexString p success fail (next p) s+> | isAlpha c = lexIdent (success p) p (c:s)+> | isSym c = lexSym (success p) p (c:s)+> | isDigit c = lexNumber (success p) p (c:s)+> | otherwise = fail p ("Illegal character " ++ show c) p s+> where token t = success p (tok t) (next p) s++> lexIdent :: (Token -> P a) -> P a+> lexIdent cont p s =+> maybe (lexOptQual cont (token Id) [ident]) (cont . token)+> (Map.lookup ident reserved_and_special_ids)+> (incr p (length ident)) rest+> where (ident,rest) = span isIdent s+> token t = idTok t [] ident++> lexSym :: (Token -> P a) -> P a+> lexSym cont p s =+> cont (idTok (maybe Sym id (Map.lookup sym reserved_and_special_ops)) [] sym)+> (incr p (length sym)) rest+> where (sym,rest) = span isSym s++> lexLeftBrace leftBrace _ _ [] = leftBrace+> lexLeftBrace leftBrace p cont (c:s) +> | c==';' = cont (tok LeftBraceSemicolon) (next p) s+> | otherwise = leftBrace++\end{verbatim}+{\em Note:} the function \texttt{lexOptQual} has been extended to provide+the qualified use of the Prelude list operators and tuples.+\begin{verbatim}++> lexOptQual :: (Token -> P a) -> Token -> [String] -> P a+> lexOptQual cont token mIdent p ('.':c:s)+> | isAlpha c = lexQualIdent cont identCont mIdent (next p) (c:s)+> | isSym c = lexQualSym cont identCont mIdent (next p) (c:s)+> | c=='(' || c=='[' +> = lexQualPreludeSym cont token identCont mIdent (next p) (c:s)+> where identCont _ _ = cont token p ('.':c:s)+> lexOptQual cont token mIdent p s = cont token p s++> lexQualIdent :: (Token -> P a) -> P a -> [String] -> P a+> lexQualIdent cont identCont mIdent p s =+> maybe (lexOptQual cont (idTok QId mIdent ident) (mIdent ++ [ident]))+> (const identCont)+> (Map.lookup ident reserved_ids)+> (incr p (length ident)) rest+> where (ident,rest) = span isIdent s++> lexQualSym :: (Token -> P a) -> P a -> [String] -> P a+> lexQualSym cont identCont mIdent p s =+> maybe (cont (idTok QSym mIdent sym)) (const identCont)+> (Map.lookup sym reserved_ops)+> (incr p (length sym)) rest+> where (sym,rest) = span isSym s+++> lexQualPreludeSym :: (Token -> P a) -> Token -> P a -> [String] -> P a+> lexQualPreludeSym cont _ identCont mIdent p ('[':']':rest) =+> cont (idTok QId mIdent "[]") (incr p 2) rest+> lexQualPreludeSym cont _ identCont mIdent p ('(':rest)+> | not (null rest') && head rest'==')' +> = cont (idTok QId mIdent ('(':tup++")")) (incr p (length tup+2)) (tail rest')+> where (tup,rest') = span (==',') rest+> lexQualPreludeSym cont token _ _ p s = cont token p s+++\end{verbatim}+{\em Note:} since Curry allows an unlimited range of integer numbers,+read numbers must be converted to Haskell type \texttt{Integer}.+\begin{verbatim}++> lexNumber :: (Token -> P a) -> P a+> lexNumber cont p ('0':c:s)+> | c `elem` "oO" = lexOctal cont nullCont (incr p 2) s+> | c `elem` "xX" = lexHexadecimal cont nullCont (incr p 2) s+> where nullCont _ _ = cont (intTok 10 "0") (next p) (c:s)+> lexNumber cont p s+> = lexOptFraction cont (integerTok 10 digits) digits+> (incr p (length digits)) rest+> where (digits,rest) = span isDigit s+> num = (read digits) :: Integer++> lexOctal :: (Token -> P a) -> P a -> P a+> lexOctal cont nullCont p s+> | null digits = nullCont undefined undefined+> | otherwise = cont (integerTok 8 digits) (incr p (length digits)) rest+> where (digits,rest) = span isOctit s++> lexHexadecimal :: (Token -> P a) -> P a -> P a+> lexHexadecimal cont nullCont p s+> | null digits = nullCont undefined undefined+> | otherwise = cont (integerTok 16 digits) (incr p (length digits)) rest+> where (digits,rest) = span isHexit s++> lexOptFraction :: (Token -> P a) -> Token -> String -> P a+> lexOptFraction cont _ mant p ('.':c:s)+> | isDigit c = lexOptExponent cont (floatTok mant frac 0 "") mant frac+> (incr p (length frac+1)) rest+> where (frac,rest) = span isDigit (c:s)+> lexOptFraction cont token mant p (c:s)+> | c `elem` "eE" = lexSignedExponent cont intCont mant "" [c] (next p) s+> where intCont _ _ = cont token p (c:s)+> lexOptFraction cont token _ p s = cont token p s++> lexOptExponent :: (Token -> P a) -> Token -> String -> String -> P a+> lexOptExponent cont token mant frac p (c:s)+> | c `elem` "eE" = lexSignedExponent cont floatCont mant frac [c] (next p) s+> where floatCont _ _ = cont token p (c:s)+> lexOptExponent cont token mant frac p s = cont token p s++> lexSignedExponent :: (Token -> P a) -> P a -> String -> String -> String -> P a+> lexSignedExponent cont floatCont mant frac e p ('+':c:s)+> | isDigit c = lexExponent cont mant frac (e++"+") id (next p) (c:s)+> lexSignedExponent cont floatCont mant frac e p ('-':c:s)+> | isDigit c = lexExponent cont mant frac (e++"-") negate (next p) (c:s)+> lexSignedExponent cont floatCont mant frac e p (c:s)+> | isDigit c = lexExponent cont mant frac e id p (c:s)+> lexSignedExponent cont floatCont mant frac e p s = floatCont p s++> lexExponent :: (Token -> P a) -> String -> String -> String -> (Int -> Int) -> P a+> lexExponent cont mant frac e expSign p s =+> cont (floatTok mant frac exp (e++digits)) (incr p (length digits)) rest+> where (digits,rest) = span isDigit s+> exp = expSign (convertIntegral 10 digits)++> lexChar :: Position -> SuccessP a -> FailP a -> P a+> lexChar p0 success fail p [] = fail p0 "Illegal character constant" p []+> lexChar p0 success fail p (c:s)+> | c == '\\' = lexEscape p (lexCharEnd p0 success fail) fail (next p) s+> | c == '\n' = fail p0 "Illegal character constant" p (c:s)+> | c == '\t' = lexCharEnd p0 success fail c "\t" (tab p) s+> | otherwise = lexCharEnd p0 success fail c [c] (next p) s++> lexCharEnd :: Position -> SuccessP a -> FailP a -> Char -> String -> P a+> lexCharEnd p0 success fail c o p ('\'':s) = success p0 (charTok c o) (next p) s+> lexCharEnd p0 success fail c o p s =+> fail p0 "Improperly terminated character constant" p s++> lexString :: Position -> SuccessP a -> FailP a -> P a+> lexString p0 success fail = lexStringRest p0 success fail "" id++> lexStringRest :: Position -> SuccessP a -> FailP a -> String -> (String -> String) -> P a+> lexStringRest p0 success fail s0 so p [] = +> fail p0 "Improperly terminated string constant" p []+> lexStringRest p0 success fail s0 so p (c:s)+> | c == '\\' =+> lexStringEscape p (lexStringRest p0 success fail) fail s0 so (next p) s+> | c == '\"' = success p0 (stringTok (reverse s0) (so "")) (next p) s+> | c == '\n' = fail p0 "Improperly terminated string constant" p []+> | c == '\t' = lexStringRest p0 success fail (c:s0) (so . (c:)) (tab p) s+> | otherwise = lexStringRest p0 success fail (c:s0) (so . (c:)) (next p) s++> lexStringEscape :: Position -> (String -> (String -> String) -> P a) -> FailP a -> +> String -> (String -> String) -> P a+> lexStringEscape p0 success fail s0 so p [] = lexEscape p0 undefined fail p []+> lexStringEscape p0 success fail s0 so p (c:s)+> | c == '&' = success s0 (so . ("\\&"++)) (next p) s+> | isSpace c = lexStringGap (success s0) fail so p (c:s)+> | otherwise = lexEscape p0 (\ c' s' -> success (c':s0) (so . (s'++))) fail p (c:s)++> lexStringGap :: ((String -> String) -> P a) -> FailP a -> (String -> String) -> P a+> lexStringGap success fail so p [] = fail p "End of file in string gap" p []+> lexStringGap success fail so p (c:s)+> | c == '\\' = success (so . (c:)) (next p) s+> | c == '\t' = lexStringGap success fail (so . (c:)) (tab p) s+> | c == '\n' = lexStringGap success fail (so . (c:)) (nl p) s+> | isSpace c = lexStringGap success fail (so . (c:)) (next p) s+> | otherwise = fail p ("Illegal character in string gap " ++ show c) p s++> lexEscape :: Position -> (Char -> String -> P a) -> FailP a -> P a+> lexEscape p0 success fail p ('a':s) = success '\a' "\\a" (next p) s+> lexEscape p0 success fail p ('b':s) = success '\b' "\\b" (next p) s+> lexEscape p0 success fail p ('f':s) = success '\f' "\\f" (next p) s+> lexEscape p0 success fail p ('n':s) = success '\n' "\\n" (next p) s+> lexEscape p0 success fail p ('r':s) = success '\r' "\\r" (next p) s+> lexEscape p0 success fail p ('t':s) = success '\t' "\\t" (next p) s+> lexEscape p0 success fail p ('v':s) = success '\v' "\\v" (next p) s+> lexEscape p0 success fail p ('\\':s) = success '\\' "\\\\" (next p) s+> lexEscape p0 success fail p ('"':s) = success '\"' "\\\"" (next p) s+> lexEscape p0 success fail p ('\'':s) = success '\'' "\\\'" (next p) s+> lexEscape p0 success fail p ('^':c:s)+> | isUpper c || c `elem` "@[\\]^_" =+> success (chr (ord c `mod` 32)) ("\\^"++[c]) (incr p 2) s+> lexEscape p0 success fail p ('o':c:s)+> | isOctit c = numEscape p0 success fail 8 isOctit ("\\o"++) (next p) (c:s)+> lexEscape p0 success fail p ('x':c:s)+> | isHexit c = numEscape p0 success fail 16 isHexit ("\\x"++) (next p) (c:s)+> lexEscape p0 success fail p (c:s)+> | isDigit c = numEscape p0 success fail 10 isDigit ("\\"++) p (c:s)+> lexEscape p0 success fail p s = asciiEscape p0 success fail p s++> asciiEscape :: Position -> (Char -> String -> P a) -> FailP a -> P a+> asciiEscape p0 success fail p ('N':'U':'L':s) = success '\NUL' "\\NUL" (incr p 3) s+> asciiEscape p0 success fail p ('S':'O':'H':s) = success '\SOH' "\\SOH" (incr p 3) s+> asciiEscape p0 success fail p ('S':'T':'X':s) = success '\STX' "\\STX" (incr p 3) s+> asciiEscape p0 success fail p ('E':'T':'X':s) = success '\ETX' "\\ETX" (incr p 3) s+> asciiEscape p0 success fail p ('E':'O':'T':s) = success '\EOT' "\\EOT" (incr p 3) s+> asciiEscape p0 success fail p ('E':'N':'Q':s) = success '\ENQ' "\\ENQ" (incr p 3) s+> asciiEscape p0 success fail p ('A':'C':'K':s) = success '\ACK' "\\ACK" (incr p 3) s +> asciiEscape p0 success fail p ('B':'E':'L':s) = success '\BEL' "\\BEL" (incr p 3) s+> asciiEscape p0 success fail p ('B':'S':s) = success '\BS' "\\BS" (incr p 2) s+> asciiEscape p0 success fail p ('H':'T':s) = success '\HT' "\\HT" (incr p 2) s+> asciiEscape p0 success fail p ('L':'F':s) = success '\LF' "\\LF" (incr p 2) s+> asciiEscape p0 success fail p ('V':'T':s) = success '\VT' "\\VT" (incr p 2) s+> asciiEscape p0 success fail p ('F':'F':s) = success '\FF' "\\FF" (incr p 2) s+> asciiEscape p0 success fail p ('C':'R':s) = success '\CR' "\\CR" (incr p 2) s+> asciiEscape p0 success fail p ('S':'O':s) = success '\SO' "\\SO" (incr p 2) s+> asciiEscape p0 success fail p ('S':'I':s) = success '\SI' "\\SI" (incr p 2) s+> asciiEscape p0 success fail p ('D':'L':'E':s) = success '\DLE' "\\DLE" (incr p 3) s +> asciiEscape p0 success fail p ('D':'C':'1':s) = success '\DC1' "\\DC1" (incr p 3) s+> asciiEscape p0 success fail p ('D':'C':'2':s) = success '\DC2' "\\DC2" (incr p 3) s+> asciiEscape p0 success fail p ('D':'C':'3':s) = success '\DC3' "\\DC3" (incr p 3) s+> asciiEscape p0 success fail p ('D':'C':'4':s) = success '\DC4' "\\DC4" (incr p 3) s+> asciiEscape p0 success fail p ('N':'A':'K':s) = success '\NAK' "\\NAK" (incr p 3) s+> asciiEscape p0 success fail p ('S':'Y':'N':s) = success '\SYN' "\\SYN" (incr p 3) s+> asciiEscape p0 success fail p ('E':'T':'B':s) = success '\ETB' "\\ETB" (incr p 3) s+> asciiEscape p0 success fail p ('C':'A':'N':s) = success '\CAN' "\\CAN" (incr p 3) s +> asciiEscape p0 success fail p ('E':'M':s) = success '\EM' "\\EM" (incr p 2) s+> asciiEscape p0 success fail p ('S':'U':'B':s) = success '\SUB' "\\SUB" (incr p 3) s+> asciiEscape p0 success fail p ('E':'S':'C':s) = success '\ESC' "\\ESC" (incr p 3) s+> asciiEscape p0 success fail p ('F':'S':s) = success '\FS' "\\FS" (incr p 2) s+> asciiEscape p0 success fail p ('G':'S':s) = success '\GS' "\\GS" (incr p 2) s+> asciiEscape p0 success fail p ('R':'S':s) = success '\RS' "\\RS" (incr p 2) s+> asciiEscape p0 success fail p ('U':'S':s) = success '\US' "\\US" (incr p 2) s+> asciiEscape p0 success fail p ('S':'P':s) = success '\SP' "\\SP" (incr p 2) s+> asciiEscape p0 success fail p ('D':'E':'L':s) = success '\DEL' "\\DEL" (incr p 3) s+> asciiEscape p0 success fail p s = fail p0 "Illegal escape sequence" p s++> numEscape :: Position -> (Char -> String -> P a) -> FailP a -> Int+> -> (Char -> Bool) -> (String -> String) -> P a+> numEscape p0 success fail b isDigit so p s+> | n >= min && n <= max = success (chr n) (so digits) (incr p (length digits)) rest+> | otherwise = fail p0 "Numeric escape out-of-range" p s+> where (digits,rest) = span isDigit s+> n = convertIntegral b digits+> min = ord minBound+> max = ord maxBound++\end{verbatim}
+ src/Curry/Syntax/Parser.lhs view
@@ -0,0 +1,806 @@++% $Id: CurryParser.lhs,v 1.75 2004/02/15 23:11:28 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{CurryParser.lhs}+\section{A Parser for Curry}+The Curry parser is implemented using the (mostly) LL(1) parsing+combinators described in appendix~\ref{sec:ll-parsecomb}.+\begin{verbatim}++> module Curry.Syntax.Parser where++> import Curry.Base.Ident+> import Curry.Base.Position+> import Curry.Base.MessageMonad+> import Curry.Syntax.LLParseComb+> import Curry.Syntax.Type+> import Curry.Syntax.Lexer++> instance Symbol Token where+> isEOF (Token c _) = c == EOF++\end{verbatim}+\paragraph{Modules}+\begin{verbatim}++> parseSource :: Bool -> FilePath -> String -> MsgMonad Module+> parseSource flat path = +> fmap addSrcRefs . applyParser ( moduleHeader <*> decls flat) lexer path++> parseHeader :: FilePath -> String -> MsgMonad Module+> parseHeader = prefixParser (moduleHeader <*->+> (leftBrace `opt` undefined) <*>+> many (importDecl <*-> many semicolon))+> lexer++> moduleHeader :: Parser Token ([Decl] -> Module) a+> moduleHeader = Module <$-> token KW_module+> <*> (mIdent <?> "module name expected")+> <*> ((Just <$> exportSpec) `opt` Nothing)+> <*-> (token KW_where <?> "where expected")+> `opt` Module mainMIdent Nothing++> exportSpec :: Parser Token ExportSpec a+> exportSpec = Exporting <$> position <*> parens (export `sepBy` comma)++> export :: Parser Token Export a+> export = qtycon <**> (parens spec `opt` Export)+> <|> Export <$> qfun <\> qtycon+> <|> ExportModule <$-> token KW_module <*> mIdent+> where spec = ExportTypeAll <$-> token DotDot+> <|> flip ExportTypeWith <$> con `sepBy` comma++\end{verbatim}+\paragraph{Interfaces}+Since this modified version of MCC uses FlatCurry interfaces instead of+".icurry" files, a separate parser is not required any longer.+\begin{verbatim}++> --parseInterface :: FilePath -> String -> Error Interface+> --parseInterface fn s = applyParser parseIface lexer fn s++> --parseIface :: Parser Token Interface a+> --parseIface = Interface <$-> token Id_interface+> -- <*> (mIdent <?> "module name expected")+> -- <*-> (token KW_where <?> "where expected")+> -- <*> braces intfDecls++\end{verbatim}++++\paragraph{Declarations}+\begin{verbatim}++> decls :: Bool -> Parser Token [Decl] a+> decls = layout . globalDecls++> globalDecls :: Bool -> Parser Token [Decl] a+> globalDecls flat =+> (:) <$> importDecl <*> (semicolon <-*> globalDecls flat `opt` [])+> <|> topDecl flat `sepBy` semicolon++> topDecl :: Bool -> Parser Token Decl a+> topDecl flat+> | flat = infixDecl <|> dataDecl flat <|> typeDecl <|> functionDecl flat+> | otherwise = infixDecl+> <|> dataDecl flat <|> newtypeDecl <|> typeDecl+> <|> functionDecl flat <|> externalDecl++> localDefs :: Bool -> Parser Token [Decl] a+> localDefs flat = token KW_where <-*> layout (valueDecls flat)+> `opt` []++> valueDecls :: Bool -> Parser Token [Decl] a+> valueDecls flat = localDecl flat `sepBy` semicolon+> where localDecl flat+> | flat = infixDecl <|> valueDecl flat+> | otherwise = infixDecl <|> valueDecl flat <|> externalDecl++> importDecl :: Parser Token Decl a+> importDecl =+> flip . ImportDecl <$> position <*-> token KW_import +> <*> (True <$-> token Id_qualified `opt` False)+> <*> mIdent+> <*> (Just <$-> token Id_as <*> mIdent `opt` Nothing)+> <*> (Just <$> importSpec `opt` Nothing)++> importSpec :: Parser Token ImportSpec a+> importSpec = position <**> (Hiding <$-> token Id_hiding `opt` Importing)+> <*> parens (spec `sepBy` comma)+> where spec = tycon <**> (parens constrs `opt` Import)+> <|> Import <$> fun <\> tycon+> constrs = ImportTypeAll <$-> token DotDot+> <|> flip ImportTypeWith <$> con `sepBy` comma++> infixDecl :: Parser Token Decl a+> infixDecl = infixDeclLhs InfixDecl <*> funop `sepBy1` comma++> infixDeclLhs :: (Position -> Infix -> Integer -> a) -> Parser Token a b+> infixDeclLhs f = f <$> position <*> tokenOps infixKW <*> integer+> where infixKW = [(KW_infix,Infix),(KW_infixl,InfixL),(KW_infixr,InfixR)]++> dataDecl :: Bool -> Parser Token Decl a+> dataDecl flat = typeDeclLhs DataDecl KW_data <*> constrs+> where constrs = equals <-*> constrDecl flat `sepBy1` bar+> `opt` []++> newtypeDecl :: Parser Token Decl a+> newtypeDecl =+> typeDeclLhs NewtypeDecl KW_newtype <*-> equals <*> newConstrDecl++> typeDecl :: Parser Token Decl a+> typeDecl = typeDeclLhs TypeDecl KW_type <*-> equals <*> typeDeclRhs --type0++> typeDeclLhs :: (Position -> Ident -> [Ident] -> a) -> Category+> -> Parser Token a b+> typeDeclLhs f kw = f <$> position <*-> token kw <*> tycon <*> many typeVar+> where typeVar = tyvar <|> anonId <$-> token Underscore++> typeDeclRhs :: Parser Token TypeExpr a+> typeDeclRhs = type0+> <|> flip RecordType Nothing+> <$> (layoutOff <-*> braces (labelDecls `sepBy` comma))++> labelDecls = (,) <$> labId `sepBy1` comma <*-> token DoubleColon <*> type0++> constrDecl :: Bool -> Parser Token ConstrDecl a+> constrDecl flat = position <**> (existVars <**> constr)+> where constr = conId <**> identDecl+> <|> leftParen <-*> parenDecl+> <|> type1 <\> conId <\> leftParen <**> opDecl+> identDecl = many type2 <**> (conType <$> opDecl `opt` conDecl)+> parenDecl = conOpDeclPrefix +> <$> conSym <*-> rightParen <*> type2 <*> type2+> <|> tupleType <*-> rightParen <**> opDecl+> opDecl = conOpDecl <$> conop <*> type1+> conType f tys c = f (ConstructorType (qualify c) tys)+> conDecl tys c tvs p = ConstrDecl p tvs c tys+> conOpDecl op ty2 ty1 tvs p = ConOpDecl p tvs ty1 op ty2+> conOpDeclPrefix op ty1 ty2 tvs p = ConOpDecl p tvs ty1 op ty2++> newConstrDecl :: Parser Token NewConstrDecl a+> newConstrDecl =+> NewConstrDecl <$> position <*> existVars <*> con <*> type2++> existVars :: Parser Token [Ident] a+> {-+> existVars flat+> | flat = succeed []+> | otherwise = token Id_forall <-*> many1 tyvar <*-> dot `opt` []+> -}+> existVars = succeed []++> functionDecl :: Bool -> Parser Token Decl a+> functionDecl flat = position <**> decl+> where decl = fun `sepBy1` comma <**> funListDecl flat+> <|?> funDecl <$> lhs <*> declRhs flat+> lhs = (\f -> (f,FunLhs f [])) <$> fun+> <|?> funLhs++> valueDecl :: Bool -> Parser Token Decl a+> valueDecl flat = position <**> decl+> where decl = var `sepBy1` comma <**> valListDecl flat+> <|?> valDecl <$> constrTerm0 <*> declRhs flat+> <|?> funDecl <$> curriedLhs <*> declRhs flat+> valDecl t@(ConstructorPattern c ts)+> | not (isConstrId c) = funDecl (f,FunLhs f ts)+> where f = unqualify c+> valDecl t = opDecl id t+> opDecl f (InfixPattern t1 op t2)+> | isConstrId op = opDecl (f . InfixPattern t1 op) t2+> | otherwise = funDecl (op',OpLhs (f t1) op' t2)+> where op' = unqualify op+> opDecl f t = patDecl (f t)+> isConstrId c = c == qConsId || isQualified c || isQTupleId c++> funDecl :: (Ident,Lhs) -> Rhs -> Position -> Decl+> funDecl (f,lhs) rhs p = FunctionDecl p f [Equation p lhs rhs]++> patDecl :: ConstrTerm -> Rhs -> Position -> Decl+> patDecl t rhs p = PatternDecl p t rhs++> funListDecl :: Bool -> Parser Token ([Ident] -> Position -> Decl) a+> funListDecl flat+> | flat = typeSig <$-> token DoubleColon <*> type0+> <|> evalAnnot <$-> token KW_eval <*> tokenOps evalKW+> <|> externalDecl <$-> token KW_external+> | otherwise = typeSig <$-> token DoubleColon <*> type0+> <|> evalAnnot <$-> token KW_eval <*> tokenOps evalKW+> where typeSig ty vs p = TypeSig p vs ty+> evalAnnot ev vs p = EvalAnnot p vs ev+> evalKW = [(KW_rigid,EvalRigid),(KW_choice,EvalChoice)]+> externalDecl vs p = FlatExternalDecl p vs++> valListDecl :: Bool -> Parser Token ([Ident] -> Position -> Decl) a+> valListDecl flat = funListDecl flat <|> extraVars <$-> token KW_free+> where extraVars vs p = ExtraVariables p vs++> funLhs :: Parser Token (Ident,Lhs) a+> funLhs = funLhs <$> fun <*> many1 constrTerm2+> <|?> flip ($ id) <$> constrTerm1 <*> opLhs'+> <|?> curriedLhs+> where opLhs' = opLhs <$> funSym <*> constrTerm0+> <|> infixPat <$> gConSym <\> funSym <*> constrTerm1 <*> opLhs'+> <|> backquote <-*> opIdLhs+> opIdLhs = opLhs <$> funId <*-> checkBackquote <*> constrTerm0+> <|> infixPat <$> qConId <\> funId <*-> backquote <*> constrTerm1+> <*> opLhs'+> funLhs f ts = (f,FunLhs f ts)+> opLhs op t2 f t1 = (op,OpLhs (f t1) op t2)+> infixPat op t2 f g t1 = f (g . InfixPattern t1 op) t2++> curriedLhs :: Parser Token (Ident,Lhs) a+> curriedLhs = apLhs <$> parens funLhs <*> many1 constrTerm2+> where apLhs (f,lhs) ts = (f,ApLhs lhs ts)++> declRhs :: Bool -> Parser Token Rhs a+> declRhs flat = rhs flat equals++> rhs :: Bool -> Parser Token a b -> Parser Token Rhs b+> rhs flat eq = rhsExpr <*> localDefs flat+> where rhsExpr = SimpleRhs <$-> eq <*> position <*> expr flat+> <|> GuardedRhs <$> many1 (condExpr flat eq)++> externalDecl :: Parser Token Decl a+> externalDecl =+> ExternalDecl <$> position <*-> token KW_external+> <*> callConv <*> (Just <$> string `opt` Nothing)+> <*> fun <*-> token DoubleColon <*> type0+> where callConv = CallConvPrimitive <$-> token Id_primitive+> <|> CallConvCCall <$-> token Id_ccall+> <?> "Unsupported calling convention"++\end{verbatim}+\paragraph{Interface declarations}+\begin{verbatim}++> --intfDecls :: Parser Token [IDecl] a+> --intfDecls = (:) <$> iImportDecl <*> (semicolon <-*> intfDecls `opt` [])+> -- <|> intfDecl `sepBy` semicolon++> --intfDecl :: Parser Token IDecl a+> --intfDecl = iInfixDecl+> -- <|> iHidingDecl <|> iDataDecl <|> iNewtypeDecl <|> iTypeDecl+> -- <|> iFunctionDecl <\> token Id_hiding++> --iImportDecl :: Parser Token IDecl a+> --iImportDecl = IImportDecl <$> position <*-> token KW_import <*> mIdent++> --iInfixDecl :: Parser Token IDecl a+> --iInfixDecl = infixDeclLhs IInfixDecl <*> qfunop++> --iHidingDecl :: Parser Token IDecl a+> --iHidingDecl = position <*-> token Id_hiding <**> (dataDecl <|> funcDecl)+> -- where dataDecl = hiddenData <$-> token KW_data <*> tycon <*> many tyvar+> -- funcDecl = hidingFunc <$-> token DoubleColon <*> type0+> -- hiddenData tc tvs p = HidingDataDecl p tc tvs+> -- hidingFunc ty p = IFunctionDecl p hidingId ty+> -- hidingId = qualify (mkIdent "hiding")++> --iDataDecl :: Parser Token IDecl a+> --iDataDecl = iTypeDeclLhs IDataDecl KW_data <*> constrs+> -- where constrs = equals <-*> iConstrDecl `sepBy1` bar+> -- `opt` []+> -- iConstrDecl = Just <$> constrDecl False <\> token Underscore+> -- <|> Nothing <$-> token Underscore++> --iNewtypeDecl :: Parser Token IDecl a+> --iNewtypeDecl =+> -- iTypeDeclLhs INewtypeDecl KW_newtype <*-> equals <*> newConstrDecl++> --iTypeDecl :: Parser Token IDecl a+> --iTypeDecl = iTypeDeclLhs ITypeDecl KW_type <*-> equals <*> type0++> --iTypeDeclLhs :: (Position -> QualIdent -> [Ident] -> a) -> Category+> -- -> Parser Token a b+> --iTypeDeclLhs f kw = f <$> position <*-> token kw <*> qtycon <*> many tyvar++> --iFunctionDecl :: Parser Token IDecl a+> --iFunctionDecl = IFunctionDecl <$> position <*> qfun <*-> token DoubleColon+> -- <*> type0++\end{verbatim}+\paragraph{Types}+\begin{verbatim}++> type0 :: Parser Token TypeExpr a+> type0 = type1 `chainr1` (ArrowType <$-> token RightArrow)++> type1 :: Parser Token TypeExpr a+> type1 = ConstructorType <$> qtycon <*> many type2+> <|> type2 <\> qtycon++> type2 :: Parser Token TypeExpr a+> type2 = anonType <|> identType <|> parenType <|> listType++> anonType :: Parser Token TypeExpr a+> anonType = VariableType anonId <$-> token Underscore++> identType :: Parser Token TypeExpr a+> identType = VariableType <$> tyvar+> <|> flip ConstructorType [] <$> qtycon <\> tyvar++> parenType :: Parser Token TypeExpr a+> parenType = parens tupleType++> tupleType :: Parser Token TypeExpr a+> tupleType = type0 <??> (tuple <$> many1 (comma <-*> type0))+> `opt` TupleType []+> where tuple tys ty = TupleType (ty:tys)++> listType :: Parser Token TypeExpr a+> listType = ListType <$> brackets type0++\end{verbatim}+\paragraph{Literals}+\begin{verbatim}++> literal :: Parser Token Literal a+> literal = mk Char <$> char+> <|> mkInt <$> integer+> <|> mk Float <$> float+> <|> mk String <$> string++\end{verbatim}+\paragraph{Patterns}+\begin{verbatim}++> constrTerm0 :: Parser Token ConstrTerm a+> constrTerm0 = constrTerm1 `chainr1` (flip InfixPattern <$> gconop)++> constrTerm1 :: Parser Token ConstrTerm a+> constrTerm1 = varId <**> identPattern+> <|> ConstructorPattern <$> qConId <\> varId <*> many constrTerm2+> <|> minus <**> negNum+> <|> fminus <**> negFloat+> <|> leftParen <-*> parenPattern+> <|> constrTerm2 <\> qConId <\> leftParen+> where identPattern = optAsPattern+> <|> conPattern <$> many1 constrTerm2+> parenPattern = minus <**> minusPattern negNum+> <|> fminus <**> minusPattern negFloat+> <|> gconPattern+> <|> funSym <\> minus <\> fminus <*-> rightParen+> <**> identPattern+> <|> parenTuplePattern <\> minus <\> fminus <*-> rightParen+> minusPattern p = rightParen <-*> identPattern+> <|> parenMinusPattern p <*-> rightParen+> gconPattern = ConstructorPattern <$> gconId <*-> rightParen+> <*> many constrTerm2+> conPattern ts = flip ConstructorPattern ts . qualify++> constrTerm2 :: Parser Token ConstrTerm a+> constrTerm2 = literalPattern <|> anonPattern <|> identPattern+> <|> parenPattern <|> listPattern <|> lazyPattern+> <|> recordPattern++> literalPattern :: Parser Token ConstrTerm a+> literalPattern = LiteralPattern <$> literal++> anonPattern :: Parser Token ConstrTerm a+> anonPattern = VariablePattern anonId <$-> token Underscore++> identPattern :: Parser Token ConstrTerm a+> identPattern = varId <**> optAsPattern+> <|> flip ConstructorPattern [] <$> qConId <\> varId++> parenPattern :: Parser Token ConstrTerm a+> parenPattern = leftParen <-*> parenPattern+> where parenPattern = minus <**> minusPattern negNum+> <|> fminus <**> minusPattern negFloat+> <|> flip ConstructorPattern [] <$> gconId <*-> rightParen+> <|> funSym <\> minus <\> fminus <*-> rightParen+> <**> optAsPattern+> <|> parenTuplePattern <\> minus <\> fminus <*-> rightParen+> minusPattern p = rightParen <-*> optAsPattern+> <|> parenMinusPattern p <*-> rightParen++> listPattern :: Parser Token ConstrTerm a+> listPattern = mk' ListPattern <$> brackets (constrTerm0 `sepBy` comma)++> lazyPattern :: Parser Token ConstrTerm a+> lazyPattern = mk LazyPattern <$-> token Tilde <*> constrTerm2++> recordPattern :: Parser Token ConstrTerm a+> recordPattern = layoutOff <-*> braces content+> where+> content = RecordPattern <$> fields <*> record+> fields = fieldPatt `sepBy` comma+> fieldPatt = Field <$> position <*> labId <*-> checkEquals <*> constrTerm0+> record = Just <$-> checkBar <*> constrTerm2 `opt` Nothing++\end{verbatim}+Partial patterns used in the combinators above, but also for parsing+the left-hand side of a declaration.+\begin{verbatim}++> gconId :: Parser Token QualIdent a+> gconId = colon <|> tupleCommas++> negNum,negFloat :: Parser Token (Ident -> ConstrTerm) a+> negNum = flip NegativePattern +> <$> (mkInt <$> integer <|> mk Float <$> float)+> negFloat = flip NegativePattern . mk Float +> <$> (fromIntegral <$> integer <|> float)++> optAsPattern :: Parser Token (Ident -> ConstrTerm) a+> optAsPattern = flip AsPattern <$-> token At <*> constrTerm2+> `opt` VariablePattern++> optInfixPattern :: Parser Token (ConstrTerm -> ConstrTerm) a+> optInfixPattern = infixPat <$> gconop <*> constrTerm0+> `opt` id+> where infixPat op t2 t1 = InfixPattern t1 op t2++> optTuplePattern :: Parser Token (ConstrTerm -> ConstrTerm) a+> optTuplePattern = tuple <$> many1 (comma <-*> constrTerm0)+> `opt` ParenPattern+> where tuple ts t = mk TuplePattern (t:ts)++> parenMinusPattern :: Parser Token (Ident -> ConstrTerm) a+> -> Parser Token (Ident -> ConstrTerm) a+> parenMinusPattern p = p <.> optInfixPattern <.> optTuplePattern++> parenTuplePattern :: Parser Token ConstrTerm a+> parenTuplePattern = constrTerm0 <**> optTuplePattern+> `opt` mk TuplePattern []++\end{verbatim}+\paragraph{Expressions}+\begin{verbatim}++> condExpr :: Bool -> Parser Token a b -> Parser Token CondExpr b+> condExpr flat eq =+> CondExpr <$> position <*-> bar <*> expr0 flat <*-> eq <*> expr flat++> expr :: Bool -> Parser Token Expression a+> expr flat = expr0 flat <??> (flip Typed <$-> token DoubleColon <*> type0)++> expr0 :: Bool -> Parser Token Expression a+> expr0 flat = expr1 flat `chainr1` (flip InfixApply <$> infixOp)++> expr1 :: Bool -> Parser Token Expression a+> expr1 flat = UnaryMinus <$> (minus <|> fminus) <*> expr2 flat+> <|> expr2 flat++> expr2 :: Bool -> Parser Token Expression a+> expr2 flat = lambdaExpr flat <|> letExpr flat <|> doExpr flat+> <|> ifExpr flat <|> caseExpr flat+> <|> expr3 flat <**> applicOrSelect+> where+> applicOrSelect = flip RecordSelection +> <$-> (token RightArrow <?> "-> expected")+> <*> labId+> <|?> (\es e -> foldl1 Apply (e:es))+> <$> many (expr3 flat) ++> expr3 :: Bool -> Parser Token Expression a+> expr3 flat = expr3' +> where+> expr3' = constant <|> variable <|> parenExpr flat+> <|> listExpr flat <|> recordExpr flat++> constant :: Parser Token Expression a+> constant = Literal <$> literal++> variable :: Parser Token Expression a+> variable = Variable <$> qFunId++> parenExpr :: Bool -> Parser Token Expression a+> parenExpr flat = parens pExpr+> where pExpr = (minus <|> fminus) <**> minusOrTuple+> <|> Constructor <$> tupleCommas+> <|> leftSectionOrTuple <\> minus <\> fminus+> <|> opOrRightSection <\> minus <\> fminus+> `opt` mk Tuple []+> minusOrTuple = flip UnaryMinus <$> expr1 flat <.> infixOrTuple+> `opt` Variable . qualify+> leftSectionOrTuple = expr1 flat <**> infixOrTuple+> infixOrTuple = ($ id) <$> infixOrTuple'+> infixOrTuple' = infixOp <**> leftSectionOrExp+> <|> (.) <$> (optType <.> tupleExpr)+> leftSectionOrExp = expr1 flat <**> (infixApp <$> infixOrTuple')+> `opt` leftSection+> optType = flip Typed <$-> token DoubleColon <*> type0+> `opt` id+> tupleExpr = tuple <$> many1 (comma <-*> expr flat)+> `opt` Paren+> opOrRightSection = qFunSym <**> optRightSection+> <|> colon <**> optCRightSection+> <|> infixOp <\> colon <\> qFunSym <**> rightSection+> optRightSection = (. InfixOp) <$> rightSection `opt` Variable+> optCRightSection = (. InfixConstr) <$> rightSection `opt` Constructor+> rightSection = flip RightSection <$> expr0 flat+> infixApp f e2 op g e1 = f (g . InfixApply e1 op) e2+> leftSection op f e = LeftSection (f e) op+> tuple es e = mk Tuple (e:es)++> infixOp :: Parser Token InfixOp a+> infixOp = InfixOp <$> qfunop+> <|> InfixConstr <$> colon++> listExpr :: Bool -> Parser Token Expression a+> listExpr flat = brackets (elements `opt` mk' List [])+> where elements = expr flat <**> rest+> rest = comprehension+> <|> enumeration (flip EnumFromTo) EnumFrom+> <|> comma <-*> expr flat <**>+> (enumeration (flip3 EnumFromThenTo) (flip EnumFromThen)+> <|> list <$> many (comma <-*> expr flat))+> `opt` (\e -> mk' List [e])+> comprehension = flip (mk ListCompr) <$-> bar <*> quals flat+> enumeration enumTo enum =+> token DotDot <-*> (enumTo <$> expr flat `opt` enum)+> list es e2 e1 = mk' List (e1:e2:es)+> flip3 f x y z = f z y x++> recordExpr :: Bool -> Parser Token Expression a+> recordExpr flat = layoutOff <-*> braces content+> where content = RecordConstr <$> fieldConstr `sepBy` comma+> <|?> RecordUpdate <$> fieldUpdate `sepBy` comma+> <*-> checkBar <*> expr flat+> fieldConstr = Field <$> position <*> labId +> <*-> checkEquals <*> expr flat+> fieldUpdate = Field <$> position <*> labId +> <*-> checkBinds <*> expr flat++> lambdaExpr :: Bool -> Parser Token Expression a+> lambdaExpr flat =+> mk Lambda <$-> token Backslash <*> many1 constrTerm2+> <*-> (token RightArrow <?> "-> expected") <*> expr flat++> letExpr :: Bool -> Parser Token Expression a+> letExpr flat = Let <$-> token KW_let <*> layout (valueDecls flat)+> <*-> (token KW_in <?> "in expected") <*> expr flat++> doExpr :: Bool -> Parser Token Expression a+> doExpr flat = uncurry Do <$-> token KW_do <*> layout (stmts flat)++> ifExpr :: Bool -> Parser Token Expression a+> ifExpr flat =+> mk IfThenElse <$-> token KW_if <*> expr flat+> <*-> (token KW_then <?> "then expected") <*> expr flat+> <*-> (token KW_else <?> "else expected") <*> expr flat++> caseExpr :: Bool -> Parser Token Expression a+> caseExpr flat = mk Case <$-> token KW_case <*> expr flat+> <*-> (token KW_of <?> "of expected") <*> layout (alts flat)++> alts :: Bool -> Parser Token [Alt] a+> alts flat = alt flat `sepBy1` semicolon++> alt :: Bool -> Parser Token Alt a+> alt flat = Alt <$> position <*> constrTerm0+> <*> rhs flat (token RightArrow <?> "-> expected")++\end{verbatim}+\paragraph{Statements in list comprehensions and \texttt{do} expressions}+Parsing statements is a bit difficult because the syntax of patterns+and expressions largely overlaps. The parser will first try to+recognize the prefix \emph{Pattern}~\texttt{<-} of a binding statement+and if this fails fall back into parsing an expression statement. In+addition, we have to be prepared that the sequence+\texttt{let}~\emph{LocalDefs} can be either a let-statement or the+prefix of a let expression.+\begin{verbatim}++> stmts :: Bool -> Parser Token ([Statement],Expression) a+> stmts flat = stmt flat (reqStmts flat) (optStmts flat)++> reqStmts :: Bool -> Parser Token (Statement -> ([Statement],Expression)) a+> reqStmts flat = (\(sts,e) st -> (st : sts,e)) <$-> semicolon <*> stmts flat++> optStmts :: Bool -> Parser Token (Expression -> ([Statement],Expression)) a+> optStmts flat = succeed (mk StmtExpr) <.> reqStmts flat+> `opt` (,) []++> quals :: Bool -> Parser Token [Statement] a+> quals flat = stmt flat (succeed id) (succeed $ mk StmtExpr) `sepBy1` comma++> stmt :: Bool -> Parser Token (Statement -> a) b+> -> Parser Token (Expression -> a) b -> Parser Token a b+> stmt flat stmtCont exprCont = letStmt flat stmtCont exprCont+> <|> exprOrBindStmt flat stmtCont exprCont++> letStmt :: Bool -> Parser Token (Statement -> a) b+> -> Parser Token (Expression -> a) b -> Parser Token a b+> letStmt flat stmtCont exprCont =+> token KW_let <-*> layout (valueDecls flat) <**> optExpr+> where optExpr = flip Let <$-> token KW_in <*> expr flat <.> exprCont+> <|> succeed StmtDecl <.> stmtCont++> exprOrBindStmt :: Bool -> Parser Token (Statement -> a) b+> -> Parser Token (Expression -> a) b+> -> Parser Token a b+> exprOrBindStmt flat stmtCont exprCont =+> mk StmtBind <$> constrTerm0 <*-> leftArrow <*> expr flat <**> stmtCont+> <|?> expr flat <\> token KW_let <**> exprCont++\end{verbatim}+\paragraph{Literals, identifiers, and (infix) operators}+\begin{verbatim}++> char :: Parser Token Char a+> char = cval <$> token CharTok++> int, checkInt :: Parser Token Int a+> int = ival <$> token IntTok+> checkInt = int <?> "integer number expected"++> float, checkFloat :: Parser Token Double a+> float = fval <$> token FloatTok+> checkFloat = float <?> "floating point number expected"++> integer, checkInteger :: Parser Token Integer a+> integer = intval <$> token IntegerTok+> checkInteger = integer <?> "integer number expected"++> string :: Parser Token String a+> string = sval <$> token StringTok++> tycon, tyvar :: Parser Token Ident a+> tycon = conId+> tyvar = varId++> qtycon :: Parser Token QualIdent a+> qtycon = qConId++> varId, funId, conId, labId :: Parser Token Ident a+> varId = ident+> funId = ident+> conId = ident+> labId = renameLabel <$> ident++> funSym, conSym :: Parser Token Ident a+> funSym = sym+> conSym = sym++> var, fun, con :: Parser Token Ident a+> var = varId <|> parens (funSym <?> "operator symbol expected")+> fun = funId <|> parens (funSym <?> "operator symbol expected")+> con = conId <|> parens (conSym <?> "operator symbol expected")++> funop, conop :: Parser Token Ident a+> funop = funSym <|> backquotes (funId <?> "operator name expected")+> conop = conSym <|> backquotes (conId <?> "operator name expected")++> qFunId, qConId, qLabId :: Parser Token QualIdent a+> qFunId = qIdent+> qConId = qIdent+> qLabId = qIdent++> qFunSym, qConSym :: Parser Token QualIdent a+> qFunSym = qSym+> qConSym = qSym+> gConSym = qConSym <|> colon++> qfun, qcon :: Parser Token QualIdent a+> qfun = qFunId <|> parens (qFunSym <?> "operator symbol expected")+> qcon = qConId <|> parens (qConSym <?> "operator symbol expected")++> qfunop, qconop, gconop :: Parser Token QualIdent a+> qfunop = qFunSym <|> backquotes (qFunId <?> "operator name expected")+> qconop = qConSym <|> backquotes (qConId <?> "operator name expected")+> gconop = gConSym <|> backquotes (qConId <?> "operator name expected")++> ident :: Parser Token Ident a+> ident = (\ pos -> mkIdentPosition pos . sval) <$> position <*> +> tokens [Id,Id_as,Id_ccall,Id_forall,Id_hiding,+> Id_interface,Id_primitive,Id_qualified]++> qIdent :: Parser Token QualIdent a+> qIdent = qualify <$> ident <|> mkQIdent <$> position <*> token QId+> where mkQIdent p a = qualifyWith (mkMIdent (modul a)) +> (mkIdentPosition p (sval a))++> mIdent :: Parser Token ModuleIdent a+> mIdent = mIdent <$> position <*> +> tokens [Id,QId,Id_as,Id_ccall,Id_forall,Id_hiding,+> Id_interface,Id_primitive,Id_qualified]+> where mIdent p a = addPositionModuleIdent p $ +> mkMIdent (modul a ++ [sval a])++> sym :: Parser Token Ident a+> sym = (\ pos -> mkIdentPosition pos . sval) <$> position <*> +> tokens [Sym,Sym_Dot,Sym_Minus,Sym_MinusDot]++> qSym :: Parser Token QualIdent a+> qSym = qualify <$> sym <|> mkQIdent <$> position <*> token QSym+> where mkQIdent p a = qualifyWith (mkMIdent (modul a)) +> (mkIdentPosition p (sval a))++> colon :: Parser Token QualIdent a+> colon = (\ p _ -> qualify $ addPositionIdent p consId) <$> +> position <*> token Colon++> minus :: Parser Token Ident a+> minus = (\ p _ -> addPositionIdent p minusId) <$> +> position <*> token Sym_Minus++> fminus :: Parser Token Ident a+> fminus = (\ p _ -> addPositionIdent p fminusId) <$> +> position <*> token Sym_MinusDot++> tupleCommas :: Parser Token QualIdent a+> tupleCommas = (\ p -> qualify . addPositionIdent p . tupleId . succ . length )+> <$> position <*> many1 comma++\end{verbatim}+\paragraph{Layout}+\begin{verbatim}++> layout :: Parser Token a b -> Parser Token a b+> layout p = layoutOff <-*> bracket leftBraceSemicolon p rightBrace+> <|> layoutOn <-*> p <*-> (token VRightBrace <|> layoutEnd)++\end{verbatim}+\paragraph{More combinators}+\begin{verbatim}++> braces, brackets, parens, backquotes :: Parser Token a b -> Parser Token a b+> braces p = bracket leftBrace p rightBrace+> brackets p = bracket leftBracket p rightBracket+> parens p = bracket leftParen p rightParen+> backquotes p = bracket backquote p checkBackquote++\end{verbatim}+\paragraph{Simple token parsers}+\begin{verbatim}++> token :: Category -> Parser Token Attributes a+> token c = attr <$> symbol (Token c NoAttributes)+> where attr (Token _ a) = a++> tokens :: [Category] -> Parser Token Attributes a+> tokens = foldr1 (<|>) . map token++> tokenOps :: [(Category,a)] -> Parser Token a b+> tokenOps cs = ops [(Token c NoAttributes,x) | (c,x) <- cs]++> dot, comma, semicolon, bar, equals, binds :: Parser Token Attributes a+> dot = token Sym_Dot+> comma = token Comma+> semicolon = token Semicolon <|> token VSemicolon+> bar = token Bar+> equals = token Equals+> binds = token Binds++> checkBar, checkEquals, checkBinds :: Parser Token Attributes a+> checkBar = bar <?> "| expected"+> checkEquals = equals <?> "= expected"+> checkBinds = binds <?> ":= expected"++> backquote, checkBackquote :: Parser Token Attributes a+> backquote = token Backquote+> checkBackquote = backquote <?> "backquote (`) expected"++> leftParen, rightParen :: Parser Token Attributes a+> leftParen = token LeftParen+> rightParen = token RightParen++> leftBracket, rightBracket :: Parser Token Attributes a+> leftBracket = token LeftBracket+> rightBracket = token RightBracket++> leftBrace, leftBraceSemicolon, rightBrace :: Parser Token Attributes a+> leftBrace = token LeftBrace+> leftBraceSemicolon = token LeftBraceSemicolon+> rightBrace = token RightBrace++> leftArrow :: Parser Token Attributes a+> leftArrow = token LeftArrow++\end{verbatim}+\paragraph{Ident}+\begin{verbatim}++> mkIdentPosition :: Position -> String -> Ident+> mkIdentPosition pos = addPositionIdent pos . mkIdent++\end{verbatim}
+ src/Curry/Syntax/Pretty.lhs view
@@ -0,0 +1,367 @@++% $Id: CurryPP.lhs,v 1.50 2004/02/15 22:10:27 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{CurryPP.lhs}+\section{A Pretty Printer for Curry}\label{sec:CurryPP}+This module implements a pretty printer for Curry expressions. It was+derived from the Haskell pretty printer provided in Simon Marlow's+Haskell parser.+\begin{verbatim}++> module Curry.Syntax.Pretty where++> import Curry.Base.Ident+> import Curry.Syntax.Type++> import PrettyCombinators++\end{verbatim}+Pretty print a module+\begin{verbatim}++> ppModule :: Module -> Doc+> ppModule (Module m es ds) = ppModuleHeader m es $$ ppBlock ds++\end{verbatim}+Module header+\begin{verbatim}++> ppModuleHeader :: ModuleIdent -> Maybe ExportSpec -> Doc+> ppModuleHeader m es =+> text "module" <+> ppMIdent m <+> maybePP ppExportSpec es <+> text "where"++> ppExportSpec :: ExportSpec -> Doc+> ppExportSpec (Exporting _ es) = parenList (map ppExport es)++> ppExport :: Export -> Doc+> ppExport (Export x) = ppQIdent x+> ppExport (ExportTypeWith tc cs) = ppQIdent tc <> parenList (map ppIdent cs)+> ppExport (ExportTypeAll tc) = ppQIdent tc <> text "(..)"+> ppExport (ExportModule m) = text "module" <+> ppMIdent m++\end{verbatim}+Declarations+\begin{verbatim}++> ppBlock :: [Decl] -> Doc+> ppBlock = vcat . map ppDecl++> ppDecl :: Decl -> Doc+> ppDecl (ImportDecl _ m q asM is) =+> text "import" <+> ppQualified q <+> ppMIdent m <+> maybePP ppAs asM+> <+> maybePP ppImportSpec is+> where ppQualified q = if q then text "qualified" else empty+> ppAs m = text "as" <+> ppMIdent m+> ppDecl (InfixDecl _ fix p ops) = ppPrec fix p <+> list (map ppInfixOp ops)+> ppDecl (DataDecl _ tc tvs cs) =+> sep (ppTypeDeclLhs "data" tc tvs :+> map indent (zipWith (<+>) (equals : repeat vbar) (map ppConstr cs)))+> ppDecl (NewtypeDecl _ tc tvs nc) =+> sep [ppTypeDeclLhs "newtype" tc tvs <+> equals,indent (ppNewConstr nc)]+> ppDecl (TypeDecl _ tc tvs ty) =+> sep [ppTypeDeclLhs "type" tc tvs <+> equals,indent (ppTypeExpr 0 ty)]+> ppDecl (TypeSig _ fs ty) =+> list (map ppIdent fs) <+> text "::" <+> ppTypeExpr 0 ty+> ppDecl (EvalAnnot _ fs ev) =+> list (map ppIdent fs) <+> text "eval" <+> ppEval ev+> where ppEval EvalRigid = text "rigid"+> ppEval EvalChoice = text "choice"+> ppDecl (FunctionDecl _ _ eqs) = vcat (map ppEquation eqs)+> ppDecl (ExternalDecl p cc impent f ty) =+> sep [text "external" <+> ppCallConv cc <+> maybePP (text . show) impent,+> indent (ppDecl (TypeSig p [f] ty))]+> where ppCallConv CallConvPrimitive = text "primitive"+> ppCallConv CallConvCCall = text "ccall"+> ppDecl (FlatExternalDecl _ fs) = list (map ppIdent fs) <+> text "external"+> ppDecl (PatternDecl _ t rhs) = ppRule (ppConstrTerm 0 t) equals rhs+> ppDecl (ExtraVariables _ vs) = list (map ppIdent vs) <+> text "free"++> ppImportSpec :: ImportSpec -> Doc+> ppImportSpec (Importing _ is) = parenList (map ppImport is)+> ppImportSpec (Hiding _ is) = text "hiding" <+> parenList (map ppImport is)++> ppImport :: Import -> Doc+> ppImport (Import x) = ppIdent x+> ppImport (ImportTypeWith tc cs) = ppIdent tc <> parenList (map ppIdent cs)+> ppImport (ImportTypeAll tc) = ppIdent tc <> text "(..)"++> ppPrec :: Infix -> Integer -> Doc+> ppPrec fix p = ppAssoc fix <+> ppPrio p+> where ppAssoc InfixL = text "infixl"+> ppAssoc InfixR = text "infixr"+> ppAssoc Infix = text "infix"+> ppPrio p = if p < 0 then empty else integer p++> ppTypeDeclLhs :: String -> Ident -> [Ident] -> Doc+> ppTypeDeclLhs kw tc tvs = text kw <+> ppIdent tc <+> hsep (map ppIdent tvs)++> ppConstr :: ConstrDecl -> Doc+> ppConstr (ConstrDecl _ tvs c tys) =+> sep [ppExistVars tvs,ppIdent c <+> fsep (map (ppTypeExpr 2) tys)]+> ppConstr (ConOpDecl _ tvs ty1 op ty2) =+> sep [ppExistVars tvs,ppTypeExpr 1 ty1,ppInfixOp op <+> ppTypeExpr 1 ty2]++> ppNewConstr :: NewConstrDecl -> Doc+> ppNewConstr (NewConstrDecl _ tvs c ty) =+> sep [ppExistVars tvs,ppIdent c <+> ppTypeExpr 2 ty]++> ppExistVars :: [Ident] -> Doc+> ppExistVars tvs+> | null tvs = empty+> | otherwise = text "forall" <+> hsep (map ppIdent tvs) <+> char '.'++> ppEquation :: Equation -> Doc+> ppEquation (Equation _ lhs rhs) = ppRule (ppLhs lhs) equals rhs++> ppLhs :: Lhs -> Doc+> ppLhs (FunLhs f ts) = ppIdent f <+> fsep (map (ppConstrTerm 2) ts)+> ppLhs (OpLhs t1 f t2) =+> ppConstrTerm 1 t1 <+> ppInfixOp f <+> ppConstrTerm 1 t2+> ppLhs (ApLhs lhs ts) = parens (ppLhs lhs) <+> fsep (map (ppConstrTerm 2) ts)++> ppRule :: Doc -> Doc -> Rhs -> Doc+> ppRule lhs eq (SimpleRhs _ e ds) =+> sep [lhs <+> eq,indent (ppExpr 0 e)] $$ ppLocalDefs ds+> ppRule lhs eq (GuardedRhs es ds) =+> sep [lhs,indent (vcat (map (ppCondExpr eq) es))] $$ ppLocalDefs ds++> ppLocalDefs :: [Decl] -> Doc+> ppLocalDefs ds+> | null ds = empty+> | otherwise = indent (text "where" <+> ppBlock ds)++\end{verbatim}+Interfaces+\begin{verbatim}++> ppInterface :: Interface -> Doc+> ppInterface (Interface m ds) =+> text "interface" <+> ppMIdent m <+> text "where" <+> lbrace+> $$ vcat (punctuate semi (map ppIDecl ds)) $$ rbrace++> ppIDecl :: IDecl -> Doc+> ppIDecl (IImportDecl _ m) = text "import" <+> ppMIdent m+> ppIDecl (IInfixDecl _ fix p op) = ppPrec fix p <+> ppQInfixOp op+> ppIDecl (HidingDataDecl _ tc tvs) =+> text "hiding" <+> ppITypeDeclLhs "data" (qualify tc) tvs+> ppIDecl (IDataDecl _ tc tvs cs) =+> sep (ppITypeDeclLhs "data" tc tvs :+> map indent (zipWith (<+>) (equals : repeat vbar) (map ppIConstr cs)))+> where ppIConstr = maybe (char '_') ppConstr+> ppIDecl (INewtypeDecl _ tc tvs nc) =+> sep [ppITypeDeclLhs "newtype" tc tvs <+> equals,indent (ppNewConstr nc)]+> ppIDecl (ITypeDecl _ tc tvs ty) =+> sep [ppITypeDeclLhs "type" tc tvs <+> equals,indent (ppTypeExpr 0 ty)]+> ppIDecl (IFunctionDecl _ f _ ty) = ppQIdent f <+> text "::" <+> ppTypeExpr 0 ty++> ppITypeDeclLhs :: String -> QualIdent -> [Ident] -> Doc+> ppITypeDeclLhs kw tc tvs = text kw <+> ppQIdent tc <+> hsep (map ppIdent tvs)++\end{verbatim}+Types+\begin{verbatim}++> ppTypeExpr :: Int -> TypeExpr -> Doc+> ppTypeExpr p (ConstructorType tc tys) =+> parenExp (p > 1 && not (null tys))+> (ppQIdent tc <+> fsep (map (ppTypeExpr 2) tys))+> ppTypeExpr _ (VariableType tv) = ppIdent tv+> ppTypeExpr _ (TupleType tys) = parenList (map (ppTypeExpr 0) tys)+> ppTypeExpr _ (ListType ty) = brackets (ppTypeExpr 0 ty)+> ppTypeExpr p (ArrowType ty1 ty2) =+> parenExp (p > 0) (fsep (ppArrowType (ArrowType ty1 ty2)))+> where ppArrowType (ArrowType ty1 ty2) =+> ppTypeExpr 1 ty1 <+> rarrow : ppArrowType ty2+> ppArrowType ty = [ppTypeExpr 0 ty]+> ppTypeExpr p (RecordType fs rty) = +> braces (list (map ppTypedField fs) +> <> maybe empty (\ty -> space <> char '|' <+> ppTypeExpr 0 ty) rty)+> where+> ppTypedField (ls,ty) = +> list (map ppIdent ls) <> text "::" <> ppTypeExpr 0 ty++++\end{verbatim}+Literals+\begin{verbatim}++> ppLiteral :: Literal -> Doc+> ppLiteral (Char _ c) = text (show c)+> ppLiteral (Int _ i) = integer i+> ppLiteral (Float _ f) = double f+> ppLiteral (String _ s) = text (show s)++\end{verbatim}+Patterns+\begin{verbatim}++> ppConstrTerm :: Int -> ConstrTerm -> Doc+> ppConstrTerm p (LiteralPattern l) =+> parenExp (p > 1 && isNegative l) (ppLiteral l)+> where isNegative (Char _ _) = False+> isNegative (Int _ i) = i < 0+> isNegative (Float _ f) = f < 0.0+> isNegative (String _ _) = False+> ppConstrTerm p (NegativePattern op l) =+> parenExp (p > 1) (ppInfixOp op <> ppLiteral l)+> ppConstrTerm _ (VariablePattern v) = ppIdent v+> ppConstrTerm p (ConstructorPattern c ts) =+> parenExp (p > 1 && not (null ts))+> (ppQIdent c <+> fsep (map (ppConstrTerm 2) ts))+> ppConstrTerm p (InfixPattern t1 c t2) =+> parenExp (p > 0)+> (sep [ppConstrTerm 1 t1 <+> ppQInfixOp c,+> indent (ppConstrTerm 0 t2)])+> ppConstrTerm _ (ParenPattern t) = parens (ppConstrTerm 0 t)+> ppConstrTerm _ (TuplePattern _ ts) = parenList (map (ppConstrTerm 0) ts)+> ppConstrTerm _ (ListPattern _ ts) = bracketList (map (ppConstrTerm 0) ts)+> ppConstrTerm _ (AsPattern v t) = ppIdent v <> char '@' <> ppConstrTerm 2 t+> ppConstrTerm _ (LazyPattern _ t) = char '~' <> ppConstrTerm 2 t+> ppConstrTerm p (FunctionPattern f ts) =+> parenExp (p > 1 && not (null ts))+> (ppQIdent f <+> fsep (map (ppConstrTerm 2) ts))+> ppConstrTerm p (InfixFuncPattern t1 f t2) =+> parenExp (p > 0)+> (sep [ppConstrTerm 1 t1 <+> ppQInfixOp f,+> indent (ppConstrTerm 0 t2)])+> ppConstrTerm p (RecordPattern fs rt) =+> braces (list (map ppFieldPatt fs)+> <> (maybe empty (\t -> space <> char '|' <+> ppConstrTerm 0 t) rt))++> ppFieldPatt :: Field ConstrTerm -> Doc+> ppFieldPatt (Field _ l t) = ppIdent l <> equals <> ppConstrTerm 0 t++\end{verbatim}+Expressions+\begin{verbatim}++> ppCondExpr :: Doc -> CondExpr -> Doc+> ppCondExpr eq (CondExpr _ g e) =+> vbar <+> sep [ppExpr 0 g <+> eq,indent (ppExpr 0 e)]++> ppExpr :: Int -> Expression -> Doc+> ppExpr _ (Literal l) = ppLiteral l+> ppExpr _ (Variable v) = ppQIdent v+> ppExpr _ (Constructor c) = ppQIdent c+> ppExpr _ (Paren e) = parens (ppExpr 0 e)+> ppExpr p (Typed e ty) =+> parenExp (p > 0) (ppExpr 0 e <+> text "::" <+> ppTypeExpr 0 ty)+> ppExpr _ (Tuple _ es) = parenList (map (ppExpr 0) es)+> ppExpr _ (List _ es) = bracketList (map (ppExpr 0) es)+> ppExpr _ (ListCompr _ e qs) =+> brackets (ppExpr 0 e <+> vbar <+> list (map ppStmt qs))+> ppExpr _ (EnumFrom e) = brackets (ppExpr 0 e <+> text "..")+> ppExpr _ (EnumFromThen e1 e2) =+> brackets (ppExpr 0 e1 <> comma <+> ppExpr 0 e2 <+> text "..")+> ppExpr _ (EnumFromTo e1 e2) =+> brackets (ppExpr 0 e1 <+> text ".." <+> ppExpr 0 e2)+> ppExpr _ (EnumFromThenTo e1 e2 e3) =+> brackets (ppExpr 0 e1 <> comma <+> ppExpr 0 e2+> <+> text ".." <+> ppExpr 0 e3)+> ppExpr p (UnaryMinus op e) = parenExp (p > 1) (ppInfixOp op <> ppExpr 1 e)+> ppExpr p (Apply e1 e2) =+> parenExp (p > 1) (sep [ppExpr 1 e1,indent (ppExpr 2 e2)])+> ppExpr p (InfixApply e1 op e2) =+> parenExp (p > 0) (sep [ppExpr 1 e1 <+> ppQInfixOp (opName op),+> indent (ppExpr 1 e2)])+> ppExpr _ (LeftSection e op) = parens (ppExpr 1 e <+> ppQInfixOp (opName op))+> ppExpr _ (RightSection op e) = parens (ppQInfixOp (opName op) <+> ppExpr 1 e)+> ppExpr p (Lambda _ t e) =+> parenExp (p > 0)+> (sep [backsl <> fsep (map (ppConstrTerm 2) t) <+> rarrow,+> indent (ppExpr 0 e)])+> ppExpr p (Let ds e) =+> parenExp (p > 0)+> (sep [text "let" <+> ppBlock ds <+> text "in",ppExpr 0 e])+> ppExpr p (Do sts e) =+> parenExp (p > 0) (text "do" <+> (vcat (map ppStmt sts) $$ ppExpr 0 e))+> ppExpr p (IfThenElse _ e1 e2 e3) =+> parenExp (p > 0)+> (text "if" <+>+> sep [ppExpr 0 e1,+> text "then" <+> ppExpr 0 e2,+> text "else" <+> ppExpr 0 e3])+> ppExpr p (Case _ e alts) =+> parenExp (p > 0)+> (text "case" <+> ppExpr 0 e <+> text "of" $$+> indent (vcat (map ppAlt alts)))+> ppExpr p (RecordConstr fs) =+> braces (list (map (ppFieldExpr equals) fs))+> ppExpr p (RecordSelection e l) =+> parenExp (p > 0)+> (ppExpr 1 e <+> text "->" <+> ppIdent l)+> ppExpr p (RecordUpdate fs e) =+> braces (list (map (ppFieldExpr (text ":=")) fs)+> <+> char '|' <+> ppExpr 0 e)++> ppStmt :: Statement -> Doc+> ppStmt (StmtExpr _ e) = ppExpr 0 e+> ppStmt (StmtBind _ t e) = sep [ppConstrTerm 0 t <+> larrow,indent (ppExpr 0 e)]+> ppStmt (StmtDecl ds) = text "let" <+> ppBlock ds++> ppAlt :: Alt -> Doc+> ppAlt (Alt _ t rhs) = ppRule (ppConstrTerm 0 t) rarrow rhs++> ppFieldExpr :: Doc -> Field Expression -> Doc+> ppFieldExpr comb (Field _ l e) = ppIdent l <> comb <> ppExpr 0 e++> ppOp :: InfixOp -> Doc+> ppOp (InfixOp op) = ppQInfixOp op+> ppOp (InfixConstr op) = ppQInfixOp op++\end{verbatim}++Names+\begin{verbatim}++> ppIdent :: Ident -> Doc+> ppIdent x = parenExp (isInfixOp x) (text (name x))++> ppQIdent :: QualIdent -> Doc+> ppQIdent x = parenExp (isQInfixOp x) (text (qualName x))++> ppInfixOp :: Ident -> Doc+> ppInfixOp x = backQuoteExp (not (isInfixOp x)) (text (name x))++> ppQInfixOp :: QualIdent -> Doc+> ppQInfixOp x = backQuoteExp (not (isQInfixOp x)) (text (qualName x))++> ppMIdent :: ModuleIdent -> Doc+> ppMIdent m = text (moduleName m)++\end{verbatim}+Print printing utilities+\begin{verbatim}++> indent :: Doc -> Doc+> indent = nest 2++> maybePP :: (a -> Doc) -> Maybe a -> Doc+> maybePP pp = maybe empty pp++> parenExp :: Bool -> Doc -> Doc+> parenExp b doc = if b then parens doc else doc++> backQuoteExp :: Bool -> Doc -> Doc+> backQuoteExp b doc = if b then backQuote <> doc <> backQuote else doc++> list, parenList, bracketList, braceList :: [Doc] -> Doc+> list = fsep . punctuate comma+> parenList = parens . list+> bracketList = brackets . list+> braceList = braces . list++> backQuote,backsl,vbar,rarrow,larrow :: Doc+> backQuote = char '`'+> backsl = char '\\'+> vbar = char '|'+> rarrow = text "->"+> larrow = text "<-"++\end{verbatim}
+ src/Curry/Syntax/ShowModule.hs view
@@ -0,0 +1,499 @@+--- Transform a CurrySyntax module into a string representation without any+--- pretty printing.+--- Behaves like a derived Show instance even on parts with a specific one.+--- +--- @author Sebastian Fischer (sebf@informatik.uni-kiel.de)+--- @version December 2008+--- bug fixed by bbr+++module Curry.Syntax.ShowModule ( showModule ) where++import Curry.Base.Ident+import Curry.Base.Position+import Curry.Syntax.Type++showModule :: Module -> String+showModule m = showsModule m "\n"++showsModule :: Module -> ShowS+showsModule (Module mident espec decls)+ = showsString "Module "+ . showsModuleIdent mident . newline+ . showsMaybe showsExportSpec espec . newline+ . showsList (\d -> showsDecl d . newline) decls++showsPosition :: Position -> ShowS+showsPosition Position{line=row,column=col} = showsPair shows shows (row,col)+-- showsPosition (Position file row col)+-- = showsString "(Position "+-- . shows file . space+-- . shows row . space+-- . shows col+-- . showsString ")"++showsExportSpec :: ExportSpec -> ShowS+showsExportSpec (Exporting pos exports)+ = showsString "(Exporting "+ . showsPosition pos . space+ . showsList showsExport exports+ . showsString ")"++showsExport :: Export -> ShowS+showsExport (Export qident)+ = showsString "(Export " . showsQualIdent qident . showsString ")"+showsExport (ExportTypeWith qident ids)+ = showsString "(ExportTypeWith "+ . showsQualIdent qident . space+ . showsList showsIdent ids+ . showsString ")"+showsExport (ExportTypeAll qident)+ = showsString "(ExportTypeAll " . showsQualIdent qident . showsString ")"+showsExport (ExportModule m) + = showsString "(ExportModule " . showsModuleIdent m . showChar ')'++showsImportSpec :: ImportSpec -> ShowS+showsImportSpec (Importing pos imports)+ = showsString "(Importing "+ . showsPosition pos . space+ . showsList showsImport imports+ . showsString ")"+showsImportSpec (Hiding pos imports)+ = showsString "(Hiding "+ . showsPosition pos . space+ . showsList showsImport imports+ . showsString ")"++showsImport :: Import -> ShowS+showsImport (Import ident)+ = showsString "(Import " . showsIdent ident . showsString ")"+showsImport (ImportTypeWith ident idents)+ = showsString "(ImportTypeWith "+ . showsIdent ident . space+ . showsList showsIdent idents+ . showsString ")"+showsImport (ImportTypeAll ident)+ = showsString "(ImportTypeAll " . showsIdent ident . showsString ")"++showsDecl :: Decl -> ShowS+showsDecl (ImportDecl pos mident quali mmident mimpspec)+ = showsString "(ImportDecl "+ . showsPosition pos . space+ . showsModuleIdent mident . space+ . shows quali . space+ . showsMaybe showsModuleIdent mmident . space+ . showsMaybe showsImportSpec mimpspec+ . showsString ")"+showsDecl (InfixDecl pos infx prec idents)+ = showsString "(InfixDecl "+ . showsPosition pos . space+ . shows infx . space+ . shows prec . space+ . showsList showsIdent idents+ . showsString ")"+showsDecl (DataDecl pos ident idents consdecls)+ = showsString "(DataDecl "+ . showsPosition pos . space+ . showsIdent ident . space+ . showsList showsIdent idents . space+ . showsList showsConsDecl consdecls+ . showsString ")"+showsDecl (NewtypeDecl pos ident idents newconsdecl)+ = showsString "(NewtypeDecl "+ . showsPosition pos . space+ . showsIdent ident . space+ . showsList showsIdent idents . space+ . showsNewConsDecl newconsdecl+ . showsString ")"+showsDecl (TypeDecl pos ident idents typ)+ = showsString "(TypeDecl "+ . showsPosition pos . space+ . showsIdent ident . space+ . showsList showsIdent idents . space+ . showsTypeExpr typ+ . showsString ")"+showsDecl (TypeSig pos idents typ)+ = showsString "(TypeSig "+ . showsPosition pos . space+ . showsList showsIdent idents . space+ . showsTypeExpr typ+ . showsString ")"+showsDecl (EvalAnnot pos idents annot)+ = showsString "(EvalAnnot "+ . showsPosition pos . space+ . showsList showsIdent idents . space+ . shows annot+ . showsString ")"+showsDecl (FunctionDecl pos ident eqs)+ = showsString "(FunctionDecl "+ . showsPosition pos . space+ . showsIdent ident . space+ . showsList showsEquation eqs+ . showsString ")"+showsDecl (ExternalDecl pos cconv mstr ident typ)+ = showsString "(ExternalDecl "+ . showsPosition pos . space+ . shows cconv . space+ . shows mstr . space+ . showsIdent ident . space+ . showsTypeExpr typ+ . showsString ")"+showsDecl (FlatExternalDecl pos idents)+ = showsString "(FlatExternalDecl "+ . showsPosition pos . space+ . showsList showsIdent idents+ . showsString ")"+showsDecl (PatternDecl pos cons rhs)+ = showsString "(PatternDecl "+ . showsPosition pos . space+ . showsConsTerm cons . space+ . showsRhs rhs+ . showsString ")"+showsDecl (ExtraVariables pos idents)+ = showsString "(ExtraVariables "+ . showsPosition pos . space+ . showsList showsIdent idents+ . showsString ")"++showsConsDecl :: ConstrDecl -> ShowS+showsConsDecl (ConstrDecl pos idents ident types)+ = showsString "(ConstrDecl "+ . showsPosition pos . space+ . showsList showsIdent idents . space+ . showsIdent ident . space+ . showsList showsTypeExpr types+ . showsString ")"++showsNewConsDecl :: NewConstrDecl -> ShowS+showsNewConsDecl (NewConstrDecl pos idents ident typ)+ = showsString "(NewConstrDecl "+ . showsPosition pos . space+ . showsList showsIdent idents . space+ . showsIdent ident . space+ . showsTypeExpr typ+ . showsString ")"++showsTypeExpr :: TypeExpr -> ShowS+showsTypeExpr (ConstructorType qident types)+ = showsString "(ConstructorType "+ . showsQualIdent qident . space+ . showsList showsTypeExpr types+ . showsString ")"+showsTypeExpr (VariableType ident)+ = showsString "(VariableType " . showsIdent ident . showsString ")"+showsTypeExpr (TupleType types)+ = showsString "(TupleType " . showsList showsTypeExpr types . showsString ")"+showsTypeExpr (ListType typ)+ = showsString "(ListType " . showsTypeExpr typ . showsString ")"+showsTypeExpr (ArrowType dom ran)+ = showsString "(ArrowType "+ . showsTypeExpr dom . space+ . showsTypeExpr ran+ . showsString ")"+showsTypeExpr (RecordType fieldts mtyp)+ = showsString "(RecordType "+ . showsList (showsPair (showsList showsIdent) showsTypeExpr) fieldts . space+ . showsMaybe showsTypeExpr mtyp+ . showsString ")"++showsEquation :: Equation -> ShowS+showsEquation (Equation pos lhs rhs)+ = showsString "(Equation "+ . showsPosition pos . space+ . showsLhs lhs . space+ . showsRhs rhs+ . showsString ")"++showsLhs :: Lhs -> ShowS+showsLhs (FunLhs ident conss)+ = showsString "(FunLhs "+ . showsIdent ident . space+ . showsList showsConsTerm conss+ . showsString ")"+showsLhs (OpLhs cons1 ident cons2)+ = showsString "(OpLhs "+ . showsConsTerm cons1 . space+ . showsIdent ident . space+ . showsConsTerm cons2+ . showsString ")"+showsLhs (ApLhs lhs conss)+ = showsString "(ApLhs "+ . showsLhs lhs . space+ . showsList showsConsTerm conss+ . showsString ")"++showsRhs :: Rhs -> ShowS+showsRhs (SimpleRhs pos exp decls)+ = showsString "(SimpleRhs "+ . showsPosition pos . space+ . showsExpression exp . space+ . showsList showsDecl decls+ . showsString ")"+showsRhs (GuardedRhs cexps decls)+ = showsString "(GuardedRhs "+ . showsList showsCondExpr cexps . space+ . showsList showsDecl decls+ . showsString ")"++showsCondExpr :: CondExpr -> ShowS+showsCondExpr (CondExpr pos exp1 exp2)+ = showsString "(CondExpr "+ . showsPosition pos . space+ . showsExpression exp1 . space+ . showsExpression exp2+ . showsString ")"++showsLiteral :: Literal -> ShowS+showsLiteral (Char _ c) = showsString "(Char " . shows c . showsString ")"+showsLiteral (Int ident n)+ = showsString "(Int "+ . showsIdent ident . space+ . shows n+ . showsString ")"+showsLiteral (Float _ x) = showsString "(Float " . shows x . showsString ")"+showsLiteral (String _ s) = showsString "(String " . shows s . showsString ")"++showsConsTerm :: ConstrTerm -> ShowS+showsConsTerm (LiteralPattern lit)+ = showsString "(LiteralPattern "+ . showsLiteral lit+ . showsString ")"+showsConsTerm (NegativePattern ident lit)+ = showsString "(NegativePattern "+ . showsIdent ident . space+ . showsLiteral lit+ . showsString ")"+showsConsTerm (VariablePattern ident)+ = showsString "(VariablePattern "+ . showsIdent ident + . showsString ")"+showsConsTerm (ConstructorPattern qident conss)+ = showsString "(ConstructorPattern "+ . showsQualIdent qident . space+ . showsList showsConsTerm conss+ . showsString ")"+showsConsTerm (InfixPattern cons1 qident cons2)+ = showsString "(InfixPattern "+ . showsConsTerm cons1 . space+ . showsQualIdent qident . space+ . showsConsTerm cons2+ . showsString ")"+showsConsTerm (ParenPattern cons)+ = showsString "(ParenPattern "+ . showsConsTerm cons+ . showsString ")"+showsConsTerm (TuplePattern _ conss)+ = showsString "(TuplePattern "+ . showsList showsConsTerm conss+ . showsString ")"+showsConsTerm (ListPattern _ conss)+ = showsString "(ListPattern "+ . showsList showsConsTerm conss+ . showsString ")"+showsConsTerm (AsPattern ident cons)+ = showsString "(AsPattern "+ . showsIdent ident . space+ . showsConsTerm cons+ . showsString ")"+showsConsTerm (LazyPattern _ cons)+ = showsString "(LazyPattern "+ . showsConsTerm cons+ . showsString ")"+showsConsTerm (FunctionPattern qident conss)+ = showsString "(FunctionPattern "+ . showsQualIdent qident . space+ . showsList showsConsTerm conss+ . showsString ")"+showsConsTerm (InfixFuncPattern cons1 qident cons2)+ = showsString "(InfixFuncPattern "+ . showsConsTerm cons1 . space+ . showsQualIdent qident . space+ . showsConsTerm cons2+ . showsString ")"+showsConsTerm (RecordPattern cfields mcons)+ = shows "(RecordPattern "+ . showsList (showsField showsConsTerm) cfields . space+ . showsMaybe showsConsTerm mcons+ . showsString ")"++showsExpression :: Expression -> ShowS+showsExpression (Literal lit)+ = showsString "(Literal " . showsLiteral lit . showsString ")"+showsExpression (Variable qident)+ = showsString "(Variable " . showsQualIdent qident . showsString ")"+showsExpression (Constructor qident)+ = showsString "(Constructor " . showsQualIdent qident . showsString ")"+showsExpression (Paren exp)+ = showsString "(Paren " . showsExpression exp . showsString ")"+showsExpression (Typed exp typ)+ = showsString "(Typed "+ . showsExpression exp . space+ . showsTypeExpr typ+ . showsString ")"+showsExpression (Tuple _ exps)+ = showsString "(Tuple " . showsList showsExpression exps . showsString ")"+showsExpression (List _ exps)+ = showsString "(List " . showsList showsExpression exps . showsString ")"+showsExpression (ListCompr _ exp stmts)+ = showsString "(ListCompr "+ . showsExpression exp . space+ . showsList showsStatement stmts+ . showsString ")"+showsExpression (EnumFrom exp)+ = showsString "(EnumFrom " . showsExpression exp . showsString ")"+showsExpression (EnumFromThen exp1 exp2)+ = showsString "(EnumFromThen "+ . showsExpression exp1 . space+ . showsExpression exp2+ . showsString ")"+showsExpression (EnumFromTo exp1 exp2)+ = showsString "(EnumFromTo "+ . showsExpression exp1 . space+ . showsExpression exp2+ . showsString ")"+showsExpression (EnumFromThenTo exp1 exp2 exp3)+ = showsString "(EnumFromThenTo "+ . showsExpression exp1 . space+ . showsExpression exp2 . space+ . showsExpression exp3+ . showsString ")"+showsExpression (UnaryMinus ident exp)+ = showsString "(UnaryMinus "+ . showsIdent ident . space+ . showsExpression exp+ . showsString ")"+showsExpression (Apply exp1 exp2)+ = showsString "(Apply "+ . showsExpression exp1 . space+ . showsExpression exp2+ . showsString ")"+showsExpression (InfixApply exp1 op exp2)+ = showsString "(InfixApply "+ . showsExpression exp1 . space+ . showsInfixOp op . space+ . showsExpression exp2+ . showsString ")"+showsExpression (LeftSection exp op)+ = showsString "(LeftSection "+ . showsExpression exp . space+ . showsInfixOp op+ . showsString ")"+showsExpression (RightSection op exp)+ = showsString "(RightSection "+ . showsInfixOp op . space+ . showsExpression exp+ . showsString ")"+showsExpression (Lambda _ conss exp)+ = showsString "(Lambda "+ . showsList showsConsTerm conss . space+ . showsExpression exp + . showsString ")"+showsExpression (Let decls exp)+ = showsString "(Let "+ . showsList showsDecl decls . space+ . showsExpression exp + . showsString ")"+showsExpression (Do stmts exp)+ = showsString "(Do "+ . showsList showsStatement stmts . space+ . showsExpression exp+ . showsString ")"+showsExpression (IfThenElse _ exp1 exp2 exp3)+ = showsString "(IfThenElse "+ . showsExpression exp1 . space+ . showsExpression exp2 . space+ . showsExpression exp3+ . showsString ")"+showsExpression (Case _ exp alts)+ = showsString "(Case "+ . showsExpression exp . space+ . showsList showsAlt alts+ . showsString ")"+showsExpression (RecordConstr efields)+ = showsString "(RecordConstr "+ . showsList (showsField showsExpression) efields+ . showsString ")"+showsExpression (RecordSelection exp ident)+ = showsString "(RecordSelection "+ . showsExpression exp . space+ . showsIdent ident+ . showsString ")"+showsExpression (RecordUpdate efields exp)+ = showsString "(RecordUpdate "+ . showsList (showsField showsExpression) efields . space+ . showsExpression exp+ . showsString ")"++showsInfixOp :: InfixOp -> ShowS+showsInfixOp (InfixOp qident)+ = showsString "(InfixOp " . showsQualIdent qident . showsString ")"+showsInfixOp (InfixConstr qident)+ = showsString "(InfixConstr " . showsQualIdent qident . showsString ")"++showsStatement :: Statement -> ShowS+showsStatement (StmtExpr _ exp)+ = showsString "(StmtExpr " . showsExpression exp . showsString ")"+showsStatement (StmtDecl decls)+ = showsString "(StmtDecl " . showsList showsDecl decls . showsString ")"+showsStatement (StmtBind _ cons exp)+ = showsString "(StmtBind "+ . showsConsTerm cons . space+ . showsExpression exp+ . showsString ")"++showsAlt :: Alt -> ShowS+showsAlt (Alt pos cons rhs)+ = showsString "(Alt "+ . showsPosition pos . space+ . showsConsTerm cons . space+ . showsRhs rhs+ . showsString ")"++showsField :: (a -> ShowS) -> Field a -> ShowS+showsField sa (Field pos ident a)+ = showsString "(Field "+ . showsPosition pos . space+ . showsIdent ident . space+ . sa a+ . showsString ")"++showsString :: String -> ShowS+showsString = (++)++space :: ShowS+space = showsString " "++newline :: ShowS+newline = showsString "\n"++showsMaybe :: (a -> ShowS) -> Maybe a -> ShowS+showsMaybe shs+ = maybe (showsString "Nothing")+ (\x -> showsString "(Just " . shs x . showsString ")")++showsList :: (a -> ShowS) -> [a] -> ShowS+showsList _ [] = showsString "[]"+showsList shs (x:xs)+ = showsString "["+ . foldl (\sys y -> sys . showsString "," . shs y) (shs x) xs+ . showsString "]"++showsPair :: (a -> ShowS) -> (b -> ShowS) -> (a,b) -> ShowS+showsPair sa sb (a,b)+ = showsString "(" . sa a . showsString "," . sb b . showsString ")"+++showsIdent :: Ident -> ShowS+showsIdent (Ident _ name n)+ = showsString "(Ident " . shows name . space . shows n . showsString ")"++showsQualIdent :: QualIdent -> ShowS+showsQualIdent (QualIdent mident ident)+ = showsString "(QualIdent "+ . showsMaybe showsModuleIdent mident + . space+ . showsIdent ident+ . showsString ")"++showsModuleIdent :: ModuleIdent -> ShowS+showsModuleIdent = shows . moduleName
+ src/Curry/Syntax/Type.lhs view
@@ -0,0 +1,315 @@+> {-# LANGUAGE DeriveDataTypeable #-}++% $Id: CurrySyntax.lhs,v 1.43 2004/02/15 22:10:31 wlux Exp $+%+% Copyright (c) 1999-2004, Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{CurrySyntax.lhs}+\section{The Parse Tree}+This module provides the necessary data structures to maintain the+parsed representation of a Curry program.++\em{Note:} this modified version uses haskell type \texttt{Integer}+instead of \texttt{Int} for representing integer values. This allows+an unlimited range of integer constants in Curry programs.+\begin{verbatim}++> module Curry.Syntax.Type where++> import Curry.Base.Ident+> import Curry.Base.Position+> import Data.Generics+> import Control.Monad.State++\end{verbatim}+\paragraph{Modules}+\begin{verbatim}++> data Module = Module ModuleIdent (Maybe ExportSpec) [Decl] +> deriving (Eq,Show,Read,Typeable,Data)++> data ExportSpec = Exporting Position [Export] deriving (Eq,Show,Read,Typeable,Data)+> data Export =+> Export QualIdent -- f/T+> | ExportTypeWith QualIdent [Ident] -- T(C1,...,Cn)+> | ExportTypeAll QualIdent -- T(..)+> | ExportModule ModuleIdent+> deriving (Eq,Show,Read,Typeable,Data)++\end{verbatim}+\paragraph{Module declarations}+\begin{verbatim}++> data ImportSpec =+> Importing Position [Import]+> | Hiding Position [Import]+> deriving (Eq,Show,Read,Typeable,Data)+> data Import =+> Import Ident -- f/T+> | ImportTypeWith Ident [Ident] -- T(C1,...,Cn)+> | ImportTypeAll Ident -- T(..)+> deriving (Eq,Show,Read,Typeable,Data)++> data Decl =+> ImportDecl Position ModuleIdent Qualified (Maybe ModuleIdent)+> (Maybe ImportSpec)+> | InfixDecl Position Infix Integer [Ident]+> | DataDecl Position Ident [Ident] [ConstrDecl]+> | NewtypeDecl Position Ident [Ident] NewConstrDecl+> | TypeDecl Position Ident [Ident] TypeExpr+> | TypeSig Position [Ident] TypeExpr+> | EvalAnnot Position [Ident] EvalAnnotation+> | FunctionDecl Position Ident [Equation]+> | ExternalDecl Position CallConv (Maybe String) Ident TypeExpr+> | FlatExternalDecl Position [Ident]+> | PatternDecl Position ConstrTerm Rhs+> | ExtraVariables Position [Ident]+> deriving (Eq,Show,Read,Typeable,Data)++> data ConstrDecl =+> ConstrDecl Position [Ident] Ident [TypeExpr]+> | ConOpDecl Position [Ident] TypeExpr Ident TypeExpr+> deriving (Eq,Show,Read,Typeable,Data)+> data NewConstrDecl =+> NewConstrDecl Position [Ident] Ident TypeExpr+> deriving (Eq,Show,Read,Typeable,Data)++> type Qualified = Bool+> data Infix = InfixL | InfixR | Infix deriving (Eq,Show,Read,Typeable,Data)+> data EvalAnnotation = EvalRigid | EvalChoice deriving (Eq,Show,Read,Typeable,Data)+> data CallConv = CallConvPrimitive | CallConvCCall deriving (Eq,Show,Read,Typeable,Data)++\end{verbatim}+\paragraph{Module interfaces}+Interface declarations are restricted to type declarations and signatures. +Note that an interface function declaration additionaly contains the +function arity (= number of parameters) in order to generate+correct FlatCurry function applications.+\begin{verbatim}++> data Interface = Interface ModuleIdent [IDecl] deriving (Eq,Show,Read,Typeable,Data)++> data IDecl =+> IImportDecl Position ModuleIdent+> | IInfixDecl Position Infix Integer QualIdent+> | HidingDataDecl Position Ident [Ident] +> | IDataDecl Position QualIdent [Ident] [Maybe ConstrDecl]+> | INewtypeDecl Position QualIdent [Ident] NewConstrDecl+> | ITypeDecl Position QualIdent [Ident] TypeExpr+> | IFunctionDecl Position QualIdent Int TypeExpr+> deriving (Eq,Show,Read,Typeable,Data)++\end{verbatim}+\paragraph{Types}+\begin{verbatim}++> data TypeExpr =+> ConstructorType QualIdent [TypeExpr]+> | VariableType Ident+> | TupleType [TypeExpr]+> | ListType TypeExpr+> | ArrowType TypeExpr TypeExpr+> | RecordType [([Ident],TypeExpr)] (Maybe TypeExpr) +> -- {l1 :: t1,...,ln :: tn | r}+> deriving (Eq,Show,Read,Typeable,Data)++\end{verbatim}+\paragraph{Functions}+\begin{verbatim}++> data Equation = Equation Position Lhs Rhs deriving (Eq,Show,Read,Typeable,Data)+> data Lhs =+> FunLhs Ident [ConstrTerm]+> | OpLhs ConstrTerm Ident ConstrTerm+> | ApLhs Lhs [ConstrTerm]+> deriving (Eq,Show,Read,Typeable,Data)+> data Rhs =+> SimpleRhs Position Expression [Decl]+> | GuardedRhs [CondExpr] [Decl]+> deriving (Eq,Show,Read,Typeable,Data)+> data CondExpr = CondExpr Position Expression Expression deriving (Eq,Show,Read,Typeable,Data)++> flatLhs :: Lhs -> (Ident,[ConstrTerm])+> flatLhs lhs = flat lhs []+> where flat (FunLhs f ts) ts' = (f,ts ++ ts')+> flat (OpLhs t1 op t2) ts = (op,t1:t2:ts)+> flat (ApLhs lhs ts) ts' = flat lhs (ts ++ ts')++\end{verbatim}+\paragraph{Literals} The \texttt{Ident} argument of an \texttt{Int}+literal is used for supporting ad-hoc polymorphism on integer+numbers. An integer literal can be used either as an integer number or+as a floating-point number depending on its context. The compiler uses+the identifier of the \texttt{Int} literal for maintaining its type.+\begin{verbatim}++> data Literal =+> Char SrcRef Char -- should be Int to handle Unicode+> | Int Ident Integer+> | Float SrcRef Double+> | String SrcRef String -- should be [Int] to handle Unicode+> deriving (Eq,Show,Read,Typeable,Data)++> mk' :: ([SrcRef] -> a) -> a+> mk' = ($[])++> mk :: (SrcRef -> a) -> a+> mk = ($noRef)++> mkInt :: Integer -> Literal+> mkInt i = mk (\r -> Int (addPositionIdent (AST r) anonId) i) ++\end{verbatim}+\paragraph{Patterns}+\begin{verbatim}++> data ConstrTerm =+> LiteralPattern Literal+> | NegativePattern Ident Literal+> | VariablePattern Ident+> | ConstructorPattern QualIdent [ConstrTerm]+> | InfixPattern ConstrTerm QualIdent ConstrTerm+> | ParenPattern ConstrTerm+> | TuplePattern SrcRef [ConstrTerm]+> | ListPattern [SrcRef] [ConstrTerm]+> | AsPattern Ident ConstrTerm+> | LazyPattern SrcRef ConstrTerm+> | FunctionPattern QualIdent [ConstrTerm]+> | InfixFuncPattern ConstrTerm QualIdent ConstrTerm+> | RecordPattern [Field ConstrTerm] (Maybe ConstrTerm) +> -- {l1 = p1, ..., ln = pn} oder {l1 = p1, ..., ln = pn | p}+> deriving (Eq,Show,Read,Typeable,Data)++\end{verbatim}+\paragraph{Expressions}+\begin{verbatim}++> data Expression =+> Literal Literal+> | Variable QualIdent+> | Constructor QualIdent+> | Paren Expression+> | Typed Expression TypeExpr+> | Tuple SrcRef [Expression]+> | List [SrcRef] [Expression]+> | ListCompr SrcRef Expression [Statement] -- the ref corresponds to the main list +> | EnumFrom Expression+> | EnumFromThen Expression Expression+> | EnumFromTo Expression Expression+> | EnumFromThenTo Expression Expression Expression+> | UnaryMinus Ident Expression+> | Apply Expression Expression+> | InfixApply Expression InfixOp Expression+> | LeftSection Expression InfixOp+> | RightSection InfixOp Expression+> | Lambda SrcRef [ConstrTerm] Expression+> | Let [Decl] Expression+> | Do [Statement] Expression+> | IfThenElse SrcRef Expression Expression Expression+> | Case SrcRef Expression [Alt]+> | RecordConstr [Field Expression] -- {l1 = e1,...,ln = en}+> | RecordSelection Expression Ident -- e -> l+> | RecordUpdate [Field Expression] Expression -- {l1 := e1,...,ln := en | e}+> deriving (Eq,Show,Read,Typeable,Data)++> data InfixOp = InfixOp QualIdent | InfixConstr QualIdent deriving (Eq,Show,Read,Typeable,Data)++> data Statement =+> StmtExpr SrcRef Expression+> | StmtDecl [Decl]+> | StmtBind SrcRef ConstrTerm Expression+> deriving (Eq,Show,Read,Typeable,Data)++> data Alt = Alt Position ConstrTerm Rhs deriving (Eq,Show,Read,Typeable,Data)++> data Field a = Field Position Ident a deriving (Eq, Show,Read,Typeable,Data)++> fieldLabel :: Field a -> Ident+> fieldLabel (Field _ l _) = l++> fieldTerm :: Field a -> a+> fieldTerm (Field _ _ t) = t++> field2Tuple :: Field a -> (Ident,a)+> field2Tuple (Field _ l t) = (l,t)++> opName :: InfixOp -> QualIdent+> opName (InfixOp op) = op+> opName (InfixConstr c) = c++\end{verbatim}++> instance SrcRefOf ConstrTerm where+> srcRefOf (LiteralPattern l) = srcRefOf l+> srcRefOf (NegativePattern i _) = srcRefOf i+> srcRefOf (VariablePattern i) = srcRefOf i+> srcRefOf (ConstructorPattern i _) = srcRefOf i+> srcRefOf (InfixPattern _ i _) = srcRefOf i+> srcRefOf (ParenPattern c) = srcRefOf c+> srcRefOf (TuplePattern s _) = s+> srcRefOf (ListPattern s _) = error "list pattern has several source refs"+> srcRefOf (AsPattern i _) = srcRefOf i+> srcRefOf (LazyPattern s _) = s+> srcRefOf (FunctionPattern i _) = srcRefOf i+> srcRefOf (InfixFuncPattern _ i _) = srcRefOf i++> instance SrcRefOf Literal where+> srcRefOf (Char s _) = s+> srcRefOf (Int i _) = srcRefOf i+> srcRefOf (Float s _) = s+> srcRefOf (String s _) = s++---------------------------+-- add source references+---------------------------++> type M a = a -> State Int a+> +> addSrcRefs :: Module -> Module+> addSrcRefs x = evalState (addRef x) 0+> where +> addRef :: Data a' => M a' +> addRef = down `extM` addRefPos +> `extM` addRefSrc +> `extM` addRefIdent+> `extM` addRefListPat+> `extM` addRefListExp+> where+> down :: Data a' => M a'+> down = gmapM addRef+> +> addRefPos :: M [SrcRef]+> addRefPos _ = liftM (:[]) next+> +> addRefSrc :: M SrcRef+> addRefSrc _ = next+> +> addRefIdent :: M Ident+> addRefIdent ident = liftM (flip addRefId ident) next+>+> addRefListPat :: M ConstrTerm+> addRefListPat (ListPattern _ ts) = do+> liftM (uncurry ListPattern) (addRefList ts)+> addRefListPat ct = gmapM addRef ct+> +> addRefListExp :: M Expression+> addRefListExp (List _ ts) = do+> liftM (uncurry List) (addRefList ts)+> addRefListExp ct = gmapM addRef ct+> +> addRefList :: Data a' => [a'] -> State Int ([SrcRef],[a'])+> addRefList ts = do+> i <- next+> let add t = do t' <- addRef t;j <- next; return (j,t')+> ists <- sequence (map add ts)+> let (is,ts') = unzip ists+> return (i:is,ts')+> +> next :: State Int SrcRef+> next = do+> i <- get+> put $! i+1+> return (SrcRef [i])
+ src/Curry/Syntax/Unlit.hs view
@@ -0,0 +1,57 @@+{-+ Since version 0.7 of the language report, Curry accepts literate+ source programs. In a literate source all program lines must begin+ with a greater sign in the first column. All other lines are assumed+ to be documentation. In order to avoid some common errors with+ literate programs, Curry requires at least one program line to be+ present in the file. In addition, every block of program code must be+ preceded by a blank line and followed by a blank line.+-}+++module Curry.Syntax.Unlit(unlit) where++import Control.Monad(when, zipWithM)+import Data.Char++import Curry.Base.Position+import Curry.Base.MessageMonad+++data Line = Program !Int String+ | Blank | Comment++classify :: Int -> String -> Line+classify l ('>':cs) = Program l cs+classify _ cs+ | all isSpace cs = Blank+ | otherwise = Comment++{-+ Process a literate program into error messages (if any) and the+ corresponding non-literate program.+-}++unlit :: FilePath -> String -> MsgMonad String+unlit fn lcy = do ls <- progLines fn (zipWith classify [1..] $ lines lcy)+ when (all null ls) $+ failWith (fn ++ ": no code in literate script")+ return (unlines ls)++{-+ Check that each program line is not adjacent to a comment line and+ there is at least one program line.+-}+progLines :: FilePath -> [Line] -> MsgMonad [String]+progLines fn cs + = zipWithM adjacent (Blank : cs) cs+ where+ adjacent :: Line -> Line -> MsgMonad String+ adjacent (Program p _) Comment = message fn p "followed"+ adjacent Comment (Program p _) = message fn p "preceded"+ adjacent _ (Program _ s) = return s+ adjacent _ _ = return ""++message :: String -> Int -> String -> MsgMonad a+message file p w = failWithAt (Position file p 1 noRef) msg+ where msg = "When reading literate source: Program line is " ++ w ++ " by comment line."
+ src/Curry/Syntax/Utils.hs view
@@ -0,0 +1,202 @@+module Curry.Syntax.Utils(Expr, fv, qfv,+ QuantExpr, bv) where++import qualified Data.Set as Set++import Curry.Base.Ident +import Curry.Syntax.Type++{-+ Free and bound variables+ + The compiler needs to compute the sets of free and bound variables for+ various different entities. We will devote three type classes to that+ purpose. The \texttt{QualExpr} class is expected to take into account+ that it is possible to use a qualified name to refer to a function+ defined in the current module and therefore \emph{M.x} and $x$, where+ $M$ is the current module name, should be considered the same name.+ However note that this is correct only after renaming all local+ definitions as \emph{M.x} always denotes an entity defined at the+ top-level.+ + The \texttt{Decl} instance of \texttt{QualExpr} returns all free+ variables on the right hand side, regardless of whether they are bound+ on the left hand side. This is more convenient as declarations are+ usually processed in a declaration group where the set of free+ variables cannot be computed independently for each declaration. Also+ note that the operator in a unary minus expression is not a free+ variable. This operator always refers to a global function from the+ prelude.+-}++class Expr e where+ fv :: e -> [Ident]+class QualExpr e where+ qfv :: ModuleIdent -> e -> [Ident]+class QuantExpr e where+ bv :: e -> [Ident]++instance Expr e => Expr [e] where+ fv = concat . map fv+instance QualExpr e => QualExpr [e] where+ qfv m = concat . map (qfv m)+instance QuantExpr e => QuantExpr [e] where+ bv = concat . map bv++instance QualExpr Decl where+ qfv m (FunctionDecl _ _ eqs) = qfv m eqs+ qfv m (PatternDecl _ _ rhs) = qfv m rhs+ qfv _ _ = []++instance QuantExpr Decl where+ bv (TypeSig _ vs _) = vs+ bv (EvalAnnot _ fs _) = fs+ bv (FunctionDecl _ f _) = [f]+ bv (ExternalDecl _ _ _ f _) = [f]+ bv (FlatExternalDecl _ fs) = fs+ bv (PatternDecl _ t _) = bv t+ bv (ExtraVariables _ vs) = vs+ bv _ = []++instance QualExpr Equation where+ qfv m (Equation _ lhs rhs) = filterBv lhs (qfv m lhs ++ qfv m rhs)++instance QuantExpr Lhs where+ bv = bv . snd . flatLhs++instance QualExpr Lhs where+ qfv m lhs = qfv m (snd (flatLhs lhs))++instance QualExpr Rhs where+ qfv m (SimpleRhs _ e ds) = filterBv ds (qfv m e ++ qfv m ds)+ qfv m (GuardedRhs es ds) = filterBv ds (qfv m es ++ qfv m ds)++instance QualExpr CondExpr where+ qfv m (CondExpr _ g e) = qfv m g ++ qfv m e++instance QualExpr Expression where+ qfv _ (Literal _) = []+ qfv m (Variable v) = maybe [] return (localIdent m v)+ qfv _ (Constructor _) = []+ qfv m (Paren e) = qfv m e+ qfv m (Typed e _) = qfv m e+ qfv m (Tuple _ es) = qfv m es+ qfv m (List _ es) = qfv m es+ qfv m (ListCompr _ e qs) = foldr (qfvStmt m) (qfv m e) qs+ qfv m (EnumFrom e) = qfv m e+ qfv m (EnumFromThen e1 e2) = qfv m e1 ++ qfv m e2+ qfv m (EnumFromTo e1 e2) = qfv m e1 ++ qfv m e2+ qfv m (EnumFromThenTo e1 e2 e3) = qfv m e1 ++ qfv m e2 ++ qfv m e3+ qfv m (UnaryMinus _ e) = qfv m e+ qfv m (Apply e1 e2) = qfv m e1 ++ qfv m e2+ qfv m (InfixApply e1 op e2) = qfv m op ++ qfv m e1 ++ qfv m e2+ qfv m (LeftSection e op) = qfv m op ++ qfv m e+ qfv m (RightSection op e) = qfv m op ++ qfv m e+ qfv m (Lambda _ ts e) = filterBv ts (qfv m e)+ qfv m (Let ds e) = filterBv ds (qfv m ds ++ qfv m e)+ qfv m (Do sts e) = foldr (qfvStmt m) (qfv m e) sts+ qfv m (IfThenElse _ e1 e2 e3) = qfv m e1 ++ qfv m e2 ++ qfv m e3+ qfv m (Case _ e alts) = qfv m e ++ qfv m alts+ qfv m (RecordConstr fs) = qfv m fs+ qfv m (RecordSelection e _) = qfv m e+ qfv m (RecordUpdate fs e) = qfv m e ++ qfv m fs++qfvStmt :: ModuleIdent -> Statement -> [Ident] -> [Ident]+qfvStmt m st fvs = qfv m st ++ filterBv st fvs++instance QualExpr Statement where+ qfv m (StmtExpr _ e) = qfv m e+ qfv m (StmtDecl ds) = filterBv ds (qfv m ds)+ qfv m (StmtBind _ t e) = qfv m e++instance QualExpr Alt where+ qfv m (Alt _ t rhs) = filterBv t (qfv m rhs)++instance QuantExpr a => QuantExpr (Field a) where+ bv (Field _ _ t) = bv t++instance QualExpr a => QualExpr (Field a) where+ qfv m (Field _ _ t) = qfv m t++instance QuantExpr Statement where+ bv (StmtExpr _ e) = []+ bv (StmtBind _ t e) = bv t+ bv (StmtDecl ds) = bv ds++instance QualExpr InfixOp where+ qfv m (InfixOp op) = qfv m (Variable op)+ qfv _ (InfixConstr _) = []++instance QuantExpr ConstrTerm where+ bv (LiteralPattern _) = []+ bv (NegativePattern _ _) = []+ bv (VariablePattern v) = [v]+ bv (ConstructorPattern c ts) = bv ts+ bv (InfixPattern t1 op t2) = bv t1 ++ bv t2+ bv (ParenPattern t) = bv t+ bv (TuplePattern _ ts) = bv ts+ bv (ListPattern _ ts) = bv ts+ bv (AsPattern v t) = v : bv t+ bv (LazyPattern _ t) = bv t+ bv (FunctionPattern f ts) = bvFuncPatt (FunctionPattern f ts)+ bv (InfixFuncPattern t1 op t2) = bvFuncPatt (InfixFuncPattern t1 op t2)+ bv (RecordPattern fs r) = (maybe [] bv r) ++ bv fs++instance QualExpr ConstrTerm where+ qfv _ (LiteralPattern _) = []+ qfv _ (NegativePattern _ _) = []+ qfv _ (VariablePattern _) = []+ qfv m (ConstructorPattern _ ts) = qfv m ts+ qfv m (InfixPattern t1 _ t2) = qfv m [t1,t2]+ qfv m (ParenPattern t) = qfv m t+ qfv m (TuplePattern _ ts) = qfv m ts+ qfv m (ListPattern _ ts) = qfv m ts+ qfv m (AsPattern _ ts) = qfv m ts+ qfv m (LazyPattern _ t) = qfv m t+ qfv m (FunctionPattern f ts) + = (maybe [] return (localIdent m f)) ++ qfv m ts+ qfv m (InfixFuncPattern t1 op t2) + = (maybe [] return (localIdent m op)) ++ qfv m [t1,t2]+ qfv m (RecordPattern fs r) = (maybe [] (qfv m) r) ++ qfv m fs++instance Expr TypeExpr where+ fv (ConstructorType _ tys) = fv tys+ fv (VariableType tv)+ | tv == anonId = []+ | otherwise = [tv]+ fv (TupleType tys) = fv tys+ fv (ListType ty) = fv ty+ fv (ArrowType ty1 ty2) = fv ty1 ++ fv ty2+ fv (RecordType fs rty) = (maybe [] fv rty) ++ fv (map snd fs)++filterBv :: QuantExpr e => e -> [Ident] -> [Ident]+filterBv e = filter (`Set.notMember` Set.fromList (bv e))++{-+ Since multiple variable occurrences are allowed in function patterns,+ it is necessary to compute the list of bound variables in a different way:+ Each variable occuring in the function pattern will be unique in the result+ list.+ -}++bvFuncPatt :: ConstrTerm -> [Ident]+bvFuncPatt = bvfp []+ where+ bvfp bvs (LiteralPattern _) = bvs+ bvfp bvs (NegativePattern _ _) = bvs+ bvfp bvs (VariablePattern v)+ | elem v bvs = bvs+ | otherwise = v:bvs+ bvfp bvs (ConstructorPattern c ts) = foldl bvfp bvs ts+ bvfp bvs (InfixPattern t1 op t2) = foldl bvfp bvs [t1,t2]+ bvfp bvs (ParenPattern t) = bvfp bvs t+ bvfp bvs (TuplePattern _ ts) = foldl bvfp bvs ts+ bvfp bvs (ListPattern _ ts) = foldl bvfp bvs ts+ bvfp bvs (AsPattern v t)+ | elem v bvs = bvfp bvs t+ | otherwise = bvfp (v:bvs) t+ bvfp bvs (LazyPattern _ t) = bvfp bvs t+ bvfp bvs (FunctionPattern f ts) = foldl bvfp bvs ts+ bvfp bvs (InfixFuncPattern t1 op t2) = foldl bvfp bvs [t1, t2]+ bvfp bvs (RecordPattern fs r)+ = foldl bvfp (maybe bvs (bvfp bvs) r) (map fieldTerm fs)
src/CurryBuilder.hs view
@@ -13,16 +13,18 @@ import System.Exit import System.Time import Control.Monad+import qualified Data.Map as Map import Data.Maybe import Data.List import System.IO -import Modules (compileModule_)+import Curry.Base.Ident++import Modules (compileModule) import CurryCompilerOpts import CurryDeps-import Ident+import Filenames import PathUtils-import Env ------------------------------------------------------------------------------- @@ -71,7 +73,7 @@ compileFile file = do unless (noVerb options) (putStrLn ("compiling " ++ file ++ " ..."))- compileCurry (compOpts True) file+ compileModule (compOpts True) file return () skipFile file@@ -83,7 +85,7 @@ (putStrLn ("generating " ++ (head (targetNames file)) ++ " ..."))- compileCurry (compOpts False) file+ compileModule (compOpts False) file return () targetNames fn @@ -121,7 +123,7 @@ genDeps :: [FilePath] -> FilePath -> IO ([(ModuleIdent,Source)], [String]) genDeps paths file- = fmap (flattenDeps . sortDeps) (deps paths [] emptyEnv file)+ = fmap flattenDeps (deps paths [] Map.empty file) -------------------------------------------------------------------------------@@ -168,9 +170,6 @@ -- outOfDate :: [ClockTime] -> [ClockTime] -> Bool outOfDate tgtimes dptimes = or (map (\t -> or (map ((<) t) dptimes)) tgtimes)---compileCurry = compileModule_ ------------------------------------------------------------------------------- -- Error handling
src/CurryDeps.lhs view
@@ -13,74 +13,34 @@ dependencies and to update programs composed of multiple modules. \begin{verbatim} -> module CurryDeps where+> module CurryDeps(Source(..),+> deps, flattenDeps, sourceDeps, moduleDeps+> ) where > import Data.List+> import qualified Data.Map as Map > import Data.Maybe > import Control.Monad -> import Error-> import Ident-> import Unlit-> import CurrySyntax hiding(Interface(..))-> import CurryParser(parseHeader)-> import SCC-> import Env+> import Curry.Base.Ident+> import Curry.Base.MessageMonad +> import Curry.Syntax hiding(Interface(..))++> import SCC+> import Filenames > import PathUtils > data Source = Source FilePath [ModuleIdent] > | Interface FilePath > | Unknown > deriving (Eq,Ord,Show)-> type SourceEnv = Env ModuleIdent Source--\end{verbatim}-The module has two entry points. The function \texttt{buildScript}-computes either a build or clean script for a module while-\texttt{makeDepend} computes dependency rules for inclusion into a-Makefile.-\begin{verbatim}--> buildScript :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool-> -> [FilePath] -> [FilePath] -> Maybe FilePath -> FilePath -> -> IO [String]-> buildScript clean debug linkAlways flat xml acy uacy-> paths libraryPaths ofn fn =-> do-> mfn' <- getCurryPath (paths ++ libraryPaths) fn-> (fn',es1) <- return (maybe ("",["Error: missing module \"" ++ fn ++ "\""])-> (\x -> (x,[]))-> mfn')-> (ms,es2) <- fmap -> (flattenDeps . sortDeps)-> (deps paths (filter (`notElem` paths) libraryPaths) emptyEnv fn')-> es <- return (es1 ++ es2)-> when (null es)-> (putStr -> (makeScript clean debug flat xml acy uacy linkAlways -> (outputFile fn') fn ms))-> return es-> where outputFile fn-> | takeExtension fn `elem` moduleExts ++ objectExts = Nothing-> | otherwise = ofn `mplus` Just fn-> makeScript clean = if clean then makeCleanScript else makeBuildScript--> makeDepend :: [FilePath] -> [FilePath] -> Maybe FilePath -> [FilePath]-> -> IO ()-> makeDepend paths libraryPaths ofn ms =-> do-> flatDeps <- liftM (makeDeps True) (allDeps flat)-> objectDeps <- liftM (makeDeps False) (allDeps nonFlat)-> maybe putStr writeFile ofn (flatDeps ++ objectDeps)-> where (flat,nonFlat) = partition (flatExt `isSuffixOf`) ms-> allDeps = foldM (deps paths libraryPaths') emptyEnv-> libraryPaths' = filter (`notElem` paths) libraryPaths+> type SourceEnv = Map.Map ModuleIdent Source > deps :: [FilePath] -> [FilePath] -> SourceEnv -> FilePath -> IO SourceEnv > deps paths libraryPaths mEnv fn > | e `elem` sourceExts = sourceDeps paths libraryPaths (mkMIdent [r]) mEnv fn-> | e == icurryExt = return emptyEnv+> | e == icurryExt = return Map.empty > | e `elem` objectExts = targetDeps paths libraryPaths mEnv r > | otherwise = targetDeps paths libraryPaths mEnv fn > where r = dropExtension fn@@ -90,7 +50,7 @@ > -> IO SourceEnv > targetDeps paths libraryPaths mEnv fn = > lookupFile [""] sourceExts fn >>=-> maybe (return (bindEnv m Unknown mEnv)) (sourceDeps paths libraryPaths m mEnv)+> maybe (return (Map.insert m Unknown mEnv)) (sourceDeps paths libraryPaths m mEnv) > where m = mkMIdent [fn] \end{verbatim}@@ -108,12 +68,6 @@ directories more than twice. \begin{verbatim} -> lookupModule :: [FilePath] -> [FilePath] -> ModuleIdent-> -> IO (Maybe FilePath)-> lookupModule paths libraryPaths m-> = lookupFile ("" : paths ++ libraryPaths) moduleExts fn-> where fn = foldr1 catPath (moduleQualifiers m)- \end{verbatim} In order to compute the dependency graph, source files for each module need to be looked up. When a source module is found, its header is@@ -126,7 +80,7 @@ > moduleDeps :: [FilePath] -> [FilePath] -> SourceEnv -> ModuleIdent > -> IO SourceEnv > moduleDeps paths libraryPaths mEnv m =-> case lookupEnv m mEnv of+> case Map.lookup m mEnv of > Just _ -> return mEnv > Nothing -> > do@@ -134,265 +88,55 @@ > case mbFn of > Just fn > | icurryExt `isSuffixOf` fn ->-> return (bindEnv m (Interface fn) mEnv)+> return (Map.insert m (Interface fn) mEnv) > | otherwise -> sourceDeps paths libraryPaths m mEnv fn-> Nothing -> return (bindEnv m Unknown mEnv)+> Nothing -> return (Map.insert m Unknown mEnv) > sourceDeps :: [FilePath] -> [FilePath] -> ModuleIdent -> SourceEnv > -> FilePath -> IO SourceEnv > sourceDeps paths libraryPaths m mEnv fn = > do > s <- readModule fn-> case parseHeader fn (unlitLiterate fn s) of-> Ok (Module m' _ ds) ->+> case fst $ runMsg $ parseHeader fn s of+> Right (Module m' _ ds) -> > let ms = imports m' ds in-> foldM (moduleDeps paths libraryPaths) (bindEnv m (Source fn ms) mEnv) ms-> Error _ -> return (bindEnv m (Source fn []) mEnv)+> foldM (moduleDeps paths libraryPaths) (Map.insert m (Source fn ms) mEnv) ms+> Left _ -> return (Map.insert m (Source fn []) mEnv) > imports :: ModuleIdent -> [Decl] -> [ModuleIdent] > imports m ds = nub $ > [preludeMIdent | m /= preludeMIdent] ++ [m | ImportDecl _ m _ _ _ <- ds] -> unlitLiterate :: FilePath -> String -> String-> unlitLiterate fn-> | lcurryExt `isSuffixOf` fn = snd . unlit fn-> | otherwise = id -\end{verbatim}-It is quite straight forward to generate Makefile dependencies from-the dependency environment. In order for these dependencies to work,-the Makefile must include a rule-\begin{verbatim}-.SUFFIXES: .lcurry .curry .icurry-.o.icurry: @echo interface $@ not found, remove $< and recompile; exit 1-\end{verbatim}-This dependency rule introduces an indirect dependency between a-module and its interface. In particular, the interface may be updated-when the module is recompiled and a new object file is generated but-it does not matter if the interface is out-of-date with respect to the-object code.-\begin{verbatim} -> makeDeps :: Bool -> SourceEnv -> String-> makeDeps flat mEnv =-> unlines (filter (not . null) (map (depsLine . snd) (envToList mEnv)))-> where depsLine (Source fn ms) =-> targetName fn ++ ": " ++ fn ++ " " ++-> unwords (filter (not . null) (map interf ms))-> depsLine (Interface _) = []-> depsLine Unknown = []-> interf m = maybe [] interfFile (lookupEnv m mEnv)-> interfFile (Source fn _) = interfName fn-> interfFile (Interface fn) = fn-> interfFile Unknown = ""-> targetName = if flat then flatName else objectName False--\end{verbatim} If we want to compile the program instead of generating Makefile dependencies the environment has to be sorted topologically. Note that the dependency graph should not contain any cycles.-\begin{verbatim} -> sortDeps :: SourceEnv -> [[(ModuleIdent,Source)]]-> sortDeps = scc (modules . fst) (imports . snd) . envToList-> where modules m = [m]-> imports (Source _ ms) = ms-> imports (Interface _) = []-> imports Unknown = []--> flattenDeps :: [[(ModuleIdent,Source)]] -> ([(ModuleIdent,Source)],[String])-> flattenDeps [] = ([],[])-> flattenDeps (dep:deps) =-> case dep of-> [] -> (ms',es')-> [m] -> (m:ms',es')-> _ -> (ms',cyclicError (map fst dep) : es')-> where (ms',es') = flattenDeps deps--> cyclicError :: [ModuleIdent] -> String-> cyclicError (m:ms) =-> "Cylic import dependency between modules " ++ show m ++ rest ms-> where rest [m] = " and " ++ show m-> rest (m:ms) = ", " ++ show m ++ rest' ms-> rest' [m] = ", and " ++ show m-> rest' (m:ms) = ", " ++ show m ++ rest' ms--\end{verbatim}-The function \texttt{makeBuildScript} returns a shell script that-rebuilds several program representations (e.g. interfaces, FlatCurry etc.)-given a sorted list of module informations. The-script uses the command \verb|compile| and \verb|link| to build-programs and representations. They should be defined to reasonable values in the-environment where the script is executed (e.g. compile=cyc-The script deliberately uses-the \verb|-e| shell option so that the script is terminated upon the-first error. Unlike the original function \texttt{makeBuildScript} this-modification uses the command "smake" to check the out-of-dateness-of dependend program files.-\begin{verbatim}--> makeBuildScript :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> -> Maybe FilePath -> FilePath -> [(ModuleIdent,Source)] -> -> String-> makeBuildScript debug flat xml acy uacy linkAlways ofn fn mEnv =-> unlines ("set -e" : (map (compCommands . snd) mEnv)-> ++ (maybe [] linkCommands ofn))-> where -> compCommands (Source fn' ms)-> | (acy || uacy) && dropExtension fn /= dropExtension fn'-> = (smake ([flatName fn', flatIntName fn'])-> (fn' : catMaybes (map flatInt ms))-> "")-> ++ " || (\\" --rm -f " ++ (interfName fn') ++ " && \\"-> ++ unwords ["compile", "--flat", fn', "-o",-> flatName fn']-> ++ ")"-> | otherwise-> = (smake (targetNames fn')-> (fn' : catMaybes (map flatInt ms))-> "")-> ++ " || (\\" --rm -f " ++ (interfName fn')-> ++ (compile fn') ++ ")"-> compCommands (Interface _) = []-> compCommands Unknown = []->-> linkCommands fn'-> | linkAlways = [link fn' os]-> | otherwise = [smake [fn'] os "", " || \\", (link fn' os)]-> where os = reverse (catMaybes (map (object . snd) mEnv))->-> smake ts ds rule-> = "$CURRY_PATH/smake " -> ++ (unwords ts) ++ " : " -> ++ (unwords ds)-> ++ (if null rule then "" else " : " ++ rule)->-> compile fn' = unwords ["compile", cFlag, fn', "-o", -> head (targetNames fn')] ->-> cFlag | flat = "--flat"-> | xml = "--xml"-> | acy = "--acy"-> | uacy = "--uacy"-> | otherwise = "-c"+> flattenDeps :: SourceEnv -> ([(ModuleIdent,Source)],[String])+> flattenDeps = fdeps . sortDeps+> where+> sortDeps :: SourceEnv -> [[(ModuleIdent,Source)]]+> sortDeps = scc modules imports . Map.toList >-> oGen fn' | flat || xml || acy || uacy = []-> | otherwise = ["-o", head (targetNames fn')]+> modules (m, _) = [m] >-> link fn' os = unwords ("link" : "-o" : fn' : os)+> imports (_,Source _ ms) = ms+> imports (_,Interface _) = []+> imports (_,Unknown) = [] >-> flatInt m =-> case lookup m mEnv of-> Just (Source fn' _) -> -> Just (flatIntName fn')-> Just (Interface fn') -> -> Just (flatIntName (takeBaseName fn'))-> Just Unknown -> -> Nothing-> _ -> Nothing+> fdeps :: [[(ModuleIdent,Source)]] -> ([(ModuleIdent,Source)],[String])+> fdeps = foldr checkdep ([], [])+> +> checkdep [] (ms', es') = (ms',es')+> checkdep [m] (ms', es') = (m:ms',es')+> checkdep dep (ms', es') = (ms',cyclicError (map fst dep) : es') >-> object (Source fn' _) = Just (head (targetNames fn'))-> object (Interface _) = Nothing-> object Unknown = Nothing+> cyclicError :: [ModuleIdent] -> String+> cyclicError (m:ms) =+> "Cylic import dependency between modules " ++ show m ++ rest ms >-> targetNames fn' | flat = [flatName fn', flatIntName fn']-> | xml = [xmlName fn']-> | acy = [acyName fn']-> | uacy = [uacyName fn']-> | otherwise = [objectName debug fn']---\end{verbatim}-The function \texttt{makeCleanScript} returns a shell script that-removes all compiled files for a module. The script uses the command-\verb|remove| to delete the files. It should be defined to a-reasonable value in the environment where the script is executed.-\begin{verbatim}--> makeCleanScript :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> -> Maybe FilePath -> FilePath -> [(ModuleIdent,Source)] -> -> String-> makeCleanScript debug flat xml acy uacy _ ofn _ mEnv =-> unwords ("remove" : foldr files (maybe [] return ofn) (map snd mEnv))-> where d = if debug then 2 else 0-> files = if flat then flatFiles else nonFlatFiles-> flatFiles (Source fn _) fs =-> drop d [interfName fn,flatName fn] ++ fs-> flatFiles (Interface _) fs = fs-> flatFiles Unknown fs = fs-> nonFlatFiles (Source fn _) fs =-> drop d [interfName fn,objectName False fn,objectName True fn] ++-> fs-> nonFlatFiles (Interface _) fs = fs-> nonFlatFiles Unknown fs = fs--\end{verbatim}-The function \verb|getCurryPath| searches in predefined paths-for the corresponding \texttt{.curry} or \texttt{.lcurry} file, -if the given file name has no extension.-\begin{verbatim}--> getCurryPath :: [FilePath] -> FilePath -> IO (Maybe FilePath)-> getCurryPath paths fn-> = lookupFile filepaths exts fn-> where-> filepaths = "":paths'-> fnext = takeExtension fn-> exts | null fnext = sourceExts-> | otherwise = [fnext]-> paths' | pathSeparator `elem` fn = []-> | otherwise = paths---\end{verbatim}-The following functions compute the name of the target file (e.g.-interface file, flat curry file etc.)-for a source module. Note that-output files are always created in the same directory as the source-file.-\begin{verbatim}--> interfName :: FilePath -> FilePath-> interfName sfn = replaceExtension sfn icurryExt--> flatName :: FilePath -> FilePath-> flatName fn = replaceExtension fn flatExt--> flatIntName :: FilePath -> FilePath-> flatIntName fn = replaceExtension fn flatIntExt--> xmlName :: FilePath -> FilePath-> xmlName fn = replaceExtension fn xmlExt--> acyName :: FilePath -> FilePath-> acyName fn = replaceExtension fn acyExt--> uacyName :: FilePath -> FilePath-> uacyName fn = replaceExtension fn uacyExt--> sourceRepName :: FilePath -> FilePath-> sourceRepName fn = replaceExtension fn sourceRepExt--> objectName :: Bool -> FilePath -> FilePath-> objectName debug = name (if debug then debugExt else oExt)-> where name ext fn = replaceExtension fn ext--> curryExt, lcurryExt, icurryExt, oExt :: String-> curryExt = ".curry"-> lcurryExt = ".lcurry"-> icurryExt = ".icurry"-> flatExt = ".fcy"-> flatIntExt = ".fint"-> xmlExt = "_flat.xml"-> acyExt = ".acy"-> uacyExt = ".uacy"-> sourceRepExt = ".cy"-> oExt = ".o"-> debugExt = ".d.o"--> sourceExts, moduleExts, objectExts :: [String]-> sourceExts = [curryExt,lcurryExt]-> moduleExts = sourceExts ++ [icurryExt]-> objectExts = [oExt]--\end{verbatim}+> rest [m] = " and " ++ show m+> rest ms = rest' ms+> rest' [m] = ", and " ++ show m+> rest' (m:ms) = ", " ++ show m ++ rest' ms
src/CurryEnv.hs view
@@ -7,12 +7,16 @@ -- November 2005, -- Martin Engelke (men@informatik.uni-kiel.de) ---module CurryEnv (CurryEnv, - moduleId, exports, imports, interface, infixDecls,- typeSynonyms, curryEnv) where+module CurryEnv (CurryEnv(..), curryEnv) where import Data.Maybe +import Curry.Base.Position+import Curry.Base.Ident++import Curry.Syntax++import Types import Base @@ -91,14 +95,14 @@ -- Generate interface declarations for all type synonyms in the module. genTypeSyns :: TCEnv -> Module -> [IDecl] genTypeSyns tcEnv (Module mident _ decls)- = map (genTypeSynDecl mident tcEnv) (filter isTypeSyn decls)+ = concatMap (genTypeSynDecl mident tcEnv) decls ---genTypeSynDecl :: ModuleIdent -> TCEnv -> Decl -> IDecl+genTypeSynDecl :: ModuleIdent -> TCEnv -> Decl -> [IDecl] genTypeSynDecl mid tcEnv (TypeDecl pos ident params texpr)- = genTypeDecl pos mid ident params tcEnv texpr+ = [genTypeDecl pos mid ident params tcEnv texpr] genTypeSynDecl _ _ _ - = internalError "@CurryInfo.genTypeSynDecl: illegal declaration"+ = [] -- genTypeDecl :: Position -> ModuleIdent -> Ident -> [Ident] -> TCEnv@@ -166,17 +170,3 @@ [RenamingType qident' _ _] -> Just qident' [AliasType qident' _ _] -> Just qident' _ -> Nothing-----isTypeSyn :: Decl -> Bool-isTypeSyn (TypeDecl _ _ _ texpr)- = case texpr of- RecordType _ _ -> False- _ -> True-isTypeSyn _ = False--------------------------------------------------------------------------------------------------------------------------------------------------------------------
src/CurryHtml.hs view
@@ -1,11 +1,17 @@-module CurryHtml(program2html,source2html) where+module CurryHtml(source2html) where -import SyntaxColoring-import Ident import Data.Char hiding(Space)-import CurryDeps(getCurryPath)-import PathUtils (writeModule)- +import Control.Exception++import Curry.Base.Ident+import Curry.Base.MessageMonad++import SyntaxColoring+import PathUtils (readModule, writeModule, getCurryPath)+import Frontend+++ --- translate source file into HTML file with syntaxcoloring --- @param outputfilename --- @param sourcefilename@@ -21,8 +27,38 @@ (if null outputfilename then writeModule output else writeFile output) (program2html modulname program)- + +--- @param importpaths+--- @param filename +--- @return program+filename2program :: [String] -> String -> IO Program+filename2program paths filename+ = do cont <- readModule filename+ typingParseResult <- (catchError (typingParse paths filename cont))+ fullParseResult <- (catchError (fullParse paths filename cont))+ parseResult <- (catchError (return (parse filename cont)))+ lexResult <- (catchError (return (Frontend.lex filename cont)))+ return (genProgram cont (typingParseResult : fullParseResult : [parseResult]) lexResult)+++--- this function intercepts errors and converts it to Messages +--- @param a show-function for (Result a) +--- @param a function that generates a (Result a)+--- @return (Result a) without runtimeerrors ++-- FIXME This is ugly. Avoid exceptions and report failure via MsgMonad instead! (hsi)+catchError :: Show a =>IO (MsgMonad a) -> IO (MsgMonad a)+catchError toDo = Control.Exception.catch (toDo >>= returnNF) handler + where + -- This refers to base3+ handler (ErrorCall str) = return (failWith str)+ handler e = return (failWith (show e)) + + returnNF a = normalform a `seq` return a+ normalform = length . show . runMsg+ + --- generates htmlcode with syntax highlighting --- @param modulname --- @param a program@@ -66,15 +102,11 @@ code2class (TypeConstructor TypeDecla _) = "typeconstructor_typedecla" code2class (TypeConstructor TypeUse _) = "typeconstructor_typeuse" code2class (TypeConstructor TypeExport _) = "typeconstructor_typeexport"-code2class (CodeError _ _) = "codeerror" code2class (CodeWarning _ _) = "codewarning" code2class (NotParsed _) = "notparsed" code2html :: Bool -> Code -> String -code2html _ code@(CodeError _ c) =- (spanTag (code2class code) - (code2html False c)) code2html ownClass code@(CodeWarning _ c) = (if ownClass then spanTag (code2class code) else id) (code2html False c) @@ -89,9 +121,8 @@ (htmlQuote (code2string c)) spanTag :: String -> String -> String-spanTag cl str- |null cl = str- | otherwise = "<span class=\""++ cl ++ "\">" ++ str ++ "</span>"+spanTag [] str = str+spanTag cl str = "<span class=\""++ cl ++ "\">" ++ str ++ "</span>" replace :: Char -> String -> String -> String replace old new = foldr (\ x -> if x == old then (new ++) else ([x]++)) ""@@ -101,7 +132,7 @@ addHtmlLink :: String -> QualIdent -> String addHtmlLink html qualIdent =- let (maybeModuleIdent,ident) = splitQualIdent qualIdent in + let (maybeModuleIdent,ident) = (qualidMod qualIdent, qualidId qualIdent) in "<a href=\"" ++ (maybe "" (\x -> show x ++ "_curry.html") maybeModuleIdent) ++ "#"++
− src/CurryLexer.lhs
@@ -1,630 +0,0 @@--% $Id: CurryLexer.lhs,v 1.40 2004/03/04 22:39:12 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{CurryLexer.lhs}-\section{A Lexer for Curry}-In this section a lexer for Curry is implemented.-\begin{verbatim}- -> module CurryLexer (lexFile,lexer, Token (..), Category(..), Attributes(..)) where--> import Data.Char -> import Data.List-> import qualified Data.Map as Map--> import LexComb-> import Position----\end{verbatim}-\paragraph{Tokens} Note that the equality and ordering instances of-\texttt{Token} disregard the attributes.-\begin{verbatim}--> data Token = Token Category Attributes--> instance Eq Token where-> Token t1 _ == Token t2 _ = t1 == t2-> instance Ord Token where-> Token t1 _ `compare` Token t2 _ = t1 `compare` t2--> data Category =-> -- literals-> CharTok | IntTok | FloatTok | IntegerTok | StringTok-> -- identifiers-> | Id | QId | Sym | QSym-> -- punctuation symbols-> | LeftParen | RightParen | Semicolon | LeftBrace | RightBrace-> | LeftBracket | RightBracket | Comma | Underscore | Backquote-> -- turn off layout (inserted by bbr)-> | LeftBraceSemicolon-> -- virtual punctation (inserted by layout)-> | VSemicolon | VRightBrace-> -- reserved identifiers-> | KW_case | KW_choice | KW_data | KW_do | KW_else | KW_eval | KW_external-> | KW_free | KW_if | KW_import | KW_in | KW_infix | KW_infixl | KW_infixr-> | KW_let | KW_module | KW_newtype | KW_of | KW_rigid | KW_then | KW_type-> | KW_where-> -- reserved operators-> | At | Colon | DotDot | DoubleColon | Equals | Backslash | Bar-> | LeftArrow | RightArrow | Tilde | Binds-> -- special identifiers-> | Id_as | Id_ccall | Id_forall | Id_hiding | Id_interface | Id_primitive-> | Id_qualified-> -- special operators-> | Sym_Dot | Sym_Minus | Sym_MinusDot-> -- end-of-file token-> | EOF-> -- comments (only for full lexer) inserted by men & bbr-> | LineComment | NestedComment -> deriving (Eq,Ord)--\end{verbatim}-There are different kinds of attributes associated with the tokens.-Most attributes simply save the string corresponding to the token.-However, for qualified identifiers, we also record the list of module-qualifiers. The values corresponding to a literal token are properly-converted already. To simplify the creation and extraction of-attribute values we make use of records.-\begin{verbatim}--> data Attributes =-> NoAttributes-> | CharAttributes{ cval :: Char, original :: String}-> | IntAttributes{ ival :: Int , original :: String}-> | FloatAttributes{ fval :: Double, original :: String}-> | IntegerAttributes{ intval :: Integer, original :: String}-> | StringAttributes{ sval :: String, original :: String}-> | IdentAttributes{ modul :: [String], sval :: String}--> instance Show Attributes where-> showsPrec _ NoAttributes = showChar '_'-> showsPrec _ (CharAttributes cval _) = shows cval-> showsPrec _ (IntAttributes ival _) = shows ival-> showsPrec _ (FloatAttributes fval _) = shows fval-> showsPrec _ (IntegerAttributes intval _) = shows intval-> showsPrec _ (StringAttributes sval _) = shows sval-> showsPrec _ (IdentAttributes mIdent ident) =-> showString ("`" ++ concat (intersperse "." (mIdent ++ [ident])) ++ "'")--\end{verbatim}-The following functions can be used to construct tokens with-specific attributes.-\begin{verbatim}--> tok :: Category -> Token-> tok t = Token t NoAttributes--> idTok :: Category -> [String] -> String -> Token-> idTok t mIdent ident = Token t IdentAttributes{ modul = mIdent, sval = ident }--> charTok :: Char -> String -> Token-> charTok c o = Token CharTok CharAttributes{ cval = c, original = o }--> intTok :: Int -> String -> Token-> intTok base digits =-> Token IntTok IntAttributes{ ival = convertIntegral base digits,-> original = digits}--> floatTok :: String -> String -> Int -> String -> Token-> floatTok mant frac exp rest =-> Token FloatTok FloatAttributes{ fval = convertFloating mant frac exp, -> original = mant++"."++frac++rest}- -> integerTok :: Integer -> String -> Token-> integerTok base digits =-> Token IntegerTok-> IntegerAttributes{intval = (convertIntegral base digits) :: Integer,-> original = digits}--> stringTok :: String -> String -> Token-> stringTok cs o = Token StringTok StringAttributes{ sval = cs, original = o }--> lineCommentTok :: String -> Token-> lineCommentTok s = Token LineComment StringAttributes{ sval = s, original = s}--> nestedCommentTok :: String -> Token-> nestedCommentTok s = Token NestedComment StringAttributes{ sval = s, original = s }--\end{verbatim}-The \texttt{Show} instance of \texttt{Token} is designed to display-all tokens in their source representation.-\begin{verbatim}--> instance Show Token where-> showsPrec _ (Token Id a) = showString "identifier " . shows a-> showsPrec _ (Token QId a) = showString "qualified identifier " . shows a-> showsPrec _ (Token Sym a) = showString "operator " . shows a-> showsPrec _ (Token QSym a) = showString "qualified operator " . shows a-> showsPrec _ (Token IntTok a) = showString "integer " . shows a-> showsPrec _ (Token FloatTok a) = showString "float " . shows a-> showsPrec _ (Token CharTok a) = showString "character " . shows a-> showsPrec _ (Token IntegerTok a) = showString "integer " . shows a-> showsPrec _ (Token StringTok a) = showString "string " . shows a-> showsPrec _ (Token LeftParen _) = showString "`('"-> showsPrec _ (Token RightParen _) = showString "`)'"-> showsPrec _ (Token Semicolon _) = showString "`;'"-> showsPrec _ (Token LeftBrace _) = showString "`{'"-> showsPrec _ (Token RightBrace _) = showString "`}'"-> showsPrec _ (Token LeftBracket _) = showString "`['"-> showsPrec _ (Token RightBracket _) = showString "`]'"-> showsPrec _ (Token Comma _) = showString "`,'"-> showsPrec _ (Token Underscore _) = showString "`_'"-> showsPrec _ (Token Backquote _) = showString "``'"-> showsPrec _ (Token VSemicolon _) =-> showString "`;' (inserted due to layout)"-> showsPrec _ (Token VRightBrace _) =-> showString "`}' (inserted due to layout)"-> showsPrec _ (Token At _) = showString "`@'"-> showsPrec _ (Token Colon _) = showString "`:'"-> showsPrec _ (Token DotDot _) = showString "`..'"-> showsPrec _ (Token DoubleColon _) = showString "`::'"-> showsPrec _ (Token Equals _) = showString "`='"-> showsPrec _ (Token Backslash _) = showString "`\\'"-> showsPrec _ (Token Bar _) = showString "`|'"-> showsPrec _ (Token LeftArrow _) = showString "`<-'"-> showsPrec _ (Token RightArrow _) = showString "`->'"-> showsPrec _ (Token Tilde _) = showString "`~'"-> showsPrec _ (Token Binds _) = showString "`:='"-> showsPrec _ (Token Sym_Dot _) = showString "operator `.'"-> showsPrec _ (Token Sym_Minus _) = showString "operator `-'"-> showsPrec _ (Token Sym_MinusDot _) = showString "operator `-.'"-> showsPrec _ (Token KW_case _) = showString "`case'"-> showsPrec _ (Token KW_choice _) = showString "`choice'"-> showsPrec _ (Token KW_data _) = showString "`data'"-> showsPrec _ (Token KW_do _) = showString "`do'"-> showsPrec _ (Token KW_else _) = showString "`else'"-> showsPrec _ (Token KW_eval _) = showString "`eval'"-> showsPrec _ (Token KW_external _) = showString "`external'"-> showsPrec _ (Token KW_free _) = showString "`free'"-> showsPrec _ (Token KW_if _) = showString "`if'"-> showsPrec _ (Token KW_import _) = showString "`import'"-> showsPrec _ (Token KW_in _) = showString "`in'"-> showsPrec _ (Token KW_infix _) = showString "`infix'"-> showsPrec _ (Token KW_infixl _) = showString "`infixl'"-> showsPrec _ (Token KW_infixr _) = showString "`infixr'"-> showsPrec _ (Token KW_let _) = showString "`let'"-> showsPrec _ (Token KW_module _) = showString "`module'"-> showsPrec _ (Token KW_newtype _) = showString "`newtype'"-> showsPrec _ (Token KW_of _) = showString "`of'"-> showsPrec _ (Token KW_rigid _) = showString "`rigid'"-> showsPrec _ (Token KW_then _) = showString "`then'"-> showsPrec _ (Token KW_type _) = showString "`type'"-> showsPrec _ (Token KW_where _) = showString "`where'"-> showsPrec _ (Token Id_as _) = showString "identifier `as'"-> showsPrec _ (Token Id_ccall _) = showString "identifier `ccall'"-> showsPrec _ (Token Id_forall _) = showString "identifier `forall'"-> showsPrec _ (Token Id_hiding _) = showString "identifier `hiding'"-> showsPrec _ (Token Id_interface _) = showString "identifier `interface'"-> showsPrec _ (Token Id_primitive _) = showString "identifier `primitive'"-> showsPrec _ (Token Id_qualified _) = showString "identifier `qualified'"-> showsPrec _ (Token EOF _) = showString "<end-of-file>"-> showsPrec _ (Token LineComment a) = shows a-> showsPrec _ (Token NestedComment a) = shows a--\end{verbatim}-Tables for reserved operators and identifiers-\begin{verbatim}--> reserved_ops, reserved_and_special_ops :: Map.Map String Category-> reserved_ops = Map.fromList [-> ("@", At),-> ("::", DoubleColon),-> ("..", DotDot),-> ("=", Equals),-> ("\\", Backslash),-> ("|", Bar),-> ("<-", LeftArrow),-> ("->", RightArrow),-> ("~", Tilde),-> (":=", Binds)-> ]-> reserved_and_special_ops = foldr (uncurry Map.insert) reserved_ops [-> (":", Colon),-> (".", Sym_Dot),-> ("-", Sym_Minus),-> ("-.", Sym_MinusDot)-> ]--> reserved_ids, reserved_and_special_ids :: Map.Map String Category-> reserved_ids = Map.fromList [-> ("case", KW_case),-> ("choice", KW_choice),-> ("data", KW_data),-> ("do", KW_do),-> ("else", KW_else),-> ("eval", KW_eval),-> ("external", KW_external),-> ("free", KW_free),-> ("if", KW_if),-> ("import", KW_import),-> ("in", KW_in),-> ("infix", KW_infix),-> ("infixl", KW_infixl),-> ("infixr", KW_infixr),-> ("let", KW_let),-> ("module", KW_module),-> ("newtype", KW_newtype),-> ("of", KW_of),-> ("rigid", KW_rigid),-> ("then", KW_then),-> ("type", KW_type),-> ("where", KW_where)-> ]-> reserved_and_special_ids = foldr (uncurry Map.insert) reserved_ids [-> ("as", Id_as),-> ("ccall", Id_ccall),-> ("forall", Id_forall),-> ("hiding", Id_hiding),-> ("interface", Id_interface),-> ("primitive", Id_primitive),-> ("qualified", Id_qualified)-> ]--\end{verbatim}-Character classes-\begin{verbatim}--> isIdent, isSym, isOctit, isHexit :: Char -> Bool-> isIdent c = isAlphaNum c || c `elem` "'_"-> isSym c = c `elem` "~!@#$%^&*+-=<>:?./|\\" {-$-}-> isOctit c = c >= '0' && c <= '7'-> isHexit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'--inserted for full lexing (men&bbr)--> isLineComment, isNestedComment :: String -> Bool-> isLineComment ('-':'-':_) = True-> isLineComment _ = False-> isNestedComment ('{':'-':s) = True-> isNestedComment _ = False---\end{verbatim}-Lexing functions-\begin{verbatim}--> type SuccessP a = Position -> Token -> P a-> type FailP a = Position -> String -> P a--> lexFile :: P [(Position,Token)]-> lexFile = fullLexer tokens failP-> where tokens p t@(Token c _)-> | c == EOF = returnP [(p,t)]-> | otherwise = lexFile `thenP` returnP . ((p,t):)--> lexer :: SuccessP a -> FailP a -> P a-> lexer success fail = skipBlanks-> where -- skipBlanks moves past whitespace and comments-> skipBlanks p [] bol = success p (tok EOF) p [] bol-> skipBlanks p ('\t':s) bol = skipBlanks (tab p) s bol-> skipBlanks p ('\n':s) bol = skipBlanks (nl p) s True-> skipBlanks p ('-':'-':s) bol =-> skipBlanks (nl p) (tail' (dropWhile (/= '\n') s)) True-> skipBlanks p ('{':'-':s) bol =-> nestedComment p skipBlanks fail (incr p 2) s bol-> skipBlanks p (c:s) bol-> | isSpace c = skipBlanks (next p) s bol-> | otherwise =-> (if bol then lexBOL else lexToken) success fail p (c:s) bol-> tail' [] = []-> tail' (_:tl) = tl--> fullLexer :: SuccessP a -> FailP a -> P a-> fullLexer success fail = skipBlanks-> where -- skipBlanks moves past whitespace -> skipBlanks p [] bol = success p (tok EOF) p [] bol-> skipBlanks p ('\t':s) bol = skipBlanks (tab p) s bol-> skipBlanks p ('\n':s) bol = skipBlanks (nl p) s True-> skipBlanks p s@('-':'-':_) bol = lexLineComment success p s bol-> skipBlanks p s@('{':'-':_) bol =-> lexNestedComment 0 id p success fail p s bol-> skipBlanks p (c:s) bol-> | isSpace c = skipBlanks (next p) s bol-> | otherwise =-> (if bol then lexBOL else lexToken) success fail p (c:s) bol-> tail' [] = []-> tail' (_:tl) = tl--> lexLineComment :: SuccessP a -> P a-> lexLineComment success p s = case break (=='\n') s of-> (comment,rest) -> success p (lineCommentTok comment) (incr p (length comment)) rest- -> lexNestedComment :: Int -> (String -> String) -> -> Position -> SuccessP a -> FailP a -> P a-> lexNestedComment 1 comment p0 success fail p ('-':'}':s) = -> success p0 (nestedCommentTok (comment "-}") ) (incr p 2) s -> lexNestedComment n comment p0 success fail p ('{':'-':s) = -> lexNestedComment (n+1) (comment . ("{-"++)) p0 success fail (incr p 2) s-> lexNestedComment n comment p0 success fail p ('-':'}':s) = -> lexNestedComment (n-1) (comment . ("-}"++)) p0 success fail (incr p 2) s-> lexNestedComment n comment p0 success fail p (c@'\t':s) = -> lexNestedComment n (comment . (c:)) p0 success fail (tab p) s-> lexNestedComment n comment p0 success fail p (c@'\n':s) = -> lexNestedComment n (comment . (c:)) p0 success fail (nl p) s-> lexNestedComment n comment p0 success fail p (c:s) = -> lexNestedComment n (comment . (c:)) p0 success fail (next p) s-> lexNestedComment n comment p0 success fail p "" = -> fail p0 "Unterminated nested comment" p []--> nestedComment :: Position -> P a -> FailP a -> P a-> nestedComment p0 success fail p ('-':'}':s) = success (incr p 2) s-> nestedComment p0 success fail p ('{':'-':s) =-> nestedComment p (nestedComment p0 success fail) fail (incr p 2) s-> nestedComment p0 success fail p ('\t':s) =-> nestedComment p0 success fail (tab p) s-> nestedComment p0 success fail p ('\n':s) =-> nestedComment p0 success fail (nl p) s-> nestedComment p0 success fail p (_:s) =-> nestedComment p0 success fail (next p) s-> nestedComment p0 success fail p [] =-> fail p0 "Unterminated nested comment at end-of-file" p []---> lexBOL :: SuccessP a -> FailP a -> P a-> lexBOL success fail p s _ [] = lexToken success fail p s False []-> lexBOL success fail p s _ ctxt@(n:rest)-> | col < n = success p (tok VRightBrace) p s True rest-> | col == n = success p (tok VSemicolon) p s False ctxt-> | otherwise = lexToken success fail p s False ctxt-> where col = column p--> lexToken :: SuccessP a -> FailP a -> P a-> lexToken success fail p [] = success p (tok EOF) p []-> lexToken success fail p (c:s)-> | c == '(' = token LeftParen-> | c == ')' = token RightParen-> | c == ',' = token Comma-> | c == ';' = token Semicolon-> | c == '[' = token LeftBracket-> | c == ']' = token RightBracket-> | c == '_' = token Underscore-> | c == '`' = token Backquote-> | c == '{' = lexLeftBrace (token LeftBrace) (next p) (success p) s -> | c == '}' = \bol -> token RightBrace bol . drop 1-> | c == '\'' = lexChar p success fail (next p) s-> | c == '\"' = lexString p success fail (next p) s-> | isAlpha c = lexIdent (success p) p (c:s)-> | isSym c = lexSym (success p) p (c:s)-> | isDigit c = lexNumber (success p) p (c:s)-> | otherwise = fail p ("Illegal character " ++ show c) p s-> where token t = success p (tok t) (next p) s--> lexIdent :: (Token -> P a) -> P a-> lexIdent cont p s =-> maybe (lexOptQual cont (token Id) [ident]) (cont . token)-> (Map.lookup ident reserved_and_special_ids)-> (incr p (length ident)) rest-> where (ident,rest) = span isIdent s-> token t = idTok t [] ident--> lexSym :: (Token -> P a) -> P a-> lexSym cont p s =-> cont (idTok (maybe Sym id (Map.lookup sym reserved_and_special_ops)) [] sym)-> (incr p (length sym)) rest-> where (sym,rest) = span isSym s--> lexLeftBrace leftBrace _ _ [] = leftBrace-> lexLeftBrace leftBrace p cont (c:s) -> | c==';' = cont (tok LeftBraceSemicolon) (next p) s-> | otherwise = leftBrace--\end{verbatim}-{\em Note:} the function \texttt{lexOptQual} has been extended to provide-the qualified use of the Prelude list operators and tuples.-\begin{verbatim}--> lexOptQual :: (Token -> P a) -> Token -> [String] -> P a-> lexOptQual cont token mIdent p ('.':c:s)-> | isAlpha c = lexQualIdent cont identCont mIdent (next p) (c:s)-> | isSym c = lexQualSym cont identCont mIdent (next p) (c:s)-> | c=='(' || c=='[' -> = lexQualPreludeSym cont token identCont mIdent (next p) (c:s)-> where identCont _ _ = cont token p ('.':c:s)-> lexOptQual cont token mIdent p s = cont token p s--> lexQualIdent :: (Token -> P a) -> P a -> [String] -> P a-> lexQualIdent cont identCont mIdent p s =-> maybe (lexOptQual cont (idTok QId mIdent ident) (mIdent ++ [ident]))-> (const identCont)-> (Map.lookup ident reserved_ids)-> (incr p (length ident)) rest-> where (ident,rest) = span isIdent s--> lexQualSym :: (Token -> P a) -> P a -> [String] -> P a-> lexQualSym cont identCont mIdent p s =-> maybe (cont (idTok QSym mIdent sym)) (const identCont)-> (Map.lookup sym reserved_ops)-> (incr p (length sym)) rest-> where (sym,rest) = span isSym s---> lexQualPreludeSym :: (Token -> P a) -> Token -> P a -> [String] -> P a-> lexQualPreludeSym cont _ identCont mIdent p ('[':']':rest) =-> cont (idTok QId mIdent "[]") (incr p 2) rest-> lexQualPreludeSym cont _ identCont mIdent p ('(':rest)-> | not (null rest') && head rest'==')' -> = cont (idTok QId mIdent ('(':tup++")")) (incr p (length tup+2)) (tail rest')-> where (tup,rest') = span (==',') rest-> lexQualPreludeSym cont token _ _ p s = cont token p s---\end{verbatim}-{\em Note:} since Curry allows an unlimited range of integer numbers,-read numbers must be converted to Haskell type \texttt{Integer}.-\begin{verbatim}--> lexNumber :: (Token -> P a) -> P a-> lexNumber cont p ('0':c:s)-> | c `elem` "oO" = lexOctal cont nullCont (incr p 2) s-> | c `elem` "xX" = lexHexadecimal cont nullCont (incr p 2) s-> where nullCont _ _ = cont (intTok 10 "0") (next p) (c:s)-> lexNumber cont p s-> = lexOptFraction cont (integerTok 10 digits) digits-> (incr p (length digits)) rest-> where (digits,rest) = span isDigit s-> num = (read digits) :: Integer--> lexOctal :: (Token -> P a) -> P a -> P a-> lexOctal cont nullCont p s-> | null digits = nullCont undefined undefined-> | otherwise = cont (integerTok 8 digits) (incr p (length digits)) rest-> where (digits,rest) = span isOctit s--> lexHexadecimal :: (Token -> P a) -> P a -> P a-> lexHexadecimal cont nullCont p s-> | null digits = nullCont undefined undefined-> | otherwise = cont (integerTok 16 digits) (incr p (length digits)) rest-> where (digits,rest) = span isHexit s--> lexOptFraction :: (Token -> P a) -> Token -> String -> P a-> lexOptFraction cont _ mant p ('.':c:s)-> | isDigit c = lexOptExponent cont (floatTok mant frac 0 "") mant frac-> (incr p (length frac+1)) rest-> where (frac,rest) = span isDigit (c:s)-> lexOptFraction cont token mant p (c:s)-> | c `elem` "eE" = lexSignedExponent cont intCont mant "" [c] (next p) s-> where intCont _ _ = cont token p (c:s)-> lexOptFraction cont token _ p s = cont token p s--> lexOptExponent :: (Token -> P a) -> Token -> String -> String -> P a-> lexOptExponent cont token mant frac p (c:s)-> | c `elem` "eE" = lexSignedExponent cont floatCont mant frac [c] (next p) s-> where floatCont _ _ = cont token p (c:s)-> lexOptExponent cont token mant frac p s = cont token p s--> lexSignedExponent :: (Token -> P a) -> P a -> String -> String -> String -> P a-> lexSignedExponent cont floatCont mant frac e p ('+':c:s)-> | isDigit c = lexExponent cont mant frac (e++"+") id (next p) (c:s)-> lexSignedExponent cont floatCont mant frac e p ('-':c:s)-> | isDigit c = lexExponent cont mant frac (e++"-") negate (next p) (c:s)-> lexSignedExponent cont floatCont mant frac e p (c:s)-> | isDigit c = lexExponent cont mant frac e id p (c:s)-> lexSignedExponent cont floatCont mant frac e p s = floatCont p s--> lexExponent :: (Token -> P a) -> String -> String -> String -> (Int -> Int) -> P a-> lexExponent cont mant frac e expSign p s =-> cont (floatTok mant frac exp (e++digits)) (incr p (length digits)) rest-> where (digits,rest) = span isDigit s-> exp = expSign (convertIntegral 10 digits)--> lexChar :: Position -> SuccessP a -> FailP a -> P a-> lexChar p0 success fail p [] = fail p0 "Illegal character constant" p []-> lexChar p0 success fail p (c:s)-> | c == '\\' = lexEscape p (lexCharEnd p0 success fail) fail (next p) s-> | c == '\n' = fail p0 "Illegal character constant" p (c:s)-> | c == '\t' = lexCharEnd p0 success fail c "\t" (tab p) s-> | otherwise = lexCharEnd p0 success fail c [c] (next p) s--> lexCharEnd :: Position -> SuccessP a -> FailP a -> Char -> String -> P a-> lexCharEnd p0 success fail c o p ('\'':s) = success p0 (charTok c o) (next p) s-> lexCharEnd p0 success fail c o p s =-> fail p0 "Improperly terminated character constant" p s--> lexString :: Position -> SuccessP a -> FailP a -> P a-> lexString p0 success fail = lexStringRest p0 success fail "" id--> lexStringRest :: Position -> SuccessP a -> FailP a -> String -> (String -> String) -> P a-> lexStringRest p0 success fail s0 so p [] = -> fail p0 "Improperly terminated string constant" p []-> lexStringRest p0 success fail s0 so p (c:s)-> | c == '\\' =-> lexStringEscape p (lexStringRest p0 success fail) fail s0 so (next p) s-> | c == '\"' = success p0 (stringTok (reverse s0) (so "")) (next p) s-> | c == '\n' = fail p0 "Improperly terminated string constant" p []-> | c == '\t' = lexStringRest p0 success fail (c:s0) (so . (c:)) (tab p) s-> | otherwise = lexStringRest p0 success fail (c:s0) (so . (c:)) (next p) s--> lexStringEscape :: Position -> (String -> (String -> String) -> P a) -> FailP a -> -> String -> (String -> String) -> P a-> lexStringEscape p0 success fail s0 so p [] = lexEscape p0 undefined fail p []-> lexStringEscape p0 success fail s0 so p (c:s)-> | c == '&' = success s0 (so . ("\\&"++)) (next p) s-> | isSpace c = lexStringGap (success s0) fail so p (c:s)-> | otherwise = lexEscape p0 (\ c' s' -> success (c':s0) (so . (s'++))) fail p (c:s)--> lexStringGap :: ((String -> String) -> P a) -> FailP a -> (String -> String) -> P a-> lexStringGap success fail so p [] = fail p "End of file in string gap" p []-> lexStringGap success fail so p (c:s)-> | c == '\\' = success (so . (c:)) (next p) s-> | c == '\t' = lexStringGap success fail (so . (c:)) (tab p) s-> | c == '\n' = lexStringGap success fail (so . (c:)) (nl p) s-> | isSpace c = lexStringGap success fail (so . (c:)) (next p) s-> | otherwise = fail p ("Illegal character in string gap " ++ show c) p s--> lexEscape :: Position -> (Char -> String -> P a) -> FailP a -> P a-> lexEscape p0 success fail p ('a':s) = success '\a' "\\a" (next p) s-> lexEscape p0 success fail p ('b':s) = success '\b' "\\b" (next p) s-> lexEscape p0 success fail p ('f':s) = success '\f' "\\f" (next p) s-> lexEscape p0 success fail p ('n':s) = success '\n' "\\n" (next p) s-> lexEscape p0 success fail p ('r':s) = success '\r' "\\r" (next p) s-> lexEscape p0 success fail p ('t':s) = success '\t' "\\t" (next p) s-> lexEscape p0 success fail p ('v':s) = success '\v' "\\v" (next p) s-> lexEscape p0 success fail p ('\\':s) = success '\\' "\\\\" (next p) s-> lexEscape p0 success fail p ('"':s) = success '\"' "\\\"" (next p) s-> lexEscape p0 success fail p ('\'':s) = success '\'' "\\\'" (next p) s-> lexEscape p0 success fail p ('^':c:s)-> | isUpper c || c `elem` "@[\\]^_" =-> success (chr (ord c `mod` 32)) ("\\^"++[c]) (incr p 2) s-> lexEscape p0 success fail p ('o':c:s)-> | isOctit c = numEscape p0 success fail 8 isOctit ("\\o"++) (next p) (c:s)-> lexEscape p0 success fail p ('x':c:s)-> | isHexit c = numEscape p0 success fail 16 isHexit ("\\x"++) (next p) (c:s)-> lexEscape p0 success fail p (c:s)-> | isDigit c = numEscape p0 success fail 10 isDigit ("\\"++) p (c:s)-> lexEscape p0 success fail p s = asciiEscape p0 success fail p s--> asciiEscape :: Position -> (Char -> String -> P a) -> FailP a -> P a-> asciiEscape p0 success fail p ('N':'U':'L':s) = success '\NUL' "\\NUL" (incr p 3) s-> asciiEscape p0 success fail p ('S':'O':'H':s) = success '\SOH' "\\SOH" (incr p 3) s-> asciiEscape p0 success fail p ('S':'T':'X':s) = success '\STX' "\\STX" (incr p 3) s-> asciiEscape p0 success fail p ('E':'T':'X':s) = success '\ETX' "\\ETX" (incr p 3) s-> asciiEscape p0 success fail p ('E':'O':'T':s) = success '\EOT' "\\EOT" (incr p 3) s-> asciiEscape p0 success fail p ('E':'N':'Q':s) = success '\ENQ' "\\ENQ" (incr p 3) s-> asciiEscape p0 success fail p ('A':'C':'K':s) = success '\ACK' "\\ACK" (incr p 3) s -> asciiEscape p0 success fail p ('B':'E':'L':s) = success '\BEL' "\\BEL" (incr p 3) s-> asciiEscape p0 success fail p ('B':'S':s) = success '\BS' "\\BS" (incr p 2) s-> asciiEscape p0 success fail p ('H':'T':s) = success '\HT' "\\HT" (incr p 2) s-> asciiEscape p0 success fail p ('L':'F':s) = success '\LF' "\\LF" (incr p 2) s-> asciiEscape p0 success fail p ('V':'T':s) = success '\VT' "\\VT" (incr p 2) s-> asciiEscape p0 success fail p ('F':'F':s) = success '\FF' "\\FF" (incr p 2) s-> asciiEscape p0 success fail p ('C':'R':s) = success '\CR' "\\CR" (incr p 2) s-> asciiEscape p0 success fail p ('S':'O':s) = success '\SO' "\\SO" (incr p 2) s-> asciiEscape p0 success fail p ('S':'I':s) = success '\SI' "\\SI" (incr p 2) s-> asciiEscape p0 success fail p ('D':'L':'E':s) = success '\DLE' "\\DLE" (incr p 3) s -> asciiEscape p0 success fail p ('D':'C':'1':s) = success '\DC1' "\\DC1" (incr p 3) s-> asciiEscape p0 success fail p ('D':'C':'2':s) = success '\DC2' "\\DC2" (incr p 3) s-> asciiEscape p0 success fail p ('D':'C':'3':s) = success '\DC3' "\\DC3" (incr p 3) s-> asciiEscape p0 success fail p ('D':'C':'4':s) = success '\DC4' "\\DC4" (incr p 3) s-> asciiEscape p0 success fail p ('N':'A':'K':s) = success '\NAK' "\\NAK" (incr p 3) s-> asciiEscape p0 success fail p ('S':'Y':'N':s) = success '\SYN' "\\SYN" (incr p 3) s-> asciiEscape p0 success fail p ('E':'T':'B':s) = success '\ETB' "\\ETB" (incr p 3) s-> asciiEscape p0 success fail p ('C':'A':'N':s) = success '\CAN' "\\CAN" (incr p 3) s -> asciiEscape p0 success fail p ('E':'M':s) = success '\EM' "\\EM" (incr p 2) s-> asciiEscape p0 success fail p ('S':'U':'B':s) = success '\SUB' "\\SUB" (incr p 3) s-> asciiEscape p0 success fail p ('E':'S':'C':s) = success '\ESC' "\\ESC" (incr p 3) s-> asciiEscape p0 success fail p ('F':'S':s) = success '\FS' "\\FS" (incr p 2) s-> asciiEscape p0 success fail p ('G':'S':s) = success '\GS' "\\GS" (incr p 2) s-> asciiEscape p0 success fail p ('R':'S':s) = success '\RS' "\\RS" (incr p 2) s-> asciiEscape p0 success fail p ('U':'S':s) = success '\US' "\\US" (incr p 2) s-> asciiEscape p0 success fail p ('S':'P':s) = success '\SP' "\\SP" (incr p 2) s-> asciiEscape p0 success fail p ('D':'E':'L':s) = success '\DEL' "\\DEL" (incr p 3) s-> asciiEscape p0 success fail p s = fail p0 "Illegal escape sequence" p s--> numEscape :: Position -> (Char -> String -> P a) -> FailP a -> Int-> -> (Char -> Bool) -> (String -> String) -> P a-> numEscape p0 success fail b isDigit so p s-> | n >= min && n <= max = success (chr n) (so digits) (incr p (length digits)) rest-> | otherwise = fail p0 "Numeric escape out-of-range" p s-> where (digits,rest) = span isDigit s-> n = convertIntegral b digits-> min = ord minBound-> max = ord maxBound--\end{verbatim}
− src/CurryPP.lhs
@@ -1,369 +0,0 @@--% $Id: CurryPP.lhs,v 1.50 2004/02/15 22:10:27 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{CurryPP.lhs}-\section{A Pretty Printer for Curry}\label{sec:CurryPP}-This module implements a pretty printer for Curry expressions. It was-derived from the Haskell pretty printer provided in Simon Marlow's-Haskell parser.-\begin{verbatim}--> module CurryPP(module CurryPP, Doc) where-> import Ident-> import CurrySyntax-> import Pretty--\end{verbatim}-Pretty print a module-\begin{verbatim}--> ppModule :: Module -> Doc-> ppModule (Module m es ds) = ppModuleHeader m es $$ ppBlock ds--\end{verbatim}-Module header-\begin{verbatim}--> ppModuleHeader :: ModuleIdent -> Maybe ExportSpec -> Doc-> ppModuleHeader m es =-> text "module" <+> ppMIdent m <+> maybePP ppExportSpec es <+> text "where"--> ppExportSpec :: ExportSpec -> Doc-> ppExportSpec (Exporting _ es) = parenList (map ppExport es)--> ppExport :: Export -> Doc-> ppExport (Export x) = ppQIdent x-> ppExport (ExportTypeWith tc cs) = ppQIdent tc <> parenList (map ppIdent cs)-> ppExport (ExportTypeAll tc) = ppQIdent tc <> text "(..)"-> ppExport (ExportModule m) = text "module" <+> ppMIdent m--\end{verbatim}-Declarations-\begin{verbatim}--> ppBlock :: [Decl] -> Doc-> ppBlock = vcat . map ppDecl--> ppDecl :: Decl -> Doc-> ppDecl (ImportDecl _ m q asM is) =-> text "import" <+> ppQualified q <+> ppMIdent m <+> maybePP ppAs asM-> <+> maybePP ppImportSpec is-> where ppQualified q = if q then text "qualified" else empty-> ppAs m = text "as" <+> ppMIdent m-> ppDecl (InfixDecl _ fix p ops) = ppPrec fix p <+> list (map ppInfixOp ops)-> ppDecl (DataDecl _ tc tvs cs) =-> sep (ppTypeDeclLhs "data" tc tvs :-> map indent (zipWith (<+>) (equals : repeat vbar) (map ppConstr cs)))-> ppDecl (NewtypeDecl _ tc tvs nc) =-> sep [ppTypeDeclLhs "newtype" tc tvs <+> equals,indent (ppNewConstr nc)]-> ppDecl (TypeDecl _ tc tvs ty) =-> sep [ppTypeDeclLhs "type" tc tvs <+> equals,indent (ppTypeExpr 0 ty)]-> ppDecl (TypeSig _ fs ty) =-> list (map ppIdent fs) <+> text "::" <+> ppTypeExpr 0 ty-> ppDecl (EvalAnnot _ fs ev) =-> list (map ppIdent fs) <+> text "eval" <+> ppEval ev-> where ppEval EvalRigid = text "rigid"-> ppEval EvalChoice = text "choice"-> ppDecl (FunctionDecl _ _ eqs) = vcat (map ppEquation eqs)-> ppDecl (ExternalDecl p cc impent f ty) =-> sep [text "external" <+> ppCallConv cc <+> maybePP (text . show) impent,-> indent (ppDecl (TypeSig p [f] ty))]-> where ppCallConv CallConvPrimitive = text "primitive"-> ppCallConv CallConvCCall = text "ccall"-> ppDecl (FlatExternalDecl _ fs) = list (map ppIdent fs) <+> text "external"-> ppDecl (PatternDecl _ t rhs) = ppRule (ppConstrTerm 0 t) equals rhs-> ppDecl (ExtraVariables _ vs) = list (map ppIdent vs) <+> text "free"--> ppImportSpec :: ImportSpec -> Doc-> ppImportSpec (Importing _ is) = parenList (map ppImport is)-> ppImportSpec (Hiding _ is) = text "hiding" <+> parenList (map ppImport is)--> ppImport :: Import -> Doc-> ppImport (Import x) = ppIdent x-> ppImport (ImportTypeWith tc cs) = ppIdent tc <> parenList (map ppIdent cs)-> ppImport (ImportTypeAll tc) = ppIdent tc <> text "(..)"--> ppPrec :: Infix -> Integer -> Doc-> ppPrec fix p = ppAssoc fix <+> ppPrio p-> where ppAssoc InfixL = text "infixl"-> ppAssoc InfixR = text "infixr"-> ppAssoc Infix = text "infix"-> ppPrio p = if p < 0 then empty else integer p--> ppTypeDeclLhs :: String -> Ident -> [Ident] -> Doc-> ppTypeDeclLhs kw tc tvs = text kw <+> ppIdent tc <+> hsep (map ppIdent tvs)--> ppConstr :: ConstrDecl -> Doc-> ppConstr (ConstrDecl _ tvs c tys) =-> sep [ppExistVars tvs,ppIdent c <+> fsep (map (ppTypeExpr 2) tys)]-> ppConstr (ConOpDecl _ tvs ty1 op ty2) =-> sep [ppExistVars tvs,ppTypeExpr 1 ty1,ppInfixOp op <+> ppTypeExpr 1 ty2]--> ppNewConstr :: NewConstrDecl -> Doc-> ppNewConstr (NewConstrDecl _ tvs c ty) =-> sep [ppExistVars tvs,ppIdent c <+> ppTypeExpr 2 ty]--> ppExistVars :: [Ident] -> Doc-> ppExistVars tvs-> | null tvs = empty-> | otherwise = text "forall" <+> hsep (map ppIdent tvs) <+> char '.'--> ppEquation :: Equation -> Doc-> ppEquation (Equation _ lhs rhs) = ppRule (ppLhs lhs) equals rhs--> ppLhs :: Lhs -> Doc-> ppLhs (FunLhs f ts) = ppIdent f <+> fsep (map (ppConstrTerm 2) ts)-> ppLhs (OpLhs t1 f t2) =-> ppConstrTerm 1 t1 <+> ppInfixOp f <+> ppConstrTerm 1 t2-> ppLhs (ApLhs lhs ts) = parens (ppLhs lhs) <+> fsep (map (ppConstrTerm 2) ts)--> ppRule :: Doc -> Doc -> Rhs -> Doc-> ppRule lhs eq (SimpleRhs _ e ds) =-> sep [lhs <+> eq,indent (ppExpr 0 e)] $$ ppLocalDefs ds-> ppRule lhs eq (GuardedRhs es ds) =-> sep [lhs,indent (vcat (map (ppCondExpr eq) es))] $$ ppLocalDefs ds--> ppLocalDefs :: [Decl] -> Doc-> ppLocalDefs ds-> | null ds = empty-> | otherwise = indent (text "where" <+> ppBlock ds)--\end{verbatim}-Interfaces-\begin{verbatim}--> ppInterface :: Interface -> Doc-> ppInterface (Interface m ds) =-> text "interface" <+> ppMIdent m <+> text "where" <+> lbrace-> $$ vcat (punctuate semi (map ppIDecl ds)) $$ rbrace--> ppIDecl :: IDecl -> Doc-> ppIDecl (IImportDecl _ m) = text "import" <+> ppMIdent m-> ppIDecl (IInfixDecl _ fix p op) = ppPrec fix p <+> ppQInfixOp op-> ppIDecl (HidingDataDecl _ tc tvs) =-> text "hiding" <+> ppITypeDeclLhs "data" (qualify tc) tvs-> ppIDecl (IDataDecl _ tc tvs cs) =-> sep (ppITypeDeclLhs "data" tc tvs :-> map indent (zipWith (<+>) (equals : repeat vbar) (map ppIConstr cs)))-> where ppIConstr = maybe (char '_') ppConstr-> ppIDecl (INewtypeDecl _ tc tvs nc) =-> sep [ppITypeDeclLhs "newtype" tc tvs <+> equals,indent (ppNewConstr nc)]-> ppIDecl (ITypeDecl _ tc tvs ty) =-> sep [ppITypeDeclLhs "type" tc tvs <+> equals,indent (ppTypeExpr 0 ty)]-> ppIDecl (IFunctionDecl _ f _ ty) = ppQIdent f <+> text "::" <+> ppTypeExpr 0 ty--> ppITypeDeclLhs :: String -> QualIdent -> [Ident] -> Doc-> ppITypeDeclLhs kw tc tvs = text kw <+> ppQIdent tc <+> hsep (map ppIdent tvs)--\end{verbatim}-Types-\begin{verbatim}--> ppTypeExpr :: Int -> TypeExpr -> Doc-> ppTypeExpr p (ConstructorType tc tys) =-> parenExp (p > 1 && not (null tys))-> (ppQIdent tc <+> fsep (map (ppTypeExpr 2) tys))-> ppTypeExpr _ (VariableType tv) = ppIdent tv-> ppTypeExpr _ (TupleType tys) = parenList (map (ppTypeExpr 0) tys)-> ppTypeExpr _ (ListType ty) = brackets (ppTypeExpr 0 ty)-> ppTypeExpr p (ArrowType ty1 ty2) =-> parenExp (p > 0) (fsep (ppArrowType (ArrowType ty1 ty2)))-> where ppArrowType (ArrowType ty1 ty2) =-> ppTypeExpr 1 ty1 <+> rarrow : ppArrowType ty2-> ppArrowType ty = [ppTypeExpr 0 ty]-> ppTypeExpr p (RecordType fs rty) = -> braces (list (map ppTypedField fs) -> <> maybe empty (\ty -> space <> char '|' <+> ppTypeExpr 0 ty) rty)-> where-> ppTypedField (ls,ty) = -> list (map ppIdent ls) <> text "::" <> ppTypeExpr 0 ty--\end{verbatim}-Literals-\begin{verbatim}--> ppLiteral :: Literal -> Doc-> ppLiteral (Char _ c) = text (show c)-> ppLiteral (Int _ i) = integer i-> ppLiteral (Float _ f) = double f-> ppLiteral (String _ s) = text (show s)--\end{verbatim}-Patterns-\begin{verbatim}--> ppConstrTerm :: Int -> ConstrTerm -> Doc-> ppConstrTerm p (LiteralPattern l) =-> parenExp (p > 1 && isNegative l) (ppLiteral l)-> where isNegative (Char _ _) = False-> isNegative (Int _ i) = i < 0-> isNegative (Float _ f) = f < 0.0-> isNegative (String _ _) = False-> ppConstrTerm p (NegativePattern op l) =-> parenExp (p > 1) (ppInfixOp op <> ppLiteral l)-> ppConstrTerm _ (VariablePattern v) = ppIdent v-> ppConstrTerm p (ConstructorPattern c ts) =-> parenExp (p > 1 && not (null ts))-> (ppQIdent c <+> fsep (map (ppConstrTerm 2) ts))-> ppConstrTerm p (InfixPattern t1 c t2) =-> parenExp (p > 0)-> (sep [ppConstrTerm 1 t1 <+> ppQInfixOp c,-> indent (ppConstrTerm 0 t2)])-> ppConstrTerm _ (ParenPattern t) = parens (ppConstrTerm 0 t)-> ppConstrTerm _ (TuplePattern _ ts) = parenList (map (ppConstrTerm 0) ts)-> ppConstrTerm _ (ListPattern _ ts) = bracketList (map (ppConstrTerm 0) ts)-> ppConstrTerm _ (AsPattern v t) = ppIdent v <> char '@' <> ppConstrTerm 2 t-> ppConstrTerm _ (LazyPattern _ t) = char '~' <> ppConstrTerm 2 t-> ppConstrTerm p (FunctionPattern f ts) =-> parenExp (p > 1 && not (null ts))-> (ppQIdent f <+> fsep (map (ppConstrTerm 2) ts))-> ppConstrTerm p (InfixFuncPattern t1 f t2) =-> parenExp (p > 0)-> (sep [ppConstrTerm 1 t1 <+> ppQInfixOp f,-> indent (ppConstrTerm 0 t2)])-> ppConstrTerm p (RecordPattern fs rt) =-> braces (list (map ppFieldPatt fs)-> <> (maybe empty (\t -> space <> char '|' <+> ppConstrTerm 0 t) rt))--> ppFieldPatt :: Field ConstrTerm -> Doc-> ppFieldPatt (Field _ l t) = ppIdent l <> equals <> ppConstrTerm 0 t--\end{verbatim}-Expressions-\begin{verbatim}--> ppCondExpr :: Doc -> CondExpr -> Doc-> ppCondExpr eq (CondExpr _ g e) =-> vbar <+> sep [ppExpr 0 g <+> eq,indent (ppExpr 0 e)]--> ppExpr :: Int -> Expression -> Doc-> ppExpr _ (Literal l) = ppLiteral l-> ppExpr _ (Variable v) = ppQIdent v-> ppExpr _ (Constructor c) = ppQIdent c-> ppExpr _ (Paren e) = parens (ppExpr 0 e)-> ppExpr p (Typed e ty) =-> parenExp (p > 0) (ppExpr 0 e <+> text "::" <+> ppTypeExpr 0 ty)-> ppExpr _ (Tuple _ es) = parenList (map (ppExpr 0) es)-> ppExpr _ (List _ es) = bracketList (map (ppExpr 0) es)-> ppExpr _ (ListCompr _ e qs) =-> brackets (ppExpr 0 e <+> vbar <+> list (map ppStmt qs))-> ppExpr _ (EnumFrom e) = brackets (ppExpr 0 e <+> text "..")-> ppExpr _ (EnumFromThen e1 e2) =-> brackets (ppExpr 0 e1 <> comma <+> ppExpr 0 e2 <+> text "..")-> ppExpr _ (EnumFromTo e1 e2) =-> brackets (ppExpr 0 e1 <+> text ".." <+> ppExpr 0 e2)-> ppExpr _ (EnumFromThenTo e1 e2 e3) =-> brackets (ppExpr 0 e1 <> comma <+> ppExpr 0 e2-> <+> text ".." <+> ppExpr 0 e3)-> ppExpr p (UnaryMinus op e) = parenExp (p > 1) (ppInfixOp op <> ppExpr 1 e)-> ppExpr p (Apply e1 e2) =-> parenExp (p > 1) (sep [ppExpr 1 e1,indent (ppExpr 2 e2)])-> ppExpr p (InfixApply e1 op e2) =-> parenExp (p > 0) (sep [ppExpr 1 e1 <+> ppQInfixOp (opName op),-> indent (ppExpr 1 e2)])-> ppExpr _ (LeftSection e op) = parens (ppExpr 1 e <+> ppQInfixOp (opName op))-> ppExpr _ (RightSection op e) = parens (ppQInfixOp (opName op) <+> ppExpr 1 e)-> ppExpr p (Lambda _ t e) =-> parenExp (p > 0)-> (sep [backsl <> fsep (map (ppConstrTerm 2) t) <+> rarrow,-> indent (ppExpr 0 e)])-> ppExpr p (Let ds e) =-> parenExp (p > 0)-> (sep [text "let" <+> ppBlock ds <+> text "in",ppExpr 0 e])-> ppExpr p (Do sts e) =-> parenExp (p > 0) (text "do" <+> (vcat (map ppStmt sts) $$ ppExpr 0 e))-> ppExpr p (IfThenElse _ e1 e2 e3) =-> parenExp (p > 0)-> (text "if" <+>-> sep [ppExpr 0 e1,-> text "then" <+> ppExpr 0 e2,-> text "else" <+> ppExpr 0 e3])-> ppExpr p (Case _ e alts) =-> parenExp (p > 0)-> (text "case" <+> ppExpr 0 e <+> text "of" $$-> indent (vcat (map ppAlt alts)))-> ppExpr p (RecordConstr fs) =-> braces (list (map (ppFieldExpr equals) fs))-> ppExpr p (RecordSelection e l) =-> parenExp (p > 0)-> (ppExpr 1 e <+> text "->" <+> ppIdent l)-> ppExpr p (RecordUpdate fs e) =-> braces (list (map (ppFieldExpr (text ":=")) fs)-> <+> char '|' <+> ppExpr 0 e)--> ppStmt :: Statement -> Doc-> ppStmt (StmtExpr _ e) = ppExpr 0 e-> ppStmt (StmtBind _ t e) = sep [ppConstrTerm 0 t <+> larrow,indent (ppExpr 0 e)]-> ppStmt (StmtDecl ds) = text "let" <+> ppBlock ds--> ppAlt :: Alt -> Doc-> ppAlt (Alt _ t rhs) = ppRule (ppConstrTerm 0 t) rarrow rhs--> ppFieldExpr :: Doc -> Field Expression -> Doc-> ppFieldExpr comb (Field _ l e) = ppIdent l <> comb <> ppExpr 0 e--> ppOp :: InfixOp -> Doc-> ppOp (InfixOp op) = ppQInfixOp op-> ppOp (InfixConstr op) = ppQInfixOp op--\end{verbatim}-Goals-\begin{verbatim}--> ppGoal :: Goal -> Doc-> ppGoal (Goal _ e ds) = sep [ppExpr 0 e,indent (ppLocalDefs ds)]--\end{verbatim}-Names-\begin{verbatim}--> ppIdent :: Ident -> Doc-> ppIdent x = parenExp (isInfixOp x) (text (name x))--> ppQIdent :: QualIdent -> Doc-> ppQIdent x = parenExp (isQInfixOp x) (text (qualName x))--> ppInfixOp :: Ident -> Doc-> ppInfixOp x = backQuoteExp (not (isInfixOp x)) (text (name x))--> ppQInfixOp :: QualIdent -> Doc-> ppQInfixOp x = backQuoteExp (not (isQInfixOp x)) (text (qualName x))--> ppMIdent :: ModuleIdent -> Doc-> ppMIdent m = text (moduleName m)--\end{verbatim}-Print printing utilities-\begin{verbatim}--> indent :: Doc -> Doc-> indent = nest 2--> maybePP :: (a -> Doc) -> Maybe a -> Doc-> maybePP pp = maybe empty pp--> parenExp :: Bool -> Doc -> Doc-> parenExp b doc = if b then parens doc else doc--> backQuoteExp :: Bool -> Doc -> Doc-> backQuoteExp b doc = if b then backQuote <> doc <> backQuote else doc--> list, parenList, bracketList, braceList :: [Doc] -> Doc-> list = fsep . punctuate comma-> parenList = parens . list-> bracketList = brackets . list-> braceList = braces . list--> backQuote,backsl,vbar,rarrow,larrow :: Doc-> backQuote = char '`'-> backsl = char '\\'-> vbar = char '|'-> rarrow = text "->"-> larrow = text "<-"--\end{verbatim}
− src/CurryParser.lhs
@@ -1,818 +0,0 @@--% $Id: CurryParser.lhs,v 1.75 2004/02/15 23:11:28 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{CurryParser.lhs}-\section{A Parser for Curry}-The Curry parser is implemented using the (mostly) LL(1) parsing-combinators described in appendix~\ref{sec:ll-parsecomb}.-\begin{verbatim}--> module CurryParser where-> import Ident-> import Position-> import Error-> import LLParseComb-> import CurrySyntax-> import CurryLexer--> instance Symbol Token where-> isEOF (Token c _) = c == EOF--\end{verbatim}-\paragraph{Modules}-\begin{verbatim}--> parseSource :: Bool -> FilePath -> String -> Error Module-> parseSource flat path mod = -> fmap addSrcRefs (applyParser (parseModule flat) lexer path mod)--> parseHeader :: FilePath -> String -> Error Module-> parseHeader = prefixParser (moduleHeader <*->-> (leftBrace `opt` undefined) <*>-> many (importDecl <*-> many semicolon))-> lexer--> parseModule :: Bool -> Parser Token Module a-> parseModule flat = moduleHeader <*> decls flat--> moduleHeader :: Parser Token ([Decl] -> Module) a-> moduleHeader = Module <$-> token KW_module-> <*> (mIdent <?> "module name expected")-> <*> ((Just <$> exportSpec) `opt` Nothing)-> <*-> (token KW_where <?> "where expected")-> `opt` Module mainMIdent Nothing--> exportSpec :: Parser Token ExportSpec a-> exportSpec = Exporting <$> position <*> parens (export `sepBy` comma)--> export :: Parser Token Export a-> export = qtycon <**> (parens spec `opt` Export)-> <|> Export <$> qfun <\> qtycon-> <|> ExportModule <$-> token KW_module <*> mIdent-> where spec = ExportTypeAll <$-> token DotDot-> <|> flip ExportTypeWith <$> con `sepBy` comma--\end{verbatim}-\paragraph{Interfaces}-Since this modified version of MCC uses FlatCurry interfaces instead of-".icurry" files, a separate parser is not required any longer.-\begin{verbatim}--> --parseInterface :: FilePath -> String -> Error Interface-> --parseInterface fn s = applyParser parseIface lexer fn s--> --parseIface :: Parser Token Interface a-> --parseIface = Interface <$-> token Id_interface-> -- <*> (mIdent <?> "module name expected")-> -- <*-> (token KW_where <?> "where expected")-> -- <*> braces intfDecls--\end{verbatim}-\paragraph{Goals}-\begin{verbatim}--> parseGoal :: String -> Error Goal-> parseGoal s = applyParser goal lexer "" s--> goal :: Parser Token Goal a-> goal = Goal <$> position <*> expr False <*> localDefs False--\end{verbatim}-\paragraph{Declarations}-\begin{verbatim}--> decls :: Bool -> Parser Token [Decl] a-> decls flat = layout (globalDecls flat)--> globalDecls :: Bool -> Parser Token [Decl] a-> globalDecls flat =-> (:) <$> importDecl <*> (semicolon <-*> globalDecls flat `opt` [])-> <|> topDecl flat `sepBy` semicolon--> topDecl :: Bool -> Parser Token Decl a-> topDecl flat-> | flat = infixDecl <|> dataDecl flat <|> typeDecl <|> functionDecl flat-> | otherwise = infixDecl-> <|> dataDecl flat <|> newtypeDecl <|> typeDecl-> <|> functionDecl flat <|> externalDecl--> localDefs :: Bool -> Parser Token [Decl] a-> localDefs flat = token KW_where <-*> layout (valueDecls flat)-> `opt` []--> valueDecls :: Bool -> Parser Token [Decl] a-> valueDecls flat = localDecl flat `sepBy` semicolon-> where localDecl flat-> | flat = infixDecl <|> valueDecl flat-> | otherwise = infixDecl <|> valueDecl flat <|> externalDecl--> importDecl :: Parser Token Decl a-> importDecl =-> flip . ImportDecl <$> position <*-> token KW_import -> <*> (True <$-> token Id_qualified `opt` False)-> <*> mIdent-> <*> (Just <$-> token Id_as <*> mIdent `opt` Nothing)-> <*> (Just <$> importSpec `opt` Nothing)--> importSpec :: Parser Token ImportSpec a-> importSpec = position <**> (Hiding <$-> token Id_hiding `opt` Importing)-> <*> parens (spec `sepBy` comma)-> where spec = tycon <**> (parens constrs `opt` Import)-> <|> Import <$> fun <\> tycon-> constrs = ImportTypeAll <$-> token DotDot-> <|> flip ImportTypeWith <$> con `sepBy` comma--> infixDecl :: Parser Token Decl a-> infixDecl = infixDeclLhs InfixDecl <*> funop `sepBy1` comma--> infixDeclLhs :: (Position -> Infix -> Integer -> a) -> Parser Token a b-> infixDeclLhs f = f <$> position <*> tokenOps infixKW <*> integer-> where infixKW = [(KW_infix,Infix),(KW_infixl,InfixL),(KW_infixr,InfixR)]--> dataDecl :: Bool -> Parser Token Decl a-> dataDecl flat = typeDeclLhs DataDecl KW_data <*> constrs-> where constrs = equals <-*> constrDecl flat `sepBy1` bar-> `opt` []--> newtypeDecl :: Parser Token Decl a-> newtypeDecl =-> typeDeclLhs NewtypeDecl KW_newtype <*-> equals <*> newConstrDecl--> typeDecl :: Parser Token Decl a-> typeDecl = typeDeclLhs TypeDecl KW_type <*-> equals <*> typeDeclRhs --type0--> typeDeclLhs :: (Position -> Ident -> [Ident] -> a) -> Category-> -> Parser Token a b-> typeDeclLhs f kw = f <$> position <*-> token kw <*> tycon <*> many typeVar-> where typeVar = tyvar <|> anonId <$-> token Underscore--> typeDeclRhs :: Parser Token TypeExpr a-> typeDeclRhs = type0-> <|> (flip RecordType) Nothing-> <$> (layoutOff <-*> braces (labelDecls `sepBy` comma))--> labelDecls = (,) <$> labId `sepBy1` comma <*-> token DoubleColon <*> type0--> constrDecl :: Bool -> Parser Token ConstrDecl a-> constrDecl flat = position <**> (existVars <**> constr)-> where constr = conId <**> identDecl-> <|> leftParen <-*> parenDecl-> <|> type1 <\> conId <\> leftParen <**> opDecl-> identDecl = many type2 <**> (conType <$> opDecl `opt` conDecl)-> parenDecl = conOpDeclPrefix -> <$> conSym <*-> rightParen <*> type2 <*> type2-> <|> tupleType <*-> rightParen <**> opDecl-> opDecl = conOpDecl <$> conop <*> type1-> conType f tys c = f (ConstructorType (qualify c) tys)-> conDecl tys c tvs p = ConstrDecl p tvs c tys-> conOpDecl op ty2 ty1 tvs p = ConOpDecl p tvs ty1 op ty2-> conOpDeclPrefix op ty1 ty2 tvs p = ConOpDecl p tvs ty1 op ty2--> newConstrDecl :: Parser Token NewConstrDecl a-> newConstrDecl =-> NewConstrDecl <$> position <*> existVars <*> con <*> type2--> existVars :: Parser Token [Ident] a-> {--> existVars flat-> | flat = succeed []-> | otherwise = token Id_forall <-*> many1 tyvar <*-> dot `opt` []-> -}-> existVars = succeed []--> functionDecl :: Bool -> Parser Token Decl a-> functionDecl flat = position <**> decl-> where decl = fun `sepBy1` comma <**> funListDecl flat-> <|?> funDecl <$> lhs <*> declRhs flat-> lhs = (\f -> (f,FunLhs f [])) <$> fun-> <|?> funLhs--> valueDecl :: Bool -> Parser Token Decl a-> valueDecl flat = position <**> decl-> where decl = var `sepBy1` comma <**> valListDecl flat-> <|?> valDecl <$> constrTerm0 <*> declRhs flat-> <|?> funDecl <$> curriedLhs <*> declRhs flat-> valDecl t@(ConstructorPattern c ts)-> | not (isConstrId c) = funDecl (f,FunLhs f ts)-> where f = unqualify c-> valDecl t = opDecl id t-> opDecl f (InfixPattern t1 op t2)-> | isConstrId op = opDecl (f . InfixPattern t1 op) t2-> | otherwise = funDecl (op',OpLhs (f t1) op' t2)-> where op' = unqualify op-> opDecl f t = patDecl (f t)-> isConstrId c = c == qConsId || isQualified c || isQTupleId c--> funDecl :: (Ident,Lhs) -> Rhs -> Position -> Decl-> funDecl (f,lhs) rhs p = FunctionDecl p f [Equation p lhs rhs]--> patDecl :: ConstrTerm -> Rhs -> Position -> Decl-> patDecl t rhs p = PatternDecl p t rhs--> funListDecl :: Bool -> Parser Token ([Ident] -> Position -> Decl) a-> funListDecl flat-> | flat = typeSig <$-> token DoubleColon <*> type0-> <|> evalAnnot <$-> token KW_eval <*> tokenOps evalKW-> <|> externalDecl <$-> token KW_external-> | otherwise = typeSig <$-> token DoubleColon <*> type0-> <|> evalAnnot <$-> token KW_eval <*> tokenOps evalKW-> where typeSig ty vs p = TypeSig p vs ty-> evalAnnot ev vs p = EvalAnnot p vs ev-> evalKW = [(KW_rigid,EvalRigid),(KW_choice,EvalChoice)]-> externalDecl vs p = FlatExternalDecl p vs--> valListDecl :: Bool -> Parser Token ([Ident] -> Position -> Decl) a-> valListDecl flat = funListDecl flat <|> extraVars <$-> token KW_free-> where extraVars vs p = ExtraVariables p vs--> funLhs :: Parser Token (Ident,Lhs) a-> funLhs = funLhs <$> fun <*> many1 constrTerm2-> <|?> flip ($ id) <$> constrTerm1 <*> opLhs'-> <|?> curriedLhs-> where opLhs' = opLhs <$> funSym <*> constrTerm0-> <|> infixPat <$> gConSym <\> funSym <*> constrTerm1 <*> opLhs'-> <|> backquote <-*> opIdLhs-> opIdLhs = opLhs <$> funId <*-> checkBackquote <*> constrTerm0-> <|> infixPat <$> qConId <\> funId <*-> backquote <*> constrTerm1-> <*> opLhs'-> funLhs f ts = (f,FunLhs f ts)-> opLhs op t2 f t1 = (op,OpLhs (f t1) op t2)-> infixPat op t2 f g t1 = f (g . InfixPattern t1 op) t2--> curriedLhs :: Parser Token (Ident,Lhs) a-> curriedLhs = apLhs <$> parens funLhs <*> many1 constrTerm2-> where apLhs (f,lhs) ts = (f,ApLhs lhs ts)--> declRhs :: Bool -> Parser Token Rhs a-> declRhs flat = rhs flat equals--> rhs :: Bool -> Parser Token a b -> Parser Token Rhs b-> rhs flat eq = rhsExpr <*> localDefs flat-> where rhsExpr = SimpleRhs <$-> eq <*> position <*> expr flat-> <|> GuardedRhs <$> many1 (condExpr flat eq)--> externalDecl :: Parser Token Decl a-> externalDecl =-> ExternalDecl <$> position <*-> token KW_external-> <*> callConv <*> (Just <$> string `opt` Nothing)-> <*> fun <*-> token DoubleColon <*> type0-> where callConv = CallConvPrimitive <$-> token Id_primitive-> <|> CallConvCCall <$-> token Id_ccall-> <?> "Unsupported calling convention"--\end{verbatim}-\paragraph{Interface declarations}-\begin{verbatim}--> --intfDecls :: Parser Token [IDecl] a-> --intfDecls = (:) <$> iImportDecl <*> (semicolon <-*> intfDecls `opt` [])-> -- <|> intfDecl `sepBy` semicolon--> --intfDecl :: Parser Token IDecl a-> --intfDecl = iInfixDecl-> -- <|> iHidingDecl <|> iDataDecl <|> iNewtypeDecl <|> iTypeDecl-> -- <|> iFunctionDecl <\> token Id_hiding--> --iImportDecl :: Parser Token IDecl a-> --iImportDecl = IImportDecl <$> position <*-> token KW_import <*> mIdent--> --iInfixDecl :: Parser Token IDecl a-> --iInfixDecl = infixDeclLhs IInfixDecl <*> qfunop--> --iHidingDecl :: Parser Token IDecl a-> --iHidingDecl = position <*-> token Id_hiding <**> (dataDecl <|> funcDecl)-> -- where dataDecl = hiddenData <$-> token KW_data <*> tycon <*> many tyvar-> -- funcDecl = hidingFunc <$-> token DoubleColon <*> type0-> -- hiddenData tc tvs p = HidingDataDecl p tc tvs-> -- hidingFunc ty p = IFunctionDecl p hidingId ty-> -- hidingId = qualify (mkIdent "hiding")--> --iDataDecl :: Parser Token IDecl a-> --iDataDecl = iTypeDeclLhs IDataDecl KW_data <*> constrs-> -- where constrs = equals <-*> iConstrDecl `sepBy1` bar-> -- `opt` []-> -- iConstrDecl = Just <$> constrDecl False <\> token Underscore-> -- <|> Nothing <$-> token Underscore--> --iNewtypeDecl :: Parser Token IDecl a-> --iNewtypeDecl =-> -- iTypeDeclLhs INewtypeDecl KW_newtype <*-> equals <*> newConstrDecl--> --iTypeDecl :: Parser Token IDecl a-> --iTypeDecl = iTypeDeclLhs ITypeDecl KW_type <*-> equals <*> type0--> --iTypeDeclLhs :: (Position -> QualIdent -> [Ident] -> a) -> Category-> -- -> Parser Token a b-> --iTypeDeclLhs f kw = f <$> position <*-> token kw <*> qtycon <*> many tyvar--> --iFunctionDecl :: Parser Token IDecl a-> --iFunctionDecl = IFunctionDecl <$> position <*> qfun <*-> token DoubleColon-> -- <*> type0--\end{verbatim}-\paragraph{Types}-\begin{verbatim}--> type0 :: Parser Token TypeExpr a-> type0 = type1 `chainr1` (ArrowType <$-> token RightArrow)--> type1 :: Parser Token TypeExpr a-> type1 = ConstructorType <$> qtycon <*> many type2-> <|> type2 <\> qtycon--> type2 :: Parser Token TypeExpr a-> type2 = anonType <|> identType <|> parenType <|> listType--> anonType :: Parser Token TypeExpr a-> anonType = VariableType anonId <$-> token Underscore--> identType :: Parser Token TypeExpr a-> identType = VariableType <$> tyvar-> <|> flip ConstructorType [] <$> qtycon <\> tyvar--> parenType :: Parser Token TypeExpr a-> parenType = parens tupleType--> tupleType :: Parser Token TypeExpr a-> tupleType = type0 <??> (tuple <$> many1 (comma <-*> type0))-> `opt` TupleType []-> where tuple tys ty = TupleType (ty:tys)--> listType :: Parser Token TypeExpr a-> listType = ListType <$> brackets type0--\end{verbatim}-\paragraph{Literals}-\begin{verbatim}--> literal :: Parser Token Literal a-> literal = mk Char <$> char-> <|> mkInt <$> integer-> <|> mk Float <$> float-> <|> mk String <$> string--\end{verbatim}-\paragraph{Patterns}-\begin{verbatim}--> constrTerm0 :: Parser Token ConstrTerm a-> constrTerm0 = constrTerm1 `chainr1` (flip InfixPattern <$> gconop)--> constrTerm1 :: Parser Token ConstrTerm a-> constrTerm1 = varId <**> identPattern-> <|> ConstructorPattern <$> qConId <\> varId <*> many constrTerm2-> <|> minus <**> negNum-> <|> fminus <**> negFloat-> <|> leftParen <-*> parenPattern-> <|> constrTerm2 <\> qConId <\> leftParen-> where identPattern = optAsPattern-> <|> conPattern <$> many1 constrTerm2-> parenPattern = minus <**> minusPattern negNum-> <|> fminus <**> minusPattern negFloat-> <|> gconPattern-> <|> funSym <\> minus <\> fminus <*-> rightParen-> <**> identPattern-> <|> parenTuplePattern <\> minus <\> fminus <*-> rightParen-> minusPattern p = rightParen <-*> identPattern-> <|> parenMinusPattern p <*-> rightParen-> gconPattern = ConstructorPattern <$> gconId <*-> rightParen-> <*> many constrTerm2-> conPattern ts = flip ConstructorPattern ts . qualify--> constrTerm2 :: Parser Token ConstrTerm a-> constrTerm2 = literalPattern <|> anonPattern <|> identPattern-> <|> parenPattern <|> listPattern <|> lazyPattern-> <|> recordPattern--> literalPattern :: Parser Token ConstrTerm a-> literalPattern = LiteralPattern <$> literal--> anonPattern :: Parser Token ConstrTerm a-> anonPattern = VariablePattern anonId <$-> token Underscore--> identPattern :: Parser Token ConstrTerm a-> identPattern = varId <**> optAsPattern-> <|> flip ConstructorPattern [] <$> qConId <\> varId--> parenPattern :: Parser Token ConstrTerm a-> parenPattern = leftParen <-*> parenPattern-> where parenPattern = minus <**> minusPattern negNum-> <|> fminus <**> minusPattern negFloat-> <|> flip ConstructorPattern [] <$> gconId <*-> rightParen-> <|> funSym <\> minus <\> fminus <*-> rightParen-> <**> optAsPattern-> <|> parenTuplePattern <\> minus <\> fminus <*-> rightParen-> minusPattern p = rightParen <-*> optAsPattern-> <|> parenMinusPattern p <*-> rightParen--> listPattern :: Parser Token ConstrTerm a-> listPattern = mk' ListPattern <$> brackets (constrTerm0 `sepBy` comma)--> lazyPattern :: Parser Token ConstrTerm a-> lazyPattern = mk LazyPattern <$-> token Tilde <*> constrTerm2--> recordPattern :: Parser Token ConstrTerm a-> recordPattern = layoutOff <-*> braces content-> where-> content = RecordPattern <$> fields <*> record-> fields = fieldPatt `sepBy` comma-> fieldPatt = Field <$> position <*> labId <*-> checkEquals <*> constrTerm0-> record = Just <$-> checkBar <*> constrTerm2 `opt` Nothing--\end{verbatim}-Partial patterns used in the combinators above, but also for parsing-the left-hand side of a declaration.-\begin{verbatim}--> gconId :: Parser Token QualIdent a-> gconId = colon <|> tupleCommas--> negNum,negFloat :: Parser Token (Ident -> ConstrTerm) a-> negNum = flip NegativePattern -> <$> (mkInt <$> integer <|> mk Float <$> float)-> negFloat = flip NegativePattern . mk Float -> <$> (fromIntegral <$> integer <|> float)--> optAsPattern :: Parser Token (Ident -> ConstrTerm) a-> optAsPattern = flip AsPattern <$-> token At <*> constrTerm2-> `opt` VariablePattern--> optInfixPattern :: Parser Token (ConstrTerm -> ConstrTerm) a-> optInfixPattern = infixPat <$> gconop <*> constrTerm0-> `opt` id-> where infixPat op t2 t1 = InfixPattern t1 op t2--> optTuplePattern :: Parser Token (ConstrTerm -> ConstrTerm) a-> optTuplePattern = tuple <$> many1 (comma <-*> constrTerm0)-> `opt` ParenPattern-> where tuple ts t = mk TuplePattern (t:ts)--> parenMinusPattern :: Parser Token (Ident -> ConstrTerm) a-> -> Parser Token (Ident -> ConstrTerm) a-> parenMinusPattern p = p <.> optInfixPattern <.> optTuplePattern--> parenTuplePattern :: Parser Token ConstrTerm a-> parenTuplePattern = constrTerm0 <**> optTuplePattern-> `opt` mk TuplePattern []--\end{verbatim}-\paragraph{Expressions}-\begin{verbatim}--> condExpr :: Bool -> Parser Token a b -> Parser Token CondExpr b-> condExpr flat eq =-> CondExpr <$> position <*-> bar <*> expr0 flat <*-> eq <*> expr flat--> expr :: Bool -> Parser Token Expression a-> expr flat = expr0 flat <??> (flip Typed <$-> token DoubleColon <*> type0)--> expr0 :: Bool -> Parser Token Expression a-> expr0 flat = expr1 flat `chainr1` (flip InfixApply <$> infixOp)--> expr1 :: Bool -> Parser Token Expression a-> expr1 flat = UnaryMinus <$> (minus <|> fminus) <*> expr2 flat-> <|> expr2 flat--> expr2 :: Bool -> Parser Token Expression a-> expr2 flat = lambdaExpr flat <|> letExpr flat <|> doExpr flat-> <|> ifExpr flat <|> caseExpr flat-> <|> expr3 flat <**> applicOrSelect-> where-> applicOrSelect = flip RecordSelection -> <$-> (token RightArrow <?> "-> expected")-> <*> labId-> <|?> (\es e -> foldl1 Apply (e:es))-> <$> many (expr3 flat) --> expr3 :: Bool -> Parser Token Expression a-> expr3 flat = expr3' -> where-> expr3' = constant <|> variable <|> parenExpr flat-> <|> listExpr flat <|> recordExpr flat--> constant :: Parser Token Expression a-> constant = Literal <$> literal--> variable :: Parser Token Expression a-> variable = Variable <$> qFunId--> parenExpr :: Bool -> Parser Token Expression a-> parenExpr flat = parens pExpr-> where pExpr = (minus <|> fminus) <**> minusOrTuple-> <|> Constructor <$> tupleCommas-> <|> leftSectionOrTuple <\> minus <\> fminus-> <|> opOrRightSection <\> minus <\> fminus-> `opt` mk Tuple []-> minusOrTuple = flip UnaryMinus <$> expr1 flat <.> infixOrTuple-> `opt` Variable . qualify-> leftSectionOrTuple = expr1 flat <**> infixOrTuple-> infixOrTuple = ($ id) <$> infixOrTuple'-> infixOrTuple' = infixOp <**> leftSectionOrExp-> <|> (.) <$> (optType <.> tupleExpr)-> leftSectionOrExp = expr1 flat <**> (infixApp <$> infixOrTuple')-> `opt` leftSection-> optType = flip Typed <$-> token DoubleColon <*> type0-> `opt` id-> tupleExpr = tuple <$> many1 (comma <-*> expr flat)-> `opt` Paren-> opOrRightSection = qFunSym <**> optRightSection-> <|> colon <**> optCRightSection-> <|> infixOp <\> colon <\> qFunSym <**> rightSection-> optRightSection = (. InfixOp) <$> rightSection `opt` Variable-> optCRightSection = (. InfixConstr) <$> rightSection `opt` Constructor-> rightSection = flip RightSection <$> expr0 flat-> infixApp f e2 op g e1 = f (g . InfixApply e1 op) e2-> leftSection op f e = LeftSection (f e) op-> tuple es e = mk Tuple (e:es)--> infixOp :: Parser Token InfixOp a-> infixOp = InfixOp <$> qfunop-> <|> InfixConstr <$> colon--> listExpr :: Bool -> Parser Token Expression a-> listExpr flat = brackets (elements `opt` mk' List [])-> where elements = expr flat <**> rest-> rest = comprehension-> <|> enumeration (flip EnumFromTo) EnumFrom-> <|> comma <-*> expr flat <**>-> (enumeration (flip3 EnumFromThenTo) (flip EnumFromThen)-> <|> list <$> many (comma <-*> expr flat))-> `opt` (\e -> mk' List [e])-> comprehension = flip (mk ListCompr) <$-> bar <*> quals flat-> enumeration enumTo enum =-> token DotDot <-*> (enumTo <$> expr flat `opt` enum)-> list es e2 e1 = mk' List (e1:e2:es)-> flip3 f x y z = f z y x--> recordExpr :: Bool -> Parser Token Expression a-> recordExpr flat = layoutOff <-*> braces content-> where content = RecordConstr <$> fieldConstr `sepBy` comma-> <|?> RecordUpdate <$> fieldUpdate `sepBy` comma-> <*-> checkBar <*> expr flat-> fieldConstr = Field <$> position <*> labId -> <*-> checkEquals <*> expr flat-> fieldUpdate = Field <$> position <*> labId -> <*-> checkBinds <*> expr flat--> lambdaExpr :: Bool -> Parser Token Expression a-> lambdaExpr flat =-> mk Lambda <$-> token Backslash <*> many1 constrTerm2-> <*-> (token RightArrow <?> "-> expected") <*> expr flat--> letExpr :: Bool -> Parser Token Expression a-> letExpr flat = Let <$-> token KW_let <*> layout (valueDecls flat)-> <*-> (token KW_in <?> "in expected") <*> expr flat--> doExpr :: Bool -> Parser Token Expression a-> doExpr flat = uncurry Do <$-> token KW_do <*> layout (stmts flat)--> ifExpr :: Bool -> Parser Token Expression a-> ifExpr flat =-> mk IfThenElse <$-> token KW_if <*> expr flat-> <*-> (token KW_then <?> "then expected") <*> expr flat-> <*-> (token KW_else <?> "else expected") <*> expr flat--> caseExpr :: Bool -> Parser Token Expression a-> caseExpr flat = mk Case <$-> token KW_case <*> expr flat-> <*-> (token KW_of <?> "of expected") <*> layout (alts flat)--> alts :: Bool -> Parser Token [Alt] a-> alts flat = alt flat `sepBy1` semicolon--> alt :: Bool -> Parser Token Alt a-> alt flat = Alt <$> position <*> constrTerm0-> <*> rhs flat (token RightArrow <?> "-> expected")--\end{verbatim}-\paragraph{Statements in list comprehensions and \texttt{do} expressions}-Parsing statements is a bit difficult because the syntax of patterns-and expressions largely overlaps. The parser will first try to-recognize the prefix \emph{Pattern}~\texttt{<-} of a binding statement-and if this fails fall back into parsing an expression statement. In-addition, we have to be prepared that the sequence-\texttt{let}~\emph{LocalDefs} can be either a let-statement or the-prefix of a let expression.-\begin{verbatim}--> stmts :: Bool -> Parser Token ([Statement],Expression) a-> stmts flat = stmt flat (reqStmts flat) (optStmts flat)--> reqStmts :: Bool -> Parser Token (Statement -> ([Statement],Expression)) a-> reqStmts flat = (\(sts,e) st -> (st : sts,e)) <$-> semicolon <*> stmts flat--> optStmts :: Bool -> Parser Token (Expression -> ([Statement],Expression)) a-> optStmts flat = succeed (mk StmtExpr) <.> reqStmts flat-> `opt` (,) []--> quals :: Bool -> Parser Token [Statement] a-> quals flat = stmt flat (succeed id) (succeed $ mk StmtExpr) `sepBy1` comma--> stmt :: Bool -> Parser Token (Statement -> a) b-> -> Parser Token (Expression -> a) b -> Parser Token a b-> stmt flat stmtCont exprCont = letStmt flat stmtCont exprCont-> <|> exprOrBindStmt flat stmtCont exprCont--> letStmt :: Bool -> Parser Token (Statement -> a) b-> -> Parser Token (Expression -> a) b -> Parser Token a b-> letStmt flat stmtCont exprCont =-> token KW_let <-*> layout (valueDecls flat) <**> optExpr-> where optExpr = flip Let <$-> token KW_in <*> expr flat <.> exprCont-> <|> succeed StmtDecl <.> stmtCont--> exprOrBindStmt :: Bool -> Parser Token (Statement -> a) b-> -> Parser Token (Expression -> a) b-> -> Parser Token a b-> exprOrBindStmt flat stmtCont exprCont =-> mk StmtBind <$> constrTerm0 <*-> leftArrow <*> expr flat <**> stmtCont-> <|?> expr flat <\> token KW_let <**> exprCont--\end{verbatim}-\paragraph{Literals, identifiers, and (infix) operators}-\begin{verbatim}--> char :: Parser Token Char a-> char = cval <$> token CharTok--> int, checkInt :: Parser Token Int a-> int = ival <$> token IntTok-> checkInt = int <?> "integer number expected"--> float, checkFloat :: Parser Token Double a-> float = fval <$> token FloatTok-> checkFloat = float <?> "floating point number expected"--> integer, checkInteger :: Parser Token Integer a-> integer = intval <$> token IntegerTok-> checkInteger = integer <?> "integer number expected"--> string :: Parser Token String a-> string = sval <$> token StringTok--> tycon, tyvar :: Parser Token Ident a-> tycon = conId-> tyvar = varId--> qtycon :: Parser Token QualIdent a-> qtycon = qConId--> varId, funId, conId, labId :: Parser Token Ident a-> varId = ident-> funId = ident-> conId = ident-> labId = renameLabel <$> ident--> funSym, conSym :: Parser Token Ident a-> funSym = sym-> conSym = sym--> var, fun, con :: Parser Token Ident a-> var = varId <|> parens (funSym <?> "operator symbol expected")-> fun = funId <|> parens (funSym <?> "operator symbol expected")-> con = conId <|> parens (conSym <?> "operator symbol expected")--> funop, conop :: Parser Token Ident a-> funop = funSym <|> backquotes (funId <?> "operator name expected")-> conop = conSym <|> backquotes (conId <?> "operator name expected")--> qFunId, qConId, qLabId :: Parser Token QualIdent a-> qFunId = qIdent-> qConId = qIdent-> qLabId = qIdent--> qFunSym, qConSym :: Parser Token QualIdent a-> qFunSym = qSym-> qConSym = qSym-> gConSym = qConSym <|> colon--> qfun, qcon :: Parser Token QualIdent a-> qfun = qFunId <|> parens (qFunSym <?> "operator symbol expected")-> qcon = qConId <|> parens (qConSym <?> "operator symbol expected")--> qfunop, qconop, gconop :: Parser Token QualIdent a-> qfunop = qFunSym <|> backquotes (qFunId <?> "operator name expected")-> qconop = qConSym <|> backquotes (qConId <?> "operator name expected")-> gconop = gConSym <|> backquotes (qConId <?> "operator name expected")--> ident :: Parser Token Ident a-> ident = (\ pos t -> mkIdentPosition pos $ sval t) <$> position <*> -> tokens [Id,Id_as,Id_ccall,Id_forall,Id_hiding,-> Id_interface,Id_primitive,Id_qualified]--> qIdent :: Parser Token QualIdent a-> qIdent = qualify <$> ident <|> mkQIdent <$> position <*> token QId-> where mkQIdent p a = qualifyWith (mkMIdent (modul a)) -> (mkIdentPosition p (sval a))--> mIdent :: Parser Token ModuleIdent a-> mIdent = mIdent <$> position <*> -> tokens [Id,QId,Id_as,Id_ccall,Id_forall,Id_hiding,-> Id_interface,Id_primitive,Id_qualified]-> where mIdent p a = addPositionModuleIdent p $ -> mkMIdent (modul a ++ [sval a])--> sym :: Parser Token Ident a-> sym = (\ pos t -> mkIdentPosition pos $ sval t) <$> position <*> -> tokens [Sym,Sym_Dot,Sym_Minus,Sym_MinusDot]--> qSym :: Parser Token QualIdent a-> qSym = qualify <$> sym <|> mkQIdent <$> position <*> token QSym-> where mkQIdent p a = qualifyWith (mkMIdent (modul a)) -> (mkIdentPosition p (sval a))--> colon :: Parser Token QualIdent a-> colon = (\ p _ -> qualify $ addPositionIdent p consId) <$> -> position <*> token Colon--> minus :: Parser Token Ident a-> minus = (\ p _ -> addPositionIdent p minusId) <$> -> position <*> token Sym_Minus--> fminus :: Parser Token Ident a-> fminus = (\ p _ -> addPositionIdent p fminusId) <$> -> position <*> token Sym_MinusDot--> tupleCommas :: Parser Token QualIdent a-> tupleCommas = (\ p str -> qualify $-> addPositionIdent p (tupleId $ -> (1 + ) $ -> length str))-> <$> position <*> many1 comma--\end{verbatim}-\paragraph{Layout}-\begin{verbatim}--> layout :: Parser Token a b -> Parser Token a b-> layout p = layoutOff <-*> bracket leftBraceSemicolon p rightBrace-> <|> layoutOn <-*> p <*-> (token VRightBrace <|> layoutEnd)--\end{verbatim}-\paragraph{More combinators}-\begin{verbatim}--> braces, brackets, parens, backquotes :: Parser Token a b -> Parser Token a b-> braces p = bracket leftBrace p rightBrace-> brackets p = bracket leftBracket p rightBracket-> parens p = bracket leftParen p rightParen-> backquotes p = bracket backquote p checkBackquote--\end{verbatim}-\paragraph{Simple token parsers}-\begin{verbatim}--> token :: Category -> Parser Token Attributes a-> token c = attr <$> symbol (Token c NoAttributes)-> where attr (Token _ a) = a--> tokens :: [Category] -> Parser Token Attributes a-> tokens cs = foldr1 (<|>) (map token cs)--> tokenOps :: [(Category,a)] -> Parser Token a b-> tokenOps cs = ops [(Token c NoAttributes,x) | (c,x) <- cs]--> dot, comma, semicolon, bar, equals, binds :: Parser Token Attributes a-> dot = token Sym_Dot-> comma = token Comma-> semicolon = token Semicolon <|> token VSemicolon-> bar = token Bar-> equals = token Equals-> binds = token Binds--> checkBar, checkEquals, checkBinds :: Parser Token Attributes a-> checkBar = bar <?> "| expected"-> checkEquals = equals <?> "= expected"-> checkBinds = binds <?> ":= expected"--> backquote, checkBackquote :: Parser Token Attributes a-> backquote = token Backquote-> checkBackquote = backquote <?> "backquote (`) expected"--> leftParen, rightParen :: Parser Token Attributes a-> leftParen = token LeftParen-> rightParen = token RightParen--> leftBracket, rightBracket :: Parser Token Attributes a-> leftBracket = token LeftBracket-> rightBracket = token RightBracket--> leftBrace, leftBraceSemicolon, rightBrace :: Parser Token Attributes a-> leftBrace = token LeftBrace-> leftBraceSemicolon = token LeftBraceSemicolon-> rightBrace = token RightBrace--> leftArrow :: Parser Token Attributes a-> leftArrow = token LeftArrow--\end{verbatim}-\paragraph{Ident}-\begin{verbatim}--> mkIdentPosition :: Position -> String -> Ident-> mkIdentPosition pos str = addPositionIdent pos $ mkIdent str--\end{verbatim}
− src/CurrySyntax.lhs
@@ -1,323 +0,0 @@-> {-# LANGUAGE DeriveDataTypeable #-}--% $Id: CurrySyntax.lhs,v 1.43 2004/02/15 22:10:31 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{CurrySyntax.lhs}-\section{The Parse Tree}-This module provides the necessary data structures to maintain the-parsed representation of a Curry program.--\em{Note:} this modified version uses haskell type \texttt{Integer}-instead of \texttt{Int} for representing integer values. This allows-an unlimited range of integer constants in Curry programs.-\begin{verbatim}--> module CurrySyntax where-> import Ident-> import Position-> import Data.Generics-> import Control.Monad.State--\end{verbatim}-\paragraph{Modules}-\begin{verbatim}--> data Module = Module ModuleIdent (Maybe ExportSpec) [Decl] -> deriving (Eq,Show,Read,Typeable,Data)--> data ExportSpec = Exporting Position [Export] deriving (Eq,Show,Read,Typeable,Data)-> data Export =-> Export QualIdent -- f/T-> | ExportTypeWith QualIdent [Ident] -- T(C1,...,Cn)-> | ExportTypeAll QualIdent -- T(..)-> | ExportModule ModuleIdent-> deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}-\paragraph{Module declarations}-\begin{verbatim}--> data ImportSpec =-> Importing Position [Import]-> | Hiding Position [Import]-> deriving (Eq,Show,Read,Typeable,Data)-> data Import =-> Import Ident -- f/T-> | ImportTypeWith Ident [Ident] -- T(C1,...,Cn)-> | ImportTypeAll Ident -- T(..)-> deriving (Eq,Show,Read,Typeable,Data)--> data Decl =-> ImportDecl Position ModuleIdent Qualified (Maybe ModuleIdent)-> (Maybe ImportSpec)-> | InfixDecl Position Infix Integer [Ident]-> | DataDecl Position Ident [Ident] [ConstrDecl]-> | NewtypeDecl Position Ident [Ident] NewConstrDecl-> | TypeDecl Position Ident [Ident] TypeExpr-> | TypeSig Position [Ident] TypeExpr-> | EvalAnnot Position [Ident] EvalAnnotation-> | FunctionDecl Position Ident [Equation]-> | ExternalDecl Position CallConv (Maybe String) Ident TypeExpr-> | FlatExternalDecl Position [Ident]-> | PatternDecl Position ConstrTerm Rhs-> | ExtraVariables Position [Ident]-> deriving (Eq,Show,Read,Typeable,Data)--> data ConstrDecl =-> ConstrDecl Position [Ident] Ident [TypeExpr]-> | ConOpDecl Position [Ident] TypeExpr Ident TypeExpr-> deriving (Eq,Show,Read,Typeable,Data)-> data NewConstrDecl =-> NewConstrDecl Position [Ident] Ident TypeExpr-> deriving (Eq,Show,Read,Typeable,Data)--> type Qualified = Bool-> data Infix = InfixL | InfixR | Infix deriving (Eq,Show,Read,Typeable,Data)-> data EvalAnnotation = EvalRigid | EvalChoice deriving (Eq,Show,Read,Typeable,Data)-> data CallConv = CallConvPrimitive | CallConvCCall deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}-\paragraph{Module interfaces}-Interface declarations are restricted to type declarations and signatures. -Note that an interface function declaration additionaly contains the -function arity (= number of parameters) in order to generate-correct FlatCurry function applications.-\begin{verbatim}--> data Interface = Interface ModuleIdent [IDecl] deriving (Eq,Show,Read,Typeable,Data)--> data IDecl =-> IImportDecl Position ModuleIdent-> | IInfixDecl Position Infix Integer QualIdent-> | HidingDataDecl Position Ident [Ident] -> | IDataDecl Position QualIdent [Ident] [Maybe ConstrDecl]-> | INewtypeDecl Position QualIdent [Ident] NewConstrDecl-> | ITypeDecl Position QualIdent [Ident] TypeExpr-> | IFunctionDecl Position QualIdent Int TypeExpr-> deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}-\paragraph{Types}-\begin{verbatim}--> data TypeExpr =-> ConstructorType QualIdent [TypeExpr]-> | VariableType Ident-> | TupleType [TypeExpr]-> | ListType TypeExpr-> | ArrowType TypeExpr TypeExpr-> | RecordType [([Ident],TypeExpr)] (Maybe TypeExpr) -> -- {l1 :: t1,...,ln :: tn | r}-> deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}-\paragraph{Functions}-\begin{verbatim}--> data Equation = Equation Position Lhs Rhs deriving (Eq,Show,Read,Typeable,Data)-> data Lhs =-> FunLhs Ident [ConstrTerm]-> | OpLhs ConstrTerm Ident ConstrTerm-> | ApLhs Lhs [ConstrTerm]-> deriving (Eq,Show,Read,Typeable,Data)-> data Rhs =-> SimpleRhs Position Expression [Decl]-> | GuardedRhs [CondExpr] [Decl]-> deriving (Eq,Show,Read,Typeable,Data)-> data CondExpr = CondExpr Position Expression Expression deriving (Eq,Show,Read,Typeable,Data)--> flatLhs :: Lhs -> (Ident,[ConstrTerm])-> flatLhs lhs = flat lhs []-> where flat (FunLhs f ts) ts' = (f,ts ++ ts')-> flat (OpLhs t1 op t2) ts = (op,t1:t2:ts)-> flat (ApLhs lhs ts) ts' = flat lhs (ts ++ ts')--\end{verbatim}-\paragraph{Literals} The \texttt{Ident} argument of an \texttt{Int}-literal is used for supporting ad-hoc polymorphism on integer-numbers. An integer literal can be used either as an integer number or-as a floating-point number depending on its context. The compiler uses-the identifier of the \texttt{Int} literal for maintaining its type.-\begin{verbatim}--> data Literal =-> Char SrcRef Char -- should be Int to handle Unicode-> | Int Ident Integer-> | Float SrcRef Double-> | String SrcRef String -- should be [Int] to handle Unicode-> deriving (Eq,Show,Read,Typeable,Data)--> mk' :: ([SrcRef] -> a) -> a-> mk' = ($[])--> mk :: (SrcRef -> a) -> a-> mk = ($noRef)--> mkInt :: Integer -> Literal-> mkInt i = mk (\r -> Int (addPositionIdent (AST r) anonId) i) --\end{verbatim}-\paragraph{Patterns}-\begin{verbatim}--> data ConstrTerm =-> LiteralPattern Literal-> | NegativePattern Ident Literal-> | VariablePattern Ident-> | ConstructorPattern QualIdent [ConstrTerm]-> | InfixPattern ConstrTerm QualIdent ConstrTerm-> | ParenPattern ConstrTerm-> | TuplePattern SrcRef [ConstrTerm]-> | ListPattern [SrcRef] [ConstrTerm]-> | AsPattern Ident ConstrTerm-> | LazyPattern SrcRef ConstrTerm-> | FunctionPattern QualIdent [ConstrTerm]-> | InfixFuncPattern ConstrTerm QualIdent ConstrTerm-> | RecordPattern [Field ConstrTerm] (Maybe ConstrTerm) -> -- {l1 = p1, ..., ln = pn} oder {l1 = p1, ..., ln = pn | p}-> deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}-\paragraph{Expressions}-\begin{verbatim}--> data Expression =-> Literal Literal-> | Variable QualIdent-> | Constructor QualIdent-> | Paren Expression-> | Typed Expression TypeExpr-> | Tuple SrcRef [Expression]-> | List [SrcRef] [Expression]-> | ListCompr SrcRef Expression [Statement] -- the ref corresponds to the main list -> | EnumFrom Expression-> | EnumFromThen Expression Expression-> | EnumFromTo Expression Expression-> | EnumFromThenTo Expression Expression Expression-> | UnaryMinus Ident Expression-> | Apply Expression Expression-> | InfixApply Expression InfixOp Expression-> | LeftSection Expression InfixOp-> | RightSection InfixOp Expression-> | Lambda SrcRef [ConstrTerm] Expression-> | Let [Decl] Expression-> | Do [Statement] Expression-> | IfThenElse SrcRef Expression Expression Expression-> | Case SrcRef Expression [Alt]-> | RecordConstr [Field Expression] -- {l1 = e1,...,ln = en}-> | RecordSelection Expression Ident -- e -> l-> | RecordUpdate [Field Expression] Expression -- {l1 := e1,...,ln := en | e}-> deriving (Eq,Show,Read,Typeable,Data)--> data InfixOp = InfixOp QualIdent | InfixConstr QualIdent deriving (Eq,Show,Read,Typeable,Data)--> data Statement =-> StmtExpr SrcRef Expression-> | StmtDecl [Decl]-> | StmtBind SrcRef ConstrTerm Expression-> deriving (Eq,Show,Read,Typeable,Data)--> data Alt = Alt Position ConstrTerm Rhs deriving (Eq,Show,Read,Typeable,Data)--> data Field a = Field Position Ident a deriving (Eq, Show,Read,Typeable,Data)--> fieldLabel :: Field a -> Ident-> fieldLabel (Field _ l _) = l--> fieldTerm :: Field a -> a-> fieldTerm (Field _ _ t) = t--> field2Tuple :: Field a -> (Ident,a)-> field2Tuple (Field _ l t) = (l,t)--> opName :: InfixOp -> QualIdent-> opName (InfixOp op) = op-> opName (InfixConstr c) = c--\end{verbatim}-\paragraph{Goals}-A goal is equivalent to an unconditional right hand side of an equation.-\begin{verbatim}--> data Goal = Goal Position Expression [Decl] deriving (Eq,Show,Read,Typeable,Data)--\end{verbatim}--> instance SrcRefOf ConstrTerm where-> srcRefOf (LiteralPattern l) = srcRefOf l-> srcRefOf (NegativePattern i _) = srcRefOf i-> srcRefOf (VariablePattern i) = srcRefOf i-> srcRefOf (ConstructorPattern i _) = srcRefOf i-> srcRefOf (InfixPattern _ i _) = srcRefOf i-> srcRefOf (ParenPattern c) = srcRefOf c-> srcRefOf (TuplePattern s _) = s-> srcRefOf (ListPattern s _) = error "list pattern has several source refs"-> srcRefOf (AsPattern i _) = srcRefOf i-> srcRefOf (LazyPattern s _) = s-> srcRefOf (FunctionPattern i _) = srcRefOf i-> srcRefOf (InfixFuncPattern _ i _) = srcRefOf i--> instance SrcRefOf CurrySyntax.Literal where-> srcRefOf (Char s _) = s-> srcRefOf (Int i _) = srcRefOf i-> srcRefOf (Float s _) = s-> srcRefOf (String s _) = s-------------------------------- add source references------------------------------> type M a = a -> State Int a-> -> addSrcRefs :: Module -> Module-> addSrcRefs x = evalState (addRef x) 0-> where -> addRef :: Data a' => M a' -> addRef = down `extM` addRefPos -> `extM` addRefSrc -> `extM` addRefIdent-> `extM` addRefListPat-> `extM` addRefListExp-> where-> down :: Data a' => M a'-> down = gmapM addRef-> -> addRefPos :: M [SrcRef]-> addRefPos _ = liftM (:[]) next-> -> addRefSrc :: M SrcRef-> addRefSrc _ = next-> -> addRefIdent :: M Ident-> addRefIdent ident = liftM (flip addRefId ident) next->-> addRefListPat :: M ConstrTerm-> addRefListPat (ListPattern _ ts) = do-> liftM (uncurry ListPattern) (addRefList ts)-> addRefListPat ct = gmapM addRef ct-> -> addRefListExp :: M Expression-> addRefListExp (List _ ts) = do-> liftM (uncurry List) (addRefList ts)-> addRefListExp ct = gmapM addRef ct-> -> addRefList :: Data a' => [a'] -> State Int ([SrcRef],[a'])-> addRefList ts = do-> i <- next-> let add t = do t' <- addRef t;j <- next; return (j,t')-> ists <- sequence (map add ts)-> let (is,ts') = unzip ists-> return (i:is,ts')-> -> current,next :: State Int SrcRef-> current = liftM (SrcRef . (:[])) get->-> next = do-> i <- get-> put $! i+1-> return (SrcRef [i])
src/Desugar.lhs view
@@ -1,4 +1,3 @@- % $Id: Desugar.lhs,v 1.42 2004/02/15 22:10:32 wlux Exp $ % % Copyright (c) 2001-2004, Wolfgang Lux@@ -60,19 +59,25 @@ all names must be properly qualified before calling this module.} \begin{verbatim} -> module Desugar(desugar,desugarGoal) where+> module Desugar(desugar) where > import Data.Maybe-> import Control.Monad+> import Control.Arrow(second)+> import Control.Monad.State as S > import Data.List +> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax.Utils+> import Curry.Syntax++> import Types > import Base-> import Combined > import Typing > import Utils-> import Ident + posE = undefined \end{verbatim}@@ -84,10 +89,10 @@ variables. \begin{verbatim} -> type DesugarState a = StateT ValueEnv (St Int) a+> type DesugarState a = S.StateT ValueEnv (S.State Int) a > run :: DesugarState a -> ValueEnv -> a-> run m tyEnv = runSt (callSt m tyEnv) 1+> run m tyEnv = S.evalState (S.evalStateT m tyEnv) 1 \end{verbatim} The desugaring phase keeps only the type, function, and value@@ -115,90 +120,12 @@ > dss <- mapM (desugarRecordDecl m tcEnv) ds > let ds' = concat dss > ds'' <- desugarDeclGroup m tcEnv ds'-> tyEnv' <- fetchSt+> tyEnv' <- S.get > return (filter isTypeDecl ds' ++ ds'', tyEnv') \end{verbatim}-While a goal of type \texttt{IO \_} is executed directly by the-runtime system, all other goals are evaluated under an interactive-top-level which displays the solutions of the goal and in particular-the bindings of the free variables. For this reason, the free-variables declared in the \texttt{where} clause of a goal are-translated into free variables of the goal. In addition, the goal-is transformed into a first order expression by performing a-unification with another variable. Thus, a goal-\begin{quote}- \emph{expr}- \texttt{where} $v_1$,\dots,$v_n$ \texttt{free}; \emph{decls}-\end{quote}-where no free variable declarations occur in \emph{decls} is-translated into the function-\begin{quote}- \emph{f} $v_0$ $v_1$ \dots{} $v_n$ \texttt{=}- $v_0$ \texttt{=:=} \emph{expr}- \texttt{where} \emph{decls}-\end{quote}-where $v_0$ is a fresh variable. -\textbf{Note:} The debugger assumes that the goal is always a nullary-function. This means that we must not $\eta$-expand functional goal-expressions. In order to avoid the $\eta$-expansion we cheat a little-bit here and change the type of the goal into $\forall\alpha.\alpha$-if it really has a functional type. -\ToDo{Fix the debugger to handle functional goals so that this-hack is no longer needed.}-\begin{verbatim}--> desugarGoal :: Bool -> ValueEnv -> TCEnv -> ModuleIdent -> Ident -> Goal-> -> (Maybe [Ident],Module,ValueEnv)-> desugarGoal debug tyEnv tcEnv m g (Goal p e ds)-> | debug || isIO ty =-> desugarGoalIO tyEnv tcEnv p m g (Let ds e)-> (if debug && arrowArity ty > 0 then typeVar 0 else ty)-> | otherwise = desugarGoal' tyEnv tcEnv p m g vs e' ty-> where ty = typeOf tyEnv e-> (vs,e') = liftGoalVars (if null ds then e else Let ds e)-> isIO (TypeConstructor tc [_]) = tc == qIOId-> isIO _ = False--> desugarGoalIO :: ValueEnv -> TCEnv -> Position -> ModuleIdent -> Ident-> -> Expression -> Type -> (Maybe [Ident],Module,ValueEnv)-> desugarGoalIO tyEnv tcEnv p m g e ty =-> (Nothing,-> Module m Nothing [goalDecl p g [] e'],-> bindFun m g (polyType ty) tyEnv')-> where (e',tyEnv') = run (desugarGoalExpr m tcEnv e) tyEnv--> desugarGoal' :: ValueEnv -> TCEnv -> Position -> ModuleIdent -> Ident -> [Ident]-> -> Expression -> Type -> (Maybe [Ident],Module,ValueEnv)-> desugarGoal' tyEnv tcEnv p m g vs e ty =-> (Just vs',-> Module m Nothing [goalDecl p g (v0:vs') (apply prelUnif [mkVar v0,e'])],-> bindFun m v0 (monoType ty) (bindFun m g (polyType ty') tyEnv'))-> where (e',tyEnv') = run (desugarGoalExpr m tcEnv e) tyEnv-> v0 = anonId-> vs' = filter (`elem` qfv m e') vs-> ty' = TypeArrow ty (foldr (TypeArrow . typeOf tyEnv) successType vs')--> goalDecl :: Position -> Ident -> [Ident] -> Expression -> Decl-> goalDecl p g vs e = funDecl p g (map VariablePattern vs) e--> desugarGoalExpr :: ModuleIdent -> TCEnv -> Expression-> -> DesugarState (Expression,ValueEnv)-> desugarGoalExpr m tcEnv e =-> do-> e' <- desugarExpr m tcEnv (first "") e-> tyEnv' <- fetchSt-> return (e',tyEnv')--> liftGoalVars :: Expression -> ([Ident],Expression)-> liftGoalVars (Let ds e) =-> (concat [vs | ExtraVariables _ vs <- vds],Let ds' e)-> where (vds,ds') = partition isExtraVariables ds-> liftGoalVars e = ([],e)--\end{verbatim} Within a declaration group, all type signatures and evaluation annotations are discarded. First, the patterns occurring in the left hand sides are desugared. Due to lazy patterns this may add further@@ -219,7 +146,7 @@ > return (PatternDecl p t' rhs : concat dss') > desugarDeclLhs m tcEnv (FlatExternalDecl p fs) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > return (map (externalDecl tyEnv p) fs) > where externalDecl tyEnv p f = > ExternalDecl p CallConvPrimitive (Just (name f)) f@@ -243,7 +170,7 @@ > desugarDeclRhs :: ModuleIdent -> TCEnv -> Decl -> DesugarState Decl > desugarDeclRhs m tcEnv (FunctionDecl p f eqs) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > let ty = (flip typeOf (Variable (qual f))) tyEnv > liftM (FunctionDecl p f) > (mapM (desugarEquation m tcEnv (arrowArgs ty)) eqs)@@ -278,7 +205,7 @@ > desugarLiteral :: Literal -> DesugarState (Either Literal ([SrcRef],[Literal])) > desugarLiteral (Char p c) = return (Left (Char p c))-> desugarLiteral (Int v i) = liftM (Left . fixType) fetchSt+> desugarLiteral (Int v i) = liftM (Left . fixType) S.get > where > fixType tyEnv > | typeOf tyEnv v == floatType @@ -312,12 +239,12 @@ > desugarTerm _ _ _ ds (VariablePattern v) = return (ds,VariablePattern v) > desugarTerm m tcEnv p ds (ConstructorPattern c [t]) = > do-> tyEnv <- fetchSt-> liftM (if isNewtypeConstr tyEnv c then id else apSnd (constrPat c))+> tyEnv <- S.get+> liftM (if isNewtypeConstr tyEnv c then id else second (constrPat c)) > (desugarTerm m tcEnv p ds t) > where constrPat c t = ConstructorPattern c [t] > desugarTerm m tcEnv p ds (ConstructorPattern c ts) =-> liftM (apSnd (ConstructorPattern c)) (mapAccumM (desugarTerm m tcEnv p) ds ts)+> liftM (second (ConstructorPattern c)) (mapAccumM (desugarTerm m tcEnv p) ds ts) > desugarTerm m tcEnv p ds (InfixPattern t1 op t2) = > desugarTerm m tcEnv p ds (ConstructorPattern op [t1,t2]) > desugarTerm m tcEnv p ds (ParenPattern t) = desugarTerm m tcEnv p ds t@@ -326,7 +253,7 @@ > where tupleConstr ts = addRef pos $ > if null ts then qUnitId else qTupleId (length ts) > desugarTerm m tcEnv p ds (ListPattern pos ts) =-> liftM (apSnd (desugarList pos cons nil)) (mapAccumM (desugarTerm m tcEnv p) ds ts)+> liftM (second (desugarList pos cons nil)) (mapAccumM (desugarTerm m tcEnv p) ds ts) > where nil p' = ConstructorPattern (addRef p' qNilId) [] > cons p' t ts = ConstructorPattern (addRef p' qConsId) [t,ts] @@ -334,13 +261,13 @@ > liftM (desugarAs p v) (desugarTerm m tcEnv p ds t) > desugarTerm m tcEnv p ds (LazyPattern pos t) = desugarLazy pos m p ds t > desugarTerm m tcEnv p ds (FunctionPattern f ts) =-> liftM (apSnd (FunctionPattern f)) (mapAccumM (desugarTerm m tcEnv p) ds ts)+> liftM (second (FunctionPattern f)) (mapAccumM (desugarTerm m tcEnv p) ds ts) > desugarTerm m tcEnv p ds (InfixFuncPattern t1 f t2) = > desugarTerm m tcEnv p ds (FunctionPattern f [t1,t2]) > desugarTerm m tcEnv p ds (RecordPattern fs _) > | null fs = internalError "desugarTerm: empty record" > | otherwise =-> do tyEnv <- fetchSt +> do tyEnv <- S.get > case (lookupValue (fieldLabel (head fs)) tyEnv) of > [Label _ r _] -> > desugarRecordPattern m tcEnv p ds (map field2Tuple fs) r@@ -363,7 +290,7 @@ > LazyPattern pos t' -> desugarLazy pos m p ds t' > _ -> > do-> v0 <- fetchSt >>= freshIdent m "_#lazy" . monoType . flip typeOf t+> v0 <- S.get >>= freshIdent m "_#lazy" . monoType . flip typeOf t > let v' = addPositionIdent (AST pos) v0 > return (patDecl p{ast=pos} t (mkVar v') : ds,VariablePattern v') @@ -381,7 +308,7 @@ > desugarRhs :: ModuleIdent -> TCEnv -> Position -> Rhs -> DesugarState Rhs > desugarRhs m tcEnv p rhs = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > e' <- desugarExpr m tcEnv p (expandRhs tyEnv prelFailed rhs) > return (SimpleRhs p e' []) @@ -431,7 +358,7 @@ > liftM (apply prelEnumFromThenTo) (mapM (desugarExpr m tcEnv p) [e1,e2,e3]) > desugarExpr m tcEnv p (UnaryMinus op e) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > liftM (Apply (unaryMinus op (typeOf tyEnv e))) (desugarExpr m tcEnv p e) > where unaryMinus op ty > | op == minusId =@@ -440,7 +367,7 @@ > | otherwise = internalError "unaryMinus" > desugarExpr m tcEnv p (Apply (Constructor c) e) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > liftM (if isNewtypeConstr tyEnv c then id else (Apply (Constructor c))) > (desugarExpr m tcEnv p e) > desugarExpr m tcEnv p (Apply e1 e2) =@@ -466,7 +393,7 @@ > return (Apply (Apply prelFlip op') e') > desugarExpr m tcEnv p exp@(Lambda r ts e) = > do-> f <- fetchSt >>=+> f <- S.get >>= > freshIdent m "_#lambda" . polyType . flip typeOf exp > desugarExpr m tcEnv p (Let [funDecl (AST r) f ts e] (mkVar f)) > desugarExpr m tcEnv p (Let ds e) =@@ -490,9 +417,9 @@ > | otherwise = > do > e' <- desugarExpr m tcEnv p e-> v <- fetchSt >>= freshIdent m "_#case" . monoType . flip typeOf e+> v <- S.get >>= freshIdent m "_#case" . monoType . flip typeOf e > alts' <- mapM (desugarAltLhs m tcEnv) alts-> tyEnv <- fetchSt+> tyEnv <- S.get > alts'' <- mapM (desugarAltRhs m tcEnv) > (map (expandAlt tyEnv v) (init (tails alts'))) > return (mkCase m v e' alts'')@@ -504,12 +431,12 @@ > | otherwise = > do let l = fieldLabel (head fs) > fs' = map field2Tuple fs-> tyEnv <- fetchSt+> tyEnv <- S.get > case (lookupValue l tyEnv) of > [Label l' r _] -> desugarRecordConstr m tcEnv p r fs' > _ -> internalError "desugarExpr: illegal record construction" > desugarExpr m tcEnv p (RecordSelection e l) =-> do tyEnv <- fetchSt+> do tyEnv <- S.get > case (lookupValue l tyEnv) of > [Label _ r _] -> desugarRecordSelection m tcEnv p r l e > _ -> internalError "desugarExpr: illegal record selection"@@ -518,7 +445,7 @@ > | otherwise = > do let l = fieldLabel (head fs) > fs' = map field2Tuple fs-> tyEnv <- fetchSt+> tyEnv <- S.get > case (lookupValue l tyEnv) of > [Label _ r _] -> desugarRecordUpdate m tcEnv p r rexpr fs' > _ -> internalError "desugarExpr: illegal record update"@@ -582,14 +509,14 @@ > desugarRecordDecl m tcEnv (TypeDecl p r vs (RecordType fss _)) = > case (qualLookupTC r' tcEnv) of > [AliasType _ n (TypeRecord fs' _)] ->-> do tyEnv <- fetchSt+> do tyEnv <- S.get > let tys = concatMap (\ (ls,ty) -> replicate (length ls) ty) fss > --tys' = map (elimRecordTypes tyEnv) tys > rdecl = DataDecl p r vs [ConstrDecl p [] r tys] > rty' = TypeConstructor r' (map TypeVariable [0 .. n-1]) > rcts' = ForAllExist 0 n (foldr TypeArrow rty' (map snd fs')) > rfuncs <- mapM (genRecordFuncs m tcEnv p r' rty' (map fst fs')) fs'-> updateSt_ (bindGlobalInfo DataConstructor m r rcts')+> S.modify (bindGlobalInfo DataConstructor m r rcts') > return (rdecl:(concat rfuncs)) > _ -> internalError "desugarRecordDecl: no record" > where r' = qualifyWith m r@@ -637,7 +564,7 @@ > elimFunctionPattern m p [] = return ([],[]) > elimFunctionPattern m p (t:ts) > | containsFunctionPattern t-> = do tyEnv <- fetchSt+> = do tyEnv <- S.get > ident <- freshIdent m "_#funpatt" (monoType (typeOf tyEnv t)) > (ts',its') <- elimFunctionPattern m p ts > return ((VariablePattern ident):ts', (ident,t):its')@@ -734,7 +661,7 @@ > (updId, updFunc) = genUpdateFunc m p r ls l > selType = polyType (TypeArrow rty ty) > updType = polyType (TypeArrow rty (TypeArrow ty rty))-> updateSt_ (bindFun m selId selType . bindFun m updId updType)+> S.modify (bindFun m selId selType . bindFun m updId updType) > return [selFunc,updFunc] > _ -> internalError "genRecordFuncs: wrong type" @@ -805,7 +732,7 @@ > | isVarPattern t = desugarExpr m tcEnv p (qualExpr t e l) > | otherwise = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > v0 <- freshIdent m "_#var" (monoType (typeOf tyEnv t)) > l0 <- freshIdent m "_#var" (monoType (typeOf tyEnv e)) > let v = addRefId refBind v0@@ -835,8 +762,8 @@ > freshIdent :: ModuleIdent -> String -> TypeScheme -> DesugarState Ident > freshIdent m prefix ty = > do-> x <- liftM (mkName prefix) (liftSt (updateSt (1 +)))-> updateSt_ (bindFun m x ty)+> x <- liftM (mkName prefix) (S.lift (S.modify succ >> S.get))+> S.modify (bindFun m x ty) > return x > where mkName pre n = mkIdent (pre ++ show n) @@ -844,7 +771,6 @@ Prelude entities \begin{verbatim} -> prelUnif = Variable $ preludeIdent "=:=" > prelBind = prel ">>=" > prelBind_ = prel ">>" > prelFlip = Variable $ preludeIdent "flip"@@ -867,7 +793,7 @@ > truePattern = ConstructorPattern qTrueId [] > falsePattern = ConstructorPattern qFalseId []-> successPattern = ConstructorPattern (qualify successId) []+ > preludeIdent :: String -> QualIdent > preludeIdent = qualifyWith preludeMIdent . mkIdent
− src/Env.lhs
@@ -1,55 +0,0 @@-% -*- LaTeX -*--% $Id: Env.lhs,v 1.9 2002/12/20 15:07:56 lux Exp $-%-% Copyright (c) 2002, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{Env.lhs}-\section{Environments}-The module \texttt{Env} implements environments. An environment-$\rho = \left\{x_1\mapsto t_1,\dots,x_n\mapsto t_n\right\}$ is a-finite mapping from (finitely many) variables $x_1,\dots,x_n$ to-some kind of expression or term. For any environment we have the-following definitions:-\begin{displaymath}- \begin{array}{l}- \rho(x) = \left\{\begin{array}{ll}- t_i&\mbox{if $x=x_i$}\\- \bot&\mbox{otherwise}\end{array}\right. \\- \mathop{{\mathcal D}om}(\rho) = \left\{x_1,\dots,x_n\right\} \\- \mathop{{\mathcal C}odom}(\rho) = \left\{t_1,\dots,t_n\right\}- \end{array}-\end{displaymath}--Unfortunately we cannot define \texttt{Env} as a \texttt{newtype}-because of a bug in the nhc compiler.-\begin{verbatim}--> module Env where--> import qualified Data.Map as Map--> newtype Env a b = Env (Map.Map a b) deriving Show--> emptyEnv :: Ord a => Env a b-> emptyEnv = Env Map.empty--> envToList :: Ord v => Env v e -> [(v,e)]-> envToList (Env rho) = Map.toList rho--> bindEnv :: Ord v => v -> e -> Env v e -> Env v e-> bindEnv v e (Env rho) = Env (Map.insert v e rho)--> unbindEnv :: Ord v => v -> Env v e -> Env v e-> unbindEnv v (Env rho) = Env (Map.delete v rho)--> lookupEnv :: Ord v => v -> Env v e -> Maybe e-> lookupEnv v (Env rho) = Map.lookup v rho--> envSize :: Ord v => Env v e -> Int-> envSize (Env rho) = Map.size rho--> instance Ord a => Functor (Env a) where-> fmap f (Env rho) = Env (fmap f rho)--\end{verbatim}
− src/Error.lhs
@@ -1,35 +0,0 @@-% -*- LaTeX -*--% $Id: Error.lhs,v 1.1 2003/05/07 22:38:42 wlux Exp $-%-% Copyright (c) 2003, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{Error.lhs}-\section{Errors}\label{sec:error}-The \texttt{Error} type is used for describing the result of a-computation that can fail. In contrast to the standard \texttt{Maybe}-type, its \texttt{Error} case provides for an error message that-describes the failure.-\begin{verbatim}--> module Error where-> import Control.Monad--> data Error a = Ok a | Error String deriving (Eq,Ord,Show)--> instance Functor Error where-> fmap f (Ok x) = Ok (f x)-> fmap f (Error e) = Error e--> instance Monad Error where-> return x = Ok x-> fail s = Error s-> Ok x >>= f = f x-> Error e >>= _ = Error e--> ok :: Error a -> a-> ok (Ok x) = x-> ok (Error e) = error e---\end{verbatim}
src/Eval.lhs view
@@ -11,24 +11,24 @@ happens already while checking the definitions of the module. \begin{verbatim} -> module Eval(evalEnv,evalEnvGoal) where+> module Eval(evalEnv) where++> import qualified Data.Map as Map++> import Curry.Syntax > import Base-> import Env + \end{verbatim} The function \texttt{evalEnv} collects all evaluation annotations of the module by traversing the syntax tree. \begin{verbatim} > evalEnv :: [Decl] -> EvalEnv-> evalEnv = foldr collectAnnotsDecl emptyEnv--> evalEnvGoal :: Goal -> EvalEnv-> evalEnvGoal (Goal _ e ds) =-> collectAnnotsExpr e (foldr collectAnnotsDecl emptyEnv ds)+> evalEnv = foldr collectAnnotsDecl Map.empty > collectAnnotsDecl :: Decl -> EvalEnv -> EvalEnv-> collectAnnotsDecl (EvalAnnot _ fs ev) env = foldr (flip bindEval ev) env fs+> collectAnnotsDecl (EvalAnnot _ fs ev) env = foldr (flip Map.insert ev) env fs > collectAnnotsDecl (FunctionDecl _ _ eqs) env = foldr collectAnnotsEqn env eqs > collectAnnotsDecl (PatternDecl _ _ rhs) env = collectAnnotsRhs rhs env > collectAnnotsDecl _ env = env
src/Exports.lhs view
@@ -19,6 +19,10 @@ > import qualified Data.Set as Set > import qualified Data.Map as Map +> import Curry.Syntax+> import Types+> import Curry.Base.Position+> import Curry.Base.Ident > import Base > import TopEnv @@ -40,7 +44,7 @@ > Linear -> > case linear ([c | ExportTypeWith _ cs <- es', c <- cs] ++ > [unqualify f | Export f <- es']) of-> Linear -> Module m (Just (Exporting noPos es')) ds+> Linear -> Module m (Just (Exporting NoPos es')) ds > NonLinear v -> errorAt' (ambiguousExportValue v) > NonLinear tc -> errorAt' (ambiguousExportType tc) > where ms = Set.fromList [fromMaybe m asM | ImportDecl _ m _ asM _ <- ds]@@ -197,7 +201,7 @@ > exportInterface :: Module -> PEnv -> TCEnv -> ValueEnv -> Interface > exportInterface (Module m (Just (Exporting _ es)) _) pEnv tcEnv tyEnv = > Interface m (imports ++ precs ++ hidden ++ ds)-> where imports = map (IImportDecl noPos) (usedModules ds)+> where imports = map (IImportDecl NoPos) (usedModules ds) > precs = foldr (infixDecl m pEnv) [] es > hidden = map (hiddenTypeDecl m tcEnv) (hiddenTypes ds) > ds = foldr (typeDecl m tcEnv) (foldr (funDecl m tyEnv) [] es) es@@ -206,7 +210,7 @@ > infixDecl :: ModuleIdent -> PEnv -> Export -> [IDecl] -> [IDecl] > infixDecl m pEnv (Export f) ds = iInfixDecl m pEnv f ds > infixDecl m pEnv (ExportTypeWith tc cs) ds =-> foldr (iInfixDecl m pEnv . qualifyLike (fst (splitQualIdent tc))) ds cs+> foldr (iInfixDecl m pEnv . qualifyLike (qualidMod tc)) ds cs > where qualifyLike = maybe qualify qualifyWith > iInfixDecl :: ModuleIdent -> PEnv -> QualIdent -> [IDecl] -> [IDecl]@@ -214,7 +218,7 @@ > case qualLookupP op pEnv of > [] -> ds > [PrecInfo _ (OpPrec fix pr)] ->-> IInfixDecl noPos fix pr (qualUnqualify m op) : ds+> IInfixDecl NoPos fix pr (qualUnqualify m op) : ds > _ -> internalError "infixDecl" > typeDecl :: ModuleIdent -> TCEnv -> Export -> [IDecl] -> [IDecl]@@ -226,7 +230,7 @@ > (constrDecls m (drop n nameSupply) cs cs') : ds > [RenamingType tc n (Data c n' ty)] > | c `elem` cs ->-> iTypeDecl INewtypeDecl m tc n (NewConstrDecl noPos tvs c ty') : ds+> iTypeDecl INewtypeDecl m tc n (NewConstrDecl NoPos tvs c ty') : ds > | otherwise -> iTypeDecl IDataDecl m tc n [] : ds > where tvs = take n' (drop n nameSupply) > ty' = fromQualType m ty@@ -240,7 +244,7 @@ > iTypeDecl :: (Position -> QualIdent -> [Ident] -> a -> IDecl) > -> ModuleIdent -> QualIdent -> Int -> a -> IDecl-> iTypeDecl f m tc n = f noPos (qualUnqualify m tc) (take n nameSupply)+> iTypeDecl f m tc n = f NoPos (qualUnqualify m tc) (take n nameSupply) > constrDecls :: ModuleIdent -> [Ident] -> [Ident] -> [Maybe (Data [Type])] > -> [Maybe ConstrDecl]@@ -253,14 +257,14 @@ > iConstrDecl :: [Ident] -> Ident -> [TypeExpr] -> ConstrDecl > iConstrDecl tvs op [ty1,ty2]-> | isInfixOp op = ConOpDecl noPos tvs ty1 op ty2-> iConstrDecl tvs c tys = ConstrDecl noPos tvs c tys+> | isInfixOp op = ConOpDecl NoPos tvs ty1 op ty2+> iConstrDecl tvs c tys = ConstrDecl NoPos tvs c tys > funDecl :: ModuleIdent -> ValueEnv -> Export -> [IDecl] -> [IDecl] > funDecl m tyEnv (Export f) ds = > case qualLookupValue f tyEnv of > [Value _ (ForAll _ ty)] ->-> IFunctionDecl noPos (qualUnqualify m f) (arrowArity ty) +> IFunctionDecl NoPos (qualUnqualify m f) (arrowArity ty) > (fromQualType m ty) : ds > _ -> internalError ("funDecl: " ++ show f) > funDecl _ _ (ExportTypeWith _ _) ds = ds@@ -286,9 +290,8 @@ \begin{verbatim} > usedModules :: [IDecl] -> [ModuleIdent]-> usedModules ds = nub (catMaybes (map modul (foldr identsDecl [] ds)))+> usedModules ds = nub (catMaybes (map qualidMod (foldr identsDecl [] ds))) > where nub = Set.toList . Set.fromList-> modul = fst . splitQualIdent > identsDecl :: IDecl -> [QualIdent] -> [QualIdent] > identsDecl (IDataDecl _ tc _ cs) xs =@@ -329,7 +332,7 @@ > [RenamingType _ n _] -> hidingDataDecl tc n > _ -> internalError "hiddenTypeDecl" > where hidingDataDecl tc n =-> HidingDataDecl noPos (unqualify tc) (take n nameSupply)+> HidingDataDecl NoPos (unqualify tc) (take n nameSupply) > hiddenTypes :: [IDecl] -> [QualIdent] > hiddenTypes ds = [tc | tc <- Set.toList tcs, not (isQualified tc)]
− src/ExtendedFlat.hs
@@ -1,517 +0,0 @@----------------------------------------------------------------------------------- Library to support meta-programming in Curry.-------- This library contains a definition for representing FlatCurry programs---- in Haskell (type "Prog").-------- @author Michael Hanus---- @version September 2003-------- Version for Haskell (slightly modified):---- December 2004, Martin Engelke (men@informatik.uni-kiel.de)-------- Added part calls for constructors, Bernd Brassel, August 2005---- Added source references, Bernd Brassel, May 2009---------------------------------------------------------------------------------{-# LANGUAGE DeriveDataTypeable, RankNTypes #-}--module ExtendedFlat (SrcRef,Prog(..), QName(..), Visibility(..),- TVarIndex, TypeDecl(..), ConsDecl(..), TypeExpr(..),- OpDecl(..), Fixity(..),- VarIndex(..), - FuncDecl(..), Rule(..), - CaseType(..), CombType(..), Expr(..), BranchExpr(..),- Pattern(..), Literal(..), - readFlatCurry, readFlatInterface, readFlat, - writeFlatCurry,writeExtendedFlat,gshowsPrec,- qnOf,mkQName,- mkIdx,idxOf) where--import PathUtils (writeModule,maybeReadModule)-import Data.List(intersperse)-import Control.Monad (liftM)-import Data.Generics hiding (Fixity)-import Position (SrcRef)-import System.FilePath------------------------------------------------------------------------------------ Definition of data types for representing FlatCurry programs:--- =============================================================----- Data type for representing a Curry module in the intermediate form.---- A value of this data type has the form---- <CODE>---- (Prog modname imports typedecls functions opdecls translation_table)---- </CODE>---- where modname: name of this module,---- imports: list of modules names that are imported,---- typedecls, opdecls, functions, translation of type names---- and constructor/function names: see below--data Prog = Prog String [String] [TypeDecl] [FuncDecl] [OpDecl] - deriving (Read, Show, Eq,Data,Typeable)-------------------------------------------------------------------------------- The data type for representing qualified names.---- In FlatCurry all names are qualified to avoid name clashes.---- The first component is the module name and the second component the---- unqualified name as it occurs in the source program.---- The additional information about source references and types should---- be invisible for the normal usage of QName.----------------------------------------------------------------------------data QName = QName {srcRef :: Maybe SrcRef,- typeofQName :: Maybe TypeExpr,- modName :: String,- localName :: String} deriving (Data,Typeable)---app_prec = 10-hi_prec = app_prec+1--instance Read QName where- readsPrec d r = - [ (mkQName nm,s) | (nm,s) <- readsPrec d r ]- ++ readParen (d > app_prec) - (\r' -> [ (QName ref typ n m,res) - | ("QName",s0) <- lex r',- (ref,s1) <- readsPrec hi_prec s0,- (typ,s2) <- readsPrec hi_prec s1,- (n,s3) <- readsPrec hi_prec s2,- (m,res) <- readsPrec hi_prec s3 ]) r- --instance Show QName where- showsPrec d (QName r t m n)= - showParen (d > app_prec) $ showString "QName " .- showsPrec hi_prec r . showChar ' ' .- showsPrec hi_prec t . showChar ' ' .- showsPrec hi_prec m . showChar ' ' .- showsPrec hi_prec n--instance Eq QName where (==) = onName (==)-instance Ord QName where compare = onName compare--mkQName :: (String,String) -> QName-mkQName = uncurry (QName Nothing Nothing)--qnOf :: QName -> (String,String) -qnOf QName{modName=m,localName=n} = (m,n)--onName :: ((String,String) -> (String,String) -> a) -> QName -> QName -> a-onName f QName{modName=m,localName=l} QName{modName=m',localName=l'} =- f (m,l) (m',l')-------------------------------------------------------------------------------- The data type for representing variable names.---- The additional information should---- be invisible for the normal usage of VarIndex.----------------------------------------------------------------------------data VarIndex = VarIndex {- typeofVar :: Maybe TypeExpr,- index :: Int- } deriving (Data,Typeable)--onIndex :: (Int -> a) -> VarIndex -> a-onIndex f VarIndex{index=i} = f i--(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d-f .: g = \x -> f . g x--onIndexes :: (Int -> Int -> a) -> VarIndex -> VarIndex -> a-onIndexes = onIndex .: onIndex--mkIdx :: Int -> VarIndex-mkIdx = VarIndex Nothing--idxOf :: VarIndex -> Int-idxOf VarIndex{index=i}= i--instance Read VarIndex where- readsPrec d r = - [ (mkIdx i,s) | (i,s) <- readsPrec d r ]- ++ readParen (d > app_prec) - (\r' -> [ (VarIndex typ i,res) - | ("VarIndex",s0) <- lex r',- (typ,s1) <- readsPrec hi_prec s0,- (i,res) <- readsPrec hi_prec s1]) r- --instance Show VarIndex where- showsPrec d (VarIndex t i)= - showParen (d > app_prec) $ showString "VarIndex " .- showsPrec hi_prec t . showChar ' ' .- showsPrec hi_prec i---instance Eq VarIndex where (==) = onIndexes (==)-instance Ord VarIndex where compare = onIndexes compare--instance Num VarIndex where- (+) = mkIdx .: onIndexes (+)- (*) = mkIdx .: onIndexes (*)- (-) = mkIdx .: onIndexes (-)- abs = mkIdx . onIndex abs- signum = mkIdx . onIndex signum- fromInteger = mkIdx . fromInteger------------------------------------------------------------------ Data type to specify the visibility of various entities.---------------------------------------------------------------data Visibility = Public -- public (exported) entity- | Private -- private entity- deriving (Read, Show, Eq,Data,Typeable)----- The data type for representing type variables.---- They are represented by (TVar i) where i is a type variable index.--type TVarIndex = Int----- Data type for representing definitions of algebraic data types.---- <PRE>---- A data type definition of the form-------- data t x1...xn = ...| c t1....tkc |...-------- is represented by the FlatCurry term-------- (Type t [i1,...,in] [...(Cons c kc [t1,...,tkc])...])-------- where each ij is the index of the type variable xj-------- Note: the type variable indices are unique inside each type declaration---- and are usually numbered from 0-------- Thus, a data type declaration consists of the name of the data type,---- a list of type parameters and a list of constructor declarations.---- </PRE>--data TypeDecl = Type QName Visibility [TVarIndex] [ConsDecl]- | TypeSyn QName Visibility [TVarIndex] TypeExpr- deriving (Read, Show, Eq,Data,Typeable)----- A constructor declaration consists of the name and arity of the---- constructor and a list of the argument types of the constructor.--data ConsDecl = Cons QName Int Visibility [TypeExpr]- deriving (Read, Show, Eq,Data,Typeable)------ Data type for type expressions.---- A type expression is either a type variable, a function type,---- or a type constructor application.-------- Note: the names of the predefined type constructors are---- "Int", "Float", "Bool", "Char", "IO", "Success",---- "()" (unit type), "(,...,)" (tuple types), "[]" (list type)--data TypeExpr =- TVar TVarIndex -- type variable- | FuncType TypeExpr TypeExpr -- function type t1->t2- | TCons QName [TypeExpr] -- type constructor application- deriving (Read, Show, Eq,Data,Typeable) -- TCons module name typeargs------ Data type for operator declarations.---- An operator declaration "fix p n" in Curry corresponds to the---- FlatCurry term (Op n fix p).---- Note: the constructor definition of 'Op' differs from the original---- PAKCS definition using Haskell type 'Integer' instead of 'Int'---- for representing the precedence. --data OpDecl = Op QName Fixity Integer deriving (Read, Show, Eq,Data,Typeable)----- Data types for the different choices for the fixity of an operator.--data Fixity = InfixOp | InfixlOp | InfixrOp deriving (Read, Show, Eq,Data,Typeable)------ Data type for representing object variables.---- Object variables occurring in expressions are represented by (Var i)---- where i is a variable index.----- Data type for representing function declarations.---- <PRE>---- A function declaration in FlatCurry is a term of the form-------- (Func name arity type (Rule [i_1,...,i_arity] e))-------- and represents the function "name" with definition-------- name :: type---- name x_1...x_arity = e-------- where each i_j is the index of the variable x_j-------- Note: the variable indices are unique inside each function declaration---- and are usually numbered from 0-------- External functions are represented as (Func name arity type (External s))---- where s is the external name associated to this function.-------- Thus, a function declaration consists of the name, arity, type, and rule.---- </PRE>--data FuncDecl = Func QName Int Visibility TypeExpr Rule- deriving (Read, Show, Eq,Data,Typeable)------ A rule is either a list of formal parameters together with an expression---- or an "External" tag.--data Rule = Rule [VarIndex] Expr- | External String- deriving (Read, Show, Eq,Data,Typeable)----- Data type for classifying case expressions.---- Case expressions can be either flexible or rigid in Curry.--data CaseType = Rigid | Flex deriving (Read, Show, Eq,Data,Typeable)----- Data type for classifying combinations---- (i.e., a function/constructor applied to some arguments).---- @cons FuncCall - a call to a function all arguments are provided---- @cons ConsCall - a call with a constructor at the top,---- all arguments are provided---- @cons FuncPartCall - a partial call to a function---- (i.e., not all arguments are provided) ---- where the parameter is the number of---- missing arguments---- @cons ConsPartCall - a partial call to a constructor along with ---- number of missing arguments--data CombType = FuncCall - | ConsCall - | FuncPartCall Int - | ConsPartCall Int deriving (Read, Show, Eq,Data,Typeable)----- Data type for representing expressions.-------- Remarks:---- <PRE>---- 1. if-then-else expressions are represented as function calls:---- (if e1 then e2 else e3)---- is represented as---- (Comb FuncCall ("Prelude","if_then_else") [e1,e2,e3])---- ---- 2. Higher order applications are represented as calls to the (external)---- function "apply". For instance, the rule---- app f x = f x---- is represented as---- (Rule [0,1] (Comb FuncCall ("Prelude","apply") [Var 0, Var 1]))---- ---- 3. A conditional rule is represented as a call to an external function---- "cond" where the first argument is the condition (a constraint).---- For instance, the rule---- equal2 x | x=:=2 = success---- is represented as---- (Rule [0]---- (Comb FuncCall ("Prelude","cond")---- [Comb FuncCall ("Prelude","=:=") [Var 0, Lit (Intc 2)],---- Comb FuncCall ("Prelude","success") []]))---- ---- 4. Functions with evaluation annotation "choice" are represented---- by a rule whose right-hand side is enclosed in a call to the---- external function "Prelude.commit".---- Furthermore, all rules of the original definition must be---- represented by conditional expressions (i.e., (cond [c,e]))---- after pattern matching.---- Example:---- ---- m eval choice---- m [] y = y---- m x [] = x---- ---- is translated into (note that the conditional branches can be also---- wrapped with Free declarations in general):---- ---- Rule [0,1]---- (Comb FuncCall ("Prelude","commit")---- [Or (Case Rigid (Var 0)---- [(Pattern ("Prelude","[]") []---- (Comb FuncCall ("Prelude","cond")---- [Comb FuncCall ("Prelude","success") [],---- Var 1]))] )---- (Case Rigid (Var 1)---- [(Pattern ("Prelude","[]") []---- (Comb FuncCall ("Prelude","cond")---- [Comb FuncCall ("Prelude","success") [],---- Var 0]))] )])---- ---- Operational meaning of (Prelude.commit e):---- evaluate e with local search spaces and commit to the first---- (Comb FuncCall ("Prelude","cond") [c,ge]) in e whose constraint c---- is satisfied---- </PRE>---- @cons Var - variable (represented by unique index)---- @cons Lit - literal (Integer/Float/Char constant)---- @cons Comb - application (f e1 ... en) of function/constructor f---- with n<=arity(f)---- @cons Free - introduction of free local variables---- @cons Or - disjunction of two expressions (used to translate rules---- with overlapping left-hand sides)---- @cons Case - case distinction (rigid or flex)--data Expr = Var VarIndex - | Lit Literal- | Comb CombType QName [Expr]- | Free [VarIndex] Expr- | Let [(VarIndex,Expr)] Expr- | Or Expr Expr- | Case SrcRef CaseType Expr [BranchExpr]- deriving (Read, Show, Eq,Data,Typeable)------ Data type for representing branches in a case expression.---- <PRE>---- Branches "(m.c x1...xn) -> e" in case expressions are represented as-------- (Branch (Pattern (m,c) [i1,...,in]) e)-------- where each ij is the index of the pattern variable xj, or as-------- (Branch (LPattern (Intc i)) e)-------- for integers as branch patterns (similarly for other literals---- like float or character constants).---- </PRE>--data BranchExpr = Branch Pattern Expr deriving (Read, Show, Eq,Data,Typeable)----- Data type for representing patterns in case expressions.--data Pattern = Pattern QName [VarIndex]- | LPattern Literal- deriving (Read, Show, Eq,Data,Typeable)----- Data type for representing literals occurring in an expression---- or case branch. It is either an integer, a float, or a character constant.---- Note: the constructor definition of 'Intc' differs from the original---- PAKCS definition. It uses Haskell type 'Integer' instead of 'Int'---- to provide an unlimited range of integer numbers. Furthermore---- float values are represented with Haskell type 'Double' instead of---- 'Float'.--data Literal = Intc SrcRef Integer- | Floatc SrcRef Double- | Charc SrcRef Char- deriving (Read, Show, Eq,Data,Typeable)-------------------------------------------------------------------------------------------------------------------------------------------------------------------- Reads a FlatCurry file (extension ".fcy") and returns the corresponding--- FlatCurry program term (type 'Prog') as a value of type 'Maybe'.-readFlatCurry :: FilePath -> IO (Maybe Prog)-readFlatCurry fn - = do let filename = genFlatFilename ".fcy" fn- readFlat filename---- Reads a FlatInterface file (extension ".fint") and returns the--- corresponding term (type 'Prog') as a value of type 'Maybe'.-readFlatInterface :: String -> IO (Maybe Prog)-readFlatInterface fn- = do let filename = genFlatFilename ".fint" fn- readFlat filename---- Reads a Flat file and returns the corresponding term (type 'Prog') as--- a value of type 'Maybe'.-readFlat :: FilePath -> IO (Maybe Prog)-readFlat = liftM (fmap read) . maybeReadModule- --- Writes a FlatCurry program term into a file.-writeFlatCurry :: String -> Prog -> IO ()-writeFlatCurry filename prog- = writeModule filename (showFlatCurry' False prog)---- Writes a FlatCurry program term with source references into a file.-writeExtendedFlat :: String -> Prog -> IO ()-writeExtendedFlat filename prog =- writeModule (replaceExtension filename ".efc") (showFlatCurry' True prog)---- Shows FlatCurry program in a more nicely way.-showFlatCurry :: Prog -> String-showFlatCurry (Prog mname imps types funcs ops) =- "Prog "++show mname++"\n "++- show imps ++"\n ["++- concat (intersperse ",\n " (map (\t->show t) types)) ++"]\n ["++- concat (intersperse ",\n " (map (\f->show f) funcs)) ++"]\n "++- show ops ++"\n"- ---- Add the extension 'ext' to the filename 'fn' if it doesn't--- already exist.-genFlatFilename :: String -> FilePath -> FilePath-genFlatFilename ext fn- | drop (length fn - length ext) fn == ext- = fn- | otherwise- = fn ++ ext--showFlatCurry' :: Bool -> Prog -> String-showFlatCurry' b x = gshowsPrec b False x ""--gshowsPrec :: Data a => Bool -> Bool -> a -> ShowS-gshowsPrec showType d = - genericShowsPrec d `ext1Q` showsList- `ext2Q` showsTuple- `extQ` (const id :: SrcRef -> ShowS)- `extQ` (const id :: [SrcRef] -> ShowS)- `extQ` (shows :: String -> ShowS)- `extQ` (shows :: Char -> ShowS)- `extQ` showsQName d- `extQ` showsVarIndex d- - where- showsQName :: Bool -> QName -> ShowS- showsQName d qn@QName{modName=m,localName=n,typeofQName=t} = - if showType then showParen d (shows qn{srcRef=Nothing})- else shows (m,n)-- showsVarIndex :: Bool -> VarIndex -> ShowS- showsVarIndex d v@VarIndex{index=i} = - if showType then showParen d (shows v)- else shows i-- genericShowsPrec :: Data a => Bool -> a -> ShowS- genericShowsPrec d t = let args = intersperse (showChar ' ') $- gmapQ (gshowsPrec showType True) t in- showParen (d && not (null args)) $- showString (showConstr (toConstr t)) .- (if null args then id else showChar ' ') .- foldr (.) id args-- showsList :: Data a => [a] -> ShowS- showsList xs = showChar '[' . - foldr (.) (showChar ']') - (intersperse (showChar ',') $ - map (gshowsPrec showType False) xs)- -- showsTuple :: (Data a,Data b) => (a,b) -> ShowS- showsTuple (x,y) = showChar '(' . - gshowsPrec showType False x . - showChar ',' .- gshowsPrec showType False y .- showChar ')' ---newtype Q r a = Q (a -> r)- -ext2Q :: (Data d, Typeable2 t) => (d -> q) -> - (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q-ext2Q def ext arg =- case dataCast2 (Q ext) of- Just (Q ext') -> ext' arg- Nothing -> def arg----------------------------------------------------------------------------------------------------------------------------------------------------------------
src/Frontend.hs view
@@ -7,37 +7,27 @@ -- December 2005, -- Martin Engelke (men@informatik.uni-kiel.de) ---module Frontend (lex, parse, fullParse, typingParse, abstractIO, flatIO,- Result(..), Message(..)- )where+module Frontend (lex, parse, fullParse, typingParse)where -import Data.List import Data.Maybe-import Control.Monad+import qualified Data.Map as Map+import Control.Monad.Writer+import Control.Monad.Error import Prelude hiding (lex) import Modules import CurryBuilder import CurryCompilerOpts-import CurryParser-import CurryLexer-import GenAbstractCurry-import GenFlatCurry-import CaseCompletion-import CurryDeps hiding (unlitLiterate)-import qualified CurrySyntax as CS-import qualified AbstractCurry as ACY-import qualified ExtendedFlat as FCY-import qualified Error as Err-import CompilerResults-import Message-import CurryEnv-import Unlit-import Ident-import Position-import PathUtils-import Env+import Curry.Base.MessageMonad+import qualified Curry.Syntax as CS+import Curry.Syntax.Lexer +import CurryDeps+import Curry.Base.Ident+import Curry.Base.Position+import Filenames+import PathUtils+import Base(ModuleEnv) ------------------------------------------------------------------------------- -------------------------------------------------------------------------------@@ -45,18 +35,15 @@ -- Returns the result of a lexical analysis of the source program 'src'. -- The result is a list of tuples consisting of a position and a token -- (see Modules "Position" and "CurryLexer")-lex :: FilePath -> String -> Result [(Position,Token)]-lex fn src = genToks (lexFile (first fn) src False [])+lex :: FilePath -> String -> MsgMonad [(Position,Token)]+lex fn src = lexFile (first fn) src False [] -- Returns the result of a syntactical analysis of the source program 'src'. -- The result is the syntax tree of the program (type 'Module'; see Module -- "CurrySyntax").-parse :: FilePath -> String -> Result CS.Module-parse fn src = let (err, src') = unlitLiterate fn src- in if null err- then genCurrySyntax fn (parseSource True fn src')- else Failure [message_ Error err]+parse :: FilePath -> String -> MsgMonad CS.Module+parse fn src = CS.parseModule True fn src >>= genCurrySyntax fn -- Returns the syntax tree of the source program 'src' (type 'Module'; see@@ -65,26 +52,25 @@ -- searches for standard Curry libraries in the path defined in the -- environment variable "PAKCSLIBPATH". Additional search paths can -- be defined using the argument 'paths'.-fullParse :: [FilePath] -> FilePath -> String -> IO (Result CS.Module)-fullParse paths fn src =- genFullCurrySyntax simpleCheckModule paths fn (parse fn src)+fullParse :: [FilePath] -> FilePath -> String -> IO (MsgMonad CS.Module)+fullParse paths fn src = -- liftM msgmonad2result $+ genFullCurrySyntax simpleCheckModule paths fn (parse fn src) -- Behaves like 'fullParse', but Returns the syntax tree of the source -- program 'src' (type 'Module'; see Module "CurrySyntax") after inferring -- the types of identifiers.-typingParse :: [FilePath] -> FilePath -> String -> IO (Result CS.Module)-typingParse paths fn src = - genFullCurrySyntax checkModule paths fn (parse fn src)+typingParse :: [FilePath] -> FilePath -> String -> IO (MsgMonad CS.Module)+typingParse paths fn src = genFullCurrySyntax checkModule paths fn (parse fn src) +{- -- Compiles the source programm 'src' to an AbstractCurry program. -- 'fullParse' always searches for standard Curry libraries in the path -- defined in the environment variable "PAKCSLIBPATH". Additional search -- paths can be defined using the argument 'paths'. -- Notes: Due to the lack of error handling in the current version of the -- front end, this function may fail when an error occurs-abstractIO :: [FilePath] -> FilePath -> String -> IO (Result ACY.CurryProg)-abstractIO paths fn src = - genAbstractIO paths fn (parse fn src)+abstractIO :: [FilePath] -> FilePath -> String -> IO (MsgMonad ACY.CurryProg)+abstractIO paths fn src = genAbstractIO paths fn (parse fn src) -- Compiles the source program 'src' to a FlatCurry program. -- 'fullParse' always searches for standard Curry libraries in the path @@ -92,17 +78,9 @@ -- paths can be defined using the argument 'paths'. -- Note: Due to the lack of error handling in the current version of the -- front end, this function may fail when an error occurs-flatIO :: [FilePath] -> FilePath -> String -> IO (Result FCY.Prog)-flatIO paths fn src = - genFlatIO paths fn (parse fn src)------------------------------------------------------------------------------------- Result handling--data Result a = Result [Message] a | Failure [Message] deriving Show---- See module "Message":+flatIO :: [FilePath] -> FilePath -> String -> IO (MsgMonad FCY.Prog)+flatIO paths fn src = genFlatIO paths fn (parse fn src)+-} ------------------------------------------------------------------------------- -------------------------------------------------------------------------------@@ -118,52 +96,45 @@ ---genToks :: Err.Error [(Position,Token)] -> Result [(Position,Token)]-genToks (Err.Ok toks) = Result [] toks-genToks (Err.Error err) = Failure [message_ Error err]------genCurrySyntax :: FilePath -> Err.Error CS.Module -> Result (CS.Module)-genCurrySyntax fn (Err.Ok mod)- = let mod'@(CS.Module mid _ _) = patchModuleId fn (importPrelude fn mod)- in if isValidModuleId fn mid- then Result [] mod'- else Failure [message_ Error (err_invalidModuleName mid)]-genCurrySyntax _ (Err.Error err)- = Failure [message_ Error err]+genCurrySyntax :: FilePath -> CS.Module -> MsgMonad (CS.Module)+genCurrySyntax fn mod+ = let mod'@(CS.Module mid _ _) = patchModuleId fn (importPrelude fn mod)+ in if isValidModuleId fn mid+ then return mod'+ else failWith $ err_invalidModuleName mid ---genFullCurrySyntax check paths fn (Result msgs mod)- = do errs <- makeInterfaces paths mod- if null errs- then do mEnv <- loadInterfaces paths mod- (_, _, _, mod', _, msgs') <- check (opts paths) mEnv mod- return (Result (msgs ++ msgs') mod')- else return (Failure (msgs ++ map (message_ Error) errs))-genFullCurrySyntax _ _ _ (Failure msgs) = return (Failure msgs)+genFullCurrySyntax :: (Options -> Base.ModuleEnv -> CS.Module -> IO (t1, t2, t3, CS.Module, t4, [WarnMsg]))+ -> [FilePath] -> t -> MsgMonad CS.Module -> IO (MsgMonad CS.Module)+genFullCurrySyntax check paths fn m+ = runMsgIO m $ \mod -> do errs <- makeInterfaces paths mod+ if null errs+ then do mEnv <- loadInterfaces paths mod+ (_, _, _, mod', _, msgs') <- check (opts paths) mEnv mod+ return (tell msgs' >> return mod')+ else return (failWith (head errs)) ----genAbstractIO :: [FilePath] -> FilePath -> Result CS.Module- -> IO (Result ACY.CurryProg)-genAbstractIO paths fn (Result msgs mod)- = do errs <- makeInterfaces paths mod+{-+genAbstractIO :: [FilePath] -> FilePath -> MsgMonad CS.Module+ -> IO (MsgMonad ACY.CurryProg)+genAbstractIO paths fn m+ = runMsgIO m $ \mod ->+ do errs <- makeInterfaces paths mod if null errs then do mEnv <- loadInterfaces paths mod (tyEnv, tcEnv, _, mod', _, msgs') <- simpleCheckModule (opts paths) mEnv mod- return (Result (msgs ++ msgs') - (genTypedAbstract tyEnv tcEnv mod'))- else return (Failure (msgs ++ map (message_ Error) errs))-genAbstractIO _ _ (Failure msgs) = return (Failure msgs)+ return (tell msgs' >> return (genTypedAbstract tyEnv tcEnv mod'))+ else return (failWith $ head errs) ---genFlatIO :: [FilePath] -> FilePath -> Result CS.Module -> IO (Result FCY.Prog)-genFlatIO paths fn (Result msgs mod)- = do errs <- makeInterfaces paths mod+genFlatIO :: [FilePath] -> FilePath -> MsgMonad CS.Module -> IO (MsgMonad FCY.Prog)+genFlatIO paths fn m+ = runMsgIO m $ \ mod -> + do errs <- makeInterfaces paths mod if null errs then (do mEnv <- loadInterfaces paths mod (tyEnv, tcEnv, aEnv, mod', intf, msgs') <- @@ -174,10 +145,10 @@ cEnv = curryEnv mEnv tcEnv intf mod' (prog,msgs'') = genFlatCurry (opts paths) cEnv mEnv tyEnv tcEnv aEnv' il'- return (Result (msgs'' ++ msgs ++ msgs') prog)+ return (tell msgs'' >> tell msgs' >> return prog) )- else return (Failure (msgs ++ map (message_ Error) errs))-genFlatIO _ _ (Failure msgs) = return (Failure msgs)+ else return (failWith $ head errs)+-} -------------------------------------------------------------------------------@@ -188,16 +159,15 @@ makeInterfaces paths (CS.Module mid _ decls) = do let imports = [preludeMIdent | mid /= preludeMIdent] ++ [imp | CS.ImportDecl _ imp _ _ _ <- decls]- (deps, errs) <- fmap (flattenDeps . sortDeps)- (foldM (moduleDeps paths []) emptyEnv imports)+ (deps, errs) <- fmap flattenDeps (foldM (moduleDeps paths []) Map.empty imports) when (null errs) (mapM_ (compile deps . snd) deps) return errs where compile deps (Source file' mods) = do smake [flatName file', flatIntName file']- (file':catMaybes (map (flatInterface deps) mods))- (compileCurry (opts paths) file')- (return defaultResults)+ (file':mapMaybe (flatInterface deps) mods)+ (compileModule (opts paths) file')+ (return Nothing) return () compile _ _ = return () @@ -207,47 +177,12 @@ Just (Interface file) -> Just (flatIntName (dropExtension file)) _ -> Nothing --- Declares the filename as module name, if the module name is not--- explicitly declared in the module.-patchModuleId :: FilePath -> CS.Module -> CS.Module-patchModuleId fn (CS.Module mid mexports decls)- | (moduleName mid) == "main"- = CS.Module (mkMIdent [takeBaseName fn]) mexports decls- | otherwise- = CS.Module mid mexports decls ---- Adds an import declaration for the prelude to the module, if--- it is not the prelude itself. If the module already has an explicit--- import for the prelude, then a qualified import is added.-importPrelude :: FilePath -> CS.Module -> CS.Module-importPrelude fn (CS.Module m es ds)- = CS.Module m es (if m == preludeMIdent then ds else ds')- where ids = [decl | decl@(CS.ImportDecl _ _ _ _ _) <- ds]- ds' = CS.ImportDecl (first fn) preludeMIdent- (preludeMIdent `elem` map importedModule ids)- Nothing Nothing : ds- importedModule (CS.ImportDecl _ m q asM is) = fromMaybe m asM-- -- Returns 'True', if file name and module name are equal. isValidModuleId :: FilePath -> ModuleIdent -> Bool isValidModuleId fn mid = last (moduleQualifiers mid) == takeBaseName fn ---- Converts a literate source program to a non-literate source program-unlitLiterate :: FilePath -> String -> (String,String)-unlitLiterate fn src- | isLiterateSource fn = unlit fn src- | otherwise = ("",src)--isLiterateSource :: FilePath -> Bool-isLiterateSource fn = litExt `isSuffixOf` fn--litExt = ".lcurry"--compileCurry = compileModule_ ------------------------------------------------------------------------------- -- Messages
src/GenAbstractCurry.hs view
@@ -10,17 +10,20 @@ module GenAbstractCurry (genTypedAbstract, genUntypedAbstract) where +import qualified Data.Map as Map+import qualified Data.Set as Set import Data.Maybe import Data.List import Data.Char -import AbstractCurry+import Curry.Syntax+import Curry.AbstractCurry+ import Base import Types-import Ident-import Position+import Curry.Base.Ident+import Curry.Base.Position import TopEnv-import Env -------------------------------------------------------------------------------@@ -54,13 +57,13 @@ = mapfoldl genImportDecl env (reverse (importDecls partitions)) (types, _) = mapfoldl genTypeDecl env (reverse (typeDecls partitions))- (funcs, _) - = mapfoldl (genFuncDecl False) + (_, funcs) + = Map.mapAccumWithKey (genFuncDecl False) env (funcDecls partitions) (ops, _) = mapfoldl genOpDecl env (reverse (opDecls partitions))- in CurryProg modname imps types funcs ops+ in CurryProg modname imps types (Map.elems funcs) ops -------------------------------------------------------------------------------@@ -87,16 +90,16 @@ partitionDecl partitions (FlatExternalDecl pos ids) = partitionFuncDecls (\id -> FlatExternalDecl pos [id]) partitions ids partitionDecl partitions (InfixDecl pos fix prec idents)- = partitions {opDecls = (map (\id -> (InfixDecl pos fix prec [id])) idents)- ++ (opDecls partitions)}+ = partitions {opDecls = map (\id -> (InfixDecl pos fix prec [id])) idents+ ++ opDecls partitions } partitionDecl partitions decl = case decl of ImportDecl _ _ _ _ _ - -> partitions {importDecls = decl:(importDecls partitions)}+ -> partitions {importDecls = decl: importDecls partitions } DataDecl _ _ _ _ - -> partitions {typeDecls = decl:(typeDecls partitions)}+ -> partitions {typeDecls = decl : typeDecls partitions } TypeDecl _ _ _ _ - -> partitions {typeDecls = decl:(typeDecls partitions)}+ -> partitions {typeDecls = decl : typeDecls partitions } _ -> partitions @@ -106,7 +109,7 @@ = partitions {funcDecls = foldl partitionFuncDecl (funcDecls partitions) ids} where partitionFuncDecl funcs' id- = insertEntry id ((genDecl id):(fromMaybe [] (lookup id funcs'))) funcs'+ = Map.insert id (genDecl id : fromMaybe [] (Map.lookup id funcs')) funcs' -- Data type for representing partitions of CurrySyntax declarations@@ -117,14 +120,14 @@ -- to collect them within an association list data Partitions = Partitions {importDecls :: [Decl], typeDecls :: [Decl],- funcDecls :: [(Ident,[Decl])],+ funcDecls :: Map.Map Ident [Decl], opDecls :: [Decl] } deriving Show -- Generates initial partitions. emptyPartitions = Partitions {importDecls = [], typeDecls = [],- funcDecls = [],+ funcDecls = Map.empty, opDecls = [] } @@ -202,15 +205,15 @@ (ls,ts) = unzip fs (ts',env1) = mapfoldl genTypeExpr env ts ls' = map name ls- in case mr of+ in case mr of Nothing -> (CRecordType (zip ls' ts') Nothing, env1) Just tvar@(VariableType _) -> let (CTVar iname, env2) = genTypeExpr env1 tvar in (CRecordType (zip ls' ts') (Just iname), env2)- Just rec@(RecordType _ _)- -> let (CRecordType fields rbase, env2) = genTypeExpr env1 rec- fields' = foldr (\ (l,t) -> insertEntry l t) + (Just r@(RecordType _ _))+ -> let (CRecordType fields rbase, env2) = genTypeExpr env1 r+ fields' = foldr (uncurry insertEntry) fields (zip ls' ts') in (CRecordType fields' rbase, env2)@@ -240,8 +243,8 @@ -- - since infered types are internally represented in flat style, -- all type variables are renamed with generated symbols when -- generating typed AbstractCurry.-genFuncDecl :: Bool -> AbstractEnv -> (Ident, [Decl]) -> (CFuncDecl, AbstractEnv)-genFuncDecl isLocal env (ident, decls)+genFuncDecl :: Bool -> AbstractEnv -> Ident -> [Decl] -> (AbstractEnv, CFuncDecl)+genFuncDecl isLocal env ident decls | not (null decls) = let name = genQName False env (qualify ident) visibility = genVisibility env ident@@ -255,21 +258,21 @@ (\ (FunctionDecl _ _ equs) -> mapfoldl genRule env1 equs) (find isFunctionDecl decls)- mexternal = applyMaybe genExternal (find isExternal decls)+ mexternal = fmap genExternal (find isExternal decls) arity = compArity mtype rules typeexpr = fromMaybe (CTCons ("Prelude","untyped") []) mtype rule = compRule evalannot rules mexternal env3 = if isLocal then env1 else resetScope env2- in (CFunc name arity visibility typeexpr rule, env3)+ in (env3, CFunc name arity visibility typeexpr rule) | otherwise = internalError ("missing declaration for function \"" ++ show ident ++ "\"") where genFuncType env decls | acytype == UntypedAcy- = applyMaybe (genTypeSig env) (find isTypeSig decls)+ = fmap (genTypeSig env) (find isTypeSig decls) | acytype == TypedAcy- = applyMaybe (genTypeExpr env) mftype+ = fmap (genTypeExpr env) mftype | otherwise = Nothing where @@ -300,7 +303,7 @@ mtypeexpr compArityFromType (CTVar _) = 0- compArityFromType (CFuncType _ t2) = 1 + (compArityFromType t2)+ compArityFromType (CFuncType _ t2) = 1 + compArityFromType t2 compArityFromType (CTCons _ _) = 0 compRule evalannot rules mexternal@@ -371,7 +374,7 @@ -- The association list 'fdecls' is necessary because function -- rules may not be together in the declaration list- genLocals :: AbstractEnv -> [(Ident,[Decl])] -> [Decl] + genLocals :: AbstractEnv -> Map.Map Ident [Decl] -> [Decl] -> ([CLocalDecl], AbstractEnv) genLocals env _ [] = ([], env) genLocals env fdecls ((FunctionDecl _ ident _):decls)@@ -390,15 +393,15 @@ (locals, env2) = genLocals (endScope env1) fdecls - ((FlatExternalDecl pos (tail idents)):decls)+ (FlatExternalDecl pos (tail idents):decls) in (funcdecl:locals, env2)- genLocals env fdecls ((PatternDecl pos constr rhs):decls)+ genLocals env fdecls (PatternDecl pos constr rhs : decls) = let (patt, env1) = genLocalPattern pos env constr (plocals, env2) = genLocalDecls (beginScope env1) (simplifyRhsLocals rhs) (expr, env3) = genLocalPattRhs pos env2 (simplifyRhsExpr rhs) (locals, env4) = genLocals (endScope env3) fdecls decls- in ((CLocalPat patt expr plocals):locals, env4)+ in (CLocalPat patt expr plocals:locals, env4) genLocals env fdecls ((ExtraVariables pos idents):decls) | null idents = genLocals env fdecls decls | otherwise@@ -408,23 +411,23 @@ ++ " for free variable \"" ++ show ident ++ "\"")) (getVarIndex env ident)- decls' = (ExtraVariables pos (tail idents)):decls+ decls' = ExtraVariables pos (tail idents) : decls (locals, env') = genLocals env fdecls decls'- in ((CLocalVar (idx, name ident)):locals, env')+ in (CLocalVar (idx, name ident) : locals, env') genLocals env fdecls ((TypeSig _ _ _):decls) = genLocals env fdecls decls genLocals _ _ decl = internalError ("unexpected local declaration: \n" ++ show (head decl)) - genLocalFuncDecl :: AbstractEnv -> [(Ident,[Decl])] -> Ident + genLocalFuncDecl :: AbstractEnv -> Map.Map Ident [Decl] -> Ident -> (CLocalDecl, AbstractEnv) genLocalFuncDecl env fdecls ident = let fdecl = fromMaybe (internalError ("missing declaration" ++ " for local function \"" ++ show ident ++ "\""))- (lookup ident fdecls)- (funcdecl, _) = genFuncDecl True env (ident,fdecl)+ (Map.lookup ident fdecls)+ (_, funcdecl) = genFuncDecl True env ident fdecl in (CLocalFunc funcdecl, env) genLocalPattern pos env (LiteralPattern lit)@@ -477,7 +480,7 @@ = let (fields', env1) = mapfoldl (genField genLocalPattern) env fields (mr', env2) = maybe (Nothing, env1)- ((applyFst Just) . (genLocalPattern pos env1))+ (applyFst Just . genLocalPattern pos env1) mr in (CPRecord fields' mr', env2) @@ -518,7 +521,7 @@ genExpr pos env (List _ args) = let cons = Constructor qConsId nil = Constructor qNilId- in genExpr pos env (foldr (\e1 e2 -> Apply (Apply cons e1) e2) nil args)+ in genExpr pos env (foldr (Apply . Apply cons) nil args) genExpr pos env (ListCompr _ expr stmts) = let (stmts', env1) = mapfoldl (genStatement pos) (beginScope env) stmts (expr', env2) = genExpr pos env1 expr@@ -659,7 +662,7 @@ genPattern pos env (RecordPattern fields mr) = let (fields', env1) = mapfoldl (genField genPattern) env fields (mr', env2) = maybe (Nothing, env1)- ((applyFst Just) . (genPattern pos env1))+ (applyFst Just . genPattern pos env1) mr in (CPRecord fields' mr', env2) @@ -693,12 +696,10 @@ | otherwise = genQualName qident where- ident = unqualify qident- genQualName qid- = let (mmid, id) = splitQualIdent qid+ = let (mmid, id) = (qualidMod qid, qualidId qid) mid = maybe (moduleId env)- (\mid' -> fromMaybe mid' (lookupEnv mid' (imports env)))+ (\mid' -> fromMaybe mid' (Map.lookup mid' (imports env))) mmid in (moduleName mid, name id) @@ -749,12 +750,12 @@ data AbstractEnv = AbstractEnv {moduleId :: ModuleIdent, typeEnv :: ValueEnv, tconsEnv :: TCEnv,- exports :: Env Ident (),- imports :: Env ModuleIdent ModuleIdent,+ exports :: Set.Set Ident,+ imports :: Map.Map ModuleIdent ModuleIdent, varIndex :: Int, tvarIndex :: Int,- varScope :: [Env Ident Int],- tvarScope :: [Env Ident Int],+ varScope :: [Map.Map Ident Int],+ tvarScope :: [Map.Map Ident Int], acyType :: AbstractType } deriving Show @@ -770,12 +771,12 @@ {moduleId = mid, typeEnv = tyEnv, tconsEnv = tcEnv,- exports = foldl (buildExportTable mid decls) emptyEnv exps',- imports = foldl buildImportTable emptyEnv decls,+ exports = foldl (buildExportTable mid decls) Set.empty exps',+ imports = foldl buildImportTable Map.empty decls, varIndex = 0, tvarIndex = 0,- varScope = [emptyEnv],- tvarScope = [emptyEnv],+ varScope = [Map.empty],+ tvarScope = [Map.empty], acyType = absType } where@@ -785,25 +786,25 @@ -- Generates a list of exports for all specified top level declarations buildExports :: ModuleIdent -> [Decl] -> [Export] buildExports _ [] = []-buildExports mid ((DataDecl _ ident _ _):ds) - = (ExportTypeAll (qualifyWith mid ident)):(buildExports mid ds)+buildExports mid (DataDecl _ ident _ _:ds) + = ExportTypeAll (qualifyWith mid ident) : buildExports mid ds buildExports mid ((NewtypeDecl _ ident _ _):ds)- = (ExportTypeAll (qualifyWith mid ident)):(buildExports mid ds)+ = ExportTypeAll (qualifyWith mid ident) : buildExports mid ds buildExports mid ((TypeDecl _ ident _ _):ds)- = (Export (qualifyWith mid ident)):(buildExports mid ds)+ = Export (qualifyWith mid ident) : buildExports mid ds buildExports mid ((FunctionDecl _ ident _):ds)- = (Export (qualifyWith mid ident)):(buildExports mid ds)-buildExports mid ((ExternalDecl _ _ _ ident _):ds)- = (Export (qualifyWith mid ident)):(buildExports mid ds)-buildExports mid ((FlatExternalDecl _ idents):ds)- = (map (Export . (qualifyWith mid)) idents) ++ (buildExports mid ds)+ = Export (qualifyWith mid ident) : buildExports mid ds+buildExports mid (ExternalDecl _ _ _ ident _ : ds)+ = Export (qualifyWith mid ident) : buildExports mid ds+buildExports mid (FlatExternalDecl _ idents : ds)+ = map (Export . qualifyWith mid) idents ++ buildExports mid ds buildExports mid (_:ds) = buildExports mid ds -- Builds a table containing all exported (i.e. public) identifiers -- from a module.-buildExportTable :: ModuleIdent -> [Decl] -> Env Ident () -> Export - -> Env Ident ()+buildExportTable :: ModuleIdent -> [Decl] -> Set.Set Ident -> Export + -> Set.Set Ident buildExportTable mid _ exptab (Export qident) | isJust (localIdent mid qident) = insertExportedIdent exptab (unqualify qident)@@ -826,8 +827,8 @@ buildExportTable _ _ exptab (ExportModule _) = exptab ---insertExportedIdent :: Env Ident () -> Ident -> Env Ident ()-insertExportedIdent env ident = bindEnv ident () env+insertExportedIdent :: Set.Set Ident -> Ident -> Set.Set Ident+insertExportedIdent env ident = Set.insert ident env -- getConstrIdents :: Decl -> [Ident]@@ -839,16 +840,16 @@ -- Builds a table for dereferencing import aliases-buildImportTable :: Env ModuleIdent ModuleIdent -> Decl- -> Env ModuleIdent ModuleIdent+buildImportTable :: Map.Map ModuleIdent ModuleIdent -> Decl+ -> Map.Map ModuleIdent ModuleIdent buildImportTable env (ImportDecl _ mid _ malias _)- = bindEnv (fromMaybe mid malias) mid env+ = Map.insert (fromMaybe mid malias) mid env buildImportTable env _ = env -- Checks whether an identifier is exported or not. isExported :: AbstractEnv -> Ident -> Bool-isExported env ident = isJust (lookupEnv ident (exports env))+isExported env ident = Set.member ident (exports env) -- Generates an unique index for the variable 'ident' and inserts it@@ -857,9 +858,9 @@ genVarIndex env ident = let idx = varIndex env vtabs = varScope env- vtab = head vtabs --if null vtabs then emptyEnv else head vtabs+ vtab = head vtabs --if null vtabs then Map.empty else head vtabs in (idx, env {varIndex = idx + 1,- varScope = (bindEnv ident idx vtab):(sureTail vtabs)})+ varScope = Map.insert ident idx vtab : sureTail vtabs}) -- Generates an unique index for the type variable 'ident' and inserts it -- into the type variable table of the current scope.@@ -867,20 +868,20 @@ genTVarIndex env ident = let idx = tvarIndex env vtabs = tvarScope env- vtab = head vtabs --if null vtabs then emptyEnv else head vtabs+ vtab = head vtabs --if null vtabs then Map.empty else head vtabs in (idx, env {tvarIndex = idx + 1,- tvarScope = (bindEnv ident idx vtab):(sureTail vtabs)})+ tvarScope = Map.insert ident idx vtab : sureTail vtabs }) -- Looks up the unique index for the variable 'ident' in the -- variable table of the current scope. getVarIndex :: AbstractEnv -> Ident -> Maybe Int-getVarIndex env ident = lookupEnv ident (head (varScope env))+getVarIndex env ident = Map.lookup ident (head (varScope env)) -- Looks up the unique index for the type variable 'ident' in the type -- variable table of the current scope. getTVarIndex :: AbstractEnv -> Ident -> Maybe Int-getTVarIndex env ident = lookupEnv ident (head (tvarScope env))+getTVarIndex env ident = Map.lookup ident (head (tvarScope env)) -- Generates an indentifier which doesn't occur in the variable table@@ -895,31 +896,18 @@ = ident where ident = mkIdent (name ++ show idx) --- Generates an indentifier which doesn't occur in the type variable table--- of the current scope.-freshTVar :: AbstractEnv -> String -> Ident-freshTVar env name = genFreshTVar env name 0- where- genFreshTVar env name idx- | isJust (getTVarIndex env ident)- = genFreshTVar env name (idx + 1)- | otherwise - = ident- where ident = mkIdent (name ++ show idx)-- -- Sets the index counter back to zero and deletes all stack entries. resetScope :: AbstractEnv -> AbstractEnv resetScope env = env {varIndex = 0, tvarIndex = 0,- varScope = [emptyEnv],- tvarScope = [emptyEnv]}+ varScope = [Map.empty],+ tvarScope = [Map.empty]} -- Starts a new scope, i.e. copies and pushes the variable table of the current -- scope onto the top of the stack beginScope :: AbstractEnv -> AbstractEnv-beginScope env = env {varScope = (head vs):vs,- tvarScope = (head tvs):tvs}+beginScope env = env {varScope = head vs :vs,+ tvarScope = head tvs :tvs } where vs = varScope env tvs = tvarScope env@@ -969,7 +957,7 @@ -- Checks, whether a symbol is defined in the Prelude. isPreludeSymbol :: QualIdent -> Bool isPreludeSymbol qident- = let (mmid, ident) = splitQualIdent qident+ = let (mmid, ident) = (qualidMod qident, qualidId qident) in (isJust mmid && preludeMIdent == fromJust mmid) || elem ident [unitId, listId, nilId, consId] || isTupleId ident@@ -986,7 +974,7 @@ qualLookupType :: QualIdent -> ValueEnv -> Maybe TypeExpr qualLookupType qident tyEnv = case (qualLookupValue qident tyEnv) of- [Value _ ts] -> (\ (ForAll _ ty) -> Just (toCSType ty)) ts+ [Value _ ts] -> (\ (ForAll _ ty) -> Just (fromType ty)) ts _ -> Nothing -- Looks up the type of a symbol in the type environment and@@ -994,66 +982,14 @@ lookupType :: Ident -> ValueEnv -> Maybe TypeExpr lookupType ident tyEnv = case (lookupValue ident tyEnv) of- [Value _ ts] -> (\ (ForAll _ ty) -> Just (toCSType ty)) ts+ [Value _ ts] -> (\ (ForAll _ ty) -> Just (fromType ty)) ts _ -> Nothing --- Converts the internal representation of the types from the type--- envorinment to CurrySyntax representation-toCSType :: Type -> TypeExpr-toCSType = fromType -{--toCSType (TypeConstructor qident types)- = ConstructorType qident (map toCSType types)-toCSType (TypeVariable idx)- = VariableType (mkVarIdent idx)-toCSType (TypeConstrained types _)- = toCSType (head types)-toCSType (TypeArrow type1 type2)- = ArrowType (toCSType type1) (toCSType type2)-toCSType (TypeSkolem idx)- = VariableType (mkVarIdent idx)--}--{-----solveTypeSyn :: TCEnv -> QualIdent -> [TypeExpr] -> Maybe TypeExpr-solveTypeSyn tcEnv qident args- = case (qualLookupTC qident tcEnv) of- [AliasType _ _ t] -> Just (adaptType args t)- _ -> case (lookupTC (unqualify qident) tcEnv) of- [AliasType _ _ t] -> Just (adaptType args t)- _ -> Nothing-----adaptType :: [TypeExpr] -> Type -> TypeExpr-adaptType args texpr = adapt (zip [0 .. ((length args) - 1)] args) texpr- where- adapt its (TypeConstructor qident types)- = ConstructorType qident (map (adapt its) types)- adapt its (TypeVariable idx)- = fromMaybe (internalError "cannot adapt type variable")- (lookup idx its)- adapt its (TypeConstrained types _)- = adapt its (head types)- adapt its (TypeArrow type1 type2)- = ArrowType (adapt its type1) (adapt its type2)- adapt its (TypeSkolem idx)- = adapt its (TypeVariable idx)--}---- Generates a variable name from an index.-mkVarIdent :: Int -> Ident-mkVarIdent i | i < 0 = mkIdent ('b':(show (i * (-1)))) - | i < 26 = mkIdent [chr (i + ord 'a')]- | otherwise = mkIdent ('a':(show i))- -- -- The following functions transform left-hand-side and right-hand-side terms -- for a better handling simplifyLhs :: Lhs -> [ConstrTerm]-simplifyLhs lhs = snd (flatLhs lhs)+simplifyLhs = snd . flatLhs simplifyRhsExpr :: Rhs -> [(Expression, Expression)] simplifyRhsExpr (SimpleRhs _ expr _) @@ -1066,11 +1002,7 @@ simplifyRhsLocals (GuardedRhs _ locals) = locals --- Applies the function 'f' on the value which is wrapped in 'Just'.-applyMaybe :: (a -> b) -> Maybe a -> Maybe b-applyMaybe f (Just x) = Just (f x)-applyMaybe _ Nothing = Nothing-+-- FIXME This mapfold is a twisted mapAccumL -- A combination of 'map' and 'foldl'. It maps a function to a list -- from left to right while updating the argument 'e' continously. mapfoldl :: (a -> b -> (c,a)) -> a -> [b] -> ([c], a)@@ -1084,7 +1016,7 @@ insertEntry k e [] = [(k,e)] insertEntry k e ((x,y):xys) | k == x = (k,e):xys- | otherwise = (x,y):(insertEntry k e xys)+ | otherwise = (x,y) : insertEntry k e xys -- Returns the list without the first element. If the list is empty, an
src/GenFlatCurry.hs view
@@ -15,32 +15,27 @@ import Data.Maybe import Data.List import qualified Data.Map as Map-import Base (ArityEnv, ArityInfo(..), ModuleEnv, PEnv, PrecInfo(..), - OpPrec(..), TCEnv, TypeInfo(..), ValueEnv, ValueInfo(..),- lookupValue, qualLookupTC,- qualLookupArity, lookupArity, internalError) ---import FlatWithSrcRefs-import ExtendedFlat--import qualified IL-import qualified CurrySyntax as CS+import Curry.Base.MessageMonad+import Curry.Base.Ident as Id +import Base {-(ArityEnv, ArityInfo(..), ModuleEnv, + TCEnv, TypeInfo(..), ValueEnv, ValueInfo(..),+ lookupValue, qualLookupTC,+ qualLookupArity, lookupArity, internalError,+ qualLookupValue)-}+import Curry.ExtendedFlat+import qualified IL.Type as IL+import qualified IL.CurryToIL as IL+import qualified Curry.Syntax as CS import CurryEnv (CurryEnv) import qualified CurryEnv- import ScopeEnv (ScopeEnv) import qualified ScopeEnv-- import Types import CurryCompilerOpts-import Message import PatchPrelude-import Ident as Id-import Env ---import Debug.Trace trace _ x = x @@ -48,7 +43,7 @@ -- transforms intermediate language code (IL) to FlatCurry code genFlatCurry :: Options -> CurryEnv -> ModuleEnv -> ValueEnv -> TCEnv - -> ArityEnv -> IL.Module -> (Prog, [Message])+ -> ArityEnv -> IL.Module -> (Prog, [WarnMsg]) genFlatCurry opts cEnv mEnv tyEnv tcEnv aEnv mod = (patchPreludeFCY prog, messages) where (prog, messages) @@ -57,7 +52,7 @@ -- transforms intermediate language code (IL) to FlatCurry interfaces genFlatInterface :: Options -> CurryEnv -> ModuleEnv -> ValueEnv -> TCEnv- -> ArityEnv -> IL.Module -> (Prog, [Message])+ -> ArityEnv -> IL.Module -> (Prog, [WarnMsg]) genFlatInterface opts cEnv mEnv tyEnv tcEnv aEnv mod = (patchPreludeFCY intf, messages) where (intf, messages) @@ -177,16 +172,19 @@ = liftM Var (lookupVarIndex ident) visitExpression (IL.Function qident _) = do arity_ <- lookupIdArity qident+ qname <- visitQualIdent qident+ -- ftype <- lookupIdType qident+ -- let qident' = qname{ typeofQName = ftype } maybe (internalError (funcArity qident))- (\arity -> genFuncCall qident arity [])+ (\arity -> genFuncCall qname arity []) arity_ visitExpression (IL.Constructor qident arity) = do arity_ <- lookupIdArity qident maybe (internalError (consArity qident)) (\arity -> genConsCall qident arity []) arity_-visitExpression (IL.Apply expression1 expression2)- = genFlatApplication (IL.Apply expression1 expression2)+visitExpression (IL.Apply e1 e2)+ = genFlatApplication e1 e2 visitExpression (IL.Case r evalannot expression alts) = do ea <- visitEval evalannot expr <- visitExpression expression@@ -208,12 +206,10 @@ newVarIndex (bindingIdent binding) bind <- visitBinding binding expr <- visitExpression expression- case expr of- Let binds expr' -> return (Let (bind:binds) expr')- _ -> return (Let [bind] expr)+ return (Let [bind] expr) visitExpression (IL.Letrec bindings expression) = do beginScope- mapM_ newVarIndex (map bindingIdent bindings)+ mapM_ (newVarIndex . bindingIdent) bindings binds <- mapM visitBinding bindings expr <- visitExpression expression endScope@@ -275,8 +271,8 @@ -- visitEval :: IL.Eval -> FlatState CaseType-visitEval IL.Rigid = return (Rigid)-visitEval IL.Flex = return (Flex)+visitEval IL.Rigid = return Rigid+visitEval IL.Flex = return Flex -- visitBinding :: IL.Binding -> FlatState (VarIndex, Expr)@@ -300,8 +296,8 @@ visitTypeIDecl :: CS.IDecl -> FlatState TypeDecl visitTypeIDecl (CS.IDataDecl _ qident params constrs_) = do let mid = fromMaybe (internalError "GenFlatCurry: no module name")- (fst (splitQualIdent qident))- is = [0 .. (length params) - 1]+ (qualidMod qident)+ is = [0 .. length params - 1] cdecls <- mapM (visitConstrIDecl mid (zip params is)) (catMaybes constrs_) qname <- visitQualIdent qident@@ -317,7 +313,7 @@ visitConstrIDecl :: ModuleIdent -> [(Ident, Int)] -> CS.ConstrDecl -> FlatState ConsDecl visitConstrIDecl mid tis (CS.ConstrDecl _ _ ident typeexprs)- = do texprs <- mapM visitType (map (fst . cs2ilType tis) typeexprs)+ = do texprs <- mapM (visitType . (fst . cs2ilType tis)) typeexprs qname <- visitQualIdent (qualifyWith mid ident) return (Cons qname (length typeexprs) Public texprs) visitConstrIDecl mid tis (CS.ConOpDecl pos ids type1 ident type2)@@ -338,13 +334,13 @@ -- visitModuleIdent :: ModuleIdent -> FlatState String-visitModuleIdent mident = return (Id.moduleName mident)+visitModuleIdent = return . Id.moduleName -- visitQualIdent :: QualIdent -> FlatState QName visitQualIdent qident = do mid <- moduleId- let (mmod, ident) = splitQualIdent qident+ let (mmod, ident) = (qualidMod qident, qualidId qident) mod | elem ident [listId, consId, nilId, unitId] || isTupleId ident = Id.moduleName preludeMIdent | otherwise@@ -354,7 +350,7 @@ -- visitExternalName :: String -> FlatState String visitExternalName name - = moduleId >>= (\mid -> return ((Id.moduleName mid) ++ "." ++ name))+ = moduleId >>= \mid -> return (Id.moduleName mid ++ "." ++ name) -------------------------------------------------------------------------------@@ -372,11 +368,11 @@ getExportedImports = do mid <- moduleId exps <- exports- genExportedIDecls (envToList (getExpImports mid emptyEnv exps))+ genExportedIDecls (Map.toList (getExpImports mid Map.empty exps)) ---getExpImports :: ModuleIdent -> Env ModuleIdent [CS.Export] -> [CS.Export]- -> Env ModuleIdent [CS.Export]+getExpImports :: ModuleIdent -> Map.Map ModuleIdent [CS.Export] -> [CS.Export]+ -> Map.Map ModuleIdent [CS.Export] getExpImports mident expenv [] = expenv getExpImports mident expenv ((CS.Export qident):exps) = getExpImports mident @@ -394,20 +390,19 @@ (bindExpImport mident qident (CS.ExportTypeAll qident) expenv) exps getExpImports mident expenv ((CS.ExportModule mident'):exps)- = getExpImports mident (bindEnv mident' [] expenv) exps+ = getExpImports mident (Map.insert mident' [] expenv) exps -- bindExpImport :: ModuleIdent -> QualIdent -> CS.Export - -> Env ModuleIdent [CS.Export] -> Env ModuleIdent [CS.Export]+ -> Map.Map ModuleIdent [CS.Export] -> Map.Map ModuleIdent [CS.Export] bindExpImport mident qident export expenv | isJust (localIdent mident qident) = expenv | otherwise- = let (mmod, _) = splitQualIdent qident- mod = fromJust mmod- in maybe (bindEnv mod [export] expenv)- (\es -> bindEnv mod (export:es) expenv) - (lookupEnv mod expenv)+ = let (Just mod) = qualidMod qident+ in maybe (Map.insert mod [export] expenv)+ (\es -> Map.insert mod (export:es) expenv) + (Map.lookup mod expenv) -- genExportedIDecls :: [(ModuleIdent,[CS.Export])] -> FlatState [CS.IDecl]@@ -477,9 +472,9 @@ ------------------------------------------------------------------------------- ---genFlatApplication :: IL.Expression -> FlatState Expr-genFlatApplication applicexpr- = genFlatApplic [] applicexpr+genFlatApplication :: IL.Expression -> IL.Expression -> FlatState Expr+genFlatApplication e1 e2+ = genFlatApplic [e2] e1 where genFlatApplic args expression = case expression of@@ -487,8 +482,9 @@ -> genFlatApplic (expr2:args) expr1 (IL.Function qident _) -> do arity_ <- lookupIdArity qident+ qname <- visitQualIdent qident maybe (internalError (funcArity qident))- (\arity -> genFuncCall qident arity args)+ (\arity -> genFuncCall qname arity args) arity_ (IL.Constructor qident _) -> do arity_ <- lookupIdArity qident@@ -499,36 +495,39 @@ genApplicComb expr args ---genFuncCall :: QualIdent -> Int -> [IL.Expression] -> FlatState Expr-genFuncCall qident arity args+genFuncCall :: QName -> Int -> [IL.Expression] -> FlatState Expr+genFuncCall qname arity args | arity > cnt - = genComb qident args (FuncPartCall (arity - cnt))+ = genComb qname args (FuncPartCall (arity - cnt)) | arity < cnt = do let (funcargs, applicargs) = splitAt arity args- funccall <- genComb qident funcargs FuncCall+ funccall <- genComb qname funcargs FuncCall genApplicComb funccall applicargs | otherwise - = genComb qident args FuncCall+ = genComb qname args FuncCall where cnt = length args -- genConsCall :: QualIdent -> Int -> [IL.Expression] -> FlatState Expr genConsCall qident arity args | arity > cnt - = genComb qident args (ConsPartCall (arity - cnt))+ = do qname <- visitQualIdent qident+ genComb qname args (ConsPartCall (arity - cnt)) | arity < cnt = do let (funcargs, applicargs) = splitAt arity args- conscall <- genComb qident funcargs ConsCall+ qname <- visitQualIdent qident+ conscall <- genComb qname funcargs ConsCall genApplicComb conscall applicargs | otherwise - = genComb qident args ConsCall + = do qname <- visitQualIdent qident+ genComb qname args ConsCall where cnt = length args ---genComb :: QualIdent -> [IL.Expression] -> CombType -> FlatState Expr-genComb qident args combtype+genComb :: QName -> [IL.Expression] -> CombType -> FlatState Expr+genComb qname args combtype = do exprs <- mapM visitExpression args- qname <- visitQualIdent qident+-- qname <- visitQualIdent qident return (Comb combtype qname exprs) --@@ -544,7 +543,7 @@ -- genOpDecls :: FlatState [OpDecl]-genOpDecls = fixities >>= (\fix -> mapM genOpDecl fix)+genOpDecls = fixities >>= mapM genOpDecl -- genOpDecl :: CS.IDecl -> FlatState OpDecl@@ -604,7 +603,7 @@ genRecordType :: CS.IDecl -> FlatState TypeDecl genRecordType (CS.ITypeDecl _ qident params (CS.RecordType fields _)) = do let is = [0 .. (length params) - 1]- (mod,ident) = splitQualIdent qident+ (mod,ident) = (qualidMod qident, qualidId qident) qname <- visitQualIdent ((maybe qualify qualifyWith mod) (recordExtId ident)) labels <- mapM (genRecordLabel mod (zip params is)) fields@@ -682,17 +681,14 @@ = internalError ("GenFlatCurry.matchTypeVars: " ++ show ty ++ "\n" ++ show typeexpr) - matchList ms tys typeexprs- = foldl (\ms' (ty,typeexpr) -> match ms' ty typeexpr)- ms- (zip tys typeexprs)+ matchList ms tys+ = foldl (\ms' (ty,typeexpr) -> match ms' ty typeexpr) ms . zip tys flattenRecordTypeFields :: [([Ident],CS.TypeExpr)] -> [(Ident,CS.TypeExpr)]-flattenRecordTypeFields fss+flattenRecordTypeFields = concatMap (\ (labels, typeexpr) -> map (\label -> (label,typeexpr)) labels)- fss ------------------------------------------------------------------------------- @@ -756,29 +752,10 @@ missingVarIndex id = "GenFlatCurry: missing index for \"" ++ show id ++ "\"" -overlappingRules qid = (OverlapRules,- "function \""- ++ show qid +overlappingRules qid = "function \""+ ++ qualName qid ++ "\" is non-deterministic due to non-trivial "- ++ "overlapping rules")-----------------------------------------------------------------------------------prelude_types :: [TypeDecl]-prelude_types = [(Type (preludeName "()") Public [] - [(Cons (preludeName "()") 0 Public [])]),- (Type (preludeName "[]") Public [0] - [(Cons (preludeName "[]") 0 Public []),- (Cons (preludeName ":") 2 Public - [(TVar 0),(TCons (preludeName "[]") [(TVar 0)])])])]- ++ map mkTupleType [2..15]- where- preludeName = curry mkQName "Prelude"- mkTupleType n = let last = n-1- name = preludeName("(" ++ replicate last ',' ++ ")")- idxs = [0..last]- vars = map TVar idxs- in Type name Public idxs [Cons name n Public vars]+ ++ "overlapping rules" -------------------------------------------------------------------------------@@ -851,13 +828,13 @@ -- Data type for representing an environment which contains information needed -- for generating FlatCurry code. data FlatEnv = FlatEnv{ moduleIdE :: ModuleIdent,- functionIdE :: QualIdent,+ functionIdE :: QualIdent, -- function name for error messages compilerOptsE :: Options, moduleEnvE :: ModuleEnv, arityEnvE :: ArityEnv, typeEnvE :: ValueEnv, tConsEnvE :: TCEnv,- publicEnvE :: Env Ident IdentExport,+ publicEnvE :: Map.Map Ident IdentExport, fixitiesE :: [CS.IDecl], typeSynonymsE :: [CS.IDecl], importsE :: [CS.IDecl],@@ -867,7 +844,7 @@ varIdsE :: ScopeEnv Ident VarIndex, tvarIndexE :: Int, tvarIdsE :: ScopeEnv Ident TVarIndex,- messagesE :: [Message],+ messagesE :: [WarnMsg], genInterfaceE :: Bool } @@ -884,7 +861,7 @@ -- Runs a 'FlatState' action and returns the result run :: Options -> CurryEnv -> ModuleEnv -> ValueEnv -> TCEnv -> ArityEnv - -> Bool -> FlatState a -> (a, [Message])+ -> Bool -> FlatState a -> (a, [WarnMsg]) run opts cEnv mEnv tyEnv tcEnv aEnv genIntf f = (result, messagesE env) where@@ -955,7 +932,7 @@ -- isPublic :: Bool -> QualIdent -> FlatState Bool isPublic isConstr qid = gets (\env -> maybe False isP- (lookupEnv (unqualify qid) + (Map.lookup (unqualify qid) (publicEnvE env))) where isP NotConstr = not isConstr@@ -965,7 +942,7 @@ -- lookupModuleIntf :: ModuleIdent -> FlatState (Maybe [CS.IDecl]) lookupModuleIntf mid- = gets (lookupEnv mid . moduleEnvE)+ = gets (Map.lookup mid . moduleEnvE) -- lookupIdArity :: QualIdent -> FlatState (Maybe Int)@@ -980,6 +957,20 @@ _ -> Nothing _ -> Nothing +--+lookupIdType :: QualIdent -> FlatState (Maybe TypeExpr)+lookupIdType qid+ = do aEnv <- gets typeEnvE+ lookupT qid aEnv+ where+ lookupT qid aEnv = let vals = qualLookupValue qid aEnv + ts = [ t | Value _ (ForAll _ t) <- vals]+ in case ts of + t : _ -> do t' <- visitType (IL.translType t)+ return (Just t')+ [] -> error ("no type for " ++ show qid ++ show vals ++ show aEnv) -- return Nothing++ -- Generates a new index for a variable newVarIndex :: Ident -> FlatState VarIndex newVarIndex id@@ -1005,46 +996,11 @@ varIdsE = ScopeEnv.new }) --- Generates a new index for a type variable-newTVarIndex :: Ident -> FlatState Int-newTVarIndex id- = do idx0 <- gets tvarIndexE- let idx = 1 + idx0- vids <- gets tvarIdsE- modify (\env -> env{ tvarIndexE = idx,- tvarIdsE = ScopeEnv.insert id idx vids- })- return idx---- Looks up the index of an existing type variable or generates a new index,--- if the type variable doesn't exist-getTVarIndex :: Ident -> FlatState Int-getTVarIndex id- = do idx0 <- gets tvarIndexE- let idx = idx0 + 1- vids <- gets tvarIdsE - maybe (do modify (\env -> env{ tvarIndexE = idx,- tvarIdsE = ScopeEnv.insert id idx vids })- return idx)- return- (ScopeEnv.lookup id vids)- ---lookupTVarIndex :: Ident -> FlatState (Maybe Int)-lookupTVarIndex id- = gets (ScopeEnv.lookup id . tvarIdsE)-----clearTVarIndices :: FlatState ()-clearTVarIndices = modify (\env -> env { tvarIndexE = 0,- tvarIdsE = ScopeEnv.new - })-----genWarning :: (WarningType,String) -> FlatState ()-genWarning (warnType,msg)+genWarning :: String -> FlatState ()+genWarning msg = modify (\env -> env{ messagesE = warnMsg:(messagesE env) })- where warnMsg = message_ (Warning warnType) msg+ where warnMsg = WarnMsg Nothing msg -- genInterface :: FlatState Bool@@ -1076,14 +1032,14 @@ -- Note: Currently the record functions (selection and update) for all public -- record labels are inserted into the environment, though they are not -- explicitly declared in the export specifications.-genPubEnv :: ModuleIdent -> [CS.IDecl] -> Env Ident IdentExport-genPubEnv mid idecls = foldl (bindEnvIDecl mid) emptyEnv idecls+genPubEnv :: ModuleIdent -> [CS.IDecl] -> Map.Map Ident IdentExport+genPubEnv mid idecls = foldl (bindEnvIDecl mid) Map.empty idecls -bindIdentExport :: Ident -> Bool -> Env Ident IdentExport -> Env Ident IdentExport+bindIdentExport :: Ident -> Bool -> Map.Map Ident IdentExport -> Map.Map Ident IdentExport bindIdentExport id isConstr env =- maybe (bindEnv id (if isConstr then OnlyConstr else NotConstr) env)- (\ ie -> bindEnv id (updateIdentExport ie isConstr) env)- (lookupEnv id env)+ maybe (Map.insert id (if isConstr then OnlyConstr else NotConstr) env)+ (\ ie -> Map.insert id (updateIdentExport ie isConstr) env)+ (Map.lookup id env) where updateIdentExport OnlyConstr True = OnlyConstr updateIdentExport OnlyConstr False = NotOnlyConstr@@ -1093,7 +1049,7 @@ ---bindEnvIDecl :: ModuleIdent -> Env Ident IdentExport -> CS.IDecl -> Env Ident IdentExport+bindEnvIDecl :: ModuleIdent -> Map.Map Ident IdentExport -> CS.IDecl -> Map.Map Ident IdentExport bindEnvIDecl mid env (CS.IDataDecl _ qid _ mcdecls) = maybe env (\id -> foldl bindEnvConstrDecl@@ -1111,30 +1067,24 @@ bindEnvIDecl _ env _ = env ---bindEnvITypeDecl :: Env Ident IdentExport -> Ident -> CS.TypeExpr- -> Env Ident IdentExport+bindEnvITypeDecl :: Map.Map Ident IdentExport -> Ident -> CS.TypeExpr+ -> Map.Map Ident IdentExport bindEnvITypeDecl env id (CS.RecordType fs _) = bindIdentExport id False (foldl (bindEnvRecordLabel id) env fs) bindEnvITypeDecl env id texpr = bindIdentExport id False env ---bindEnvConstrDecl :: Env Ident IdentExport -> CS.ConstrDecl -> Env Ident IdentExport+bindEnvConstrDecl :: Map.Map Ident IdentExport -> CS.ConstrDecl -> Map.Map Ident IdentExport bindEnvConstrDecl env (CS.ConstrDecl _ _ id _) = bindIdentExport id True env bindEnvConstrDecl env (CS.ConOpDecl _ _ _ id _) = bindIdentExport id True env ---bindEnvNewConstrDecl :: Env Ident IdentExport -> CS.NewConstrDecl -> Env Ident IdentExport+bindEnvNewConstrDecl :: Map.Map Ident IdentExport -> CS.NewConstrDecl -> Map.Map Ident IdentExport bindEnvNewConstrDecl env (CS.NewConstrDecl _ _ id _) = bindIdentExport id False env ---bindEnvRecordLabel :: Ident -> Env Ident IdentExport -> ([Ident],CS.TypeExpr) - -> Env Ident IdentExport-bindEnvRecordLabel rec env ([lab],_)- = bindIdentExport (recSelectorId (qualify rec) lab)- False- (bindIdentExport (recUpdateId (qualify rec) lab) False env)------------------------------------------------------------------------------------------------------------------------------------------------------------------+bindEnvRecordLabel :: Ident -> Map.Map Ident IdentExport -> ([Ident],CS.TypeExpr) -> Map.Map Ident IdentExport+bindEnvRecordLabel r env ([lab], _) = bindIdentExport (recSelectorId (qualify r) lab) False expo+ where + expo = (bindIdentExport (recUpdateId (qualify r) lab) False env)
− src/IL.lhs
@@ -1,108 +0,0 @@-% $Id: IL.lhs,v 1.18 2003/10/28 05:43:38 wlux Exp $-%-% Copyright (c) 1999-2003 Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{IL.lhs}-\section{The intermediate language}-The module \texttt{IL} defines the intermediate language which will be-compiled into abstract machine code. The intermediate language removes-a lot of syntactic sugar from the Curry source language. Top-level-declarations are restricted to data type and function definitions. A-newtype definition serves mainly as a hint to the backend that it must-provide an auxiliary function for partial applications of the-constructor. \textbf{Newtype constructors must not occur in patterns-and may be used in expressions only as partial applications.}--Type declarations use a de-Bruijn indexing scheme (starting at 0) for-type variables. In the type of a function, all type variables are-numbered in the order of their occurence from left to right, i.e., a-type \texttt{(Int -> b) -> (a,b) -> c -> (a,c)} is translated into the-type (using integer numbers to denote the type variables)-\texttt{(Int -> 0) -> (1,0) -> 2 -> (1,2)}.--Pattern matching in an equation is handled via flexible and rigid-\texttt{Case} expressions. Overlapping rules are translated with the-help of \texttt{Or} expressions. The intermediate language has three-kinds of binding expressions, \texttt{Exist} expressions introduce a-new logical variable, \texttt{Let} expression support a single-non-recursive variable binding, and \texttt{Letrec} expressions-introduce multiple variables with recursive initializer expressions.-The intermediate language explicitly distinguishes (local) variables-and (global) functions in expressions.--\em{Note:} this modified version uses haskell type \texttt{Integer}-instead of \texttt{Int} for representing integer values. This provides-an unlimited range of integer constants in Curry programs.-\begin{verbatim}--> module IL where-> import Ident-> import Position (SrcRef(..))--> data Module = Module ModuleIdent [ModuleIdent] [Decl] deriving (Eq,Show)--> data Decl = -> DataDecl QualIdent Int [ConstrDecl [Type]]-> | NewtypeDecl QualIdent Int (ConstrDecl Type)-> | FunctionDecl QualIdent [Ident] Type Expression-> | ExternalDecl QualIdent CallConv String Type-> deriving (Eq,Show)--> data ConstrDecl a = ConstrDecl QualIdent a deriving (Eq,Show)-> data CallConv = Primitive | CCall deriving (Eq,Show)--> data Type =-> TypeConstructor QualIdent [Type]-> | TypeVariable Int-> | TypeArrow Type Type-> deriving (Eq,Show)--> data Literal = Char SrcRef Char | Int SrcRef Integer | Float SrcRef Double deriving (Eq,Show)--> data ConstrTerm =-> -- literal patterns-> LiteralPattern Literal-> -- constructors-> | ConstructorPattern QualIdent [Ident]-> -- default-> | VariablePattern Ident-> deriving (Eq,Show)--> data Expression =-> -- literal constants-> Literal Literal-> -- variables, functions, constructors-> | Variable Ident | Function QualIdent Int | Constructor QualIdent Int-> -- applications-> | Apply Expression Expression-> -- case expressions-> | Case SrcRef Eval Expression [Alt]-> -- non-determinisismic or-> | Or Expression Expression-> -- binding forms-> | Exist Ident Expression-> | Let Binding Expression-> | Letrec [Binding] Expression-> deriving (Eq,Show)--> data Eval = Rigid | Flex deriving (Eq,Show)-> data Alt = Alt ConstrTerm Expression deriving (Eq,Show)-> data Binding = Binding Ident Expression deriving (Eq,Show)--\end{verbatim}--> instance SrcRefOf ConstrTerm where-> srcRefOf (LiteralPattern l) = srcRefOf l-> srcRefOf (ConstructorPattern i _) = srcRefOf i-> srcRefOf (VariablePattern i) = srcRefOf i---> instance SrcRefOf Literal where-> srcRefOf (Char s _) = s-> srcRefOf (Int s _) = s-> srcRefOf (Float s _) = s --
+ src/IL/CurryToIL.lhs view
@@ -0,0 +1,598 @@++% $Id: ILTrans.lhs,v 1.86 2004/02/13 19:23:58 wlux Exp $+%+% Copyright (c) 1999-2003, Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{ILTrans.lhs}+\section{Translating Curry into the Intermediate Language}+After desugaring and lifting have been performed, the source code is+translated into the intermediate language. Besides translating from+source terms and expressions into intermediate language terms and+expressions this phase in particular has to implement the pattern+matching algorithm for equations and case expressions.++Because of name conflicts between the source and intermediate language+data structures, we can use only a qualified import for the+\texttt{IL} module.+\begin{verbatim}++> module IL.CurryToIL(ilTrans,ilTransIntf, translType) where++> import Data.Maybe+> import Data.List+> import qualified Data.Set as Set+> import qualified Data.Map as Map++> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax+> import Curry.Syntax.Utils++> import Types+> import Base+> import qualified IL.Type as IL+> import Utils++++\end{verbatim}+\paragraph{Modules}+At the top-level, the compiler has to translate data type, newtype,+function, and external declarations. When translating a data type or+newtype declaration, we ignore the types in the declaration and lookup+the types of the constructors in the type environment instead because+these types are already fully expanded, i.e., they do not include any+alias types.+\begin{verbatim}++> ilTrans :: Bool -> ValueEnv -> TCEnv -> EvalEnv -> Module -> IL.Module+> ilTrans flat tyEnv tcEnv evEnv (Module m _ ds) = +> IL.Module m (imports m ds') ds'+> where ds' = concatMap (translGlobalDecl flat m tyEnv tcEnv evEnv) ds++> translGlobalDecl :: Bool -> ModuleIdent -> ValueEnv -> TCEnv -> EvalEnv+> -> Decl -> [IL.Decl]+> translGlobalDecl _ m tyEnv tcEnv _ (DataDecl _ tc tvs cs) =+> [translData m tyEnv tcEnv tc tvs cs]+> translGlobalDecl _ m tyEnv tcEnv _ (NewtypeDecl _ tc tvs nc) =+> [translNewtype m tyEnv tcEnv tc tvs nc]+> translGlobalDecl flat m tyEnv tcEnv evEnv (FunctionDecl pos f eqs) =+> [translFunction pos flat m tyEnv tcEnv evEnv f eqs]+> translGlobalDecl _ m tyEnv tcEnv _ (ExternalDecl _ cc ie f _) =+> [translExternal m tyEnv tcEnv f cc (fromJust ie)]+> translGlobalDecl _ _ _ _ _ _ = []++> translData :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] -> [ConstrDecl]+> -> IL.Decl+> translData m tyEnv tcEnv tc tvs cs =+> IL.DataDecl (qualifyWith m tc) (length tvs)+> (map (translConstrDecl m tyEnv tcEnv) cs)++> translNewtype :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] +> -> NewConstrDecl -> IL.Decl+> translNewtype m tyEnv tcEnv tc tvs (NewConstrDecl _ _ c _) =+> IL.NewtypeDecl (qualifyWith m tc) (length tvs)+> (IL.ConstrDecl c' (translType' m tyEnv tcEnv ty))+> -- (IL.ConstrDecl c' (translType ty))+> where c' = qualifyWith m c+> TypeArrow ty _ = constrType tyEnv c'++> translConstrDecl :: ModuleIdent -> ValueEnv -> TCEnv -> ConstrDecl+> -> IL.ConstrDecl [IL.Type]+> translConstrDecl m tyEnv tcEnv d =+> IL.ConstrDecl c' (map (translType' m tyEnv tcEnv)+> (arrowArgs (constrType tyEnv c')))+> -- IL.ConstrDecl c' (map translType (arrowArgs (constrType tyEnv c')))+> where c' = qualifyWith m (constr d)+> constr (ConstrDecl _ _ c _) = c+> constr (ConOpDecl _ _ _ op _) = op++> translExternal :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> CallConv+> -> String -> IL.Decl+> translExternal m tyEnv tcEnv f cc ie =+> IL.ExternalDecl f' (callConv cc) ie +> (translType' m tyEnv tcEnv (varType tyEnv f'))+> -- IL.ExternalDecl f' (callConv cc) ie (translType (varType tyEnv f'))+> where f' = qualifyWith m f+> callConv CallConvPrimitive = IL.Primitive+> callConv CallConvCCall = IL.CCall++\end{verbatim}+\paragraph{Interfaces}+In order to generate code, the compiler also needs to know the tags+and arities of all imported data constructors. For that reason we+compile the data type declarations of all interfaces into the+intermediate language, too. In this case we do not lookup the+types in the environment because the types in the interfaces are+already fully expanded. Note that we do not translate data types+which are imported into the interface from some other module.+\begin{verbatim}++> ilTransIntf :: ValueEnv -> TCEnv -> Interface -> [IL.Decl]+> ilTransIntf tyEnv tcEnv (Interface m ds) = +> foldr (translIntfDecl m tyEnv tcEnv) [] ds++> translIntfDecl :: ModuleIdent -> ValueEnv -> TCEnv -> IDecl -> [IL.Decl] +> -> [IL.Decl]+> translIntfDecl m tyEnv tcEnv (IDataDecl _ tc tvs cs) ds+> | not (isQualified tc) = +> translIntfData m tyEnv tcEnv (unqualify tc) tvs cs : ds+> translIntfDecl _ _ _ _ ds = ds++> translIntfData :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] +> -> [Maybe ConstrDecl] -> IL.Decl+> translIntfData m tyEnv tcEnv tc tvs cs =+> IL.DataDecl (qualifyWith m tc) (length tvs)+> (map (maybe hiddenConstr +> (translIntfConstrDecl m tyEnv tcEnv tvs)) cs)+> where hiddenConstr = IL.ConstrDecl qAnonId []+> qAnonId = qualify anonId++> translIntfConstrDecl :: ModuleIdent -> ValueEnv -> TCEnv -> [Ident] +> -> ConstrDecl -> IL.ConstrDecl [IL.Type]+> translIntfConstrDecl m tyEnv tcEnv tvs (ConstrDecl _ _ c tys) =+> IL.ConstrDecl (qualifyWith m c) (map (translType' m tyEnv tcEnv)+> (toQualTypes m tvs tys))+> -- IL.ConstrDecl (qualifyWith m c) (map translType (toQualTypes m tvs tys))+> translIntfConstrDecl m tyEnv tcEnv tvs (ConOpDecl _ _ ty1 op ty2) =+> IL.ConstrDecl (qualifyWith m op)+> (map (translType' m tyEnv tcEnv)+> (toQualTypes m tvs [ty1,ty2]))+> -- IL.ConstrDecl (qualifyWith m op)+> -- (map translType (toQualTypes m tvs [ty1,ty2]))++\end{verbatim}+\paragraph{Types}+The type representation in the intermediate language is the same as+the internal representation except that it does not support+constrained type variables and skolem types. The former are fixed and+the later are replaced by fresh type constructors.++Due to possible occurrence of record types, it is necessary to transform+them back into their corresponding type constructors.+\begin{verbatim}++> translType' :: ModuleIdent -> ValueEnv -> TCEnv -> Type -> IL.Type+> translType' m tyEnv tcEnv ty =+> translType (elimRecordTypes m tyEnv tcEnv (maximum (0:(typeVars ty))) ty)++> translType :: Type -> IL.Type+> translType (TypeConstructor tc tys) =+> IL.TypeConstructor tc (map translType tys)+> translType (TypeVariable tv) = IL.TypeVariable tv+> translType (TypeConstrained tys _) = translType (head tys)+> translType (TypeArrow ty1 ty2) =+> IL.TypeArrow (translType ty1) (translType ty2)+> translType (TypeSkolem k) =+> IL.TypeConstructor (qualify (mkIdent ("_" ++ show k))) []++> elimRecordTypes :: ModuleIdent -> ValueEnv -> TCEnv -> Int -> Type -> Type+> elimRecordTypes m tyEnv tcEnv n (TypeConstructor t tys) =+> TypeConstructor t (map (elimRecordTypes m tyEnv tcEnv n) tys)+> elimRecordTypes m tyEnv tcEnv n (TypeVariable v) =+> TypeVariable v+> elimRecordTypes m tyEnv tcEnv n (TypeConstrained tys v) =+> TypeConstrained (map (elimRecordTypes m tyEnv tcEnv n) tys) v+> elimRecordTypes m tyEnv tcEnv n (TypeArrow t1 t2) =+> TypeArrow (elimRecordTypes m tyEnv tcEnv n t1)+> (elimRecordTypes m tyEnv tcEnv n t2)+> elimRecordTypes m tyEnv tcEnv n (TypeSkolem v) =+> TypeSkolem v+> elimRecordTypes m tyEnv tcEnv n (TypeRecord fs _)+> | null fs = internalError "elimRecordTypes: empty record type"+> | otherwise =+> case (lookupValue (fst (head fs)) tyEnv) of+> [Label _ r _] ->+> case (qualLookupTC r tcEnv) of+> [AliasType _ n' (TypeRecord fs' _)] ->+> let is = [0 .. n'-1]+> vs = foldl (matchTypeVars fs)+> Map.empty+> fs'+> tys = map (\i -> maybe (TypeVariable (i+n))+> (elimRecordTypes m tyEnv tcEnv n)+> (Map.lookup i vs))+> is +> in TypeConstructor r tys+> _ -> internalError "elimRecordTypes: no record type"+> _ -> internalError "elimRecordTypes: no label"++> matchTypeVars :: [(Ident,Type)] -> Map.Map Int Type -> (Ident,Type) +> -> Map.Map Int Type+> matchTypeVars fs vs (l,ty) =+> maybe vs (match vs ty) (lookup l fs)+> where+> match vs (TypeVariable i) ty' = Map.insert i ty' vs+> match vs (TypeConstructor _ tys) (TypeConstructor _ tys') =+> matchList vs tys tys'+> match vs (TypeConstrained tys _) (TypeConstrained tys' _) =+> matchList vs tys tys'+> match vs (TypeArrow ty1 ty2) (TypeArrow ty1' ty2') =+> matchList vs [ty1,ty2] [ty1',ty2']+> match vs (TypeSkolem _) (TypeSkolem _) = vs+> match vs (TypeRecord fs _) (TypeRecord fs' _) =+> foldl (matchTypeVars fs') vs fs+> match vs ty ty' = +> internalError ("matchTypeVars: " ++ show ty ++ "\n" ++ show ty')+>+> matchList vs tys tys' = +> foldl (\vs' (ty,ty') -> match vs' ty ty') vs (zip tys tys')++\end{verbatim}+\paragraph{Functions}+Each function in the program is translated into a function of the+intermediate language. The arguments of the function are renamed such+that all variables occurring in the same position (in different+equations) have the same name. This is necessary in order to+facilitate the translation of pattern matching into a \texttt{case}+expression. We use the following simple convention here: The top-level+arguments of the function are named from left to right \texttt{\_1},+\texttt{\_2}, and so on. The names of nested arguments are constructed+by appending \texttt{\_1}, \texttt{\_2}, etc. from left to right to+the name that were assigned to a variable occurring at the position of+the constructor term.++Some special care is needed for the selector functions introduced by+the compiler in place of pattern bindings. In order to generate the+code for updating all pattern variables, the equality of names between+the pattern variables in the first argument of the selector function+and their repeated occurrences in the remaining arguments must be+preserved. This means that the second and following arguments of a+selector function have to be renamed according to the name mapping+computed for its first argument.++If an evaluation annotation is available for a function, it determines+the evaluation mode of the case expression. Otherwise, the function+uses flexible matching.+\begin{verbatim}++> type RenameEnv = Map.Map Ident Ident++> translFunction :: Position -> Bool -> ModuleIdent -> ValueEnv -> TCEnv+> -> EvalEnv -> Ident -> [Equation] -> IL.Decl+> translFunction pos flat m tyEnv tcEnv evEnv f eqs =+> -- | f == mkIdent "fun" = error (show (translType' m tyEnv tcEnv ty))+> -- | otherwise = +> IL.FunctionDecl f' vs (translType' m tyEnv tcEnv ty) expr+> -- = IL.FunctionDecl f' vs (translType ty)+> -- (match ev vs (map (translEquation tyEnv vs vs'') eqs))+> where f' = qualifyWith m f+> ty = varType tyEnv f'+> -- ty' = elimRecordType m tyEnv tcEnv (maximum (0:(typeVars ty))) ty+> ev' = Map.lookup f evEnv+> ev = maybe (defaultMode ty) evalMode ev'+> vs = if not flat && isFpSelectorId f then translArgs eqs vs' else vs'+> (vs',vs'') = splitAt (equationArity (head eqs)) +> (argNames (mkIdent ""))+> expr | ev' == Just EvalChoice+> = IL.Apply +> (IL.Function +> (qualifyWith preludeMIdent (mkIdent "commit"))+> 1)+> (match (ast pos) IL.Rigid vs +> (map (translEquation tyEnv vs vs'') eqs))+> | otherwise+> = match (ast pos) ev vs (map (translEquation tyEnv vs vs'') eqs)+> ---+> -- (vs',vs'') = splitAt (arrowArity ty) (argNames (mkIdent ""))++> evalMode :: EvalAnnotation -> IL.Eval+> evalMode EvalRigid = IL.Rigid+> evalMode EvalChoice = error "eval choice is not yet supported"++> defaultMode :: Type -> IL.Eval+> defaultMode _ = IL.Flex+>+> --defaultMode ty = if isIO (arrowBase ty) then IL.Rigid else IL.Flex+> -- where TypeConstructor qIOId _ = ioType undefined+> -- isIO (TypeConstructor tc [_]) = tc == qIOId+> -- isIO _ = False++> translArgs :: [Equation] -> [Ident] -> [Ident]+> translArgs [Equation _ (FunLhs _ (t:ts)) _] (v:_) =+> v : map (translArg (bindRenameEnv v t Map.empty)) ts+> where translArg env (VariablePattern v) = fromJust (Map.lookup v env)++> translEquation :: ValueEnv -> [Ident] -> [Ident] -> Equation+> -> ([NestedTerm],IL.Expression)+> translEquation tyEnv vs vs' (Equation _ (FunLhs _ ts) rhs) =+> (zipWith translTerm vs ts,+> translRhs tyEnv vs' (foldr2 bindRenameEnv Map.empty vs ts) rhs)++> translRhs :: ValueEnv -> [Ident] -> RenameEnv -> Rhs -> IL.Expression+> translRhs tyEnv vs env (SimpleRhs _ e _) = translExpr tyEnv vs env e+++> equationArity :: Equation -> Int+> equationArity (Equation _ lhs _) = p_equArity lhs+> where+> p_equArity (FunLhs _ ts) = length ts+> p_equArity (OpLhs _ _ _) = 2+> p_equArity _ = error "ILTrans - illegal equation"+++\end{verbatim}+\paragraph{Pattern Matching}+The pattern matching code searches for the left-most inductive+argument position in the left hand sides of all rules defining an+equation. An inductive position is a position where all rules have a+constructor rooted term. If such a position is found, a \texttt{case}+expression is generated for the argument at that position. The+matching code is then computed recursively for all of the alternatives+independently. If no inductive position is found, the algorithm looks+for the left-most demanded argument position, i.e., a position where+at least one of the rules has a constructor rooted term. If such a+position is found, an \texttt{or} expression is generated with those+cases that have a variable at the argument position in one branch and+all other rules in the other branch. If there is no demanded position,+the pattern matching is finished and the compiler translates the right+hand sides of the remaining rules, eventually combining them using+\texttt{or} expressions.++Actually, the algorithm below combines the search for inductive and+demanded positions. The function \texttt{match} scans the argument+lists for the left-most demanded position. If this turns out to be+also an inductive position, the function \texttt{matchInductive} is+called in order to generate a \texttt{case} expression. Otherwise, the+function \texttt{optMatch} is called that tries to find an inductive+position in the remaining arguments. If one is found,+\texttt{matchInductive} is called, otherwise the function+\texttt{optMatch} uses the demanded argument position found by+\texttt{match}.+\begin{verbatim}++> data NestedTerm = NestedTerm IL.ConstrTerm [NestedTerm] deriving Show++> pattern (NestedTerm t _) = t+> arguments (NestedTerm _ ts) = ts++> translLiteral :: Literal -> IL.Literal+> translLiteral (Char p c) = IL.Char p c+> translLiteral (Int id i) = IL.Int (ast (positionOfIdent id)) i+> translLiteral (Float p f) = IL.Float p f+> translLiteral _ = internalError "translLiteral"++> translTerm :: Ident -> ConstrTerm -> NestedTerm+> translTerm _ (LiteralPattern l) =+> NestedTerm (IL.LiteralPattern (translLiteral l)) []+> translTerm v (VariablePattern _) = NestedTerm (IL.VariablePattern v) []+> translTerm v (ConstructorPattern c ts) =+> NestedTerm (IL.ConstructorPattern c (take (length ts) vs))+> (zipWith translTerm vs ts)+> where vs = argNames v+> translTerm v (AsPattern _ t) = translTerm v t+> translTerm _ _ = internalError "translTerm"++> bindRenameEnv :: Ident -> ConstrTerm -> RenameEnv -> RenameEnv+> bindRenameEnv _ (LiteralPattern _) env = env+> bindRenameEnv v (VariablePattern v') env = Map.insert v' v env+> bindRenameEnv v (ConstructorPattern _ ts) env =+> foldr2 bindRenameEnv env (argNames v) ts+> bindRenameEnv v (AsPattern v' t) env = Map.insert v' v (bindRenameEnv v t env)+> bindRenameEnv _ _ env = internalError "bindRenameEnv"++> argNames :: Ident -> [Ident]+> argNames v = [mkIdent (prefix ++ show i) | i <- [1..]]+> where prefix = name v ++ "_"++> type Match = ([NestedTerm],IL.Expression)+> type Match' = ([NestedTerm] -> [NestedTerm],[NestedTerm],IL.Expression)++> isDefaultPattern :: IL.ConstrTerm -> Bool+> isDefaultPattern (IL.VariablePattern _) = True+> isDefaultPattern _ = False++> isDefaultMatch :: (IL.ConstrTerm,a) -> Bool+> isDefaultMatch = isDefaultPattern . fst++> match :: SrcRef -> IL.Eval -> [Ident] -> [Match] -> IL.Expression+> match _ ev [] alts = foldl1 IL.Or (map snd alts)+> match pos ev (v:vs) alts+> | null vars = e1+> | null nonVars = e2+> | otherwise = optMatch pos ev (IL.Or e1 e2) (v:) vs (map skipArg alts)+> where (vars,nonVars) = partition isDefaultMatch (map tagAlt alts)+> e1 = matchInductive pos ev id v vs nonVars+> e2 = match pos ev vs (map snd vars)+> tagAlt (t:ts,e) = (pattern t,(arguments t ++ ts,e))+> skipArg (t:ts,e) = ((t:),ts,e)++> optMatch :: SrcRef -> IL.Eval -> IL.Expression -> ([Ident] -> [Ident]) +> -> [Ident] ->[Match'] -> IL.Expression+> optMatch _ ev e prefix [] alts = e+> optMatch pos ev e prefix (v:vs) alts+> | null vars = matchInductive pos ev prefix v vs nonVars+> | otherwise = optMatch pos ev e (prefix . (v:)) vs (map skipArg alts)+> where (vars,nonVars) = partition isDefaultMatch (map tagAlt alts)+> tagAlt (prefix,t:ts,e) = (pattern t,(prefix (arguments t ++ ts),e))+> skipArg (prefix,t:ts,e) = (prefix . (t:),ts,e)++> matchInductive :: SrcRef -> IL.Eval -> ([Ident] -> [Ident]) -> Ident +> -> [Ident] ->[(IL.ConstrTerm,Match)] -> IL.Expression+> matchInductive pos ev prefix v vs alts =+> IL.Case pos ev (IL.Variable v) (matchAlts ev prefix vs alts)++> matchAlts :: IL.Eval -> ([Ident] -> [Ident]) -> [Ident] ->+> [(IL.ConstrTerm,Match)] -> [IL.Alt]+> matchAlts ev prefix vs [] = []+> matchAlts ev prefix vs ((t,alt):alts) =+> IL.Alt t (match (srcRefOf t) +> ev (prefix (vars t ++ vs)) (alt : map snd same)) :+> matchAlts ev prefix vs others+> where (same,others) = partition ((t ==) . fst) alts +> vars (IL.ConstructorPattern _ vs) = vs+> vars _ = []++\end{verbatim}+Matching in a \texttt{case}-expression works a little bit differently.+In this case, the alternatives are matched from the first to the last+alternative and the first matching alternative is chosen. All+remaining alternatives are discarded.++\ToDo{The case matching algorithm should use type information in order+to detect total matches and immediately discard all alternatives which+cannot be reached.}+\begin{verbatim}++> caseMatch :: SrcRef -> ([Ident] -> [Ident]) -> [Ident] -> [Match'] +> -> IL.Expression+> caseMatch _ prefix [] alts = thd3 (head alts)+> caseMatch r prefix (v:vs) alts+> | isDefaultMatch (head alts') =+> caseMatch r (prefix . (v:)) vs (map skipArg alts)+> | otherwise =+> IL.Case r IL.Rigid (IL.Variable v) (caseMatchAlts prefix vs alts')+> where alts' = map tagAlt alts+> tagAlt (prefix,t:ts,e) = (pattern t,(prefix,arguments t ++ ts,e))+> skipArg (prefix,t:ts,e) = (prefix . (t:),ts,e)++> caseMatchAlts ::+> ([Ident] -> [Ident]) -> [Ident] -> [(IL.ConstrTerm,Match')] -> [IL.Alt]+> caseMatchAlts prefix vs alts = map caseAlt (ts ++ ts')+> where (ts',ts) = partition isDefaultPattern (nub (map fst alts))+> caseAlt t =+> IL.Alt t (caseMatch (srcRefOf t) id (prefix (vars t ++ vs))+> (matchingCases t alts))+> matchingCases t =+> map (joinArgs (vars t)) . filter (matches t . fst)+> matches t t' = t == t' || isDefaultPattern t'+> joinArgs vs (IL.VariablePattern _,(prefix,ts,e)) =+> (id,prefix (map varPattern vs ++ ts),e)+> joinArgs _ (_,(prefix,ts,e)) = (id,prefix ts,e)+> varPattern v = NestedTerm (IL.VariablePattern v) []+> vars (IL.ConstructorPattern _ vs) = vs+> vars _ = []++\end{verbatim}+\paragraph{Expressions}+Note that the case matching algorithm assumes that the matched+expression is accessible through a variable. The translation of case+expressions therefore introduces a let binding for the scrutinized+expression and immediately throws it away after the matching -- except+if the matching algorithm has decided to use that variable in the+right hand sides of the case expression. This may happen, for+instance, if one of the alternatives contains an \texttt{@}-pattern.+\begin{verbatim}++> translExpr :: ValueEnv -> [Ident] -> RenameEnv -> Expression -> IL.Expression+> translExpr _ _ _ (Literal l) = IL.Literal (translLiteral l)+> translExpr tyEnv _ env (Variable v) =+> case lookupVar v env of+> Just v' -> IL.Variable v'+> Nothing -> IL.Function v (arrowArity (varType tyEnv v))+> where lookupVar v env+> | isQualified v = Nothing+> | otherwise = Map.lookup (unqualify v) env+> translExpr tyEnv _ _ (Constructor c) =+> IL.Constructor c (arrowArity (constrType tyEnv c))+> translExpr tyEnv vs env (Apply e1 e2) =+> IL.Apply (translExpr tyEnv vs env e1) (translExpr tyEnv vs env e2)+> translExpr tyEnv vs env (Let ds e) =+> case ds of+> [ExtraVariables _ vs] -> foldr IL.Exist e' vs+> [d] | all (`notElem` bv d) (qfv emptyMIdent d) ->+> IL.Let (translBinding env' d) e'+> _ -> IL.Letrec (map (translBinding env') ds) e'+> where e' = translExpr tyEnv vs env' e+> env' = foldr2 Map.insert env bvs bvs+> bvs = bv ds+> translBinding env (PatternDecl _ (VariablePattern v) rhs) =+> IL.Binding v (translRhs tyEnv vs env rhs)+> translBinding env p = error $ "unexpected binding: "++show p+> translExpr tyEnv ~(v:vs) env (Case r e alts) =+> case caseMatch r id [v] (map (translAlt v) alts) of+> IL.Case r mode (IL.Variable v') alts'+> | v == v' && v `notElem` fv alts' -> IL.Case r mode e' alts'+> e''+> | v `elem` fv e'' -> IL.Let (IL.Binding v e') e''+> | otherwise -> e''+> where e' = translExpr tyEnv vs env e+> translAlt v (Alt _ t rhs) =+> (id,+> [translTerm v t],+> translRhs tyEnv vs (bindRenameEnv v t env) rhs)+> translExpr _ _ _ _ = internalError "translExpr"++> instance Expr IL.Expression where+> fv (IL.Variable v) = [v]+> fv (IL.Apply e1 e2) = fv e1 ++ fv e2+> fv (IL.Case _ _ e alts) = fv e ++ fv alts+> fv (IL.Or e1 e2) = fv e1 ++ fv e2+> fv (IL.Exist v e) = filter (/= v) (fv e)+> fv (IL.Let (IL.Binding v e1) e2) = fv e1 ++ filter (/= v) (fv e2)+> fv (IL.Letrec bds e) = filter (`notElem` vs) (fv es ++ fv e)+> where (vs,es) = unzip [(v,e) | IL.Binding v e <- bds]+> fv _ = []++> instance Expr IL.Alt where+> fv (IL.Alt (IL.ConstructorPattern _ vs) e) = filter (`notElem` vs) (fv e)+> fv (IL.Alt (IL.VariablePattern v) e) = filter (v /=) (fv e)+> fv (IL.Alt _ e) = fv e++\end{verbatim}+\paragraph{Auxiliary Definitions}+The functions \texttt{varType} and \texttt{constrType} return the type+of variables and constructors, respectively. The quantifiers are+stripped from the types.+\begin{verbatim}++> varType :: ValueEnv -> QualIdent -> Type+> varType tyEnv f =+> case qualLookupValue f tyEnv of+> [Value _ (ForAll _ ty)] -> ty+> _ -> internalError ("varType: " ++ show f)++> constrType :: ValueEnv -> QualIdent -> Type+> constrType tyEnv c =+> case qualLookupValue c tyEnv of+> [DataConstructor _ (ForAllExist _ _ ty)] -> ty+> [NewtypeConstructor _ (ForAllExist _ _ ty)] -> ty+> _ -> internalError ("constrType: " ++ show c)++\end{verbatim}+The list of import declarations in the intermediate language code is+determined by collecting all module qualifiers used in the current+module.+\begin{verbatim}++> imports :: ModuleIdent -> [IL.Decl] -> [ModuleIdent]+> imports m = Set.toList . Set.delete m . Set.fromList . foldr modulesDecl []++> modulesDecl :: IL.Decl -> [ModuleIdent] -> [ModuleIdent]+> modulesDecl (IL.DataDecl _ _ cs) ms = foldr modulesConstrDecl ms cs+> where modulesConstrDecl (IL.ConstrDecl _ tys) ms = foldr modulesType ms tys+> modulesDecl (IL.NewtypeDecl _ _ (IL.ConstrDecl _ ty)) ms = modulesType ty ms+> modulesDecl (IL.FunctionDecl _ _ ty e) ms = modulesType ty (modulesExpr e ms)+> modulesDecl (IL.ExternalDecl _ _ _ ty) ms = modulesType ty ms++> modulesType :: IL.Type -> [ModuleIdent] -> [ModuleIdent]+> modulesType (IL.TypeConstructor tc tys) ms =+> modules tc (foldr modulesType ms tys)+> modulesType (IL.TypeVariable _) ms = ms+> modulesType (IL.TypeArrow ty1 ty2) ms = modulesType ty1 (modulesType ty2 ms)++> modulesExpr :: IL.Expression -> [ModuleIdent] -> [ModuleIdent]+> modulesExpr (IL.Function f _) ms = modules f ms+> modulesExpr (IL.Constructor c _) ms = modules c ms+> modulesExpr (IL.Apply e1 e2) ms = modulesExpr e1 (modulesExpr e2 ms)+> modulesExpr (IL.Case _ _ e as) ms = modulesExpr e (foldr modulesAlt ms as)+> where modulesAlt (IL.Alt t e) ms = modulesConstrTerm t (modulesExpr e ms)+> modulesConstrTerm (IL.ConstructorPattern c _) ms = modules c ms+> modulesConstrTerm _ ms = ms+> modulesExpr (IL.Or e1 e2) ms = modulesExpr e1 (modulesExpr e2 ms)+> modulesExpr (IL.Exist _ e) ms = modulesExpr e ms+> modulesExpr (IL.Let b e) ms = modulesBinding b (modulesExpr e ms)+> modulesExpr (IL.Letrec bs e) ms = foldr modulesBinding (modulesExpr e ms) bs+> modulesExpr _ ms = ms++> modulesBinding :: IL.Binding -> [ModuleIdent] -> [ModuleIdent]+> modulesBinding (IL.Binding _ e) = modulesExpr e++> modules :: QualIdent -> [ModuleIdent] -> [ModuleIdent]+> modules x ms = maybe ms (: ms) (qualidMod x)++\end{verbatim}+
+ src/IL/Pretty.lhs view
@@ -0,0 +1,167 @@+% $Id: ILPP.lhs,v 1.22 2003/10/28 05:43:43 wlux Exp $+%+% Copyright (c) 1999-2003 Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{ILPP.lhs}+\section{A pretty printer for the intermediate language}+This module implements just another pretty printer, this time for the+intermediate language. It was mainly adapted from the Curry pretty+printer (see sect.~\ref{sec:CurryPP}) which, in turn, is based on Simon+Marlow's pretty printer for Haskell.+\begin{verbatim}++> module IL.Pretty(ppModule) where+> +> import Curry.Base.Ident+> +> import IL.Type+> import PrettyCombinators++> default(Int,Double)++> dataIndent = 2+> bodyIndent = 2+> exprIndent = 2+> caseIndent = 2+> altIndent = 2++> ppModule :: Module -> Doc+> ppModule (Module m is ds) =+> vcat (text "module" <+> text (show m) <+> text "where" :+> map ppImport is ++ map ppDecl ds)++> ppImport :: ModuleIdent -> Doc+> ppImport m = text "import" <+> text (show m)++> ppDecl :: Decl -> Doc+> ppDecl (DataDecl tc n cs) =+> sep (text "data" <+> ppTypeLhs tc n :+> map (nest dataIndent)+> (zipWith (<+>) (equals : repeat (char '|')) (map ppConstr cs)))+> ppDecl (NewtypeDecl tc n (ConstrDecl c ty)) =+> sep [text "newtype" <+> ppTypeLhs tc n <+> equals,+> nest dataIndent (ppConstr (ConstrDecl c [ty]))]+> ppDecl (FunctionDecl f vs ty exp) =+> ppTypeSig f ty $$+> sep [ppQIdent f <+> hsep (map ppIdent vs) <+> equals,+> nest bodyIndent (ppExpr 0 exp)]+> ppDecl (ExternalDecl f cc ie ty) =+> sep [text "external" <+> ppCallConv cc <+> text (show ie),+> nest bodyIndent (ppTypeSig f ty)]+> where ppCallConv Primitive = text "primitive"+> ppCallConv CCall = text "ccall"++> ppTypeLhs :: QualIdent -> Int -> Doc+> ppTypeLhs tc n = ppQIdent tc <+> hsep (map text (take n typeVars))++> ppConstr :: ConstrDecl [Type] -> Doc+> ppConstr (ConstrDecl c tys) = ppQIdent c <+> fsep (map (ppType 2) tys)++> ppTypeSig :: QualIdent -> Type -> Doc+> ppTypeSig f ty = ppQIdent f <+> text "::" <+> ppType 0 ty++> ppType :: Int -> Type -> Doc+> ppType p (TypeConstructor tc tys)+> | isQTupleId tc = parens (fsep (punctuate comma (map (ppType 0) tys)))+> | unqualify tc == nilId = brackets (ppType 0 (head tys))+> | otherwise =+> ppParen (p > 1 && not (null tys))+> (ppQIdent tc <+> fsep (map (ppType 2) tys))+> ppType _ (TypeVariable n)+> | n >= 0 = text (typeVars !! n)+> | otherwise = text ('_':show (-n))+> ppType p (TypeArrow ty1 ty2) =+> ppParen (p > 0) (fsep (ppArrow (TypeArrow ty1 ty2)))+> where ppArrow (TypeArrow ty1 ty2) =+> ppType 1 ty1 <+> text "->" : ppArrow ty2+> ppArrow ty = [ppType 0 ty]++> ppBinding :: Binding -> Doc+> ppBinding (Binding v exp) =+> sep [ppIdent v <+> equals,nest bodyIndent (ppExpr 0 exp)]++> ppAlt :: Alt -> Doc+> ppAlt (Alt pat exp) =+> sep [ppConstrTerm pat <+> text "->",nest altIndent (ppExpr 0 exp)]++> ppLiteral :: Literal -> Doc+> ppLiteral (Char _ c) = text (show c)+> ppLiteral (Int _ i) = integer i+> ppLiteral (Float _ f) = double f++> ppConstrTerm :: ConstrTerm -> Doc+> ppConstrTerm (LiteralPattern l) = ppLiteral l+> ppConstrTerm (ConstructorPattern c [v1,v2])+> | isQInfixOp c = ppIdent v1 <+> ppQInfixOp c <+> ppIdent v2+> ppConstrTerm (ConstructorPattern c vs)+> | isQTupleId c = parens (fsep (punctuate comma (map ppIdent vs)))+> | otherwise = ppQIdent c <+> fsep (map ppIdent vs)+> ppConstrTerm (VariablePattern v) = ppIdent v++> ppExpr :: Int -> Expression -> Doc+> ppExpr p (Literal l) = ppLiteral l+> ppExpr p (Variable v) = ppIdent v+> ppExpr p (Function f _) = ppQIdent f+> ppExpr p (Constructor c _) = ppQIdent c+> ppExpr p (Apply (Apply (Function f _) e1) e2)+> | isQInfixOp f = ppInfixApp p e1 f e2+> ppExpr p (Apply (Apply (Constructor c _) e1) e2)+> | isQInfixOp c = ppInfixApp p e1 c e2+> ppExpr p (Apply e1 e2) =+> ppParen (p > 2) (sep [ppExpr 2 e1,nest exprIndent (ppExpr 3 e2)])+> ppExpr p (Case _ ev e alts) =+> ppParen (p > 0)+> (text "case" <+> ppEval ev <+> ppExpr 0 e <+> text "of" $$+> nest caseIndent (vcat (map ppAlt alts)))+> where ppEval Rigid = text "rigid"+> ppEval Flex = text "flex"+> ppExpr p (Or e1 e2) =+> ppParen (p > 0) (sep [ppExpr 0 e1,char '|' <+> ppExpr 0 e2])+> ppExpr p (Exist v e) =+> ppParen (p > 0)+> (sep [text "let" <+> ppIdent v <+> text "free" <+> text "in",+> ppExpr 0 e])+> ppExpr p (Let b e) =+> ppParen (p > 0) (sep [text "let" <+> ppBinding b <+> text "in",ppExpr 0 e])+> ppExpr p (Letrec bs e) =+> ppParen (p > 0)+> (sep [text "letrec" <+> vcat (map ppBinding bs) <+> text "in",+> ppExpr 0 e])++> ppInfixApp :: Int -> Expression -> QualIdent -> Expression -> Doc+> ppInfixApp p e1 op e2 =+> ppParen (p > 1)+> (sep [ppExpr 2 e1 <+> ppQInfixOp op,nest exprIndent (ppExpr 2 e2)])++> ppIdent :: Ident -> Doc+> ppIdent ident+> | isInfixOp ident = parens (ppName ident)+> | otherwise = ppName ident++> ppQIdent :: QualIdent -> Doc+> ppQIdent ident+> | isQInfixOp ident = parens (ppQual ident)+> | otherwise = ppQual ident++> ppQInfixOp :: QualIdent -> Doc+> ppQInfixOp op+> | isQInfixOp op = ppQual op+> | otherwise = char '`' <> ppQual op <> char '`'++> ppName :: Ident -> Doc+> ppName x = text (name x)++> ppQual :: QualIdent -> Doc+> ppQual x = text (qualName x)++> typeVars :: [String]+> typeVars = [mkTypeVar c i | i <- [0..], c <- ['a' .. 'z']]+> where mkTypeVar c i = c : if i == 0 then [] else show i++> ppParen :: Bool -> Doc -> Doc+> ppParen p = if p then parens else id++\end{verbatim}
+ src/IL/Scope.hs view
@@ -0,0 +1,124 @@+module IL.Scope (getModuleScope,+ insertDeclScope, insertConstrDeclScope,+ insertCallConvScope, insertTypeScope,+ insertLiteralScope, insertConstrTermScope,+ insertExprScope, insertAltScope,+ insertBindingScope) where++import Curry.Base.Ident++import IL.Type+import OldScopeEnv as ScopeEnv+++-------------------------------------------------------------------------------++--+getModuleScope :: Module -> ScopeEnv+getModuleScope (Module _ _ decls) = foldl insertDecl newScopeEnv decls+++--+insertDeclScope :: ScopeEnv -> Decl -> ScopeEnv+insertDeclScope env (DataDecl _ _ _) = env+insertDeclScope env (NewtypeDecl _ _ _) = env+insertDeclScope env (FunctionDecl _ params _ _)+ = foldr ScopeEnv.insertIdent (ScopeEnv.beginScope env) params+insertDeclScope env (ExternalDecl _ _ _ _) = env+++--+insertConstrDeclScope :: ScopeEnv -> ConstrDecl [Type] -> ScopeEnv+insertConstrDeclScope env _ = env+++--+insertCallConvScope :: ScopeEnv -> CallConv -> ScopeEnv+insertCallConvScope env _ = env+++--+insertTypeScope :: ScopeEnv -> Type -> ScopeEnv+insertTypeScope env _ = env+++--+insertLiteralScope :: ScopeEnv -> Literal -> ScopeEnv+insertLiteralScope env _ = env+++--+insertConstrTermScope :: ScopeEnv -> ConstrTerm -> ScopeEnv+insertConstrTermScope env _ = env+++--+insertExprScope :: ScopeEnv -> Expression -> ScopeEnv+insertExprScope env (Literal _) = env+insertExprScope env (Variable _) = env+insertExprScope env (Function _ _) = env+insertExprScope env (Constructor _ _) = env+insertExprScope env (Apply _ _) = env+insertExprScope env (Case _ _ _ _) = env+insertExprScope env (Or _ _) = env+insertExprScope env (Exist ident _)+ = ScopeEnv.insertIdent ident (ScopeEnv.beginScope env)+insertExprScope env (Let bind _)+ = insertBinding (beginScope env) bind+insertExprScope env (Letrec binds _)+ = foldl insertBinding (beginScope env) binds+++--+insertAltScope :: ScopeEnv -> Alt -> ScopeEnv+insertAltScope env (Alt cterm _)+ = insertConstrTerm (ScopeEnv.beginScope env) cterm+++--+insertBindingScope :: ScopeEnv -> Binding -> ScopeEnv+insertBindingScope env _ = env+++-------------------------------------------------------------------------------+-------------------------------------------------------------------------------++--+insertDecl :: ScopeEnv -> Decl -> ScopeEnv+insertDecl env (DataDecl qident _ cdecls)+ = foldl insertConstrDecl+ (ScopeEnv.insertIdent (unqualify qident) env)+ cdecls++insertDecl env (NewtypeDecl qident _ cdecl)+ = insertConstrDecl (ScopeEnv.insertIdent (unqualify qident) env) cdecl++insertDecl env (FunctionDecl qident _ _ _)+ = ScopeEnv.insertIdent (unqualify qident) env++insertDecl env (ExternalDecl qident _ _ _)+ = ScopeEnv.insertIdent (unqualify qident) env+++--+insertConstrDecl :: ScopeEnv -> ConstrDecl a -> ScopeEnv+insertConstrDecl env (ConstrDecl qident _)+ = ScopeEnv.insertIdent (unqualify qident) env+++--+insertConstrTerm :: ScopeEnv -> ConstrTerm -> ScopeEnv+insertConstrTerm env (LiteralPattern _) = env+insertConstrTerm env (ConstructorPattern _ params)+ = foldr ScopeEnv.insertIdent env params+insertConstrTerm env (VariablePattern ident)+ = ScopeEnv.insertIdent ident env+++--+insertBinding :: ScopeEnv -> Binding -> ScopeEnv+insertBinding env (Binding ident _) = ScopeEnv.insertIdent ident env+++-------------------------------------------------------------------------------+-------------------------------------------------------------------------------
+ src/IL/Type.lhs view
@@ -0,0 +1,109 @@+% $Id: IL.lhs,v 1.18 2003/10/28 05:43:38 wlux Exp $+%+% Copyright (c) 1999-2003 Wolfgang Lux+% See LICENSE for the full license.+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{IL.lhs}+\section{The intermediate language}+The module \texttt{IL} defines the intermediate language which will be+compiled into abstract machine code. The intermediate language removes+a lot of syntactic sugar from the Curry source language. Top-level+declarations are restricted to data type and function definitions. A+newtype definition serves mainly as a hint to the backend that it must+provide an auxiliary function for partial applications of the+constructor. \textbf{Newtype constructors must not occur in patterns+and may be used in expressions only as partial applications.}++Type declarations use a de-Bruijn indexing scheme (starting at 0) for+type variables. In the type of a function, all type variables are+numbered in the order of their occurence from left to right, i.e., a+type \texttt{(Int -> b) -> (a,b) -> c -> (a,c)} is translated into the+type (using integer numbers to denote the type variables)+\texttt{(Int -> 0) -> (1,0) -> 2 -> (1,2)}.++Pattern matching in an equation is handled via flexible and rigid+\texttt{Case} expressions. Overlapping rules are translated with the+help of \texttt{Or} expressions. The intermediate language has three+kinds of binding expressions, \texttt{Exist} expressions introduce a+new logical variable, \texttt{Let} expression support a single+non-recursive variable binding, and \texttt{Letrec} expressions+introduce multiple variables with recursive initializer expressions.+The intermediate language explicitly distinguishes (local) variables+and (global) functions in expressions.++\em{Note:} this modified version uses haskell type \texttt{Integer}+instead of \texttt{Int} for representing integer values. This provides+an unlimited range of integer constants in Curry programs.+\begin{verbatim}++> module IL.Type where++> import Curry.Base.Ident+> import Curry.Base.Position (SrcRef(..))++> data Module = Module ModuleIdent [ModuleIdent] [Decl] deriving (Eq,Show)++> data Decl = +> DataDecl QualIdent Int [ConstrDecl [Type]]+> | NewtypeDecl QualIdent Int (ConstrDecl Type)+> | FunctionDecl QualIdent [Ident] Type Expression+> | ExternalDecl QualIdent CallConv String Type+> deriving (Eq,Show)++> data ConstrDecl a = ConstrDecl QualIdent a deriving (Eq,Show)+> data CallConv = Primitive | CCall deriving (Eq,Show)++> data Type =+> TypeConstructor QualIdent [Type]+> | TypeVariable Int+> | TypeArrow Type Type+> deriving (Eq,Show)++> data Literal = Char SrcRef Char | Int SrcRef Integer | Float SrcRef Double deriving (Eq,Show)++> data ConstrTerm =+> -- literal patterns+> LiteralPattern Literal+> -- constructors+> | ConstructorPattern QualIdent [Ident]+> -- default+> | VariablePattern Ident+> deriving (Eq,Show)++> data Expression =+> -- literal constants+> Literal Literal+> -- variables, functions, constructors+> | Variable Ident | Function QualIdent Int | Constructor QualIdent Int+> -- applications+> | Apply Expression Expression+> -- case expressions+> | Case SrcRef Eval Expression [Alt]+> -- non-determinisismic or+> | Or Expression Expression+> -- binding forms+> | Exist Ident Expression+> | Let Binding Expression+> | Letrec [Binding] Expression+> deriving (Eq,Show)++> data Eval = Rigid | Flex deriving (Eq,Show)+> data Alt = Alt ConstrTerm Expression deriving (Eq,Show)+> data Binding = Binding Ident Expression deriving (Eq,Show)++\end{verbatim}++> instance SrcRefOf ConstrTerm where+> srcRefOf (LiteralPattern l) = srcRefOf l+> srcRefOf (ConstructorPattern i _) = srcRefOf i+> srcRefOf (VariablePattern i) = srcRefOf i+++> instance SrcRefOf Literal where+> srcRefOf (Char s _) = s+> srcRefOf (Int s _) = s+> srcRefOf (Float s _) = s ++
+ src/IL/XML.lhs view
@@ -0,0 +1,518 @@++% $Id: ILxml.lhs,v 1.0 2001/06/19 12:19:18 rafa Exp $+%+% $Log: ILxml.lhs,v $+%+% Revision 1.1 2001/06/19 12:19:18 rafa+% Pretty printer in XML for the intermediate language added.+%+%+% Modified by Martin Engelke (men@informatik.uni-kiel.de)+%+\nwfilename{ILxml.lhs}+\section{A pretty printer in XML for the intermediate language}+This module implements just another pretty printer, this time in XML and for+the intermediate language. It was mainly adapted from the Curry pretty+printer (see sect.~\ref{sec:CurryPP}), which in turn is based on Simon+Marlow's pretty printer for Haskell. The format of the output intends to be+similar to that of Flat-Curry XML representation.+\begin{verbatim}++> module IL.XML(module IL.XML) where++> import Data.Maybe++> import Curry.Base.Ident+> import qualified Curry.Syntax as CS++> import IL.Type+> import CurryEnv+> import PrettyCombinators++++> -- identation level+> level::Int+> level = 3++> xmlModule :: CurryEnv -> Module -> Doc+> xmlModule cEnv m = text "<prog>" $$ nest level (xmlBody cEnv m) +> $$ text "</prog>"++> xmlBody :: CurryEnv -> Module -> Doc+> xmlBody cEnv (Module name imports decls) =+> xmlElement "module" xmlModuleDecl moduleDecl $$+> xmlElement "import" xmlImportDecl importDecl $$+> xmlElement "types" xmlTypeDecl typeDecl $$+> xmlElement "functions" xmlFunctionDecl functionDecl $$+> xmlElement "operators" xmlOperatorDecl operatorDecl $$+> xmlElement "translation" xmlTranslationDecl translationDecl+> where+> moduleDecl = [name]+> importDecl = imports+> operatorDecl = infixDecls cEnv+> translationDecl = foldl (qualIDeclId (moduleId cEnv))+> [] +> (interface cEnv)+> (functionDecl,typeDecl) = splitDecls decls++> -- =========================================================================++> xmlModuleDecl :: ModuleIdent -> Doc+> xmlModuleDecl name = xmlModuleIdent name++> -- =========================================================================++> xmlImportDecl :: ModuleIdent -> Doc+> xmlImportDecl name = xmlElement "module" xmlModuleDecl [name]+++> -- =========================================================================+> -- T Y P E S+> -- =========================================================================++> xmlTypeDecl :: Decl -> Doc+> xmlTypeDecl (DataDecl tc arity cs) =+> beginType $$+> nest level (xmlTypeParams arity) $$+> xmlLines xmlConstructor cs $$+> endType+> where+> beginType = text "<type name=\"" <> (xmlQualIdent tc) <> text "\">"+> endType = text "</type>"++> xmlTypeParams :: Int -> Doc+> xmlTypeParams n = xmlElement "params" xmlTypeVar [0..(n-1)]++> xmlConstructor :: ConstrDecl [Type] -> Doc+> xmlConstructor (ConstrDecl ident []) = xmlConstructorBegin ident 0+> xmlConstructor (ConstrDecl ident l) =+> xmlConstructorBegin ident (length l) $$+> xmlLines xmlType l $$+> xmlConstructorEnd+> where+> xmlConstructorEnd = text "</cons>"++> xmlConstructorBegin :: QualIdent -> Int -> Doc+> xmlConstructorBegin ident n = xmlHeadingWithArity "cons" ident n (n==0)++> xmlHeadingWithArity :: String -> QualIdent -> Int -> Bool -> Doc+> xmlHeadingWithArity tagName ident n single =+> if single+> then prefix<>text "/>"+> else prefix<> text ">"+> where+> prefix = text ("<"++tagName++" name=\"") <> name <> text "\" " <> arity+> arity = text "arity=\"" <> xmlInt n <> text "\""+> name = xmlQualIdent ident+++> xmlType :: Type -> Doc+> xmlType (TypeConstructor ident []) = xmlTypeConsBegin ident True+> xmlType (TypeConstructor ident l) = xmlTypeConsBegin ident False $$+> xmlLines xmlType l $$+> xmlTypeConsEnd+> where+> xmlTypeConsEnd = text "</tcons>"++> xmlType (TypeVariable n) = xmlTypeVar n+> xmlType (TypeArrow a b) = xmlTypeFun a b++> xmlTypeConsBegin :: QualIdent -> Bool -> Doc+> xmlTypeConsBegin ident single =+> if single+> then prefix <> text "/>"+> else prefix <> text ">"+> where+> name = xmlQualIdent ident+> prefix = text "<tcons name=\"" <> name <> text "\""++> xmlTypeVar :: Int -> Doc+> xmlTypeVar n = text "<tvar>"<> xmlInt n <> text "</tvar>"++> xmlTypeFun :: Type -> Type -> Doc+> xmlTypeFun a b = xmlElement "functype" xmlType [a,b]+++> -- =========================================================================+> -- F U N C T I O N S+> -- =========================================================================++> xmlFunctionDecl :: Decl -> Doc+> xmlFunctionDecl (NewtypeDecl tc arity (ConstrDecl ident ty)) =+> xmlFunctionDecl (FunctionDecl ident [arg] ftype (Variable arg))+> where+> arg = mkIdent "_1"+> ftype = TypeArrow ty (TypeConstructor tc (map TypeVariable [0..arity-1]))++> xmlFunctionDecl (FunctionDecl ident largs fType expr) =+> heading $$ nest level (xmlRule largs expr) $$ end+> where+> heading = xmlBeginFunction ident (length largs) fType+> end = text "</func>"++> xmlFunctionDecl (ExternalDecl ident callConv internalName fType) =+> heading $$ external $$ end+> where+> heading = xmlBeginFunction ident (xmlFunctionArity fType) fType+> external = text ("<external>"+> ++ xmlFormat internalName+> ++ "</external>")+> end = text "</func>"++> xmlBeginFunction :: QualIdent -> Int -> Type -> Doc+> xmlBeginFunction ident n fType =+> heading $$ typeDecls+> where+> heading = xmlHeadingWithArity "func" ident n False+> typeDecls = nest level (xmlType fType)++> xmlEndFunction :: Doc+> xmlEndFunction = text "</func>"++> xmlFunctionArity :: Type -> Int+> xmlFunctionArity (TypeConstructor ident l) = 0+> xmlFunctionArity (TypeVariable n) = 0+> xmlFunctionArity (TypeArrow a b) = 1 + (xmlFunctionArity b)++> xmlRule :: [Ident] -> Expression -> Doc+> xmlRule lArgs e = text "<rule>" $$+> nest level (xmlLhs lArgs) $$+> nest level (xmlRhs lArgs e) $$+> text "</rule>"++> xmlLhs :: [Ident] -> Doc+> xmlLhs l = xmlElement "lhs" xmlVar [0..((length l)-1)]++> xmlRhs :: [Ident] -> Expression -> Doc+> xmlRhs l e = text "<rhs>" $$ nest level rhs $$ text "</rhs>"+> where+> varDicc = xmlBuildDicc l+> (rhs, _) = xmlExpr varDicc e++> -- =========================================================================++> -- =========================================================================+> -- E X P R E S S I O N S+> -- =========================================================================++> xmlExpr :: [(Int,Ident)] -> Expression -> (Doc,[(Int,Ident)])+> xmlExpr d (Literal lit) = (xmlLiteral (xmlLit lit),d)+> xmlExpr d (Variable ident) = xmlExprVar d ident+> xmlExpr d (Function ident arity) = (xmlSingleApp ident arity True,d)+> xmlExpr d (Constructor ident arity) = (xmlSingleApp ident arity False,d)+> xmlExpr d exp@(Apply e1 e2) = xmlApply d exp (xmlAppArgs exp)+> xmlExpr d (Case _ eval expr alt) = xmlCase d eval expr alt+> xmlExpr d (Or expr1 expr2) = xmlOr d expr1 expr2+> xmlExpr d (Exist ident expr) = xmlFree d ident expr+> xmlExpr d (Let binding expr) = xmlLet d binding expr+> xmlExpr d (Letrec lBinding expr) = xmlLetrec d lBinding expr+> --error "Recursive let bindings not supported in FlatCurry"++> -- =========================================================================++> xmlSingleApp :: QualIdent -> Int -> Bool -> Doc+> xmlSingleApp ident arity isFunction =+> if arity>0+> then xmlCombHeading identDoc (text "PartCall") True+> else xmlCombHeading identDoc (text totalApp) True+> where+> identDoc = xmlQualIdent ident+> totalApp = if isFunction then "FuncCall" else "ConsCall"+++> xmlCombHeading :: Doc -> Doc -> Bool -> Doc+> xmlCombHeading name cType single =+> if single+> then prefix <> text " />"+> else prefix <> text ">"+> where+> prefix = text "<comb type=\""<>cType<>text "\" name=\""<>name<>text "\""++> -- =========================================================================++> xmlExprVar :: [(Int,Ident)] -> Ident -> (Doc,[(Int,Ident)])+> xmlExprVar d ident =+> if isNew+> then (xmlVar newVar, (newVar,ident):d)+> else (xmlVar var, d)+> where+> var = xmlLookUp ident d+> isNew = var == -1+> newVar = xmlNewVar d++> -- =========================================================================+++> xmlApply :: [(Int,Ident)] -> Expression -> (Expression,[Expression]) ->+> (Doc,[(Int,Ident)])++> xmlApply d exp ((Function ident arity),lExp) =+> xmlApplyFunctor d ident arity lExp True++> xmlApply d exp ((Constructor ident arity),lExp) =+> xmlApplyFunctor d ident arity lExp False++> xmlApply d (Apply expr1 expr2) e' =+> (text "<apply>" $$ nest level e1 $$ nest level e2 $$ text "</apply>", d2)+> where+> (e1,d1) = xmlExpr d expr1+> (e2,d2) = xmlExpr d1 expr2++> xmlApplyFunctor ::[(Int,Ident)] -> QualIdent -> Int -> [Expression] ->+> Bool -> (Doc,[(Int,Ident)])+> xmlApplyFunctor d ident arity lArgs isFunction =+> xmlCombApply d (xmlQualIdent ident) (text cTypeS) n lArgs+> where+> n = length (lArgs)+> cTypeS = if n==arity+> then if isFunction+> then "FuncCall"+> else "ConsCall"+> else "PartCall"+++> xmlCombApply :: [(Int,Ident)] -> Doc -> Doc -> Int ->+> [Expression] -> (Doc,[(Int,Ident)])+> xmlCombApply d name cType 0 lArgs =+> (xmlCombHeading name cType True,d)+> xmlCombApply d name cType n lArgs =+> (xmlCombHeading name cType False $$ xmlLines id lDocs$$ text "</comb>", d1)+> where+> (lDocs,d1) = xmlMapDicc d xmlExpr lArgs+++> xmlAppArgs :: Expression -> (Expression,[Expression])+> xmlAppArgs (Apply e1 e2) = (e,lArgs++[e2])+> where+> (e,lArgs) = (xmlAppArgs e1)+> xmlAppArgs e = (e,[])+> -- =========================================================================+++> -- =========================================================================++> xmlCase :: [(Int,Ident)] -> Eval -> Expression -> [Alt] -> (Doc,[(Int,Ident)])+> xmlCase d eval expr lAlt =+> (heading $$ nest level e1 $$ xmlLines id lDocs$$ end,d2)+> where+> sEval = if eval==Rigid then "\"Rigid\"" else "\"Flex\""+> heading = text "<case type=" <> text sEval <> text ">"+> end = text "</case>"+> (e1,_) = xmlExpr d expr+> (lDocs,d2) = xmlMapDicc d xmlBranch lAlt++> xmlOr :: [(Int,Ident)] -> Expression -> Expression -> (Doc,[(Int,Ident)])+> xmlOr d expr1 expr2 =+> (text "<or>" $$ nest level e1 $$ nest level e2 $$ text "</or>",d2)+> where+> (e1,d1) = xmlExpr d expr1+> (e2,d2) = xmlExpr d1 expr2+++> xmlBranch :: [(Int,Ident)] -> Alt -> (Doc,[(Int,Ident)])+> xmlBranch d (Alt pattern expr) =+> (text "<branch>" $$ nest level e1 $$ nest level e2 $$ text "</branch>",d2)+> where+> (e1,d1) = xmlPattern d pattern+> (e2,d2) = xmlExpr d1 expr+++> xmlPattern :: [(Int,Ident)] -> ConstrTerm -> (Doc,[(Int,Ident)])+> xmlPattern d (LiteralPattern lit) = (xmlLitPattern (xmlLit lit),d)+> xmlPattern d (ConstructorPattern ident lArgs) = xmlConsPattern d ident lArgs+> xmlPattern d (VariablePattern _) = error "Variable patterns not allowed in Flat Curry"++> xmlConsPattern :: [(Int,Ident)] -> QualIdent -> [Ident] -> (Doc,[(Int,Ident)])+> xmlConsPattern d ident lArgs =+> (heading $$ xmlLines id lDocs $$ end,d2)+> where+> heading = text "<pattern name=\""<> (xmlQualIdent ident) <>+> text "\"" <> endh+> endh = if (length lArgs)>0 then text ">" else text "/>"+> end = if (length lArgs)>0 then text "</pattern>" else empty+> (lDocs,d2) = xmlMapDicc d xmlExprVar lArgs++> -- =========================================================================+++> xmlFree :: [(Int,Ident)] -> Ident -> Expression -> (Doc,[(Int,Ident)])+> xmlFree d ident exp =+> (text "<freevars>" $$ nest level v $$ nest level e $$ text "</freevars>",d2)+> where+> (v,d1) = xmlExprVar d ident+> (e,d2) = xmlExpr d1 exp+++> -- =========================================================================++> xmlLet :: [(Int,Ident)] -> Binding -> Expression -> (Doc,[(Int,Ident)])+> xmlLet d binding exp =+> (text "<let>" $$ nest level b $$ nest level e $$ text "</let>", d2)+> where+> (b,d1) = xmlBinding d binding+> (e,d2) = xmlExpr d1 exp++> xmlBinding :: [(Int,Ident)] -> Binding -> (Doc,[(Int,Ident)])+> xmlBinding d (Binding ident exp) =+> (text "<binding>" $$ nest level v $$ nest level e $$ text "</binding>",d2)+> where+> (v,_) = xmlExprVar d ident+> (e,d2) = xmlExpr d exp++> -- =========================================================================++> xmlLetrec :: [(Int,Ident)] -> [Binding] -> Expression -> (Doc,[(Int,Ident)])+> xmlLetrec d lB exp =+> (text "<letrec>" $$ xmlLines id b $$ nest level e $$ text "</letrec>",d2)+> where+> (b,d1) = xmlMapDicc d xmlBinding lB+> (e,d2) = xmlExpr d1 exp++> -- =========================================================================+++> -- =========================================================================+> -- A U X I L I A R Y F U N C T I O N S+> -- =========================================================================++> splitDecls :: [Decl] -> ([Decl],[Decl])+> splitDecls [] = ([],[])+> splitDecls (x:xs) = case x of+> DataDecl _ _ _ -> (functionDecl,x:typeDecl)+> NewtypeDecl _ _ _ -> (x:functionDecl,typeDecl)+> FunctionDecl _ _ _ _ -> (x:functionDecl,typeDecl)+> ExternalDecl _ _ _ _ -> (x:functionDecl,typeDecl)+> where+> (functionDecl,typeDecl) = splitDecls xs+++++> xmlElement :: Eq a => String -> (a -> Doc) -> [a] -> Doc+> xmlElement name f [] = text ("<"++name++" />")+> xmlElement name f lDecls = beginElement $$ xmlLines f lDecls $$ endElement+> where+> beginElement = text ("<"++name++">")+> endElement = text ("</"++name++">")+>++> xmlLines :: (a -> Doc) -> [a] -> Doc+> xmlLines f = (nest level).vcat.(map f)+++> xmlMapDicc::[(Int,Ident)] -> ([(Int,Ident)] -> a -> (Doc,[(Int,Ident)])) ->+> [a] -> ([Doc],[(Int,Ident)])+> xmlMapDicc d f lArgs = foldl newArg ([],d) lArgs+> where+> newArg (l,d) e = (l++[v'],d')+> where (v',d') = f d e+>+++> -- The dictionary identifies var names with integers+> -- it will be ordered starting at the greatest integer+> xmlBuildDicc :: [Ident] -> [(Int,Ident)]+> xmlBuildDicc l = reverse (zip [0..((length l)-1)] l)++> -- looks for a ident in the dictorionary. If it appears returns its+> -- associated value. Otherwise, -1 is returned+> xmlLookUp :: Ident -> [(Int,Ident)] -> Int+> xmlLookUp ident [] = -1+> xmlLookUp ident ((n,name):xs) = if ident==name+> then n+> else xmlLookUp ident xs++> -- generates a integer corresponding to a new var+> xmlNewVar :: [(Int,Ident)] -> Int+> xmlNewVar [] = 0+> xmlNewVar ((n,ident):xs) = n+1++> xmlVar :: Int -> Doc+> xmlVar n = text "<var>" <> xmlInt n <> text "</var>"++> xmlLiteral :: Doc -> Doc+> xmlLiteral d = text "<lit>" $$ nest level d $$ text "</lit>"++> xmlLitPattern :: Doc -> Doc+> xmlLitPattern d = text "<lpattern>" $$ nest level d $$ text "</lpattern>"+++> xmlLit :: Literal -> Doc+> xmlLit (Char _ c) = text "<charc>" <> xmlInt (fromEnum c) <> text "</charc>"+> xmlLit (Int _ n) = text "<intc>" <> xmlInteger n <> text "</intc>"+> xmlLit (Float _ n) = text "<floatc>" <> xmlFloat n <> text "</floatc>"++> xmlOperatorDecl :: CS.IDecl -> Doc+> xmlOperatorDecl (CS.IInfixDecl _ fixity prec qident) =+> text "<op fixity=\"" <> xmlFixity fixity +> <> text "\" prec=\"" <> xmlInteger prec <> text "\">"+> <> xmlIdent (unqualify qident)+> <> text "</op>"++> xmlFixity :: CS.Infix -> Doc+> xmlFixity CS.InfixL = text "InfixlOp"+> xmlFixity CS.InfixR = text "InfixrOp"+> xmlFixity CS.Infix = text "InfixOp"+++> xmlTranslationDecl :: QualIdent -> Doc+> xmlTranslationDecl expId =+> text "<trans>" +> $$ nest level ( text "<name>" <> xmlIdent (unqualify expId) <> text "</name>"+> $$ text "<intname>" <> xmlQualIdent expId <> text "</intname>")+> $$ text "</trans>"+++> xmlIdent :: Ident -> Doc+> xmlIdent ident = text (xmlFormat (name ident))++> xmlInt :: Int -> Doc+> xmlInt n = text (show n)++> xmlInteger :: Integer -> Doc+> xmlInteger n = text (show n)++> xmlFloat :: Double -> Doc+> xmlFloat n = text (show n)++> xmlQualIdent :: QualIdent -> Doc+> xmlQualIdent ident = text (xmlFormat (qualName ident))++> xmlModuleIdent:: ModuleIdent -> Doc+> xmlModuleIdent name = text (xmlFormat (moduleName name))++> xmlFormat :: String -> String+> xmlFormat [] = []+> xmlFormat ('>':xs) = ">"++xmlFormat xs+> xmlFormat ('<':xs) = "<"++xmlFormat xs+> xmlFormat ('&':xs) = "&"++xmlFormat xs+> xmlFormat (x:xs) = x:(xmlFormat xs)++> -- =========================================================================++> qualIDeclId :: ModuleIdent -> [QualIdent] -> CS.IDecl -> [QualIdent]+> qualIDeclId mid qids (CS.IDataDecl _ qid _ mcdecls)+> = foldl (qualConstrDeclId mid) (qid:qids) (catMaybes mcdecls)+> qualIDeclId mid qids (CS.INewtypeDecl _ qid _ ncdecl)+> = qualNewConstrDeclId mid (qid:qids) ncdecl+> qualIDeclId mid qids (CS.ITypeDecl _ qid _ _)+> = qid:qids+> qualIDeclId mid qids (CS.IFunctionDecl _ qid _ _)+> = qid:qids+> qualIDeclId mid qids _ = qids++> qualConstrDeclId :: ModuleIdent -> [QualIdent] -> CS.ConstrDecl +> -> [QualIdent]+> qualConstrDeclId mid qids (CS.ConstrDecl _ _ id _)+> = (qualifyWith mid id):qids+> qualConstrDeclId mid qids (CS.ConOpDecl _ _ _ id _)+> = (qualifyWith mid id):qids++> qualNewConstrDeclId :: ModuleIdent -> [QualIdent] -> CS.NewConstrDecl +> -> [QualIdent]+> qualNewConstrDeclId mid qids (CS.NewConstrDecl _ _ id _)+> = (qualifyWith mid id):qids+++\end{verbatim}
− src/ILPP.lhs
@@ -1,166 +0,0 @@-% -*- LaTeX -*--% $Id: ILPP.lhs,v 1.22 2003/10/28 05:43:43 wlux Exp $-%-% Copyright (c) 1999-2003 Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{ILPP.lhs}-\section{A pretty printer for the intermediate language}-This module implements just another pretty printer, this time for the-intermediate language. It was mainly adapted from the Curry pretty-printer (see sect.~\ref{sec:CurryPP}) which, in turn, is based on Simon-Marlow's pretty printer for Haskell.-\begin{verbatim}--> module ILPP(module ILPP, Doc) where-> import Ident-> import IL-> import Pretty--> default(Int,Double)--> dataIndent = 2-> bodyIndent = 2-> exprIndent = 2-> caseIndent = 2-> altIndent = 2--> ppModule :: Module -> Doc-> ppModule (Module m is ds) =-> vcat (text "module" <+> text (show m) <+> text "where" :-> map ppImport is ++ map ppDecl ds)--> ppImport :: ModuleIdent -> Doc-> ppImport m = text "import" <+> text (show m)--> ppDecl :: Decl -> Doc-> ppDecl (DataDecl tc n cs) =-> sep (text "data" <+> ppTypeLhs tc n :-> map (nest dataIndent)-> (zipWith (<+>) (equals : repeat (char '|')) (map ppConstr cs)))-> ppDecl (NewtypeDecl tc n (ConstrDecl c ty)) =-> sep [text "newtype" <+> ppTypeLhs tc n <+> equals,-> nest dataIndent (ppConstr (ConstrDecl c [ty]))]-> ppDecl (FunctionDecl f vs ty exp) =-> ppTypeSig f ty $$-> sep [ppQIdent f <+> hsep (map ppIdent vs) <+> equals,-> nest bodyIndent (ppExpr 0 exp)]-> ppDecl (ExternalDecl f cc ie ty) =-> sep [text "external" <+> ppCallConv cc <+> text (show ie),-> nest bodyIndent (ppTypeSig f ty)]-> where ppCallConv Primitive = text "primitive"-> ppCallConv CCall = text "ccall"--> ppTypeLhs :: QualIdent -> Int -> Doc-> ppTypeLhs tc n = ppQIdent tc <+> hsep (map text (take n typeVars))--> ppConstr :: ConstrDecl [Type] -> Doc-> ppConstr (ConstrDecl c tys) = ppQIdent c <+> fsep (map (ppType 2) tys)--> ppTypeSig :: QualIdent -> Type -> Doc-> ppTypeSig f ty = ppQIdent f <+> text "::" <+> ppType 0 ty--> ppType :: Int -> Type -> Doc-> ppType p (TypeConstructor tc tys)-> | isQTupleId tc = parens (fsep (punctuate comma (map (ppType 0) tys)))-> | unqualify tc == nilId = brackets (ppType 0 (head tys))-> | otherwise =-> ppParen (p > 1 && not (null tys))-> (ppQIdent tc <+> fsep (map (ppType 2) tys))-> ppType _ (TypeVariable n)-> | n >= 0 = text (typeVars !! n)-> | otherwise = text ('_':show (-n))-> ppType p (TypeArrow ty1 ty2) =-> ppParen (p > 0) (fsep (ppArrow (TypeArrow ty1 ty2)))-> where ppArrow (TypeArrow ty1 ty2) =-> ppType 1 ty1 <+> text "->" : ppArrow ty2-> ppArrow ty = [ppType 0 ty]--> ppBinding :: Binding -> Doc-> ppBinding (Binding v exp) =-> sep [ppIdent v <+> equals,nest bodyIndent (ppExpr 0 exp)]--> ppAlt :: Alt -> Doc-> ppAlt (Alt pat exp) =-> sep [ppConstrTerm pat <+> text "->",nest altIndent (ppExpr 0 exp)]--> ppLiteral :: Literal -> Doc-> ppLiteral (Char _ c) = text (show c)-> ppLiteral (Int _ i) = integer i-> ppLiteral (Float _ f) = double f--> ppConstrTerm :: ConstrTerm -> Doc-> ppConstrTerm (LiteralPattern l) = ppLiteral l-> ppConstrTerm (ConstructorPattern c [v1,v2])-> | isQInfixOp c = ppIdent v1 <+> ppQInfixOp c <+> ppIdent v2-> ppConstrTerm (ConstructorPattern c vs)-> | isQTupleId c = parens (fsep (punctuate comma (map ppIdent vs)))-> | otherwise = ppQIdent c <+> fsep (map ppIdent vs)-> ppConstrTerm (VariablePattern v) = ppIdent v--> ppExpr :: Int -> Expression -> Doc-> ppExpr p (Literal l) = ppLiteral l-> ppExpr p (Variable v) = ppIdent v-> ppExpr p (Function f _) = ppQIdent f-> ppExpr p (Constructor c _) = ppQIdent c-> ppExpr p (Apply (Apply (Function f _) e1) e2)-> | isQInfixOp f = ppInfixApp p e1 f e2-> ppExpr p (Apply (Apply (Constructor c _) e1) e2)-> | isQInfixOp c = ppInfixApp p e1 c e2-> ppExpr p (Apply e1 e2) =-> ppParen (p > 2) (sep [ppExpr 2 e1,nest exprIndent (ppExpr 3 e2)])-> ppExpr p (Case _ ev e alts) =-> ppParen (p > 0)-> (text "case" <+> ppEval ev <+> ppExpr 0 e <+> text "of" $$-> nest caseIndent (vcat (map ppAlt alts)))-> where ppEval Rigid = text "rigid"-> ppEval Flex = text "flex"-> ppExpr p (Or e1 e2) =-> ppParen (p > 0) (sep [ppExpr 0 e1,char '|' <+> ppExpr 0 e2])-> ppExpr p (Exist v e) =-> ppParen (p > 0)-> (sep [text "let" <+> ppIdent v <+> text "free" <+> text "in",-> ppExpr 0 e])-> ppExpr p (Let b e) =-> ppParen (p > 0) (sep [text "let" <+> ppBinding b <+> text "in",ppExpr 0 e])-> ppExpr p (Letrec bs e) =-> ppParen (p > 0)-> (sep [text "letrec" <+> vcat (map ppBinding bs) <+> text "in",-> ppExpr 0 e])--> ppInfixApp :: Int -> Expression -> QualIdent -> Expression -> Doc-> ppInfixApp p e1 op e2 =-> ppParen (p > 1)-> (sep [ppExpr 2 e1 <+> ppQInfixOp op,nest exprIndent (ppExpr 2 e2)])--> ppIdent :: Ident -> Doc-> ppIdent ident-> | isInfixOp ident = parens (ppName ident)-> | otherwise = ppName ident--> ppQIdent :: QualIdent -> Doc-> ppQIdent ident-> | isQInfixOp ident = parens (ppQual ident)-> | otherwise = ppQual ident--> ppQInfixOp :: QualIdent -> Doc-> ppQInfixOp op-> | isQInfixOp op = ppQual op-> | otherwise = char '`' <> ppQual op <> char '`'--> ppName :: Ident -> Doc-> ppName x = text (name x)--> ppQual :: QualIdent -> Doc-> ppQual x = text (qualName x)--> typeVars :: [String]-> typeVars = [mkTypeVar c i | i <- [0..], c <- ['a' .. 'z']]-> where mkTypeVar c i = c : if i == 0 then [] else show i--> ppParen :: Bool -> Doc -> Doc-> ppParen p = if p then parens else id--\end{verbatim}
− src/ILScope.hs
@@ -1,124 +0,0 @@-module ILScope (getModuleScope,- insertDeclScope, insertConstrDeclScope,- insertCallConvScope, insertTypeScope,- insertLiteralScope, insertConstrTermScope,- insertExprScope, insertAltScope,- insertBindingScope) where---import IL-import Ident-import OldScopeEnv as ScopeEnv---------------------------------------------------------------------------------------getModuleScope :: Module -> ScopeEnv-getModuleScope (Module _ _ decls) = foldl insertDecl newScopeEnv decls------insertDeclScope :: ScopeEnv -> Decl -> ScopeEnv-insertDeclScope env (DataDecl _ _ _) = env-insertDeclScope env (NewtypeDecl _ _ _) = env-insertDeclScope env (FunctionDecl _ params _ _)- = foldr ScopeEnv.insertIdent (ScopeEnv.beginScope env) params-insertDeclScope env (ExternalDecl _ _ _ _) = env------insertConstrDeclScope :: ScopeEnv -> ConstrDecl [Type] -> ScopeEnv-insertConstrDeclScope env _ = env------insertCallConvScope :: ScopeEnv -> CallConv -> ScopeEnv-insertCallConvScope env _ = env------insertTypeScope :: ScopeEnv -> Type -> ScopeEnv-insertTypeScope env _ = env------insertLiteralScope :: ScopeEnv -> Literal -> ScopeEnv-insertLiteralScope env _ = env------insertConstrTermScope :: ScopeEnv -> ConstrTerm -> ScopeEnv-insertConstrTermScope env _ = env------insertExprScope :: ScopeEnv -> Expression -> ScopeEnv-insertExprScope env (Literal _) = env-insertExprScope env (Variable _) = env-insertExprScope env (Function _ _) = env-insertExprScope env (Constructor _ _) = env-insertExprScope env (Apply _ _) = env-insertExprScope env (Case _ _ _ _) = env-insertExprScope env (Or _ _) = env-insertExprScope env (Exist ident _)- = ScopeEnv.insertIdent ident (ScopeEnv.beginScope env)-insertExprScope env (Let bind _)- = insertBinding (beginScope env) bind-insertExprScope env (Letrec binds _)- = foldl insertBinding (beginScope env) binds------insertAltScope :: ScopeEnv -> Alt -> ScopeEnv-insertAltScope env (Alt cterm _)- = insertConstrTerm (ScopeEnv.beginScope env) cterm------insertBindingScope :: ScopeEnv -> Binding -> ScopeEnv-insertBindingScope env _ = env-----------------------------------------------------------------------------------------------------------------------------------------------------------------------insertDecl :: ScopeEnv -> Decl -> ScopeEnv-insertDecl env (DataDecl qident _ cdecls)- = foldl insertConstrDecl- (ScopeEnv.insertIdent (unqualify qident) env)- cdecls--insertDecl env (NewtypeDecl qident _ cdecl)- = insertConstrDecl (ScopeEnv.insertIdent (unqualify qident) env) cdecl--insertDecl env (FunctionDecl qident _ _ _)- = ScopeEnv.insertIdent (unqualify qident) env--insertDecl env (ExternalDecl qident _ _ _)- = ScopeEnv.insertIdent (unqualify qident) env------insertConstrDecl :: ScopeEnv -> ConstrDecl a -> ScopeEnv-insertConstrDecl env (ConstrDecl qident _)- = ScopeEnv.insertIdent (unqualify qident) env------insertConstrTerm :: ScopeEnv -> ConstrTerm -> ScopeEnv-insertConstrTerm env (LiteralPattern _) = env-insertConstrTerm env (ConstructorPattern _ params)- = foldr ScopeEnv.insertIdent env params-insertConstrTerm env (VariablePattern ident)- = ScopeEnv.insertIdent ident env------insertBinding :: ScopeEnv -> Binding -> ScopeEnv-insertBinding env (Binding ident _) = ScopeEnv.insertIdent ident env------------------------------------------------------------------------------------------------------------------------------------------------------------------
− src/ILTrans.lhs
@@ -1,595 +0,0 @@--% $Id: ILTrans.lhs,v 1.86 2004/02/13 19:23:58 wlux Exp $-%-% Copyright (c) 1999-2003, Wolfgang Lux-% See LICENSE for the full license.-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{ILTrans.lhs}-\section{Translating Curry into the Intermediate Language}-After desugaring and lifting have been performed, the source code is-translated into the intermediate language. Besides translating from-source terms and expressions into intermediate language terms and-expressions this phase in particular has to implement the pattern-matching algorithm for equations and case expressions.--Because of name conflicts between the source and intermediate language-data structures, we can use only a qualified import for the-\texttt{IL} module.-\begin{verbatim}--> module ILTrans(ilTrans,ilTransIntf) where--> import Data.Maybe-> import Data.List-> import qualified Data.Set as Set-> import qualified Data.Map as Map--> import Base-> import qualified IL-> import Utils-> import Env-----\end{verbatim}-\paragraph{Modules}-At the top-level, the compiler has to translate data type, newtype,-function, and external declarations. When translating a data type or-newtype declaration, we ignore the types in the declaration and lookup-the types of the constructors in the type environment instead because-these types are already fully expanded, i.e., they do not include any-alias types.-\begin{verbatim}--> ilTrans :: Bool -> ValueEnv -> TCEnv -> EvalEnv -> Module -> IL.Module-> ilTrans flat tyEnv tcEnv evEnv (Module m _ ds) = -> IL.Module m (imports m ds') ds'-> where ds' = concatMap (translGlobalDecl flat m tyEnv tcEnv evEnv) ds--> translGlobalDecl :: Bool -> ModuleIdent -> ValueEnv -> TCEnv -> EvalEnv-> -> Decl -> [IL.Decl]-> translGlobalDecl _ m tyEnv tcEnv _ (DataDecl _ tc tvs cs) =-> [translData m tyEnv tcEnv tc tvs cs]-> translGlobalDecl _ m tyEnv tcEnv _ (NewtypeDecl _ tc tvs nc) =-> [translNewtype m tyEnv tcEnv tc tvs nc]-> translGlobalDecl flat m tyEnv tcEnv evEnv (FunctionDecl pos f eqs) =-> [translFunction pos flat m tyEnv tcEnv evEnv f eqs]-> translGlobalDecl _ m tyEnv tcEnv _ (ExternalDecl _ cc ie f _) =-> [translExternal m tyEnv tcEnv f cc (fromJust ie)]-> translGlobalDecl _ _ _ _ _ _ = []--> translData :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] -> [ConstrDecl]-> -> IL.Decl-> translData m tyEnv tcEnv tc tvs cs =-> IL.DataDecl (qualifyWith m tc) (length tvs)-> (map (translConstrDecl m tyEnv tcEnv) cs)--> translNewtype :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] -> -> NewConstrDecl -> IL.Decl-> translNewtype m tyEnv tcEnv tc tvs (NewConstrDecl _ _ c _) =-> IL.NewtypeDecl (qualifyWith m tc) (length tvs)-> (IL.ConstrDecl c' (translType' m tyEnv tcEnv ty))-> -- (IL.ConstrDecl c' (translType ty))-> where c' = qualifyWith m c-> TypeArrow ty _ = constrType tyEnv c'--> translConstrDecl :: ModuleIdent -> ValueEnv -> TCEnv -> ConstrDecl-> -> IL.ConstrDecl [IL.Type]-> translConstrDecl m tyEnv tcEnv d =-> IL.ConstrDecl c' (map (translType' m tyEnv tcEnv)-> (arrowArgs (constrType tyEnv c')))-> -- IL.ConstrDecl c' (map translType (arrowArgs (constrType tyEnv c')))-> where c' = qualifyWith m (constr d)-> constr (ConstrDecl _ _ c _) = c-> constr (ConOpDecl _ _ _ op _) = op--> translExternal :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> CallConv-> -> String -> IL.Decl-> translExternal m tyEnv tcEnv f cc ie =-> IL.ExternalDecl f' (callConv cc) ie -> (translType' m tyEnv tcEnv (varType tyEnv f'))-> -- IL.ExternalDecl f' (callConv cc) ie (translType (varType tyEnv f'))-> where f' = qualifyWith m f-> callConv CallConvPrimitive = IL.Primitive-> callConv CallConvCCall = IL.CCall--\end{verbatim}-\paragraph{Interfaces}-In order to generate code, the compiler also needs to know the tags-and arities of all imported data constructors. For that reason we-compile the data type declarations of all interfaces into the-intermediate language, too. In this case we do not lookup the-types in the environment because the types in the interfaces are-already fully expanded. Note that we do not translate data types-which are imported into the interface from some other module.-\begin{verbatim}--> ilTransIntf :: ValueEnv -> TCEnv -> Interface -> [IL.Decl]-> ilTransIntf tyEnv tcEnv (Interface m ds) = -> foldr (translIntfDecl m tyEnv tcEnv) [] ds--> translIntfDecl :: ModuleIdent -> ValueEnv -> TCEnv -> IDecl -> [IL.Decl] -> -> [IL.Decl]-> translIntfDecl m tyEnv tcEnv (IDataDecl _ tc tvs cs) ds-> | not (isQualified tc) = -> translIntfData m tyEnv tcEnv (unqualify tc) tvs cs : ds-> translIntfDecl _ _ _ _ ds = ds--> translIntfData :: ModuleIdent -> ValueEnv -> TCEnv -> Ident -> [Ident] -> -> [Maybe ConstrDecl] -> IL.Decl-> translIntfData m tyEnv tcEnv tc tvs cs =-> IL.DataDecl (qualifyWith m tc) (length tvs)-> (map (maybe hiddenConstr -> (translIntfConstrDecl m tyEnv tcEnv tvs)) cs)-> where hiddenConstr = IL.ConstrDecl qAnonId []-> qAnonId = qualify anonId--> translIntfConstrDecl :: ModuleIdent -> ValueEnv -> TCEnv -> [Ident] -> -> ConstrDecl -> IL.ConstrDecl [IL.Type]-> translIntfConstrDecl m tyEnv tcEnv tvs (ConstrDecl _ _ c tys) =-> IL.ConstrDecl (qualifyWith m c) (map (translType' m tyEnv tcEnv)-> (toQualTypes m tvs tys))-> -- IL.ConstrDecl (qualifyWith m c) (map translType (toQualTypes m tvs tys))-> translIntfConstrDecl m tyEnv tcEnv tvs (ConOpDecl _ _ ty1 op ty2) =-> IL.ConstrDecl (qualifyWith m op)-> (map (translType' m tyEnv tcEnv)-> (toQualTypes m tvs [ty1,ty2]))-> -- IL.ConstrDecl (qualifyWith m op)-> -- (map translType (toQualTypes m tvs [ty1,ty2]))--\end{verbatim}-\paragraph{Types}-The type representation in the intermediate language is the same as-the internal representation except that it does not support-constrained type variables and skolem types. The former are fixed and-the later are replaced by fresh type constructors.--Due to possible occurrence of record types, it is necessary to transform-them back into their corresponding type constructors.-\begin{verbatim}--> translType' :: ModuleIdent -> ValueEnv -> TCEnv -> Type -> IL.Type-> translType' m tyEnv tcEnv ty =-> translType (elimRecordTypes m tyEnv tcEnv (maximum (0:(typeVars ty))) ty)--> translType :: Type -> IL.Type-> translType (TypeConstructor tc tys) =-> IL.TypeConstructor tc (map translType tys)-> translType (TypeVariable tv) = IL.TypeVariable tv-> translType (TypeConstrained tys _) = translType (head tys)-> translType (TypeArrow ty1 ty2) =-> IL.TypeArrow (translType ty1) (translType ty2)-> translType (TypeSkolem k) =-> IL.TypeConstructor (qualify (mkIdent ("_" ++ show k))) []--> elimRecordTypes :: ModuleIdent -> ValueEnv -> TCEnv -> Int -> Type -> Type-> elimRecordTypes m tyEnv tcEnv n (TypeConstructor t tys) =-> TypeConstructor t (map (elimRecordTypes m tyEnv tcEnv n) tys)-> elimRecordTypes m tyEnv tcEnv n (TypeVariable v) =-> TypeVariable v-> elimRecordTypes m tyEnv tcEnv n (TypeConstrained tys v) =-> TypeConstrained (map (elimRecordTypes m tyEnv tcEnv n) tys) v-> elimRecordTypes m tyEnv tcEnv n (TypeArrow t1 t2) =-> TypeArrow (elimRecordTypes m tyEnv tcEnv n t1)-> (elimRecordTypes m tyEnv tcEnv n t2)-> elimRecordTypes m tyEnv tcEnv n (TypeSkolem v) =-> TypeSkolem v-> elimRecordTypes m tyEnv tcEnv n (TypeRecord fs _)-> | null fs = internalError "elimRecordTypes: empty record type"-> | otherwise =-> case (lookupValue (fst (head fs)) tyEnv) of-> [Label _ r _] ->-> case (qualLookupTC r tcEnv) of-> [AliasType _ n' (TypeRecord fs' _)] ->-> let is = [0 .. n'-1]-> vs = foldl (matchTypeVars fs)-> Map.empty-> fs'-> tys = map (\i -> maybe (TypeVariable (i+n))-> (elimRecordTypes m tyEnv tcEnv n)-> (Map.lookup i vs))-> is -> in TypeConstructor r tys-> _ -> internalError "elimRecordTypes: no record type"-> _ -> internalError "elimRecordTypes: no label"--> matchTypeVars :: [(Ident,Type)] -> Map.Map Int Type -> (Ident,Type) -> -> Map.Map Int Type-> matchTypeVars fs vs (l,ty) =-> maybe vs (match vs ty) (lookup l fs)-> where-> match vs (TypeVariable i) ty' = Map.insert i ty' vs-> match vs (TypeConstructor _ tys) (TypeConstructor _ tys') =-> matchList vs tys tys'-> match vs (TypeConstrained tys _) (TypeConstrained tys' _) =-> matchList vs tys tys'-> match vs (TypeArrow ty1 ty2) (TypeArrow ty1' ty2') =-> matchList vs [ty1,ty2] [ty1',ty2']-> match vs (TypeSkolem _) (TypeSkolem _) = vs-> match vs (TypeRecord fs _) (TypeRecord fs' _) =-> foldl (matchTypeVars fs') vs fs-> match vs ty ty' = -> internalError ("matchTypeVars: " ++ show ty ++ "\n" ++ show ty')->-> matchList vs tys tys' = -> foldl (\vs' (ty,ty') -> match vs' ty ty') vs (zip tys tys')--\end{verbatim}-\paragraph{Functions}-Each function in the program is translated into a function of the-intermediate language. The arguments of the function are renamed such-that all variables occurring in the same position (in different-equations) have the same name. This is necessary in order to-facilitate the translation of pattern matching into a \texttt{case}-expression. We use the following simple convention here: The top-level-arguments of the function are named from left to right \texttt{\_1},-\texttt{\_2}, and so on. The names of nested arguments are constructed-by appending \texttt{\_1}, \texttt{\_2}, etc. from left to right to-the name that were assigned to a variable occurring at the position of-the constructor term.--Some special care is needed for the selector functions introduced by-the compiler in place of pattern bindings. In order to generate the-code for updating all pattern variables, the equality of names between-the pattern variables in the first argument of the selector function-and their repeated occurrences in the remaining arguments must be-preserved. This means that the second and following arguments of a-selector function have to be renamed according to the name mapping-computed for its first argument.--If an evaluation annotation is available for a function, it determines-the evaluation mode of the case expression. Otherwise, the function-uses flexible matching.-\begin{verbatim}--> type RenameEnv = Env Ident Ident--> translFunction :: Position -> Bool -> ModuleIdent -> ValueEnv -> TCEnv-> -> EvalEnv -> Ident -> [Equation] -> IL.Decl-> translFunction pos flat m tyEnv tcEnv evEnv f eqs =-> -- | f == mkIdent "fun" = error (show (translType' m tyEnv tcEnv ty))-> -- | otherwise = -> IL.FunctionDecl f' vs (translType' m tyEnv tcEnv ty) expr-> -- = IL.FunctionDecl f' vs (translType ty)-> -- (match ev vs (map (translEquation tyEnv vs vs'') eqs))-> where f' = qualifyWith m f-> ty = varType tyEnv f'-> -- ty' = elimRecordType m tyEnv tcEnv (maximum (0:(typeVars ty))) ty-> ev' = lookupEval f evEnv-> ev = maybe (defaultMode ty) evalMode ev'-> vs = if not flat && isFpSelectorId f then translArgs eqs vs' else vs'-> (vs',vs'') = splitAt (equationArity (head eqs)) -> (argNames (mkIdent ""))-> expr | ev' == Just EvalChoice-> = IL.Apply -> (IL.Function -> (qualifyWith preludeMIdent (mkIdent "commit"))-> 1)-> (match (ast pos) IL.Rigid vs -> (map (translEquation tyEnv vs vs'') eqs))-> | otherwise-> = match (ast pos) ev vs (map (translEquation tyEnv vs vs'') eqs)-> ----> -- (vs',vs'') = splitAt (arrowArity ty) (argNames (mkIdent ""))--> evalMode :: EvalAnnotation -> IL.Eval-> evalMode EvalRigid = IL.Rigid-> evalMode EvalChoice = error "eval choice is not yet supported"--> defaultMode :: Type -> IL.Eval-> defaultMode _ = IL.Flex->-> --defaultMode ty = if isIO (arrowBase ty) then IL.Rigid else IL.Flex-> -- where TypeConstructor qIOId _ = ioType undefined-> -- isIO (TypeConstructor tc [_]) = tc == qIOId-> -- isIO _ = False--> translArgs :: [Equation] -> [Ident] -> [Ident]-> translArgs [Equation _ (FunLhs _ (t:ts)) _] (v:_) =-> v : map (translArg (bindRenameEnv v t emptyEnv)) ts-> where translArg env (VariablePattern v) = fromJust (lookupEnv v env)--> translEquation :: ValueEnv -> [Ident] -> [Ident] -> Equation-> -> ([NestedTerm],IL.Expression)-> translEquation tyEnv vs vs' (Equation _ (FunLhs _ ts) rhs) =-> (zipWith translTerm vs ts,-> translRhs tyEnv vs' (foldr2 bindRenameEnv emptyEnv vs ts) rhs)--> translRhs :: ValueEnv -> [Ident] -> RenameEnv -> Rhs -> IL.Expression-> translRhs tyEnv vs env (SimpleRhs _ e _) = translExpr tyEnv vs env e---> equationArity :: Equation -> Int-> equationArity (Equation _ lhs _) = p_equArity lhs-> where-> p_equArity (FunLhs _ ts) = length ts-> p_equArity (OpLhs _ _ _) = 2-> p_equArity _ = error "ILTrans - illegal equation"---\end{verbatim}-\paragraph{Pattern Matching}-The pattern matching code searches for the left-most inductive-argument position in the left hand sides of all rules defining an-equation. An inductive position is a position where all rules have a-constructor rooted term. If such a position is found, a \texttt{case}-expression is generated for the argument at that position. The-matching code is then computed recursively for all of the alternatives-independently. If no inductive position is found, the algorithm looks-for the left-most demanded argument position, i.e., a position where-at least one of the rules has a constructor rooted term. If such a-position is found, an \texttt{or} expression is generated with those-cases that have a variable at the argument position in one branch and-all other rules in the other branch. If there is no demanded position,-the pattern matching is finished and the compiler translates the right-hand sides of the remaining rules, eventually combining them using-\texttt{or} expressions.--Actually, the algorithm below combines the search for inductive and-demanded positions. The function \texttt{match} scans the argument-lists for the left-most demanded position. If this turns out to be-also an inductive position, the function \texttt{matchInductive} is-called in order to generate a \texttt{case} expression. Otherwise, the-function \texttt{optMatch} is called that tries to find an inductive-position in the remaining arguments. If one is found,-\texttt{matchInductive} is called, otherwise the function-\texttt{optMatch} uses the demanded argument position found by-\texttt{match}.-\begin{verbatim}--> data NestedTerm = NestedTerm IL.ConstrTerm [NestedTerm] deriving Show--> pattern (NestedTerm t _) = t-> arguments (NestedTerm _ ts) = ts--> translLiteral :: Literal -> IL.Literal-> translLiteral (Char p c) = IL.Char p c-> translLiteral (Int id i) = IL.Int (ast (positionOfIdent id)) i-> translLiteral (Float p f) = IL.Float p f-> translLiteral _ = internalError "translLiteral"--> translTerm :: Ident -> ConstrTerm -> NestedTerm-> translTerm _ (LiteralPattern l) =-> NestedTerm (IL.LiteralPattern (translLiteral l)) []-> translTerm v (VariablePattern _) = NestedTerm (IL.VariablePattern v) []-> translTerm v (ConstructorPattern c ts) =-> NestedTerm (IL.ConstructorPattern c (take (length ts) vs))-> (zipWith translTerm vs ts)-> where vs = argNames v-> translTerm v (AsPattern _ t) = translTerm v t-> translTerm _ _ = internalError "translTerm"--> bindRenameEnv :: Ident -> ConstrTerm -> RenameEnv -> RenameEnv-> bindRenameEnv _ (LiteralPattern _) env = env-> bindRenameEnv v (VariablePattern v') env = bindEnv v' v env-> bindRenameEnv v (ConstructorPattern _ ts) env =-> foldr2 bindRenameEnv env (argNames v) ts-> bindRenameEnv v (AsPattern v' t) env = bindEnv v' v (bindRenameEnv v t env)-> bindRenameEnv _ _ env = internalError "bindRenameEnv"--> argNames :: Ident -> [Ident]-> argNames v = [mkIdent (prefix ++ show i) | i <- [1..]]-> where prefix = name v ++ "_"--> type Match = ([NestedTerm],IL.Expression)-> type Match' = ([NestedTerm] -> [NestedTerm],[NestedTerm],IL.Expression)--> isDefaultPattern :: IL.ConstrTerm -> Bool-> isDefaultPattern (IL.VariablePattern _) = True-> isDefaultPattern _ = False--> isDefaultMatch :: (IL.ConstrTerm,a) -> Bool-> isDefaultMatch = isDefaultPattern . fst--> match :: SrcRef -> IL.Eval -> [Ident] -> [Match] -> IL.Expression-> match _ ev [] alts = foldl1 IL.Or (map snd alts)-> match pos ev (v:vs) alts-> | null vars = e1-> | null nonVars = e2-> | otherwise = optMatch pos ev (IL.Or e1 e2) (v:) vs (map skipArg alts)-> where (vars,nonVars) = partition isDefaultMatch (map tagAlt alts)-> (nonArgs,args) = partition (null.fst) alts-> e1 = matchInductive pos ev id v vs nonVars-> e2 = match pos ev vs (map snd vars)-> tagAlt (t:ts,e) = (pattern t,(arguments t ++ ts,e))-> skipArg (t:ts,e) = ((t:),ts,e)--> optMatch :: SrcRef -> IL.Eval -> IL.Expression -> ([Ident] -> [Ident]) -> -> [Ident] ->[Match'] -> IL.Expression-> optMatch _ ev e prefix [] alts = e-> optMatch pos ev e prefix (v:vs) alts-> | null vars = matchInductive pos ev prefix v vs nonVars-> | otherwise = optMatch pos ev e (prefix . (v:)) vs (map skipArg alts)-> where (vars,nonVars) = partition isDefaultMatch (map tagAlt alts)-> tagAlt (prefix,t:ts,e) = (pattern t,(prefix (arguments t ++ ts),e))-> skipArg (prefix,t:ts,e) = (prefix . (t:),ts,e)--> matchInductive :: SrcRef -> IL.Eval -> ([Ident] -> [Ident]) -> Ident -> -> [Ident] ->[(IL.ConstrTerm,Match)] -> IL.Expression-> matchInductive pos ev prefix v vs alts =-> IL.Case pos ev (IL.Variable v) (matchAlts ev prefix vs alts)--> matchAlts :: IL.Eval -> ([Ident] -> [Ident]) -> [Ident] ->-> [(IL.ConstrTerm,Match)] -> [IL.Alt]-> matchAlts ev prefix vs [] = []-> matchAlts ev prefix vs ((t,alt):alts) =-> IL.Alt t (match (srcRefOf t) -> ev (prefix (vars t ++ vs)) (alt : map snd same)) :-> matchAlts ev prefix vs others-> where (same,others) = partition ((t ==) . fst) alts -> vars (IL.ConstructorPattern _ vs) = vs-> vars _ = []--\end{verbatim}-Matching in a \texttt{case}-expression works a little bit differently.-In this case, the alternatives are matched from the first to the last-alternative and the first matching alternative is chosen. All-remaining alternatives are discarded.--\ToDo{The case matching algorithm should use type information in order-to detect total matches and immediately discard all alternatives which-cannot be reached.}-\begin{verbatim}--> caseMatch :: SrcRef -> ([Ident] -> [Ident]) -> [Ident] -> [Match'] -> -> IL.Expression-> caseMatch _ prefix [] alts = thd3 (head alts)-> caseMatch r prefix (v:vs) alts-> | isDefaultMatch (head alts') =-> caseMatch r (prefix . (v:)) vs (map skipArg alts)-> | otherwise =-> IL.Case r IL.Rigid (IL.Variable v) (caseMatchAlts prefix vs alts')-> where alts' = map tagAlt alts-> tagAlt (prefix,t:ts,e) = (pattern t,(prefix,arguments t ++ ts,e))-> skipArg (prefix,t:ts,e) = (prefix . (t:),ts,e)--> caseMatchAlts ::-> ([Ident] -> [Ident]) -> [Ident] -> [(IL.ConstrTerm,Match')] -> [IL.Alt]-> caseMatchAlts prefix vs alts = map caseAlt (ts ++ ts')-> where (ts',ts) = partition isDefaultPattern (nub (map fst alts))-> caseAlt t =-> IL.Alt t (caseMatch (srcRefOf t) id (prefix (vars t ++ vs))-> (matchingCases t alts))-> matchingCases t =-> map (joinArgs (vars t)) . filter (matches t . fst)-> matches t t' = t == t' || isDefaultPattern t'-> joinArgs vs (IL.VariablePattern _,(prefix,ts,e)) =-> (id,prefix (map varPattern vs ++ ts),e)-> joinArgs _ (_,(prefix,ts,e)) = (id,prefix ts,e)-> varPattern v = NestedTerm (IL.VariablePattern v) []-> vars (IL.ConstructorPattern _ vs) = vs-> vars _ = []--\end{verbatim}-\paragraph{Expressions}-Note that the case matching algorithm assumes that the matched-expression is accessible through a variable. The translation of case-expressions therefore introduces a let binding for the scrutinized-expression and immediately throws it away after the matching -- except-if the matching algorithm has decided to use that variable in the-right hand sides of the case expression. This may happen, for-instance, if one of the alternatives contains an \texttt{@}-pattern.-\begin{verbatim}--> translExpr :: ValueEnv -> [Ident] -> RenameEnv -> Expression -> IL.Expression-> translExpr _ _ _ (Literal l) = IL.Literal (translLiteral l)-> translExpr tyEnv _ env (Variable v) =-> case lookupVar v env of-> Just v' -> IL.Variable v'-> Nothing -> IL.Function v (arrowArity (varType tyEnv v))-> where lookupVar v env-> | isQualified v = Nothing-> | otherwise = lookupEnv (unqualify v) env-> translExpr tyEnv _ _ (Constructor c) =-> IL.Constructor c (arrowArity (constrType tyEnv c))-> translExpr tyEnv vs env (Apply e1 e2) =-> IL.Apply (translExpr tyEnv vs env e1) (translExpr tyEnv vs env e2)-> translExpr tyEnv vs env (Let ds e) =-> case ds of-> [ExtraVariables _ vs] -> foldr IL.Exist e' vs-> [d] | all (`notElem` bv d) (qfv emptyMIdent d) ->-> IL.Let (translBinding env' d) e'-> _ -> IL.Letrec (map (translBinding env') ds) e'-> where e' = translExpr tyEnv vs env' e-> env' = foldr2 bindEnv env bvs bvs-> bvs = bv ds-> translBinding env (PatternDecl _ (VariablePattern v) rhs) =-> IL.Binding v (translRhs tyEnv vs env rhs)-> translBinding env p = error $ "unexpected binding: "++show p-> translExpr tyEnv ~(v:vs) env (Case r e alts) =-> case caseMatch r id [v] (map (translAlt v) alts) of-> IL.Case r mode (IL.Variable v') alts'-> | v == v' && v `notElem` fv alts' -> IL.Case r mode e' alts'-> e''-> | v `elem` fv e'' -> IL.Let (IL.Binding v e') e''-> | otherwise -> e''-> where e' = translExpr tyEnv vs env e-> translAlt v (Alt _ t rhs) =-> (id,-> [translTerm v t],-> translRhs tyEnv vs (bindRenameEnv v t env) rhs)-> translExpr _ _ _ _ = internalError "translExpr"--> instance Expr IL.Expression where-> fv (IL.Variable v) = [v]-> fv (IL.Apply e1 e2) = fv e1 ++ fv e2-> fv (IL.Case _ _ e alts) = fv e ++ fv alts-> fv (IL.Or e1 e2) = fv e1 ++ fv e2-> fv (IL.Exist v e) = filter (/= v) (fv e)-> fv (IL.Let (IL.Binding v e1) e2) = fv e1 ++ filter (/= v) (fv e2)-> fv (IL.Letrec bds e) = filter (`notElem` vs) (fv es ++ fv e)-> where (vs,es) = unzip [(v,e) | IL.Binding v e <- bds]-> fv _ = []--> instance Expr IL.Alt where-> fv (IL.Alt (IL.ConstructorPattern _ vs) e) = filter (`notElem` vs) (fv e)-> fv (IL.Alt (IL.VariablePattern v) e) = filter (v /=) (fv e)-> fv (IL.Alt _ e) = fv e--\end{verbatim}-\paragraph{Auxiliary Definitions}-The functions \texttt{varType} and \texttt{constrType} return the type-of variables and constructors, respectively. The quantifiers are-stripped from the types.-\begin{verbatim}--> varType :: ValueEnv -> QualIdent -> Type-> varType tyEnv f =-> case qualLookupValue f tyEnv of-> [Value _ (ForAll _ ty)] -> ty-> _ -> internalError ("varType: " ++ show f)--> constrType :: ValueEnv -> QualIdent -> Type-> constrType tyEnv c =-> case qualLookupValue c tyEnv of-> [DataConstructor _ (ForAllExist _ _ ty)] -> ty-> [NewtypeConstructor _ (ForAllExist _ _ ty)] -> ty-> _ -> internalError ("constrType: " ++ show c)--\end{verbatim}-The list of import declarations in the intermediate language code is-determined by collecting all module qualifiers used in the current-module.-\begin{verbatim}--> imports :: ModuleIdent -> [IL.Decl] -> [ModuleIdent]-> imports m = Set.toList . Set.delete m . Set.fromList . foldr modulesDecl []--> modulesDecl :: IL.Decl -> [ModuleIdent] -> [ModuleIdent]-> modulesDecl (IL.DataDecl _ _ cs) ms = foldr modulesConstrDecl ms cs-> where modulesConstrDecl (IL.ConstrDecl _ tys) ms = foldr modulesType ms tys-> modulesDecl (IL.NewtypeDecl _ _ (IL.ConstrDecl _ ty)) ms = modulesType ty ms-> modulesDecl (IL.FunctionDecl _ _ ty e) ms = modulesType ty (modulesExpr e ms)-> modulesDecl (IL.ExternalDecl _ _ _ ty) ms = modulesType ty ms--> modulesType :: IL.Type -> [ModuleIdent] -> [ModuleIdent]-> modulesType (IL.TypeConstructor tc tys) ms =-> modules tc (foldr modulesType ms tys)-> modulesType (IL.TypeVariable _) ms = ms-> modulesType (IL.TypeArrow ty1 ty2) ms = modulesType ty1 (modulesType ty2 ms)--> modulesExpr :: IL.Expression -> [ModuleIdent] -> [ModuleIdent]-> modulesExpr (IL.Function f _) ms = modules f ms-> modulesExpr (IL.Constructor c _) ms = modules c ms-> modulesExpr (IL.Apply e1 e2) ms = modulesExpr e1 (modulesExpr e2 ms)-> modulesExpr (IL.Case _ _ e as) ms = modulesExpr e (foldr modulesAlt ms as)-> where modulesAlt (IL.Alt t e) ms = modulesConstrTerm t (modulesExpr e ms)-> modulesConstrTerm (IL.ConstructorPattern c _) ms = modules c ms-> modulesConstrTerm _ ms = ms-> modulesExpr (IL.Or e1 e2) ms = modulesExpr e1 (modulesExpr e2 ms)-> modulesExpr (IL.Exist _ e) ms = modulesExpr e ms-> modulesExpr (IL.Let b e) ms = modulesBinding b (modulesExpr e ms)-> modulesExpr (IL.Letrec bs e) ms = foldr modulesBinding (modulesExpr e ms) bs-> modulesExpr _ ms = ms--> modulesBinding :: IL.Binding -> [ModuleIdent] -> [ModuleIdent]-> modulesBinding (IL.Binding _ e) = modulesExpr e--> modules :: QualIdent -> [ModuleIdent] -> [ModuleIdent]-> modules x ms = maybe ms (: ms) (fst (splitQualIdent x))--\end{verbatim}-
− src/ILxml.lhs
@@ -1,518 +0,0 @@--% $Id: ILxml.lhs,v 1.0 2001/06/19 12:19:18 rafa Exp $-%-% $Log: ILxml.lhs,v $-%-% Revision 1.1 2001/06/19 12:19:18 rafa-% Pretty printer in XML for the intermediate language added.-%-%-% Modified by Martin Engelke (men@informatik.uni-kiel.de)-%-\nwfilename{ILxml.lhs}-\section{A pretty printer in XML for the intermediate language}-This module implements just another pretty printer, this time in XML and for-the intermediate language. It was mainly adapted from the Curry pretty-printer (see sect.~\ref{sec:CurryPP}), which in turn is based on Simon-Marlow's pretty printer for Haskell. The format of the output intends to be-similar to that of Flat-Curry XML representation.-\begin{verbatim}--> module ILxml(module ILxml, Doc) where--> import Data.Maybe-> import Data.Char(chr,ord,isAlphaNum)--> import Ident-> import IL-> import qualified CurrySyntax as CS-> import CurryEnv-> import Pretty----> -- identation level-> level::Int-> level = 3--> xmlModule :: CurryEnv -> Module -> Doc-> xmlModule cEnv m = text "<prog>" $$ nest level (xmlBody cEnv m) -> $$ text "</prog>"--> xmlBody :: CurryEnv -> Module -> Doc-> xmlBody cEnv (Module name imports decls) =-> xmlElement "module" xmlModuleDecl moduleDecl $$-> xmlElement "import" xmlImportDecl importDecl $$-> xmlElement "types" xmlTypeDecl typeDecl $$-> xmlElement "functions" xmlFunctionDecl functionDecl $$-> xmlElement "operators" xmlOperatorDecl operatorDecl $$-> xmlElement "translation" xmlTranslationDecl translationDecl-> where-> moduleDecl = [name]-> importDecl = imports-> operatorDecl = infixDecls cEnv-> translationDecl = foldl (qualIDeclId (moduleId cEnv))-> [] -> (interface cEnv)-> (functionDecl,typeDecl) = splitDecls decls--> -- =========================================================================--> xmlModuleDecl :: ModuleIdent -> Doc-> xmlModuleDecl name = xmlModuleIdent name--> -- =========================================================================--> xmlImportDecl :: ModuleIdent -> Doc-> xmlImportDecl name = xmlElement "module" xmlModuleDecl [name]---> -- =========================================================================-> -- T Y P E S-> -- =========================================================================--> xmlTypeDecl :: Decl -> Doc-> xmlTypeDecl (DataDecl tc arity cs) =-> beginType $$-> nest level (xmlTypeParams arity) $$-> xmlLines xmlConstructor cs $$-> endType-> where-> beginType = text "<type name=\"" <> (xmlQualIdent tc) <> text "\">"-> endType = text "</type>"--> xmlTypeParams :: Int -> Doc-> xmlTypeParams n = xmlElement "params" xmlTypeVar [0..(n-1)]--> xmlConstructor :: ConstrDecl [Type] -> Doc-> xmlConstructor (ConstrDecl ident []) = xmlConstructorBegin ident 0-> xmlConstructor (ConstrDecl ident l) =-> xmlConstructorBegin ident (length l) $$-> xmlLines xmlType l $$-> xmlConstructorEnd-> where-> xmlConstructorEnd = text "</cons>"--> xmlConstructorBegin :: QualIdent -> Int -> Doc-> xmlConstructorBegin ident n = xmlHeadingWithArity "cons" ident n (n==0)--> xmlHeadingWithArity :: String -> QualIdent -> Int -> Bool -> Doc-> xmlHeadingWithArity tagName ident n single =-> if single-> then prefix<>text "/>"-> else prefix<> text ">"-> where-> prefix = text ("<"++tagName++" name=\"") <> name <> text "\" " <> arity-> arity = text "arity=\"" <> xmlInt n <> text "\""-> name = xmlQualIdent ident---> xmlType :: Type -> Doc-> xmlType (TypeConstructor ident []) = xmlTypeConsBegin ident True-> xmlType (TypeConstructor ident l) = xmlTypeConsBegin ident False $$-> xmlLines xmlType l $$-> xmlTypeConsEnd-> where-> xmlTypeConsEnd = text "</tcons>"--> xmlType (TypeVariable n) = xmlTypeVar n-> xmlType (TypeArrow a b) = xmlTypeFun a b--> xmlTypeConsBegin :: QualIdent -> Bool -> Doc-> xmlTypeConsBegin ident single =-> if single-> then prefix <> text "/>"-> else prefix <> text ">"-> where-> name = xmlQualIdent ident-> prefix = text "<tcons name=\"" <> name <> text "\""--> xmlTypeVar :: Int -> Doc-> xmlTypeVar n = text "<tvar>"<> xmlInt n <> text "</tvar>"--> xmlTypeFun :: Type -> Type -> Doc-> xmlTypeFun a b = xmlElement "functype" xmlType [a,b]---> -- =========================================================================-> -- F U N C T I O N S-> -- =========================================================================--> xmlFunctionDecl :: Decl -> Doc-> xmlFunctionDecl (NewtypeDecl tc arity (ConstrDecl ident ty)) =-> xmlFunctionDecl (FunctionDecl ident [arg] ftype (Variable arg))-> where-> arg = mkIdent "_1"-> ftype = TypeArrow ty (TypeConstructor tc (map TypeVariable [0..arity-1]))--> xmlFunctionDecl (FunctionDecl ident largs fType expr) =-> heading $$ nest level (xmlRule largs expr) $$ end-> where-> heading = xmlBeginFunction ident (length largs) fType-> end = text "</func>"--> xmlFunctionDecl (ExternalDecl ident callConv internalName fType) =-> heading $$ external $$ end-> where-> heading = xmlBeginFunction ident (xmlFunctionArity fType) fType-> external = text ("<external>"-> ++ xmlFormat internalName-> ++ "</external>")-> end = text "</func>"--> xmlBeginFunction :: QualIdent -> Int -> Type -> Doc-> xmlBeginFunction ident n fType =-> heading $$ typeDecls-> where-> heading = xmlHeadingWithArity "func" ident n False-> typeDecls = nest level (xmlType fType)--> xmlEndFunction :: Doc-> xmlEndFunction = text "</func>"--> xmlFunctionArity :: Type -> Int-> xmlFunctionArity (TypeConstructor ident l) = 0-> xmlFunctionArity (TypeVariable n) = 0-> xmlFunctionArity (TypeArrow a b) = 1 + (xmlFunctionArity b)--> xmlRule :: [Ident] -> Expression -> Doc-> xmlRule lArgs e = text "<rule>" $$-> nest level (xmlLhs lArgs) $$-> nest level (xmlRhs lArgs e) $$-> text "</rule>"--> xmlLhs :: [Ident] -> Doc-> xmlLhs l = xmlElement "lhs" xmlVar [0..((length l)-1)]--> xmlRhs :: [Ident] -> Expression -> Doc-> xmlRhs l e = text "<rhs>" $$ nest level rhs $$ text "</rhs>"-> where-> varDicc = xmlBuildDicc l-> (rhs,dicc) = xmlExpr varDicc e--> -- =========================================================================--> -- =========================================================================-> -- E X P R E S S I O N S-> -- =========================================================================--> xmlExpr :: [(Int,Ident)] -> Expression -> (Doc,[(Int,Ident)])-> xmlExpr d (Literal lit) = (xmlLiteral (xmlLit lit),d)-> xmlExpr d (Variable ident) = xmlExprVar d ident-> xmlExpr d (Function ident arity) = (xmlSingleApp ident arity True,d)-> xmlExpr d (Constructor ident arity) = (xmlSingleApp ident arity False,d)-> xmlExpr d exp@(Apply e1 e2) = xmlApply d exp (xmlAppArgs exp)-> xmlExpr d (Case _ eval expr alt) = xmlCase d eval expr alt-> xmlExpr d (Or expr1 expr2) = xmlOr d expr1 expr2-> xmlExpr d (Exist ident expr) = xmlFree d ident expr-> xmlExpr d (Let binding expr) = xmlLet d binding expr-> xmlExpr d (Letrec lBinding expr) = xmlLetrec d lBinding expr-> --error "Recursive let bindings not supported in FlatCurry"--> -- =========================================================================--> xmlSingleApp :: QualIdent -> Int -> Bool -> Doc-> xmlSingleApp ident arity isFunction =-> if arity>0-> then xmlCombHeading identDoc (text "PartCall") True-> else xmlCombHeading identDoc (text totalApp) True-> where-> identDoc = xmlQualIdent ident-> totalApp = if isFunction then "FuncCall" else "ConsCall"---> xmlCombHeading :: Doc -> Doc -> Bool -> Doc-> xmlCombHeading name cType single =-> if single-> then prefix <> text " />"-> else prefix <> text ">"-> where-> prefix = text "<comb type=\""<>cType<>text "\" name=\""<>name<>text "\""--> -- =========================================================================--> xmlExprVar :: [(Int,Ident)] -> Ident -> (Doc,[(Int,Ident)])-> xmlExprVar d ident =-> if isNew-> then (xmlVar newVar, (newVar,ident):d)-> else (xmlVar var, d)-> where-> var = xmlLookUp ident d-> isNew = var == -1-> newVar = xmlNewVar d--> -- =========================================================================---> xmlApply :: [(Int,Ident)] -> Expression -> (Expression,[Expression]) ->-> (Doc,[(Int,Ident)])--> xmlApply d exp ((Function ident arity),lExp) =-> xmlApplyFunctor d ident arity lExp True--> xmlApply d exp ((Constructor ident arity),lExp) =-> xmlApplyFunctor d ident arity lExp False--> xmlApply d (Apply expr1 expr2) e' =-> (text "<apply>" $$ nest level e1 $$ nest level e2 $$ text "</apply>", d2)-> where-> (e1,d1) = xmlExpr d expr1-> (e2,d2) = xmlExpr d1 expr2--> xmlApplyFunctor ::[(Int,Ident)] -> QualIdent -> Int -> [Expression] ->-> Bool -> (Doc,[(Int,Ident)])-> xmlApplyFunctor d ident arity lArgs isFunction =-> xmlCombApply d (xmlQualIdent ident) (text cTypeS) n lArgs-> where-> n = length (lArgs)-> cTypeS = if n==arity-> then if isFunction-> then "FuncCall"-> else "ConsCall"-> else "PartCall"---> xmlCombApply :: [(Int,Ident)] -> Doc -> Doc -> Int ->-> [Expression] -> (Doc,[(Int,Ident)])-> xmlCombApply d name cType 0 lArgs =-> (xmlCombHeading name cType True,d)-> xmlCombApply d name cType n lArgs =-> (xmlCombHeading name cType False $$ xmlLines id lDocs$$ text "</comb>", d1)-> where-> (lDocs,d1) = xmlMapDicc d xmlExpr lArgs---> xmlAppArgs :: Expression -> (Expression,[Expression])-> xmlAppArgs (Apply e1 e2) = (e,lArgs++[e2])-> where-> (e,lArgs) = (xmlAppArgs e1)-> xmlAppArgs e = (e,[])-> -- =========================================================================---> -- =========================================================================--> xmlCase :: [(Int,Ident)] -> Eval -> Expression -> [Alt] -> (Doc,[(Int,Ident)])-> xmlCase d eval expr lAlt =-> (heading $$ nest level e1 $$ xmlLines id lDocs$$ end,d2)-> where-> sEval = if eval==Rigid then "\"Rigid\"" else "\"Flex\""-> heading = text "<case type=" <> text sEval <> text ">"-> end = text "</case>"-> (e1,d1) = xmlExpr d expr-> (lDocs,d2) = xmlMapDicc d xmlBranch lAlt--> xmlOr :: [(Int,Ident)] -> Expression -> Expression -> (Doc,[(Int,Ident)])-> xmlOr d expr1 expr2 =-> (text "<or>" $$ nest level e1 $$ nest level e2 $$ text "</or>",d2)-> where-> (e1,d1) = xmlExpr d expr1-> (e2,d2) = xmlExpr d1 expr2---> xmlBranch :: [(Int,Ident)] -> Alt -> (Doc,[(Int,Ident)])-> xmlBranch d (Alt pattern expr) =-> (text "<branch>" $$ nest level e1 $$ nest level e2 $$ text "</branch>",d2)-> where-> (e1,d1) = xmlPattern d pattern-> (e2,d2) = xmlExpr d1 expr---> xmlPattern :: [(Int,Ident)] -> ConstrTerm -> (Doc,[(Int,Ident)])-> xmlPattern d (LiteralPattern lit) = (xmlLitPattern (xmlLit lit),d)-> xmlPattern d (ConstructorPattern ident lArgs) = xmlConsPattern d ident lArgs-> xmlPattern d (VariablePattern _) = error "Variable patterns not allowed in Flat Curry"--> xmlConsPattern :: [(Int,Ident)] -> QualIdent -> [Ident] -> (Doc,[(Int,Ident)])-> xmlConsPattern d ident lArgs =-> (heading $$ xmlLines id lDocs $$ end,d2)-> where-> heading = text "<pattern name=\""<> (xmlQualIdent ident) <>-> text "\"" <> endh-> endh = if (length lArgs)>0 then text ">" else text "/>"-> end = if (length lArgs)>0 then text "</pattern>" else empty-> (lDocs,d2) = xmlMapDicc d xmlExprVar lArgs--> -- =========================================================================---> xmlFree :: [(Int,Ident)] -> Ident -> Expression -> (Doc,[(Int,Ident)])-> xmlFree d ident exp =-> (text "<freevars>" $$ nest level v $$ nest level e $$ text "</freevars>",d2)-> where-> (v,d1) = xmlExprVar d ident-> (e,d2) = xmlExpr d1 exp---> -- =========================================================================--> xmlLet :: [(Int,Ident)] -> Binding -> Expression -> (Doc,[(Int,Ident)])-> xmlLet d binding exp =-> (text "<let>" $$ nest level b $$ nest level e $$ text "</let>", d2)-> where-> (b,d1) = xmlBinding d binding-> (e,d2) = xmlExpr d1 exp--> xmlBinding :: [(Int,Ident)] -> Binding -> (Doc,[(Int,Ident)])-> xmlBinding d (Binding ident exp) =-> (text "<binding>" $$ nest level v $$ nest level e $$ text "</binding>",d2)-> where-> (v,d1) = xmlExprVar d ident-> (e,d2) = xmlExpr d exp--> -- =========================================================================--> xmlLetrec :: [(Int,Ident)] -> [Binding] -> Expression -> (Doc,[(Int,Ident)])-> xmlLetrec d lB exp =-> (text "<letrec>" $$ xmlLines id b $$ nest level e $$ text "</letrec>",d2)-> where-> (b,d1) = xmlMapDicc d xmlBinding lB-> (e,d2) = xmlExpr d1 exp--> -- =========================================================================---> -- =========================================================================-> -- A U X I L I A R Y F U N C T I O N S-> -- =========================================================================--> splitDecls :: [Decl] -> ([Decl],[Decl])-> splitDecls [] = ([],[])-> splitDecls (x:xs) = case x of-> DataDecl _ _ _ -> (functionDecl,x:typeDecl)-> NewtypeDecl _ _ _ -> (x:functionDecl,typeDecl)-> FunctionDecl _ _ _ _ -> (x:functionDecl,typeDecl)-> ExternalDecl _ _ _ _ -> (x:functionDecl,typeDecl)-> where-> (functionDecl,typeDecl) = splitDecls xs-----> xmlElement :: Eq a => String -> (a -> Doc) -> [a] -> Doc-> xmlElement name f [] = text ("<"++name++" />")-> xmlElement name f lDecls = beginElement $$ xmlLines f lDecls $$ endElement-> where-> beginElement = text ("<"++name++">")-> endElement = text ("</"++name++">")->--> xmlLines :: (a -> Doc) -> [a] -> Doc-> xmlLines f = (nest level).vcat.(map f)---> xmlMapDicc::[(Int,Ident)] -> ([(Int,Ident)] -> a -> (Doc,[(Int,Ident)])) ->-> [a] -> ([Doc],[(Int,Ident)])-> xmlMapDicc d f lArgs = foldl newArg ([],d) lArgs-> where-> newArg (l,d) e = (l++[v'],d')-> where (v',d') = f d e->---> -- The dictionary identifies var names with integers-> -- it will be ordered starting at the greatest integer-> xmlBuildDicc :: [Ident] -> [(Int,Ident)]-> xmlBuildDicc l = reverse (zip [0..((length l)-1)] l)--> -- looks for a ident in the dictorionary. If it appears returns its-> -- associated value. Otherwise, -1 is returned-> xmlLookUp :: Ident -> [(Int,Ident)] -> Int-> xmlLookUp ident [] = -1-> xmlLookUp ident ((n,name):xs) = if ident==name-> then n-> else xmlLookUp ident xs--> -- generates a integer corresponding to a new var-> xmlNewVar :: [(Int,Ident)] -> Int-> xmlNewVar [] = 0-> xmlNewVar ((n,ident):xs) = n+1--> xmlVar :: Int -> Doc-> xmlVar n = text "<var>" <> xmlInt n <> text "</var>"--> xmlLiteral :: Doc -> Doc-> xmlLiteral d = text "<lit>" $$ nest level d $$ text "</lit>"--> xmlLitPattern :: Doc -> Doc-> xmlLitPattern d = text "<lpattern>" $$ nest level d $$ text "</lpattern>"---> xmlLit :: Literal -> Doc-> xmlLit (Char _ c) = text "<charc>" <> xmlInt (ord c) <> text "</charc>"-> xmlLit (Int _ n) = text "<intc>" <> xmlInteger n <> text "</intc>"-> xmlLit (Float _ n) = text "<floatc>" <> xmlFloat n <> text "</floatc>"--> xmlOperatorDecl :: CS.IDecl -> Doc-> xmlOperatorDecl (CS.IInfixDecl _ fixity prec qident) =-> text "<op fixity=\"" <> xmlFixity fixity -> <> text "\" prec=\"" <> xmlInteger prec <> text "\">"-> <> xmlIdent (unqualify qident)-> <> text "</op>"--> xmlFixity :: CS.Infix -> Doc-> xmlFixity CS.InfixL = text "InfixlOp"-> xmlFixity CS.InfixR = text "InfixrOp"-> xmlFixity CS.Infix = text "InfixOp"---> xmlTranslationDecl :: QualIdent -> Doc-> xmlTranslationDecl expId =-> text "<trans>" -> $$ nest level ( text "<name>" <> xmlIdent (unqualify expId) <> text "</name>"-> $$ text "<intname>" <> xmlQualIdent expId <> text "</intname>")-> $$ text "</trans>"---> xmlIdent :: Ident -> Doc-> xmlIdent ident = text (xmlFormat (name ident))--> xmlInt :: Int -> Doc-> xmlInt n = text (show n)--> xmlInteger :: Integer -> Doc-> xmlInteger n = text (show n)--> xmlFloat :: Double -> Doc-> xmlFloat n = text (show n)--> xmlQualIdent :: QualIdent -> Doc-> xmlQualIdent ident = text (xmlFormat (qualName ident))--> xmlModuleIdent:: ModuleIdent -> Doc-> xmlModuleIdent name = text (xmlFormat (moduleName name))--> xmlFormat :: String -> String-> xmlFormat [] = []-> xmlFormat ('>':xs) = ">"++xmlFormat xs-> xmlFormat ('<':xs) = "<"++xmlFormat xs-> xmlFormat ('&':xs) = "&"++xmlFormat xs-> xmlFormat (x:xs) = x:(xmlFormat xs)--> -- =========================================================================--> qualIDeclId :: ModuleIdent -> [QualIdent] -> CS.IDecl -> [QualIdent]-> qualIDeclId mid qids (CS.IDataDecl _ qid _ mcdecls)-> = foldl (qualConstrDeclId mid) (qid:qids) (catMaybes mcdecls)-> qualIDeclId mid qids (CS.INewtypeDecl _ qid _ ncdecl)-> = qualNewConstrDeclId mid (qid:qids) ncdecl-> qualIDeclId mid qids (CS.ITypeDecl _ qid _ _)-> = qid:qids-> qualIDeclId mid qids (CS.IFunctionDecl _ qid _ _)-> = qid:qids-> qualIDeclId mid qids _ = qids--> qualConstrDeclId :: ModuleIdent -> [QualIdent] -> CS.ConstrDecl -> -> [QualIdent]-> qualConstrDeclId mid qids (CS.ConstrDecl _ _ id _)-> = (qualifyWith mid id):qids-> qualConstrDeclId mid qids (CS.ConOpDecl _ _ _ id _)-> = (qualifyWith mid id):qids--> qualNewConstrDeclId :: ModuleIdent -> [QualIdent] -> CS.NewConstrDecl -> -> [QualIdent]-> qualNewConstrDeclId mid qids (CS.NewConstrDecl _ _ id _)-> = (qualifyWith mid id):qids---\end{verbatim}
− src/Ident.lhs
@@ -1,415 +0,0 @@-> {-# LANGUAGE DeriveDataTypeable #-}--% $Id: Ident.lhs,v 1.21 2004/10/29 13:08:09 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{Ident.lhs}-\section{Identifiers}-This module provides the implementation of identifiers and some-utility functions for identifiers, which are used at various places in-the compiler.--Identifiers comprise the name of the denoted entity and an \emph{id},-which can be used for renaming identifiers, e.g., in order to resolve-name conflicts between identifiers from different scopes. An-identifier with an \emph{id} $0$ is considered as not being renamed-and, hence, its \emph{id} will not be shown.--\ToDo{Probably we should use \texttt{Integer} for the \emph{id}s.}--Qualified identifiers may optionally be prefixed by a module-name. \textbf{The order of the cases \texttt{UnqualIdent} and-\texttt{QualIdent} is important. Some parts of the compiler rely on-the fact that all qualified identifiers are greater than any-unqualified identifier.}-\begin{verbatim}--> module Ident(Ident,QualIdent,ModuleIdent,SrcRefOf(..),-> mkIdent,name,qualName,uniqueId,renameIdent,unRenameIdent,-> mkMIdent,moduleName,moduleQualifiers,isInfixOp,isQInfixOp,-> qualify,qualifyWith,qualQualify,isQualified,-> unqualify,qualUnqualify,localIdent,splitQualIdent,-> emptyMIdent,mainMIdent,preludeMIdent,-> anonId,unitId,boolId,charId,intId,floatId,listId,ioId,-> successId,trueId,falseId,nilId,consId,mainId,-> tupleId,isTupleId,tupleArity,-> minusId,fminusId,updIdentName,-> qUnitId,qBoolId,qCharId,qIntId,qFloatId,qListId,qIOId,-> qSuccessId,qTrueId,qFalseId,qNilId,qConsId,-> qTupleId,isQTupleId,qTupleArity,-> fpSelectorId,isFpSelectorId,isQualFpSelectorId,-> recSelectorId,qualRecSelectorId,-> recUpdateId, qualRecUpdateId, recordExtId, labelExtId,-> isRecordExtId, isLabelExtId, fromRecordExtId, fromLabelExtId,-> renameLabel, isLabel, fpSelExt, recSelExt, recUpdExt,-> recordExt, labelExt, mkLabelIdent,hasPositionIdent,-> showsIdent,showsQualIdent,showsModuleIdent,-> addPositionIdent, removePositionIdent, positionOfIdent,-> addPositionModuleIdent, removePositionModuleIdent,addRef,addRefId,-> positionOfModuleIdent,positionOfQualIdent,updQualIdent ) where--> import Data.Char-> import Data.List-> import Data.Maybe-> import Data.Generics--> import Position---> data Ident = Ident String Int -> | IdentPosition Position String Int deriving (Read,Data,Typeable)-> data QualIdent = UnqualIdent Ident | QualIdent ModuleIdent Ident-> deriving (Eq,Ord,Read,Data,Typeable)-> data ModuleIdent = ModuleIdent [String] -> |ModuleIdentPosition Position [String] deriving (Data,Typeable)--> instance Eq Ident where-> ident1 == ident2 = name ident1 == name ident2 && -> uniqueId ident1 == uniqueId ident2--> instance Ord ModuleIdent where-> mident1 `compare` mident2 =-> moduleQualifiers mident1 `compare` moduleQualifiers mident2--> instance Eq ModuleIdent where-> mident1 == mident2 = moduleQualifiers mident1 == moduleQualifiers mident2 --> instance Read ModuleIdent where-> readsPrec p s = [ (mkMIdent [m],s') | (m,s') <- readsPrec p s ]--> instance Ord Ident where-> ident1 `compare` ident2 =-> (name ident1,uniqueId ident1) `compare` (name ident2,uniqueId ident2)--> instance Show Ident where-> showsPrec _ (Ident x n)-> | n == 0 = showString x-> | otherwise = showString x . showChar '.' . shows n-> showsPrec _ (IdentPosition _ x n)-> | n == 0 = showString x-> | otherwise = showString x . showChar '.' . shows n-> instance Show QualIdent where-> showsPrec _ (UnqualIdent x) = shows x-> showsPrec _ (QualIdent m x) = shows m . showChar '.' . shows x-> instance Show ModuleIdent where-> showsPrec _ m = showString (moduleName m)--> hasPositionIdent :: Ident -> Bool-> hasPositionIdent (Ident _ _ ) = False-> hasPositionIdent (IdentPosition _ _ _) = True--> addPositionIdent :: Position -> Ident -> Ident-> addPositionIdent pos (Ident x n) = IdentPosition pos x n-> addPositionIdent AST{ast=sr} (IdentPosition pos x n) = -> IdentPosition pos{ast=sr} x n-> addPositionIdent pos (IdentPosition _ x n) = -> IdentPosition pos x n--> removePositionIdent :: Ident -> Ident-> removePositionIdent (Ident x n) = (Ident x n)-> removePositionIdent (IdentPosition _ x n) = (Ident x n)--> positionOfIdent :: Ident -> Position-> positionOfIdent (Ident _ _) = noPos-> positionOfIdent (IdentPosition pos _ _) = pos--> addPositionModuleIdent :: Position -> ModuleIdent -> ModuleIdent-> addPositionModuleIdent pos (ModuleIdent x) = ModuleIdentPosition pos x -> addPositionModuleIdent pos (ModuleIdentPosition _ x) = ModuleIdentPosition pos x --> removePositionModuleIdent :: ModuleIdent -> ModuleIdent-> removePositionModuleIdent (ModuleIdent x) = (ModuleIdent x)-> removePositionModuleIdent (ModuleIdentPosition _ x) = (ModuleIdent x)--> positionOfModuleIdent :: ModuleIdent -> Position-> positionOfModuleIdent (ModuleIdent _) = noPos-> positionOfModuleIdent (ModuleIdentPosition pos _) = pos--> positionOfQualIdent :: QualIdent -> Position-> positionOfQualIdent = positionOfIdent . snd . splitQualIdent--> mkIdent :: String -> Ident-> mkIdent x = Ident x 0--> name :: Ident -> String-> name (Ident x _) = x-> name (IdentPosition _ x _) = x--> qualName :: QualIdent -> String-> qualName (UnqualIdent x) = name x-> qualName (QualIdent m x) = moduleName m ++ "." ++ name x--> uniqueId :: Ident -> Int-> uniqueId (Ident _ n) = n-> uniqueId (IdentPosition _ _ n) = n--> renameIdent :: Ident -> Int -> Ident-> renameIdent (Ident x _) n = Ident x n-> renameIdent (IdentPosition p x _) n = IdentPosition p x n--> unRenameIdent :: Ident -> Ident-> unRenameIdent (Ident x _) = Ident x 0-> unRenameIdent (IdentPosition p x _) = IdentPosition p x 0--> mkMIdent :: [String] -> ModuleIdent-> mkMIdent = ModuleIdent--> moduleName :: ModuleIdent -> String-> moduleName (ModuleIdent xs) = concat (intersperse "." xs)-> moduleName (ModuleIdentPosition _ xs) = concat (intersperse "." xs)--> moduleQualifiers :: ModuleIdent -> [String]-> moduleQualifiers (ModuleIdent xs) = xs-> moduleQualifiers (ModuleIdentPosition _ xs) = xs--> isInfixOp :: Ident -> Bool-> isInfixOp (Ident ('<':c:cs) _)=-> last (c:cs) /= '>' || not (isAlphaNum c) && c `notElem` "_(["-> isInfixOp (Ident (c:_) _) = not (isAlphaNum c) && c `notElem` "_(["-> isInfixOp (Ident _ _) = False -- error "Zero-length identifier"-> isInfixOp x@(IdentPosition _ _ _) = isInfixOp $ removePositionIdent x--> isQInfixOp :: QualIdent -> Bool-> isQInfixOp (UnqualIdent x) = isInfixOp x-> isQInfixOp (QualIdent _ x) = isInfixOp x--\end{verbatim}-The functions \texttt{qualify} and \texttt{qualifyWith} convert an-unqualified identifier into a qualified identifier (without and with a-given module prefix, respectively).-\begin{verbatim}--> qualify :: Ident -> QualIdent-> qualify = UnqualIdent--> qualifyWith :: ModuleIdent -> Ident -> QualIdent-> qualifyWith = QualIdent--> qualQualify :: ModuleIdent -> QualIdent -> QualIdent-> qualQualify m (UnqualIdent x) = QualIdent m x-> qualQualify _ x = x--> isQualified :: QualIdent -> Bool-> isQualified (UnqualIdent _) = False-> isQualified (QualIdent _ _) = True--> unqualify :: QualIdent -> Ident-> unqualify (UnqualIdent x) = x-> unqualify (QualIdent _ x) = x--> qualUnqualify :: ModuleIdent -> QualIdent -> QualIdent-> qualUnqualify m (UnqualIdent x) = UnqualIdent x-> qualUnqualify m (QualIdent m' x)-> | m == m' = UnqualIdent x-> | otherwise = QualIdent m' x--> localIdent :: ModuleIdent -> QualIdent -> Maybe Ident-> localIdent _ (UnqualIdent x) = Just x-> localIdent m (QualIdent m' x)-> | m == m' = Just x-> | otherwise = Nothing--> splitQualIdent :: QualIdent -> (Maybe ModuleIdent,Ident)-> splitQualIdent (UnqualIdent x) = (Nothing,x)-> splitQualIdent (QualIdent m x) = (Just m,x)--> updQualIdent :: (ModuleIdent -> ModuleIdent) -> (Ident -> Ident) -> QualIdent -> QualIdent-> updQualIdent _ g (UnqualIdent x) = UnqualIdent (g x)-> updQualIdent f g (QualIdent m x) = QualIdent (f m) (g x)--> addRef :: SrcRef -> QualIdent -> QualIdent-> addRef r = updQualIdent id (addRefId r)--> addRefId :: SrcRef -> Ident -> Ident-> addRefId r = addPositionIdent (AST r)--\end{verbatim}-A few identifiers a predefined here.-\begin{verbatim}--> emptyMIdent, mainMIdent, preludeMIdent :: ModuleIdent-> emptyMIdent = ModuleIdent []-> mainMIdent = ModuleIdent ["main"]-> preludeMIdent = ModuleIdent ["Prelude"]--> anonId :: Ident-> anonId = Ident "_" 0--> unitPId :: Position -> Ident-> unitPId p = IdentPosition p "()" 0--> unitId, boolId, charId, intId, floatId, listId, ioId, successId :: Ident-> unitId = Ident "()" 0-> boolId = Ident "Bool" 0-> charId = Ident "Char" 0-> intId = Ident "Int" 0-> floatId = Ident "Float" 0-> listId = Ident "[]" 0-> ioId = Ident "IO" 0-> successId = Ident "Success" 0--> trueId, falseId, nilId, consId :: Ident-> trueId = Ident "True" 0-> falseId = Ident "False" 0-> nilId = Ident "[]" 0-> consId = Ident ":" 0--> tupleId :: Int -> Ident-> tupleId n-> | n >= 2 = Ident ("(" ++ replicate (n - 1) ',' ++ ")") 0-> | otherwise = error "internal error: tupleId"--> isTupleId :: Ident -> Bool-> isTupleId x = n > 1 && x == tupleId n-> where n = length (name x) - 1--> tupleArity :: Ident -> Int-> tupleArity x-> | n > 1 && x == tupleId n = n-> | otherwise = error "internal error: tupleArity"-> where n = length (name x) - 1--> mainId, minusId, fminusId :: Ident-> mainId = Ident "main" 0-> minusId = Ident "-" 0-> fminusId = Ident "-." 0--> qUnitId, qNilId, qConsId, qListId :: QualIdent-> qUnitId = UnqualIdent unitId-> qListId = UnqualIdent listId-> qNilId = UnqualIdent nilId-> qConsId = UnqualIdent consId--> qBoolId, qCharId, qIntId, qFloatId, qSuccessId, qIOId :: QualIdent-> qBoolId = QualIdent preludeMIdent boolId-> qCharId = QualIdent preludeMIdent charId-> qIntId = QualIdent preludeMIdent intId-> qFloatId = QualIdent preludeMIdent floatId-> qSuccessId = QualIdent preludeMIdent successId-> qIOId = QualIdent preludeMIdent ioId--> qTrueId, qFalseId :: QualIdent-> qTrueId = QualIdent preludeMIdent trueId-> qFalseId = QualIdent preludeMIdent falseId--> qTupleId :: Int -> QualIdent-> qTupleId = UnqualIdent . tupleId--> isQTupleId :: QualIdent -> Bool-> isQTupleId = isTupleId . unqualify--> qTupleArity :: QualIdent -> Int-> qTupleArity = tupleArity . unqualify--\end{verbatim}-Micellaneous function for generating and testing extended identifiers.-\begin{verbatim}--> fpSelectorId :: Int -> Ident-> fpSelectorId n = Ident (fpSelExt ++ show n) 0--> isFpSelectorId :: Ident -> Bool-> isFpSelectorId f = any (fpSelExt `isPrefixOf`) (tails (name f))--> isQualFpSelectorId :: QualIdent -> Bool-> isQualFpSelectorId = isFpSelectorId . unqualify--> recSelectorId :: QualIdent -> Ident -> Ident-> recSelectorId r l =-> mkIdent (recSelExt ++ name (unqualify r) ++ "." ++ name l)--> qualRecSelectorId :: ModuleIdent -> QualIdent -> Ident -> QualIdent-> qualRecSelectorId m r l = qualifyWith m' (recSelectorId r l)-> where m' = (fromMaybe m (fst (splitQualIdent r)))--> recUpdateId :: QualIdent -> Ident -> Ident-> recUpdateId r l = -> mkIdent (recUpdExt ++ name (unqualify r) ++ "." ++ name l)--> qualRecUpdateId :: ModuleIdent -> QualIdent -> Ident -> QualIdent-> qualRecUpdateId m r l = qualifyWith m' (recUpdateId r l)-> where m' = (fromMaybe m (fst (splitQualIdent r)))--> recordExtId :: Ident -> Ident-> recordExtId r = mkIdent (recordExt ++ name r)--> labelExtId :: Ident -> Ident-> labelExtId l = mkIdent (labelExt ++ name l)--> fromRecordExtId :: Ident -> Ident-> fromRecordExtId r -> | p == recordExt = mkIdent r'-> | otherwise = r-> where (p,r') = splitAt (length recordExt) (name r)--> fromLabelExtId :: Ident -> Ident-> fromLabelExtId l -> | p == labelExt = mkIdent l'-> | otherwise = l-> where (p,l') = splitAt (length labelExt) (name l)--> isRecordExtId :: Ident -> Bool-> isRecordExtId r = recordExt `isPrefixOf` name r--> isLabelExtId :: Ident -> Bool-> isLabelExtId l = labelExt `isPrefixOf` name l--> mkLabelIdent :: String -> Ident-> mkLabelIdent c = renameIdent (mkIdent c) (-1)--> renameLabel :: Ident -> Ident-> renameLabel l = renameIdent l (-1)--> isLabel :: Ident -> Bool-> isLabel l = uniqueId l == (-1)---> fpSelExt = "_#selFP"-> recSelExt = "_#selR@"-> recUpdExt = "_#updR@"-> recordExt = "_#Rec:"-> labelExt = "_#Lab:"--> showsString :: String -> ShowS-> showsString = (++)--> space :: ShowS-> space = showsString " "--> showsIdent :: Ident -> ShowS-> showsIdent x@(IdentPosition _ _ _) = showsIdent $ removePositionIdent x-> showsIdent (Ident name n)-> = showsString "(Ident " . shows name . space . shows n . showsString ")"--> showsQualIdent :: QualIdent -> ShowS-> showsQualIdent (UnqualIdent ident)-> = showsString "(UnqualIdent " . showsIdent ident . showsString ")"-> showsQualIdent (QualIdent mident ident)-> = showsString "(QualIdent "-> . showsModuleIdent mident . space-> . showsIdent ident-> . showsString ")"--> showsModuleIdent :: ModuleIdent -> ShowS-> showsModuleIdent = shows . moduleName--showsModuleIdent x@(ModuleIdentPosition _ _) = - showsModuleIdent $ removePositionModuleIdent x-showsModuleIdent (ModuleIdent []) = showsString "(ModuleIdent [])"-showsModuleIdent (ModuleIdent (s:strs))- = showsString "(ModuleIdent ["- . foldl (\sys y -> sys . showsString "," . shows y) (shows s) strs- . showsString "])"--\end{verbatim}--> instance SrcRefOf Ident where srcRefOf = srcRefOf . positionOfIdent-> instance SrcRefOf QualIdent where srcRefOf = srcRefOf . unqualify--> updIdentName :: (String -> String) -> Ident -> Ident-> updIdentName f ident = let p=positionOfIdent ident-> i=uniqueId ident-> n=name ident in-> addPositionIdent p $ flip renameIdent i $ mkIdent (f n)
src/Imports.lhs view
@@ -16,8 +16,11 @@ > import qualified Data.Set as Set > import qualified Data.Map as Map +> import Curry.Syntax+> import Types+> import Curry.Base.Position+> import Curry.Base.Ident > import Base-> import Env > import TopEnv @@ -31,10 +34,10 @@ The same is true for type expressions. \begin{verbatim} -> type ExpPEnv = Env Ident PrecInfo-> type ExpTCEnv = Env Ident TypeInfo-> type ExpValueEnv = Env Ident ValueInfo-> type ExpArityEnv = Env Ident ArityInfo+> type ExpPEnv = Map.Map Ident PrecInfo+> type ExpTCEnv = Map.Map Ident TypeInfo+> type ExpValueEnv = Map.Map Ident ValueInfo+> type ExpArityEnv = Map.Map Ident ArityInfo \end{verbatim} When an interface is imported, the compiler first transforms the@@ -69,10 +72,10 @@ > isVisible _ _ = const True > importEntities :: Entity a => ModuleIdent -> Bool -> (Ident -> Bool)-> -> (a -> a) -> Env Ident a -> TopEnv a -> TopEnv a+> -> (a -> a) -> Map.Map Ident a -> TopEnv a -> TopEnv a > importEntities m q isVisible f mEnv env = > foldr (uncurry (if q then qualImportTopEnv m else importUnqual m)) env-> [(x,f y) | (x,y) <- envToList mEnv, isVisible x]+> [(x,f y) | (x,y) <- Map.toList mEnv, isVisible x] > where importUnqual m x y = importTopEnv m x y . qualImportTopEnv m x y > importData :: (Ident -> Bool) -> TypeInfo -> TypeInfo@@ -111,18 +114,18 @@ module name. \begin{verbatim} -> intfEnv :: (ModuleIdent -> IDecl -> Env Ident a -> Env Ident a)-> -> Interface -> Env Ident a-> intfEnv bind (Interface m ds) = foldr (bind m) emptyEnv ds+> intfEnv :: (ModuleIdent -> IDecl -> Map.Map Ident a -> Map.Map Ident a)+> -> Interface -> Map.Map Ident a+> intfEnv bind (Interface m ds) = foldr (bind m) Map.empty ds > bindPrec :: ModuleIdent -> IDecl -> ExpPEnv -> ExpPEnv > bindPrec m (IInfixDecl _ fix p op) =-> bindEnv (unqualify op) (PrecInfo (qualQualify m op) (OpPrec fix p))+> Map.insert (unqualify op) (PrecInfo (qualQualify m op) (OpPrec fix p)) > bindPrec _ _ = id > bindTC :: ModuleIdent -> IDecl -> ExpTCEnv -> ExpTCEnv > bindTC m (IDataDecl _ tc tvs cs) mTCEnv -> | isJust (lookupEnv (unqualify tc) mTCEnv) =+> | isJust (Map.lookup (unqualify tc) mTCEnv) = > mTCEnv > | otherwise = > bindType DataType m tc tvs (map (fmap mkData) cs) mTCEnv@@ -150,7 +153,7 @@ > bindType :: (QualIdent -> Int -> a -> TypeInfo) -> ModuleIdent -> QualIdent > -> [Ident] -> a -> ExpTCEnv -> ExpTCEnv > bindType f m tc tvs =-> bindEnv (unqualify tc) . f (qualQualify m tc) (length tvs) +> Map.insert (unqualify tc) . f (qualQualify m tc) (length tvs) > bindTy :: ModuleIdent -> IDecl -> ExpValueEnv -> ExpValueEnv > bindTy m (IDataDecl _ tc tvs cs) =@@ -163,7 +166,7 @@ > -- flip (foldr (bindRecLabel m r')) fs > -- where r' = qualifyWith m (fromRecordExtId (unqualify r)) > bindTy m (IFunctionDecl _ f _ ty) =-> bindEnv (unqualify f)+> Map.insert (unqualify f) > (Value (qualQualify m f) (polyType (toQualType m [] ty))) > bindTy m _ = id @@ -183,27 +186,27 @@ > --bindRecLabel :: ModuleIdent -> QualIdent -> ([Ident],TypeExpr) > -- -> ExpValueEnv -> ExpValueEnv > --bindRecLabel m r ([l],ty) =-> -- bindEnv l (Label (qualify l) r (polyType (toQualType m [] ty)))+> -- Map.insert l (Label (qualify l) r (polyType (toQualType m [] ty))) > bindValue :: (QualIdent -> ExistTypeScheme -> ValueInfo) -> ModuleIdent > -> QualIdent -> [Ident] -> Ident -> [Ident] -> TypeExpr > -> ExpValueEnv -> ExpValueEnv-> bindValue f m tc tvs c evs ty = bindEnv c (f (qualifyLike tc c) sigma)+> bindValue f m tc tvs c evs ty = Map.insert c (f (qualifyLike tc c) sigma) > where sigma = ForAllExist (length tvs) (length evs) (toQualType m tvs ty)-> qualifyLike x = maybe qualify qualifyWith (fst (splitQualIdent x))+> qualifyLike x = maybe qualify qualifyWith (qualidMod x) > bindA :: ModuleIdent -> IDecl -> ExpArityEnv -> ExpArityEnv > bindA m (IDataDecl _ _ _ cs) expAEnv > = foldr (bindConstrA m) expAEnv (catMaybes cs) > bindA m (IFunctionDecl _ f a _) expAEnv-> = bindEnv (unqualify f) (ArityInfo (qualQualify m f) a) expAEnv+> = Map.insert (unqualify f) (ArityInfo (qualQualify m f) a) expAEnv > bindA _ _ expAEnv = expAEnv > bindConstrA :: ModuleIdent -> ConstrDecl -> ExpArityEnv -> ExpArityEnv > bindConstrA m (ConstrDecl _ _ c tys) expAEnv-> = bindEnv c (ArityInfo (qualifyWith m c) (length tys)) expAEnv+> = Map.insert c (ArityInfo (qualifyWith m c) (length tys)) expAEnv > bindConstrA m (ConOpDecl _ _ _ c _) expAEnv-> = bindEnv c (ArityInfo (qualifyWith m c) 2) expAEnv+> = Map.insert c (ArityInfo (qualifyWith m c) 2) expAEnv \end{verbatim} After the environments have been initialized, the optional import@@ -262,14 +265,14 @@ > expandThing :: ModuleIdent -> ExpTCEnv -> ExpValueEnv -> Ident > -> [Import] > expandThing m tcEnv tyEnv tc =-> case lookupEnv tc tcEnv of+> case Map.lookup tc tcEnv of > Just _ -> expandThing' m tyEnv tc (Just [ImportTypeWith tc []]) > Nothing -> expandThing' m tyEnv tc Nothing > expandThing' :: ModuleIdent -> ExpValueEnv -> Ident > -> Maybe [Import] -> [Import] > expandThing' m tyEnv f tcImport =-> case lookupEnv f tyEnv of+> case Map.lookup f tyEnv of > Just v > | isConstr v -> maybe (errorAt' (importDataConstr m f)) id tcImport > | otherwise -> Import f : maybe [] id tcImport@@ -281,21 +284,21 @@ > expandHide :: ModuleIdent -> ExpTCEnv -> ExpValueEnv -> Ident > -> [Import] > expandHide m tcEnv tyEnv tc =-> case lookupEnv tc tcEnv of+> case Map.lookup tc tcEnv of > Just _ -> expandHide' m tyEnv tc (Just [ImportTypeWith tc []]) > Nothing -> expandHide' m tyEnv tc Nothing > expandHide' :: ModuleIdent -> ExpValueEnv -> Ident > -> Maybe [Import] -> [Import] > expandHide' m tyEnv f tcImport =-> case lookupEnv f tyEnv of+> case Map.lookup f tyEnv of > Just _ -> Import f : maybe [] id tcImport > Nothing -> maybe (errorAt' (undefinedEntity m f)) id tcImport > expandTypeWith :: ModuleIdent -> ExpTCEnv -> Ident -> [Ident] > -> Import > expandTypeWith m tcEnv tc cs =-> case lookupEnv tc tcEnv of+> case Map.lookup tc tcEnv of > Just (DataType _ _ cs') -> > ImportTypeWith tc (map (checkConstr [c | Just (Data c _ _) <- cs']) cs) > Just (RenamingType _ _ (Data c _ _)) ->@@ -308,7 +311,7 @@ > expandTypeAll :: ModuleIdent -> ExpTCEnv -> Ident -> Import > expandTypeAll m tcEnv tc =-> case lookupEnv tc tcEnv of+> case Map.lookup tc tcEnv of > Just (DataType _ _ cs) -> ImportTypeWith tc [c | Just (Data c _ _) <- cs] > Just (RenamingType _ _ (Data c _ _)) -> ImportTypeWith tc [c] > Just _ -> errorAt' (nonDataType m tc)@@ -357,11 +360,6 @@ > undefinedEntity m x = > (positionOfIdent x, > "Module " ++ moduleName m ++ " does not export " ++ name x)--> undefinedType :: ModuleIdent -> Ident -> (Position,String)-> undefinedType m tc =-> (positionOfIdent tc, -> "Module " ++ moduleName m ++ " does not export a type " ++ name tc) > undefinedDataConstr :: ModuleIdent -> Ident -> Ident -> (Position,String) > undefinedDataConstr m tc c =
src/InterfaceCheck.hs view
@@ -11,7 +11,7 @@ import Data.List -import ExtendedFlat+import Curry.ExtendedFlat
src/KindCheck.lhs view
@@ -23,10 +23,13 @@ is defined more than once. \begin{verbatim} -> module KindCheck(kindCheck,kindCheckGoal) where+> module KindCheck(kindCheck) where > import Data.Maybe +> import Curry.Syntax+> import Curry.Base.Position+> import Curry.Base.Ident > import Base hiding (bindArity) > import TopEnv @@ -44,16 +47,10 @@ > kindCheck m tcEnv ds = > case linear (map tconstr ds') of > Linear -> map (checkDecl m kEnv) ds-> NonLinear (PIdent p tc) -> errorAt' (duplicateType tc)+> NonLinear tc -> errorAt' (duplicateType tc) > where ds' = filter isTypeDecl ds > kEnv = foldr (bindArity m) (fmap tcArity tcEnv) ds' -> kindCheckGoal :: TCEnv -> Goal -> Goal-> kindCheckGoal tcEnv (Goal p e ds) =-> Goal p (checkExpr m kEnv e) (map (checkDecl m kEnv) ds)-> where kEnv = fmap tcArity tcEnv-> m = mkMIdent []- \end{verbatim} The kind environment only needs to record the arity of each type constructor. \begin{verbatim}@@ -113,7 +110,7 @@ > | tv `elem` tvs = errorAt' (nonLinear tv) > | otherwise = tv : checkTypeLhs kEnv tvs > where isTypeConstr tv = not (null (lookupKind tv kEnv))-> checkTypeLhs kEnv [] = []+> checkTypeLhs _ [] = [] > checkConstrDecl :: ModuleIdent -> KindEnv -> [Ident] -> ConstrDecl -> ConstrDecl > checkConstrDecl m kEnv tvs (ConstrDecl p evs c tys) =@@ -268,10 +265,10 @@ Auxiliary definitions \begin{verbatim} -> tconstr :: Decl -> PIdent-> tconstr (DataDecl p tc _ _) = PIdent p tc-> tconstr (NewtypeDecl p tc _ _) = PIdent p tc-> tconstr (TypeDecl p tc _ _) = PIdent p tc+> tconstr :: Decl -> Ident+> tconstr (DataDecl p tc _ _) = tc+> tconstr (NewtypeDecl p tc _ _) = tc+> tconstr (TypeDecl p tc _ _) = tc > tconstr _ = internalError "tconstr" \end{verbatim}
− src/LLParseComb.lhs
@@ -1,292 +0,0 @@-% -*- LaTeX -*--% $Id: LLParseComb.lhs,v 1.26 2004/02/15 23:11:30 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{LLParseComb.lhs}-\section{Parsing Combinators}\label{sec:ll-parsecomb}-The parsing combinators implemented in the module \texttt{LLParseComb}-are based on the LL(1) parsing combinators developed by Swierstra and-Duponcheel~\cite{SwierstraDuponcheel96:Parsers}. They have been-adapted to using continuation passing style in order to work with the-lexing combinators described in the previous section. In addition, the-facilities for error correction are omitted in this implementation.--The two functions \texttt{applyParser} and \texttt{prefixParser} use-the specified parser for parsing a string. When \texttt{applyParser}-is used, an error is reported if the parser does not consume the whole-string, whereas \texttt{prefixParser} discards the rest of the input-string in this case.-\begin{verbatim}--> module LLParseComb(Symbol(..),Parser,-> applyParser,prefixParser, position,succeed,symbol,-> (<?>),(<|>),(<|?>),(<*>),(<\>),(<\\>),-> opt,(<$>),(<$->),(<*->),(<-*>),(<**>),(<??>),(<.>),-> many,many1, sepBy,sepBy1, chainr,chainr1,chainl,chainl1,-> bracket,ops, layoutOn,layoutOff,layoutEnd) where--> import Control.Monad-> import Data.Maybe-> import qualified Data.Set as Set-> import qualified Data.Map as Map---> import Position---> import Error-> import LexComb--> infixl 5 <\>, <\\>-> infixl 4 <*>, <$>, <$->, <*->, <-*>, <**>, <??>, <.>-> infixl 3 <|>, <|?>-> infixl 2 <?>, `opt`--\end{verbatim}-\paragraph{Parser types}-\begin{verbatim}--> class (Ord s,Show s) => Symbol s where-> isEOF :: s -> Bool--> type Empty = Bool-> type SuccessCont s a = Position -> s -> P a-> type FailureCont a = Position -> String -> P a-> type Lexer s a = SuccessCont s a -> FailureCont a -> P a-> type ParseFun s a b = (a -> SuccessCont s b) -> FailureCont b-> -> SuccessCont s b--> data Parser s a b = Parser (Maybe (ParseFun s a b))-> (Map.Map s (Lexer s b -> ParseFun s a b))--> instance Symbol s => Show (Parser s a b) where-> showsPrec p (Parser e ps) = showParen (p >= 10) $ -- $-> showString "Parser " . shows (isJust e) .-> showChar ' ' . shows (Map.keysSet ps)--> applyParser :: Symbol s => Parser s a a -> Lexer s a -> FilePath -> String-> -> Error a-> applyParser p lexer = parse (lexer (choose p lexer done failP) failP)-> where done x pos s-> | isEOF s = returnP x-> | otherwise = failP pos (unexpected s)--> prefixParser :: Symbol s => Parser s a a -> Lexer s a -> FilePath -> String-> -> Error a-> prefixParser p lexer = parse (lexer (choose p lexer discard failP) failP)-> where discard x _ _ = returnP x--> choose :: Symbol s => Parser s a b -> Lexer s b -> ParseFun s a b-> choose (Parser e ps) lexer success fail pos s =-> case Map.lookup s ps of-> Just p -> p lexer success fail pos s-> Nothing ->-> case e of-> Just p -> p success fail pos s-> Nothing -> fail pos (unexpected s)--> unexpected :: Symbol s => s -> String-> unexpected s-> | isEOF s = "Unexpected end-of-file"-> | otherwise = "Unexpected token " ++ show s--\end{verbatim}-\paragraph{Basic combinators}-\begin{verbatim}--> position :: Symbol s => Parser s Position b-> position = Parser (Just p) Map.empty-> where p success _ pos = success pos pos--> succeed :: Symbol s => a -> Parser s a b-> succeed x = Parser (Just p) Map.empty-> where p success _ = success x--> symbol :: Symbol s => s -> Parser s s a-> symbol s = Parser Nothing (Map.singleton s p)-> where p lexer success fail pos s = lexer (success s) fail--> (<?>) :: Symbol s => Parser s a b -> String -> Parser s a b-> p <?> msg = p <|> Parser (Just pfail) Map.empty-> where pfail _ fail pos _ = fail pos msg--> (<|>) :: Symbol s => Parser s a b -> Parser s a b -> Parser s a b-> Parser e1 ps1 <|> Parser e2 ps2-> | isJust e1 && isJust e2 = error "Ambiguous parser for empty word"-> | not (Set.null common) = error ("Ambiguous parser for " ++ show common)-> | otherwise = Parser (e1 `mplus` e2) (Map.union ps1 ps2)-> where common = Map.keysSet ps1 `Set.intersection` Map.keysSet ps2--\end{verbatim}-The parsing combinators presented so far require that the grammar-being parsed is LL(1). In some cases it may be difficult or even-impossible to transform a grammar into LL(1) form. As a remedy, we-include a non-deterministic version of the choice combinator in-addition to the deterministic combinator adapted from the paper. For-every symbol from the intersection of the parser's first sets, the-combinator \texttt{(<|?>)} applies both parsing functions to the input-stream and uses that one which processes the longer prefix of the-input stream irrespective of whether it succeeds or fails. If both-functions recognize the same prefix, we choose the one that succeeds-and report an ambiguous parse error if both succeed.-\begin{verbatim}--> (<|?>) :: Symbol s => Parser s a b -> Parser s a b -> Parser s a b-> Parser e1 ps1 <|?> Parser e2 ps2-> | isJust e1 && isJust e2 = error "Ambiguous parser for empty word"-> | otherwise = Parser (e1 `mplus` e2) (Map.union ps1' ps2)-> where ps1' = Map.fromList [(s,maybe p (try p) (Map.lookup s ps2))-> | (s,p) <- Map.toList ps1]-> try p1 p2 lexer success fail pos s =-> closeP1 p2s `thenP` \p2s' ->-> closeP1 p2f `thenP` \p2f' ->-> parse p1 (retry p2s') (retry p2f')-> where p2s r1 = parse p2 (select True r1) (select False r1)-> p2f r1 = parse p2 (flip (select False) r1) (select False r1)-> parse p psucc pfail =-> p lexer (successK psucc) (failK pfail) pos s-> successK k x pos s = k (pos,success x pos s)-> failK k pos msg = k (pos,fail pos msg)-> retry k (pos,p) = closeP0 p `thenP` curry k pos-> select suc (pos1,p1) (pos2,p2) =-> case pos1 `compare` pos2 of-> GT -> p1-> EQ-> | suc -> error ("Ambiguous parse before " ++ show pos1)-> | otherwise -> p1-> LT -> p2--> (<*>) :: Symbol s => Parser s (a -> b) c -> Parser s a c -> Parser s b c-> Parser (Just p1) ps1 <*> ~p2@(Parser e2 ps2) =-> Parser (fmap (seqEE p1) e2)-> (Map.union (fmap (flip seqPP p2) ps1) (fmap (seqEP p1) ps2))-> Parser Nothing ps1 <*> p2 = Parser Nothing (fmap (flip seqPP p2) ps1)--> seqEE :: Symbol s => ParseFun s (a -> b) c -> ParseFun s a c-> -> ParseFun s b c-> seqEE p1 p2 success fail = p1 (\f -> p2 (success . f) fail) fail--> seqEP :: Symbol s => ParseFun s (a -> b) c -> (Lexer s c -> ParseFun s a c)-> -> Lexer s c -> ParseFun s b c-> seqEP p1 p2 lexer success fail = p1 (\f -> p2 lexer (success . f) fail) fail--> seqPP :: Symbol s => (Lexer s c -> ParseFun s (a -> b) c) -> Parser s a c-> -> Lexer s c -> ParseFun s b c-> seqPP p1 p2 lexer success fail =-> p1 lexer (\f -> choose p2 lexer (success . f) fail) fail--\end{verbatim}-The combinators \verb|<\\>| and \verb|<\>| can be used to restrict-the first set of a parser. This is useful for combining two parsers-with an overlapping first set with the deterministic combinator <|>.-\begin{verbatim}--> (<\>) :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c-> p <\> Parser _ ps = p <\\> Map.keys ps--> (<\\>) :: Symbol s => Parser s a b -> [s] -> Parser s a b-> Parser e ps <\\> xs = Parser e (foldr Map.delete ps xs)--\end{verbatim}-\paragraph{Other combinators.}-Note that some of these combinators have not been published in the-paper, but were taken from the implementation found on the web.-\begin{verbatim}--> opt :: Symbol s => Parser s a b -> a -> Parser s a b-> p `opt` x = p <|> succeed x--> (<$>) :: Symbol s => (a -> b) -> Parser s a c -> Parser s b c-> f <$> p = succeed f <*> p--> (<$->) :: Symbol s => a -> Parser s b c -> Parser s a c-> f <$-> p = const f <$> p {-$-}--> (<*->) :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c-> p <*-> q = const <$> p <*> q {-$-}--> (<-*>) :: Symbol s => Parser s a c -> Parser s b c -> Parser s b c-> p <-*> q = const id <$> p <*> q {-$-}--> (<**>) :: Symbol s => Parser s a c -> Parser s (a -> b) c -> Parser s b c-> p <**> q = flip ($) <$> p <*> q--> (<??>) :: Symbol s => Parser s a b -> Parser s (a -> a) b -> Parser s a b-> p <??> q = p <**> (q `opt` id)--> (<.>) :: Symbol s => Parser s (a -> b) d -> Parser s (b -> c) d-> -> Parser s (a -> c) d-> p1 <.> p2 = p1 <**> ((.) <$> p2)--> many :: Symbol s => Parser s a b -> Parser s [a] b-> many p = many1 p `opt` []--> many1 :: Symbol s => Parser s a b -> Parser s [a] b-> -- many1 p = (:) <$> p <*> many p-> many1 p = (:) <$> p <*> (many1 p `opt` [])--\end{verbatim}-The first definition of \texttt{many1} is commented out because it-does not compile under nhc. This is due to a -- known -- bug in the-type checker of nhc which expects a default declaration when compiling-mutually recursive functions with class constraints. However, no such-default can be given in the above case because neither of the types-involved is a numeric type.-\begin{verbatim}--> sepBy :: Symbol s => Parser s a c -> Parser s b c -> Parser s [a] c-> p `sepBy` q = p `sepBy1` q `opt` []--> sepBy1 :: Symbol s => Parser s a c -> Parser s b c -> Parser s [a] c-> p `sepBy1` q = (:) <$> p <*> many (q <-*> p) {-$-}--> chainr :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b -> a-> -> Parser s a b-> chainr p op x = chainr1 p op `opt` x--> chainr1 :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b-> -> Parser s a b-> chainr1 p op = r-> where r = p <**> (flip <$> op <*> r `opt` id) {-$-}--> chainl :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b -> a-> -> Parser s a b-> chainl p op x = chainl1 p op `opt` x--> chainl1 :: Symbol s => Parser s a b -> Parser s (a -> a -> a) b-> -> Parser s a b-> chainl1 p op = foldF <$> p <*> many (flip <$> op <*> p)-> where foldF x [] = x-> foldF x (f:fs) = foldF (f x) fs--> bracket :: Symbol s => Parser s a c -> Parser s b c -> Parser s a c-> -> Parser s b c-> bracket open p close = open <-*> p <*-> close--> ops :: Symbol s => [(s,a)] -> Parser s a b-> ops [] = error "internal error: ops"-> ops [(s,x)] = x <$-> symbol s-> ops ((s,x):rest) = x <$-> symbol s <|> ops rest--\end{verbatim}-\paragraph{Layout combinators}-Note that the layout functions grab the next token (and its position).-After modifying the layout context, the continuation is called with-the same token and an undefined result.-\begin{verbatim}--> layoutOn :: Symbol s => Parser s a b-> layoutOn = Parser (Just on) Map.empty-> where on success _ pos = pushContext (column pos) . success undefined pos--> layoutOff :: Symbol s => Parser s a b-> layoutOff = Parser (Just off) Map.empty-> where off success _ pos = pushContext (-1) . success undefined pos--> layoutEnd :: Symbol s => Parser s a b-> layoutEnd = Parser (Just end) Map.empty-> where end success _ pos = popContext . success undefined pos--\end{verbatim}
− src/LexComb.lhs
@@ -1,102 +0,0 @@-% -*- LaTeX -*--% $Id: LexComb.lhs,v 1.16 2004/01/20 16:44:14 wlux Exp $-%-% Copyright (c) 1999-2004, Wolfgang Lux-% See LICENSE for the full license.-%-\nwfilename{LexComb.lhs}-\section{Lexing combinators}-The module \texttt{LexComb} provides the basic types and combinators-to implement the lexers. The combinators use continuation passing code-in a monadic style. The first argument of the continuation function is-the string to be parsed, the second is the current position, and the-third is a flag which signals the lexer that it is lexing the-beginning of a line and therefore has to check for layout tokens. The-fourth argument is a stack of indentations that is used to handle-nested layout groups.-\begin{verbatim}--> module LexComb where-> import Position-> import Error-> import Data.Char--> infixl 1 `thenP`, `thenP_`--> type Indent = Int-> type Context = [Indent]-> type P a = Position -> String -> Bool -> Context -> Error a--> parse :: P a -> FilePath -> String -> Error a-> parse p fn s = p (first fn) s False []--\end{verbatim}-Monad functions for the lexer.-\begin{verbatim}--> returnP :: a -> P a-> returnP x _ _ _ _ = Ok x--> thenP :: P a -> (a -> P b) -> P b-> thenP lex k pos s bol ctxt = lex pos s bol ctxt >>= \x -> k x pos s bol ctxt--> thenP_ :: P a -> P b -> P b-> p1 `thenP_` p2 = p1 `thenP` \_ -> p2--> failP :: Position -> String -> P a-> failP pos msg _ _ _ _ = Error (parseError pos msg)--> closeP0 :: P a -> P (P a)-> closeP0 lex pos s bol ctxt = Ok (\_ _ _ _ -> lex pos s bol ctxt)--> closeP1 :: (a -> P b) -> P (a -> P b)-> closeP1 f pos s bol ctxt = Ok (\x _ _ _ _ -> f x pos s bol ctxt)--> parseError :: Position -> String -> String-> parseError p what = "\n" ++ show p ++ ": " ++ what--\end{verbatim}-Combinators that handle layout.-\begin{verbatim}--> pushContext :: Int -> P a -> P a-> pushContext col cont pos s bol ctxt = cont pos s bol (col:ctxt)--> popContext :: P a -> P a-> popContext cont pos s bol (_:ctxt) = cont pos s bol ctxt-> popContext cont pos s bol [] = -> error "parse error: popping layout from empty context stack. \-> \Perhaps you have inserted too many '}'?"--\end{verbatim}-Conversions from strings into numbers.-\begin{verbatim}--> convertSignedIntegral :: Num a => a -> String -> a-> convertSignedIntegral b ('+':s) = convertIntegral b s-> convertSignedIntegral b ('-':s) = - convertIntegral b s-> convertSignedIntegral b s = convertIntegral b s--> convertIntegral :: Num a => a -> String -> a-> convertIntegral b = foldl op 0-> where m `op` n | isDigit n = b * m + fromIntegral (ord n - ord0)-> | isUpper n = b * m + fromIntegral (ord n - ordA)-> | otherwise = b * m + fromIntegral (ord n - orda)-> ord0 = ord '0'-> ordA = ord 'A' - 10-> orda = ord 'a' - 10--> convertSignedFloating :: Fractional a => String -> String -> Int -> a-> convertSignedFloating ('+':m) f e = convertFloating m f e-> convertSignedFloating ('-':m) f e = - convertFloating m f e-> convertSignedFloating m f e = convertFloating m f e--> convertFloating :: Fractional a => String -> String -> Int -> a-> convertFloating m f e-> | e' == 0 = m'-> | e' > 0 = m' * 10^e'-> | otherwise = m' / 10^(-e')-> where m' = convertIntegral 10 (m ++ f)-> e' = e - length f--\end{verbatim}
src/Lift.lhs view
@@ -20,23 +20,24 @@ > module Lift(lift) where > import Control.Monad+> import qualified Control.Monad.State as S > import Data.List+> import qualified Data.Map as Map > import qualified Data.Set as Set +> import Curry.Syntax+> import Curry.Syntax.Utils+> import Types+> import Curry.Base.Ident > import Base-> import Env > import TopEnv----> import Combined > import SCC > lift :: ValueEnv -> EvalEnv -> Module -> (Module,ValueEnv,EvalEnv) > lift tyEnv evEnv (Module m es ds) = > (Module m es (concatMap liftFunDecl ds'),tyEnv',evEnv') > where (ds',tyEnv',evEnv') =-> runSt (callSt (abstractModule m ds) tyEnv) evEnv+> S.evalState (S.evalStateT (abstractModule m ds) tyEnv) evEnv \end{verbatim} \paragraph{Abstraction}@@ -49,16 +50,16 @@ i.e. the function applied to its free variables. \begin{verbatim} -> type AbstractState a = StateT ValueEnv (St EvalEnv) a-> type AbstractEnv = Env Ident Expression+> type AbstractState a = S.StateT ValueEnv (S.State EvalEnv) a+> type AbstractEnv = Map.Map Ident Expression > abstractModule :: ModuleIdent -> [Decl] > -> AbstractState ([Decl],ValueEnv,EvalEnv) > abstractModule m ds = > do-> ds' <- mapM (abstractDecl m "" [] emptyEnv) ds-> tyEnv' <- fetchSt-> evEnv' <- liftSt fetchSt+> ds' <- mapM (abstractDecl m "" [] Map.empty) ds+> tyEnv' <- S.get+> evEnv' <- S.lift S.get > return (ds',tyEnv',evEnv') > abstractDecl :: ModuleIdent -> String -> [Ident] -> AbstractEnv -> Decl@@ -149,9 +150,9 @@ > return (Let vds' e') > abstractFunDecls m pre lvs env (fds:fdss) vds e = > do-> fs' <- liftM (\tyEnv -> filter (not . isLifted tyEnv) fs) fetchSt-> updateSt_ (abstractFunTypes m pre fvs fs')-> liftSt (updateSt_ (abstractFunAnnots m pre fs'))+> fs' <- liftM (\tyEnv -> filter (not . isLifted tyEnv) fs) S.get+> S.modify (abstractFunTypes m pre fvs fs')+> S.lift (S.modify (abstractFunAnnots m pre fs')) > fds' <- mapM (abstractFunDecl m pre fvs lvs env') > [d | d <- fds, any (`elem` fs') (bv d)] > e' <- abstractFunDecls m pre lvs env' fdss vds e@@ -160,8 +161,8 @@ > fvs = filter (`elem` lvs) (Set.toList fvsRhs) > env' = foldr (bindF (map mkVar fvs)) env fs > fvsRhs = Set.unions-> [Set.fromList (maybe [v] (qfv m) (lookupEnv v env)) | v <- qfv m fds]-> bindF fvs f = bindEnv f (apply (mkFun m pre f) fvs)+> [Set.fromList (maybe [v] (qfv m) (Map.lookup v env)) | v <- qfv m fds]+> bindF fvs f = Map.insert f (apply (mkFun m pre f) fvs) > isLifted tyEnv f = null (lookupValue f tyEnv) > abstractFunTypes :: ModuleIdent -> String -> [Ident] -> [Ident]@@ -176,8 +177,8 @@ > abstractFunAnnots :: ModuleIdent -> String -> [Ident] -> EvalEnv -> EvalEnv > abstractFunAnnots m pre fs evEnv = foldr abstractFunAnnot evEnv fs > where abstractFunAnnot f evEnv =-> case lookupEnv f evEnv of-> Just ev -> bindEnv (liftIdent pre f) ev (unbindEnv f evEnv)+> case Map.lookup f evEnv of+> Just ev -> Map.insert (liftIdent pre f) ev (Map.delete f evEnv) > Nothing -> evEnv > abstractFunDecl :: ModuleIdent -> String -> [Ident] -> [Ident]@@ -196,7 +197,7 @@ > abstractExpr m pre lvs env (Variable v) > | isQualified v = return (Variable v) > | otherwise = maybe (return (Variable v)) (abstractExpr m pre lvs env)-> (lookupEnv (unqualify v) env)+> (Map.lookup (unqualify v) env) > abstractExpr _ _ _ _ (Constructor c) = return (Constructor c) > abstractExpr m pre lvs env (Apply e1 e2) = > do@@ -216,14 +217,6 @@ > abstractAlt m pre lvs env (Alt p t rhs) = > liftM (Alt p t) (abstractRhs m pre (lvs ++ bv t) env rhs) -> abstractCondExpr :: ModuleIdent -> String -> [Ident] -> AbstractEnv-> -> CondExpr -> AbstractState CondExpr-> abstractCondExpr m pre lvs env (CondExpr p g e) =-> do-> g' <- abstractExpr m pre lvs env g-> e' <- abstractExpr m pre lvs env e-> return (CondExpr p g' e')- \end{verbatim} \paragraph{Lifting} After the abstraction pass, all local function declarations are lifted@@ -273,10 +266,6 @@ > liftAlt (Alt p t rhs) = (Alt p t rhs',ds') > where (rhs',ds') = liftRhs rhs -> liftCondExpr :: CondExpr -> (CondExpr,[Decl])-> liftCondExpr (CondExpr p g e) = (CondExpr p g' e',ds' ++ ds'')-> where (g',ds') = liftExpr g-> (e',ds'') = liftExpr e \end{verbatim} \paragraph{Auxiliary definitions}
− src/Message.hs
@@ -1,74 +0,0 @@---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Message - A library for dealing with compiler messages------ Note: This module overwrites the functions declared in "Message"--- --- January 2006,--- Martin Engelke (men@informatik.uni-kiel.de)----module Message where--import Position-------------------------------------------------------------------------------------- Type for representing compiler messages (currently errors and warnings)-data Message = Message MessageType (Maybe Position) String---- Data type for representing available compiler message types-data MessageType = Warning WarningType | Error deriving Eq---- the different warnings are categorized by WarningType-data WarningType = UnrefTypeVar- | UnrefVar- | ShadowingVar- | IdleCaseAlt- | OverlapCase- | OverlapRules- | RulesNotTogether- | MultipleImportModule- | MultipleImportSymbol- | MultipleHiding - deriving Eq---- An instance of Show for converting messages to readable strings-instance Show Message where- show (Message (Warning _) mpos msg) = showMessage "Warning" mpos msg- show (Message Error mpos msg) = showMessage "ERROR" mpos msg---------------------------------------------------------------------------------------message :: MessageType -> Position -> String -> Message-message mtype pos msg = Message mtype (Just pos) msg-----message_ :: MessageType -> String -> Message-message_ mtype msg = Message mtype Nothing msg-----countMessages :: MessageType -> [Message] -> Int-countMessages mtype msgs = length (filter (((==) mtype) . messageType) msgs)-----messageType :: Message -> MessageType-messageType (Message mtype _ _) = mtype-----------------------------------------------------------------------------------------------------------------------------------------------------------------------showMessage :: String -> (Maybe Position) -> String -> String-showMessage what mpos msg- = what ++ ": " ++ pos ++ msg- where- pos = maybe "" (\p -> show p ++ ": ") mpos------------------------------------------------------------------------------------------------------------------------------------------------------------------
src/Modules.lhs view
@@ -15,54 +15,59 @@ import declarations are commented out \begin{verbatim} -> module Modules(compileModule, compileModule_,+> module Modules(compileModule,+> importPrelude, patchModuleId, > loadInterfaces, transModule, > simpleCheckModule, checkModule > ) where + > import Data.List+> import qualified Data.Map as Map > import System.IO > import Data.Maybe > import Control.Monad +> import Curry.Base.MessageMonad+> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax+> import Curry.Syntax.Pretty(ppModule,ppIDecl)+> import Curry.Syntax.ShowModule(showModule)+ > import Base-> import Unlit(unlit)-> import CurryParser(parseSource,parseGoal) -- xxxGoal entfernen-> import ShowCurrySyntax(showModule)-> import KindCheck(kindCheck,kindCheckGoal)+> import Types+> import KindCheck(kindCheck) > import SyntaxCheck(syntaxCheck)-> import PrecCheck(precCheck,precCheckGoal)-> import TypeCheck(typeCheck,typeCheckGoal)-> import WarnCheck-> import Message+> import PrecCheck(precCheck)+> import TypeCheck(typeCheck)+> import WarnCheck(warnCheck) > import Arity > import Imports(importInterface,importInterfaceIntf,importUnifyData) > import Exports(expandInterface,exportInterface)-> import Eval(evalEnv,evalEnvGoal)-> import Qual(qual,qualGoal)-> import Desugar(desugar,desugarGoal)+> import Eval(evalEnv)+> import Qual(qual)+> import Desugar(desugar) > import Simplify(simplify) > import Lift(lift)-> import qualified IL-> import ILTrans(ilTrans,ilTransIntf)-> import ILxml(xmlModule) -- check-> import ExtendedFlat+> import qualified IL.Type as IL+> import IL.CurryToIL(ilTrans)+> import IL.XML(xmlModule)+> import Curry.ExtendedFlat > import GenFlatCurry (genFlatCurry,genFlatInterface)-> import AbstractCurry+> import qualified Curry.AbstractCurry as AC > import GenAbstractCurry > import InterfaceCheck > import CurryEnv-> import CurryPP(ppModule,ppInterface,ppIDecl,ppGoal)-> import qualified ILPP(ppModule)+> import qualified IL.Pretty(ppModule) > import CurryCompilerOpts(Options(..),Dump(..))-> import CompilerResults > import CaseCompletion > import PathUtils+> import Filenames > import TypeSubst-> import Pretty-> import Error-> import Env+> import PrettyCombinators > import TopEnv+> import qualified Curry.ExtendedFlat as EF \end{verbatim} The function \texttt{compileModule} is the main entry-point of this@@ -88,13 +93,10 @@ code are obsolete and commented out. \begin{verbatim} -> compileModule :: Options -> FilePath -> IO ()-> compileModule opts fn = compileModule_ opts fn >> return ()--> compileModule_ :: Options -> FilePath -> IO CompilerResults-> compileModule_ opts fn =+> compileModule :: Options -> FilePath -> IO (Maybe FilePath)+> compileModule opts fn = > do-> mod <- liftM (parseModule likeFlat fn) (readModule fn)+> mod <- liftM (importPrelude fn . ok . parseModule likeFlat fn) (readModule fn) > let m = patchModuleId fn mod > checkModuleId fn m > mEnv <- loadInterfaces (importPaths opts) m@@ -103,12 +105,12 @@ > do (tyEnv, tcEnv, aEnv, m', intf, _) <- simpleCheckModule opts mEnv m > if uacy then genAbstract opts fn tyEnv tcEnv m' > else do-> let outputFile = maybe (replaceExtension fn sourceRepExt) +> let outputFile = maybe (sourceRepName fn) > id > (output opts) > outputMod = showModule m' > writeModule outputFile outputMod-> return defaultResults+> return Nothing > else > do (tyEnv, tcEnv, aEnv, m', intf, _) <- checkModule opts mEnv m > let (il,aEnv',dumps) = transModule fcy False False @@ -125,15 +127,11 @@ > genCode opts fn mEnv tyEnv tcEnv aEnv intf m il > | fcy || xml = genFlat opts fn mEnv tyEnv tcEnv aEnv intf m il > | acy = genAbstract opts fn tyEnv tcEnv m-> | otherwise = return defaultResults--> parseModule :: Bool -> FilePath -> String -> Module-> parseModule likeFlat fn =-> importPrelude fn . ok . parseSource likeFlat fn . unlitLiterate fn+> | otherwise = return Nothing > loadInterfaces :: [FilePath] -> Module -> IO ModuleEnv > loadInterfaces paths (Module m _ ds) =-> foldM (loadInterface paths [m]) emptyEnv+> foldM (loadInterface paths [m]) Map.empty > [(p,m) | ImportDecl p m _ _ _ <- ds] > checkModuleId :: Monad m => FilePath -> Module -> m ()@@ -146,7 +144,7 @@ > ++ ".curry\"") > simpleCheckModule :: Options -> ModuleEnv -> Module -> -> IO (ValueEnv,TCEnv,ArityEnv,Module,Interface,[Message])+> -> IO (ValueEnv,TCEnv,ArityEnv,Module,Interface,[WarnMsg]) > simpleCheckModule opts mEnv (Module m es ds) = > do unless (noWarn opts) (printMessages msgs) > return (tyEnv'', tcEnv, aEnv'', modul, intf, msgs)@@ -160,12 +158,12 @@ > $ kindCheck m tcEnv topDs > ds' = impDs ++ qual m tyEnv topDs' > modul = (Module m es ds') --expandInterface (Module m es ds') tcEnv tyEnv-> (pEnv'',tcEnv'',tyEnv'',aEnv'') +> (_,tcEnv'',tyEnv'',aEnv'') > = qualifyEnv mEnv pEnv' tcEnv tyEnv aEnv > intf = exportInterface modul pEnv' tcEnv'' tyEnv'' > checkModule :: Options -> ModuleEnv -> Module -> -> IO (ValueEnv,TCEnv,ArityEnv,Module,Interface,[Message])+> -> IO (ValueEnv,TCEnv,ArityEnv,Module,Interface,[WarnMsg]) > checkModule opts mEnv (Module m es ds) = > do unless (noWarn opts) (printMessages msgs) > when (m == mkMIdent ["field114..."])@@ -216,8 +214,8 @@ > (DumpDesugared,ppModule desugared), > (DumpSimplified,ppModule simplified), > (DumpLifted,ppModule lifted),-> (DumpIL,ILPP.ppModule il),-> (DumpCase,ILPP.ppModule il')+> (DumpIL,IL.Pretty.ppModule il),+> (DumpCase,IL.Pretty.ppModule il') > ] > qualifyEnv :: ModuleEnv -> PEnv -> TCEnv -> ValueEnv -> ArityEnv@@ -228,7 +226,7 @@ > foldr bindGlobal tyEnv' (localBindings tyEnv), > foldr bindQual aEnv' (localBindings aEnv)) > where (pEnv',tcEnv',tyEnv',aEnv') =-> foldl importInterface initEnvs (envToList mEnv)+> foldl importInterface initEnvs (Map.toList mEnv) > importInterface (pEnv,tcEnv,tyEnv,aEnv) (m,ds) = > importInterfaceIntf (Interface m ds) pEnv tcEnv tyEnv aEnv > bindQual (_,y) = qualBindTopEnv "Modules.qualifyEnv" (origName y) y@@ -236,30 +234,18 @@ > | uniqueId x == 0 = bindQual (x,y) > | otherwise = bindTopEnv "Modules.qualifyEnv" x y -> --ilImports :: ValueEnv -> TCEnv -> ModuleEnv -> IL.Module -> [IL.Decl]-> --ilImports tyEnv tcEnv mEnv (IL.Module _ is _) =-> -- concat [ilTransIntf tyEnv tcEnv (Interface m ds) -> -- | (m,ds) <- envToList mEnv, m `elem` is]- > writeXML :: Maybe FilePath -> FilePath -> CurryEnv -> IL.Module -> IO () > writeXML tfn sfn cEnv il = writeModule ofn (showln code)-> where ofn = fromMaybe (replaceExtension sfn xmlExt) tfn+> where ofn = fromMaybe (xmlName sfn) tfn > code = (xmlModule cEnv il) > writeFlat :: Options -> Maybe FilePath -> FilePath -> CurryEnv -> ModuleEnv > -> ValueEnv -> TCEnv -> ArityEnv -> IL.Module -> IO Prog > writeFlat opts tfn sfn cEnv mEnv tyEnv tcEnv aEnv il > = writeFlatFile opts (genFlatCurry opts cEnv mEnv tyEnv tcEnv aEnv il)-> (fromMaybe (replaceExtension sfn flatExt) tfn)--> writeFInt :: Options -> Maybe FilePath -> FilePath -> CurryEnv -> ModuleEnv-> -> ValueEnv -> TCEnv -> ArityEnv -> IL.Module -> IO Prog-> writeFInt opts tfn sfn cEnv mEnv tyEnv tcEnv aEnv il -> = writeFlatFile opts{extendedFlat=False}-> (genFlatInterface opts cEnv mEnv tyEnv tcEnv aEnv il)-> (fromMaybe (takeBaseName sfn ++ fintExt) tfn)+> (fromMaybe (flatName sfn) tfn) -> writeFlatFile :: (Show a) => Options -> (Prog, [a]) -> String -> IO Prog+> writeFlatFile :: Options -> (Prog, [WarnMsg]) -> String -> IO Prog > writeFlatFile opts@Options{extendedFlat=ext} (res,msgs) fname = do > unless (noWarn opts) (printMessages msgs) > if ext then writeExtendedFlat fname res@@ -270,125 +256,20 @@ > writeTypedAbs :: Maybe FilePath -> FilePath -> ValueEnv -> TCEnv -> Module > -> IO () > writeTypedAbs tfn sfn tyEnv tcEnv mod-> = writeCurry fname (genTypedAbstract tyEnv tcEnv mod)-> where fname = fromMaybe (replaceExtension sfn acyExt) tfn+> = AC.writeCurry fname (genTypedAbstract tyEnv tcEnv mod)+> where fname = fromMaybe (acyName sfn) tfn > writeUntypedAbs :: Maybe FilePath -> FilePath -> ValueEnv -> TCEnv > -> Module -> IO () > writeUntypedAbs tfn sfn tyEnv tcEnv mod-> = writeCurry fname (genUntypedAbstract tyEnv tcEnv mod)-> where fname = fromMaybe (replaceExtension sfn uacyExt) tfn+> = AC.writeCurry fname (genUntypedAbstract tyEnv tcEnv mod)+> where fname = fromMaybe (uacyName sfn) tfn > showln :: Show a => a -> String > showln x = shows x "\n" \end{verbatim}-A goal is compiled with respect to a given module. If no module is-specified the Curry prelude is used. The source module has to be-parsed and type checked before the goal can be compiled. Otherwise-compilation of a goal is similar to that of a module. -\em{Note:} These functions are obsolete when using the MCC as frontend-for PAKCS.-\begin{verbatim}--> --compileGoal :: Options -> Maybe String -> Maybe FilePath -> IO ()-> --compileGoal opts g fn =-> -- do-> -- (ccode,dumps) <- maybe (return startupCode) goalCode g-> -- mapM_ (doDump opts) dumps-> -- writeCCode ofn ccode-> -- where ofn = fromMaybe (internalError "No filename for startup code")-> -- (output opts)-> -- startupCode = (genMain "curry_run",[])-> -- goalCode = doCompileGoal (debug opts) (importPath opts) fn--> --doCompileGoal :: Bool -> [FilePath] -> Maybe FilePath -> String-> -- -> IO (CFile,[(Dump,Doc)])-> --doCompileGoal debug paths fn g =-> -- do-> -- (mEnv,_,ds) <- loadGoalModule paths fn-> -- let (tyEnv,g') = checkGoal mEnv ds (ok (parseGoal g))-> -- (ccode,dumps) =-> -- transGoal debug runGoal mEnv tyEnv (mkIdent "goal") g'-> -- ccode' = genMain runGoal-> -- return (mergeCFile ccode ccode',dumps)-> -- where runGoal = "curry_runGoal"--> --typeGoal :: Options -> String -> Maybe FilePath -> IO ()-> --typeGoal opts g fn =-> -- do-> -- (mEnv,m,ds) <- loadGoalModule (importPath opts) fn-> -- let (tyEnv,Goal _ e _) = checkGoal mEnv ds (ok (parseGoal g))-> -- print (ppType m (typeOf tyEnv e))--> --loadGoalModule :: [FilePath] -> Maybe FilePath-> -- -> IO (ModuleEnv,ModuleIdent,[Decl])-> --loadGoalModule paths fn =-> -- do-> -- Module m _ ds <- maybe (return emptyModule) parseGoalModule fn-> -- mEnv <- loadInterfaces paths (Module m Nothing ds)-> -- let (_,_,_,_,intf) = checkModule mEnv (Module m Nothing ds)-> -- return (bindModule intf mEnv,m,filter isImportDecl ds ++ [importMain m])-> -- where emptyModule = importPrelude "" (Module emptyMIdent Nothing [])-> -- parseGoalModule fn = liftM (parseModule False fn) (readFile fn)-> -- importMain m = ImportDecl (first "") m False Nothing Nothing--> --checkGoal :: ModuleEnv -> [Decl] -> Goal -> (ValueEnv,Goal)-> --checkGoal mEnv impDs g = (tyEnv'',qualGoal tyEnv' g')-> -- where (pEnv,tcEnv,tyEnv,aEnv) = importModules mEnv impDs-> -- g' = precCheckGoal pEnv $ syntaxCheckGoal tyEnv-> -- $ kindCheckGoal tcEnv g-> -- tyEnv' = typeCheckGoal tcEnv tyEnv g'-> -- (_,_,tyEnv'',_) = qualifyEnv mEnv pEnv tcEnv tyEnv' emptyTopEnv--> --transGoal :: Bool -> String -> ModuleEnv -> ValueEnv -> Ident -> Goal-> -- -> (CFile,[(Dump,Doc)])-> --transGoal debug run mEnv tyEnv goalId g = (ccode,dumps)-> -- where qGoalId = qualifyWith emptyMIdent goalId-> -- evEnv = evalEnvGoal g-> -- (vs,desugared,tyEnv') = desugarGoal debug tyEnv emptyMIdent goalId g-> -- (simplified,tyEnv'') = simplify False tyEnv' evEnv desugared-> -- (lifted,tyEnv''',evEnv') = lift tyEnv'' evEnv simplified-> -- il = ilTrans False tyEnv''' evEnv' lifted-> -- ilDbg = if debug then dAddMain goalId (dTransform False il) else il-> -- ilNormal = liftProg ilDbg-> -- cam = camCompile ilNormal-> -- imports = camCompileData (ilImports mEnv ilDbg)-> -- ccode =-> -- genModule imports cam ++-> -- genEntry run (fun qGoalId) (fmap (map name) vs)-> -- dumps = [-> -- (DumpRenamed,ppGoal g),-> -- (DumpTypes,ppTypes emptyMIdent (localBindings tyEnv)),-> -- (DumpDesugared,ppModule desugared),-> -- (DumpSimplified,ppModule simplified),-> -- (DumpLifted,ppModule lifted),-> -- (DumpIL,ILPP.ppModule il),-> -- (DumpTransformed,ILPP.ppModule ilDbg),-> -- (DumpNormalized,ILPP.ppModule ilNormal),-> -- (DumpCam,CamPP.ppModule cam)-> -- ]--\end{verbatim}-The compiler adds a startup function for the default goal-\texttt{main.main} to the \texttt{main} module. Thus, there is no need-to determine the type of the goal when linking the program.-\begin{verbatim}--> --compileDefaultGoal :: Bool -> ModuleEnv -> Interface -> Maybe CFile-> --compileDefaultGoal debug mEnv (Interface m ds)-> -- | m == mainMIdent && any (qMainId ==) [f | IFunctionDecl _ f _ _ <- ds] =-> -- Just ccode-> -- | otherwise = Nothing-> -- where qMainId = qualify mainId-> -- mEnv' = bindModule (Interface m ds) mEnv-> -- (tyEnv,g) =-> -- checkGoal mEnv' [ImportDecl (first "") m False Nothing Nothing]-> -- (Goal (first "") (Variable qMainId) [])-> -- (ccode,_) = transGoal debug "curry_run" mEnv' tyEnv mainId g--\end{verbatim} The function \texttt{importModules} brings the declarations of all imported modules into scope for the current module. \begin{verbatim}@@ -397,7 +278,7 @@ > importModules mEnv ds = (pEnv,importUnifyData tcEnv,tyEnv,aEnv) > where (pEnv,tcEnv,tyEnv,aEnv) = foldl importModule initEnvs ds > importModule (pEnv,tcEnv,tyEnv,aEnv) (ImportDecl p m q asM is) =-> case lookupModule m mEnv of+> case Map.lookup m mEnv of > Just ds -> importInterface p (fromMaybe m asM) q is > (Interface m ds) pEnv tcEnv tyEnv aEnv > Nothing -> internalError "importModule"@@ -421,7 +302,7 @@ > importLabels mEnv ds = foldl importLabelTypes initLabelEnv ds > where > importLabelTypes lEnv (ImportDecl p m _ asM is) =-> case (lookupModule m mEnv) of+> case (Map.lookup m mEnv) of > Just ds' -> foldl (importLabelType p (fromMaybe m asM) is) lEnv ds' > Nothing -> internalError "importLabels" > importLabelTypes lEnv _ = lEnv@@ -449,10 +330,10 @@ > addImportedLabels :: ModuleIdent -> LabelEnv -> ValueEnv -> ValueEnv > addImportedLabels m lEnv tyEnv = -> foldr addLabelType tyEnv (concatMap snd (envToList lEnv))+> foldr addLabelType tyEnv (concatMap snd (Map.toList lEnv)) > where > addLabelType (LabelType l r ty) tyEnv = -> let m' = fromMaybe m (fst (splitQualIdent r))+> let m' = fromMaybe m (qualidMod r) > in importTopEnv m' l > (Label (qualify l) (qualQualify m' r) (polyType ty)) > tyEnv@@ -511,7 +392,7 @@ > importPrelude :: FilePath -> Module -> Module > importPrelude fn (Module m es ds) = > Module m es (if m == preludeMIdent then ds else ds')-> where ids = filter isImportDecl ds+> where ids = [decl | decl@(ImportDecl _ _ _ _ _) <- ds] > ds' = ImportDecl (first fn) preludeMIdent > (preludeMIdent `elem` map importedModule ids) > Nothing Nothing : ds@@ -536,7 +417,7 @@ > lookupInterface paths m >>= > maybe (errorAt p (interfaceNotFound m)) > (compileInterface paths ctxt mEnv m)-> where isLoaded m mEnv = maybe False (const True) (lookupModule m mEnv)+> where isLoaded m mEnv = maybe False (const True) (Map.lookup m mEnv) \end{verbatim} After reading an interface, all imported interfaces are recursively@@ -571,18 +452,7 @@ > (map (\i -> (p, mkMIdent [i])) is) > where p = first m -> --checkInterface :: ModuleEnv -> Interface -> Interface-> --checkInterface mEnv (Interface m ds) =-> -- intfCheck pEnv tcEnv tyEnv (Interface m ds)-> -- where (pEnv,tcEnv,tyEnv) = foldl importInterface initEnvs ds-> -- importInterface (pEnv,tcEnv,tyEnv) (IImportDecl p m) =-> -- case lookupModule m mEnv of-> -- Just ds -> importInterfaceIntf (Interface m ds) pEnv tcEnv tyEnv-> -- Nothing -> internalError "importInterface"-> -- importInterface (pEnv,tcEnv,tyEnv) _ = (pEnv,tcEnv,tyEnv) --\end{verbatim} Interface files are updated by the Curry builder when necessary. (see module \texttt{CurryBuilder}). @@ -601,25 +471,6 @@ the file is closed. \begin{verbatim} -> --updateInterface :: FilePath -> Interface -> IO ()-> --updateInterface sfn i =-> -- do-> -- eq <- catch (matchInterface ifn i) (const (return False))-> -- unless eq (writeInterface ifn i)-> -- where ifn = dropExtension sfn ++ intfExt--> --matchInterface :: FilePath -> Interface -> IO Bool-> --matchInterface ifn i =-> -- do-> -- h <- openFile ifn ReadMode-> -- s <- hGetContents h-> -- case parseInterface ifn s of-> -- Ok i' | i `intfEquiv` fixInterface i' -> return True-> -- _ -> hClose h >> return False--> --writeInterface :: FilePath -> Interface -> IO ()-> --writeInterface ifn = writeFile ifn . showln . ppInterface- \end{verbatim} The compiler searches for interface files in the import search path using the extension \texttt{".fint"}. Note that the current@@ -627,24 +478,10 @@ \begin{verbatim} > lookupInterface :: [FilePath] -> ModuleIdent -> IO (Maybe FilePath)-> lookupInterface paths m = lookupFile ("":paths) [fintExt] ifn+> lookupInterface paths m = lookupFile ("":paths) [flatIntExt] ifn > where ifn = foldr1 catPath (moduleQualifiers m) \end{verbatim}-Literate source files use the extension \texttt{".lcurry"}.-\begin{verbatim}--> unlitLiterate :: FilePath -> String -> String-> unlitLiterate fn s-> | not (isLiterateSource fn) = s-> | null es = s'-> | otherwise = error es-> where (es,s') = unlit fn s--> isLiterateSource :: FilePath -> Bool-> isLiterateSource fn = litExt `isSuffixOf` fn--\end{verbatim} The \texttt{doDump} function writes the selected information to the standard output. \begin{verbatim}@@ -678,7 +515,7 @@ \begin{verbatim} > genFlat :: Options -> FilePath -> ModuleEnv -> ValueEnv -> TCEnv -> ArityEnv -> -> Interface -> Module -> IL.Module -> IO CompilerResults+> -> Interface -> Module -> IL.Module -> IO (Maybe FilePath) > genFlat opts fname mEnv tyEnv tcEnv aEnv intf mod il > | flat opts > = do writeFlat opts Nothing fname cEnv mEnv tyEnv tcEnv aEnv il@@ -686,7 +523,7 @@ > if force opts > then > do writeInterface flatInterface intMsgs-> return defaultResults+> return Nothing > else > do mfint <- readFlatInterface fintName > let flatIntf = fromMaybe emptyIntf mfint@@ -694,14 +531,14 @@ > && not (interfaceCheck flatIntf flatInterface) > then > do writeInterface flatInterface intMsgs-> return defaultResults-> else return defaultResults+> return Nothing+> else return Nothing > | flatXml opts-> = writeXML (output opts) fname cEnv il >> return defaultResults+> = writeXML (output opts) fname cEnv il >> return Nothing > | otherwise > = internalError "@Modules.genFlat: illegal option" > where-> fintName = replaceExtension fname fintExt+> fintName = flatIntName fname > cEnv = curryEnv mEnv tcEnv intf mod > emptyIntf = Prog "" [] [] [] [] > writeInterface intf msgs = do@@ -710,20 +547,20 @@ > genAbstract :: Options -> FilePath -> ValueEnv -> TCEnv -> Module -> -> IO CompilerResults+> -> IO (Maybe FilePath) > genAbstract opts fname tyEnv tcEnv mod > | abstract opts > = do writeTypedAbs Nothing fname tyEnv tcEnv mod -> return defaultResults+> return Nothing > | untypedAbstract opts > = do writeUntypedAbs Nothing fname tyEnv tcEnv mod-> return defaultResults+> return Nothing > | otherwise > = internalError "@Modules.genAbstract: illegal option" -> printMessages :: Show a => [a] -> IO ()+> printMessages :: [WarnMsg] -> IO () > printMessages [] = return ()-> printMessages msgs = hPutStrLn stderr $ unlines $ map show msgs+> printMessages msgs = hPutStrLn stderr $ unlines $ map showWarning msgs \end{verbatim} The function \texttt{ppTypes} is used for pretty-printing the types@@ -756,20 +593,6 @@ \end{verbatim}-Various filename extensions-\begin{verbatim}--> cExt = ".c"-> xmlExt = "_flat.xml"-> flatExt = ".fcy"-> fintExt = ".fint"-> acyExt = ".acy"-> uacyExt = ".uacy"-> sourceRepExt = ".cy"-> intfExt = ".icurry"-> litExt = ".lcurry"--\end{verbatim} Error functions. \begin{verbatim} @@ -789,3 +612,78 @@ > "Expected interface for " ++ show m ++ " but found " ++ show m' \end{verbatim}+++++> bindFlatInterface :: Prog -> ModuleEnv -> ModuleEnv+> bindFlatInterface (Prog m imps ts fs os)+> = Map.insert (mkMIdent [m])+> ((map genIImportDecl imps)+> ++ (map genITypeDecl ts')+> ++ (map genIFuncDecl fs)+> ++ (map genIOpDecl os))+> where+> genIImportDecl :: String -> IDecl+> genIImportDecl imp = IImportDecl pos (mkMIdent [imp])+>+> genITypeDecl :: TypeDecl -> IDecl+> genITypeDecl (Type qn _ is cs)+> | recordExt `isPrefixOf` localName qn+> = ITypeDecl pos+> (genQualIdent qn)+> (map (genVarIndexIdent "a") is)+> (RecordType (map genLabeledType cs) Nothing)+> | otherwise+> = IDataDecl pos +> (genQualIdent qn) +> (map (genVarIndexIdent "a") is) +> (map (Just . genConstrDecl) cs)+> genITypeDecl (TypeSyn qn _ is t)+> = ITypeDecl pos+> (genQualIdent qn)+> (map (genVarIndexIdent "a") is)+> (genTypeExpr t)+>+> genIFuncDecl :: FuncDecl -> IDecl+> genIFuncDecl (Func qn a _ t _) +> = IFunctionDecl pos (genQualIdent qn) a (genTypeExpr t)+>+> genIOpDecl :: OpDecl -> IDecl+> genIOpDecl (Op qn f p) = IInfixDecl pos (genInfix f) p (genQualIdent qn)+>+> genConstrDecl :: ConsDecl -> ConstrDecl+> genConstrDecl (Cons qn _ _ ts)+> = ConstrDecl pos [] (mkIdent (localName qn)) (map genTypeExpr ts)+>+> genLabeledType :: EF.ConsDecl -> ([Ident],Curry.Syntax.TypeExpr)+> genLabeledType (Cons qn _ _ [t])+> = ([renameLabel (fromLabelExtId (mkIdent $ localName qn))], genTypeExpr t)+>+> genTypeExpr :: EF.TypeExpr -> Curry.Syntax.TypeExpr+> genTypeExpr (TVar i)+> = VariableType (genVarIndexIdent "a" i)+> genTypeExpr (FuncType t1 t2) +> = ArrowType (genTypeExpr t1) (genTypeExpr t2)+> genTypeExpr (TCons qn ts) +> = ConstructorType (genQualIdent qn) (map genTypeExpr ts)+>+> genInfix :: EF.Fixity -> Infix+> genInfix EF.InfixOp = Infix+> genInfix EF.InfixlOp = InfixL+> genInfix EF.InfixrOp = InfixR+>+> genQualIdent :: EF.QName -> QualIdent+> genQualIdent EF.QName{modName=mod,localName=name} = +> qualifyWith (mkMIdent [mod]) (mkIdent name)+>+> genVarIndexIdent :: String -> Int -> Ident+> genVarIndexIdent v i = mkIdent (v ++ show i)+>+> isSpecialPreludeType :: TypeDecl -> Bool+> isSpecialPreludeType (Type EF.QName{modName=mod,localName=name} _ _ _) +> = (name == "[]" || name == "()") && mod == "Prelude"+> isSpecialPreludeType _ = False+>+> pos = first m+> ts' = filter (not . isSpecialPreludeType) ts
src/NestEnv.lhs view
@@ -18,13 +18,17 @@ > module NestEnv(module TopEnv, NestEnv, bindNestEnv,qualBindNestEnv, > lookupNestEnv,qualLookupNestEnv, > toplevelEnv,globalEnv,nestEnv) where-> import Env++> import qualified Data.Map as Map++> import Curry.Base.Ident+ > import TopEnv-> import Ident -> data NestEnv a = GlobalEnv (TopEnv a) | LocalEnv (NestEnv a) (Env Ident a)-> deriving Show +> data NestEnv a = GlobalEnv (TopEnv a) | LocalEnv (NestEnv a) (Map.Map Ident a)+> -- deriving Show+ > instance Functor NestEnv where > fmap f (GlobalEnv env) = GlobalEnv (fmap f env) > fmap f (LocalEnv genv env) = LocalEnv (fmap f genv) (fmap f env)@@ -33,9 +37,9 @@ > bindNestEnv x y (GlobalEnv env) > = GlobalEnv (bindTopEnv "NestEnv.bindNestEnv" x y env) > bindNestEnv x y (LocalEnv genv env) =-> case lookupEnv x env of+> case Map.lookup x env of > Just _ -> error "internal error: bindNestEnv"-> Nothing -> LocalEnv genv (bindEnv x y env)+> Nothing -> LocalEnv genv (Map.insert x y env) > qualBindNestEnv :: QualIdent -> a -> NestEnv a -> NestEnv a > qualBindNestEnv x y (GlobalEnv env) @@ -43,15 +47,15 @@ > qualBindNestEnv x y (LocalEnv genv env) > | isQualified x = error "internal error: qualBindNestEnv" > | otherwise =-> case lookupEnv x' env of+> case Map.lookup x' env of > Just _ -> error "internal error: qualBindNestEnv"-> Nothing -> LocalEnv genv (bindEnv x' y env)+> Nothing -> LocalEnv genv (Map.insert x' y env) > where x' = unqualify x > lookupNestEnv :: Ident -> NestEnv a -> [a] > lookupNestEnv x (GlobalEnv env) = lookupTopEnv x env > lookupNestEnv x (LocalEnv genv env) =-> case lookupEnv x env of+> case Map.lookup x env of > Just y -> [y] > Nothing -> lookupNestEnv x genv @@ -68,6 +72,6 @@ > globalEnv = GlobalEnv > nestEnv :: NestEnv a -> NestEnv a-> nestEnv env = LocalEnv env emptyEnv+> nestEnv env = LocalEnv env Map.empty \end{verbatim}
src/OldScopeEnv.hs view
@@ -7,10 +7,9 @@ genIdent, genIdentList) where import Data.Maybe--import Ident-import Env+import qualified Data.Map as Map +import Curry.Base.Ident -------------------------------------------------------------------------------@@ -23,7 +22,7 @@ -- Generates a new instance of a scope table newScopeEnv :: ScopeEnv-newScopeEnv = (newIdEnv, [], 0)+newScopeEnv = (Map.empty, [], 0) -- Inserts an identifier into the current level of the scope environment@@ -66,7 +65,7 @@ beginScope (topleveltab, leveltabs, level) = case leveltabs of (lt:lts) -> (topleveltab, (lt:lt:lts), level + 1)- [] -> (topleveltab, [newIdEnv], 1)+ [] -> (topleveltab, [Map.empty], 1) -- Decreases the level of the scope. Identifier from higher levels@@ -116,24 +115,20 @@ ------------------------------------------------------------------------------- -- Private declarations... -type IdEnv = Env IdRep Int+type IdEnv = Map.Map IdRep Int data IdRep = Name String | Index Int deriving (Eq, Ord) ------------------------------------------------------------------------------- ----newIdEnv :: IdEnv-newIdEnv = emptyEnv - -- insertId :: Int -> Ident -> IdEnv -> IdEnv insertId level ident env- = bindEnv (Name (name ident)) + = Map.insert (Name (name ident)) level - (bindEnv (Index (uniqueId ident)) level env)+ (Map.insert (Index (uniqueId ident)) level env) --@@ -143,7 +138,7 @@ -- getIdLevel :: Ident -> IdEnv -> Maybe Int-getIdLevel ident env = lookupEnv (Index (uniqueId ident)) env+getIdLevel ident env = Map.lookup (Index (uniqueId ident)) env --@@ -158,12 +153,12 @@ -- nameExists :: String -> IdEnv -> Bool-nameExists name env = isJust (lookupEnv (Name name) env)+nameExists name env = isJust (Map.lookup (Name name) env) -- indexExists :: Int -> IdEnv -> Bool-indexExists index env = isJust (lookupEnv (Index index) env)+indexExists index env = isJust (Map.lookup (Index index) env) -------------------------------------------------------------------------------
src/PatchPrelude.hs view
@@ -1,7 +1,7 @@ module PatchPrelude where -import ExtendedFlat+import Curry.ExtendedFlat -- the prelude has to be extended by data declarations for list and tuples
src/PathUtils.hs view
@@ -6,12 +6,13 @@ -} module PathUtils(-- re-exports from System.FilePath:- takeBaseName, replaceExtension, dropExtension,+ takeBaseName, -- replaceExtension,+ dropExtension, takeDirectory, takeExtension, pathSeparator, catPath, - lookupFile,+ lookupModule, lookupFile, getCurryPath, writeModule,readModule, doesModuleExist,maybeReadModule,getModuleModTime) where @@ -21,7 +22,16 @@ import Control.Monad (unless) +import Curry.Base.Ident+import Filenames ++lookupModule :: [FilePath] -> [FilePath] -> ModuleIdent+ -> IO (Maybe FilePath)+lookupModule paths libraryPaths m+ = lookupFile ("" : paths ++ libraryPaths) moduleExts fn+ where fn = foldr1 catPath (moduleQualifiers m)+ catPath :: FilePath -> FilePath -> FilePath catPath = combine @@ -65,7 +75,7 @@ writeModule filename contents = do let filename' = inCurrySubdir filename subdir = takeDirectory filename'- ensureDirectoryExists (takeDirectory filename')+ ensureDirectoryExists subdir writeFile filename' contents ensureDirectoryExists :: FilePath -> IO ()@@ -93,3 +103,20 @@ getModuleModTime :: FilePath -> IO ClockTime getModuleModTime = onExistingFileDo getModificationTime+++{-+ The function \verb|getCurryPath| searches in predefined paths+ for the corresponding \texttt{.curry} or \texttt{.lcurry} file, + if the given file name has no extension.+-}+getCurryPath :: [FilePath] -> FilePath -> IO (Maybe FilePath)+getCurryPath paths fn = lookupFile filepaths exts fn+ where+ filepaths = "":paths'+ fnext = takeExtension fn+ exts | null fnext = sourceExts+ | otherwise = [fnext]+ paths' | pathSeparator `elem` fn = []+ | otherwise = paths+
− src/Position.lhs
@@ -1,94 +0,0 @@-> {-# LANGUAGE DeriveDataTypeable #-}--% -*- LaTeX -*--% $Id: Position.lhs,v 1.2 2000/10/08 09:55:43 lux Exp $-%-% $Log: Position.lhs,v $-% Revision 1.2 2000/10/08 09:55:43 lux-% Column numbers now start at 1. If the column number is less than 1 it-% will not be shown.-%-% Revision 1.1 2000/07/23 11:03:37 lux-% Positions now implemented in a separate module.-%-%-\nwfilename{Position.lhs}-\section{Positions}-A source file position consists of a filename, a line number, and a-column number. A tab stop is assumed at every eighth column.-\begin{verbatim}--> module Position where-> import Data.Generics--> newtype SrcRef = SrcRef [Int] deriving (Typeable,Data) -- a pointer to the origin---- the instances for standard classes or such that SrcRefs are invisible--> instance Show SrcRef where show _ = ""-> instance Read SrcRef where readsPrec _ s = [(noRef,s)]-> instance Eq SrcRef where _ == _ = True-> instance Ord SrcRef where compare _ _ = EQ--> noRef :: SrcRef-> noRef = SrcRef []->-> incSrcRef :: SrcRef -> Int -> SrcRef-> incSrcRef (SrcRef [i]) j = SrcRef [i+j]-> incSrcRef is _ = error $ "internal error; increment source ref: " ++ show is--> data Position -> = Position{ file :: FilePath, line :: Int, column :: Int, ast :: SrcRef }-> | AST { ast :: SrcRef }-> deriving (Eq, Ord,Data,Typeable)->-> incPosition :: Position -> Int -> Position-> incPosition p j = p{ast=incSrcRef (ast p) j}--> instance Read Position where-> readsPrec p s = -> [ (Position{file="",line=i,column=j,ast=noRef},s') | ((i,j),s') <- readsPrec p s]--> instance Show Position where-> showsPrec _ Position{file=fn,line=l,column=c} =-> (if null fn then id else shows fn . showString ", ") .-> showString "line " . shows l .-> (if c > 0 then showChar '.' . shows c else id)-> showsPrec _ AST{} = id--> tabWidth :: Int-> tabWidth = 8--> first :: FilePath -> Position-> first fn = Position fn 1 1 noRef--> incr :: Position -> Int -> Position-> incr p@Position{column=c} n = p{column=c + n}--> next :: Position -> Position-> next = flip incr 1--> tab :: Position -> Position-> tab p@Position{column=c} = p{column=c + tabWidth - (c - 1) `mod` tabWidth}--> nl :: Position -> Position-> nl p@Position{line=l} = p{line=l + 1, column=1}--> noPos, noPos' :: Position-> noPos = Position{ file = "", line = 0, column = 0, ast = noRef }-> noPos' = AST noRef--> showLine :: Position -> String-> showLine x@Position{line=l,column=c} -> | x == noPos = ""-> | otherwise = "(line " ++ show l ++ "." ++ show c ++ ") "--\end{verbatim}--> class SrcRefOf a where-> srcRefsOf :: a -> [SrcRef]-> srcRefsOf = (:[]) . srcRefOf-> srcRefOf :: a -> SrcRef-> srcRefOf = head . srcRefsOf--> instance SrcRefOf Position where srcRefOf = ast
src/PrecCheck.lhs view
@@ -16,10 +16,15 @@ of the operators involved. \begin{verbatim} -> module PrecCheck(precCheck,precCheckGoal) where+> module PrecCheck(precCheck) where > import Data.List +> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax+> import Curry.Syntax.Utils+ > import Base \end{verbatim}@@ -34,13 +39,13 @@ > bindPrecs m ds pEnv = > case linear ops of > Linear ->-> case [PIdent p op | PIdent p op <- ops, op `notElem` bvs] of+> case [ op | op <- ops, op `notElem` bvs] of > [] -> foldr bindPrec pEnv fixDs-> PIdent p op : _ -> errorAt' (undefinedOperator op)-> NonLinear (PIdent p op) -> errorAt' (duplicatePrecedence op)+> op : _ -> errorAt' (undefinedOperator op)+> NonLinear op -> errorAt' (duplicatePrecedence op) > where (fixDs,nonFixDs) = partition isInfixDecl ds > bvs = concatMap boundValues nonFixDs-> ops = [PIdent p op | InfixDecl p _ _ ops <- fixDs, op <- ops]+> ops = [ op | InfixDecl p _ _ ops <- fixDs, op <- ops] > bindPrec (InfixDecl _ fix pr ops) pEnv > | p == defaultP = pEnv > | otherwise = foldr (flip (bindP m) p) pEnv ops@@ -72,11 +77,6 @@ > precCheck :: ModuleIdent -> PEnv -> [Decl] -> (PEnv,[Decl]) > precCheck = checkDecls -> precCheckGoal :: PEnv -> Goal -> Goal-> precCheckGoal pEnv (Goal p e ds) = Goal p (checkExpr m pEnv' e) ds'-> where (pEnv',ds') = checkDecls m pEnv ds-> m = emptyMIdent- > checkDecls :: ModuleIdent -> PEnv -> [Decl] -> (PEnv,[Decl]) > checkDecls m pEnv ds = pEnv' `seq` (pEnv',ds') > where pEnv' = bindPrecs m ds pEnv@@ -247,8 +247,7 @@ > InfixApply (fixUPrec pEnv uop e1 op1 e2) op2 e3 > | pr2 > 6 = UnaryMinus uop (fixRPrec pEnv e1 op1 (InfixApply e2 op2 e3)) > | otherwise = errorAt' $ ambiguousParse "unary" (qualify uop) (opName op2)-> where OpPrec fix1 pr1 = opPrec op1 pEnv-> OpPrec fix2 pr2 = opPrec op2 pEnv+> where OpPrec fix2 pr2 = opPrec op2 pEnv > fixUPrec _ uop e1 op e2 = UnaryMinus uop (InfixApply e1 op e2) > fixRPrec :: PEnv -> Expression -> InfixOp -> Expression
− src/Pretty.lhs
@@ -1,905 +0,0 @@-Hand converted to standard Haskell -- jcp--*********************************************************************************-* *-* John Hughes's and Simon Peyton Jones's Pretty Printer Combinators *-* *-* based on "The Design of a Pretty-printing Library" *-* in Advanced Functional Programming, *-* Johan Jeuring and Erik Meijer (eds), LNCS 925 *-* http://www.cs.chalmers.se/~rjmh/Papers/pretty.ps *-* *-* Heavily modified by Simon Peyton Jones, Dec 96 *-* *-*********************************************************************************--Version 3.0 28 May 1997- * Cured massive performance bug. If you write-- foldl <> empty (map (text.show) [1..10000])-- you get quadratic behaviour with V2.0. Why? For just the same reason as you get- quadratic behaviour with left-associated (++) chains.-- This is really bad news. One thing a pretty-printer abstraction should- certainly guarantee is insensivity to associativity. It matters: suddenly- GHC's compilation times went up by a factor of 100 when I switched to the- new pretty printer.- - I fixed it with a bit of a hack (because I wanted to get GHC back on the- road). I added two new constructors to the Doc type, Above and Beside:- - <> = Beside- $$ = Above- - Then, where I need to get to a "TextBeside" or "NilAbove" form I "force"- the Doc to squeeze out these suspended calls to Beside and Above; but in so- doing I re-associate. It's quite simple, but I'm not satisfied that I've done- the best possible job. I'll send you the code if you are interested.-- * Added new exports:- punctuate, hang- int, integer, float, double, rational,- lparen, rparen, lbrack, rbrack, lbrace, rbrace,-- * fullRender's type signature has changed. Rather than producing a string it- now takes an extra couple of arguments that tells it how to glue fragments- of output together:-- fullRender :: Mode- -> Int -- Line length- -> Float -- Ribbons per line- -> (TextDetails -> a -> a) -- What to do with text- -> a -- What to do at the end- -> Doc- -> a -- Result-- The "fragments" are encapsulated in the TextDetails data type:- data TextDetails = Chr Char- | Str String- | PStr FAST_STRING-- The Chr and Str constructors are obvious enough. The PStr constructor has a packed- string (FAST_STRING) inside it. It's generated by using the new "ptext" export.-- An advantage of this new setup is that you can get the renderer to do output- directly (by passing in a function of type (TextDetails -> IO () -> IO ()),- rather than producing a string that you then print.---Version 2.0 24 April 1997- * Made empty into a left unit for <> as well as a right unit;- it is also now true that- nest k empty = empty- which wasn't true before.-- * Fixed an obscure bug in sep that occassionally gave very wierd behaviour-- * Added $+$-- * Corrected and tidied up the laws and invariants--======================================================================-Relative to John's original paper, there are the following new features:--1. There's an empty document, "empty". It's a left and right unit for - both <> and $$, and anywhere in the argument list for- sep, hcat, hsep, vcat, fcat etc.-- It is Really Useful in practice.--2. There is a paragraph-fill combinator, fsep, that's much like sep,- only it keeps fitting things on one line until itc can't fit any more.--3. Some random useful extra combinators are provided. - <+> puts its arguments beside each other with a space between them,- unless either argument is empty in which case it returns the other--- hcat is a list version of <>- hsep is a list version of <+>- vcat is a list version of $$-- sep (separate) is either like hsep or like vcat, depending on what fits-- cat is behaves like sep, but it uses <> for horizontal conposition- fcat is behaves like fsep, but it uses <> for horizontal conposition-- These new ones do the obvious things:- char, semi, comma, colon, space,- parens, brackets, braces, - quotes, doubleQuotes- -4. The "above" combinator, $$, now overlaps its two arguments if the- last line of the top argument stops before the first line of the second begins.- For example: text "hi" $$ nest 5 "there"- lays out as- hi there- rather than- hi- there-- There are two places this is really useful-- a) When making labelled blocks, like this:- Left -> code for left- Right -> code for right- LongLongLongLabel ->- code for longlonglonglabel- The block is on the same line as the label if the label is- short, but on the next line otherwise.-- b) When laying out lists like this:- [ first- , second- , third- ]- which some people like. But if the list fits on one line- you want [first, second, third]. You can't do this with- John's original combinators, but it's quite easy with the- new $$.-- The combinator $+$ gives the original "never-overlap" behaviour.--5. Several different renderers are provided:- * a standard one- * one that uses cut-marks to avoid deeply-nested documents - simply piling up in the right-hand margin- * one that ignores indentation (fewer chars output; good for machines)- * one that ignores indentation and newlines (ditto, only more so)--6. Numerous implementation tidy-ups- Use of unboxed data types to speed up the implementation----\begin{code}-module Pretty (- Doc, -- Abstract- Mode(..), TextDetails(..),- Style,-- empty, nest,-- text, char, ptext,- int, integer, float, double, rational,- parens, brackets, braces, quotes, doubleQuotes,- semi, comma, colon, space, equals,- lparen, rparen, lbrack, rbrack, lbrace, rbrace,-- (<>), (<+>), hcat, hsep, - ($$), ($+$), vcat, - sep, cat, - fsep, fcat, -- hang, punctuate,- - renderStyle, - render, fullRender- ) where---- Don't import Util( assertPanic ) because it makes a loop in the module structure--import Data.Ratio-infixl 6 <> -infixl 6 <+>-infixl 5 $$, $+$-\end{code}----*********************************************************-* *-\subsection{CPP magic so that we can compile with both GHC and Hugs}-* *-*********************************************************--The library uses unboxed types to get a bit more speed, but these CPP macros-allow you to use either GHC or Hugs. To get GHC, just set the CPP variable- __GLASGOW_HASKELL__---*********************************************************-* *-\subsection{The interface}-* *-*********************************************************--The primitive @Doc@ values--\begin{code}-empty :: Doc-text :: String -> Doc -char :: Char -> Doc--semi, comma, colon, space, equals :: Doc-lparen, rparen, lbrack, rbrack, lbrace, rbrace :: Doc--parens, brackets, braces :: Doc -> Doc -quotes, doubleQuotes :: Doc -> Doc--int :: Int -> Doc-integer :: Integer -> Doc-float :: Float -> Doc-double :: Double -> Doc-rational :: Rational -> Doc-\end{code}---Combining @Doc@ values--\begin{code}-(<>) :: Doc -> Doc -> Doc -- Beside-hcat :: [Doc] -> Doc -- List version of <>-(<+>) :: Doc -> Doc -> Doc -- Beside, separated by space-hsep :: [Doc] -> Doc -- List version of <+>--($$) :: Doc -> Doc -> Doc -- Above; if there is no- -- overlap it "dovetails" the two-vcat :: [Doc] -> Doc -- List version of $$--cat :: [Doc] -> Doc -- Either hcat or vcat-sep :: [Doc] -> Doc -- Either hsep or vcat-fcat :: [Doc] -> Doc -- ``Paragraph fill'' version of cat-fsep :: [Doc] -> Doc -- ``Paragraph fill'' version of sep--nest :: Int -> Doc -> Doc -- Nested-\end{code}--GHC-specific ones.--\begin{code}-hang :: Doc -> Int -> Doc -> Doc-punctuate :: Doc -> [Doc] -> [Doc] -- punctuate p [d1, ... dn] = [d1 <> p, d2 <> p, ... dn-1 <> p, dn]-\end{code}--Displaying @Doc@ values. --\begin{code}-instance Show Doc where- showsPrec prec doc cont = showDoc doc cont--render :: Doc -> String -- Uses default style-fullRender :: Mode- -> Int -- Line length- -> Float -- Ribbons per line- -> (TextDetails -> a -> a) -- What to do with text- -> a -- What to do at the end- -> Doc- -> a -- Result--renderStyle :: Style -> Doc -> String-data Style = Style { lineLength :: Int, -- In chars- ribbonsPerLine :: Float, -- Ratio of ribbon length to line length- mode :: Mode- }-style :: Style -- The default style-style = Style { lineLength = 100, ribbonsPerLine = 2.5, mode = PageMode }--data Mode = PageMode -- Normal - | ZigZagMode -- With zig-zag cuts- | LeftMode -- No indentation, infinitely long lines- | OneLineMode -- All on one line--\end{code}---*********************************************************-* *-\subsection{The @Doc@ calculus}-* *-*********************************************************--The @Doc@ combinators satisfy the following laws:-\begin{verbatim}-Laws for $$-~~~~~~~~~~~-<a1> (x $$ y) $$ z = x $$ (y $$ z)-<a2> empty $$ x = x-<a3> x $$ empty = x-- ...ditto $+$...--Laws for <>-~~~~~~~~~~~-<b1> (x <> y) <> z = x <> (y <> z)-<b2> empty <> x = empty-<b3> x <> empty = x-- ...ditto <+>...--Laws for text-~~~~~~~~~~~~~-<t1> text s <> text t = text (s++t)-<t2> text "" <> x = x, if x non-empty--Laws for nest-~~~~~~~~~~~~~-<n1> nest 0 x = x-<n2> nest k (nest k' x) = nest (k+k') x-<n3> nest k (x <> y) = nest k z <> nest k y-<n4> nest k (x $$ y) = nest k x $$ nest k y-<n5> nest k empty = empty-<n6> x <> nest k y = x <> y, if x non-empty--** Note the side condition on <n6>! It is this that-** makes it OK for empty to be a left unit for <>.--Miscellaneous-~~~~~~~~~~~~~-<m1> (text s <> x) $$ y = text s <> ((text "" <> x)) $$ - nest (-length s) y)--<m2> (x $$ y) <> z = x $$ (y <> z)- if y non-empty---Laws for list versions-~~~~~~~~~~~~~~~~~~~~~~-<l1> sep (ps++[empty]++qs) = sep (ps ++ qs)- ...ditto hsep, hcat, vcat, fill...--<l2> nest k (sep ps) = sep (map (nest k) ps)- ...ditto hsep, hcat, vcat, fill...--Laws for oneLiner-~~~~~~~~~~~~~~~~~-<o1> oneLiner (nest k p) = nest k (oneLiner p)-<o2> oneLiner (x <> y) = oneLiner x <> oneLiner y -\end{verbatim}---You might think that the following verion of <m1> would-be neater:-\begin{verbatim}-<3 NO> (text s <> x) $$ y = text s <> ((empty <> x)) $$ - nest (-length s) y)-\end{verbatim}-But it doesn't work, for if x=empty, we would have-\begin{verbatim}- text s $$ y = text s <> (empty $$ nest (-length s) y)- = text s <> nest (-length s) y-\end{verbatim}----*********************************************************-* *-\subsection{Simple derived definitions}-* *-*********************************************************--\begin{code}-semi = char ';'-colon = char ':'-comma = char ','-space = char ' '-equals = char '='-lparen = char '('-rparen = char ')'-lbrack = char '['-rbrack = char ']'-lbrace = char '{'-rbrace = char '}'--int n = text (show n)-integer n = text (show n)-float n = text (show n)-double n = text (show n)-rational n = text (show n)--- SIGBJORN wrote instead:--- rational n = text (show (fromRationalX n))--quotes p = char '`' <> p <> char '\''-doubleQuotes p = char '"' <> p <> char '"'-parens p = char '(' <> p <> char ')'-brackets p = char '[' <> p <> char ']'-braces p = char '{' <> p <> char '}'---hcat = foldr (<>) empty-hsep = foldr (<+>) empty-vcat = foldr ($$) empty--hang d1 n d2 = d1 $$ (nest n d2)--punctuate p [] = []-punctuate p (d:ds) = go d ds- where- go d [] = [d]- go d (e:es) = (d <> p) : go e es-\end{code}---*********************************************************-* *-\subsection{The @Doc@ data type}-* *-*********************************************************--A @Doc@ represents a {\em set} of layouts. A @Doc@ with-no occurrences of @Union@ or @NoDoc@ represents just one layout.-\begin{code}-data Doc- = Empty -- empty- | NilAbove Doc -- text "" $$ x- | TextBeside TextDetails Int Doc -- text s <> x - | Nest Int Doc -- nest k x- | Union Doc Doc -- ul `union` ur- | NoDoc -- The empty set of documents- | Beside Doc Bool Doc -- True <=> space between- | Above Doc Bool Doc -- True <=> never overlap--type RDoc = Doc -- RDoc is a "reduced Doc", guaranteed not to have a top-level Above or Beside---reduceDoc :: Doc -> RDoc-reduceDoc (Beside p g q) = beside p g (reduceDoc q)-reduceDoc (Above p g q) = above p g (reduceDoc q)-reduceDoc p = p---data TextDetails = Chr Char- | Str String- | PStr String-space_text = Chr ' '-nl_text = Chr '\n'-\end{code}--Here are the invariants:-\begin{itemize}-\item-The argument of @NilAbove@ is never @Empty@. Therefore-a @NilAbove@ occupies at least two lines.--\item-The arugment of @TextBeside@ is never @Nest@.--\item -The layouts of the two arguments of @Union@ both flatten to the same string.--\item -The arguments of @Union@ are either @TextBeside@, or @NilAbove@.--\item-The right argument of a union cannot be equivalent to the empty set (@NoDoc@).-If the left argument of a union is equivalent to the empty set (@NoDoc@),-then the @NoDoc@ appears in the first line.--\item -An empty document is always represented by @Empty@.-It can't be hidden inside a @Nest@, or a @Union@ of two @Empty@s.--\item -The first line of every layout in the left argument of @Union@-is longer than the first line of any layout in the right argument.-(1) ensures that the left argument has a first line. In view of (3),-this invariant means that the right argument must have at least two-lines.-\end{itemize}--\begin{code}- -- Arg of a NilAbove is always an RDoc-nilAbove_ p = NilAbove p-- -- Arg of a TextBeside is always an RDoc-textBeside_ s sl p = TextBeside s sl p-- -- Arg of Nest is always an RDoc-nest_ k p = Nest k p-- -- Args of union are always RDocs-union_ p q = Union p q--\end{code}---Notice the difference between- * NoDoc (no documents)- * Empty (one empty document; no height and no width)- * text "" (a document containing the empty string;- one line high, but has no width)----*********************************************************-* *-\subsection{@empty@, @text@, @nest@, @union@}-* *-*********************************************************--\begin{code}-empty = Empty--char c = textBeside_ (Chr c) 1 Empty-text s = case length s of {sl -> textBeside_ (Str s) sl Empty}-ptext s = case length s of {sl -> textBeside_ (PStr s) sl Empty}--nest k p = mkNest k (reduceDoc p) -- Externally callable version---- mkNest checks for Nest's invariant that it doesn't have an Empty inside it-mkNest k (Nest k1 p) = mkNest (k + k1) p-mkNest k NoDoc = NoDoc-mkNest k Empty = Empty-mkNest 0 p = p -- Worth a try!-mkNest k p = nest_ k p---- mkUnion checks for an empty document-mkUnion Empty q = Empty-mkUnion p q = p `union_` q-\end{code}--*********************************************************-* *-\subsection{Vertical composition @$$@}-* *-*********************************************************---\begin{code}-p $$ q = Above p False q-p $+$ q = Above p True q--above :: Doc -> Bool -> RDoc -> RDoc-above (Above p g1 q1) g2 q2 = above p g1 (above q1 g2 q2)-above p@(Beside _ _ _) g q = aboveNest (reduceDoc p) g 0 (reduceDoc q)-above p g q = aboveNest p g 0 (reduceDoc q)--aboveNest :: RDoc -> Bool -> Int -> RDoc -> RDoc--- Specfication: aboveNest p g k q = p $g$ (nest k q)--aboveNest NoDoc g k q = NoDoc-aboveNest (p1 `Union` p2) g k q = aboveNest p1 g k q `union_` - aboveNest p2 g k q- -aboveNest Empty g k q = mkNest k q-aboveNest (Nest k1 p) g k q = nest_ k1 (aboveNest p g (k - k1) q)- -- p can't be Empty, so no need for mkNest- -aboveNest (NilAbove p) g k q = nilAbove_ (aboveNest p g k q)-aboveNest (TextBeside s sl p) g k q = textBeside_ s sl rest- where- k1 = k - sl- rest = case p of- Empty -> nilAboveNest g k1 q- other -> aboveNest p g k1 q-\end{code}--\begin{code}-nilAboveNest :: Bool -> Int -> RDoc -> RDoc--- Specification: text s <> nilaboveNest g k q --- = text s <> (text "" $g$ nest k q)--nilAboveNest g k Empty = Empty -- Here's why the "text s <>" is in the spec!-nilAboveNest g k (Nest k1 q) = nilAboveNest g (k + k1) q--nilAboveNest g k q | (not g) && (k > 0) -- No newline if no overlap- = textBeside_ (Str (spaces k)) k q- | otherwise -- Put them really above- = nilAbove_ (mkNest k q)-\end{code}---*********************************************************-* *-\subsection{Horizontal composition @<>@}-* *-*********************************************************--\begin{code}-p <> q = Beside p False q-p <+> q = Beside p True q--beside :: Doc -> Bool -> RDoc -> RDoc--- Specification: beside g p q = p <g> q- -beside NoDoc g q = NoDoc-beside (p1 `Union` p2) g q = (beside p1 g q) `union_` (beside p2 g q)-beside Empty g q = q-beside (Nest k p) g q = nest_ k (beside p g q) -- p non-empty-beside p@(Beside p1 g1 q1) g2 q2 - {- (A `op1` B) `op2` C == A `op1` (B `op2` C) iff op1 == op2 - [ && (op1 == <> || op1 == <+>) ] -}- | g1 == g2 = beside p1 g1 (beside q1 g2 q2)- | otherwise = beside (reduceDoc p) g2 q2-beside p@(Above _ _ _) g q = beside (reduceDoc p) g q-beside (NilAbove p) g q = nilAbove_ (beside p g q)-beside (TextBeside s sl p) g q = textBeside_ s sl rest- where- rest = case p of- Empty -> nilBeside g q- other -> beside p g q-\end{code}--\begin{code}-nilBeside :: Bool -> RDoc -> RDoc--- Specification: text "" <> nilBeside g p --- = text "" <g> p--nilBeside g Empty = Empty -- Hence the text "" in the spec-nilBeside g (Nest _ p) = nilBeside g p-nilBeside g p | g = textBeside_ space_text 1 p- | otherwise = p-\end{code}--*********************************************************-* *-\subsection{Separate, @sep@, Hughes version}-* *-*********************************************************--\begin{code}--- Specification: sep ps = oneLiner (hsep ps)--- `union`--- vcat ps--sep = sepX True -- Separate with spaces-cat = sepX False -- Don't--sepX x [] = empty-sepX x (p:ps) = sep1 x (reduceDoc p) 0 ps----- Specification: sep1 g k ys = sep (x : map (nest k) ys)--- = oneLiner (x <g> nest k (hsep ys))--- `union` x $$ nest k (vcat ys)--sep1 :: Bool -> RDoc -> Int -> [Doc] -> RDoc-sep1 g NoDoc k ys = NoDoc-sep1 g (p `Union` q) k ys = sep1 g p k ys- `union_`- (aboveNest q False k (reduceDoc (vcat ys)))--sep1 g Empty k ys = mkNest k (sepX g ys)-sep1 g (Nest n p) k ys = nest_ n (sep1 g p (k - n) ys)--sep1 g (NilAbove p) k ys = nilAbove_ (aboveNest p False k (reduceDoc (vcat ys)))-sep1 g (TextBeside s sl p) k ys = textBeside_ s sl (sepNB g p (k - sl) ys)---- Specification: sepNB p k ys = sep1 (text "" <> p) k ys--- Called when we have already found some text in the first item--- We have to eat up nests--sepNB g (Nest _ p) k ys = sepNB g p k ys--sepNB g Empty k ys = oneLiner (nilBeside g (reduceDoc rest))- `mkUnion` - nilAboveNest False k (reduceDoc (vcat ys))- where- rest | g = hsep ys- | otherwise = hcat ys--sepNB g p k ys = sep1 g p k ys-\end{code}--*********************************************************-* *-\subsection{@fill@}-* *-*********************************************************--\begin{code}-fsep = fill True-fcat = fill False---- Specification: --- fill [] = empty--- fill [p] = p--- fill (p1:p2:ps) = oneLiner p1 <#> nest (length p1) --- (fill (oneLiner p2 : ps))--- `union`--- p1 $$ fill ps--fill g [] = empty-fill g (p:ps) = fill1 g (reduceDoc p) 0 ps---fill1 :: Bool -> RDoc -> Int -> [Doc] -> Doc-fill1 g NoDoc k ys = NoDoc-fill1 g (p `Union` q) k ys = fill1 g p k ys- `union_`- (aboveNest q False k (fill g ys))--fill1 g Empty k ys = mkNest k (fill g ys)-fill1 g (Nest n p) k ys = nest_ n (fill1 g p (k - n) ys)--fill1 g (NilAbove p) k ys = nilAbove_ (aboveNest p False k (fill g ys))-fill1 g (TextBeside s sl p) k ys = textBeside_ s sl (fillNB g p (k - sl) ys)--fillNB g (Nest _ p) k ys = fillNB g p k ys-fillNB g Empty k [] = Empty-fillNB g Empty k (y:ys) = nilBeside g (fill1 g (oneLiner (reduceDoc y)) k1 ys)- `mkUnion` - nilAboveNest False k (fill g (y:ys))- where- k1 | g = k - 1- | otherwise = k--fillNB g p k ys = fill1 g p k ys-\end{code}---*********************************************************-* *-\subsection{Selecting the best layout}-* *-*********************************************************--\begin{code}-best :: Mode- -> Int -- Line length- -> Int -- Ribbon length- -> RDoc- -> RDoc -- No unions in here!--best OneLineMode w r p- = get p- where- get Empty = Empty- get NoDoc = NoDoc- get (NilAbove p) = nilAbove_ (get p)- get (TextBeside s sl p) = textBeside_ s sl (get p)- get (Nest k p) = get p -- Elide nest- get (p `Union` q) = first (get p) (get q)--best mode w r p- = get w p- where- get :: Int -- (Remaining) width of line- -> Doc -> Doc- get w Empty = Empty- get w NoDoc = NoDoc- get w (NilAbove p) = nilAbove_ (get w p)- get w (TextBeside s sl p) = textBeside_ s sl (get1 w sl p)- get w (Nest k p) = nest_ k (get (w - k) p)- get w (p `Union` q) = nicest w r (get w p) (get w q)-- get1 :: Int -- (Remaining) width of line- -> Int -- Amount of first line already eaten up- -> Doc -- This is an argument to TextBeside => eat Nests- -> Doc -- No unions in here!-- get1 w sl Empty = Empty- get1 w sl NoDoc = NoDoc- get1 w sl (NilAbove p) = nilAbove_ (get (w - sl) p)- get1 w sl (TextBeside t tl p) = textBeside_ t tl (get1 w (sl + tl) p)- get1 w sl (Nest k p) = get1 w sl p- get1 w sl (p `Union` q) = nicest1 w r sl (get1 w sl p) - (get1 w sl q)--nicest w r p q = nicest1 w r 0 p q-nicest1 w r sl p q | fits ((w `minn` r) - sl) p = p- | otherwise = q--fits :: Int -- Space available- -> Doc- -> Bool -- True if *first line* of Doc fits in space available- -fits n p | n < 0 = False-fits n NoDoc = False-fits n Empty = True-fits n (NilAbove _) = True-fits n (TextBeside _ sl p) = fits (n - sl) p--minn x y | x < y = x- | otherwise = y-\end{code}--@first@ and @nonEmptySet@ are similar to @nicest@ and @fits@, only simpler.-@first@ returns its first argument if it is non-empty, otherwise its second.--\begin{code}-first p q | nonEmptySet p = p - | otherwise = q--nonEmptySet NoDoc = False-nonEmptySet (p `Union` q) = True-nonEmptySet Empty = True-nonEmptySet (NilAbove p) = True -- NoDoc always in first line-nonEmptySet (TextBeside _ _ p) = nonEmptySet p-nonEmptySet (Nest _ p) = nonEmptySet p-\end{code}--@oneLiner@ returns the one-line members of the given set of @Doc@s.--\begin{code}-oneLiner :: Doc -> Doc-oneLiner NoDoc = NoDoc-oneLiner Empty = Empty-oneLiner (NilAbove p) = NoDoc-oneLiner (TextBeside s sl p) = textBeside_ s sl (oneLiner p)-oneLiner (Nest k p) = nest_ k (oneLiner p)-oneLiner (p `Union` q) = oneLiner p-\end{code}----*********************************************************-* *-\subsection{Displaying the best layout}-* *-*********************************************************---\begin{code}-renderStyle Style{mode=mode, lineLength=lineLength, ribbonsPerLine=ribbonsPerLine} doc - = fullRender mode lineLength ribbonsPerLine string_txt "" doc--render doc = showDoc doc ""-showDoc doc rest = fullRender PageMode 100 1.5 string_txt rest doc--string_txt (Chr c) s = c:s-string_txt (Str s1) s2 = s1 ++ s2-string_txt (PStr s1) s2 = s1 ++ s2-\end{code}--\begin{code}--fullRender OneLineMode _ _ txt end doc = easy_display space_text txt end (reduceDoc doc)-fullRender LeftMode _ _ txt end doc = easy_display nl_text txt end (reduceDoc doc)--fullRender mode line_length ribbons_per_line txt end doc- = display mode line_length ribbon_length txt end best_doc- where - best_doc = best mode hacked_line_length ribbon_length (reduceDoc doc)-- hacked_line_length, ribbon_length :: Int- ribbon_length = round (fromIntegral line_length / ribbons_per_line)- hacked_line_length = case mode of { ZigZagMode -> maxBound; other -> line_length }--display mode page_width ribbon_width txt end doc- = case page_width - ribbon_width of { gap_width ->- case gap_width `quot` 2 of { shift ->- let- lay k (Nest k1 p) = lay (k + k1) p- lay k Empty = end- - lay k (NilAbove p) = nl_text `txt` lay k p- - lay k (TextBeside s sl p)- = case mode of- ZigZagMode | k >= gap_width- -> nl_text `txt` (- Str (multi_ch shift '/') `txt` (- nl_text `txt` (- lay1 (k - shift) s sl p)))-- | k < 0- -> nl_text `txt` (- Str (multi_ch shift '\\') `txt` (- nl_text `txt` (- lay1 (k + shift) s sl p )))-- other -> lay1 k s sl p- - lay1 k s sl p = Str (indent k) `txt` (s `txt` lay2 (k + sl) p)- - lay2 k (NilAbove p) = nl_text `txt` lay k p- lay2 k (TextBeside s sl p) = s `txt` (lay2 (k + sl) p)- lay2 k (Nest _ p) = lay2 k p- lay2 k Empty = end- in- lay 0 doc- }}--cant_fail = error "easy_display: NoDoc"-easy_display nl_text txt end doc - = lay doc cant_fail- where- lay NoDoc no_doc = no_doc- lay (Union p q) no_doc = {- lay p -} (lay q cant_fail) -- Second arg can't be NoDoc- lay (Nest k p) no_doc = lay p no_doc- lay Empty no_doc = end- lay (NilAbove p) no_doc = nl_text `txt` lay p cant_fail -- NoDoc always on first line- lay (TextBeside s sl p) no_doc = s `txt` lay p no_doc--indent n | n >= 8 = '\t' : indent (n - 8)- | otherwise = spaces n--multi_ch 0 ch = ""-multi_ch n ch = ch : multi_ch (n - 1) ch--spaces 0 = ""-spaces n = ' ' : spaces (n - 1)-\end{code}-
+ src/PrettyCombinators.lhs view
@@ -0,0 +1,905 @@+Hand converted to standard Haskell -- jcp++*********************************************************************************+* *+* John Hughes's and Simon Peyton Jones's Pretty Printer Combinators *+* *+* based on "The Design of a Pretty-printing Library" *+* in Advanced Functional Programming, *+* Johan Jeuring and Erik Meijer (eds), LNCS 925 *+* http://www.cs.chalmers.se/~rjmh/Papers/pretty.ps *+* *+* Heavily modified by Simon Peyton Jones, Dec 96 *+* *+*********************************************************************************++Version 3.0 28 May 1997+ * Cured massive performance bug. If you write++ foldl <> empty (map (text.show) [1..10000])++ you get quadratic behaviour with V2.0. Why? For just the same reason as you get+ quadratic behaviour with left-associated (++) chains.++ This is really bad news. One thing a pretty-printer abstraction should+ certainly guarantee is insensivity to associativity. It matters: suddenly+ GHC's compilation times went up by a factor of 100 when I switched to the+ new pretty printer.+ + I fixed it with a bit of a hack (because I wanted to get GHC back on the+ road). I added two new constructors to the Doc type, Above and Beside:+ + <> = Beside+ $$ = Above+ + Then, where I need to get to a "TextBeside" or "NilAbove" form I "force"+ the Doc to squeeze out these suspended calls to Beside and Above; but in so+ doing I re-associate. It's quite simple, but I'm not satisfied that I've done+ the best possible job. I'll send you the code if you are interested.++ * Added new exports:+ punctuate, hang+ int, integer, float, double, rational,+ lparen, rparen, lbrack, rbrack, lbrace, rbrace,++ * fullRender's type signature has changed. Rather than producing a string it+ now takes an extra couple of arguments that tells it how to glue fragments+ of output together:++ fullRender :: Mode+ -> Int -- Line length+ -> Float -- Ribbons per line+ -> (TextDetails -> a -> a) -- What to do with text+ -> a -- What to do at the end+ -> Doc+ -> a -- Result++ The "fragments" are encapsulated in the TextDetails data type:+ data TextDetails = Chr Char+ | Str String+ | PStr FAST_STRING++ The Chr and Str constructors are obvious enough. The PStr constructor has a packed+ string (FAST_STRING) inside it. It's generated by using the new "ptext" export.++ An advantage of this new setup is that you can get the renderer to do output+ directly (by passing in a function of type (TextDetails -> IO () -> IO ()),+ rather than producing a string that you then print.+++Version 2.0 24 April 1997+ * Made empty into a left unit for <> as well as a right unit;+ it is also now true that+ nest k empty = empty+ which wasn't true before.++ * Fixed an obscure bug in sep that occassionally gave very wierd behaviour++ * Added $+$++ * Corrected and tidied up the laws and invariants++======================================================================+Relative to John's original paper, there are the following new features:++1. There's an empty document, "empty". It's a left and right unit for + both <> and $$, and anywhere in the argument list for+ sep, hcat, hsep, vcat, fcat etc.++ It is Really Useful in practice.++2. There is a paragraph-fill combinator, fsep, that's much like sep,+ only it keeps fitting things on one line until itc can't fit any more.++3. Some random useful extra combinators are provided. + <+> puts its arguments beside each other with a space between them,+ unless either argument is empty in which case it returns the other+++ hcat is a list version of <>+ hsep is a list version of <+>+ vcat is a list version of $$++ sep (separate) is either like hsep or like vcat, depending on what fits++ cat is behaves like sep, but it uses <> for horizontal conposition+ fcat is behaves like fsep, but it uses <> for horizontal conposition++ These new ones do the obvious things:+ char, semi, comma, colon, space,+ parens, brackets, braces, + quotes, doubleQuotes+ +4. The "above" combinator, $$, now overlaps its two arguments if the+ last line of the top argument stops before the first line of the second begins.+ For example: text "hi" $$ nest 5 "there"+ lays out as+ hi there+ rather than+ hi+ there++ There are two places this is really useful++ a) When making labelled blocks, like this:+ Left -> code for left+ Right -> code for right+ LongLongLongLabel ->+ code for longlonglonglabel+ The block is on the same line as the label if the label is+ short, but on the next line otherwise.++ b) When laying out lists like this:+ [ first+ , second+ , third+ ]+ which some people like. But if the list fits on one line+ you want [first, second, third]. You can't do this with+ John's original combinators, but it's quite easy with the+ new $$.++ The combinator $+$ gives the original "never-overlap" behaviour.++5. Several different renderers are provided:+ * a standard one+ * one that uses cut-marks to avoid deeply-nested documents + simply piling up in the right-hand margin+ * one that ignores indentation (fewer chars output; good for machines)+ * one that ignores indentation and newlines (ditto, only more so)++6. Numerous implementation tidy-ups+ Use of unboxed data types to speed up the implementation++++\begin{code}+module PrettyCombinators (+ Doc, -- Abstract+ Mode(..), TextDetails(..),+ Style,++ empty, nest,++ text, char, ptext,+ int, integer, float, double, rational,+ parens, brackets, braces, quotes, doubleQuotes,+ semi, comma, colon, space, equals,+ lparen, rparen, lbrack, rbrack, lbrace, rbrace,++ (<>), (<+>), hcat, hsep, + ($$), ($+$), vcat, + sep, cat, + fsep, fcat, ++ hang, punctuate,+ + renderStyle, + render, fullRender+ ) where++-- Don't import Util( assertPanic ) because it makes a loop in the module structure++import Data.Ratio+infixl 6 <> +infixl 6 <+>+infixl 5 $$, $+$+\end{code}++++*********************************************************+* *+\subsection{CPP magic so that we can compile with both GHC and Hugs}+* *+*********************************************************++The library uses unboxed types to get a bit more speed, but these CPP macros+allow you to use either GHC or Hugs. To get GHC, just set the CPP variable+ __GLASGOW_HASKELL__+++*********************************************************+* *+\subsection{The interface}+* *+*********************************************************++The primitive @Doc@ values++\begin{code}+empty :: Doc+text :: String -> Doc +char :: Char -> Doc++semi, comma, colon, space, equals :: Doc+lparen, rparen, lbrack, rbrack, lbrace, rbrace :: Doc++parens, brackets, braces :: Doc -> Doc +quotes, doubleQuotes :: Doc -> Doc++int :: Int -> Doc+integer :: Integer -> Doc+float :: Float -> Doc+double :: Double -> Doc+rational :: Rational -> Doc+\end{code}+++Combining @Doc@ values++\begin{code}+(<>) :: Doc -> Doc -> Doc -- Beside+hcat :: [Doc] -> Doc -- List version of <>+(<+>) :: Doc -> Doc -> Doc -- Beside, separated by space+hsep :: [Doc] -> Doc -- List version of <+>++($$) :: Doc -> Doc -> Doc -- Above; if there is no+ -- overlap it "dovetails" the two+vcat :: [Doc] -> Doc -- List version of $$++cat :: [Doc] -> Doc -- Either hcat or vcat+sep :: [Doc] -> Doc -- Either hsep or vcat+fcat :: [Doc] -> Doc -- ``Paragraph fill'' version of cat+fsep :: [Doc] -> Doc -- ``Paragraph fill'' version of sep++nest :: Int -> Doc -> Doc -- Nested+\end{code}++GHC-specific ones.++\begin{code}+hang :: Doc -> Int -> Doc -> Doc+punctuate :: Doc -> [Doc] -> [Doc] -- punctuate p [d1, ... dn] = [d1 <> p, d2 <> p, ... dn-1 <> p, dn]+\end{code}++Displaying @Doc@ values. ++\begin{code}+instance Show Doc where+ showsPrec prec doc cont = showDoc doc cont++render :: Doc -> String -- Uses default style+fullRender :: Mode+ -> Int -- Line length+ -> Float -- Ribbons per line+ -> (TextDetails -> a -> a) -- What to do with text+ -> a -- What to do at the end+ -> Doc+ -> a -- Result++renderStyle :: Style -> Doc -> String+data Style = Style { lineLength :: Int, -- In chars+ ribbonsPerLine :: Float, -- Ratio of ribbon length to line length+ mode :: Mode+ }+style :: Style -- The default style+style = Style { lineLength = 100, ribbonsPerLine = 2.5, mode = PageMode }++data Mode = PageMode -- Normal + | ZigZagMode -- With zig-zag cuts+ | LeftMode -- No indentation, infinitely long lines+ | OneLineMode -- All on one line++\end{code}+++*********************************************************+* *+\subsection{The @Doc@ calculus}+* *+*********************************************************++The @Doc@ combinators satisfy the following laws:+\begin{verbatim}+Laws for $$+~~~~~~~~~~~+<a1> (x $$ y) $$ z = x $$ (y $$ z)+<a2> empty $$ x = x+<a3> x $$ empty = x++ ...ditto $+$...++Laws for <>+~~~~~~~~~~~+<b1> (x <> y) <> z = x <> (y <> z)+<b2> empty <> x = empty+<b3> x <> empty = x++ ...ditto <+>...++Laws for text+~~~~~~~~~~~~~+<t1> text s <> text t = text (s++t)+<t2> text "" <> x = x, if x non-empty++Laws for nest+~~~~~~~~~~~~~+<n1> nest 0 x = x+<n2> nest k (nest k' x) = nest (k+k') x+<n3> nest k (x <> y) = nest k z <> nest k y+<n4> nest k (x $$ y) = nest k x $$ nest k y+<n5> nest k empty = empty+<n6> x <> nest k y = x <> y, if x non-empty++** Note the side condition on <n6>! It is this that+** makes it OK for empty to be a left unit for <>.++Miscellaneous+~~~~~~~~~~~~~+<m1> (text s <> x) $$ y = text s <> ((text "" <> x)) $$ + nest (-length s) y)++<m2> (x $$ y) <> z = x $$ (y <> z)+ if y non-empty+++Laws for list versions+~~~~~~~~~~~~~~~~~~~~~~+<l1> sep (ps++[empty]++qs) = sep (ps ++ qs)+ ...ditto hsep, hcat, vcat, fill...++<l2> nest k (sep ps) = sep (map (nest k) ps)+ ...ditto hsep, hcat, vcat, fill...++Laws for oneLiner+~~~~~~~~~~~~~~~~~+<o1> oneLiner (nest k p) = nest k (oneLiner p)+<o2> oneLiner (x <> y) = oneLiner x <> oneLiner y +\end{verbatim}+++You might think that the following verion of <m1> would+be neater:+\begin{verbatim}+<3 NO> (text s <> x) $$ y = text s <> ((empty <> x)) $$ + nest (-length s) y)+\end{verbatim}+But it doesn't work, for if x=empty, we would have+\begin{verbatim}+ text s $$ y = text s <> (empty $$ nest (-length s) y)+ = text s <> nest (-length s) y+\end{verbatim}++++*********************************************************+* *+\subsection{Simple derived definitions}+* *+*********************************************************++\begin{code}+semi = char ';'+colon = char ':'+comma = char ','+space = char ' '+equals = char '='+lparen = char '('+rparen = char ')'+lbrack = char '['+rbrack = char ']'+lbrace = char '{'+rbrace = char '}'++int n = text (show n)+integer n = text (show n)+float n = text (show n)+double n = text (show n)+rational n = text (show n)+-- SIGBJORN wrote instead:+-- rational n = text (show (fromRationalX n))++quotes p = char '`' <> p <> char '\''+doubleQuotes p = char '"' <> p <> char '"'+parens p = char '(' <> p <> char ')'+brackets p = char '[' <> p <> char ']'+braces p = char '{' <> p <> char '}'+++hcat = foldr (<>) empty+hsep = foldr (<+>) empty+vcat = foldr ($$) empty++hang d1 n d2 = d1 $$ (nest n d2)++punctuate p [] = []+punctuate p (d:ds) = go d ds+ where+ go d [] = [d]+ go d (e:es) = (d <> p) : go e es+\end{code}+++*********************************************************+* *+\subsection{The @Doc@ data type}+* *+*********************************************************++A @Doc@ represents a {\em set} of layouts. A @Doc@ with+no occurrences of @Union@ or @NoDoc@ represents just one layout.+\begin{code}+data Doc+ = Empty -- empty+ | NilAbove Doc -- text "" $$ x+ | TextBeside TextDetails Int Doc -- text s <> x + | Nest Int Doc -- nest k x+ | Union Doc Doc -- ul `union` ur+ | NoDoc -- The empty set of documents+ | Beside Doc Bool Doc -- True <=> space between+ | Above Doc Bool Doc -- True <=> never overlap++type RDoc = Doc -- RDoc is a "reduced Doc", guaranteed not to have a top-level Above or Beside+++reduceDoc :: Doc -> RDoc+reduceDoc (Beside p g q) = beside p g (reduceDoc q)+reduceDoc (Above p g q) = above p g (reduceDoc q)+reduceDoc p = p+++data TextDetails = Chr Char+ | Str String+ | PStr String+space_text = Chr ' '+nl_text = Chr '\n'+\end{code}++Here are the invariants:+\begin{itemize}+\item+The argument of @NilAbove@ is never @Empty@. Therefore+a @NilAbove@ occupies at least two lines.++\item+The arugment of @TextBeside@ is never @Nest@.++\item +The layouts of the two arguments of @Union@ both flatten to the same string.++\item +The arguments of @Union@ are either @TextBeside@, or @NilAbove@.++\item+The right argument of a union cannot be equivalent to the empty set (@NoDoc@).+If the left argument of a union is equivalent to the empty set (@NoDoc@),+then the @NoDoc@ appears in the first line.++\item +An empty document is always represented by @Empty@.+It can't be hidden inside a @Nest@, or a @Union@ of two @Empty@s.++\item +The first line of every layout in the left argument of @Union@+is longer than the first line of any layout in the right argument.+(1) ensures that the left argument has a first line. In view of (3),+this invariant means that the right argument must have at least two+lines.+\end{itemize}++\begin{code}+ -- Arg of a NilAbove is always an RDoc+nilAbove_ p = NilAbove p++ -- Arg of a TextBeside is always an RDoc+textBeside_ s sl p = TextBeside s sl p++ -- Arg of Nest is always an RDoc+nest_ k p = Nest k p++ -- Args of union are always RDocs+union_ p q = Union p q++\end{code}+++Notice the difference between+ * NoDoc (no documents)+ * Empty (one empty document; no height and no width)+ * text "" (a document containing the empty string;+ one line high, but has no width)++++*********************************************************+* *+\subsection{@empty@, @text@, @nest@, @union@}+* *+*********************************************************++\begin{code}+empty = Empty++char c = textBeside_ (Chr c) 1 Empty+text s = case length s of {sl -> textBeside_ (Str s) sl Empty}+ptext s = case length s of {sl -> textBeside_ (PStr s) sl Empty}++nest k p = mkNest k (reduceDoc p) -- Externally callable version++-- mkNest checks for Nest's invariant that it doesn't have an Empty inside it+mkNest k (Nest k1 p) = mkNest (k + k1) p+mkNest k NoDoc = NoDoc+mkNest k Empty = Empty+mkNest 0 p = p -- Worth a try!+mkNest k p = nest_ k p++-- mkUnion checks for an empty document+mkUnion Empty q = Empty+mkUnion p q = p `union_` q+\end{code}++*********************************************************+* *+\subsection{Vertical composition @$$@}+* *+*********************************************************+++\begin{code}+p $$ q = Above p False q+p $+$ q = Above p True q++above :: Doc -> Bool -> RDoc -> RDoc+above (Above p g1 q1) g2 q2 = above p g1 (above q1 g2 q2)+above p@(Beside _ _ _) g q = aboveNest (reduceDoc p) g 0 (reduceDoc q)+above p g q = aboveNest p g 0 (reduceDoc q)++aboveNest :: RDoc -> Bool -> Int -> RDoc -> RDoc+-- Specfication: aboveNest p g k q = p $g$ (nest k q)++aboveNest NoDoc g k q = NoDoc+aboveNest (p1 `Union` p2) g k q = aboveNest p1 g k q `union_` + aboveNest p2 g k q+ +aboveNest Empty g k q = mkNest k q+aboveNest (Nest k1 p) g k q = nest_ k1 (aboveNest p g (k - k1) q)+ -- p can't be Empty, so no need for mkNest+ +aboveNest (NilAbove p) g k q = nilAbove_ (aboveNest p g k q)+aboveNest (TextBeside s sl p) g k q = textBeside_ s sl rest+ where+ k1 = k - sl+ rest = case p of+ Empty -> nilAboveNest g k1 q+ other -> aboveNest p g k1 q+\end{code}++\begin{code}+nilAboveNest :: Bool -> Int -> RDoc -> RDoc+-- Specification: text s <> nilaboveNest g k q +-- = text s <> (text "" $g$ nest k q)++nilAboveNest g k Empty = Empty -- Here's why the "text s <>" is in the spec!+nilAboveNest g k (Nest k1 q) = nilAboveNest g (k + k1) q++nilAboveNest g k q | (not g) && (k > 0) -- No newline if no overlap+ = textBeside_ (Str (spaces k)) k q+ | otherwise -- Put them really above+ = nilAbove_ (mkNest k q)+\end{code}+++*********************************************************+* *+\subsection{Horizontal composition @<>@}+* *+*********************************************************++\begin{code}+p <> q = Beside p False q+p <+> q = Beside p True q++beside :: Doc -> Bool -> RDoc -> RDoc+-- Specification: beside g p q = p <g> q+ +beside NoDoc g q = NoDoc+beside (p1 `Union` p2) g q = (beside p1 g q) `union_` (beside p2 g q)+beside Empty g q = q+beside (Nest k p) g q = nest_ k (beside p g q) -- p non-empty+beside p@(Beside p1 g1 q1) g2 q2 + {- (A `op1` B) `op2` C == A `op1` (B `op2` C) iff op1 == op2 + [ && (op1 == <> || op1 == <+>) ] -}+ | g1 == g2 = beside p1 g1 (beside q1 g2 q2)+ | otherwise = beside (reduceDoc p) g2 q2+beside p@(Above _ _ _) g q = beside (reduceDoc p) g q+beside (NilAbove p) g q = nilAbove_ (beside p g q)+beside (TextBeside s sl p) g q = textBeside_ s sl rest+ where+ rest = case p of+ Empty -> nilBeside g q+ other -> beside p g q+\end{code}++\begin{code}+nilBeside :: Bool -> RDoc -> RDoc+-- Specification: text "" <> nilBeside g p +-- = text "" <g> p++nilBeside g Empty = Empty -- Hence the text "" in the spec+nilBeside g (Nest _ p) = nilBeside g p+nilBeside g p | g = textBeside_ space_text 1 p+ | otherwise = p+\end{code}++*********************************************************+* *+\subsection{Separate, @sep@, Hughes version}+* *+*********************************************************++\begin{code}+-- Specification: sep ps = oneLiner (hsep ps)+-- `union`+-- vcat ps++sep = sepX True -- Separate with spaces+cat = sepX False -- Don't++sepX x [] = empty+sepX x (p:ps) = sep1 x (reduceDoc p) 0 ps+++-- Specification: sep1 g k ys = sep (x : map (nest k) ys)+-- = oneLiner (x <g> nest k (hsep ys))+-- `union` x $$ nest k (vcat ys)++sep1 :: Bool -> RDoc -> Int -> [Doc] -> RDoc+sep1 g NoDoc k ys = NoDoc+sep1 g (p `Union` q) k ys = sep1 g p k ys+ `union_`+ (aboveNest q False k (reduceDoc (vcat ys)))++sep1 g Empty k ys = mkNest k (sepX g ys)+sep1 g (Nest n p) k ys = nest_ n (sep1 g p (k - n) ys)++sep1 g (NilAbove p) k ys = nilAbove_ (aboveNest p False k (reduceDoc (vcat ys)))+sep1 g (TextBeside s sl p) k ys = textBeside_ s sl (sepNB g p (k - sl) ys)++-- Specification: sepNB p k ys = sep1 (text "" <> p) k ys+-- Called when we have already found some text in the first item+-- We have to eat up nests++sepNB g (Nest _ p) k ys = sepNB g p k ys++sepNB g Empty k ys = oneLiner (nilBeside g (reduceDoc rest))+ `mkUnion` + nilAboveNest False k (reduceDoc (vcat ys))+ where+ rest | g = hsep ys+ | otherwise = hcat ys++sepNB g p k ys = sep1 g p k ys+\end{code}++*********************************************************+* *+\subsection{@fill@}+* *+*********************************************************++\begin{code}+fsep = fill True+fcat = fill False++-- Specification: +-- fill [] = empty+-- fill [p] = p+-- fill (p1:p2:ps) = oneLiner p1 <#> nest (length p1) +-- (fill (oneLiner p2 : ps))+-- `union`+-- p1 $$ fill ps++fill g [] = empty+fill g (p:ps) = fill1 g (reduceDoc p) 0 ps+++fill1 :: Bool -> RDoc -> Int -> [Doc] -> Doc+fill1 g NoDoc k ys = NoDoc+fill1 g (p `Union` q) k ys = fill1 g p k ys+ `union_`+ (aboveNest q False k (fill g ys))++fill1 g Empty k ys = mkNest k (fill g ys)+fill1 g (Nest n p) k ys = nest_ n (fill1 g p (k - n) ys)++fill1 g (NilAbove p) k ys = nilAbove_ (aboveNest p False k (fill g ys))+fill1 g (TextBeside s sl p) k ys = textBeside_ s sl (fillNB g p (k - sl) ys)++fillNB g (Nest _ p) k ys = fillNB g p k ys+fillNB g Empty k [] = Empty+fillNB g Empty k (y:ys) = nilBeside g (fill1 g (oneLiner (reduceDoc y)) k1 ys)+ `mkUnion` + nilAboveNest False k (fill g (y:ys))+ where+ k1 | g = k - 1+ | otherwise = k++fillNB g p k ys = fill1 g p k ys+\end{code}+++*********************************************************+* *+\subsection{Selecting the best layout}+* *+*********************************************************++\begin{code}+best :: Mode+ -> Int -- Line length+ -> Int -- Ribbon length+ -> RDoc+ -> RDoc -- No unions in here!++best OneLineMode w r p+ = get p+ where+ get Empty = Empty+ get NoDoc = NoDoc+ get (NilAbove p) = nilAbove_ (get p)+ get (TextBeside s sl p) = textBeside_ s sl (get p)+ get (Nest k p) = get p -- Elide nest+ get (p `Union` q) = first (get p) (get q)++best mode w r p+ = get w p+ where+ get :: Int -- (Remaining) width of line+ -> Doc -> Doc+ get w Empty = Empty+ get w NoDoc = NoDoc+ get w (NilAbove p) = nilAbove_ (get w p)+ get w (TextBeside s sl p) = textBeside_ s sl (get1 w sl p)+ get w (Nest k p) = nest_ k (get (w - k) p)+ get w (p `Union` q) = nicest w r (get w p) (get w q)++ get1 :: Int -- (Remaining) width of line+ -> Int -- Amount of first line already eaten up+ -> Doc -- This is an argument to TextBeside => eat Nests+ -> Doc -- No unions in here!++ get1 w sl Empty = Empty+ get1 w sl NoDoc = NoDoc+ get1 w sl (NilAbove p) = nilAbove_ (get (w - sl) p)+ get1 w sl (TextBeside t tl p) = textBeside_ t tl (get1 w (sl + tl) p)+ get1 w sl (Nest k p) = get1 w sl p+ get1 w sl (p `Union` q) = nicest1 w r sl (get1 w sl p) + (get1 w sl q)++nicest w r p q = nicest1 w r 0 p q+nicest1 w r sl p q | fits ((w `minn` r) - sl) p = p+ | otherwise = q++fits :: Int -- Space available+ -> Doc+ -> Bool -- True if *first line* of Doc fits in space available+ +fits n p | n < 0 = False+fits n NoDoc = False+fits n Empty = True+fits n (NilAbove _) = True+fits n (TextBeside _ sl p) = fits (n - sl) p++minn x y | x < y = x+ | otherwise = y+\end{code}++@first@ and @nonEmptySet@ are similar to @nicest@ and @fits@, only simpler.+@first@ returns its first argument if it is non-empty, otherwise its second.++\begin{code}+first p q | nonEmptySet p = p + | otherwise = q++nonEmptySet NoDoc = False+nonEmptySet (p `Union` q) = True+nonEmptySet Empty = True+nonEmptySet (NilAbove p) = True -- NoDoc always in first line+nonEmptySet (TextBeside _ _ p) = nonEmptySet p+nonEmptySet (Nest _ p) = nonEmptySet p+\end{code}++@oneLiner@ returns the one-line members of the given set of @Doc@s.++\begin{code}+oneLiner :: Doc -> Doc+oneLiner NoDoc = NoDoc+oneLiner Empty = Empty+oneLiner (NilAbove p) = NoDoc+oneLiner (TextBeside s sl p) = textBeside_ s sl (oneLiner p)+oneLiner (Nest k p) = nest_ k (oneLiner p)+oneLiner (p `Union` q) = oneLiner p+\end{code}++++*********************************************************+* *+\subsection{Displaying the best layout}+* *+*********************************************************+++\begin{code}+renderStyle Style{mode=mode, lineLength=lineLength, ribbonsPerLine=ribbonsPerLine} doc + = fullRender mode lineLength ribbonsPerLine string_txt "" doc++render doc = showDoc doc ""+showDoc doc rest = fullRender PageMode 100 1.5 string_txt rest doc++string_txt (Chr c) s = c:s+string_txt (Str s1) s2 = s1 ++ s2+string_txt (PStr s1) s2 = s1 ++ s2+\end{code}++\begin{code}++fullRender OneLineMode _ _ txt end doc = easy_display space_text txt end (reduceDoc doc)+fullRender LeftMode _ _ txt end doc = easy_display nl_text txt end (reduceDoc doc)++fullRender mode line_length ribbons_per_line txt end doc+ = display mode line_length ribbon_length txt end best_doc+ where + best_doc = best mode hacked_line_length ribbon_length (reduceDoc doc)++ hacked_line_length, ribbon_length :: Int+ ribbon_length = round (fromIntegral line_length / ribbons_per_line)+ hacked_line_length = case mode of { ZigZagMode -> maxBound; other -> line_length }++display mode page_width ribbon_width txt end doc+ = case page_width - ribbon_width of { gap_width ->+ case gap_width `quot` 2 of { shift ->+ let+ lay k (Nest k1 p) = lay (k + k1) p+ lay k Empty = end+ + lay k (NilAbove p) = nl_text `txt` lay k p+ + lay k (TextBeside s sl p)+ = case mode of+ ZigZagMode | k >= gap_width+ -> nl_text `txt` (+ Str (multi_ch shift '/') `txt` (+ nl_text `txt` (+ lay1 (k - shift) s sl p)))++ | k < 0+ -> nl_text `txt` (+ Str (multi_ch shift '\\') `txt` (+ nl_text `txt` (+ lay1 (k + shift) s sl p )))++ other -> lay1 k s sl p+ + lay1 k s sl p = Str (indent k) `txt` (s `txt` lay2 (k + sl) p)+ + lay2 k (NilAbove p) = nl_text `txt` lay k p+ lay2 k (TextBeside s sl p) = s `txt` (lay2 (k + sl) p)+ lay2 k (Nest _ p) = lay2 k p+ lay2 k Empty = end+ in+ lay 0 doc+ }}++cant_fail = error "easy_display: NoDoc"+easy_display nl_text txt end doc + = lay doc cant_fail+ where+ lay NoDoc no_doc = no_doc+ lay (Union p q) no_doc = {- lay p -} (lay q cant_fail) -- Second arg can't be NoDoc+ lay (Nest k p) no_doc = lay p no_doc+ lay Empty no_doc = end+ lay (NilAbove p) no_doc = nl_text `txt` lay p cant_fail -- NoDoc always on first line+ lay (TextBeside s sl p) no_doc = s `txt` lay p no_doc++indent n | n >= 8 = '\t' : indent (n - 8)+ | otherwise = spaces n++multi_ch 0 ch = ""+multi_ch n ch = ch : multi_ch (n - 1) ch++spaces 0 = ""+spaces n = ' ' : spaces (n - 1)+\end{code}+
src/Qual.lhs view
@@ -19,17 +19,16 @@ \em{Note:} The modified version also qualifies type constructors \begin{verbatim} -> module Qual(qual,qualGoal) where+> module Qual(qual) where++> import Curry.Base.Ident+> import Curry.Syntax+ > import Base > import TopEnv > qual :: ModuleIdent -> ValueEnv -> [Decl] -> [Decl] > qual m tyEnv ds = map (qualDecl m tyEnv) ds--> qualGoal :: ValueEnv -> Goal -> Goal-> qualGoal tyEnv (Goal p e ds) =-> Goal p (qualExpr (mkMIdent []) tyEnv e) -> (map (qualDecl (mkMIdent []) tyEnv) ds) > qualDecl :: ModuleIdent -> ValueEnv -> Decl -> Decl > qualDecl m tyEnv (FunctionDecl p f eqs) =
src/ScopeEnv.hs view
@@ -15,7 +15,7 @@ level, exists, beginScope, endScope, endScopeUp, toList, toLevelList, currentLevel) where -import Env+import qualified Data.Map as Map import Prelude hiding (lookup) -------------------------------------------------------------------------------@@ -23,14 +23,14 @@ -- Returns an empty scope environment new :: Ord a => ScopeEnv a b-new = ScopeEnv 0 emptyEnv []+new = ScopeEnv 0 Map.empty [] -- Inserts a value under a key into the environment of the current scope insert :: Ord a => a -> b -> ScopeEnv a b -> ScopeEnv a b insert key val env = modifySE insertLev env where- insertLev lev local = bindEnv key (val,lev) local+ insertLev lev local = Map.insert key (val,lev) local -- Updates the value stored under an existing key in the environment of @@ -39,8 +39,8 @@ update key val env = modifySE updateLev env where updateLev lev local = maybe local - (\ (_,lev') -> bindEnv key (val,lev') local)- (lookupEnv key local)+ (\ (_,lev') -> Map.insert key (val,lev') local)+ (Map.lookup key local) -- Modifies the value of an existing key by applying the function 'fun' -- in the environment of the current scope@@ -49,8 +49,8 @@ where modifyLev lev local = maybe local- (\ (val',lev') -> bindEnv key (fun val', lev') local)- (lookupEnv key local)+ (\ (val',lev') -> Map.insert key (fun val', lev') local)+ (Map.lookup key local) -- Looks up the value which is stored under a key from the environment of@@ -58,7 +58,7 @@ lookup :: Ord a => a -> ScopeEnv a b -> Maybe b lookup key env = selectSE lookupLev env where- lookupLev lev local = maybe Nothing (Just . fst) (lookupEnv key local)+ lookupLev lev local = maybe Nothing (Just . fst) (Map.lookup key local) -- Similar to 'lookup', but returns an alternative value, if the key@@ -71,14 +71,14 @@ level :: Ord a => a -> ScopeEnv a b -> Int level key env = selectSE levelLev env where- levelLev lev local = maybe (-1) snd (lookupEnv key local)+ levelLev lev local = maybe (-1) snd (Map.lookup key local) -- Checks, whether a key exists in the environment of the current scope exists :: Ord a => a -> ScopeEnv a b -> Bool exists key env = selectSE existsLev env where- existsLev lev local = maybe False (const True) (lookupEnv key local)+ existsLev lev local = maybe False (const True) (Map.lookup key local) -- Switches to the next scope (i.e. pushes the environment of the current@@ -106,18 +106,18 @@ endScopeUp (ScopeEnv _ top []) = ScopeEnv 0 top [] endScopeUp (ScopeEnv lev top (local:[]))- = ScopeEnv 0 (foldr (updateSE local) top (envToList top)) []+ = ScopeEnv 0 (foldr (updateSE local) top (Map.toList top)) [] endScopeUp (ScopeEnv lev top (local:local':locals)) = ScopeEnv (lev - 1) top - ((foldr (updateSE local) local' (envToList local')):locals)+ ((foldr (updateSE local) local' (Map.toList local')):locals) -- Returns the environment of current scope as a (key,value) list toList :: Ord a => ScopeEnv a b -> [(a,b)] toList env = selectSE toListLev env where- toListLev lev local = map (\ (key,(val,_)) -> (key,val)) (envToList local)+ toListLev lev local = map (\ (key,(val,_)) -> (key,val)) (Map.toList local) -- Returns all (key,value) pairs from the environment of the current scope @@ -127,7 +127,7 @@ where toLevelListLev lev local = map (\ (key,(val,_)) -> (key,val))- (filter (\ (_,(_,lev')) -> lev' == lev) (envToList local))+ (filter (\ (_,(_,lev')) -> lev' == lev) (Map.toList local)) -- Returns the current level@@ -140,7 +140,7 @@ -- Privates... ---modifySE :: (Int -> Env a (b,Int) -> Env a (b,Int)) -> ScopeEnv a b +modifySE :: (Int -> Map.Map a (b,Int) -> Map.Map a (b,Int)) -> ScopeEnv a b -> ScopeEnv a b modifySE f (ScopeEnv _ top []) = ScopeEnv 0 (f 0 top) []@@ -148,19 +148,19 @@ = ScopeEnv lev top ((f lev local):locals) ---selectSE :: (Int -> Env a (b,Int) -> c) -> ScopeEnv a b -> c+selectSE :: (Int -> Map.Map a (b,Int) -> c) -> ScopeEnv a b -> c selectSE f (ScopeEnv _ top []) = f 0 top selectSE f (ScopeEnv lev _ (local:_)) = f lev local ---updateSE :: Ord a => Env a (b,Int) -> (a,(b,Int)) -> Env a (b,Int) - -> Env a (b,Int)+updateSE :: Ord a => Map.Map a (b,Int) -> (a,(b,Int)) -> Map.Map a (b,Int) + -> Map.Map a (b,Int) updateSE local (key,(_,lev)) local' = maybe local' (\ (val',lev') - -> if lev == lev' then bindEnv key (val',lev) local' + -> if lev == lev' then Map.insert key (val',lev) local' else local')- (lookupEnv key local)+ (Map.lookup key local) @@ -168,7 +168,7 @@ ------------------------------------------------------------------------------- -- Data type for representing information in nested scopes.-data ScopeEnv a b = ScopeEnv Int (Env a (b,Int)) [Env a (b,Int)]+data ScopeEnv a b = ScopeEnv Int (Map.Map a (b,Int)) [Map.Map a (b,Int)] deriving Show
− src/ShowCurrySyntax.hs
@@ -1,493 +0,0 @@---- Transform a CurrySyntax module into a string representation without any---- pretty printing.---- Behaves like a derived Show instance even on parts with a specific one.---- ---- @author Sebastian Fischer (sebf@informatik.uni-kiel.de)---- @version December 2008---- bug fixed by bbr---module ShowCurrySyntax ( showModule ) where--import Ident-import Position-import CurrySyntax--showModule :: Module -> String-showModule m = showsModule m "\n"--showsModule :: Module -> ShowS-showsModule (Module mident espec decls)- = showsString "Module "- . showsModuleIdent mident . newline- . showsMaybe showsExportSpec espec . newline- . showsList (\d -> showsDecl d . newline) decls--showsPosition :: Position -> ShowS-showsPosition Position{line=row,column=col} = showsPair shows shows (row,col)--- showsPosition (Position file row col)--- = showsString "(Position "--- . shows file . space--- . shows row . space--- . shows col--- . showsString ")"--showsExportSpec :: ExportSpec -> ShowS-showsExportSpec (Exporting pos exports)- = showsString "(Exporting "- . showsPosition pos . space- . showsList showsExport exports- . showsString ")"--showsExport :: Export -> ShowS-showsExport (Export qident)- = showsString "(Export " . showsQualIdent qident . showsString ")"-showsExport (ExportTypeWith qident ids)- = showsString "(ExportTypeWith "- . showsQualIdent qident . space- . showsList showsIdent ids- . showsString ")"-showsExport (ExportTypeAll qident)- = showsString "(ExportTypeAll " . showsQualIdent qident . showsString ")"-showsExport (ExportModule m) - = showsString "(ExportModule " . showsModuleIdent m . showChar ')'--showsImportSpec :: ImportSpec -> ShowS-showsImportSpec (Importing pos imports)- = showsString "(Importing "- . showsPosition pos . space- . showsList showsImport imports- . showsString ")"-showsImportSpec (Hiding pos imports)- = showsString "(Hiding "- . showsPosition pos . space- . showsList showsImport imports- . showsString ")"--showsImport :: Import -> ShowS-showsImport (Import ident)- = showsString "(Import " . showsIdent ident . showsString ")"-showsImport (ImportTypeWith ident idents)- = showsString "(ImportTypeWith "- . showsIdent ident . space- . showsList showsIdent idents- . showsString ")"-showsImport (ImportTypeAll ident)- = showsString "(ImportTypeAll " . showsIdent ident . showsString ")"--showsDecl :: Decl -> ShowS-showsDecl (ImportDecl pos mident quali mmident mimpspec)- = showsString "(ImportDecl "- . showsPosition pos . space- . showsModuleIdent mident . space- . shows quali . space- . showsMaybe showsModuleIdent mmident . space- . showsMaybe showsImportSpec mimpspec- . showsString ")"-showsDecl (InfixDecl pos infx prec idents)- = showsString "(InfixDecl "- . showsPosition pos . space- . shows infx . space- . shows prec . space- . showsList showsIdent idents- . showsString ")"-showsDecl (DataDecl pos ident idents consdecls)- = showsString "(DataDecl "- . showsPosition pos . space- . showsIdent ident . space- . showsList showsIdent idents . space- . showsList showsConsDecl consdecls- . showsString ")"-showsDecl (NewtypeDecl pos ident idents newconsdecl)- = showsString "(NewtypeDecl "- . showsPosition pos . space- . showsIdent ident . space- . showsList showsIdent idents . space- . showsNewConsDecl newconsdecl- . showsString ")"-showsDecl (TypeDecl pos ident idents typ)- = showsString "(TypeDecl "- . showsPosition pos . space- . showsIdent ident . space- . showsList showsIdent idents . space- . showsTypeExpr typ- . showsString ")"-showsDecl (TypeSig pos idents typ)- = showsString "(TypeSig "- . showsPosition pos . space- . showsList showsIdent idents . space- . showsTypeExpr typ- . showsString ")"-showsDecl (EvalAnnot pos idents annot)- = showsString "(EvalAnnot "- . showsPosition pos . space- . showsList showsIdent idents . space- . shows annot- . showsString ")"-showsDecl (FunctionDecl pos ident eqs)- = showsString "(FunctionDecl "- . showsPosition pos . space- . showsIdent ident . space- . showsList showsEquation eqs- . showsString ")"-showsDecl (ExternalDecl pos cconv mstr ident typ)- = showsString "(ExternalDecl "- . showsPosition pos . space- . shows cconv . space- . shows mstr . space- . showsIdent ident . space- . showsTypeExpr typ- . showsString ")"-showsDecl (FlatExternalDecl pos idents)- = showsString "(FlatExternalDecl "- . showsPosition pos . space- . showsList showsIdent idents- . showsString ")"-showsDecl (PatternDecl pos cons rhs)- = showsString "(PatternDecl "- . showsPosition pos . space- . showsConsTerm cons . space- . showsRhs rhs- . showsString ")"-showsDecl (ExtraVariables pos idents)- = showsString "(ExtraVariables "- . showsPosition pos . space- . showsList showsIdent idents- . showsString ")"--showsConsDecl :: ConstrDecl -> ShowS-showsConsDecl (ConstrDecl pos idents ident types)- = showsString "(ConstrDecl "- . showsPosition pos . space- . showsList showsIdent idents . space- . showsIdent ident . space- . showsList showsTypeExpr types- . showsString ")"-showsConstrDecl (ConOpDecl pos idents rtyp ident ltyp)- = showsString "(ConOpDecl "- . showsPosition pos . space- . showsList showsIdent idents . space- . showsTypeExpr rtyp . space- . showsIdent ident . space- . showsTypeExpr ltyp- . showsString ")"--showsNewConsDecl :: NewConstrDecl -> ShowS-showsNewConsDecl (NewConstrDecl pos idents ident typ)- = showsString "(NewConstrDecl "- . showsPosition pos . space- . showsList showsIdent idents . space- . showsIdent ident . space- . showsTypeExpr typ- . showsString ")"--showsTypeExpr :: TypeExpr -> ShowS-showsTypeExpr (ConstructorType qident types)- = showsString "(ConstructorType "- . showsQualIdent qident . space- . showsList showsTypeExpr types- . showsString ")"-showsTypeExpr (VariableType ident)- = showsString "(VariableType " . showsIdent ident . showsString ")"-showsTypeExpr (TupleType types)- = showsString "(TupleType " . showsList showsTypeExpr types . showsString ")"-showsTypeExpr (ListType typ)- = showsString "(ListType " . showsTypeExpr typ . showsString ")"-showsTypeExpr (ArrowType dom ran)- = showsString "(ArrowType "- . showsTypeExpr dom . space- . showsTypeExpr ran- . showsString ")"-showsTypeExpr (RecordType fieldts mtyp)- = showsString "(RecordType "- . showsList (showsPair (showsList showsIdent) showsTypeExpr) fieldts . space- . showsMaybe showsTypeExpr mtyp- . showsString ")"--showsEquation :: Equation -> ShowS-showsEquation (Equation pos lhs rhs)- = showsString "(Equation "- . showsPosition pos . space- . showsLhs lhs . space- . showsRhs rhs- . showsString ")"--showsLhs :: Lhs -> ShowS-showsLhs (FunLhs ident conss)- = showsString "(FunLhs "- . showsIdent ident . space- . showsList showsConsTerm conss- . showsString ")"-showsLhs (OpLhs cons1 ident cons2)- = showsString "(OpLhs "- . showsConsTerm cons1 . space- . showsIdent ident . space- . showsConsTerm cons2- . showsString ")"-showsLhs (ApLhs lhs conss)- = showsString "(ApLhs "- . showsLhs lhs . space- . showsList showsConsTerm conss- . showsString ")"--showsRhs :: Rhs -> ShowS-showsRhs (SimpleRhs pos exp decls)- = showsString "(SimpleRhs "- . showsPosition pos . space- . showsExpression exp . space- . showsList showsDecl decls- . showsString ")"-showsRhs (GuardedRhs cexps decls)- = showsString "(GuardedRhs "- . showsList showsCondExpr cexps . space- . showsList showsDecl decls- . showsString ")"--showsCondExpr :: CondExpr -> ShowS-showsCondExpr (CondExpr pos exp1 exp2)- = showsString "(CondExpr "- . showsPosition pos . space- . showsExpression exp1 . space- . showsExpression exp2- . showsString ")"--showsLiteral :: Literal -> ShowS-showsLiteral (Char _ c) = showsString "(Char " . shows c . showsString ")"-showsLiteral (Int ident n)- = showsString "(Int "- . showsIdent ident . space- . shows n- . showsString ")"-showsLiteral (Float _ x) = showsString "(Float " . shows x . showsString ")"-showsLiteral (String _ s) = showsString "(String " . shows s . showsString ")"--showsConsTerm :: ConstrTerm -> ShowS-showsConsTerm (LiteralPattern lit)- = showsString "(LiteralPattern "- . showsLiteral lit- . showsString ")"-showsConsTerm (NegativePattern ident lit)- = showsString "(NegativePattern "- . showsIdent ident . space- . showsLiteral lit- . showsString ")"-showsConsTerm (VariablePattern ident)- = showsString "(VariablePattern "- . showsIdent ident - . showsString ")"-showsConsTerm (ConstructorPattern qident conss)- = showsString "(ConstructorPattern "- . showsQualIdent qident . space- . showsList showsConsTerm conss- . showsString ")"-showsConsTerm (InfixPattern cons1 qident cons2)- = showsString "(InfixPattern "- . showsConsTerm cons1 . space- . showsQualIdent qident . space- . showsConsTerm cons2- . showsString ")"-showsConsTerm (ParenPattern cons)- = showsString "(ParenPattern "- . showsConsTerm cons- . showsString ")"-showsConsTerm (TuplePattern _ conss)- = showsString "(TuplePattern "- . showsList showsConsTerm conss- . showsString ")"-showsConsTerm (ListPattern _ conss)- = showsString "(ListPattern "- . showsList showsConsTerm conss- . showsString ")"-showsConsTerm (AsPattern ident cons)- = showsString "(AsPattern "- . showsIdent ident . space- . showsConsTerm cons- . showsString ")"-showsConsTerm (LazyPattern _ cons)- = showsString "(LazyPattern "- . showsConsTerm cons- . showsString ")"-showsConsTerm (FunctionPattern qident conss)- = showsString "(FunctionPattern "- . showsQualIdent qident . space- . showsList showsConsTerm conss- . showsString ")"-showsConsTerm (InfixFuncPattern cons1 qident cons2)- = showsString "(InfixFuncPattern "- . showsConsTerm cons1 . space- . showsQualIdent qident . space- . showsConsTerm cons2- . showsString ")"-showsConsTerm (RecordPattern cfields mcons)- = shows "(RecordPattern "- . showsList (showsField showsConsTerm) cfields . space- . showsMaybe showsConsTerm mcons- . showsString ")"--showsExpression :: Expression -> ShowS-showsExpression (Literal lit)- = showsString "(Literal " . showsLiteral lit . showsString ")"-showsExpression (Variable qident)- = showsString "(Variable " . showsQualIdent qident . showsString ")"-showsExpression (Constructor qident)- = showsString "(Constructor " . showsQualIdent qident . showsString ")"-showsExpression (Paren exp)- = showsString "(Paren " . showsExpression exp . showsString ")"-showsExpression (Typed exp typ)- = showsString "(Typed "- . showsExpression exp . space- . showsTypeExpr typ- . showsString ")"-showsExpression (Tuple _ exps)- = showsString "(Tuple " . showsList showsExpression exps . showsString ")"-showsExpression (List _ exps)- = showsString "(List " . showsList showsExpression exps . showsString ")"-showsExpression (ListCompr _ exp stmts)- = showsString "(ListCompr "- . showsExpression exp . space- . showsList showsStatement stmts- . showsString ")"-showsExpression (EnumFrom exp)- = showsString "(EnumFrom " . showsExpression exp . showsString ")"-showsExpression (EnumFromThen exp1 exp2)- = showsString "(EnumFromThen "- . showsExpression exp1 . space- . showsExpression exp2- . showsString ")"-showsExpression (EnumFromTo exp1 exp2)- = showsString "(EnumFromTo "- . showsExpression exp1 . space- . showsExpression exp2- . showsString ")"-showsExpression (EnumFromThenTo exp1 exp2 exp3)- = showsString "(EnumFromThenTo "- . showsExpression exp1 . space- . showsExpression exp2 . space- . showsExpression exp3- . showsString ")"-showsExpression (UnaryMinus ident exp)- = showsString "(UnaryMinus "- . showsIdent ident . space- . showsExpression exp- . showsString ")"-showsExpression (Apply exp1 exp2)- = showsString "(Apply "- . showsExpression exp1 . space- . showsExpression exp2- . showsString ")"-showsExpression (InfixApply exp1 op exp2)- = showsString "(InfixApply "- . showsExpression exp1 . space- . showsInfixOp op . space- . showsExpression exp2- . showsString ")"-showsExpression (LeftSection exp op)- = showsString "(LeftSection "- . showsExpression exp . space- . showsInfixOp op- . showsString ")"-showsExpression (RightSection op exp)- = showsString "(RightSection "- . showsInfixOp op . space- . showsExpression exp- . showsString ")"-showsExpression (Lambda _ conss exp)- = showsString "(Lambda "- . showsList showsConsTerm conss . space- . showsExpression exp - . showsString ")"-showsExpression (Let decls exp)- = showsString "(Let "- . showsList showsDecl decls . space- . showsExpression exp - . showsString ")"-showsExpression (Do stmts exp)- = showsString "(Do "- . showsList showsStatement stmts . space- . showsExpression exp- . showsString ")"-showsExpression (IfThenElse _ exp1 exp2 exp3)- = showsString "(IfThenElse "- . showsExpression exp1 . space- . showsExpression exp2 . space- . showsExpression exp3- . showsString ")"-showsExpression (Case _ exp alts)- = showsString "(Case "- . showsExpression exp . space- . showsList showsAlt alts- . showsString ")"-showsExpression (RecordConstr efields)- = showsString "(RecordConstr "- . showsList (showsField showsExpression) efields- . showsString ")"-showsExpression (RecordSelection exp ident)- = showsString "(RecordSelection "- . showsExpression exp . space- . showsIdent ident- . showsString ")"-showsExpression (RecordUpdate efields exp)- = showsString "(RecordUpdate "- . showsList (showsField showsExpression) efields . space- . showsExpression exp- . showsString ")"--showsInfixOp :: InfixOp -> ShowS-showsInfixOp (InfixOp qident)- = showsString "(InfixOp " . showsQualIdent qident . showsString ")"-showsInfixOp (InfixConstr qident)- = showsString "(InfixConstr " . showsQualIdent qident . showsString ")"--showsStatement :: Statement -> ShowS-showsStatement (StmtExpr _ exp)- = showsString "(StmtExpr " . showsExpression exp . showsString ")"-showsStatement (StmtDecl decls)- = showsString "(StmtDecl " . showsList showsDecl decls . showsString ")"-showsStatement (StmtBind _ cons exp)- = showsString "(StmtBind "- . showsConsTerm cons . space- . showsExpression exp- . showsString ")"--showsAlt :: Alt -> ShowS-showsAlt (Alt pos cons rhs)- = showsString "(Alt "- . showsPosition pos . space- . showsConsTerm cons . space- . showsRhs rhs- . showsString ")"--showsField :: (a -> ShowS) -> Field a -> ShowS-showsField sa (Field pos ident a)- = showsString "(Field "- . showsPosition pos . space- . showsIdent ident . space- . sa a- . showsString ")"--showsString :: String -> ShowS-showsString = (++)--space :: ShowS-space = showsString " "--newline :: ShowS-newline = showsString "\n"--showsMaybe :: (a -> ShowS) -> Maybe a -> ShowS-showsMaybe shs- = maybe (showsString "Nothing")- (\x -> showsString "(Just " . shs x . showsString ")")--showsList :: (a -> ShowS) -> [a] -> ShowS-showsList _ [] = showsString "[]"-showsList shs (x:xs)- = showsString "["- . foldl (\sys y -> sys . showsString "," . shs y) (shs x) xs- . showsString "]"--showsPair :: (a -> ShowS) -> (b -> ShowS) -> (a,b) -> ShowS-showsPair sa sb (a,b)- = showsString "(" . sa a . showsString "," . sb b . showsString ")"--
src/Simplify.lhs view
@@ -24,17 +24,23 @@ > module Simplify(simplify) where -> import Control.Monad+> import Control.Monad.Reader as R+> import Control.Monad.State as S+> import qualified Data.Map as Map +> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax+> import Curry.Syntax.Utils++> import Types > import Base-> import Combined-> import Env > import SCC > import Typing -> type SimplifyState a = StateT ValueEnv (ReaderT EvalEnv (St Int)) a-> type InlineEnv = Env Ident Expression+> type SimplifyState a = S.StateT ValueEnv (ReaderT EvalEnv (S.State Int)) a+> type InlineEnv = Map.Map Ident Expression > type SimplifyFlags = Bool > flatFlag :: SimplifyFlags -> Bool@@ -42,13 +48,13 @@ > simplify :: SimplifyFlags -> ValueEnv -> EvalEnv -> Module -> (Module,ValueEnv) > simplify flags tyEnv evEnv m -> = runSt (callRt (callSt (simplifyModule flags m) tyEnv) evEnv) 1+> = S.evalState (R.runReaderT (S.evalStateT (simplifyModule flags m) tyEnv) evEnv) 1 > simplifyModule :: SimplifyFlags -> Module -> SimplifyState (Module,ValueEnv) > simplifyModule flat (Module m es ds) = > do-> ds' <- mapM (simplifyDecl flat m emptyEnv) ds-> tyEnv <- fetchSt+> ds' <- mapM (simplifyDecl flat m Map.empty) ds+> tyEnv <- S.get > return (Module m es ds',tyEnv) > simplifyDecl :: SimplifyFlags -> ModuleIdent -> InlineEnv -> Decl -> SimplifyState Decl@@ -135,22 +141,23 @@ > simplifyEquation flat m env (Equation p lhs rhs) = > do > rhs' <- simplifyRhs flat m env rhs-> tyEnv <- fetchSt-> evEnv <- liftSt envRt+> tyEnv <- S.get+> evEnv <- S.lift R.ask > return (inlineFun flat m tyEnv evEnv p lhs rhs') > inlineFun :: SimplifyFlags -> ModuleIdent -> ValueEnv -> EvalEnv -> Position -> Lhs -> Rhs > -> [Equation] > inlineFun flags m tyEnv evEnv p (FunLhs f ts) > (SimpleRhs _ (Let [FunctionDecl _ f' eqs'] e) _)-> | f' `notElem` qfv m eqs' && e' == Variable (qualify f') &&+> | True -- False -- inlining of functions is deactivated (hsi)+> && f' `notElem` qfv m eqs' && e' == Variable (qualify f') && > n == arrowArity (funType m tyEnv (qualify f')) && > (evMode evEnv f == evMode evEnv f' || > and [all isVarPattern ts | Equation _ (FunLhs _ ts) _ <- eqs']) =-> map (merge p f ts' vs') eqs'+> map (mergeEqns p f ts' vs') eqs' > where n :: Int -- type signature necessary for nhc > (n,vs',ts',e') = etaReduce 0 [] (reverse ts) e-> merge p f ts vs (Equation _ (FunLhs _ ts') rhs) =+> mergeEqns p f ts vs (Equation _ (FunLhs _ ts') rhs) = > Equation p (FunLhs f (ts ++ zipWith AsPattern vs ts')) rhs > etaReduce n vs (VariablePattern v : ts) (Apply e (Variable v')) > | qualify v == v' = etaReduce (n+1) (v:vs) ts e@@ -188,7 +195,7 @@ > simplifyExpr flat m env (Variable v) > | isQualified v = return (Variable v) > | otherwise = maybe (return (Variable v)) (simplifyExpr flat m env)-> (lookupEnv (unqualify v) env)+> (Map.lookup (unqualify v) env) > simplifyExpr _ _ _ (Constructor c) = return (Constructor c) > simplifyExpr flags m env (Apply (Let ds e1) e2) > = simplifyExpr flags m env (Let ds (Apply e1 e2))@@ -203,7 +210,7 @@ > return (Apply e1' e2') > simplifyExpr flags m env (Let ds e) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > dss' <- mapM (sharePatternRhs m tyEnv) ds > simplifyLet flags m env > (scc bv (qfv m) (foldr (hoistDecls flags) [] (concat dss'))) e@@ -251,7 +258,7 @@ > simplifyLet flags m env (ds:dss) e = > do > ds' <- mapM (simplifyDecl flags m env) ds-> tyEnv <- fetchSt+> tyEnv <- S.get > e' <- simplifyLet flags m (inlineVars flags m tyEnv ds' env) dss e > dss'' <- > mapM (expandPatternBindings flags m tyEnv (qfv m ds' ++ qfv m e')) ds'@@ -260,13 +267,15 @@ > inlineVars :: SimplifyFlags -> ModuleIdent -> ValueEnv -> [Decl] -> InlineEnv -> InlineEnv > inlineVars flags m tyEnv [PatternDecl _ (VariablePattern v) (SimpleRhs _ e _)] env-> | canInline e = bindEnv v e env-> where canInline (Literal _) = True-> canInline (Constructor _) = True-> canInline (Variable v')-> | isQualified v' = arrowArity (funType m tyEnv v') > 0-> | otherwise = v /= unqualify v'-> canInline _ = False+> | canInline e = Map.insert v e env+> where+> canInline (Literal _) = True+> canInline (Constructor _) = True+> canInline _ = False -- inlining of variables is deactivated (hsi)+> canInline (Variable v')+> | isQualified v' = arrowArity (funType m tyEnv v') > 0+> | otherwise = v /= unqualify v'+> canInline _ = False > inlineVars _ _ _ _ env = env > mkLet :: SimplifyFlags -> ModuleIdent -> [Decl] -> Expression -> Expression@@ -431,14 +440,14 @@ > _ -> internalError ("funType " ++ show f) > evMode :: EvalEnv -> Ident -> Maybe EvalAnnotation-> evMode evEnv f = lookupEnv f evEnv+> evMode evEnv f = Map.lookup f evEnv > freshIdent :: ModuleIdent -> (Int -> Ident) -> TypeScheme > -> SimplifyState Ident > freshIdent m f ty = > do-> x <- liftM f (liftSt (liftRt (updateSt (1 +))))-> updateSt_ (bindFun m x ty)+> x <- liftM f (S.lift (R.lift ( S.modify succ >> S.get)))+> S.modify (bindFun m x ty) > return x > shuffle :: [a] -> [[a]]
src/SyntaxCheck.lhs view
@@ -24,12 +24,16 @@ > import Data.Maybe > import Data.List-> import Control.Monad+> import qualified Data.Map as Map+> import Control.Monad.State as S +> import Curry.Syntax+> import Curry.Syntax.Utils+> import Types+> import Curry.Base.Position+> import Curry.Base.Ident > import Base-> import Env > import NestEnv-> import Combined > import Utils \end{verbatim}@@ -44,8 +48,7 @@ addition, this process will also rename the local variables. \begin{verbatim} -> syntaxCheck :: Bool -> ModuleIdent -> ImportEnv -> ArityEnv -> ValueEnv -> -> TCEnv -> [Decl] -> [Decl]+> syntaxCheck :: Bool -> ModuleIdent -> ImportEnv -> ArityEnv -> ValueEnv -> TCEnv -> [Decl] -> [Decl] > syntaxCheck withExt m iEnv aEnv tyEnv tcEnv ds = > case linear (concatMap constrs tds) of > --Linear -> tds ++ run (checkModule withExt m env vds)@@ -59,22 +62,18 @@ > tds' > env2 = foldr (bindTypes m) env1 rs -> --syntaxCheckGoal :: Bool -> ValueEnv -> Goal -> Goal-> --syntaxCheckGoal withExt tyEnv g =-> -- run (checkGoal withExt (mkMIdent []) (globalEnv (fmap renameInfo tyEnv)) g)- \end{verbatim} A global state transformer is used for generating fresh integer keys by which the variables get renamed. \begin{verbatim} -> type RenameState a = St Int a+> type RenameState a = S.State Int a > run :: RenameState a -> a-> run m = runSt m (globalKey + 1)+> run m = S.evalState m (globalKey + 1) > newId :: RenameState Int-> newId = updateSt (1 +)+> newId = S.modify succ >> S.get \end{verbatim} \ToDo{Probably the state transformer should use an \texttt{Integer} @@ -113,7 +112,7 @@ > renameInfo tcEnv iEnv aEnv (NewtypeConstructor _ _) > = Constr 1 > renameInfo tcEnv iEnv aEnv (Value qid _)-> = let (mmid, id) = splitQualIdent qid+> = let (mmid, id) = (qualidMod qid, qualidId qid) > qid' = maybe qid > (\mid -> maybe qid > (\mid' -> qualifyWith mid' id)@@ -234,7 +233,7 @@ > | (isJust mmid) && ((fromJust mmid) == preludeMIdent) && (ident == consId) > = qualLookupNestEnv (qualify ident) env > | otherwise = []-> where (mmid, ident) = splitQualIdent v+> where (mmid, ident) = (qualidMod v, qualidId v) > lookupTupleConstr :: Ident -> [RenameInfo] > lookupTupleConstr v@@ -256,13 +255,6 @@ > checkTopDecls withExt m env ds = > checkDeclGroup (bindFuncDecl m) withExt m globalKey env ds -> --checkGoal :: Bool -> ModuleIdent -> RenameEnv -> Goal -> RenameState Goal-> --checkGoal withExt m env (Goal p e ds) =-> -- do-> -- (env',ds') <- checkLocalDecls withExt m env ds-> -- e' <- checkExpr withExt p m env' e-> -- return (Goal p e' ds')- > checkTypeDecl :: Bool -> ModuleIdent -> Decl -> Decl > checkTypeDecl withExt m d@(TypeDecl p r tvs (RecordType fs rty)) > | not withExt = errorAt (positionOfIdent r) noRecordExt@@ -370,7 +362,7 @@ > | isJust m || isDataConstr op' env = > checkOpLhs k env (f . InfixPattern t1 op) t2 > | otherwise = Left (op'',OpLhs (f t1) op'' t2)-> where (m,op') = splitQualIdent op+> where (m,op') = (qualidMod op, qualidId op) > op'' = renameIdent op' k > checkOpLhs _ _ f t = Right (f t) @@ -591,8 +583,7 @@ > checkConstrTerm withExt k p m env (RecordPattern fs t) > | not withExt = errorAt p noRecordExt > | not (null fs) =-> let (Field _ label patt) = head fs-> p' = positionOfIdent label+> let (Field _ label _) = head fs > in case (lookupVar label env) of > [] -> errorAt' (undefinedLabel label) > [RecordLabel r ls]@@ -741,7 +732,7 @@ > checkExpr withExt p m env (RecordConstr fs) > | not withExt = errorAt p noRecordExt > | not (null fs) = -> let (Field _ label expr) = head fs+> let (Field _ label _) = head fs > in case (lookupVar label env) of > [] -> errorAt' (undefinedLabel label) > [RecordLabel r ls]@@ -772,7 +763,7 @@ > checkExpr withExt p m env (RecordUpdate fs e) > | not withExt = errorAt p noRecordExt > | not (null fs) =-> let (Field _ label expr) = head fs+> let (Field _ label _) = head fs > in case (lookupVar label env) of > [] -> errorAt' (undefinedLabel label) > [RecordLabel r ls]@@ -868,16 +859,16 @@ it is necessary to sort the list of declarations. > sortFuncDecls :: [Decl] -> [Decl]-> sortFuncDecls decls = sortFD emptyEnv [] decls+> sortFuncDecls decls = sortFD Map.empty [] decls > where > sortFD env res [] = reverse res > sortFD env res (decl:decls) > = case decl of > FunctionDecl _ ident _-> | isJust (lookupEnv ident env)+> | isJust (Map.lookup ident env) > -> sortFD env (insertBy cmpFuncDecl decl res) decls > | otherwise-> -> sortFD (bindEnv ident () env) (decl:res) decls+> -> sortFD (Map.insert ident () env) (decl:res) decls > _ -> sortFD env (decl:res) decls > cmpFuncDecl :: Decl -> Decl -> Ordering@@ -886,26 +877,13 @@ > | otherwise = GT > cmpFuncDecl decl1 decl2 = GT -> cmpPos :: Position -> Position -> Ordering-> cmpPos p1 p2 | lp1 < lp2 = LT-> | lp1 == lp2 = EQ-> | otherwise = GT-> where lp1 = line p1-> lp2 = line p2+cmpPos :: Position -> Position -> Ordering+cmpPos p1 p2 | lp1 < lp2 = LT+ | lp1 == lp2 = EQ+ | otherwise = GT+ where lp1 = line p1+ lp2 = line p2 -> getDeclPos :: Decl -> Position-> getDeclPos (ImportDecl pos _ _ _ _) = pos-> getDeclPos (InfixDecl pos _ _ _) = pos-> getDeclPos (DataDecl pos _ _ _) = pos-> getDeclPos (NewtypeDecl pos _ _ _) = pos-> getDeclPos (TypeDecl pos _ _ _) = pos-> getDeclPos (TypeSig pos _ _) = pos-> getDeclPos (EvalAnnot pos _ _) = pos-> getDeclPos (FunctionDecl pos _ _) = pos-> getDeclPos (ExternalDecl pos _ _ _ _) = pos-> getDeclPos (FlatExternalDecl pos _) = pos-> getDeclPos (PatternDecl pos _ _) = pos-> getDeclPos (ExtraVariables pos _) = pos \end{verbatim} Due to the lack of a capitalization convention in Curry, it is@@ -1106,18 +1084,6 @@ > where arguments 0 = "no arguments" > arguments 1 = "1 argument" > arguments n = show n ++ " arguments"--> --partialFuncPatt :: QualIdent -> Int -> Int -> String-> --partialFuncPatt f arity argc =-> -- "Function pattern " ++ qualName f ++ " expects at least " -> -- ++ arguments arity ++ " but is applied to " ++ show argc-> -- where arguments 0 = "no arguments"-> -- arguments 1 = "1 argument"-> -- arguments n = show n ++ " arguments"--> noExpressionStatement :: String-> noExpressionStatement =-> "Last statement in a do expression must be an expression" > illegalRecordPatt :: String > illegalRecordPatt = "Expexting `_` after `|` in the record pattern"
src/SyntaxColoring.hs view
@@ -1,24 +1,24 @@ module SyntaxColoring (Program,Code(..),TypeKind(..),ConstructorKind(..),- IdentifierKind(..),FunctionKind(..),filename2program,+ IdentifierKind(..),FunctionKind(..), genProgram, code2string,getQualIdent, position2code, area2codes) where import Debug.Trace+import Data.Function(on) import Data.Maybe+import Data.Either import Data.List--import CurryLexer-import Position-import Frontend-import Ident-import CurrySyntax import Data.Char hiding(Space)-import Message-import Control.Exception-import PathUtils (readModule) +import Curry.Base.Position+import Curry.Base.Ident+import Curry.Base.MessageMonad+import Curry.Syntax +import Curry.Syntax.Lexer ++ debug = False -- mergen von Token und Codes trace' s x = if debug then trace s x else x@@ -28,10 +28,6 @@ trace'' s x = if debug' then trace s x else x -debug'' = False -- parseResults und codes--trace''' s x = if debug'' then trace s x else x- type Program = [(Int,Int,Code)] data Code = Keyword String@@ -47,9 +43,9 @@ | CharCode String | Symbol String | Identifier IdentifierKind QualIdent- | CodeWarning [Message] Code- | CodeError [Message] Code- | NotParsed String deriving Show+ | CodeWarning [WarnMsg] Code+ | NotParsed String+ deriving Show data TypeKind = TypeDecla | TypeUse@@ -71,50 +67,21 @@ | OtherFunctionKind deriving Show - ---- @param importpaths---- @param filename ---- @return program-filename2program :: [String] -> String -> IO Program-filename2program paths filename=- readModule filename >>= \ cont ->- (catchError show (typingParse paths filename cont)) >>= \ typingParseResult ->- (catchError show (fullParse paths filename cont)) >>= \ fullParseResult -> - (catchError show (return (parse filename cont))) >>= \ parseResult ->- (catchError show (return (Frontend.lex filename cont))) >>= \ lexResult -> - return (genProgram cont (typingParseResult : fullParseResult : [parseResult]) lexResult) - - --- @param plaintext --- @param list with parse-Results with descending quality e.g. [typingParse,fullParse,parse] --- @param lex-Result --- @return program-genProgram :: String -> [Result Module] -> Result [(Position,Token)] -> Program -genProgram _ parseResults (Result mess posNtokList) = - let messages = (prepareMessages - (concatMap getMessages parseResults ++ - mess))- mergedMessages = (mergeMessages' (trace' ("Messages: " ++ show messages) messages) - posNtokList)- (nameList,codes) = catIdentifiers parseResults in- trace''' ("parseResults : " ++ show parseResults ++ "\n\nCodes: " ++ show codes ++ "\n\nToken: " ++ show mergedMessages)- (tokenNcodes2codes- nameList- 1 - 1- mergedMessages - codes) -- -genProgram plainText parseResults (Failure messages) =- trace' (unlines (map (\(Message _ _ str) -> str) allMessages)) - (buildMessagesIntoPlainText allMessages plainText) - where- allMessages = prepareMessages (concatMap getMessages parseResults ++ - messages) - +genProgram :: String -> [MsgMonad Module] -> MsgMonad [(Position,Token)] -> Program +genProgram plainText parseResults m+ = case runMsg m of+ (Left e, msgs) -> buildMessagesIntoPlainText (e : msgs) plainText+ (Right posNtokList, mess) + -> let messages = (prepareMessages (concatMap getMessages parseResults ++ mess))+ mergedMessages = (mergeMessages' (trace' ("Messages: " ++ show messages) messages) posNtokList)+ (nameList,codes) = catIdentifiers parseResults+ in tokenNcodes2codes nameList 1 1 mergedMessages codes --- @param Program@@ -138,25 +105,9 @@ | otherwise = area2codes xs p1 p2 where posBegin = Position file l c noRef- posEnd = Position file l (c + (length (code2string code))) noRef- ----- this function intercepts errors and converts it to Messages ---- @param a show-function for (Result a) ---- @param a function that generates a (Result a)---- @return (Result a) without runtimeerrors -catchError :: (Result a -> String) -> IO (Result a) -> IO (Result a)-catchError toString toDo = Control.Exception.catch (toDo >>= returnComplete toString) handler - where - handler (ErrorCall str) = return (Failure [setMessagePosition (Message Error Nothing str)])- handler e = return (Failure [Message Error Nothing (show e)]) - - returnComplete :: (a -> String) -> a -> IO a- returnComplete toString a = f (toString a) (return a)- where- f [] r = r- f (_:xs) r = f xs r + posEnd = Position file l (c + length (code2string code)) noRef + --- @param code --- @return qualIdent if available getQualIdent :: Code -> Maybe QualIdent@@ -167,18 +118,12 @@ getQualIdent _ = Nothing --- privates------------------------------------------------------------------------------------- -codeWithoutPos :: (Int,Int,Code) -> Code-codeWithoutPos (_,_,c) = c - -- DEBUGGING----------- wird bald nicht mehr gebraucht -setMessagePosition :: Message -> Message-setMessagePosition m@(Message _ (Just p) _) = trace'' ("pos:" ++ show p ++ ":" ++ show m) m-setMessagePosition (Message typ _ m) = - let mes@(Message _ pos _) = (Message typ (getPositionFromString m) m) in+setMessagePosition :: WarnMsg -> WarnMsg+setMessagePosition m@(WarnMsg (Just p) _) = trace'' ("pos:" ++ show p ++ ":" ++ show m) m+setMessagePosition (WarnMsg _ m) = + let mes@(WarnMsg pos _) = (WarnMsg (getPositionFromString m) m) in trace'' ("pos:" ++ show pos ++ ":" ++ show mes) mes getPositionFromString :: String -> Maybe Position@@ -208,7 +153,6 @@ flatCode :: Code -> Code flatCode (CodeWarning _ code) = code-flatCode (CodeError _ code) = code flatCode code = code @@ -216,31 +160,28 @@ -- ----------Message--------------------------------------- -getMessages :: Result a -> [Message]-getMessages (Result mess _) = mess-getMessages (Failure mess) = mess+getMessages :: MsgMonad a -> [WarnMsg]+getMessages = snd . runMsg --(Result mess _) = mess+-- getMessages (Failure mess) = mess -lessMessage :: Message -> Message -> Bool-lessMessage (Message _ mPos1 _) (Message _ mPos2 _) = mPos1 < mPos2+lessMessage :: WarnMsg -> WarnMsg -> Bool+lessMessage (WarnMsg mPos1 _) (WarnMsg mPos2 _) = mPos1 < mPos2 -nubMessages :: [Message] -> [Message] +nubMessages :: [WarnMsg] -> [WarnMsg] nubMessages = nubBy eqMessage -eqMessage :: Message -> Message -> Bool-eqMessage (Message f1 p1 s1) (Message f2 p2 s2) = (f1 == f2) && (p1 == p2) && (s1 == s2)+eqMessage :: WarnMsg -> WarnMsg -> Bool+eqMessage (WarnMsg p1 s1) (WarnMsg p2 s2) = (p1 == p2) && (s1 == s2) -prepareMessages :: [Message] -> [Message] +prepareMessages :: [WarnMsg] -> [WarnMsg] prepareMessages = qsort lessMessage . map setMessagePosition . nubMessages -hasError [] = False-hasError ((Message Error _ _):ms) = True-hasError (_:ms) = hasError ms -buildMessagesIntoPlainText :: [Message] -> String -> Program+buildMessagesIntoPlainText :: [WarnMsg] -> String -> Program buildMessagesIntoPlainText messages text = buildMessagesIntoPlainText' messages (lines text) [] 1 where- buildMessagesIntoPlainText' :: [Message] -> [String] -> [String] -> Int -> Program+ buildMessagesIntoPlainText' :: [WarnMsg] -> [String] -> [String] -> Int -> Program buildMessagesIntoPlainText' _ [] [] _ = [] buildMessagesIntoPlainText' _ [] postStrs line = @@ -253,11 +194,11 @@ if null pre then buildMessagesIntoPlainText' post preStrs (postStrs ++ [str]) (ln + 1) else (ln,1,NotParsed (unlines postStrs)) : - (if hasError pre then (ln,1,CodeError pre (NotParsed str)) : [(ln,1,NewLine)] - else (ln,1,CodeWarning pre (NotParsed str)) : [(ln,1,NewLine)]) ++- (buildMessagesIntoPlainText' post preStrs [] (ln + 1)) + (ln,1,CodeWarning pre (NotParsed str)) :+ (ln,1,NewLine) :+ buildMessagesIntoPlainText' post preStrs [] (ln + 1) where - isLeq (Message _ (Just p) _) = line p <= ln + isLeq (WarnMsg (Just p) _) = line p <= ln isLeq _ = True @@ -265,19 +206,19 @@ --- @param parse-Modules [typingParse,fullParse,parse] -catIdentifiers :: [Result Module] -> ([(ModuleIdent,ModuleIdent)],[Code])-catIdentifiers [] = ([],[])-catIdentifiers [(Failure _)] = ([],[])-catIdentifiers [(Result _ m@(Module moduleIdent maybeExportSpec decls))] =- catIdentifiers' m Nothing-catIdentifiers ((Failure _):y:ys) = - catIdentifiers (y:ys) -catIdentifiers rs@((Result _ m@(Module _ _ _)):y:ys) = - catIdentifiers' (getLastModule (reverse rs)) (Just m)- where- getLastModule ((Failure _):xs) = getLastModule xs- getLastModule ((Result _ m@(Module _ _ _)):_) = m+catIdentifiers :: [MsgMonad Module] -> ([(ModuleIdent,ModuleIdent)],[Code])+catIdentifiers = catIds . rights . map (fst . runMsg)+ where + catIds [] = ([],[])+ catIds [m] =+ catIdentifiers' m Nothing+ catIds rs@(m:y:ys) = + catIdentifiers' (last rs) (Just m) +-- not in base befoer base4++rights xs = [ x | Right x <- xs]+ --- @param parse-Module --- @param Maybe betterParse-Module catIdentifiers' :: Module -> Maybe Module -> ([(ModuleIdent,ModuleIdent)],[Code])@@ -285,19 +226,18 @@ Nothing = let codes = (concatMap decl2codes (qsort lessDecl decls)) in (concatMap renamedImports decls, - ([ModuleName moduleIdent] ++- (maybe [] exportSpec2codes maybeExportSpec) ++- codes)) + ModuleName moduleIdent :+ maybe [] exportSpec2codes maybeExportSpec ++ codes) catIdentifiers' (Module moduleIdent maybeExportSpec1 _) (Just (Module _ maybeExportSpec2 decls)) = let codes = (concatMap decl2codes (qsort lessDecl decls)) in (concatMap renamedImports decls, replaceFunctionCalls $ - map (addModuleIdent moduleIdent) $+ map (addModuleIdent moduleIdent) ([ModuleName moduleIdent] ++- (mergeExports2codes + mergeExports2codes (maybe [] (\(Exporting _ i) -> i) maybeExportSpec1)- (maybe [] (\(Exporting _ i) -> i) maybeExportSpec2)) +++ (maybe [] (\(Exporting _ i) -> i) maybeExportSpec2) ++ codes)) @@ -325,55 +265,46 @@ idOccur2functionCall :: [QualIdent] -> Code -> Code idOccur2functionCall qualIdents ide@(Identifier IdOccur qualIdent) - | isQualified qualIdent = (Function FunctionCall qualIdent)- | elem qualIdent qualIdents = (Function FunctionCall qualIdent)+ | isQualified qualIdent = Function FunctionCall qualIdent+ | elem qualIdent qualIdents = Function FunctionCall qualIdent | otherwise = ide idOccur2functionCall qualIdents (CodeWarning mess code) =- (CodeWarning mess (idOccur2functionCall qualIdents code))-idOccur2functionCall qualIdents (CodeError mess code) =- (CodeError mess (idOccur2functionCall qualIdents code)) + CodeWarning mess (idOccur2functionCall qualIdents code) idOccur2functionCall _ code = code addModuleIdent :: ModuleIdent -> Code -> Code-addModuleIdent moduleIdent (Function x qualIdent) +addModuleIdent moduleIdent c@(Function x qualIdent) | uniqueId (unqualify qualIdent) == 0 =- (Function x (qualQualify moduleIdent qualIdent))- | otherwise = (Function x qualIdent) + Function x (qualQualify moduleIdent qualIdent)+ | otherwise = c addModuleIdent moduleIdent cn@(ConstructorName x qualIdent) | not $ isQualified qualIdent =- (ConstructorName x (qualQualify moduleIdent qualIdent)) + ConstructorName x (qualQualify moduleIdent qualIdent) | otherwise = cn addModuleIdent moduleIdent tc@(TypeConstructor TypeDecla qualIdent) | not $ isQualified qualIdent =- (TypeConstructor TypeDecla (qualQualify moduleIdent qualIdent)) + TypeConstructor TypeDecla (qualQualify moduleIdent qualIdent) | otherwise = tc addModuleIdent moduleIdent (CodeWarning mess code) =- (CodeWarning mess (addModuleIdent moduleIdent code)) -addModuleIdent moduleIdent (CodeError mess code) =- (CodeError mess (addModuleIdent moduleIdent code)) + CodeWarning mess (addModuleIdent moduleIdent code) addModuleIdent _ c = c -- ---------------------------------------- -mergeMessages :: [Message] -> [(Position,Token)] -> [([Message],Position,Token)]-mergeMessages mess pos = mergeMessages' (prepareMessages mess) pos----mergeMessages' :: [Message] -> [(Position,Token)] -> [([Message],Position,Token)]+mergeMessages' :: [WarnMsg] -> [(Position,Token)] -> [([WarnMsg],Position,Token)] mergeMessages' _ [] = [] mergeMessages' [] ((p,t):ps) = ([],p,t) : mergeMessages' [] ps-mergeMessages' mss@(m@(Message _ mPos x):ms) ((p,t):ps) - | mPos <= Just p = (trace' (show mPos ++ " <= " ++ show (Just p) ++ " Message: " ++ x) ([m],p,t)) : mergeMessages' ms ps +mergeMessages' mss@(m@(WarnMsg mPos x):ms) ((p,t):ps) + | mPos <= Just p = trace' (show mPos ++ " <= " ++ show (Just p) ++ " Message: " ++ x) ([m],p,t) : mergeMessages' ms ps | otherwise = ([],p,t) : mergeMessages' mss ps -tokenNcodes2codes :: [(ModuleIdent,ModuleIdent)] -> Int -> Int -> [([Message],Position,Token)] -> [Code] -> [(Int,Int,Code)]+tokenNcodes2codes :: [(ModuleIdent,ModuleIdent)] -> Int -> Int -> [([WarnMsg],Position,Token)] -> [Code] -> [(Int,Int,Code)] tokenNcodes2codes _ _ _ [] _ = [] tokenNcodes2codes nameList currLine currCol toks@((messages,pos@Position{line=line,column=col},token):ts) codes | currLine < line = - trace' (" NewLine: ")+ trace' " NewLine: " ((currLine,currCol,NewLine) : tokenNcodes2codes nameList (currLine + 1) 1 toks codes) | currCol < col = @@ -419,14 +350,11 @@ newLine = (currLine + length (lines tokenStr)) - 1 newCol = currCol + length tokenStr - rename mid = Just $ maybe mid id (lookup mid nameList)+ rename mid = Just $ fromMaybe mid (lookup mid nameList) addMessage [] = [] addMessage ((l,c,code):cs)- | null messages = ((l,c,code):cs)- | hasError messages = - trace' ("Error bei code: " ++ show codes ++ ":" ++ show messages) - ((l,c,CodeError messages code): addMessage cs)+ | null messages = (l,c,code):cs | otherwise = trace' ("Warning bei code: " ++ show codes ++ ":" ++ show messages) ((l,c,CodeWarning messages code): addMessage cs) @@ -434,12 +362,12 @@ renameModuleIdents :: [(ModuleIdent,ModuleIdent)] -> Code -> Code renameModuleIdents nameList c = case c of- Function x qualIdent -> Function x (rename qualIdent (splitQualIdent qualIdent))- Identifier x qualIdent -> Identifier x (rename qualIdent (splitQualIdent qualIdent))+ Function x qualIdent -> Function x (rename qualIdent (qualidMod qualIdent))+ Identifier x qualIdent -> Identifier x (rename qualIdent (qualidMod qualIdent)) _ -> c where- rename x (Nothing,_) = x- rename x (Just m,i) = maybe x (\ m' -> qualifyWith m' i) (lookup m nameList)+ rename x (Nothing) = x+ rename x (Just m) = maybe x (\ m' -> qualifyWith m' (qualidId x)) (lookup m nameList) {- codeWithoutUniqueID :: Code -> String@@ -454,11 +382,11 @@ codeQualifiers = maybe [] moduleQualifiers . getModuleIdent getModuleIdent :: Code -> Maybe ModuleIdent-getModuleIdent (ConstructorName _ qualIdent) = fst $ splitQualIdent qualIdent-getModuleIdent (Function _ qualIdent) = fst $ splitQualIdent qualIdent+getModuleIdent (ConstructorName _ qualIdent) = qualidMod qualIdent+getModuleIdent (Function _ qualIdent) = qualidMod qualIdent getModuleIdent (ModuleName moduleIdent) = Just moduleIdent-getModuleIdent (Identifier _ qualIdent) = fst $ splitQualIdent qualIdent -getModuleIdent (TypeConstructor _ qualIdent) = fst $ splitQualIdent qualIdent+getModuleIdent (Identifier _ qualIdent) = qualidMod qualIdent +getModuleIdent (TypeConstructor _ qualIdent) = qualidMod qualIdent getModuleIdent _ = Nothing @@ -551,7 +479,7 @@ lessDecl :: Decl -> Decl -> Bool-lessDecl decl1 decl2 = getPosition decl1 < getPosition decl2+lessDecl = (<) `on` getPosition qsort _ [] = [] qsort less (x:xs) = qsort less [y | y <- xs, less y x] ++ [x] ++ qsort less [y | y <- xs, not $ less y x]@@ -598,7 +526,7 @@ export2codes _ (ExportTypeWith qualIdent idents) = - [TypeConstructor TypeExport qualIdent] ++ map (Function OtherFunctionKind . qualify) idents+ TypeConstructor TypeExport qualIdent : map (Function OtherFunctionKind . qualify) idents export2codes _ (ExportTypeAll qualIdent) = [TypeConstructor TypeExport qualIdent] export2codes _ (ExportModule moduleIdent) = @@ -610,9 +538,9 @@ maybe [] ((:[]) . ModuleName) mModuleIdent ++ maybe [] (importSpec2codes moduleIdent) importSpec decl2codes (InfixDecl _ _ _ idents) =- (map (Function InfixFunction . qualify) idents) + map (Function InfixFunction . qualify) idents decl2codes (DataDecl _ ident idents constrDecls) =- [TypeConstructor TypeDecla (qualify ident)] ++ + TypeConstructor TypeDecla (qualify ident) : map (Identifier UnknownId . qualify) idents ++ concatMap constrDecl2codes constrDecls decl2codes (NewtypeDecl xPosition xIdent yIdents xNewConstrDecl) =@@ -642,7 +570,7 @@ lhs2codes :: Lhs -> [Code] lhs2codes (FunLhs ident constrTerms) =- (Function FunDecl $ qualify ident) : concatMap constrTerm2codes constrTerms+ Function FunDecl (qualify ident) : concatMap constrTerm2codes constrTerms lhs2codes (OpLhs constrTerm1 ident constrTerm2) = constrTerm2codes constrTerm1 ++ [Function FunDecl $ qualify ident] ++ constrTerm2codes constrTerm2 lhs2codes (ApLhs lhs constrTerms) =@@ -663,17 +591,17 @@ constrTerm2codes (NegativePattern ident literal) = [] constrTerm2codes (VariablePattern ident) = [Identifier IdDecl (qualify ident)] constrTerm2codes (ConstructorPattern qualIdent constrTerms) =- (ConstructorName ConstrPattern qualIdent) : concatMap constrTerm2codes constrTerms+ ConstructorName ConstrPattern qualIdent : concatMap constrTerm2codes constrTerms constrTerm2codes (InfixPattern constrTerm1 qualIdent constrTerm2) = constrTerm2codes constrTerm1 ++ [ConstructorName ConstrPattern qualIdent] ++ constrTerm2codes constrTerm2 constrTerm2codes (ParenPattern constrTerm) = constrTerm2codes constrTerm constrTerm2codes (TuplePattern _ constrTerms) = concatMap constrTerm2codes constrTerms constrTerm2codes (ListPattern _ constrTerms) = concatMap constrTerm2codes constrTerms constrTerm2codes (AsPattern ident constrTerm) =- (Function OtherFunctionKind $ qualify ident) : constrTerm2codes constrTerm+ Function OtherFunctionKind (qualify ident) : constrTerm2codes constrTerm constrTerm2codes (LazyPattern _ constrTerm) = constrTerm2codes constrTerm constrTerm2codes (FunctionPattern qualIdent constrTerms) = - (Function OtherFunctionKind qualIdent) : concatMap constrTerm2codes constrTerms+ Function OtherFunctionKind qualIdent : concatMap constrTerm2codes constrTerms constrTerm2codes (InfixFuncPattern constrTerm1 qualIdent constrTerm2) = constrTerm2codes constrTerm1 ++ [Function InfixFunction qualIdent] ++ constrTerm2codes constrTerm2 @@ -704,7 +632,7 @@ expression2codes expression2 ++ expression2codes expression3 expression2codes (UnaryMinus ident expression) = - [Symbol (name ident)] ++ expression2codes expression + Symbol (name ident) : expression2codes expression expression2codes (Apply expression1 expression2) = expression2codes expression1 ++ expression2codes expression2 expression2codes (InfixApply expression1 infixOp expression2) = @@ -744,7 +672,7 @@ constrDecl2codes :: ConstrDecl -> [Code] constrDecl2codes (ConstrDecl _ idents ident typeExprs) =- (ConstructorName ConstrDecla $ qualify ident) : concatMap typeExpr2codes typeExprs+ ConstructorName ConstrDecla (qualify ident) : concatMap typeExpr2codes typeExprs constrDecl2codes (ConOpDecl _ idents typeExpr1 ident typeExpr2) = typeExpr2codes typeExpr1 ++ [ConstructorName ConstrDecla $ qualify ident] ++ typeExpr2codes typeExpr2 @@ -757,14 +685,14 @@ import2codes moduleIdent (Import ident) = [Function OtherFunctionKind $ qualifyWith moduleIdent ident] import2codes moduleIdent (ImportTypeWith ident idents) = - [ConstructorName OtherConstrKind $ qualifyWith moduleIdent ident] ++ + ConstructorName OtherConstrKind (qualifyWith moduleIdent ident) : map (Function OtherFunctionKind . qualifyWith moduleIdent) idents import2codes moduleIdent (ImportTypeAll ident) = [ConstructorName OtherConstrKind $ qualifyWith moduleIdent ident] typeExpr2codes :: TypeExpr -> [Code] typeExpr2codes (ConstructorType qualIdent typeExprs) = - (TypeConstructor TypeUse qualIdent) : concatMap typeExpr2codes typeExprs+ TypeConstructor TypeUse qualIdent : concatMap typeExpr2codes typeExprs typeExpr2codes (VariableType ident) = [Identifier IdOccur (qualify ident)] typeExpr2codes (TupleType typeExprs) = @@ -851,14 +779,13 @@ attributes2string (StringAttributes sval _) = showSt sval attributes2string (IdentAttributes mIdent ident) =concat (intersperse "." (mIdent ++ [ident])) -basename = reverse . takeWhile (/='/') . reverse showCh c | c == '\\' = "'\\\\'" | elem c ('\127' : ['\001' .. '\031']) = show c | otherwise = toString c where- toString c = "'" ++ c : "'"+ toString c = '\'' : c : "'" showSt = addQuotes . concatMap toGoodChar where@@ -870,4 +797,4 @@ | c == '"' = "\\\"" | otherwise = c : "" where- justShow = reverse . tail . reverse . tail . show+ justShow = init . tail . show
src/TopEnv.lhs view
@@ -41,10 +41,10 @@ > allImports,moduleImports,localBindings) where > import Data.Maybe+> import qualified Data.Map as Map+> import Control.Arrow(second)+> import Curry.Base.Ident -> import Env-> import Ident-> import Utils > data Source = Local | Import [ModuleIdent] deriving (Eq,Show) @@ -55,32 +55,32 @@ > | origName x == origName y = Just x > | otherwise = Nothing -> newtype TopEnv a = TopEnv (Env QualIdent [(Source,a)]) deriving Show+> newtype TopEnv a = TopEnv (Map.Map QualIdent [(Source,a)]) deriving Show > instance Functor TopEnv where-> fmap f (TopEnv env) = TopEnv (fmap (map (apSnd f)) env)+> fmap f (TopEnv env) = TopEnv (fmap (map (second f)) env) -> entities :: QualIdent -> Env QualIdent [(Source,a)] -> [(Source,a)]-> entities x env = fromMaybe [] (lookupEnv x env)+> entities :: QualIdent -> Map.Map QualIdent [(Source,a)] -> [(Source,a)]+> entities x env = fromMaybe [] (Map.lookup x env) > emptyTopEnv :: TopEnv a-> emptyTopEnv = TopEnv emptyEnv+> emptyTopEnv = TopEnv Map.empty > predefTopEnv :: Entity a => QualIdent -> a -> TopEnv a -> TopEnv a > predefTopEnv x y (TopEnv env) =-> case lookupEnv x env of+> case Map.lookup x env of > Just _ -> error "internal error: predefTopEnv"-> Nothing -> TopEnv (bindEnv x [(Import [],y)] env)+> Nothing -> TopEnv (Map.insert x [(Import [],y)] env) > importTopEnv :: Entity a => ModuleIdent -> Ident -> a -> TopEnv a -> TopEnv a > importTopEnv m x y (TopEnv env) =-> TopEnv (bindEnv x' (mergeImport m y (entities x' env)) env)+> TopEnv (Map.insert x' (mergeImport m y (entities x' env)) env) > where x' = qualify x > qualImportTopEnv :: Entity a => ModuleIdent -> Ident -> a -> TopEnv a > -> TopEnv a > qualImportTopEnv m x y (TopEnv env) =-> TopEnv (bindEnv x' (mergeImport m y (entities x' env)) env)+> TopEnv (Map.insert x' (mergeImport m y (entities x' env)) env) > where x' = qualifyWith m x > mergeImport :: Entity a => ModuleIdent -> a -> [(Source,a)] -> [(Source,a)]@@ -96,7 +96,7 @@ > qualBindTopEnv :: String -> QualIdent -> a -> TopEnv a -> TopEnv a > qualBindTopEnv fun x y (TopEnv env) =-> TopEnv (bindEnv x (bindLocal y (entities x env)) env)+> TopEnv (Map.insert x (bindLocal y (entities x env)) env) > where bindLocal y ys > | null [y' | (Local,y') <- ys] = (Local,y) : ys > | otherwise = error ("internal error: \"qualBindTopEnv " @@ -108,14 +108,14 @@ > qualRebindTopEnv :: QualIdent -> a -> TopEnv a -> TopEnv a > qualRebindTopEnv x y (TopEnv env) =-> TopEnv (bindEnv x (rebindLocal (entities x env)) env)+> TopEnv (Map.insert x (rebindLocal (entities x env)) env) > where rebindLocal [] = error "internal error: qualRebindTopEnv" > rebindLocal ((Local,_) : ys) = (Local,y) : ys > rebindLocal ((Import ms,y) : ys) = (Import ms,y) : rebindLocal ys > unbindTopEnv :: Ident -> TopEnv a -> TopEnv a > unbindTopEnv x (TopEnv env) =-> TopEnv (bindEnv x' (unbindLocal (entities x' env)) env)+> TopEnv (Map.insert x' (unbindLocal (entities x' env)) env) > where x' = qualify x > unbindLocal [] = error "internal error: unbindTopEnv" > unbindLocal ((Local,_) : ys) = ys@@ -129,11 +129,11 @@ > allImports :: TopEnv a -> [(QualIdent,a)] > allImports (TopEnv env) =-> [(x,y) | (x,ys) <- envToList env, (Import _,y) <- ys]+> [(x,y) | (x,ys) <- Map.toList env, (Import _,y) <- ys] > unqualBindings :: TopEnv a -> [(Ident,(Source,a))] > unqualBindings (TopEnv env) =-> [(x',y) | (x,ys) <- takeWhile (not . isQualified . fst) (envToList env),+> [(x',y) | (x,ys) <- takeWhile (not . isQualified . fst) (Map.toList env), > let x' = unqualify x, y <- ys] > moduleImports :: ModuleIdent -> TopEnv a -> [(Ident,a)]
src/TypeCheck.lhs view
@@ -21,21 +21,25 @@ type annotation is present. \begin{verbatim} -> module TypeCheck(typeCheck,typeCheckGoal) where+> module TypeCheck(typeCheck) where -> import Control.Monad+> import Control.Monad.State as S > import Data.List > import Data.Maybe+> import qualified Data.Map as Map > import qualified Data.Set as Set +> import Curry.Base.Position+> import Curry.Base.Ident+> import Curry.Syntax+> import Curry.Syntax.Pretty+> import Curry.Syntax.Utils++ > import Base-> import Pretty-> import Ident-> import CurryPP-> import Env+> import Types+> import PrettyCombinators > import TopEnv--> import Combined > import SCC > import TypeSubst > import Utils@@ -57,36 +61,24 @@ > typeCheck :: ModuleIdent -> TCEnv -> ValueEnv -> [Decl] -> (TCEnv,ValueEnv) > typeCheck m tcEnv tyEnv ds =-> run (tcDecls m tcEnv' emptyEnv vds >>-> liftSt fetchSt >>= \theta -> fetchSt >>= \tyEnv' ->+> run (tcDecls m tcEnv' Map.empty vds >>+> S.lift S.get >>= \theta -> S.get >>= \tyEnv' -> > return (tcEnv',subst theta tyEnv')) > (bindLabels m tcEnv' (bindConstrs m tcEnv' tyEnv)) > where (tds,vds) = partition isTypeDecl ds > tcEnv' = bindTypes m tds tcEnv \end{verbatim}-Type checking of a goal expression is simpler because the type-constructor environment is fixed already and there are no-type declarations in a goal.-\begin{verbatim} -> typeCheckGoal :: TCEnv -> ValueEnv -> Goal -> ValueEnv-> typeCheckGoal tcEnv tyEnv (Goal p e ds) =-> run (tcRhs m0 tcEnv tyEnv emptyEnv (SimpleRhs p e ds) >>-> liftSt fetchSt >>= \theta -> fetchSt >>= \tyEnv' ->-> return (subst theta tyEnv')) tyEnv-> where m0 = mkMIdent []--\end{verbatim} The type checker makes use of nested state monads in order to maintain the type environment, the current substitution, and a counter which is used for generating fresh type variables. \begin{verbatim} -> type TcState a = StateT ValueEnv (StateT TypeSubst (St Int)) a+> type TcState a = S.StateT ValueEnv (S.StateT TypeSubst (S.State Int)) a > run :: TcState a -> ValueEnv -> a-> run m tyEnv = runSt (callSt (callSt m tyEnv) idSubst) 0+> run m tyEnv = S.evalState (S.evalStateT (S.evalStateT m tyEnv) idSubst) 0 \end{verbatim} \paragraph{Defining Types}@@ -218,10 +210,10 @@ inferred type is less general than the signature. \begin{verbatim} -> type SigEnv = Env Ident TypeExpr+> type SigEnv = Map.Map Ident TypeExpr > bindTypeSig :: Ident -> TypeExpr -> SigEnv -> SigEnv-> bindTypeSig = bindEnv+> bindTypeSig = Map.insert > bindTypeSigs :: Decl -> SigEnv -> SigEnv > bindTypeSigs (TypeSig _ vs ty) env =@@ -229,7 +221,7 @@ > bindTypeSigs _ env = env > lookupTypeSig :: Ident -> SigEnv -> Maybe TypeExpr-> lookupTypeSig = lookupEnv+> lookupTypeSig = Map.lookup > qualLookupTypeSig :: ModuleIdent -> QualIdent -> SigEnv -> Maybe TypeExpr > qualLookupTypeSig m f sigs = localIdent m f >>= flip lookupTypeSig sigs@@ -259,8 +251,8 @@ > nameType (RecordType fs rty) tvs = > (RecordType (zip ls tys') (listToMaybe rty'), tvs) > where (ls, tys) = unzip fs-> (tys', tvs') = nameTypes tys tvs-> (rty', tvs'') = nameTypes (maybeToList rty) tvs+> (tys', _) = nameTypes tys tvs+> (rty', _) = nameTypes (maybeToList rty) tvs \end{verbatim} \paragraph{Type Inference}@@ -302,17 +294,17 @@ > mapM_ (tcExtraVar m tcEnv sigs ) vs > tcDeclGroup m tcEnv sigs ds = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > tysLhs <- mapM (tcDeclLhs m tcEnv sigs) ds > tysRhs <- mapM (tcDeclRhs m tcEnv tyEnv0 sigs) ds > sequence_ (zipWith3 (unifyDecl m) ds tysLhs tysRhs)-> theta <- liftSt fetchSt+> theta <- S.lift S.get > mapM_ (genDecl m tcEnv sigs (fvEnv (subst theta tyEnv0)) theta) ds > --tcForeignFunct :: ModuleIdent -> TCEnv -> Position -> CallConv -> Ident > -- -> TypeExpr -> TcState () > --tcForeignFunct m tcEnv p cc f ty =-> -- updateSt_ (bindFun m f (checkForeignType cc (expandPolyType tcEnv ty)))+> -- S.modify (bindFun m f (checkForeignType cc (expandPolyType tcEnv ty))) > -- where checkForeignType CallConvPrimitive ty = ty > -- checkForeignType CallConvCCall (ForAll n ty) = > -- ForAll n (checkCCallType ty)@@ -332,11 +324,11 @@ > tcExternalFunct :: ModuleIdent -> TCEnv -> Ident -> TypeExpr -> TcState () > tcExternalFunct m tcEnv f ty =-> updateSt_ (bindFun m f (expandPolyType m tcEnv ty))+> S.modify (bindFun m f (expandPolyType m tcEnv ty)) > tcFlatExternalFunct :: ModuleIdent -> TCEnv -> SigEnv -> Ident -> TcState () > tcFlatExternalFunct m tcEnv sigs f =-> typeOf f tcEnv sigs >>= updateSt_ . bindFun m f+> typeOf f tcEnv sigs >>= S.modify . bindFun m f > where typeOf f tcEnv sigs = > case lookupTypeSig f sigs of > Just ty -> return (expandPolyType m tcEnv ty)@@ -345,7 +337,7 @@ > tcExtraVar :: ModuleIdent -> TCEnv -> SigEnv -> Ident > -> TcState () > tcExtraVar m tcEnv sigs v =-> typeOf v tcEnv sigs >>= updateSt_ . bindFun m v . monoType+> typeOf v tcEnv sigs >>= S.modify . bindFun m v . monoType > where typeOf v tcEnv sigs = > case lookupTypeSig v sigs of > Just ty@@ -404,9 +396,9 @@ > genDecl :: ModuleIdent -> TCEnv -> SigEnv -> Set.Set Int -> TypeSubst -> Decl > -> TcState () > genDecl m tcEnv sigs lvs theta (FunctionDecl _ f _) =-> updateSt_ (genVar True m tcEnv sigs lvs theta f)+> S.modify (genVar True m tcEnv sigs lvs theta f) > genDecl m tcEnv sigs lvs theta (PatternDecl p t _) =-> mapM_ (updateSt_ . genVar False m tcEnv sigs lvs theta ) (bv t)+> mapM_ (S.modify . genVar False m tcEnv sigs lvs theta ) (bv t) > genVar :: Bool -> ModuleIdent -> TCEnv -> SigEnv -> Set.Set Int -> TypeSubst > -> Ident -> ValueEnv -> ValueEnv@@ -442,7 +434,7 @@ > tcLiteral m (Int v _) = --return intType > do > ty <- freshConstrained [intType,floatType]-> updateSt_ (bindFun m v (monoType ty))+> S.modify (bindFun m v (monoType ty)) > return ty > tcLiteral _ (Float _ _) = return floatType > tcLiteral _ (String _ _) = return stringType@@ -456,12 +448,12 @@ > ty <- case lookupTypeSig v sigs of > Just t -> inst (expandPolyType m tcEnv t) > Nothing -> freshTypeVar-> updateSt_ (bindFun m v (monoType ty))+> S.modify (bindFun m v (monoType ty)) > return ty > > tcConstrTerm m tcEnv sigs p t@(ConstructorPattern c ts) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- skol (constrType m c tyEnv) > unifyArgs (ppConstrTerm 0 t) ts ty > where unifyArgs _ [] ty = return ty@@ -473,7 +465,7 @@ > unifyArgs _ _ _ = internalError "tcConstrTerm" > tcConstrTerm m tcEnv sigs p t@(InfixPattern t1 op t2) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- skol (constrType m op tyEnv) > unifyArgs (ppConstrTerm 0 t) [t1,t2] ty > where unifyArgs _ [] ty = return ty@@ -504,7 +496,7 @@ > tcConstrTerm m tcEnv sigs p (LazyPattern _ t) = tcConstrTerm m tcEnv sigs p t > tcConstrTerm m tcEnv sigs p t@(FunctionPattern f ts) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- inst (funType m f tyEnv) --skol (constrType m c tyEnv) > unifyArgs (ppConstrTerm 0 t) ts ty > where unifyArgs _ [] ty = return ty@@ -553,14 +545,14 @@ > ty <- maybe freshTypeVar > (inst . expandPolyType m tcEnv) > (lookupTypeSig v sigs)-> tyEnv <- fetchSt-> ty' <- maybe (updateSt_ (bindFun m v (monoType ty)) >> return ty)+> tyEnv <- S.get+> ty' <- maybe (S.modify (bindFun m v (monoType ty)) >> return ty) > (\ (ForAll _ t) -> return t) > (sureVarType v tyEnv) > return ty' > tcConstrTermFP m tcEnv sigs p t@(ConstructorPattern c ts) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- skol (constrType m c tyEnv) > unifyArgs (ppConstrTerm 0 t) ts ty > where unifyArgs _ [] ty = return ty@@ -572,7 +564,7 @@ > unifyArgs _ _ _ = internalError "tcConstrTermFP" > tcConstrTermFP m tcEnv sigs p t@(InfixPattern t1 op t2) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- skol (constrType m op tyEnv) > unifyArgs (ppConstrTerm 0 t) [t1,t2] ty > where unifyArgs _ [] ty = return ty@@ -603,7 +595,7 @@ > tcConstrTermFP m tcEnv sigs p (LazyPattern _ t) = tcConstrTermFP m tcEnv sigs p t > tcConstrTermFP m tcEnv sigs p t@(FunctionPattern f ts) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > ty <- inst (funType m f tyEnv) --skol (constrType m c tyEnv) > unifyArgs (ppConstrTerm 0 t) ts ty > where unifyArgs _ [] ty = return ty@@ -640,11 +632,11 @@ > -> Field ConstrTerm -> TcState (Ident,Type) > tcFieldPatt tcPatt m f@(Field _ l t) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > let p = positionOfIdent l > lty <- maybe (freshTypeVar > >>= (\lty' ->-> updateSt_+> S.modify > (bindLabel l (qualifyWith m (mkIdent "#Rec")) > (polyType lty')) > >> return lty'))@@ -689,15 +681,15 @@ > tcExpr m tcEnv sigs p (Variable v) = > case qualLookupTypeSig m v sigs of > Just ty -> inst (expandPolyType m tcEnv ty)-> Nothing -> fetchSt >>= inst . funType m v-> tcExpr m tcEnv sigs p (Constructor c) = fetchSt >>= instExist . constrType m c+> Nothing -> S.get >>= inst . funType m v+> tcExpr m tcEnv sigs p (Constructor c) = S.get >>= instExist . constrType m c > tcExpr m tcEnv sigs p (Typed e sig) = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > ty <- tcExpr m tcEnv sigs p e > inst sigma' >>= > flip (unify p "explicitly typed expression" (ppExpr 0 e) m) ty-> theta <- liftSt fetchSt+> theta <- S.lift S.get > let sigma = gen (fvEnv (subst theta tyEnv0)) (subst theta ty) > unless (sigma == sigma') > (errorAt p (typeSigTooGeneral m (text "Expression:" <+> ppExpr 0 e)@@ -718,7 +710,7 @@ > tcElems doc es ty > tcExpr m tcEnv sigs p (ListCompr _ e qs) = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > mapM_ (tcQual m tcEnv sigs p) qs > ty <- tcExpr m tcEnv sigs p e > checkSkolems p m (text "Expression:" <+> ppExpr 0 e) tyEnv0 (listType ty)@@ -814,21 +806,21 @@ > return (TypeArrow alpha gamma) > tcExpr m tcEnv sigs p exp@(Lambda r ts e) = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > tys <- mapM (tcConstrTerm m tcEnv sigs p) ts > ty <- tcExpr m tcEnv sigs p e > checkSkolems p m (text "Expression:" <+> ppExpr 0 exp) tyEnv0 > (foldr TypeArrow ty tys) > tcExpr m tcEnv sigs p (Let ds e) = > do-> tyEnv0 <- fetchSt-> theta <- liftSt fetchSt+> tyEnv0 <- S.get+> theta <- S.lift S.get > tcDecls m tcEnv sigs ds > ty <- tcExpr m tcEnv sigs p e > checkSkolems p m (text "Expression:" <+> ppExpr 0 e) tyEnv0 ty > tcExpr m tcEnv sigs p (Do sts e) = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > mapM_ (tcStmt m tcEnv sigs p) sts > alpha <- freshTypeVar > ty <- tcExpr m tcEnv sigs p e@@ -846,7 +838,7 @@ > return ty3 > tcExpr m tcEnv sigs p (Case _ e alts) = > do-> tyEnv0 <- fetchSt+> tyEnv0 <- S.get > ty <- tcExpr m tcEnv sigs p e > alpha <- freshTypeVar > tcAlts tyEnv0 ty alpha alts@@ -868,10 +860,10 @@ > tcExpr m tcEnv sigs p r@(RecordSelection e l) = > do > ty <- tcExpr m tcEnv sigs p e-> tyEnv <- fetchSt+> tyEnv <- S.get > lty <- maybe (freshTypeVar > >>= (\lty' -> -> updateSt_ +> S.modify > (bindLabel l (qualifyWith m (mkIdent "#Rec")) > (monoType lty')) > >> return lty'))@@ -923,11 +915,11 @@ > -> TcState (Ident,Type) > tcFieldExpr m tcEnv sigs comb f@(Field _ l e) = > do-> tyEnv <- fetchSt+> tyEnv <- S.get > let p = positionOfIdent l > lty <- maybe (freshTypeVar > >>= (\lty' -> -> updateSt_ +> S.modify > (bindLabel l (qualifyWith m (mkIdent "#Rec")) > (monoType lty')) > >> return lty'))@@ -950,14 +942,14 @@ > -> TcState (Type,Type) > tcArrow p what doc m ty = > do-> theta <- liftSt fetchSt+> theta <- S.lift S.get > unaryArrow (subst theta ty) > where unaryArrow (TypeArrow ty1 ty2) = return (ty1,ty2) > unaryArrow (TypeVariable tv) = > do > alpha <- freshTypeVar > beta <- freshTypeVar-> liftSt (updateSt_ (bindVar tv (TypeArrow alpha beta)))+> S.lift (S.modify (bindVar tv (TypeArrow alpha beta))) > return (alpha,beta) > unaryArrow ty = errorAt p (nonFunctionType what doc m ty) @@ -969,7 +961,7 @@ > do > beta <- freshTypeVar > gamma <- freshTypeVar-> liftSt (updateSt_ (bindVar tv (TypeArrow beta gamma)))+> S.lift (S.modify (bindVar tv (TypeArrow beta gamma))) > return (ty1,beta,gamma) > binaryArrow ty1 ty2 = > errorAt p (nonBinaryOp what doc m (TypeArrow ty1 ty2))@@ -983,13 +975,13 @@ > unify :: Position -> String -> Doc -> ModuleIdent -> Type -> Type > -> TcState () > unify p what doc m ty1 ty2 =-> liftSt $ {-$-}+> S.lift $ {-$-} > do-> theta <- fetchSt+> theta <- S.get > let ty1' = subst theta ty1 > let ty2' = subst theta ty2 > either (errorAt p . typeMismatch what doc m ty1' ty2')-> (updateSt_ . compose)+> (S.modify . compose) > (unifyTypes m ty1' ty2') > unifyTypes :: ModuleIdent -> Type -> Type -> Either Doc TypeSubst@@ -1086,7 +1078,7 @@ > -> TcState Type > checkSkolems p m what tyEnv ty = > do-> theta <- liftSt fetchSt+> theta <- S.lift S.get > let ty' = subst theta ty > fs = fsEnv (subst theta tyEnv) > unless (all (`Set.member` fs) (typeSkolems ty'))@@ -1100,7 +1092,7 @@ \begin{verbatim} > fresh :: (Int -> a) -> TcState a-> fresh f = liftM f (liftSt (liftSt (updateSt (1 +))))+> fresh f = liftM f (S.lift (S.lift (S.modify succ >> S.get))) > freshVar :: (Int -> a) -> TcState a > freshVar f = fresh (\n -> f (- n - 1))@@ -1184,20 +1176,6 @@ > [Value _ sigma] -> sigma > _ -> internalError ("funType " ++ show f) -> sureFunType :: ModuleIdent -> QualIdent -> ValueEnv -> Maybe TypeScheme-> sureFunType m f tyEnv =-> case (qualLookupValue f tyEnv) of-> [Value _ sigma] -> Just sigma-> vs -> case (qualLookupValue (qualQualify m f) tyEnv) of-> [Value _ sigma] -> Just sigma-> _ -> Nothing--> labelType :: Ident -> ValueEnv -> TypeScheme-> labelType l tyEnv =-> case lookupValue l tyEnv of-> Label _ _ sigma : _ -> sigma-> _ -> internalError ("labelType " ++ show l)- > sureLabelType :: Ident -> ValueEnv -> Maybe TypeScheme > sureLabelType l tyEnv = > case lookupValue l tyEnv of@@ -1319,11 +1297,6 @@ > vcat [text "Existential type escapes out of its scope", what, > text "Type:" <+> ppType m ty] -> invalidCType :: String -> ModuleIdent -> Type -> String-> invalidCType what m ty = show $-> vcat [text ("Invalid " ++ what ++ " type in foreign declaration"),-> ppType m ty]- > recursiveType :: ModuleIdent -> Int -> Type -> Doc > recursiveType m tv ty = incompatibleTypes m (TypeVariable tv) ty @@ -1345,3 +1318,14 @@ > text "are incompatible"] \end{verbatim}+++\end{verbatim}+The following functions implement pretty-printing for types.+\begin{verbatim}++> ppType :: ModuleIdent -> Type -> Doc+> ppType m = ppTypeExpr 0 . fromQualType m++> ppTypeScheme :: ModuleIdent -> TypeScheme -> Doc+> ppTypeScheme m (ForAll _ ty) = ppType m ty
src/TypeSubst.lhs view
@@ -15,6 +15,8 @@ > import Data.Maybe > import Data.List +> import Types+ > import Subst > import Base > import TopEnv
src/Types.lhs view
@@ -16,7 +16,7 @@ > import Data.List > import Data.Maybe -> import Ident+> import Curry.Base.Ident \end{verbatim} A type is either a type variable, an application of a type constructor@@ -47,7 +47,7 @@ > | TypeArrow Type Type > | TypeSkolem Int > | TypeRecord [(Ident,Type)] (Maybe Int)-> deriving (Eq,Show)+> deriving (Show, Eq) \end{verbatim} The function \texttt{isArrowType} checks whether a type is a function@@ -172,8 +172,8 @@ quantified variables. \begin{verbatim} -> data TypeScheme = ForAll Int Type deriving (Eq,Show)-> data ExistTypeScheme = ForAllExist Int Int Type deriving (Eq,Show)+> data TypeScheme = ForAll Int Type deriving (Show, Eq)+> data ExistTypeScheme = ForAllExist Int Int Type deriving (Show, Eq) \end{verbatim} The functions \texttt{monoType} and \texttt{polyType} translate a type@@ -215,3 +215,37 @@ > typeVar = TypeVariable \end{verbatim}++++> qualifyType :: ModuleIdent -> Type -> Type+> qualifyType m (TypeConstructor tc tys)+> | isTupleId tc' = tupleType tys'+> | tc' == unitId && n == 0 = unitType+> | tc' == listId && n == 1 = listType (head tys')+> | otherwise = TypeConstructor (qualQualify m tc) tys'+> where n = length tys'+> tc' = unqualify tc+> tys' = map (qualifyType m) tys+> qualifyType _ (TypeVariable tv) = TypeVariable tv+> qualifyType m (TypeConstrained tys tv) =+> TypeConstrained (map (qualifyType m) tys) tv+> qualifyType m (TypeArrow ty1 ty2) =+> TypeArrow (qualifyType m ty1) (qualifyType m ty2)+> qualifyType _ (TypeSkolem k) = TypeSkolem k+> qualifyType m (TypeRecord fs rty) =+> TypeRecord (map (\ (l,ty) -> (l, qualifyType m ty)) fs) rty+++> unqualifyType :: ModuleIdent -> Type -> Type+> unqualifyType m (TypeConstructor tc tys) =+> TypeConstructor (qualUnqualify m tc) (map (unqualifyType m) tys)+> unqualifyType _ (TypeVariable tv) = TypeVariable tv+> unqualifyType m (TypeConstrained tys tv) =+> TypeConstrained (map (unqualifyType m) tys) tv+> unqualifyType m (TypeArrow ty1 ty2) =+> TypeArrow (unqualifyType m ty1) (unqualifyType m ty2)+> unqualifyType m (TypeSkolem k) = TypeSkolem k+> unqualifyType m (TypeRecord fs rty) =+> TypeRecord (map (\ (l,ty) -> (l, unqualifyType m ty)) fs) rty+
src/Typing.lhs view
@@ -12,10 +12,14 @@ > import Data.Maybe > import Control.Monad+> import Control.Monad.State as S +> import Curry.Base.Ident+> import Curry.Syntax++> import Types > import Base > import TypeSubst-> import Combined > import TopEnv > import Utils @@ -84,10 +88,10 @@ environment.} \begin{verbatim} -> type TyState a = StateT TypeSubst (St Int) a+> type TyState a = S.StateT TypeSubst (S.State Int) a > run :: TyState a -> ValueEnv -> a-> run m tyEnv = runSt (callSt m idSubst) 0+> run m tyEnv = S.evalState (S.evalStateT m idSubst) 0 > class Typeable a where > typeOf :: ValueEnv -> a -> Type@@ -108,7 +112,7 @@ > where doComputeType = > do > ty <- f tyEnv x-> theta <- fetchSt+> theta <- S.get > return (fixTypeVars tyEnv (subst theta ty)) > fixTypeVars :: ValueEnv -> Type -> Type@@ -281,7 +285,7 @@ \begin{verbatim} > freshTypeVar :: TyState Type-> freshTypeVar = liftM TypeVariable $ liftSt $ updateSt (1 +)+> freshTypeVar = liftM TypeVariable $ S.lift (S.modify succ >> S.get) > instType :: Int -> Type -> TyState Type > instType n ty =@@ -304,7 +308,7 @@ > unify :: Type -> Type -> TyState () > unify ty1 ty2 =-> updateSt_ (\theta -> unifyTypes (subst theta ty1) (subst theta ty2) theta)+> S.modify (\theta -> unifyTypes (subst theta ty1) (subst theta ty2) theta) > unifyList :: [Type] -> [Type] -> TyState () > unifyList tys1 tys2 = sequence_ (zipWith unify tys1 tys2)@@ -312,14 +316,14 @@ > unifyArrow :: Type -> TyState (Type,Type) > unifyArrow ty = > do-> theta <- fetchSt+> theta <- S.get > case subst theta ty of > TypeVariable tv > | tv >= 0 -> > do > ty1 <- freshTypeVar > ty2 <- freshTypeVar-> updateSt_ (bindVar tv (TypeArrow ty1 ty2))+> S.modify (bindVar tv (TypeArrow ty1 ty2)) > return (ty1,ty2) > TypeArrow ty1 ty2 -> return (ty1,ty2) > ty' -> internalError ("unifyArrow (" ++ show ty' ++ ")")
− src/Unlit.lhs
@@ -1,110 +0,0 @@-% -*- LaTeX -*--% $Id: Unlit.lhs,v 1.2 2002/10/01 06:55:50 lux Exp $-%-% $Log: Unlit.lhs,v $-% Revision 1.2 2002/10/01 06:55:50 lux-% unlit returns an error message to the caller instead of calling error.-%-% Revision 1.1 2000/02/07 14:05:55 lux-% The compiler now supports literate source files. Literate source files-% must end with the suffix ".lcurry".-%-%-\nwfilename{Unlit.lhs}-\section{Literate comments}-Since version 0.7 of the language report, Curry accepts literate-source programs. In a literate source all program lines must begin-with a greater sign in the first column. All other lines are assumed-to be documentation. In order to avoid some common errors with-literate programs, Curry requires at least one program line to be-present in the file. In addition, every block of program code must be-preceded by a blank line and followed by a blank line.--The module \texttt{Unlit} acts as a preprocessor which converts-literate source programs into the ``un-literate'' format accepted by-the lexer. The implementation, together with the comments below, was-derived from appendix D in the Haskell 1.2 report.-\begin{verbatim}--> module Unlit(unlit) where-> import Data.Char-> import Position--\end{verbatim}-Each of the lines in a literate script is a program line, a blank-line, or a comment line. In the first case the text is kept with the-line.-\begin{verbatim}--> data Classified = Program String | Blank | Comment--\end{verbatim}-In a literate program, program lines begin with a \verb|>| character,-blank lines contain only whitespace, and all other lines are comment-lines.-\begin{verbatim}--> classify :: String -> Classified-> classify "" = Blank-> classify (c:cs)-> | c == '>' = Program cs-> | all isSpace (c:cs) = Blank-> | otherwise = Comment--\end{verbatim}-In the corresponding program, program lines have the leading \verb|>|-replaced by a leading space, to preserve tab alignments.-\begin{verbatim}--> unclassify :: Classified -> String-> unclassify (Program cs) = ' ' : cs-> unclassify Blank = ""-> unclassify Comment = ""--\end{verbatim}-Process a literate program into error messages (if any) and the-corresponding non-literate program.-\begin{verbatim}--> unlit :: FilePath -> String -> (String,String)-> unlit fn lcy = (es,cy)-> where cs = map classify (lines lcy)-> es = unlines (errors fn cs)-> cy = unlines (map unclassify cs)--\end{verbatim}-Check that each program line is not adjacent to a comment line and-there is at least one program line.-\begin{verbatim}--> errors :: FilePath -> [Classified] -> [String]-> errors fn cs =-> concat (zipWith3 adjacent (iterate nl (first fn)) cs (tail cs)) ++-> empty fn (filter isProgram cs)--\end{verbatim}-Given a line number and a pair of adjacent lines, generate a list of-error messages, which will contain either one entry or none.-\begin{verbatim}--> adjacent :: Position -> Classified -> Classified -> [String]-> adjacent p (Program _) Comment = [message (nl p) "after"]-> adjacent p Comment (Program _) = [message p "before"]-> adjacent p _ _ = []--> message p w = show p ++ ": comment line " ++ w ++ " program line."--\end{verbatim}-Given the list of program lines generate an error if this list is-empty.-\begin{verbatim}--> empty :: FilePath -> [Classified] -> [String]-> empty fn [] = [show (first fn) ++ ": no code in literate script"]-> empty fn _ = []--> isProgram :: Classified -> Bool-> isProgram (Program _) = True-> isProgram _ = False--\end{verbatim}
src/Utils.lhs view
@@ -12,16 +12,10 @@ \begin{verbatim} > module Utils where-> infixr 5 ++! -\end{verbatim}-\paragraph{Pairs}-The functions \texttt{apFst} and \texttt{apSnd} apply a function to-the first and second components of a pair, resp.-\begin{verbatim}+> import Data.List(foldl') -> apFst f (x,y) = (f x,y)-> apSnd f (x,y) = (x,f y)+> infixr 5 ++! \end{verbatim} \paragraph{Triples}@@ -62,9 +56,9 @@ case of the recursion. \begin{verbatim} -> foldl_strict :: (a -> b -> a) -> a -> [b] -> a-> foldl_strict f z [] = z-> foldl_strict f z (x:xs) = let z' = f z x in z' `seq` foldl_strict f z' xs+foldl_strict :: (a -> b -> a) -> a -> [b] -> a+foldl_strict = foldl'+ \end{verbatim} \paragraph{Folding with two lists}
src/WarnCheck.hs view
@@ -8,22 +8,47 @@ -- module WarnCheck (warnCheck) where -import Control.Monad+import Control.Monad.State+import qualified Data.Map as Map import Data.List -import CurrySyntax-import Ident-import Position-import Base (ValueEnv, ValueInfo(..), qualLookupValue, lookupValue)+import Curry.Base.Ident+import Curry.Base.Position+import Curry.Base.MessageMonad+import Curry.Syntax++import Base (ValueEnv, ValueInfo(..), qualLookupValue) import TopEnv import qualified ScopeEnv import ScopeEnv (ScopeEnv)-import Message-import Env +------------------------------------------------------------------------------- +-- Data type for representing the current state of generating warnings.+-- The monadic representation of the state allows the usage of monadic +-- syntax (do expression) for dealing easier and safer with its+-- contents. +type CheckState = State CState++data CState = CState {messages :: [WarnMsg],+ scope :: ScopeEnv QualIdent IdInfo,+ values :: ValueEnv,+ moduleId :: ModuleIdent }++-- Runs a 'CheckState' action and returns the list of messages+run :: CheckState a -> [WarnMsg]+run f+ = reverse (messages (execState f emptyState))++emptyState :: CState+emptyState = CState {messages = [],+ scope = ScopeEnv.new,+ values = emptyTopEnv,+ moduleId = mkMIdent []+ }+ ------------------------------------------------------------------------------- -- Find potentially incorrect code in a Curry program and generate@@ -33,7 +58,7 @@ -- - idle case alternatives -- - overlapping case alternatives -- - function rules which are not together-warnCheck :: ModuleIdent -> ValueEnv -> [Decl] -> [Decl] -> [Message]+warnCheck :: ModuleIdent -> ValueEnv -> [Decl] -> [Decl] -> [WarnMsg] warnCheck mid vals imports decls = run (do addImportedValues vals addModuleId mid@@ -164,6 +189,7 @@ (foldM' genWarning' (map unrefVar idents')) endScope + -- checkCondExpr :: ModuleIdent -> CondExpr -> CheckState () checkCondExpr mid (CondExpr _ cond expr)@@ -325,6 +351,7 @@ checkOverlappingAlts mid alts --+-- FIXME this looks buggy: is alts' required to be non-null or not? (hsi) checkIdleAlts :: ModuleIdent -> [Alt] -> CheckState () checkIdleAlts mid alts = do alts' <- dropUnless' isVarAlt alts@@ -382,16 +409,16 @@ -- Find function rules which are not together checkDeclOccurrences :: [Decl] -> CheckState ()-checkDeclOccurrences decls = checkDO (mkIdent "") emptyEnv decls+checkDeclOccurrences decls = checkDO (mkIdent "") Map.empty decls where checkDO prevId env [] = return () checkDO prevId env ((FunctionDecl pos ident _):decls) = do c <- isConsId ident if not (c || prevId == ident)- then (maybe (checkDO ident (bindEnv ident pos env) decls)+ then (maybe (checkDO ident (Map.insert ident pos env) decls) (\pos' -> genWarning' (rulesNotTogether ident pos') >> checkDO ident env decls)- (lookupEnv ident env))+ (Map.lookup ident env)) else checkDO ident env decls checkDO _ env (_:decls) = checkDO (mkIdent "") env decls@@ -399,15 +426,15 @@ -- check import declarations for multiply imported modules checkImports :: [Decl] -> CheckState ()-checkImports imps = checkImps emptyEnv imps+checkImports imps = checkImps Map.empty imps where checkImps env [] = return () checkImps env ((ImportDecl pos mid _ _ spec):imps) | mid /= preludeMIdent- = maybe (checkImps (bindEnv mid (fromImpSpec spec) env) imps)+ = maybe (checkImps (Map.insert mid (fromImpSpec spec) env) imps) (\ishs -> checkImpSpec env pos mid ishs spec >>= (\env' -> checkImps env' imps))- (lookupEnv mid env)+ (Map.lookup mid env) | otherwise = checkImps env imps checkImps env (_:imps) = checkImps env imps@@ -417,21 +444,21 @@ checkImpSpec env pos mid (is,hs) (Just (Importing _ is')) | null is && any (\i' -> notElem i' hs) is' = do genWarning' (multiplyImportedModule mid)- return (bindEnv mid (is',hs) env)+ return (Map.insert mid (is',hs) env) | null iis- = return (bindEnv mid (is' ++ is,hs) env)+ = return (Map.insert mid (is' ++ is,hs) env) | otherwise = do foldM' genWarning' (map ((multiplyImportedSymbol mid) . impName) iis)- return (bindEnv mid (unionBy cmpImport is' is,hs) env)+ return (Map.insert mid (unionBy cmpImport is' is,hs) env) where iis = intersectBy cmpImport is' is checkImpSpec env pos mid (is,hs) (Just (Hiding _ hs')) | null ihs- = return (bindEnv mid (is,hs' ++ hs) env)+ = return (Map.insert mid (is,hs' ++ hs) env) | otherwise = do foldM' genWarning' (map ((multiplyHiddenSymbol mid) . impName) ihs)- return (bindEnv mid (is,unionBy cmpImport hs' hs) env)+ return (Map.insert mid (is,unionBy cmpImport hs' hs) env) where ihs = intersectBy cmpImport hs' hs cmpImport (ImportTypeWith id1 cs1) (ImportTypeWith id2 cs2)@@ -572,68 +599,29 @@ _ -> info --- Data type for representing the current state of generating warnings.--- The monadic representation of the state allows the usage of monadic --- syntax (do expression) for dealing easier and safer with its--- contents.-data CheckState a = CheckState (CState () -> CState a)--data CState a = CState {messages :: [Message],- scope :: ScopeEnv QualIdent IdInfo,- values :: ValueEnv,- moduleId :: ModuleIdent,- result :: a- }- ---emptyState :: CState ()-emptyState = CState {messages = [],- scope = ScopeEnv.new,- values = emptyTopEnv,- moduleId = mkMIdent [],- result = ()- }---- modifyScope :: (ScopeEnv QualIdent IdInfo -> ScopeEnv QualIdent IdInfo)- -> CState a -> CState a+ -> CState -> CState modifyScope f state = state{ scope = f (scope state) } --- 'CheckState' is declared as an instance of 'Monad' to use its actions--- in 'do' expressions-instance Monad CheckState where-- -- (>>=) :: CheckState a -> (a -> CheckState b) -> CheckState b- (CheckState f) >>= g - = CheckState (\state -> let state' = f state- CheckState h = g (result state')- in h (state'{ result = () }))-- -- (>>) :: CheckState a -> CheckState b -> CheckState b- a >> b = a >>= (\_ -> b)-- -- return :: a -> CheckState a- return val = CheckState (\state -> state{ result = val })-- ---genWarning :: Position -> (WarningType,String) -> CheckState ()-genWarning pos (warnType,msg)- = CheckState (\state -> state{ messages = warnMsg:(messages state) })- where warnMsg = message (Warning warnType) pos msg+genWarning :: Position -> String -> CheckState ()+genWarning pos msg+ = modify (\state -> state{ messages = warnMsg:(messages state) })+ where warnMsg = WarnMsg (Just pos) msg -genWarning' :: (Position,WarningType,String) -> CheckState ()-genWarning' (pos,warnType,msg)- = CheckState (\state -> state{ messages = warnMsg:(messages state) })- where warnMsg = message (Warning warnType) pos msg +genWarning' :: (Position, String) -> CheckState ()+genWarning' (pos, msg)+ = modify (\state -> state{ messages = warnMsg:(messages state) })+ where warnMsg = WarnMsg (Just pos) msg -- insertVar :: Ident -> CheckState () insertVar id | isAnnonId id = return () | otherwise- = CheckState + = modify (\state -> modifyScope (ScopeEnv.insert (commonId id) (VarInfo False)) state) @@ -642,101 +630,90 @@ insertTypeVar id | isAnnonId id = return () | otherwise - = CheckState + = modify (\state -> modifyScope (ScopeEnv.insert (typeId id) (VarInfo False)) state) -- insertConsId :: Ident -> CheckState () insertConsId id- = CheckState + = modify (\state -> modifyScope (ScopeEnv.insert (commonId id) ConsInfo) state) -- insertTypeConsId :: Ident -> CheckState () insertTypeConsId id- = CheckState + = modify (\state -> modifyScope (ScopeEnv.insert (typeId id) ConsInfo) state) -- isVarId :: Ident -> CheckState Bool isVarId id- = CheckState (\state -> state{ result = isVar state (commonId id) })+ = gets (\state -> isVar state (commonId id)) -- isConsId :: Ident -> CheckState Bool isConsId id - = CheckState (\state -> state{ result = isCons state (qualify id) })+ = gets (\state -> isCons state (qualify id)) -- isQualConsId :: QualIdent -> CheckState Bool isQualConsId qid- = CheckState (\state -> state{ result = isCons state qid })+ = gets (\state -> isCons state qid) -- isShadowingVar :: Ident -> CheckState Bool isShadowingVar id - = CheckState - (\state -> state{ result = isShadowing state (commonId id) })-----isShadowingTypeVar :: Ident -> CheckState Bool-isShadowingTypeVar id- = CheckState - (\state -> state{ result = isShadowing state (typeId id) })+ = gets (\state -> isShadowing state (commonId id)) -- visitId :: Ident -> CheckState () visitId id - = CheckState + = modify (\state -> modifyScope (ScopeEnv.modify visitVariable (commonId id)) state) -- visitTypeId :: Ident -> CheckState () visitTypeId id - = CheckState + = modify (\state -> modifyScope (ScopeEnv.modify visitVariable (typeId id)) state) ---isUnrefVar :: Ident -> CheckState Bool-isUnrefVar id - = CheckState (\state -> state{ result = isUnref state (commonId id) })---- isUnrefTypeVar :: Ident -> CheckState Bool isUnrefTypeVar id- = CheckState (\state -> state{ result = isUnref state (typeId id) })+ = gets (\state -> isUnref state (typeId id)) -- returnUnrefVars :: CheckState [Ident] returnUnrefVars - = CheckState (\state -> + = gets (\state -> let ids = map fst (ScopeEnv.toLevelList (scope state)) unrefs = filter (isUnref state) ids- in state{ result = map unqualify unrefs })+ in map unqualify unrefs ) -- addModuleId :: ModuleIdent -> CheckState ()-addModuleId mid = CheckState (\state -> state{ moduleId = mid })+addModuleId mid = modify (\state -> state{ moduleId = mid }) ---returnModuleId :: CheckState ModuleIdent-returnModuleId = CheckState (\state -> state{ result = moduleId state }) +withScope :: CheckState a -> CheckState ()+withScope m = beginScope >> m >> endScope+ -- beginScope :: CheckState ()-beginScope = CheckState (\state -> modifyScope ScopeEnv.beginScope state)+beginScope = modify (\state -> modifyScope ScopeEnv.beginScope state) -- endScope :: CheckState ()-endScope = CheckState (\state -> modifyScope ScopeEnv.endScopeUp state)+endScope = modify (\state -> modifyScope ScopeEnv.endScopeUp state) -- Adds the content of a value environment to the state addImportedValues :: ValueEnv -> CheckState ()-addImportedValues vals = CheckState (\state -> state{ values = vals })+addImportedValues vals = modify (\state -> state{ values = vals }) -- foldM' :: (a -> CheckState ()) -> [a] -> CheckState ()@@ -768,36 +745,31 @@ if p then all' mpred xs else return False --- Runs a 'CheckState' action and returns the list of messages-run :: CheckState a -> [Message]-run (CheckState f)- = reverse (messages (f emptyState)) - ------------------------------------------------------------------------------- ---isShadowing :: CState a -> QualIdent -> Bool+isShadowing :: CState -> QualIdent -> Bool isShadowing state qid = let sc = scope state in maybe False isVariable (ScopeEnv.lookup qid sc) && ScopeEnv.level qid sc < ScopeEnv.currentLevel sc ---isUnref :: CState a -> QualIdent -> Bool+isUnref :: CState -> QualIdent -> Bool isUnref state qid = let sc = scope state in maybe False (not . variableVisited) (ScopeEnv.lookup qid sc) && ScopeEnv.level qid sc == ScopeEnv.currentLevel sc ---isVar :: CState a -> QualIdent -> Bool+isVar :: CState -> QualIdent -> Bool isVar state qid = maybe (isAnnonId (unqualify qid)) isVariable (ScopeEnv.lookup qid (scope state)) ---isCons :: CState a -> QualIdent -> Bool+isCons :: CState -> QualIdent -> Bool isCons state qid = maybe (isImportedCons state qid) isConstructor (ScopeEnv.lookup qid (scope state))@@ -831,56 +803,49 @@ ------------------------------------------------------------------------------- -- Warnings... -unrefTypeVar :: Ident -> (Position,WarningType,String)+unrefTypeVar :: Ident -> (Position, String) unrefTypeVar id = (positionOfIdent id,- UnrefTypeVar, "unreferenced type variable \"" ++ show id ++ "\"") -unrefVar :: Ident -> (Position,WarningType,String)+unrefVar :: Ident -> (Position, String) unrefVar id = (positionOfIdent id,- UnrefVar,- "unreferenced variable \"" ++ show id ++ "\"")+ "unused declaration of variable \"" ++ show id ++ "\"") -shadowingVar :: Ident -> (Position,WarningType,String)+shadowingVar :: Ident -> (Position, String) shadowingVar id = (positionOfIdent id,- ShadowingVar, "shadowing symbol \"" ++ show id ++ "\"") -idleCaseAlts :: (WarningType,String)-idleCaseAlts = (IdleCaseAlt,"idle case alternative(s)")+idleCaseAlts :: String+idleCaseAlts = "idle case alternative(s)" -overlappingCaseAlt :: (WarningType,String)-overlappingCaseAlt = (OverlapCase,"redundant overlapping case alternative")+overlappingCaseAlt :: String+overlappingCaseAlt = "redundant overlapping case alternative" -rulesNotTogether :: Ident -> Position -> (Position,WarningType,String)+rulesNotTogether :: Ident -> Position -> (Position, String) rulesNotTogether id pos = (positionOfIdent id,- RulesNotTogether, "rules for function \"" ++ show id ++ "\" " ++ "are not together " ++ "(first occurrence at " ++ show (line pos) ++ "." ++ show (column pos) ++ ")") -multiplyImportedModule :: ModuleIdent -> (Position,WarningType,String)+multiplyImportedModule :: ModuleIdent -> (Position, String) multiplyImportedModule mid = (positionOfModuleIdent mid,- MultipleImportModule, "module \"" ++ show mid ++ "\" was imported more than once") -multiplyImportedSymbol :: ModuleIdent -> Ident -> (Position,WarningType,String)+multiplyImportedSymbol :: ModuleIdent -> Ident -> (Position, String) multiplyImportedSymbol mid ident = (positionOfIdent ident,- MultipleImportSymbol, "symbol \"" ++ show ident ++ "\" was imported from module \"" ++ show mid ++ "\" more than once") -multiplyHiddenSymbol :: ModuleIdent -> Ident -> (Position,WarningType,String)+multiplyHiddenSymbol :: ModuleIdent -> Ident -> (Position, String) multiplyHiddenSymbol mid ident = (positionOfIdent ident,- MultipleHiding, "symbol \"" ++ show ident ++ "\" from module \"" ++ show mid ++ "\" was hidden more than once") @@ -893,9 +858,6 @@ tail_ alt [] = alt tail_ _ (_:xs) = xs -head_ :: a -> [a] -> a-head_ alt [] = alt-head_ _ (x:_) = x -- cmpListM :: Monad m => (a -> a -> m Bool) -> [a] -> [a] -> m Bool
src/cymake.hs view
@@ -16,13 +16,13 @@ import Data.List import Data.Maybe import System.IO-import System.Environment-import System.Exit+import System.Environment(getArgs, getProgName)+import System.Exit(ExitCode(..), exitWith) import Control.Monad (unless) import Data.Char (isDigit) import GetOpt-import CurryBuilder+import CurryBuilder(buildCurry) import CurryCompilerOpts import CurryHtml @@ -45,7 +45,7 @@ | null errs' && not (elem Html opts) = do unless (noVerb options') (putStrLn $ "This is cymake, version 0.1." - ++ filter isDigit "$Revision: 3624 $")+ ++ filter isDigit "$Revision: 3630 $") mapM_ (buildCurry options') files | null errs' = do let importFiles = nub $ importPaths opts'