@@ -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
@@ -74,6 +73,7 @@ data DecisionTree a
74 , _edges :: [(Test, DecisionTree a)]
73 , _edges :: [(Test, DecisionTree a)]
75 , _default :: Maybe (DecisionTree a)
74 , _default :: Maybe (DecisionTree a)
79data Jump = Jump
79data Jump = Jump
@@ -144,37 +144,23 @@ toDecisionTree variantDict rawBranches =
144 Nothing ->
144 Nothing ->
147− smallDefaults branches
147+ pickPath variantDict branches
150− testsAtPath path branches
153− map (edgesFor path branches) relevantTests
155− (rawEdges, unexplored) =
156− if isComplete variantDict relevantTests then
158− , snd (last allRawEdges)
161− else
149+ (edges, fallback) =
162− ( allRawEdges
150+ gatherEdges variantDict branches path
163− , filter (isIrrelevantTo path) branches
166− edges =
152+ decisionEdges =
167− map (second (toDecisionTree variantDict)) rawEdges
153+ map (second (toDecisionTree variantDict)) edges
169− case (edges, unexplored) of
155+ case (decisionEdges, fallback) of
170 ([(_tag, decisionTree)], []) ->
156 ([(_tag, decisionTree)], []) ->
171 decisionTree
157 decisionTree
173 (_, []) ->
159 (_, []) ->
174− Decision path edges Nothing
160+ Decision path decisionEdges Nothing
176 (_, _) ->
162 (_, _) ->
177− Decision path edges (Just (toDecisionTree variantDict unexplored))
163+ Decision path decisionEdges (Just (toDecisionTree variantDict fallback))
180isComplete :: VariantDict -> [Test] -> Bool
166isComplete :: VariantDict -> [Test] -> Bool
@@ -283,6 +269,28 @@ getSubstitution (path, A.A _ pattern) =
272+-- GATHER OUTGOING EDGES
274+gatherEdges :: VariantDict -> [Branch] -> Path -> ([(Test, [Branch])], [Branch])
275+gatherEdges variantDict branches path =
278+ testsAtPath path branches
281+ map (edgesFor path branches) relevantTests
283+ if isComplete variantDict relevantTests then
285+ , snd (last allRawEdges)
290+ , filter (isIrrelevantTo path) branches
286-- FIND RELEVANT TESTS
294-- FIND RELEVANT TESTS
288testsAtPath :: Path -> [Branch] -> [Test]
296testsAtPath :: Path -> [Branch] -> [Test]
@@ -420,18 +428,20 @@ needsTests (A.A _ pattern) =
423−-- PATH PICKING HEURISTICS
431+-- PICK A PATH
425−smallDefaults :: [Branch] -> Path
433+pickPath :: VariantDict -> [Branch] -> Path
426−smallDefaults branches =
434+pickPath variantDict branches =
428 allPaths =
436 allPaths =
429 Maybe.mapMaybe isChoicePath (concatMap _patterns branches)
437 Maybe.mapMaybe isChoicePath (concatMap _patterns branches)
432− map (\path -> (path, length (filter (isIrrelevantTo path) branches))) allPaths
434− fst (List.minimumBy (compare `on` snd) weightedPaths)
439+ case bests (addWeights (smallDefaults branches) allPaths) of
444+ head (bests (addWeights (smallBranchingFactor variantDict branches) tiedPaths))
437isChoicePath :: (Path, CPattern) -> Maybe Path
447isChoicePath :: (Path, CPattern) -> Maybe Path
@@ -442,4 +452,38 @@ isChoicePath (path, pattern) =
455+addWeights :: (Path -> Int) -> [Path] -> [(Path, Int)]
456+addWeights toWeight paths =
457+ map (\path -> (path, toWeight path)) paths
460+bests :: [(Path, Int)] -> [Path]
461+bests ((path,weight):weightedPaths) =
463+ gatherMinimum acc@(minWeight, paths) (path, weight) =
464+ if weight == minWeight then
465+ (minWeight, path : paths)
467+ else if weight < minWeight then
473+ snd (List.foldl' gatherMinimum (weight, [path]) weightedPaths)
476+-- PATH PICKING HEURISTICS
478+smallDefaults :: [Branch] -> Path -> Int
479+smallDefaults branches path =
480+ length (filter (isIrrelevantTo path) branches)
445−-- smallBranchingFactor :: [Branch] -> Path
483+smallBranchingFactor :: VariantDict -> [Branch] -> Path -> Int
484+smallBranchingFactor variantDict branches path =
487+ gatherEdges variantDict branches path
489+ length edges + (if null fallback then 0 else 1)