module Language.Grammars.ZipperAG.Examples.LET.Let_Meaning_HO_NestedST_Circ where
import Data.Generics.Zipper
import Language.Grammars.ZipperAG
import Data.Data
import Language.Grammars.ZipperAG.Examples.LET.Let_DataTypes_Boilerplate
import Language.Grammars.ZipperAG.Examples.LET.Let_Scope
import Language.Grammars.ZipperAG.Examples.LET.Let_Bidi
solve :: Zipper RootA -> Int
solve ag = let ho_st = toZipper (createSTRoot ag)
in pointFree ho_st isSolved calculate solveSTRoot
pointFree :: Zipper a -> (Zipper a -> Bool) -> (Zipper a -> b) -> (Zipper a -> Zipper a) -> b
pointFree ag cond calc incre = if cond ag
then calc ag
else pointFree (incre ag) cond calc incre
solveSTRoot :: Zipper RootHO -> Zipper RootHO
solveSTRoot ag = toZipper $ RootHO (solveST $ ag.$1) (lexeme_RootHO ag)
solveST :: Zipper RootHO -> ListHO
solveST ag = case (constructorHO ag) of
"ConsVarHO" -> if ((not $ isSolved $ ag.$2) && (isSolved $ ag.$3))
then ConsVarHO (lexeme_ConsVarHO_Var ag) (IsSolved $ calculate $ ag.$3) (lexeme_ConsVarHO_A ag) (solveST $ ag.$4)
else ConsVarHO (lexeme_ConsVarHO_Var ag) (lexeme_ConsVarHO_isSolved ag) (lexeme_ConsVarHO_A ag) (solveST $ ag.$4)
"ConsLetHO" -> if ((not $ isSolved $ ag.$2) && (isSolved $ ag.$3))
then ConsLetHO (lexeme_ConsLetHO_Var ag) (IsSolved $ calculate $ ag.$3) (lexeme_ConsLetHO_NestedST ag) (solveST $ ag.$4)
else let nested_ST = ag.$3
new_ST = NestedListHO (solveST $ nested_ST.$1) (lexeme_NestedListHO $ nested_ST)
in ConsLetHO (lexeme_ConsLetHO_Var ag) (lexeme_ConsLetHO_isSolved ag) (new_ST) (solveST $ ag.$4)
"EmptyListHO" -> EmptyListHO
"NestedListHO" -> solveST $ ag.$1
calculate :: Zipper RootHO -> Int
calculate ag = case (constructorHO ag) of
"RootHO" -> calculate $ ag.$2
"NestedListHO" -> calculate $ ag.$2
"Plus" -> (calculate $ ag.$1) + (calculate $ ag.$2)
"Divide" -> (calculate $ ag.$1) `div` (calculate $ ag.$2)
"Minus" -> (calculate $ ag.$1) (calculate $ ag.$2)
"Time" -> (calculate $ ag.$1) * (calculate $ ag.$2)
"Variable" -> getVarValue (lexeme_Variable ag) ag
"Constant" -> lexeme_Constant ag
getVarValue :: String -> Zipper RootHO -> Int
getVarValue name ag = case (constructorHO ag) of
"RootHO" -> auxGetVarValue name ag
"NestedListHO" -> auxGetVarValue name ag
_ -> getVarValue name (parent ag)
auxGetVarValue :: String -> Zipper RootHO -> Int
auxGetVarValue name ag = case (constructorHO ag) of
"RootHO" -> auxGetVarValue name (ag.$1)
"NestedListHO" -> auxGetVarValue name (ag.$1)
"ConsVarHO" -> if (lexeme_ConsVarHO_Var ag == name) then (auxGetVarValue name (ag.$2))
else (auxGetVarValue name (ag.$4))
"ConsLetHO" -> if (lexeme_ConsLetHO_Var ag == name) then (auxGetVarValue name (ag.$2))
else (auxGetVarValue name (ag.$4))
"IsSolved" -> lexeme_IsSolved ag
"EmptyListHO" -> oneUpGetVarValue name ag
oneUpGetVarValue :: String -> Zipper RootHO -> Int
oneUpGetVarValue name ag = case (constructorHO ag) of
"NestedListHO" -> getVarValue name (parent ag)
_ -> oneUpGetVarValue name (parent ag)
isSolved :: Zipper RootHO -> Bool
isSolved ag = case (constructorHO ag) of
"RootHO" -> (isSolved $ ag.$1) || (isSolved $ ag.$2)
"NestedListHO" -> isSolved $ ag.$1
"ConsVarHO" -> (isSolved $ ag.$2) && (isSolved $ ag.$4)
"ConsLetHO" -> (isSolved $ ag.$2) && (isSolved $ ag.$4)
"EmptyListHO" -> True
"IsSolved" -> True
"NotSolved" -> False
"Plus" -> (isSolved $ ag.$1) && (isSolved $ ag.$2)
"Divide" -> (isSolved $ ag.$1) && (isSolved $ ag.$2)
"Minus" -> (isSolved $ ag.$1) && (isSolved $ ag.$2)
"Time" -> (isSolved $ ag.$1) && (isSolved $ ag.$2)
"Variable" -> isVarSolved (lexeme_Variable ag) ag
"Constant" -> True
isVarSolved :: String -> Zipper RootHO -> Bool
isVarSolved name ag = case (constructorHO ag) of
"RootHO" -> auxIsVarSolved name ag
"NestedListHO" -> auxIsVarSolved name ag
_ -> isVarSolved name (parent ag)
auxIsVarSolved :: String -> Zipper RootHO -> Bool
auxIsVarSolved name ag = case (constructorHO ag) of
"RootHO" -> auxIsVarSolved name (ag.$1)
"NestedListHO" -> auxIsVarSolved name (ag.$1)
"ConsVarHO" -> if (lexeme_ConsVarHO_Var ag == name) then (auxIsVarSolved name (ag.$2))
else (auxIsVarSolved name (ag.$4))
"ConsLetHO" -> if (lexeme_ConsLetHO_Var ag == name) then (auxIsVarSolved name (ag.$2))
else (auxIsVarSolved name (ag.$4))
"IsSolved" -> True
"NotSolved" -> False
"EmptyListHO" -> oneUpIsVarSolved name ag
oneUpIsVarSolved :: String -> Zipper RootHO -> Bool
oneUpIsVarSolved name ag = case (constructorHO ag) of
"NestedListHO" -> isVarSolved name (parent ag)
_ -> oneUpIsVarSolved name (parent ag)
createSTRoot :: Zipper RootA -> RootHO
createSTRoot ag = case (constructorHO ag) of
"RootA" -> RootHO (createST ag) (lexeme_InA ((ag.$1).$2))
createST :: Zipper RootA -> ListHO
createST ag = case (constructorHO ag) of
"RootA" -> createST $ ag.$1
"LetA" -> createST $ ag.$1
"ConsAssignA" -> ConsVarHO (lexeme_ConsAssignA_1 ag) (NotSolved) (lexeme_ConsAssignA_2 ag) (createST $ ag.$3)
"ConsLetA" -> ConsLetHO (lexeme_ConsLetA_1 ag) (NotSolved) (NestedListHO (createST $ ag.$2) (lexeme_InA $ (ag.$2).$2)) (createST $ ag.$3)
"EmptyListA" -> EmptyListHO
data RootHO = RootHO ListHO A
deriving (Show, Data, Typeable)
data ListHO = ConsVarHO String IsSolved A ListHO
| ConsLetHO String IsSolved ListHO ListHO
| NestedListHO ListHO A
| EmptyListHO
deriving (Show, Data, Typeable)
data IsSolved = IsSolved Int | NotSolved
deriving (Show, Data, Typeable)
lexeme_IsSolved :: Zipper a -> Int
lexeme_IsSolved ag = case (getHole ag :: Maybe IsSolved) of
Just (IsSolved n) -> n
_ -> error "Error on lexeme_IsSolved!"
lexeme_RootHO :: Zipper a -> A
lexeme_RootHO ag = case (getHole ag :: Maybe RootHO) of
Just(RootHO _ a) -> a
_ -> error "Error on lexeme_RootHO!"
lexeme_ConsVarHO_Var :: Zipper a -> String
lexeme_ConsVarHO_Var ag = case (getHole ag :: Maybe ListHO) of
Just(ConsVarHO v _ _ _) -> v
_ -> error "Error on lexeme_ConsVarHO_Var!"
lexeme_ConsVarHO_isSolved :: Zipper a -> IsSolved
lexeme_ConsVarHO_isSolved ag = case (getHole ag :: Maybe ListHO) of
Just(ConsVarHO _ v _ _) -> v
_ -> error "Error on lexeme_ConsVarHO_isSolved!"
lexeme_ConsVarHO_A :: Zipper a -> A
lexeme_ConsVarHO_A ag = case (getHole ag :: Maybe ListHO) of
Just(ConsVarHO _ _ v _) -> v
_ -> error "Error on lexeme_ConsVarHO_A!"
lexeme_ConsLetHO_Var :: Zipper a -> String
lexeme_ConsLetHO_Var ag = case (getHole ag :: Maybe ListHO) of
Just(ConsLetHO v _ _ _) -> v
_ -> error "Error on lexeme_ConsLetHO_Var!"
lexeme_ConsLetHO_isSolved :: Zipper a -> IsSolved
lexeme_ConsLetHO_isSolved ag = case (getHole ag :: Maybe ListHO) of
Just(ConsLetHO _ v _ _) -> v
_ -> error "Error on lexeme_ConsLetHO_isSolved!"
lexeme_ConsLetHO_NestedST :: Zipper a -> ListHO
lexeme_ConsLetHO_NestedST ag = case (getHole ag :: Maybe ListHO) of
Just(ConsLetHO _ _ v _) -> v
_ -> error "Error on lexeme_ConsLetHO_NestedST!"
lexeme_NestedListHO :: Zipper a -> A
lexeme_NestedListHO ag = case (getHole ag :: Maybe ListHO) of
Just(NestedListHO _ a) -> a
_ -> error "Error on lexeme_NestedListHO!"
constructorHO :: Zipper a -> String
constructorHO ag = case (getHole ag :: Maybe RootHO) of
Just(RootHO _ _) -> "RootHO"
_ -> case (getHole ag :: Maybe ListHO) of
Just(ConsVarHO _ _ _ _) -> "ConsVarHO"
Just(ConsLetHO _ _ _ _) -> "ConsLetHO"
Just(NestedListHO _ _ ) -> "NestedListHO"
Just(EmptyListHO ) -> "EmptyListHO"
_ -> case (getHole ag :: Maybe IsSolved) of
Just(IsSolved _) -> "IsSolved"
Just(NotSolved) -> "NotSolved"
_ -> constructor ag
solve_ho_plus_circularity p = solve $ toZipper (getRootC_RootA $ toZipper p)