{- CAO Compiler
Copyright (C) 2014 Cryptography and Information Security Group, HASLab - INESC TEC and Universidade do Minho
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . -}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-
Module : $Header$
Description : Syntax manipulation utils.
Copyright : (C) 2014 Cryptography and Information Security Group, HASLab - INESC TEC and Universidade do Minho
License : GPL
Maintainer : Paulo Silva
Stability : experimental
Portability : non-portable ()
General functions for AST manipulation or query are provided.
-}
module Language.CAO.Syntax.Utils
(-- * Variable manipulation
FV ( fvs )
, BV ( bvs )
, RN ( (<|>) )
, Renamable(..)
, Subst ( subst )
, IsVar
, lvname
, lvalNames
, globals
, getVars
, getLVars
, getRVars
, sameKind
-- * Sequences
, isAscSeq
-- * AST Queries
, isSimpleLVal
, isAssignStmt
, isLit
, isIntLit
, isSimpleVDecl
, isReturn
, defVar
, getDeclVar
, isRange
, isEqNeq
, type2TyDecl
, Typeable(typeOf)
) where
import Data.IntMap ( IntMap )
import qualified Data.IntMap as IntMap
import Data.List ( foldl' )
import Data.Map ( Map )
import qualified Data.Map as Map
import Data.Set ( Set )
import qualified Data.Set as Set
import Language.CAO.Common.Literal
import Language.CAO.Common.Outputable
import Language.CAO.Common.Polynomial
import Language.CAO.Common.SrcLoc
import Language.CAO.Common.Utils ( mapSnd )
import Language.CAO.Common.Var
import Language.CAO.Index
import Language.CAO.Index.Utils
import Language.CAO.Syntax
import Language.CAO.Type
import Language.CAO.Type.Utils
type family VarOf f :: *
type instance VarOf Name = Name
type instance VarOf Var = Var
type instance VarOf (Maybe a) = VarOf a
type instance VarOf [a] = VarOf a
type instance VarOf (Located a) = VarOf a
type instance VarOf (Either a a) = VarOf a
type instance VarOf (Prog a) = a
type instance VarOf (Def a) = a
type instance VarOf (VarDecl a) = a
type instance VarOf (ConstAnn a) = a
type instance VarOf (ConstDecl a) = a
type instance VarOf (Fun a) = a
type instance VarOf (TyDef a) = a
type instance VarOf (TyDecl a) = a
type instance VarOf (Expr a) = a
type instance VarOf (TExpr a) = a
type instance VarOf (BinOp a) = a
type instance VarOf (Stmt a) = a
type instance VarOf (Arg a) = a
type instance VarOf (Mod a) = a
type instance VarOf (Pol a) = a
type instance VarOf (Mon a) = a
type instance VarOf (MCoef a) = a
type instance VarOf (MBase a) = a
type instance VarOf (APat a) = a
type instance VarOf (RowAPat a) = a
type instance VarOf (Literal a) = a
type instance VarOf (LVal a) = a
type instance VarOf (Type a) = a
type instance VarOf (Class a) = a
type instance VarOf (ICond a) = a
type instance VarOf (IExpr a) = a
type family SubstOf f :: *
type instance SubstOf Name = Name
type instance SubstOf Var = Var
type instance SubstOf (Maybe a) = SubstOf a
type instance SubstOf [a] = SubstOf a
type instance SubstOf (Located a) = SubstOf a
type instance SubstOf (Prog a) = Expr a
type instance SubstOf (Def a) = Expr a
type instance SubstOf (VarDecl a) = Expr a
type instance SubstOf (ConstDecl a) = Expr a
type instance SubstOf (Fun a) = Expr a
type instance SubstOf (TyDef a) = Expr a
type instance SubstOf (TyDecl a) = Expr a
type instance SubstOf (Expr a) = Expr a
type instance SubstOf (TExpr a) = Expr a
type instance SubstOf (BinOp a) = Expr a
type instance SubstOf (Stmt a) = Expr a
type instance SubstOf (Arg a) = Expr a
type instance SubstOf (Mod a) = Expr a
type instance SubstOf (Pol a) = IExpr a
type instance SubstOf (Mon a) = IExpr a
type instance SubstOf (MCoef a) = IExpr a
type instance SubstOf (MBase a) = Expr a
type instance SubstOf (APat a) = Expr a
type instance SubstOf (RowAPat a) = Expr a
type instance SubstOf (Literal a) = Expr a
type instance SubstOf (LVal a) = Expr a
type instance SubstOf (Type a) = IExpr a
type instance SubstOf (Class a) = Expr a
type instance SubstOf (ICond a) = IExpr a
type instance SubstOf (IExpr a) = IExpr a
class (FV id, BV id, Ord id, PP id, RN id) => IsVar id where
instance IsVar Name where
instance IsVar Var where
--------------------------------------------------------------------------------
-- Free variables
--------------------------------------------------------------------------------
-- | Free variables
class FV f where
fvs :: (Ord b, VarOf f ~ b) => f -> Set b
fvsLst :: (Ord b, VarOf f ~ b) => [f] -> Set b
fvsLst = Set.unions . map fvs
instance FV a => FV (Maybe a) where
fvs Nothing = Set.empty
fvs (Just a) = fvs a
instance FV a => FV (Located a) where
fvs (L _ a) = fvs a
instance FV a => FV [a] where
fvs = fvsLst
instance (FV a, a ~ b) => FV (Either a b) where
fvs (Left l) = fvs l
fvs (Right r) = fvs r
instance FV Name where
fvs = Set.singleton
instance FV Var where
fvs = Set.singleton
instance (IsVar a, a ~ VarOf a) => FV (Def a) where
fvs (VarDef vd) = fvs vd
fvs (FunDef fd) = fvs fd
fvs (TyDef td) = fvs td
fvs (ConstDef cd) = fvs cd
instance (IsVar a, a ~ VarOf a) => FV (VarDecl a) where
fvs (VarD v td me) = (fvs td `Set.union` fvs me) Set.\\ fvs v
fvs (MultiD vs td) = fvs td Set.\\ fvs vs
fvs (ContD v td es) = (fvs td `Set.union` fvs es) Set.\\ fvs v
instance (IsVar a, a ~ VarOf a) => FV (ConstAnn a) where
fvs None = Set.empty
fvs (ConstInit e) = fvs e
fvs (ConstCond c) = fvs c
instance (IsVar a, a ~ VarOf a) => FV (ConstDecl a) where
fvs (ConstD v td i) = (fvs td `Set.union` fvs i) Set.\\ fvs v
fvs (MultiConstD vs td c) = (fvs td `Set.union` fvs c) Set.\\ fvs vs
instance (IsVar a, a ~ VarOf a) => FV (Fun a) where
fvs (Fun v args rt body) = (fvs body `Set.union` fvs rt)
Set.\\ (fvs v `Set.union` fvs args)
instance (IsVar a, a ~ VarOf a) => FV (Arg a) where
fvs (Arg a _) = fvs a
fvs (ArgConst a _ _) = fvs a
instance (IsVar a, a ~ VarOf a) => FV (TyDef a) where
fvs (TySynDef v td)
= fvs td Set.\\ fvs v
fvs (StructDecl v flds)
= Set.unions (map (fvs . snd) flds)
Set.\\ Set.unions (fvs v: map (fvs . fst) flds)
instance (IsVar a, a ~ VarOf a) => FV (TyDecl a) where
fvs IntD = Set.empty
fvs RIntD = Set.empty
fvs BoolD = Set.empty
fvs (BitsD _ e) = fvs e
fvs (ModD m) = fvs m
fvs (VectorD e td) = fvs e `Set.union` fvs td
fvs (MatrixD e1 e2 td) = fvs e1 `Set.union` fvs e2 `Set.union` fvs td
fvs (TySynD v) = fvs v
instance (IsVar a, a ~ VarOf a) => FV (Mod a) where
fvs (ModNum e) = fvs e
fvs (ModPol td ti pol) = (fvs td `Set.union` fvs pol) Set.\\ fvs ti
instance (IsVar a, a ~ VarOf a) => FV (TExpr a) where
fvs (TyE _ e) = fvs e
instance (IsVar a, a ~ VarOf a) => FV (Expr a) where
fvs (Var v) = fvs v
fvs (Lit l) = fvs l
fvs (FunCall v args) = fvs v `Set.union` fvs args
fvs (StructProj e fi) = fvs e `Set.union` fvs fi
fvs (UnaryOp _ e) = fvs e
fvs (BinaryOp _ e1 e2) = fvs e1 `Set.union` fvs e2
fvs (Access e1 pat) = fvs e1 `Set.union` fvs pat
fvs (Cast _ td e) = fvs td `Set.union` fvs e
instance (IsVar a, a ~ VarOf a) => FV (BinOp a) where
fvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => FV (Literal a) where
fvs (PLit p) = fvs p
fvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => FV (APat a) where
fvs (VectP rp) = fvs rp
fvs (MatP rp cp) = fvs rp `Set.union` fvs cp
instance (IsVar a, a ~ VarOf a) => FV (RowAPat a) where
fvs (CElem e) = fvs e
fvs (CRange e1 e2) = fvs e1 `Set.union` fvs e2
instance (IsVar a, a ~ VarOf a) => FV (Stmt a) where
fvs (VDecl vd) = fvs vd
fvs (CDecl cd) = fvs cd
fvs (Assign lvs es) = fvs lvs `Set.union` fvs es
fvs (FCallS n es) = fvs n `Set.union` fvs es
fvs (Ret e) = fvs e
fvs (Ite i t e) = fvs i `Set.union` fvs t `Set.union` fvs e
fvs (Seq (SeqIter v s e b _) ss) =
(fvs s `Set.union` fvs e `Set.union` fvs b `Set.union` fvs ss)
Set.\\ fvs v
fvs (While e ss) = fvs e `Set.union` fvs ss
fvs (Nop _) = Set.empty
fvsLst [] = Set.empty
fvsLst (VDecl vd:ss) = fvs ss Set.\\ fvs vd
fvsLst (s:ss) = fvs s `Set.union` fvs ss
instance (IsVar a, a ~ VarOf a) => FV (LVal a) where
fvs (LVVar v) = fvs v
fvs (LVStruct lv fi) = fvs lv `Set.union` fvs fi
fvs (LVCont _ lv p) = fvs lv `Set.union` fvs p
instance (IsVar a, a ~ VarOf a) => FV (Pol a) where
fvs (Pol ms) = fvs ms
instance (IsVar a, a ~ VarOf a) => FV (Mon a) where
fvs (Mon c b) = fvs c `Set.union` fvs b
instance (IsVar a, a ~ VarOf a) => FV (MCoef a) where
fvs (CoefI _) = Set.empty
fvs (CoefP p) = fvs p
instance (IsVar a, a ~ VarOf a) => FV (MBase a) where
fvs EZero = Set.empty
fvs (MExpI n _) = fvs n
instance (IsVar a, a ~ VarOf a) => FV (Type a) where
fvs Int = Set.empty
fvs RInt = Set.empty
fvs Bool = Set.empty
fvs Bullet = Set.empty
fvs (Bits _ e) = fvs e
fvs (Indet t) = fvs t
fvs (Tuple ts) = fvs ts
fvs (Vector e t) = fvs e `Set.union` fvs t
fvs (TySyn v t) = fvs v `Set.union` fvs t
fvs (SField v t) = fvs v `Set.union` fvs t
fvs (Mod mty e p) = Set.unions [fvs mty, fvs e, fvs p]
fvs (Matrix e1 e2 t) = Set.unions [fvs e1, fvs e2, fvs t]
fvs (FuncSig ts t c) = Set.unions [fvs ts, fvs t, fvs c]
fvs (Struct v fs) = Set.unions [fvs v, fvs (map fst fs),
fvs (map snd fs)]
fvs (Index v mc t) = Set.unions [fvs v, fvs mc, fvs t]
fvs (TyVar _) = Set.empty
fvs (IntVar _) = Set.empty
fvs (ModVar _) = Set.empty
instance (IsVar a, a ~ VarOf a) => FV (IExpr a) where
fvs (IInt _) = Set.empty
fvs (IInd v) = Set.singleton v
fvs (ISum es) = fvs es
fvs (IArith _ e1 e2) = fvs e1 `Set.union` fvs e2
fvs (ISym e) = fvs e
instance (IsVar a, a ~ VarOf a) => FV (ICond a) where
fvs (IBool _) = Set.empty
fvs (IBInd v) = Set.singleton v
fvs (INot c) = fvs c
fvs (IAnd cs) = fvs cs
fvs (IBoolOp _ e1 e2) = fvs e1 `Set.union` fvs e2
fvs (ILeq e) = fvs e
fvs (IEq e) = fvs e
instance (IsVar a, a ~ VarOf a) => FV (Class a) where
fvs _ = Set.empty
--------------------------------------------------------------------------------
-- Bound variables (defs, args, etc ...)
-- * The bound variables of fun/proc definition are it's local variables
--------------------------------------------------------------------------------
-- | Bound variables (defs, args, etc ...)
-- The bound variables of function/procedure definition are its local variables.
class BV f where
bvs :: (Ord b, VarOf f ~ b) => f -> Set b
instance BV a => BV (Maybe a) where
bvs Nothing = Set.empty
bvs (Just a) = bvs a
instance BV a => BV (Located a) where
bvs (L _ a) = bvs a
instance BV a => BV [a] where
bvs = Set.unions . map bvs
globals :: Prog Var -> Set Var
globals = Set.filter isGlobal . bvs
instance (IsVar a, a ~ VarOf a) => BV (Prog a) where
bvs (Prog defs ip) = bvs defs `Set.union` maybe Set.empty bvs ip
instance (IsVar a, a ~ VarOf a) => BV (Def a) where
bvs (VarDef vd) = bvs vd
bvs (FunDef fd) = bvs fd
bvs (TyDef td) = bvs td
bvs (ConstDef cd) = bvs cd
instance (IsVar a, a ~ VarOf a) => BV (VarDecl a) where
bvs (VarD v _ _) = fvs v
bvs (MultiD vs _) = fvs vs
bvs (ContD v _ _) = fvs v
instance (IsVar a, a ~ VarOf a) => BV (ConstDecl a) where
bvs (ConstD v _ _) = fvs v
bvs (MultiConstD vs _ _) = fvs vs
instance (IsVar a, a ~ VarOf a) => BV (Fun a) where
bvs (Fun v args _ body) = bvs body `Set.union` fvs v `Set.union` fvs args
instance (IsVar a, a ~ VarOf a) => BV (TyDef a) where
bvs (TySynDef v _)
= fvs v
bvs (StructDecl v flds)
= Set.unions $ fvs v : map (fvs . fst) flds
instance (IsVar a, a ~ VarOf a) => BV (Mod a) where
bvs (ModNum _) = Set.empty
bvs (ModPol _ ti _) = fvs ti
instance (IsVar a, a ~ VarOf a) => BV (Stmt a) where
bvs (VDecl vd) = bvs vd
bvs (CDecl cd) = bvs cd
bvs (Ite _ t e) = bvs t `Set.union` bvs e
bvs (Seq (SeqIter v _ _ _ _) ss) = fvs v `Set.union` bvs ss
bvs (While _ ss) = bvs ss
bvs _ = Set.empty
instance BV Name where
bvs _ = Set.empty
instance BV Var where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (Arg a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (TyDecl a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (TExpr a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (Expr a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (BinOp a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (Literal a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (APat a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (RowAPat a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (LVal a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (Pol a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (Mon a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (MCoef a) where
bvs _ = Set.empty
instance (IsVar a, a ~ VarOf a) => BV (MBase a) where
bvs _ = Set.empty
--------------------------------------------------------------------------------
-- Variable substitution
--------------------------------------------------------------------------------
infixl 7 ~>
infixl 6 +>
infixl 5 \\
infixl 4 .$.
infixr 4 <|>
-- | Variable substitution
class (IsVar v1, IsVar v2) => Renamable v1 v2 where
-- | Remaning environment
data SEnv v1 v2 :: *
-- | Capture predicate
captures :: SEnv v1 v2 -> Set v1 -> Set v1 -> Bool
-- | Empty renaming environment
emptyRN :: SEnv v1 v2
-- | Singleton environment where substitution @v1 -> v2@ is stored
(~>) :: v1 -> v2 -> SEnv v1 v2
-- | Returns the variable that should replace @v1@ from the remaing
-- environment
(.$.) :: SEnv v1 v2 -> v1 -> v2
-- | (Left-biased) Union of two renaming environments
(+>) :: SEnv v1 v2 -> SEnv v1 v2 -> SEnv v1 v2
-- | Removes a set of variables from the domain of the renaming
-- environment
(\\) :: SEnv v1 v2 -> Set v1 -> SEnv v1 v2
instance Renamable Name Name where
data SEnv Name Name = NN (Map Name Name)
captures (NN s) bs
= Set.fold goC False
where goC _ True
= True
goC f False
| Just fv <- Map.lookup f s = fv `Set.member` bs
| otherwise = False
emptyRN = NN Map.empty
v1 ~> v2 = NN $ Map.insert v1 v2 Map.empty
NN s2 +> NN s1 = NN $ Map.union s1 s2
NN s \\ v = NN $ Set.fold Map.delete s v
NN s .$. v
| Just v' <- Map.lookup v s = v'
| otherwise = v
instance Renamable Var Var where
data SEnv Var Var = VV (IntMap Var)
captures (VV s) bs
= Set.fold goC False
where goC _ True
= True
goC f False
| Just fv <- IntMap.lookup (varId f) s
= fv `Set.member` bs
| otherwise
= False
emptyRN = VV IntMap.empty
v1 ~> v2 = VV $ IntMap.insert (varId v1) v2 IntMap.empty
VV s2 +> VV s1 = VV $ IntMap.union s1 s2
VV s \\ v = VV $ Set.fold (\a b -> IntMap.delete (varId a) b) s v
f@(VV s) .$. v
| Just v' <- IntMap.lookup (varId v) s = setType (varType v' <|> f) v'
| otherwise = v
-- In substitutions from Name to Var, all variables MUST be in the renaming
-- environment
instance Renamable Name Var where
data SEnv Name Var = NV (Map Name Var)
captures (NV s) bs
= Set.fold goC False
where goC _ True
= True
goC f False
| Just fv <- Map.lookup f s = varName fv `Set.member` bs
| otherwise = False
emptyRN = NV Map.empty
v1 ~> v2 = NV $ Map.insert v1 v2 Map.empty
NV s2 +> NV s1 = NV $ Map.union s1 s2
NV s \\ v = NV $ Set.fold Map.delete s v
NV s .$. v
| Just v' <- Map.lookup v s = v'
| otherwise = error $ ".\
\: Not in scope" ++ showPprDebug v
--------------------------------------------------------------------------------
-- Types where substitution is defined
type family RNTy t v :: *
type instance RNTy Name t = t
type instance RNTy Var t = t
type instance RNTy [a] b = [RNTy a b]
type instance RNTy (Maybe a) b = Maybe (RNTy a b)
type instance RNTy (Located a) b = Located (RNTy a b)
type instance RNTy (Prog a) b = Prog (RNTy a b)
type instance RNTy (Def a) b = Def (RNTy a b)
type instance RNTy (Fun a) b = Fun (RNTy a b)
type instance RNTy (TyDef a) b = TyDef (RNTy a b)
type instance RNTy (VarDecl a) b = VarDecl (RNTy a b)
type instance RNTy (LVal a) b = LVal (RNTy a b)
type instance RNTy (Stmt a) b = Stmt (RNTy a b)
type instance RNTy (Arg a) b = Arg (RNTy a b)
type instance RNTy (Literal a) b = Literal (RNTy a b)
type instance RNTy (Class a) b = Class (RNTy a b)
type instance RNTy (Type a) b = Type (RNTy a b)
type instance RNTy (Mod a) b = Mod (RNTy a b)
type instance RNTy (TyDecl a) b = TyDecl (RNTy a b)
type instance RNTy (APat a) b = APat (RNTy a b)
type instance RNTy (RowAPat a) b = RowAPat (RNTy a b)
type instance RNTy (Expr a) b = Expr (RNTy a b)
type instance RNTy (TExpr a) b = TExpr (RNTy a b)
type instance RNTy (BinOp a) b = BinOp (RNTy a b)
type instance RNTy (Pol a) b = Pol (RNTy a b)
type instance RNTy (Mon a) b = Mon (RNTy a b)
type instance RNTy (MCoef a) b = MCoef (RNTy a b)
type instance RNTy (MBase a) b = MBase (RNTy a b)
type instance RNTy (ICond a) b = ICond (RNTy a b)
type instance RNTy (IExpr a) b = IExpr (RNTy a b)
-- INVARIANT: Variable capture MUST NOT happen.
-- | Renamables for variables types
class RN t where
(<|>) :: (Renamable v0 v, VarOf t ~ v0, VarOf v0 ~ v0)
=> t -> SEnv v0 v -> RNTy t v
substLst :: (Renamable v0 v, VarOf t ~ v0, VarOf v0 ~ v0)
=> [t] -> SEnv v0 v -> [RNTy t v]
substLst lst f = map (<|> f) lst
-- Renamables for variable types
instance RN Name where
n <|> s = s .$. n
instance RN Var where
n <|> s = s .$. n
rnTuple :: (Renamable v0 c,
RN a, RN b,
VarOf a ~ v0, VarOf b ~ v0, VarOf v0 ~ v0)
=> (a, b) -> SEnv v0 c -> (RNTy a c, RNTy b c)
rnTuple (a,b) f = (a <|> f, b <|> f)
-- Renamables for containers
instance RN a => RN [a] where
lst <|> f = substLst lst f
instance RN a => RN (Maybe a) where
Nothing <|> _ = Nothing
(Just v) <|> f = Just $ v <|> f
instance RN a => RN (Located a) where
(L l v) <|> f = L l $ v <|> f
-- Substitution of top-level variables:
-- > Substitute all variables except local vars bound
-- > by local variables.
--
-- Example:
-- def v0 : ...
--
-- def f ( ... v0 ...) { ... v0 ... }
-- def g ( ... ) { ... v0 ... }
--
-- subst v0 ~> v1
--
-- def v1 : ...
--
-- def f ( ... v0 ...) { ... v0 ... }
-- def g ( ... ) { ... v1 ... }
--
instance RN a => RN (Prog a) where
Prog defs ip <|> f = Prog (defs <|> f) (ip <|> f)
instance RN a => RN (Def a) where
VarDef vd <|> f = VarDef $ vd <|> f
FunDef vd <|> f = FunDef $ vd <|> f
TyDef vd <|> f = TyDef $ vd <|> f
_ <|> _ = error ".\
\: Not defined!"
substLst [] _ = []
substLst (d:ds) f
| captures f (bvs d) (fvs ds)
= error ".\
\: Variable capture!"
| otherwise
= (d <|> f) : substLst ds f
instance RN a => RN (Fun a) where
Fun n args rt stmts <|> f
| captures f bs fs
= error ".\
\: Variable capture!"
| otherwise
= Fun n' args' rt' stmts'
where n' = n <|> f'
args' = args <|> f'
rt' = rt <|> f'
stmts' = stmts <|> f'
f' = f \\ bs
fs = fvs args `Set.union` fvs stmts
bs = fvs n `Set.union` fvs args
instance RN a => RN (TyDef a) where
TySynDef n td <|> f
= TySynDef (n <|> f') (td <|> f')
where f' = f \\ fvs n
StructDecl n flds <|> f
= StructDecl (n <|> f') (map (`rnTuple` f') flds)
where f' = f \\ fvs n `Set.union` fvs (map fst flds)
instance RN a => RN (VarDecl a) where
VarD n td i <|> f = VarD (n <|> f') (td <|> f') (i <|> f')
where f' = f \\ fvs n
MultiD ns td <|> f = MultiD (ns <|> f') (td <|> f')
where f' = f \\ fvs ns
ContD n td is <|> f = ContD (n <|> f') (td <|> f') (is <|> f')
where f' = f \\ fvs n
instance RN a => RN (LVal a) where
LVVar v <|> f = LVVar $ v <|> f
LVStruct lv fi <|> f = LVStruct (lv <|> f) (fi <|> f)
LVCont t lv pat <|> f = LVCont (t <|> f) (lv <|> f) (pat <|> f)
instance RN a => RN (Stmt a) where
VDecl vd <|> f =
VDecl (vd <|> f)
Assign lvs es <|> f =
Assign (lvs <|> f) (es <|> f)
FCallS n es <|> f =
FCallS (n <|> f) (es <|> f)
Ret e <|> f =
Ret (e <|> f)
Ite i t e <|> f =
Ite (i <|> f) (t <|> f) (e <|> f)
Seq (SeqIter v s e b r) ss <|> f
| captures f (fvs v) freevs
= error ".:\
\ variable capture!"
| otherwise
= Seq ( SeqIter (v <|> f')
(s <|> f')
(e <|> f')
(b <|> f')
r )
( ss <|> f' )
where freevs = fvs s
`Set.union` fvs e
`Set.union` fvs b
`Set.union` fvs ss
f' = f \\ fvs v
While e ss <|> f =
While (e <|> f) (ss <|> f)
Nop a <|> _ = Nop a
_ <|> _ = error ".\
\: Not defined!"
substLst [] _
= []
substLst (s:ss) f
| captures f (bvs s) (fvs ss)
= error ".\
\: Variable capture!"
| otherwise
= (s <|> f) : substLst ss f
instance RN a => RN (Arg a) where
Arg n td <|> f = Arg (n <|> f) (td <|> f)
_ <|> _ = error ".\
\: Not defined!"
substLst [] _ = []
substLst (a:as) f
| captures f (fvs a) (fvs as)
= error ".\
\: Variable capture!"
| otherwise
= (a <|> f) : substLst as f
instance RN a => RN (Literal a) where
ILit p <|> _ = ILit p
BLit p <|> _ = BLit p
BSLit s p <|> _ = BSLit s p
PLit p <|> f = PLit $ p <|> f
instance RN a => RN (Class a) where
Pure <|> _ = Pure
RO <|> _ = RO
Proc lst <|> f = Proc $ lst <|> f
instance RN a => RN (Type a) where
Index v c t <|> f = Index (v <|> f) (c <|> f) (t <|> f)
Mod ty ti p <|> f = Mod (ty <|> f) (ti <|> f) (p <|> f)
Vector i ty <|> f = Vector (i <|> f) (ty <|> f)
Matrix i j ty <|> f = Matrix (i <|> f) (j <|> f) (ty <|> f)
TySyn n ty <|> f = TySyn (n <|> f) (ty <|> f)
FuncSig args rt c <|> f = FuncSig (args <|> f) (rt <|> f) (c <|> f)
Struct n flds <|> f = Struct (n <|> f) (map (`rnTuple` f) flds)
SField n ty <|> f = SField (n <|> f) (ty <|> f)
Indet ty <|> f = Indet (ty <|> f)
Tuple tys <|> f = Tuple (tys <|> f)
Bits s n <|> f = Bits s (n <|> f)
Int <|> _ = Int
RInt <|> _ = RInt
Bool <|> _ = Bool
Bullet <|> _ = Bullet
-- These should not be needed in the end
TyVar n <|> _ = TyVar n
IntVar n <|> _ = IntVar n
ModVar n <|> _ = ModVar n
instance RN a => RN (Mod a) where
ModNum e <|> f = ModNum $ e <|> f
ModPol td ti pol <|> f = ModPol (td <|> f) (ti <|> f) (pol <|> f)
instance RN a => RN (TyDecl a) where
IntD <|> _ = IntD
RIntD <|> _ = RIntD
BoolD <|> _ = BoolD
BitsD s e <|> f = BitsD s $ e <|> f
ModD m <|> f = ModD $ m <|> f
VectorD e td <|> f = VectorD (e <|> f) (td <|> f)
MatrixD e1 e2 td <|> f = MatrixD (e1 <|> f) (e2 <|> f) (td <|> f)
TySynD v <|> f = TySynD (v <|> f)
instance RN a => RN (APat a) where
VectP rp <|> f = VectP $ rp <|> f
MatP rp cp <|> f = MatP (rp <|> f) (cp <|> f)
instance RN a => RN (RowAPat a) where
CElem e <|> f = CElem $ e <|> f
CRange e1 e2 <|> f = CRange (e1 <|> f) (e2 <|> f)
instance RN a => RN (TExpr a) where
TyE ty e <|> f = TyE (ty <|> f) (e <|> f)
instance RN a => RN (Expr a) where
Var v <|> f = Var $ v <|> f
Lit l <|> f = Lit (l <|> f)
FunCall n args <|> f = FunCall (n <|> f) (args <|> f)
StructProj e fi <|> f = StructProj (e <|> f) (fi <|> f)
UnaryOp op e <|> f = UnaryOp op $ e <|> f
BinaryOp op e1 e2 <|> f = BinaryOp (op <|> f) (e1 <|> f) (e2 <|> f)
Access td pat <|> f = Access (td <|> f) (pat <|> f)
Cast b td e <|> f = Cast b (td <|> f) (e <|> f)
instance RN a => RN (BinOp a) where
ArithOp op <|> _ = ArithOp op
BoolOp op <|> _ = BoolOp op
BitOp op <|> _ = BitOp op
BitsSROp op <|> _ = BitsSROp op
CmpOp ty op <|> f = CmpOp (ty <|> f) op
Concat <|>_ = Concat
-- Renaming for polynomials
instance RN a => RN (Pol a) where
Pol ms <|> f = Pol $ ms <|> f
instance RN a => RN (Mon a) where
Mon c e <|> f = Mon (c <|> f) (e <|> f)
instance RN a => RN (MCoef a) where
CoefP p <|> f = CoefP $ p <|> f
CoefI i <|> f = CoefI $ i <|> f
instance RN a => RN (MBase a) where
EZero <|> _ = EZero
MExpI n e <|> f = MExpI (n <|> f) e
-- TODO: Capture avoiding!!
instance RN a => RN (ICond a) where
IBool b <|> _ = IBool b
IBInd v <|> f = IBInd $ v <|> f
INot e <|> f = INot $ e <|> f
IAnd le <|> f = IAnd $ le <|> f
ILeq e <|> f = ILeq $ e <|> f
IEq e <|> f = IEq $ e <|> f
IBoolOp op e1 e2 <|> f = IBoolOp op (e1 <|> f) (e2 <|> f)
instance RN a => RN (IExpr a) where
IInt n <|> _ = IInt n
IInd v <|> f = IInd $ v <|> f
ISum le <|> f = ISum $ le <|> f
ISym e <|> f = ISym $ e <|> f
IArith op e1 e2 <|> f = IArith op (e1 <|> f) (e2 <|> f)
-- | Substitutions
class Subst f where
-- | Substitution of variable @v0@ by @v1@.
subst :: (VarOf f ~ v0, SubstOf f ~ v1) => (v0, v1) -> f -> f
substBlock :: (VarOf f ~ v0, SubstOf f ~ v1) => (v0, v1) -> [f] -> [f]
substBlock v = map (subst v)
instance Subst a => Subst (Located a) where
subst f = fmap (subst f)
instance Subst a => Subst (Maybe a) where
subst f = fmap (subst f)
instance Subst a => Subst [a] where
subst = substBlock
instance Eq a => Subst (RowAPat a) where
subst f (CElem e) = CElem $ subst f e
subst f (CRange e1 e2) = CRange (subst f e1) (subst f e2)
instance Eq a => Subst (APat a) where
subst f (VectP e) = VectP $ subst f e
subst f (MatP e1 e2) = MatP (subst f e1) (subst f e2)
instance Eq a => Subst (TExpr a) where
subst f (TyE ty e) = TyE ty (subst f e)
instance Eq a => Subst (Expr a) where
subst (v0, e) v@(Var v1)
| v1 == v0 = e
| otherwise = v
subst _ l@(Lit _) = l
subst f (FunCall n es) = FunCall n $ map (subst f) es
subst f (StructProj e n) = StructProj (subst f e) n
subst f (UnaryOp op e) = UnaryOp op (subst f e)
subst f (BinaryOp op e1 e2) = BinaryOp op (subst f e1) (subst f e2)
subst f (Access e p) = Access (subst f e) (subst f p)
subst f (Cast b td e) = Cast b (subst f td) (subst f e)
instance Eq a => Subst (BinOp a) where
subst _ c = c
instance Eq a => Subst (TyDecl a) where
subst f (BitsD s e) = BitsD s $ subst f e
subst f (ModD m) = ModD $ subst f m
subst f (VectorD e td) = VectorD (subst f e) (subst f td)
subst f (MatrixD r c td) = MatrixD (subst f r) (subst f c) (subst f td)
subst _ d = d
instance Eq a => Subst (Mod a) where
subst f (ModNum e) = ModNum $ subst f e
subst f (ModPol td n pol) = ModPol (subst f td) n pol
instance Eq a => Subst (Stmt a) where
subst f (VDecl vd) = VDecl (subst f vd)
subst f (Assign lvs es) = Assign (map (subst f) lvs) (map (subst f) es)
subst f (FCallS n es) = FCallS n $ map (subst f) es
subst f (Ret es) = Ret $ map (subst f) es
subst f (Ite i t e) = Ite (subst f i) (subst f t) (subst f e)
subst f@(v0,_) sq@(Seq (SeqIter v1 s e b r) ss)
| v0 == v1 = sq
| otherwise = Seq (SeqIter v1 (subst f s)
(subst f e)
(subst f b)
r ) $ subst f ss
subst f (While e ss) = While (subst f e) (subst f ss)
subst _ (Nop a) = Nop a
subst _ _ = error ".\
\: Not defined!"
substBlock _ [] = []
substBlock f@(v0, _) ss@(VDecl vd : rest)
| v0 `elem` getDeclVar vd = ss
| otherwise = VDecl (subst f vd) : substBlock f rest
substBlock f (s:ss) = subst f s : subst f ss
instance Eq a => Subst (LVal a) where
subst _ v@(LVVar _) = v
subst f (LVStruct lv e) = LVStruct (subst f lv) e
subst f (LVCont ty lv pat) = LVCont ty (subst f lv) (subst f pat)
instance Eq a => Subst (VarDecl a) where
subst f (VarD n td e) = VarD n (subst f td) (subst f e)
subst f (MultiD n td) = MultiD n (subst f td)
subst f (ContD n td es) = ContD n (subst f td) $ map (subst f) es
instance Eq a => Subst (Pol a) where
subst f (Pol ps) = Pol (map (subst f) ps)
instance Eq a => Subst (Mon a) where
subst f (Mon c b) = Mon (subst f c) b
instance Eq a => Subst (MCoef a) where
subst f (CoefI i) = CoefI $ subst f i
subst f (CoefP p) = CoefP $ subst f p
instance Eq a => Subst (Type a) where
subst _ Int = Int
subst _ RInt = RInt
subst _ Bool = Bool
subst f (Bits b i) = Bits b $ subst f i
subst f (Mod a b c) = Mod (subst f a) b (subst f c)
subst f (Vector n t) = Vector (subst f n) (subst f t)
subst f (Matrix n m t) = Matrix (subst f n) (subst f m) (subst f t)
subst f (TySyn v t) = TySyn v (subst f t)
subst f (FuncSig ta tr c) = FuncSig (map (subst f) ta) (subst f tr) c
subst f (Struct v t) = Struct v (map (mapSnd (subst f)) t)
subst f (SField v t) = SField v (subst f t)
subst f (Indet t) = Indet (subst f t)
subst f (Tuple t) = Tuple $ subst f t
subst _ Bullet = Bullet
subst f (Index v c t) = Index v (subst f c) (subst f t)
subst _ _ = error ".\
\: Not defined!"
instance Eq a => Subst (ICond a) where
subst _ v@(IBInd _) = v
subst _ l@(IBool _) = l
subst f (INot e) = INot $ subst f e
subst f (IAnd le) = IAnd $ map (subst f) le
subst f (IBoolOp op e1 e2) = IBoolOp op (subst f e1) (subst f e2)
subst f (ILeq e) = ILeq $ subst f e
subst f (IEq e) = IEq $ subst f e
instance Eq a => Subst (IExpr a) where
subst (v0, e) v@(IInd v1)
| v1 == v0 = e
| otherwise = v
subst _ l@(IInt _) = l
subst f (ISum le) = ISum $ map (subst f) le
subst f (ISym e) = ISym $ subst f e
subst f (IArith op e1 e2) = IArith op (subst f e1) (subst f e2)
--------------------------------------------------------------------------------
-- General Utils
--
lvname :: LVal id -> id
lvname (LVVar v) = unLoc v
lvname (LVStruct lv _) = lvname lv
lvname (LVCont _ lv _) = lvname lv
lvalNames :: Ord id => [LStmt id] -> Set id
lvalNames = foldl' lvalNames' Set.empty
where
lvalNames' vs (unLoc -> Assign lvs _)
= vs `Set.union` Set.fromList (map lvname lvs)
lvalNames' vs (unLoc -> Ite _ t e)
= vs `Set.union` lvalNames t `Set.union` maybe Set.empty lvalNames e
lvalNames' vs (unLoc -> While _ ss')
= vs `Set.union` lvalNames ss'
lvalNames' vs (unLoc -> Seq _ ss')
= vs `Set.union` lvalNames ss'
lvalNames' vs _
= vs
getVars :: LStmt Var -> [Var]
getVars ss = Set.toList $ Set.filter nsVar $ fvs ss
getLVars :: Ord id => LStmt id -> [id]
getLVars ss = Set.toList $ lvalNames [ss]
getRVars :: LStmt Var -> [Var]
getRVars ss = Set.toList $ Set.filter nsVar (fvs ss) Set.\\ lvalNames [ss]
sameKind :: LStmt Var -> LStmt Var -> Bool
(L _ s1) `sameKind` (L _ s2) = s1 `doSK` s2
where
doSK :: Stmt Var -> Stmt Var -> Bool
doSK (VDecl _) (VDecl _)
= True
doSK (Assign lvs1 es1) (Assign lvs2 es2)
| length lvs1 == length lvs2 && length es1 == length es2
= all (uncurry sameKindExpr) $ zip es1 es2
doSK (FCallS fn1 es1) (FCallS fn2 es2)
= fn1 == fn2 && all (uncurry sameKindExpr) (zip es1 es2)
doSK (Ret es1) (Ret es2)
= all (uncurry sameKindExpr) $ zip es1 es2
doSK (Ite i1 t1 Nothing) (Ite i2 t2 Nothing)
= sameKindExpr i1 i2 && all (uncurry sameKind) (zip t1 t2)
doSK (Ite i1 t1 (Just e1)) (Ite i2 t2 (Just e2))
= sameKindExpr i1 i2 && all (uncurry sameKind) (zip t1 t2)
&& all (uncurry sameKind) (zip e1 e2)
doSK (Seq si1 ss1) (Seq si2 ss2)
| seqIdx si1 == seqIdx si2 = all (uncurry sameKind) (zip ss1 ss2)
doSK (While _ _) (While _ _)
= False -- Need to have same number of iterations
doSK _ _
= False
-- TODO: Review pattern: | guard = True. Is there any good reason to use this?
sameKindExpr :: TLExpr Var -> TLExpr Var -> Bool
sameKindExpr (L _ (TyE _ le1)) (L _ (TyE _ le2)) = ske le1 le2
where
ske (Var _) (Var _)
= True
ske (Lit _) (Lit _)
= True
ske (FunCall (L _ fn1) es1) (FunCall (L _ fn2) es2)
| fn1 == fn2 && all (uncurry sameKindExpr) (zip es1 es2)
= True
ske (StructProj e1 _ ) (StructProj e2 _ )
| sameKindExpr e1 e2
= True
ske (BinaryOp op1 e11 e12) (BinaryOp op2 e21 e22)
| op1 == op2 && sameKindExpr e11 e21 && sameKindExpr e12 e22
= True
ske (UnaryOp op1 e1) (UnaryOp op2 e2)
= op1 == op2 && sameKindExpr e1 e2
ske (Access e1 p1) (Access e2 p2)
= sameKindExpr e1 e2 && sameKindPat p1 p2
ske (Cast _ _ e1) (Cast _ _ e2)
= sameKindExpr e1 e2
ske _ _
= False
sameKindPat :: APat Var -> APat Var -> Bool
sameKindPat (VectP rp1) (VectP rp2)
= sameKindRP rp1 rp2
sameKindPat (MatP rp1 cp1) (MatP rp2 cp2)
= sameKindRP rp1 rp2 && sameKindRP cp1 cp2
sameKindPat _ _
= False
sameKindRP :: RowAPat Var -> RowAPat Var -> Bool
sameKindRP (CElem e1) (CElem e2)
= sameKindExpr e1 e2
sameKindRP (CRange e11 e12) (CRange e21 e22)
= sameKindExpr e11 e21 && sameKindExpr e12 e22
sameKindRP _ _
= False
isAscSeq :: SeqIter id -> Bool
isAscSeq = maybe True aux . seqBy
where
aux :: LExpr id -> Bool
aux (L _ (Lit (ILit n))) = n > 0
aux _ = error ": not expected case"
{-# INLINE isSimpleLVal #-}
isSimpleLVal :: LVal id -> Bool
isSimpleLVal (LVVar _) = True
isSimpleLVal _ = False
{-# INLINE isAssignStmt #-}
isAssignStmt :: Stmt id -> Bool
isAssignStmt (Assign _ _) = True
isAssignStmt _ = False
{-# INLINE isLit #-}
isLit :: Expr id -> Bool
isLit (Lit _) = True
isLit _ = False
{-# INLINE isIntLit #-}
isIntLit :: Expr id -> Bool
isIntLit (Lit (ILit _)) = True
isIntLit _ = False
{-# INLINE isSimpleVDecl #-}
isSimpleVDecl :: Stmt id -> Bool
isSimpleVDecl (VDecl (VarD {})) = True
isSimpleVDecl (VDecl (MultiD {})) = True
isSimpleVDecl _ = False
{-# INLINE isReturn #-}
isReturn :: Stmt a -> Bool
isReturn (Ret _) = True
isReturn _ = False
defVar :: LDef id -> [id]
defVar = defV . unLoc
where
defV (VarDef (VarD n _ _)) = [unLoc n]
defV (VarDef (MultiD n _)) = map unLoc n
defV (VarDef (ContD n _ _)) = [unLoc n]
defV (ConstDef (ConstD n _ _)) = [unLoc n]
defV (ConstDef (MultiConstD n _ _)) = map unLoc n
defV (FunDef f) = [unLoc $ funId f]
defV (TyDef (TySynDef t _)) = [unLoc t]
defV (TyDef (StructDecl s _)) = [unLoc s]
getDeclVar :: VarDecl id -> [id]
getDeclVar (VarD n _ _) = [unLoc n]
getDeclVar (MultiD n _) = map unLoc n
getDeclVar (ContD n _ _) = [unLoc n]
{-# INLINE isRange #-}
isRange :: APat id -> Bool
isRange (VectP (CRange _ _)) = True
isRange (MatP (CRange _ _) _) = True
isRange (MatP _ (CRange _ _)) = True
isRange _ = False
{-# INLINE isEqNeq #-}
isEqNeq :: COp -> Bool
isEqNeq bop = case bop of
Eq -> True
Neq -> True
_ -> False
type2TyDecl :: Type Var -> TyDecl Var
type2TyDecl Int = IntD
type2TyDecl RInt = RIntD
type2TyDecl Bool = BoolD
type2TyDecl (Bits s n) = BitsD s (ind2Expr n)
type2TyDecl (Mod Nothing Nothing (Pol [Mon (CoefI n) EZero]))
= ModD $ ModNum $ ind2Expr n
type2TyDecl (Mod (Just b) (Just i) p)
= ModD $ ModPol (type2TyDecl b) i p
type2TyDecl (Vector k it)
= VectorD (ind2Expr k) (type2TyDecl it)
type2TyDecl (Matrix u v it)
= MatrixD (ind2Expr u) (ind2Expr v) (type2TyDecl it)
type2TyDecl (Struct sn _)
= TySynD (L genSrcLoc sn)
type2TyDecl (SField _ t) = type2TyDecl t
type2TyDecl (Index _ _ t) = type2TyDecl t
type2TyDecl t
= error $ ".: " ++ showPprDebug t
class Typeable a where
typeOf :: a -> Type Var
instance Typeable Var where
typeOf = varType
instance Typeable (TExpr Var) where
typeOf (TyE t _) = t
instance Typeable (LVal Var) where
typeOf (LVVar v) = varType $ unLoc v
typeOf (LVStruct lv fi) = fieldType fi (typeOf lv)
typeOf (LVCont ty _ _) = ty
instance Typeable a => Typeable (Located a) where
typeOf (L _ e) = typeOf e
instance Typeable (IExpr Var) where
typeOf = queryIndexTy
instance Typeable (Type Var) where
typeOf = id