hydra-kernel-0.17.0: src/main/haskell/Hydra/Show/Paths.hs
-- Note: this is an automatically generated file. Do not edit.
-- | Utilities for working with subterm steps and paths.
module Hydra.Show.Paths where
import qualified Hydra.Ast as Ast
import qualified Hydra.Coders as Coders
import qualified Hydra.Core as Core
import qualified Hydra.Docs as Docs
import qualified Hydra.Error.Checking as Checking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.File as ErrorFile
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Error.System as ErrorSystem
import qualified Hydra.Errors as Errors
import qualified Hydra.File as File
import qualified Hydra.Graph as Graph
import qualified Hydra.Json.Model as Model
import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs
import qualified Hydra.Overlay.Haskell.Lib.Sets as Sets
import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
import qualified Hydra.Names as Names
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Query as Query
import qualified Hydra.Relational as Relational
import qualified Hydra.Rewriting as Rewriting
import qualified Hydra.System as System
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Time as Time
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variants as Variants
import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci
import qualified Data.Map as M
-- | Convert a subterm step to a string representation
subtermStep :: Paths.SubtermStep -> Maybe String
subtermStep step =
let idx = \i -> Nothing
idxSuff = \suffix -> \i -> Optionals.map (\s -> Strings.cat2 s suffix) (idx i)
in case step of
Paths.SubtermStepAnnotatedBody -> Nothing
Paths.SubtermStepApplicationFunction -> Just "fun"
Paths.SubtermStepApplicationArgument -> Just "arg"
Paths.SubtermStepLambdaBody -> Just "body"
Paths.SubtermStepUnionCasesDefault -> Just "default"
Paths.SubtermStepUnionCasesBranch v0 -> Just (Strings.cat2 "." (Core.unName v0))
Paths.SubtermStepLetBody -> Just "in"
Paths.SubtermStepLetBinding v0 -> Just (Strings.cat2 (Core.unName v0) "=")
Paths.SubtermStepListElement v0 -> idx v0
Paths.SubtermStepMapKey v0 -> idxSuff ".key" v0
Paths.SubtermStepMapValue v0 -> idxSuff ".value" v0
Paths.SubtermStepOptionalTerm -> Just "given"
Paths.SubtermStepProductTerm v0 -> idx v0
Paths.SubtermStepRecordField v0 -> Just (Strings.cat2 "." (Core.unName v0))
Paths.SubtermStepSetElement v0 -> idx v0
Paths.SubtermStepSumTerm -> Nothing
Paths.SubtermStepTypeLambdaBody -> Nothing
Paths.SubtermStepTypeApplicationTerm -> Nothing
Paths.SubtermStepInjectionTerm -> Nothing
Paths.SubtermStepWrappedTerm -> Nothing
-- | Build a subterm graph from a term
termToSubtermGraph :: M.Map Packaging.ModuleName String -> Core.Term -> Paths.SubtermGraph
termToSubtermGraph namespaces term =
let dontCareStep = Paths.SubtermStepAnnotatedBody
helper =
\ids -> \mroot -> \path -> \state -> \stepTerm ->
let step = Pairs.first stepTerm
currentTerm = Pairs.second stepTerm
nodesEdges = Pairs.first state
visited = Pairs.second state
nodes = Pairs.first nodesEdges
edges = Pairs.second nodesEdges
nextPath = Lists.cons step path
in case currentTerm of
Core.TermLet v0 ->
let bindings = Core.letBindings v0
env = Core.letBody v0
bindingNames = Lists.map Core.bindingName bindings
addBindingName =
\nodesVisitedIds -> \name ->
let currentNodesVisited = Pairs.first nodesVisitedIds
currentIds = Pairs.second nodesVisitedIds
currentNodes = Pairs.first currentNodesVisited
currentVisited = Pairs.second currentNodesVisited
rawLabel = Names.compactName namespaces name
uniqueLabel = Names.chooseUniqueLabel currentVisited rawLabel
node =
Paths.SubtermNode {
Paths.subtermNodeName = name,
Paths.subtermNodeLabel = rawLabel,
Paths.subtermNodeId = uniqueLabel}
newVisited = Sets.insert uniqueLabel currentVisited
newNodes = Lists.cons node currentNodes
newIds = Maps.insert name node currentIds
in ((newNodes, newVisited), newIds)
nodesVisitedIds1 = Lists.foldl addBindingName (([], visited), ids) bindingNames
nodes1 = Pairs.first (Pairs.first nodesVisitedIds1)
visited1 = Pairs.second (Pairs.first nodesVisitedIds1)
ids1 = Pairs.second nodesVisitedIds1
addBindingTerm =
\currentState -> \nodeBinding ->
let root = Pairs.first nodeBinding
binding = Pairs.second nodeBinding
term1 = Core.bindingTerm binding
in (helper ids1 (Just root) [] currentState (dontCareStep, term1))
nodeBindingPairs = Lists.zip nodes1 bindings
stateAfterBindings = Lists.foldl addBindingTerm ((Lists.concat2 nodes1 nodes, edges), visited1) nodeBindingPairs
in (helper ids1 mroot nextPath stateAfterBindings (Paths.SubtermStepLetBody, env))
Core.TermVariable v0 -> Optionals.cases mroot state (\root -> Optionals.cases (Maps.lookup v0 ids) state (\node ->
let edge =
Paths.SubtermEdge {
Paths.subtermEdgeSource = root,
Paths.subtermEdgePath = (Paths.SubtermPath (Lists.reverse nextPath)),
Paths.subtermEdgeTarget = node}
newEdges = Lists.cons edge edges
in ((nodes, newEdges), visited)))
_ -> Lists.foldl (helper ids mroot nextPath) state (Rewriting.subtermsWithSteps currentTerm)
initialState = (([], []), Sets.empty)
result = helper Maps.empty Nothing [] initialState (dontCareStep, term)
finalNodesEdges = Pairs.first result
finalNodes = Pairs.first finalNodesEdges
finalEdges = Pairs.second finalNodesEdges
in Paths.SubtermGraph {
Paths.subtermGraphNodes = finalNodes,
Paths.subtermGraphEdges = finalEdges}