2016-02-04 11:19:08 +03:00
|
|
|
{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts, TypeFamilies #-}
|
|
|
|
module Translate(
|
2016-12-16 09:58:19 +03:00
|
|
|
translateStringToSyntaxGraph,
|
|
|
|
translateStringToCollapsedGraphAndDecl,
|
|
|
|
translateModuleToCollapsedGraphs
|
2016-02-04 11:19:08 +03:00
|
|
|
) where
|
|
|
|
|
2016-02-05 08:53:21 +03:00
|
|
|
import Diagrams.Prelude((<>))
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-12-07 08:09:04 +03:00
|
|
|
import Data.Maybe(catMaybes)
|
2016-11-28 04:25:30 +03:00
|
|
|
import Control.Monad(replicateM)
|
2016-02-06 08:07:06 +03:00
|
|
|
import Control.Monad.State(State, evalState)
|
2016-02-27 09:58:49 +03:00
|
|
|
import Data.Either(partitionEithers)
|
2016-12-26 08:45:58 +03:00
|
|
|
import Data.List(unzip5, partition, intercalate)
|
2016-11-28 04:25:30 +03:00
|
|
|
import qualified Language.Haskell.Exts as Exts
|
|
|
|
import Language.Haskell.Exts(Decl(..), parseDecl, Name(..), Pat(..), Rhs(..),
|
|
|
|
Exp(..), QName(..), fromParseResult, Match(..), QOp(..), GuardedRhs(..),
|
2016-12-16 11:47:48 +03:00
|
|
|
Stmt(..), Binds(..), Alt(..), Module(..), SpecialCon(..), prettyPrint)
|
2016-12-01 07:45:50 +03:00
|
|
|
import qualified Data.Graph.Inductive.PatriciaTree as FGR
|
2016-06-18 23:17:09 +03:00
|
|
|
--import Data.Maybe(catMaybes)
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-11-28 04:25:30 +03:00
|
|
|
import GraphAlgorithms(collapseNodes)
|
2016-12-07 08:09:04 +03:00
|
|
|
import TranslateCore(Reference, SyntaxGraph(..), EvalContext, GraphAndRef, Sink,
|
2016-06-18 23:17:09 +03:00
|
|
|
syntaxGraphFromNodes, syntaxGraphFromNodesEdges, getUniqueName, combineExpressions,
|
2016-11-22 00:57:53 +03:00
|
|
|
edgesForRefPortList, makeApplyGraph,
|
2016-03-28 02:49:58 +03:00
|
|
|
namesInPattern, lookupReference, deleteBindings, makeEdges,
|
2016-12-18 04:13:36 +03:00
|
|
|
makeBox, nTupleString, nListString,
|
2016-12-07 04:02:54 +03:00
|
|
|
syntaxGraphToFglGraph, getUniqueString)
|
2016-12-01 07:45:50 +03:00
|
|
|
import Types(NameAndPort(..), IDState,
|
2016-12-09 06:19:47 +03:00
|
|
|
initialIdState, Edge, SyntaxNode(..), IngSyntaxGraph, NodeName, Port(..), SgNamedNode,
|
|
|
|
LikeApplyFlavor(..))
|
2016-12-18 04:13:36 +03:00
|
|
|
import Util(makeSimpleEdge, nameAndPort, justName)
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-02-27 09:58:49 +03:00
|
|
|
-- OVERVIEW --
|
|
|
|
-- The core functions and data types used in this module are in TranslateCore.
|
|
|
|
-- The TranslateCore also contains most/all of the translation functions that
|
|
|
|
-- do not use Language.Haskell.Exts.
|
2016-02-18 10:14:14 +03:00
|
|
|
|
2016-12-12 12:06:21 +03:00
|
|
|
-- HELPER FUNCTIONS --
|
|
|
|
|
|
|
|
makeVarExp :: String -> Exp
|
|
|
|
makeVarExp = Var . UnQual . Ident
|
|
|
|
|
|
|
|
makeQVarOp :: String -> QOp
|
|
|
|
makeQVarOp = QVarOp . UnQual . Ident
|
|
|
|
|
2016-12-26 08:45:58 +03:00
|
|
|
bindsToSyntaxGraph :: [(String, Reference)] -> SyntaxGraph
|
|
|
|
bindsToSyntaxGraph binds = SyntaxGraph mempty mempty mempty binds mempty
|
|
|
|
|
|
|
|
makeAsBindGraph :: Reference -> [Maybe String] -> SyntaxGraph
|
|
|
|
makeAsBindGraph ref asNames = bindsToSyntaxGraph $ catMaybes $ fmap makeBind asNames where
|
|
|
|
makeBind mName = case mName of
|
|
|
|
Nothing -> Nothing
|
|
|
|
Just asName -> Just (asName, ref)
|
|
|
|
|
2016-12-12 12:06:21 +03:00
|
|
|
-- END HELPER FUNCTIONS --
|
|
|
|
|
2016-02-05 08:53:21 +03:00
|
|
|
nameToString :: Language.Haskell.Exts.Name -> String
|
2016-02-04 11:19:08 +03:00
|
|
|
nameToString (Ident s) = s
|
|
|
|
nameToString (Symbol s) = s
|
|
|
|
|
2016-02-25 02:10:06 +03:00
|
|
|
qNameToString :: QName -> String
|
2016-02-27 09:58:49 +03:00
|
|
|
qNameToString (Qual (Exts.ModuleName modName) name) = modName ++ "." ++ nameToString name
|
2016-02-25 02:10:06 +03:00
|
|
|
qNameToString (UnQual name) = nameToString name
|
2016-03-05 11:12:55 +03:00
|
|
|
qNameToString (Special UnitCon) = "()"
|
|
|
|
qNameToString (Special ListCon) = "[]"
|
|
|
|
qNameToString (Special FunCon) = "(->)"
|
|
|
|
qNameToString (Special (TupleCon _ n)) = nTupleString n
|
|
|
|
qNameToString (Special Cons) = "(:)"
|
|
|
|
-- unboxed singleton tuple constructor
|
|
|
|
qNameToString (Special UnboxedSingleCon) = "(# #)"
|
2016-02-25 02:10:06 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalPApp :: QName -> [Pat] -> State IDState (SyntaxGraph, NameAndPort)
|
2016-12-14 00:40:23 +03:00
|
|
|
evalPApp name patterns = case patterns of
|
|
|
|
[] -> makeBox constructorName
|
|
|
|
_ -> do
|
|
|
|
patName <- getUniqueName "pat"
|
|
|
|
evaledPatterns <- mapM evalPattern patterns
|
|
|
|
pure $ makePatternGraph patName constructorName evaledPatterns (length evaledPatterns)
|
|
|
|
where
|
2016-03-22 03:36:02 +03:00
|
|
|
constructorName = qNameToString name
|
2016-02-22 07:26:12 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalPLit :: Exts.Sign -> Exts.Literal -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-23 09:01:03 +03:00
|
|
|
evalPLit Exts.Signless l = evalLit l
|
|
|
|
evalPLit Exts.Negative l = makeBox ('-' : showLiteral l)
|
|
|
|
|
2016-12-26 08:45:58 +03:00
|
|
|
evalPAsPat :: Name -> Pat -> State IDState (GraphAndRef, Maybe String)
|
2016-03-05 00:24:09 +03:00
|
|
|
evalPAsPat n p = do
|
2016-12-26 08:45:58 +03:00
|
|
|
((evaledPatGraph, evaledPatRef), mInnerName) <- evalPattern p
|
2016-03-05 00:24:09 +03:00
|
|
|
let
|
2016-12-26 08:45:58 +03:00
|
|
|
outerName = nameToString n
|
|
|
|
asBindGraph = makeAsBindGraph (Left outerName) [mInnerName]
|
|
|
|
pure ((asBindGraph <> evaledPatGraph, evaledPatRef), Just outerName)
|
|
|
|
|
|
|
|
makePatternResult :: Functor f => f (t, b) -> f ((t, Either a b), Maybe a)
|
|
|
|
makePatternResult = fmap (\(graph, namePort) -> ((graph, Right namePort), Nothing))
|
2016-03-05 00:24:09 +03:00
|
|
|
|
2016-12-26 08:45:58 +03:00
|
|
|
evalPattern :: Pat -> State IDState (GraphAndRef, Maybe String)
|
2016-02-04 11:19:08 +03:00
|
|
|
evalPattern p = case p of
|
2016-12-26 08:45:58 +03:00
|
|
|
PVar n -> pure ((mempty, Left $ nameToString n), Nothing)
|
|
|
|
PLit s l -> makePatternResult $ evalPLit s l
|
2016-03-06 09:26:03 +03:00
|
|
|
PInfixApp p1 qName p2 -> evalPattern (PApp qName [p1, p2])
|
2016-12-26 08:45:58 +03:00
|
|
|
PApp name patterns -> makePatternResult $ evalPApp name patterns
|
2016-02-24 10:14:00 +03:00
|
|
|
-- TODO special tuple handling.
|
2016-03-05 06:00:45 +03:00
|
|
|
PTuple _ patterns ->
|
2016-12-26 08:45:58 +03:00
|
|
|
makePatternResult $ evalPApp (Exts.UnQual . Ident . nTupleString . length $ patterns) patterns
|
2016-03-06 09:26:03 +03:00
|
|
|
PList patterns ->
|
2016-12-26 08:45:58 +03:00
|
|
|
makePatternResult $ evalPApp (Exts.UnQual . Ident . nListString . length $ patterns) patterns
|
2016-02-23 00:26:47 +03:00
|
|
|
PParen pat -> evalPattern pat
|
2016-03-05 00:24:09 +03:00
|
|
|
PAsPat n subPat -> evalPAsPat n subPat
|
2016-12-26 08:45:58 +03:00
|
|
|
PWildCard -> makePatternResult $ makeBox "_"
|
2016-03-05 00:24:09 +03:00
|
|
|
_ -> error $ "evalPattern: No pattern in case for " ++ show p
|
|
|
|
-- TODO: Other cases
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-03-05 05:49:02 +03:00
|
|
|
-- strToGraphRef is not in TranslateCore, since it is only used by evalQName.
|
2016-06-18 23:17:09 +03:00
|
|
|
strToGraphRef :: EvalContext -> String -> State IDState (SyntaxGraph, Reference)
|
2016-03-05 05:49:02 +03:00
|
|
|
strToGraphRef c str = fmap mapper (makeBox str) where
|
|
|
|
mapper gr = if str `elem` c
|
|
|
|
then (mempty, Left str)
|
|
|
|
else fmap Right gr
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalQName :: QName -> EvalContext -> State IDState (SyntaxGraph, Reference)
|
2016-12-14 00:40:23 +03:00
|
|
|
evalQName qName c = case qName of
|
|
|
|
UnQual _ -> graphRef
|
|
|
|
Qual _ _ -> graphRef
|
|
|
|
_ -> fmap Right <$> makeBox qNameString
|
|
|
|
where
|
|
|
|
qNameString = qNameToString qName
|
|
|
|
graphRef = strToGraphRef c qNameString
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
-- evalQOp :: QOp -> EvalContext -> State IDState (SyntaxGraph, Reference)
|
2016-03-28 02:49:58 +03:00
|
|
|
-- evalQOp (QVarOp n) = evalQName n
|
|
|
|
-- evalQOp (QConOp n) = evalQName n
|
2016-02-19 09:07:38 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
-- qOpToString :: QOp -> String
|
|
|
|
-- qOpToString (QVarOp n) = qNameToString n
|
|
|
|
-- qOpToString (QConOp n) = qNameToString n
|
2016-03-22 05:11:19 +03:00
|
|
|
|
2016-12-07 04:02:54 +03:00
|
|
|
--findReferencedIcon :: Reference -> [(NodeName, Icon)] -> Maybe (Name, Icon)
|
|
|
|
-- findReferencedIcon :: Either t NameAndPort -> [(NodeName, t1)] -> Maybe (NodeName, t1)
|
2016-06-18 23:17:09 +03:00
|
|
|
-- findReferencedIcon (Left str) _ = Nothing
|
|
|
|
-- findReferencedIcon (Right (NameAndPort name _)) nameIconMap = (\x -> (name, x)) <$> lookup name nameIconMap
|
2016-04-09 09:54:59 +03:00
|
|
|
|
2016-12-07 08:09:04 +03:00
|
|
|
-- TODO Refactor decideIfNested and makePatternGraph
|
|
|
|
decideIfNested :: ((SyntaxGraph, t1), t) ->
|
|
|
|
(Maybe ((SyntaxGraph, t1), t), Maybe SgNamedNode, [Sink], [(String, Reference)], [(NodeName, NodeName)])
|
|
|
|
decideIfNested ((SyntaxGraph [nameAndIcon] [] sinks bindings eMap, _), _) = (Nothing, Just nameAndIcon, sinks, bindings, eMap)
|
|
|
|
decideIfNested valAndPort = (Just valAndPort, Nothing, [], [], [])
|
|
|
|
|
2016-12-26 08:45:58 +03:00
|
|
|
asNameBind :: (GraphAndRef, Maybe String) -> Maybe (String, Reference)
|
|
|
|
asNameBind ((_, ref), mAsName) = case mAsName of
|
|
|
|
Nothing -> Nothing
|
|
|
|
Just asName -> Just (asName, ref)
|
|
|
|
|
2016-12-07 08:09:04 +03:00
|
|
|
-- TODO Consider removing the Int numArgs parameter.
|
2016-12-26 08:45:58 +03:00
|
|
|
makePatternGraph :: NodeName -> String -> [(GraphAndRef, Maybe String)] -> Int -> (SyntaxGraph, NameAndPort)
|
2016-12-07 08:09:04 +03:00
|
|
|
makePatternGraph applyIconName funStr argVals _ = nestedApplyResult
|
|
|
|
where
|
|
|
|
argumentPorts = map (nameAndPort applyIconName . Port) [2,3..]
|
2016-12-26 08:45:58 +03:00
|
|
|
argValsWithoutAsNames = fmap fst argVals
|
|
|
|
(unnestedArgsAndPort, nestedArgs, nestedSinks, nestedBindings, nestedEMaps) =
|
|
|
|
unzip5 $ fmap decideIfNested (zip argValsWithoutAsNames argumentPorts)
|
|
|
|
|
|
|
|
asNameBinds = catMaybes $ fmap asNameBind argVals
|
2016-12-07 08:09:04 +03:00
|
|
|
|
|
|
|
allSinks = mconcat nestedSinks
|
2016-12-26 08:45:58 +03:00
|
|
|
allBinds = mconcat nestedBindings <> asNameBinds
|
2016-12-07 08:09:04 +03:00
|
|
|
|
|
|
|
originalPortExpPairs = catMaybes unnestedArgsAndPort
|
|
|
|
portExpressionPairs = originalPortExpPairs
|
|
|
|
combinedGraph = combineExpressions True portExpressionPairs
|
|
|
|
icons = [(applyIconName, NestedPatternApplyNode funStr nestedArgs)]
|
|
|
|
newEMap = ((\(n, _) -> (n, applyIconName)) <$> catMaybes nestedArgs) <> mconcat nestedEMaps
|
|
|
|
|
|
|
|
newGraph = SyntaxGraph icons [] allSinks allBinds newEMap
|
|
|
|
nestedApplyResult = (newGraph <> combinedGraph, nameAndPort applyIconName (Port 1))
|
|
|
|
|
|
|
|
makePatternGraph' :: NodeName -> String -> [(SyntaxGraph, Reference)] -> Int -> (SyntaxGraph, NameAndPort)
|
|
|
|
makePatternGraph' applyIconName funStr argVals numArgs = (newGraph <> combinedGraph, nameAndPort applyIconName (Port 1))
|
2016-04-09 09:54:59 +03:00
|
|
|
where
|
2016-12-07 04:02:54 +03:00
|
|
|
argumentPorts = map (nameAndPort applyIconName . Port) [2,3..]
|
2016-06-18 23:17:09 +03:00
|
|
|
combinedGraph = combineExpressions True $ zip argVals argumentPorts
|
|
|
|
icons = [(applyIconName, PatternApplyNode funStr numArgs)]
|
|
|
|
newGraph = syntaxGraphFromNodes icons
|
|
|
|
|
2016-12-12 09:19:23 +03:00
|
|
|
removeCompose :: Exp -> Exp -> Exp
|
|
|
|
removeCompose f x = case removeParen f of
|
|
|
|
(InfixApp f1 (QVarOp (UnQual (Symbol "."))) f2) -> App f1 $ removeCompose f2 x
|
|
|
|
_ -> App f x
|
|
|
|
|
|
|
|
-- TODO Refactor this and all sub-expressions
|
|
|
|
evaluateAppExpression :: EvalContext -> Exp -> Exp -> State IDState (SyntaxGraph, NameAndPort)
|
|
|
|
evaluateAppExpression c f e = if appScore <= compScore
|
|
|
|
then evalApp c ApplyNodeFlavor (simplifyApp noComposeExp)
|
|
|
|
else evalApp c ComposeNodeFlavor (simplifyComposeApply noComposeExp)
|
2016-12-09 06:19:47 +03:00
|
|
|
where
|
2016-12-12 09:19:23 +03:00
|
|
|
noComposeExp = removeCompose f e
|
|
|
|
(appScore, compScore) = applyComposeScore noComposeExp
|
2016-12-09 06:19:47 +03:00
|
|
|
|
|
|
|
evalApp :: EvalContext -> LikeApplyFlavor -> (Exp, [Exp]) -> State IDState (SyntaxGraph, NameAndPort)
|
|
|
|
evalApp c flavor (funExp, argExps) = do
|
2016-02-10 05:58:28 +03:00
|
|
|
funVal <- evalExp c funExp
|
|
|
|
argVals <- mapM (evalExp c) argExps
|
2016-12-07 04:02:54 +03:00
|
|
|
applyIconName <- getUniqueName "app0"
|
2016-12-09 06:19:47 +03:00
|
|
|
pure $ makeApplyGraph flavor False applyIconName funVal argVals (length argExps)
|
2016-02-19 09:07:38 +03:00
|
|
|
|
2016-03-05 08:35:23 +03:00
|
|
|
qOpToExp :: QOp -> Exp
|
|
|
|
qOpToExp (QVarOp n) = Var n
|
|
|
|
qOpToExp (QConOp n) = Con n
|
|
|
|
|
2016-12-12 09:19:23 +03:00
|
|
|
evalCompose :: EvalContext -> [Exp] -> State IDState (SyntaxGraph, NameAndPort)
|
|
|
|
evalCompose c functions = do
|
|
|
|
let reversedFunctios = reverse functions
|
|
|
|
evaluatedFunctions <- mapM (evalExp c) reversedFunctios
|
|
|
|
neverUsedPort <- Left <$> getUniqueString "unusedArgument"
|
|
|
|
applyIconName <- getUniqueName "compose"
|
|
|
|
pure $ makeApplyGraph ComposeNodeFlavor False applyIconName
|
|
|
|
(mempty, neverUsedPort) evaluatedFunctions (length evaluatedFunctions)
|
|
|
|
|
2016-12-12 12:06:21 +03:00
|
|
|
simplifyCompose :: Exp -> [Exp]
|
2016-12-12 09:19:23 +03:00
|
|
|
simplifyCompose e = case removeParen e of
|
|
|
|
(InfixApp exp1 (QVarOp (UnQual (Symbol "."))) exp2) -> exp1 : simplifyCompose exp2
|
|
|
|
x -> [x]
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalInfixApp :: EvalContext -> Exp -> QOp -> Exp -> State IDState (SyntaxGraph, Reference)
|
2016-12-14 00:40:23 +03:00
|
|
|
evalInfixApp c e1 op e2 = case op of
|
|
|
|
QVarOp (UnQual (Symbol sym)) -> case sym of
|
|
|
|
"$" -> evalExp c (App e1 e2)
|
|
|
|
"." -> fmap Right <$> evalCompose c (e1 : simplifyCompose e2)
|
|
|
|
_ -> defaultCase
|
|
|
|
_ -> defaultCase
|
|
|
|
where
|
|
|
|
defaultCase = evalExp c $ App (App (qOpToExp op) e1) e2
|
2016-12-09 06:19:47 +03:00
|
|
|
|
|
|
|
scoreExpressions :: Exp -> Exp -> (Int, Int)
|
|
|
|
scoreExpressions exp1 exp2 = (appScore, compScore) where
|
|
|
|
(e1App, e1Comp) = applyComposeScore exp1
|
|
|
|
(e2App, e2Comp) = applyComposeScore exp2
|
|
|
|
|
|
|
|
leftApp = min e1App (1 + e1Comp)
|
|
|
|
rightApp = 1 + min e2App e2Comp
|
|
|
|
|
|
|
|
appScore = max leftApp rightApp
|
|
|
|
|
|
|
|
leftComp = 1 + min e1App e1Comp
|
|
|
|
rightComp = min (1 + e2App) e2Comp
|
|
|
|
|
|
|
|
compScore = max leftComp rightComp
|
|
|
|
|
2016-12-12 09:19:23 +03:00
|
|
|
removeParen :: Exp -> Exp
|
|
|
|
removeParen e = case e of
|
|
|
|
Paren x -> removeParen x
|
|
|
|
x -> x
|
|
|
|
|
2016-12-09 06:19:47 +03:00
|
|
|
simplifyExp :: Exp -> Exp
|
2016-12-12 09:19:23 +03:00
|
|
|
simplifyExp e = case removeParen e of
|
2016-12-09 06:19:47 +03:00
|
|
|
InfixApp exp1 (QVarOp (UnQual (Symbol "$"))) exp2 -> App exp1 exp2
|
2016-12-12 09:19:23 +03:00
|
|
|
-- Don't convert compose to apply
|
|
|
|
InfixApp _ (QVarOp (UnQual (Symbol "."))) _ -> e
|
2016-12-19 08:15:59 +03:00
|
|
|
App (Var (UnQual (Symbol "<$>"))) arg -> App (makeVarExp "fmap") arg
|
2016-12-09 06:19:47 +03:00
|
|
|
InfixApp exp1 op exp2 -> App (App (qOpToExp op) exp1) exp2
|
2016-12-14 10:21:34 +03:00
|
|
|
LeftSection exp1 op -> App (qOpToExp op) exp1
|
2016-12-09 06:19:47 +03:00
|
|
|
x -> x
|
|
|
|
|
|
|
|
-- TODO Consider putting this logic in a separate "simplifyExpression" function.
|
|
|
|
-- | Returns the amount of nesting if the App is converted to (applyNode, composeNode)
|
|
|
|
applyComposeScore :: Exp -> (Int, Int)
|
2016-12-13 12:53:04 +03:00
|
|
|
applyComposeScore e = case simplifyExp e of
|
|
|
|
App exp1 exp2 -> scoreExpressions exp1 exp2
|
2016-12-12 09:19:23 +03:00
|
|
|
_ -> (0, 0)
|
2016-12-09 06:19:47 +03:00
|
|
|
|
|
|
|
-- Todo add test for this function
|
2016-02-10 05:58:28 +03:00
|
|
|
simplifyApp :: Exp -> (Exp, [Exp])
|
2016-12-13 12:53:04 +03:00
|
|
|
simplifyApp e = case simplifyExp e of
|
|
|
|
App exp1 exp2 -> (funExp, args <> [exp2])
|
|
|
|
where
|
|
|
|
(funExp, args) = simplifyApp exp1
|
|
|
|
x -> (x, [])
|
2016-02-06 08:07:06 +03:00
|
|
|
|
2016-12-12 09:19:23 +03:00
|
|
|
simplifyComposeApply :: Exp -> (Exp, [Exp])
|
|
|
|
simplifyComposeApply e = case simplifyExp e of
|
2016-12-13 12:53:04 +03:00
|
|
|
App exp1 exp2 -> (argExp, funcs <> [exp1])
|
2016-12-09 06:19:47 +03:00
|
|
|
where
|
2016-12-12 09:19:23 +03:00
|
|
|
(argExp, funcs) = simplifyComposeApply exp2
|
2016-12-09 06:19:47 +03:00
|
|
|
simpleExp -> (simpleExp, [])
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalIf :: EvalContext -> Exp -> Exp -> Exp -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-18 10:14:14 +03:00
|
|
|
evalIf c e1 e2 e3 = do
|
|
|
|
e1Val <- evalExp c e1
|
|
|
|
e2Val <- evalExp c e2
|
|
|
|
e3Val <- evalExp c e3
|
2016-12-07 04:02:54 +03:00
|
|
|
guardName <- getUniqueName "if"
|
2016-02-18 10:14:14 +03:00
|
|
|
let
|
2016-06-18 23:17:09 +03:00
|
|
|
icons = [(guardName, GuardNode 2)]
|
2016-02-18 10:14:14 +03:00
|
|
|
combinedGraph =
|
2016-12-07 04:02:54 +03:00
|
|
|
combineExpressions False $ zip [e1Val, e2Val, e3Val] (map (nameAndPort guardName . Port) [3, 2, 4])
|
2016-06-18 23:17:09 +03:00
|
|
|
newGraph = syntaxGraphFromNodes icons <> combinedGraph
|
2016-12-20 07:27:31 +03:00
|
|
|
pure (newGraph, nameAndPort guardName (Port 1))
|
2016-02-18 02:36:57 +03:00
|
|
|
|
2016-02-21 06:22:09 +03:00
|
|
|
evalStmt :: EvalContext -> Stmt -> State IDState GraphAndRef
|
2016-02-19 09:51:16 +03:00
|
|
|
evalStmt c (Qualifier e) = evalExp c e
|
|
|
|
|
2016-02-21 06:22:09 +03:00
|
|
|
evalStmts :: EvalContext -> [Stmt] -> State IDState GraphAndRef
|
2016-02-19 09:51:16 +03:00
|
|
|
evalStmts c [stmt] = evalStmt c stmt
|
|
|
|
|
2016-02-21 06:22:09 +03:00
|
|
|
evalGuaredRhs :: EvalContext -> GuardedRhs -> State IDState (GraphAndRef, GraphAndRef)
|
2016-02-19 09:51:16 +03:00
|
|
|
evalGuaredRhs c (GuardedRhs _ stmts e) = do
|
|
|
|
expVal <- evalExp c e
|
|
|
|
stmtsVal <- evalStmts c stmts
|
|
|
|
pure (stmtsVal, expVal)
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalGuardedRhss :: EvalContext -> [GuardedRhs] -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-19 09:51:16 +03:00
|
|
|
evalGuardedRhss c rhss = do
|
2016-12-07 04:02:54 +03:00
|
|
|
guardName <- getUniqueName "guard"
|
2016-02-19 09:51:16 +03:00
|
|
|
evaledRhss <- mapM (evalGuaredRhs c) rhss
|
|
|
|
let
|
|
|
|
(bools, exps) = unzip evaledRhss
|
2016-12-07 04:02:54 +03:00
|
|
|
expsWithPorts = zip exps $ map (nameAndPort guardName . Port) [2,4..]
|
|
|
|
boolsWithPorts = zip bools $ map (nameAndPort guardName . Port) [3,5..]
|
2016-02-23 00:26:47 +03:00
|
|
|
combindedGraph = combineExpressions False $ expsWithPorts <> boolsWithPorts
|
2016-06-18 23:17:09 +03:00
|
|
|
icons = [(guardName, GuardNode (length rhss))]
|
|
|
|
newGraph = syntaxGraphFromNodes icons <> combindedGraph
|
2016-12-07 04:02:54 +03:00
|
|
|
pure (newGraph, nameAndPort guardName (Port 1))
|
2016-02-19 09:51:16 +03:00
|
|
|
|
2016-02-27 09:58:49 +03:00
|
|
|
-- This is in Translate and not Translate core since currently it is only used by evalLit.
|
2016-06-18 23:17:09 +03:00
|
|
|
makeLiteral :: (Show x) => x -> State IDState (SyntaxGraph, NameAndPort)
|
2016-12-24 13:02:59 +03:00
|
|
|
makeLiteral = makeBox . show
|
2016-02-23 09:01:03 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalLit :: Exts.Literal -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-20 00:46:14 +03:00
|
|
|
evalLit (Exts.Int x) = makeLiteral x
|
|
|
|
evalLit (Exts.Char x) = makeLiteral x
|
|
|
|
evalLit (Exts.String x) = makeLiteral x
|
|
|
|
-- TODO: Print the Rational as a floating point.
|
|
|
|
evalLit (Exts.Frac x) = makeLiteral x
|
|
|
|
-- TODO: Test the unboxed literals
|
|
|
|
evalLit (Exts.PrimInt x) = makeLiteral x
|
|
|
|
evalLit (Exts.PrimWord x) = makeLiteral x
|
|
|
|
evalLit (Exts.PrimFloat x) = makeLiteral x
|
|
|
|
evalLit (Exts.PrimDouble x) = makeLiteral x
|
|
|
|
evalLit (Exts.PrimChar x) = makeLiteral x
|
|
|
|
evalLit (Exts.PrimString x) = makeLiteral x
|
|
|
|
|
2016-02-23 09:01:03 +03:00
|
|
|
showLiteral :: Exts.Literal -> String
|
|
|
|
showLiteral (Exts.Int x) = show x
|
|
|
|
showLiteral (Exts.Char x) = show x
|
|
|
|
showLiteral (Exts.String x) = show x
|
|
|
|
-- TODO: Print the Rational as a floating point.
|
|
|
|
showLiteral (Exts.Frac x) = show x
|
|
|
|
-- TODO: Test the unboxed literals
|
|
|
|
showLiteral (Exts.PrimInt x) = show x
|
|
|
|
showLiteral (Exts.PrimWord x) = show x
|
|
|
|
showLiteral (Exts.PrimFloat x) = show x
|
|
|
|
showLiteral (Exts.PrimDouble x) = show x
|
|
|
|
showLiteral (Exts.PrimChar x) = show x
|
|
|
|
showLiteral (Exts.PrimString x) = show x
|
|
|
|
|
2016-02-22 07:26:12 +03:00
|
|
|
getBoundVarName :: Decl -> [String]
|
2016-02-23 00:26:47 +03:00
|
|
|
-- TODO Should evalState be used here?
|
|
|
|
getBoundVarName (PatBind _ pat _ _) = namesInPattern $ evalState (evalPattern pat) initialIdState
|
2016-02-25 01:46:49 +03:00
|
|
|
getBoundVarName (FunBind (Match _ name _ _ _ _:_)) = [nameToString name]
|
2016-03-05 05:49:02 +03:00
|
|
|
-- TODO: Other cases
|
2016-03-06 09:26:03 +03:00
|
|
|
getBoundVarName (TypeSig _ _ _) = []
|
2016-03-05 05:49:02 +03:00
|
|
|
getBoundVarName decl = error $ "getBoundVarName: No pattern in case for " ++ show decl
|
2016-02-21 05:47:56 +03:00
|
|
|
|
2016-02-22 02:15:16 +03:00
|
|
|
--TODO: Should this call makeEdges?
|
2016-06-18 23:17:09 +03:00
|
|
|
evalBinds :: EvalContext -> Binds -> State IDState (SyntaxGraph, EvalContext)
|
2016-02-21 05:47:56 +03:00
|
|
|
evalBinds c (BDecls decls) = do
|
|
|
|
let
|
2016-02-22 07:26:12 +03:00
|
|
|
boundNames = concatMap getBoundVarName decls
|
2016-02-21 05:47:56 +03:00
|
|
|
augmentedContext = boundNames <> c
|
2016-02-21 09:35:13 +03:00
|
|
|
evaledDecl <- mconcat <$> mapM (evalDecl augmentedContext) decls
|
|
|
|
pure (evaledDecl, augmentedContext)
|
2016-02-21 05:47:56 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalGeneralLet :: (EvalContext -> State IDState (SyntaxGraph, Reference)) -> EvalContext -> Binds -> State IDState (SyntaxGraph, Reference)
|
2016-02-22 06:34:33 +03:00
|
|
|
evalGeneralLet expOrRhsEvaler c bs = do
|
2016-02-21 09:35:13 +03:00
|
|
|
(bindGraph, bindContext) <- evalBinds c bs
|
2016-02-22 06:34:33 +03:00
|
|
|
expVal <- expOrRhsEvaler bindContext
|
2016-02-21 05:47:56 +03:00
|
|
|
let
|
2016-02-21 09:35:13 +03:00
|
|
|
(expGraph, expResult) = expVal
|
2016-02-22 02:15:16 +03:00
|
|
|
newGraph = deleteBindings . makeEdges $ expGraph <> bindGraph
|
2016-12-07 05:39:38 +03:00
|
|
|
bindings = sgSources bindGraph
|
2016-02-23 09:01:03 +03:00
|
|
|
pure (newGraph, lookupReference bindings expResult)
|
2016-02-20 00:46:14 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalLet :: EvalContext -> Binds -> Exp -> State IDState (SyntaxGraph, Reference)
|
2016-02-22 06:34:33 +03:00
|
|
|
evalLet context binds e = evalGeneralLet (`evalExp` e) context binds
|
|
|
|
|
2016-02-24 07:47:08 +03:00
|
|
|
-- TODO: Refactor this with evalPatBind
|
2016-12-26 08:45:58 +03:00
|
|
|
evalPatAndRhs :: EvalContext -> Pat -> Rhs -> Maybe Binds -> State IDState (Bool, SyntaxGraph, Reference, Reference, Maybe String)
|
2016-02-24 07:47:08 +03:00
|
|
|
evalPatAndRhs c pat rhs maybeWhereBinds = do
|
|
|
|
patternNames <- namesInPattern <$> evalPattern pat
|
|
|
|
let rhsContext = patternNames <> c
|
2016-12-18 02:25:10 +03:00
|
|
|
(rhsGraph, rhsRef) <- rhsWithBinds maybeWhereBinds rhs rhsContext
|
2016-12-26 08:45:58 +03:00
|
|
|
((patGraph, patRef), mPatAsName) <- evalPattern pat
|
2016-02-24 07:47:08 +03:00
|
|
|
let
|
|
|
|
grWithEdges = makeEdges (rhsGraph <> patGraph)
|
2016-12-18 02:25:10 +03:00
|
|
|
lookedUpRhsRef = lookupReference (sgSources grWithEdges) rhsRef
|
|
|
|
-- The pattern and rhs are conneted if makeEdges added extra edges, or if the rhsRef refers to a source
|
|
|
|
-- in the pattern
|
|
|
|
patRhsAreConnected = (rhsRef /= lookedUpRhsRef) ||
|
2016-06-18 23:17:09 +03:00
|
|
|
length (sgEdges grWithEdges) > (length (sgEdges rhsGraph) + length (sgEdges patGraph))
|
2016-12-26 08:45:58 +03:00
|
|
|
pure (patRhsAreConnected, deleteBindings grWithEdges, patRef, lookedUpRhsRef, mPatAsName)
|
2016-02-24 07:47:08 +03:00
|
|
|
|
|
|
|
-- returns (combined graph, pattern reference, rhs reference)
|
2016-12-26 08:45:58 +03:00
|
|
|
evalAlt :: EvalContext -> Exts.Alt -> State IDState (Bool, SyntaxGraph, Reference, Reference, Maybe String)
|
2016-02-27 09:58:49 +03:00
|
|
|
evalAlt c (Exts.Alt _ pat rhs maybeBinds) = evalPatAndRhs c pat rhs maybeBinds
|
2016-02-24 07:47:08 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalCase :: EvalContext -> Exp -> [Alt] -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-24 07:47:08 +03:00
|
|
|
evalCase c e alts = do
|
|
|
|
evaledAlts <- mapM (evalAlt c) alts
|
|
|
|
(expGraph, expRef) <- evalExp c e
|
|
|
|
caseIconName <- getUniqueName "case"
|
|
|
|
let
|
2016-12-26 08:45:58 +03:00
|
|
|
(patRhsConnected, altGraphs, patRefs, rhsRefs, asNames) = unzip5 evaledAlts
|
2016-02-24 07:47:08 +03:00
|
|
|
combindedAltGraph = mconcat altGraphs
|
|
|
|
numAlts = length alts
|
2016-12-07 04:02:54 +03:00
|
|
|
icons = [(caseIconName, CaseNode numAlts)]
|
2016-06-18 23:17:09 +03:00
|
|
|
caseGraph = syntaxGraphFromNodes icons
|
2016-12-07 04:02:54 +03:00
|
|
|
expEdge = (expRef, nameAndPort caseIconName (Port 0))
|
|
|
|
patEdges = zip patRefs $ map (nameAndPort caseIconName . Port) [2,4..]
|
|
|
|
rhsEdges = zip patRhsConnected $ zip rhsRefs $ map (nameAndPort caseIconName . Port) [3,5..]
|
2016-02-24 07:47:08 +03:00
|
|
|
(connectedRhss, unConnectedRhss) = partition fst rhsEdges
|
|
|
|
resultIconNames <- replicateM numAlts (getUniqueName "caseResult")
|
|
|
|
let
|
2016-12-18 02:25:10 +03:00
|
|
|
makeCaseResult :: NodeName -> Reference -> SyntaxGraph
|
|
|
|
makeCaseResult resultIconName rhsRef = case rhsRef of
|
|
|
|
Left _ -> mempty
|
|
|
|
Right rhsPort -> syntaxGraphFromNodesEdges rhsNewIcons rhsNewEdges
|
|
|
|
where
|
|
|
|
rhsNewIcons = [(resultIconName, CaseResultNode)]
|
|
|
|
rhsNewEdges = [makeSimpleEdge (rhsPort, justName resultIconName)]
|
2016-02-24 07:47:08 +03:00
|
|
|
caseResultGraphs = mconcat $ zipWith makeCaseResult resultIconNames (fmap (fst . snd) connectedRhss)
|
2016-12-18 02:25:10 +03:00
|
|
|
filteredRhsEdges = fmap snd unConnectedRhss
|
2016-02-26 05:37:04 +03:00
|
|
|
patternEdgesGraph = edgesForRefPortList True patEdges
|
|
|
|
caseEdgeGraph = edgesForRefPortList False (expEdge : filteredRhsEdges)
|
2016-12-26 08:45:58 +03:00
|
|
|
|
|
|
|
bindGraph = makeAsBindGraph expRef asNames
|
|
|
|
|
|
|
|
finalGraph = deleteBindings $ makeEdges $ mconcat [bindGraph, patternEdgesGraph, caseResultGraphs, expGraph, caseEdgeGraph, caseGraph, combindedAltGraph]
|
2016-12-07 04:02:54 +03:00
|
|
|
pure (finalGraph, nameAndPort caseIconName (Port 1))
|
2016-02-24 07:47:08 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalTuple :: EvalContext -> [Exp] -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-24 10:14:00 +03:00
|
|
|
evalTuple c exps = do
|
|
|
|
argVals <- mapM (evalExp c) exps
|
2016-06-18 23:17:09 +03:00
|
|
|
funVal <- makeBox $ nTupleString (length exps)
|
2016-12-07 04:02:54 +03:00
|
|
|
applyIconName <- getUniqueName "tupleApp"
|
2016-12-09 06:19:47 +03:00
|
|
|
pure $ makeApplyGraph ApplyNodeFlavor False applyIconName (fmap Right funVal) argVals (length exps)
|
2016-02-24 10:14:00 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalListExp :: EvalContext -> [Exp] -> State IDState (SyntaxGraph, NameAndPort)
|
2016-03-28 02:49:58 +03:00
|
|
|
evalListExp _ [] = makeBox "[]"
|
2016-12-09 06:19:47 +03:00
|
|
|
evalListExp c exps = evalApp c ApplyNodeFlavor (makeVarExp . nListString . length $ exps, exps)
|
2016-03-05 10:49:48 +03:00
|
|
|
|
2016-12-13 12:53:04 +03:00
|
|
|
evalLeftSection :: EvalContext -> Exp -> QOp -> State IDState (SyntaxGraph, Reference)
|
|
|
|
evalLeftSection c e op = evalExp c $ App (qOpToExp op) e
|
2016-03-05 08:35:23 +03:00
|
|
|
|
2016-12-09 06:19:47 +03:00
|
|
|
evalRightSection :: EvalContext -> QOp -> Exp -> State IDState (SyntaxGraph, NameAndPort)
|
2016-03-05 08:35:23 +03:00
|
|
|
evalRightSection c op e = do
|
|
|
|
expVal <- evalExp c e
|
2016-06-18 23:17:09 +03:00
|
|
|
funVal <- evalExp c (qOpToExp op)
|
2016-12-07 04:02:54 +03:00
|
|
|
applyIconName <- getUniqueName "tupleApp"
|
2016-03-05 08:35:23 +03:00
|
|
|
-- TODO: A better option would be for makeApplyGraph to take the list of expressions as Maybes.
|
2016-12-07 04:02:54 +03:00
|
|
|
neverUsedPort <- Left <$> getUniqueString "unusedArgument"
|
2016-12-09 06:19:47 +03:00
|
|
|
pure $ makeApplyGraph ApplyNodeFlavor False applyIconName funVal [(mempty, neverUsedPort), expVal] 2
|
2016-03-05 08:35:23 +03:00
|
|
|
|
2016-03-05 05:49:02 +03:00
|
|
|
-- evalEnums is only used by evalExp
|
2016-06-18 23:17:09 +03:00
|
|
|
evalEnums :: EvalContext -> String -> [Exp] -> State IDState (SyntaxGraph, Reference)
|
2016-12-12 12:06:21 +03:00
|
|
|
evalEnums c s exps = fmap Right <$> evalApp c ApplyNodeFlavor (makeVarExp s, exps)
|
2016-03-06 05:01:35 +03:00
|
|
|
|
|
|
|
desugarDo :: [Stmt] -> Exp
|
|
|
|
desugarDo [Qualifier e] = e
|
|
|
|
desugarDo (Qualifier e : stmts) = InfixApp e thenOp (desugarDo stmts)
|
|
|
|
where thenOp = makeQVarOp ">>"
|
|
|
|
desugarDo (Generator srcLoc pat e : stmts) =
|
|
|
|
InfixApp e (makeQVarOp ">>=") (Lambda srcLoc [pat] (desugarDo stmts))
|
|
|
|
desugarDo (LetStmt binds : stmts) = Let binds (desugarDo stmts)
|
|
|
|
|
2016-03-06 09:26:03 +03:00
|
|
|
-- TODO: Finish evalRecConstr
|
2016-06-18 23:17:09 +03:00
|
|
|
evalRecConstr :: EvalContext -> QName -> [Exts.FieldUpdate] -> State IDState (SyntaxGraph, Reference)
|
2016-03-28 02:49:58 +03:00
|
|
|
evalRecConstr c qName _ = evalQName qName c
|
2016-03-06 09:26:03 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalExp :: EvalContext -> Exp -> State IDState (SyntaxGraph, Reference)
|
2016-02-10 05:58:28 +03:00
|
|
|
evalExp c x = case x of
|
2016-02-27 02:58:50 +03:00
|
|
|
Var n -> evalQName n c
|
|
|
|
Con n -> evalQName n c
|
2016-02-21 06:22:09 +03:00
|
|
|
Lit l -> fmap Right <$> evalLit l
|
2016-04-10 04:59:40 +03:00
|
|
|
InfixApp e1 op e2 -> evalInfixApp c e1 op e2
|
2016-12-12 12:06:21 +03:00
|
|
|
App f arg -> fmap Right <$> evaluateAppExpression c f arg
|
2016-03-06 09:26:03 +03:00
|
|
|
NegApp e -> evalExp c (App (makeVarExp "negate") e)
|
2016-02-21 06:22:09 +03:00
|
|
|
Lambda _ patterns e -> fmap Right <$> evalLambda c patterns e
|
2016-02-21 09:35:13 +03:00
|
|
|
Let bs e -> evalLet c bs e
|
2016-02-21 06:22:09 +03:00
|
|
|
If e1 e2 e3 -> fmap Right <$> evalIf c e1 e2 e3
|
2016-02-24 07:47:08 +03:00
|
|
|
Case e alts -> fmap Right <$> evalCase c e alts
|
2016-03-06 05:01:35 +03:00
|
|
|
Do stmts -> evalExp c (desugarDo stmts)
|
2016-02-24 10:14:00 +03:00
|
|
|
-- TODO special tuple symbol
|
|
|
|
Tuple _ exps -> fmap Right <$> evalTuple c exps
|
2016-03-05 10:49:48 +03:00
|
|
|
List exps -> fmap Right <$> evalListExp c exps
|
2016-02-21 05:47:56 +03:00
|
|
|
Paren e -> evalExp c e
|
2016-12-13 12:53:04 +03:00
|
|
|
LeftSection e op -> evalLeftSection c e op
|
2016-03-05 08:35:23 +03:00
|
|
|
RightSection op e -> fmap Right <$> evalRightSection c op e
|
2016-03-06 09:26:03 +03:00
|
|
|
RecConstr n updates -> evalRecConstr c n updates
|
|
|
|
-- TODO: Do RecUpdate correcly
|
2016-03-28 02:49:58 +03:00
|
|
|
RecUpdate e _ -> evalExp c e
|
2016-03-05 05:49:02 +03:00
|
|
|
EnumFrom e -> evalEnums c "enumFrom" [e]
|
|
|
|
EnumFromTo e1 e2 -> evalEnums c "enumFromTo" [e1, e2]
|
|
|
|
EnumFromThen e1 e2 -> evalEnums c "enumFromThen" [e1, e2]
|
|
|
|
EnumFromThenTo e1 e2 e3 -> evalEnums c "enumFromThenTo" [e1, e2, e3]
|
2016-03-06 09:26:03 +03:00
|
|
|
-- TODO: Add the type signiture to ExpTypeSig.
|
|
|
|
ExpTypeSig _ e _ -> evalExp c e
|
2016-03-05 05:49:02 +03:00
|
|
|
-- TODO: Add other cases
|
|
|
|
_ -> error $ "evalExp: No pattern in case for " ++ show x
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-02-08 05:01:57 +03:00
|
|
|
-- | First argument is the right hand side.
|
|
|
|
-- The second arugement is a list of strings that are bound in the environment.
|
2016-06-18 23:17:09 +03:00
|
|
|
evalRhs :: EvalContext -> Rhs -> State IDState (SyntaxGraph, Reference)
|
2016-02-23 09:01:03 +03:00
|
|
|
evalRhs c (UnGuardedRhs e) = evalExp c e
|
|
|
|
evalRhs c (GuardedRhss rhss) = fmap Right <$> evalGuardedRhss c rhss
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
rhsWithBinds :: Maybe Binds -> Rhs -> EvalContext -> State IDState (SyntaxGraph, Reference)
|
2016-02-23 09:01:03 +03:00
|
|
|
rhsWithBinds maybeWhereBinds rhs rhsContext = case maybeWhereBinds of
|
|
|
|
Nothing -> evalRhs rhsContext rhs
|
|
|
|
Just b -> evalGeneralLet (`evalRhs` rhs) rhsContext b
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalPatBind :: EvalContext -> Decl -> State IDState SyntaxGraph
|
2016-02-23 00:26:47 +03:00
|
|
|
evalPatBind c (PatBind _ pat rhs maybeWhereBinds) = do
|
2016-02-23 09:01:03 +03:00
|
|
|
patternNames <- namesInPattern <$> evalPattern pat
|
|
|
|
let rhsContext = patternNames <> c
|
|
|
|
(rhsGraph, rhsRef) <- rhsWithBinds maybeWhereBinds rhs rhsContext
|
2016-12-26 08:45:58 +03:00
|
|
|
((patGraph, patRef), patAsName) <- evalPattern pat
|
2016-02-23 00:26:47 +03:00
|
|
|
let
|
|
|
|
(newEdges, newSinks, bindings) = case patRef of
|
|
|
|
(Left s) -> (mempty, mempty, [(s, rhsRef)])
|
|
|
|
(Right patPort) -> case rhsRef of
|
2016-02-26 05:37:04 +03:00
|
|
|
-- TODO This edge/sink should have a special arrow head to indicate an input to a pattern.
|
2016-02-23 00:26:47 +03:00
|
|
|
(Left rhsStr) -> (mempty, [(rhsStr, patPort)], mempty)
|
2016-02-26 05:37:04 +03:00
|
|
|
(Right rhsPort) -> ([makeSimpleEdge (rhsPort, patPort)], mempty, mempty)
|
2016-12-26 08:45:58 +03:00
|
|
|
asBindGraph = makeAsBindGraph rhsRef [patAsName]
|
|
|
|
gr = asBindGraph <> SyntaxGraph mempty newEdges newSinks bindings mempty
|
2016-02-23 09:01:03 +03:00
|
|
|
pure . makeEdges $ (gr <> rhsGraph <> patGraph)
|
2016-02-22 06:34:33 +03:00
|
|
|
|
2016-12-26 08:45:58 +03:00
|
|
|
-- TODO Returning a SyntaxGraph is probably not very efficient
|
|
|
|
asBindGraphZipper :: Maybe String -> NameAndPort -> SyntaxGraph
|
|
|
|
asBindGraphZipper asName nameNPort = makeAsBindGraph (Right nameNPort) [asName]
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
generalEvalLambda :: EvalContext -> [Pat] -> (EvalContext -> State IDState GraphAndRef) -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-23 09:01:03 +03:00
|
|
|
generalEvalLambda context patterns rhsEvalFun = do
|
2016-02-23 03:13:53 +03:00
|
|
|
lambdaName <- getUniqueName "lam"
|
2016-12-26 08:45:58 +03:00
|
|
|
patternValsWithAsNames <- mapM evalPattern patterns
|
2016-02-23 03:13:53 +03:00
|
|
|
let
|
2016-12-26 08:45:58 +03:00
|
|
|
patternVals = fmap fst patternValsWithAsNames
|
|
|
|
patternStrings = concatMap namesInPattern patternValsWithAsNames
|
2016-02-23 09:01:03 +03:00
|
|
|
rhsContext = patternStrings <> context
|
2016-12-07 04:02:54 +03:00
|
|
|
lambdaPorts = map (nameAndPort lambdaName . Port) [2,3..]
|
2016-02-23 03:13:53 +03:00
|
|
|
patternGraph = mconcat $ map fst patternVals
|
|
|
|
|
2016-03-21 12:00:04 +03:00
|
|
|
(patternEdges, newBinds) =
|
2016-03-28 02:49:58 +03:00
|
|
|
partitionEithers $ zipWith makePatternEdges patternVals lambdaPorts
|
2016-12-18 04:13:36 +03:00
|
|
|
|
|
|
|
(rhsRawGraph, rhsRef) <- rhsEvalFun rhsContext
|
2016-02-23 03:13:53 +03:00
|
|
|
let
|
2016-12-18 04:13:36 +03:00
|
|
|
icons = [(lambdaName, FunctionDefNode (length patterns))]
|
|
|
|
returnPort = nameAndPort lambdaName (Port 0)
|
|
|
|
(newEdges, newSinks) = case rhsRef of
|
|
|
|
Left s -> (patternEdges, [(s, returnPort)])
|
|
|
|
Right rhsPort -> (makeSimpleEdge (rhsPort, returnPort) : patternEdges, mempty)
|
|
|
|
finalGraph = SyntaxGraph icons newEdges newSinks newBinds mempty
|
2016-12-26 08:45:58 +03:00
|
|
|
|
|
|
|
asBindGraph = mconcat $ zipWith asBindGraphZipper (fmap snd patternValsWithAsNames) lambdaPorts
|
|
|
|
|
|
|
|
pure (deleteBindings . makeEdges $ (asBindGraph <> rhsRawGraph <> patternGraph <> finalGraph), nameAndPort lambdaName (Port 1))
|
2016-02-27 09:58:49 +03:00
|
|
|
where
|
|
|
|
-- TODO Like evalPatBind, this edge should have an indicator that it is the input to a pattern.
|
2016-03-22 03:36:02 +03:00
|
|
|
-- makePatternEdges creates the edges between the patterns and the parameter ports.
|
2016-03-28 02:49:58 +03:00
|
|
|
makePatternEdges :: GraphAndRef -> NameAndPort -> Either Edge (String, Reference)
|
|
|
|
makePatternEdges (_, Right patPort) lamPort =
|
2016-03-21 12:00:04 +03:00
|
|
|
Left $ makeSimpleEdge (lamPort, patPort)
|
2016-03-28 02:49:58 +03:00
|
|
|
makePatternEdges (_, Left str) lamPort = Right (str, Right lamPort)
|
2016-02-27 09:58:49 +03:00
|
|
|
|
2016-02-23 09:01:03 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalLambda :: EvalContext -> [Pat] -> Exp -> State IDState (SyntaxGraph, NameAndPort)
|
2016-02-23 09:01:03 +03:00
|
|
|
evalLambda c patterns e = generalEvalLambda c patterns (`evalExp` e)
|
2016-02-23 02:45:53 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalMatch :: EvalContext -> Match -> State IDState SyntaxGraph
|
2016-02-23 09:01:03 +03:00
|
|
|
evalMatch c (Match _ name patterns _ rhs maybeWhereBinds) = do
|
|
|
|
let
|
|
|
|
matchFunNameString = nameToString name
|
|
|
|
newContext = matchFunNameString : c
|
|
|
|
(lambdaGraph, lambdaPort) <-
|
|
|
|
generalEvalLambda newContext patterns (rhsWithBinds maybeWhereBinds rhs)
|
|
|
|
let
|
2016-12-26 08:45:58 +03:00
|
|
|
newBinding = bindsToSyntaxGraph [(matchFunNameString, Right lambdaPort)]
|
2016-02-23 09:01:03 +03:00
|
|
|
pure $ makeEdges (newBinding <> lambdaGraph)
|
2016-02-23 02:45:53 +03:00
|
|
|
|
2016-03-22 01:42:32 +03:00
|
|
|
-- Only used by matchesToCase
|
|
|
|
matchToAlt :: Match -> Alt
|
|
|
|
matchToAlt (Match srcLocation _ mtaPats _ rhs binds) = Alt srcLocation altPattern rhs binds where
|
|
|
|
altPattern = case mtaPats of
|
|
|
|
[onePat] -> onePat
|
|
|
|
_ -> PTuple Exts.Boxed mtaPats
|
2016-02-27 09:58:49 +03:00
|
|
|
|
2016-02-27 02:58:50 +03:00
|
|
|
matchesToCase :: Match -> [Match] -> State IDState Match
|
|
|
|
matchesToCase match [] = pure match
|
|
|
|
matchesToCase firstMatch@(Match srcLoc funName pats mType _ _) restOfMatches = do
|
2016-12-07 04:02:54 +03:00
|
|
|
tempStrings <- replicateM (length pats) (getUniqueString "_tempvar")
|
2016-02-25 01:46:49 +03:00
|
|
|
let
|
|
|
|
tempPats = fmap (PVar . Ident) tempStrings
|
2016-12-12 12:06:21 +03:00
|
|
|
tempVars = fmap makeVarExp tempStrings
|
2016-02-25 01:46:49 +03:00
|
|
|
tuple = Tuple Exts.Boxed tempVars
|
2016-02-27 02:58:50 +03:00
|
|
|
caseExp = case tempVars of
|
2016-02-27 09:58:49 +03:00
|
|
|
[oneTempVar] -> Case oneTempVar alts
|
2016-02-27 02:58:50 +03:00
|
|
|
_ -> Case tuple alts
|
2016-02-25 01:46:49 +03:00
|
|
|
rhs = UnGuardedRhs caseExp
|
|
|
|
match = Match srcLoc funName tempPats mType rhs Nothing
|
|
|
|
pure match
|
2016-02-27 09:58:49 +03:00
|
|
|
where
|
|
|
|
allMatches = firstMatch:restOfMatches
|
|
|
|
alts = fmap matchToAlt allMatches
|
|
|
|
|
2016-02-25 01:46:49 +03:00
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalMatches :: EvalContext -> [Match] -> State IDState SyntaxGraph
|
2016-02-22 02:15:16 +03:00
|
|
|
evalMatches _ [] = pure mempty
|
2016-02-27 02:58:50 +03:00
|
|
|
evalMatches c (firstMatch:restOfMatches) = matchesToCase firstMatch restOfMatches >>= evalMatch c
|
2016-02-04 11:19:08 +03:00
|
|
|
|
2016-12-16 11:47:48 +03:00
|
|
|
-- Pretty printing the entire type sig results in extra whitespace in the middle
|
|
|
|
-- TODO May want to trim whitespace from (prettyPrint typeForNames)
|
2016-12-18 04:13:36 +03:00
|
|
|
evalTypeSig :: Decl -> State IDState (SyntaxGraph, NameAndPort)
|
2016-12-16 11:47:48 +03:00
|
|
|
evalTypeSig (TypeSig _ names typeForNames) = makeBox
|
|
|
|
(intercalate "," (fmap prettyPrint names)
|
|
|
|
++ " :: "
|
|
|
|
++ prettyPrint typeForNames)
|
|
|
|
|
2016-06-18 23:17:09 +03:00
|
|
|
evalDecl :: EvalContext -> Decl -> State IDState SyntaxGraph
|
2016-12-14 00:40:23 +03:00
|
|
|
evalDecl c d = case d of
|
|
|
|
PatBind _ _ _ _ -> evalPatBind c d
|
2016-02-21 05:47:56 +03:00
|
|
|
FunBind matches -> evalMatches c matches
|
2016-12-16 11:47:48 +03:00
|
|
|
TypeSig _ _ _ -> fst <$> evalTypeSig d
|
2016-02-24 10:14:00 +03:00
|
|
|
--TODO: Add other cases here
|
|
|
|
_ -> pure mempty
|
2016-02-21 08:26:25 +03:00
|
|
|
|
2016-07-03 00:43:18 +03:00
|
|
|
showTopLevelBinds :: SyntaxGraph -> State IDState SyntaxGraph
|
2016-12-07 05:39:38 +03:00
|
|
|
showTopLevelBinds gr = do
|
2016-07-03 00:43:18 +03:00
|
|
|
let
|
2016-12-07 05:39:38 +03:00
|
|
|
binds = sgSources gr
|
2016-07-03 00:43:18 +03:00
|
|
|
addBind (_, Left _) = pure mempty
|
|
|
|
addBind (patName, Right port) = do
|
|
|
|
uniquePatName <- getUniqueName patName
|
|
|
|
let
|
2016-12-07 04:02:54 +03:00
|
|
|
icons = [(uniquePatName, BindNameNode patName)]
|
2016-12-08 13:41:47 +03:00
|
|
|
edges = [makeSimpleEdge (port, justName uniquePatName)]
|
2016-07-03 00:43:18 +03:00
|
|
|
edgeGraph = syntaxGraphFromNodesEdges icons edges
|
|
|
|
pure edgeGraph
|
|
|
|
newGraph <- mconcat <$> mapM addBind binds
|
|
|
|
pure $ newGraph <> gr
|
|
|
|
|
2016-12-16 09:58:19 +03:00
|
|
|
translateDeclToSyntaxGraph :: Decl -> SyntaxGraph
|
|
|
|
translateDeclToSyntaxGraph d = graph where
|
|
|
|
evaluatedDecl = evalDecl mempty d >>= showTopLevelBinds
|
|
|
|
graph = evalState evaluatedDecl initialIdState
|
|
|
|
|
|
|
|
-- | Convert a single function declaration into a SyntaxGraph
|
|
|
|
translateStringToSyntaxGraph :: String -> SyntaxGraph
|
|
|
|
translateStringToSyntaxGraph = translateDeclToSyntaxGraph . fromParseResult . parseDecl
|
|
|
|
|
2016-12-16 11:47:48 +03:00
|
|
|
syntaxGraphToCollapsedGraph :: SyntaxGraph -> IngSyntaxGraph FGR.Gr
|
|
|
|
syntaxGraphToCollapsedGraph = collapseNodes . syntaxGraphToFglGraph
|
|
|
|
|
2016-12-16 09:58:19 +03:00
|
|
|
translateDeclToCollapsedGraph :: Decl -> IngSyntaxGraph FGR.Gr
|
2016-12-16 11:47:48 +03:00
|
|
|
translateDeclToCollapsedGraph = syntaxGraphToCollapsedGraph . translateDeclToSyntaxGraph
|
2016-02-27 09:58:49 +03:00
|
|
|
|
|
|
|
-- Profiling: about 1.5% of total time.
|
2016-12-16 09:58:19 +03:00
|
|
|
translateStringToCollapsedGraphAndDecl :: String -> (IngSyntaxGraph FGR.Gr, Decl)
|
|
|
|
translateStringToCollapsedGraphAndDecl s = (drawing, decl) where
|
2016-05-10 09:45:37 +03:00
|
|
|
decl = fromParseResult (parseDecl s) -- :: ParseResult Module
|
2016-12-16 09:58:19 +03:00
|
|
|
drawing = translateDeclToCollapsedGraph decl
|
2016-07-03 00:43:18 +03:00
|
|
|
|
2016-12-16 09:58:19 +03:00
|
|
|
-- TODO Put the type declarations in a box below the image.
|
|
|
|
translateModuleToCollapsedGraphs :: Module -> [IngSyntaxGraph FGR.Gr]
|
|
|
|
translateModuleToCollapsedGraphs (Module _ _ _ _ _ _ decls) = fmap translateDeclToCollapsedGraph decls
|