TTTAS 0.4.2 → 0.6.0
raw patch · 7 files changed
+794/−758 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Language.AbstractSyntax.TTTAS: (&&&&) :: Arrow2 arr => arr a b -> arr a b' -> arr a (Pair b b')
- Language.AbstractSyntax.TTTAS: (****) :: Arrow2 arr => arr a b -> arr a' b' -> arr (Pair a a') (Pair b b')
- Language.AbstractSyntax.TTTAS: (>>>>) :: Category2 cat => cat a b -> cat b c -> cat a c
- Language.AbstractSyntax.TTTAS: Empty :: Env t use ()
- Language.AbstractSyntax.TTTAS: Eq :: Equal a a
- Language.AbstractSyntax.TTTAS: Ext :: Env t use def' -> t a use -> Env t use (def', a)
- Language.AbstractSyntax.TTTAS: List :: [a s] -> List a s
- Language.AbstractSyntax.TTTAS: P :: (a s, b s) -> Pair a b s
- Language.AbstractSyntax.TTTAS: Result :: (m s) -> (b s) -> (FinalEnv t s) -> Result m t b
- Language.AbstractSyntax.TTTAS: Suc :: Ref a env' -> Ref a (env', b)
- Language.AbstractSyntax.TTTAS: T :: (forall x. Ref x e -> Ref x s) -> T e s
- Language.AbstractSyntax.TTTAS: Trafo2 :: (forall env1. m env1 -> TrafoE2 m t env1 a b) -> Trafo2 m t a b
- Language.AbstractSyntax.TTTAS: TrafoE2 :: (m env2) -> (forall s. a s -> T env2 s -> Env t s env1 -> UpdFinalEnv t s -> (b s, T env1 s, Env t s env2, UpdFinalEnv t s)) -> TrafoE2 m t env1 a b
- Language.AbstractSyntax.TTTAS: Unit :: Unit s
- Language.AbstractSyntax.TTTAS: Upd :: (FinalEnv t s -> FinalEnv t s) -> UpdFinalEnv t s
- Language.AbstractSyntax.TTTAS: Zero :: Ref a (env', a)
- Language.AbstractSyntax.TTTAS: arr2 :: Arrow2 arr => (forall s. a s -> b s) -> arr a b
- Language.AbstractSyntax.TTTAS: class Category2 arr => Arrow2 (arr :: (* -> *) -> (* -> *) -> *)
- Language.AbstractSyntax.TTTAS: class Arrow2 arr => ArrowLoop2 arr
- Language.AbstractSyntax.TTTAS: data Env term use def
- Language.AbstractSyntax.TTTAS: data Equal :: * -> * -> *
- Language.AbstractSyntax.TTTAS: data Ref a env
- Language.AbstractSyntax.TTTAS: data Result m t b
- Language.AbstractSyntax.TTTAS: data Trafo2 m t a b
- Language.AbstractSyntax.TTTAS: data TrafoE2 m t env1 a b
- Language.AbstractSyntax.TTTAS: data Unit s
- Language.AbstractSyntax.TTTAS: first2 :: Arrow2 arr => arr a b -> arr (Pair a c) (Pair b c)
- Language.AbstractSyntax.TTTAS: instance Arrow2 (Trafo2 m t)
- Language.AbstractSyntax.TTTAS: instance ArrowLoop2 (Trafo2 m t)
- Language.AbstractSyntax.TTTAS: instance Category2 (Trafo2 m t)
- Language.AbstractSyntax.TTTAS: lookup :: Ref a env -> env -> a
- Language.AbstractSyntax.TTTAS: lookupEnv :: Ref a env -> Env t s env -> t a s
- Language.AbstractSyntax.TTTAS: loop2 :: ArrowLoop2 arr => arr (Pair a c) (Pair b c) -> arr a b
- Language.AbstractSyntax.TTTAS: match :: Ref a env -> Ref b env -> Maybe (Equal a b)
- Language.AbstractSyntax.TTTAS: newSRef2 :: Trafo2 Unit t (t a) (Ref a)
- Language.AbstractSyntax.TTTAS: newtype List a s
- Language.AbstractSyntax.TTTAS: newtype Pair a b s
- Language.AbstractSyntax.TTTAS: newtype T e s
- Language.AbstractSyntax.TTTAS: newtype UpdFinalEnv t s
- Language.AbstractSyntax.TTTAS: runTrafo2 :: Trafo2 m t a b -> m () -> (forall s. a s) -> Result m t b
- Language.AbstractSyntax.TTTAS: second2 :: Arrow2 arr => arr a b -> arr (Pair c a) (Pair c b)
- Language.AbstractSyntax.TTTAS: sequenceA2 :: [Trafo2 m t a b] -> Trafo2 m t a (List b)
- Language.AbstractSyntax.TTTAS: type FinalEnv t usedef = Env t usedef usedef
- Language.AbstractSyntax.TTTAS: unT :: T e s -> forall x. Ref x e -> Ref x s
- Language.AbstractSyntax.TTTAS: update :: (a -> a) -> Ref a env -> env -> env
- Language.AbstractSyntax.TTTAS: updateEnv :: (t a s -> t a s) -> Ref a env -> Env t s env -> Env t s env
- Language.AbstractSyntax.TTTAS: updateFinalEnv2 :: Trafo2 m t (UpdFinalEnv t) Unit
+ Language.AbstractSyntax.TTTAS: getFinalEnv :: Trafo m t s () (FinalEnv t s)
+ Language.AbstractSyntax.TTTAS: putFinalEnv :: Trafo m t s (FinalEnv t s) ()
+ Language.AbstractSyntax.TTTAS.Common: Empty :: Env t use ()
+ Language.AbstractSyntax.TTTAS.Common: Eq :: Equal a a
+ Language.AbstractSyntax.TTTAS.Common: Ext :: Env t use def' -> t a use -> Env t use (def', a)
+ Language.AbstractSyntax.TTTAS.Common: Result :: (m s) -> (b s) -> (FinalEnv t s) -> Result m t b
+ Language.AbstractSyntax.TTTAS.Common: Suc :: Ref a env' -> Ref a (env', b)
+ Language.AbstractSyntax.TTTAS.Common: T :: (forall x. Ref x e -> Ref x s) -> T e s
+ Language.AbstractSyntax.TTTAS.Common: Unit :: Unit s
+ Language.AbstractSyntax.TTTAS.Common: Zero :: Ref a (env', a)
+ Language.AbstractSyntax.TTTAS.Common: data Env term use def
+ Language.AbstractSyntax.TTTAS.Common: data Equal :: * -> * -> *
+ Language.AbstractSyntax.TTTAS.Common: data Ref a env
+ Language.AbstractSyntax.TTTAS.Common: data Result m t b
+ Language.AbstractSyntax.TTTAS.Common: data Unit s
+ Language.AbstractSyntax.TTTAS.Common: lookup :: Ref a env -> env -> a
+ Language.AbstractSyntax.TTTAS.Common: lookupEnv :: Ref a env -> Env t s env -> t a s
+ Language.AbstractSyntax.TTTAS.Common: match :: Ref a env -> Ref b env -> Maybe (Equal a b)
+ Language.AbstractSyntax.TTTAS.Common: newtype T e s
+ Language.AbstractSyntax.TTTAS.Common: type FinalEnv t usedef = Env t usedef usedef
+ Language.AbstractSyntax.TTTAS.Common: unT :: T e s -> forall x. Ref x e -> Ref x s
+ Language.AbstractSyntax.TTTAS.Common: update :: (a -> a) -> Ref a env -> env -> env
+ Language.AbstractSyntax.TTTAS.Common: updateEnv :: (t a s -> t a s) -> Ref a env -> Env t s env -> Env t s env
+ Language.AbstractSyntax.TTTAS2: (&&&) :: Arrow2 arr => arr a b -> arr a b' -> arr a (Pair b b')
+ Language.AbstractSyntax.TTTAS2: (***) :: Arrow2 arr => arr a b -> arr a' b' -> arr (Pair a a') (Pair b b')
+ Language.AbstractSyntax.TTTAS2: (>>>) :: Category2 cat => cat a b -> cat b c -> cat a c
+ Language.AbstractSyntax.TTTAS2: List :: [a s] -> List a s
+ Language.AbstractSyntax.TTTAS2: P :: (a s, b s) -> Pair a b s
+ Language.AbstractSyntax.TTTAS2: Trafo :: (forall env1. m env1 -> TrafoE m t env1 a b) -> Trafo m t a b
+ Language.AbstractSyntax.TTTAS2: TrafoE :: (m env2) -> (forall s. a s -> T env2 s -> Env t s env1 -> FinalEnv t s -> (b s, T env1 s, Env t s env2, FinalEnv t s)) -> TrafoE m t env1 a b
+ Language.AbstractSyntax.TTTAS2: arr :: Arrow2 arr => (forall s. a s -> b s) -> arr a b
+ Language.AbstractSyntax.TTTAS2: castSRef :: m e -> Ref a e -> TrafoE m t e x (Ref a)
+ Language.AbstractSyntax.TTTAS2: class Category2 arr => Arrow2 (arr :: (* -> *) -> (* -> *) -> *)
+ Language.AbstractSyntax.TTTAS2: class Arrow2 arr => ArrowLoop2 arr
+ Language.AbstractSyntax.TTTAS2: data Trafo m t a b
+ Language.AbstractSyntax.TTTAS2: data TrafoE m t env1 a b
+ Language.AbstractSyntax.TTTAS2: extEnv :: m (e, a) -> TrafoE m t e (t a) (Ref a)
+ Language.AbstractSyntax.TTTAS2: first :: Arrow2 arr => arr a b -> arr (Pair a c) (Pair b c)
+ Language.AbstractSyntax.TTTAS2: getFinalEnv :: Trafo m t Unit (FinalEnv2 t)
+ Language.AbstractSyntax.TTTAS2: instance Arrow2 (Trafo m t)
+ Language.AbstractSyntax.TTTAS2: instance ArrowLoop2 (Trafo m t)
+ Language.AbstractSyntax.TTTAS2: instance Category2 (Trafo m t)
+ Language.AbstractSyntax.TTTAS2: loop :: ArrowLoop2 arr => arr (Pair a c) (Pair b c) -> arr a b
+ Language.AbstractSyntax.TTTAS2: newSRef :: Trafo Unit t (t a) (Ref a)
+ Language.AbstractSyntax.TTTAS2: newtype List a s
+ Language.AbstractSyntax.TTTAS2: newtype Pair a b s
+ Language.AbstractSyntax.TTTAS2: putFinalEnv :: Trafo m t (FinalEnv2 t) Unit
+ Language.AbstractSyntax.TTTAS2: returnA :: Arrow2 arr => arr a a
+ Language.AbstractSyntax.TTTAS2: runTrafo :: Trafo m t a b -> m () -> (forall s. a s) -> Result m t b
+ Language.AbstractSyntax.TTTAS2: second :: Arrow2 arr => arr a b -> arr (Pair c a) (Pair c b)
+ Language.AbstractSyntax.TTTAS2: sequenceA :: [Trafo m t a b] -> Trafo m t a (List b)
+ Language.AbstractSyntax.TTTAS2: updateFinalEnv :: Trafo m t (UpdFinalEnv t) Unit
+ Language.AbstractSyntax.TTTAS2: updateSRef :: m e -> Ref a e -> FUpd i t a -> TrafoE m t e (SI i) (Ref a)
- Language.AbstractSyntax.TTTAS: TrafoE :: (m env2) -> (a -> T env2 s -> Env t s env1 -> (FinalEnv t s -> FinalEnv t s) -> (b, T env1 s, Env t s env2, FinalEnv t s -> FinalEnv t s)) -> TrafoE m t s env1 a b
+ Language.AbstractSyntax.TTTAS: TrafoE :: (m env2) -> (a -> T env2 s -> Env t s env1 -> FinalEnv t s -> (b, T env1 s, Env t s env2, FinalEnv t s)) -> TrafoE m t s env1 a b
Files
- TTTAS.cabal +4/−2
- examples/CSE.hs +0/−196
- examples/CSE1.hs +202/−0
- examples/CSE2.hs +165/−244
- src/Language/AbstractSyntax/TTTAS.hs +55/−316
- src/Language/AbstractSyntax/TTTAS/Common.hs +122/−0
- src/Language/AbstractSyntax/TTTAS2.hs +246/−0
TTTAS.cabal view
@@ -1,7 +1,8 @@ cabal-version: >=1.2.3 build-type: Simple name: TTTAS-version: 0.4.2++version: 0.6.0 license: LGPL license-file: COPYRIGHT maintainer: Marcos Viera <mviera@fing.edu.uy>@@ -13,7 +14,8 @@ extra-source-files: README, LICENSE-LGPL, TTTAS.bib library build-depends: base >= 4 && < 5- exposed-modules: Language.AbstractSyntax.TTTAS + exposed-modules: Language.AbstractSyntax.TTTAS, Language.AbstractSyntax.TTTAS2,+ Language.AbstractSyntax.TTTAS.Common extensions: Arrows, KindSignatures, RankNTypes, GADTs, CPP hs-source-dirs: src ghc-options: -Wall
− examples/CSE.hs
@@ -1,196 +0,0 @@-{-# OPTIONS -fglasgow-exts -XGADTs -XArrows #-}--module CSE where--import Language.AbstractSyntax.TTTAS-import Prelude hiding (lookup)-import Control.Arrow--data Expr a env where- Var :: Ref a env -> Expr a env- IntVal :: Int -> Expr Int env- BoolVal :: Bool -> Expr Bool env - Cons :: Expr a env -> Expr [a] env - -> Expr [a] env- Nil :: Expr [a] env- Add :: Expr Int env -> Expr Int env - -> Expr Int env- LessThan :: Expr Int env -> Expr Int env - -> Expr Bool env - If :: Expr Bool env -> Expr a env - -> Expr a env -> Expr a env--eval :: Expr a env -> env -> a-eval (Var r) e = lookup r e-eval (IntVal i) _ = i-eval (BoolVal b) _ = b-eval (Add x y) e = eval x e + eval y e-eval (Cons x y) e = eval x e : eval y e-eval Nil _ = []-eval (LessThan x y) e = eval x e < eval y e-eval (If x y z) e = if eval x e - then eval y e- else eval z e--type Decls env = Env Expr env env--data TDecls env = forall env' . TDecls (Decls env') - (T env env')--a = Suc Zero-b = Zero-exampledecls :: Decls (((),Int),Int)-exampledecls = - Empty `Ext` (IntVal 4) - `Ext` (Add (Add (Var a) (IntVal 4)) - (Add (Var a) (IntVal 4)))--resdecls :: TDecls (((),Int),Int)-resdecls = cse exampledecls--evalDecls :: Decls env -> env-evalVar :: Ref a env -> TDecls env -> a-evalVar var (TDecls ds (T tt))- = lookup (tt var) (evalDecls ds)--value_a = evalVar a resdecls-value_b = evalVar b resdecls--evalDecls (ds :: Decls env) = - let result :: env- result = evalD ds- evalD :: Env Expr env def -> def- evalD Empty = ()- evalD (Ext ds e) = (evalD ds,eval e result)- in result--resdecls2 :: TDecls (((),Int),Int) -resdecls2 = -- TDecls- ( Empty `Ext` (IntVal 4) - `Ext` (Add (Var (Suc (Suc Zero))) - (Var (Suc (Suc Zero))))- `Ext` (Add (Var (Suc Zero)) - (Var (Suc Zero)))- )- ( T (\ref -> case ref of - Zero -> Zero - Suc Zero -> Suc (Suc Zero))- :: T (((), Int), Int) ((((), Int), Int), Int))--instance Show (Ref a env) where- show x = "#" ++ (show $ refint x) -refint :: Ref a env -> Int-refint Zero = 0-refint (Suc x) = 1 + refint x-instance Show (Expr a env) where- show (Var r) = "v" ++ (show $ refint r)- show (IntVal i) = show i- show (BoolVal i) = show i- show (Add x y) = "(" ++ show x ++ "+"++ show y ++ ")"- show (LessThan x y) = "(" ++ show x ++ "<"++ show y ++ ")"- show (If x y z) = "if" ++ show x ++ "then"++ show y ++ "else" ++ show z--equals :: Expr a env -> Expr b env -> Maybe (Equal a b)-equals (Var r1) (Var r2) = match r1 r2-equals (IntVal i1) (IntVal i2) - | i1==i2 = Just Eq-equals (LessThan x1 y1) (LessThan x2 y2) - = do Eq <- equals x1 x2 - Eq <- equals y1 y2 - return Eq --equals (BoolVal b1) (BoolVal b2) - | b1==b2 = Just Eq-equals (Add x1 y1) (Add x2 y2) = do- Eq <- equals x1 x2- Eq <- equals y1 y2 - return Eq -equals (If x1 y1 z1) (If x2 y2 z2) - = do- Eq <- equals x1 x2- Eq <- equals y1 y2 - Eq <- equals z1 z2 - return Eq -equals _ _ = Nothing--newtype Memo env env'- = Memo - ( forall x . Expr x env - -> Maybe (Ref x env')- )--emptyMemo :: Memo env ()-emptyMemo = Memo (const Nothing)--type TrafoCSE env = Trafo (Memo env) Expr--insertIfNew :: forall s a env . Expr a env - -> TrafoCSE env s (Expr a s) (Ref a s)-insertIfNew e = - Trafo- (\(Memo m :: Memo env env') -> case m e of- Nothing -> extEnv (extMemo e (Memo m)) - Just r -> castSRef (Memo m) r - )- -extMemo :: Expr a env -> Memo env env' - -> Memo env (env',a)-extMemo e (Memo m) - = Memo (\s -> case equals e s of- Just Eq -> Just Zero- Nothing -> fmap Suc (m s)- ) --app_cse :: Expr a env - -> TrafoCSE env s (T env s) (Ref a s) -app_cse (Var r) = proc (T tenv_s) -> - returnA -< tenv_s r--app_cse e@(IntVal i) = proc _ -> - insertIfNew e -< IntVal i --app_cse e@(LessThan x y) - = proc tt -> - do l <- app_cse x -< tt- r <- app_cse y -< tt- insertIfNew e -< LessThan (Var l) (Var r)-app_cse e@(BoolVal b) = proc _ -> - insertIfNew e -< BoolVal b -app_cse e@(Add x y) = proc tt -> - do l <- app_cse x -< tt- r <- app_cse y -< tt- insertIfNew e -< Add (Var l) (Var r)- -app_cse e@(If x y z) = proc tt -> - do b <- app_cse x -< tt- l <- app_cse y -< tt- r <- app_cse z -< tt- insertIfNew e -< If (Var b) (Var l) (Var r)- -cse_env :: Env Expr env env'- -> TrafoCSE env s- (T env s) - (Env Ref s env')--cse_env Empty = proc _ -> returnA -< Empty -cse_env (Ext es e) = proc tt ->- do renv <- cse_env es -< tt- r <- app_cse e -< tt- returnA -< Ext renv r --refTransformer :: Env Ref s env -> T env s-refTransformer refs = T (\r -> lookupEnv r refs)--trafo :: Decls env -> TrafoCSE env s () (T env s)-trafo decls = proc _ -> - do rec let tt = refTransformer refs- refs <- cse_env decls -< tt- returnA -< tt--cse :: forall env . Decls env -> TDecls env-cse decls- = case runTrafo (trafo decls) emptyMemo () of- Result _ t env -> TDecls env t-
+ examples/CSE1.hs view
@@ -0,0 +1,202 @@+{-# LANGUAGE ExistentialQuantification, ScopedTypeVariables, RankNTypes, GADTs, Arrows #-}+++module CSE where++import Language.AbstractSyntax.TTTAS+import Prelude hiding (lookup)+import Control.Arrow++ifThenElse c t e = case c of+ True -> t+ False -> e+data Expr a env where+ Var :: Ref a env -> Expr a env+ IntVal :: Int -> Expr Int env+ BoolVal :: Bool -> Expr Bool env + Cons :: Expr a env -> Expr [a] env + -> Expr [a] env+ Nil :: Expr [a] env+ Add :: Expr Int env -> Expr Int env + -> Expr Int env+ LessThan :: Expr Int env -> Expr Int env + -> Expr Bool env + If :: Expr Bool env -> Expr a env + -> Expr a env -> Expr a env++eval :: Expr a env -> env -> a+eval (Var r) e = lookup r e+eval (IntVal i) _ = i+eval (BoolVal b) _ = b+eval (Add x y) e = eval x e + eval y e+eval (Cons x y) e = eval x e : eval y e+eval Nil _ = []+eval (LessThan x y) e = eval x e < eval y e+eval (If x y z) e = if eval x e + then eval y e+ else eval z e++type Decls env = Env Expr env env++data TDecls env = forall env' . TDecls (Decls env') + (T env env')++a = Suc Zero+b = Zero+exampledecls :: Decls (((),Int),Int)+exampledecls = + Empty `Ext` (IntVal 4) + `Ext` (Add (Add (Var a) (IntVal 4)) + (Add (Var a) (IntVal 4)))++resdecls :: TDecls (((),Int),Int)+resdecls = cse exampledecls++evalDecls :: Decls env -> env+evalVar :: Ref a env -> TDecls env -> a+evalVar var (TDecls ds (T tt))+ = lookup (tt var) (evalDecls ds)++value_a = evalVar a resdecls+value_b = evalVar b resdecls++evalDecls (ds :: Decls env) = + let result :: env+ result = evalD ds+ evalD :: Env Expr env def -> def+ evalD Empty = ()+ evalD (Ext ds e) = (evalD ds,eval e result)+ in result++resdecls2 :: TDecls (((),Int),Int) +resdecls2 = ++ TDecls+ ( Empty `Ext` (IntVal 4) + `Ext` (Add (Var (Suc (Suc Zero))) + (Var (Suc (Suc Zero))))+ `Ext` (Add (Var (Suc Zero)) + (Var (Suc Zero)))+ )+ ( T (\ref -> case ref of + Zero -> Zero + Suc Zero -> Suc (Suc Zero))+ :: T (((), Int), Int) ((((), Int), Int), Int))++instance Show (Ref a env) where+ show x = "#" ++ (show $ refint x) +refint :: Ref a env -> Int+refint Zero = 0+refint (Suc x) = 1 + refint x+instance Show (Expr a env) where+ show (Var r) = "v" ++ (show $ refint r)+ show (IntVal i) = show i+ show (BoolVal i) = show i+ show (Add x y) = "(" ++ show x ++ "+"++ show y ++ ")"+ show (LessThan x y) = "(" ++ show x ++ "<"++ show y ++ ")"+ show (If x y z) = "if" ++ show x ++ "then"++ show y ++ "else" ++ show z++equals :: Expr a env -> Expr b env -> Maybe (Equal a b)+equals (Var r1) (Var r2) = match r1 r2+equals (IntVal i1) (IntVal i2) + | i1==i2 = Just Eq+equals (LessThan x1 y1) (LessThan x2 y2) + = do Eq <- equals x1 x2 + Eq <- equals y1 y2 + return Eq ++equals (BoolVal b1) (BoolVal b2) + | b1==b2 = Just Eq+equals (Add x1 y1) (Add x2 y2) = do+ Eq <- equals x1 x2+ Eq <- equals y1 y2 + return Eq +equals (If x1 y1 z1) (If x2 y2 z2) + = do+ Eq <- equals x1 x2+ Eq <- equals y1 y2 + Eq <- equals z1 z2 + return Eq +equals _ _ = Nothing++newtype Memo env env'+ = Memo + ( forall x . Expr x env + -> Maybe (Ref x env')+ )++emptyMemo :: Memo env ()+emptyMemo = Memo (const Nothing)++type TrafoCSE env = Trafo (Memo env) Expr++insertIfNew :: forall s a env . Expr a env + -> TrafoCSE env s (Expr a s) (Ref a s)+insertIfNew e = + Trafo+ (\(Memo m :: Memo env env') -> case m e of+ Nothing -> extEnv (extMemo e (Memo m)) + Just r -> castSRef (Memo m) r + )+ +extMemo :: Expr a env -> Memo env env' + -> Memo env (env',a)+extMemo e (Memo m) + = Memo (\s -> case equals e s of+ Just Eq -> Just Zero+ Nothing -> fmap Suc (m s)+ ) ++app_cse :: Expr a env + -> TrafoCSE env s (T env s) (Ref a s) +app_cse (Var r) = proc (T tenv_s) -> + returnA -< tenv_s r++app_cse e@(IntVal i) = proc _ -> + insertIfNew e -< IntVal i ++app_cse e@(LessThan x y) + = proc tt -> + do l <- app_cse x -< tt+ r <- app_cse y -< tt+ insertIfNew e -< LessThan (Var l) (Var r)+app_cse e@(BoolVal b) = proc _ -> + insertIfNew e -< BoolVal b +app_cse e@(Add x y) = proc tt -> + do l <- app_cse x -< tt+ r <- app_cse y -< tt+ insertIfNew e -< Add (Var l) (Var r)+ +app_cse e@(If x y z) = proc tt -> + do b <- app_cse x -< tt+ l <- app_cse y -< tt+ r <- app_cse z -< tt+ insertIfNew e -< If (Var b) (Var l) (Var r)+ +cse_env :: Env Expr env env'+ -> TrafoCSE env s + (T env s) + (Env Ref s env')++cse_env Empty = proc _ -> returnA -< Empty +cse_env (Ext es e) = proc tt ->+ do renv <- cse_env es -< tt+ r <- app_cse e -< tt+ returnA -< Ext renv r ++refTransformer :: Env Ref s env -> T env s+refTransformer refs = T (\r -> lookupEnv r refs)++data EmptyEnv s = EmptyEnv++trafo :: Decls env -> TrafoCSE env s () (T env s)+trafo decls = proc _ -> + do rec let tt = refTransformer refs+ refs <- cse_env decls -< tt+ returnA -< tt++cse :: forall env . Decls env -> TDecls env+cse decls+ = case runTrafo (trafo decls) emptyMemo () of+ Result _ t env -> TDecls env t+
examples/CSE2.hs view
@@ -1,285 +1,206 @@-{-# OPTIONS -fglasgow-exts -XGADTs #-}-module CSE2 where+{-# LANGUAGE ExistentialQuantification, ScopedTypeVariables, RankNTypes, GADTs, Arrows #-} - import Language.AbstractSyntax.TTTAS+-- We can't use arrow notation because RebindableSyntax +-- doesn't work well with Arrows (yet) +module CSE where - data Expr1 a where- IntVal1 :: Int -> Expr1 Int- BoolVal1 :: Bool -> Expr1 Bool- Add1 :: Expr1 Int -> Expr1 Int -> Expr1 Int- LessThan1 :: Expr1 Int -> Expr1 Int -> Expr1 Bool- If1 :: Expr1 Bool -> Expr1 a -> Expr1 a -> Expr1 a +import Language.AbstractSyntax.TTTAS2+import Prelude hiding (lookup)+-- import Control.Arrow +ifThenElse c t e = case c of+ True -> t+ False -> e+data Expr a env where+ Var :: Ref a env -> Expr a env+ IntVal :: Int -> Expr Int env+ BoolVal :: Bool -> Expr Bool env + Cons :: Expr a env -> Expr [a] env + -> Expr [a] env+ Nil :: Expr [a] env+ Add :: Expr Int env -> Expr Int env + -> Expr Int env+ LessThan :: Expr Int env -> Expr Int env + -> Expr Bool env + If :: Expr Bool env -> Expr a env + -> Expr a env -> Expr a env - data Expr a env where- Var :: Ref a env -> Expr a env- IntVal :: Int -> Expr Int env- BoolVal :: Bool -> Expr Bool env - Add :: Expr Int env -> Expr Int env - -> Expr Int env- LessThan :: Expr Int env -> Expr Int env- -> Expr Bool env - If :: Expr Bool env -> Expr a env - -> Expr a env -> Expr a env+eval :: Expr a env -> env -> a+eval (Var r) e = lookup r e+eval (IntVal i) _ = i+eval (BoolVal b) _ = b+eval (Add x y) e = eval x e + eval y e+eval (Cons x y) e = eval x e : eval y e+eval Nil _ = []+eval (LessThan x y) e = eval x e < eval y e+eval (If x y z) e = if eval x e + then eval y e+ else eval z e - -----------------------------EASY VERSION (Expr1 -> Env)- - newtype MapExpr1 env2- = MapExpr1 - ( forall x . Expr1 x - -> Maybe (Ref x env2)- )- - emptyExpr1 :: MapExpr1 env2 - emptyExpr1 = MapExpr1 (const Nothing)+type Decls env = Env Expr env env - type TrafoCSE1 inp out = Trafo2 MapExpr1 Expr inp out+data TDecls env = forall env' . TDecls (Decls env') + (T env env') - data FinalExprs = forall env. FinalExprs (Env Expr env env)+a = Suc Zero+b = Zero+exampledecls :: Decls (((),Int),Int)+exampledecls = + Empty `Ext` (IntVal 4) + `Ext` (Add (Add (Var a) (IntVal 4)) + (Add (Var a) (IntVal 4))) - cse1 :: Expr1 t -> FinalExprs- cse1 e- = let result = runTrafo2 (app_cse1 e) emptyExpr1 undefined- in case result of - Result _ _ envs -> FinalExprs envs+resdecls :: TDecls (((),Int),Int)+resdecls = cse exampledecls - app_cse1 :: Expr1 a -> TrafoCSE1 t (Ref a) - app_cse1 e@(IntVal1 i) = arr2 (const (IntVal i)) - >>>> insertExpr1 e - app_cse1 e@(BoolVal1 b) = arr2 (const (BoolVal b)) - >>>> insertExpr1 e - app_cse1 e@(Add1 x y) = (app_cse1 x &&&& app_cse1 y) - >>>> arr2 (\(P (l,r)) -> Add (Var l) (Var r)) - >>>> insertExpr1 e- app_cse1 e@(LessThan1 x y) - = (app_cse1 x &&&& app_cse1 y) - >>>> arr2 (\(P (l,r)) -> LessThan (Var l) (Var r))- >>>> insertExpr1 e- app_cse1 e@(If1 x y z) = (app_cse1 x &&&& app_cse1 y &&&& app_cse1 z) - >>>> arr2 (\(P (P (b,l),r)) -> If (Var b) (Var l) (Var r)) - >>>> insertExpr1 e+evalDecls :: Decls env -> env+evalVar :: Ref a env -> TDecls env -> a+evalVar var (TDecls ds (T tt))+ = lookup (tt var) (evalDecls ds) - insertExpr1 :: Expr1 a -> TrafoCSE1 (Expr a) (Ref a)- insertExpr1 e = - Trafo2- (\(MapExpr1 m) -> case m e of- Nothing -> - case newERef1 e- of Trafo2 step -> step (MapExpr1 m)- Just r -> TrafoE2 (MapExpr1 m) - (\e (T t) env1 upds -> (t r, T t, env1, upds))- )+value_a = evalVar a resdecls+value_b = evalVar b resdecls - newERef1 :: Expr1 a - -> TrafoCSE1 (Expr a) (Ref a)- newERef1 e =- Trafo2 - (\(MapExpr1 m :: MapExpr1 env1) ->- let m2 = MapExpr1 (\s -> aux1 (matchExpr1 e s) m s)- in TrafoE2 m2 - (\e (T t) env1 upds -> ( t Zero- , T (t . Suc) - , Ext env1 e- , upds- ) ) )+evalDecls (ds :: Decls env) = + let result :: env+ result = evalD ds+ evalD :: Env Expr env def -> def+ evalD Empty = ()+ evalD (Ext ds e) = (evalD ds,eval e result)+ in result - aux1 :: Maybe (Equal a x) -> (Expr1 x -> Maybe (Ref x env1)) - -> Expr1 x -> Maybe (Ref x (env1,a))- aux1 (Just Eq) _ _ = Just Zero- aux1 Nothing m s = fmap Suc (m s)+resdecls2 :: TDecls (((),Int),Int) +resdecls2 = - matchExpr1 :: Expr1 a -> Expr1 b - -> Maybe (Equal a b)- matchExpr1 (IntVal1 i1) (IntVal1 i2) - | i1==i2 = Just Eq- matchExpr1 (BoolVal1 b1) (BoolVal1 b2) - | b1==b2 = Just Eq- matchExpr1 (Add1 x1 y1) (Add1 x2 y2) - = do- Eq <- matchExpr1 x1 x2- Eq <- matchExpr1 y1 y2 - return Eq - matchExpr1 (LessThan1 x1 y1) (LessThan1 x2 y2) - = do- Eq <- matchExpr1 x1 x2- Eq <- matchExpr1 y1 y2 - return Eq - matchExpr1 (If1 x1 y1 z1) (If1 x2 y2 z2) - = do- Eq <- matchExpr1 x1 x2- Eq <- matchExpr1 y1 y2 - Eq <- matchExpr1 z1 z2 - return Eq - matchExpr1 _ _ = Nothing+ TDecls+ ( Empty `Ext` (IntVal 4) + `Ext` (Add (Var (Suc (Suc Zero))) + (Var (Suc (Suc Zero))))+ `Ext` (Add (Var (Suc Zero)) + (Var (Suc Zero)))+ )+ ( T (\ref -> case ref of + Zero -> Zero + Suc Zero -> Suc (Suc Zero))+ :: T (((), Int), Int) ((((), Int), Int), Int)) - --- little test1- n1 x = IntVal1 x- env1 = Add1 (Add1 (n1 2) (n1 3)) (Add1 (n1 4) (Add1 (n1 2) (n1 3)))+instance Show (Ref a env) where+ show x = "#" ++ (show $ refint x) +refint :: Ref a env -> Int+refint Zero = 0+refint (Suc x) = 1 + refint x+instance Show (Expr a env) where+ show (Var r) = "v" ++ (show $ refint r)+ show (IntVal i) = show i+ show (BoolVal i) = show i+ show (Add x y) = "(" ++ show x ++ "+"++ show y ++ ")"+ show (LessThan x y) = "(" ++ show x ++ "<"++ show y ++ ")"+ show (If x y z) = "if" ++ show x ++ "then"++ show y ++ "else" ++ show z - res1 = show $ cse1 env1+equals :: Expr a env -> Expr b env -> Maybe (Equal a b)+equals (Var r1) (Var r2) = match r1 r2+equals (IntVal i1) (IntVal i2) + | i1==i2 = Just Eq+equals (LessThan x1 y1) (LessThan x2 y2) + = do Eq <- equals x1 x2 + Eq <- equals y1 y2 + return Eq +equals (BoolVal b1) (BoolVal b2) + | b1==b2 = Just Eq+equals (Add x1 y1) (Add x2 y2) = do+ Eq <- equals x1 x2+ Eq <- equals y1 y2 + return Eq +equals (If x1 y1 z1) (If x2 y2 z2) + = do+ Eq <- equals x1 x2+ Eq <- equals y1 y2 + Eq <- equals z1 z2 + return Eq +equals _ _ = Nothing - ----------------------------MORE COMPLICATED VERSION (Env -> Env)+newtype Memo env env'+ = Memo + ( forall x . Expr x env + -> Maybe (Ref x env')+ ) +emptyMemo :: Memo env ()+emptyMemo = Memo (const Nothing) +type TrafoCSE2 env = Trafo (Memo env) Expr - newtype MapExpr env env2- = MapExpr - ( forall x . Expr x env - -> Maybe (Ref x env2)- )+insertIfNew :: forall s a env . Expr a env + -> TrafoCSE2 env (Expr a ) (Ref a )+insertIfNew e = + Trafo+ (\(Memo m :: Memo env env') -> case m e of+ Nothing -> extEnv (extMemo e (Memo m)) + Just r -> castSRef (Memo m) r + )+ +extMemo :: Expr a env -> Memo env env' + -> Memo env (env',a)+extMemo e (Memo m) + = Memo (\s -> case equals e s of+ Just Eq -> Just Zero+ Nothing -> fmap Suc (m s)+ ) - emptyExpr :: MapExpr env env2 - emptyExpr = MapExpr (const Nothing)+app_cse :: Expr a env + -> TrafoCSE2 env (T env) (Ref a) - initExpr :: TrafoCSE env a b - -> Trafo2 Unit Expr a b- initExpr (Trafo2 st)- = Trafo2 (\_ -> case st emptyExpr of- TrafoE2 _ f -> TrafoE2 Unit f- )+app_cse (Var r) = arr (\(T tenv_s) -> tenv_s r)+app_cse e@(IntVal i) = arr (const (IntVal i)) + >>> insertIfNew e +app_cse e@(BoolVal b) = arr (const (BoolVal b)) + >>> insertIfNew e +app_cse e@(Add x y) = (app_cse x &&& app_cse y) + >>> arr (\(P (l,r)) -> Add (Var l) (Var r)) + >>> insertIfNew e - type TrafoCSE env inp out = Trafo2 (MapExpr env) Expr inp out+app_cse e@(LessThan x y) + = (app_cse x &&& app_cse y) + >>> arr (\(P (l,r)) -> LessThan (Var l) (Var r))+ >>> insertIfNew e - newtype Mapping old new - = Mapping (Env Ref new old) -- map2trans :: Mapping env s -> T env s- map2trans (Mapping env) - = T (\r -> (lookupEnv r env))-+app_cse e@(If x y z) = (app_cse x &&& app_cse y &&& app_cse z) + >>> arr (\(P (P (b,l),r)) -> If (Var b) (Var l) (Var r)) + >>> insertIfNew e + +newtype EEnv r e1 e2 = EEnv (Env r e2 e1) - cse :: Env Expr env env -> FinalExprs- cse e- = let result = runTrafo2 - ( loop2 $ second2 $- arr2 (\menv_s -> map2trans menv_s) >>>> cse_env e - )- Unit -- meta-data- undefined -- input- in case result of - Result _ _ env -> FinalExprs env+cse_env :: Env Expr env env'+ -> TrafoCSE2 env + (T env ) + (EEnv Ref env') - cse_env :: Env Expr env env'- -> Trafo2 Unit - Expr- (T env) - (Mapping env')+cse_env Empty = arr (const (EEnv Empty)) - cse_env (Ext es e) = (initExpr (app_cse e) &&&& cse_env es) - >>>> arr2 (\(P (r, (Mapping renv)))- -> Mapping (Ext renv r)+cse_env (Ext es e) = (app_cse e &&& cse_env es) + >>> arr (\(P (r, (EEnv renv)))+ -> EEnv (Ext renv r) )- cse_env Empty = arr2 (const (Mapping Empty)) - app_cse :: Expr a env -> TrafoCSE env (T env) (Ref a) - app_cse (Var r) = arr2 (\(T tenv_s) -> tenv_s r)- app_cse e@(IntVal i) = arr2 (const (IntVal i)) - >>>> insertExpr e - app_cse e@(BoolVal b) = arr2 (const (BoolVal b)) - >>>> insertExpr e - app_cse e@(Add x y) = (app_cse x &&&& app_cse y) - >>>> arr2 (\(P (l,r)) -> Add (Var l) (Var r)) - >>>> insertExpr e- app_cse e@(LessThan x y) - = (app_cse x &&&& app_cse y) - >>>> arr2 (\(P (l,r)) -> LessThan (Var l) (Var r))- >>>> insertExpr e- app_cse e@(If x y z) = (app_cse x &&&& app_cse y &&&& app_cse z) - >>>> arr2 (\(P (P (b,l),r)) -> If (Var b) (Var l) (Var r)) - >>>> insertExpr e-- insertExpr :: Expr a env -> TrafoCSE env (Expr a) (Ref a)- insertExpr e = - Trafo2- (\(MapExpr m) -> case m e of- Nothing -> - case newERef e- of Trafo2 step -> step (MapExpr m)- Just r -> TrafoE2 (MapExpr m) - (\e (T t) env1 upds -> (t r, T t, env1, upds))- )-- newERef :: Expr a env- -> TrafoCSE env (Expr a) (Ref a)- newERef e =- Trafo2 - (\(MapExpr m :: MapExpr env env1) ->- let m2 = MapExpr (\s -> aux (matchExpr e s) m s)- in TrafoE2 m2 - (\e (T t) env1 upds -> ( t Zero- , T (t . Suc) - , Ext env1 e- , upds- ) ) )-- aux :: Maybe (Equal a x) -> (Expr x env -> Maybe (Ref x env1)) - -> Expr x env -> Maybe (Ref x (env1,a))- aux (Just Eq) _ _ = Just Zero- aux Nothing m s = fmap Suc (m s)+refTransformer :: Env Ref s env -> T env s+refTransformer refs = T (\r -> lookupEnv r refs) - matchExpr :: Expr a env -> Expr b env - -> Maybe (Equal a b)- matchExpr (Var r1) (Var r2) = match r1 r2- matchExpr (IntVal i1) (IntVal i2) - | i1==i2 = Just Eq- matchExpr (BoolVal b1) (BoolVal b2) - | b1==b2 = Just Eq- matchExpr (Add x1 y1) (Add x2 y2) = do- Eq <- matchExpr x1 x2- Eq <- matchExpr y1 y2 - return Eq - matchExpr (LessThan x1 y1) (LessThan x2 y2) - = do- Eq <- matchExpr x1 x2- Eq <- matchExpr y1 y2 - return Eq - matchExpr (If x1 y1 z1) (If x2 y2 z2) - = do- Eq <- matchExpr x1 x2- Eq <- matchExpr y1 y2 - Eq <- matchExpr z1 z2 - return Eq - matchExpr _ _ = Nothing-+data EmptyEnv s = EmptyEnv - --- little test2- vx = Var Zero- n x = IntVal x- env2 = Empty `Ext` (n 2)- `Ext` (Add (Add vx (n 3)) (Add (n 4) (Add vx (n 3))))- - res2 = show $ cse env2+trafo :: Decls env -> TrafoCSE2 env EmptyEnv (T env )+trafo decls = loop $ arr (\(P (_,EEnv refs)) -> refTransformer refs) >>> (arr id &&& cse_env decls) - ------------------------- SHOW-- instance Show (Ref a env) where- show x = "#" ++ (show $ refint x)- - refint :: Ref a env -> Int- refint Zero = 0- refint (Suc x) = 1 + refint x-- instance Show (Expr a env) where- show (Var r) = show r- show (IntVal i) = show i- show (BoolVal i) = show i- show (Add x y) = "(" ++ show x ++ "+"++ show y ++ ")"- show (LessThan x y) = "(" ++ show x ++ "<"++ show y ++ ")"- show (If x y z) = "if" ++ show x ++ "then"++ show y ++ "else" ++ show z-- instance Show (Env Expr env1 env2) where- show (Ext es e) = (show e) ++ "|" ++ show es- show Empty = ""-- instance Show FinalExprs where- show (FinalExprs env) = show env+cse :: forall env . Decls env -> TDecls env+cse decls+ = case runTrafo (trafo decls) emptyMemo EmptyEnv of+ Result _ t env -> TDecls env t
src/Language/AbstractSyntax/TTTAS.hs view
@@ -1,6 +1,6 @@-{-# OPTIONS -XKindSignatures -XRankNTypes -XArrows -XGADTs #-} -{-# LANGUAGE CPP #-} +{-# OPTIONS -XKindSignatures -XRankNTypes -XArrows -XGADTs #-} + {-| Library for Typed Transformations of Typed Abstract Syntax. @@ -10,18 +10,15 @@ For more documentation see the TTTAS webpage: <http://www.cs.uu.nl/wiki/bin/view/Center/TTTAS>. + + For an example see examples/CSE1.hs + -} module Language.AbstractSyntax.TTTAS ( -- * Typed References and Environments - - -- ** Typed References - Ref(..), Equal(..), - match, lookup, update, - - -- ** Declarations - Env(..), FinalEnv, T(..), - lookupEnv, updateEnv, + module Language.AbstractSyntax.TTTAS.Common, + -- * Transformation Library @@ -29,136 +26,34 @@ Trafo(..), TrafoE(..), -- ** Create New References - Unit(..), newSRef, extEnv, castSRef, updateSRef, - -- ** Update the Final Environment - updateFinalEnv, + -- ** State-like operations on the Final Environment + getFinalEnv, putFinalEnv, updateFinalEnv, -- ** Run a Trafo - Result(..), runTrafo, -- ** Other Combinators - sequenceA, + sequenceA, - -- * Alternative Transformation Library - - -- ** Trafo2 - Trafo2(..), TrafoE2(..), - -- ** Create New References - newSRef2, - - -- ** Update the Final Environment - UpdFinalEnv(..), updateFinalEnv2, - - -- ** Run a Trafo2 - runTrafo2, - - -- ** Arrow-style Combinators - Pair(..), Arrow2(..), ArrowLoop2(..), - (>>>>), - List(..), sequenceA2 - ) where -import Unsafe.Coerce ( unsafeCoerce ) -import qualified Prelude as P -#if __GLASGOW_HASKELL__ >= 609 -import Control.Category +#if __GLASGOW_HASKELL__ >= 710 +import Prelude hiding (lookup,(.), id, sequenceA) +#else import Prelude hiding (lookup,(.), id) -#endif +#endif +import Unsafe.Coerce ( unsafeCoerce ) +import Control.Category import Control.Arrow -#if __GLASGOW_HASKELL__ < 609 - hiding (pure) -import Prelude hiding (lookup) -#endif +import Language.AbstractSyntax.TTTAS.Common --- | The 'Ref' type for represents typed indices which are --- labeled with both the type of value to which they --- refer and the type of the environment (a nested --- Cartesian product, growing to the right) in which --- this value lives. - -- The constructor 'Zero' expresses that the first - -- element of the environment has to be of type @a@. - -- The constructor 'Suc' does not care about the type - -- of the first element in the environment, - -- being polymorphic in the type @b@. -data Ref a env where - Zero :: Ref a (env',a) - Suc :: Ref a env' -> Ref a (env',b) --- | The 'Equal' type encodes type equality. -data Equal :: * -> * -> * where - Eq :: Equal a a - --- | The function 'match' compares two references for equality. --- If they refer to the same element in the environment --- the value @Just Eq@ is returned, expressing the fact that --- the types of the referred values are the same too. -match :: Ref a env -> Ref b env -> Maybe (Equal a b) -match Zero Zero = Just Eq -match (Suc x) (Suc y) = match x y -match _ _ = Nothing - --- | The function 'lookup' returns the element indexed in the --- environment parameter by the 'Ref' parameter. The types --- guarantee that the lookup succeeds. -lookup :: Ref a env -> env -> a -lookup Zero (_,a) = a -lookup (Suc r) (e,_) = lookup r e - --- | The function 'update' takes an additional function as --- argument, which is used to update the value the --- reference addresses. -update :: (a -> a) -> Ref a env -> env -> env -update f Zero (e,a) = (e,f a) -update f (Suc r) (e,x) = (update f r e,x) - - --- | The type @Env term use def@ represents a sequence of --- instantiations of type @forall a. term a use@, where --- all the instances of @a@ are stored in the type parameter --- @def@. The type @use@ is a sequence containing the --- types to which may be referred from within terms of type --- @term a use@. -data Env term use def where - Empty :: Env t use () - Ext :: Env t use def' -> t a use - -> Env t use (def',a) - - -lookupEnv :: Ref a env -> Env t s env -> t a s -lookupEnv Zero (Ext _ t) = t -lookupEnv (Suc r) (Ext ts _) = lookupEnv r ts -lookupEnv _ _ = error "Error: The impossible happened!" - -updateEnv :: (t a s -> t a s) -> Ref a env - -> Env t s env -> Env t s env -updateEnv f Zero (Ext ts t) - = Ext ts (f t) -updateEnv f (Suc r) (Ext ts t) - = Ext (updateEnv f r ts) t -updateEnv _ _ _ - = error "Error: The impossible happened!" - - --- | When the types @def@ and @use@ of an 'Env' coincide, --- we can be sure that the references in the terms do not --- point to values outside the environment but point --- to terms representing the right type. This kind of --- environment is the /final environment/ of a transformation. -type FinalEnv t usedef = Env t usedef usedef - --- | The type 'T' encodes a 'Ref'-transformer. It is usually used --- to transform references from an actual environment to --- the final one. -newtype T e s = T {unT :: forall x . Ref x e -> Ref x s} - -- | The type 'Trafo' is the type of the transformation steps on a heterogeneous collection. -- The argument @m@ stands for the type of the meta-data. -- A |Trafo| takes the meta-data on the current environment |env1| as input and @@ -167,6 +62,10 @@ -- The type variable @s@ represents the type of the final result, which we do expose. -- Its role is similar to the @s@ in the type @ST s a@. -- The arguments @a@ and @b@ are the Arrow's input and output, respectively. + + + + data Trafo m t s a b = Trafo (forall env1 . m env1 -> TrafoE m t s env1 a b) @@ -175,22 +74,20 @@ -- It can be seen that a 'Trafo' is a function taking as arguments: the input (@a@), -- a 'Ref'-transformer (@T env2 s@) from the environment constructed in this step -- to the final environment, the environment (@Env t s env1@) where the current --- transformation starts and a function (@FinalEnv t s -> FinalEnv t s@) to update --- (modify) the final environment. The function returns: the output (@b@), +-- transformation starts and the "final environment" (@FinalEnv t s@) +-- with the updates thus far applied. +-- The function returns: the output (@b@), -- a 'Ref'-transformer (@T env1 s@) from the initial environment of this step to the final --- environment, the environment (@Env t s env2@) constructed in this step and a function --- (@FinalEnv t s -> FinalEnv t s@) to update (modify) the final environment. --- NOTE: The function (@FinalEnv t s -> FinalEnv t s@) was introduced in version 0.3. --- It's carried throw the transformation steps and can be modified (composed to another function) --- using the function 'updateFinalEnv'. +-- environment, the environment (@Env t s env2@) constructed in this step and the final environment +-- (@FinalEnv t s@) possibly updated. data TrafoE m t s env1 a b = forall env2 . TrafoE ( m env2) - ( a -> T env2 s -> Env t s env1 -> (FinalEnv t s -> FinalEnv t s) - -> ( b, T env1 s, Env t s env2, (FinalEnv t s -> FinalEnv t s)) + ( a -> T env2 s -> Env t s env1 -> FinalEnv t s + -> ( b, T env1 s, Env t s env2, FinalEnv t s) ) -data Unit s = Unit + -- | The Trafo 'newSRef' takes a typed term as input, adds it to the environment -- and yields a reference pointing to this value. -- No meta-information on the environment is recorded by 'newSRef'; @@ -200,20 +97,33 @@ = Trafo (\ _-> extEnv Unit) --- | The function 'updateFinalEnv' returns a 'Trafo' that introduces a function --- (@FinalEnv t s -> FinalEnv t s@) to update the final environment. + +-- | Change the final environment by the one passed in the input. +putFinalEnv :: Trafo m t s (FinalEnv t s) () +putFinalEnv = Trafo $ \m -> (TrafoE m (\fe t e _ -> ((), t, e, fe))) + +-- | Return as output the final environment. +getFinalEnv :: Trafo m t s () (FinalEnv t s) +getFinalEnv = Trafo $ \m -> (TrafoE m (\_ t e fe -> (fe, t, e, fe))) + +-- | The function 'updateFinalEnv' returns a 'Trafo' that updates the +-- final environment using the input function +-- (@FinalEnv t s -> FinalEnv t s@). updateFinalEnv :: Trafo m t s (FinalEnv t s -> FinalEnv t s) () -updateFinalEnv = Trafo $ \m -> (TrafoE m (\f' t e f -> ((), t, e, f' . f))) +updateFinalEnv = proc f -> + do fe <- getFinalEnv -< () + putFinalEnv -< f fe + -- Trafo $ \m -> (TrafoE m (\f t e fe -> ((), t, e, f fe))) -- | The function 'extEnv' returns a 'TrafoE' that extends the current environment. extEnv :: m (e,a) -> TrafoE m t s e (t a s) (Ref a s) -extEnv m = TrafoE m $ \ta (T tr) env f -> (tr Zero, T (tr P.. Suc), Ext env ta, f ) +extEnv m = TrafoE m $ \ta (T tr) env fe -> (tr Zero, T (tr . Suc), Ext env ta, fe ) -- | The function 'castSRef' returns a 'TrafoE' that casts the reference -- passed as parameter (in the constructed environment) to one in the final environment. castSRef :: m e -> Ref a e -> TrafoE m t s e x (Ref a s) -castSRef m r = TrafoE m $ (\ _ (T t) decls f -> (t r, T t, decls, f)) +castSRef m r = TrafoE m $ (\ _ (T t) decls fe -> (t r, T t, decls, fe)) -- | The function 'updateSRef' returns a 'TrafoE' that updates the value pointed -- by the reference passed as parameter into the current environment. @@ -222,14 +132,11 @@ instance Functor (TrafoE m t s e a) where - fmap f (TrafoE m step) = TrafoE m $ \i t e fs -> case step i t e fs of - (i',t',e',fs') -> (f i',t',e',fs') + fmap f (TrafoE m step) = TrafoE m $ \i t e fe -> case step i t e fe of + (i',t',e',fe') -> (f i',t',e',fe') --- | The type 'Result' is the type of the result of \"running\" a 'Trafo'. --- Because @s@ could be anything we have to hide it using existential quantification. -data Result m t b - = forall s . Result (m s) (b s) (FinalEnv t s) + -- | The function 'runTrafo' takes as arguments the 'Trafo' we want to run, meta-information -- for the empty environment, and an input value. -- The result of 'runTrafo' (type 'Result') is the final environment (@Env t s s@) together @@ -240,15 +147,14 @@ -> Result m t b runTrafo trafo m a = case trafo of Trafo trf -> case trf m of - TrafoE m2 f -> - case f a (T unsafeCoerce) Empty P.id of -- the function could also be passed as argument - (rb, _, env2, fenvs) -> - Result (unsafeCoerce m2) + TrafoE m2 f -> + let (rb, _, env2, fenv) = f a (T unsafeCoerce) Empty (unsafeCoerce env2) + in Result (unsafeCoerce m2) rb - (fenvs $ unsafeCoerce env2) + (unsafeCoerce fenv) -#if __GLASGOW_HASKELL__ >= 609 + instance Category (Trafo m t s) where -- |(.) :: Trafo m t s b c -> Trafo m t s a b -> Trafo m t s a c| Trafo t2 . Trafo t1 = @@ -268,32 +174,12 @@ -- |id :: Trafo m t s a a| id = Trafo (\m -> TrafoE m (\a t e f -> (a, t, e, f)) ) -#endif - - instance Arrow (Trafo m t s) where -- |arr :: (a -> b) -> Trafo m t s a b| arr f = Trafo (\m -> TrafoE m (\a t e fs -> (f a, t, e, fs)) ) -#if __GLASGOW_HASKELL__ < 609 - Trafo t1 >>> Trafo t2 = - Trafo - (\m1 -> case t1 m1 of - TrafoE m2 f1 -> case t2 m2 of - TrafoE m3 f2 -> - TrafoE - m3 - (\a tt env1 fs -> - let (b,tt1, env2, fs') = f1 a tt2 env1 fs - (c,tt2, env3, fs'') = f2 b tt env2 fs' - in (c,tt1, env3, fs'') - ) - ) - -#endif - -- |first :: Trafo m t s a b -> Trafo m t s (a, c) (b, c)| first (Trafo tr) = Trafo (\m1 -> case tr m1 of @@ -331,151 +217,4 @@ bs <- sequenceA xs -< a returnA -< (b:bs) - - - --- | Alternative version of 'Trafo' where the universal quantification --- over |s| is moved inside the quantification over |env2|. --- Note that the type variables |a| and |b| are now labelled with |s|, --- and hence have kind |(* -> *)|. -data Trafo2 m t a b = - Trafo2 (forall env1 . m env1 -> TrafoE2 m t env1 a b) -data TrafoE2 m t env1 a b = - forall env2 . TrafoE2 - (m env2) - (forall s . a s -> T env2 s -> Env t s env1 -> UpdFinalEnv t s - -> (b s, T env1 s, Env t s env2, UpdFinalEnv t s) - ) - -newtype UpdFinalEnv t s = Upd (FinalEnv t s -> FinalEnv t s) - --- | The function 'runTrafo2' takes as arguments the 'Trafo2' we want to run, meta-information --- for the empty environment, and an input value. --- The result of 'runTrafo2' (type 'Result') is the final environment (@Env t s s@) together --- with the resulting meta-data (@m s@), and the output value (@b s@). --- The rank-2 type for 'runTrafo2' ensures that transformation steps cannot make --- any assumptions about the type of final environment (@s@). --- It is an alternative version of 'runTrafo' which does not use --- 'unsafeCoerce'. -runTrafo2 :: Trafo2 m t a b -> m () -> (forall s . a s) - -> Result m t b -runTrafo2 trafo m a = - case trafo of - Trafo2 trf -> case trf m of - TrafoE2 m2 f -> - let (rb, _, env2, Upd upds) = f a (T P.id) Empty (Upd P.id) - in Result m2 rb (upds env2) - - --- | The Trafo2 'newSRef2' takes a typed term as input, adds it to the environment --- and yields a reference pointing to this value. --- No meta-information on the environment is recorded by 'newSRef2'; --- therefore we use the type 'Unit' for the meta-data. -newSRef2 :: Trafo2 Unit t (t a) (Ref a) -newSRef2 - = Trafo2 - (\Unit -> TrafoE2 - Unit - (\ta (T tr) env upds -> - ( tr Zero - , T (tr P.. Suc) - , Ext env ta - , upds - ) ) ) - - --- | The function 'updateFinalEnv2' returns a 'Trafo2' that introduces a function --- (@(UpdFinalEnv t)@) to update the final environment. -updateFinalEnv2 :: Trafo2 m t (UpdFinalEnv t) Unit -updateFinalEnv2 = Trafo2 $ \m -> (TrafoE2 m (\(Upd u') t e (Upd u) -> (Unit, t, e, (Upd $ u' P.. u)))) - - -newtype Pair a b s = P (a s, b s) - -class Category2 (cat :: (* -> *) -> (* -> *) -> *) where - id2 :: cat a a - (.:.) :: cat b c -> cat a b -> cat a c - -class Category2 arr => Arrow2 (arr :: (* -> *) -> (* -> *) -> *) where - arr2 :: (forall s . a s -> b s) -> arr a b - first2 :: arr a b -> arr (Pair a c) (Pair b c) - second2 :: arr a b -> arr (Pair c a) (Pair c b) - (****) :: arr a b -> arr a' b' - -> arr (Pair a a') (Pair b b') - (&&&&) :: arr a b -> arr a b' -> arr a (Pair b b') - -class Arrow2 arr => ArrowLoop2 arr where - loop2 :: arr (Pair a c) (Pair b c) -> arr a b - - -instance Category2 (Trafo2 m t) where - id2 = Trafo2 (\m -> TrafoE2 m (\a t e u -> (a, t, e, u))) - - (.:.) (Trafo2 sb) (Trafo2 sa) = - Trafo2 - (\m1 -> - case sa m1 of - TrafoE2 m2 f1 -> case sb m2 of - TrafoE2 m3 f2 -> - TrafoE2 - m3 - (\a t3s e1 u1 -> let (b, t1s, e2, u2) = f1 a t2s e1 u1 - (c, t2s, e3, u3) = f2 b t3s e2 u2 - in (c, t1s, e3, u3) - )) - - -(>>>>) :: Category2 cat => cat a b -> cat b c -> cat a c -f >>>> g = g .:. f - - -instance Arrow2 (Trafo2 m t) where - arr2 f - = Trafo2 (\m -> TrafoE2 m (\a t e u -> (f a, t, e, u)) ) - - - first2 (Trafo2 s) - = Trafo2 - (\m1 -> case s m1 of - TrafoE2 m2 f -> - TrafoE2 m2 - (\(P (a, c)) t2s e1 u1 -> - let (b,t12,e2,u2) = f a t2s e1 u1 - in (P (b, c),t12,e2,u2) - ) - ) - - second2 f = arr2 swap >>>> first2 f >>>> arr2 swap - where swap :: Pair c a s -> Pair a c s - swap ~(P (x, y)) = P (y, x) - - f **** g = first2 f >>>> second2 g - - f &&&& g = arr2 (\b -> P (b, b)) >>>> (f **** g) - - -instance ArrowLoop2 (Trafo2 m t) where - loop2 (Trafo2 st) = - Trafo2 - (\m -> case st m of - TrafoE2 m1 f1 -> - TrafoE2 m1 - (\a t e u -> - let (P (b, x),t1,e1,u1) = f1 (P (a, x)) t e u - in (b,t1,e1,u1) - ) - ) - - -newtype List a s = List [a s] - --- | The combinator 'sequenceA2' sequentially composes a list --- of 'Trafo2's into a 'Trafo2' that yields a 'List' of outputs. --- Its use is analogous to the combinator 'sequence' combinator --- for 'Monad's. -sequenceA2 :: [Trafo2 m t a b] -> Trafo2 m t a (List b) -sequenceA2 [] = arr2 (const (List [])) -sequenceA2 (x:xs) - = (x &&&& sequenceA2 xs) >>>> - arr2 (\(P (a,List as)) -> List (a:as))
+ src/Language/AbstractSyntax/TTTAS/Common.hs view
@@ -0,0 +1,122 @@+{-# OPTIONS -XKindSignatures -XRankNTypes -XArrows -XGADTs #-} + + +{-| + Library for Typed Transformations of Typed Abstract Syntax. + + The library is documented in the paper: /Typed Transformations of Typed Abstract Syntax/ + + Bibtex entry: <http://www.cs.uu.nl/wiki/bin/viewfile/Center/TTTAS?rev=1;filename=TTTAS.bib> + + For more documentation see the TTTAS webpage: + <http://www.cs.uu.nl/wiki/bin/view/Center/TTTAS>. +-} + +module Language.AbstractSyntax.TTTAS.Common ( + -- * Typed References and Environments + + -- ** Typed References + Ref(..), Equal(..), + match, lookup, update, + + -- ** Declarations + Env(..), FinalEnv, T(..), + lookupEnv, updateEnv, + Unit(..), + Result(..), + + ) where + +import Prelude hiding (lookup) + + +-- | The 'Ref' type for represents typed indices which are +-- labeled with both the type of value to which they +-- refer and the type of the environment (a nested +-- Cartesian product, growing to the right) in which +-- this value lives. + -- The constructor 'Zero' expresses that the first + -- element of the environment has to be of type @a@. + -- The constructor 'Suc' does not care about the type + -- of the first element in the environment, + -- being polymorphic in the type @b@. +data Ref a env where + Zero :: Ref a (env',a) + Suc :: Ref a env' -> Ref a (env',b) + +-- | The 'Equal' type encodes type equality. +data Equal :: * -> * -> * where + Eq :: Equal a a + +-- | The function 'match' compares two references for equality. +-- If they refer to the same element in the environment +-- the value @Just Eq@ is returned, expressing the fact that +-- the types of the referred values are the same too. +match :: Ref a env -> Ref b env -> Maybe (Equal a b) +match Zero Zero = Just Eq +match (Suc x) (Suc y) = match x y +match _ _ = Nothing + +-- | The function 'lookup' returns the element indexed in the +-- environment parameter by the 'Ref' parameter. The types +-- guarantee that the lookup succeeds. +lookup :: Ref a env -> env -> a +lookup Zero (_,a) = a +lookup (Suc r) (e,_) = lookup r e + +-- | The function 'update' takes an additional function as +-- argument, which is used to update the value the +-- reference addresses. +update :: (a -> a) -> Ref a env -> env -> env +update f Zero (e,a) = (e,f a) +update f (Suc r) (e,x) = (update f r e,x) + + +-- | The type @Env term use def@ represents a sequence of +-- instantiations of type @forall a. term a use@, where +-- all the instances of @a@ are stored in the type parameter +-- @def@. The type @use@ is a sequence containing the +-- types to which may be referred from within terms of type +-- @term a use@. +data Env term use def where + Empty :: Env t use () + Ext :: Env t use def' -> t a use + -> Env t use (def',a) + + +data Unit s = Unit + +lookupEnv :: Ref a env -> Env t s env -> t a s +lookupEnv Zero (Ext _ t) = t +lookupEnv (Suc r) (Ext ts _) = lookupEnv r ts +lookupEnv _ _ = error "Error: The impossible happened!" + +updateEnv :: (t a s -> t a s) -> Ref a env + -> Env t s env -> Env t s env +updateEnv f Zero (Ext ts t) + = Ext ts (f t) +updateEnv f (Suc r) (Ext ts t) + = Ext (updateEnv f r ts) t +updateEnv _ _ _ + = error "Error: The impossible happened!" + + +-- | When the types @def@ and @use@ of an 'Env' coincide, +-- we can be sure that the references in the terms do not +-- point to values outside the environment but point +-- to terms representing the right type. This kind of +-- environment is the /final environment/ of a transformation. +type FinalEnv t usedef = Env t usedef usedef + +-- | The type 'Result' is the type of the result of \"running\" a 'Trafo'. +-- Because @s@ could be anything we have to hide it using existential quantification. +data Result m t b + = forall s . Result (m s) (b s) (FinalEnv t s) + + + +-- | The type 'T' encodes a 'Ref'-transformer. It is usually used +-- to transform references from an actual environment to +-- the final one. +newtype T e s = T {unT :: forall x . Ref x e -> Ref x s} +
+ src/Language/AbstractSyntax/TTTAS2.hs view
@@ -0,0 +1,246 @@+{-# OPTIONS -XKindSignatures -XRankNTypes -XArrows -XGADTs #-} + + +{-| + Library for Typed Transformations of Typed Abstract Syntax. + + The library is documented in the paper: /Typed Transformations of Typed Abstract Syntax/ + + Bibtex entry: <http://www.cs.uu.nl/wiki/bin/viewfile/Center/TTTAS?rev=1;filename=TTTAS.bib> + + For more documentation see the TTTAS webpage: + <http://www.cs.uu.nl/wiki/bin/view/Center/TTTAS>. + + For an example see examples/CSE2.hs + + IMPORTANT: We would like to be able to use RebinadbleSyntax + to use Arrow's Syntax in this variant of TTTAS, + but this extension still doesn't work well with Arrows. +-} + +module Language.AbstractSyntax.TTTAS2 ( + -- * Typed References and Environments + module Language.AbstractSyntax.TTTAS.Common, + + -- * Transformation Library + + -- ** Trafo + Trafo(..), TrafoE(..), + + -- ** Create New References + newSRef, + extEnv, + castSRef, + updateSRef, + + -- ** State-like operations on the Final Environment + getFinalEnv, putFinalEnv, updateFinalEnv, + + -- ** Run a Trafo + runTrafo, + + -- ** Arrow-style Combinators + Pair(..), Arrow2(..), ArrowLoop2(..), + (>>>), + List(..), sequenceA, returnA + + ) where + +#if __GLASGOW_HASKELL__ >= 710 +import Prelude hiding (lookup, sequenceA) +#else +import Prelude hiding (lookup) +#endif + +import Language.AbstractSyntax.TTTAS.Common + + + + +-- | Alternative version of 'Trafo' where the universal quantification +-- over |s| is moved inside the quantification over |env2|. +-- Note that the type variables |a| and |b| are now labelled with |s|, +-- and hence have kind |(* -> *)|. +data Trafo m t a b = + Trafo (forall env1 . m env1 -> TrafoE m t env1 a b) +data TrafoE m t env1 a b = + forall env2 . TrafoE + (m env2) + (forall s . a s -> T env2 s -> Env t s env1 -> FinalEnv t s + -> (b s, T env1 s, Env t s env2, FinalEnv t s) + ) + + +-- | The function 'runTrafo' takes as arguments the 'Trafo' we want to run, meta-information +-- for the empty environment, and an input value. +-- The result of 'runTrafo' (type 'Result') is the final environment (@Env t s s@) together +-- with the resulting meta-data (@m s@), and the output value (@b s@). +-- The rank-2 type for 'runTrafo2' ensures that transformation steps cannot make +-- any assumptions about the type of final environment (@s@). +-- It is an alternative version of 'runTrafo' which does not use +-- 'unsafeCoerce'. +runTrafo :: Trafo m t a b -> m () -> (forall s . a s) + -> Result m t b +runTrafo trafo m a = + case trafo of + Trafo trf -> case trf m of + TrafoE m2 f -> + let (rb, _, env2, fenv) = f a (T id) Empty env2 + in Result m2 rb fenv + + +-- | The Trafo2 'newSRef2' takes a typed term as input, adds it to the environment +-- and yields a reference pointing to this value. +-- No meta-information on the environment is recorded by 'newSRef2'; +-- therefore we use the type 'Unit' for the meta-data. +newSRef :: Trafo Unit t (t a) (Ref a) +newSRef + = Trafo + (\Unit -> TrafoE + Unit + (\ta (T tr) env fenv -> + ( tr Zero + , T (tr . Suc) + , Ext env ta + , fenv + ) ) ) + + +-- | The function 'extEnv' returns a 'TrafoE' that extends the current environment. +extEnv :: m (e,a) -> TrafoE m t e (t a ) (Ref a ) +extEnv m = TrafoE m $ \ta (T tr) env fe -> (tr Zero, T (tr . Suc), Ext env ta, fe ) + +-- | The function 'castSRef' returns a 'TrafoE' that casts the reference +-- passed as parameter (in the constructed environment) to one in the final environment. +castSRef :: m e -> Ref a e -> TrafoE m t e x (Ref a) +castSRef m r = TrafoE m $ (\ _ (T t) decls fe -> (t r, T t, decls, fe)) + +data FUpd i t a = FUpd (forall s. i -> t a s -> t a s) +newtype SI i s = SI i + +-- | The function 'updateSRef' returns a 'TrafoE' that updates the value pointed +-- by the reference passed as parameter into the current environment. +updateSRef :: m e -> Ref a e -> FUpd i t a -> TrafoE m t e (SI i) (Ref a) +updateSRef m r (FUpd f) = TrafoE m $ \(SI i) (T t) decls fs -> (t r, T t, updateEnv (f i) r decls, fs) + + +newtype UpdFinalEnv t s = Upd (FinalEnv t s -> FinalEnv t s) + +newtype FinalEnv2 t s = Final (FinalEnv t s) + +-- | The function 'updateFinalEnv' returns a 'Trafo' that introduces a function +-- (@(UpdFinalEnv t)@) to update the final environment. +updateFinalEnv :: Trafo m t (UpdFinalEnv t) Unit +updateFinalEnv = Trafo $ \m -> (TrafoE m (\(Upd u) t e fe -> (Unit, t, e, u fe))) + +-- | Change the final environment by the one passed in the input. +putFinalEnv :: Trafo m t (FinalEnv2 t) Unit +putFinalEnv = Trafo $ \m -> (TrafoE m (\(Final fe) t e _ -> (Unit, t, e, fe))) + +-- | Return as output the final environment. +getFinalEnv :: Trafo m t Unit (FinalEnv2 t) +getFinalEnv = Trafo $ \m -> (TrafoE m (\_ t e fe -> ((Final fe), t, e, fe))) + +{- +-- | The function 'updateFinalEnv' returns a 'Trafo' that introduces a function +-- (@FinalEnv t s -> FinalEnv t s@) to update the final environment. +updateFinalEnv :: Trafo m t s (FinalEnv t s -> FinalEnv t s) () +updateFinalEnv = proc f -> + do fe <- getFinalEnv -< () + putFinalEnv -< f fe + -- Trafo $ \m -> (TrafoE m (\f t e fe -> ((), t, e, f fe))) +-} + +newtype Pair a b s = P (a s, b s) + +class Category2 (cat :: (* -> *) -> (* -> *) -> *) where + id2 :: cat a a + (.:.) :: cat b c -> cat a b -> cat a c + +class Category2 arr => Arrow2 (arr :: (* -> *) -> (* -> *) -> *) where + arr :: (forall s . a s -> b s) -> arr a b + first :: arr a b -> arr (Pair a c) (Pair b c) + second :: arr a b -> arr (Pair c a) (Pair c b) + (***) :: arr a b -> arr a' b' + -> arr (Pair a a') (Pair b b') + (&&&) :: arr a b -> arr a b' -> arr a (Pair b b') + +class Arrow2 arr => ArrowLoop2 arr where + loop :: arr (Pair a c) (Pair b c) -> arr a b + + +instance Category2 (Trafo m t) where + id2 = Trafo (\m -> TrafoE m (\a t e u -> (a, t, e, u))) + + (.:.) (Trafo sb) (Trafo sa) = + Trafo + (\m1 -> + case sa m1 of + TrafoE m2 f1 -> case sb m2 of + TrafoE m3 f2 -> + TrafoE + m3 + (\a t3s e1 u1 -> let (b, t1s, e2, u2) = f1 a t2s e1 u1 + (c, t2s, e3, u3) = f2 b t3s e2 u2 + in (c, t1s, e3, u3) + )) + + +(>>>) :: Category2 cat => cat a b -> cat b c -> cat a c +f >>> g = g .:. f + + +instance Arrow2 (Trafo m t) where + arr f + = Trafo (\m -> TrafoE m (\a t e u -> (f a, t, e, u)) ) + + + first (Trafo s) + = Trafo + (\m1 -> case s m1 of + TrafoE m2 f -> + TrafoE m2 + (\(P (a, c)) t2s e1 u1 -> + let (b,t12,e2,u2) = f a t2s e1 u1 + in (P (b, c),t12,e2,u2) + ) + ) + + second f = arr swap >>> first f >>> arr swap + where swap :: Pair c a s -> Pair a c s + swap ~(P (x, y)) = P (y, x) + + f *** g = first f >>> second g + + f &&& g = arr (\b -> P (b, b)) >>> (f *** g) + + +instance ArrowLoop2 (Trafo m t) where + loop (Trafo st) = + Trafo + (\m -> case st m of + TrafoE m1 f1 -> + TrafoE m1 + (\a t e u -> + let (P (b, x),t1,e1,u1) = f1 (P (a, x)) t e u + in (b,t1,e1,u1) + ) + ) + + +newtype List a s = List [a s] + +-- | The combinator 'sequenceA2' sequentially composes a list +-- of 'Trafo2's into a 'Trafo2' that yields a 'List' of outputs. +-- Its use is analogous to the combinator 'sequence' combinator +-- for 'Monad's. +sequenceA :: [Trafo m t a b] -> Trafo m t a (List b) +sequenceA [] = arr (const (List [])) +sequenceA (x:xs) + = (x &&& sequenceA xs) >>> + arr (\(P (a,List as)) -> List (a:as)) + +returnA :: Arrow2 arr => arr a a +returnA = arr id + +