Skip to content

Commit

Permalink
Add simple where-provenance to agda2hs
Browse files Browse the repository at this point in the history
By keeping track of which where-clause modules we have in scope, we can determine if a function if from a where-clause

Fixes #353
  • Loading branch information
anka-213 authored and jespercockx committed Sep 20, 2024
1 parent 424f93c commit 0e0b080
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/Agda2Hs/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ initCompileEnv tlm rewrites = CompileEnv
, minRecordName = Nothing
, locals = []
, compilingLocal = False
, whereModules = []
, copatternsEnabled = False
, rewrites = rewrites
, writeImports = True
Expand Down
16 changes: 6 additions & 10 deletions src/Agda2Hs/Compile/Function.hs
Original file line number Diff line number Diff line change
Expand Up @@ -222,20 +222,16 @@ compileClause' curModule projName x ty c@Clause{..} = do
/\ (curModule `isFatherModuleOf`) . qnameModule

children <- filter isWhereDecl <$> asks locals
whereDecls <- compileLocal $ mapM (getConstInfo >=> compileFun' True) children

-- Jesper, 2023-10-30: We should compile the body in the module of the
-- `where` declarations (if there are any) in order to drop the arguments
-- that correspond to the pattern variables of this clause from the calls to
-- the functions defined in the `where` block.
-- let inWhereModule = case children of
-- [] -> id
-- (c:_) -> withCurrentModule $ qnameModule c
-- TODO: remove this when Agda exposes where-provenance in 'Internal' syntax
let withWhereModule = case children of
[] -> id
(c:_) -> addWhereModule $ qnameModule c
whereDecls <- withWhereModule $ compileLocal $ mapM (getConstInfo >=> compileFun' True) children

let Just body = clauseBody
Just (unArg -> typ) = clauseType

hsBody <- compileTerm typ body
hsBody <- withWhereModule $ compileTerm typ body

let rhs = Hs.UnGuardedRhs () hsBody
whereBinds | null whereDecls = Nothing
Expand Down
6 changes: 3 additions & 3 deletions src/Agda2Hs/Compile/Term.hs
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,17 @@ compileDef f ty args =

currentMod <- currentModule
let defMod = qnameModule f

defIsClass <- isClassModule defMod
-- TODO: simplify this when Agda exposes where-provenance in 'Internal' syntax
isLocal <- asks compilingLocal
localDefs <- asks locals -- If we're calling into a where-clause
outerWhereModules <- asks whereModules -- W

(ty', args') <-

-- if the function is called from the same module it's defined in,
-- we drop the module parameters
-- NOTE(flupe): in the future we're not always gonna be erasing module parameters
if f `elem` localDefs || (isLocal || defIsClass) && (mnameToList defMod `isPrefixOf` mnameToList currentMod) then do
if defMod `elem` outerWhereModules || defIsClass && (mnameToList defMod `isPrefixOf` mnameToList currentMod) then do
npars <- size <$> lookupSection defMod
let (pars, rest) = splitAt npars args
ty' <- piApplyM ty pars
Expand Down
2 changes: 2 additions & 0 deletions src/Agda2Hs/Compile/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ data CompileEnv = CompileEnv
-- ^ keeps track of the current clause's where declarations
, compilingLocal :: Bool
-- ^ whether we are currently compiling a where clause or pattern-matching lambda
, whereModules :: [ModuleName]
-- ^ the where-blocks currently in scope. Hack until Agda adds where-prominence
, copatternsEnabled :: Bool
-- ^ whether copatterns should be allowed when compiling patterns
, rewrites :: SpecialRules
Expand Down
3 changes: 3 additions & 0 deletions src/Agda2Hs/Compile/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ checkInstance u = do
compileLocal :: C a -> C a
compileLocal = local $ \e -> e { compilingLocal = True }

addWhereModule :: ModuleName -> C a -> C a
addWhereModule mName = local $ \e -> e { whereModules = mName : whereModules e }

modifyLCase :: (Int -> Int) -> CompileState -> CompileState
modifyLCase f (CompileState {lcaseUsed = n}) = CompileState {lcaseUsed = f n}

Expand Down
6 changes: 2 additions & 4 deletions test/Issue353.agda
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ module _ (b : Bool) where
bar = foo True 0
{-# COMPILE AGDA2HS bar #-}

-- Still broken, since they are actually the same module here
-- would generate baz = bar in haskell
baz : Bool
baz = bar
{-# COMPILE AGDA2HS baz #-}

-- Still broken, because we cant differentiate this from where-blocks
callFromNested : Bool
callFromNested = nested
where nested = bar
-- {-# COMPILE AGDA2HS callFromNested #-}
{-# COMPILE AGDA2HS callFromNested #-}

-- The check is needed both for instance declarations and where-clauses
6 changes: 6 additions & 0 deletions test/golden/Issue353.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ bar b = foo True 0
baz :: Bool -> Bool
baz b = bar b

callFromNested :: Bool -> Bool
callFromNested b = nested
where
nested :: Bool
nested = bar b

0 comments on commit 0e0b080

Please sign in to comment.