@@ -12,7 +12,6 @@ as SML/NJ to get nice trees.
14import Control.Arrow (second)
14import Control.Arrow (second)
15−import Data.Function (on)
16import qualified Data.List as List
15import qualified Data.List as List
17import qualified Data.Map as Map
16import qualified Data.Map as Map
18import qualified Data.Set as Set
17import qualified Data.Set as Set
@@ -144,37 +143,23 @@ toDecisionTree variantDict rawBranches =
144 Nothing ->
143 Nothing ->
147− smallDefaults branches
146+ pickPath variantDict branches
149− relevantTests =
148+ (edges, fallback) =
150− testsAtPath path branches
149+ gatherEdges variantDict branches path
152− allRawEdges =
151+ decisionEdges =
153− map (edgesFor path branches) relevantTests
155− (rawEdges, unexplored) =
156− if isComplete variantDict relevantTests then
158− , snd (last allRawEdges)
163− , filter (isIrrelevantTo path) branches
167− map (second (toDecisionTree variantDict)) rawEdges
152+ map (second (toDecisionTree variantDict)) edges
169− case (edges, unexplored) of
154+ case (decisionEdges, fallback) of
170 ([(_tag, decisionTree)], []) ->
155 ([(_tag, decisionTree)], []) ->
171 decisionTree
156 decisionTree
173 (_, []) ->
158 (_, []) ->
174− Decision path edges Nothing
159+ Decision path decisionEdges Nothing
176 (_, _) ->
161 (_, _) ->
177− Decision path edges (Just (toDecisionTree variantDict unexplored))
162+ Decision path decisionEdges (Just (toDecisionTree variantDict fallback))
180isComplete :: VariantDict -> [Test] -> Bool
165isComplete :: VariantDict -> [Test] -> Bool
@@ -283,6 +268,28 @@ getSubstitution (path, A.A _ pattern) =
271+-- GATHER OUTGOING EDGES
273+gatherEdges :: VariantDict -> [Branch] -> Path -> ([(Test, [Branch])], [Branch])
274+gatherEdges variantDict branches path =
277+ testsAtPath path branches
280+ map (edgesFor path branches) relevantTests
282+ if isComplete variantDict relevantTests then
284+ , snd (last allRawEdges)
289+ , filter (isIrrelevantTo path) branches
286-- FIND RELEVANT TESTS
293-- FIND RELEVANT TESTS
288testsAtPath :: Path -> [Branch] -> [Test]
295testsAtPath :: Path -> [Branch] -> [Test]
@@ -420,18 +427,20 @@ needsTests (A.A _ pattern) =
423−-- PATH PICKING HEURISTICS
430+-- PICK A PATH
425−smallDefaults :: [Branch] -> Path
432+pickPath :: VariantDict -> [Branch] -> Path
426−smallDefaults branches =
433+pickPath variantDict branches =
428 allPaths =
435 allPaths =
429 Maybe.mapMaybe isChoicePath (concatMap _patterns branches)
436 Maybe.mapMaybe isChoicePath (concatMap _patterns branches)
432− map (\path -> (path, length (filter (isIrrelevantTo path) branches))) allPaths
434− fst (List.minimumBy (compare `on` snd) weightedPaths)
438+ case bests (addWeights (smallDefaults branches) allPaths) of
443+ head (bests (addWeights (smallBranchingFactor variantDict branches) tiedPaths))
437isChoicePath :: (Path, CPattern) -> Maybe Path
446isChoicePath :: (Path, CPattern) -> Maybe Path
@@ -442,4 +451,38 @@ isChoicePath (path, pattern) =
454+addWeights :: (Path -> Int) -> [Path] -> [(Path, Int)]
455+addWeights toWeight paths =
456+ map (\path -> (path, toWeight path)) paths
459+bests :: [(Path, Int)] -> [Path]
460+bests ((path,weight):weightedPaths) =
462+ gatherMinimum acc@(minWeight, paths) (path, weight) =
463+ if weight == minWeight then
464+ (minWeight, path : paths)
466+ else if weight < minWeight then
472+ snd (List.foldl' gatherMinimum (weight, [path]) weightedPaths)
475+-- PATH PICKING HEURISTICS
477+smallDefaults :: [Branch] -> Path -> Int
478+smallDefaults branches path =
479+ length (filter (isIrrelevantTo path) branches)
445−-- smallBranchingFactor :: [Branch] -> Path
482+smallBranchingFactor :: VariantDict -> [Branch] -> Path -> Int
483+smallBranchingFactor variantDict branches path =
486+ gatherEdges variantDict branches path
488+ length edges + (if null fallback then 0 else 1)