packages feed

curry-frontend-0.2.1: src/Curry/Syntax/Type.lhs

> {-# 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])