{-# LANGUAGE UnicodeSyntax #-} -- | Term to graph transformation where variable names are resolved to graph edges (or constants) module Resolver (resolve) where import Prelude.Unicode import Term import Graph import GraphRewriting.Graph import GraphRewriting.Graph.Write import Control.Monad (liftM, zipWithM) type Compiler = Rewrite NodeWW type Environment = [Name] data Name = Name {symbol ∷ String, reference ∷ Compiler Edge} resolve ∷ Λ → Graph NodeWW resolve term = flip execGraph emptyGraph $ do o ← newEdge i ← newNode Initiator {out = o} compile [] o term compile ∷ Environment → Edge → Λ → Compiler () compile env p term = case term of A func arg → do f ← newEdge x ← newEdge _ ← newNode Applicator {inp = p, func = f, arg = x} compile env f func compile env x arg Λ x e → do b ← newEdge (v, n) ← bindName x _ ← newNode Abstractor {name = x, inp = p, body = b, var = v} compile (n : env) b e V var → case env of [ ] → newNode Primitive {inp = p, name = var} >> return () n:ns → if var ≡ symbol n then mergeEdges p =<< reference n else compile ns p term L binds e → do (es, names) ← liftM unzip $ mapM bindName (map fst binds) let env' = names ⧺ env _ ← zipWithM (compile env') es (Prelude.map snd binds) compile env' p e bindName ∷ String → Compiler (Edge, Name) bindName sym = do v ← newEdge s ← newNode Multiplexer {out = v, ins = []} let ref = do e ← newEdge modifyNode s $ \s → s {ins = e : ins s} return e return (v, Name {symbol = sym, reference = ref})