mirror of
https://github.com/anoma/juvix.git
synced 2024-12-11 08:25:46 +03:00
Change terminating keyword behavior (#82)
This commit is contained in:
parent
8146b2a91d
commit
7b1371c4b9
48
app/Main.hs
48
app/Main.hs
@ -6,17 +6,21 @@ import Commands.Extra
|
|||||||
import Commands.MicroJuvix
|
import Commands.MicroJuvix
|
||||||
import Commands.MiniHaskell
|
import Commands.MiniHaskell
|
||||||
import Commands.MonoJuvix
|
import Commands.MonoJuvix
|
||||||
import Commands.Termination as T
|
import Commands.Termination as Termination
|
||||||
import Control.Exception qualified as IO
|
import Control.Exception qualified as IO
|
||||||
import Control.Monad.Extra
|
import Control.Monad.Extra
|
||||||
|
import Data.HashMap.Strict qualified as HashMap
|
||||||
import MiniJuvix.Pipeline
|
import MiniJuvix.Pipeline
|
||||||
import MiniJuvix.Prelude hiding (Doc)
|
import MiniJuvix.Prelude hiding (Doc)
|
||||||
import MiniJuvix.Prelude.Pretty hiding (Doc)
|
import MiniJuvix.Prelude.Pretty hiding (Doc)
|
||||||
|
import MiniJuvix.Syntax.Abstract.InfoTable qualified as Abstract
|
||||||
|
import MiniJuvix.Syntax.Abstract.Language qualified as Abstract
|
||||||
import MiniJuvix.Syntax.Abstract.Pretty qualified as Abstract
|
import MiniJuvix.Syntax.Abstract.Pretty qualified as Abstract
|
||||||
import MiniJuvix.Syntax.Concrete.Language qualified as M
|
import MiniJuvix.Syntax.Concrete.Language qualified as Concrete
|
||||||
import MiniJuvix.Syntax.Concrete.Parser qualified as Parser
|
import MiniJuvix.Syntax.Concrete.Parser qualified as Parser
|
||||||
import MiniJuvix.Syntax.Concrete.Scoped.Highlight qualified as Scoper
|
import MiniJuvix.Syntax.Concrete.Scoped.Highlight qualified as Scoper
|
||||||
import MiniJuvix.Syntax.Concrete.Scoped.InfoTable qualified as Scoper
|
import MiniJuvix.Syntax.Concrete.Scoped.InfoTable qualified as Scoper
|
||||||
|
import MiniJuvix.Syntax.Concrete.Scoped.Name qualified as Scoper
|
||||||
import MiniJuvix.Syntax.Concrete.Scoped.Pretty qualified as Scoper
|
import MiniJuvix.Syntax.Concrete.Scoped.Pretty qualified as Scoper
|
||||||
import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Html
|
import MiniJuvix.Syntax.Concrete.Scoped.Pretty.Html
|
||||||
import MiniJuvix.Syntax.Concrete.Scoped.Scoper qualified as Scoper
|
import MiniJuvix.Syntax.Concrete.Scoped.Scoper qualified as Scoper
|
||||||
@ -24,8 +28,8 @@ import MiniJuvix.Syntax.MicroJuvix.Pretty qualified as Micro
|
|||||||
import MiniJuvix.Syntax.MicroJuvix.TypeChecker qualified as MicroTyped
|
import MiniJuvix.Syntax.MicroJuvix.TypeChecker qualified as MicroTyped
|
||||||
import MiniJuvix.Syntax.MiniHaskell.Pretty qualified as MiniHaskell
|
import MiniJuvix.Syntax.MiniHaskell.Pretty qualified as MiniHaskell
|
||||||
import MiniJuvix.Syntax.MonoJuvix.Pretty qualified as Mono
|
import MiniJuvix.Syntax.MonoJuvix.Pretty qualified as Mono
|
||||||
import MiniJuvix.Termination qualified as T
|
import MiniJuvix.Termination qualified as Termination
|
||||||
import MiniJuvix.Termination.CallGraph qualified as A
|
import MiniJuvix.Termination.CallGraph qualified as Termination
|
||||||
import MiniJuvix.Translation.AbstractToMicroJuvix qualified as Micro
|
import MiniJuvix.Translation.AbstractToMicroJuvix qualified as Micro
|
||||||
import MiniJuvix.Translation.MicroJuvixToMonoJuvix qualified as Mono
|
import MiniJuvix.Translation.MicroJuvixToMonoJuvix qualified as Mono
|
||||||
import MiniJuvix.Translation.MonoJuvixToMiniHaskell qualified as MiniHaskell
|
import MiniJuvix.Translation.MonoJuvixToMiniHaskell qualified as MiniHaskell
|
||||||
@ -288,7 +292,7 @@ mkScopePrettyOptions g ScopeOptions {..} =
|
|||||||
Scoper._optInlineImports = _scopeInlineImports
|
Scoper._optInlineImports = _scopeInlineImports
|
||||||
}
|
}
|
||||||
|
|
||||||
parseModuleIO :: FilePath -> IO (M.Module 'M.Parsed 'M.ModuleTop)
|
parseModuleIO :: FilePath -> IO (Concrete.Module 'Concrete.Parsed 'Concrete.ModuleTop)
|
||||||
parseModuleIO = fromRightIO id . Parser.runModuleParserIO
|
parseModuleIO = fromRightIO id . Parser.runModuleParserIO
|
||||||
|
|
||||||
minijuvixYamlFile :: FilePath
|
minijuvixYamlFile :: FilePath
|
||||||
@ -433,40 +437,46 @@ runCLI cli = do
|
|||||||
results <- runIO (upToAbstract (getEntryPoint root opts))
|
results <- runIO (upToAbstract (getEntryPoint root opts))
|
||||||
let topModule = head (results ^. Abstract.resultModules)
|
let topModule = head (results ^. Abstract.resultModules)
|
||||||
infotable = results ^. Abstract.resultTable
|
infotable = results ^. Abstract.resultTable
|
||||||
callMap0 = T.buildCallMap infotable topModule
|
callMap0 = Termination.buildCallMap infotable topModule
|
||||||
callMap = case _callsFunctionNameFilter of
|
callMap = case _callsFunctionNameFilter of
|
||||||
Nothing -> callMap0
|
Nothing -> callMap0
|
||||||
Just f -> T.filterCallMap f callMap0
|
Just f -> Termination.filterCallMap f callMap0
|
||||||
opts' = T.callsPrettyOptions opts
|
opts' = Termination.callsPrettyOptions opts
|
||||||
renderStdOutAbs (Abstract.ppOut opts' callMap)
|
renderStdOutAbs (Abstract.ppOut opts' callMap)
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
Termination (CallGraph opts@CallGraphOptions {..}) -> do
|
Termination (CallGraph opts@CallGraphOptions {..}) -> do
|
||||||
results <- runIO (upToAbstract (getEntryPoint root opts))
|
results <- runIO (upToAbstract (getEntryPoint root opts))
|
||||||
let topModule = head (results ^. Abstract.resultModules)
|
let topModule = head (results ^. Abstract.resultModules)
|
||||||
infotable = results ^. Abstract.resultTable
|
infotable = results ^. Abstract.resultTable
|
||||||
callMap = T.buildCallMap infotable topModule
|
callMap = Termination.buildCallMap infotable topModule
|
||||||
opts' =
|
opts' =
|
||||||
Abstract.defaultOptions
|
Abstract.defaultOptions
|
||||||
{ Abstract._optShowNameId = globalOptions ^. globalShowNameIds
|
{ Abstract._optShowNameId = globalOptions ^. globalShowNameIds
|
||||||
}
|
}
|
||||||
completeGraph = T.completeCallGraph callMap
|
completeGraph = Termination.completeCallGraph callMap
|
||||||
filteredGraph = maybe completeGraph (`T.unsafeFilterGraph` completeGraph) _graphFunctionNameFilter
|
filteredGraph = maybe completeGraph (`Termination.unsafeFilterGraph` completeGraph) _graphFunctionNameFilter
|
||||||
rEdges = T.reflexiveEdges filteredGraph
|
rEdges = Termination.reflexiveEdges filteredGraph
|
||||||
|
recBehav = map Termination.recursiveBehaviour rEdges
|
||||||
recBehav = map T.recursiveBehaviour rEdges
|
|
||||||
renderStdOutAbs (Abstract.ppOut opts' filteredGraph)
|
renderStdOutAbs (Abstract.ppOut opts' filteredGraph)
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
forM_ recBehav $ \r -> do
|
forM_ recBehav $ \r -> do
|
||||||
let sopts =
|
let funName = Termination._recursiveBehaviourFun r
|
||||||
|
funRef = Abstract.FunctionRef (Scoper.unqualifiedSymbol funName)
|
||||||
|
funInfo = HashMap.lookupDefault impossible funRef (infotable ^. Abstract.infoFunctions)
|
||||||
|
markedTerminating = funInfo ^. (Abstract.functionInfoDef . Abstract.funDefTerminating)
|
||||||
|
sopts =
|
||||||
Scoper.defaultOptions
|
Scoper.defaultOptions
|
||||||
{ Scoper._optShowNameId = globalOptions ^. globalShowNameIds
|
{ Scoper._optShowNameId = globalOptions ^. globalShowNameIds
|
||||||
}
|
}
|
||||||
n = toAnsiText' (Scoper.ppOut sopts (A._recursiveBehaviourFun r))
|
n = toAnsiText' (Scoper.ppOut sopts funName)
|
||||||
renderStdOutAbs (Abstract.ppOut opts' r)
|
renderStdOutAbs (Abstract.ppOut opts' r)
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
case T.findOrder r of
|
if
|
||||||
Nothing -> putStrLn (n <> " Fails the termination checking") >> exitFailure
|
| markedTerminating -> putStrLn (n <> " Terminates by assumption ")
|
||||||
Just (T.LexOrder k) -> putStrLn (n <> " Terminates with order " <> show (toList k))
|
| otherwise ->
|
||||||
|
case Termination.findOrder r of
|
||||||
|
Nothing -> putStrLn (n <> " Fails the termination checking") >> exitFailure
|
||||||
|
Just (Termination.LexOrder k) -> putStrLn (n <> " Terminates with order " <> show (toList k))
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
|
@ -152,17 +152,8 @@ checkExpression ::
|
|||||||
checkExpression e =
|
checkExpression e =
|
||||||
viewCall e >>= \case
|
viewCall e >>= \case
|
||||||
Just c -> do
|
Just c -> do
|
||||||
h <- asks _infoFunctions
|
registerCall c
|
||||||
let fname = c ^. callRef
|
mapM_ (checkExpression . snd) (c ^. callArgs)
|
||||||
info = HashMap.lookupDefault impossible fname h
|
|
||||||
markedTerminating = info ^. (functionInfoDef . funDefTerminating)
|
|
||||||
if
|
|
||||||
| markedTerminating -> do
|
|
||||||
let cargs = map (\x -> (CallRow (Just (0, RLe)), snd x)) (c ^. callArgs)
|
|
||||||
registerCall $ FunCall fname cargs
|
|
||||||
| otherwise -> do
|
|
||||||
registerCall c
|
|
||||||
mapM_ (checkExpression . snd) (c ^. callArgs)
|
|
||||||
Nothing -> case e of
|
Nothing -> case e of
|
||||||
ExpressionApplication a -> checkApplication a
|
ExpressionApplication a -> checkApplication a
|
||||||
ExpressionFunction f -> checkFunction f
|
ExpressionFunction f -> checkFunction f
|
||||||
|
11
tests/positive/Termination/Mutual.mjuvix
Normal file
11
tests/positive/Termination/Mutual.mjuvix
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module Mutual;
|
||||||
|
|
||||||
|
axiom A : Type;
|
||||||
|
|
||||||
|
terminating f : A -> A -> A;
|
||||||
|
terminating g : A -> A -> A;
|
||||||
|
|
||||||
|
g x y := f x x;
|
||||||
|
f x y := g x (f x x);
|
||||||
|
|
||||||
|
end;
|
7
tests/positive/Termination/Undefined.mjuvix
Normal file
7
tests/positive/Termination/Undefined.mjuvix
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module Undefined;
|
||||||
|
|
||||||
|
axiom A : Type;
|
||||||
|
terminating undefined : A;
|
||||||
|
undefined := undefined;
|
||||||
|
|
||||||
|
end;
|
Loading…
Reference in New Issue
Block a user