module Direct.Rules where import Prelude.Unicode import Direct.Graph import GraphRewriting import GraphRewriting.Pattern.InteractionNet ruleS ∷ (View [Port] n, View SKI n) ⇒ Rule n ruleS = do S {inp = si} ← node Applicator {inp = i1, out1 = o1, out2 = f} ← nodeAt si require (si ≡ o1) Applicator {inp = i2, out1 = o2, out2 = g} ← nodeAt i1 require (i1 ≡ o2) Applicator {inp = i3, out1 = o3, out2 = x} ← nodeAt i2 require (i2 ≡ o3) replace4 $ \l r lr rr → [Node $ Applicator {inp = i3, out1 = l, out2 = r}, Node $ Applicator {inp = l, out1 = f, out2 = lr}, Node $ Applicator {inp = r, out1 = g, out2 = rr}, Node $ Duplicator {inp1 = lr, inp2 = rr, out = x}] ruleK ∷ (View [Port] n, View SKI n) ⇒ Rule n ruleK = do K {inp = si} ← node Applicator {inp = i1, out1 = o1, out2 = x} ← nodeAt si require (si ≡ o1) Applicator {inp = i2, out1 = o2, out2 = y} ← nodeAt i1 require (i1 ≡ o2) replace0 [Wire x i2, Node $ Eraser {inp = y}] ruleI ∷ (View [Port] n, View SKI n) ⇒ Rule n ruleI = do I {} :-: Applicator {inp = iA, out2 = o2} ← activePair rewire [[iA,o2]] combinatorAt ∷ (View [Port] n, View SKI n) ⇒ Edge → Pattern n SKI combinatorAt e = anyOf [s,k,i] where s = do {s@S {} ← nodeAt e; return s} k = do {k@K {} ← nodeAt e; return k} i = do {i@I {} ← nodeAt e; return i} duplicateCombinator ∷ (View [Port] n, View SKI n) ⇒ Rule n duplicateCombinator = do Duplicator {inp1 = i1, inp2 = i2, out = o} ← node c ← combinatorAt o replace0 [Node $ c {inp = i1}, Node $ c {inp = i2}] duplicateApp ∷ (View [Port] n, View SKI n) ⇒ Rule n duplicateApp = do Duplicator {inp1 = i1, inp2 = i2, out = o} ← node Applicator {inp = i, out1 = o1, out2 = o2} ← nodeAt o replace4 $ \l lr rl r → [Node $ Applicator {inp = i1, out1 = l, out2 = lr}, Node $ Applicator {inp = i2, out1 = rl, out2 = r}, Node $ Duplicator {inp1 = l, inp2 = rl, out = o1}, Node $ Duplicator {inp1 = lr, inp2 = r, out = o2}] eraseCombinator ∷ (View [Port] n, View SKI n) ⇒ Rule n eraseCombinator = do Eraser {inp = i} ← node combinatorAt i erase eraseApp ∷ (View [Port] n, View SKI n) ⇒ Rule n eraseApp = do Eraser {inp = i} ← node Applicator {out1 = o1, out2 = o2} ← nodeAt i replace0 [Node $ Eraser {inp = o1}, Node $ Eraser {inp = o2}] eliminate ∷ (View [Port] n, View SKI n) ⇒ Rule n eliminate = do Eraser {inp = iE} ← node Duplicator {out = oD, inp1 = i1, inp2 = i2} ← neighbour =<< previous require (iE ≡ i1 ∨ iE ≡ i2) if iE ≡ i1 then rewire [[oD,i2]] else rewire [[oD,i1]]