-- |This module provides a Uniplate instance for the f-lite syntax. It also -- re-exports the Uniplate library. module Optimus.Uniplate( module Data.Generics.Uniplate, extract ) where import Flite.Syntax import Flite.Writer import Data.Generics.Uniplate instance Uniplate Exp where uniplate (Case x as) = (x:ys, \(x:ys) -> Case x (zip ps ys)) where (ps, ys) = unzip as uniplate (Let bs x) = (x:ys, \(x:ys) -> Let (zip vs ys) x) where (vs, ys) = unzip bs uniplate (App x ys) = (x:ys, \(x:ys) -> App x ys) uniplate (Var i) = ([], \[] -> Var i) uniplate (Con i) = ([], \[] -> Con i) uniplate (Fun i) = ([], \[] -> Fun i) uniplate (Int i) = ([], \[] -> Int i) uniplate (Bottom) = ([], \[] -> Bottom) -- |Given a 'Uniplate' traversable tree and a function that extracts information -- from tree nodes, extract all the information in the tree. extract :: Uniplate a => (a -> [b]) -> a -> [b] extract f = fst . runWriter . descendM (\a -> writeMany (f a) >> return a)