USubstitute.hs

module USubstitute(module USubstitute,Free) where
import UAbstract
import Utils2(mapSnd,apFst)
import UFree
--import Debug2(badtrace)
default(Int)

type Subst1 syntax = Exp -> Var -> syntax -> syntax

substitute e' x = subst e' x

class Subst syntax where
  subst :: Subst1 syntax
  substList :: Subst1 [syntax]

  substList e' x = map (subst e' x)

instance Subst a => Subst [a] where
  subst = substList

instance (Subst a,Subst b) => Subst (a,b) where
  subst e' x (e1,e2) = (subst e' x e1,subst e' x e2)

instance (Subst a,Subst b,Subst c) => Subst (a,b,c) where
  subst e' x (e1,e2,e3) = (subst e' x e1,subst e' x e2,subst e' x e3)

instance Subst Con where
  subst _ _ con = con

instance Subst Exp where
  subst e' x expr =
    --badtrace ("subst in "++show expr) $
    case expr of
      EAnnot a e -> EAnnot a (s e)
      EApp e1 e2 -> EApp (s e1) (s e2)
      EVar y   -> if y==x then e' else expr
  --  ECon c es  -> eCon c (map s es)
      ECon c     -> eCon0 c
  --  ELCon c es -> ELCon c (map s es)
      EAbs (y:-t) b ->
	  if y==x
	  then EAbs (y:-t') b
	  else EAbs (y':-t') (s b')
	where
	  (y',b') = avoidNameCapture y b e'
	  t' = s t

      ELet decls b -> ELet (subst e' x decls) b'
	 where b' = if x `elem` namesDecls decls
		    then b
		    else s b
      ETyped e t -> ETyped (s e) (s t)
      EProofOf t e -> EProofOf (s t) (s e)
      ECase e bs -> ECase (s e) (subst e' x bs)
      EPi (y:-t) b -> EPi (y':-s t) (if y==x then b else b')
	where (y',b') = avoidNameCapture y b e'
      ESort s -> expr
      ESum sum -> ESum (subst e' x sum)

      EProj b y -> EProj (s b) y
      ESig sig -> expr --ESig (substSig e' x sig) --!!!
      EStr str -> EStr (subst e' x str)
      EMeta m -> expr
      EChar _ -> expr
      EString _ -> expr
      EInt _ -> expr
      ERat _ -> expr

      --ECom n -> e
      --EExit -> e
    where
      s = subst e' x

instance Subst Decl where

  substList e' x [] = []
  substList e' x (d:ds) =
      if x `elem` namesDecl d
      then substDeclTypes e' x d:ds
      else subst e' x d:substList e' x ds
    where
      substDeclTypes e' x d = d -- !!!

  subst e' x decl =
    case decl of
      (Decl c defs) -> Decl c (map def defs)
      d@(Comment _) -> d
      d@(ImportDecl _) -> d
    where
      def = mapDefB (subst e' x)

instance Subst DefB where
  -- precondition: x `notElem` namesDecls defb ??
  subst e' x defb =
      case defb of
        CommentDef _ -> defb
	Value (n,(ctx,ev,et)) -> Value (n,(s ctx,s' ctx ev,s' ctx et))
	Binding (n,e) -> Binding (n,s e)
	Package (n,(ctx,b)) -> Package (n,(s ctx,s' ctx b))
	Open (e,oargs) -> Open (s e,oargs) -- !!
	Data (n,(ctx,d)) -> Data (n,(s ctx,s' ctx d))
	Type (n,(ctx,e)) -> Type (n,(s ctx,s' ctx e))
	Axiom (n,(ctx,e)) -> Axiom (n,(s ctx,s' ctx e))
    where
      s y = subst e' x y
      s' ctx e = if x `elem` namesCtx ctx then e else s e

instance Subst PackageBody where
  subst e' x b =
    case b of
      PackageDef decls -> PackageDef (subst e' x decls)
      PackageInst e -> PackageInst (subst e' x e)

instance Subst SigPart where
  substList e' x [] = []
  substList e' x (p:ps) = subst e' x p:
			  if x `elem` partNames p
			  then ps
			  else substList e' x ps

  subst e' x (SigField lbl e) = SigField lbl (subst e' x e)
  subst e' x (SigDef def) = SigDef (subst e' x def)

instance Subst Constructor where
  subst e' x (Constr con) = Constr (subst e' x con)

instance Subst Context where
  subst e' x (Ctx l ps) = Ctx l (substBs ps)
   where
     substBs [] = []
     substBs ((y,t):bs) = (y,subst e' x t):
			  if y==x
			  then bs
			  else substBs bs


instance Subst Branch where
  subst e' x br@(Branch (c,(ns,b))) =
      if x `elem` ns
      then br
      else Branch (c,(ns',subst e' x b'))
    where (ns',b') = avoidNameCaptures ns b e'

avoidNameCapture y@(Var s) b e =
    if y `freeIn` e
    then (freshvar,subst (EVar freshvar) y b)
    else (y,b)
  where
    freshvar = head [ x | x<-[Var (s++show n)|n<-[1..]],
	                 not (x `freeIn` b || x `freeIn` e)]

avoidNameCaptures ys b e =
  case ys of
    [] -> ([],b)
    y:ys -> (y':ys',b'')
      where (y',b')   = avoidNameCapture y b e
            (ys',b'') = avoidNameCaptures ys b' e


--if x `freeIn` e then x definitely occurs free in e
--                else x may occur free in e

x `freeIn` expr = x `elem` free expr

{-
x `freeIn` expr =
  --badtrace ("freeIn "++show x++" "++show expr) $
  case expr of
    EAnnot _ e -> x `freeIn` e
    EApp e1 e2 -> x `freeIn` e1 || x `freeIn` e2
    EVar y   -> y==x
--  ECon c es  -> any (x `freeIn`) es
    ECon _     -> False
--  ELCon c es -> any (x `freeIn`) es
    EAbs (y:-t) b -> x `freeIn` t || y/=x && x `freeIn` b

    ELet decls b -> x `freeInDecls` decls ||
		    x `notElem` namesDecls decls && x `freeIn` b
    ECase e bs -> x `freeIn` e || x `freeInBranches` bs
    EPi (y:-t) b  -> x `freeIn` t || y/=x && x `freeIn` b
    ESort s    -> False
    ESum sum   -> x `freeInSum` sum
    EProj b y  -> x `freeIn` b
    ESig sig   -> x `freeInSig` sig
    EStr str   -> x `freeInDecls` str
    EMeta m    -> False
    EProofOf e1 e2 -> x `freeIn` e1 || x `freeIn` e2
    ETyped e1 e2 ->  x `freeIn` e1 || x `freeIn` e2

    EChar _ -> False
    EString _ -> False
    EInt _ -> False
    ERat _ -> False

x `freeInBranches` bs = any (x `freeInBranch`) bs
x `freeInBranch` Branch (c,(ns,e)) = x `notElem` ns && x `freeIn` e

x `freeInSum` sum =
  or [x `freeInCtx` c || x `notElem` namesCtx c && x `freeInComment` cm 
      | (c,cm)<- map (\ (Constr (_,a))->a) sum]

freeInComment x = any (x `freeIn`)

x `freeInDecls` [] = False
x `freeInDecls` (d:ds) =
  x `freeInDecl` d || x `notElem` namesDecl d && x `freeInDecls` ds

x `freeInDecl` d =
    case d of
      (Decl c defs) -> any freeInDef defs -- ok safe approximation
      d@(Comment _) -> False
      d@(ImportDecl _) -> False
  where
    freeInDef (DefA _ defb) = x `freeInDefB` defb

x `freeInDefB` defb =
  case defb of
    CommentDef _ -> False
    Value (n,(ctx,ev,et)) -> x `freeInCtx` ctx ||
			     x `notElem` namesCtx ctx &&
			     ( x `freeIn` et || 
			       x/=n && x `freeIn` ev)
    Binding (n,e) -> x `freeIn` e
    Package (n,(ctx,b)) -> x `freeInCtx` ctx ||
			   x `notElem` namesCtx ctx && x `freeInPkgBody` b
    Open (e,oargs) -> True -- bad safe approximation !!!
    Data (n,(ctx,sum)) -> x `freeInCtx` ctx ||
			  x/=n && x `notElem` namesCtx ctx &&
			  x `freeInSum` sum
    Type (n,(ctx,e)) -> x `freeInCtx` ctx ||
			x `notElem` namesCtx ctx && x `freeIn` e
    Axiom (n,(ctx,e)) -> x `freeInCtx` ctx || x `freeIn` e

x `freeInSig` [] = False
x `freeInSig` (p:ps) =
    freeInPart p || x `notElem` partNames p && x `freeInSig` ps
  where
    freeInPart p =
      case p of
	SigDef def -> x `freeInDefB` def
	SigField lbl e -> x `freeIn` e

x `freeInCtx` (Ctx _ bs) = freeInBs bs
  where
    freeInBs [] = False
    freeInBs ((y,e):bs) = x `freeIn` e || y/=x && freeInBs bs

x `freeInPkgBody` body =
  case body of
    PackageDef decls -> x `freeInDecls` decls
    PackageInst e -> x `freeIn` e
-}

Plain-text version of USubstitute.hs | Valid HTML?