mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-08-19 10:46:22 -06:00
faster and correct dependency checking
This commit is contained in:
@@ -53,8 +53,8 @@ checkModule opts cwd sgr mo@(m,mi) = do
|
|||||||
abs <- lookupModule gr a
|
abs <- lookupModule gr a
|
||||||
checkCompleteGrammar opts cwd gr (a,abs) mo
|
checkCompleteGrammar opts cwd gr (a,abs) mo
|
||||||
_ -> return mo
|
_ -> return mo
|
||||||
infoss <- checkInModule cwd mi NoLoc empty $ topoSortJments2 mo
|
infos <- checkInModule cwd mi NoLoc empty $ topoSortJments mo
|
||||||
foldM (foldM (checkInfo opts cwd sgr)) mo infoss
|
foldM (checkInfo opts cwd sgr) mo infos
|
||||||
|
|
||||||
-- check if restricted inheritance modules are still coherent
|
-- check if restricted inheritance modules are still coherent
|
||||||
-- i.e. that the defs of remaining names don't depend on omitted names
|
-- i.e. that the defs of remaining names don't depend on omitted names
|
||||||
@@ -71,7 +71,7 @@ checkRestrictedInheritance cwd sgr (name,mo) = checkInModule cwd mo NoLoc empty
|
|||||||
let incld c = Set.member c (Set.fromList incl)
|
let incld c = Set.member c (Set.fromList incl)
|
||||||
let illegal c = Set.member c (Set.fromList excl)
|
let illegal c = Set.member c (Set.fromList excl)
|
||||||
let illegals = [(f,is) |
|
let illegals = [(f,is) |
|
||||||
(f,cs) <- allDeps, incld f, let is = filter illegal cs, not (null is)]
|
(f,_,cs) <- allDeps, incld f, let is = filter illegal cs, not (null is)]
|
||||||
case illegals of
|
case illegals of
|
||||||
[] -> return ()
|
[] -> return ()
|
||||||
cs -> checkWarn ("In inherited module" <+> i <> ", dependence of excluded constants:" $$
|
cs -> checkWarn ("In inherited module" <+> i <> ", dependence of excluded constants:" $$
|
||||||
|
|||||||
@@ -35,9 +35,6 @@ module GF.Data.Operations (
|
|||||||
prBracket, prArgList, prSemicList, prCurlyList, restoreEscapes,
|
prBracket, prArgList, prSemicList, prCurlyList, restoreEscapes,
|
||||||
numberedParagraphs, prConjList, prIfEmpty, wrapLines,
|
numberedParagraphs, prConjList, prIfEmpty, wrapLines,
|
||||||
|
|
||||||
-- ** Topological sorting
|
|
||||||
topoTest, topoTest2,
|
|
||||||
|
|
||||||
-- ** Misc
|
-- ** Misc
|
||||||
readIntArg,
|
readIntArg,
|
||||||
iterFix, chunks,
|
iterFix, chunks,
|
||||||
@@ -53,7 +50,6 @@ import Control.Monad (liftM,liftM2) --,ap
|
|||||||
import Control.Monad.Fix
|
import Control.Monad.Fix
|
||||||
|
|
||||||
import GF.Data.ErrM
|
import GF.Data.ErrM
|
||||||
import GF.Data.Relation
|
|
||||||
import qualified Control.Monad.Fail as Fail
|
import qualified Control.Monad.Fail as Fail
|
||||||
|
|
||||||
infixr 5 +++
|
infixr 5 +++
|
||||||
@@ -188,26 +184,6 @@ wrapLines n s@(c:cs) =
|
|||||||
l = length w
|
l = length w
|
||||||
_ -> s -- give up!!
|
_ -> s -- give up!!
|
||||||
|
|
||||||
-- | Topological sorting with test of cyclicity
|
|
||||||
topoTest :: Ord a => [(a,[a])] -> Either [a] [[a]]
|
|
||||||
topoTest = topologicalSort . mkRel'
|
|
||||||
|
|
||||||
-- | Topological sorting with test of cyclicity, new version /TH 2012-06-26
|
|
||||||
topoTest2 :: Ord a => [(a,[a])] -> Either [[a]] [[a]]
|
|
||||||
topoTest2 g0 = maybe (Right cycles) Left (tsort g)
|
|
||||||
where
|
|
||||||
g = g0++[(n,[])|n<-nub (concatMap snd g0)\\map fst g0]
|
|
||||||
|
|
||||||
cycles = findCycles (mkRel' g)
|
|
||||||
|
|
||||||
tsort nes =
|
|
||||||
case partition (null.snd) nes of
|
|
||||||
([],[]) -> Just []
|
|
||||||
([],_) -> Nothing
|
|
||||||
(ns,rest) -> (leaves:) `fmap` tsort [(n,es \\ leaves) | (n,es)<-rest]
|
|
||||||
where leaves = map fst ns
|
|
||||||
|
|
||||||
|
|
||||||
-- | Fix point iterator (for computing e.g. transitive closures or reachability)
|
-- | Fix point iterator (for computing e.g. transitive closures or reachability)
|
||||||
iterFix :: Eq a => ([a] -> [a]) -> [a] -> [a]
|
iterFix :: Eq a => ([a] -> [a]) -> [a] -> [a]
|
||||||
iterFix more start = iter start start
|
iterFix more start = iter start start
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import GF.Data.Operations
|
|||||||
import PGF2(BindType(..),PGF)
|
import PGF2(BindType(..),PGF)
|
||||||
import PGF2.Transactions(LIndex,LVar,LParam(..),PArg(..),Symbol(..),Rule(..))
|
import PGF2.Transactions(LIndex,LVar,LParam(..),PArg(..),Symbol(..),Rule(..))
|
||||||
|
|
||||||
|
import Data.Graph
|
||||||
import Data.Array.IArray(Array)
|
import Data.Array.IArray(Array)
|
||||||
import Data.Array.Unboxed(UArray)
|
import Data.Array.Unboxed(UArray)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
@@ -276,10 +277,11 @@ isCompleteModule m = mstatus m == MSComplete && mtype m /= MTInterface
|
|||||||
|
|
||||||
-- | all abstract modules sorted from least to most dependent
|
-- | all abstract modules sorted from least to most dependent
|
||||||
allAbstracts :: Grammar -> [ModuleName]
|
allAbstracts :: Grammar -> [ModuleName]
|
||||||
allAbstracts gr =
|
allAbstracts gr =
|
||||||
case topoTest [(i,extends m) | (i,m) <- modules gr, mtype m == MTAbstract] of
|
let scc = stronglyConnComp [(mn,mn,extends mo) | (mn,mo) <- modules gr, mtype mo == MTAbstract]
|
||||||
Left is -> is
|
in case [mns | CyclicSCC mns <- scc] of
|
||||||
Right cycles -> error $ render ("Cyclic abstract modules:" <+> vcat (map hsep cycles))
|
[] -> [mn | AcyclicSCC mn <- scc]
|
||||||
|
cycles -> error $ render ("Cyclic abstract modules:" <+> vcat (map hsep cycles))
|
||||||
|
|
||||||
-- | the last abstract in dependency order (head of list)
|
-- | the last abstract in dependency order (head of list)
|
||||||
greatestAbstract :: Grammar -> Maybe ModuleName
|
greatestAbstract :: Grammar -> Maybe ModuleName
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ import GF.Grammar.Printer
|
|||||||
import Control.Monad.Identity(Identity(..))
|
import Control.Monad.Identity(Identity(..))
|
||||||
import qualified Data.Traversable as T(mapM)
|
import qualified Data.Traversable as T(mapM)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Control.Monad (liftM, liftM2, liftM3)
|
import Control.Monad (liftM, liftM2, liftM3, forM)
|
||||||
import Data.List (sortBy,nub)
|
import Data.List (sortBy,nub)
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import GF.Text.Pretty(render,(<+>),hsep,fsep)
|
import Data.Graph
|
||||||
|
import GF.Text.Pretty(render,(<+>),($$),hsep,fsep,vcat,nest)
|
||||||
import qualified Control.Monad.Fail as Fail
|
import qualified Control.Monad.Fail as Fail
|
||||||
|
|
||||||
-- ** Functions for constructing and analysing source code terms.
|
-- ** Functions for constructing and analysing source code terms.
|
||||||
@@ -538,16 +539,25 @@ sortRec = sortBy ordLabel where
|
|||||||
|
|
||||||
-- | dependency check, detecting circularities and returning topo-sorted list
|
-- | dependency check, detecting circularities and returning topo-sorted list
|
||||||
|
|
||||||
allDependencies :: (ModuleName -> Bool) -> Map.Map Ident Info -> [(Ident,[Ident])]
|
allDependencies :: (ModuleName -> Bool) -> Map.Map Ident Info -> [(Ident,Info,[Ident])]
|
||||||
allDependencies ism b =
|
allDependencies ism b =
|
||||||
[(f, nub (concatMap opty (pts i))) | (f,i) <- Map.toList b]
|
[(f, i, nub (concatMap opty (pts i))) | (f,i) <- Map.toList b]
|
||||||
where
|
where
|
||||||
opersIn t = case t of
|
opersIn t = case t of
|
||||||
Q (n,c) | ism n -> [c]
|
Q (n,c) | ism n -> [c]
|
||||||
QC (n,c) | ism n -> [c]
|
QC (n,c) | ism n -> [c]
|
||||||
|
EPatt _ _ p -> opersInPatt p
|
||||||
|
T _ cs -> mconcatMap (\(p,t) -> opersInPatt p ++ opersIn t) cs
|
||||||
_ -> collectOp opersIn t
|
_ -> collectOp opersIn t
|
||||||
|
|
||||||
|
opersInPatt p = case p of
|
||||||
|
PTilde t -> opersIn t
|
||||||
|
PM (n,c) | ism n -> [c]
|
||||||
|
_ -> collectPattOp opersInPatt p
|
||||||
|
|
||||||
opty (Just (L _ ty)) = opersIn ty
|
opty (Just (L _ ty)) = opersIn ty
|
||||||
opty _ = []
|
opty _ = []
|
||||||
|
|
||||||
pts i = case i of
|
pts i = case i of
|
||||||
ResOper pty pt -> [pty,pt]
|
ResOper pty pt -> [pty,pt]
|
||||||
ResOverload _ tyts -> concat [[Just ty, Just tr] | (ty,tr) <- tyts]
|
ResOverload _ tyts -> concat [[Just ty, Just tr] | (ty,tr) <- tyts]
|
||||||
@@ -560,22 +570,14 @@ allDependencies ism b =
|
|||||||
|
|
||||||
topoSortJments :: ErrorMonad m => SourceModule -> m [(Ident,Info)]
|
topoSortJments :: ErrorMonad m => SourceModule -> m [(Ident,Info)]
|
||||||
topoSortJments (m,mi) = do
|
topoSortJments (m,mi) = do
|
||||||
is <- either
|
let sccs = stronglyConnComp (map toNode (allDependencies (==m) (jments mi)))
|
||||||
return
|
cycles = [map fst jmts | CyclicSCC jmts <- sccs]
|
||||||
(\cyc -> raise (render ("circular definitions:" <+> fsep (head cyc))))
|
case cycles of
|
||||||
(topoTest (allDependencies (==m) (jments mi)))
|
[] -> return [jmt | AcyclicSCC jmt <- sccs]
|
||||||
return (reverse [(i,info) | i <- is, Just info <- [Map.lookup i (jments mi)]])
|
_ -> raise (render ("circular definitions:" $$
|
||||||
|
nest 3 (vcat (map fsep cycles))))
|
||||||
topoSortJments2 :: ErrorMonad m => SourceModule -> m [[(Ident,Info)]]
|
where
|
||||||
topoSortJments2 (m,mi) = do
|
toNode (id,info,deps) = ((id,info),id,deps)
|
||||||
iss <- either
|
|
||||||
return
|
|
||||||
(\cyc -> raise (render ("circular definitions:"
|
|
||||||
<+> fsep (head cyc))))
|
|
||||||
(topoTest2 (allDependencies (==m) (jments mi)))
|
|
||||||
return
|
|
||||||
[[(i,info) | i<-is,Just info<-[Map.lookup i (jments mi)]] | is<-iss]
|
|
||||||
|
|
||||||
|
|
||||||
mkStrs p = case p of
|
mkStrs p = case p of
|
||||||
PAlt a b -> do
|
PAlt a b -> do
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import GF.Grammar.CFG
|
|||||||
--import GF.Infra.Ident (Ident)
|
--import GF.Infra.Ident (Ident)
|
||||||
|
|
||||||
import GF.Data.Graph
|
import GF.Data.Graph
|
||||||
--import GF.Data.Relation
|
|
||||||
import GF.Speech.FiniteState
|
import GF.Speech.FiniteState
|
||||||
--import GF.Speech.CFG
|
--import GF.Speech.CFG
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user