Small dependency ordering optimizations

This commit is contained in:
James Eversole 2025-01-26 16:06:40 -06:00
parent 918d929c09
commit f71f88dce3
2 changed files with 30 additions and 26 deletions

View File

@ -62,4 +62,4 @@ jobs:
./tricu ./tricu
token: '${{ secrets.RELEASE_TOKEN }}' token: '${{ secrets.RELEASE_TOKEN }}'
body: '${{ gitea.event.head_commit.message }}' body: '${{ gitea.event.head_commit.message }}'
pre_release: true prerelease: true

View File

@ -3,7 +3,7 @@ module Eval where
import Parser import Parser
import Research import Research
import Data.List (partition) import Data.List (partition, (\\))
import Data.Map (Map) import Data.Map (Map)
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Set as Set import qualified Data.Set as Set
@ -122,16 +122,19 @@ reorderDefs env defs
| otherwise = orderedDefs ++ others | otherwise = orderedDefs ++ others
where where
(defsOnly, others) = partition isDef defs (defsOnly, others) = partition isDef defs
defNames = [ name | SDef name _ _ <- defsOnly ]
defsWithFreeVars = [(def, freeVars body) | def@(SDef _ _ body) <- defsOnly]
graph = buildDepGraph defsOnly graph = buildDepGraph defsOnly
sortedDefs = sortDeps graph sortedDefs = sortDeps graph
defMap = Map.fromList [(name, def) | def@(SDef name _ _) <- defsOnly] defMap = Map.fromList [(name, def) | def@(SDef name _ _) <- defsOnly]
orderedDefs = map (\name -> defMap Map.! name) sortedDefs orderedDefs = map (\name -> defMap Map.! name) sortedDefs
topDefNames = Set.fromList (Map.keys defMap)
envNames = Set.fromList (Map.keys env) freeVarsDefs = foldMap snd defsWithFreeVars
freeVarsDefs = foldMap (\(SDef _ _ body) -> freeVars body) defsOnly
freeVarsOthers = foldMap freeVars others freeVarsOthers = foldMap freeVars others
allFreeVars = freeVarsDefs <> freeVarsOthers allFreeVars = freeVarsDefs <> freeVarsOthers
validNames = topDefNames `Set.union` envNames validNames = Set.fromList defNames `Set.union` Set.fromList (Map.keys env)
missingDeps = Set.toList (allFreeVars `Set.difference` validNames) missingDeps = Set.toList (allFreeVars `Set.difference` validNames)
isDef (SDef _ _ _) = True isDef (SDef _ _ _) = True
@ -153,20 +156,21 @@ buildDepGraph topDefs
countOccurrences = foldr (\x -> Map.insertWith (+) x 1) Map.empty countOccurrences = foldr (\x -> Map.insertWith (+) x 1) Map.empty
sortDeps :: Map.Map String (Set.Set String) -> [String] sortDeps :: Map.Map String (Set.Set String) -> [String]
sortDeps graph = go [] (Map.keys graph) sortDeps graph = go [] Set.empty (Map.keys graph)
where where
go sorted [] = sorted go sorted sortedSet [] = sorted
go sorted remaining go sorted sortedSet remaining =
| null ready = let ready = [ name | name <- remaining
errorWithoutStackTrace , let deps = Map.findWithDefault Set.empty name graph
"ERROR: Top-level cyclic dependency detected and prohibited\n\ , Set.isSubsetOf deps sortedSet ]
\RESOLVE: Use nested lambdas" notReady = remaining \\ ready
| otherwise = go (sorted ++ ready) notReady in if null ready
where then errorWithoutStackTrace
ready = [ name | name <- remaining "ERROR: Cyclic dependency detected and prohibited.\n\
, all (`elem` sorted) (Set.toList (graph Map.! name))] \RESOLVE: Use nested lambdas."
notReady = else go (sorted ++ ready)
[ name | name <- remaining , name `notElem` ready] (Set.union sortedSet (Set.fromList ready))
notReady
depends :: [TricuAST] -> TricuAST -> Set.Set String depends :: [TricuAST] -> TricuAST -> Set.Set String
depends topDefs (SDef _ _ body) = depends topDefs (SDef _ _ body) =