1 {-# LANGUAGE PatternSynonyms #-} -- For Comb
2 {-# LANGUAGE TemplateHaskell #-} -- For branch
3 {-# LANGUAGE ViewPatterns #-} -- For unSimplComb
4 {-# OPTIONS_GHC -fno-warn-orphans #-} -- For MakeLetName TH.Name
5 -- | Bottom-up optimization of 'Comb'inators,
6 -- reexamining downward as needed after each optimization.
7 module Symantic.Parser.Grammar.Optimize where
9 import Data.Bool (Bool(..), (&&), not)
10 import Data.Bifunctor (second)
11 import Data.Either (Either(..), either)
12 import Data.Eq (Eq(..))
13 import Data.Function (($), (.))
14 import Data.Kind (Constraint)
15 import Data.Maybe (Maybe(..))
16 import Data.Functor.Identity (Identity(..))
17 import Unsafe.Coerce (unsafeCoerce)
18 import Type.Reflection (Typeable, typeRep, eqTypeRep, (:~~:)(..))
19 import Data.Semigroup (Semigroup(..))
20 import qualified Data.Foldable as Foldable
21 import qualified Data.Functor as F
22 import qualified Data.HashMap.Strict as HM
23 import qualified Data.HashSet as HS
24 import Data.Hashable (Hashable)
25 import qualified Language.Haskell.TH as TH
27 import Symantic.Parser.Grammar.Combinators
28 import Symantic.Parser.Grammar.Production
29 import Symantic.Parser.Grammar.SharingObserver
30 import Symantic.Syntaxes.Derive
31 import qualified Symantic.Syntaxes.Classes as Prod
32 import qualified Symantic.Semantics.Data as Prod
35 import Data.Function (($), flip)
36 import Debug.Trace (trace)
41 type OptimizeGrammar = KnotComb TH.Name
43 -- | TODO: remove useless wrapping?
44 newtype TiedComb repr a = TiedComb
45 { combSimpl :: SimplComb repr a
46 --, combRefs :: HS.HashSet letName
50 data KnotComb letName repr a = KnotComb
51 { knotCombOpens :: OpenRecs letName (SomeLet (TiedComb repr))
52 -- ^ 'TiedComb' for all 'letName' in 'lets'.
54 LetRecs letName (SomeLet (TiedComb repr)) ->
56 -- ^ 'TiedComb' of the current combinator,
57 -- with access to the final 'knotCombOpens'.
61 Derivable (SimplComb repr) =>
62 KnotComb TH.Name repr a -> repr a
63 optimizeGrammar = derive . derive
65 type instance Derived (KnotComb letName repr) = SimplComb repr
66 instance Derivable (KnotComb letName repr) where
67 derive opt = combSimpl $
68 knotCombOpen opt (mutualFix (knotCombOpens opt))
69 instance LiftDerived (KnotComb letName repr) where
70 liftDerived x = KnotComb
71 { knotCombOpens = HM.empty
72 , knotCombOpen = \_final -> TiedComb
76 instance LiftDerived1 (KnotComb letName repr) where
78 { knotCombOpen = \final -> TiedComb
79 { combSimpl = f (combSimpl (knotCombOpen a final))
82 instance (Eq letName, Hashable letName) => LiftDerived2 (KnotComb letName repr) where
83 liftDerived2 f a b = KnotComb
84 { knotCombOpens = knotCombOpens a <> knotCombOpens b
85 , knotCombOpen = \final -> TiedComb
87 (combSimpl (knotCombOpen a final))
88 (combSimpl (knotCombOpen b final))
91 instance (Eq letName, Hashable letName) => LiftDerived3 (KnotComb letName repr) where
92 liftDerived3 f a b c = KnotComb
93 { knotCombOpens = HM.unions
98 , knotCombOpen = \final -> TiedComb
100 (combSimpl (knotCombOpen a final))
101 (combSimpl (knotCombOpen b final))
102 (combSimpl (knotCombOpen c final))
105 instance (Eq letName, Hashable letName) => LiftDerived4 (KnotComb letName repr) where
106 liftDerived4 f a b c d = KnotComb
107 { knotCombOpens = HM.unions
113 , knotCombOpen = \final -> TiedComb
115 (combSimpl (knotCombOpen a final))
116 (combSimpl (knotCombOpen b final))
117 (combSimpl (knotCombOpen c final))
118 (combSimpl (knotCombOpen d final))
122 -- * Data family 'Comb'
123 -- | 'Comb'inators of the 'Grammar'.
124 -- This is an extensible data-type.
126 (comb :: ReprComb -> Constraint)
127 :: ReprComb -> ReprComb
128 type instance Derived (Comb comb repr) = repr
130 -- | 'unsafeCoerce' restrained to 'SimplComb'.
131 -- Useful to avoid dependant-map when inlining.
132 unsafeSimplComb :: SimplComb repr a -> SimplComb repr b
133 unsafeSimplComb = unsafeCoerce
135 -- | Convenient utility to pattern-match a 'SimplComb'.
136 pattern Comb :: Typeable comb => Comb comb repr a -> SimplComb repr a
137 pattern Comb x <- (unSimplComb -> Just x)
139 -- ** Type 'SimplComb'
140 -- | Interpreter simplifying combinators.
141 -- Useful to handle a list of 'Comb'inators
142 -- without requiring impredicative quantification.
143 -- Must be used by pattern-matching
144 -- on the 'SimplComb' data-constructor,
145 -- to bring the constraints in scope.
147 -- The optimizations are directly applied within it,
148 -- to avoid introducing an extra newtype,
149 -- this also give a more understandable code.
150 data SimplComb repr a =
152 (Derivable (Comb comb repr), Typeable comb) =>
154 { combData :: Comb comb repr a
155 -- ^ Some 'Comb'inator existentialized
156 -- over the actual combinator symantic class.
158 -- ^ Whether this combinator must be inlined
159 -- in place of a 'ref'erence pointing to it
160 -- (instead of generating a 'call').
161 , combRefs :: HS.HashSet TH.Name
162 -- ^ 'ref''s names reacheable from combinator
163 -- (including those behind 'ref's).
166 type instance Derived (SimplComb repr) = repr
167 instance Derivable (SimplComb repr) where
168 derive SimplComb{..} = derive combData
170 -- | @(unSimplComb c :: 'Maybe' ('Comb' comb repr a))@
171 -- extract the data-constructor from the given 'SimplComb'
172 -- iif. it belongs to the @('Comb' comb repr a)@ data-instance.
176 SimplComb repr a -> Maybe (Comb comb repr a)
177 unSimplComb SimplComb{ combData = c :: Comb c repr a } =
178 case typeRep @comb `eqTypeRep` typeRep @c of
183 data instance Comb CombAlternable repr a where
184 Alt :: Exception -> SimplComb repr a -> SimplComb repr a -> Comb CombAlternable repr a
185 Empty :: Comb CombAlternable repr a
186 Throw :: ExceptionLabel -> Comb CombAlternable repr a
187 Try :: SimplComb repr a -> Comb CombAlternable repr a
188 instance CombAlternable repr => Derivable (Comb CombAlternable repr) where
190 Alt exn x y -> alt exn (derive x) (derive y)
192 Throw exn -> throw exn
193 Try x -> try (derive x)
195 ( CombAlternable repr
196 , CombApplicable repr
199 , CombSelectable repr
200 ) => CombAlternable (SimplComb repr) where
204 , combRefs = HS.empty
207 alt _exn p@(Comb Pure{}) _ = p
208 -- & trace "Left Catch Law"
209 alt _exn (Comb Empty) u = u
210 -- & trace "Left Neutral Law"
211 alt _exn u (Comb Empty) = u
212 -- & trace "Right Neutral Law"
213 alt exn (Comb (Alt exn' u v)) w | exn' == exn = u <|> (v <|> w)
214 -- See Lemma 1 (Associativity of choice for labeled PEGs)
215 -- in https://doi.org/10.1145/2851613.2851750
216 -- & trace "Associativity Law"
217 alt exn (Comb (Look p)) (Comb (Look q)) = look (alt exn (try p) q)
218 -- & trace "Distributivity Law"
219 alt exn x y = SimplComb
220 { combData = Alt exn x y
222 , combRefs = combRefs x <> combRefs y
225 throw exn = SimplComb
226 { combData = Throw exn
228 , combRefs = HS.empty
231 try (Comb (p :$>: x)) = try p $> x
232 -- & trace "Try Interchange Law"
233 try (Comb (f :<$>: p)) = f <$> try p
234 -- & trace "Try Interchange Law"
238 , combRefs = combRefs x
241 ( CombApplicable repr
242 , CombAlternable repr
245 , CombSelectable repr
248 ) => CombAlternable (KnotComb letName repr)
251 data instance Comb CombApplicable repr a where
252 Pure :: Production '[] a -> Comb CombApplicable repr a
253 (:<*>:) :: SimplComb repr (a -> b) -> SimplComb repr a -> Comb CombApplicable repr b
254 (:<*:) :: SimplComb repr a -> SimplComb repr b -> Comb CombApplicable repr a
255 (:*>:) :: SimplComb repr a -> SimplComb repr b -> Comb CombApplicable repr b
256 infixl 4 :<*>:, :<*:, :*>:
257 pattern (:<$>:) :: Production '[] (a -> b) -> SimplComb repr a -> Comb CombApplicable repr b
258 pattern t :<$>: x <- Comb (Pure t) :<*>: x
259 pattern (:$>:) :: SimplComb repr a -> Production '[] b -> Comb CombApplicable repr b
260 pattern x :$>: t <- x :*>: Comb (Pure t)
261 instance CombApplicable repr => Derivable (Comb CombApplicable repr) where
264 f :<*>: x -> derive f <*> derive x
265 x :<*: y -> derive x <* derive y
266 x :*>: y -> derive x *> derive y
268 ( CombApplicable repr
269 , CombAlternable repr
272 , CombSelectable repr
273 ) => CombApplicable (SimplComb repr) where
276 , combInline = False -- TODO: maybe True?
277 , combRefs = HS.empty
279 f <$> Comb (Branch b l r) =
281 ((Prod..) Prod..@ f <$> l)
282 ((Prod..) Prod..@ f <$> r)
283 -- & trace "Branch Distributivity Law"
284 f <$> Comb (Conditional a bs def) =
286 (second (f <$>) F.<$> bs)
288 -- & trace "Conditional Distributivity Law"
289 -- Being careful here to use (<*>),
290 -- instead of SimplComb { combData = f <$> combData x },
291 -- in order to apply the optimizations of (<*>).
292 f <$> x = pure f <*> x
295 -- & trace "Commutativity Law"
297 Comb Empty <*> _ = empty
298 -- & trace "App Right Absorption Law"
299 u <*> Comb Empty = u *> empty
300 -- & trace "App Failure Weakening Law"
301 Comb (Pure f) <*> Comb (Pure x) = pure (f Prod..@ x)
302 -- & trace "Homomorphism Law"
304 Comb (Pure f) <*> Comb (g :<$>: p) =
305 -- This is basically a shortcut,
306 -- it can be caught by one Composition Law
307 -- and two Homomorphism Law.
308 (Prod..) Prod..@ f Prod..@ g <$> p
309 -- & trace "Functor Composition Law"
311 u <*> Comb (Pure x) = Prod.flip Prod..@ (Prod.$) Prod..@ x <$> u
312 -- & trace "Interchange Law"
313 u <*> Comb (v :<*>: w) = (((Prod..) <$> u) <*> v) <*> w
314 -- & trace "Composition Law"
315 Comb (u :*>: v) <*> w = u *> (v <*> w)
316 -- & trace "Reassociation Law 1"
317 u <*> Comb (v :<*: w) = (u <*> v) <* w
318 -- & trace "Reassociation Law 2"
319 u <*> Comb (v :$>: x) = (u <*> pure x) <* v
320 -- & trace "Reassociation Law 3"
321 p <*> Comb (NegLook q) =
322 (p <*> pure Prod.unit) <* negLook q
323 -- & trace "Absorption Law"
325 { combData = x :<*>: y
327 , combRefs = combRefs x <> combRefs y
330 Comb Empty *> _ = empty
331 -- & trace "App Right Absorption Law"
332 Comb (_ :<$>: p) *> q = p *> q
333 -- & trace "Right Absorption Law"
335 -- & trace "Identity Law"
336 Comb (u :$>: _) *> v = u *> v
337 -- & trace "Identity Law"
338 u *> Comb (v :*>: w) = (u *> v) *> w
339 -- & trace "Associativity Law"
341 { combData = x :*>: y
343 , combRefs = combRefs x <> combRefs y
346 Comb Empty <* _ = empty
347 -- & trace "App Right Absorption Law"
348 u <* Comb Empty = u *> empty
349 -- & trace "App Failure Weakening Law"
350 p <* Comb (_ :<$>: q) = p <* q
351 -- & trace "Left Absorption Law"
353 -- & trace "Identity Law"
354 u <* Comb (v :$>: _) = u <* v
355 -- & trace "Identity Law"
356 Comb (u :<*: v) <* w = u <* (v <* w)
357 -- & trace "Associativity Law"
359 { combData = x :<*: y
361 , combRefs = combRefs x <> combRefs y
364 ( CombApplicable repr
365 , CombAlternable repr
368 , CombSelectable repr
371 ) => CombApplicable (KnotComb letName repr)
374 data instance Comb CombFoldable repr a where
375 ChainPre :: SimplComb repr (a -> a) -> SimplComb repr a -> Comb CombFoldable repr a
376 ChainPost :: SimplComb repr a -> SimplComb repr (a -> a) -> Comb CombFoldable repr a
377 instance CombFoldable repr => Derivable (Comb CombFoldable repr) where
379 ChainPre op p -> chainPre (derive op) (derive p)
380 ChainPost p op -> chainPost (derive p) (derive op)
381 instance CombFoldable repr => CombFoldable (SimplComb repr) where
382 chainPre op p = SimplComb
383 { combData = ChainPre op p
385 , combRefs = combRefs op <> combRefs p
387 chainPost p op = SimplComb
388 { combData = ChainPost p op
390 , combRefs = combRefs p <> combRefs op
396 ) => CombFoldable (KnotComb letName repr)
399 data instance Comb CombLookable repr a where
400 Look :: SimplComb repr a -> Comb CombLookable repr a
401 NegLook :: SimplComb repr a -> Comb CombLookable repr ()
402 Eof :: Comb CombLookable repr ()
403 instance CombLookable repr => Derivable (Comb CombLookable repr) where
405 Look x -> look (derive x)
406 NegLook x -> negLook (derive x)
409 ( CombAlternable repr
410 , CombApplicable repr
412 , CombSelectable repr
414 ) => CombLookable (SimplComb repr) where
415 look p@(Comb Pure{}) = p
416 -- & trace "Pure Look Law"
417 look p@(Comb Empty) = p
418 -- & trace "Dead Look Law"
419 look (Comb (Look x)) = look x
420 -- & trace "Idempotence Law"
421 look (Comb (NegLook x)) = negLook x
422 -- & trace "Left Identity Law"
423 look (Comb (p :$>: x)) = look p $> x
424 -- & trace "Interchange Law"
425 look (Comb (f :<$>: p)) = f <$> look p
426 -- & trace "Interchange Law"
430 , combRefs = combRefs x
433 negLook (Comb Pure{}) = empty
434 -- & trace "Pure Negative-Look"
435 negLook (Comb Empty) = pure Prod.unit
436 -- & trace "Dead Negative-Look"
437 negLook (Comb (NegLook x)) = look (try x *> pure Prod.unit)
438 -- & trace "Double Negation Law"
439 negLook (Comb (Try x)) = negLook x
440 -- & trace "Zero Consumption Law"
441 negLook (Comb (Look x)) = negLook x
442 -- & trace "Right Identity Law"
443 negLook (Comb (Alt _exn (Comb (Try p)) q)) = negLook p *> negLook q
444 -- FIXME: see if this really holds for all exceptions.
445 -- & trace "Transparency Law"
446 negLook (Comb (p :$>: _)) = negLook p
447 -- & trace "NegLook Idempotence Law"
448 negLook x = SimplComb
449 { combData = NegLook x
451 , combRefs = combRefs x
457 , combRefs = HS.empty
461 , CombAlternable repr
462 , CombApplicable repr
463 , CombSelectable repr
467 ) => CombLookable (KnotComb letName repr)
470 data instance Comb CombMatchable repr a where
473 [(Production '[] (a -> Bool), SimplComb repr b)] ->
475 Comb CombMatchable repr b
476 instance CombMatchable repr => Derivable (Comb CombMatchable repr) where
478 Conditional a bs def ->
479 conditional (derive a)
480 ((\(p, b) -> (p, derive b)) F.<$> bs)
483 ( CombApplicable repr
484 , CombAlternable repr
486 , CombSelectable repr
488 ) => CombMatchable (SimplComb repr) where
489 conditional (Comb Empty) _ def = def
490 -- & trace "Conditional Absorption Law"
491 conditional a bs (Comb Empty)
492 | Foldable.all (\case { (_, Comb Empty) -> True; _ -> False }) bs = a *> empty
493 -- & trace "Conditional Weakening Law"
494 conditional (Comb (Pure a)) bs def =
495 Foldable.foldr (\(p, b) acc ->
496 if runValue (p Prod..@ a) then b else acc
498 -- & trace "Conditional Pure Law"
499 conditional a bs d = SimplComb
500 { combData = Conditional a bs d
502 , combRefs = HS.unions
505 : ((\(_p, b) -> combRefs b) F.<$> bs)
509 , CombAlternable repr
510 , CombApplicable repr
512 , CombSelectable repr
515 ) => CombMatchable (KnotComb letName repr) where
516 conditional a bs d = KnotComb
517 { knotCombOpens = HM.unions
520 : ((\(_p, b) -> knotCombOpens b) F.<$> bs)
521 , knotCombOpen = \final -> TiedComb
522 { combSimpl = conditional
523 (combSimpl (knotCombOpen a final))
524 ((\(p, b) -> (p, combSimpl (knotCombOpen b final))) F.<$> bs)
525 (combSimpl (knotCombOpen d final))
530 data instance Comb (CombSatisfiable tok) repr a where
532 CombSatisfiable tok repr =>
533 Production '[] (tok -> Bool) ->
534 Comb (CombSatisfiable tok) repr tok
536 CombSatisfiable tok repr =>
537 Derivable (Comb (CombSatisfiable tok) repr) where
539 Satisfy p -> satisfy p
541 (CombSatisfiable tok repr, Typeable tok) =>
542 CombSatisfiable tok (SimplComb repr) where
543 satisfy p = SimplComb
544 { combData = Satisfy p
545 , combInline = False -- TODO: True? depending on p?
546 , combRefs = HS.empty
549 ( CombSatisfiable tok repr
553 ) => CombSatisfiable tok (KnotComb letName repr)
556 data instance Comb CombSelectable repr a where
558 SimplComb repr (Either a b) ->
559 SimplComb repr (a -> c) ->
560 SimplComb repr (b -> c) ->
561 Comb CombSelectable repr c
562 instance CombSelectable repr => Derivable (Comb CombSelectable repr) where
564 Branch lr l r -> branch (derive lr) (derive l) (derive r)
566 ( CombApplicable repr
567 , CombAlternable repr
569 , CombSelectable repr
571 ) => CombSelectable (SimplComb repr) where
572 branch (Comb Empty) _ _ = empty
573 -- & trace "Branch Absorption Law"
574 branch b (Comb Empty) (Comb Empty) = b *> empty
575 -- & trace "Branch Weakening Law"
576 branch (Comb (Pure lr)) l r =
578 Left value -> l <*> pure (ProdE (Prod v c))
580 v = Prod.SomeData $ Prod.Var $ Identity value
581 c = Prod.SomeData $ Prod.Var
582 [|| case $$(runCode lr) of Left x -> x ||]
583 Right value -> r <*> pure (ProdE (Prod v c))
585 v = Prod.SomeData $ Prod.Var $ Identity value
586 c = Prod.SomeData $ Prod.Var
587 [|| case $$(runCode lr) of Right x -> x ||]
588 -- & trace "Branch Pure Either Law"
589 branch b (Comb (Pure l)) (Comb (Pure r)) =
590 ProdE (Prod v c) <$> b
591 -- & trace "Branch Generalised Identity Law"
593 v = Prod.SomeData $ Prod.Var $ Identity $ either (runValue l) (runValue r)
594 c = Prod.SomeData $ Prod.Var [|| either $$(runCode l) $$(runCode r) ||]
595 branch (Comb (x :*>: y)) p q = x *> branch y p q
596 -- & trace "Interchange Law"
597 branch b l (Comb Empty) =
598 branch (pure (ProdE (Prod v c)) <*> b) empty l
599 -- & trace "Negated Branch Law"
601 v = Prod.SomeData $ Prod.Var $ Identity $ either Right Left
602 c = Prod.SomeData $ Prod.Var $ [||either Right Left||]
603 branch (Comb (Branch b (Comb Empty) (Comb (Pure lr)))) (Comb Empty) br =
604 branch (pure (ProdE (Prod v c)) <*> b) empty br
605 -- & trace "Branch Fusion Law"
607 v = Prod.SomeData $ Prod.Var $ Identity $ \case
610 case runValue lr r of
613 c = Prod.SomeData $ Prod.Var
614 [|| \case Left{} -> Left ()
615 Right r -> case $$(runCode lr) r of
617 Right rr -> Right rr ||]
618 branch b l r = SimplComb
619 { combData = Branch b l r
621 , combRefs = HS.unions [ combRefs b, combRefs l, combRefs r ]
624 ( CombSelectable repr
625 , CombAlternable repr
626 , CombApplicable repr
631 ) => CombSelectable (KnotComb letName repr)
633 -- CombRegisterableUnscoped
634 data instance Comb CombRegisterableUnscoped repr a where
635 NewUnscoped :: UnscopedRegister a -> SimplComb repr a -> SimplComb repr b -> Comb CombRegisterableUnscoped repr b
636 GetUnscoped :: UnscopedRegister a -> Comb CombRegisterableUnscoped repr a
637 PutUnscoped :: UnscopedRegister a -> SimplComb repr a -> Comb CombRegisterableUnscoped repr ()
638 instance CombRegisterableUnscoped repr => Derivable (Comb CombRegisterableUnscoped repr) where
640 NewUnscoped r ini x -> newUnscoped r (derive ini) (derive x)
641 GetUnscoped r -> getUnscoped r
642 PutUnscoped r x -> putUnscoped r (derive x)
643 instance -- TODO: optimizations
644 ( CombRegisterableUnscoped repr
645 ) => CombRegisterableUnscoped (SimplComb repr) where
646 newUnscoped r ini x = SimplComb
647 { combData = NewUnscoped r ini x
648 , combInline = combInline ini && combInline x
649 , combRefs = combRefs ini <> combRefs x
651 getUnscoped r = SimplComb
652 { combData = GetUnscoped r
654 , combRefs = HS.empty
656 putUnscoped r x = SimplComb
657 { combData = PutUnscoped r x
658 , combInline = combInline x
659 , combRefs = combRefs x
662 ( CombRegisterableUnscoped repr
665 ) => CombRegisterableUnscoped (KnotComb letName repr) where
668 data instance Comb (Letsable letName) repr a where
670 LetBindings letName (SimplComb repr) ->
672 Comb (Letsable letName) repr a
674 Letsable letName repr =>
675 Derivable (Comb (Letsable letName) repr) where
678 ((\(SomeLet sub) -> SomeLet (derive sub)) F.<$> defs)
681 (Letsable letName repr, Typeable letName) =>
682 Letsable letName (SimplComb repr) where
683 lets defs body = SimplComb
684 { combData = Lets defs body
686 , combRefs = HS.unions
688 : ((\(SomeLet sub) -> combRefs sub) F.<$> HM.elems defs)
691 Letsable TH.Name repr =>
692 Letsable TH.Name (KnotComb TH.Name repr) where
693 lets defs body = KnotComb
697 : ((\(SomeLet sub) -> SomeLet . knotCombOpen sub) F.<$> defs)
698 -- Not really necessary to include 'knotCombOpens' of 'defs' here
699 -- since there is only a single 'lets' at the top of the AST,
701 : ((\(SomeLet sub) -> knotCombOpens sub) F.<$> HM.elems defs)
702 , knotCombOpen = \final -> TiedComb
704 let bodySimpl = combSimpl $ knotCombOpen body final in
705 let defsSimpl = (\(SomeLet sub) -> SomeLet $ combSimpl $ knotCombOpen sub final) F.<$> defs in
706 let defsUsed = HS.unions
708 : ((\(SomeLet sub) -> combRefs sub) F.<$> HM.elems defsSimpl) in
709 lets (HM.intersection defsSimpl (HS.toMap defsUsed)) bodySimpl
714 data instance Comb (Referenceable letName) repr a where
715 Ref :: Bool -> letName -> Comb (Referenceable letName) repr a
717 Referenceable letName repr =>
718 Derivable (Comb (Referenceable letName) repr) where
720 Ref isRec name -> ref isRec name
722 Referenceable TH.Name repr =>
723 Referenceable TH.Name (SimplComb repr) where
724 ref isRec name = SimplComb
725 { combData = Ref isRec name
726 , combInline = not isRec
727 , combRefs = HS.singleton name
730 Referenceable TH.Name repr =>
731 Referenceable TH.Name (KnotComb TH.Name repr) where
732 ref isRec name = KnotComb
733 { knotCombOpens = HM.empty
734 , knotCombOpen = \final ->
737 { combSimpl = ref isRec name
739 else case final HM.! name of
741 { combSimpl = p@SimplComb{ combInline = True }
742 } -> a{combSimpl = unsafeSimplComb p}
744 { combSimpl = SimplComb{ combRefs = refs }
746 { combSimpl = (ref isRec name)
747 { combRefs = HS.insert name refs }