Type

Plain source file: Type.hs (Apr 20, 2001)

Type is imported by: Main.

module Type(typeTopDecls) where

import List(partition)
import TokenId
import Syntax
import SyntaxPos
import IdKind
import State
import NT
import TypeLib(typeUnify,typeUnifyMany,typeUnifyApply,typePatCon,typeExpCon
              ,typeIdentDict,debugTranslating,getIdent,getTypeErrors,typeError
              ,typeNewTVar,typeIdentDef,checkExist,funType,extendEnv,getEnv
              ,getState,setState
              ,msgFun,msgPat,msgLit,msgBool,msgGdExps,msgAltExps,msgCase
              ,msgAltPats,msgIf,msgApply,msgList,msgExpType,msgAs,msgNK)
import TypeEnv(initEnv,envDecls,tvarsInEnv,envPats,envPat)
import Extra
import MergeSort(group,unique)
import TypeSubst
import TypeCtx
import TypeData
import PackedString(PackedString,packString,unpackPS)
import Info
import IntState
import TypeUtil(ntIS)
import TypeUnify(unify)
import Nice
import Bind(identPat)
import Extract(type2NT)
import AssocTree
import Tree234
import Remove1_3
import Id(Id)

--import PPSyntax   -- just for debugging
--import StrSyntax  -- just for debugging

typeTopDecls tidFun defaults state code dbgtrans topdecls =
  let defaults' =
        case defaults of
	  Nothing -> [tidFun (tInteger,TCon),tidFun (tDouble,TCon)]
	  Just def -> def 
      result =  typeTopDeclScc topdecls tidFun defaults' dbgtrans finalState state
      finalState = snd result
  in case result of
       (topdecls,state) ->
          case mapS typeCode code  tidFun  state of
            (code,state) ->
	       (code,topdecls,state)

typeCode d@(CodeClass pos cls) tidFun state = (d,state)
typeCode (CodeInstance pos cls typ _ _ ms) tidFun state =
  let clsInfo = dropJust (lookupIS state cls)
      sc = superclassesI clsInfo
      (free,ctxs) = dropJust (lookupAT (instancesI clsInfo) typ)
  in case uniqueISs state ctxs of
      (ctxsi,state) ->
	(CodeInstance pos cls typ (map snd ctxsi)
	     (map (buildCtx state noPos (map (mapFst (mapSnd NTvar)) ctxsi) . ( \ cls -> TypeDict cls (NTcons typ (map NTvar free)) [(0,pos)])) sc) ms
	,state)


typeTopDeclScc :: Decls Id 
               -> ((TokenId,IdKind) -> Int) 
               -> [Id] -> Bool -> a 
               -> IntState 
               -> (Decls Id,IntState)

typeTopDeclScc (DeclsScc xs) tidFun defaults dbgtrans finalState state =
     case mapS typeDepend xs (TypeDown initEnv tidFun defaults [] [] dbgtrans) (TypeState state idSubst initCtxs []) of
	(xs,TypeState state phi ctxs ectxsi) -> (DeclsScc (concat xs),state)


typeDeclScc (DeclsScc xs) =
  mapS typeDepend xs >>>= \ xs ->
  unitS (DeclsScc (concat xs))


typeDepend (DeclsNoRec d13) =
  fixDecl13 d13 >>>= \ d -> 
  typeScc [d] >>>= \ (dicts,[d]) ->
  unitS (map DeclsNoRec dicts ++ [DeclsNoRec d])

typeDepend (DeclsRec ds13) =
  mapS fixDecl13 ds13 >>>= \ ds ->
  typeScc ds >>>= \ (dicts,ds) ->
  unitS (map DeclsNoRec dicts ++ [DeclsRec ds])

--- ======== The hairy part

typeScc :: [Decl Id] 
        -> TypeDown -> TypeState -> (([Decl Id],[Decl Id]),TypeState)

typeScc decls down@(TypeDown env tidFun defaults ctxsDict envDict dbgtrans)
              up@(TypeState state phi inCtxs ectxsi) = 
  let -- ctxs should only get up but the monad can not handle that!
      trueExp :: Exp Id  -- this expression has become superfluous,
                         -- but it is a lot of work to remove it from the code
      trueExp = ExpCon noPos (tidFun (tTrue,Con))

      nextTvar :: Int
      (nextTvar,_) = uniqueIS state -- take a look at the next type variable

      envHere :: [(Int, NT)]
      (envHere,up'@(TypeState state' phi' ctxs' ectxsi')) =
		envDecls decls () (TypeState state phi initCtxs [])

      decls' :: [Decl Int]
      (decls',up''@(TypeState state'' phi'' ctxs'' existCtxsi)) =
		mapS typeDecl decls
                     (TypeDown (envHere++env) tidFun defaults
                               (usedCtx ++ ctxsDict)
                               (derivedDict ++ envDict) dbgtrans)
                     up'

      phiEnv :: [(Int,NT)]
      phiEnv     = substEnv phi'' env
      phiEnvHere :: [(Int,NT)]
      phiEnvHere = substEnv phi'' envHere
      phiCtxs :: [TypeDict]
      phiCtxs    = substCtxs phi'' ctxs''

      globalTVars :: [Int]
      globalTVars = (unique . tvarsInEnv) phiEnv

      uniqueCtxs :: [TypeDict]
      uniqueCtxs =	-- These contexts are needed
		( map (\(TypeDict c v ip:cvips) ->
                         TypeDict c v (ip++concatMap (\(TypeDict c v ip)-> ip)
                                                     cvips))
		. group
		)  phiCtxs

      existCtxs :: [(Int,NT)]
      existCtxs = map fst existCtxsi

      globalCtxs :: [(Int,NT)]
      localCtxs0 :: [(Int,NT)]
      (globalCtxs,localCtxs0) =   -- These are the simplified context
                                  -- that are needed
		( partition  ( \ (c,nt) -> stripNT nt `elem` globalTVars)
	        . ctxsReduce state
 		. concatMap (ctxsSimplify state [])
--                . map ( \ (TypeDict c nt _) -> (c,nt))
                ) uniqueCtxs

      localCtxs :: [(Int,NT)]
      localCtxs = filter (`notElem` existCtxs) localCtxs0


    	-- get some unique identifiers

      globalCtxsi :: [((Int,NT),Int)]
      (globalCtxsi,state1) = uniqueISs state'' globalCtxs

      localCtxsi :: [((Int,NT),Int)]
      (localCtxsi,state2) = uniqueISs state1 localCtxs

	-- Contexts that depend on type variables that are not all quantified

      outCtxs :: [TypeDict]
      outCtxs = map ( \ ((c,nt),i) -> TypeDict c nt [(i,noPos)]) globalCtxsi

	-- Set up argument and available dictionaries for identifiers
        -- without a given type

      derivedArgs :: [(Int,Exp Int)]
      derivedArgs = map (\((c,nt),i) -> (stripNT nt,ExpVar noPos i)) localCtxsi
      derivedDict :: [(Int,[Exp Int])]
      derivedDict = map (\(i,nt) -> (i, (map snd
                                        . filter ((`elem` freeNT nt) . fst))
                                        derivedArgs)
                        ) phiEnvHere   -- default is fixed in bindType

	-- Create mapping from Int to expression for requested dictionary

      usedCtx :: [(Int,Exp Int)]
      usedCtx = concatMap (\(TypeDict c nt ips) ->
                             let dict = buildCtx state noPos
                                          (existCtxsi++localCtxsi++globalCtxsi)
                                          (TypeDict c nt ips)
			     in map (\(i,p) -> (i,dict)) ips
                          ) uniqueCtxs

	-- Insert types into state (comparing with given type if such exist)
        -- and add dictionary arguments

      declsDict :: [Decl Int]
      declsDict = map (\(_,i) ->
			 case lookup i ctxsDict of
			   Just exp -> DeclFun noPos i [Fun [] (Unguarded exp)
                                                            (DeclsScc [])]
                      ) globalCtxsi 

      (decls'',state3) = mapS bindType decls'
                              (globalTVars,trueExp,localCtxsi
                              ,phiEnvHere,defaults)
                              state2
  in
{-
	strace ("usedCtx = " ++ show (map fst usedCtx)) $
	strace ("globalCtxs = " ++ show globalCtxs) $
	strace ("localCtxs0 = " ++ show localCtxs0) $
	strace ("existCtxs = " ++ show existCtxs) $
	strace ("phi'' = " ++ show phi'') $
	strace ("ctxs'' = " ++ show ctxs'') $
	strace ("phiCtxs = " ++ show phiCtxs) $
-}
     
((declsDict,decls'')
     ,TypeState state3 (stripSubst phi'' nextTvar) (outCtxs++inCtxs) existCtxsi)


--------------------- Fix arguments and types

isExist (NTexist _) = True
isExist _           = False


bindType :: Decl Id 
         -> ([Int], Exp Int, [((Int, NT), Int)], [(Int, NT)], [Int]) 
         -> IntState 
         -> (Decl Id, IntState)

bindType decl@(DeclPat (Alt pat gdexps decls))
         down@(globalTVars,trueExp,[],envHere,defaults) state =
  -- No context for left hand patterns!
  case mapS0 checkType (identPat pat) down state of
    state -> (decl,state)
 where
  checkType (pos,ident) (globalTVars,trueExp,localCtxi,envHere,defaults) state =
    case lookup ident envHere of
      Nothing -> strace ("Nothing derived for " ++ show ident ++
                         " at "++strPos pos) state
      Just derivedNT ->
	let derivedFree = filter (`notElem` globalTVars)
                                 (snub (freeNT derivedNT))
        in case ntIS state ident of
            (NoType,state) ->
	      updateIS state ident (newNT
                                     (NewType derivedFree [] []
                                              [polyNT derivedFree derivedNT]))
            (given@(NewType givenFree [] givenCtx [givenNT]),state) -> 
	      if length givenFree /= length derivedFree
	      then addError state
                            ("Derived type " ++ show derivedFree
                            ++ niceNT Nothing state (mkALNT derivedNT) derivedNT
                            ++ " is not an instance of " 
		   	    ++ show givenFree
			    ++ niceNT Nothing state (mkAL givenFree) givenNT
                            ++ " at " ++ strPos pos)
	      else state

bindType decl@(DeclPat (Alt pat gdexps decls))
         down@(globalTVars,trueExp,localCtxsi,envHere,defaults) state =
  -- No context for left hand patterns!
  (decl,addError (foldr typeError state (identPat pat)) errmsg)
 where
  errmsg = "Context for " ++ mixCommaAnd ((map (strIS state) . unique .
                                           map (fst . fst)) localCtxsi)
	   ++ " needed in left hand pattern at " ++ strPos (getPos pat) ++ "."
  nt = NewType [1] [] [] [NTvar 1]   -- Used instead of derived type, not sure
                                     -- if it is any idea
  typeError (pos,ident) state = (updateIS state ident (newNT nt))

bindType decl@(DeclPrimitive pos fun arity typ) down state =
  (decl,state)
bindType decl@(DeclForeignImp pos str fun arity cast typ _) down state =
  (decl,state)
bindType decl@(DeclForeignExp pos str fun typ) down state =
  (decl,state)
bindType decl@(DeclFun pos fun funs)
         (globalTVars,trueExp,localCtxi,envHere,defaults) state =
  case ntIS state fun of
    (NoType,state) ->
      let derivedNT = assocDef  envHere (error "162") fun
	  derivedFree = filter (`notElem` globalTVars) (snub (freeNT derivedNT))
	  derivedCtxi :: [((Int,NT),Int)]
	  defaultCtxi :: [((Int,NT),Int)]
	  (derivedCtxi,defaultCtxi) = partition ((`elem` derivedFree) . stripNT
                                                 . snd . fst) localCtxi
      in  case filter (isExist . snd . fst) defaultCtxi of
	    [] -> 
               case buildDefaults pos defaultCtxi trueExp defaults state of
	         (defaultDecls,state) ->
	            (DeclFun pos fun
                             (map (bindFun (map (\ (c_v,i) -> ExpVar pos i)
                                                derivedCtxi)
                                           (map DeclsNoRec defaultDecls))  funs)
	            ,updateIS state fun
                              (newNT (NewType derivedFree []
                                              (map (mapSnd stripNT . fst)
                                                   derivedCtxi)
                                              [polyNT derivedFree derivedNT]))
	            )
	    er -> (decl, addError state ("Dictionary can not be found "
                                        ++ "for existential types, "
                                        ++ "error detected at " ++ strPos pos)
	  	  )

    (given@(NewType givenFree [] givenCtx [givenNT]),state) -> 
      let derivedNT = assocDef envHere (error "171")  fun
	  derivedFree = filter (`notElem` globalTVars) (snub (freeNT derivedNT))
      in
      case unify state idSubst (derivedNT,givenNT) of 
        Left (phi,err) ->
          (decl
          ,addError state
               ("Derived type for " ++ strIS state fun ++ " at " ++ strPos pos 
               ++" can not be unified with given type due to " ++ err
               ++"\nDerived:"++niceNT Nothing state (mkALNT derivedNT) derivedNT
               ++"\nGiven  :" ++ niceNT Nothing state (mkAL givenFree) givenNT))
	Right phi ->
	  let phis = ( foldr (\ (k,v) t -> addAT t (++) k [v]) initAT
                     . map fixSubst 
                     . treeMapList (:)
                     ) phi

              al = mkAL (givenFree ++ freeNT derivedNT)

	      fixSubst (v,NTvar v') = if v `elem` givenFree then (v',NTvar v)
                                                            else (v,NTvar v')
	      fixSubst (v,NTany v') = if v `elem` givenFree then (v',NTvar v)
                                                            else (v,NTvar v')
              fixSubst p = p

              one2many phi = ( filter ((/= 1).length.snd)
                             . treeMapList (:)) phis
              freebound phi = ( filter ((`elem` givenFree).fst)
                              . filter ((== 1).length . snd)
                              . treeMapList (:)
                              ) phis

              safePhi phi v =
                      case lookupAT phi v of
                         Nothing -> Just v
                         Just xs -> findV xs

              findV [NTvar v] = Just v
              findV [NTany v] = Just v
              findV _ = Nothing

	      sameNT (NTany _) v   = NTany v
	      sameNT (NTvar _) v   = NTvar v
	      sameNT (NTexist _) v = NTexist v


              localCtxi' = ( map dropJust
                           . filter isJust
                           . map (\((c,nt),i) ->
                                   case safePhi phis (stripNT nt) of
				     Just v  -> Just ((c,sameNT nt v),i)
				     Nothing -> Nothing) -- either one2many
                                                         -- of freebound
                           ) localCtxi
	      (derivedCtxi,defaultCtxi) =
                  partition ((`elem` givenFree) . stripNT .snd.fst) localCtxi'
	      derivedIntPairI = map (mapFst (mapSnd stripNT)) derivedCtxi

              ctxcheck ctxi = filter ((`notElem` givenCtx) . fst) ctxi

          in
          case (one2many phis,freebound phis,ctxcheck derivedIntPairI) of
            ([],[],[]) ->
                -- Type is ok, but we need to introduce new unique ints
                -- for excessive contexts, eg, (Eq a,Ord a)
	        let (mGivenCtxi',state2) =
                          (uniqueISs state . zip givenCtx
                          . map (\cv-> lookup cv derivedIntPairI)) givenCtx
                    givenCtxi' = map stripAndFix mGivenCtxi'
                    stripAndFix ((c,Nothing),u) = (c,u)
                    stripAndFix ((c,Just v),u) = (c,v)
                in
                case filter (isExist . snd . fst) defaultCtxi of
	          [] ->
                    case buildDefaults pos defaultCtxi trueExp
                                       defaults state2 of
		      (defaultDecls,state3) ->
		          (DeclFun pos fun
                                   (map (bindFun (map (\(c_v,i)-> ExpVar pos i)
                                                      givenCtxi')
                                                 (map DeclsNoRec defaultDecls))
                                        funs)
                               ,state3
		               )
 	          er ->
                    (decl
		    ,addError state
                        ("Dictionary can not be found for existential types, "
                        ++ "error detected at " ++ strPos pos
                        ++ " (signature given)"))
            (eOne2Many,eFreeBound,eCtxs) ->
                let sOne2Many xs =
                        concatMap (\(v,nts)->
                                   "\n    type variable "
                                   ++ niceNT Nothing state al (NTvar v)
                                   ++ " bound to "
			           ++ mixCommaAnd (map (niceNT Nothing state al)
                                                        nts)
                                  ) xs
                    sFreeBound [] = []
                    sFreeBound [(v,t)] =
                        "\n    given free variable "
                        ++ niceNT Nothing state al (NTvar v)
                        ++ " is bound to " ++ niceNT Nothing state al (head t)
                    sFreeBound xs =
                        "\n    given free variables "
                        ++ mixCommaAnd (map (niceNT Nothing state al
                                            . NTvar . fst) xs)
                        ++ " are bound to "
                        ++ mixCommaAnd (map (niceNT Nothing state al
                                            . head . snd) xs)
                        ++ " respectively"
                    sCtxs [] = ""
                    sCtxs xs = "\n    different contexts"
                in 
	        (decl
                ,addError state
                    ("Derived type for " ++ strIS state fun
                    ++ " at " ++ strPos pos ++ " does not match due to:"
                    ++ sOne2Many eOne2Many ++ sFreeBound eFreeBound
                    ++ sCtxs eCtxs
                    ++ "\nDerived:"
                    ++ niceCtxs Nothing state al (map fst derivedIntPairI)
                    ++ niceNT Nothing state al derivedNT
                    ++ "\nGiven  :"
                    ++ niceCtxs Nothing state al givenCtx
                    ++ niceNT Nothing state al givenNT))

bindFun dictArgs defaultDecls (Fun args gdexps (DeclsScc decls)) =
  Fun (dictArgs++args) gdexps (DeclsScc (defaultDecls ++ decls))


      

--------------------- Nice


typeDecl d@(DeclPrimitive pos fun arity typ) =
  unitS d
typeDecl d@(DeclForeignImp pos str fun arity cast typ _) =
  unitS d
typeDecl d@(DeclForeignExp pos str fun typ) =
  unitS d
typeDecl (DeclPat (Alt pat rhs decls)) =
  typePat pat        >>>= \(pat,patT,eTVar) ->
  typeDeclScc decls    >>>= \decls ->
  typeRhs rhs >>>= \(rhs,rhsT) ->
  typeUnify (msgPat pat) patT rhsT >>>= \_ ->
--  checkExist [] eTVar >>> 
  unitS (DeclPat (Alt pat rhs decls))
typeDecl (DeclFun pos fun funs) =
  typeIdentDef id pos fun >>>= \ (_,funT) -> 
  typeNewTVar >>>= \retT ->
  getIdent (t_Arrow,TCon) >>>= \arrow ->
  mapS (typeFun fun arrow funT retT) funs >>>= \funs ->
  {-
  typeIdentDef id pos fun >>>= \ (_,funT) -> 
  (\down up@(TypeState state _ _ _) -> 
     trace ('\n':'\n': niceInt Nothing state fun 
            ('\n': niceNT Nothing state (map (\x-> (x,'a':show x)) [1..]) funT))
     (True,up)) >>>= \True ->
  -}
  unitS (DeclFun pos fun funs)


typeFun :: Id -> Id -> NT -> NT -> Fun Id 
        -> State TypeDown TypeState (Fun Id) TypeState

typeFun fun arrow funT retT (Fun args13 rhs decls) =
  mapS fixPat13 args13   >>>= \ args ->
  envPats args       >>>= \ argsE ->
  getEnv	     >>>= \ oldEnv ->
  extendEnv argsE    >=>
  mapS typePat args  >>>= \args ->
  case unzip3 args of
    (args,argsT,eTVar) -> 
       typeUnify (msgFun rhs) funT (funType arrow (argsT++[retT])) >>>= \_ ->
       {-
       (\down up@(TypeState state _ _ _) -> 
         trace ("\n\ntypeFun: " ++ show (length argsT) ++ "  " ++ 
                niceInt Nothing state fun 
               ('\n': niceNT Nothing state 
                        (map (\x -> (x, 'a':show x)) [1..]) funT))
               (True,up)) >>>= \True ->
       -}
       typeDeclScc decls    >>>= \decls ->
       typeRhs rhs >>>= \(rhs,rhsT) ->
       typeUnify (msgFun rhs) retT rhsT >>>= \_ ->
       checkExist oldEnv (concat eTVar) >>> 
       unitS (Fun args rhs decls) -- ,funType arrow (argsT++[gdexpsT])))



typeLit e@(ExpLit pos (LitInteger _ _)) =    --- Add fromInteger
  debugTranslating >>>= \dbgtrans ->
  if dbgtrans then
      getIdent (tInteger,TCon) >>>= \tcon -> unitS (e,NTcons tcon [])
  else
      getIdent (tInteger,TCon) >>>= \ tcon ->
      getIdent (tfromInteger,Var) >>>= \ tfromInteger ->
      typeIdentDict (ExpVar pos) pos tfromInteger >>>= \ (exp,expT) ->
      typeUnifyApply (msgLit pos "integer") [expT,NTcons tcon []] >>>= \ t ->
      unitS (ExpApplication pos [exp,e],t)
typeLit e@(ExpLit pos (LitRational _ _)) =	--- Add fromRational
  debugTranslating >>>= \dbgtrans ->
  if dbgtrans then
      getIdent (tRational,TCon) >>>= \tcon -> unitS (e,NTcons tcon [])
  else
      getIdent (tRational,TCon) >>>= \ tcon ->
      getIdent (tfromRational,Var) >>>= \ tfromRational ->
      typeIdentDict (ExpVar pos) pos tfromRational >>>= \ (exp,expT) ->
      typeUnifyApply (msgLit pos "rational") [expT,NTcons tcon []] >>>= \ t ->
      unitS (ExpApplication pos [exp,e],t)
typeLit e@(ExpLit pos (LitString _ _)) = getIdent (tString,TCon) >>>= \tcon ->
                                         unitS (e,NTcons tcon [])
typeLit e@(ExpLit pos (LitInt _ _))    = getIdent (tInt,TCon)    >>>= \tcon ->
                                         unitS (e,NTcons tcon [])
typeLit e@(ExpLit pos (LitFloat _ _))  = getIdent (tFloat,TCon)  >>>= \tcon ->
                                         unitS (e,NTcons tcon [])
typeLit e@(ExpLit pos (LitDouble _ _)) = getIdent (tDouble,TCon) >>>= \tcon ->
                                         unitS (e,NTcons tcon [])
typeLit e@(ExpLit pos (LitChar _ _))   = getIdent (tChar,TCon)   >>>= \tcon ->
                                         unitS (e,NTcons tcon [])

typeUnifyBool g t =
  getIdent (tBool,TCon) >>>= \ tcon ->
  typeUnify (msgBool g) (NTcons tcon []) t

typeGdExp (g,e) =
  typeExp g >>>= \(g,gT) ->
  typeUnifyBool g gT >>>= \_ ->
  typeExp e >>>= \(e,eT) ->
  unitS ((g,e),eT)


typeRhs (Unguarded e) = typeExp e >>>= \(e,eT) -> unitS (Unguarded e,eT)
typeRhs (Guarded gdexps) =
  mapS typeGdExp gdexps >>>= \ gdexps ->
  case unzip gdexps of
   (gdexps,gdexpsT) -> 
     typeUnifyMany (msgGdExps gdexps) gdexpsT >>>= \ t ->
     unitS (Guarded gdexps,t)


typeAlt (Alt pat13 rhs decls) =
  fixPat13 pat13	    >>>= \pat ->
  envPat pat                >>>= \patE -> 
  getEnv	     >>>= \ oldEnv ->
  extendEnv patE            >=>
  typePat pat               >>>= \ (pat,patT,eTVar) ->
  typeDeclScc decls           >>>= \decls ->
  typeRhs rhs >>>= \(rhs,rhsT) ->
  checkExist oldEnv eTVar >>> 
  unitS (Alt pat rhs decls,(patT,rhsT))


typeExp :: Exp Id -> TypeDown -> TypeState -> ((Exp Id,NT),TypeState)

typeExp (ExpRecord exp fields) = removeExpRecord exp fields >>>= typeExp
typeExp (ExpDo pos stmts) = removeDo stmts >>>= typeExp
typeExp (ExpCase pos exp alts) =
  typeExp exp >>>= \(exp,expT) ->
  mapS typeAlt alts >>>= \alts ->
  case unzip alts of
    (alts,altsT) ->
      case unzip altsT of
	(altsTP,altsTE) ->
          typeUnifyMany (msgAltPats alts) altsTP >>>= \ patT ->
          typeUnify     (msgCase exp)  expT patT >>>= \ _ ->
          typeUnifyMany (msgAltExps alts) altsTE >>>= \ t ->
          unitS (ExpCase pos exp alts,t)

typeExp (ExpIf pos cond exp1 exp2)   =
  typeExp cond           >>>= \ (cond,condT) ->
  typeUnifyBool cond condT    >>>= \_ ->
  typeExp exp1           >>>= \ (exp1,exp1T) ->
  typeExp exp2           >>>= \ (exp2,exp2T) ->
  typeUnify (msgIf exp1 exp2) exp1T exp2T  >>>= \ t ->
  unitS (ExpIf pos cond exp1 exp2,t)

typeExp (ExpApplication pos es)   =
  mapS typeExp es >>>= \es' ->
  case unzip es' of
    (es'',esT) -> 
      typeUnifyApply (msgApply es'') esT >>>= \ t ->
      unitS (ExpApplication pos es'',t)

typeExp e@(ExpVar pos ident)        =
  typeIdentDict (ExpVar pos) pos ident

typeExp (ExpCon pos ident)        =
  typeExpCon pos ident

typeExp e@(ExpLit pos lit)        =
  typeLit e

typeExp (ExpList  pos es)         =
  mapS typeExp es            >>>= \es ->
  case unzip es of
   (es,esT) -> 
     typeUnifyMany (msgList es) esT >>>= \t ->
     getIdent (t_List,TCon)     >>>= \tcon ->
     unitS (ExpList pos es,NTcons tcon [t])
 where
  mapL = map :: ((a->b) -> [a] -> [b])

typeExp (ExpLambda pos pats13 exp)  =
--  phiMark >>>= \ mark ->
  mapS fixPat13 pats13 >>>= \ pats ->
  envPats pats   >>>= \ patsE ->
  getEnv	     >>>= \ oldEnv ->
  extendEnv patsE >=>
  mapS typePat pats   >>>= \ pats ->
  typeExp exp    >>>= \ (exp,expT) ->
  getIdent (t_Arrow,TCon) >>>= \arrow ->
  case unzip3 pats of
     (pats,patsT,eTVar) -> -- phiPrune2 "Lambda" patsE (funType arrow (patsT++[expT])) >>>= \ t ->
		     checkExist oldEnv (concat eTVar) >>> 
		     unitS (ExpLambda pos pats exp,funType arrow (patsT++[expT]))

typeExp (ExpLet pos decls exp)    =
  typeDeclScc decls >>>= \decls ->
  typeExp exp     >>>= \(exp,expT) ->
  unitS (ExpLet pos decls exp,expT)

typeExp (ExpType pos exp ctxs t) = -- Ignoring ctx and doesn't check if the
                                   -- free variables really are free !!!
  (if not (null ctxs) 
  then strace ("Context at " ++ strPos (getPos ctxs)
              ++ " in typed expression is ignored :-(")
  else id) $
  typeExp exp >>>= \ (exp,expT) ->
  let nt = type2NT t
      free = snub (freeNT nt)
  in 
    mapS (\ _ -> typeNewTVar) free >>>= \ free' -> 
    let phi = list2Subst (zip free (map ( \ (NTany a) -> NTvar a) free')) 
    in typeUnify (msgExpType pos) (subst phi nt) expT >>>= \ expT ->
       unitS (exp,expT)

typeExp (PatWildcard pos) =
  typeNewTVar >>>= \tvar ->
  unitS (PatWildcard pos,tvar)

typeExp e =
  getTypeErrors >>>= \errs->
  error ("when typing expression at " ++ strPos (getPos e) ++ "\n"++
         unlines errs)  --  ++ "\n" ++ ppExp False dummyIntState e 0)


-------------------

typePat (ExpApplication pos es)   =
  mapS typePat es >>>= \es ->
  case unzip3 es of
    (es,esT,eTVar) -> 
      typeUnifyApply (msgApply es) esT >>>= \ t ->
      unitS (ExpApplication pos es,t,concat eTVar)

typePat e@(ExpVar pos ident)        =
  typeIdentDict (ExpVar pos) pos ident >>>= \ (e,t) ->
  unitS (e,t,[])

typePat (ExpCon pos ident)        =
  typePatCon pos ident

typePat e@(ExpLit pos lit)        =
  typeLit e >>>= \ (e,t) ->
  unitS (e,t,[])

typePat (ExpList  pos es)         =
  mapS typePat es            >>>= \es ->
  case unzip3 es of
   (es,esT,eTVar) -> 
     typeUnifyMany (msgList es) esT >>>= \t ->
     getIdent (t_List,TCon)     >>>= \tcon ->
     unitS (ExpList pos es,NTcons tcon [t],concat eTVar)
 where
  mapL = map :: ((a->b) -> [a] -> [b])

typePat (ExpType pos exp ctxs t) = -- Ignoring ctx and doesn't check if the
                                   -- free variables really are free !!!
  (if not (null ctxs) 
  then strace ("Context at " ++ strPos (getPos ctxs)
              ++ " in typed expression is ignored :-(")
  else id) $
  typePat exp >>>= \ (exp,expT,eTVar) ->
  let nt = type2NT t
      free = snub (freeNT nt)
  in 
    mapS (\ _ -> typeNewTVar) free >>>= \ free' -> 
    let phi = list2Subst (zip free (map ( \ (NTany a) -> NTvar a) free')) 
    in typeUnify (msgExpType pos) (subst phi nt) expT >>>= \ expT ->
       unitS (exp,expT,eTVar)

typePat (PatAs             pos ident pat) =
  typeIdentDef (PatAs pos) pos ident >>>= \ (patas,identT) ->
  typePat pat     >>>= \ (pat,patT,eTVar) ->
  typeUnify (msgAs pos) identT patT >>>= \ t ->
  unitS (patas pat,t,eTVar)

typePat e@(PatWildcard       pos) = 
  typeNewTVar >>>= \tvar ->
  unitS (e,tvar,[])
typePat (PatIrrefutable    pos pat) =
  typePat pat >>>= \ (pat,patT,eTVar) ->
  unitS (PatIrrefutable pos pat,patT,eTVar)

typePat (PatNplusK         pos n n' k le sub) =
  typeIdentDict (ExpVar pos) pos n  >>>= \ (ExpVar _ n, typN) ->
  typeIdentDict (ExpVar pos) pos n' >>>= \ (ExpVar _ n', typN') ->
  typeExp k                         >>>= \ (k,typK) ->
  typeExp le                        >>>= \ (le,typLE) ->
  typeUnifyBool le typLE            >>>= \ _ ->
  typeExp sub                       >>>= \ (sub,typSUB) ->
  typeUnify (msgNK pos) typK typN   >>>= \ t ->
  typeUnify (msgNK pos) typN' typN  >>>= \ t ->
  typeUnify (msgNK pos) typSUB typN >>>= \ t ->
  unitS (PatNplusK pos n n' k le sub,t,[])

typePat e                         = error ("typePat " ++ strPos (getPos e))


-------------------

-- fixPat13 change 1.3 patterns into 1.2 patterns
-- that is, it removes record patterns.
-- No InfixList at this point!

fixDecl13 (DeclPat (Alt pat gdexps decls)) =
    fixPat13 pat >>>= \ pat -> unitS (DeclPat (Alt pat gdexps decls))
fixDecl13 decl = unitS decl

fixPat13 (ExpRecord	 exp fields)  = 
  removeExpRecord exp fields >>>= fixPat13
fixPat13 (ExpApplication pos pats)    = 
  unitS (ExpApplication pos) =>>> mapS fixPat13 pats
fixPat13 (ExpList        pos pats)    = 
  unitS (ExpList pos)        =>>> mapS fixPat13 pats
fixPat13 (PatAs          pos tid pat) = 
  unitS (PatAs pos tid)      =>>> fixPat13 pat
fixPat13 (PatIrrefutable pos pat)     = 
  unitS (PatIrrefutable pos) =>>> fixPat13 pat
fixPat13 pat  = unitS pat



removeExpRecord :: Exp Id -> [Field Id] -> TypeMonad (Exp Id)
removeExpRecord exp fields =
  getState >>>= \state ->
  case translateExpRecord exp fields state of
    (Right transExp,state') -> setState state' >>> unitS transExp
    (Left error,state') -> setState state' >>> typeError error  

Index

(HTML for this module was generated on May 15, 2003. About the conversion tool.)