ADPfusion 0.2.1.0 → 0.4.0.0
raw patch · 73 files changed
+5601/−2885 lines, 73 filesdep +ADPfusiondep +OrderedBitsdep +bitsdep −deepseqdep −ghc-primdep −repadep ~PrimitiveArraydep ~QuickCheckdep ~basenew-component:exe:Durbinnew-component:exe:Nussinovnew-component:exe:PartNussinov
Dependencies added: ADPfusion, OrderedBits, bits, log-domain, mmorph, monad-primitive, mtl, test-framework, test-framework-quickcheck2, test-framework-th, tuple
Dependencies removed: deepseq, ghc-prim, repa
Dependency ranges changed: PrimitiveArray, QuickCheck, base, primitive, strict, template-haskell, transformers, vector
Files
- ADP/Fusion.hs +26/−68
- ADP/Fusion/Apply.hs +2/−4
- ADP/Fusion/Base.hs +15/−0
- ADP/Fusion/Base/Classes.hs +142/−0
- ADP/Fusion/Base/Multi.hs +189/−0
- ADP/Fusion/Base/Point.hs +112/−0
- ADP/Fusion/Base/Set.hs +103/−0
- ADP/Fusion/Base/Subword.hs +75/−0
- ADP/Fusion/Chr.hs +0/−306
- ADP/Fusion/Classes.hs +0/−396
- ADP/Fusion/Empty.hs +0/−56
- ADP/Fusion/Examples/Palindrome.hs +0/−118
- ADP/Fusion/Examples/TwoDim.hs +0/−98
- ADP/Fusion/Multi.hs +0/−70
- ADP/Fusion/Multi/Classes.hs +0/−112
- ADP/Fusion/Multi/Empty.hs +0/−47
- ADP/Fusion/Multi/GChr.hs +0/−101
- ADP/Fusion/Multi/None.hs +0/−52
- ADP/Fusion/None.hs +0/−58
- ADP/Fusion/QuickCheck.hs +0/−531
- ADP/Fusion/QuickCheck/Common.hs +10/−0
- ADP/Fusion/QuickCheck/Point.hs +293/−0
- ADP/Fusion/QuickCheck/Set.hs +248/−0
- ADP/Fusion/QuickCheck/Subword.hs +171/−0
- ADP/Fusion/Region.hs +0/−148
- ADP/Fusion/SynVar.hs +17/−0
- ADP/Fusion/SynVar/Array.hs +292/−0
- ADP/Fusion/SynVar/Array/Point.hs +79/−0
- ADP/Fusion/SynVar/Array/Set.hs +164/−0
- ADP/Fusion/SynVar/Array/Subword.hs +174/−0
- ADP/Fusion/SynVar/Array/Type.hs +144/−0
- ADP/Fusion/SynVar/Axiom.hs +14/−0
- ADP/Fusion/SynVar/Backtrack.hs +28/−0
- ADP/Fusion/SynVar/Fill.hs +180/−0
- ADP/Fusion/SynVar/Indices.hs +109/−0
- ADP/Fusion/SynVar/Recursive.hs +74/−0
- ADP/Fusion/SynVar/Recursive/Point.hs +3/−0
- ADP/Fusion/SynVar/Recursive/Subword.hs +13/−0
- ADP/Fusion/SynVar/Recursive/Type.hs +80/−0
- ADP/Fusion/TH.hs +56/−26
- ADP/Fusion/TH/Backtrack.hs +262/−0
- ADP/Fusion/TH/Common.hs +19/−0
- ADP/Fusion/Table.hs +0/−563
- ADP/Fusion/Term.hs +17/−0
- ADP/Fusion/Term/Chr.hs +197/−0
- ADP/Fusion/Term/Chr/Point.hs +91/−0
- ADP/Fusion/Term/Chr/Subword.hs +61/−0
- ADP/Fusion/Term/Chr/Type.hs +57/−0
- ADP/Fusion/Term/Deletion.hs +76/−0
- ADP/Fusion/Term/Deletion/Point.hs +62/−0
- ADP/Fusion/Term/Deletion/Type.hs +27/−0
- ADP/Fusion/Term/Edge.hs +64/−0
- ADP/Fusion/Term/Edge/Set.hs +73/−0
- ADP/Fusion/Term/Edge/Type.hs +32/−0
- ADP/Fusion/Term/Epsilon.hs +116/−0
- ADP/Fusion/Term/Epsilon/Point.hs +62/−0
- ADP/Fusion/Term/Epsilon/Subword.hs +37/−0
- ADP/Fusion/Term/Epsilon/Type.hs +27/−0
- ADP/Fusion/Term/PeekIndex/Subword.hs +24/−0
- ADP/Fusion/Term/PeekIndex/Type.hs +31/−0
- ADP/Fusion/Term/Strng.hs +11/−0
- ADP/Fusion/Term/Strng/Point.hs +43/−0
- ADP/Fusion/Term/Strng/Type.hs +56/−0
- ADPfusion.cabal +343/−87
- LICENSE +1/−1
- README.md +26/−39
- changelog +0/−4
- changelog.md +31/−0
- src/Durbin.hs +122/−0
- src/NeedlemanWunsch.hs +323/−0
- src/Nussinov.hs +132/−0
- src/PartNussinov.hs +275/−0
- tests/properties.hs +90/−0
ADP/Fusion.hs view
@@ -1,16 +1,3 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE EmptyDataDecls #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-} -- | Generalized fusion system for grammars. --@@ -18,54 +5,32 @@ -- bind a terminal symbol to an input of length 0 and then run your grammar, -- you probably get errors, garbled data or random crashes. Such checks are -- done via asserts in non-production code.------ TODO each combinator should come with a special outer check. Given some--- index (say (i,j), this can then check if i-const >= 0, or j+const<=n, or--- i+const<=j. That should speed up everything that uses GChr combinators.--- Separating out this check means that certain inner loops can run without any--- conditions and just jump. module ADP.Fusion- -- basic combinators- ( (<<<)- , (<<#)- , (|||)- , (...)- , (~~)- , (%)- -- filters- , check- -- parsers- , chr- , chrLeft- , chrRight- , peekL- , peekR- , empty- , region- , sregion--- , Tbl (..)--- , BtTbl (..)- , MTbl (..)- , ENE (..)- , ENZ (..)- , None (..)+ ( module ADP.Fusion+ , module ADP.Fusion.Apply+ , module ADP.Fusion.Base+ , module ADP.Fusion.Term+ , module ADP.Fusion.SynVar+ , module ADP.Fusion.TH ) where -import Data.Strict.Tuple-import GHC.Exts (inline)+import Data.Strict.Tuple+import GHC.Exts (inline) import qualified Data.Vector.Fusion.Stream.Monadic as S -import ADP.Fusion.Apply-import ADP.Fusion.Chr-import ADP.Fusion.Classes-import ADP.Fusion.Empty-import ADP.Fusion.Region-import ADP.Fusion.Table-import ADP.Fusion.None+import ADP.Fusion.Apply+import ADP.Fusion.Base+import ADP.Fusion.SynVar+import ADP.Fusion.Term+import ADP.Fusion.TH +import qualified Data.Vector.Unboxed as VU +import Data.PrimitiveArray ++ -- | Apply a function to symbols on the RHS of a production rule. Builds the -- stack of symbols from 'xs' using 'build', then hands this stack to -- 'mkStream' together with the initial 'iniT' telling 'mkStream' that we are@@ -74,17 +39,17 @@ -- function 'f'. infixl 8 <<<-(<<<) f xs = \ij -> outerCheck (checkValidIndex (build xs) ij) . S.map (apply (inline f) . getArg) . mkStream (build xs) (outer ij) $ ij+(<<<) f xs = \lu ij -> S.map (apply (inline f) . getArg) . mkStream (build xs) (initialContext ij) lu $ ij {-# INLINE (<<<) #-} infixl 8 <<#-(<<#) f xs = \ij -> outerCheck (checkValidIndex (build xs) ij) . S.mapM (apply (inline f) . getArg) . mkStream (build xs) (outer ij) $ ij+(<<#) f xs = \lu ij -> S.mapM (apply (inline f) . getArg) . mkStream (build xs) (initialContext ij) lu $ ij {-# INLINE (<<#) #-} -- | Combine two RHSs to give a choice between parses. infixl 7 |||-(|||) xs ys = \ij -> xs ij S.++ ys ij+(|||) xs ys = \lu ij -> xs lu ij S.++ ys lu ij {-# INLINE (|||) #-} -- | Applies the objective function 'h' to a stream 's'. The objective function@@ -92,14 +57,14 @@ -- things). infixl 5 ...-(...) s h = h . s+(...) s h = \lu ij -> (inline h) $ s lu ij {-# INLINE (...) #-} --- | Additional outer check with user-given check function--infixl 6 `check`-check xs f = \ij -> let chk = f ij in chk `seq` outerCheck chk (xs ij)-{-# INLINE check #-}+-- -- | Additional outer check with user-given check function+-- +-- infixl 6 `check`+-- check xs f = \ij -> let chk = f ij in chk `seq` outerCheck chk (xs ij)+-- {-# INLINE check #-} -- | Separator between RHS symbols. @@ -112,11 +77,4 @@ infixl 9 % (%) = (:!:) {-# INLINE (%) #-}-------
ADP/Fusion/Apply.hs view
@@ -1,10 +1,8 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-} module ADP.Fusion.Apply where -import Data.Array.Repa.Index+--import Data.Array.Repa.Index+import Data.PrimitiveArray (Z(..), (:.)(..))
+ ADP/Fusion/Base.hs view
@@ -0,0 +1,15 @@++module ADP.Fusion.Base+ ( module ADP.Fusion.Base.Classes+ , module ADP.Fusion.Base.Multi+ , module ADP.Fusion.Base.Point+ , module ADP.Fusion.Base.Set+ , module ADP.Fusion.Base.Subword+ ) where++import ADP.Fusion.Base.Classes+import ADP.Fusion.Base.Multi+import ADP.Fusion.Base.Point+import ADP.Fusion.Base.Set+import ADP.Fusion.Base.Subword+
+ ADP/Fusion/Base/Classes.hs view
@@ -0,0 +1,142 @@++module ADP.Fusion.Base.Classes where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Size+import qualified Data.Vector.Fusion.Stream.Monadic as S++import Data.PrimitiveArray++++data OutsideContext s+ = OStatic s+ | ORightOf s+ | OFirstLeft s+ | OLeftOf s++data InsideContext s+ = IStatic s+ | IVariable s++data ComplementContext+ = Complemented++class RuleContext i where+ type Context i :: *+ initialContext :: i -> Context i++-- | During construction of the stream, we need to extract individual elements+-- from symbols in production rules. An element in a stream is fixed by both,+-- the type @x@ of the actual argument we want to grab (say individual+-- characters we parse from an input) and the type of indices @i@ we use.+--+-- @Elm@ data constructors are all eradicated during fusion and should never+-- show up in CORE.++class Element x i where+ data Elm x i :: *+ type Arg x :: *+ getArg :: Elm x i -> Arg x+ getIdx :: Elm x i -> i+ getOmx :: Elm x i -> i++-- | @mkStream@ creates the actual stream of elements (@Elm@) that will be fed+-- to functions on the left of the @(<<<)@ operator. Streams work over all+-- monads and are specialized for each combination of arguments @x@ and indices+-- @i@.++class (Monad m) => MkStream m x i where+ mkStream :: x -> Context i -> i -> i -> S.Stream m (Elm x i)++-- | Finally, we need to be able to correctly build together symbols on the+-- right-hand side of the @(<<<)@ operator.+--+-- The default makes sure that the last (or only) argument left over is+-- correctly assigned a @Z@ to terminate the symbol stack.++class Build x where+ type Stack x :: *+ type Stack x = S :!: x+ build :: x -> Stack x+ default build :: (Stack x ~ (S :!: x)) => x -> Stack x+ build x = S :!: x+ {-# Inline build #-}++instance Build x => Build (x:!:y) where+ type Stack (x:!:y) = Stack x :!: y+ build (x:!:y) = build x :!: y+ {-# Inline build #-}++-- | Similar to 'Z', but terminates an argument stack.++data S = S+ deriving (Eq,Show)++instance+ (+ ) => Element S i where+ data Elm S i = ElmS !i !i+ type Arg S = Z+ getArg (ElmS _ _) = Z+ getIdx (ElmS i _) = i+ getOmx (ElmS _ o) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance Show ix => Show (Elm S ix)++-- | 'staticCheck' acts as a static filter. If 'b' is true, we keep all stream+-- elements. If 'b' is false, we discard all stream elements.++staticCheck :: Monad m => Bool -> S.Stream m a -> S.Stream m a+staticCheck b (S.Stream step t n) = b `seq` S.Stream snew (CheckLeft (b:.t)) (toMax n) where+ {-# Inline [0] snew #-}+ snew (CheckLeft (False:._)) = return $ S.Done+ snew (CheckLeft (True :.s)) = return $ S.Skip (CheckRight s)+ snew (CheckRight s ) = do r <- step s+ case r of+ S.Yield x s' -> return $ S.Yield x (CheckRight s')+ S.Skip s' -> return $ S.Skip (CheckRight s')+ S.Done -> return $ S.Done+{-# INLINE staticCheck #-}++data StaticCheck a b = CheckLeft a | CheckRight b+++-- | Constrains the behaviour of the memoizing tables. They may be 'EmptyOk' if+-- @i==j@ is allowed (empty subwords or similar); or they may need 'NonEmpty'+-- indices, or finally they can be 'OnlyZero' (only @i==j@ allowed) which is+-- useful in multi-dimensional casese.++data TableConstraint+ = EmptyOk+ | NonEmpty+ | OnlyZero+ deriving (Eq,Show)++minSize :: TableConstraint -> Int+minSize NonEmpty = 1+minSize _ = 0+{-# INLINE minSize #-}++class ModifyConstraint t where+ toNonEmpty :: t -> t+ toEmpty :: t -> t++-- |++type family TblConstraint x :: *++type instance TblConstraint (is:.i) = TblConstraint is :. TblConstraint i+type instance TblConstraint Z = Z+type instance TblConstraint (Outside o) = TblConstraint o+type instance TblConstraint (Complement o) = TblConstraint o++-- TODO move into the sub-modules++type instance TblConstraint PointL = TableConstraint+type instance TblConstraint PointR = TableConstraint+type instance TblConstraint Subword = TableConstraint+
+ ADP/Fusion/Base/Multi.hs view
@@ -0,0 +1,189 @@++module ADP.Fusion.Base.Multi where++import qualified Data.Vector.Fusion.Stream.Monadic as S+import Data.Strict.Tuple++import Data.PrimitiveArray++import ADP.Fusion.Base.Classes++++-- * Multi-dimensional extension++-- | Terminates a multi-dimensional terminal symbol stack.++data M = M+ deriving (Eq,Show)++infixl 2 :|++-- | Terminal symbols are stacked together with @a@ tails and @b@ head.++data TermSymbol a b = a :| b+ deriving (Eq,Show)++instance Build (TermSymbol a b)++-- | Extracts the type of a multi-dimensional terminal argument.++type family TermArg x :: *+type instance TermArg M = Z++instance (Element ls i) => Element (ls :!: TermSymbol a b) i where+ data Elm (ls :!: TermSymbol a b) i = ElmTS !(TermArg (TermSymbol a b)) !i !i !(Elm ls i)+ type Arg (ls :!: TermSymbol a b) = Arg ls :. TermArg (TermSymbol a b)+ getArg (ElmTS a _ _ ls) = getArg ls :. a+ getIdx (ElmTS _ i _ _ ) = i+ getOmx (ElmTS _ _ o _ ) = o+ {-# INLINE getArg #-}+ {-# INLINE getIdx #-}++deriving instance (Show i, Show (TermArg (TermSymbol a b)), Show (Elm ls i)) => Show (Elm (ls :!: TermSymbol a b) i)++instance+ ( Monad m+ , MkStream m ls i+ , Element ls i+ , TerminalStream m (TermSymbol a b) i+ , TermStaticVar (TermSymbol a b) i+ ) => MkStream m (ls :!: TermSymbol a b) i where+ mkStream (ls :!: ts) sv lu i+ = S.map fromTerminalStream+ . terminalStream ts sv i+ . S.map toTerminalStream+ $ mkStream ls (termStaticVar ts sv i) lu (termStreamIndex ts sv i)+ {-# Inline mkStream #-}++-- | Handles each individual argument within a stack of terminal symbols.++class TerminalStream m t i where+ terminalStream :: t -> Context i -> i -> S.Stream m (S5 s j j i i) -> S.Stream m (S6 s j j i i (TermArg t))++iPackTerminalStream a sv (ii:._) = terminalStream a sv ii . S.map (\(S5 s zi zo (is:.i) (os:.o) ) -> S5 s (zi:.i) (zo:.o) is os )+{-# Inline iPackTerminalStream #-}++oPackTerminalStream a sv (O (is:.i)) = terminalStream a sv (O is) . S.map (\(S5 s zi zo (O (is:.i)) (O (os:.o))) -> S5 s (zi:.i) (zo:.o) (O is) (O os))+{-# Inline oPackTerminalStream #-}++instance (Monad m) => TerminalStream m M Z where+ terminalStream M _ Z = S.map (\(S5 s j1 j2 Z Z) -> S6 s j1 j2 Z Z Z)+ {-# INLINE terminalStream #-}++instance (Monad m) => TerminalStream m M (Outside Z) where+ terminalStream M _ (O Z) = S.map (\(S5 s j1 j2 (O Z) (O Z)) -> S6 s j1 j2 (O Z) (O Z) Z)+ {-# INLINE terminalStream #-}++instance Monad m => MkStream m S Z where+ mkStream _ _ _ _ = S.singleton (ElmS Z Z)+ {-# INLINE mkStream #-}++instance Monad m => MkStream m S (Outside Z) where+ mkStream _ _ _ _ = S.singleton (ElmS (O Z) (O Z))+ {-# INLINE mkStream #-}++-- | For multi-dimensional terminals we need to be able to calculate how the+-- static/variable signal changes and if the index for the inner part needs to+-- be modified.++class TermStaticVar t i where+ termStaticVar :: t -> Context i -> i -> Context i+ termStreamIndex :: t -> Context i -> i -> i++instance TermStaticVar M Z where+ termStaticVar _ _ _ = Z+ termStreamIndex _ _ _ = Z+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++instance TermStaticVar M (Outside Z) where+ termStaticVar _ _ _ = Z+ termStreamIndex _ _ _ = O Z+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++instance+ ( TermStaticVar a is+ , TermStaticVar b i+ ) => TermStaticVar (TermSymbol a b) (is:.i) where+ termStaticVar (a:|b) (vs:.v) (is:.i) = termStaticVar a vs is :. termStaticVar b v i+ termStreamIndex (a:|b) (vs:.v) (is:.i) = termStreamIndex a vs is :. termStreamIndex b v i+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++instance+ ( TermStaticVar a (Outside is)+ , TermStaticVar b (Outside i)+ ) => TermStaticVar (TermSymbol a b) (Outside (is:.i)) where+ termStaticVar (a:|b) (vs:.v) (O (is:.i)) = termStaticVar a vs (O is) :. termStaticVar b v (O i)+ termStreamIndex (a:|b) (vs:.v) (O (is:.i)) =+ let (O js) = termStreamIndex a vs (O is)+ (O j) = termStreamIndex b v (O i)+ in O (js:.j)+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++data S4 a b c d = S4 !a !b !c !d++data S5 a b c d e = S5 !a !b !c !d !e++data S6 a b c d e f = S6 !a !b !c !d !e !f++fromTerminalStream (S6 s Z Z i o e) = ElmTS e i o s+{-# INLINE fromTerminalStream #-}++toTerminalStream s = S5 s Z Z (getIdx s) (getOmx s)+{-# INLINE toTerminalStream #-}++instance RuleContext Z where+ type Context Z = Z+ initialContext _ = Z+ {-# INLINE initialContext #-}++instance RuleContext (Outside Z) where+ type Context (Outside Z) = Z+ initialContext _ = Z+ {-# INLINE initialContext #-}++instance (RuleContext is, RuleContext i) => RuleContext (is:.i) where+ type Context (is:.i) = Context is:.Context i+ initialContext (is:.i) = initialContext is:.initialContext i+ {-# INLINE initialContext #-}++instance (RuleContext (Outside is), RuleContext (Outside i)) => RuleContext (Outside (is:.i)) where+ type Context (Outside (is:.i)) = Context (Outside is):.Context (Outside i)+ initialContext (O (is:.i)) = initialContext (O is):.initialContext (O i)+ {-# INLINE initialContext #-}++class TableStaticVar i where+ tableStaticVar :: Context i -> i -> Context i+ tableStreamIndex :: TblConstraint i -> Context i -> i -> i++instance TableStaticVar Z where+ tableStaticVar _ _ = Z+ tableStreamIndex _ _ _ = Z+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}++instance TableStaticVar (Outside Z) where+ tableStaticVar _ _ = Z+ tableStreamIndex _ _ _ = O Z+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}++instance (TableStaticVar is, TableStaticVar i) => TableStaticVar (is:.i) where+ tableStaticVar (vs:.v) (is:.i) = tableStaticVar vs is :. tableStaticVar v i+ tableStreamIndex (cs:.c) (vs:.v) (is:.i) = tableStreamIndex cs vs is :. tableStreamIndex c v i+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}++instance (TableStaticVar (Outside is), TableStaticVar (Outside i)) => TableStaticVar (Outside (is:.i)) where+ tableStaticVar (vs:.v) (O (is:.i)) = tableStaticVar vs (O is) :. tableStaticVar v (O i)+ tableStreamIndex (cs:.c) (vs:.v) (O (is:.i)) =+ let (O js) = tableStreamIndex cs vs (O is)+ (O j) = tableStreamIndex c v (O i)+ in O (js:.j)+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}+
+ ADP/Fusion/Base/Point.hs view
@@ -0,0 +1,112 @@++module ADP.Fusion.Base.Point where++import Data.Vector.Fusion.Stream.Monadic (singleton,map,filter,Step(..),flatten)+import Data.Vector.Fusion.Stream.Size+import Debug.Trace+import Prelude hiding (map,filter)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base.Classes+import ADP.Fusion.Base.Multi++++instance RuleContext PointL where+ type Context PointL = InsideContext Int+ initialContext _ = IStatic 0+ {-# Inline initialContext #-}++instance RuleContext (Outside PointL) where+ type Context (Outside PointL) = OutsideContext Int+ initialContext _ = OStatic 0+ {-# Inline initialContext #-}++instance RuleContext (Complement PointL) where+ type Context (Complement PointL) = ComplementContext+ initialContext _ = Complemented+ {-# Inline initialContext #-}++++instance (Monad m) => MkStream m S PointL where+ mkStream S (IStatic d) (PointL u) (PointL j)+ = staticCheck (j>=0 && j<=d) . singleton $ ElmS (PointL 0) (PointL 0)+ mkStream S (IVariable _) (PointL u) (PointL j)+ = staticCheck (0<=j) . singleton $ ElmS (PointL 0) (PointL 0)+ {-# Inline mkStream #-}++instance (Monad m) => MkStream m S (Outside PointL) where+ mkStream S (OStatic d) (O (PointL u)) (O (PointL i))+ = staticCheck (i>=0 && i+d<=u && u == i) . singleton $ ElmS (O $ PointL i) (O . PointL $ i+d)+ mkStream S (OFirstLeft d) (O (PointL u)) (O (PointL i))+ = staticCheck (i>=0 && i+d<=u) . singleton $ ElmS (O $ PointL i) (O . PointL $ i+d)+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , MkStream m S is+ , Context (is:.PointL) ~ (Context is:.(InsideContext Int))+ ) => MkStream m S (is:.PointL) where+ mkStream S (vs:.IStatic d) (lus:.PointL u) (is:.PointL i)+ = staticCheck (i>=0 && i<=d && i<=u)+ . map (\(ElmS zi zo) -> ElmS (zi:.PointL 0) (zo:.PointL 0))+ $ mkStream S vs lus is+ {-+ mkStream S (vs:.IVariable ) (lus:.PointL u) (is:.PointL i)+ = flatten mk step Unknown $ mkStream S vs lus is+ where mk e = i `seq` return (e,i)+ step (ElmS zi zo,k )+ | k>=0 && k<=u = return $ Yield (ElmS (zi:.PointL k) (zo:.PointL 0)) (ElmS zi zo, -1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ -}+ -- TODO here, we have a problem in the interplay of @staticCheck@ or+ -- @flatten@ and how we modify @is@. Apparently, once we demand to know+ -- about @i@, fusion breaks down.+ mkStream S (vs:.IVariable d) (lus:.PointL u) (is:.PointL i)+ = staticCheck (i>=0 && i<=u)+ $ map (\(ElmS zi zo) -> ElmS (zi:.PointL 0) (zo:.PointL 0))+ $ mkStream S vs lus is+ {-# INLINE mkStream #-}++instance+ ( Monad m+ , MkStream m S (Outside is)+ , Context (Outside (is:.PointL)) ~ (Context (Outside is) :. OutsideContext Int)+ ) => MkStream m S (Outside (is:.PointL)) where+ mkStream S (vs:.OStatic d) (O (lus:.PointL u)) (O (is:.PointL i))+ = staticCheck (i>=0 && i+d == u)+ . map (\(ElmS (O zi) (O zo)) -> ElmS (O (zi:.PointL i)) (O (zo:.(PointL $ i+d))))+ $ mkStream S vs (O lus) (O is)+ mkStream S (vs:.OFirstLeft d) (O (us:.PointL u)) (O (is:.PointL i))+ = staticCheck (i>=0 && i+d<=u)+ . map (\(ElmS (O zi) (O zo)) -> ElmS (O (zi:.PointL i)) (O (zo:.(PointL $ i+d))))+ $ mkStream S vs (O us) (O is)+ {-# Inline mkStream #-}++instance TableStaticVar PointL where+ tableStaticVar (IStatic d) _ = IVariable d+ tableStaticVar (IVariable d) _ = IVariable d+ -- NOTE this code used to destroy fusion. If we inline tableStreamIndex+ -- very late (after 'mkStream', probably) then everything works out.+ tableStreamIndex c _ (PointL j)+ | c==EmptyOk = PointL j+ | c==NonEmpty = PointL $ j-1+ | c==OnlyZero = PointL j -- this should then actually request a size in 'tableStaticVar' ...+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}++instance TableStaticVar (Outside PointL) where+ tableStaticVar (OStatic d) _ = OFirstLeft d+ tableStreamIndex c _ (O (PointL j))+ | c==EmptyOk = O (PointL j)+ | c==NonEmpty = O (PointL $ j-1)+ | c==OnlyZero = O (PointL j) -- this should then actually request a size in 'tableStaticVar' ...+ {-# INLINE [0] tableStaticVar #-}+ {-# INLINE [0] tableStreamIndex #-}+
+ ADP/Fusion/Base/Set.hs view
@@ -0,0 +1,103 @@++-- | The @Context@ for a @BitSet@ is the number of bits we should reserve+-- for the more right-most symbols, which request a number of reserved+-- bits.++module ADP.Fusion.Base.Set where++import Data.Vector.Fusion.Stream.Monadic (singleton,filter,enumFromStepN,map,unfoldr)+import Data.Vector.Fusion.Stream.Size+import Debug.Trace+import Prelude hiding (map,filter)+import Data.Bits++import Data.PrimitiveArray++import ADP.Fusion.Base.Classes+import ADP.Fusion.Base.Multi++++type instance TblConstraint BitSet = TableConstraint+type instance TblConstraint (BitSet:>Interface i:>Interface j) = TableConstraint++++instance RuleContext BitSet where+ type Context BitSet = InsideContext Int+ initialContext _ = IStatic 0+ {-# Inline initialContext #-}++instance RuleContext (Outside BitSet) where+ type Context (Outside BitSet) = OutsideContext ()+ initialContext _ = OStatic ()+ {-# Inline initialContext #-}++instance RuleContext (Complement BitSet) where+ type Context (Complement BitSet) = ComplementContext+ initialContext _ = Complemented+ {-# Inline initialContext #-}++++instance RuleContext (BS2I First Last) where+ type Context (BS2I First Last) = InsideContext Int+ initialContext _ = IStatic 0+ {-# Inline initialContext #-}++instance RuleContext (Outside (BS2I First Last)) where+ type Context (Outside (BS2I First Last)) = OutsideContext ()+ initialContext _ = OStatic ()+ {-# Inline initialContext #-}++instance RuleContext (Complement (BS2I First Last)) where+ type Context (Complement (BS2I First Last)) = ComplementContext+ initialContext _ = Complemented+ {-# Inline initialContext #-}++++instance+ ( Monad m+ ) => MkStream m S BitSet where+ mkStream S (IStatic c) u s+ = staticCheck (c <= popCount s) . singleton $ ElmS s 0+ mkStream S (IVariable c) u s+ = staticCheck (c <= popCount s) . singleton $ ElmS 0 0+ {-# Inline mkStream #-}++++instance+ ( Monad m+ ) => MkStream m S (BS2I First Last) where+ mkStream S (IStatic rp) u sij@(s:>Iter i:>j)+ = staticCheck (popCount s == 0 && rp == 0) . singleton $ ElmS (0:>Iter i:>Iter i) undefbs2i+ mkStream S (IVariable rp) u sij@(s:>Iter i:>j)+ = staticCheck (popCount s >= rp) . singleton $ ElmS (0:>Iter i:>Iter i) undefbs2i+ {-# Inline mkStream #-}++instance+ ( Monad m+ ) => MkStream m S (Outside (BS2I First Last)) where++instance+ ( Monad m+ ) => MkStream m S (Complement (BS2I First Last)) where++++-- | An undefined bitset with 2 interfaces.++undefbs2i :: BS2I f l+undefbs2i = (-1) :> (-1) :> (-1)+{-# Inline undefbs2i #-}++undefi :: Interface i+undefi = (-1)+{-# Inline undefi #-}++-- | We sometimes need ++data ThisThatNaught a b = This a | That b | Naught+
+ ADP/Fusion/Base/Subword.hs view
@@ -0,0 +1,75 @@++-- | Instances to allow 'Subword's to be used as index structures in+-- @ADPfusion@.++module ADP.Fusion.Base.Subword where++import Data.Vector.Fusion.Stream.Monadic (singleton,filter,enumFromStepN,map,unfoldr)+import Data.Vector.Fusion.Stream.Size+import Debug.Trace+import Prelude hiding (map,filter)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base.Classes+import ADP.Fusion.Base.Multi++++instance RuleContext Subword where+ type Context Subword = InsideContext ()+ initialContext _ = IStatic ()+ {-# Inline initialContext #-}++instance RuleContext (Outside Subword) where+ type Context (Outside Subword) = OutsideContext (Int:.Int)+ initialContext _ = OStatic (0:.0)+ {-# Inline initialContext #-}++instance RuleContext (Complement Subword) where+ type Context (Complement Subword) = ComplementContext+ initialContext _ = Complemented+ {-# Inline initialContext #-}++-- TODO write instance++-- instance RuleContext (Complement Subword)++++instance (Monad m) => MkStream m S Subword where+ mkStream S (IStatic ()) (Subword (_:.h)) (Subword (i:.j))+ = staticCheck (i>=0 && i==j && j<=h) . singleton $ ElmS (subword i i) (subword 0 0)+ -- NOTE it seems that a static check within an @IVariable@ context+ -- destroys fusion; maybe because of the outer flatten? We don't actually+ -- need a static check anyway because the next flatten takes care of+ -- conditional checks. @filter@ on the other hand, does work.+ -- TODO test with and without filter using quickcheck+ mkStream S (IVariable ()) (Subword (_:.h)) (Subword (i:.j))+ = filter (const $ 0<=i && i<=j && j<=h) . singleton $ ElmS (subword i i) (subword 0 0)+ {-# Inline mkStream #-}++instance (Monad m) => MkStream m S (Outside Subword) where+ mkStream S (OStatic (di:.dj)) (O (Subword (_:.h))) (O (Subword (i:.j)))+ = staticCheck (i==0 && j+dj==h) . singleton $ ElmS (O $ subword i j) (O $ Subword (i:.j+dj))+ mkStream S (OFirstLeft (di:.dj)) (O (Subword (_:.h))) (O (Subword (i:.j)))+ = let i' = i-di+ in staticCheck (0 <= i' && i<=j && j+dj<=h) . singleton $ ElmS (O $ subword i' i') (O $ subword i' i')+ mkStream S (OLeftOf (di:.dj)) (O (Subword (_:.h))) (O (Subword (i:.j)))+ = let i' = i-di+ in staticCheck (0 <= i' && i<=j && j+dj<=h)+ $ map (\k -> ElmS (O $ subword 0 k) (O $ subword k j))+ $ enumFromStepN 0 1 (i'+1)+ {-# Inline mkStream #-}++instance (Monad m) => MkStream m S (Complement Subword) where+ mkStream S Complemented (C (Subword (_:.h))) (C (Subword (i:.j)))+ = map (\(k,l) -> ElmS (C $ subword k l) (C $ subword k l))+ $ unfoldr go (i,i)+ where go (k,l)+ | k >h || k >j = Nothing+ | l==h || l==j = Just ( (k,l) , (k+1,k+1) )+ | otherwise = Just ( (k,l) , (k ,l+1) )+ {-# Inline [0] go #-}+ {-# Inline mkStream #-}+
− ADP/Fusion/Chr.hs
@@ -1,306 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.Chr where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Unboxed as VU-import qualified Data.Vector.Generic as VG-import Data.Strict.Maybe-import Prelude hiding (Maybe(..))--import Data.Array.Repa.Index.Subword--import ADP.Fusion.Classes--import Debug.Trace------ | Parses a single character.--chr xs = GChr (VG.unsafeIndex) xs-{-# INLINE chr #-}---- | Parses a single character and returns the character to the left in a--- strict Maybe.--chrLeft xs = GChr f xs where- f xs k = ( xs VG.!? (k-1)- , VG.unsafeIndex xs k- )- {-# INLINE f #-}-{-# INLINE chrLeft #-}---- With default character--chrLeftD d xs = GChr f xs where- f xs k = ( Prelude.maybe d id $ xs VG.!? (k-1)- , VG.unsafeIndex xs k- )- {-# INLINE f #-}-{-# INLINE chrLeftD #-}---- | Parses a single character and returns the character to the right in a--- strict Maybe.--chrRight xs = GChr f xs where- f xs k = ( VG.unsafeIndex xs k- , xs VG.!? (k+1)- )- {-# INLINE f #-}-{-# INLINE chrRight #-}---- | A generic Character parser that reads a single character but allows--- passing additional information.--data GChr r x where -- = forall v . VG.Vector v x =>- GChr :: VG.Vector v x => !(v x -> Int -> r) -> !(v x) -> GChr r x--instance Build (GChr r x)--instance- ( ValidIndex ls Subword- ) => ValidIndex (ls :!: GChr r x) Subword where- validIndex (ls :!: GChr _ xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<=VG.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: GChr _ _) ix = let (a:!:b:!:c) = getParserRange ls ix in (a:!:b+1:!:max 0 (c-1))- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: GChr r x) Subword where- data Elm (ls :!: GChr r x) Subword = ElmGChr !(Elm ls Subword) !r !Subword- type Arg (ls :!: GChr r x) = Arg ls :. r- getArg !(ElmGChr ls x _) = getArg ls :. x- getIdx !(ElmGChr _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: GChr r x) Subword where- mkStream !(ls :!: GChr f xs) Outer !ij@(Subword (i:.j)) =- let dta = f xs (j-1)- in dta `seq` S.map (\s -> ElmGChr s dta (subword (j-1) j)) $ mkStream ls Outer (subword i $ j-1)- mkStream !(ls :!: GChr f xs) (Inner cnc szd) !ij@(Subword (i:.j))- = S.map (\s -> let Subword (k:.l) = getIdx s- in ElmGChr s (f xs l) (subword l $ l+1)- )- $ mkStream ls (Inner cnc szd) (subword i $ j-1)- {-# INLINE mkStream #-}---- | Wrapping a GChr to allow zero/one behaviour. Parses a character (or not)--- in a strict maybe.--newtype ZeroOne r x = ZeroOne { unZeroOne :: GChr r x }--zoLeft xs = ZeroOne $ chrLeft xs-{-# INLINE zoLeft #-}------ | Generalized peek.--data GPeek r x = GPeek !(VU.Vector x -> Int -> r) !(VU.Vector x) !(Int:!:Int)--instance Build (GPeek r x)--instance- ( ValidIndex ls Subword- , VU.Unbox x- ) => ValidIndex (ls :!: GPeek r x) Subword where- validIndex (ls :!: GPeek _ xs _) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: GPeek _ _ (a':!:c')) ix =- let (a:!:b:!:c) = getParserRange ls ix in (a+a' :!: b :!: (c+c'))- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: GPeek r x) Subword where- data Elm (ls :!: GPeek r x) Subword = ElmGPeek !(Elm ls Subword) !r !Subword- type Arg (ls :!: GPeek r x) = Arg ls :. r- getArg !(ElmGPeek ls x _) = getArg ls :. x- getIdx !(ElmGPeek _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: GPeek r x) Subword where- mkStream !(ls :!: GPeek f xs _) Outer !ij@(Subword (i:.j)) =- let dta = f xs (j-1)- in dta `seq` S.map (\s -> ElmGPeek s dta (subword j j)) $ mkStream ls Outer ij- mkStream !(ls :!: GPeek f xs _) (Inner cnc szd) !ij@(Subword (i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s- in ElmGPeek s (f xs (l-1)) (subword l l)- )- $ mkStream ls (Inner cnc szd) ij- {-# INLINE mkStream #-}---{---- * Parse a single character.--data Chr x = Chr !(VU.Vector x)----chr = Chr---{-# INLINE chr #-}--instance- ( ValidIndex ls Subword- , VU.Unbox xs- ) => ValidIndex (ls :!: Chr xs) Subword where- validIndex (ls :!: Chr xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- let- in i>=a && j<VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: Chr xs) ix = let (a:!:b:!:c) = getParserRange ls ix in (a:!:b+1:!:max 0 (c-1))- {-# INLINE getParserRange #-}--instance Build (Chr x)--instance- ( Elms ls Subword- ) => Elms (ls :!: Chr x) Subword where- data Elm (ls :!: Chr x) Subword = ElmChr !(Elm ls Subword) !x !Subword- type Arg (ls :!: Chr x) = Arg ls :. x- getArg !(ElmChr ls x _) = getArg ls :. x- getIdx !(ElmChr _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}---- |------ For 'Outer' cases, we extract the data, 'seq' it and then stream. This moves--- extraction out of the loop.--instance- ( Monad m- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: Chr x) Subword where- mkStream !(ls :!: Chr xs) Outer !ij@(Subword(i:.j)) =- let dta = VG.unsafeIndex xs (j-1)- in dta `seq` S.map (\s -> ElmChr s dta (subword (j-1) j)) $ mkStream ls Outer (subword i $ j-1)- mkStream !(ls :!: Chr xs) (Inner cnc szd) !ij@(Subword(i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s- in ElmChr s (VG.unsafeIndex xs l) (subword l $ l+1)- )- $ mkStream ls (Inner cnc szd) (subword i $ j-1)- {-# INLINE mkStream #-}--}------ * Peeking to the left--data PeekL x = PeekL !(VU.Vector x)--peekL = PeekL-{-# INLINE peekL #-}--instance Build (PeekL x)--instance- ( ValidIndex ls Subword- , VU.Unbox x- ) => ValidIndex (ls :!: PeekL x) Subword where- validIndex (ls :!: PeekL xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<=VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: PeekL xs) ix = let (a:!:b:!:c) = getParserRange ls ix in if b==0 then (a+1:!:b:!:c) else (a:!:b:!:c)- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: PeekL x) Subword where- data Elm (ls :!: PeekL x) Subword = ElmPeekL !(Elm ls Subword) !x !Subword- type Arg (ls :!: PeekL x) = Arg ls :. x- getArg !(ElmPeekL ls x _) = getArg ls :. x- getIdx !(ElmPeekL _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: PeekL x) Subword where- mkStream !(ls :!: PeekL xs) Outer !ij@(Subword(i:.j)) =- let dta = VU.unsafeIndex xs (j-1)- in dta `seq` S.map (\s -> ElmPeekL s dta (subword j j)) $ mkStream ls Outer ij- mkStream !(ls :!: PeekL xs) (Inner cnc szd) !ij@(Subword(i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s- in ElmPeekL s (VU.unsafeIndex xs $ l-1) (subword l l)- )- $ mkStream ls (Inner cnc szd) ij- {-# INLINE mkStream #-}------ * Peeking to the right--data PeekR x = PeekR !(VU.Vector x)--peekR = PeekR-{-# INLINE peekR #-}--instance Build (PeekR x)--instance- ( ValidIndex ls Subword- , VU.Unbox x- ) => ValidIndex (ls :!: PeekR x) Subword where- validIndex (ls :!: PeekR xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<=VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: PeekR xs) ix = let (a:!:b:!:c) = getParserRange ls ix in (a:!:b:!:c+1)- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: PeekR x) Subword where- data Elm (ls :!: PeekR x) Subword = ElmPeekR !(Elm ls Subword) !x !Subword- type Arg (ls :!: PeekR x) = Arg ls :. x- getArg !(ElmPeekR ls x _) = getArg ls :. x- getIdx !(ElmPeekR _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: PeekR x) Subword where- mkStream !(ls :!: PeekR xs) Outer !ij@(Subword(i:.j)) =- let dta = VU.unsafeIndex xs j- in dta `seq` S.map (\s -> ElmPeekR s dta (subword j j)) $ mkStream ls Outer ij- mkStream !(ls :!: PeekR xs) (Inner cnc szd) !ij@(Subword(i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s- in ElmPeekR s (VU.unsafeIndex xs l) (subword l l)- )- $ mkStream ls (Inner cnc szd) ij- {-# INLINE mkStream #-}-
− ADP/Fusion/Classes.hs
@@ -1,396 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.Classes where--import Data.Array.Repa.Index-import Data.Strict.Maybe-import Data.Strict.Tuple-import Data.Vector.Fusion.Stream.Size-import Prelude hiding (Maybe(..))-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Prelude as P--import Data.Array.Repa.Index.Subword-import Data.Array.Repa.Index.Outside-import Data.Array.Repa.Index.Points------ * Data and type constructors---- | The Inner/Outer handler. We encode three states. We are in 'Outer' or--- right-most position, or 'Inner' position. The 'Inner' position encodes if--- loop conditional 'CheckNoCheck' need to be performed.------ In f <<< Z % table % table, the two tables already perform a conditional--- branch, so that Z/table does not have to check boundary conditions.------ In f <<< Z % table % char, no check is performed in table/char, so Z/table--- needs to perform a boundary check.--data CheckNoCheck- = Check- | NoCheck- deriving (Eq,Show)--data InnerOuter- = Inner !CheckNoCheck !(Maybe Int)- | Outer- deriving (Eq,Show)--data ENE- = EmptyT- | NonEmptyT- | ZeroT- deriving (Eq,Show)------ * Classes---- |--class Elms x i where- data Elm x i :: *- type Arg x :: *- getArg :: Elm x i -> Arg x- getIdx :: Elm x i -> i---- |--class Index i where- type InOut i :: *- type ENZ i :: *- type PartialIndex i :: *- type ParserRange i :: *- outer :: i -> InOut i- leftPartialIndex :: i -> PartialIndex i- rightPartialIndex :: i -> PartialIndex i- fromPartialIndices :: PartialIndex i -> PartialIndex i -> i--class EmptyENZ enz where- toEmptyENZ :: enz -> enz- toNonEmptyENZ :: enz -> enz---- |--class (Monad m) => MkStream m x i where- mkStream :: x -> InOut i -> i -> S.Stream m (Elm x i)---- | Build the stack using (%)--class Build x where- type Stack x :: *- type Stack x = Z :!: x- build :: x -> Stack x- default build :: (Stack x ~ (Z :!: x)) => x -> Stack x- build x = Z :!: x- {-# INLINE build #-}---- | 'ValidIndex', via 'validIndex' statically checks if an index 'i' is valid--- for a stack of terminals and non-terminals 'x'. 'validIndex' is used to--- short-circuit streams via 'outerCheck'.--class (Index i) => ValidIndex x i where- validIndex :: x -> ParserRange i -> i -> Bool- getParserRange :: x -> i -> ParserRange i------ * Helper functions---- | Correct wrapping of 'validIndex' and 'getParserRange'.--checkValidIndex x i = validIndex x (getParserRange x i) i-{-# INLINE checkValidIndex #-}---- | 'outerCheck' acts as a static filter. If 'b' is true, we keep all stream--- elements. If 'b' is false, we discard all stream elements.--outerCheck :: Monad m => Bool -> S.Stream m a -> S.Stream m a-outerCheck b (S.Stream step sS n) = b `seq` S.Stream snew (Left (b,sS)) Unknown where- {-# INLINE [1] snew #-}- snew (Left (False,s)) = return $ S.Done- snew (Left (True ,s)) = return $ S.Skip (Right s)- snew (Right s ) = do r <- step s- case r of- S.Yield x s' -> return $ S.Yield x (Right s')- S.Skip s' -> return $ S.Skip (Right s')- S.Done -> return $ S.Done-{-# INLINE outerCheck #-}------ * Instances------ ** Unsorted--instance EmptyENZ ENE where- toEmptyENZ ene | ene==NonEmptyT = EmptyT- | otherwise = ene- toNonEmptyENZ ene | ene==EmptyT = NonEmptyT- | otherwise = ene- {-# INLINE toEmptyENZ #-}- {-# INLINE toNonEmptyENZ #-}------ ** PointL--instance Index PointL where- type InOut PointL = InnerOuter- type ENZ PointL = ENE- type PartialIndex PointL = Int- type ParserRange PointL = (Int:!:Int:!:Int)- outer _ = Outer- leftPartialIndex (PointL (i:.j)) = i- rightPartialIndex (PointL (i:.j)) = j- fromPartialIndices i j = pointL i j- {-# INLINE outer #-}- {-# INLINE leftPartialIndex #-}- {-# INLINE rightPartialIndex #-}- {-# INLINE fromPartialIndices #-}--instance ValidIndex Z PointL where- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}- validIndex _ _ _ = True- getParserRange _ _ = (0 :!: 0 :!: 0)------ ** 'Subword'--instance Index Subword where- type InOut Subword = InnerOuter- type ENZ Subword = ENE- type PartialIndex Subword = Int- type ParserRange Subword = (Int :!: Int :!: Int)- outer _ = Outer- leftPartialIndex (Subword (i:.j)) = i- rightPartialIndex (Subword (i:.j)) = j- fromPartialIndices i j = subword i j- {-# INLINE outer #-}- {-# INLINE leftPartialIndex #-}- {-# INLINE rightPartialIndex #-}- {-# INLINE fromPartialIndices #-}---- | The bottom of every stack of RHS arguments in a grammar.--instance- ( Monad m- ) => MkStream m Z Subword where- mkStream Z Outer !(Subword (i:.j)) = S.unfoldr step i where- step !k- | k==j = P.Just $ (ElmZ (subword i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner NoCheck Nothing) !(Subword (i:.j)) = S.singleton $ ElmZ $ subword i i- mkStream Z (Inner NoCheck (Just z)) !(Subword (i:.j)) = S.unfoldr step i where- step !k- | k<=j && k+z>=j = P.Just $ (ElmZ (subword i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner Check Nothing) !(Subword (i:.j)) = S.unfoldr step i where- step !k- | k<=j = P.Just $ (ElmZ (subword i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner Check (Just z)) !(Subword (i:.j)) = S.unfoldr step i where- step !k- | k<=j && k+z>=j = P.Just $ (ElmZ (subword i i), j+1)- | otherwise = P.Nothing- {-# INLINE mkStream #-}--instance ValidIndex Z Subword where- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}- validIndex _ _ _ = True- getParserRange _ _ = (0 :!: 0 :!: 0)------ ** Outside--instance Index Outside where- type InOut Outside = InnerOuter- type ENZ Outside = ENE- type PartialIndex Outside = Int- type ParserRange Outside = (Int :!: Int :!: Int)- outer _ = Outer- leftPartialIndex (Outside (i:.j)) = error "outside: not sure yet" -- i- rightPartialIndex (Outside (i:.j)) = error "outside: not sure yet" -- j- fromPartialIndices i j = error "outside: not sure yet" -- outside i j- {-# INLINE outer #-}- {-# INLINE leftPartialIndex #-}- {-# INLINE rightPartialIndex #-}- {-# INLINE fromPartialIndices #-}---- | The bottom of every stack of RHS arguments in a grammar.--instance- ( Monad m- ) => MkStream m Z Outside where- {-- mkStream Z Outer !(Outside (i:.j)) = S.unfoldr step i where- step !k- | k==j = P.Just $ (ElmZ (outside i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner NoCheck Nothing) !(Outside (i:.j)) = S.singleton $ ElmZ $ outside i i- mkStream Z (Inner NoCheck (Just z)) !(Outside (i:.j)) = S.unfoldr step i where- step !k- | k<=j && k+z>=j = P.Just $ (ElmZ (outside i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner Check Nothing) !(Outside (i:.j)) = S.unfoldr step i where- step !k- | k<=j = P.Just $ (ElmZ (outside i i), j+1)- | otherwise = P.Nothing- mkStream Z (Inner Check (Just z)) !(Outside (i:.j)) = S.unfoldr step i where- step !k- | k<=j && k+z>=j = P.Just $ (ElmZ (outside i i), j+1)- | otherwise = P.Nothing- {-# INLINE mkStream #-}- -}--instance ValidIndex Z Outside where- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}- validIndex _ _ _ = True- getParserRange _ _ = (0 :!: 0 :!: 0)------ ** 'Z'--instance Index Z where- type InOut Z = Z- type ENZ Z = Z- type PartialIndex Z = Z- type ParserRange Z = Z- outer Z = Z- leftPartialIndex Z = Z- rightPartialIndex Z = Z- fromPartialIndices Z Z = Z- {-# INLINE outer #-}- {-# INLINE leftPartialIndex #-}- {-# INLINE rightPartialIndex #-}- {-# INLINE fromPartialIndices #-}--instance EmptyENZ Z where- toEmptyENZ _ = Z- toNonEmptyENZ _ = Z- {-# INLINE toEmptyENZ #-}- {-# INLINE toNonEmptyENZ #-}--instance- (- ) => Elms Z ix where- data Elm Z ix = ElmZ !ix- type Arg Z = Z- getArg !(ElmZ _) = Z- getIdx !(ElmZ ix) = ix- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance Monad m => MkStream m Z Z where- mkStream _ _ _ = S.singleton (ElmZ Z)- {-# INLINE mkStream #-}--instance ValidIndex Z Z where- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}- validIndex _ _ _ = True- getParserRange _ _ = Z------ * Multi-dim instances---- ** '(is:.i)'--instance (Index is, Index i) => Index (is:.i) where- type InOut (is:.i) = InOut is :. InOut i- type ENZ (is:.i) = ENZ is :. ENZ i- type PartialIndex (is:.i) = PartialIndex is :. PartialIndex i- type ParserRange (is:.i) = ParserRange is :. ParserRange i- outer (is:.i) = outer is :. outer i- leftPartialIndex (is:.i) = leftPartialIndex is :. leftPartialIndex i- rightPartialIndex (is:.i) = rightPartialIndex is :. rightPartialIndex i- fromPartialIndices (is:.i) (js:.j) = fromPartialIndices is js :. fromPartialIndices i j- {-# INLINE outer #-}- {-# INLINE leftPartialIndex #-}- {-# INLINE rightPartialIndex #-}- {-# INLINE fromPartialIndices #-}--instance (EmptyENZ es, EmptyENZ e) => EmptyENZ (es:.e) where- toEmptyENZ (es:.e) = toEmptyENZ es :. toEmptyENZ e- toNonEmptyENZ (es:.e) = toNonEmptyENZ es :. toNonEmptyENZ e- {-# INLINE toEmptyENZ #-}- {-# INLINE toNonEmptyENZ #-}--instance (ValidIndex Z is, ValidIndex Z i) => ValidIndex Z (is:.i) where- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}- validIndex _ _ _ = True- getParserRange Z (is:.i) = getParserRange Z is :. getParserRange Z i------ ** multi-dim with Subword--instance- ( Monad m- , MkStream m Z is- ) => MkStream m Z (is:.Subword) where- mkStream Z (io:.Outer) (is:.Subword (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.subword i i)) . S.filter (const $ i==j) $ mkStream Z io is- mkStream Z (io:.Inner NoCheck Nothing) (is:.Subword (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.subword i i)) $ mkStream Z io is- mkStream Z (io:.Inner NoCheck (Just z)) (is:.Subword (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.subword i i)) . S.filter (const $ i<=j && i+z>=j) $ mkStream Z io is- mkStream Z (io:.Inner Check Nothing) (is:.Subword (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.subword i i)) . S.filter (const $ i<=j) $ mkStream Z io is- mkStream Z (io:.Inner Check (Just z)) (is:.Subword (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.subword i i)) . S.filter (const $ i<=j && i+z>=j) $ mkStream Z io is- {-# INLINE mkStream #-}------ ** multi-dim with PointL---- TODO automatically created, check correctness--instance- ( Monad m- , MkStream m Z is- ) => MkStream m Z (is:.PointL) where- mkStream Z (io:.Outer) (is:.PointL (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.pointL i i)) . S.filter (const $ i==j) $ mkStream Z io is- mkStream Z (io:.Inner NoCheck Nothing) (is:.PointL (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.pointL i i)) $ mkStream Z io is- mkStream Z (io:.Inner NoCheck (Just z)) (is:.PointL (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.pointL i i)) . S.filter (const $ i<=j && i+z>=j) $ mkStream Z io is- mkStream Z (io:.Inner Check Nothing) (is:.PointL (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.pointL i i)) . S.filter (const $ i<=j) $ mkStream Z io is- mkStream Z (io:.Inner Check (Just z)) (is:.PointL (i:.j))- = S.map (\(ElmZ jt) -> ElmZ (jt:.pointL i i)) . S.filter (const $ i<=j && i+z>=j) $ mkStream Z io is- {-# INLINE mkStream #-}-------- * Special instances--instance Build x => Build (x:!:y) where- type Stack (x:!:y) = Stack x :!: y- build (x:!:y) = build x :!: y- {-# INLINE build #-}-
− ADP/Fusion/Empty.hs
@@ -1,56 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.Empty where--import Data.Array.Repa.Index-import Data.Strict.Maybe-import Data.Strict.Tuple-import Prelude hiding (Maybe(..))-import qualified Data.Vector.Fusion.Stream.Monadic as S--import Data.Array.Repa.Index.Subword--import ADP.Fusion.Classes----data Empty = Empty--empty = Empty-{-# INLINE empty #-}--instance- ( ValidIndex ls Subword- ) => ValidIndex (ls :!: Empty) Subword where- validIndex (ls:!:Empty) abc ij@(Subword (i:.j)) = i==j && validIndex ls abc ij- {-# INLINE validIndex #-}--instance Build Empty--instance- ( Elms ls Subword- ) => Elms (ls :!: Empty) Subword where- data Elm (ls :!: Empty) Subword = ElmEmpty !(Elm ls Subword) !() !Subword- type Arg (ls :!: Empty) = Arg ls :. ()- getArg !(ElmEmpty ls () _) = getArg ls :. ()- getIdx !(ElmEmpty _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:Empty) Subword where- mkStream !(ls:!:Empty) Outer !ij@(Subword (i:.j))- = S.map (\s -> ElmEmpty s () (subword i j))- $ S.filter (\_ -> i==j)- $ mkStream ls Outer ij- {-# INLINE mkStream #-}-
− ADP/Fusion/Examples/Palindrome.hs
@@ -1,118 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE RecordWildCards #-}--module ADP.Fusion.Examples.Palindrome where--import Data.Vector.Fusion.Stream.Monadic (Stream (..))-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Unboxed as VU-import qualified Data.Vector as V-import Data.Array.Repa.Index-import Control.Monad-import Control.Monad.Trans.Class-import qualified Control.Monad.Trans.Writer.Lazy as W-import qualified Control.Arrow as A--import Data.PrimitiveArray as PA-import Data.PrimitiveArray.Zero as PA--import ADP.Fusion hiding (empty)-import ADP.Fusion.Empty hiding (empty)-import ADP.Fusion.Chr-import ADP.Fusion.Table-import Data.Array.Repa.Index.Subword-import ADP.Fusion.TH----data SignatureT m x r = Signature- { pair :: Char -> x -> Char -> x- , empty :: () -> x- , h :: Stream m x -> m r- }---- makeAlgebraProduct ''SignatureT--{----- gPalindrome :: Signature m x -> Empty -> Char -> tbl -> (tbl, Subword -> m x)--gPalindrome Signature{..} e c s =- ( s, ( empty <<< e |||- pair <<< c % s % c ... h- )- )-{-# INLINE gPalindrome #-}----aPair :: Monad m => Signature m Int Int-aPair = Signature- { pair = \l x r -> if l==r then (x+4983) else -999999- , empty = \() -> 4711- , h = S.foldl' max (-888888)- }-{-# INLINE aPair #-}--aPretty :: Monad m => Signature m String (Stream m String)-aPretty = Signature- { pair = \l x r -> "(" ++ x ++ ")"- , empty = \() -> ""- , h = return . id- }--(<**) :: (Monad m, CombElem x' x) => Signature m x x' -> Signature m y y' -> Signature m (x,Stream m y) y'-(<**) x y = Signature- { pair = \l (zx,zy) r -> (pair x l zx r, S.map (\z -> pair y l z r) zy)- , empty = \() -> (empty x (), S.singleton $ empty y ())- , h = \zs -> do hfst <- h x $ S.map fst zs- h y $ S.concatMap snd . S.filter (combElem hfst . fst) $ zs- }-{-# INLINE (<**) #-}--(***) :: (Monad m) => Signature m x x' -> Signature m y y' -> Signature m (x,y) (x',y')-(***) x y = Signature- { pair = \l (zx,zy) r -> (pair x l zx r, pair y l zy r)- , empty = \() -> (empty x (), empty y ())--- , h = \zs -> do hfst <- h x $ S.map fst zs--- let phfs = S.concatMap snd . S.filter (combElem hfst . fst) $ zs--- hsnd <- h y phfs- }-{-# INLINE (***) #-}--class CombElem x y where- combElem :: x -> y -> Bool--instance (Eq x) => CombElem x x where- combElem = (==)--instance (VU.Unbox x, Eq x) => CombElem (VU.Vector x) x where- combElem xs y = VU.elem y xs--instance (Eq x) => CombElem (V.Vector x) x where- combElem xs y = V.elem y xs--palindromeFill :: VU.Vector Char -> IO (PA.Unboxed (Z:.Subword) Int)-palindromeFill inp = do- let n = VU.length inp- !t' <- newWithM (Z:.subword 0 0) (Z:.subword 0 n) 0- let t= mTblSw EmptyT t'- let b = chr inp- let e = Empty- fillTable $ gPalindrome aPair e b t- freeze t'-{-# NOINLINE palindromeFill #-}--fillTable (MTbl _ tbl, f) = do- let (_,Z:.Subword (0:.n)) = boundsM tbl- forM_ [n,n-1..0] $ \i -> forM_ [i..n] $ \j -> do- (f $ subword i j) >>= writeM tbl (Z:.subword i j)-{-# INLINE fillTable #-}---}-
− ADP/Fusion/Examples/TwoDim.hs
@@ -1,98 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeOperators #-}---- | This is not really a working example, but rather to check the GHC-Core for--- fusion.----module ADP.Fusion.Examples.TwoDim where-module Main where--import Data.Vector.Fusion.Stream.Monadic (Stream (..))-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Unboxed as VU-import qualified Data.Vector as V-import Data.Array.Repa.Index-import Control.Monad-import Control.Monad.Trans.Class-import qualified Control.Monad.Trans.Writer.Lazy as W-import qualified Control.Arrow as A-import System.IO.Unsafe (unsafePerformIO)-import Control.Applicative--import Data.Array.Repa.Index.Points-import Data.PrimitiveArray as PA-import Data.PrimitiveArray.Zero as PA--import ADP.Fusion hiding (empty)-import ADP.Fusion.Empty hiding (empty)-import ADP.Fusion.Chr-import ADP.Fusion.Table-import ADP.Fusion.Multi-import Data.Array.Repa.Index.Subword-import ADP.Fusion.TH----main = do- ls <- lines <$> getContents- align ls--align [] = return ()-align [c] = error "single last line"-align (a:b:xs) = do- putStrLn a- putStrLn b- print $ needlemanWunsch (VU.fromList a) (VU.fromList b)- align xs--data Signature m x r c = Signature- { step_step :: x -> (Z:.c :.c ) -> x- , step_loop :: x -> (Z:.c :.()) -> x- , loop_step :: x -> (Z:.():.c ) -> x- , nil_nil :: (Z:.():.()) -> x- , h :: Stream m x -> m r- }---- grammar :: Signature m x r c -> ???-grammar Signature{..} a i1 i2 =- ( a, step_step <<< a % (T:!chr i1:!chr i2) |||- step_loop <<< a % (T:!chr i1:!None ) |||- loop_step <<< a % (T:!None :!chr i2) |||- nil_nil <<< (T:!Empty:!Empty) ... h- )-{-# INLINE grammar #-}--sScore :: Monad m => Signature m Int Int Char-sScore = Signature- { step_step = \x (Z:.a:.b) -> if a==b then x+1 else x-1- , step_loop = \x _ -> x-1- , loop_step = \x _ -> x-1- , nil_nil = const 0- , h = S.foldl' max 0- }-{-# INLINE sScore #-}--needlemanWunsch i1 i2 = (ws ! (Z:.pointL 0 n1:.pointL 0 n2), bt) where- ws = unsafePerformIO (forwardPhase i1 i2)- n1 = VU.length i1- n2 = VU.length i2- bt = [] :: String-{-# NOINLINE needlemanWunsch #-}--forwardPhase :: VU.Vector Char -> VU.Vector Char -> IO (PA.Unboxed (Z:.PointL:.PointL) Int)-forwardPhase i1 i2 = do- let n1 = VU.length i1- let n2 = VU.length i2- !t' <- newWithM (Z:.pointL 0 0:.pointL 0 0) (Z:.pointL 0 n1:.pointL 0 n2) 0- let t= mTbl (Z:.EmptyT:.EmptyT) t'- fillTable $ grammar sScore t i1 i2- freeze t'-{-# INLINE forwardPhase #-}--fillTable (MTbl _ tbl, f) = do- let (_,Z:.PointL(0:.n1):.PointL(0:.n2)) = boundsM tbl- forM_ [0 .. n1] $ \k1 -> forM_ [0 .. n2] $ \k2 -> do- (f $ Z:.pointL 0 k1:.pointL 0 k2) >>= writeM tbl (Z:.pointL 0 k1:.pointL 0 k2)-{-# INLINE fillTable #-}-
− ADP/Fusion/Multi.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE UnicodeSyntax #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeOperators #-}---- | The multi-tape extension of ADPfusion. Just re-exports everything.--module ADP.Fusion.Multi- ( module ADP.Fusion.Multi.Classes- , module ADP.Fusion.Multi.Empty- , module ADP.Fusion.Multi.GChr- , module ADP.Fusion.Multi.None- ) where--import ADP.Fusion.Multi.Classes-import ADP.Fusion.Multi.None-import ADP.Fusion.Multi.GChr-import ADP.Fusion.Multi.Empty----{--type instance TermOf (Term ts (ZeroOne r xs)) = TermOf ts :. Maybe r--instance- ( TermValidIndex ts is- ) => TermValidIndex (Term ts (ZeroOne r xs)) (is:.PointL) where- termDimensionsValid (ts:!ZeroOne (gchr)) = termDimensionsValid (ts:!gchr)- {-- getTermParserRange (ts:!- -}------- The experimental zero/one wrapper--instance- ( Monad m- , TermElm m ts is- ) => TermElm m (Term ts (ZeroOne r xs)) (is:.PointL) where- termStream (ts:!(ZeroOne (GChr f xs))) (io:.o) (is:.ij@(PointL(i:.j)))- = doubleStream- . termStream (ts:!GChr f xs) (io:.o) (is:.ij)- where- {-# INLINE doubleStream #-}- doubleStream (S.Stream step sS n) = S.Stream sNew (Left sS) (2*n) where- {-# INLINE [1] sNew #-}- sNew (Left s) = do r <- step s- case r of- S.Yield (abc:!:(es:.e)) s' -> return $ S.Yield (abc:!:(es:.Just e)) (Right s')- S.Skip s' -> return $ S.Skip (Left s')- S.Done -> return $ S.Done- sNew (Right s) = do r <- step s- case r of- S.Yield (abc:!:(es:.e)) s' -> return $ S.Yield (abc:!:(es:.Nothing)) (Left s')--- S.Skip s' -> return $ S.Skip (Left s')--- S.Done -> return $ S.Done- {-# INLINE termStream #-}--}----- Empty-
− ADP/Fusion/Multi/Classes.hs
@@ -1,112 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeFamilies #-}--module ADP.Fusion.Multi.Classes where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import qualified Data.Vector.Fusion.Stream.Monadic as S--import ADP.Fusion.Classes------ | The zero-th dimension of every terminal parser.--data TermBase = T---- | Combine a terminal parser of dimension k in @a@ with a new 1-dim parser--- @b@ generating a parser of dimension k+1.--data Term a b = a :! b---- | A 'termStream' extracts all terminal elements from a multi-dimensional--- terminal symbol.--class- ( Monad m- ) => TermElm m t ix where- termStream :: t -> InOut ix -> ix -> S.Stream m (ze :!: zix :!: ix) -> S.Stream m (ze :!: zix :!: ix :!: TermOf t)---- |--type family TermOf t :: *---- | To calculate parser ranges and index validity we need an additional type--- class that recurses over the individual 'Term' elements.--class TermValidIndex t i where- termDimensionsValid :: t -> ParserRange i -> i -> Bool- getTermParserRange :: t -> i -> ParserRange i -> ParserRange i- termInnerOuter :: t -> i -> InOut i -> InOut i- termLeftIndex :: t -> i -> i------ * The instance declarations for generic @Term a b@ data ctors.--instance Build (Term a b)--instance- ( ValidIndex ls ix- , TermValidIndex (Term a b) ix- , Show ix- , Show (ParserRange ix)- ) => ValidIndex (ls :!: Term a b) ix where- validIndex (ls :!: t) abc ix =- termDimensionsValid t abc ix && validIndex ls abc ix- {-# INLINE validIndex #-}- getParserRange (ls :!: t) ix = getTermParserRange t ix (getParserRange ls ix)- {-# INLINE getParserRange #-}--instance- ( Elms ls ix- ) => Elms (ls :!: Term a b) ix where- data Elm (ls :!: Term a b) ix = ElmTerm !(Elm ls ix) !(TermOf (Term a b)) !ix- type Arg (ls :!: Term a b) = Arg ls :. (TermOf (Term a b))- getArg !(ElmTerm ls x _) = getArg ls :. x- getIdx !(ElmTerm _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls ix- , MkStream m ls ix- , TermElm m (Term a b) ix- , TermValidIndex (Term a b) ix- ) => MkStream m (ls :!: Term a b) ix where- mkStream !(ls :!: t) !io !ij- = S.map (\(s:!:Z:!:zij:!:e) -> ElmTerm s e zij)- $ termStream t io ij- $ S.map (\s -> (s :!: Z :!: getIdx s))- $ mkStream ls (termInnerOuter t ij io) (termLeftIndex t ij)- {-# INLINE mkStream #-}------ * Terminal stream of 'TermBase' with index 'Z'--type instance TermOf TermBase = Z--instance- ( Monad m- ) => TermElm m (TermBase) Z where- termStream T _ Z = S.map (\(zs:!:zix:!:Z) -> (zs:!:zix:!:Z:!:Z))- {-# INLINE termStream #-}--instance TermValidIndex TermBase Z where- termDimensionsValid T Z Z = True- getTermParserRange T Z Z = Z- termInnerOuter T Z Z = Z- termLeftIndex T Z = Z- {-# INLINE termDimensionsValid #-}- {-# INLINE getTermParserRange #-}- {-# INLINE termInnerOuter #-}- {-# INLINE termLeftIndex #-}-
− ADP/Fusion/Multi/Empty.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeOperators #-}--module ADP.Fusion.Multi.Empty where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import qualified Data.Vector.Fusion.Stream.Monadic as S--import Data.Array.Repa.Index.Points--import ADP.Fusion.Classes-import ADP.Fusion.Empty-import ADP.Fusion.Multi.Classes----type instance TermOf (Term ts Empty) = TermOf ts :. ()--instance- ( Monad m- , TermElm m ts is- ) => TermElm m (Term ts Empty) (is:.PointL) where- termStream (ts:!Empty) (io:.Outer) (is:.ij@(PointL(i:.j))) =- S.map (\(zs:!:(zix:.kl):!:zis:!:e) -> (zs:!:zix:!:(zis:.kl):!:(e:.())))- . S.filter (const (i==j))- . termStream ts io is- . S.map (\(zs:!:zix:!:(zis:.kl)) -> (zs:!:(zix:.kl):!:zis))- {-# INLINE termStream #-}--instance- ( TermValidIndex ts is- ) => TermValidIndex (Term ts Empty) (is:.PointL) where- termDimensionsValid (ts:!Empty) (prs:.(a:!:b:!:c)) (is:.PointL(i:.j))- = termDimensionsValid ts prs is- getTermParserRange (ts:!Empty) (is:._) (prs:.(a:!:b:!:c))- = getTermParserRange ts is prs :. (a:!:b:!:c)- termInnerOuter (ts:!_) (is:._) (ios:.io) = termInnerOuter ts is ios :. io- termLeftIndex (ts:!_) (is:.ij) = termLeftIndex ts is :. ij- {-# INLINE termDimensionsValid #-}- {-# INLINE getTermParserRange #-}- {-# INLINE termInnerOuter #-}- {-# INLINE termLeftIndex #-}-
− ADP/Fusion/Multi/GChr.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeOperators #-}--module ADP.Fusion.Multi.GChr where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Generic as VG--import Data.Array.Repa.Index.Points-import Data.Array.Repa.Index.Subword--import ADP.Fusion.Chr-import ADP.Fusion.Classes-import ADP.Fusion.Multi.Classes---type instance TermOf (Term ts (GChr r xs)) = TermOf ts :. r------ * Multi-dim 'Subword's.---- TODO we want to evaluate @f xs $ j-1@ just once before the stream is--- generated. Unfortunately, this will evaluate cases like index (-1) as well,--- which leads to crashes. The code below is safe but slower. We should--- incorporate a version that performs and @outerCheck@ in the code.--instance- ( Monad m- , TermElm m ts is- ) => TermElm m (Term ts (GChr r xs)) (is:.Subword) where- termStream (ts :! GChr f xs) (io:.Outer) (is:.ij@(Subword(i:.j)))- = S.map (\(zs :!: (zix:.kl) :!: zis :!: e) -> (zs :!: zix :!: (zis:.subword (j-1) j) :!: (e:.(f xs $ j-1))))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- termStream (ts :! GChr f xs) (io:.Inner _ _) (is:.ij)- = S.map (\(zs :!: (zix:.kl@(Subword(k:.l))) :!: zis :!: e) -> let dta = f xs l in dta `seq` (zs :!: zix :!: (zis:.subword l (l+1)) :!: (e:.dta)))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- {-# INLINE termStream #-}--instance- ( TermValidIndex ts is- ) => TermValidIndex (Term ts (GChr r xs)) (is:.Subword) where- termDimensionsValid (ts:!GChr _ xs) (prs:.(a:!:b:!:c)) (is:.Subword(i:.j))- = i>=a && j<=VG.length xs -c && i+b<=j && termDimensionsValid ts prs is- getTermParserRange (ts:!GChr _ _) (is:._) (prs:.(a:!:b:!:c))- = getTermParserRange ts is prs :. (a:!:b+1:!:max 0 (c-1))- termInnerOuter (ts:!_) (is:._) (ios:.io) = termInnerOuter ts is ios :. io- termLeftIndex (ts:!_) (is:.Subword (i:.j)) = termLeftIndex ts is :. subword i (j-1)- {-# INLINE termDimensionsValid #-}- {-# INLINE getTermParserRange #-}- {-# INLINE termInnerOuter #-}- {-# INLINE termLeftIndex #-}------ * Multi-dim 'PointL's---- | NOTE This instance is currently the only one using an "inline outer--- check". If This behaves well, it could be possible to put checks for valid--- indices inside the outerCheck function. (Currently disabled, as the compiler--- chokes on four-way alignments).--instance- ( Monad m- , TermElm m ts is- ) => TermElm m (Term ts (GChr r xs)) (is:.PointL) where- termStream (ts :! GChr f xs) (io:.Outer) (is:.ij@(PointL(i:.j)))- -- = outerCheck (j>0)- -- . let dta = (f xs $ j-1) in dta `seq` S.map (\(zs :!: (zix:.kl) :!: zis :!: e) -> (zs :!: zix :!: (zis:.pointL (j-1) j) :!: (e:.dta)))- = S.map (\(zs :!: (zix:.kl) :!: zis :!: e) -> (zs :!: zix :!: (zis:.pointL (j-1) j) :!: (e:.(f xs $ j-1))))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- termStream (ts :! GChr f xs) (io:.Inner _ _) (is:.ij)- = S.map (\(zs :!: (zix:.kl@(PointL(k:.l))) :!: zis :!: e) -> let dta = f xs l in dta `seq` (zs :!: zix :!: (zis:.pointL l (l+1)) :!: (e:.dta)))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- {-# INLINE termStream #-}---- TODO auto-generated, check correctness--instance- ( TermValidIndex ts is- ) => TermValidIndex (Term ts (GChr r xs)) (is:.PointL) where- termDimensionsValid (ts:!GChr _ xs) (prs:.(a:!:b:!:c)) (is:.PointL(i:.j))- = {- i>=a && j<=VG.length xs -c && i+b<=j && -} termDimensionsValid ts prs is- getTermParserRange (ts:!GChr _ _) (is:._) (prs:.(a:!:b:!:c))- = getTermParserRange ts is prs :. (a:!:b+1:!:max 0 (c-1))- termInnerOuter (ts:!_) (is:._) (ios:.io) = termInnerOuter ts is ios :. io- termLeftIndex (ts:!_) (is:.PointL (i:.j)) = termLeftIndex ts is :. pointL i (j-1)- {-# INLINE termDimensionsValid #-}- {-# INLINE getTermParserRange #-}- {-# INLINE termInnerOuter #-}- {-# INLINE termLeftIndex #-}-
− ADP/Fusion/Multi/None.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeOperators #-}--module ADP.Fusion.Multi.None where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import qualified Data.Vector.Fusion.Stream.Monadic as S--import Data.Array.Repa.Index.Points--import ADP.Fusion.Classes-import ADP.Fusion.Multi.Classes-import ADP.Fusion.None----type instance TermOf (Term ts None) = TermOf ts :. ()--instance- ( Monad m- , TermElm m ts is- ) => TermElm m (Term ts None) (is:.PointL) where- termStream (ts :! None) (io:.Outer) (is:.ij@(PointL(i:.j))) =- S.map (\(zs :!: (zix:.kl) :!: zis :!: e) -> (zs :!: zix :!: (zis:.kl) :!: (e:.())))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- termStream (ts :! None) (io:.Inner _ _) (is:.ij)- = S.map (\(zs :!: (zix:.kl) :!: zis :!: e) -> (zs :!: zix :!: (zis:.kl) :!: (e:.())))- . termStream ts io is- . S.map (\(zs :!: zix :!: (zis:.kl)) -> (zs :!: (zix:.kl) :!: zis))- {-# INLINE termStream #-}---- TODO auto-gen'ed--instance- ( TermValidIndex ts is- ) => TermValidIndex (Term ts None) (is:.PointL) where- termDimensionsValid (ts:!None) (prs:.(a:!:b:!:c)) (is:.PointL(i:.j))- = termDimensionsValid ts prs is- getTermParserRange (ts:!None) (is:._) (prs:.(a:!:b:!:c))- = getTermParserRange ts is prs :. (a:!:b:!:c)- termInnerOuter (ts:!_) (is:._) (ios:.io) = termInnerOuter ts is ios :. io- termLeftIndex (ts:!_) (is:.ij) = termLeftIndex ts is :. ij- {-# INLINE termDimensionsValid #-}- {-# INLINE getTermParserRange #-}- {-# INLINE termInnerOuter #-}- {-# INLINE termLeftIndex #-}-
− ADP/Fusion/None.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.None where--import Data.Array.Repa.Index-import Data.Strict.Maybe-import Data.Strict.Tuple-import Prelude hiding (Maybe(..))-import qualified Data.Vector.Fusion.Stream.Monadic as S--import Data.Array.Repa.Index.Subword--import ADP.Fusion.Classes----data None = None--none = None-{-# INLINE none #-}---- None is always valid--instance- ( ValidIndex ls Subword- ) => ValidIndex (ls :!: None) Subword where- validIndex (ls:!:None) abc ij@(Subword (i:.j)) = validIndex ls abc ij- {-# INLINE validIndex #-}--instance Build None--instance- ( Elms ls Subword- ) => Elms (ls :!: None) Subword where- data Elm (ls :!: None) Subword = ElmNone !(Elm ls Subword) !() !Subword- type Arg (ls :!: None) = Arg ls :. ()- getArg !(ElmNone ls () _) = getArg ls :. ()- getIdx !(ElmNone _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:None) Subword where- mkStream !(ls:!:None) Outer !ij@(Subword (i:.j))- = S.map (\s -> ElmNone s () (subword i j))- $ S.filter (\_ -> i==j)- $ mkStream ls Outer ij- {-# INLINE mkStream #-}-
− ADP/Fusion/QuickCheck.hs
@@ -1,531 +0,0 @@-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}--module ADP.Fusion.QuickCheck where--import Control.Monad-import Control.Applicative-import Data.Array.Repa.Index-import Data.Array.Repa.Shape-import Data.Array.Repa.Arbitrary-import Debug.Trace-import qualified Data.Vector.Fusion.Stream as S-import qualified Data.Vector.Fusion.Stream.Monadic as SM-import qualified Data.Vector.Unboxed as VU-import Test.QuickCheck-import Test.QuickCheck.All-import Test.QuickCheck.Monadic-import Data.List ((\\))-import System.IO.Unsafe--import Data.Array.Repa.Index.Subword-import Data.Array.Repa.Index.Point-import Data.Array.Repa.Index.Points-import qualified Data.PrimitiveArray as PA-import qualified Data.PrimitiveArray.Zero as PA--import ADP.Fusion-import ADP.Fusion.Table-import ADP.Fusion.Multi----- | Check if a single region returns the correct result (namely a slice from--- the input).--prop_R sw@(Subword (i:.j)) = zs == ls where- zs = id <<< region xs ... S.toList $ sw- ls = [VU.slice i (j-i) xs | i>=0, j<=100]---- | Two regions next to each other.--prop_RR sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< region xs % region xs ... S.toList $ sw- ls = [(VU.slice i (k-i) xs, VU.slice k (j-k) xs) | k <- [i..j]]---- | And finally, three regions (with smaller subword sizes only)--prop_RRR sw@(Subword (i:.j)) = (j-i<=30) ==> zs == ls where- zs = (,,) <<< region xs % region xs % region xs ... S.toList $ sw- ls = [ ( VU.slice i (k-i) xs- , VU.slice k (l-k) xs- , VU.slice l (j-l) xs- ) | k <- [i..j], l <- [k..j]]---- | Three sized regions (with smaller subword sizes only)--prop_SSS sw@(Subword (i:.j)) = zs == ls where- zs = (,,) <<< sregion 3 10 xs % sregion 3 10 xs % sregion 3 10 xs ... S.toList $ sw- ls = [ ( VU.slice i (k-i) xs- , VU.slice k (l-k) xs- , VU.slice l (j-l) xs- ) | k <- [i..j], l <- [k..j], minimum [k-i,l-k,j-l] >=3, maximum [k-i,l-k,j-l] <= 10]---- | Single-character parser.--prop_C sw@(Subword (i:.j)) = zs == ls where- zs = id <<< chr xs ... S.toList $ sw- ls = [xs VU.! i | i+1==j, i>=0, j<=100]---- | 2x Single-character parser.--prop_CC sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< chr xs % chr xs ... S.toList $ sw- ls = [(xs VU.! i, xs VU.! (i+1)) | i+2==j]---- ** Single character plus peeking--prop_PlC sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< peekL xs % chr xs ... S.toList $ sw- ls = [(xs VU.! (j-2), xs VU.! (j-1)) | j>1, i+1==j]--prop_PrC sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< peekR xs % chr xs ... S.toList $ sw- ls = [(xs VU.! (j-1), xs VU.! (j-1)) | i+1==j]--prop_CPr sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< chr xs % peekR xs ... S.toList $ sw- ls = [(xs VU.! (j-1), xs VU.! j) | i>=0, j<=99,i+1==j]--prop_CPl sw@(Subword (i:.j)) = zs == ls where- zs = (,) <<< chr xs % peekL xs ... S.toList $ sw- ls = [(xs VU.! (j-1), xs VU.! (j-1)) | i+1==j]---- | 2x Single-character parser bracketing a single region.--prop_CRC sw@(Subword (i:.j)) = zs == ls- where- zs = (,,) <<< chr xs % region xs % chr xs ... S.toList $ sw- ls = [(xs VU.! i, VU.slice (i+1) (j-i-2) xs , xs VU.! (j-1)) |i+2<=j]---- | 2x Single-character parser bracketing regions.--prop_CRRC sw@(Subword (i:.j)) = zs == ls- where- zs = (,,,) <<< chr xs % region xs % region xs % chr xs ... S.toList $ sw- ls = [ ( xs VU.! i- , VU.slice (i+1) (k-i-1) xs- , VU.slice k (j-k-1) xs- , xs VU.! (j-1)- ) | k <- [i+1 .. j-1]]---- | complex behaviour with characters and regions--prop_CRCRC sw@(Subword (i:.j)) = zs == ls where- zs = (,,,,) <<< chr xs % region xs % chr xs % region xs % chr xs ... S.toList $ sw- ls = [ ( xs VU.! i- , VU.slice (i+1) (k-i-1) xs- , xs VU.! k- , VU.slice (k+1) (j-k-2) xs- , xs VU.! (j-1)- ) | k <- [i+1 .. j-2] ]---- | Interior-loop like structures.--prop_Interior1 sw@(Subword (i:.j)) = zs == ls where- zs = (,,) <<< chr xs % peekR xs % sregion 1 5 xs ... S.toList $ sw- ls = [ ( xs VU.! i- , xs VU.! (i+1)- , VU.slice (i+1) (j-i-1) xs- ) | j-i>=2, j-i<=6- ]--prop_Interior2 sw@(Subword (i:.j)) = zs == ls where- zs = (,,,,) <<< chr xs % peekR xs % sregion 1 5 xs % peekR xs % sregion 2 5 xs ... S.toList $ sw- ls = [ ( xs VU.! i- , xs VU.! (i+1)- , VU.slice (i+1) (k-i-1) xs- , xs VU.! k- , VU.slice k (j-k) xs- ) | j-i>=4, j-i<=11, k <- [i+2 .. (min j $ i+6)], j-k>=2, j-k<=5- ]--prop_Interior3 sw@(Subword (i:.j)) = zs == ls where- zs = (,,,,,,) <<< chr xs % peekR xs % sregion 1 5 xs % peekR xs % sregion 2 5 xs % peekL xs % sregion 1 5 xs ... S.toList $ sw- ls = [ ( xs VU.! i- , xs VU.! (i+1)- , VU.slice (i+1) (k-i-1) xs- , xs VU.! k- , VU.slice k (l-k) xs- , xs VU.! (l-1)- , VU.slice l (j-l) xs- ) | i>= 0- , j<= 100- , k <- [i..j]- , l <- [k..j]- , j-i>=5, j-i<=16- , k-i-1>=1, k-i-1<=5- , l-k>=2, l-k<=5- , j-l>=1, j-l<=5- ]--prop_Interior4 sw@(Subword (i:.j)) = zs == ls where- zs = (,,,,,,,,) <<< chr xs % peekR xs % sregion 1 5 xs % peekR xs % sregion 2 5 xs % peekL xs % sregion 1 5 xs % peekL xs % chr xs ... S.toList $ sw- ls = [ ( xs VU.! i- , xs VU.! (i+1)- , VU.slice (i+1) (k-i-1) xs- , xs VU.! k- , VU.slice k (l-k) xs- , xs VU.! (l-1)- , VU.slice l (j-l-1) xs- , xs VU.! (j-2)- , xs VU.! (j-1)- ) | k <- [i..j]- , l <- [k..j]- , j-i>=6, j-i<=17- , k-i-1>=1, k-i-1<=5- , l-k>=2, l-k<=5- , j-l-1>=1, j-l-1<=5- ]--prop_Interior5 sw@(Subword (i:.j)) = zs == ls where- zs = (,,,,,,,,,,) <<< peekL xs % chr xs % peekR xs % sregion 1 5 xs % peekR xs % sregion 2 5 xs % peekL xs % sregion 1 5 xs % peekL xs % chr xs % peekR xs ... S.toList $ sw- ls = [ ( xs VU.! (i-1)- , xs VU.! i- , xs VU.! (i+1)- , VU.slice (i+1) (k-i-1) xs- , xs VU.! k- , VU.slice k (l-k) xs- , xs VU.! (l-1)- , VU.slice l (j-l-1) xs- , xs VU.! (j-2)- , xs VU.! (j-1)- , xs VU.! j- ) | i>= 1- , j<= 99- , k <- [i..j]- , l <- [k..j]- , i>0, j-1 < VU.length xs- , j-i>=6, j-i<=17- , k-i-1>=1, k-i-1<=5- , l-k>=2, l-k<=5- , j-l-1>=1, j-l-1<=5- ]---- | A single mutable table should return one result.--prop_Mt sw@(Subword (i:.j)) = monadicIO $ do- mxs :: PA.MutArr IO (PA.Unboxed (Z:.Subword) Int) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw EmptyT mxs- zs <- run $ id <<< mt ... SM.toList $ sw- ls <- run $ sequence $ [(PA.readM mxs (Z:.sw)) | i<=j]- assert $ zs == ls---- | table, then character.--prop_MtC sw@(Subword (i:.j)) = monadicIO $ do- mxs :: (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int)) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw EmptyT mxs- zs <- run $ (,) <<< mt % chr xs ... SM.toList $ sw- ls <- run $ sequence $ [(PA.readM mxs (Z:.subword i (j-1))) >>= \a -> return (a,xs VU.! (j-1)) | i<j]- assert $ zs == ls---- | Character, then table.--prop_CMt sw@(Subword (i:.j)) = monadicIO $ do- mxs :: (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int)) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw EmptyT mxs- zs <- run $ (,) <<< chr xs % mt ... SM.toList $ sw- ls <- run $ sequence $ [(PA.readM mxs (Z:.subword (i+1) j)) >>= \a -> return (xs VU.! i,a) | i<j]- assert $ zs == ls---- | Two mutable tables. Basically like Region's.--prop_MtMt sw@(Subword (i:.j)) = monadicIO $ do- mxs :: (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int)) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw EmptyT mxs- zs <- run $ (,) <<< mt % mt ... SM.toList $ sw- ls <- run $ sequence $ [(PA.readM mxs (Z:.subword i k)) >>= \a -> PA.readM mxs (Z:.subword k j) >>= \b -> return (a,b) | k <- [i..j]]- assert $ zs == ls---- | Just to make it more interesting, sprinkle in some 'Chr' symbols.--prop_CMtCMtC sw@(Subword (i:.j)) = monadicIO $ do- mxs :: (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int)) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw EmptyT mxs- zs <- run $ (,,,,) <<< chr xs % mt % chr xs % mt % chr xs ... SM.toList $ sw- ls <- run $ sequence $ [ (PA.readM mxs (Z:.subword (i+1) k)) >>=- \a -> PA.readM mxs (Z:.subword (k+1) (j-1)) >>=- \b -> return ( xs VU.! i- , a- , xs VU.! k- , b- , xs VU.! (j-1)- )- | k <- [i+1..j-2]]- assert $ zs == ls---- | And now with non-empty tables.--prop_CMnCMnC sw@(Subword (i:.j)) = monadicIO $ do- mxs :: (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int)) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ] -- (1 :: Int)- let mt = mTblSw NonEmptyT mxs- zs <- run $ (,,,,) <<< chr xs % mt % chr xs % mt % chr xs ... SM.toList $ sw- ls <- run $ sequence $ [ (PA.readM mxs (Z:.subword (i+1) k)) >>=- \a -> PA.readM mxs (Z:.subword (k+1) (j-1)) >>=- \b -> return ( xs VU.! i- , a- , xs VU.! k- , b- , xs VU.! (j-1)- )- | k <- [i+2..j-3]]- assert $ zs == ls--{-- - Currently not allowing 0-dim multi-tapes.--prop_Tt ix@Z = zs == ls where- zs = id <<< T ... S.toList $ ix- ls = [ Z ]--}---- **--prop_Tc ix@(Z:.Subword(i:.j)) = zs == ls where- zs = id <<< (T:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i) | i>=0, j<= 100, i+1==j ]--prop_Tcc ix@(Z:.Subword(i:.j):.Subword(k:.l)) = zs == ls where- zs = id <<< (T:!chr xs:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i:.xs VU.! k) | i>=0, j<=100, k>=0, j<=100, i+1==j, k+1==l ]---- **--prop_TcTc ix@(Z:.Subword(i:.j)) = zs == ls where- zs = (,) <<< (T:!chr xs) % (T:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i,Z:.xs VU.! (i+1)) | i>=0, j<= 100, i+2==j ]--prop_TccTcc ix@(Z:.Subword(i:.j):.Subword(k:.l)) = zs == ls where- zs = (,) <<< (T:!chr xs:!chr xs) % (T:!chr xs:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i:.xs VU.! k, Z:.xs VU.! (i+1):.xs VU.! (k+1)) | i>=0, j<=100, k>=0, j<=100, i+2==j, k+2==l ]---- **--prop_Mt2 ix@(Z:.Subword(i:.j)) = monadicIO $ do- mxs :: PA.MutArr IO (PA.Unboxed (Z:.Subword) Int) <- run $ PA.fromListM (Z:.subword 0 0) (Z:.subword 0 100) [0 ..]- let mt = mTbl (Z:.EmptyT) mxs -- :: MTbl (Z:.Subword) (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int))- zs <- run $ id <<< mt ... SM.toList $ ix- ls <- run $ sequence $ [ (PA.readM mxs (Z:.subword i j)) | i>=0, j<=100, i<=j ]- assert $ zs == ls--prop_MtMt2 ix@(Z:.Subword(i:.j)) = monadicIO $ do- mxs :: PA.MutArr IO (PA.Unboxed (Z:.Subword) Int) <- run $ PA.fromListM (Z:.subword 0 0) (Z:.subword 0 100) [0 ..]- let mt = mTbl (Z:.EmptyT) mxs -- :: MTbl (Z:.Subword) (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int))- zs <- run $ (,) <<< mt % mt ... SM.toList $ ix- ls <- run $ sequence $ [ liftM2 (,) (PA.readM mxs (Z:.subword i k)) (PA.readM mxs (Z:.subword k j)) | i>=0, j<=100, k<-[i..j] ]- assert $ zs == ls--prop_MtMtMt2 ix@(Z:.Subword(i:.j)) = monadicIO $ do- mxs :: PA.MutArr IO (PA.Unboxed (Z:.Subword) Int) <- run $ PA.fromListM (Z:.subword 0 0) (Z:.subword 0 100) [0 ..]- let mt = mTbl (Z:.EmptyT) mxs -- :: MTbl (Z:.Subword) (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int))- zs <- run $ (,,) <<< mt % mt % mt ... SM.toList $ ix- ls <- run $ sequence $ [ liftM3 (,,) (PA.readM mxs (Z:.subword i k)) (PA.readM mxs (Z:.subword k l)) (PA.readM mxs (Z:.subword l j)) | i>=0, j<=100, k<-[i..j], l<-[k..j] ]- assert $ zs == ls--prop_TcMtTc ix@(Z:.Subword(i:.j)) = monadicIO $ do- mxs :: PA.MutArr IO (PA.Unboxed (Z:.Subword) Int) <- run $ PA.fromListM (Z:.subword 0 0) (Z:.subword 0 100) [0 ..]- let mt = mTbl (Z:.EmptyT) mxs :: MTbl (Z:.Subword) (PA.MutArr IO (PA.Unboxed (Z:.Subword) Int))- zs <- run $ (,,) <<< (T:!chr xs) % mt % (T:!chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [ (PA.readM mxs (Z:.subword (i+1) (j-1)) >>= \z -> return (Z:.xs VU.! i,z,Z:.xs VU.! (j-1))) | i>=0, j<=100, i+2<=j ]- assert $ zs == ls--prop_2dim ix@(Z:.TinySubword(i:.j):.TinySubword(k:.l)) = monadicIO $ do- mxs <- run $ pure $ mxsSwSw- let mt = mTbl (Z:.EmptyT:.EmptyT) mxs- zs <- run $ (,) <<< mt % mt ... SM.toList $ Z:.subword i j:.subword k l- ls <- run $ sequence $ [ liftM2 (,) (PA.readM mxs (Z:.subword i a:.subword k b)) (PA.readM mxs (Z:.subword a j:.subword b l)) | i>=0, j<=100, k>=0, l<=100, a<-[i..j], b<-[k..l] ]- assert $ zs==ls--prop_2dimCMCMC ix@(Z:.TinySubword(i:.j):.TinySubword(k:.l)) = monadicIO $ do- mxs <- run $ pure $ mxsSwSw -- :: PA.MutArr IO (PA.Unboxed (Z:.Subword:.Subword) Int) <- run $ PA.fromListM (Z:.subword 0 0:.subword 0 0) (Z:.subword 0 100:.subword 0 100) [0 ..]- let mt = mTbl (Z:.EmptyT:.EmptyT) mxs- zs <- run $ (,,,,) <<< (T:!chr xs:!chr xs) % mt % (T:!chr xs:!chr xs) % mt % (T:!chr xs:!chr xs) ... SM.toList $ Z:.subword i j:.subword k l- ls <- run $ sequence $ [ liftM5 (,,,,) (pure $ Z:.xs VU.! i:.xs VU.! k)- (PA.readM mxs (Z:.subword (i+1) a:.subword (k+1) b))- (pure $ Z:.xs VU.! a:.xs VU.! b)- (PA.readM mxs (Z:.subword (a+1) (j-1):.subword (b+1) (l-1)))- (pure $ Z:.xs VU.! (j-1):.xs VU.! (l-1))- | j-i>=3, l-k>=3, i>=0, j<=100, k>=0, l<=100, a<-[i+1..j-2], b<-[k+1..l-2] ]- assert $ zs==ls---- * working on 'PointL's--prop_P_Tt ix@(Z:.PointL (i:.j)) = zs == ls where- zs = id <<< (T:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i) | i+1==j ]--prop_P_CC ix@(Z:.PointL (i:.j)) = zs == ls where- zs = (,) <<< (T:!chr xs) % (T:!chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! i, Z:.xs VU.! (i+1)) | i+2==j ]--prop_P_2dimCMCMC ix@(Z:.PointL(i:.j):.PointL(k:.l)) = monadicIO $ do- mxs <- run $ pure $ mxsPP- let mt = mTbl (Z:.EmptyT:.EmptyT) mxs- zs <- run $ (,,,,) <<< (T:!chr xs:!chr xs) % mt % (T:!chr xs:!chr xs) % mt % (T:!chr xs:!chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [ liftM5 (,,,,) (pure $ Z:.xs VU.! i:.xs VU.! k)- (PA.readM mxs (Z:.pointL (i+1) a:.pointL (k+1) b))- (pure $ Z:.xs VU.! a:.xs VU.! b)- (PA.readM mxs (Z:.pointL (a+1) (j-1):.pointL (b+1) (l-1)))- (pure $ Z:.xs VU.! (j-1):.xs VU.! (l-1))- | j-i>=3, l-k>=3, i>=0, j<=100, k>=0, l<=100, a<-[i+1..j-2], b<-[k+1..l-2] ]- assert $ zs==ls--{--prop_TcTc ix@(Z:.Point i) = {- traceShow (zs,ls) $ -} zs == ls where- zs = (,) <<< Term (T:.Chr xs) % Term (T:.Chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! (i-2), Z:.xs VU.! (i-1)) | i>1 ]---- deriving instance Show (Elm (None :. Term (T :. Chr Int)) (Z :. Point))--prop_TpTc ix@(Z:.Point i) = {- traceShow (zs,ls) $ -} zs == ls where- zs = (,) <<< Term (T:.Peek (-1) xs) % Term (T:.Chr xs) ... S.toList $ ix- ls = [ (Z:.f i, Z:.xs VU.! (i-1)) | i>0 ]- f i = if i>1 then xs VU.! (i-2) else (-1)--prop_TcTpTc ix@(Z:.Point i) = {- traceShow (zs,ls) $ -} zs == ls where- zs = (,,) <<< Term (T:.Chr xs) % Term (T:.Peek (-1) xs) % Term (T:.Chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! (i-2), Z:.f i, Z:.xs VU.! (i-1)) | i>1 ]- f i = if i>1 then xs VU.! (i-2) else (-1)--{--prop_Mt_Tc ix@(Z:.Subword(i:.j)) = monadicIO $ do- mxs :: (PA.MU IO (Z:.Subword) Int) <- run $ PA.fromListM (Z:. Subword (0:.0)) (Z:. Subword (0:.100)) [0 .. ]- let mt = mtable mxs- zs <- run $ (,) <<< mt % Term (T:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [(PA.readM mxs (Z:.subword i (j-1))) >>= \a -> return (a,Z:.xs VU.! (j-1)) | i<j ]- assert $ zs == ls--}--prop_P_Mt_Tt ix@(Z:.Point i) = monadicIO $ do- mxs :: (PA.MU IO (Z:.Point) Int) <- run $ PA.fromListM (Z:.Point 0) (Z:.Point 100) [0 .. ]- let mt = mtable mxs- zs <- run $ (,) <<< mt % Term (T:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [(PA.readM mxs (Z:.Point (i-1))) >>= \a -> return (a,Z:.xs VU.! (i-1)) | i>0 ]- assert $ zs == ls--prop_P_Mt_TpTc ix@(Z:.Point i) = monadicIO $ do- mxs :: (PA.MU IO (Z:.Point) Int) <- run $ PA.fromListM (Z:.Point 0) (Z:.Point 100) [0 .. ]- let mt = mtable mxs- let f i = if i>1 then xs VU.! (i-2) else (-1)- zs <- run $ (,,) <<< mt % Term (T:.Peek (-1) xs) % Term (T:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [(PA.readM mxs (Z:.Point (i-1))) >>= \a -> return (a,Z:.f i,Z:.xs VU.! (i-1)) | i>0 ]- assert $ zs == ls---- | and with 2-tape grammars--prop_Tcc ix@(Z:.Subword(i:.j):.Subword(k:.l)) = zs == ls where- zs = id <<< Term (T:.Chr xs:.Chr xs) ... S.toList $ ix- ls = [ ( Z- :. xs VU.! i- :. xs VU.! k- ) | i+1==j, k+1==l ]--prop_Mt_Tcc (Z:.TinySubword (i:.j):.TinySubword (k:.l)) = monadicIO $ do- let ix = Z :. subword i j :. subword k l- mxs :: (PA.MU IO (Z:.Subword:.Subword) Int) <- run $ PA.fromListM (Z:. Subword (0:.0):.Subword(0:.0)) (Z:. Subword (0:.j+1):.Subword (0:.k+1)) [0 .. ]- let mt = mtable mxs- zs <- run $ (,) <<< mt % Term (T:.Chr xs:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [ (PA.readM mxs (Z:.subword i (j-1):.subword k (l-1))) >>= \a -> return (a,Z:.xs VU.! (j-1):.xs VU.! (l-1)) | i<j,k<l ]- assert $ zs == ls--prop_P_Ttt ix@(Z:.Point i:.Point j) = zs == ls where- zs = id <<< Term (T:.Chr xs:.Chr xs) ... S.toList $ ix- ls = [ (Z:.xs VU.! (i-1):.xs VU.! (j-1)) | i>0, j>0 ]--prop_P_Mt_Ttt ix@(Z:.Point i:.Point j) = monadicIO $ do- mxs :: (PA.MU IO (Z:.Point:.Point) Int) <- run $ PA.fromListM (Z:.Point 0:.Point 0) (Z:.Point 100:.Point 100) [0 .. ]- let mt = mtable mxs- zs <- run $ (,) <<< mt % Term (T:.Chr xs:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [(PA.readM mxs (Z:.Point (i-1):.Point (j-1))) >>= \a -> return (a,Z:.xs VU.! (i-1):.xs VU.! (j-1)) | i>0,j>0 ]- assert $ zs == ls--prop_P_Mt_Tpp_Ttt ix@(Z:.Point i:.Point j) = monadicIO $ do- mxs :: (PA.MU IO (Z:.Point:.Point) Int) <- run $ PA.fromListM (Z:.Point 0:.Point 0) (Z:.Point 100:.Point 100) [0 .. ]- let mt = mtable mxs- let f i j = Z:. (if i>1 then xs VU.! (i-2) else (-1)) :. (if j>1 then xs VU.! (j-2) else (-1))- zs <- run $ (,,) <<< mt % Term (T:.Peek (-1) xs:.Peek (-1) xs) % Term (T:.Chr xs:.Chr xs) ... SM.toList $ ix- ls <- run $ sequence $ [(PA.readM mxs (Z:.Point (i-1):.Point (j-1))) >>= \a -> return (a,f i j,Z:.xs VU.! (i-1):.xs VU.! (j-1)) | i>0,j>0 ]- -- traceShow (zs,ls) $- assert $ zs == ls---- | and with 3-tape grammars--prop_Tccc ix@(Z:.Subword(i:.j):.Subword(k:.l):.Subword(a:.b)) = zs == ls where- zs = id <<< Term (T:.Chr xs:.Chr xs:.Chr xs) ... S.toList $ ix- ls = [ ( Z- :. xs VU.! i- :. xs VU.! k- :. xs VU.! a- ) | i+1==j, k+1==l, a+1==b ]---- * helper functions and stuff---- | Helper function to create non-specialized regions--region = Region Nothing Nothing---- |--mtable xs = MTable Eall xs--{---- | A subword (i,j) should always produce an index in the allowed range--prop_subwordIndex (Small n, Subword (i:.j)) = (n>j) ==> p where- p = n * (n+1) `div` 2 >= k- k = subwordIndex (subword 0 n) (subword i j)--}---}---- | data set. Can be made fixed as the maximal subword size is statically known!--xs = VU.fromList [0 .. 99 :: Int]----------TODO will break if PrimitiveArray assertions are active (need to fixe exact length of list)--mxsSwSw = unsafePerformIO $ zzz where- zzz :: IO (PA.MutArr IO (PA.Unboxed (Z:.Subword:.Subword) Int))- zzz = PA.fromListM (Z:.subword 0 0:.subword 0 0) (Z:.subword 0 100:.subword 0 100) [0 ..]--mxsPP = unsafePerformIO $ zzz where- zzz :: IO (PA.MutArr IO (PA.Unboxed (Z:.PointL:.PointL) Int))- zzz = PA.fromListM (Z:.pointL 0 0:.pointL 0 0) (Z:.pointL 0 100:.pointL 0 100) [0 ..]---- * general quickcheck stuff--options = stdArgs {maxSuccess = 1000}--customCheck = quickCheckWithResult options--allProps = $forAllProperties customCheck----newtype Small = Small Int- deriving (Show)--instance Arbitrary Small where- arbitrary = Small <$> choose (0,100)- shrink (Small i) = Small <$> shrink i--newtype TinySubword = TinySubword (Int:.Int)- deriving (Show)--instance Arbitrary TinySubword where- arbitrary = do a <- choose (0,20)- b <- choose (0,20)- return $ TinySubword $ min a b :. max a b- shrink (TinySubword (a:.b)) = [TinySubword (a:.b-1) | a<b]--instance Arbitrary z => Arbitrary (z:.TinySubword) where- arbitrary = (:.) <$> arbitrary <*> arbitrary- shrink (z:.s) = (:.) <$> shrink z <*> shrink s--
+ ADP/Fusion/QuickCheck/Common.hs view
@@ -0,0 +1,10 @@++{-# Options_GHC -O0 #-}++module ADP.Fusion.QuickCheck.Common where++import Debug.Trace++++tr zs ls b = traceShow (zs," ",ls,length zs,length ls) b
+ ADP/Fusion/QuickCheck/Point.hs view
@@ -0,0 +1,293 @@++{-# Options_GHC -O0 #-}++module ADP.Fusion.QuickCheck.Point where++import Control.Applicative+import Control.Monad+import Data.Strict.Tuple+import Data.Vector.Fusion.Util+import Debug.Trace+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Unboxed as VU+import System.IO.Unsafe+import Test.QuickCheck+import Test.QuickCheck.All+import Test.QuickCheck.Monadic++import Data.PrimitiveArray++import ADP.Fusion++++-- * Epsilon cases++prop_Epsilon ix@(PointL j) = zs == ls where+ zs = (id <<< Epsilon ... S.toList) maxPL ix+ ls = [ () | j == 0 ]++prop_O_Epsilon ix@(O (PointL j)) = zs == ls where+ zs = (id <<< Epsilon ... S.toList) (O maxPL) ix+ ls = [ () | j == 100 ]++prop_ZEpsilon ix@(Z:.PointL j) = zs == ls where+ zs = (id <<< (M:|Epsilon) ... S.toList) (Z:.maxPL) ix+ ls = [ Z:.() | j == 0 ]++prop_O_ZEpsilon ix@(O (Z:.PointL j)) = zs == ls where+ zs = (id <<< (M:|Epsilon) ... S.toList) (O (Z:.maxPL)) ix+ ls = [ Z:.() | j == 100 ]++prop_O_ZEpsilonEpsilon ix@(O (Z:.PointL j:.PointL l)) = zs == ls where+ zs = (id <<< (M:|Epsilon:|Epsilon) ... S.toList) (O (Z:.maxPL:.maxPL)) ix+ ls = [ Z:.():.() | j == 100, l == 100 ]++++-- * Deletion cases++prop_O_ItNC ix@(O (PointL j)) = zs == ls where+ t = ITbl 0 0 EmptyOk xsPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % Deletion % chr xs ... S.toList) (O $ maxPL) ix+ ls = [ ( unsafeIndex xsPo (O $ PointL $ j+1)+ , ()+ , xs VU.! (j+0)+ ) | j >= 0, j <= 99 ]+{-# Noinline prop_O_ItNC #-}++prop_O_ZItNC ix@(O (Z:.PointL j)) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|Deletion) % (M:|chr xs) ... S.toList) (O (Z:.maxPL)) ix+ ls = [ ( unsafeIndex xsZPo (O (Z:.PointL (j+1)))+ , Z:.()+ , Z:.xs VU.! (j+0)+ ) | j >= 0, j <= 99 ]++prop_O_2dimIt_NC_CN ix@(O (Z:.PointL j:.PointL l)) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|Deletion:|chr xs) % (M:|chr xs:|Deletion) ... S.toList) (O (Z:.maxPL:.maxPL)) ix+ ls = [ ( unsafeIndex xsPPo (O (Z:.PointL (j+1):.PointL (l+1)))+ , Z:.() :.xs VU.! (l+0)+ , Z:.xs VU.! (j+0):.()+ ) | j>=0, l>=0, j<=99, l<=99 ]++prop_2dimIt_NC_CN ix@(Z:.PointL j:.PointL l) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPP (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|Deletion:|chr xs) % (M:|chr xs:|Deletion) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ ( unsafeIndex xsPP (Z:.PointL (j-1):.PointL (l-1))+ , Z:.() :.xs VU.! (l-1)+ , Z:.xs VU.! (j-1):.()+ ) | j>=1, l>=1, j<=100, l<=100 ]++++-- * terminal cases++-- | A single character terminal++prop_Tt ix@(Z:.PointL j) = zs == ls where+ zs = (id <<< (M:|chr xs) ... S.toList) (Z:.maxPL) ix+ ls = [ (Z:.xs VU.! (j-1)) | 1==j ]++--prop_O_Tt ix@(Z:.O (PointL j)) = traceShow (j,zs,ls) $ zs == ls where+-- zs = (id <<< (M:|chr xs) ... S.toList) (Z:.O maxPL) ix+-- ls = [ (Z:.xs VU.! (j-1)) | 1==j ]++-- | Two single-character terminals++prop_CC ix@(Z:.PointL i) = zs == ls where+ zs = ((,) <<< (M:|chr xs) % (M:|chr xs) ... S.toList) (Z:.maxPL) ix+ ls = [ (Z:.xs VU.! (i-2), Z:.xs VU.! (i-1)) | 2==i ]++-- | Just a table++prop_It ix@(PointL j) = zs == ls where+ t = ITbl 0 0 EmptyOk xsP (\ _ _ -> Id 1)+ zs = (id <<< t ... S.toList) maxPL ix+ ls = [ unsafeIndex xsP ix | j>=0, j<=100 ]++prop_O_It ix@(O (PointL j)) = zs == ls where+ t = ITbl 0 0 EmptyOk xsPo (\ _ _ -> Id 1)+ zs = (id <<< t ... S.toList) (O maxPL) ix+ ls = [ unsafeIndex xsPo ix | j>=0, j<=100 ]++prop_ZIt ix@(Z:.PointL j) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZP (\ _ _ -> Id 1)+ zs = (id <<< t ... S.toList) (Z:.maxPL) ix+ ls = [ unsafeIndex xsZP ix | j>=0, j<=100 ]++prop_O_ZIt ix@(O (Z:.PointL j)) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZPo (\ _ _ -> Id 1)+ zs = (id <<< t ... S.toList) (O (Z:.maxPL)) ix+ ls = [ unsafeIndex xsZPo ix | j>=0, j<=100 ]++-- | Table, then single terminal++prop_ItC ix@(PointL j) = zs == ls where+ t = ITbl 0 0 EmptyOk xsP (\ _ _ -> Id 1)+ zs = ((,) <<< t % chr xs ... S.toList) maxPL ix+ ls = [ ( unsafeIndex xsP (PointL $ j-1)+ , xs VU.! (j-1)+ ) | j>=1, j<=100 ]++-- | @A^*_j -> A^*_{j+1} c_{j+1)@ !++prop_O_ItC ix@(O (PointL j)) = zs == ls where+ t = ITbl 0 0 EmptyOk xsPo (\ _ _ -> Id 1)+ zs = ((,) <<< t % chr xs ... S.toList) (O $ maxPL) ix+ ls = [ ( unsafeIndex xsPo (O $ PointL $ j+1)+ , xs VU.! (j+0)+ ) | j >= 0, j < 100 ]++prop_O_ItCC ix@(O (PointL j)) = zs == ls where+ t = ITbl 0 0 EmptyOk xsPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % chr xs % chr xs ... S.toList) (O $ maxPL) ix+ ls = [ ( unsafeIndex xsPo (O $ PointL $ j+2)+ , xs VU.! (j+0)+ , xs VU.! (j+1)+ ) | j >= 0, j <= 98 ]+{-# Noinline prop_O_ItCC #-}++prop_O_ZItCC ix@(O (Z:.PointL j)) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|chr xs) % (M:|chr xs) ... S.toList) (O (Z:.maxPL)) ix+ ls = [ ( unsafeIndex xsZPo (O (Z:.PointL (j+2)))+ , Z:.xs VU.! (j+0)+ , Z:.xs VU.! (j+1)+ ) | j >= 0, j <= 98 ]++-- | synvar followed by a 2-tape character terminal++prop_2dimItCC ix@(Z:.PointL j:.PointL l) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPP (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|chr xs:|chr xs) % (M:|chr xs:|chr xs) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ ( unsafeIndex xsPP (Z:.PointL (j-2):.PointL (l-2))+ , Z:.xs VU.! (j-2):.xs VU.! (l-2)+ , Z:.xs VU.! (j-1):.xs VU.! (l-1)+ ) | j>=2, l>=2, j<=100, l<=100 ]++prop_O_2dimItCC ix@(O (Z:.PointL j:.PointL l)) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPPo (\ _ _ -> Id 1)+ zs = ((,,) <<< t % (M:|chr xs:|chr xs) % (M:|chr xs:|chr xs) ... S.toList) (O (Z:.maxPL:.maxPL)) ix+ ls = [ ( unsafeIndex xsPPo (O (Z:.PointL (j+2):.PointL (l+2)))+ , Z:.xs VU.! (j+0):.xs VU.! (l+0)+ , Z:.xs VU.! (j+1):.xs VU.! (l+1)+ ) | j>=0, l>=0, j<=98, l<=98 ]++-- * direct index tests++xprop_O_ixZItCC ix@(O (Z:.PointL j)) = zs where+ t = ITbl 0 0 (Z:.EmptyOk) xsZPo (\ _ _ -> Id 1)+ zs = (id >>> t % (M:|chr xs) % (M:|chr xs) ... S.toList) (O (Z:.maxPL)) ix++-- * 'Strng' tests++-- ** Just the 'Strng' terminal++prop_ManyS ix@(PointL j) = zs == ls where+ zs = (id <<< manyS xs ... S.toList) maxPL ix+ ls = [ (VU.slice 0 j xs) ]++prop_SomeS ix@(PointL j) = zs == ls where+ zs = (id <<< someS xs ... S.toList) maxPL ix+ ls = [ (VU.slice 0 j xs) | j>0 ]++prop_2dim_ManyS_ManyS ix@(Z:.PointL i:.PointL j) = zs == ls where+ zs = (id <<< (M:|manyS xs:|manyS xs) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ (Z:.VU.slice 0 i xs:.VU.slice 0 j xs) ]++prop_2dim_SomeS_SomeS ix@(Z:.PointL i:.PointL j) = zs == ls where+ zs = (id <<< (M:|someS xs:|someS xs) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ (Z:.VU.slice 0 i xs:.VU.slice 0 j xs) | i > 0 && j > 0 ]++-- ** Together with a syntactic variable.++prop_Itbl_ManyS ix@(PointL i) = zs == ls where+ t = ITbl 0 0 EmptyOk xsP (\ _ _ -> Id 1)+ zs = ((,) <<< t % manyS xs ... S.toList) maxPL ix+ ls = [ (unsafeIndex xsP (PointL k), VU.slice k (i-k) xs) | k <- [0..i] ]++prop_Itbl_SomeS ix@(PointL i) = zs == ls where+ t = ITbl 0 0 EmptyOk xsP (\ _ _ -> Id 1)+ zs = ((,) <<< t % someS xs ... S.toList) maxPL ix+ ls = [ (unsafeIndex xsP (PointL k), VU.slice k (i-k) xs) | k <- [0..i-1] ]++prop_1dim_Itbl_ManyS ix@(Z:.PointL i) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZP (\ _ _ -> Id 1)+ zs = ((,) <<< t % (M:|manyS xs) ... S.toList) (Z:.maxPL) ix+ ls = [ (unsafeIndex xsZP (Z:.PointL k), Z:. VU.slice k (i-k) xs) | k <- [0..i] ]++prop_1dim_Itbl_SomeS ix@(Z:.PointL i) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk) xsZP (\ _ _ -> Id 1)+ zs = ((,) <<< t % (M:|someS xs) ... S.toList) (Z:.maxPL) ix+ ls = [ (unsafeIndex xsZP (Z:.PointL k), Z:. VU.slice k (i-k) xs) | k <- [0..i-1] ]++prop_2dim_Itbl_ManyS_ManyS ix@(Z:.PointL i:.PointL j) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPP (\ _ _ -> Id 1)+ zs = ((,) <<< t % (M:|manyS xs:|manyS xs) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ (unsafeIndex xsPP (Z:.PointL k:.PointL l), Z:. VU.slice k (i-k) xs :. VU.slice l (j-l) xs) | k <- [0..i], l <- [0..j] ]++prop_2dim_Itbl_SomeS_SomeS ix@(Z:.PointL i:.PointL j) = zs == ls where+ t = ITbl 0 0 (Z:.EmptyOk:.EmptyOk) xsPP (\ _ _ -> Id 1)+ zs = ((,) <<< t % (M:|someS xs:|someS xs) ... S.toList) (Z:.maxPL:.maxPL) ix+ ls = [ (unsafeIndex xsPP (Z:.PointL k:.PointL l), Z:. VU.slice k (i-k) xs :. VU.slice l (j-l) xs) | k <- [0..i-1], l <- [0..j-1] ]+++++infixl 8 >>>+(>>>) f xs = \lu ij -> S.map f . mkStream (build xs) (initialContext ij) lu $ ij++class GetIxs x i where+ type R x i :: *+ getIxs :: Elm x i -> R x i++instance GetIxs S i where+ type R S i = Z:.(i,i)+ getIxs e = Z:.(getIdx e, getOmx e)++instance GetIxs ls i => GetIxs (ls :!: Chr a b) i where+ type R (ls :!: Chr a b) i = R ls i :. (i,i)+ getIxs (ElmChr _ i o s) = getIxs s :. (i,o)++instance GetIxs ls i => GetIxs (ls :!: ITbl m a i x) i where+ type R (ls :!: ITbl m a i x) i = R ls i :. (i,i)+ getIxs (ElmITbl _ i o s) = getIxs s :. (i,o)++xsP :: Unboxed (PointL) Int+xsP = fromList (PointL 0) maxPL [0 ..]++xsZP :: Unboxed (Z:.PointL) Int+xsZP = fromList (Z:.PointL 0) (Z:.maxPL) [0 ..]++xsPo :: Unboxed (Outside (PointL)) Int+xsPo = fromList (O $ PointL 0) (O $ maxPL) [0 ..]++xsZPo :: Unboxed (Outside (Z:.PointL)) Int+xsZPo = fromList (O (Z:.PointL 0)) (O (Z:.maxPL)) [0 ..]++xsPP :: Unboxed (Z:.PointL:.PointL) Int+xsPP = fromList (Z:.PointL 0:.PointL 0) (Z:.maxPL:.maxPL) [0 ..]++xsPPo :: Unboxed (Outside (Z:.PointL:.PointL)) Int+xsPPo = fromList (O (Z:.PointL 0:.PointL 0)) (O (Z:.maxPL:.maxPL)) [0 ..]++mxsPP = unsafePerformIO $ zzz where+ zzz :: IO (MutArr IO (Unboxed (Z:.PointL:.PointL) Int))+ zzz = fromListM (Z:.PointL 0:.PointL 0) (Z:.maxPL:.maxPL) [0 ..]++maxPL = PointL 100++xs = VU.fromList [0 .. 99 :: Int]++-- * general quickcheck stuff++options = stdArgs {maxSuccess = 1000}++customCheck = quickCheckWithResult options++return []+allProps = $forAllProperties customCheck+
+ ADP/Fusion/QuickCheck/Set.hs view
@@ -0,0 +1,248 @@++{-# Options_GHC -O0 #-}++module ADP.Fusion.QuickCheck.Set where++import Data.Bits+import Data.Vector.Fusion.Util+import Debug.Trace+import qualified Data.List as L+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Unboxed as VU+import Test.QuickCheck hiding (NonEmpty)+import Test.QuickCheck.All+import Test.QuickCheck.Monadic++import Data.Bits.Ordered+import Data.PrimitiveArray++import ADP.Fusion+import ADP.Fusion.QuickCheck.Common++++-- * BitSets without interfaces++-- ** Inside checks++prop_b_ii ix@(BitSet _) = zs == ls where+ tia = ITbl 0 0 EmptyOk xsB (\ _ _ -> Id 1)+ tib = ITbl 0 0 EmptyOk xsB (\ _ _ -> Id 1)+ zs = ((,) <<< tia % tib ... S.toList) highestB ix+ ls = [ ( xsB ! kk , xsB ! (ix `xor` kk) )+ | k <- VU.toList . popCntSorted $ popCount ix -- [ 0 .. 2^(popCount ix) -1 ]+ , let kk = popShiftL ix (BitSet k)+ ]++prop_b_ii_nn ix@(BitSet _) = zs == ls where+ tia = ITbl 0 0 NonEmpty xsB (\ _ _ -> Id 1)+ tib = ITbl 0 0 NonEmpty xsB (\ _ _ -> Id 1)+ zs = ((,) <<< tia % tib ... S.toList) highestB ix+ ls = [ ( xsB ! kk , xsB ! (ix `xor` kk) )+ | k <- VU.toList . popCntSorted $ popCount ix -- [ 0 .. 2^(popCount ix) -1 ]+ , let kk = popShiftL ix (BitSet k)+ , popCount kk > 0+ , popCount (ix `xor` kk) > 0+ ]++prop_b_iii ix@(BitSet _) = zs == ls where+ tia = ITbl 0 0 EmptyOk xsB (\ _ _ -> Id 1)+ tib = ITbl 0 0 EmptyOk xsB (\ _ _ -> Id 1)+ tic = ITbl 0 0 EmptyOk xsB (\ _ _ -> Id 1)+ zs = ((,,) <<< tia % tib % tic ... S.toList) highestB ix+ ls = [ ( xsB ! kk , xsB ! ll , xsB ! mm )+ | k <- VU.toList . popCntSorted $ popCount ix+ , l <- VU.toList . popCntSorted $ popCount ix - popCount k+ , let kk = popShiftL ix (BitSet k)+ , let ll = popShiftL (ix `xor` kk) (BitSet l)+ , let mm = (ix `xor` (kk .|. ll))+ ]++prop_b_iii_nnn ix@(BitSet _) = zs == ls where+ tia = ITbl 0 0 NonEmpty xsB (\ _ _ -> Id 1)+ tib = ITbl 0 0 NonEmpty xsB (\ _ _ -> Id 1)+ tic = ITbl 0 0 NonEmpty xsB (\ _ _ -> Id 1)+ zs = ((,,) <<< tia % tib % tic ... S.toList) highestB ix+ ls = [ ( xsB ! kk , xsB ! ll , xsB ! mm )+ | k <- VU.toList . popCntSorted $ popCount ix+ , l <- VU.toList . popCntSorted $ popCount ix - popCount k+ , let kk = popShiftL ix (BitSet k)+ , let ll = popShiftL (ix `xor` kk) (BitSet l)+ , let mm = (ix `xor` (kk .|. ll))+ , popCount kk > 0, popCount ll > 0, popCount mm > 0+ ]+++-- * Outside checks+-- These checks are very similar to those in the @Subword@ module. We just+-- need to be a bit more careful, as indexed sets have overlap.++-- ** Two non-terminals.+--+-- @A_s -> B_(s\t) C_t (s\t) ++ t == s@+-- @s = 111 , s\t = 101, t = 010@+--+-- with @Z@ the full set.+-- @Z = 1111@++-- @B*_Z\(s\t) -> A*_Z\s C_t@+-- @Z\(s\t) = 1010, Z\s = 1000, t = 010@+++++-- * BitSets with two interfaces++-- ** Inside checks++prop_bii_i :: BS2I First Last -> Bool+prop_bii_i ix@(s:>i:>j) = zs == ls where+ tia = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+ zs = (id <<< tia ... S.toList) highestBII ix+ ls = [ xsBII ! ix ]++prop_bii_i_n :: BS2I First Last -> Bool+prop_bii_i_n ix@(s:>i:>j) = zs == ls where+ tia = ITbl 0 0 NonEmpty xsBII (\ _ _ -> Id 1)+ zs = (id <<< tia ... S.toList) highestBII ix+ ls = [ xsBII ! ix | popCount s > 0 ]++-- | Edges should never work as a single terminal element.++prop_bii_e :: BS2I First Last -> Bool+prop_bii_e ix@(s:>Iter i:>Iter j) = zs == ls where+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = (id <<< e ... S.toList) highestBII ix+ ls = [] :: [ (Int,Int) ]++-- | Edges extend only in cases where in @i -> j@, @i@ actually happens to+-- be a true interface.++prop_bii_ie :: BS2I First Last -> Bool+prop_bii_ie ix@(s:>i:>Iter j) = zs == ls where+ tia = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,) <<< tia % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>(Iter k :: Interface Last)) , (k,j) )+ | let t = s `clearBit` j+ , k <- activeBitsL t ]++prop_bii_ie_n :: BS2I First Last -> Bool+prop_bii_ie_n ix@(s:>i:>Iter j) = zs == ls where+ tia = ITbl 0 0 NonEmpty xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,) <<< tia % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>(Iter k :: Interface Last)) , (k,j) )+ | let t = s `clearBit` j+ , popCount t >= 2+ , k <- activeBitsL t+ , k /= getIter i+ ]++prop_bii_iee :: BS2I First Last -> Bool+prop_bii_iee ix@(s:>i:>Iter j) = L.sort zs == L.sort ls where+ tia = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,,) <<< tia % e % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>kk) , (k,l) , (l,j) )+ | let tmp = (s `clearBit` j)+ , l <- activeBitsL tmp+ , l /= getIter i+ , let t = tmp `clearBit` l+ , k <- activeBitsL t+ , let kk = Iter k+ ]++prop_bii_ieee :: BS2I First Last -> Bool+prop_bii_ieee ix@(s:>i:>Iter j) = L.sort zs == L.sort ls where+ tia = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,,,) <<< tia % e % e % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>kk) , (k,l) , (l,m) , (m,j) )+ | let tmpM = (s `clearBit` j)+ , m <- activeBitsL tmpM+ , m /= getIter i+ , let tmpL = (tmpM `clearBit` m)+ , l <- activeBitsL tmpL+ , l /= getIter i+ , let t = tmpL `clearBit` l+ , k <- activeBitsL t+ , let kk = Iter k+ ]++prop_bii_iee_n :: BS2I First Last -> Bool+prop_bii_iee_n ix@(s:>i:>Iter j) = L.sort zs == L.sort ls where+ tia = ITbl 0 0 NonEmpty xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,,) <<< tia % e % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>kk) , (k,l) , (l,j) )+ | let tmp = (s `clearBit` j)+ , l <- activeBitsL tmp+ , l /= getIter i+ , let t = tmp `clearBit` l+ , popCount t >= 2+ , k <- activeBitsL t+ , k /= getIter i+ , let kk = Iter k+ ]++prop_bii_ieee_n :: BS2I First Last -> Bool+prop_bii_ieee_n ix@(s:>i:>Iter j) = L.sort zs == L.sort ls where+ tia = ITbl 0 0 NonEmpty xsBII (\ _ _ -> Id 1)+ e = Edge (\ i j -> (i,j)) :: Edge (Int,Int)+ zs = ((,,,) <<< tia % e % e % e ... S.toList) highestBII ix+ ls = [ ( xsBII ! (t:>i:>kk) , (k,l) , (l,m) , (m,j) )+ | let tmpM = (s `clearBit` j)+ , m <- activeBitsL tmpM+ , m /= getIter i+ , let tmpL = (tmpM `clearBit` m)+ , l <- activeBitsL tmpL+ , l /= getIter i+ , let t = tmpL `clearBit` l+ , popCount t >= 2+ , k <- activeBitsL t+ , k /= getIter i+ , let kk = Iter k+ ]++-- prop_bii_ii (ix@(s:>i:>j) :: (BitSet:>Interface First:>Interface Last)) = tr zs ls $ zs == ls where+-- tia = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+-- tib = ITbl 0 0 EmptyOk xsBII (\ _ _ -> Id 1)+-- zs = ((,) <<< tia % tib ... S.toList) highestBII ix+-- ls = [ ( xsBII ! kk , xsBII ! ll )+-- | k <- VU.toList . popCntSorted $ popCount s+-- , ki <- if k==0 then [0] else activeBitsL k+-- , kj <- if | k==0 -> [0] | popCount k==1 -> [ki] | otherwise -> activeBitsL (k `clearBit` ki)+-- , let kk = (BitSet k:>Iter ki:>Iter kj)+-- , let l = s `xor` BitSet k+-- , li <- if l==0 then [0] else activeBitsL l+-- , lj <- if | l==0 -> [0] | popCount l==1 -> [li] | otherwise -> activeBitsL (l `clearBit` li)+-- , let ll = (l:>Iter li:>Iter lj)+-- ]++++-- * Helper functions++highBit = fromIntegral arbitraryBitSetMax -- should be the same as the highest bit in Index.Set.arbitrary+highestB = BitSet $ 2^(highBit+1) -1+highestBII = highestB :> Iter (highBit-1) :> Iter (highBit-1) -- assuming @highBit >= 1@++xsB :: Unboxed BitSet Int+xsB = fromList (BitSet 0) highestB [ 0 .. ]++xoB :: Unboxed (Outside BitSet) Int+xoB = fromList (O (BitSet 0)) (O highestB) [ 0 .. ]++xsBII :: Unboxed (BitSet:>Interface First:>Interface Last) Int+xsBII = fromList (BitSet 0:>Iter 0:>Iter 0) highestBII [ 0 .. ]++-- * general quickcheck stuff++options = stdArgs {maxSuccess = 1000}++customCheck = quickCheckWithResult options++return []+allProps = $forAllProperties customCheck+
+ ADP/Fusion/QuickCheck/Subword.hs view
@@ -0,0 +1,171 @@++{-# Options_GHC -O0 #-}++module ADP.Fusion.QuickCheck.Subword where++import Test.QuickCheck+import Test.QuickCheck.All+import Test.QuickCheck.Monadic+import qualified Data.Vector.Fusion.Stream as S+import Data.Vector.Fusion.Util+import Debug.Trace+import qualified Data.List as L+import qualified Data.Vector.Unboxed as VU++import Data.PrimitiveArray++import ADP.Fusion+import ADP.Fusion.QuickCheck.Common++++-- * Outside checks++-- ** two non-terminals on the r.h.s.+--+-- A_ij -> B_ik C_kj+--+-- B*_ik -> A*_ij C_kj+-- C*_kj -> B_ik A*_ij++prop_sv_OI ox@(O (Subword (i:.k))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ tic = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ zs = ((,) <<< toa % tic ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( unsafeIndex xoS (O $ subword i j)+ , unsafeIndex xsS ( subword k j) )+ | j <- [ k .. highest ] ]++prop_sv_IO ox@(O (Subword (k:.j))) = zs == ls where+ tib = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,) <<< tib % toa ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( unsafeIndex xsS ( subword i k)+ , unsafeIndex xoS (O $ subword i j) )+ | j <= highest, i <- [ 0 .. k ] ]++-- ** three non-terminals on the r.h.s. (this provides situations where two+-- syntactic terminals are on the same side)+--+-- A_ij -> B_ik C_kl D_lj+--+-- B*_ik -> A*_ij C_kl D_lj+-- C*_kl -> B_ik A*_ij D_lj+-- D*_lj -> B_ik C_kl A*_ij++prop_sv_OII ox@(O (Subword (i:.k))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ tic = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ tid = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ zs = ((,,) <<< toa % tic % tid ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( unsafeIndex xoS (O $ subword i j)+ , unsafeIndex xsS ( subword k l)+ , unsafeIndex xsS ( subword l j) )+ | j <- [ k .. highest ], l <- [ k .. j ] ]++prop_sv_IOI ox@(O (Subword (k:.l))) = zs == ls where+ tib = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ tid = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ zs = ((,,) <<< tib % toa % tid ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( unsafeIndex xsS ( subword i k)+ , unsafeIndex xoS (O $ subword i j)+ , unsafeIndex xsS ( subword l j) )+ | i <- [ 0 .. k ], j <- [ l .. highest ] ]++prop_sv_IIO ox@(O (Subword (l:.j))) = zs == ls where+ tib = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ tic = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,,) <<< tib % tic % toa ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( unsafeIndex xsS ( subword i k)+ , unsafeIndex xsS ( subword k l)+ , unsafeIndex xoS (O $ subword i j) )+ | j <= highest, i <- [ 0 .. l ], k <- [ i .. l ] ]++-- ** four non-terminals on the r.h.s. ?++-- ** five non-terminals on the r.h.s. ?++-- ** Non-terminal and terminal combinations++prop_cOc ox@(O( Subword (i:.j))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,,) <<< chr csS % toa % chr csS ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( csS VU.! (i-1)+ , unsafeIndex xoS (O $ subword (i-1) (j+1))+ , csS VU.! (j ) )+ | i > 0 && j < highest ]++prop_ccOcc ox@(O(Subword (i:.j))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,,,,) <<< chr csS % chr csS % toa % chr csS % chr csS ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( csS VU.! (i-2)+ , csS VU.! (i-1)+ , unsafeIndex xoS (O $ subword (i-2) (j+2))+ , csS VU.! (j )+ , csS VU.! (j+1) )+ | i > 1 && j < highest -1 ]++prop_cOccc ox@(O(Subword (i:.j))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,,,,) <<< chr csS % toa % chr csS % chr csS % chr csS ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( csS VU.! (i-1)+ , unsafeIndex xoS (O $ subword (i-1) (j+3))+ , csS VU.! (j )+ , csS VU.! (j+1)+ , csS VU.! (j+2) )+ | i > 0 && j < highest -2 ]++-- ** Terminals, syntactic terminals, and non-terminals++prop_cOcIc ox@(O (Subword (i:.k))) = zs == ls where+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ tic = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ zs = ((,,,,) <<< chr csS % toa % chr csS % tic % chr csS ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( csS VU.! (i-1)+ , unsafeIndex xoS (O $ subword (i-1) j )+ , csS VU.! (k )+ , unsafeIndex xsS ( subword (k+1) (j-1) )+ , csS VU.! (j-1) )+ | i > 0, j <- [ k+2 .. highest ] ]++prop_cIcOc ox@(O (Subword (k:.j))) = zs == ls where+ tib = ITbl 0 0 EmptyOk xsS (\ _ _ -> Id (1,1))+ toa = ITbl 0 0 EmptyOk xoS (\ _ _ -> Id (1,1))+ zs = ((,,,,) <<< chr csS % tib % chr csS % toa % chr csS ... S.toList) (O $ subword 0 highest) ox+ ls = [ ( csS VU.! (i )+ , unsafeIndex xsS ( subword (i+1) (k-1))+ , csS VU.! (k-1)+ , unsafeIndex xoS (O $ subword i (j+1))+ , csS VU.! (j ) )+ | j+1 <= highest, k>1, i <- [ 0 .. k-2 ] ]++-- ** Epsilonness++prop_Epsilon ox@(O (Subword (i:.j))) = zs == ls where+ zs = (id <<< Epsilon ... S.toList) (O $ subword 0 highest) ox+ ls = [ () | i==0 && j==highest ]++++highest = 2++csS :: VU.Vector (Int,Int)+csS = VU.fromList [ (i,i+1) | i <- [0 .. highest] ] -- this should be @highest -1@, we should die if we see @(highest,highest+1)@++xsS :: Unboxed Subword (Int,Int)+xsS = fromList (subword 0 0) (subword 0 highest) [ (i,j) | i <- [ 0 .. highest ] , j <- [ i .. highest ] ]++xoS :: Unboxed (Outside Subword) (Int,Int)+xoS = fromList (O $ subword 0 0) (O $ subword 0 highest) [ (i,j) | i <- [ 0 .. highest ] , j <- [ i .. highest ] ]++-- * general quickcheck stuff++options = stdArgs {maxSuccess = 10000}++customCheck = quickCheckWithResult options++return []+allProps = $forAllProperties customCheck+
− ADP/Fusion/Region.hs
@@ -1,148 +0,0 @@-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.Region where--import Data.Array.Repa.Index-import Data.Strict.Tuple-import Data.Vector.Fusion.Stream.Size-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Unboxed as VU-import Data.Strict.Maybe-import Prelude hiding (Maybe(..))--import Data.Array.Repa.Index.Subword--import ADP.Fusion.Classes--import Control.Exception (assert)-import Debug.Trace------ * Regions of unlimited size--data Region x = Region !(VU.Vector x)--instance Build (Region x)--instance- ( ValidIndex ls Subword- , VU.Unbox xs- ) => ValidIndex (ls :!: Region xs) Subword where- validIndex (ls :!: Region xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<=VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: Region xs) ix = let (a:!:b:!:c) = getParserRange ls ix in (a:!:b:!:c)- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: Region x) Subword where- data Elm (ls :!: Region x) Subword = ElmRegion !(Elm ls Subword) !(VU.Vector x) !Subword- type Arg (ls :!: Region x) = Arg ls :. VU.Vector x- getArg !(ElmRegion ls xs _) = getArg ls :. xs- getIdx !(ElmRegion _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:Region x) Subword where- mkStream !(ls:!:Region xs) Outer !ij@(Subword (i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s in ElmRegion s (VU.unsafeSlice l (j-l) xs) (subword l j))- $ mkStream ls (Inner Check Nothing) ij- mkStream !(ls:!:Region xs) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (k:.l)) = getIdx s- l' = case szd of Nothing -> l- Just z -> max l (j-z)- in return (s :!: l :!: l')- step !(s :!: k :!: l)- | l > j = return S.Done- | otherwise = return $ S.Yield (ElmRegion s (VU.unsafeSlice k (l-k) xs) (subword k l)) (s :!: k :!: l+1)- {-# INLINE mkStream #-}--region :: VU.Vector x -> Region x-region = Region-{-# INLINE region #-}------ * Regions of unlimited size--data SRegion x = SRegion !Int !Int !(VU.Vector x)--instance Build (SRegion x)--instance- ( ValidIndex ls Subword- , VU.Unbox xs- ) => ValidIndex (ls :!: SRegion xs) Subword where- validIndex (ls :!: SRegion lb ub xs) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- i>=a && j<=VU.length xs -c && i+b<=j && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: SRegion lb ub xs) ix = let (a:!:b:!:c) = getParserRange ls ix in (a:!:b+lb:!:max 0 (c-lb))- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: SRegion x) Subword where- data Elm (ls :!: SRegion x) Subword = ElmSRegion !(Elm ls Subword) !(VU.Vector x) !Subword- type Arg (ls :!: SRegion x) = Arg ls :. VU.Vector x- getArg !(ElmSRegion ls xs _) = getArg ls :. xs- getIdx !(ElmSRegion _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}---- |------ TODO Check that all inner / outer sized calculations are correct------ NOTE mkStream/Inner gives a size hint of Nothing, as in purely inner cases,--- min/max boundaries are determined solely from the running rightmost index--- from the next inner component.------ NOTE the filter in mkStream/Outer is still necessary to check for--- lowerbound>0 conditions. We /could/ send the lower bound down with another--- size hint, but this only makes sense if you have use cases, where the lower--- bound is a lot higher than "0". Otherwise the current code is simpler.------ TODO use drop instead of filter: still condition, but large lower bounds are captured------ TODO remove mkStream/Outer : filter and test if one condition less gives--- much better runtimes.--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:SRegion x) Subword where- mkStream !(ls:!:SRegion lb ub xs) Outer !ij@(Subword (i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s in assert (l>=0 && j-i>=0) $ ElmSRegion s (VU.slice l (j-l) xs) (subword l j))- $ S.filter (\s -> let (Subword (k:.l)) = getIdx s in (j-l >= lb && j-l <= ub))- $ mkStream ls (Inner Check (Just ub)) ij- mkStream !(ls:!:SRegion lb ub xs) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (k:.l)) = getIdx s- l' = case szd of Nothing -> l+lb- Just z -> max (l+lb) (j-z)- in return (s :!: l :!: l')- step !(s :!: k :!: l)- | l>j || l-k>ub = return S.Done- | otherwise = return $ assert (k>=0 && l-k>=0) $ S.Yield (ElmSRegion s (VU.slice k (l-k) xs) (subword k l)) (s :!: k :!: l+1)- {-# INLINE mkStream #-}---- |-sregion :: Int -> Int -> VU.Vector x -> SRegion x-sregion = SRegion-{-# INLINE sregion #-}-
+ ADP/Fusion/SynVar.hs view
@@ -0,0 +1,17 @@++-- | This module re-exports all table types.++module ADP.Fusion.SynVar+ ( module ADP.Fusion.SynVar.Array+ , module ADP.Fusion.SynVar.Axiom+ , module ADP.Fusion.SynVar.Backtrack+ , module ADP.Fusion.SynVar.Fill+ , module ADP.Fusion.SynVar.Recursive+ ) where++import ADP.Fusion.SynVar.Array+import ADP.Fusion.SynVar.Axiom+import ADP.Fusion.SynVar.Backtrack+import ADP.Fusion.SynVar.Fill+import ADP.Fusion.SynVar.Recursive+
+ ADP/Fusion/SynVar/Array.hs view
@@ -0,0 +1,292 @@++module ADP.Fusion.SynVar.Array+ ( module ADP.Fusion.SynVar.Array.Type+ , module ADP.Fusion.SynVar.Array.Point+ , module ADP.Fusion.SynVar.Array.Set+ , module ADP.Fusion.SynVar.Array.Subword+ ) where++import ADP.Fusion.SynVar.Array.Point+import ADP.Fusion.SynVar.Array.Set+import ADP.Fusion.SynVar.Array.Subword+import ADP.Fusion.SynVar.Array.Type++{-++{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE RankNTypes #-}++{-# LANGUAGE MagicHash #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternGuards #-}++-- | Tables in ADPfusion memoize results of parses. In the forward phase, table+-- cells are filled by a table-filling method from @Data.PrimitiveArray@. In+-- the backtracking phase, grammar rules are associated with tables to provide+-- efficient backtracking.+--+-- TODO multi-dim tables with 'OnlyZero' need a static check!+--+-- TODO PointL , PointR need sanity checks for boundaries+--+-- TODO the sanity checks are acutally a VERY BIG TODO since currently we do+-- not protect against stupidity at all!+--+-- TODO have boxed tables for top-down parsing.+--+-- TODO combine forward and backward phases to simplify the external interface+-- to the programmer.+--+-- TODO include the notion of @interfaces@ into tables. With Outside+-- grammars coming up now, we need this.++module ADP.Fusion.Table.Array+-- ( MTbl (..)+-- , BtTbl (..)+ ( ITbl (..)+-- , Backtrack (..)+ , ToBT (..)+ ) where++import Control.Exception(assert)+import Control.Monad.Primitive (PrimMonad)+import Data.Vector.Fusion.Stream.Size (Size(Unknown))+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Unboxed as VU+import GHC.Exts+import Data.Bits++import Data.PrimitiveArray -- (Z(..), (:.)(..), Subword(..), subword, PointL(..), pointL, PointR(..), pointR,topmostIndex, Outside(..))+import qualified Data.PrimitiveArray as PA++import ADP.Fusion.Classes+import ADP.Fusion.Multi.Classes+import ADP.Fusion.Table.Axiom+import ADP.Fusion.Table.Backtrack+import ADP.Fusion.Table.Indices++import Debug.Trace++++-- ** Mutable fill-phase tables.++-- | The backtracking version.++++++-- TODO empty table @ms@ stuff++instance+ ( Monad m+ , Element ls (BS2I First Last)+ , PA.PrimArrayOps arr (BS2I First Last) x+ , MkStream m ls (BS2I First Last)+ ) => MkStream m (ls :!: ITbl m arr (BS2I First Last) x) (BS2I First Last) where+ -- outermost case. Grab inner indices, calculate the remainder of the+ -- set, return value+ mkStream (ls :!: ITbl c t _) Static s (BitSet b:>Interface i:>Interface j)+ = S.map (\z -> let (BitSet zb:>_:>Interface zj) = getIdx z -- the bitset we get from the guy before us+ here = (BitSet (b `xor` zb .|. zj):>Interface zj:>Interface j) -- everything missing, set common interface+ in ElmITbl (t PA.! here) here z+ )+ $ mkStream ls (Variable Check Nothing) s (BitSet (clearBit b j):>Interface i:>Interface j)+ -- generate all possible subsets of the index. With A @Variable+ -- _ Nothing@, there is something to the right that will fill up the set.+ mkStream (ls :!: ITbl c t _) (Variable Check Nothing) full (BitSet b:>Interface i:>Interface j)+ = S.flatten mk step Unknown+ $ mkStream ls (Variable Check Nothing) full (BitSet b:>Interface i:>Interface j)+ where mk z = return (z,Just $ BitSet 0:>Interface 0:>Interface 0)+ step (_,Nothing) = return $ S.Done+ step (z,Just s ) = return $ S.Yield (ElmITbl (t PA.! s) s z) (z,succSet full s)+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ -- generate only those indices with the requested number of set bits+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls (BS2I First Last)+ , PA.PrimArrayOps arr (BS2I First Last) x+ , MkStream mB ls (BS2I First Last)+ ) => MkStream mB (ls :!: BT (ITbl mF arr (BS2I First Last) x) mF mB r) (BS2I First Last) where+ mkStream (ls :!: BtITbl c arr bt) Static full (BitSet b:>Interface i:>Interface j)+ = S.map (\z -> let (BitSet zb:>Interface zi:>Interface zj) = getIdx z+ here = BitSet (clearBit b j):>Interface i:>Interface zj+ d = arr PA.! here+ in ElmBtITbl' d (bt full here) here z)+ $ mkStream ls (Variable Check Nothing) full (BitSet (clearBit b j):>Interface i:>Interface (-1))+ mkStream (ls :!: BtITbl c arr bt) (Variable Check Nothing) full (BitSet b:>Interface i:>Interface j)+ = S.flatten mk step Unknown+ $ mkStream ls (Variable Check Nothing) full (BitSet b:>Interface i:>Interface j)+ where mk z = return (z,Just $ BitSet 0:>Interface 0:>Interface 0)+ step (_,Nothing) = return $ S.Done+ step (z,Just s ) = return $ S.Yield (ElmBtITbl' (arr PA.! s) (bt full s) s z) (z,succSet full s)+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , PA.PrimArrayOps arr (Outside PointL) x+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: ITbl m arr (Outside PointL) x) (Outside PointL) where+ mkStream (ls :!: ITbl c t _) Static lu (O (PointL (i:.j)))+ = let ms = minSize c in seq ms $ seq t $+ S.mapM (\s -> let O (PointL (h:.k)) = getIdx s+ in return $ ElmITbl (t PA.! O (pointL k j)) (O $ pointL k j) s)+ $ mkStream ls (Variable Check Nothing) lu (O . pointL i $ j + ms)+-- mkStream _ _ _ _ = error "mkStream / ITbl / Outside PointL not implemented"+ {-# INLINE mkStream #-}++instance+ ( Monad mB+ , Element ls (Outside PointL)+ , PA.PrimArrayOps arr (Outside PointL) x+ , MkStream mB ls (Outside PointL)+ ) => MkStream mB (ls :!: BT (ITbl mF arr (Outside PointL) x) mF mB r) (Outside PointL) where+ mkStream (ls :!: BtITbl c arr bt) Static lu (O (PointL (i:.j)))+ = let ms = minSize c in ms `seq`+ S.map (\s -> let O (PointL (h:.k)) = getIdx s+ ix = O $ pointL k j+ d = arr PA.! ix+ in ElmBtITbl' d (bt lu ix) ix s)+ $ mkStream ls (Variable Check Nothing) lu (O . pointL i $ j + ms)+-- mkStream _ _ _ _ = error "mkStream / BT ITbl / Outside PointL not implemented"+ {-# INLINE mkStream #-}++-- | TODO As soon as we don't do static checking on @EmptyOk/NonEmpty@+-- anymore, this works! If we check @c@, we immediately have fusion+-- breaking down!++{-+instance+ ( Monad m+ , Element ls Subword+ , PA.PrimArrayOps arr Subword x+ , MkStream m ls Subword+ ) => MkStream m (ls :!: ITbl m arr Subword x) Subword where+ mkStream (ls :!: ITbl c t _) Static lu (Subword (i:.j))+ = let ms = minSize c in ms `seq`+ S.mapM (\s -> let Subword (_:.l) = getIdx s+ in return $ ElmITbl (t PA.! subword l j) (subword l j) s)+ $ mkStream ls (Variable Check Nothing) lu (subword i $ j - ms) -- - minSize c)+ mkStream (ls :!: ITbl c t _) (Variable _ Nothing) lu (Subword (i:.j))+ = let ms = minSize c+ {- data PBI a = PBI !a !(Int#)+ mk s = let (Subword (_:.l)) = getIdx s ; !(I# jlm) = j-l-ms in return $ PBI s jlm+ step !(PBI s z) | 1# <- z >=# 0# = do let (Subword (_:.k)) = getIdx s+ return $ S.Yield (ElmITbl (t PA.! subword k (j-(I# z))) (subword k $ j-(I# z)) s) (PBI s (z -# 1#))+ | otherwise = return S.Done+ -}+ {-+ mk s = let (Subword (_:.l)) = getIdx s in return (s :. j - l - ms)+ step (s:.z) | 1# <- z' >=# 0# = do let (Subword (_:.k)) = getIdx s+ return $ S.Yield (ElmITbl (t PA.! subword k (j-z)) (subword k $ j-z) s) (s:.z-1)+ | otherwise = return S.Done+ where !(I# z') = z+ -}+ mk s = let (Subword (_:.l)) = getIdx s in return (s :. j - l - ms)+ step (s:.z) | z>=0 = do let (Subword (_:.k)) = getIdx s+ return $ S.Yield (ElmITbl (t PA.! subword k (j-z)) (subword k $ j-z) s) (s:.z-1)+ | otherwise = return S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (subword i j)+ {-# INLINE mkStream #-}+-}++{-+instance+ ( Monad mB+ , Element ls Subword+ , MkStream mB ls Subword+ , PA.PrimArrayOps arr Subword x+ ) => MkStream mB (ls :!: BT (ITbl mF arr Subword x) mF mB r) Subword where+ mkStream (ls :!: BtITbl c arr bt) Static lu (Subword (i:.j))+ = let ms = minSize c in ms `seq`+ S.map (\s -> let (Subword (_:.l)) = getIdx s+ ix = subword l j+ d = arr PA.! ix+ in ElmBtITbl' d (bt lu ix) ix s)+ $ mkStream ls (Variable Check Nothing) lu (subword i $ j - ms)+ mkStream (ls :!: BtITbl c arr bt) (Variable _ Nothing) lu (Subword (i:.j))+ = let ms = minSize c+ mk s = let (Subword (_:.l)) = getIdx s in return (s:.j-l-ms)+ step (s:.z)+ | z>=0 = do let (Subword (_:.k)) = getIdx s+ ix = subword k (j-z)+ d = arr PA.! ix+ return $ S.Yield (ElmBtITbl' d (bt lu ix) ix s) (s:.z-1)+ | otherwise = return $ S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (subword i j)+ {-# INLINE mkStream #-}+-}++{-+instance+ ( Monad m+ , Element ls (Outside Subword)+ , PA.PrimArrayOps arr Subword x+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: ITbl m arr Subword x) (Outside Subword) where+ mkStream (ls :!: ITbl c t _) Static lu (O (Subword (i:.j)))+ = let ms = minSize c in ms `seq`+ S.mapM (\s -> let (O (Subword (_:.l))) = getIdx s+ in return $ ElmITbl (t PA.! (subword l j)) (O $ subword l j) s)+ $ mkStream ls (Variable Check Nothing) lu (O $ subword i $ j - ms) -- - minSize c)+ mkStream (ls :!: ITbl c t _) (Variable _ Nothing) lu (O (Subword (i:.j)))+ = let ms = minSize c+ mk s = let (O( Subword (_:.l))) = getIdx s in return (s :. j - l - ms)+ step (s:.z) | z>=0 = do let (O (Subword (_:.k))) = getIdx s+ return $ S.Yield (ElmITbl (t PA.! (subword k (j-z))) (O . subword k $ j-z) s) (s:.z-1)+ | otherwise = return S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (O $ subword i j)+ {-# INLINE mkStream #-}+-}++{-+instance+ ( Monad m+ , Element ls (Outside Subword)+ , PA.PrimArrayOps arr (Outside Subword) x+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: ITbl m arr (Outside Subword) x) (Outside Subword) where+ mkStream (ls :!: ITbl c t _) Static lu (O (Subword (i:.j)))+ = let ms = minSize c in ms `seq`+ S.mapM (\s -> let (O (Subword (_:.l))) = getIdx s+ in return $ ElmITbl (t PA.! (O $ subword l j)) (O $ subword l j) s)+ $ mkStream ls (Variable Check Nothing) lu (O $ subword i $ j - ms) -- - minSize c)+ mkStream (ls :!: ITbl c t _) (Variable _ Nothing) lu (O (Subword (i:.j)))+ = let ms = minSize c+ mk s = let (O( Subword (_:.l))) = getIdx s in return (s :. j - l - ms)+ step (s:.z) | z>=0 = do let (O (Subword (_:.k))) = getIdx s+ return $ S.Yield (ElmITbl (t PA.! (O $ subword k (j-z))) (O . subword k $ j-z) s) (s:.z-1)+ | otherwise = return S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (O $ subword i j)+ {-# INLINE mkStream #-}+-}+++++-- * Axiom for backtracking++-}+
+ ADP/Fusion/SynVar/Array/Point.hs view
@@ -0,0 +1,79 @@++module ADP.Fusion.SynVar.Array.Point where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic+import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util (delay_inline)+import Debug.Trace+import Prelude hiding (map,mapM)+--import qualified Data.Vector.Fusion.Stream.Monadic as S++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Array.Type+import ADP.Fusion.SynVar.Backtrack++++instance+ ( Monad m+ , Element ls PointL+ , PrimArrayOps arr PointL x+ , MkStream m ls PointL+ ) => MkStream m (ls :!: ITbl m arr PointL x) PointL where+ mkStream (ls :!: ITbl _ _ c t _) (IStatic d) u j@(PointL pj)+ = let ms = minSize c in ms `seq`+ map (ElmITbl (t!j) j (PointL 0))+ $ mkStream ls (IVariable d) u (PointL $ pj - ms)+ -- We can't really make sure that this is the only time we access the+ -- ITbl, so the user should know what they are doing.+ mkStream (ls :!: ITbl _ _ c t _) (IVariable d) u j@(PointL pj)+ = flatten mk step Unknown $ mkStream ls (IVariable d) u (delay_inline PointL $! pj - ms)+ where mk s = let PointL k = getIdx s in return (s :. k)+ step (s :. k)+ | k+ms>pj = return $ Done+ | otherwise = return $ Yield (ElmITbl (t!PointL k) (PointL k) (PointL 0) s) (s :. k+1)+ !ms = minSize c+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls PointL+ , PrimArrayOps arr PointL x+ , MkStream mB ls PointL+ ) => MkStream mB (ls :!: Backtrack (ITbl mF arr PointL x) mF mB r) PointL where+ mkStream (ls :!: BtITbl c t bt) (IStatic d) u j@(PointL pj)+ = let ms = minSize c in ms `seq`+ mapM (\s -> bt u j >>= \bb -> return $ ElmBtITbl (t!j) (bb {-bt u j-}) j (PointL 0) s)+ $ mkStream ls (IVariable d) u (PointL $ pj - ms)+ {-# INLINE mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , PrimArrayOps arr (Outside PointL) x+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: ITbl m arr (Outside PointL) x) (Outside PointL) where+ mkStream (ls :!: ITbl _ _ c t _) (OStatic d) u (O (PointL pj))+ = let ms = minSize c in ms `seq`+ map (\z -> let o = getOmx z+ in ElmITbl (t ! o) o o z)+ $ mkStream ls (OFirstLeft d) u (O $ PointL $ pj - ms)+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls (Outside PointL)+ , PrimArrayOps arr (Outside PointL) x+ , MkStream mB ls (Outside PointL)+ ) => MkStream mB (ls :!: Backtrack (ITbl mF arr (Outside PointL) x) mF mB r) (Outside PointL) where+ mkStream (ls :!: BtITbl c t bt) (OStatic d) u (O (PointL pj))+ = let ms = minSize c in ms `seq`+ mapM (\s -> let o = getOmx s in bt u o >>= \bb -> return $ ElmBtITbl (t!o) (bb{-bt u o-}) o o s)+ $ mkStream ls (OFirstLeft d) u (O $ PointL $ pj - ms)+ {-# INLINE mkStream #-}+
+ ADP/Fusion/SynVar/Array/Set.hs view
@@ -0,0 +1,164 @@++module ADP.Fusion.SynVar.Array.Set where++import Data.Bits+import Data.Bits.Extras+import Data.Bits.Ordered+import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic+import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util (delay_inline)+import Debug.Trace+import Prelude hiding (map)+import Control.Applicative ((<$>))++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Array.Type+import ADP.Fusion.SynVar.Backtrack++++-- * Bitsets without any interfaces.++-- NOTE that we have to give as the filled index elements all bits that are+-- set in total, not just those we set right here. Otherwise the next+-- element will try a wrong set of indices.+--+-- NOTE even in the @IStatic@ case, we need to use flatten. If a node+-- requested a reserved bit, we need to free each reserved bit at least+-- once.++instance+ ( Monad m+ , Element ls BitSet+ , PrimArrayOps arr BitSet x+ , MkStream m ls BitSet+ ) => MkStream m (ls :!: ITbl m arr BitSet x) BitSet where+ mkStream (ls :!: ITbl _ _ c t _) (IStatic rp) u s+ = flatten mk step Unknown $ mkStream ls (delay_inline IVariable $ rp - csize) u s+ where !csize | c==EmptyOk = 0+ | c==NonEmpty = 1+ mk z+ | cm < csize = return (z , mask , Nothing)+ | otherwise = return (z , mask , Just k )+ where k = (BitSet $ 2^cm-1)+ cm = popCount mask - rp+ mask = s `xor` (getIdx z)+ step (_,_,Nothing) = return $ Done+ step (z,mask,Just k)+ | pk > popCount s - rp = return $ Done+ | otherwise = let kk = popShiftL mask k+ in return $ Yield (ElmITbl (t!kk) (kk .|. getIdx z) (BitSet 0) z) (z,mask,setSucc (BitSet 0) (2^pk -1) k)+ where pk = popCount k+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ mkStream (ls :!: ITbl _ _ c t _) (IVariable rp) u s+ = flatten mk step Unknown $ mkStream ls (IVariable rp) u s+ where mk z+ | c==EmptyOk = return (z , mask , cm , Just 0 )+ | cm == 0 = return (z , mask , cm , Nothing) -- we are non-empty but have no free bits left+ | c==NonEmpty = return (z , mask , cm , Just 1 )+ where mask = s `xor` (getIdx z) -- bits that are still free+ cm = popCount mask+ step (z,mask,cm,Nothing) = return $ Done+ step (z,mask,cm,Just k )+ | popCount s < popCount (kk .|. getIdx z) + rp = return $ Done+ | otherwise = return $ Yield (ElmITbl (t!kk) (kk .|. getIdx z) (BitSet 0) z) (z,mask,cm,setSucc (BitSet 0) (2^cm -1) k)+ where kk = popShiftL mask k+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++++-- * Bitsets with two interfaces.+--+-- NOTE These are annoying to get right, if you also want to have good+-- performance.++instance+ ( Monad m+ , Element ls (BS2I First Last)+ , PrimArrayOps arr (BS2I First Last) x+ , MkStream m ls (BS2I First Last)+ , Show x+ ) => MkStream m (ls :!: ITbl m arr (BS2I First Last) x) (BS2I First Last) where+ mkStream (ls :!: ITbl _ _ c t _) (IStatic rp) u sij@(s:>i:>j@(Iter jj))+ = flatten mk step Unknown $ mkStream ls (delay_inline IVariable rpn) u (delay_inline id $ tij)+ -- calculate new index. if we don't know the right-most interface+ -- anymore, than someone has taken it already. Also, if this+ -- synvar may be empty, do not modify the index. Otherwise, if+ -- @j@ is still known, remove it from the index set.+ where tij | jj == -1 = sij+ | c == EmptyOk = sij+ | c == NonEmpty = s `clearBit` jj :> i :> Iter (-1)+ -- In case we do not know the rightmost interface, we instead+ -- increase the number of reserved bits.+ rpn | jj == -1+ && c == NonEmpty = rp+1+ | otherwise = rp+ nec | c == NonEmpty = 1+ | c == EmptyOk = 0+ mk z+ -- in case we have a non-empty synvar but not enough bits, we+ -- shall have nothing. We only need one extra mask bit, because+ -- @j@ is still known.+ | popCount mask < 1 && c == NonEmpty && j >= 0 = return $ Naught+ -- If @j@ is not known we need two bits to be non-empty.+ | popCount mask < 2 && c == NonEmpty && j < 0 = return $ Naught+ -- Not enough bits to reserve.+ | popCount mask - rp < 0 = return $ Naught+ -- @j@ is still known, just create the sets ending in @j@+ | j >= 0 = return $ This (z,mask)+ -- @j@ is not known, we have a lot of work to do. Create the+ -- required @bits@ and prepare a @mask@ which will set the+ -- correct bits.+ | j < 0 = return $ That (z,mask,Just bits,maybeLsb bits)+ -- we somehow ended up with an improper state+ | otherwise = error $ show (sij,mask,bits)+ where (zs:>_:>Iter zk) = getIdx z+ mask = s `xor` zs+ bits = BitSet $ 2 ^ (popCount mask - rp - nec) - 1+ step Naught = return $ Done+ -- In case @j@ is known, we calculate the bits @msk@ that are not+ -- filled yet. We grab the previous right interface @zk@ and use+ -- it as the new left interface. We also use @j@ as the right+ -- interface. @ix@ holds everything that is now covered, withe+ -- the interface @i@ and @j@.+ step (This (z,mask)) = return $ Yield (ElmITbl (t!(msk:>k:>j)) ix undefbs2i z) Naught+ where (zs:>_:>zk) = getIdx z+ k = Iter $ getIter zk+ ix = (zs .|. msk) :> i :> j+ msk = if popCount mask == 0 then mask else mask `setBit` getIter k `setBit` jj+ -- whenever there is nothing more to do in the variable case.+ step (That (z,mask,Nothing,_)) = return $ Done+ -- We need to permute our population a bit. Once done, we grab+ -- the lowest significant bit.+ step (That (z,mask,Just bits,Nothing)) = return $ Skip (That (z,mask,nbts, maybeLsb =<< nbts))+ where nbts = popPermutation (popCount mask) bits+ -- The variable case.+ step (That (z,mask,Just bits,Just y))+ -- we do not have enough bits to be non-empty.+ | popCount bb < 2 && c == NonEmpty+ -- our two interfaces are the same, but we are non-empty in+ -- which case this shouldn't happen.+ || getIter kk == getIter yy && c == NonEmpty+ -- our pop-count plus reserved count doesn't match up with the+ -- mask. We skip this as well.+ || popCount bb + rp /= popCount mask = return $ Skip (That (z,mask,Just bits, maybeNextActive y bits))+ -- finally, we can create the index for the current stuff+ -- @bb:>kk:>yy@ and prepare the full index, going from @i@ to+ -- @yy@, because someone grabbed @j@ already. Must have been+ -- an @Edge@ or s.th. similar.+ | otherwise = return $ Yield (ElmITbl (t!(bb:>kk:>yy)) ((zs .|. bb):>i:>yy) undefbs2i z)+ (That (z,mask,Just bits, maybeNextActive y bits))+ where (zs:>_:>zk) = getIdx z+ kk = Iter $ getIter zk+ yy = Iter . lsb $ popShiftL mask (bit y)+ bb = popShiftL mask bits `setBit` getIter kk `setBit` getIter yy+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}+
+ ADP/Fusion/SynVar/Array/Subword.hs view
@@ -0,0 +1,174 @@++module ADP.Fusion.SynVar.Array.Subword where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util (delay_inline)+import Data.Vector.Fusion.Stream.Monadic+import Debug.Trace+import Prelude hiding (map,mapM)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Array.Type+import ADP.Fusion.SynVar.Backtrack+++++-- TODO delay inline @(subword i $ j - minSize c)@ or face fusion-breakage.+-- Can we just have @Inline [0] subword@ to fix this?++instance+ ( Monad m+ , Element ls Subword+ , PrimArrayOps arr Subword x+ , MkStream m ls Subword+ ) => MkStream m (ls :!: ITbl m arr Subword x) Subword where+ mkStream (ls :!: ITbl _ _ c t _) (IStatic ()) hh (Subword (i:.j))+ = map (\s -> let (Subword (_:.l)) = getIdx s+ in ElmITbl (t ! subword l j) (subword l j) (subword 0 0) s)+ $ mkStream ls (IVariable ()) hh (delay_inline Subword (i:.j - minSize c))+ mkStream (ls :!: ITbl _ _ c t _) (IVariable ()) hh (Subword (i:.j))+ = flatten mk step Unknown $ mkStream ls (IVariable ()) hh (delay_inline Subword (i:.j - minSize c))+ where mk s = let Subword (_:.l) = getIdx s in return (s :. j - l - minSize c)+ step (s:.z) | z >= 0 = do let Subword (_:.k) = getIdx s+ l = j - z+ kl = subword k l+ return $ Yield (ElmITbl (t ! kl) kl (subword 0 0) s) (s:. z-1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls Subword+ , MkStream mB ls Subword+ , PrimArrayOps arr Subword x+ ) => MkStream mB (ls :!: Backtrack (ITbl mF arr Subword x) mF mB r) Subword where+ mkStream (ls :!: BtITbl c t bt) (IStatic ()) hh ij@(Subword (i:.j))+ = mapM (\s -> let Subword (_:.l) = getIdx s+ lj = subword l j+ in bt hh lj >>= \ ~bb -> return $ ElmBtITbl (t ! lj) (bb {-bt hh lj-}) lj (subword 0 0) s)+ $ mkStream ls (IVariable ()) hh (delay_inline Subword (i:.j - minSize c))+ mkStream (ls :!: BtITbl c t bt) (IVariable ()) hh ij@(Subword (i:.j))+ = flatten mk step Unknown $ mkStream ls (IVariable ()) hh (delay_inline Subword (i:.j - minSize c))+ where mk s = let Subword (_:.l) = getIdx s in return (s :. j - l - minSize c)+ step (s:.z) | z >= 0 = do let Subword (_:.k) = getIdx s+ l = j - z+ kl = subword k l+ bt hh kl >>= \ ~bb -> return $ Yield (ElmBtITbl (t ! kl) (bb {-bt hh kl-}) kl (subword 0 0) s) (s:.z-1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}+++instance+ ( Monad m+ , Element ls (Outside Subword)+ , PrimArrayOps arr (Outside Subword) x+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: ITbl m arr (Outside Subword) x) (Outside Subword) where+ -- TODO what about @c / minSize@+ mkStream (ls :!: ITbl _ _ c t _) (OStatic (di:.dj)) u ij@(O (Subword (i:.j)))+ = map (\s -> let O (Subword (k:._)) = getOmx s+ kj = O $ Subword (k:.j+dj)+ in ElmITbl (t ! kj) (O $ Subword (i:.j+dj)) kj s) -- @ij@ or s.th. else shouldn't matter?+ $ mkStream ls (OFirstLeft (di:.dj)) u ij+ mkStream (ls :!: ITbl _ _ c t _) (ORightOf (di:.dj)) u@(O (Subword (_:.h))) ij@(O (Subword (i:.j)))+ = flatten mk step Unknown $ mkStream ls (OFirstLeft (di:.dj)) u ij+ where mk s = return (s:.j+dj)+ step (s:.l) | l <= h = do let (O (Subword (k:._))) = getIdx s+ kl = O $ Subword (k:.l)+ return $ Yield (ElmITbl (t ! kl) (O (Subword (j+dj:.j+dj))) kl s) (s:.l+1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ mkStream (ls :!: ITbl _ _ c t _) (OFirstLeft d) u ij = error "Array/Outside Subword : OFirstLeft : should never be reached!"+ mkStream (ls :!: ITbl _ _ c t _) (OLeftOf d) u ij = error "Array/Outside Subword : OLeftOf : should never be reached!"+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , Element ls (Outside Subword)+ , PrimArrayOps arr Subword x+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: ITbl m arr Subword x) (Outside Subword) where+ -- TODO what about @c / minSize@+ mkStream (ls :!: ITbl _ _ c t _) (OStatic (di:.dj)) u ij@(O (Subword (i:.j)))+ = map (\s -> let O (Subword (_:.k)) = getIdx s+ o@(O (Subword (_:.l))) = getOmx s+ kl = Subword (k-dj:.l-dj)+ in ElmITbl (t ! kl) (O (Subword (k:.l))) o s)+ $ mkStream ls (ORightOf (di:.dj)) u ij+ mkStream (ls :!: ITbl _ _ c t _) (ORightOf d) u@(O (Subword (_:.h))) ij@(O (Subword (i:.j)))+ = flatten mk step Unknown $ mkStream ls (ORightOf d) u ij+ where mk s = let O (Subword (_:.l)) = getIdx s+ in return (s :.l:.l + minSize c)+ step (s:.k:.l)+ | let O (Subword (_:.o)) = getOmx s+ , l <= o = do let kl = Subword (k:.l)+ return $ Yield (ElmITbl (t ! kl) (O kl) (getOmx s) s) (s:.k:.l+1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ mkStream (ls :!: ITbl _ _ c t _) (OFirstLeft (di:.dj)) u ij@(O (Subword (i:.j)))+ = map (\s -> let O (Subword (l:._)) = getOmx s+ O (Subword (_:.k)) = getIdx s+ kl = Subword (k:.i-di)+ in ElmITbl (t ! kl) (O kl) (getOmx s) s)+ $ mkStream ls (OLeftOf (di:.dj)) u ij+ mkStream (ls :!: ITbl _ _ c t _) (OLeftOf d) u ij@(O (Subword (i:.j)))+ = flatten mk step Unknown $ mkStream ls (OLeftOf d) u ij+ where mk s = let O (Subword (_:.l)) = getIdx s in return (s:.l)+ step (s:.l) | l <= i = do let O (Subword (_:.k)) = getIdx s+ kl = Subword (k:.l)+ return $ Yield (ElmITbl (t ! kl) (O kl) (getOmx s) s) (s:.l+1)+ | otherwise = return $ Done+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Complement Subword)+ , PrimArrayOps arr Subword x+ , MkStream m ls (Complement Subword)+ ) => MkStream m (ls :!: ITbl m arr Subword x) (Complement Subword) where+ mkStream (ls :!: ITbl _ _ c t _) Complemented u ij+ = map (\s -> let (C ix) = getIdx s+ in ElmITbl (t ! ix) (C ix) (getOmx s) s)+ $ mkStream ls Complemented u ij+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Complement Subword)+ , PrimArrayOps arr (Outside Subword) x+ , MkStream m ls (Complement Subword)+ ) => MkStream m (ls :!: ITbl m arr (Outside Subword) x) (Complement Subword) where+ mkStream (ls :!: ITbl _ _ c t _) Complemented u ij+ = map (\s -> let (C ox) = getOmx s -- TODO shouldn't this be @getIdx@ as well? on the count of everything being terminals in Complement?+ in ElmITbl (t ! (O ox)) (getIdx s) (C ox) s)+ $ mkStream ls Complemented u ij+ {-# Inline mkStream #-}++++instance ModifyConstraint (ITbl m arr Subword x) where+ toNonEmpty (ITbl b l _ arr f) = ITbl b l NonEmpty arr f+ toEmpty (ITbl b l _ arr f) = ITbl b l EmptyOk arr f+ {-# Inline toNonEmpty #-}+ {-# Inline toEmpty #-}++instance ModifyConstraint (Backtrack (ITbl mF arr Subword x) mF mB r) where+ toNonEmpty (BtITbl _ arr bt) = BtITbl NonEmpty arr bt+ toEmpty (BtITbl _ arr bt) = BtITbl EmptyOk arr bt+ {-# Inline toNonEmpty #-}+ {-# Inline toEmpty #-}+
+ ADP/Fusion/SynVar/Array/Type.hs view
@@ -0,0 +1,144 @@++module ADP.Fusion.SynVar.Array.Type where++import Data.Strict.Tuple hiding (uncurry,snd)+import Data.Vector.Fusion.Stream.Monadic (map,Stream,head,mapM)+import Debug.Trace+import Prelude hiding (map,head,mapM)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Backtrack+import ADP.Fusion.SynVar.Axiom+import ADP.Fusion.SynVar.Indices++++-- | Immutable table.++data ITbl m arr i x where+ ITbl :: { iTblBigOrder :: !Int+ , iTblLittleOrder :: !Int+ , iTblConstraint :: !(TblConstraint i)+ , iTblArray :: !(arr i x)+ , iTblFun :: !(i -> i -> m x)+ } -> ITbl m arr i x++instance Build (ITbl m arr i x)++instance GenBacktrackTable (ITbl mF arr i x) mF mB r where+ data Backtrack (ITbl mF arr i x) mF mB r = BtITbl !(TblConstraint i) !(arr i x) (i -> i -> mB [r])+ type BacktrackIndex (ITbl mF arr i x) = i+ toBacktrack (ITbl _ _ c arr _) _ bt = BtITbl c arr bt+ {-# Inline toBacktrack #-}++instance+ ( Monad m+ , PrimArrayOps arr i x+ , IndexStream i+ ) => Axiom (ITbl m arr i x) where+ type AxiomStream (ITbl m arr i x) = m x+ axiom (ITbl _ _ c arr _) = do+ k <- (head . uncurry streamDown) $ bounds arr+ return $ arr ! k+ {-# Inline axiom #-}++instance+ ( Monad mB+ , PrimArrayOps arr i x+ , IndexStream i+ ) => Axiom (Backtrack (ITbl mF arr i x) mF mB r) where+ type AxiomStream (Backtrack (ITbl mF arr i x) mF mB r) = mB [r]+ axiom (BtITbl c arr bt) = do+ h <- (head . uncurry streamDown) $ bounds arr+ bt (snd $ bounds arr) h+ {-# Inline axiom #-}++instance Element ls i => Element (ls :!: ITbl m arr j x) i where+ data Elm (ls :!: ITbl m arr j x) i = ElmITbl !x !i !i !(Elm ls i)+ type Arg (ls :!: ITbl m arr j x) = Arg ls :. x+ getArg (ElmITbl x _ _ ls) = getArg ls :. x+ getIdx (ElmITbl _ i _ _ ) = i+ getOmx (ElmITbl _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance (Show i, Show (Elm ls i), Show x) => Show (Elm (ls :!: ITbl m arr j x) i)++instance Element ls i => Element (ls :!: (Backtrack (ITbl mF arr i x) mF mB r)) i where+ data Elm (ls :!: (Backtrack (ITbl mF arr i x) mF mB r)) i = ElmBtITbl !x [r] !i !i !(Elm ls i)+ type Arg (ls :!: (Backtrack (ITbl mF arr i x) mF mB r)) = Arg ls :. (x, [r])+ getArg (ElmBtITbl x s _ _ ls) = getArg ls :. (x,s)+ getIdx (ElmBtITbl _ _ i _ _ ) = i+ getOmx (ElmBtITbl _ _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++instance (Show x, Show i, Show (Elm ls i)) => Show (Elm (ls :!: (Backtrack (ITbl mF arr i x) mF mB r)) i) where+ show (ElmBtITbl x _ i o s) = show (x,i,o) ++ " " ++ show s++instance+ ( Monad m+ , Element ls (is:.i)+ , TableStaticVar (is:.i)+ , TableIndices (is:.i)+ , MkStream m ls (is:.i)+ , PrimArrayOps arr (is:.i) x+ ) => MkStream m (ls :!: ITbl m arr (is:.i) x) (is:.i) where+ mkStream (ls :!: ITbl _ _ c t _) vs lu is+ = map (\(S5 s _ _ i o) -> ElmITbl (t ! i) i o s)+ . tableIndices c vs is+ . map (\s -> S5 s Z Z (getIdx s) (getOmx s))+ $ mkStream ls (tableStaticVar vs is) lu (tableStreamIndex c vs is)+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls (is:.i)+ , TableStaticVar (is:.i)+ , TableIndices (is:.i)+ , MkStream mB ls (is:.i)+ , PrimArrayOps arr (is:.i) x+ ) => MkStream mB (ls :!: Backtrack (ITbl mF arr (is:.i) x) mF mB r) (is:.i) where+ mkStream (ls :!: BtITbl c t bt) vs us is+ = mapM (\(S5 s _ _ i o) -> bt us i >>= \ ~bb -> return $ ElmBtITbl (t ! i) (bb {-bt us i-}) i o s)+ . tableIndices c vs is+ . map (\s -> S5 s Z Z (getIdx s) (getOmx s))+ $ mkStream ls (tableStaticVar vs is) us (tableStreamIndex c vs is)+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Outside (is:.i))+ , TableStaticVar (Outside (is:.i))+ , TableIndices (Outside (is:.i))+ , MkStream m ls (Outside (is:.i))+ , PrimArrayOps arr (Outside (is:.i)) x+ , Show (is:.i)+ ) => MkStream m (ls :!: ITbl m arr (Outside (is:.i)) x) (Outside (is:.i)) where+ mkStream (ls :!: ITbl _ _ c t _) vs lu is+ = map (\(S5 s _ _ i o) -> ElmITbl (t ! o) i o s)+ . tableIndices c vs is+ . map (\s -> S5 s Z Z (getIdx s) (getOmx s))+ $ mkStream ls (tableStaticVar vs is) lu (tableStreamIndex c vs is)+ {-# Inline mkStream #-}++instance+ ( Monad mB+ , Element ls (Outside (is:.i))+ , TableStaticVar (Outside (is:.i))+ , TableIndices (Outside (is:.i))+ , MkStream mB ls (Outside (is:.i))+ , PrimArrayOps arr (Outside (is:.i)) x+ , Show (is:.i)+ ) => MkStream mB (ls :!: Backtrack (ITbl mF arr (Outside (is:.i)) x) mF mB r) (Outside (is:.i)) where+ mkStream (ls :!: BtITbl c t bt) vs us is+ = mapM (\(S5 s _ _ i o) -> bt us o >>= \bb -> return $ ElmBtITbl (t ! o) (bb {-bt us o-}) i o s)+ . tableIndices c vs is+ . map (\s -> S5 s Z Z (getIdx s) (getOmx s))+ $ mkStream ls (tableStaticVar vs is) us (tableStreamIndex c vs is)+ {-# Inline mkStream #-}+
+ ADP/Fusion/SynVar/Axiom.hs view
@@ -0,0 +1,14 @@++-- | The 'axiom' runs a backtracking algebra. The name comes from Robert+-- Giegerichs @ADP@ where @axiom@ runs the fully formed algorithm.++module ADP.Fusion.SynVar.Axiom where++-- | The Axiom type class++class Axiom t where+ -- | The corresponding stream being returned by 'axiom'+ type AxiomStream t :: *+ -- | Given a table, run the axiom+ axiom :: t -> AxiomStream t+
+ ADP/Fusion/SynVar/Backtrack.hs view
@@ -0,0 +1,28 @@++-- | Wrap forward tables in such a way as to allow backtracking via+-- algebras.++module ADP.Fusion.SynVar.Backtrack where++import Data.Vector.Fusion.Stream.Monadic (Stream)++import ADP.Fusion.Base++++-- |+--+-- TODO this should go into @ADP.Fusion.Table.Backtrack@, more than just+-- tabulated syntactic vars are going to use it.+--+-- NOTE You probably need to give the @monad morphism@ between @mF@ and+-- @mB@ so as to be able to extract forward results in the backtracking+-- phase.++class GenBacktrackTable t (mF :: * -> *) (mB :: * -> *) r where+ data Backtrack t (mF :: * -> *) (mB :: * -> *) r :: *+ type BacktrackIndex t :: *+ toBacktrack :: t -> (forall a . mF a -> mB a) -> (BacktrackIndex t -> BacktrackIndex t -> mB [r]) -> Backtrack t mF mB r++instance Build (Backtrack t mF mB r)+
+ ADP/Fusion/SynVar/Fill.hs view
@@ -0,0 +1,180 @@++module ADP.Fusion.SynVar.Fill where++import Control.Monad.Morph (hoist, MFunctor (..))+import Control.Monad.Primitive (PrimMonad (..))+import Control.Monad.ST+import Control.Monad.Trans.Class (lift, MonadTrans (..))+import Data.Vector.Fusion.Util (Id(..))+import GHC.Exts (inline)+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import System.IO.Unsafe+import Control.Monad (when,forM_)+import Data.List (nub,sort)+import qualified Data.Vector.Unboxed as VU++import Data.PrimitiveArray++import ADP.Fusion.SynVar.Array -- TODO we want to keep only classes in here, move instances to the corresponding modules++import Debug.Trace++++-- * Specialized table-filling wrapper for 'MTbl's+--+-- TODO table-filling does /not/ work for single-dimensional stuff++-- | Run and freeze 'MTbl's. Since actually running the table-filling part+-- is usually the last thing to do, we can freeze as well.++runFreezeMTbls ts = do+ unsafeRunFillTables $ expose ts+ freezeTables $ onlyTables ts+{-# INLINE runFreezeMTbls #-}++++-- * Expose inner mutable tables++-- | Expose the actual mutable table with an 'MTbl'. (Should be temporary+-- until 'MTbl's get a more thorough treatment for auto-filling.++class ExposeTables t where+ type TableFun t :: *+ type OnlyTables t :: *+ expose :: t -> TableFun t+ onlyTables :: t -> OnlyTables t++instance ExposeTables Z where+ type TableFun Z = Z+ type OnlyTables Z = Z+ expose Z = Z+ onlyTables Z = Z+ {-# INLINE expose #-}+ {-# INLINE onlyTables #-}++-- Thanks to the table being a gadt we now the internal types+--+-- TODO move to Table/Array.hs++--instance (ExposeTables ts) => ExposeTables (ts:.(MTbl m arr i x)) where+-- type TableFun (ts:. MTbl m arr i x) = TableFun ts :. (PA.MutArr m (arr i x), i -> m x)+-- type OnlyTables (ts:. MTbl m arr i x) = OnlyTables ts :. (PA.MutArr m (arr i x))+-- expose (ts:.MTbl _ t f) = expose ts :. (t,f)+-- onlyTables (ts:.MTbl _ t _) = onlyTables ts :. t+-- {-# INLINE expose #-}+-- {-# INLINE onlyTables #-}++++-- * Unsafely mutate 'ITbls' and similar tables in the forward phase.++-- | Mutate a cell in a stack of syntactic variables.+--+-- TODO generalize to monad morphism via @mmorph@ package. This will allow+-- more interesting @mrph@ functions that can, for example, track some+-- state in the forward phase. (Note that this can be dangerous, we do+-- /not/ want to have this state influence forward results, unless that can+-- be made deterministic, or we'll break Bellman)++class MutateCell (s :: *) (im :: * -> *) (om :: * -> *) i where+ mutateCell :: Int -> Int -> (forall a . im a -> om a) -> s -> i -> i -> om ()++-- |++class MutateTables (s :: *) (im :: * -> *) (om :: * -> *) where+ mutateTables :: (forall a . im a -> om a) -> s -> om s++class TableOrder (s :: *) where+ tableLittleOrder :: s -> [Int]+ tableBigOrder :: s -> [Int]++instance TableOrder Z where+ tableLittleOrder Z = []+ tableBigOrder Z = []+ {-# Inline tableLittleOrder #-}+ {-# Inline tableBigOrder #-}++instance (TableOrder ts) => TableOrder (ts:.ITbl im arr i x) where+ tableLittleOrder (ts:.ITbl _ tlo _ _ _) = tlo : tableLittleOrder ts+ tableBigOrder (ts:.ITbl tbo _ _ _ _) = tbo : tableBigOrder ts+ {-# Inline tableLittleOrder #-}+ {-# Inline tableBigOrder #-}++-- ** individual instances for filling a *single cell*++instance+ ( PrimArrayOps arr i x+ , MPrimArrayOps arr i x+ , MutateCell ts im om i+ , PrimMonad om+ , Show x, Show i+ ) => MutateCell (ts:.ITbl im arr i x) im om i where+ mutateCell bo lo mrph (ts:.ITbl tbo tlo c arr f) lu i = do+ mutateCell bo lo mrph ts lu i+ when (bo==tbo && lo==tlo) $ do+ marr <- unsafeThaw arr+ z <- (inline mrph) $ f lu i+ writeM marr i z+ {-# INLINE mutateCell #-}++{-+instance+ ( MutateCell ts im om i+ ) => MutateCell (ts:.IRec im i x) im om i where+ mutateCell mrph (ts:.IRec (!c) _ _ f) lu i = do+ mutateCell mrph ts lu i+ {-# INLINE mutateCell #-}+-}++-- ** individual instances for filling a complete table and extracting the+-- bounds++instance+ ( Monad om+ , MutateCell (ts:.ITbl im arr i x) im om i+ , PrimArrayOps arr i x+ , Show i+ , IndexStream i+ , TableOrder (ts:.ITbl im arr i x)+ ) => MutateTables (ts:.ITbl im arr i x) im om where+ mutateTables mrph tt@(_:.ITbl _ _ _ arr _) = do+ let (from,to) = bounds arr+ -- TODO (1) find the set of orders for the synvars+ let !tbos = VU.fromList . nub . sort $ tableBigOrder tt+ let !tlos = VU.fromList . nub . sort $ tableLittleOrder tt+ VU.forM_ tbos $ \bo ->+ flip SM.mapM_ (streamUp from to) $ \k ->+ VU.forM_ tlos $ \lo ->+ mutateCell bo lo (inline mrph) tt to k+ return tt+ {-# INLINE mutateTables #-}++{-+instance+ ( Monad om+ , MutateCell (ts:.IRec im i x) im om i+ , IndexStream i+ ) => MutateTables (ts:.IRec im i x) im om where+ mutateTables mrph tt@(_:.IRec _ from to _) = do+ -- SM.mapM_ (mutateCell (inline mrph) tt to) $ PA.rangeStream from to+ SM.mapM_ (mutateCell (inline mrph) tt to) $ PA.streamUp from to+ return tt+ {-# INLINE mutateTables #-}+-}++instance+ ( Monad om+ ) => MutateCell Z im om i where+ mutateCell _ _ _ Z _ _ = return ()+ {-# INLINE mutateCell #-}++-- | Default table filling, assuming that the forward monad is just @IO@.+--+-- TODO generalize to @MonadIO@ or @MonadPrim@.++mutateTablesDefault :: MutateTables t Id IO => t -> t+mutateTablesDefault t = unsafePerformIO $ mutateTables (return . unId) t+{-# INLINE mutateTablesDefault #-}+
+ ADP/Fusion/SynVar/Indices.hs view
@@ -0,0 +1,109 @@++-- | With 'tableIndices' we create a stream of legal indices for this table. We+-- need 'tableIndices' in multi-dimensional tables as the type of the+-- multi-dimensional indices is generic.++module ADP.Fusion.SynVar.Indices where++import Data.Vector.Fusion.Stream.Size (Size(Unknown))+import Data.Vector.Fusion.Stream.Monadic (flatten,map,Stream, Step(..))+import Prelude hiding (map)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base++++class TableIndices i where+ tableIndices :: (Monad m) => TblConstraint i -> Context i -> i -> Stream m (S5 z j j i i) -> Stream m (S5 z j j i i)++instance TableIndices Z where+ tableIndices _ _ _ = id+ {-# INLINE tableIndices #-}++instance TableIndices (Outside Z) where+ tableIndices _ _ _ = id+ {-# INLINE tableIndices #-}++{-+instance TableIndices is => TableIndices (is:.Subword) where+ tableIndices (cs:.c) (vs:.Static) (is:.Subword (i:.j))+ = S.map (\(Tr s (x:.Subword (_:.l)) ys) -> Tr s x (is:.subword l j)) -- constraint handled: tableStreamIndex+ . tableIndices cs vs is+ . S.map moveIdxTr+ tableIndices (cs:.OnlyZero) _ _ = error "write me"+ tableIndices (cs:.c) (vs:.Variable _ Nothing) (is:.Subword (i:.j))+ = S.flatten mk step Unknown+ . tableIndices cs vs is+ . S.map moveIdxTr+ where mk (Tr s (y:.Subword (_:.l)) xs) = return $ Pn s y xs l (j-l-minSize c)+ step (Pn s y xs k z)+ | z>= 0 = return $ S.Yield (Tr s y (xs:.subword k (j-z))) (Pn s y xs k (z-1))+ | otherwise = return $ S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ {-# INLINE tableIndices #-}+-}++-- | TODO I think we need to check @cs:.c@ here+--+-- TODO yes, handle @Empty@ / @NonEmpty@ !!!++instance TableIndices is => TableIndices (is:.PointL) where+ tableIndices (cs:._) (vs:.IStatic _) (is:.PointL j)+ = map (\(S5 s (zi:.PointL _) (zo:.PointL _) is os) -> S5 s zi zo (is:.PointL j) (os:.PointL 0)) -- constraint handled: tableStreamIndex+ . tableIndices cs vs is+ . map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ tableIndices (cs:._) (vs:.IVariable d) (is:.PointL j)+ = flatten mk step Unknown+ . tableIndices cs vs is+ . map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ where mk s@(S5 _ (_:.PointL k) _ _ _) = return (s :. k)+ step (ss@(S5 s (zi:._) (zo:._) is os) :. k)+ | k > j = return $ Done+ | otherwise = return $ Yield (S5 s zi zo (is:.PointL k) (os:.PointL 0)) (ss :. k+1)+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {- TODO re-add later+ tableIndices (cs:.OnlyZero) _ _ = error "write me"+ tableIndices (cs:.c) (vs:.IVariable) (is:.PointL j)+ = flatten mk step Unknown+ . tableIndices cs vs is+ . map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ where mk (S5 s (zi:.PointL l) (zo:._) is os) = return $ S6 s zi zo is os (j-l-minSize c)+ step (S6 s zi zo is os x)+ | x >= 0 = return $ Yield (S5 s zi zo (is:.PointL (j-x)) (os:.PointL 0)) (S6 s zi zo is os (x-1))+ | otherwise = return $ Done+ {-# Inline [1] mk #-}+ {-# Inline [1] step #-}+ -}+ {-# Inline tableIndices #-}++instance TableIndices (Outside is) => TableIndices (Outside (is:.PointL)) where+ tableIndices (cs:.c) (vs:.OStatic d) (O (is:.PointL j))+ = map (\(S5 s (zi:.PointL i) (zo:.PointL o) (O is) (O os)) -> S5 s zi zo (O (is:.PointL i)) (O (os:.PointL o))) -- constraint handled: tableStreamIndex+ . tableIndices cs vs (O is)+ . map (\(S5 s zi zo (O (is:.i)) (O (os:.o))) -> S5 s (zi:.i) (zo:.o) (O is) (O os))+ {-# Inline tableIndices #-}++{-+instance TableIndices is => TableIndices (is:.PointR) where+ tableIndices (cs:.c) (vs:.Static) (is:.PointR (i:.j))+ = S.map (\(Tr s (x:.PointR (_:.l)) ys) -> Tr s x (is:.pointR l j)) -- constraint handled: tableStreamIndex+ . tableIndices cs vs is+ . S.map moveIdxTr+ tableIndices (cs:.OnlyZero) _ _ = error "write me"+ tableIndices (cs:.c) (vs:.Variable _ Nothing) (is:.PointR (i:.j))+ = S.flatten mk step Unknown+ . tableIndices cs vs is+ . S.map moveIdxTr+ where mk (Tr s (y:.PointR (_:.l)) xs) = return $ Pn s y xs l (j-l-minSize c)+ step (Pn s y xs k z)+ | z>= 0 = return $ S.Yield (Tr s y (xs:.pointR k (j-z))) (Pn s y xs k (z-1))+ | otherwise = return $ S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ {-# INLINE tableIndices #-}+-}+
+ ADP/Fusion/SynVar/Recursive.hs view
@@ -0,0 +1,74 @@++module ADP.Fusion.SynVar.Recursive+ ( module ADP.Fusion.SynVar.Recursive.Type+ , module ADP.Fusion.SynVar.Recursive.Point+ , module ADP.Fusion.SynVar.Recursive.Subword+ ) where++import ADP.Fusion.SynVar.Recursive.Point+import ADP.Fusion.SynVar.Recursive.Subword+import ADP.Fusion.SynVar.Recursive.Type+++{-+++-- * Instances++{-+instance ModifyConstraint (IRec m Subword x) where+ toNonEmpty (IRec _ iF iT f) = IRec NonEmpty iF iT f+ toEmpty (IRec _ iF iT f) = IRec EmptyOk iF iT f+ {-# INLINE toNonEmpty #-}+ {-# INLINE toEmpty #-}++instance+ ( Monad m+ , Element ls Subword+ , MkStream m ls Subword+ ) => MkStream m (ls :!: IRec m Subword x) Subword where+ mkStream (ls :!: IRec c _ _ f) Static lu (Subword (i:.j))+ = let ms = minSize c in ms `seq`+ S.mapM (\s -> let Subword (_:.l) = getIdx s+ in f lu (subword l j) >>= \z -> return $ ElmIRec z (subword l j) s)+ $ mkStream ls (Variable Check Nothing) lu (subword i $ j - ms)+ mkStream (ls :!: IRec c _ _ f) (Variable _ Nothing) lu (Subword (i:.j))+ = let ms = minSize c+ mk s = let (Subword (_:.l)) = getIdx s in return (s:.j-l-ms)+ step (s:.z)+ | z>=0 = do let (Subword (_:.k)) = getIdx s+ y <- f lu (subword k (j-z))+ return $ S.Yield (ElmIRec y (subword k $ j-z) s) (s:.z-1)+ | otherwise = return $ S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (subword i j)+ {-# INLINE mkStream #-}++instance+ ( Monad mB+ , Element ls Subword+ , MkStream mB ls Subword+ ) => MkStream mB (ls :!: BT (IRec mF Subword x) mF mB r) Subword where+ mkStream (ls :!: BtIRec c _ _ f bt) Static lu (Subword (i:.j))+ = let ms = minSize c in ms `seq`+ S.mapM (\s -> let (Subword (_:.l)) = getIdx s+ ix = subword l j+ in f lu ix >>= \fx -> return $ ElmBtIRec fx (bt lu ix) ix s)+ $ mkStream ls (Variable Check Nothing) lu (subword i $ j-ms)+ mkStream (ls :!: BtIRec c _ _ f bt) (Variable _ Nothing) lu (Subword (i:.j))+ = let ms = minSize c+ mk s = let Subword (_:.l) = getIdx s in return (s:.j-l-ms)+ step (s:.z)+ | z>=0 = do let Subword (_:.k) = getIdx s+ ix = subword k (j-z)+ f lu ix >>= \fx -> return $ S.Yield (ElmBtIRec fx (bt lu ix) ix s) (s:.z-1)+ | otherwise = return $ S.Done+ {-# INLINE [1] mk #-}+ {-# INLINE [1] step #-}+ in ms `seq` S.flatten mk step Unknown $ mkStream ls (Variable NoCheck Nothing) lu (subword i j)+ {-# INLINE mkStream #-}+-}++-}+
+ ADP/Fusion/SynVar/Recursive/Point.hs view
@@ -0,0 +1,3 @@++module ADP.Fusion.SynVar.Recursive.Point where+
+ ADP/Fusion/SynVar/Recursive/Subword.hs view
@@ -0,0 +1,13 @@++module ADP.Fusion.SynVar.Recursive.Subword where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic+import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util (delay_inline)+import Debug.Trace+import Prelude hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Recursive.Type+import ADP.Fusion.SynVar.Backtrack
+ ADP/Fusion/SynVar/Recursive/Type.hs view
@@ -0,0 +1,80 @@++module ADP.Fusion.SynVar.Recursive.Type where++import Data.Strict.Tuple ((:!:)(..))+import Data.Vector.Fusion.Stream.Monadic (Stream,head)+import Prelude hiding (head)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.SynVar.Backtrack+import ADP.Fusion.SynVar.Axiom++++data IRec m i x where+ IRec :: { iRecConstraint :: !(TblConstraint i)+ , iRecFrom :: !i+ , iRecTo :: !i+ , iRecFun :: !(i -> i -> m x)+ } -> IRec m i x++++instance Build (IRec m i x)++instance GenBacktrackTable (IRec mF i x) mF mB r where+ data Backtrack (IRec mF i x) mF mB r = BtIRec !(TblConstraint i) !i !i (i -> i -> mB x) (i -> i -> mB [r]) -- (Stream mB r))+ type BacktrackIndex (IRec mF i x) = i+ toBacktrack (IRec c iF iT f) mrph bt = BtIRec c iF iT (\lu i -> mrph $ f lu i) bt+ {-# INLINE toBacktrack #-}++++instance+ ( Monad m+ , IndexStream i+ ) => Axiom (IRec m i x) where+ type AxiomStream (IRec m i x) = m x+ axiom (IRec c l h fun) = do+ k <- (head . uncurry streamDown) (l,h)+ fun h k+ {-# Inline axiom #-}++instance+ ( Monad mB+ , IndexStream i+ ) => Axiom (Backtrack (IRec mF i x) mF mB r) where+ type AxiomStream (Backtrack (IRec mF i x) mF mB r) = mB [r] -- (Stream mB r)+ axiom (BtIRec c l h fun btfun) = do+ k <- (head . uncurry streamDown) (l,h)+ btfun h k+ {-# Inline axiom #-}++++instance Element ls i => Element (ls :!: IRec m i x) i where+ data Elm (ls :!: IRec m i x) i = ElmIRec !x !i !i !(Elm ls i)+ type Arg (ls :!: IRec m i x) = Arg ls :. x+ getArg (ElmIRec x _ _ ls) = getArg ls :. x+ getIdx (ElmIRec _ i _ _ ) = i+ getOmx (ElmIRec _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++instance Element ls i => Element (ls :!: (Backtrack (IRec mF i x) mF mB r)) i where+ data Elm (ls :!: (Backtrack (IRec mF i x) mF mB r)) i = ElmBtIRec !x !(mB (Stream mB r)) !i !i !(Elm ls i)+ type Arg (ls :!: (Backtrack (IRec mF i x) mF mB r)) = Arg ls :. (x, mB (Stream mB r))+ getArg (ElmBtIRec x s _ _ ls) = getArg ls :. (x,s)+ getIdx (ElmBtIRec _ _ i _ _ ) = i+ getOmx (ElmBtIRec _ _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++++-- TODO write multi-tape instances+
ADP/Fusion/TH.hs view
@@ -1,46 +1,76 @@-{-# LANGUAGE TemplateHaskell #-} -module ADP.Fusion.TH where+-- | The functions in here auto-create suitable algebra product functions from+-- a signature. Currently, functions @<**@ are supported which have scalar+-- results in the first variable.+--+-- TODO If we want to support classified DP, we shall also need @**<@+-- generating vector-results given a vector result, followed by a scalar+-- result.+--+-- TODO Then we also need @***@ handling the case of vector-to-vector results.+--+-- TODO note the comments in @buildBacktrackingChoice@ -import Language.Haskell.TH-import Language.Haskell.TH.Syntax-import Data.List+module ADP.Fusion.TH+ ( makeAlgebraProduct+ , (<||)+ ) where++import Data.List+import Data.Tuple.Select+import Language.Haskell.TH+import Language.Haskell.TH.Syntax import qualified Data.Vector.Fusion.Stream.Monadic as SM +import ADP.Fusion.TH.Backtrack (makeBacktrackingProductInstance,(<||))+import ADP.Fusion.TH.Common (getRuleResultType) ++makeAlgebraProduct = makeBacktrackingProductInstance++{- -- | Create the algebra product function from a signature type constructor.+--+-- TODO make the resulting function INLINE+--+-- TODO compare @synTypes@ with the stream argument types of all @hs@ (via their+-- @hns@ names). If there is a mismatch, then either not all non-terminal types+-- have a corresponding choice function or vice versa. -makeAlgebraProduct :: Name -> Q [Dec]-makeAlgebraProduct nm = do+makeAlgebraProductH :: [Name] -> Name -> Q [Dec]+makeAlgebraProductH hns nm = do rnm <- reify nm case rnm of TyConI (DataD ctx tyConName args cs d) -> case cs of -- we analyze the accessor functions and look for the objective function -- accessor. It's stream parameter is the type of the non-terminal. -- Everything else in accessors are terminal parameters.- [RecC dataConName fs] -> do- -- find the objective function type (we crash if the user has more than- -- one)- let [oF] = filter (isObjectiveF . sel3) fs- error $ unlines $ intersperse "\n" $ map show fs+ [RecC dataConName fs'] -> do+ -- split @fs@ into functions applied to rule RHSs and choice functions (@hs@)+ let (fs,hs) = partition ((`notElem` hns) . sel1) fs'+ -- the result types of the @fs@ are the types of the non-terminal symbols+ let synTypes = nub . map getRuleResultType $ fs+-- funStream <- funD (mkName "<**") [genClauseStream dataConName fs' fs hs]+ funList <- funD (mkName "<||") [genClauseBacktrack dataConName fs' fs hs]+ return+-- [ funStream+ [ funList+ , PragmaD $ InlineP (mkName "<||") Inline FunLike AllPhases+ ] _ -> fail "more than one data ctor" _ -> fail "unsupported data type" -sel3 (a,b,c) = c+-- | Creates a class for each type of product and instances for each+-- signature. -zzz :: VarStrictType -> String-zzz (nm,s,t) = show (nm,s,t)+makeClassyProducts :: Name -> Q [Dec]+makeClassyProducts conName = do+ c <- lookupValueName "BacktrackingProduct"+ case c of+ Nothing -> error "need to create class now and add instance"+ Just cl -> error "add instance"+ return []+-} -isObjectiveF :: Type -> Bool-isObjectiveF (AppT (AppT ArrowT (AppT (AppT (ConT s) _) _)) (AppT _ _)) | s == ''SM.Stream = True-isObjectiveF _ = False --- AppT (AppT ArrowT--- (AppT (AppT (ConT Data.Vector.Fusion.Stream.Monadic.Stream)--- (VarT m_1627401654)--- )--- (VarT x_1627401655)--- )--- )--- (AppT (VarT m_1627401654) (VarT r_1627401656))
+ ADP/Fusion/TH/Backtrack.hs view
@@ -0,0 +1,262 @@++-- | Backtracking which uses lists internally. The basic idea is to convert+-- each @Stream@ into a list. The consumer consumes the stream lazily, but+-- allows for fusion to happen. The hope is that this improves total+-- performance in those cases, where backtracking has significant costs.++module ADP.Fusion.TH.Backtrack where++import Data.List+import Data.Tuple.Select+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Mutable as VM+import qualified Data.Vector.Generic.Mutable as VGM+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import Control.Monad.Primitive (PrimState, PrimMonad)+import Data.Vector.Fusion.Stream.Monadic (Stream(..))+import Debug.Trace++import ADP.Fusion.TH.Common++++-- | The type class of algebra products. We have the forward signature+-- @sigF@ and the backtracking signature @sigB@. Combined via @(<||)@ we+-- have a new signature @SigR@.++class BacktrackingProduct sigF sigB where+ type SigR sigF sigB :: *+ (<||) :: sigF -> sigB -> SigR sigF sigB++makeBacktrackingProductInstance :: Name -> Q [Dec]+makeBacktrackingProductInstance tyconName = do+ t <- reify tyconName+ case t of+ TyConI (DataD ctx tyConName args cs d) -> do+ let m = getMonadName args+ case cs of+ [RecC dataconName funs] -> do+ let Just (h,m',x,r) = getObjectiveNames funs+ mL <- newName "mL"+ xL <- newName "xL"+ mR <- newName "mR"+ xR <- newName "xR"+ rR <- newName "rR"+ let lType = buildLeftType tyconName (m', x, r) (mL, xL) args+ let rType = buildRightType tyconName (m', x, r) (mR, xR, rR) args+ let sigRType = buildSigRType tyconName (m', x, r) xL (mR, xR, rR) args+ let (fs,hs) = partition ((`notElem` [h]) . sel1) funs+ Clause ps (NormalB b) ds <- genClauseBacktrack dataconName funs fs hs+ i <- [d| instance (Monad $(varT mL), Monad $(varT mR), Eq $(varT xL), $(varT mL) ~ $(varT mR)) => BacktrackingProduct $(return lType) $(return rType) where+ type SigR $(return lType) $(return rType) = $(return sigRType)+ (<||) = $(return $ LamE ps $ LetE ds b)+ {-# Inline (<||) #-}+ |]+ return i++-- | Returns the 'Name' of the monad variable.++getMonadName :: [TyVarBndr] -> Maybe Name+getMonadName = go+ where go [] = Nothing+ go (KindedTV m (AppT (AppT ArrowT StarT) StarT) : _) = Just m+ go (_ : xs) = go xs++-- | Returns the 'Name's of the objective function variables, as well as+-- the name of the objective function itself.++getObjectiveNames :: [VarStrictType] -> Maybe (Name,Name,Name,Name)+getObjectiveNames = go+ where go [] = Nothing+ go ( (hName , _ , (AppT (AppT ArrowT (AppT (AppT (ConT streamName) (VarT mS)) (VarT x))) (AppT (VarT mR) (VarT r)))) : xs)+ | streamName == ''Stream && mS == mR = Just (hName,mS,x,r)+ | otherwise = go xs+ go ( _ : xs) = go xs++buildLeftType :: Name -> (Name, Name, Name) -> (Name, Name) -> [TyVarBndr] -> Type+buildLeftType tycon (m, x, r) (mL, xL) = foldl AppT (ConT tycon) . map (VarT . go)+ where go (KindedTV z _)+ | z == m = mL -- correct monad name+ | z == x = xL -- point to new x type+ | z == r = xL -- stream and return type are the same+ | otherwise = z -- everything else can stay as is+ go s = error $ "buildLeftType: " ++ show s++buildRightType :: Name -> (Name, Name, Name) -> (Name, Name, Name) -> [TyVarBndr] -> Type+buildRightType tycon (m, x, r) (mR, xR, rR) = foldl AppT (ConT tycon) . map (VarT . go)+ where go (KindedTV z _)+ | z == m = mR+ | z == x = xR+ | z == r = rR+ | otherwise = z++buildSigRType :: Name -> (Name, Name, Name) -> (Name) -> (Name, Name, Name) -> [TyVarBndr] -> Type+buildSigRType tycon (m, x, r) (xL) (mR, xR, rR) = foldl AppT (ConT tycon) . map go+ where go (KindedTV z _)+ | z == m = VarT mR+ | z == x = (AppT (AppT (TupleT 2) (VarT xL)) (AppT ListT (VarT xR)))+ | z == r = VarT rR+ | otherwise = VarT z++-- |++genClauseBacktrack+ :: Name+ -> [VarStrictType]+ -> [VarStrictType]+ -> [VarStrictType]+ -> Q Clause+genClauseBacktrack conName allFunNames evalFunNames choiceFunNames = do+ let nonTermNames = nub . map getRuleResultType $ evalFunNames+ -- bind the l'eft and r'ight variable of the two algebras we want to join,+ -- also create unique names for the function names we shall bind later.+ nameL <- newName "l"+ varL <- varP nameL+ -- TODO automate discovery of choice functions?+ fnmsL <- sequence $ replicate (length allFunNames) (newName "fnamL")+ nameR <- newName "r"+ varR <- varP nameR+ fnmsR <- sequence $ replicate (length allFunNames) (newName "fnamR")+ -- bind the individual variables in the where part+ whereL <- valD (conP conName (map varP fnmsL)) (normalB $ varE nameL) []+ whereR <- valD (conP conName (map varP fnmsR)) (normalB $ varE nameR) []+ rce <- recConE conName+ $ zipWith3 (genChoiceFunction) (drop (length evalFunNames) fnmsL) (drop (length evalFunNames) fnmsR) choiceFunNames+ ++ zipWith3 (genAttributeFunction nonTermNames) fnmsL fnmsR evalFunNames+ -- build the function pairs+ -- to keep our sanity, lets print this stuff+ let cls = Clause [varL, varR] (NormalB rce) [whereL,whereR]+ return cls++-- |++genChoiceFunction+ :: Name+ -> Name+ -> VarStrictType+ -> Q (Name,Exp)+genChoiceFunction hL hR (name,_,t) = do+ exp <- buildBacktrackingChoice hL hR+ return (name,exp)+++-- |+--+-- TODO need fun names from @l@ and @r@++genAttributeFunction+ :: [Name]+ -> Name+ -> Name+ -> VarStrictType+ -> Q (Name,Exp)+genAttributeFunction nts fL fR (name,_,t) = do+ (lamPat,funL,funR) <-recBuildLamPat nts fL fR (init $ getRuleSynVarNames t) -- @init@ since we don't want the result as a parameter+ let exp = LamE lamPat $ TupE [funL,funR]+ return (name,exp)++-- |++recBuildLamPat :: [Name] -> Name -> Name -> [Name] -> Q ([Pat], Exp, Exp)+recBuildLamPat nts fL' fR' ts = do+ -- here we just run through all arguments, either creating an @x@ and+ -- a @ys@ for a non-term or a @t@ for a term.+ ps <- sequence [ if t `elem` nts then tupP [newName "x" >>= varP, newName "ys" >>= varP] else (newName "t" >>= varP) | t<-ts]+ let buildLfun f (TupP [VarP v,_]) = appE f (varE v)+ buildLfun f (VarP v ) = appE f (varE v)+ lfun <- foldl buildLfun (varE fL') ps+ rfun <- buildRns (VarE fR') ps+ return (ps, lfun, rfun)+++-- |+--+-- NOTE+--+-- @+-- [ f x | x <- xs ]+-- CompE [BindS (VarP x) (VarE xs), NoBindS (AppE (VarE f) (VarE x))]+-- @++buildRns+ :: Exp+-- -> [Name]+ -> [Pat]+ -> ExpQ+buildRns f ps = do+ ys <- sequence [ newName "y" | TupP [_,VarP v] <- ps ]+ let vs = zipWith (\y v -> (BindS (VarP y) (VarE v))) ys [ v | TupP [_,VarP v] <- ps ]+ let xs = go ps ys+ ff <- noBindS $ foldl (\g z -> appE g (varE z)) (return f) xs+ return $ CompE $ vs ++ [ff]+ where go [] [] = []+ go (VarP v : gs) ys = v : go gs ys -- keep terminal binders+ go (TupP _ : gs) (v:ys) = v : go gs ys -- insert new binders+ go as bs = error $ show ("not done?", as, bs)++-- | Build up the backtracking choice function. This choice function will+-- backtrack based on the first result, then return only the second.+--+-- TODO it should be (only?) this function we will need to modify to build+-- all algebra products.+--+-- @ysM@ can't be unboxed, as @snd@ of each element is a list, lazily+-- consumed. We build up @ysM@ as this makes fusion happen. Of course, this+-- is a boxed vector and not as efficient, but we gain the ability to have+-- lazily created backtracking from this!+--+-- This means strict optimization AND lazy backtracking++buildBacktrackingChoice :: Name -> Name -> Q Exp+buildBacktrackingChoice hL' hR' =+ [| \xs -> do -- first, create a boxed, mutable vector from the results+ ysM <- streamToVector xs -- VGM.unstream xs :: m (VM.MVector s (t1,[t2]))+ -- apply first choice+ hFres <- $(varE hL') $ SM.map fst $ vectorToStream ysM+ -- second choice on snd elements, then concat'ed up+ -- TODO good candidate for rewriting into flatten+ -- operation!+ $(varE hR') $ SM.concatMap (SM.fromList . snd) $ SM.filter ((hFres==) . fst) $ vectorToStream ysM+ |]++-- | Transform a monadic stream monadically into a vector.++streamToVector :: (Monad m) => SM.Stream m x -> m (V.Vector x)+streamToVector xs = do+ l <- SM.toList xs+ let v = V.fromList l+ return v+{-# Inline streamToVector #-}++-- | Transform a vector into a monadic stream.++vectorToStream :: (Monad m) => V.Vector x -> SM.Stream m x+vectorToStream = SM.fromList . V.toList+{-# Inline vectorToStream #-}++-- | Gets the names used in the evaluation function. This returns one+-- 'Name' for each variable.+--+-- In case of @TupleT 0@ the type is @()@ and there isn't a name to go with+-- it. We just @mkName "()"@ a name, but this might be slightly dangerous?+-- (Not really sure if it indeed is)+--+-- With @AppT _ _@ we have a multidim terminal and produce another hackish+-- name to be consumed above.+--+-- @+-- AppT (AppT ArrowT (AppT (AppT (ConT Data.Array.Repa.Index.:.) (AppT (AppT (ConT Data.Array.Repa.Index.:.) (ConT Data.Array.Repa.Index.Z)) (VarT c_1627675270))) (VarT c_1627675270))) (VarT x_1627675265)+-- @++getRuleSynVarNames :: Type -> [Name]+getRuleSynVarNames t' = go t' where+ go t+ | VarT x <- t = [x]+ | AppT (AppT ArrowT (VarT x )) y <- t = x : go y -- this is a syntactic variable, return the name that the incoming data is bound to+ | AppT (AppT ArrowT (AppT _ _)) y <- t = mkName "[]" : go y -- this captures that we have a multi-dim terminal.+ | AppT (AppT ArrowT (TupleT 0)) y <- t = mkName "()" : go y -- this case captures things like @nil :: () -> x@ for rules like @nil <<< Epsilon@.+ | otherwise = error $ "getRuleSynVarNames error: " ++ show t ++ " in: " ++ show t'+
+ ADP/Fusion/TH/Common.hs view
@@ -0,0 +1,19 @@++module ADP.Fusion.TH.Common where++import Data.Tuple.Select+import Language.Haskell.TH+import Language.Haskell.TH.Syntax++++-- | The last @Name@ of a rule is the name of the syntactic type of the+-- result.++getRuleResultType :: VarStrictType -> Name+getRuleResultType vst = go $ sel3 vst where+ go t+ | AppT _ (VarT x) <- t = x+ | AppT _ x <- t = go x+ | otherwise = error $ "undetermined error:" ++ show vst+
− ADP/Fusion/Table.hs
@@ -1,563 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE PatternGuards #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeSynonymInstances #-}--module ADP.Fusion.Table where--import Control.Monad.Primitive-import Data.Array.Repa.Index-import Data.Array.Repa.Shape-import Data.Strict.Tuple-import Data.Vector.Fusion.Stream.Size-import qualified Data.Vector.Fusion.Stream.Monadic as S-import qualified Data.Vector.Unboxed as VU-import Data.Strict.Maybe-import Prelude hiding (Maybe(..))--import Data.Array.Repa.Index.Subword-import Data.Array.Repa.Index.Points-import Data.Array.Repa.ExtShape-import qualified Data.PrimitiveArray as PA-import qualified Data.PrimitiveArray.Zero as PA--import ADP.Fusion.Classes--import Debug.Trace------ * Mutable table with adaptive storage.--data MTbl i xs = MTbl !(ENZ i) !xs -- (PA.MutArr m (arr i x))--mTblSw :: ENE -> PA.MutArr m (arr (Z:.Subword) x) -> MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))-mTblSw = MTbl-{-# INLINE mTblSw #-}--mTbl :: ENZ i -> PA.MutArr m (arr i x) -> MTbl i (PA.MutArr m (arr i x))-mTbl = MTbl-{-# INLINE mTbl #-}---- | Generate the list of indices for use in table lookup.------ Don't touch stuff in greek! ζ is the interior stack of arguments, α the--- stack of saved indices--class TableIndices i where- tableIndices :: Monad m => InOut i -> ENZ i -> i -> S.Stream m (ζ:!:α:!:i) -> S.Stream m (ζ:!:α:!:i)------ * Instances--instance TableIndices Z where- tableIndices Z Z Z = id- {-# INLINE tableIndices #-}--instance TableIndices Subword where- -- | These actually don't make sense in 1-dim settings, we keep the code as a- -- reminder how things should look like: @tableIndices Outer ZeroT- -- (Subword(i:.j)) = S.map (:!:subword j j)@- tableIndices _ ZeroT _ = error "TableIndices Subword/ZeroT does not make sense"- tableIndices Outer _ (Subword(i:.j)) = S.map (\(ζ:!:α:!:Subword(k:.l)) -> (ζ:!:α:!:subword l j))- tableIndices (Inner _ szd) ene (Subword(i:.j)) = S.flatten mk step Unknown where- mk (ζ:!:α:!:kl@(Subword(k:.l))) =- let le = l + case ene of { EmptyT -> 0 ; NonEmptyT -> 1 }- l' = case szd of { Nothing -> le ; Just z -> max le (j-z) }- in return (ζ:!:α:!:l:!:l')- step (ζ:!:α:!:k:!:l)- | i>j = return S.Done- | otherwise = return $ S.Yield (ζ:!:α:!:subword k l) (ζ:!:α:!:k:!:l+1)- {-# INLINE tableIndices #-}--instance TableIndices is => TableIndices (is:.Subword) where- tableIndices (os:.Outer) (es:._) (is:.Subword(i:.j))- = S.map (\(ζ:!:(α:!:Subword(_:.l)):!:is) -> (ζ:!:α:!:(is:.subword l j))) -- extend index to the end- . tableIndices os es is -- extend the @is@ part- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:!:i):!:is)) -- move topmost index to α for safekeeping- -- tables annotated with zero-width have zero width @l--l@- -- This also reduces the number of "running indices"- --- -- TODO consider returning "def"ault elements here, instead of data from- -- zero-length subword? Or does 'ZeroT' actually mean to extract (a/the)- -- zero-length subword?- --- tableIndices (os:.Inner _ szd) (es:.ZeroT) (is:.Subword(i:.j))- = S.map (\(ζ:!:(α:.Subword(k:.l)):!:is) -> (ζ:!:α:!:(is:.subword l l)))- . tableIndices os es is- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:.i):!:is))- -- the default case, where we need to create indices- tableIndices (os:.Inner _ szd) (es:.e) (is:.Subword(i:.j))- = S.flatten mk step Unknown- . tableIndices os es is- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:.i):!:is))- where mk (ζ:!:(α:.Subword (k:.l)):!:is) =- let le = l + case e of { EmptyT -> 0 ; NonEmptyT -> 1 }- l' = case szd of { Nothing -> le ; Just z -> max le (j-z) }- in return (ζ:!:α:!:is:!:l:!:l')- step (ζ:!:α:!:is:!:k:!:l)- | l > j = return $ S.Done- | otherwise = return $ S.Yield (ζ:!:α:!:(is:.subword k l)) (ζ:!:α:!:is:!:k:!:l+1)- {-# INLINE tableIndices #-}--instance TableIndices is => TableIndices (is:.PointL) where- tableIndices (os:.Outer) (es:._) (is:.PointL(i:.j))- = S.map (\(ζ:!:(α:!:PointL(_:.l)):!:is) -> (ζ:!:α:!:(is:.pointL l j))) -- extend index to the end- . tableIndices os es is -- extend the @is@ part- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:!:i):!:is)) -- move topmost index to α for safekeeping- tableIndices (os:.Inner _ szd) (es:.ZeroT) (is:.PointL(i:.j))- = S.map (\(ζ:!:(α:.PointL(k:.l)):!:is) -> (ζ:!:α:!:(is:.pointL l l))) -- does @l==lower bound@ have to be true here?- . tableIndices os es is- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:.i):!:is))- -- the default case, where we need to create indices- tableIndices (os:.Inner _ szd) (es:.e) (is:.PointL(i:.j))- = S.flatten mk step Unknown- . tableIndices os es is- . S.map (\(ζ:!:α:!:(is:.i)) -> (ζ:!:(α:.i):!:is))- where mk (ζ:!:(α:.PointL (k:.l)):!:is) =- let le = l + case e of { EmptyT -> 0 ; NonEmptyT -> 1 }- l' = case szd of { Nothing -> le ; Just z -> max le (j-z) }- in return (ζ:!:α:!:is:!:l:!:l')- step (ζ:!:α:!:is:!:k:!:l)- | l > j = return $ S.Done- | otherwise = return $ S.Yield (ζ:!:α:!:(is:.pointL k l)) (ζ:!:α:!:is:!:k:!:l+1)- {-# INLINE tableIndices #-}--instance Build (MTbl i x)---- ** Subword--instance- ( ValidIndex ls Subword- , Monad m- , PA.MPrimArrayOps arr (Z:.Subword) x- ) => ValidIndex (ls:!:MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))) Subword where- validIndex (_ :!: MTbl ZeroT _) _ _ = error "table with ZeroT found, there is no reason (actually: no implementation) for 1-dim ZeroT tables"- validIndex (ls :!: MTbl ene tbl) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- let (_,Z:.Subword (0:.n)) = PA.boundsM tbl- minsize = max b (if ene==EmptyT then 0 else 1)- in i>=a && i+minsize<=j && j<=n-c && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: MTbl ene _) ix = let (a:!:b:!:c) = getParserRange ls ix in if ene==EmptyT then (a:!:b:!:c) else (a:!:b+1:!:c)- {-# INLINE getParserRange #-}--instance- ( Elms ls Subword- ) => Elms (ls :!: MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))) Subword where- data Elm (ls :!: MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))) Subword = ElmMTblSw !(Elm ls Subword) !x !Subword -- ElmBtTbl !(Elm ls Subword) !x !(m (S.Stream m b)) !Subword- type Arg (ls :!: MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))) = Arg ls :. x- getArg !(ElmMTblSw ls x _) = getArg ls :. x- getIdx !(ElmMTblSw _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , PrimMonad m- , Elms ls Subword- , MkStream m ls Subword- , PA.MPrimArrayOps arr (Z:.Subword) x- ) => MkStream m (ls :!: MTbl Subword (PA.MutArr m (arr (Z:.Subword) x))) Subword where- mkStream !(ls:!:MTbl ene tbl) Outer !ij@(Subword (i:.j))- = S.mapM (\s -> let (Subword (_:.l)) = getIdx s in PA.readM tbl (Z:.subword l j) >>= \z -> return $ ElmMTblSw s z (subword l j))- $ mkStream ls (Inner Check Nothing) (subword i $ case ene of { EmptyT -> j ; NonEmptyT -> j-1 })- mkStream !(ls:!:MTbl ene tbl) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (_:.l)) = getIdx s- le = l + case ene of { EmptyT -> 0 ; NonEmptyT -> 1}- l' = case szd of Nothing -> le- Just z -> max le (j-z)- in return (s :!: l :!: l')- {-# INLINE [0] mk #-}- step !(s :!: k :!: l)- | l > j = return S.Done- | otherwise = PA.readM tbl (Z:.subword k l) >>= \z -> return $ S.Yield (ElmMTblSw s z (subword k l)) (s :!: k :!: l+1)- {-# INLINE [0] step #-}- {-# INLINE mkStream #-}---- ** multi-dim indices--instance- ( Elms ls (is:.i)- ) => Elms (ls :!: MTbl (is:.i) (PA.MutArr m (arr (is:.i) x))) (is:.i) where- data Elm (ls :!: MTbl (is:.i) (PA.MutArr m (arr (is:.i) x))) (is:.i) = ElmMTbl !(Elm ls (is:.i)) !x !(is:.i)- type Arg (ls :!: MTbl (is:.i) (PA.MutArr m (arr (is:.i) x))) = Arg ls :. x- getArg !(ElmMTbl ls x _) = getArg ls :. x- getIdx !(ElmMTbl _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , PrimMonad m- , PA.MPrimArrayOps arr (is:.i) x- , Elms ls (is:.i)- , NonTermValidIndex (is:.i)- , TableIndices (is:.i)- , MkStream m ls (is:.i)- ) => MkStream m (ls:!:MTbl (is:.i) (PA.MutArr m (arr (is:.i) x))) (is:.i) where- mkStream (ls :!: MTbl enz tbl) os is- = S.mapM (\(s:!:Z:!:β) -> PA.readM tbl β >>= \z -> return $ ElmMTbl s z β) -- extract data using β index- . tableIndices os enz is -- generate indices for multiple dimensions- . S.map (\s -> (s:!:Z:!:getIdx s)) -- extract the right-most current index- $ mkStream ls (nonTermInnerOuter is os) (nonTermLeftIndex is os enz) -- TODO fix os is!- {-# INLINE mkStream #-}--instance- ( ValidIndex ls (is:.i)- , PA.MPrimArrayOps arr (is:.i) x- , NonTermValidIndex (is:.i)- ) => ValidIndex (ls :!: MTbl (is:.i) (PA.MutArr m (arr (is:.i) x))) (is:.i) where- validIndex (ls :!: MTbl es tbl) abc isi =- let (_,rght) = PA.boundsM tbl- in nonTermValidIndex es rght abc isi && validIndex ls abc isi- getParserRange (ls :!: MTbl es _) ix = getNonTermParserRange es ix $ getParserRange ls ix- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}--class NonTermValidIndex i where- nonTermValidIndex :: ENZ i -> i -> ParserRange i -> i -> Bool- getNonTermParserRange :: ENZ i -> i -> ParserRange i -> ParserRange i- nonTermInnerOuter :: i -> InOut i -> InOut i- nonTermLeftIndex :: i -> InOut i -> ENZ i -> i--instance NonTermValidIndex Z where- nonTermValidIndex Z Z Z Z = True- getNonTermParserRange Z Z Z = Z- nonTermInnerOuter Z Z = Z- nonTermLeftIndex Z Z Z = Z- {-# INLINE nonTermValidIndex #-}- {-# INLINE getNonTermParserRange #-}- {-# INLINE nonTermInnerOuter #-}- {-# INLINE nonTermLeftIndex #-}--instance NonTermValidIndex is => NonTermValidIndex (is:.Subword) where- nonTermValidIndex (es:.e) (ns:.Subword(_:.n)) (abc:.(a:!:b:!:c)) (is:.Subword(i:.j)) =- let minsize = max b (if e==EmptyT then 0 else 1)- in i>=a && i+minsize<=j && j<=n-c && nonTermValidIndex es ns abc is- getNonTermParserRange (es:.e) (is:._) (abc:.(a:!:b:!:c)) =- let b' = b + if e==EmptyT then 0 else 1- in getNonTermParserRange es is abc :. (a:!:b':!:c)- nonTermInnerOuter (is:._) (os:.Outer) = nonTermInnerOuter is os :. Inner Check Nothing- nonTermInnerOuter (is:._) (os:.Inner _ _) = nonTermInnerOuter is os :. Inner NoCheck Nothing- nonTermLeftIndex (is:.Subword(i:.j)) (os:.o) (es:.e)- | o==Outer && e==NonEmptyT = nonTermLeftIndex is os es :. subword i (j-1)- | otherwise = nonTermLeftIndex is os es :. subword i j- {-# INLINE nonTermValidIndex #-}- {-# INLINE getNonTermParserRange #-}- {-# INLINE nonTermInnerOuter #-}- {-# INLINE nonTermLeftIndex #-}---- TODO autogenerated, check correctness--instance NonTermValidIndex is => NonTermValidIndex (is:.PointL) where- nonTermValidIndex (es:.e) (ns:.PointL(_:.n)) (abc:.(a:!:b:!:c)) (is:.PointL(i:.j)) =- let minsize = max b (if e==EmptyT then 0 else 1)- in i>=a && i+minsize<=j && j<=n-c && nonTermValidIndex es ns abc is- getNonTermParserRange (es:.e) (is:._) (abc:.(a:!:b:!:c)) =- let b' = b + if e==EmptyT then 0 else 1- in getNonTermParserRange es is abc :. (a:!:b':!:c)- nonTermInnerOuter (is:._) (os:.Outer) = nonTermInnerOuter is os :. Inner Check Nothing- nonTermInnerOuter (is:._) (os:.Inner _ _) = nonTermInnerOuter is os :. Inner NoCheck Nothing- nonTermLeftIndex (is:.PointL(i:.j)) (os:.o) (es:.e)- | o==Outer && e==NonEmptyT = nonTermLeftIndex is os es :. pointL i (j-1)- | otherwise = nonTermLeftIndex is os es :. pointL i j- {-# INLINE nonTermValidIndex #-}- {-# INLINE getNonTermParserRange #-}- {-# INLINE nonTermInnerOuter #-}- {-# INLINE nonTermLeftIndex #-}----data BtTbl i xs f = BtTbl !(ENZ i) !xs !f -- (i -> m (S.Stream m b))--btTbl :: ENZ i -> xs -> f -> BtTbl i xs f --(i -> m (S.Stream m b)) -> BtTbl m i xs b-btTbl = BtTbl-{-# INLINE btTbl #-}--type DefBtTbl m isi x b = BtTbl isi (PA.Unboxed isi x) (isi -> m (S.Stream m b))-type SwBtTbl m x b = BtTbl Subword (PA.Unboxed (Z:.Subword) x) (Subword -> m (S.Stream m b))--instance Build (BtTbl i xs f)--instance- ( Elms ls Subword- ) => Elms (ls :!: SwBtTbl m x b) Subword where- data Elm (ls :!: SwBtTbl m x b) Subword = ElmSwBtTbl !(Elm ls Subword) !(x,m (S.Stream m b)) !Subword- type Arg (ls :!: SwBtTbl m x b) = Arg ls :. (x,m (S.Stream m b))- getArg !(ElmSwBtTbl ls x _) = getArg ls :. x- getIdx !(ElmSwBtTbl _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls Subword- , VU.Unbox x- , MkStream m ls Subword- ) => MkStream m (ls :!: SwBtTbl m x b) Subword where- mkStream !(ls:!:BtTbl ene tbl f) Outer !ij@(Subword (i:.j))- = S.mapM (\s -> let (Subword (_:.l)) = getIdx s in return $ ElmSwBtTbl s (tbl PA.! (Z:.subword l j), f $ subword l j) (subword l j))- $ mkStream ls (Inner Check Nothing) (subword i $ case ene of { EmptyT -> j ; NonEmptyT -> j-1 })- mkStream !(ls:!:BtTbl ene tbl f) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (_:.l)) = getIdx s- le = l + case ene of { EmptyT -> 0 ; NonEmptyT -> 1}- l' = case szd of Nothing -> le- Just z -> max le (j-z)- in return (s :!: l :!: l')- step !(s :!: k :!: l)- | l > j = return S.Done- | otherwise = return $ S.Yield (ElmSwBtTbl s (tbl PA.! (Z:.subword k l), f $ subword k l) (subword k l)) (s :!: k :!: l+1)- {-# INLINE mkStream #-}--instance- ( ValidIndex ls Subword- , VU.Unbox x- ) => ValidIndex (ls :!: SwBtTbl m x b) Subword where- validIndex (_ :!: BtTbl ZeroT _ _) _ _ = error "table with ZeroT found, there is no reason (actually: no implementation) for 1-dim ZeroT tables"- validIndex (ls :!: BtTbl ene tbl _) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- let (_,Z:.Subword (0:.n)) = PA.bounds tbl- minsize = max b (if ene==EmptyT then 0 else 1)- in i>=a && i+minsize<=j && j<=n-c && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: BtTbl ene _ f) ix = let (a:!:b:!:c) = getParserRange ls ix in if ene==EmptyT then (a:!:b:!:c) else (a:!:b+1:!:c)- {-# INLINE getParserRange #-}--instance- ( Elms ls (is:.i)- ) => Elms (ls :!: DefBtTbl m (is:.i) x b) (is:.i) where- data Elm (ls :!: DefBtTbl m (is:.i) x b) (is:.i) = ElmBtTbl !(Elm ls (is:.i)) !(x,m (S.Stream m b)) !(is:.i)- type Arg (ls :!: DefBtTbl m (is:.i) x b) = Arg ls :. (x,m (S.Stream m b))- getArg !(ElmBtTbl ls x _) = getArg ls :. x- getIdx !(ElmBtTbl _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , Elms ls (is:.i)- , ExtShape (is:.i)- , Shape (is:.i)- , VU.Unbox x- , NonTermValidIndex (is:.i)- , TableIndices (is:.i)- , MkStream m ls (is:.i)- ) => MkStream m (ls:!:DefBtTbl m (is:.i) x b) (is:.i) where- mkStream (ls :!: BtTbl enz tbl f) os is- = S.map (\(s:!:Z:!:β) -> ElmBtTbl s (tbl PA.! β,f β) β) -- extract data using β index- . tableIndices os enz is -- generate indices for multiple dimensions- . S.map (\s -> (s:!:Z:!:getIdx s)) -- extract the right-most current index- $ mkStream ls (nonTermInnerOuter is os) (nonTermLeftIndex is os enz) -- TODO fix os is!- {-# INLINE mkStream #-}--instance- ( ValidIndex ls (is:.i)- , Shape (is:.i)- , ExtShape (is:.i)- , VU.Unbox x- , NonTermValidIndex (is:.i)- ) => ValidIndex (ls :!: DefBtTbl m (is:.i) x b) (is:.i) where- validIndex (ls :!: BtTbl es tbl f) abc isi =- let (_,rght) = PA.bounds tbl- in nonTermValidIndex es rght abc isi && validIndex ls abc isi- getParserRange (ls :!: BtTbl es _ _) ix = getNonTermParserRange es ix $ getParserRange ls ix- {-# INLINE validIndex #-}- {-# INLINE getParserRange #-}----class EmptyTable x where- toEmptyT :: x -> x- toNonEmptyT :: x -> x--instance (EmptyENZ (ENZ i)) => EmptyTable (MTbl i xs) where- toEmptyT (MTbl enz xs) = MTbl (toEmptyENZ enz) xs- toNonEmptyT (MTbl enz xs) = MTbl (toNonEmptyENZ enz) xs- {-# INLINE toEmptyT #-}- {-# INLINE toNonEmptyT #-}--instance (EmptyENZ (ENZ i)) => EmptyTable (BtTbl i xs f) where- toEmptyT (BtTbl enz xs f) = BtTbl (toEmptyENZ enz) xs f- toNonEmptyT (BtTbl enz xs f) = BtTbl (toNonEmptyENZ enz) xs f- {-# INLINE toEmptyT #-}- {-# INLINE toNonEmptyT #-}-----{----- * Backtracking tables.--data BtTbl m x b = BtTbl ENE !(PA.Unboxed (Z:.Subword) x) !(Subword -> m (S.Stream m b))--instance Build (BtTbl m x b)--instance- ( Monad m- , Elms ls Subword- ) => Elms (ls :!: BtTbl m x b) Subword where- data Elm (ls :!: BtTbl m x b) Subword = ElmBtTbl !(Elm ls Subword) !x !(m (S.Stream m b)) !Subword- type Arg (ls :!: BtTbl m x b) = Arg ls :. (x,m (S.Stream m b))- getArg !(ElmBtTbl ls x b _) = getArg ls :. (x,b)- getIdx !(ElmBtTbl _ _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls :!: BtTbl m x b) Subword where- mkStream !(ls:!:BtTbl ene xs f) Outer !ij@(Subword (i:.j))- = S.map (\s -> let (Subword (k:.l)) = getIdx s in ElmBtTbl s (xs PA.! (Z:.subword l j)) (f $ subword l j) (subword l j))- $ mkStream ls (Inner Check Nothing) (subword i $ case ene of { EmptyT -> j ; NoEmptyT -> j-1 })- mkStream !(ls:!:BtTbl ene xs f) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (k:.l)) = getIdx s- le = l + case ene of { EmptyT -> 0 ; NoEmptyT -> 1}- l' = case szd of Nothing -> le- Just z -> max le (j-z)- in return (s:!:l:!: l')- step !(s:!:k:!:l)- | l > j = return $ S.Done- | otherwise = return $ S.Yield (ElmBtTbl s (xs PA.! (Z:.subword k l)) (f $ subword k l) (subword k l)) (s:!:k:!:l+1)- {-# INLINE mkStream #-}------ * Unboxed mutable table for the forward phase in one dimension.--data MTbl xs = MTbl !ENE !xs--instance- ( ValidIndex ls Subword- , Monad m- , PA.MPrimArrayOps arr (Z:.Subword) x- ) => ValidIndex (ls:!:MTbl (PA.MutArr m (arr (Z:.Subword) x))) Subword where- validIndex (_ :!: MTbl ZeroT _) _ _ = error "table with ZeroT found, there is no reason (actually: no implementation) for 1-dim ZeroT tables"- validIndex (ls :!: MTbl ene tbl) abc@(a:!:b:!:c) ij@(Subword (i:.j)) =- let (_,Z:.Subword (0:.n)) = PA.boundsM tbl- minsize = max b (if ene==EmptyT then 0 else 1)- in i>=a && i+minsize<=j && j<=n-c && validIndex ls abc ij- {-# INLINE validIndex #-}- getParserRange (ls :!: MTbl ene _) ix = let (a:!:b:!:c) = getParserRange ls ix in if ene==EmptyT then (a:!:b:!:c) else (a:!:b+1:!:c)- {-# INLINE getParserRange #-}--instance Build (MTbl xs)--instance- ( Monad m- , Elms ls Subword- ) => Elms (ls :!: MTbl (PA.MutArr m (arr (Z:.Subword) x))) Subword where- data Elm (ls :!: MTbl (PA.MutArr m (arr (Z:.Subword) x))) Subword = ElmMTbl !(Elm ls Subword) !x !Subword- type Arg (ls :!: MTbl (PA.MutArr m (arr (Z:.Subword) x))) = Arg ls :. x- getArg !(ElmMTbl ls x _) = getArg ls :. x- getIdx !(ElmMTbl _ _ i) = i- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( PrimMonad m- , PA.MPrimArrayOps arr (Z:.Subword) x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:MTbl (PA.MutArr m (arr (Z:.Subword) x))) Subword where- mkStream !(ls:!:MTbl ene tbl) Outer !ij@(Subword (i:.j))- = S.mapM (\s -> let (Subword (_:.l)) = getIdx s in PA.readM tbl (Z:.subword l j) >>= \z -> return $ ElmMTbl s z (subword l j))- $ mkStream ls (Inner Check Nothing) (subword i $ case ene of { EmptyT -> j ; NoEmptyT -> j-1 })- mkStream !(ls:!:MTbl ene tbl) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (_:.l)) = getIdx s- le = l + case ene of { EmptyT -> 0 ; NoEmptyT -> 1}- l' = case szd of Nothing -> le- Just z -> max le (j-z)- in return (s :!: l :!: l')- step !(s :!: k :!: l)- | l > j = return S.Done- | otherwise = PA.readM tbl (Z:.subword k l) >>= \z -> return $ S.Yield (ElmMTbl s z (subword k l)) (s :!: k :!: l+1)- {-# INLINE mkStream #-}----{----- ** multi-tape generalization: empty / nonempty--instance- ( ValidIndex ls (is:.i)- , Monad m- , PA.MPrimArrayOps arr (is:.i) x- ) => ValidIndex (ls :!: MTbl (PA.MutArr m (arr (is:.i) x))) (is:.i) where- validIndex (ls :!: MTbl ene tbl) (is:.i) =- let- in undefined--instance- ( Monad m- ) => Elms (ls :!: MTbl (PA.MutArr m (arr (is:.i) x))) (is:.i) where--instance- ( Monad m- ) => MkStream m (ls:!: MTbl (PA.MutArr m (arr (is:.i) x))) (is:.i) where- mkStream !(ls:!:MTbl ene tbl) io is- = undefined----{--data GMtbl i x = forall m . GMtbl (ENEdim i) (PA.MutArr m (Storage i x))---}---}---}---{----- * Immutable tables.--data Tbl x = Tbl !(PA.Unboxed (Z:.Subword) x)--instance Build (Tbl x)--instance- ( Elms ls Subword- ) => Elms (ls :!: Tbl x) Subword where- data Elm (ls :!: Tbl x) Subword = ElmTbl !(Elm ls Subword) !x !Subword- type Arg (ls :!: Tbl x) = Arg ls :. x- getArg !(ElmTbl ls x _) = getArg ls :. x- getIdx !(ElmTbl _ _ idx) = idx- {-# INLINE getArg #-}- {-# INLINE getIdx #-}--instance- ( Monad m- , VU.Unbox x- , Elms ls Subword- , MkStream m ls Subword- ) => MkStream m (ls:!:Tbl x) Subword where- mkStream !(ls:!:Tbl xs) Outer !ij@(Subword (i:.j)) = S.map (\s -> let (Subword (k:.l)) = getIdx s in ElmTbl s (xs PA.! (Z:.subword l j)) (subword l j)) $ mkStream ls (Inner Check Nothing) ij- mkStream !(ls:!:Tbl xs) (Inner _ szd) !ij@(Subword (i:.j)) = S.flatten mk step Unknown $ mkStream ls (Inner NoCheck Nothing) ij where- mk !s = let (Subword (k:.l)) = getIdx s- le = l -- TODO need to add ENE here ! -- + case ene of { EmptyT -> 0 ; NoEmptyT -> 1}- l' = case szd of Nothing -> le- Just z -> max le (j-z)- in return (s :!: l :!: l')- step !(s :!: k :!: l)- | l > j = return S.Done- | otherwise = return $ S.Yield (ElmTbl s (xs PA.! (Z:.subword k l)) (subword k l)) (s :!: k :!: l+1)- {-# INLINE mkStream #-}----}--
+ ADP/Fusion/Term.hs view
@@ -0,0 +1,17 @@++module ADP.Fusion.Term+ ( module ADP.Fusion.Term.Chr+ , module ADP.Fusion.Term.Deletion+ , module ADP.Fusion.Term.Edge+ , module ADP.Fusion.Term.Epsilon+ , module ADP.Fusion.Term.PeekIndex+ , module ADP.Fusion.Term.Strng+ ) where++import ADP.Fusion.Term.Chr+import ADP.Fusion.Term.Deletion+import ADP.Fusion.Term.Edge+import ADP.Fusion.Term.Epsilon+import ADP.Fusion.Term.PeekIndex+import ADP.Fusion.Term.Strng+
+ ADP/Fusion/Term/Chr.hs view
@@ -0,0 +1,197 @@++module ADP.Fusion.Term.Chr+ ( module ADP.Fusion.Term.Chr.Type+ , module ADP.Fusion.Term.Chr.Point+ , module ADP.Fusion.Term.Chr.Subword+ ) where++import ADP.Fusion.Term.Chr.Point+import ADP.Fusion.Term.Chr.Subword+import ADP.Fusion.Term.Chr.Type++++++++{-++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE UndecidableInstances #-}++-- |+--+-- TODO PointL , PointR need sanity checks for boundaries++module ADP.Fusion.Term.Chr where++import Control.Exception(assert)+import qualified Data.Vector.Fusion.Stream.Monadic as S+import qualified Data.Vector.Unboxed as VU++import Data.PrimitiveArray -- ((:.)(..), Subword(..), subword, PointL(..), pointL, PointR(..), pointR, Outside(..))+++import Debug.Trace++++++-- ** @PointL@ single-dim instances++{-+instance+ ( Monad m+ , Element ls PointL+ , MkStream m ls PointL+ ) => MkStream m (ls :!: Chr r x) PointL where+ mkStream (ls :!: Chr f xs) Static lu@(PointL (l:.u)) (PointL (i:.j))+ = staticCheck (j>l && j>0 && j<=u && j<= VG.length xs) $+ let !z = () -- f xs (j-1) -- let-floating leads to too early evaluation+ in S.map (ElmChr (f xs $ j-1) (pointL (j-1) j))+ $ mkStream ls Static lu (pointL i $ j-1)+-- mkStream _ _ _ _ = error "mkStream / Chr / PointL not implemented"+ {-# INLINE mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: Chr r x) (Outside PointL) where+ mkStream (ls :!: Chr f xs) Static lu@(O (PointL (l:.u))) (O (PointL (i:.j)))+ = staticCheck (j<u) $+ let !z = f xs j+ in S.map (ElmChr z (O . pointL j $ j+1))+ $ mkStream ls Static lu (O . pointL i $ j+1)+-- mkStream _ _ _ _ = error "mkStream / Chr / Outside PointL not implemented"+ {-# INLINE mkStream #-}+-}+++-- ** @Subword@ single-dim instances++{-+instance+ ( Monad m+ , Element ls Subword+ , MkStream m ls Subword+ ) => MkStream m (ls :!: Chr r x) Subword where+ mkStream (ls :!: Chr f xs) Static lu@(Subword (l:.u)) ij@(Subword (i:.j))+ -- We use a static check here as we can then pull out the @z@ character+ -- lookup. In the Nussinov example (X -> f <<< z1 t z2 t) this gives+ -- a 3x performance improvement. Note that this benchmark is a bit+ -- artificial.+ --+ -- The static part is called @right-most@, i.e. when only terminals with+ -- known fixed sizes are on the right of this terminal.+ = staticCheck (j>0 && j<=u) $+ let !z = f xs (j-1)+ in S.map (ElmChr z (subword (j-1) j))+ $ mkStream ls Static lu (subword i $ j-1)+ mkStream (ls :!: Chr f xs) v lu ij@(Subword (i:.j))+ -- This version is used when to right, we already had variable-size+ -- (non-)terminals to the right.+ = S.map (\s -> let Subword (k:.l) = getIdx s+ in ElmChr (f xs l) (subword l $ l+1) s+ )+ $ mkStream ls v lu (subword i $ j-1)+ {-# INLINE mkStream #-}+-}++-- Note how the indices grow to the outside!++{-+instance+ ( Monad m+ , Element ls (Outside Subword)+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: Chr r x) (Outside Subword) where+ -- For the static case, we move the @j@ index.+ mkStream (ls :!: Chr f xs) Static lu@(O (Subword (l:.u))) ij@(O (Subword (i:.j)))+ = staticCheck (j>=0 && j<u) $+ let !z = f xs j+ in S.map (ElmChr z (O $ subword j (j+1)))+ $ mkStream ls Static lu (O $ subword i $ j+1)+ -- In the variable case, (i) we set @i@ to @i-1@ going further down. (ii) On+ -- going back up, we extract the rightmost index of the left symbol @l@ --+ -- which could be @i-1@ but need not be.+ mkStream (ls :!: Chr f xs) v lu ij@(O (Subword (i:.j)))+ = S.map (\s -> let O (Subword (_:.l)) = getIdx s+ in ElmChr (f xs l) (O . subword l $ l+1) s+ )+ $ mkStream ls v lu (O $ subword (i-1) j)+ {-# INLINE mkStream #-}+-}++++{-++-- * Multi-dimensional stuff++{-+instance TermStaticVar (Chr r x) Subword where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ (Subword (i:.j)) = subword i $ j-1+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}+-}++instance TermStaticVar (Chr r x) PointR where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ (PointR (i:.j)) = pointR i $ j-1+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++-- TODO removed the static check since *in principle* the statics system down+-- at the bottom of the stack should take care of it! Need to verify with+-- QuickCheck, though.++{-+instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a (Chr r x)) (is:.Subword) where+ terminalStream (a:>Chr f (!v)) (sv:.Static) (is:.Subword (i:.j))+ = id -- staticCheck (j>0)+ . S.map (\(Qd s (z:._) is e) -> Qd s z (is:.subword (j-1) j) (e:.f v (j-1)))+ . terminalStream a sv is+ . S.map (\(Tr s z (is:.i)) -> Tr s (z:.i) is)+ terminalStream (a:>Chr f (!v)) (sv:._) (is:.Subword (i:.j))+ = S.map (\(Qd s (z:.Subword (k:.l)) is e) -> Qd s z (is:.subword l (l+1)) (e:.f v (l-1)))+ . terminalStream a sv is+ . S.map (\(Tr s z (is:.i)) -> Tr s (z:.i) is)+ {-# INLINE terminalStream #-}+-}++{-+instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a (Chr r x)) (is:.PointR) where+ terminalStream (a:>Chr f (!v)) (sv:.Static) (is:.PointR (i:.j))+ = S.map (\(Qd s (z:._) is e) -> Qd s z (is:.pointR (j-1) j) (e:.f v (j-1)))+ . terminalStream a sv is+ . S.map (\(Tr s z (is:.i)) -> Tr s (z:.i) is)+ terminalStream (a:>Chr f (!v)) (sv:._) (is:.PointR (i:.j))+ = S.map (\(Qd s (z:.PointR (k:.l)) is e) -> Qd s z (is:.pointR l (l+1)) (e:.f v (l-1)))+ . terminalStream a sv is+ . S.map (\(Tr s z (is:.i)) -> Tr s (z:.i) is)+ {-# INLINE terminalStream #-}+-}++-}+++-}+
+ ADP/Fusion/Term/Chr/Point.hs view
@@ -0,0 +1,91 @@++module ADP.Fusion.Term.Chr.Point where++import Data.Strict.Tuple+import Debug.Trace+import qualified Data.Vector.Fusion.Stream.Monadic as S+import qualified Data.Vector.Generic as VG++import Data.PrimitiveArray++import ADP.Fusion.Base+import ADP.Fusion.Term.Chr.Type+++instance+ ( Monad m+ , Element ls PointL+ , MkStream m ls PointL+ ) => MkStream m (ls :!: Chr r x) PointL where+ mkStream (ls :!: Chr f xs) (IStatic d) (PointL u) (PointL i)+ = staticCheck (i>0 && i<=u && i<= VG.length xs)+ $ S.map (ElmChr (f xs $ i-1) (PointL $ i) (PointL 0))+ $ mkStream ls (IStatic d) (PointL u) (PointL $ i-1)+ mkStream _ _ _ _ = error "mkStream / Chr / PointL can only be implemented for IStatic"+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: Chr r x) (Outside PointL) where+ mkStream (ls :!: Chr f xs) (OStatic d) (O (PointL u)) (O (PointL i))+ = S.map (\z -> let (O (PointL k)) = getOmx z in ElmChr (f xs $ k-d-1) (O . PointL $ k-d) (getOmx z) z)+ $ mkStream ls (OStatic $ d+1) (O $ PointL u) (O $ PointL i)+ mkStream _ _ _ _ = error "Chr.Point / mkStream / Chr / Outside.PointL can only be implemented for OStatic"+ {-# Inline mkStream #-}++-- TODO @Inline [0]@ ???++instance TermStaticVar (Chr r x) PointL where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ (PointL j) = PointL $ j-1+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance TermStaticVar (Chr r x) (Outside PointL) where+ termStaticVar _ (OStatic d) _ = OStatic (d+1) + termStreamIndex _ _ j = j+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a (Chr r x)) (is:.PointL) where+ terminalStream (a:|Chr f (!v)) (sv:.IStatic _) (is:.i@(PointL j))+ = S.map (\(S6 s (zi:._) (zo:._) is os e) -> S6 s zi zo (is:.PointL j) (os:.PointL 0) (e:.f v (j-1)))+ . iPackTerminalStream a sv (is:.i)+ {-+ . terminalStream a sv is+ . S.map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ -}+ terminalStream (a:|Chr f (!v)) (sv:._) (is:.i@(PointL _))+ = S.map (\(S6 s (zi:.PointL k) (zo:.PointL l) is os e) -> S6 s zi zo (is:.PointL (k+1)) (os:.PointL 0) (e:.f v (l-1)))+ . iPackTerminalStream a sv (is:.i)+ {-+ . terminalStream a sv is+ . S.map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ -}+ {-# INLINE terminalStream #-}++instance+ ( Monad m+ , TerminalStream m a (Outside is)+ , Context (Outside (is:.PointL)) ~ (Context (Outside is) :. OutsideContext Int)+ ) => TerminalStream m (TermSymbol a (Chr r x)) (Outside (is:.PointL)) where+ terminalStream (a:|Chr f (!v)) (sv:.OStatic d) (O (is:.i))+ = S.map (\(S6 s (zi:._) (zo:.(PointL k)) (O is) (O os) e) -> S6 s zi zo (O (is:.(PointL $ k-d))) (O (os:.PointL k)) (e:.f v (k-d-1)))+ . oPackTerminalStream a sv (O (is:.i))+ {-+ . terminalStream a sv (O is)+ . S.map (\(S5 s zi zo (O (is:.i)) (O (os:.o))) -> S5 s (zi:.i) (zo:.o) (O is) (O os))+ -}+ {-+ terminalStream (a:|Chr f (!v)) (sv:._) (is:.PointL i)+ = S.map (\(S6 s (zi:.PointL k) (zo:.PointL l) is os e) -> S6 s zi zo (is:.PointL (k+1)) (os:.PointL 0) (e:.f v (l-1)))+ . terminalStream a sv is+ . S.map (\(S5 s zi zo (is:.i) (os:.o)) -> S5 s (zi:.i) (zo:.o) is os)+ -}+ {-# INLINE terminalStream #-}+
+ ADP/Fusion/Term/Chr/Subword.hs view
@@ -0,0 +1,61 @@++module ADP.Fusion.Term.Chr.Subword where++import Data.Strict.Tuple+import Data.Vector.Fusion.Util (delay_inline)+import Debug.Trace+import Data.Vector.Fusion.Stream.Monadic as S+import qualified Data.Vector.Generic as VG+import Prelude hiding (map)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.Term.Chr.Type++++instance+ ( Monad m+ , Element ls Subword+ , MkStream m ls Subword+ ) => MkStream m (ls :!: Chr r x) Subword where+ mkStream (ls :!: Chr f xs) (IStatic ()) hh (Subword (i:.j))+ = staticCheck (i>=0 && i<j && j<= VG.length xs)+ $ map (ElmChr (f xs $ j-1) (subword (j-1) j) (subword 0 0))+ $ mkStream ls (IStatic ()) hh (delay_inline Subword (i:.j-1))+ mkStream (ls :!: Chr f xs) (IVariable ()) hh (Subword (i:.j))+ = map (\s -> let Subword (_:.l) = getIdx s+ in ElmChr (f xs l) (subword l (l+1)) (subword 0 0) s)+ $ mkStream ls (IVariable ()) hh (delay_inline Subword (i:.j-1))+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , Element ls (Outside Subword)+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: Chr r x) (Outside Subword) where+ mkStream (ls :!: Chr f xs) (OStatic (di:.dj)) u ij@(O (Subword (i:.j)))+ = id -- staticCheck ( j < h ) -- TODO any check possible?+ $ map (\s -> let (O (Subword (_:.k'))) = getIdx s+ k = k'-dj-1+ in ElmChr (f xs k) (O $ subword (k'-1) k') (getOmx s) s)+ $ mkStream ls (OStatic (di:.dj+1)) u ij+ mkStream (ls :!: Chr f xs) (ORightOf (di:.dj)) u ij+ = map (\s -> let (O (Subword (_:.k'))) = getIdx s+ k = k'-dj-1+ in ElmChr (f xs k) (O $ subword (k'-1) k') (getOmx s) s)+ $ mkStream ls (ORightOf (di:.dj+1)) u ij+ mkStream (ls :!: Chr f xs) (OFirstLeft (di:.dj)) u ij+ = id+ $ map (\s -> let (O (Subword (_:.k))) = getIdx s+ in ElmChr (f xs k) (O $ subword k (k+1)) (getOmx s) s)+ $ mkStream ls (OFirstLeft (di+1:.dj)) u ij+ mkStream (ls :!: Chr f xs) (OLeftOf (di:.dj)) u ij+ = map (\s -> let (O (Subword (_:.k))) = getIdx s+ in ElmChr (f xs k) (O $ subword k (k+1)) (getOmx s) s)+ $ mkStream ls (OLeftOf (di+1:.dj)) u ij+ {-# Inline mkStream #-}+
+ ADP/Fusion/Term/Chr/Type.hs view
@@ -0,0 +1,57 @@++module ADP.Fusion.Term.Chr.Type where++import Data.Strict.Tuple+import qualified Data.Vector.Generic as VG++import Data.PrimitiveArray++import ADP.Fusion.Base+++-- | A generic Character parser that reads a single character but allows+-- passing additional information.+--+-- 'Chr' expects a function to retrieve @r@ at index position, followed by+-- the actual generic vector with data.++data Chr r x where+ Chr :: VG.Vector v x+ => !(v x -> Int -> r)+ -> !(v x)+ -> Chr r x++-- | smart constructor for regular 1-character parsers++--chr xs = Chr VG.unsafeIndex xs+chr xs = Chr (VG.unsafeIndex) xs+--chr xs = Chr (VG.!) xs+{-# Inline chr #-}++-- | Smart constructor for Maybe Peeking, followed by a character.++chrLeft xs = Chr f xs where+ f xs k = ( xs VG.!? (k-1)+ , VG.unsafeIndex xs k+ )+ {-# Inline [0] f #-}+{-# Inline chrLeft #-}++instance Build (Chr r x)++instance+ ( Element ls i+ ) => Element (ls :!: Chr r x) i where+ data Elm (ls :!: Chr r x) i = ElmChr !r !i !i !(Elm ls i)+ type Arg (ls :!: Chr r x) = Arg ls :. r+ getArg (ElmChr x _ _ ls) = getArg ls :. x+ getIdx (ElmChr _ i _ _ ) = i+ getOmx (ElmChr _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance (Show i, Show r, Show (Elm ls i)) => Show (Elm (ls :!: Chr r x) i)++type instance TermArg (TermSymbol a (Chr r x)) = TermArg a :. r+
+ ADP/Fusion/Term/Deletion.hs view
@@ -0,0 +1,76 @@++module ADP.Fusion.Term.Deletion+ ( module ADP.Fusion.Term.Deletion.Type+ , module ADP.Fusion.Term.Deletion.Point+ ) where++import ADP.Fusion.Term.Deletion.Point+import ADP.Fusion.Term.Deletion.Type+++{-+import Data.Strict.Maybe+import Data.Strict.Tuple+import Prelude hiding (Maybe(..))+import qualified Data.Vector.Fusion.Stream.Monadic as S++import Data.PrimitiveArray -- (Z(..), (:.)(..), Subword(..), subword, PointL(..), pointL, PointR(..), pointR)++import ADP.Fusion.Term.Classes+import ADP.Fusion.Term.Multi.Classes+++++none = None+{-# INLINE none #-}++-- | Since 'None' doesn't really do anything for all indices, we just thread it+-- through.++instance TermStaticVar None ix where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ ij = ij+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a None) (is:.PointL) where+ terminalStream (a:|None) (sv:._) (is:._)+ = S.map (\(Qd s (z:.i) is e) -> Qd s z (is:.i) (e:.()))+ . terminalStream a sv is+ . S.map moveIdxTr+ {-# INLINE terminalStream #-}++++-- * Single dimensional instances for 'None' are really weird++{-+instance Element ls Subword => Element (ls :!: None) Subword where+ data Elm (ls :!: None) Subword = ElmNone !Subword !(Elm ls Subword)+ type Arg (ls :!: None) = Arg ls :. ()+ getArg (ElmNone _ l) = getArg l :. ()+ getIdx (ElmNone i _) = i+ {-# INLINE getArg #-}+ {-# INLINE getIdx #-}+-}++-- | The instance does nothing (except insert @()@ into the argument+-- stack).++{-+instance+ ( Monad m+ , MkStream m ls Subword+ ) => MkStream m (ls :!: None) Subword where+ mkStream (ls :!: None) sv lu ij+ = S.map (ElmNone ij)+ $ mkStream ls sv lu ij+ {-# INLINE mkStream #-}+-}++-}+
+ ADP/Fusion/Term/Deletion/Point.hs view
@@ -0,0 +1,62 @@++module ADP.Fusion.Term.Deletion.Point where++import Data.Strict.Tuple+import qualified Data.Vector.Fusion.Stream.Monadic as S++import Data.PrimitiveArray++import ADP.Fusion.Base+import ADP.Fusion.Term.Deletion.Type++++instance+ ( Monad m+ , MkStream m ls PointL+ ) => MkStream m (ls :!: Deletion) PointL where+ mkStream (ls :!: Deletion) (IStatic d) (PointL u) (PointL i)+ = S.map (ElmDeletion (PointL i) (PointL 0))+ $ mkStream ls (IStatic d) (PointL u) (PointL i)+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: Deletion) (Outside PointL) where+ mkStream (ls :!: Deletion) (OStatic d) (O (PointL u)) (O (PointL i))+ = S.map (\z -> ElmDeletion (O $ PointL i) (getOmx z) z)+ $ mkStream ls (OStatic d) (O $ PointL u) (O $ PointL i)+ {-# Inline mkStream #-}++instance TermStaticVar Deletion PointL where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ (PointL j) = PointL j+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance TermStaticVar Deletion (Outside PointL) where+ termStaticVar _ (OStatic d) _ = OStatic d+ termStreamIndex _ _ j = j+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a Deletion) (is:.PointL) where+ terminalStream (a:|Deletion) (sv:.IStatic _) (is:.i@(PointL j))+ = S.map (\(S6 s (zi:._) (zo:._) is os e) -> S6 s zi zo (is:.PointL j) (os:.PointL 0) (e:.()))+ . iPackTerminalStream a sv (is:.i)+ {-# Inline terminalStream #-}++instance+ ( Monad m+ , TerminalStream m a (Outside is)+ ) => TerminalStream m (TermSymbol a Deletion) (Outside (is:.PointL)) where+ terminalStream (a:|Deletion) (sv:.OStatic d) (O (is:.i))+ = S.map (\(S6 s (zi:._) (zo:.PointL k) (O is) (O os) e) -> S6 s zi zo (O (is:.(PointL $ k-d))) (O (os:.PointL k)) (e:.()))+ . oPackTerminalStream a sv (O (is:.i))+ {-# Inline terminalStream #-}+
+ ADP/Fusion/Term/Deletion/Type.hs view
@@ -0,0 +1,27 @@++module ADP.Fusion.Term.Deletion.Type where++import Data.Strict.Tuple++import Data.PrimitiveArray++import ADP.Fusion.Base++++data Deletion = Deletion++instance Build Deletion++instance (Element ls i) => Element (ls :!: Deletion) i where+ data Elm (ls :!: Deletion) i = ElmDeletion !i !i !(Elm ls i)+ type Arg (ls :!: Deletion) = Arg ls :. ()+ getArg (ElmDeletion _ _ l) = getArg l :. ()+ getIdx (ElmDeletion i _ _) = i+ getOmx (ElmDeletion _ o _) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++type instance TermArg (TermSymbol a Deletion) = TermArg a :. ()+
+ ADP/Fusion/Term/Edge.hs view
@@ -0,0 +1,64 @@++module ADP.Fusion.Term.Edge+ ( module ADP.Fusion.Term.Edge.Type+ , module ADP.Fusion.Term.Edge.Set+ ) where++import ADP.Fusion.Term.Edge.Set+import ADP.Fusion.Term.Edge.Type++++{-+-- | An edge terminal returns the pair of indices forming the edge.++data Edge e where+ Edge :: !(Int -> Int -> e) -> Edge e++edge = (,)+{-# Inline edge #-}++instance Build (Edge i)++instance+ (Element ls i+ ) => Element (ls :!: Edge e) i where+ data Elm (ls :!: Edge e) i = ElmEdge !e !i !(Elm ls i)+ type Arg (ls :!: Edge e) = Arg ls :. e+ getArg (ElmEdge e _ ls) = getArg ls :. e+ getIdx (ElmEdge _ i _ ) = i+ {-# Inline getArg #-}+ {-# Inline getIdx #-}++instance+ ( Monad m+ , Element ls (BitSet:>Interface First:>Interface Last)+ , MkStream m ls (BitSet:>Interface First:>Interface Last)+ ) => MkStream m (ls :!: Edge e) (BitSet:>Interface First:>Interface Last) where+ -- encodes in the first index arg, what the previously set @Last@ was+ mkStream (ls :!: Edge f) Static s@(BitSet zb:>Interface zi:>Interface zj) (BitSet b:>Interface i:>Interface j)+ -- if we have @popCount b == 1@, then this is an initial node,+ -- creating the first node. Otherwise the edge just extends an+ -- existing node.+ -- TODO need to figure out this "first node" stuff here+ = S.map (\z -> let (BitSet zb:>_:>Interface zj) = getIdx z+ in ElmEdge (f zj j) (BitSet b:>Interface i:>Interface j) z+ )+ $ mkStream ls (Variable Check (Just (popCount b -1) )) s (BitSet (clearBit b j):>Interface i:>Interface j)+ -- in the variable case, the @Last@ point is unset and may move freely.+ -- @First@ is still fixed. In @k@, we have the number of bits from+ -- @BitSet b@ that we should set! The bit we set is also the @Last@+ -- interface bit.+ mkStream (ls :!: Edge f) (Variable Check (Just k)) s@(BitSet zb:>Interface zi:>Interface zj) c@(BitSet b:>Interface i:>_)+ = S.flatten mk step Unknown+ $ mkStream ls (Variable Check (Just $ k-1)) s c+ where mk z = let (BitSet z':>_:>_) = getIdx z ; a = b `xor` z' in return (z,a,lsbActive a)+ step (z,a,lsbA)+ | lsbA < 0 = return $ S.Done+ | otherwise = return $ S.Yield (ElmEdge (f cj lsbA) (BitSet (cs .|. bit lsbA):>Interface ci:>Interface lsbA) z) (z,a,nextActive lsbA a)+ where (BitSet cs:>Interface ci:>Interface cj) = getIdx z+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}+-}+
+ ADP/Fusion/Term/Edge/Set.hs view
@@ -0,0 +1,73 @@++module ADP.Fusion.Term.Edge.Set where++import Data.Bits+import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic+import Data.Vector.Fusion.Stream.Size+import Debug.Trace+import Prelude hiding (map)++import Data.PrimitiveArray hiding (map)+import Data.Bits.Ordered++import ADP.Fusion.Base+import ADP.Fusion.Term.Edge.Type++++instance+ ( Monad m+ , Element ls (BS2I First Last)+ , MkStream m ls (BS2I First Last)+ ) => MkStream m (ls :!: Edge e) (BS2I First Last) where+ mkStream (ls :!: Edge f) (IStatic rp) u sij@(s:>i:>j)+ = flatten mk step Unknown $ mkStream ls (IStatic rpn) u tik+ where rpn | j >= 0 = rp+ | otherwise = rp+1+ tik | j >= 0 = s `clearBit` (getIter j) :> i :> undefi+ | otherwise = sij+ mk z+ | j >= 0 && popCount s >= 2 = return $ This z+ | j < 0 && popCount s >= 2 = return $ That (z,bits,maybeLsb bits)+ | popCount s <= max 1 rp = return $ Naught+ | otherwise = error $ show ("Edge",s,i,j)+ where (zs:>_:>zk) = getIdx z+ bits = s `xor` zs+ step Naught = return Done+ step (This z)+ | popCount zs == 0 = return $ Done+ | otherwise = return $ Yield (ElmEdge (f (getIter zk) (getIter j)) sij undefbs2i z) Naught+ where (zs:>_:>zk) = getIdx z+ step (That (z,bits,Nothing)) = return $ Done+ step (That (z,bits,Just j')) = let (zs:>_:>Iter zk) = getIdx z+ tij' = (zs .|. bit j') :> Iter zk :> Iter j'+ in return $ Yield (ElmEdge (f zk j') tij' undefbs2i z) (That (z,bits,maybeNextActive j' bits))+ {-# Inline [0] mk #-}+ {-# Inline [0] step #-}+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , Element ls (Outside (BS2I First Last))+ , MkStream m ls (Outside (BS2I First Last))+ ) => MkStream m (ls :!: Edge f) (Outside (BS2I First Last)) where+ mkStream (ls :!: Edge f) (OStatic ()) u sij+ = map undefined+ $ mkStream ls (undefined) u sij+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , Element ls (Complement (BS2I First Last))+ , MkStream m ls (Complement (BS2I First Last))+ ) => MkStream m (ls :!: Edge f) (Complement (BS2I First Last)) where+ mkStream (ls :!: Edge f) Complemented u sij+ = map undefined+ $ mkStream ls Complemented u sij+ {-# Inline mkStream #-}+
+ ADP/Fusion/Term/Edge/Type.hs view
@@ -0,0 +1,32 @@++module ADP.Fusion.Term.Edge.Type where++import Data.Strict.Tuple++import Data.PrimitiveArray++import ADP.Fusion.Base++++data Edge e where+ Edge :: (Int -> Int -> e) -> Edge e++instance Build (Edge e)++instance+ ( Element ls i+ ) => Element (ls :!: Edge e) i where+ data Elm (ls :!: Edge e) i = ElmEdge !e !i !i (Elm ls i)+ type Arg (ls :!: Edge e) = Arg ls :. e+ getArg (ElmEdge e _ _ ls) = getArg ls :. e+ getIdx (ElmEdge _ i _ _ ) = i+ getOmx (ElmEdge _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance (Show i, Show e, Show (Elm ls i)) => Show (Elm (ls :!: Edge e) i)++type instance TermArg (TermSymbol a (Edge e)) = TermArg a :. e+
+ ADP/Fusion/Term/Epsilon.hs view
@@ -0,0 +1,116 @@++module ADP.Fusion.Term.Epsilon+ ( module ADP.Fusion.Term.Epsilon.Type+ , module ADP.Fusion.Term.Epsilon.Point+ , module ADP.Fusion.Term.Epsilon.Subword+ ) where++import ADP.Fusion.Term.Epsilon.Point+import ADP.Fusion.Term.Epsilon.Subword+import ADP.Fusion.Term.Epsilon.Type++{-++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}++-- | The 'Empty' terminal symbol parses only the empty (sub-)input. @Empty@+-- however, can mean different things.+--+-- 'Empty' needs to be bound to the input. We require this as certain index+-- structures have no natural notion of emptyness -- unless additional+-- information is given.+--+-- Consider, for example, linear grammars. Left-linear grammars can compare the+-- index @i@ to zero, @i==0@ to test for emptyness, while for right-linear+-- grammars, we need to test @i==N@ with @N@ the size of the input. Instead of+-- carrying @N@ around in the index, we bind the input to @Empty@.+--+-- This choice is currently a bit of a "hunch" but we do have algorithms in+-- mind, where this could be useful.++module ADP.Fusion.Term.Empty where++import Data.Strict.Maybe+import Prelude hiding (Maybe(..))++import Data.PrimitiveArray -- (Z(..), (:.)(..), Subword(..), subword, PointL(..), pointL, PointR(..), pointR, Outside(..))++import ADP.Fusion.Term.Classes+import ADP.Fusion.Term.Multi.Classes++import Debug.Trace++++-- | Empty as an argument only makes sense if empty is static. We don't get to+-- use 'staticCheck' as the underlying check for the bottom of the argument+-- stack should take care of the @i==j@ check.++{-+instance+ ( Monad m+ , MkStream m ls Subword+ ) => MkStream m (ls :!: Empty) Subword where+ mkStream (ls :!: Empty) Static lu (Subword (i:.j))+ = S.map (ElmEmpty (subword i j))+ $ mkStream ls Static lu (subword i j)+ mkStream _ _ _ _ = error "mkStream Empty/Subword called with illegal parameters"+ {-# INLINE mkStream #-}++instance+ ( Monad m+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: Empty) (Outside Subword) where+ mkStream (ls :!: Empty) Static lu (O (Subword (i:.j)))+ = S.map (ElmEmpty (O $ subword i j))+ $ mkStream ls Static lu (O $ subword i j)+ mkStream _ _ _ _ = error "mkStream Empty/Subword called with illegal parameters"+ {-# INLINE mkStream #-}+-}++type instance TermArg (TermSymbol a Empty) = TermArg a :. ()++instance TermStaticVar Empty PointL where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ ij = ij+ {-# INLINE termStaticVar #-}+ {-# INLINE termStreamIndex #-}++{-+instance TermStaticVar Empty Subword where+ termStaticVar = error "write me"+ termStreamIndex = error "write me"+-}++-- | Again, we assume that no 'staticCheck' is necessary and that @i==j@ is+-- true.++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a Empty) (is:.PointL) where+ terminalStream (a:|Empty) (sv:.Static) (is:.PointL (i:.j))+ = S.map (\(Qd s (z:.i) is e) -> Qd s z (is:.i) (e:.()))+ . terminalStream a sv is+ . S.map moveIdxTr+ terminalStream _ _ _ = error "mkStream Empty/(is:.PointL) called with illegal parameters"+ {-# INLINE terminalStream #-}++{-+instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a Empty) (is:.Subword) where+ terminalStream (a:>Empty) (sv:.Static) (is:.Subword (i:.j))+ = S.map (\(Qd s (z:.i) is e) -> Qd s z (is:.i) (e:.()))+ . terminalStream a sv is+ . S.map moveIdxTr+ terminalStream _ _ _ = error "mkStream Empty/(is:.Subword) called with illegal parameters"+ {-# INLINE terminalStream #-}+-}++-}+
+ ADP/Fusion/Term/Epsilon/Point.hs view
@@ -0,0 +1,62 @@++module ADP.Fusion.Term.Epsilon.Point where++import Data.Strict.Tuple+import qualified Data.Vector.Fusion.Stream.Monadic as S++import Data.PrimitiveArray++import ADP.Fusion.Base+import ADP.Fusion.Term.Epsilon.Type++++instance+ ( Monad m+ , MkStream m ls PointL+ ) => MkStream m (ls :!: Epsilon) PointL where+ mkStream (ls :!: Epsilon) (IStatic d) (PointL u) (PointL i)+ = S.map (ElmEpsilon (PointL i) (PointL 0))+ $ mkStream ls (IStatic d) (PointL u) (PointL i)+ {-# Inline mkStream #-}++instance+ ( Monad m+ , Element ls (Outside PointL)+ , MkStream m ls (Outside PointL)+ ) => MkStream m (ls :!: Epsilon) (Outside PointL) where+ mkStream (ls :!: Epsilon) (OStatic d) (O (PointL u)) (O (PointL i))+ = S.map (\z -> ElmEpsilon (O $ PointL i) (getOmx z) z)+ $ mkStream ls (OStatic d) (O $ PointL u) (O $ PointL i)+ {-# Inline mkStream #-}++instance TermStaticVar Epsilon PointL where+ termStaticVar _ sv _ = sv+ termStreamIndex _ _ (PointL j) = PointL j+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance TermStaticVar Epsilon (Outside PointL) where+ termStaticVar _ (OStatic d) _ = OStatic d+ termStreamIndex _ _ j = j+ {-# Inline termStaticVar #-}+ {-# Inline termStreamIndex #-}++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a Epsilon) (is:.PointL) where+ terminalStream (a:|Epsilon) (sv:.IStatic _) (is:.i@(PointL j))+ = S.map (\(S6 s (zi:._) (zo:._) is os e) -> S6 s zi zo (is:.PointL j) (os:.PointL 0) (e:.()))+ . iPackTerminalStream a sv (is:.i)+ {-# Inline terminalStream #-}++instance+ ( Monad m+ , TerminalStream m a (Outside is)+ ) => TerminalStream m (TermSymbol a Epsilon) (Outside (is:.PointL)) where+ terminalStream (a:|Epsilon) (sv:.OStatic d) (O (is:.i))+ = S.map (\(S6 s (zi:._) (zo:.PointL k) (O is) (O os) e) -> S6 s zi zo (O (is:.(PointL $ k-d))) (O (os:.PointL k)) (e:.()))+ . oPackTerminalStream a sv (O (is:.i))+ {-# Inline terminalStream #-}+
+ ADP/Fusion/Term/Epsilon/Subword.hs view
@@ -0,0 +1,37 @@++module ADP.Fusion.Term.Epsilon.Subword where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic as S+import Prelude hiding (map)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.Term.Epsilon.Type++--import Data.Vector.Fusion.Util++++instance+ ( Monad m+ , MkStream m ls Subword+ ) => MkStream m (ls :!: Epsilon) Subword where+ mkStream (ls :!: Epsilon) (IStatic ()) hh ij@(Subword (i:.j))+ = staticCheck (i==j)+ $ map (ElmEpsilon (subword i j) (subword 0 0))+ $ mkStream ls (IStatic ()) hh ij+ {-# Inline mkStream #-}++++instance+ ( Monad m+ , MkStream m ls (Outside Subword)+ ) => MkStream m (ls :!: Epsilon) (Outside Subword) where+ mkStream (ls :!: Epsilon) (OStatic d) u ij@(O (Subword (i:.j)))+ = map (ElmEpsilon (O $ subword i j) (O $ subword i j))+ $ mkStream ls (OStatic d) u ij+ {-# Inline mkStream #-}+
+ ADP/Fusion/Term/Epsilon/Type.hs view
@@ -0,0 +1,27 @@++module ADP.Fusion.Term.Epsilon.Type where++import Data.Strict.Tuple++import Data.PrimitiveArray++import ADP.Fusion.Base++++data Epsilon = Epsilon++instance Build Epsilon++instance (Element ls i) => Element (ls :!: Epsilon) i where+ data Elm (ls :!: Epsilon) i = ElmEpsilon !i !i !(Elm ls i)+ type Arg (ls :!: Epsilon) = Arg ls :. ()+ getArg (ElmEpsilon _ _ l) = getArg l :. ()+ getIdx (ElmEpsilon i _ _) = i+ getOmx (ElmEpsilon _ o _) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++type instance TermArg (TermSymbol a Epsilon) = TermArg a :. ()+
+ ADP/Fusion/Term/PeekIndex/Subword.hs view
@@ -0,0 +1,24 @@++module ADP.Fusion.Term.PeekIndex.Subword where++import Data.Strict.Tuple+import Data.Vector.Fusion.Stream.Monadic (map)+import Prelude hiding (map)++import Data.PrimitiveArray hiding (map)++import ADP.Fusion.Base+import ADP.Fusion.Term.PeekIndex.Type++++instance+ ( Monad m+ , Element ls (Complement Subword)+ , MkStream m ls (Complement Subword)+ ) => MkStream m (ls :!: PeekIndex (Complement Subword)) (Complement Subword) where+ mkStream (ls :!: PeekIndex) Complemented h ij+ = map (\s -> ElmPeekIndex (getIdx s) (getOmx s) s)+ $ mkStream ls Complemented h ij+ {-# Inline mkStream #-}+
+ ADP/Fusion/Term/PeekIndex/Type.hs view
@@ -0,0 +1,31 @@++module ADP.Fusion.Term.PeekIndex.Type where++import Data.Strict.Tuple++import Data.PrimitiveArray++import ADP.Fusion.Base++++data PeekIndex i = PeekIndex++instance Build (PeekIndex i)++instance+ ( Element ls i+ ) => Element (ls :!: PeekIndex i) i where+ data Elm (ls :!: PeekIndex i) i = ElmPeekIndex !i !i !(Elm ls i)+ type Arg (ls :!: PeekIndex i) = Arg ls :. (i :. i)+ getArg (ElmPeekIndex i o ls) = getArg ls :. (i:.o)+ getIdx (ElmPeekIndex i _ _ ) = i+ getOmx (ElmPeekIndex _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance (Show i, Show (Elm ls i)) => Show (Elm (ls :!: PeekIndex i) i)++type instance TermArg (TermSymbol a (PeekIndex i)) = TermArg a :. PeekIndex i+
+ ADP/Fusion/Term/Strng.hs view
@@ -0,0 +1,11 @@++-- | A 'Strng' matches [0..] 'Chr's.++module ADP.Fusion.Term.Strng+ ( module ADP.Fusion.Term.Strng.Type+ , module ADP.Fusion.Term.Strng.Point+ ) where++import ADP.Fusion.Term.Strng.Point+import ADP.Fusion.Term.Strng.Type+
+ ADP/Fusion/Term/Strng/Point.hs view
@@ -0,0 +1,43 @@++module ADP.Fusion.Term.Strng.Point where++import Data.Strict.Tuple+import Debug.Trace+import qualified Data.Vector.Fusion.Stream.Monadic as S+import qualified Data.Vector.Generic as VG++import Data.PrimitiveArray++import ADP.Fusion.Base+import ADP.Fusion.Term.Strng.Type++++instance+ ( Monad m+ , Element ls PointL+ , MkStream m ls PointL+ ) => MkStream m (ls :!: Strng v x) PointL where+ mkStream (ls :!: Strng f minL maxL xs) (IStatic d) (PointL u) (PointL i)+ = staticCheck (i - minL >= 0 && i <= u && minL <= maxL)+ $ S.map (\z -> let PointL j = getIdx z in ElmStrng (f j (i-j) xs) (PointL i) (PointL 0) z)+ $ mkStream ls (IVariable $ d + maxL - minL) (PointL u) (PointL $ i - minL)+ mkStream _ _ _ _ = error "mkStream / Strng / PointL / IVariable"+ {-# Inline mkStream #-}++instance TermStaticVar (Strng v x) PointL where+ termStaticVar _ (IStatic d) _ = IVariable d+ termStaticVar _ (IVariable d) _ = IVariable d+ termStreamIndex (Strng _ minL _ _) (IStatic d) (PointL j) = PointL $ j - minL+ {-# Inline [0] termStaticVar #-}+ {-# Inline [0] termStreamIndex #-}++instance+ ( Monad m+ , TerminalStream m a is+ ) => TerminalStream m (TermSymbol a (Strng v x)) (is:.PointL) where+ terminalStream (a:|Strng f minL maxL xs) (sv:.IStatic d) (is:.i@(PointL j))+ = S.map (\(S6 s (zi:.PointL pi) (zo:._) is os e) -> S6 s zi zo (is:.i) (os:.PointL 0) (e:.f pi (j-pi) xs))+ . iPackTerminalStream a sv (is:.i)+ {-# Inline terminalStream #-}+
+ ADP/Fusion/Term/Strng/Type.hs view
@@ -0,0 +1,56 @@++module ADP.Fusion.Term.Strng.Type where++import Data.Strict.Tuple+import qualified Data.Vector.Generic as VG++import Data.PrimitiveArray++import ADP.Fusion.Base++++-- | 'Strng' terminals return "strings", i.e. vectors of @Chr@s. They allow+-- the user to specify @[ 0 .. ]@ atoms to be parsed at once. It is+-- possible to both, limit the minimal and maximal number.+--+-- NOTE gadt comments are not parsed by haddock?++data Strng v x where+ Strng :: VG.Vector v x+ => !(Int -> Int -> v x -> v x) -- @slice@ function+ -> !Int -- minimal size+ -> !Int -- maximal size (just use s.th. big if you don't want a limit)+ -> !(v x) -- the actual vector+ -> Strng v x++manyS :: VG.Vector v x => v x -> Strng v x+manyS = \xs -> Strng VG.unsafeSlice 0 (VG.length xs) xs+{-# Inline manyS #-}++someS :: VG.Vector v x => v x -> Strng v x+someS = \xs -> Strng VG.unsafeSlice 1 (VG.length xs) xs+{-# Inline someS #-}++strng :: VG.Vector v x => Int -> Int -> v x -> Strng v x+strng = \minL maxL xs -> Strng VG.unsafeSlice minL maxL xs+{-# Inline strng #-}++instance Build (Strng v x)++instance+ ( Element ls i+ ) => Element (ls :!: Strng v x) i where+ data Elm (ls :!: Strng v x) i = ElmStrng !(v x) !i !i !(Elm ls i)+ type Arg (ls :!: Strng v x) = Arg ls :. v x+ getArg (ElmStrng x _ _ ls) = getArg ls :. x+ getIdx (ElmStrng _ i _ _ ) = i+ getOmx (ElmStrng _ _ o _ ) = o+ {-# Inline getArg #-}+ {-# Inline getIdx #-}+ {-# Inline getOmx #-}++deriving instance (Show i, Show (v x), Show (Elm ls i)) => Show (Elm (ls :!: Strng v x) i)++type instance TermArg (TermSymbol a (Strng v x)) = TermArg a :. v x+
ADPfusion.cabal view
@@ -1,24 +1,36 @@ name: ADPfusion-version: 0.2.1.0-author: Christian Hoener zu Siederdissen, 2011-2013-copyright: Christian Hoener zu Siederdissen, 2011-2013-homepage: http://www.tbi.univie.ac.at/~choener/adpfusion-maintainer: choener@tbi.univie.ac.at-category: Algorithms, Data Structures, Bioinformatics+version: 0.4.0.0+author: Christian Hoener zu Siederdissen, 2011-2015+copyright: Christian Hoener zu Siederdissen, 2011-2015+homepage: http://www.bioinf.uni-leipzig.de/Software/gADP/+maintainer: choener@bioinf.uni-leipzig.de+category: Algorithms, Data Structures, Bioinformatics, Formal Languages license: BSD3 license-file: LICENSE build-type: Simple stability: experimental-cabal-version: >= 1.6.0-synopsis:- Efficient, high-level dynamic programming.+cabal-version: >= 1.10.0+tested-with: GHC == 7.8.4, GHC == 7.10.1+synopsis: Efficient, high-level dynamic programming. description: ADPfusion combines stream-fusion (using the stream interface provided by the vector library) and type-level programming to provide highly efficient dynamic programming combinators. .- This library is described in:+ ADPfusion allows writing dynamic programs for single- and+ multi-tape problems. Inputs can be sequences, or sets. And new+ input types can be defined, without having to rewrite this+ library thanks to the open-world assumption of ADPfusion. .+ The library provides the machinery for Outside and Ensemble+ algorithms as well. Ensemble algorithms combine Inside and+ Outside calculations.+ .+ The homepage provides a number of tutorial-style examples, with+ linear and context-free grammars over sequence and set inputs.+ .+ Ideas implemented here are described in a couple of papers:+ . @ Christian Hoener zu Siederdissen Sneaking Around ConcatMap: Efficient Combinators for Dynamic Programming@@ -26,109 +38,353 @@ <http://doi.acm.org/10.1145/2364527.2364559> preprint: <http://www.tbi.univie.ac.at/newpapers/pdfs/TBI-p-2012-2.pdf> @ .- From the programmers' viewpoint, ADPfusion behaves very much- like the original ADP implementation- <http://bibiserv.techfak.uni-bielefeld.de/adp/> developed by- Robert Giegerich and colleagues, though both combinator- semantics and backtracking are different.- .- The library internals, however, are designed not only to speed- up ADP by a large margin (which this library does), but also to- provide further runtime improvements by allowing the programmer- to switch over to other kinds of data structures with better- time and space behaviour. Most importantly, dynamic programming- tables can be strict, removing indirections present in lazy,- boxed tables.- .- As a simple benchmark, consider the Nussinov78 algorithm which- translates to three nested for loops (for C). In the figure,- four different approaches are compared using inputs with size- 100 characters to 1000 characters in increments of 100- characters. "C" is an implementation (@./C/@ directory) in "C"- using "gcc -O3". "ADP" is the original ADP approach (see link- above), while "GAPC" uses the "GAP" language- (<http://gapc.eu/>).- .- Performance comparison figure:- <http://www.tbi.univie.ac.at/~choener/adpfusion/gaplike-nussinov-runtime.jpg>- .- Please note that actual performance will depend much on table- layout and data structures accessed during calculations, but in- general performance is very good: close to C and better than- other high-level approaches (that I know of).- .- .- .- Even complex ADP code tends to be completely optimized to loops- that use only unboxed variables (Int# and others,- indexIntArray# and others).- .- Completely novel (compared to ADP), is the idea of allowing- efficient monadic combinators. This facilitates writing code- that performs backtracking, or samples structures- stochastically, among others things.+ @+ Andrew Farmer, Christian Höner zu Siederdissen, and Andy Gill.+ The HERMIT in the stream: fusing stream fusion’s concatMap.+ 2014. Proceedings of the ACM SIGPLAN 2014 workshop on Partial evaluation and program manipulation.+ <http://dl.acm.org/citation.cfm?doid=2543728.2543736>+ @ .+ @+ Christian Höner zu Siederdissen, Ivo L. Hofacker, and Peter F. Stadler.+ Product Grammars for Alignment and Folding.+ 2014. IEEE/ACM Transactions on Computational Biology and Bioinformatics. 99.+ <http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6819790>+ @ .+ @+ Christian Höner zu Siederdissen, Sonja J. Prohaska, and Peter F. Stadler.+ Algebraic Dynamic Programming over General Data Structures.+ 2015. submitted.+ @ .- Two algorithms from the realm of computational biology are- provided as examples on how to write dynamic programming- algorithms using this library:- <http://hackage.haskell.org/package/Nussinov78> and- <http://hackage.haskell.org/package/RNAFold>. Extra-Source-Files: README.md- changelog+ changelog.md +flag examples+ description: build the examples+ default: False+ manual: True++flag llvm+ description: build using LLVM+ default: False+ manual: True++flag debug+ description: dump intermediate Core files+ default: False+ manual: True+++ library- build-depends:- base >= 4 && < 5,- deepseq >= 1.3 ,- ghc-prim ,- primitive >= 0.5 ,- PrimitiveArray >= 0.5.3 ,- QuickCheck >= 2.5 ,- repa >= 3.2 ,- strict >= 0.3.2 ,- template-haskell ,- transformers ,- vector >= 0.10++ build-depends: base >= 4.7 && < 4.9+ , bits == 0.4.*+ , mmorph == 1.0.*+ , monad-primitive == 0.1+ , mtl == 2.*+ , OrderedBits == 0.0.0.*+ , primitive >= 0.5.4 && < 0.7+ , PrimitiveArray == 0.6.0.*+ , QuickCheck >= 2.7 && < 2.9+ , strict == 0.3.*+ , template-haskell == 2.*+ , transformers >= 0.3 && < 0.5+ , tuple == 0.3.*+ , vector == 0.10.*+ exposed-modules: ADP.Fusion ADP.Fusion.Apply- ADP.Fusion.Chr- ADP.Fusion.Classes- ADP.Fusion.Empty- ADP.Fusion.Examples.Palindrome- ADP.Fusion.Multi- ADP.Fusion.Multi.Classes- ADP.Fusion.Multi.Empty- ADP.Fusion.Multi.GChr- ADP.Fusion.Multi.None- ADP.Fusion.None- ADP.Fusion.QuickCheck- ADP.Fusion.Region- ADP.Fusion.Table+ ADP.Fusion.Base+ ADP.Fusion.Base.Classes+ ADP.Fusion.Base.Multi+ ADP.Fusion.Base.Point+ ADP.Fusion.Base.Set+ ADP.Fusion.Base.Subword+ ADP.Fusion.Term+ ADP.Fusion.Term.Chr+ ADP.Fusion.Term.Chr.Point+ ADP.Fusion.Term.Chr.Subword+ ADP.Fusion.Term.Chr.Type+ ADP.Fusion.Term.Edge+ ADP.Fusion.Term.Edge.Set+ ADP.Fusion.Term.Edge.Type+ ADP.Fusion.Term.Epsilon+ ADP.Fusion.Term.Epsilon.Point+ ADP.Fusion.Term.Epsilon.Subword+ ADP.Fusion.Term.Epsilon.Type+ ADP.Fusion.Term.Deletion+ ADP.Fusion.Term.Deletion.Point+ ADP.Fusion.Term.Deletion.Type+ ADP.Fusion.Term.PeekIndex.Subword+ ADP.Fusion.Term.PeekIndex.Type+ ADP.Fusion.Term.Strng+ ADP.Fusion.Term.Strng.Point+ ADP.Fusion.Term.Strng.Type+ ADP.Fusion.SynVar+ ADP.Fusion.SynVar.Array+ ADP.Fusion.SynVar.Array.Point+ ADP.Fusion.SynVar.Array.Set+ ADP.Fusion.SynVar.Array.Subword+ ADP.Fusion.SynVar.Array.Type+ ADP.Fusion.SynVar.Axiom+ ADP.Fusion.SynVar.Backtrack+ ADP.Fusion.SynVar.Fill+ ADP.Fusion.SynVar.Indices+ ADP.Fusion.SynVar.Recursive+ ADP.Fusion.SynVar.Recursive.Point+ ADP.Fusion.SynVar.Recursive.Subword+ ADP.Fusion.SynVar.Recursive.Type ADP.Fusion.TH+ ADP.Fusion.TH.Backtrack+ ADP.Fusion.TH.Common+ ADP.Fusion.QuickCheck.Common+ ADP.Fusion.QuickCheck.Point+ ADP.Fusion.QuickCheck.Set+ ADP.Fusion.QuickCheck.Subword + default-extensions: BangPatterns+ , DefaultSignatures+ , FlexibleContexts+ , FlexibleInstances+ , GADTs+ , MultiParamTypeClasses+ , RankNTypes+ , StandaloneDeriving+ , TemplateHaskell+ , TypeFamilies+ , TypeOperators+ , TypeSynonymInstances+ , UndecidableInstances++ default-language:+ Haskell2010 ghc-options: -O2 -funbox-strict-fields +++-- Very simple two-sequence alignment.+ executable NeedlemanWunsch++ if flag(examples)+ buildable:+ True+ build-depends: base+ , ADPfusion+ , PrimitiveArray+ , template-haskell+ , vector+ else+ buildable:+ False++ hs-source-dirs:+ src main-is:- ADP/Fusion/Examples/TwoDim.hs+ NeedlemanWunsch.hs+ default-language:+ Haskell2010+ default-extensions: BangPatterns+ , FlexibleContexts+ , FlexibleInstances+ , MultiParamTypeClasses+ , RecordWildCards+ , TemplateHaskell+ , TypeFamilies+ , TypeOperators ghc-options:- -Odph+ -O2 -funbox-strict-fields -funfolding-use-threshold1000 -funfolding-keeness-factor1000- -fllvm- -optlo-O3 -optlo-std-compile-opts- -fllvm-tbaa+ if flag(llvm)+ ghc-options:+ -fllvm+ -optlo-O3 -optlo-std-compile-opts+ -fllvm-tbaa+ if flag(debug)+ ghc-options:+ -ddump-to-file+ -ddump-simpl+ -dsuppress-all++++-- Basic RNA secondary structure folding++executable Nussinov++ if flag(examples)+ buildable:+ True+ build-depends: base+ , ADPfusion+ , PrimitiveArray+ , template-haskell+ , vector+ else+ buildable:+ False++ hs-source-dirs:+ src+ main-is:+ Nussinov.hs+ default-language:+ Haskell2010+ default-extensions: BangPatterns+ , FlexibleContexts+ , FlexibleInstances+ , MultiParamTypeClasses+ , RecordWildCards+ , TemplateHaskell+ , TypeFamilies+ , TypeOperators+ ghc-options:+ -O2+ -funbox-strict-fields+ -funfolding-use-threshold1000+ -funfolding-keeness-factor1000+ if flag(llvm)+ ghc-options:+ -fllvm+ -optlo-O3 -optlo-std-compile-opts+ -fllvm-tbaa+ if flag(debug)+ ghc-options:+ -ddump-to-file+ -ddump-simpl+ -dsuppress-all++++-- Basic RNA secondary structure folding with partition function calculations++executable PartNussinov++ if flag(examples)+ buildable:+ True+ build-depends: base+ , ADPfusion+ , log-domain == 0.10.*+ , PrimitiveArray+ , template-haskell+ , vector+ else+ buildable:+ False++ hs-source-dirs:+ src+ main-is:+ PartNussinov.hs+ default-language:+ Haskell2010+ default-extensions: BangPatterns+ , FlexibleContexts+ , FlexibleInstances+ , MultiParamTypeClasses+ , RecordWildCards+ , TemplateHaskell+ , TypeFamilies+ , TypeOperators+ ghc-options:+ -O2+ -funbox-strict-fields+ -funfolding-use-threshold1000+ -funfolding-keeness-factor1000+ if flag(llvm)+ ghc-options:+ -fllvm+ -optlo-O3 -optlo-std-compile-opts+ -fllvm-tbaa+ if flag(debug)+ ghc-options:+ -ddump-to-file+ -ddump-simpl+ -dsuppress-all++++executable Durbin++ if flag(examples)+ buildable:+ True+ build-depends: base+ , ADPfusion+ , PrimitiveArray+ , template-haskell+ , vector+ else+ buildable:+ False++ hs-source-dirs:+ src+ main-is:+ Durbin.hs+ default-language:+ Haskell2010+ default-extensions: BangPatterns+ , FlexibleContexts+ , FlexibleInstances+ , MultiParamTypeClasses+ , RecordWildCards+ , TemplateHaskell+ , TypeFamilies+ , TypeOperators+ ghc-options:+ -O2+ -fcpr-off+ -funbox-strict-fields+ -funfolding-use-threshold1000+ -funfolding-keeness-factor1000+ if flag(llvm)+ ghc-options:+ -fllvm+ -optlo-O3 -optlo-std-compile-opts+ -fllvm-tbaa+ if flag(debug)+ ghc-options:+ -ddump-to-file+ -ddump-simpl+ -dsuppress-all++++test-suite properties+ type:+ exitcode-stdio-1.0+ main-is:+ properties.hs+ ghc-options:+ -threaded -rtsopts -with-rtsopts=-N+ hs-source-dirs:+ tests+ default-language:+ Haskell2010+ default-extensions: TemplateHaskell+ build-depends: base+ , ADPfusion+ , QuickCheck+ , test-framework >= 0.8 && < 0.9+ , test-framework-quickcheck2 >= 0.3 && < 0.4+ , test-framework-th >= 0.2 && < 0.3++ source-repository head type: git
LICENSE view
@@ -1,4 +1,4 @@-Copyright Christian Hoener zu Siederdissen 2011-2012+Copyright Christian Hoener zu Siederdissen 2011-2015 All rights reserved.
README.md view
@@ -1,15 +1,13 @@+# ADPfusion -ADPfusion-(c) 2012, Christian Hoener zu Siederdissen-University of Vienna, Vienna, Austria-choener@tbi.univie.ac.at-LICENSE: BSD3+[](https://travis-ci.org/choener/ADPfusion) +[*generalized ADPfusion Homepage*](http://www.bioinf.uni-leipzig.de/Software/gADP/) -Introduction-============ +# Introduction+ ADPfusion combines stream-fusion (using the stream interface provided by the vector library) and type-level programming to provide highly efficient dynamic programming combinators.@@ -46,9 +44,9 @@ <http://hackage.haskell.org/package/RNAfold>. -Installation-============ +# Installation+ If GHC-7.2.2/GHC-7.4, LLVM and cabal-install are available, you should be all set. I recommend using cabal-dev as it provides a very nice sandbox (replace cabal-dev with cabal otherwise).@@ -66,8 +64,7 @@ -Notes-=====+# Notes If you have problems, find bugs, or want to use this library to write your own DP algorithms, please send me a mail. I'm very interested in hearing what is@@ -83,35 +80,25 @@ -VERSION HISTORY-===============+# Implementors Notes -- 0.0.0.3:- - initial version, together with submitted paper -- 0.0.0.4:- - based most combinators on just two generalized Box creators- - cleaned up and simplified RNAfold example- - RNAfold execution now a bit slower. Simplified energy functions typically- only have three arguments now, which can be of 'Primary' type. While this- reduces speed because we will repeatedly ask for the same value, it is much- easier to handle the different functions and ``play'' with fusion- properties.- - RNAfold compilation massively faster: execution/compilation tradoff is- worth it for experimenting with ADPfusion; still faster than anything- except RNAfold itself. We are now now 2.8x times slower, but 3.5x times- slower- - Quickcheck properties for many combinators- - Unit tests for RNAfold functions- - will soon split off RNAfold and Nussinov and publish three hackage- libraries- - this version was never available, after being done, a split into library- and examples was performed.+- The general inlining scheme is: (i) mkStream is {-# INLINE mkStream #-},+ inner functions like mk, step, worker functions, and index-modifying+ functions get an {-# INLINE [0] funName #-}. Where there is no function to+ annotate, use delay_inline. -- 0.0.1.0- - providing just the library. Examples are found in different libraries.+- If you implement a new kind of memoizing table, like the dense Table.Array+ ones, you will have to implement mkStream code. When you hand to the left,+ the (i,j) indices and modify their extend (by, say, having NonEmpty table+ constaints), you have to delay_inline this (until inliner phase 0). Otherwise+ you will break fusion for mkStream. -- 0.0.1.1- - this version should be compatible with GHC-7.4, at least GHC-7,4.2-rc1.- - a type family (TF) version has not been able to show the same performance- as fundeps. This means that fundeps for Internal.hs stay alive, for now.+++#### Contact++Christian Hoener zu Siederdissen+choener@bioinf.uni-leipzig.de+Leipzig University, Leipzig, Germany+
− changelog
@@ -1,4 +0,0 @@-0.2:- * Streamlined interface: access everything via ADP.Fusion-- * /Multi-tape/ grammars can now be written and are fused
+ changelog.md view
@@ -0,0 +1,31 @@+0.4.0.0+-------++- travic-ci integration+- forward phase now operates on immutable tables that are internally thawed+- resembles the behavior of Data.Vector.Generic.constructN+- Empty needs to be bound to input. We require this as certain index structures+ have no natural notion of and empty index -- unless one provides additional+ information in the index++0.3.0.0+-------++- simplified boundary checking: sometimes gives performance gain (!) due to one+ loop variable less+- optimized loop variable design following "The HERMIT in the Stream" (Farmer+ et al, 2014)+- somewhat nicer programmer interfaces+- automatic filling and freezing of tables+- multiple example algorithms (build with -fexamples switch):+ - Needleman-Wunsch global alignment+ - RNA secondary structure prediction using simple base pair maximization+- updated Table code to handle single-dim Subwords in a better way.+- simplified backtracking++0.2.x.x+-------++- Streamlined interface: access everything via ADP.Fusion+- /Multi-tape/ grammars can now be written and are fused+
+ src/Durbin.hs view
@@ -0,0 +1,122 @@++-- | Nussinovs RNA secondary structure prediction algorithm via basepair+-- maximization. Follow this file from top to bottom for a short tutorial+-- on how to use @ADPfusion@.+--+-- In general the task is the following: We are given a sequence of+-- characters from the alphabet @ACGU@. There are 6 pairing rules (cf.+-- 'pairs'), @A-U@, @C-G@, @G-C@, @G-U@, @U-A@, and @U-G@ can /pair/ with+-- each other. Pairs, denoted by brackets @(@, @)@ may be juxtaposed+-- @().()@ or enclosing @(())@. /Crossing/ pairs are not allowed: @([)]@ is+-- forbidden, with @()@ and @[]@ pairing. Dots @.@ denote unpaired+-- characters.+--+-- As an example, the sequence @CACAAGGAUU@ admits the following+-- dot-bracket string @(.)..((..))@.+--+-- The algorithm below maximizes the number of legal brackets.++module Main where++import Control.Applicative+import Control.Monad+import Control.Monad.ST+import Data.Char (toUpper,toLower)+import Data.List+import Data.Vector.Fusion.Util+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Unboxed as VU+import System.Environment (getArgs)+import Text.Printf++-- Import PrimitiveArray for low-level tables and automatic table+-- filling.++import Data.PrimitiveArray as PA++-- High-level ADPfusion stuff.++import ADP.Fusion++++-- | All grammars require a signature.++data Durbin m c e x r = Durbin+ { nil :: e -> x+ , lef :: c -> x -> x+ , rig :: x -> c -> x+ , pai :: c -> x -> c -> x+ , spl :: x -> x -> x+ , h :: SM.Stream m x -> m r+ }++makeAlgebraProduct ''Durbin++bpmax :: Monad m => Durbin m Char () Int Int+bpmax = Durbin+ { nil = \ () -> 0+ , lef = \ _ x -> x+ , rig = \ x _ -> x+ , pai = \ c x d -> if pairs c d then x+1 else -999999+ , spl = \ x y -> x+y+ , h = SM.foldl' max 0+ }+{-# INLINE bpmax #-}++pairs !c !d+ = c=='A' && d=='U'+ || c=='C' && d=='G'+ || c=='G' && d=='C'+ || c=='G' && d=='U'+ || c=='U' && d=='A'+ || c=='U' && d=='G'+{-# INLINE pairs #-}++pretty :: Monad m => Durbin m Char () String [String]+pretty = Durbin+ { nil = \ () -> ""+ , lef = \ _ x -> "." ++ x+ , rig = \ x _ -> x ++ "."+ , pai = \ _ x _ -> "(" ++ x ++ ")"+ , spl = \ x y -> x ++ y+ , h = SM.toList+ }+{-# INLINE pretty #-}++-- grammar :: Durbin m Char () x r -> c' -> t' -> (t', Subword -> m r)+grammar Durbin{..} c t' =+ let t = t' ( nil <<< Epsilon |||+ lef <<< c % t |||+ rig <<< t % c |||+ pai <<< c % t % c |||+ spl <<< tt % tt ... h+ )+ tt = toNonEmpty t+ in (Z:.t)+{-# INLINE grammar #-}++runDurbin :: Int -> String -> (Int,[String])+runDurbin k inp = (d, take k . unId $ axiom b) where+ i = VU.fromList . Prelude.map toUpper $ inp+ n = VU.length i+ !(Z:.t) = mutateTablesDefault+ $ grammar bpmax+ (chr i)+ (ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) (-999999) [])) :: Z:.ITbl Id Unboxed Subword Int+ -- d = let (ITbl _ _ arr _) = t in arr PA.! subword 0 n+ d = iTblArray t PA.! subword 0 n+ !(Z:.b) = grammar (bpmax <|| pretty) (chr i) (toBacktrack t (undefined :: Id a -> Id a))++main = do+ as <- getArgs+ let k = if null as then 1 else read $ head as+ ls <- lines <$> getContents+ forM_ ls $ \l -> do+ putStrLn l+ let (s,xs) = runDurbin k l+ mapM_ (\x -> printf "%s %5d\n" x s) xs+
+ src/NeedlemanWunsch.hs view
@@ -0,0 +1,323 @@++-- | The Needleman-Wunsch global alignment algorithm. This algorithm is+-- extremely simple but provides a good showcase for what ADPfusion offers.+--+-- Follow the code from top to bottom for a tutorial on usage.+--+-- We start by importing a bunch of modules, including+-- @Data.PrimitiveArray@ for low-level arrays and automated filling of the+-- arrays or tables in the correct order.+--+-- We also need to import @ADP.Fusion@ to access the high-level code for+-- dynamic programs.+--+-- Don't forget to inline basically everything!+--+-- One note on performance: Needleman-Wunsch is actually one of the worst+-- cases for ADPfusion. Low-level implementations can get away with a very+-- small number of code steps for each cell to be filled. We can't /quite/+-- do this. The relative overhead for each cell to be written into goes+-- down with more complex grammars and algebras.++module Main where++import Control.Applicative+import Control.Monad+import Data.Vector.Fusion.Stream.Monadic (Stream (..))+import Data.Vector.Fusion.Util+import Debug.Trace+import qualified Control.Arrow as A+import qualified Data.Vector as V+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Unboxed as VU+import System.Environment (getArgs)+import System.IO.Unsafe (unsafePerformIO)+import Text.Printf++-- @Data.PrimitiveArray@ contains data structures, and index structures for+-- dynamic programming. Notably, the primitive arrays holding the cell data+-- with Boxed and Unboxed tables. In addition, linear, context-free, and+-- set data structures are made available.++import Data.PrimitiveArray as PA hiding (map)++-- @ADP.Fusion@ exposes everything necessary for higher-level DP+-- algorithms.++import ADP.Fusion++++-- | A signature connects the types of all non-terminals and terminals with+-- evaluation (or attribute) functions. In the grammar below, we not only+-- want to create all possible parses of how two strings can be aligned but+-- also evaluate each parse and choose the optimal one based on Bellman's+-- principle of optimality.+--+-- Assume we are in the matrix and want to calculate @x@:+--+-- @+-- -----+-- |d|u|+-- -----+-- |l|x|+-- -----+-- @+--+-- We can arrive from @d@, making a diagonal step, called @step_step@ as we+-- advance by one in both dimensions. This leads to an alignment of two+-- characters, one from each input, at @x@, which is combined with the+-- already calculated alignment at @d@.+--+-- We can also just step in the first dimension @step_loop@, going from @l@+-- to @x@. Which means that the first-dim character does not have+-- a partner, leading to an insert/deletion or in/del. We typically do not+-- care in which of the two dimensions the in/del happens, just that it+-- does.+--+-- The third case is an in/del in the other dimension, giving us+-- @loop_step@ or going from @u@ to @x@.+--+-- Of course, if @x@ happens to be the uppermost, leftmost cell, we have+-- nowhere to come from, so we need to inititialize (or terminate depending+-- on your view point) using the @nil_nil@ case. That one is the base case.+--+-- We also want to know which of the three cases is the best case (coming+-- from @d,l,u@), this requires a "choice" function or @h@.+--+-- We take a close look at the type signatures. @step_step :: x ->+-- (Z:.c:.c) -> x@ tells us that @step_step@ requires the score from the+-- non-terminal, typed @x@ for the alignment up to @d@, then we get the two+-- characters with type @c@ and produce a new non-terminal typed score @x@.+-- For our simple alignment we'll later choose @Char@ for @c@ and @Int@ for+-- @x@.+--+-- The type of @h :: Stream m x -> m r@ is more interesting. We get+-- a @Stream@ of @x@'s and produce an @r@ monadically. The left part is+-- clear @Stream m x@ are the results from the four rules, but the right+-- part allows us to maybe not only return the best case, types @x == r@,+-- but maybe the two best cases @r == (x,x)@ or similar. While we do not+-- use this feature here, it makes ADPfusion fully "classified DP"+-- capable, which is a really cool feature for advanced algorithms.++data Signature m x r c = Signature+ { step_step :: x -> (Z:.c :.c ) -> x+ , step_loop :: x -> (Z:.c :.()) -> x+ , loop_step :: x -> (Z:.():.c ) -> x+ , nil_nil :: (Z:.():.()) -> x+ , h :: Stream m x -> m r+ }++-- | We also want to be able to backtrace the optimal result. Given our+-- alignment, knowing that we get an alignment score of 29 doesn't help us+-- much. But with /algebra products/ we can ask for @(optimal <** pretty)@+-- and get the optimal result /and/ the parse for it.+--+-- The @(<**)@ operator is notoriously difficult to write, so we just+-- compute it ☺.+--+-- Note that haddock actually shows @(<**)@, while you just write+-- @makeAlgebraProductH ['h] ''Signature@ (the primes are TemplateHaskell!,+-- the only TemplateHaskell we need).++makeAlgebraProduct ''Signature++-- | This is the linear grammar in two dimensions describing the+-- "Needleman-Wunsch" search space. It will, in principle, enumerate the+-- exponential number of possible alignment, but due to memoization and the+-- choice function @h@, the calculation time is @O(N^2)@ and if only one+-- optimal alignment is requested, backtracking works in linear time.+--+-- The grammar first requires a 'Signature', we use @RecordWildCards@ as+-- a language extension to bind @step_step@ and friends. We also need+-- a variable for the single non-terminal (@a@), and have two inputs @i1@+-- and @i2@. Each grammar starts with a "base case" @Z:.@ followed by one+-- or more pairs of non-terminal plus rules. Here we have one pair @(a,+-- rules)@, where in @rules@ we combine the four different rules.+--+-- @step_step \<\<\< a % (M:>chr i1:>chr i2)@, for example, means that+-- @step_step@ first gets the non-terminal @a@, which will give the score+-- up to @d@ (see the ascii-art above), followed by @(%)@ the 2-dim+-- terminal for @i1@ and @i2@.+--+-- Multi-dimensional terminals are built up from the zero-dimension @M@,+-- separated by @:|@ symbols and just bind the input. In this case we want+-- individual characters from @i1@ and @i2@, so we write @chr i1@ or @chr+-- i2@.+--+-- Different rules are combined with @(|||)@ and the optimal case is+-- selected via @... h@. Rules can, of course, be co-recursive, each rule+-- can request all terminal and non-terminal symbols.+--+-- Due to the way @nil_nil@ works on @Epsilon@, @nil_nil@ is actually /only/+-- called once, when we start the alignment, not for every cell!+--+-- /However/, due to this being a high-performance library, we do not+-- provide a runtime scheme to detect misbehaving rules. Some debug-code is+-- in place that performs certain checks in non-optimized GHCI sessions,+-- but optimized code is built for raw speed, without any checks.+--+-- If you are a "conventional" DP programmer, you might miss the usual+-- indices. Just as in the spiritual father of @ADPfusion@, Robert+-- Giegerichs @ADP@, we hide the actual index calculations.++grammar Signature{..} a' i1 i2 =+ let a = a' ( step_step <<< a % (M:|chr i1:|chr i2) |||+ step_loop <<< a % (M:|chr i1:|Deletion ) |||+ loop_step <<< a % (M:|Deletion :|chr i2) |||+ nil_nil <<< (M:|Epsilon:|Epsilon) ... h+ )+ in Z:.a+{-# INLINE grammar #-}++-- | A grammar alone is not enough, we also need to say what a @step_step@+-- means, or what an optimum is. Here, we do exactly that. We create an+-- instance of the 'Signature' from above. Since this is a simple example,+-- we just say that two aligned characters @a@ and @b@ yield a score of+-- @x+1@ (with @x@ the previous alignment score) if the characters are+-- identical. Otherwise we lower the score by 2. In/dels incur a cost of+-- @-1@, meaning that a mismatch is actually the same as two in/dels, one+-- in each dimension. The start of the alignment gives an initial score of+-- 0.+--+-- And the optimal choice, of course, is to start with a default of+-- @-999999@ and find the maximum of that score and the choices we are+-- given.++sScore :: Monad m => Signature m Int Int Char+sScore = Signature+ { step_step = \x (Z:.a:.b) -> if a==b then x+1 else x-2+ , step_loop = \x _ -> x-1+ , loop_step = \x _ -> x-1+ , nil_nil = const 0+ , h = SM.foldl' max (-999999)+ }+{-# INLINE sScore #-}++-- | Scores alone are not enough, we also want to pretty-print alignments.+-- An alignment are basically two strings @[String 1, String 2]@, being+-- turned into a whole stream of alignments, using @Char@s for the+-- individual characters being aligned.+--+-- We follow the same theme as in 'sScore', but this time @h = return+-- . id@, that is the choice function @h@ does not (!) make choice but+-- rather returns all alignments. You already heard about @<**@, we'll use+-- it below.++sPretty :: Monad m => Signature m [String] [[String]] Char+sPretty = Signature+ { step_step = \[x,y] (Z:.a :.b ) -> [a :x, b :y]+ , step_loop = \[x,y] (Z:.a :.()) -> [a :x, '-':y]+ , loop_step = \[x,y] (Z:.():.b ) -> ['-':x, b :y]+ , nil_nil = const ["",""]+ , h = SM.toList+ }+{-# Inline sPretty #-}++-- | The inside grammar, with efficient table-filling (via+-- 'nwInsideForward') and backtracking. Requests @k@ co-optimal+-- backtrackings, given the inputs @i1@ and @i2@. The @fst@ element+-- returned is the score, the @snd@ are the co-optimal parses.++runNeedlemanWunsch :: Int -> String -> String -> (Int,[[String]])+runNeedlemanWunsch k i1' i2' = (d, take k bs) where+ i1 = VU.fromList i1'+ i2 = VU.fromList i2'+ n1 = VU.length i1+ n2 = VU.length i2+ !(Z:.t) = nwInsideForward i1 i2+ d = unId $ axiom t+ bs = nwInsideBacktrack i1 i2 t+{-# Noinline runNeedlemanWunsch #-}++-- | The forward or table-filling phase. It is possible to inline this code+-- directly into 'runNeedlemanWunsch'. Here, this phase is separated. If+-- you use @ghc-core@ to examine the @GHC Core@ language, you can search+-- for @nwInsideForward@ and check wether the inside code is optimized+-- well. This is normally /not/ required, and only done here, because these+-- algorithms are used to gauge efficiency of the fusion framework as well.+--+-- For your own code, you can write as done here, or in the way of+-- 'runOutsideNeedlemanWunsch'.++nwInsideForward :: VU.Vector Char -> VU.Vector Char -> Z:.ITbl Id Unboxed (Z:.PointL:.PointL) Int+nwInsideForward i1 i2 = {-# SCC "nwInsideForward" #-} mutateTablesDefault $+ grammar sScore+ (ITbl 0 0 (Z:.EmptyOk:.EmptyOk) (PA.fromAssocs (Z:.PointL 0:.PointL 0) (Z:.PointL n1:.PointL n2) (-999999) []))+ i1 i2+ where n1 = VU.length i1+ n2 = VU.length i2+{-# NoInline nwInsideForward #-}++nwInsideBacktrack :: VU.Vector Char -> VU.Vector Char -> ITbl Id Unboxed (Z:.PointL:.PointL) Int -> [[String]]+nwInsideBacktrack i1 i2 t = {-# SCC "nwInsideBacktrack" #-} unId $ axiom b+ where !(Z:.b) = grammar (sScore <|| sPretty) (toBacktrack t (undefined :: Id a -> Id a)) i1 i2+{-# NoInline nwInsideBacktrack #-}++-- | The outside version of the Needleman-Wunsch alignment algorithm. The+-- outside grammar is identical to the inside grammar! This is not+-- generally the case, but here it is. Hence we may just use outside tables+-- and the grammar from above.++runOutsideNeedlemanWunsch :: Int -> String -> String -> (Int,[[String]])+runOutsideNeedlemanWunsch k i1' i2' = {-# SCC "runOutside" #-} (d, take k . unId $ axiom b) where -- . S.toList . unId $ axiom b) where -- ,gogo) where+ i1 = VU.fromList i1'+ i2 = VU.fromList i2'+ n1 = VU.length i1+ n2 = VU.length i2+ !(Z:.t) = nwOutsideForward i1 i2+ -- d = let (ITbl _ _ arr _) = t in arr PA.! (O (Z:.PointL 0:.PointL 0))+ d = iTblArray t PA.! (O (Z:.PointL 0:.PointL 0))+ !(Z:.b) = grammar (sScore <|| sPretty) (toBacktrack t (undefined :: Id a -> Id a)) i1 i2+{-# Noinline runOutsideNeedlemanWunsch #-}++-- | Again, to be able to observe performance, we have extracted the+-- outside-table-filling part.++nwOutsideForward :: VU.Vector Char -> VU.Vector Char -> Z:.ITbl Id Unboxed (Outside (Z:.PointL:.PointL)) Int+nwOutsideForward i1 i2 = {-# SCC "nwOutsideForward" #-} mutateTablesDefault $+ grammar sScore+ (ITbl 0 0 (Z:.EmptyOk:.EmptyOk) (PA.fromAssocs (O (Z:.PointL 0:.PointL 0)) (O (Z:.PointL n1:.PointL n2)) (-999999) []))+ i1 i2+ where n1 = VU.length i1+ n2 = VU.length i2+{-# Noinline nwOutsideForward #-}++-- | This wrapper takes a list of input sequences and aligns each odd+-- sequence with the next even sequence. We want one alignment for each+-- such pair.+--+-- Since we use basic lists during backtracking, the resulting lists have+-- to be reversed for inside-backtracking. Note that because the Outside+-- grammar is quasi-right-linear, it does not require reversing the two+-- strings.+--+-- For real applications, consider using @Data.Sequence@ which has @O(1)@+-- append and prepend.++align _ [] = return ()+align _ [c] = putStrLn "single last line"+align k (a:b:xs) = {-# SCC "align" #-} do+ putStrLn a+ putStrLn b+ putStrLn ""+ let (sI,rsI) = runNeedlemanWunsch k a b+ let (sO,rsO) = runOutsideNeedlemanWunsch k a b+ forM_ rsI $ \[u,l] -> printf "%s\n%s %d\n\n" (reverse u) (reverse l) sI+ forM_ rsO $ \[u,l] -> printf "%s\n%s %d\n\n" (id u) (id l) sO+ align k xs++-- | And finally have a minimal main that reads from stdio.+--+-- If you are brave enough then put this through @ghc-core@ and look for+-- @nwInsideForward@ or @nwOutsideForward@ in the CORE. Everything coming+-- from the forward phase should be beautifully optimized and the algorithm+-- should run quite fast.++main = do+ as <- getArgs+ let k = if null as then 1 else read $ head as+ ls <- lines <$> getContents+ align k ls+
+ src/Nussinov.hs view
@@ -0,0 +1,132 @@++-- | Nussinovs RNA secondary structure prediction algorithm via basepair+-- maximization.++module Main where++import Control.Applicative+import Control.Monad+import Control.Monad.ST+import Data.Char (toUpper,toLower)+import Data.List as L+import Data.Vector.Fusion.Util+import Debug.Trace+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Unboxed as VU+import System.Environment (getArgs)+import Text.Printf++import Data.PrimitiveArray as PA++import ADP.Fusion++++data Nussinov m x r c = Nussinov+ { unp :: x -> c -> x+ , jux :: x -> c -> x -> c -> x+ , nil :: () -> x+ , h :: SM.Stream m x -> m r+ }++makeAlgebraProduct ''Nussinov++{-+ - due to backtracking schemes, we need a bunch of combintors+ -+ - how to deal with sup-optimal backtracking, without having to use (*||) ?++(<||) :: Single a -> List b -> List b -- co-optimal backtracking+(*||) :: Vector a -> List b -> List (a,b) -- classified co-optimal backtracking+(***) :: Single a -> Single b -> Vector (a,b) -- classified DP++-}++bpmax :: Monad m => Nussinov m Int Int Char+bpmax = Nussinov+ { unp = \ x c -> x+ , jux = \ x c y d -> if c `pairs` d then x + y + 1 else -999999+ , nil = \ () -> 0+ , h = SM.foldl' max (-999999)+ }+{-# INLINE bpmax #-}++prob :: Monad m => Nussinov m Double Double Char+prob = Nussinov+ { unp = \ x c -> 0.3 * x+ , jux = \ x c y d -> 0.6 * if c `pairs` d then x * y else 0+ , nil = \ () -> 0.1+ , h = SM.foldl' (+) 0+ }++-- |++pairs !c !d+ = c=='A' && d=='U'+ || c=='C' && d=='G'+ || c=='G' && d=='C'+ || c=='G' && d=='U'+ || c=='U' && d=='A'+ || c=='U' && d=='G'+{-# INLINE pairs #-}++pretty :: Monad m => Nussinov m String [String] Char -- (SM.Stream m String)+pretty = Nussinov+ { unp = \ x c -> x ++ "."+ , jux = \ x c y d -> x ++ "(" ++ y ++ ")"+ , nil = \ () -> ""+ , h = SM.toList -- return . id+ }+{-# INLINE pretty #-}++prettyL :: Monad m => Nussinov m String String Char+prettyL = Nussinov+ { unp = \ x c -> x ++ "."+ , jux = \ x c y d -> x ++ "(" ++ y ++ ")"+ , nil = \ () -> ""+ , h = SM.head -- return . id+ }+{-# INLINE prettyL #-}++grammar Nussinov{..} c t' =+ let t = t' ( unp <<< t % c |||+ jux <<< t % c % t % c |||+ nil <<< Epsilon ... h+ )+ in Z:.t+{-# INLINE grammar #-}++runNussinov :: Int -> String -> (Int,[String])+runNussinov k inp = (d, take k bs) where -- . {- . S.toList . -} unId $ axiom b) where+ i = VU.fromList . Prelude.map toUpper $ inp+ n = VU.length i+ !(Z:.t) = runInsideForward i+ d = unId $ axiom t+ bs = runInsideBacktrack i t+{-# NOINLINE runNussinov #-}++runInsideForward :: VU.Vector Char -> Z:.ITbl Id Unboxed Subword Int+runInsideForward i = mutateTablesDefault+ $ grammar bpmax+ (chr i)+ (ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) (-999999) []))+ where n = VU.length i+{-# NoInline runInsideForward #-}++runInsideBacktrack :: VU.Vector Char -> ITbl Id Unboxed Subword Int -> [String]+runInsideBacktrack i t = unId $ axiom b+ where !(Z:.b) = grammar (bpmax <|| pretty) (chr i) (toBacktrack t (undefined :: Id a -> Id a))+{-# NoInline runInsideBacktrack #-}++main = do+ as <- getArgs+ let k = if null as then 1 else read $ head as+ ls <- lines <$> getContents+ forM_ ls $ \l -> do+ putStrLn l+ let (s,xs) = runNussinov k l+ mapM_ (\x -> printf "%s %5d\n" x s) xs+
+ src/PartNussinov.hs view
@@ -0,0 +1,275 @@++-- | Nussinovs RNA secondary structure prediction algorithm via basepair+-- maximization.++module Main where++import Control.Applicative+import Control.Monad+import Control.Monad.ST+import Data.Char (toUpper,toLower)+import Data.List+import Data.Vector.Fusion.Util+import Debug.Trace+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Numeric.Log as Log+import qualified Data.Vector.Fusion.Stream as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM+import qualified Data.Vector.Unboxed as VU+import System.Environment (getArgs)+import Text.Printf++import Data.PrimitiveArray as PA++import ADP.Fusion++++-- * Inside and Outside grammar constructs++data Nussinov m c e x r = Nussinov+ { unp :: x -> c -> x+ , jux :: x -> x -> x+ , pai :: c -> x -> c -> x+ , nil :: e -> x+ , h :: SM.Stream m x -> m r+ }++makeAlgebraProduct ''Nussinov++bpmax :: Monad m => Nussinov m Char () Int Int+bpmax = Nussinov+ { unp = \ x c -> x+ , jux = \ x y -> x + y+ , pai = \ c x d -> if c `pairs` d then x+1 else (-999999)+ , nil = \ () -> 0+ , h = SM.foldl' max (-999999)+ }+{-# INLINE bpmax #-}++prob :: Monad m => Nussinov m Char () (Log Double) (Log Double)+prob = Nussinov+ { unp = \ x c -> 0.1 * x -- 'any'+ , jux = \ x y -> 0.9 * x * y -- 'any'+ , pai = \ c x d -> 1.0 * if c `pairs` d then x else 0 -- 'paired'+ , nil = \ () -> 1.0 -- 'any'+ , h = SM.foldl' (+) 0+ }+{-# Inline prob #-}++-- |++pairs !c !d+ = c=='A' && d=='U'+ || c=='C' && d=='G'+ || c=='G' && d=='C'+ || c=='G' && d=='U'+ || c=='U' && d=='A'+ || c=='U' && d=='G'+{-# INLINE pairs #-}++pretty :: Monad m => Nussinov m Char () String (SM.Stream m String)+pretty = Nussinov+ { unp = \ x c -> x ++ "."+ , jux = \ x y -> x ++ y+ , pai = \ c x d -> "(" ++ x ++ ")"+ , nil = \ () -> ""+ , h = return . id+ }+{-# INLINE pretty #-}++-- | The inside grammar is:+--+-- @+-- A -> A c+-- A -> A P+-- A -> ε+-- P -> c A c+-- @++-- insideGrammar :: Nussinov m Char () x r -> c' -> t' -> (t', Subword -> m r)+insideGrammar Nussinov{..} c a' p' =+ let a = a' ( unp <<< a % c |||+ jux <<< a % p |||+ nil <<< Epsilon ... h+ )+ p = p' ( pai <<< c % a % c ... h+ )+ in Z:.p:.a+{-# INLINE insideGrammar #-}++-- | Given the inside grammar, the outside grammar is:+--+-- @+-- B -> B c+-- B -> B P+-- B -> ε+-- B -> c Q c+-- Q -> A B+-- @++outsideGrammar Nussinov{..} c a p b' q' =+ let b = b' ( unp <<< b % c |||+ jux <<< b % p |||+ pai <<< c % q % c |||+ nil <<< Epsilon ... h+ )+ q = q' ( jux <<< a % b ... h+ )+ in Z:.b:.q+{-# INLINE outsideGrammar #-}++++-- * Ensemble collection constructs++data NussinovEnsemble m v ci x r = NussinovEnsemble+ { ens :: v -> ci -> v -> x+ , hhh :: SM.Stream m x -> m r+ }++ensemble+ :: Monad m+ => Log Double+ -> NussinovEnsemble+ m+ (Log Double)+ (Complement Subword:.(Complement Subword))+ (Subword, Log Double)+ [(Subword, Log Double)]+ensemble z = NussinovEnsemble+ { ens = \ x (C k:._) y -> ( k , x * y / z )+ , hhh = SM.toList+ }+{-# Inline ensemble #-}++ensembleGrammar NussinovEnsemble{..} i o v' =+ let v = v' ( ens <<< i % (PeekIndex :: PeekIndex (Complement Subword)) % o ... hhh )+ in Z:.v+{-# Inline ensembleGrammar #-}++-- makeAlgebraProductH ['hhh] ''NussinovEnsemble++++-- * Run different algorithm parts++runNussinov :: String -> ([(Subword, Log Double)], Log Double, [(Int,Int, Log Double, Log Double, Log Double, Log Double)])+runNussinov inp = (es,z,ys) where+ i = VU.fromList . Prelude.map toUpper $ inp+ n = VU.length i+ !(Z:.p:.a) = runInsideForward i+ !(Z:.b:.q) = runOutsideForward i a p+ es = runEnsembleForward z p q+ za = let (ITbl _ _ _ arr _) = a in arr PA.! subword 0 n+ zp = let (ITbl _ _ _ arr _) = p in arr PA.! subword 0 n+ z = za+ e = let (ITbl _ _ _ arr _) = b in Log.sum [ arr PA.! (O $ subword k k) | k <- [0 .. n] ]+ ys = [ ( k+ , l+ , fwda PA.! subword k l+ , fwdp PA.! subword k l+ , bwdb PA.! (O $ subword k l)+ , bwdq PA.! (O $ subword k l)+ )+ | let (ITbl _ _ _ fwda _) = a+ , let (ITbl _ _ _ fwdp _) = p+ , let (ITbl _ _ _ bwdb _) = b+ , let (ITbl _ _ _ bwdq _) = q+ , k <- [0 .. n]+ , l <- [k .. n]+ ]+{-# NOINLINE runNussinov #-}++neat :: String -> IO ()+neat i = do let (es,z,ys) = runNussinov i+ forM_ ys $ \ (k,_,_,_,_,_) -> printf " %6d" k+ putStrLn ""+ forM_ ys $ \ (_,l,_,_,_,_) -> printf " %6d" l+ putStrLn ""+ forM_ ys $ \ (_,_,a,_,_,_) -> printf " %0.4f" (exp $ ln a)+ putStrLn ""+ forM_ ys $ \ (_,_,_,p,_,_) -> printf " %0.4f" (exp $ ln p)+ putStrLn ""+ forM_ ys $ \ (_,_,_,_,b,_) -> printf " %0.4f" (exp $ ln b)+ putStrLn ""+ forM_ ys $ \ (_,_,_,_,_,q) -> printf " %0.4f" (exp $ ln q)+ putStrLn ""+ printf "%0.4f\n" $ exp $ ln z+ forM_ ys $ \ (_,_,_,p,_,q) -> printf " %0.4f" ((exp $ ln p) * (exp $ ln q) / (exp $ ln z))+ putStrLn ""+ putStrLn ""+ forM_ es $ \ (Subword (i:.j),v) -> printf "%3d %3d %0.4f\n" i j (exp $ ln v)+ putStrLn ""++type TblI = ITbl Id Unboxed Subword (Log Double)+type TblO = ITbl Id Unboxed (Outside Subword) (Log Double)++runInsideForward :: VU.Vector Char -> Z:.TblI:.TblI+runInsideForward i = mutateTablesDefault+ $ insideGrammar prob+ (chr i)+ (ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) 0 []))+ (ITbl 0 0 EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) 0 []))+ where n = VU.length i+{-# NoInline runInsideForward #-}++runOutsideForward :: VU.Vector Char -> TblI -> TblI -> Z:.TblO:.TblO+runOutsideForward i a p = mutateTablesDefault+ $ outsideGrammar prob+ (chr i)+ a p+ (ITbl 0 0 EmptyOk (PA.fromAssocs (O $ subword 0 0) (O $ subword 0 n) 0 []))+ (ITbl 0 1 EmptyOk (PA.fromAssocs (O $ subword 0 0) (O $ subword 0 n) 0 []))+ where n = VU.length i+{-# NoInline runOutsideForward #-}++runEnsembleForward :: Log Double -> TblI -> TblO -> [ (Subword,Log Double) ]+runEnsembleForward z i o = unId $ axiom g+ where (Z:.g) = ensembleGrammar (ensemble z)+ i o+ (IRec EmptyOk (C l) (C h))+ :: Z :. IRec Id (Complement Subword) [(Subword, Log Double)]+ (l,h) = let (ITbl _ _ _ arr _) = i in bounds arr+{-# NoInline runEnsembleForward #-}++{-+runPartitionNussinov :: String -> [(Subword,Double,Double,Double)]+runPartitionNussinov inp+ = Data.List.map (\(sh,a) -> let b = iTblArray t PA.! (O sh)+ in (sh, a, b, a*b/d)+ ) (PA.assocs $ iTblArray s)+ where+ i = VU.fromList . Prelude.map toUpper $ inp+ n = VU.length i+ s :: ITbl Id Unboxed Subword Double+ !(Z:.s) = mutateTablesDefault+ $ grammar prob+ (chr i)+ (ITbl EmptyOk (PA.fromAssocs (subword 0 0) (subword 0 n) 0 []))+ + d = iTblArray s PA.! subword 0 n+ t :: ITbl Id Unboxed (Outside Subword) Double+ !(Z:.t) = mutateTablesDefault+ $ outsideGrammar prob+ (chr i)+ --(undefined :: ITbl Id Unboxed (Outside Subword) Double)+ s+ (ITbl EmptyOk (PA.fromAssocs (O $ subword 0 0) (O $ subword 0 n) (-1) []))+{-# NOINLINE runPartitionNussinov #-}+-}++main :: IO ()+main = do+ return ()+ {-+ as <- getArgs+ let k = if null as then 1 else read $ head as+ ls <- lines <$> getContents+ forM_ ls $ \l -> do+ putStrLn l+ let (s,xs) = runNussinov k l+ mapM_ (\x -> printf "%s %5d\n" x s) xs+ -}+
+ tests/properties.hs view
@@ -0,0 +1,90 @@++-- | Test all properties automatically. We keep the QC2 modules in the main+-- library for now, as this allows for more efficient repl tests.++module Main where++import Test.Framework.Providers.QuickCheck2+import Test.Framework.TH++import qualified ADP.Fusion.QuickCheck.Subword as QSW+import qualified ADP.Fusion.QuickCheck.Set as QS+import qualified ADP.Fusion.QuickCheck.Point as QP+import ADP.Fusion.QuickCheck.Point+++{-+grep -o -e "^prop_[[:alnum:]_]*" ADP/Fusion/QuickCheck/Subword.hs | awk '{print $1"QSW", "=", "QSW."$1 }' | uniq+grep -o -e "^prop_[[:alnum:]_]*" ADP/Fusion/QuickCheck/Set.hs | awk '{print $1"QS", "=", "QS."$1 }' | uniq+grep -o -e "^prop_[[:alnum:]_]*" ADP/Fusion/QuickCheck/Point.hs | awk '{print $1"QP", "=", "QP."$1 }' | uniq+-}++-- subwords++prop_sv_OIQSW = QSW.prop_sv_OI+prop_sv_IOQSW = QSW.prop_sv_IO+prop_sv_OIIQSW = QSW.prop_sv_OII+prop_sv_IOIQSW = QSW.prop_sv_IOI+prop_sv_IIOQSW = QSW.prop_sv_IIO+prop_cOcQSW = QSW.prop_cOc+prop_ccOccQSW = QSW.prop_ccOcc+prop_cOcccQSW = QSW.prop_cOccc+prop_cOcIcQSW = QSW.prop_cOcIc+prop_cIcOcQSW = QSW.prop_cIcOc+prop_EpsilonQSW = QSW.prop_Epsilon++-- sets++prop_b_iiQS = QS.prop_b_ii+prop_b_ii_nnQS = QS.prop_b_ii_nn+prop_b_iiiQS = QS.prop_b_iii+prop_b_iii_nnnQS = QS.prop_b_iii_nnn+prop_bii_iQS = QS.prop_bii_i+prop_bii_i_nQS = QS.prop_bii_i_n+prop_bii_eQS = QS.prop_bii_e+prop_bii_ieQS = QS.prop_bii_ie+prop_bii_ie_nQS = QS.prop_bii_ie_n+prop_bii_ieeQS = QS.prop_bii_iee+prop_bii_ieeeQS = QS.prop_bii_ieee+prop_bii_iee_nQS = QS.prop_bii_iee_n+prop_bii_ieee_nQS = QS.prop_bii_ieee_n++-- points++prop_EpsilonQP = QP.prop_Epsilon+prop_O_EpsilonQP = QP.prop_O_Epsilon+prop_ZEpsilonQP = QP.prop_ZEpsilon+prop_O_ZEpsilonQP = QP.prop_O_ZEpsilon+prop_O_ZEpsilonEpsilonQP = QP.prop_O_ZEpsilonEpsilon+prop_O_ItNCQP = QP.prop_O_ItNC+prop_O_ZItNCQP = QP.prop_O_ZItNC+prop_O_2dimIt_NC_CNQP = QP.prop_O_2dimIt_NC_CN+prop_2dimIt_NC_CNQP = QP.prop_2dimIt_NC_CN+prop_TtQP = QP.prop_Tt+prop_CCQP = QP.prop_CC+prop_ItQP = QP.prop_It+prop_O_ItQP = QP.prop_O_It+prop_ZItQP = QP.prop_ZIt+prop_O_ZItQP = QP.prop_O_ZIt+prop_ItCQP = QP.prop_ItC+prop_O_ItCQP = QP.prop_O_ItC+prop_O_ItCCQP = QP.prop_O_ItCC+prop_O_ZItCCQP = QP.prop_O_ZItCC+prop_2dimItCCQP = QP.prop_2dimItCC+prop_O_2dimItCCQP = QP.prop_O_2dimItCC+prop_ManySQP = QP.prop_ManyS+prop_SomeSQP = QP.prop_SomeS+prop_2dim_ManyS_ManySQP = QP.prop_2dim_ManyS_ManyS+prop_2dim_SomeS_SomeSQP = QP.prop_2dim_SomeS_SomeS+prop_Itbl_ManySQP = QP.prop_Itbl_ManyS+prop_Itbl_SomeSQP = QP.prop_Itbl_SomeS+prop_1dim_Itbl_ManySQP = QP.prop_1dim_Itbl_ManyS+prop_1dim_Itbl_SomeSQP = QP.prop_1dim_Itbl_SomeS+prop_2dim_Itbl_ManyS_ManySQP = QP.prop_2dim_Itbl_ManyS_ManyS+prop_2dim_Itbl_SomeS_SomeSQP = QP.prop_2dim_Itbl_SomeS_SomeS++++main :: IO ()+main = $(defaultMainGenerator)+