Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add errors to the Core pipeline and check GEB prerequisites #1871

Merged
merged 11 commits into from
Mar 20, 2023
7 changes: 5 additions & 2 deletions app/Commands/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ runCommand opts@CompileOptions {..} = do
writeCoreFile :: (Members '[Embed IO, App] r) => Compile.PipelineArg -> Sem r ()
writeCoreFile Compile.PipelineArg {..} = do
coreFile <- Compile.outputFile _pipelineArgOptions _pipelineArgFile
let tab = Core.toEval _pipelineArgInfoTable
embed $ TIO.writeFile (toFilePath coreFile) (show $ Core.ppOutDefault (Core.disambiguateNames tab))
r <- runError @JuvixError $ Core.toEval _pipelineArgInfoTable
case r of
Left e -> exitJuvixError e
Right tab ->
embed $ TIO.writeFile (toFilePath coreFile) (show $ Core.ppOutDefault (Core.disambiguateNames tab))
3 changes: 2 additions & 1 deletion app/Commands/Dev/Core/Asm.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ runCommand opts = do
inputFile :: Path Abs File <- someBaseToAbs' sinputFile
s' <- embed (readFile $ toFilePath inputFile)
tab <- getRight (mapLeft JuvixError (Core.runParserMain inputFile Core.emptyInfoTable s'))
let tab' = Asm.fromCore $ Stripped.fromCore (Core.toStripped tab)
r <- runError @JuvixError $ Core.toStripped tab
tab' <- Asm.fromCore . Stripped.fromCore <$> getRight r
if
| project opts ^. coreAsmPrint ->
renderStdOut (Asm.ppOutDefault tab' tab')
Expand Down
5 changes: 3 additions & 2 deletions app/Commands/Dev/Core/Compile/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ runGebPipeline PipelineArg {..} = do
runAsmPipeline :: (Members '[Embed IO, App] r) => PipelineArg -> Sem r ()
runAsmPipeline PipelineArg {..} = do
asmFile <- Compile.outputFile _pipelineArgOptions _pipelineArgFile
let tab' = coreToAsm _pipelineArgInfoTable
code = Pretty.ppPrint tab' tab'
r <- runError @JuvixError (coreToAsm _pipelineArgInfoTable)
tab' <- getRight r
let code = Pretty.ppPrint tab' tab'
embed $ TIO.writeFile (toFilePath asmFile) code
11 changes: 5 additions & 6 deletions app/Commands/Dev/Core/FromConcrete.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ runCommand :: forall r. Members '[Embed IO, App] r => CoreFromConcreteOptions ->
runCommand localOpts = do
tab <- (^. coreResultTable) <$> runPipeline (localOpts ^. coreFromConcreteInputFile) upToCore
path :: Path Abs File <- someBaseToAbs' (localOpts ^. coreFromConcreteInputFile . pathPath)
let tab0 :: InfoTable = Core.applyTransformations (project localOpts ^. coreFromConcreteTransformations) tab
tab' :: InfoTable = if localOpts ^. coreFromConcreteNoDisambiguate then tab0 else disambiguateNames tab0

r <- runError @JuvixError $ Core.applyTransformations (project localOpts ^. coreFromConcreteTransformations) tab
tab0 :: InfoTable <- getRight r
let tab' :: InfoTable = if localOpts ^. coreFromConcreteNoDisambiguate then tab0 else disambiguateNames tab0
inInputModule :: IdentifierInfo -> Bool
inInputModule x
| localOpts ^. coreFromConcreteFilter = (== Just path) . (^? identifierLocation . _Just . intervalFile) $ x
| otherwise = True
inInputModule _ | not (localOpts ^. coreFromConcreteFilter) = True
inInputModule x = (== Just path) . (^? identifierLocation . _Just . intervalFile) $ x

mainIdens :: [IdentifierInfo] =
sortOn
Expand Down
5 changes: 3 additions & 2 deletions app/Commands/Dev/Core/Read.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ runCommand opts = do
inputFile :: Path Abs File <- someBaseToAbs' sinputFile
s' <- embed . readFile . toFilePath $ inputFile
tab <- getRight (mapLeft JuvixError (Core.runParserMain inputFile Core.emptyInfoTable s'))
let tab0 = Core.applyTransformations (project opts ^. coreReadTransformations) tab
tab' = if project opts ^. coreReadNoDisambiguate then tab0 else Core.disambiguateNames tab0
r <- runError @JuvixError $ Core.applyTransformations (project opts ^. coreReadTransformations) tab
tab0 <- getRight $ mapLeft JuvixError r
let tab' = if project opts ^. coreReadNoDisambiguate then tab0 else Core.disambiguateNames tab0
embed (Scoper.scopeTrace tab')
unless (project opts ^. coreReadNoPrint) $ do
renderStdOut (Core.ppOut opts tab')
Expand Down
5 changes: 3 additions & 2 deletions app/Commands/Dev/Core/Strip.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ runCommand :: forall r a. (Members '[Embed IO, App] r, CanonicalProjection a Cor
runCommand opts = do
inputFile :: Path Abs File <- someBaseToAbs' sinputFile
s' <- embed (readFile $ toFilePath inputFile)
tab <- getRight (mapLeft JuvixError (Core.runParserMain inputFile Core.emptyInfoTable s'))
let tab' = Stripped.fromCore (Core.toStripped tab)
(tab, _) <- getRight (mapLeft JuvixError (Core.runParser inputFile Core.emptyInfoTable s'))
r <- runError @JuvixError (Core.toStripped tab)
tab' <- getRight $ mapLeft JuvixError $ mapRight Stripped.fromCore r
unless (project opts ^. coreStripNoPrint) $ do
renderStdOut (Core.ppOut opts tab')
where
Expand Down
5 changes: 3 additions & 2 deletions app/Commands/Eval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import Juvix.Compiler.Core.Pipeline qualified as Core
runCommand :: (Members '[Embed IO, App] r) => EvalOptions -> Sem r ()
runCommand opts@EvalOptions {..} = do
Core.CoreResult {..} <- runPipeline _evalInputFile upToCore
let tab = Core.toEval _coreResultTable
evalNode =
r <- runError @JuvixError $ Core.toEval _coreResultTable
tab <- getRight r
let evalNode =
if
| isJust (_evalSymbolName) -> getNode' tab (selInfo tab)
| otherwise -> getNode' tab (mainInfo tab)
Expand Down
6 changes: 4 additions & 2 deletions app/Commands/Repl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,10 @@ runCommand opts = do
where
eval :: Core.Node -> Repl (Either JuvixError Core.Node)
eval n =
let (tab', n') = runTransformations (Core.toEvalTransformations ++ opts ^. replTransformations) infoTable n
in liftIO $
case run $ runError @JuvixError $ runTransformations (Core.toEvalTransformations ++ opts ^. replTransformations) infoTable n of
Left err -> return $ Left err
Right (tab', n') ->
liftIO $
mapLeft
(JuvixError @Core.CoreError)
<$> doEvalIO False defaultLoc tab' n'
Expand Down
138 changes: 72 additions & 66 deletions src/Juvix/Compiler/Backend/Geb/Translation/FromCore.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Data.HashMap.Strict qualified as HashMap
import Data.List qualified as List
import Juvix.Compiler.Backend.Geb.Extra
import Juvix.Compiler.Backend.Geb.Language
import Juvix.Compiler.Core.Data.IdentDependencyInfo qualified as Core
import Juvix.Compiler.Core.Data.InfoTable qualified as Core
import Juvix.Compiler.Core.Extra qualified as Core
import Juvix.Compiler.Core.Info.TypeInfo qualified as Info
Expand Down Expand Up @@ -184,72 +185,8 @@ fromCore tab = case tab ^. Core.infoMain of
Core.OpIntDiv -> convertBinop OpDiv _builtinAppArgs
Core.OpIntMod -> convertBinop OpMod _builtinAppArgs
Core.OpIntLt -> convertBinop OpLt _builtinAppArgs
Core.OpIntLe -> case _builtinAppArgs of
[arg1, arg2] -> do
arg1' <- convertNode arg1
arg2' <- convertNode arg2
let le =
MorphismLambda
Lambda
{ _lambdaVarType = ObjectInteger,
_lambdaBodyType =
ObjectHom
Hom
{ _homDomain = ObjectInteger,
_homCodomain = objectBool
},
_lambdaBody =
MorphismLambda
Lambda
{ _lambdaVarType = ObjectInteger,
_lambdaBodyType = objectBool,
_lambdaBody =
mkOr
( MorphismBinop
Binop
{ _binopOpcode = OpLt,
_binopLeft = MorphismVar Var {_varIndex = 1},
_binopRight = MorphismVar Var {_varIndex = 0}
}
)
( MorphismBinop
Binop
{ _binopOpcode = OpEq,
_binopLeft = MorphismVar Var {_varIndex = 1},
_binopRight = MorphismVar Var {_varIndex = 0}
}
)
}
}
in return $
MorphismApplication
Application
{ _applicationDomainType = ObjectInteger,
_applicationCodomainType =
ObjectHom
Hom
{ _homDomain = ObjectInteger,
_homCodomain = objectBool
},
_applicationLeft =
MorphismApplication
Application
{ _applicationDomainType = ObjectInteger,
_applicationCodomainType = objectBool,
_applicationLeft = le,
_applicationRight = arg2'
},
_applicationRight = arg1'
}
_ ->
error "wrong builtin application argument number"
Core.OpEq ->
case _builtinAppArgs of
arg : _
| Info.getNodeType arg == Core.mkTypeInteger' ->
convertBinop OpEq _builtinAppArgs
_ ->
error "unsupported equality argument types"
Core.OpIntLe -> convertOpIntLe _builtinAppArgs
Core.OpEq -> convertOpEq _builtinAppArgs
_ ->
unsupported

Expand All @@ -268,6 +205,75 @@ fromCore tab = case tab ^. Core.infoMain of
_ ->
error "wrong builtin application argument number"

convertOpIntLe :: [Core.Node] -> Trans Morphism
convertOpIntLe = \case
[arg1, arg2] -> do
arg1' <- convertNode arg1
arg2' <- convertNode arg2
let le =
MorphismLambda
Lambda
{ _lambdaVarType = ObjectInteger,
_lambdaBodyType =
ObjectHom
Hom
{ _homDomain = ObjectInteger,
_homCodomain = objectBool
},
_lambdaBody =
MorphismLambda
Lambda
{ _lambdaVarType = ObjectInteger,
_lambdaBodyType = objectBool,
_lambdaBody =
mkOr
( MorphismBinop
Binop
{ _binopOpcode = OpLt,
_binopLeft = MorphismVar Var {_varIndex = 1},
_binopRight = MorphismVar Var {_varIndex = 0}
}
)
( MorphismBinop
Binop
{ _binopOpcode = OpEq,
_binopLeft = MorphismVar Var {_varIndex = 1},
_binopRight = MorphismVar Var {_varIndex = 0}
}
)
}
}
in return $
MorphismApplication
Application
{ _applicationDomainType = ObjectInteger,
_applicationCodomainType =
ObjectHom
Hom
{ _homDomain = ObjectInteger,
_homCodomain = objectBool
},
_applicationLeft =
MorphismApplication
Application
{ _applicationDomainType = ObjectInteger,
_applicationCodomainType = objectBool,
_applicationLeft = le,
_applicationRight = arg2'
},
_applicationRight = arg1'
}
_ ->
error "wrong builtin application argument number"

convertOpEq :: [Core.Node] -> Trans Morphism
convertOpEq args = case args of
arg : _
| Info.getNodeType arg == Core.mkTypeInteger' ->
convertBinop OpEq args
_ ->
error "unsupported equality argument types"

convertConstr :: Core.Constr -> Trans Morphism
convertConstr Core.Constr {..} = do
args <- convertProduct _constrArgs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Juvix.Compiler.Core.Extra.IdentDependencyInfo where
module Juvix.Compiler.Core.Data.IdentDependencyInfo where

import Data.HashMap.Strict qualified as HashMap
import Data.HashSet qualified as HashSet
Expand Down
3 changes: 2 additions & 1 deletion src/Juvix/Compiler/Core/Data/TransformationId.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ data TransformationId
| MatchToCase
| EtaExpandApps
| DisambiguateNames
| CheckGeb
deriving stock (Data, Bounded, Enum)

data PipelineId
Expand Down Expand Up @@ -47,7 +48,7 @@ toStrippedTransformations =
toEvalTransformations ++ [LambdaLetRecLifting, TopEtaExpand, MoveApps, RemoveTypeArgs]

toGebTransformations :: [TransformationId]
toGebTransformations = toEvalTransformations ++ [UnrollRecursion, ComputeTypeInfo]
toGebTransformations = toEvalTransformations ++ [LetRecLifting, CheckGeb, UnrollRecursion, ComputeTypeInfo]

toEvalTransformations :: [TransformationId]
toEvalTransformations = [EtaExpandApps, MatchToCase, NatToInt, ConvertBuiltinTypes]
Expand Down
4 changes: 4 additions & 0 deletions src/Juvix/Compiler/Core/Data/TransformationId/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ transformationText = \case
ComputeTypeInfo -> strComputeTypeInfo
UnrollRecursion -> strUnrollRecursion
DisambiguateNames -> strDisambiguateNames
CheckGeb -> strCheckGeb

parsePipeline :: MonadParsec e Text m => m PipelineId
parsePipeline = choice [symbol (pipelineText t) $> t | t <- allElements]
Expand Down Expand Up @@ -137,3 +138,6 @@ strUnrollRecursion = "unroll-recursion"

strDisambiguateNames :: Text
strDisambiguateNames = "disambiguate-names"

strCheckGeb :: Text
strCheckGeb = "check-geb"
2 changes: 1 addition & 1 deletion src/Juvix/Compiler/Core/Evaluator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ catchEvalErrorIO loc ma =
toCoreError :: Location -> EvalError -> CoreError
toCoreError loc (EvalError {..}) =
CoreError
{ _coreErrorMsg = mappend "evaluation error: " _evalErrorMsg,
{ _coreErrorMsg = "evaluation error: " <> _evalErrorMsg,
_coreErrorNode = _evalErrorNode,
_coreErrorLoc = fromMaybe loc (lookupLocation =<< _evalErrorNode)
}
2 changes: 0 additions & 2 deletions src/Juvix/Compiler/Core/Extra.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module Juvix.Compiler.Core.Extra
( module Juvix.Compiler.Core.Extra.Utils,
module Juvix.Compiler.Core.Extra.IdentDependencyInfo,
)
where

import Juvix.Compiler.Core.Extra.IdentDependencyInfo
import Juvix.Compiler.Core.Extra.Utils
8 changes: 8 additions & 0 deletions src/Juvix/Compiler/Core/Extra/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ import Juvix.Compiler.Core.Language
isClosed :: Node -> Bool
isClosed = not . has freeVars

isTypeConstr :: InfoTable -> Type -> Bool
isTypeConstr tab ty = case typeTarget ty of
NUniv {} ->
True
NIdt Ident {..} ->
isTypeConstr tab (fromJust $ HashMap.lookup _identSymbol (tab ^. identContext))
_ -> False

freeVarsSorted :: Node -> Set Var
freeVarsSorted n = Set.fromList (n ^.. freeVars)

Expand Down
6 changes: 3 additions & 3 deletions src/Juvix/Compiler/Core/Pipeline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import Juvix.Compiler.Core.Data.InfoTable
import Juvix.Compiler.Core.Transformation

-- | Perform transformations on Core necessary for efficient evaluation
toEval :: InfoTable -> InfoTable
toEval :: Member (Error JuvixError) r => InfoTable -> Sem r InfoTable
toEval = applyTransformations toEvalTransformations

-- | Perform transformations on Core necessary before the translation to
-- Core.Stripped
toStripped :: InfoTable -> InfoTable
toStripped :: Member (Error JuvixError) r => InfoTable -> Sem r InfoTable
toStripped = applyTransformations toStrippedTransformations

-- | Perform transformations on Core necessary before the translation to GEB
toGeb :: InfoTable -> InfoTable
toGeb :: Member (Error JuvixError) r => InfoTable -> Sem r InfoTable
toGeb = applyTransformations toGebTransformations
35 changes: 19 additions & 16 deletions src/Juvix/Compiler/Core/Transformation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ module Juvix.Compiler.Core.Transformation
where

import Juvix.Compiler.Core.Data.TransformationId
import Juvix.Compiler.Core.Error
import Juvix.Compiler.Core.Transformation.Base
import Juvix.Compiler.Core.Transformation.CheckGeb
import Juvix.Compiler.Core.Transformation.ComputeTypeInfo
import Juvix.Compiler.Core.Transformation.ConvertBuiltinTypes
import Juvix.Compiler.Core.Transformation.DisambiguateNames
Expand All @@ -23,21 +25,22 @@ import Juvix.Compiler.Core.Transformation.RemoveTypeArgs
import Juvix.Compiler.Core.Transformation.TopEtaExpand
import Juvix.Compiler.Core.Transformation.UnrollRecursion

applyTransformations :: [TransformationId] -> InfoTable -> InfoTable
applyTransformations ts tbl = foldl' (flip appTrans) tbl ts
applyTransformations :: forall r. Member (Error JuvixError) r => [TransformationId] -> InfoTable -> Sem r InfoTable
applyTransformations ts tbl = foldl' (\acc tid -> acc >>= appTrans tid) (return tbl) ts
where
appTrans :: TransformationId -> InfoTable -> InfoTable
appTrans :: TransformationId -> InfoTable -> Sem r InfoTable
appTrans = \case
LambdaLetRecLifting -> lambdaLetRecLifting
LetRecLifting -> letRecLifting
Identity -> identity
TopEtaExpand -> topEtaExpand
RemoveTypeArgs -> removeTypeArgs
MoveApps -> moveApps
NatToInt -> natToInt
ConvertBuiltinTypes -> convertBuiltinTypes
ComputeTypeInfo -> computeTypeInfo
UnrollRecursion -> unrollRecursion
MatchToCase -> matchToCase
EtaExpandApps -> etaExpansionApps
DisambiguateNames -> disambiguateNames
LambdaLetRecLifting -> return . lambdaLetRecLifting
LetRecLifting -> return . letRecLifting
Identity -> return . identity
TopEtaExpand -> return . topEtaExpand
RemoveTypeArgs -> return . removeTypeArgs
MoveApps -> return . moveApps
NatToInt -> return . natToInt
ConvertBuiltinTypes -> return . convertBuiltinTypes
ComputeTypeInfo -> return . computeTypeInfo
UnrollRecursion -> return . unrollRecursion
MatchToCase -> return . matchToCase
EtaExpandApps -> return . etaExpansionApps
DisambiguateNames -> return . disambiguateNames
CheckGeb -> mapError (JuvixError @CoreError) . checkGeb
Loading