module ADP.Fusion.Core.SynVar.Recursive.Type where import Control.Applicative (Applicative,(<$>),(<*>)) import Control.Monad.Morph import Data.Proxy import Data.Strict.Tuple import Data.Vector.Fusion.Stream.Monadic (Stream,head,map,mapM) import Prelude hiding (head,map,mapM) import Data.PrimitiveArray hiding (map) import ADP.Fusion.Core.Classes import ADP.Fusion.Core.Multi import ADP.Fusion.Core.SynVar.Axiom import ADP.Fusion.Core.SynVar.Backtrack import ADP.Fusion.Core.SynVar.Indices import ADP.Fusion.Core.SynVar.TableWrap -- | A syntactic variable that does not memoize but simplify recurses. One -- needs to be somewhat careful when using this one. @ITbl@ performs -- memoization to perform DP in polynomial time (roughly speaking). If the -- rules for an @IRec@ are of a particular type, they will exponential -- running time. Things like @X -> X X@ are, for example, rather bad. Rules -- of the type @X -> Y, Y -> Z@ are ok, if @Y@ is an @IRec@ since we just -- continue on. The same holds for @Y -> a Y@. Basically, things are safe -- if there is only a (small) constant number of parses of an @IRec@ -- synvar. data IRec c i x where IRec ∷ { iRecConstraint ∷ !c , iRecTo ∷ !(LimitType i) } → IRec c i x type TwIRec (m ∷ * → *) c i x = TW (IRec c i x) (LimitType i → i → m x) type TwIRecBt c i x mF mB r = TW (Backtrack (TwIRec mF c i x) mF mB) (LimitType i → i → mB [r]) instance Build (TwIRec m c i x) instance Build (TwIRecBt c i x mF mB r) type instance TermArg (TwIRec m c i x) = x instance GenBacktrackTable (TwIRec mF c i x) mF mB where data Backtrack (TwIRec mF c i x) mF mB = BtIRec !c !(LimitType i) !(LimitType i → i → mB x) type BacktrackIndex (TwIRec mF c i x) = i toBacktrack (TW (IRec c iT) f) mrph = BtIRec c iT (\lu i -> mrph $ f lu i) {-# Inline toBacktrack #-} instance ( Monad m , IndexStream i ) ⇒ Axiom (TwIRec m c i x) where type AxiomStream (TwIRec m c i x) = m x axiom (TW (IRec _ h) fun) = do k ← head $ streamDown zeroBound' h fun h k {-# Inline axiom #-} instance ( Monad mB , IndexStream i , i ~ j , m ~ mB ) ⇒ Axiom (TW (Backtrack (TwIRec mF c i x) mF mB) (LimitType j → j → m [r])) where type AxiomStream (TW (Backtrack (TwIRec mF c i x) mF mB) (LimitType j → j → m [r])) = mB [r] axiom (TW (BtIRec c h fun) btfun) = do k <- head $ streamDown zeroBound' h btfun h k {-# Inline axiom #-} instance Element ls i ⇒ Element (ls :!: TwIRec m c u x) i where data Elm (ls :!: TwIRec m c u x) i = ElmIRec !x !(RunningIndex i) !(Elm ls i) type Arg (ls :!: TwIRec m c u x) = Arg ls :. x getArg (ElmIRec x _ ls) = getArg ls :. x getIdx (ElmIRec _ i _ ) = i {-# Inline getArg #-} {-# Inline getIdx #-} instance Element ls i ⇒ Element (ls :!: TwIRecBt c u x mF mB r) i where data Elm (ls :!: (TwIRecBt c u x mF mB r)) i = ElmBtIRec !x [r] !(RunningIndex i) !(Elm ls i) type Arg (ls :!: (TwIRecBt c u x mF mB r)) = Arg ls :. (x, [r]) getArg (ElmBtIRec x s _ ls) = getArg ls :. (x,s) getIdx (ElmBtIRec _ _ i _ ) = i {-# Inline getArg #-} {-# Inline getIdx #-} instance ( Functor m , Monad m , pos ~ (ps:.p) , posLeft ~ LeftPosTy pos (TwIRec m (cs:.c) (us:.u) x) (is:.i) , Element ls (is:.i) -- , TableStaticVar ps cs us is -- , TableStaticVar p c u i , TableStaticVar (ps:.p) (cs:.c) (us:.u) (is:.i) , AddIndexDense pos (Elm ls (is:.i)) (cs:.c) (us:.u) (is:.i) , MkStream m posLeft ls (is:.i) ) ⇒ MkStream m ('(:.) ps p) (ls :!: TwIRec m (cs:.c) (us:.u) x) (is:.i) where mkStream Proxy (ls :!: TW (IRec csc h) fun) grd usu isi = mapM (\(s,tt,ii) -> (\res -> ElmIRec res ii s) <$> fun h tt) . addIndexDense (Proxy ∷ Proxy pos) csc h usu isi $ mkStream (Proxy ∷ Proxy posLeft) ls grd usu (tableStreamIndex (Proxy ∷ Proxy pos) csc h isi) {-# Inline mkStream #-} instance ( Applicative mB , Monad mB , pos ~ (ps :. p) , posLeft ~ LeftPosTy pos (TwIRecBt (cs:.c) (us:.u) x mF mB r) (is:.i) , Element ls (is:.i) -- , TableStaticVar (us:.u) (cs:.c) (is:.i) -- , TableStaticVar ps cs us is -- , TableStaticVar p c u i , TableStaticVar (ps:.p) (cs:.c) (us:.u) (is:.i) , AddIndexDense pos (Elm ls (is:.i)) (cs:.c) (us:.u) (is:.i) , MkStream mB posLeft ls (is:.i) ) => MkStream mB ('(:.) ps p) (ls :!: TwIRecBt (cs:.c) (us:.u) x mF mB r) (is:.i) where mkStream Proxy (ls :!: TW (BtIRec csc h fun) bt) grd usu isi = mapM (\(s,tt,ii) -> (\res bb -> ElmBtIRec res bb ii s) <$> fun h tt <*> bt h tt) . addIndexDense (Proxy ∷ Proxy pos) csc h usu isi $ mkStream (Proxy ∷ Proxy posLeft) ls grd usu (tableStreamIndex (Proxy :: Proxy pos) csc h isi) {-# Inline mkStream #-}