syntactic 3.5 → 3.6
raw patch · 16 files changed
+280/−364 lines, 16 files
Files
- examples/NanoFeldspar.hs +2/−4
- src/Data/NestTuple.hs +24/−0
- src/Data/NestTuple/TH.hs +74/−0
- src/Language/Syntactic/Decoration.hs +43/−0
- src/Language/Syntactic/Functional.hs +13/−96
- src/Language/Syntactic/Functional/Sharing.hs +22/−9
- src/Language/Syntactic/Functional/Tuple.hs +9/−54
- src/Language/Syntactic/Functional/Tuple/TH.hs +24/−172
- src/Language/Syntactic/Sugar/Tuple.hs +17/−3
- src/Language/Syntactic/Sugar/TupleTyped.hs +22/−1
- src/Language/Syntactic/Syntax.hs +2/−2
- src/Language/Syntactic/TH.hs +7/−4
- syntactic.cabal +4/−4
- tests/AlgorithmTests.hs +5/−3
- tests/gold/fib.txt +6/−6
- tests/gold/spanVec.txt +6/−6
examples/NanoFeldspar.hs view
@@ -160,10 +160,8 @@ -- arguments of higher-order constructs such as `Parallel` are always -- lambdas. sharable (sel :$ _) _- | Just Sel1 <- prj sel = False- | Just Sel2 <- prj sel = False- | Just Sel3 <- prj sel = False- | Just Sel4 <- prj sel = False+ | Just Fst <- prj sel = False+ | Just Snd <- prj sel = False -- Tuple selection not shared sharable (arrl :$ _ ) _ | Just (Construct "arrLen" _) <- prj arrl = False
+ src/Data/NestTuple.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}++-- | Conversion between tuples and nested pairs++module Data.NestTuple where++++import Data.NestTuple.TH++++-- | Tuples that can be converted to/from nested pairs+class Nestable tup+ where+ -- | Representation as nested pairs+ type Nested tup+ -- | Convert to nested pairs+ nest :: tup -> Nested tup+ -- | Convert from nested pairs+ unnest :: Nested tup -> tup++mkNestableInstances 15+
+ src/Data/NestTuple/TH.hs view
@@ -0,0 +1,74 @@+module Data.NestTuple.TH where++++import Language.Haskell.TH++import Language.Syntactic.TH++++mkTupT :: [Type] -> Type+mkTupT ts = foldl AppT (TupleT (length ts)) ts++mkPairT :: Type -> Type -> Type+mkPairT a b = foldl AppT (TupleT 2) [a,b]++mkPairE :: Exp -> Exp -> Exp+mkPairE a b = TupE [a,b]++mkPairP :: Pat -> Pat -> Pat+mkPairP a b = TupP [a,b]++data Nest a+ = Leaf a+ | Pair (Nest a) (Nest a)+ deriving (Eq, Show, Functor)++foldNest :: (a -> b) -> (b -> b -> b) -> Nest a -> b+foldNest leaf pair = go+ where+ go (Leaf a) = leaf a+ go (Pair a b) = pair (go a) (go b)++toNest :: [a] -> Nest a+toNest [a] = Leaf a+toNest as = Pair (toNest bs) (toNest cs)+ where+ (bs,cs) = splitAt ((length as + 1) `div` 2) as++++-- Make instances of the form+--+-- > instance Nestable (a,...,x)+-- > where+-- > type Nested (a,...,x) = (a ... x) -- nested pairs+-- > nest (a,...,x) = (a ... x)+-- > unnest (a ... x) = (a,...,x)+mkNestableInstances+ :: Int -- ^ Max tuple width+ -> DecsQ+mkNestableInstances n = return $ map nestableInstance [2..n]+ where+ nestableInstance w = InstanceD+ []+ (AppT (ConT (mkName "Nestable")) tupT)+ [ tySynInst (mkName "Nested") [tupT] (foldNest VarT mkPairT $ toNest vars)+ , FunD (mkName "nest")+ [ Clause+ [TupP (map VarP vars)]+ (NormalB (foldNest VarE mkPairE $ toNest vars))+ []+ ]+ , FunD (mkName "unnest")+ [ Clause+ [foldNest VarP mkPairP $ toNest vars]+ (NormalB (TupE (map VarE vars)))+ []+ ]+ ]+ where+ vars = take w varSupply+ tupT = mkTupT $ map VarT vars+
src/Language/Syntactic/Decoration.hs view
@@ -23,6 +23,7 @@ import Language.Syntactic.Syntax import Language.Syntactic.Traversal import Language.Syntactic.Interpretation+import Language.Syntactic.Sugar @@ -135,4 +136,46 @@ mkTree :: [Tree NodeInfo] -> AST (sym :&: info) sig -> Tree NodeInfo mkTree args (f :$ a) = mkTree (mkTree [] a : args) f mkTree args (Sym (expr :&: info)) = Node (NodeInfo (renderSym expr) (showInfo info)) args++-- | Make a smart constructor of a symbol. 'smartSymDecor' has any type of the+-- form:+--+-- > smartSymDecor :: (sub :<: AST (sup :&: info))+-- > => info x+-- > -> sub (a :-> b :-> ... :-> Full x)+-- > -> (ASTF sup a -> ASTF sup b -> ... -> ASTF sup x)+smartSymDecor+ :: ( Signature sig+ , f ~ SmartFun (sup :&: info) sig+ , sig ~ SmartSig f+ , (sup :&: info) ~ SmartSym f+ , sub :<: sup+ )+ => info (DenResult sig) -> sub sig -> f+smartSymDecor d = smartSym' . (:&: d) . inj++-- | \"Sugared\" symbol application+--+-- 'sugarSymDecor' has any type of the form:+--+-- > sugarSymDecor ::+-- > ( sub :<: AST (sup :&: info)+-- > , Syntactic a+-- > , Syntactic b+-- > , ...+-- > , Syntactic x+-- > , Domain a ~ Domain b ~ ... ~ Domain x+-- > ) => info (Internal x)+-- > -> sub (Internal a :-> Internal b :-> ... :-> Full (Internal x))+-- > -> (a -> b -> ... -> x)+sugarSymDecor+ :: ( Signature sig+ , fi ~ SmartFun (sup :&: info) sig+ , sig ~ SmartSig fi+ , (sup :&: info) ~ SmartSym fi+ , SyntacticN f fi+ , sub :<: sup+ )+ => info (DenResult sig) -> sub sig -> f+sugarSymDecor i = sugarN . smartSymDecor i
src/Language/Syntactic/Functional.hs view
@@ -45,8 +45,6 @@ , allVars , renameUnique' , renameUnique- -- * Substitution- , parSubst -- * Alpha-equivalence , AlphaEnv , alphaEq'@@ -75,7 +73,6 @@ import Control.Monad.Reader import Control.Monad.State import Data.Dynamic-import qualified Data.Foldable as Foldable import Data.List (genericIndex) #if MIN_VERSION_GLASGOW_HASKELL(7,10,0,0) #else@@ -87,7 +84,6 @@ import qualified Data.Set as Set import Data.Tree -import Data.Constraint import Data.Hash (hashInt) import Language.Syntactic@@ -217,13 +213,13 @@ -- (ICFP 2013, <http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf>). lam_template :: (Project Binding sym) => (Name -> sym (Full a))- -- ^ Variable constructor- -> (Name -> sym (b :-> Full (a -> b)))+ -- ^ Variable symbol constructor+ -> (Name -> ASTF sym b -> ASTF sym (a -> b)) -- ^ Lambda constructor -> (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)-lam_template mkVar mkLam f = Sym (mkLam v) :$ body+lam_template mkVar mkLam f = mkLam v body where- body = f (Sym (mkVar v))+ body = f $ Sym $ mkVar v v = succ $ maxLam body -- | Higher-order interface for variable binding@@ -231,7 +227,7 @@ -- This function is 'lamT_template' specialized to domains @sym@ satisfying -- @(`Binding` `:<:` sym)@. lam :: (Binding :<: sym) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)-lam = lam_template (inj . Var) (inj . Lam)+lam = lam_template (inj . Var) (\v a -> Sym (inj (Lam v)) :$ a) -- | Convert from a term with De Bruijn indexes to one with explicit names --@@ -317,13 +313,13 @@ -- (ICFP 2013, <http://www.cse.chalmers.se/~emax/documents/axelsson2013using.pdf>). lamT_template :: Project BindingT sym => (Name -> sym (Full a))- -- ^ Variable constructor- -> (Name -> sym (b :-> Full (a -> b)))+ -- ^ Variable symbol constructor+ -> (Name -> ASTF sym b -> ASTF sym (a -> b)) -- ^ Lambda constructor -> (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)-lamT_template mkVarSym mkLamSym f = Sym (mkLamSym v) :$ body+lamT_template mkVar mkLam f = mkLam v body where- body = f (Sym $ mkVarSym v)+ body = f $ Sym $ mkVar v v = succ $ maxLamT body -- | Higher-order interface for variable binding@@ -332,7 +328,7 @@ -- @(`BindingT` `:<:` sym)@. lamT :: (BindingT :<: sym, Typeable a) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)-lamT = lamT_template (inj . VarT) (inj . LamT)+lamT = lamT_template (inj . VarT) (\v a -> Sym (inj (LamT v)) :$ a) -- | Higher-order interface for variable binding --@@ -340,7 +336,9 @@ -- @(sym ~ `Typed` s, `BindingT` `:<:` s)@. lamTyped :: (sym ~ Typed s, BindingT :<: s, Typeable a, Typeable b) => (ASTF sym a -> ASTF sym b) -> ASTF sym (a -> b)-lamTyped = lamT_template (Typed . inj . VarT) (Typed . inj . LamT)+lamTyped = lamT_template+ (Typed . inj . VarT)+ (\v a -> Sym (Typed (inj (LamT v))) :$ a) -- | Domains that \"might\" include variables and binders class BindingDomain sym@@ -584,87 +582,6 @@ -- when renaming bound variables. renameUnique :: BindingDomain sym => ASTF sym a -> ASTF sym a renameUnique = renameUnique' []----------------------------------------------------------------------------------------------------------- * Substitution--------------------------------------------------------------------------------------------------------- | Name environment-type Aliases =- ( Set Name -- Reserved names- , Map Name Name -- Aliases; co-domain must not contain reserved names- , Name -- Fresh name; must be greater than all reserved names and all names- -- in the co-domain of the alias map- )- -- Invariant: The second component of the pair is a name that is greater than- -- all names in the co-domain of the map.---- | Set up an initial alias environment from a set of reserved names-initAliases :: Set Name -> Aliases-initAliases res = (res, Map.empty, next)- where- next = Set.findMax (Set.insert (-1) res) + 1---- | Locally rename a binding-rename :: Name -> Aliases -> (Name,Aliases)-rename n al@(res,mp,next)- | Just n' <- Map.lookup n mp = (n',al)- -- This is a shadowing binding, so it's safe to reuse the name of the- -- shadowed binding (i.e. it will shadow the same binding after renaming- -- as before). This case is not strictly needed, but it allows more name- -- reuse.- | not (Set.member n res) =- (n, (Set.insert n res, Map.insert n n mp, max next (n+1)))- -- Here we reuse the name because it's not reserved. It may seem- -- pointless to map the name to itself, but this allows `parSubst` to- -- use the map to see whether a name is in scope.- | otherwise = (next, (Set.insert next res, Map.insert n next mp, next + 1))- -- Here we need a fresh name. By reserving the name we ensure that no- -- binding will be renamed to shadow the new name (unless it was already- -- a shadowing binding; see above).---- | Lookup a name in an alias environment-lookAlias :: Name -> Aliases -> Maybe Name-lookAlias n (_,mp,_) = Map.lookup n mp---- | Capture-avoiding parallel substitution------ Uses the "rapier" method described in "Secrets of the Glasgow Haskell--- Compiler inliner" (Peyton Jones and Marlow, JFP 2006) to rename variables--- where there's risk for capturing.-parSubst :: forall sym a . BindingDomain sym- => (forall a b . ASTF sym a -> ASTF sym b -> Maybe (Dict (a ~ b)))- -- ^ Type equality- -> [(Name, EF (AST sym))] -- ^ Substitution- -> ASTF sym a- -> ASTF sym a-parSubst teq subst a = go (initAliases reserved) a- where- reserved = Set.union- (freeVars a) -- TODO Not needed?- (Foldable.fold [freeVars b | (_, EF b) <- subst])-- go :: Aliases -> ASTF sym b -> ASTF sym b- go aliases var- | Just v <- prVar var- = case lookAlias v aliases of- Just v' -> renameBind (\_ -> v') var- _ -> case lookup v subst of- Just (EF b) | Just Dict <- teq var b -> b- _ -> var -- Free variable without a substitution- go aliases (lam :$ body)- | Just v <- prLam lam- , let (v',aliases') = rename v aliases- = renameBind (\_ -> v') lam :$ go aliases' body- go aliases a =- simpleMatch (\s as -> appArgs (Sym s) $ mapArgs (go aliases) as) a-- -- It is safe to use the same `subst` throughout the traversal in `go`. This- -- is because `lookup v subst` is only done when `v` is known not to be in- -- scope (variables in scope must be in the alias map). So there's no risk of- -- replacing a bound variable.
src/Language/Syntactic/Functional/Sharing.hs view
@@ -147,8 +147,9 @@ -- * Code motion -------------------------------------------------------------------------------- --- | Substituting a sub-expression. Assumes no variable capturing in the--- expressions involved.+-- | Substituting a sub-expression. Assumes that the free variables of the+-- replacing expression do not occur as binders in the whole expression (so that+-- there is no risk of capturing). substitute :: forall sym a b . (Equality sym, BindingDomain sym) => CodeMotionInterface sym@@ -156,15 +157,27 @@ -> ASTF sym a -- ^ Replacing sub-expression -> ASTF sym b -- ^ Whole expression -> ASTF sym b-substitute iface x y a- | Just y' <- castExprCM iface y a, alphaEq x a = y'- | otherwise = subst a+substitute iface x y a = subst a where- subst :: AST sym c -> AST sym c- subst (s :$ a) = subst s :$ substitute iface x y a- subst a = a+ fv = freeVars x++ subst :: ASTF sym c -> ASTF sym c+ subst a+ | Just y' <- castExprCM iface y a, alphaEq x a = y'+ | otherwise = subst' a++ subst' :: AST sym c -> AST sym c+ subst' a@(lam :$ body)+ | Just v <- prLam lam+ , Set.member v fv = a+ subst' (s :$ a) = subst' s :$ subst a+ subst' a = a+ -- Note: Since `codeMotion` only uses `substitute` to replace sub-expressions- -- with fresh variables, there's no risk of capturing.+ -- with fresh variables, the assumption above is fulfilled. However, the+ -- matching in `subst` needs to be aware of free variables, which is why the+ -- substitution stops when reaching a lambda that binds a variable that is+ -- free in the expression to be replaced. -- | Count the number of occurrences of a sub-expression count :: forall sym a b
src/Language/Syntactic/Functional/Tuple.hs view
@@ -2,38 +2,21 @@ -- | Construction and elimination of tuples -module Language.Syntactic.Functional.Tuple- ( module Language.Syntactic.Functional.Tuple- -- * Template Haskell- , eqPred- , classPred- , mkSelectClassPlusInstances- , deriveSyntacticForTuples- ) where+module Language.Syntactic.Functional.Tuple where import Language.Syntactic import Language.Syntactic.TH import Language.Syntactic.Functional-import Language.Syntactic.Functional.Tuple.TH ------------------------------------------------------------------------------------ * Generic tuple projection-----------------------------------------------------------------------------------mkSelectClassPlusInstances 15--------------------------------------------------------------------------------------- * Symbols------------------------------------------------------------------------------------- | Construction and elimination of tuples-mkTupleSym "Tuple" "Tup" "Sel" 15+data Tuple a+ where+ Pair :: Tuple (a :-> b :-> Full (a,b))+ Fst :: Tuple ((a,b) :-> Full a)+ Snd :: Tuple ((a,b) :-> Full b) deriveSymbol ''Tuple deriveEquality ''Tuple@@ -43,37 +26,9 @@ instance Eval Tuple where- evalSym Tup2 = (,)- evalSym Tup3 = (,,)- evalSym Tup4 = (,,,)- evalSym Tup5 = (,,,,)- evalSym Tup6 = (,,,,,)- evalSym Tup7 = (,,,,,,)- evalSym Tup8 = (,,,,,,,)- evalSym Tup9 = (,,,,,,,,)- evalSym Tup10 = (,,,,,,,,,)- evalSym Tup11 = (,,,,,,,,,,)- evalSym Tup12 = (,,,,,,,,,,,)- evalSym Tup13 = (,,,,,,,,,,,,)- evalSym Tup14 = (,,,,,,,,,,,,,)- evalSym Tup15 = (,,,,,,,,,,,,,,)- evalSym Sel1 = select1- evalSym Sel2 = select2- evalSym Sel3 = select3- evalSym Sel4 = select4- evalSym Sel5 = select5- evalSym Sel6 = select6- evalSym Sel7 = select7- evalSym Sel8 = select8- evalSym Sel9 = select9- evalSym Sel10 = select10- evalSym Sel11 = select11- evalSym Sel12 = select12- evalSym Sel13 = select13- evalSym Sel14 = select14- evalSym Sel15 = select15- -- It would be possible to generate this instance, but the gain would be- -- small, and it's very hard to get it wrong anyway.+ evalSym Pair = (,)+ evalSym Fst = fst+ evalSym Snd = snd instance EvalEnv Tuple env
src/Language/Syntactic/Functional/Tuple/TH.hs view
@@ -1,155 +1,23 @@ {-# LANGUAGE TemplateHaskell #-} --- | Generate types, classes and instances for tuples+-- | Generate 'Syntactic' instances for tuples -module Language.Syntactic.Functional.Tuple.TH where+module Language.Syntactic.Functional.Tuple.TH+ ( deriveSyntacticForTuples+ ) where -import Data.Generics import Language.Haskell.TH -import Language.Syntactic ((:->), Full, AST (..), (:<:), Syntactic (..))-import Language.Syntactic.TH--------------------------------------------------------------------------------------- * Generic selection classes and instances-----------------------------------------------------------------------------------class SelectX tup- where- type SelX tup- selectX :: tup -> SelX tup- -- Declare the class to be able to quote instances of it--classTemplate :: DecsQ-classTemplate =- [d| class SelectX tup- where- type SelX tup- selectX :: tup -> SelX tup- |]--instanceTemplate :: DecsQ-instanceTemplate =- [d| instance SelectX tup- where- type SelX tup = Double- selectX tup = undefined- -- Use `Double` and `undefined` as placeholders- |]--mkSelectClassPlusInstances- :: Int -- ^ Max tuple width- -> DecsQ-mkSelectClassPlusInstances n = do- [classTempl] <- classTemplate- [instanceTempl] <- instanceTemplate- let classDecs = [everywhere (mkT (fixName s)) classTempl | s <- [1..n]]- instDecs =- [ everywhere- ( mkT (fixTupType s w)- . mkT (fixTupPat s w)- . mkT (fixTupExp s w)- . mkT (fixName s)- )- instanceTempl- | w <- [2..n]- , s <- [1..w]- ]- return (classDecs ++ instDecs)---- | @"SelectX_0"@ -> @"Select33"@ (for @n=33@)-fixName :: Int -> Name -> Name-fixName s- = mkName- . concatMap (\c -> if c=='X' then show s else [c])- . takeWhile (/='_')- . nameBase--fixTupType :: Int -> Int -> Type -> Type-fixTupType s w ty- | VarT tup <- ty- , "tup" <- show tup = foldl1 AppT ((TupleT w) : tupVars)- | ConT doub <- ty- , show doub == "Double" = tupVars !! (s-1)- | otherwise = ty- where- tupVars = map VarT $ take w varSupply--fixTupPat :: Int -> Int -> Pat -> Pat-fixTupPat s w pat- | VarP tup <- pat- , "tup" <- show tup = TupP tupVars- | otherwise = pat- where- tupVars = map VarP $ take w varSupply--fixTupExp :: Int -> Int -> Exp -> Exp-fixTupExp s w ex- | VarE tup <- ex- , "tup" <- show tup = TupE tupVars- | VarE undef <- ex- , show undef == "undefined" = tupVars !! (s-1)- | otherwise = ex- where- tupVars = map VarE $ take w varSupply--------------------------------------------------------------------------------------- * Symbol type for tuple construction and elimination of tuples---------------------------------------------------------------------------------+import Data.NestTuple+import Data.NestTuple.TH -mkTupleSym- :: String -- ^ Type name- -> String -- ^ Base name for constructors- -> String -- ^ Base name for selectors- -> Int -- ^ Max tuple width- -> DecsQ-mkTupleSym tyName tupName selName n = do- let tupCons =- [ ForallC- (map PlainTV (take w varSupply))- [eqPred (VarT (mkName "sig")) (signature w)]- (NormalC (mkName (tupName ++ show w)) [])- | w <- [2..n]- ]- let selCons =- [ ForallC- [PlainTV (mkName "tup")]- [ eqPred- (VarT (mkName "sig"))- ( foldl1 AppT- [ ConT ''(:->)- , VarT (mkName "tup")- , AppT (ConT ''Full) (AppT (ConT (mkName ("Sel" ++ show s))) (VarT (mkName "tup")))- ]- )- , classPred (mkName ("Select" ++ show s)) ConT [VarT (mkName "tup")]- ]- (NormalC (mkName (selName ++ show s)) [])- | s <- [1..n]- ]- return [DataD [] (mkName tyName) [PlainTV (mkName "sig")] (tupCons ++ selCons) []]- where- signature :: Int -> Type- signature w = foldr- (\a res -> foldl1 AppT [ConT ''(:->), a, res])- (AppT (ConT ''Full)- (foldl AppT (TupleT w) vars))- vars- where- vars = map VarT $ take w varSupply+import Language.Syntactic ((:<:), Syntactic (..))+import Language.Syntactic.TH ------------------------------------------------------------------------------------ * 'Syntactic' instances for tuples---------------------------------------------------------------------------------- -- Make instances of the form -- -- > instance@@ -167,21 +35,25 @@ -- > , Domain a ~ Domain b -- > , ... -- > , Domain a ~ Domain x+-- > , extraConstraint -- > ) => -- > Syntactic (a,...,x) -- > where -- > type Domain (a,...,x) = Domain a--- > type Internal (a,...,x) = (Internal a, ..., Internal x)--- > desugar (a,...,x) = Sym (symInj TupN) :$ desugar a :$ ... :$ desugar x--- > sugar tup = (sugar (Sym (symInj Sel1) :$ tup), ..., sugar (Sym (symInj SelN) :$ tup))+-- > type Internal (a,...,x) = (Internal a ... Internal x) -- nested pairs+-- > desugar = desugar . nestTup -- use pair instance+-- > sugar = unnestTup . sugar -- use pair instance+--+-- Instances will be generated for width 3 and upwards. The existence of an+-- instance for pairs is assumed. deriveSyntacticForTuples :: (Type -> Cxt) -- ^ @internalPred@ (see above) -> (Type -> Type) -- ^ @mkDomain@ (see above)- -> (Exp -> Exp) -- ^ Symbol injection+ -> Cxt -- ^ @extraConstraint@ (see above) -> Int -- ^ Max tuple width -> DecsQ-deriveSyntacticForTuples internalPred mkDomain symInj n = return $- map deriveSyntacticForTuple [2..n]+deriveSyntacticForTuples internalPred mkDomain extraConstraint n = return $+ map deriveSyntacticForTuple [3..n] where deriveSyntacticForTuple w = InstanceD ( concat@@ -192,6 +64,7 @@ , [eqPred domainA (AppT (ConT ''Domain) b) | b <- tail varsT ]+ , extraConstraint ] ) (AppT (ConT ''Syntactic) tupT)@@ -199,41 +72,20 @@ , tySynInst ''Internal [tupT] tupTI , FunD 'desugar [ Clause- [TupP varsP]- (NormalB- ( foldl- (\s a -> foldl1 AppE [ConE '(:$), s, AppE (VarE 'desugar) a])- (AppE (ConE 'Sym) (symInj (ConE (mkName ("Tup" ++ show w)))))- varsE- )- ) []+ (NormalB (foldl AppE (VarE '(.)) $ map VarE [mkName "desugar", 'nest]))+ [] ] , FunD 'sugar [ Clause- [VarP (mkName "tup")]- (NormalB- ( TupE- [ AppE- (VarE 'sugar)- ( foldl1 AppE- [ ConE '(:$)- , AppE (ConE 'Sym) (symInj (ConE (mkName ("Sel" ++ show s))))- , VarE (mkName "tup")- ]- )- | s <- [1..w]- ]- )- ) []+ (NormalB (foldl AppE (VarE '(.)) $ map VarE ['unnest, mkName "sugar"]))+ [] ] ] where varsT = map VarT $ take w varSupply tupT = foldl AppT (TupleT w) varsT- tupTI = foldl AppT (TupleT w) $ map (AppT (ConT ''Internal)) varsT+ tupTI = foldNest id mkPairT $ toNest $ map (AppT (ConT ''Internal)) varsT domainA = AppT (ConT ''Domain) (VarT (mkName "a"))- varsP = map VarP $ take w varSupply- varsE = map VarE $ take w varSupply
src/Language/Syntactic/Sugar/Tuple.hs view
@@ -7,13 +7,27 @@ -import Language.Haskell.TH- import Language.Syntactic import Language.Syntactic.Functional.Tuple import Language.Syntactic.Functional.Tuple.TH -deriveSyntacticForTuples (const []) id (AppE (VarE 'inj)) 15+instance+ ( Syntactic a+ , Syntactic b+ , Tuple :<: Domain a+ , Domain a ~ Domain b+ ) =>+ Syntactic (a,b)+ where+ type Domain (a,b) = Domain a+ type Internal (a,b) = (Internal a, Internal b)+ desugar (a,b) = inj Pair :$ desugar a :$ desugar b+ sugar ab = (sugar $ inj Fst :$ ab, sugar $ inj Snd :$ ab)++-- `desugar` and `sugar` can be seen as applying the eta-rule for pairs.+-- <https://mail.haskell.org/pipermail/haskell-cafe/2016-April/123639.html>++deriveSyntacticForTuples (const []) id [] 15
src/Language/Syntactic/Sugar/TupleTyped.hs view
@@ -16,14 +16,35 @@ #endif import Language.Syntactic+import Language.Syntactic.TH import Language.Syntactic.Functional.Tuple+import Language.Syntactic.Functional.Tuple.TH +instance+ ( Syntactic a+ , Syntactic b+ , Typeable (Internal a)+ , Typeable (Internal b)+ , Tuple :<: sym+ , Domain a ~ Typed sym+ , Domain a ~ Domain b+ ) =>+ Syntactic (a,b)+ where+ type Domain (a,b) = Domain a+ type Internal (a,b) = (Internal a, Internal b)+ desugar (a,b) = Sym (Typed $ inj Pair) :$ desugar a :$ desugar b+ sugar ab = (sugar $ Sym (Typed $ inj Fst) :$ ab, sugar $ Sym (Typed $ inj Snd) :$ ab)++-- `desugar` and `sugar` can be seen as applying the eta-rule for pairs.+-- <https://mail.haskell.org/pipermail/haskell-cafe/2016-April/123639.html>+ deriveSyntacticForTuples (return . classPred ''Typeable ConT . return) (AppT (ConT ''Typed))- (\s -> AppE (ConE 'Typed) (AppE (VarE 'inj) s))+ [] #if __GLASGOW_HASKELL__ < 708 7 #else
src/Language/Syntactic/Syntax.hs view
@@ -175,9 +175,9 @@ type instance SmartSym (AST sym sig) = sym type instance SmartSym (a -> f) = SmartSym f --- | Make a smart constructor of a symbol. 'smartSym' has any type of the form:+-- | Make a smart constructor of a symbol. 'smartSym'' has any type of the form: ----- > smartSym+-- > smartSym' -- > :: sym (a :-> b :-> ... :-> Full x) -- > -> (ASTF sym a -> ASTF sym b -> ... -> ASTF sym x) smartSym' :: forall sig f sym
src/Language/Syntactic/TH.hs view
@@ -178,9 +178,12 @@ -- * Portability -------------------------------------------------------------------------------- +-- Using `__GLASGOW_HASKELL__` instead of `MIN_VERSION_template_haskell`,+-- because the latter doesn't work when the package is compiled with `-f-th`.+ -- | Portable method for constructing a 'Pred' of the form @(t1 ~ t2)@ eqPred :: Type -> Type -> Pred-#if MIN_VERSION_template_haskell(2,10,0)+#if __GLASGOW_HASKELL__ >= 710 eqPred t1 t2 = foldl1 AppT [EqualityT,t1,t2] #else eqPred = EqualP@@ -189,10 +192,10 @@ -- | Portable method for constructing a 'Pred' of the form @SomeClass t1 t2 ...@ classPred :: Name -- ^ Class name- -> (Name -> Type) -- ^ How to make a type for the class (typically 'ConT' or VarT)+ -> (Name -> Type) -- ^ How to make a type for the class (typically 'ConT' or 'VarT') -> [Type] -- ^ Class arguments -> Pred-#if MIN_VERSION_template_haskell(2,10,0)+#if __GLASGOW_HASKELL__ >= 710 classPred cl con = foldl AppT (con cl) #else classPred cl con = ClassP cl@@ -200,7 +203,7 @@ -- | Portable method for constructing a type synonym instances tySynInst :: Name -> [Type] -> Type -> Dec-#if MIN_VERSION_template_haskell(2,9,0)+#if __GLASGOW_HASKELL__ >= 708 tySynInst t as rhs = TySynInstD t (TySynEqn as rhs) #else tySynInst = TySynInstD
syntactic.cabal view
@@ -1,5 +1,5 @@ Name: syntactic-Version: 3.5+Version: 3.6 Synopsis: Generic representation and manipulation of abstract syntax Description: The library provides a generic representation of type-indexed abstract syntax trees (or indexed data types in general). It also permits the definition of open syntax@@ -68,13 +68,13 @@ Language.Syntactic.Sugar.MonadTyped if flag(th) exposed-modules:+ Data.NestTuple+ Data.NestTuple.TH Language.Syntactic.TH Language.Syntactic.Functional.Tuple+ Language.Syntactic.Functional.Tuple.TH Language.Syntactic.Sugar.Tuple Language.Syntactic.Sugar.TupleTyped-- other-modules:- Language.Syntactic.Functional.Tuple.TH build-depends: base >= 4 && < 5,
tests/AlgorithmTests.hs view
@@ -228,10 +228,12 @@ prop_codeMotion_vars (a :: Exp Int) = freeVars a == freeVars (cm a) prop_codeMotion_eval (a :: Exp Int) = evalAny a == evalAny (cm a) -counter = app2 (lamm 1 (lamm 2 (varr 1))) (app1 (lamm 1 (int 0)) (app2 (lamm 0 (lamm 0 (varr 1))) (int 0) (int 0))) (varr 2)+prop_bug1 = prop_codeMotion_eval exp+ where+ exp = add+ (app2 (lamm 0 (lamm 0 (varr 1))) (int 0) (int 0))+ (app2 (lamm 1 (lamm 2 (varr 1))) (int 0) (int 0)) tests = $testGroupGenerator--main = $defaultMainGenerator
tests/gold/fib.txt view
@@ -1,17 +1,17 @@ Lam v3- └╴Sel1+ └╴Fst └╴ForLoop ├╴v3- ├╴Tup2+ ├╴Pair │ ├╴0 │ └╴1 └╴Lam v2 └╴Lam v1- └╴Tup2- ├╴Sel2+ └╴Pair+ ├╴Snd │ └╴v1 └╴(+)- ├╴Sel1+ ├╴Fst │ └╴v1- └╴Sel2+ └╴Snd └╴v1
tests/gold/spanVec.txt view
@@ -3,7 +3,7 @@ ├╴ForLoop │ ├╴arrLen │ │ └╴v3- │ ├╴Tup2+ │ ├╴Pair │ │ ├╴arrIx │ │ │ ├╴v3 │ │ │ └╴0@@ -12,21 +12,21 @@ │ │ └╴0 │ └╴Lam v2 │ └╴Lam v1- │ └╴Tup2+ │ └╴Pair │ ├╴min │ │ ├╴arrIx │ │ │ ├╴v3 │ │ │ └╴v2- │ │ └╴Sel1+ │ │ └╴Fst │ │ └╴v1 │ └╴max │ ├╴arrIx │ │ ├╴v3 │ │ └╴v2- │ └╴Sel2+ │ └╴Snd │ └╴v1 └╴(-)- ├╴Sel2+ ├╴Snd │ └╴v4- └╴Sel1+ └╴Fst └╴v4