Skip to content

Commit c6bb603

Browse files
committed
add flag for disabling blocks translation
1 parent 426d10c commit c6bb603

File tree

7 files changed

+140
-113
lines changed

7 files changed

+140
-113
lines changed

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
agda2lambox -o build test/$*.agda
33

44
%.wasm: %.ast
5-
lbox wasm -o demo/$*.wasm build/$*.ast
5+
lbox wasm -o demo/$@ build/$*.ast
6+
7+
%.elm: %.typed
8+
lbox elm -o demo/$@ build/$*.ast
9+
10+
%.rs: %.typed
11+
lbox rust -o demo/$@ build/$*.ast
612

713
%.v:
814
agda2lambox -o build --rocq test/$*.agda
915

1016
%.typed:
11-
agda2lambox -o build --typed test/$*.agda
17+
agda2lambox -o build --typed --no-blocks test/$*.agda

src/Agda2Lambox/Compile.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import LambdaBox.Env (GlobalEnv(..), GlobalDecl(..), ConstantBody(..))
3434

3535

3636
-- | Compile the given names into to a λ□ environment.
37-
compile :: Target t -> [QName] -> TCM (GlobalEnv t)
37+
compile :: Target t -> [QName] -> CompileM (GlobalEnv t)
3838
compile t qs = do
3939
items <- compileLoop (compileDefinition t) qs
4040
pure $ GlobalEnv $ map itemToEntry items

src/Agda2Lambox/Compile/Monad.hs

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,48 @@
1-
{-# LANGUAGE DerivingVia, GeneralizedNewtypeDeriving, OverloadedStrings, DeriveFunctor, DeriveTraversable #-}
1+
{-# LANGUAGE DerivingVia, GeneralizedNewtypeDeriving, OverloadedStrings, DeriveFunctor, DeriveTraversable, NamedFieldPuns #-}
22
-- | Compilation monad.
33
module Agda2Lambox.Compile.Monad
44
( CompileM
5+
, CompileEnv(..)
56
, requireDef
7+
, runCompile
68
, compileLoop
79
, genericError
810
, genericDocError
911
, internalError
1012
, CompiledItem(..)
13+
, ask
14+
, asks
1115
) where
1216

1317
import Control.Monad ( unless )
18+
import Control.Monad.Reader
1419
import Control.Monad.State
1520
import Control.Monad.IO.Class ( MonadIO )
21+
import Data.Bifunctor ( bimap )
1622
import Data.Set ( Set )
1723
import Data.Set qualified as Set
24+
import Data.Set qualified as Set
25+
import Data.Map qualified as Map
26+
import Data.Maybe ( catMaybes )
1827

1928
import Agda.Syntax.Abstract (QName)
2029
import Agda.Compiler.Backend (getConstInfo, PureTCM, HasConstInfo, HasBuiltins, canonicalName)
2130
import Agda.TypeChecking.Monad (MonadDebug, MonadTrace, MonadAddContext)
2231
import Agda.TypeChecking.Monad.Debug (MonadDebug, reportSDoc)
2332
import Agda.TypeChecking.Monad.Base hiding (initState)
2433
import Agda.Utils.List ( mcons )
34+
import Agda.Utils.Monad ( unlessM )
2535
import Agda.TypeChecking.Pretty
2636
import Control.Monad.Error.Class (MonadError)
2737

28-
import Agda2Lambox.Compile.Utils (CompiledItem(..), topoSort)
38+
import Data.Foldable (traverse_)
39+
40+
-- | Compilation Environment
41+
data CompileEnv = CompileEnv
42+
{ noBlocks :: Bool
43+
-- ^ When set to 'True', constructors take no arguments,
44+
-- and regular function application is used instead.
45+
}
2946

3047
-- | Backend compilation state.
3148
data CompileState = CompileState
@@ -37,20 +54,21 @@ data CompileState = CompileState
3754
-- ^ (Locally) required definitions.
3855
}
3956

40-
-- | Initial compile state, with a set of names required for compilation.
41-
initState :: [QName] -> CompileState
42-
initState qs = CompileState
43-
{ seenDefs = Set.fromList qs
44-
, compileStack = qs
57+
-- Initial compile state.
58+
initState :: CompileState
59+
initState = CompileState
60+
{ seenDefs = Set.empty
61+
, compileStack = []
4562
, requiredDefs = Set.empty
4663
}
4764

4865
-- | Backend compilation monad.
49-
newtype CompileM a = Compile (StateT CompileState TCM a)
66+
newtype CompileM a = Compile (ReaderT CompileEnv (StateT CompileState TCM) a)
5067
deriving newtype (Functor, Applicative, Monad)
5168
deriving newtype (MonadIO, MonadFail, MonadDebug, ReadTCState, MonadTrace)
5269
deriving newtype (MonadError TCErr, MonadTCEnv, MonadTCState, HasOptions, MonadTCM)
5370
deriving newtype (MonadAddContext, MonadReduce, HasConstInfo, HasBuiltins, PureTCM)
71+
deriving newtype (MonadReader CompileEnv)
5472

5573
-- | Require a definition to be compiled.
5674
requireDef :: QName -> CompileM ()
@@ -89,19 +107,71 @@ trackDeps (Compile c) = Compile do
89107
deps <- gets requiredDefs
90108
pure (x, Set.toList deps)
91109

110+
-- | Run a compile action in 'TCM'.
111+
runCompile :: CompileEnv -> CompileM a -> TCM a
112+
runCompile env (Compile c) = evalStateT (runReaderT c env) initState
113+
92114
-- | Run the processing function as long as there are names to be compiled.
93115
-- Returns a list of compiled items, (topologically) sorted by dependency order.
94116
-- This means that whenever @A@ depends on @B@, @A@ will appear before @B@ in the list.
95117
compileLoop
96118
:: forall a. (Definition -> CompileM (Maybe a))
97-
-- ^ The compilation function
119+
-- ^ The compilation function
98120
-> [QName] -- ^ Initial names to compile
99-
-> TCM [CompiledItem a]
100-
compileLoop step names = topoSort <$> evalStateT unloop (initState names)
121+
-> CompileM [CompiledItem a]
122+
compileLoop step names = do
123+
traverse_ requireDef names
124+
topoSort <$> loop
101125
where
102126
loop :: CompileM [CompiledItem (Maybe a)]
103127
loop@(Compile unloop) = nextUnit >>= \case
104128
Nothing -> pure []
105129
Just q -> do
106130
(mr, deps) <- trackDeps . step =<< (liftTCM $ getConstInfo q)
107131
(CompiledItem q deps mr:) <$> loop
132+
133+
134+
-- * Compilation items and topological sort
135+
136+
-- | Named compilation item, with a set of dependencies.
137+
data CompiledItem a = CompiledItem
138+
{ itemName :: QName
139+
, itemDeps :: [QName]
140+
, itemValue :: a
141+
} deriving (Functor, Foldable, Traversable)
142+
143+
-- | Stateful monad for the topological sort.
144+
-- State contains the list of items that have been permanently inserted,
145+
-- along with their names.
146+
type TopoM a = State (Set QName, [CompiledItem a])
147+
148+
-- | Topological sort of compiled items, based on dependencies.
149+
-- Skipped items are required for dependency analysis, as they
150+
-- can transively force ordering
151+
-- (e.g constructors are skipped but force compilation of their datatype).
152+
-- In the end, we get a list of items that are effectively compiled.
153+
topoSort :: forall a. [CompiledItem (Maybe a)] -> [CompiledItem a]
154+
topoSort defs = snd $ execState (traverse (visit Set.empty) defs) (Set.empty, [])
155+
where
156+
items = Map.fromList $ map (\x -> (itemName x, x)) defs
157+
158+
-- | Whether an item has been permanently inserted already
159+
isMarked :: QName -> TopoM a Bool
160+
isMarked q = Set.member q <$> gets fst
161+
162+
push :: CompiledItem (Maybe a) -> TopoM a ()
163+
push item@CompiledItem{itemName, itemValue}
164+
| Just value <- itemValue
165+
= modify $ bimap (Set.insert itemName) (item {itemValue = value}:)
166+
| otherwise = pure ()
167+
168+
visit :: Set QName -> CompiledItem (Maybe a) -> TopoM a ()
169+
visit temp item@CompiledItem{..} = do
170+
-- NOTE(flupe): Visiting an item that has already been temporarily marked
171+
-- means something went wrong and we have a cycle in the graph.
172+
-- We could throw an error, but this should never happen.
173+
-- Here, we continue and pick an arbitrary order.
174+
unlessM ((Set.member itemName temp ||) <$> isMarked itemName) do
175+
let deps = catMaybes $ (`Map.lookup` items) <$> itemDeps
176+
traverse (visit (Set.insert itemName temp)) deps
177+
push item

src/Agda2Lambox/Compile/Term.hs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import Agda2Lambox.Compile.Monad
3535
-- * Term compilation monad
3636

3737
-- | λ□ compilation environment.
38-
data CompileEnv = CompileEnv
38+
data TermEnv = TermEnv
3939
{ mutuals :: [QName]
4040
-- ^ When we compile mutual function definitions,
4141
-- they are introduced at the top of the local context.
@@ -45,14 +45,14 @@ data CompileEnv = CompileEnv
4545

4646
-- | Initial compilation environment.
4747
-- No mutuals, no bound variables.
48-
initEnv :: CompileEnv
49-
initEnv = CompileEnv
48+
initEnv :: TermEnv
49+
initEnv = TermEnv
5050
{ mutuals = []
5151
, boundVars = 0
5252
}
5353

5454
-- | Compilation monad.
55-
type C a = ReaderT CompileEnv CompileM a
55+
type C a = ReaderT TermEnv CompileM a
5656

5757
-- | Run a compilation unit in @TCM@, in the initial environment.
5858
runC :: C a -> CompileM a
@@ -100,7 +100,7 @@ compileTermC = \case
100100
-- - they cannot be types.
101101
TDef qn -> do
102102
qn <- liftTCM $ canonicalName qn
103-
CompileEnv{mutuals, boundVars} <- ask
103+
TermEnv{mutuals, boundVars} <- ask
104104
case qn `elemIndex` mutuals of
105105
Nothing -> do lift $ requireDef qn
106106
pure $ LConst $ qnameToKName qn
@@ -109,7 +109,7 @@ compileTermC = \case
109109
TCon q -> do
110110
q <- liftTCM $ canonicalName q
111111
lift $ requireDef q
112-
liftTCM $ toConApp q []
112+
lift $ toConApp q []
113113

114114
-- TODO: maybe not ignore seq? (c.f. issue #12)
115115
TApp (TPrim PSeq) args -> compileTermC (last args)
@@ -118,7 +118,7 @@ compileTermC = \case
118118
q <- liftTCM $ canonicalName q
119119
lift $ requireDef q
120120
traverse compileTermC args
121-
>>= liftTCM . toConApp q
121+
>>= lift . toConApp q
122122
-- ^ For dealing with fully-applied constructors
123123

124124
TApp u es -> do
@@ -154,26 +154,14 @@ compileLit = \case
154154
qn <- liftTCM $ getBuiltinName_ builtinNat
155155
qz <- liftTCM $ getBuiltinName_ builtinZero
156156
qs <- liftTCM $ getBuiltinName_ builtinSuc
157-
z <- liftTCM $ toConApp qz []
158-
let ss = take (fromInteger i) $ repeat (toConApp qs . singleton)
159-
lift $ requireDef qn
160-
liftTCM $ foldrM ($) z ss
157+
lift do
158+
requireDef qn
159+
iterate (toConApp qs . singleton =<<)
160+
(toConApp qz [])
161+
!! fromInteger i
161162

162163
l -> genericError $ "unsupported literal: " <> prettyShow l
163164

164-
compileLitPattern :: Literal -> C LBox.Term
165-
compileLitPattern = \case
166-
167-
LitNat i -> do
168-
qn <- liftTCM $ getBuiltinName_ builtinNat
169-
qz <- liftTCM $ getBuiltinName_ builtinZero
170-
qs <- liftTCM $ getBuiltinName_ builtinSuc
171-
z <- liftTCM $ toConApp qz []
172-
let ss = take (fromInteger i) $ repeat (toConApp qs . singleton)
173-
lift $ requireDef qn
174-
liftTCM $ foldrM ($) z ss
175-
176-
l -> genericError $ "unsupported literal: " <> prettyShow l
177165

178166
compileCaseType :: CaseType -> C LBox.Inductive
179167
compileCaseType = \case

src/Agda2Lambox/Compile/Type.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import Agda.TypeChecking.Telescope (telView)
3434
data VarType = TypeVar Int | Other
3535

3636
-- | λ□ type compilation environment.
37-
data CompileEnv = CompileEnv
37+
data TypeEnv = TypeEnv
3838
{ typeVars :: Int
3939
-- ^ How many type variables we have.
4040
, boundVars :: Int
@@ -47,8 +47,8 @@ data CompileEnv = CompileEnv
4747
}
4848

4949
-- | Initialize compilation environment with a given number of type variables.
50-
initEnv :: Int -> CompileEnv
51-
initEnv tvs = CompileEnv
50+
initEnv :: Int -> TypeEnv
51+
initEnv tvs = TypeEnv
5252
{ typeVars = tvs
5353
, boundVars = tvs
5454
, boundTypes = reverse $ TypeVar <$> [0 .. tvs - 1]
@@ -73,15 +73,15 @@ underTypeVar :: Dom Type -> C a -> C a
7373
underTypeVar b x = do
7474
shouldInsert <- asks insertVars
7575
if shouldInsert then
76-
addContext b $ local (\e@CompileEnv{..} -> e
76+
addContext b $ local (\e@TypeEnv{..} -> e
7777
{ typeVars = typeVars + 1
7878
, boundVars = boundVars + 1
7979
, boundTypes = TypeVar typeVars : boundTypes
8080
}) x
8181
else underBinder b x
8282

8383
-- | Type compilation monad.
84-
type C a = ReaderT CompileEnv CompileM a
84+
type C a = ReaderT TypeEnv CompileM a
8585

8686

8787
-- | Compile constructor arguments' types, given a set number of type variables.

0 commit comments

Comments
 (0)