ecta-1.0.0.0: src/Application/TermSearch/Utils.hs
{-# LANGUAGE OverloadedStrings #-}
module Application.TermSearch.Utils where
import Data.Map ( Map )
import qualified Data.Map as Map
import Data.Text ( Text )
import qualified Data.Text as Text
import Data.ECTA
import Data.ECTA.Paths
import Data.ECTA.Term
import Application.TermSearch.Type
--------------------------------------------------------------------------------
------------------------------- Type Constructors ------------------------------
--------------------------------------------------------------------------------
typeConst :: Text -> Node
typeConst s = Node [Edge (Symbol s) []]
constrType0 :: Text -> Node
constrType0 s = Node [Edge (Symbol s) []]
constrType1 :: Text -> Node -> Node
constrType1 s n = Node [Edge (Symbol s) [n]]
constrType2 :: Text -> Node -> Node -> Node
constrType2 s n1 n2 = Node [Edge (Symbol s) [n1, n2]]
maybeType :: Node -> Node
maybeType = constrType1 "Maybe"
listType :: Node -> Node
listType = constrType1 "List"
theArrowNode :: Node
theArrowNode = Node [Edge "(->)" []]
arrowType :: Node -> Node -> Node
arrowType n1 n2 = Node [Edge "->" [theArrowNode, n1, n2]]
appType :: Node -> Node -> Node
appType n1 n2 = Node [Edge "TyApp" [n1, n2]]
mkDatatype :: Text -> [Node] -> Node
mkDatatype s ns = Node [Edge (Symbol s) ns]
--------------------
------- Functions and arguments
--------------------
constFunc :: Symbol -> Node -> Edge
constFunc s t = Edge s [t]
constArg :: Symbol -> Node -> Edge
constArg = constFunc
var1, var2, var3, var4, varAcc :: Node
var1 = Node [Edge "var1" []]
var2 = Node [Edge "var2" []]
var3 = Node [Edge "var3" []]
var4 = Node [Edge "var4" []]
varAcc = Node [Edge "acc" []]
--------------------------------------------------------------------------------
--------------------
------- Component Grouping
--------------------
mkGroups :: [(Text, TypeSkeleton)] -> (Map TypeSkeleton Text, Map Text Text)
mkGroups [] = (Map.empty, Map.empty)
mkGroups ((name, typ):comps) = let (groups, nameToRepresentative) = mkGroups comps
freshName = Text.pack ("f" <> show (Map.size groups))
in if typ `Map.member` groups
then (groups, Map.insert name (groups Map.! typ) nameToRepresentative)
else (Map.insert typ freshName groups, Map.insert name freshName nameToRepresentative)
getRepOf :: [(Text, [Text])] -> Text -> Text
getRepOf [] fname = error $ "cannot find " ++ show fname ++ " in any group"
getRepOf ((x, fnames):xs) fname
| fname `elem` fnames = x
| otherwise = getRepOf xs fname
--------------------
------- Different cases of loops
--------------------
replicatorTau :: Node
replicatorTau = createMu
(\n -> union
([var1, var2] ++ map (Node . (: []) . constructorToEdge n) usedConstructors)
)
where
constructorToEdge :: Node -> (Text, Int) -> Edge
constructorToEdge n (nm, arity) = Edge (Symbol nm) (replicate arity n)
usedConstructors = [("Pair", 2)]
replicator :: Node
replicator = Node
[ mkEdge
"Pair"
[ Node
[ mkEdge "Pair"
[replicatorTau, replicatorTau]
(mkEqConstraints [[path [0, 0], path [0, 1], path [1]]])
]
, Node [
Edge "Pair" [replicatorTau, replicatorTau]]
]
(mkEqConstraints [[path [0, 0], path [0, 1], path [1]]])
]
loop1 :: Node
loop1 = Node
[ mkEdge
"f"
[ Node
[ mkEdge
"g"
[ Node
[ Edge
"h"
[ Node
[ Edge "Pair" [replicatorTau, replicatorTau]
, Edge "var2" []
]
, Node [Edge "Pair" [replicatorTau, replicatorTau]]
]
]
]
(mkEqConstraints [[path [0, 0], path [0, 1, 0]]])
, Edge "gg" [Node [Edge "Pair" [var2, var2]]]
]
]
(mkEqConstraints [[path [0, 0, 0], path [0, 0, 1]]])
]
loop2 :: Node
loop2 = Node
[ mkEdge
"g"
[ Node
[ mkEdge "Pair"
[Node [Edge "List" [replicatorTau]], replicatorTau]
(mkEqConstraints [[path [0, 0], path [1]]])
, Edge "f" [var1, Node [Edge "List" [var1]]]
]
, Node
[ mkEdge "Pair"
[Node [Edge "List" [replicatorTau]], replicatorTau]
(mkEqConstraints [[path [0], path [1]]])
, Edge "f" [var1, var1]
]
]
(mkEqConstraints
[[path [0, 1, 0], path [1, 1]], [path [0, 0], path [1, 0]]]
)
]