module Syntax(module Syntax, Pos, TokenId) where import Util.Extra(Pos,strChr,strStr) import SysDeps(PackedString) import TokenId(TokenId) import Id(Id) import Ratio import Maybe(isNothing,fromJust) import NT {- ^ Note that some syntactic constructs contain the syntactic construct 'Type'. However, the rename pass replaces this representation by the internal type representation 'NewType' and 'NT'. So the syntactic constructs that use 'Type' are removed by the renaming pass or the type representation is only half translated @('TokenId' -> 'Id')@. Are the latter still used later? It probably would have been better if the whole syntax had been parameterised with respect to the type representation; but such an additional parameter would also be tiresome. -} data Module id = -- module modid [export] where { impdecls; fixdecls; topdecls } Module Pos id (Maybe [Export id]) [ImpDecl id] [FixDecl id] (Decls id) data Export id = ExportEntity Pos (Entity id) -- pos superfluous, same in entity? | ExportModid Pos id data ImpDecl id = -- import ?qualified? modid ?as modid? ?hiding? (import,..)? Import (Pos,id) (ImpSpec id) | ImportQ (Pos,id) (ImpSpec id) | ImportQas (Pos,id) (Pos,id) (ImpSpec id) | Importas (Pos,id) (Pos,id) (ImpSpec id) importedModule :: ImpDecl a -> a importedModule (Import (_,id) _) = id importedModule (ImportQ (_,id) _) = id importedModule (ImportQas (_,id) _ _) = id importedModule (Importas (_,id) _ _) = id data ImpSpec id = NoHiding [Entity id] | Hiding [Entity id] data Entity id = EntityVar Pos id -- ^ @varid@ | EntityConClsAll Pos id -- ^ @TyCon(..) | TyCls(..)@ | EntityConClsSome Pos id [(Pos,id)] -- ^ @TyCon | TyCls | TyCon(conid,..,conid) | TyCls(varid,..,varid)@ data InfixClass a = InfixDef | InfixL | InfixR | Infix | InfixPre a instance Eq (InfixClass a) where InfixDef == InfixDef = True InfixL == InfixL = True InfixR == InfixR = True Infix == Infix = True (InfixPre _) == (InfixPre _) = True _ == _ = False instance (Show a) => Show (InfixClass a) where showsPrec d InfixDef = showString "infixl{-def-} " showsPrec d InfixL = showString "infixl " showsPrec d InfixR = showString "infixr " showsPrec d Infix = showString "infix " showsPrec d (InfixPre a) = showString "prefix " . shows a . showChar ' ' type FixDecl id = (InfixClass id,Int,[FixId id]) data FixId a = FixCon Pos a | FixVar Pos a stripFixId :: FixId a -> a stripFixId (FixCon _ a) = a stripFixId (FixVar _ a) = a data Decls id = DeclsParse [Decl id] | DeclsScc [DeclsDepend id] -- used very often: noDecls :: Decls id noDecls = DeclsParse [] data DeclsDepend id = DeclsNoRec (Decl id) | DeclsRec [Decl id] data Decl id = -- | for type synonym: type simple = type DeclType (Simple id) (Type id) -- | renamer replaces DeclType by this. -- the type is in the symbol table, referenced by Id | DeclTypeRenamed Pos Id -- intentionally not "id" -- | {Nothing = newtype, Just False = data, Just True = data unboxed} -- context => simple = constrs -- deriving (tycls) | DeclData (Maybe Bool) [Context id] (Simple id) [Constr id] [(Pos,id)] -- | data primitive conid size | DeclDataPrim Pos id Int -- | Introduced by Rename to mark that we might need -- to generate selector functions -- position data\/dataprim [(field,selector)] | DeclConstrs Pos id [(Pos,id,id)] -- | class context => class where { signatures\/valdefs; } -- position, context, class, type variables, fundeps, method decls | DeclClass Pos [Context id] id [id] [FunDep id] (Decls id) -- | instance context => tycls inst where { valdefs } | DeclInstance Pos [Context id] id [Instance id] (Decls id) -- | default (type,..) | DeclDefault [Type id] -- | var primitive arity :: type | DeclPrimitive Pos id Int (Type id) -- | foreign import [callconv] [extfun] [unsafe|cast|noproto] var :: type -- (final id part is wrapper-fn for IO) -- callconv extfun intfun arity [u|c|n] ty wrapperId | DeclForeignImp Pos CallConv String id Int Safety (Type id) id -- | foreign export callconv [extfun] var :: type | DeclForeignExp Pos CallConv String id (Type id) -- | vars :: context => type | DeclVarsType [(Pos,id)] [Context id] (Type id) | DeclPat (Alt id) | DeclFun Pos id [Fun id] -- "var = ..." is a DeclFun, not a DeclPat -- | DeclSelect id Int id -- ^ introduced with pattern elimination (id = select Int id) -- Used for unimplemented things | DeclIgnore String | DeclError String | DeclAnnot (Decl id) [Annot id] -- | DeclPragma String String -- | infix[rl] int id,..,id | DeclFixity (FixDecl id) -- | for foreign imports\/exports data Safety = Unsafe | Safe instance Show Safety where showsPrec _ Unsafe = showString "unsafe" showsPrec _ Safe = id -- | supported foreign calling conventions data CallConv = C | Cast | Noproto | Haskell | Other String deriving Eq instance Show CallConv where showsPrec _ C = showString "ccall" showsPrec _ Cast = showString "cast" showsPrec _ Noproto = showString "noproto" showsPrec _ Haskell = showString "haskell" showsPrec _ (Other s) = showString s -- | introduced by RmClasses data ClassCode ctx id = CodeClass Pos id -- ^ class id | CodeInstance Pos id id [id] [ctx] [id] -- class id, typ id, args, ctxs, method ids -- | We parse MPTC with functional dependencies, only for hat-trans. data FunDep id = [id] :->: [id] data Annot id = AnnotArity (Pos,id) Int | AnnotPrimitive (Pos,id) PackedString | AnnotNeed [[id]] | AnnotUnknown -- | lhs pats, guarded exprs, local defs data Fun id = Fun [Pat id] (Rhs id) (Decls id) funArity :: Fun id -> Int funArity = length . \(Fun ps _ _) -> ps data Alt id = Alt (Pat id) (Rhs id) (Decls id) data Rhs id = Unguarded (Exp id) | PatGuard [([Qual id],Exp id)] -- ^ the list has at least one element data Type id = TypeCons Pos id [Type id] | TypeApp (Type id) (Type id) | TypeVar Pos id | TypeStrict Pos (Type id) data Sig id = Sig [(Pos,id)] (Type id) -- for interface file? data Simple id = Simple Pos id [(Pos,id)] simpleToType :: Simple id -> Type id simpleToType (Simple pos tcId pargs) = TypeCons pos tcId (map (TypeVar pos . snd) pargs) data Context id = Context Pos id [(Pos,id)] {- | Data constructor applied to type variables, possibly with field names. As appearing on right hand side of data or newtype definition. * ConstrCtx is always used if forall is specified * the intention is to remove Constr completely when all of nhc13 have been updated * this isn't nhc13, but rather Yhc * we have comments on the fields here, but can't make them docstrings without record syntax -} data Constr id = Constr Pos -- position of data constructor id -- data constructor [(Maybe [(Pos,id)],Type id)] -- argumentlist with field labels if any -- (many field labels with same type possible) -- the type admits impossible arguments: -- either all arguments have field names or none | ConstrCtx [(Pos,id)] -- type variabes from forall [Context id] -- context of data constructor Pos id [(Maybe [(Pos,id)],Type id)] getConstrId :: Constr id -> id getConstrId (Constr _ id _) = id getConstrId (ConstrCtx _ _ _ id _) = id getConstrArgumentList :: Constr id -> [(Maybe [(Pos,id)],Type id)] getConstrArgumentList (Constr _ _ xs) = xs getConstrArgumentList (ConstrCtx _ _ _ _ xs) = xs getConstrLabels :: Constr id -> [(Pos,id)] getConstrLabels constr = if null args || (isNothing . fst . head) args then [] else concatMap (fromJust . fst) args where args = getConstrArgumentList constr getConstrArgumentTypes :: Constr id -> [Type id] getConstrArgumentTypes constr = concat . map (\(l,t) -> replicate (times l) t) . getConstrArgumentList $ constr where times Nothing = 1 times (Just labels) = length labels constrArity :: Constr id -> Int constrArity = length . getConstrArgumentTypes type Instance id = Type id -- ^ Not 'TypeVar' {- | The following is ismorphic to the type constructor 'Qual'. Possibly Stmt should be removed and its usage replaced everywhere by 'Qual'. -} data Stmt id = StmtExp (Exp id) -- ^ @exp@ | StmtBind (Exp id) (Exp id) -- ^ @pat <- exp@ | StmtLet (Decls id) -- ^ @let { decls ; }@ type Pat id = Exp id -- | used both for expressions and patterns data Exp id = ExpScc String (Exp id) -- ^ never used! should probably be removed | ExpDict (Exp id) -- ^ hack to mark dictionary arguments | ExpLambda Pos [(Pat id)] (Exp id) -- ^ @\ pat ... pat -> exp@ | ExpLet Pos (Decls id) (Exp id) -- ^ @let { decls ; } in exp@ | ExpDo Pos [Stmt id] -- ^ @do { stmts ; }@ | ExpCase Pos (Exp id) [Alt id] -- ^ @case exp of { alts; }@ | ExpFatbar (Exp id) (Exp id) -- ^ never used! should probably be removed | ExpFail -- ^ never used! should probably be removed | ExpIf Pos (Exp id) (Exp id) (Exp id) -- ^ @if exp then exp else exp@ | ExpType Pos (Exp id) [Context id] (Type id) -- ^ exp :: context => type -- next two are sugared lists; introduced for hpc-trans | ExpListComp Pos (Exp id) [Qual id] | ExpListEnum Pos (Exp id) (Maybe (Exp id)) (Maybe (Exp id)) --- All above only in expressions, not in patterns --- Below in patterns + expressions. | ExpRecord (Exp id) [Field id] | ExpApplication Pos [Exp id] -- always at least two elements? | ExpVar Pos id | ExpCon Pos id | ExpInfixList Pos [Exp id] -- Temporary, introduced by parser because | ExpVarOp Pos id -- it does not know precedence and | ExpConOp Pos id -- associativity; removed by rename | ExpLit Pos (Lit Boxed) | ExpList Pos [Exp id] -- bracketed expression mainly for hpc-trans (need accurate pos) | ExpBrack Pos (Exp id) --- after typechecker | Exp2 Pos id id -- ^ e.g. Ord.Eq or Eq.Int --- Below only in patterns | PatAs Pos id (Pat id) | PatWildcard Pos | PatIrrefutable Pos (Pat id) -- idea: f (n+k) = exp[n] -- => f n' | k <= n' = exp[n] -- where n = n'-k -- (n+k) pattern - store: n n' k (k<=n') (n'-k) | PatNplusK Pos id id (Exp id) (Exp id) (Exp id) -- | typeRep introduced by the type check selection | ExpTypeRep Pos NT data Field id = FieldExp Pos id (Exp id) | FieldPun Pos id -- ^ H98 removes (retained for error msgs) data Boxed = Boxed | UnBoxed instance Eq Boxed where Boxed == Boxed = True UnBoxed == UnBoxed = True _ == _ = False instance Show Boxed where showsPrec d Boxed = id showsPrec d UnBoxed = showChar '#' data Lit boxed = LitInteger boxed Integer | LitRational boxed Rational | LitString boxed String | LitInt boxed Int | LitDouble boxed Double | LitFloat boxed Float | LitChar boxed Char instance (Eq b) => Eq (Lit b) where a == a' = litEqual a a' -- litEqual needed in Symbols to force correct type in gofer -- seems to be natural equality, why not data Lit (deriving Eq)? litEqual :: Eq b => Lit b -> Lit b -> Bool litEqual (LitInteger b i) (LitInteger b' i') = i == i' && b == b' litEqual (LitRational b i) (LitRational b' i') = i == i' && b == b' litEqual (LitString b s) (LitString b' s') = s == s' && b == b' litEqual (LitInt b i) (LitInt b' i') = i == i' && b == b' litEqual (LitDouble b f) (LitDouble b' f') = f == f' && b == b' litEqual (LitFloat b f) (LitFloat b' f') = f == f' && b == b' litEqual (LitChar b c) (LitChar b' c') = c == c' && b == b' litEqual _ _ = False instance (Show b) => Show (Lit b) where showsPrec d lit = litshowsPrec d lit -- litshowsPrec needed in Symbols to force correct type in gofer litshowsPrec :: (Show b) => Int -> Lit b -> ShowS litshowsPrec d (LitInteger b i) = showParen (i<0) (showsPrec d i) . shows b litshowsPrec d (LitRational b i) = -- this is a hack to show a rational in floating point representation -- precision might be lost -- therer is no library function to print a rational in full precision -- in floating point representation showParen (i<0) (showsPrec d ((fromRational i)::Double)) . shows b litshowsPrec d (LitString b str)= showString (strStr str) . shows b litshowsPrec d (LitInt b i) = showParen (i<0) (showsPrec d i) . shows b litshowsPrec d (LitDouble b f) = showParen (f<0) (showsPrec d f) . shows b litshowsPrec d (LitFloat b f) = showParen (f<0) (showsPrec d f) . shows b litshowsPrec d (LitChar b chr)= showString (strChr chr). shows b data Qual id = -- @pat <- exp@ QualPatExp (Pat id) (Exp id) -- @pat@ | QualExp (Exp id) -- @let decls@ | QualLet (Decls id) -------------------- data Interface id -- interface modid where {iimpdecl; fixdecl; itopdecl } = Interface Pos id [IImpDecl id] [FixDecl id] (IDecls id) type IImpDecl id = ImpDecl id -- No Hiding in ImpSpec type IDecls id = Decls id -- No Valdef