Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/compiler98/Extract.hs
{- --------------------------------------------------------------------------- extract: Adds arity of all defined variables to symbol table of internal state. Adds type of variables from type declarations and primitive and foreign function definitions to symbol table of internal state (but not type declarations from classes). Tests that there are not conflicting arities. Tests for instance definition: is it illegally made for a type synonym? does class require instances for superclasses which are not present? (Adds appropriate error message to internal state). type2NT transforms type from syntax tree into interal type. -} module Extract(IntState,Decls,extract,type2NT) where import Syntax(Type(..),Decls(..),Decl(..),Fun(..),Rhs(..),Exp(..),Stmt(..) ,Alt(..),Field(..),Qual(..)) import IntState(IntState,lookupIS,depthI,strIS,addError,superclassesI ,instancesI,updVarArity,updVarNT) import NT(NT(..),NewType(..),mkNTvar,mkNTcons) import Reduce(Reduce,mapR,unitR,(>>>)) import Rename(ctxs2NT) import IExtract(freeType) import Util.Extra(snub,strPos,mixLine,mixCommaAnd) import Bind(identPat) import SyntaxPos(Pos,HasPos(getPos)) import qualified Data.Map as Map import Id(Id) import Maybe {- transform type from syntax tree into internal type -} type2NT :: Type Id -> NT type2NT (TypeApp t1 t2) = NTapp (type2NT t1) (type2NT t2) type2NT (TypeCons _ ci ts) = mkNTcons ci (map type2NT ts) type2NT (TypeStrict _ t) = NTstrict (type2NT t) type2NT (TypeVar _ v) = mkNTvar v -- No KIND inference yet! {- -} extract :: Decls Id -> IntState -> IntState extract = extractDecls extractDecls :: Decls Id -> IntState -> IntState extractDecls (DeclsParse decls) = mapR extractDecl decls extractDecl :: Decl Id -> Reduce IntState IntState extractDecl (DeclInstance pos ctxs cls [instanceType@(TypeCons poscon con _)] instmethods) = (\ state -> if (isJust . depthI . fromJust . lookupIS state) con then addError state ("Instance declaration of type synonym is illegal (" ++ strIS state con ++ " at " ++ strPos poscon ++ ")") else case (filter (isNothing.snd) . map ( \ cls -> (cls,(Map.lookup con . instancesI . fromJust . lookupIS state) cls) ) . superclassesI . fromJust . lookupIS state) cls of [] -> state clss -> addError state ("Instance declaration for the class " ++ strIS state cls ++ " at " ++ strPos pos ++ " needs instance(s) of " ++ mixCommaAnd (map (strIS state . fst) clss) ++ " according to class declaration.") ) >>> extractDecls instmethods -- error if we find any type signatures extractDecl (DeclClass pos tctxs tClass tTVars fundeps (DeclsParse decls)) = mapR extractDecl' decls extractDecl (DeclPrimitive pos ident arity typ) = let nt = NewType (snub (freeType typ)) [] [] [type2NT typ] in updVarNT pos ident nt >>> updVarArity pos ident arity extractDecl (DeclForeignImp pos _ _ ident arity cast typ _) = unitR -- type extraction for ffi is now done earlier in FFITrans phase extractDecl (DeclForeignExp pos _ _ ident typ) = unitR -- type extraction for ffi is now done earlier in FFITrans phase --let nt = NewType (snub (freeType typ)) [] (ctxs2NT []) [type2NT typ] --in updVarNT pos ident nt extractDecl (DeclVarsType posidents ctxs typ) = let nt = NewType (snub (freeType typ)) [] (ctxs2NT ctxs) [type2NT typ] in mapR ( \ (pos,i) -> updVarNT pos i nt) posidents extractDecl (DeclPat alt) = extractDeclAlt alt extractDecl (DeclFun pos fun funs) = updFunArity pos fun funs >>> mapR extractFun funs extractDecl d = unitR {- extractDecl' is used in class declarations as we don't want to use top level signatures there why are the declared types not added to the symbol table? (OC) -} extractDecl' :: Decl Id -> Reduce IntState IntState extractDecl' (DeclPat alt) = extractDeclAlt alt extractDecl' (DeclFun pos fun funs) = updFunArity pos fun funs >>> mapR extractFun funs extractDecl' d = unitR {- Adds arity of defined variable to symbol table of internal state (any old arity is overwritten). Assumes that variable is already in symbol table. Adds error message, if equations of definition suggest different arities. -} updFunArity :: Pos -> Id -> [Fun a] -> Reduce IntState IntState updFunArity pos fun funs = case map fA funs of (a:xs) -> if all (a==) xs then updVarArity pos fun a else \ state -> addError state ("Multiple arities for " ++ strIS state fun ++ ": " ++ mixLine (map (\ (pos,a) -> " arity " ++ show a ++ " at " ++ strPos pos) (map fPA funs))) where fA (Fun args gdexps decls) = (length args) fPA (Fun args gdexps decls) = (getPos args,length args) extractFun :: Fun Id -> Reduce IntState IntState extractFun (Fun pats rhs decls) = extractRhs rhs >>> extractDecls decls extractRhs :: Rhs Id -> Reduce IntState IntState extractRhs (Unguarded exp) = extractExp exp extractRhs (PatGuard gdExps) = mapR extractPatGuardExp gdExps extractPatGuardExp :: ([Qual Id],Exp Id) -> Reduce IntState IntState extractPatGuardExp (quals,exp) = mapR extractQual quals >>> extractExp exp extractDeclAlt :: Alt Id -> IntState -> IntState extractDeclAlt (Alt pat rhs decls) = mapR ( \ (pos,ident) -> updVarArity pos ident 0) (identPat pat) >>> extractRhs rhs >>> extractDecls decls extractAlt :: Alt Id -> IntState -> IntState extractAlt (Alt pat rhs decls) = extractRhs rhs >>> extractDecls decls extractExp :: Exp Id -> Reduce IntState IntState extractExp (ExpScc str exp) = extractExp exp extractExp (ExpLambda pos pats exp) = extractExp exp extractExp (ExpLet pos decls exp) = extractExp exp >>> extractDecls decls extractExp (ExpDo pos stmts) = mapR extractStmt stmts extractExp (ExpCase pos exp alts) = extractExp exp >>> mapR extractAlt alts extractExp (ExpIf pos expC expT expE) = extractExp expC >>> extractExp expT >>> extractExp expE extractExp (ExpType pos exp ctxs typ) = extractExp exp --- Above only in expressions extractExp (ExpApplication pos exps) = mapR extractExp exps extractExp (ExpList pos exps) = mapR extractExp exps extractExp (ExpRecord exp fields)= extractExp exp >>> mapR extractField fields extractExp e = unitR extractField :: Field Id -> Reduce IntState IntState extractField (FieldExp _ _ exp) = extractExp exp extractField (FieldPun _ _) = unitR extractStmt :: Stmt Id -> Reduce IntState IntState extractStmt (StmtExp exp) = extractExp exp extractStmt (StmtBind pat exp) = mapR ( \ (pos,ident) -> updVarArity pos ident 0) (identPat pat) >>> extractExp exp extractStmt (StmtLet decls) = extractDecls decls extractQual :: Qual Id -> Reduce IntState IntState extractQual (QualExp exp) = extractExp exp extractQual (QualPatExp pat exp) = mapR ( \ (pos,ident) -> updVarArity pos ident 0) (identPat pat) >>> extractExp exp extractQual (QualLet decls) = extractDecls decls {- End Module Extract -------------------------------------------------------}