HaRe-0.6: tools/base/SA/ExampleScope.hs
-- $Id: ExampleScope.hs,v 1.2 2001/04/25 17:38:00 moran Exp $
module ExampleScope where
import Syntax
import List(find, nub, nubBy, (\\), sortBy, groupBy, union)
import Maybe
import SyntaxUtil(getTyName)
import Scope(Senv(..),patBound,allNames,allTypNames
,instPatToParts,typePatToParts,boundInP
,fst3,fst4,env0,freeT,freeC,restrictTvar)
import Scope2
-------------------------------------------------------------------------
-- free variable example
join (x,y) (a,b) = (x++a,y++b)
extFree :: Bind -> ([HsName],[HsName]) -> ([HsName],[HsName])
extFree (Bpat loc pat) (ev,tv) = (boundInP pat ev,tv)
extFree (Bpats loc ps) (ev,tv) = (foldr boundInP ev ps,tv)
extFree (Bname loc nm) (ev,tv) = (nm:ev,tv)
extFree (Bdecls ds) (ev,tv) =
let v = allNames ds env0
in (map fst (varNames v) ++ map fst3 (constrNames v) ++ ev
,map fst4 (classNames v) ++ (tvarNames v) ++ map fst4 (tconstrNames v) ++ tv)
extFree (Btypat tag tp) (ev,tv) =
let (tvs, cs) = allTypNames tp ([], [])
in (ev,cs ++ tvs ++ tv)
extFree (Btypats tag tps) (ev,tv) =
let (tvs,cs) = allTypNames (hsTyTuple tps) ([],[])
in (ev,cs ++ tvs ++ tv)
extFree (Btyvar nm) (ev,tv) = (ev,nm : tv)
freelib = Sc extFree id
-----------------------------------------------------------------------
-- When computing free variables type-patterns usually act like binding
-- occurences, so their are no free type-vars in a type-pattern. There
-- is one excpetion and that is in the declarations which make up the
-- where clause of a class definition, then the type patterns inside a
-- type-signature play a different role. The type variables in these
-- type-signatures are not binding, but are in the scope of the type
-- variables introduced by the type-pattern declaring the class.
--
-- class T x where <- x is bound here
-- f :: Int -> y -> x <- vars here are free, so y is free
-- g x = x + h 1
-- where h :: x -> x <- these x's are binding
-- h z = z
--
-- This is tricky to handle correctly, since default declarations, may
-- have internal type-signatures which don't obey these special rules
-- but obey the normal rules for type patterns. So we'll parameterize
-- freeD by a boolean that tells if we're immediately inside a Class
-- and make a special mapD function to propogate that information
mapD2 ef pf df tf cf tpf decl =
case decl of
HsClassDecl s c tp ds -> HsClassDecl s (cf c) (tpf tp) (df True ds)
y -> mapD ef pf (df False) tf cf tpf y
----------------------------------------------------------
freeE :: HsExp -> ([HsName],[HsName]) -> ([HsName],[HsName])
freeE (Exp x) (env @ (ev,tv)) =
case x of
HsId(HsVar s) -> if elem s ev then ([],[]) else ([s],[])
x -> accE join join join join join
(scopeE freelib env (mapE freeE freeP (freeD False) freeT2 freeC2 x))
([],[])
freeP :: HsPat -> (HsPat,([HsName],[HsName]) -> ([HsName],[HsName]))
freeP p = (p,const ([],[]))
freeD :: Bool -> [HsDecl] -> ([HsDecl],([HsName],[HsName])->([HsName],[HsName]))
freeD inClass ds = (ds,free)
where free env = let v0 = extFree (Bdecls ds) env
in (foldr (eachd v0) ([],[]) ds)
needSpecialRule (HsTypeSig loc nms c t) = inClass
needSpecialRule other = False
eachd env (Dec d) ans =
if needSpecialRule d
then let (HsTypeSig loc nms c t) = d
in (freeC2 c env) `join` (freeT2 t env) `join` ans
else accD join join join join join join
(scopeD freelib env
(mapD2 freeE freeP freeD freeT2 freeC2 freeTP d))
ans
instance Show (a -> b) where
show g = "<fun>"
freeTP :: HsType -> (HsType,([HsName],[HsName]) -> ([HsName],[HsName]))
freeTP tp = (tp,free)
where free (ev,tv) = ([],[])
freeT2 :: HsType -> ([HsName],[HsName]) -> ([HsName],[HsName])
freeT2 t (ev,tv) = ([],freeT t tv)
freeC2 :: [HsType] -> ([HsName],[HsName]) -> ([HsName],[HsName])
freeC2 cs (ev,tv) = ([],freeC cs tv)
testD ds = let (_,f) = freeD False ds in f (extFree (Bdecls ds) ([],[]))
-------------------------------------------------------------------------
-- Example extend function for the static env Senv of the static checker
extTvar nm env = env {tvarNames = (nm) : tvarNames env}
extend :: Bind -> Senv -> Senv
extend (Bpat loc pat) env = foldr extName env uniqueNames
where (uniqueNames,dups,constrArities) = patBound pat ([],[],[])
extName nm env = env {varNames = (nm,loc) : varNames env}
extend (Bpats loc ps) env = foldr extend env (map (Bpat loc) ps)
extend (Bdecls ds) env = allNames ds env
extend (Bname loc nm) env = env {varNames = (nm,loc) : varNames env}
extend (Btypat tag tp) env =
case tag of
ClassTag -> -- (Env e x) -- expects (C v1 ... vn)
let (constr, tvs) = typePatToParts tp
in foldr extTvar env tvs
InstTag -> -- (Env [Int] Bool) -- expects (C t1 ... tn)
let (classname, ts) = instPatToParts tp
(tvs, cs) = foldr allTypNames ([], []) ts
in foldr extTvar env tvs
SigTag -> -- (e : typ)
let (tvs, cs) = allTypNames tp ([], [])
in foldr extTvar env tvs
extend (Btypats tag (tps @ (constr : args))) env =
case tag of
DataTPS -> foldr (\ t e -> extTvar (getTyName t) e) env tps
TypeTPS -> foldr (\ t e -> extTvar (getTyName t) e) env args
staticlib = Sc extend restrictTvar
getd = freeD