Skip to content

Commit 9c57a53

Browse files
committed
Add (bare) typechecker
1 parent d25a767 commit 9c57a53

File tree

5 files changed

+75
-1
lines changed

5 files changed

+75
-1
lines changed

agda2lambox.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ executable agda2lambox
3636
LambdaBox.Type,
3737
LambdaBox.Env,
3838
LambdaBox,
39+
LambdaBox.Typecheck,
3940
CoqGen,
4041
SExpr,
4142
Paths_agda2lambox

src/LambdaBox/Names.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ data ModPath
1919
-- ^ parameters of functors
2020
| MPDot ModPath Ident
2121
-- ^ submodules
22+
deriving (Eq)
2223

2324
-- | Absolute name of objects in the Rocq kernel.
2425
data KerName = KerName
2526
{ kerModPath :: ModPath
2627
, kerName :: Ident
2728
}
29+
deriving (Eq)
2830

2931
-- | Reference to an inductive datatype.
3032
data Inductive = Inductive
@@ -33,6 +35,7 @@ data Inductive = Inductive
3335
, indInd :: Int
3436
-- ^ Which of those is the inductive we care about.
3537
}
38+
deriving (Eq)
3639

3740
-- | Names used in binders
3841
data Name = Anon | Named Ident

src/LambdaBox/Type.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ data Type
1515
-- Uses De Bruijn *levels* and NOT indices.
1616
| TInd Inductive
1717
| TConst KerName
18+
deriving (Eq)
1819

1920
instance Pretty Type where
2021
prettyPrec p = \case

src/LambdaBox/Typecheck.hs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{-# LANGUAGE DataKinds #-}
2+
module LambdaBox.Typecheck where
3+
4+
import Agda2Lambox.Compile.Target
5+
import LambdaBox
6+
import Agda.Utils.Monad
7+
8+
type Env = Int -> Type
9+
10+
extend :: Env -> Type -> Env
11+
extend env ty 0 = ty
12+
extend env ty i = env (i - 1)
13+
14+
-- | Infer the type of a term
15+
infer :: MonadFail m => Term Typed -> Env -> m Type
16+
infer term env =
17+
case term of
18+
LBox -> return TBox
19+
LRel n -> return $ env n
20+
LLambda n (Some ty) b ->
21+
infer b (extend env ty)
22+
LLetIn n t b -> do
23+
ty <- infer t env
24+
ty' <- infer b (extend env ty)
25+
return (TArr ty ty')
26+
LApp t t' -> do
27+
TArr t1 t2 <- infer t env
28+
ifM (check t' t1 env)
29+
(return t2)
30+
(fail "Failure")
31+
LConst kn -> fail "Not implemented" -- FIXME
32+
LConstruct ind i ts -> fail "Not implemented" -- FIXME
33+
LCase ind n t bs -> fail "Not implemented" -- FIXME
34+
LFix mfix i -> fail "Not implemented" -- FIXME
35+
36+
-- | Check a term against a type
37+
check :: MonadFail m => Term Typed -> Type -> Env -> m Bool
38+
check term ty env = case term of
39+
LBox -> return $ TBox == ty
40+
LRel n -> return $ env n == ty
41+
LLambda n (Some ty) b -> case ty of
42+
TArr t1 t2 -> check b t2 (extend env t1)
43+
_ -> return False
44+
LLetIn n t b -> do
45+
ty' <- infer t env
46+
check b ty (extend env ty')
47+
LApp t t' -> do
48+
TArr t1 t2 <- infer t env
49+
check t' t1 env
50+
LConst c -> return False
51+
LConstruct ind n ts -> return False
52+
LCase ind i t bs -> return False
53+
LFix mfix i -> return False
54+
55+
typecheck :: GlobalEnv Typed -> Bool
56+
typecheck _ = False

src/Main.hs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import CoqGen ( prettyCoq )
3535
import SExpr ( prettySexp )
3636
import LambdaBox.Env
3737
import LambdaBox.Names (KerName)
38+
import LambdaBox.Typecheck (typecheck)
3839
import Agda2Lambox.Compile.Monad (runCompile, CompileEnv(..))
3940

4041

@@ -48,12 +49,13 @@ data Output = RocqOutput | AstOutput
4849
data Options = forall t. Options
4950
{ optOutDir :: Maybe FilePath
5051
, optTarget :: Target t
52+
, optWithTC :: Bool
5153
, optOutput :: Output
5254
, optNoBlocks :: Bool
5355
}
5456

5557
instance NFData Options where
56-
rnf (Options m t o nb) = rnf m `seq` rnf t `seq` rnf o `seq` rnf nb
58+
rnf (Options m t tc o nb) = rnf m `seq` rnf t `seq` rnf tc `seq` rnf o `seq` rnf nb
5759

5860
-- | Setter for output directory option.
5961
outdirOpt :: Monad m => FilePath -> Options -> m Options
@@ -68,11 +70,15 @@ rocqOpt opts = return opts { optOutput = RocqOutput }
6870
noBlocksOpt :: Monad m => Options -> m Options
6971
noBlocksOpt opts = return opts { optNoBlocks = True }
7072

73+
withTC :: Monad m => Options -> m Options
74+
withTC opts = return opts { optWithTC = True }
75+
7176
-- | Default backend options.
7277
defaultOptions :: Options
7378
defaultOptions = Options
7479
{ optOutDir = Nothing
7580
, optTarget = ToUntyped
81+
, optWithTC = False
7682
, optOutput = AstOutput
7783
, optNoBlocks = False
7884
}
@@ -97,6 +103,8 @@ agda2lambox = Backend backend
97103
"Write output files to DIR. (default: project root)"
98104
, Option ['t'] ["typed"] (NoArg typedOpt)
99105
"Compile to typed λ□ environments."
106+
, Option "tc" ["typecheck"] (NoArg typedOpt)
107+
"Typecheck output λ□."
100108
, Option ['c'] ["rocq"] (NoArg rocqOpt)
101109
"Output a Rocq file."
102110
, Option [] ["no-blocks"] (NoArg noBlocksOpt)
@@ -134,6 +142,11 @@ writeModule Options{..} menv IsMain m defs = do
134142
mains <- getMain optTarget programs
135143
env <- runCompile (CompileEnv optNoBlocks) $ compile defs
136144

145+
liftIO $ putStrLn $ "Typechecking generated λ□."
146+
if (typecheck env)
147+
then genericError "Failure"
148+
else liftIO $ putStrLn "Success"
149+
137150
liftIO $ createDirectoryIfMissing True outDir
138151

139152
let fileName = outDir </> prettyShow m

0 commit comments

Comments
 (0)