Skip to content

Commit

Permalink
Add compiler flag for effect encapsulation #211
Browse files Browse the repository at this point in the history
  • Loading branch information
Maja Reichert committed Sep 28, 2020
2 parents 0d7f489 + 46da67a commit 67bf20c
Show file tree
Hide file tree
Showing 20 changed files with 591 additions and 29 deletions.
15 changes: 14 additions & 1 deletion base/Prelude.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Metadata #
##############################################################################

version = 4
version = 5
module-name = 'Prelude'
library-name = 'Base'
exported-types = [
Expand Down Expand Up @@ -83,6 +83,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Bool -> Prelude.Bool -> Prelude.Bool'
Expand All @@ -92,6 +93,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

##############################################################################
# Integer #
Expand All @@ -112,6 +114,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Integer'
Expand All @@ -121,6 +124,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Integer'
Expand All @@ -130,6 +134,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Integer'
Expand All @@ -139,6 +144,7 @@ exported-values = [
arity = 2
effects = ['Partiality']
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -148,6 +154,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -157,6 +164,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -166,6 +174,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -175,6 +184,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -184,6 +194,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer -> Prelude.Bool'
Expand All @@ -193,6 +204,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = false

[[functions]]
haskell-type = 'Prelude.Integer -> Prelude.Integer'
Expand All @@ -202,6 +214,7 @@ exported-values = [
arity = 1
effects = []
needs-free-args = true
encapsulates-effects = false

##############################################################################
# Lists #
Expand Down
8 changes: 7 additions & 1 deletion base/Test/QuickCheck.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Metadata #
##############################################################################

version = 4
version = 5
module-name = 'Test.QuickCheck'
library-name = 'Base'
exported-types = [
Expand Down Expand Up @@ -45,6 +45,7 @@ exported-values = [
arity = 1
effects = []
needs-free-args = true
encapsulates-effects = true

##############################################################################
# Operators #
Expand All @@ -58,6 +59,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = true

[[functions]]
haskell-type = 'a -> a -> Test.QuickCheck.Property'
Expand All @@ -67,6 +69,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = true

[[functions]]
haskell-type = 'a -> a -> Test.QuickCheck.Property'
Expand All @@ -76,6 +79,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = true

[[functions]]
haskell-type = 'Test.QuickCheck.Property -> Test.QuickCheck.Property -> Test.QuickCheck.Property'
Expand All @@ -85,6 +89,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = true

[[functions]]
haskell-type = 'Test.QuickCheck.Property -> Test.QuickCheck.Property -> Test.QuickCheck.Property'
Expand All @@ -94,6 +99,7 @@ exported-values = [
arity = 2
effects = []
needs-free-args = true
encapsulates-effects = true

##############################################################################
# Imported from `Prelude` #
Expand Down
3 changes: 3 additions & 0 deletions free-compiler.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ library freec-internal
, FreeC.Pass.EffectAnalysisPass
, FreeC.Pass.EtaConversionPass
, FreeC.Pass.ExportPass
, FreeC.Pass.FlattenExprPass
, FreeC.Pass.ImplicitPreludePass
, FreeC.Pass.ImportPass
, FreeC.Pass.KindCheckPass
Expand All @@ -183,6 +184,7 @@ library freec-internal
, FreeC.Pass.ResolverPass
, FreeC.Pass.TypeInferencePass
, FreeC.Pass.TypeSignaturePass
, FreeC.Pass.SharingAnalysisPass
, FreeC.Pipeline
, FreeC.Pretty
, FreeC.Util.Config
Expand Down Expand Up @@ -258,6 +260,7 @@ test-suite freec-unit-tests
, FreeC.Pass.EffectAnalysisPassTests
, FreeC.Pass.EtaConversionPassTests
, FreeC.Pass.ExportPassTests
, FreeC.Pass.FlattenExprPassTests
, FreeC.Pass.KindCheckPassTests
, FreeC.Pass.LetSortPassTests
, FreeC.Pass.ResolverPassTests
Expand Down
12 changes: 7 additions & 5 deletions src/exe/FreeC/Backend.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import FreeC.Backend.Agda.Pretty ()
import qualified FreeC.Backend.Coq.Base as Coq.Base
import qualified FreeC.Backend.Coq.Converter.Module as Coq.Converter
import FreeC.Backend.Coq.Pretty ()
import FreeC.IR.Strip ( stripExprType )
import qualified FreeC.IR.Syntax as IR
import FreeC.Monad.Application
import FreeC.Pretty ( showPretty )
Expand Down Expand Up @@ -51,11 +52,12 @@ defaultBackend = backendName coqBackend
-------------------------------------------------------------------------------
-- | A dummy backend that just pretty prints the IR.
irBackend :: Backend
irBackend = Backend { backendName = "ir"
, backendConvertModule = return . showPretty
, backendFileExtension = "ir"
, backendSpecialAction = return ()
}
irBackend = Backend
{ backendName = "ir"
, backendConvertModule = return . showPretty . stripExprType
, backendFileExtension = "ir"
, backendSpecialAction = return ()
}

-------------------------------------------------------------------------------
-- Coq Backend --
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,10 @@ transformRecFuncDecl
-- Even though we know the type of the original and additional arguments
-- the return type is unknown, since the right-hand side of @case@
-- expressions is not annotated.
-- The helper function uses all effects that are used by the original
-- The helper function uses all effects that are used by the original
-- function.
freeArgsNeeded <- inEnv $ needsFreeArgs name
encEffects <- inEnv $ encapsulatesEffects name
effects <- inEnv $ lookupEffects name
_entry <- renameAndAddEntry
$ FuncEntry
Expand All @@ -175,6 +176,7 @@ transformRecFuncDecl
, entryStrictArgs = map IR.varPatIsStrict helperArgs
, entryReturnType = fromJust helperReturnType
, entryNeedsFreeArgs = freeArgsNeeded
, entryEncapsulatesEffects = encEffects
, entryEffects = effects
, entryName = helperName
, entryIdent = undefined -- filled by renamer
Expand Down
9 changes: 9 additions & 0 deletions src/lib/FreeC/Environment.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module FreeC.Environment
, addEffectsToEntry
-- * Looking up Entries from the Environment
, lookupEntry
, encapsulatesEffects
, isFunction
, isVariable
, isPureVar
Expand Down Expand Up @@ -158,6 +159,14 @@ addEffectsToEntry name effects env = case lookupEntry IR.ValueScope name env of
-------------------------------------------------------------------------------
-- Looking up Entries from the Environment --
-------------------------------------------------------------------------------

-- | Tests whether the function with the given name encapsulates effects.
--
-- Returns @False@ if there is no such function.
encapsulatesEffects :: IR.QName -> Environment -> Bool
encapsulatesEffects = maybe False (isFuncEntry .&&. entryEncapsulatesEffects)
.: lookupEntry IR.ValueScope

-- | Looks up the entry with the given original name in the given scope of
-- the given environment.
lookupEntry :: IR.Scope -> IR.QName -> Environment -> Maybe EnvEntry
Expand Down
2 changes: 2 additions & 0 deletions src/lib/FreeC/Environment/Entry.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ data EnvEntry
, entryNeedsFreeArgs :: Bool
-- ^ Whether the arguments of the @Free@ monad need to be
-- passed to the function.
, entryEncapsulatesEffects :: Bool
-- ^ Whether the function should encapsulate effects.
, entryEffects :: [Effect]
-- ^ The effects of the function, i.e. which type classes are needed
-- during the translation.
Expand Down
5 changes: 4 additions & 1 deletion src/lib/FreeC/Environment/ModuleInterface/Decoder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ import FreeC.Util.Config
-- a breaking change is made to the encoder or decoder, it is less likely
-- that the implementation of the corresponding change in the other module
-- is forgotten.
-- TODO bump version number
moduleInterfaceFileFormatVersion :: Integer
moduleInterfaceFileFormatVersion = 4
moduleInterfaceFileFormatVersion = 5

-- | Parses an IR AST node from an Aeson string.
parseAesonIR :: Parseable a => Text -> Aeson.Parser a
Expand Down Expand Up @@ -271,6 +272,7 @@ instance Aeson.FromJSON ModuleInterface where
haskellType <- obj .: "haskell-type"
effects <- obj .: "effects"
freeArgsNeeded <- obj .: "needs-free-args"
effectsEncapsulated <- obj .: "encapsulates-effects"
coqName <- obj .: "coq-name"
agdaName <- obj .: "agda-name"
-- TODO this does not work with vanishing type arguments.
Expand All @@ -284,6 +286,7 @@ instance Aeson.FromJSON ModuleInterface where
, entryStrictArgs = replicate arity False
, entryReturnType = returnType
, entryNeedsFreeArgs = freeArgsNeeded
, entryEncapsulatesEffects = effectsEncapsulated
, entryEffects = effects
, entryIdent = coqName
, entryAgdaIdent = agdaName
Expand Down
6 changes: 5 additions & 1 deletion src/lib/FreeC/Environment/ModuleInterface/Encoder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import FreeC.Util.Config
-- that the implementation of the corresponding change in the other module
-- is forgotten.
moduleInterfaceFileFormatVersion :: Integer
moduleInterfaceFileFormatVersion = 4
moduleInterfaceFileFormatVersion = 5

instance Aeson.ToJSON IR.QName where
toJSON = Aeson.toJSON . showPretty
Expand Down Expand Up @@ -124,6 +124,7 @@ encodeEntry entry
, "arity" .= arity
, "effects" .= effects
, "needs-free-args" .= freeArgsNeeded
, "encapsulates-effects" .= effectsEncapsulated
]
| otherwise = error "encodeEntry: Cannot serialize (type) variable entry."
where
Expand Down Expand Up @@ -156,6 +157,9 @@ encodeEntry entry
freeArgsNeeded :: Aeson.Value
freeArgsNeeded = Aeson.toJSON (entryNeedsFreeArgs entry)

effectsEncapsulated :: Aeson.Value
effectsEncapsulated = Aeson.toJSON (entryEncapsulatesEffects entry)

haskellType :: Aeson.Value
haskellType = Aeson.toJSON (foldr (IR.FuncType NoSrcSpan)
(entryReturnType entry) (entryArgTypes entry))
Expand Down
4 changes: 4 additions & 0 deletions src/lib/FreeC/IR/Strip.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import qualified FreeC.IR.Syntax as IR
class StripExprType node where
stripExprType :: node -> node

instance StripExprType IR.Module where
stripExprType ast
= ast { IR.modFuncDecls = map stripExprType (IR.modFuncDecls ast) }

-- | Strips the expression type annotations from function declarations.
instance StripExprType IR.FuncDecl where
stripExprType funcDecl
Expand Down
Loading

0 comments on commit 67bf20c

Please sign in to comment.