{-# LANGUAGE DeriveDataTypeable#-}

module Language.Grammars.ZipperAG.Examples.RepMin where

import Data.Maybe
import Data.Data
import Prelude
import Data.Generics.Zipper
import Language.Grammars.ZipperAG

data Root = Root Tree
       deriving (Eq, Ord, Show, Typeable, Data)

data Tree = Leaf Int
          | Fork Tree Tree
       deriving (Eq, Ord, Show, Typeable, Data)

tree = Root $ Fork (Leaf 1) 
             (Fork (Leaf 4)
                   (Leaf 7))

constructor :: Zipper Root -> String
constructor a = case (getHole a :: Maybe Tree) of
				   Just (Fork _ _) -> "Fork"
				   Just (Leaf _) -> "Leaf"
				   _ -> case (getHole a :: Maybe Root ) of
				   			Just (Root _) -> "Root"

lexeme :: Zipper Root -> Int
lexeme t = let Leaf v = fromJust (getHole t :: Maybe Tree)
			      in v

---- Inherited ----
globmin :: Zipper Root -> Int
globmin t = case constructor t of
							"Root" -> locmin t
							"Leaf" -> globmin $ parent t
							"Fork" -> globmin $ parent t

---- Synthesized ----
locmin :: Zipper Root -> Int
locmin t =  case constructor t of                   
						  "Root" -> locmin $ t.$1
						  "Leaf" -> lexeme t
						  "Fork" -> min (locmin $ t.$1 ) (locmin $ t.$2 )

replace :: Zipper Root -> Tree
replace t = case constructor t of                   
						  "Root" -> replace ( t.$1 )
						  "Leaf" -> Leaf (globmin t)
						  "Fork" -> Fork (replace $ t.$1 ) (replace $ t.$2 )


semantics :: Root -> Tree
semantics t = replace (toZipper t)