definition system, repl

This commit is contained in:
Rachel Lambda Samuelsson 2022-07-26 23:07:13 +02:00
parent 79ad67ffec
commit c7fb1d5cd3
14 changed files with 384 additions and 500 deletions

View File

@ -22,12 +22,12 @@ A dependently typed system
# TODO # TODO
* Repl
* Defs
* Performence optimisation * Performence optimisation
* Parsing !!! (this is like 90% of the time currently lmao)
* Memoize normalisation and conversion somehow? * Memoize normalisation and conversion somehow?
* Repl
* Universes * Universes
* Implicit arguments * Implicit arguments

View File

@ -1,6 +1,8 @@
.PHONY: all run .PHONY: all run
all: all:
idris2 --build pi.ipkg idris2 --build pi.ipkg
clean:
idris2 --clean pi.ipkg
run: run:
./build/exec/pi ./build/exec/pi
test: test:

View File

@ -5,7 +5,6 @@ modules = Core.Check
, Core.Misc , Core.Misc
, Core.Normalize , Core.Normalize
, Core.Term , Core.Term
, Core.Tests
, Core.Value , Core.Value
, Parser.Parse , Parser.Parse

View File

@ -5,6 +5,8 @@ import Control.Monad.Either
import Control.Monad.Identity import Control.Monad.Identity
import Data.Vect import Data.Vect
import Data.Fin import Data.Fin
import Data.IOArray
import Data.IORef
import Core.Term import Core.Term
import Core.Value import Core.Value
@ -12,21 +14,27 @@ import Core.Normalize
import Core.Misc import Core.Misc
import Core.Convert import Core.Convert
%default total %default total
-- extend environment, used to ensure environment is always in normal form -- extend environment, used to ensure environment is always in normal form
extV : Ctx n -> Value -> PI (Ctx (S n)) extV : {auto deftrs : RefA DTR Value}
-> {auto frst : Ref NST Nat}
-> Ctx n -> Value -> PI (Ctx (S n))
extV ctx val = whnf val >>= pure . (`Data.Vect.(::)` ctx) extV ctx val = whnf val >>= pure . (`Data.Vect.(::)` ctx)
-- to extend, closure env, term -- to extend, closure env, term
extT : Ctx m -> Ctx n -> Term n -> PI (Ctx (S m)) extT : {auto deftrs : RefA DTR Value}
-> {auto frst : Ref NST Nat}
-> Ctx m -> Ctx n -> Term n -> PI (Ctx (S m))
extT ctx env = extV ctx . VClos env extT ctx env = extV ctx . VClos env
mutual mutual
public export public export
-- terms types expected term -- terms types expected term
check : Ctx n -> Ctx n -> Value -> Term n -> PI Bool check : {auto deftrs : RefA DTR Value}
-> {auto deftys : RefA DTY Value}
-> {auto frst : Ref NST Nat}
-> Ctx n -> Ctx n -> Value -> Term n -> PI Bool
check trs tys xpt' tr = do check trs tys xpt' tr = do
xpt <- whnf xpt' xpt <- whnf xpt'
case tr of case tr of
@ -49,7 +57,11 @@ mutual
_ => convert xpt =<< infer trs tys tr _ => convert xpt =<< infer trs tys tr
-- terms types term -- terms types term
infer : Ctx n -> Ctx n -> Term n -> PI Value public export
infer : {auto deftrs : RefA DTR Value}
-> {auto deftys : RefA DTY Value}
-> {auto frst : Ref NST Nat}
-> Ctx n -> Ctx n -> Term n -> PI Value
infer trs tys TType = pure VType infer trs tys TType = pure VType
infer trs tys TTop = pure VType infer trs tys TTop = pure VType
infer trs tys TBot = pure VType infer trs tys TBot = pure VType
@ -57,14 +69,19 @@ mutual
infer trs tys TStar = pure VTop infer trs tys TStar = pure VTop
infer trs tys TZero = pure VNat infer trs tys TZero = pure VNat
infer trs tys (TVar i) = pure (index i tys) infer trs tys (TVar i) = pure (index i tys)
infer trs tys (TDef i) = do
res <- getArr DTY i
case res of
Just x => pure x
Nothing => oops "TDef type lookup"
infer trs tys (TApp f x) = infer trs tys f >>= whnf >>= infer trs tys (TApp f x) = infer trs tys f >>= whnf >>=
\case \case
VClos env (TPi a b) => do VClos env (TPi a b) => do
guardS ("app x:\n" ++ show !(whnf (VClos env a))) =<< check trs tys (VClos env a) x guardS ("app x:\n" ++ show !(whnf (VClos env a))) =<< check trs tys (VClos env a) x
tr <- whnf (VClos trs x) tr <- whnf (VClos trs x)
pure (VClos (tr :: env) b) pure (VClos (tr :: env) b)
_ => oops "expected infer pi" _ => oops "expected infer pi"
infer trs tys (TPi a b) = do infer trs tys (TPi a b) = do
v <- VGen <$> fresh v <- VGen <$> fresh
@ -141,6 +158,9 @@ mutual
infer trs tys x = oops ("cannot infer type " ++ show x) infer trs tys x = oops ("cannot infer type " ++ show x)
public export public export
typecheck : Term 0 -> Term 0 -> Either String (Bool, List String) typecheck : {auto deftrs : RefA DTR Value}
-> {auto deftys : RefA DTY Value}
-> {auto frst : Ref NST Nat}
-> Term 0 -> Term 0 -> IO (Either String Bool)
typecheck tr ty = resolve $ (&&) <$> check [] [] VType ty typecheck tr ty = resolve $ (&&) <$> check [] [] VType ty
<*> delay <$> check [] [] (VClos [] ty) tr <*> delay <$> check [] [] (VClos [] ty) tr

View File

@ -11,102 +11,100 @@ import Control.Monad.Either
import Data.Nat import Data.Nat
import Data.Vect import Data.Vect
import Data.IOArray
import Data.IORef
%default total %default total
public export public export
convert : Value -> Value -> PI Bool convert : {auto deftrs : RefA DTR Value}
-> {auto frst : Ref NST Nat}
-> Value -> Value -> PI Bool
convert u1 u2 = do convert u1 u2 = do
u1' <- whnf u1 u1' <- whnf u1
u2' <- whnf u2 u2' <- whnf u2
logS ("checking equality of terms '" ++ show u1 ++ "' and '" ++ show u2 ++ "'.") assert_total $ case (u1', u2') of
logS ("with value representations '" ++ show u1' ++ "' and '" ++ show u2' ++ "'.") (VType, VType) => pure True
assert_total $ -- :( (VTop, VTop) => pure True
case (u1', u2') of (VStar, VStar) => pure True
(VType, VType) => pure True (VBot, VBot) => pure True
(VTop, VTop) => pure True (VNat, VNat) => pure True
(VStar, VStar) => pure True
(VBot, VBot) => pure True
(VNat, VNat) => pure True
(VGen k1, VGen k2) => pure (k1 == k2) (VGen k1, VGen k2) => pure (k1 == k2)
(VApp f1 x1, VApp f2 x2) => (&&) <$> convert f1 f2 <*> delay <$> convert x1 x2 (VApp f1 x1, VApp f2 x2) => (&&) <$> convert f1 f2 <*> delay <$> convert x1 x2
(VClos env1 (TLam sc1), VClos env2 (TLam sc2)) => do (VClos env1 (TLam sc1), VClos env2 (TLam sc2)) => do
v <- VGen <$> fresh v <- VGen <$> fresh
convert (VClos (v :: env1) sc1) (VClos (v :: env2) sc2) convert (VClos (v :: env1) sc1) (VClos (v :: env2) sc2)
(VClos env1 (TPi a1 b1), VClos env2 (TPi a2 b2)) => do (VClos env1 (TPi a1 b1), VClos env2 (TPi a2 b2)) => do
v <- VGen <$> fresh v <- VGen <$> fresh
guardS (show a1 ++ " | " ++ show a2) =<< convert (VClos env1 a1) (VClos env2 a2) (&&) <$> convert (VClos env1 a1) (VClos env2 a2)
convert (VClos (v :: env1) b1) (VClos (v :: env2) b2) <*> delay <$> convert (VClos (v :: env1) b1) (VClos (v :: env2) b2)
(VClos env1 (TSigma a1 b1), VClos env2 (TSigma a2 b2)) => do (VClos env1 (TSigma a1 b1), VClos env2 (TSigma a2 b2)) => do
termGuard env1 env2 a1 a2 termGuard env1 env2 a1 a2
termConv env1 env2 b1 b2 termConv env1 env2 b1 b2
(VClos env1 (TPair a1 b1), VClos env2 (TPair a2 b2)) => do (VClos env1 (TPair a1 b1), VClos env2 (TPair a2 b2)) => do
termGuard env1 env2 a1 a2 termGuard env1 env2 a1 a2
termConv env1 env2 b1 b2 termConv env1 env2 b1 b2
(VClos env1 (TId ty1 a1 b1), VClos env2 (TId ty2 a2 b2)) => do (VClos env1 (TId ty1 a1 b1), VClos env2 (TId ty2 a2 b2)) => do
termGuard env1 env2 ty1 ty2 termGuard env1 env2 ty1 ty2
termGuard env1 env2 a1 a2 termGuard env1 env2 a1 a2
termConv env1 env2 b1 b2 termConv env1 env2 b1 b2
(VClos env1 (TRefl ty1 tr1), VClos env2 (TRefl ty2 tr2)) => do (VClos env1 (TRefl ty1 tr1), VClos env2 (TRefl ty2 tr2)) => do
termGuard env1 env2 ty1 ty2 termGuard env1 env2 ty1 ty2
termConv env1 env2 tr1 tr2 termConv env1 env2 tr1 tr2
(VClos env1 (TNatInd c1 z1 s1), VClos env2 (TNatInd c2 z2 s2)) => do (VClos env1 (TNatInd c1 z1 s1), VClos env2 (TNatInd c2 z2 s2)) => do
termGuard env1 env2 c1 c2 termGuard env1 env2 c1 c2
termGuard env1 env2 z1 z2 termGuard env1 env2 z1 z2
termConv env1 env2 s1 s2 termConv env1 env2 s1 s2
(VClos _ TZero, VClos _ TZero) => pure True (VClos _ TZero, VClos _ TZero) => pure True
(VClos env1 (TSuc n1), VClos env2 (TSuc n2)) => do (VClos env1 (TSuc n1), VClos env2 (TSuc n2)) => do
termConv env1 env2 n1 n2 termConv env1 env2 n1 n2
(VClos env1 (TJ ty1 a1 b1 c1 d1), VClos env2 (TJ ty2 a2 b2 c2 d2)) => do (VClos env1 (TJ ty1 a1 b1 c1 d1), VClos env2 (TJ ty2 a2 b2 c2 d2)) => do
termGuard env1 env2 ty1 ty2 termGuard env1 env2 ty1 ty2
termGuard env1 env2 a1 a2 termGuard env1 env2 a1 a2
termGuard env1 env2 b1 b2 termGuard env1 env2 b1 b2
termGuard env1 env2 c1 c2 termGuard env1 env2 c1 c2
termConv env1 env2 d1 d2 termConv env1 env2 d1 d2
(VClos env1 (TSigInd a1 b1 c1 f1), VClos env2 (TSigInd a2 b2 c2 f2)) => do (VClos env1 (TSigInd a1 b1 c1 f1), VClos env2 (TSigInd a2 b2 c2 f2)) => do
termGuard env1 env2 a1 a2 termGuard env1 env2 a1 a2
termGuard env1 env2 b1 b2 termGuard env1 env2 b1 b2
termGuard env1 env2 c1 c2 termGuard env1 env2 c1 c2
termConv env1 env2 f1 f2 termConv env1 env2 f1 f2
(VClos env1 (TBotInd c1), VClos env2 (TBotInd c2)) => termConv env1 env2 c1 c2 (VClos env1 (TBotInd c1), VClos env2 (TBotInd c2)) => termConv env1 env2 c1 c2
(VClos env1 (TTopInd c1 st1), VClos env2 (TTopInd c2 st2)) => do (VClos env1 (TTopInd c1 st1), VClos env2 (TTopInd c2 st2)) => do
termGuard env1 env2 c1 c2 termGuard env1 env2 c1 c2
termConv env1 env2 st1 st2 termConv env1 env2 st1 st2
-- η rules -- η rules
-- fresh cannot appear in vsc, so this is fine -- fresh cannot appear in vsc, so this is fine
(vsc, VClos env (TLam (TApp sc (TVar 0)))) => do (vsc, VClos env (TLam (TApp sc (TVar 0)))) => do
v <- VGen <$> fresh v <- VGen <$> fresh
convert vsc (VClos (v :: env) sc) convert vsc (VClos (v :: env) sc)
(VClos env (TLam (TApp sc (TVar 0))), vsc) => do (VClos env (TLam (TApp sc (TVar 0))), vsc) => do
v <- VGen <$> fresh v <- VGen <$> fresh
convert vsc (VClos (v :: env) sc) convert vsc (VClos (v :: env) sc)
-- VApp (v1, v2) => oops ("cannot convert \n" ++ show v1 ++ "\n\n" ++ show v2)
-- (VApp v1 v2 , VClos env (TApp t1 t2)) => (&&) <$> convert v1 (VClos env t1) <*> delay <$> convert v1 (VClos env t1) where
-- (VClos env (TApp t1 t2), VApp v1 v2) => (&&) <$> convert v1 (VClos env t1) <*> delay <$> convert v1 (VClos env t1) termConv : Ctx n -> Ctx m -> Term n -> Term m -> PI Bool
termConv env1 env2 a1 a2 = do
(v1, v2) => oops ("cannot convert \n" ++ show v1 ++ "\n\n" ++ show v2) a1' <- eval env1 a1
where a2' <- eval env2 a2
termConv : Ctx n -> Ctx m -> Term n -> Term m -> PI Bool convert a1' a2'
termConv env1 env2 a1 a2 = do termGuard : Ctx n -> Ctx m -> Term n -> Term m -> PI ()
a1' <- eval env1 a1 termGuard env1 env2 a1 a2 = termConv env1 env2 a1 a2 >>=
a2' <- eval env2 a2 guardS ("cannot convert \n" ++ show a1 ++ "\n\n" ++ show a2)
convert a1' a2'
termGuard : Ctx n -> Ctx m -> Term n -> Term m -> PI ()
termGuard env1 env2 a1 a2 = guardS "termGuard" =<< termConv env1 env2 a1 a2

View File

@ -6,6 +6,8 @@ import Control.Monad.Either
import Data.Nat import Data.Nat
import Data.Vect import Data.Vect
import Data.IORef
import Data.IOArray
%default total %default total
@ -19,13 +21,46 @@ Name = String
public export public export
PI : Type -> Type PI : Type -> Type
PI = EitherT String (RWS () (List String) Nat) PI = EitherT String IO
public export public export
resolve : PI a -> Either String (a, List String) data NST : Type where
resolve a = case runRWS (runEitherT a) () 0 of public export
(Left e, _) => Left e data DTY : Type where
(Right r, _, s) => Right (r, s) public export
data DTR : Type where
public export
data RefP : Type -> Type -> Type where
MkRefP : (label : Type) -> a -> RefP label a
public export
RefA : Type -> Type -> Type
RefA label a = RefP label (IOArray a)
public export
Ref : Type -> Type -> Type
Ref label a = RefP label (IORef a)
public export
getRef : HasIO io => (label : Type) -> {auto ref : Ref label a} -> io a
getRef _ {ref = MkRefP _ ref} = readIORef ref
public export
putRef : HasIO io => (label : Type) -> {auto ref : Ref label a} -> a -> io ()
putRef _ {ref = MkRefP _ ref} = writeIORef ref
public export
getArr : HasIO io => (label : Type) -> {auto ref : RefA label a} -> Int -> io (Maybe a)
getArr _ {ref = MkRefP _ ref} = readArray ref
public export
putArr : HasIO io => (label : Type) -> {auto ref : RefA label a} -> Int -> a -> io Bool
putArr _ {ref = MkRefP _ ref} = writeArray ref
public export
resolve : PI a -> IO (Either String a)
resolve a = runEitherT a
public export public export
oops : String -> PI a oops : String -> PI a
@ -36,19 +71,9 @@ guardS : String -> Bool -> PI ()
guardS str True = pure () guardS str True = pure ()
guardS str False = oops str guardS str False = oops str
public export public export
fresh : PI Nat fresh : {auto frst : Ref NST Nat} -> PI Nat
fresh = do fresh = do
i <- get i <- getRef NST
put (S i) putRef NST (S i)
pure i pure i
public export
logS : String -> PI ()
logS = tell . (`Prelude.(::)` [])
public export
headM : Vect n a -> Maybe a
headM [] = Nothing
headM (x :: _) = Just x

View File

@ -10,12 +10,16 @@ import Control.Monad.Either
import Data.Nat import Data.Nat
import Data.Vect import Data.Vect
import Data.IOArray
import Data.IORef
%default total %default total
mutual mutual
public export public export
app : Value -> Value -> PI Value app : {auto deftrs : RefA DTR Value}
-> {auto frst : Ref NST Nat}
-> Value -> Value -> PI Value
app (VClos env (TLam sc)) x = eval (x :: env) sc app (VClos env (TLam sc)) x = eval (x :: env) sc
app (VClos env (TTopInd c st)) VTop = eval env st app (VClos env (TTopInd c st)) VTop = eval env st
@ -36,8 +40,15 @@ mutual
app f x = pure (VApp f x) app f x = pure (VApp f x)
public export public export
eval : Ctx n -> Term n -> PI Value eval : {auto deftrs : RefA DTR Value}
eval env (TVar i) = pure (index i env) -> {auto frst : Ref NST Nat}
-> Ctx n -> Term n -> PI Value
eval env (TVar i) = pure (index i env)
eval env (TDef i) = do
res <- getArr DTR i
case res of
Just x => pure x
Nothing => oops "TDef term lookup"
eval env TType = pure VType eval env TType = pure VType
eval env TTop = pure VTop eval env TTop = pure VTop
eval env TStar = pure VStar eval env TStar = pure VStar
@ -55,7 +66,9 @@ mutual
eval env tr = pure (VClos env tr) eval env tr = pure (VClos env tr)
public export public export
whnf : Value -> PI Value whnf : {auto deftrs : RefA DTR Value}
-> {auto frst : Ref NST Nat}
-> Value -> PI Value
whnf (VClos env tr) = eval env tr whnf (VClos env tr) = eval env tr
whnf (VApp f x) = do whnf (VApp f x) = do
f' <- whnf f f' <- whnf f

View File

@ -9,6 +9,9 @@ import Core.Misc
{- {-
The type of terms is indexed by the size of the environment in which The type of terms is indexed by the size of the environment in which
they are valid, that is, it is impossible to construct an ill-scoped term. they are valid, that is, it is impossible to construct an ill-scoped term.
Defs are used for performance reasons and are not implemented in a type safe manner.
if a def is not in scope the checker will scream at you.
-} -}
public export public export
data Term : (_ : Index) -> Type where data Term : (_ : Index) -> Type where
@ -40,8 +43,11 @@ data Term : (_ : Index) -> Type where
TPi : Term n -> Term (S n) -> Term n -- Pi type (∏ _ : A . B _ ) TPi : Term n -> Term (S n) -> Term n -- Pi type (∏ _ : A . B _ )
TApp : Term n -> Term n -> Term n -- Appliction TApp : Term n -> Term n -> Term n -- Appliction
TVar : Fin n -> Term n -- Variable TVar : Fin n -> Term n -- Variable
TDef : Int -> Term n -- Def Variable
infixl 3 `TApp` infixl 3 `TApp`
public export public export
@ -76,6 +82,7 @@ Show (Term n) where
show (TApp f x) = "(" ++ show f ++ ") TApp (" ++ show x ++ ")" show (TApp f x) = "(" ++ show f ++ ") TApp (" ++ show x ++ ")"
show (TVar i) = "Var " ++ show i show (TVar i) = "Var " ++ show i
show (TDef i) = "Def " ++ show i
public export public export
weakTr : Term n -> Term (S n) weakTr : Term n -> Term (S n)
@ -105,6 +112,7 @@ weakTr = go 0
go n (TVar i) = if weaken i < n go n (TVar i) = if weaken i < n
then TVar (weaken i) then TVar (weaken i)
else TVar (FS i) else TVar (FS i)
go n (TDef i) = TDef i
public export public export
weakTr2 : Term n -> Term (2+n) weakTr2 : Term n -> Term (2+n)

View File

@ -1,155 +0,0 @@
module Core.Tests
import Core.Term
import Core.Check
import Core.Convert
import Core.Misc
import Core.Normalize
import Core.Value
import Control.Monad.RWS
import Control.Monad.Identity
import Control.Monad.Either
import Data.Fin
%default total
{- λA. λx. x : ∏ (A : Type) → A → A -}
test_id : Either String (Bool, List String)
test_id = typecheck (TLam (TLam (TVar 0)))
(TPi TType (TPi (TVar 0) (TVar 1)))
{- λA. λB. λf. λx. f x : ∏ (A : Type) ∏ (B : A → Type) ∏ (f : ∏ (x : A) B x) ∏ (x : A) B x -}
test_app : Either String (Bool, List String)
test_app = typecheck (TLam (TLam (TLam (TLam (TVar 1 `TApp` TVar 0)))))
(TPi TType
(TPi (TPi (TVar 0) TType)
(TPi (TPi (TVar 1) (TVar 1 `TApp` TVar 0))
(TPi (TVar 2) (TVar 2 `TApp` TVar 0)))))
{- λf. λx. f x ≃ λf. λx. (λy. f y) x -}
eta_test : Either String (Bool, List String)
eta_test = resolve action
where
action : PI Bool
action = do
x <- eval ctx0 (TLam (TLam (TVar 1 `TApp` TVar 0)))
y <- eval ctx0 (TLam (TLam (TLam (TVar 2 `TApp` TVar 0) `TApp` TVar 0)))
convert x y
addition : Term 0
addition = TNatInd (TLam (TPi TNat TNat))
(TLam (TVar 0))
(TLam {-n-} (TLam {-n+-} (TLam {-m-} (TSuc (TVar 1 `TApp` TVar 0)))))
additionty : Term 0
additionty = TPi TNat (TPi TNat TNat)
additionty_test : Either String (Bool, List String)
additionty_test = typecheck additionty TType
addition_test : Either String (Bool, List String)
addition_test = typecheck addition additionty
{- 2 + 1 = 3 -}
addition_compute_test : Either String (Bool, List String)
addition_compute_test = resolve action
where
action : PI Bool
action = do
x <- eval ctx0 (addition `TApp` TSuc (TSuc TZero) `TApp` TSuc TZero)
y <- eval ctx0 (TSuc (TSuc (TSuc TZero)))
convert x y
multi : Term 0
multi = TNatInd (TLam (TPi TNat TNat))
(TLam TZero)
(TLam {-n-} (TLam {-n*-} (TLam {-m-} (weakTr3 addition `TApp` TVar 0 `TApp` (TVar 1 `TApp` TVar 0)))))
multity : Term 0
multity = TPi TNat (TPi TNat TNat)
multity_test : Either String (Bool, List String)
multity_test = typecheck multity TType
multi_test : Either String (Bool, List String)
multi_test = typecheck multi multity
{- 2 * 3 = 6 -}
multi_compute_test : Either String (Bool, List String)
multi_compute_test = resolve action
where
action : PI Bool
action = do
x <- eval ctx0 (multi `TApp` TSuc (TSuc TZero) `TApp` TSuc (TSuc (TSuc TZero)))
y <- eval ctx0 (TSuc (TSuc (TSuc (TSuc (TSuc (TSuc TZero))))))
convert x y
-- no, not that kind
unit_test : Either String (Bool, List String)
unit_test = typecheck TStar TTop
absurd_test : Either String (Bool, List String)
absurd_test = typecheck (TLam (TBotInd (TLam (TVar 1)))) (TPi TType (TPi TBot (TVar 1)))
pr1ty : Term 0
pr1ty = TPi TType {- A : Type -}
(TPi (TPi (TVar 0) TType) {- B : A → Type -}
(TPi (TSigma (TVar 1) (TVar 0)) {- Σ A B -}
(TVar 2)))
pr1 : Term 0
pr1 = TLam {- A : Type -}
(TLam {- B : A → Type -}
(TSigInd (TVar 1) (TVar 0) (TLam {-ΣAB-} (TVar 2)) (TLam (TLam (TVar 1)))))
pr1ty_test : Either String (Bool, List String)
pr1ty_test = typecheck pr1ty TType
pr1_test : Either String (Bool, List String)
pr1_test = typecheck pr1 pr1ty
pr2ty : Term 0
pr2ty = TPi TType {- A : Type -}
(TPi (TPi (TVar 0) TType) {- B : A → Type -}
(TPi (TSigma (TVar 1) (TVar 0)) {- Σ A B -}
(TVar 1 `TApp` (TSigInd (TVar 2) (TVar 1) (TLam (TVar 3)) (TLam (TLam (TVar 1))) `TApp` TVar 0))))
pr2 : Term 0
pr2 = TLam {- A : Type -}
(TLam {- B : A → Type -}
(TSigInd (TVar 1)
(TVar 0)
(TLam {-ΣAB-}
(TVar 1 `TApp` (TSigInd (TVar 2) (TVar 1) (TLam (TVar 3)) (TLam (TLam (TVar 1))) `TApp` TVar 0)))
(TLam (TLam (TVar 0)))))
pr2ty_test : Either String (Bool, List String)
pr2ty_test = typecheck pr2ty TType
pr2_test : Either String (Bool, List String)
pr2_test = typecheck pr2 pr2ty
pr2ty_let : Term 0
pr2ty_let = TLet pr1ty pr1 {- pr1 : pr1ty -}
(TPi TType {- A : Type -}
(TPi (TPi (TVar 0) TType) {- B : A → Type -}
(TPi (TSigma (TVar 1) (TVar 0)) {- Σ A B -}
(TVar 1 `TApp` (TVar 3 `TApp` TVar 2 `TApp` TVar 1 `TApp` TVar 0)))))
pr2_let : Term 0
pr2_let = TLet pr1ty pr1 {- pr1 : pr1ty -}
(TLam {- A : Type -}
(TLam {- B : A → Type -}
(TSigInd (TVar 1)
(TVar 0)
(TLam {-ΣAB-}
(TVar 1 `TApp` (TVar 3 `TApp` TVar 2 `TApp` TVar 1 `TApp` TVar 0)))
(TLam (TLam (TVar 0))))))
pr2ty_let_test : Either String (Bool, List String)
pr2ty_let_test = typecheck pr2ty_let TType
pr2_let_test : Either String (Bool, List String)
pr2_let_test = typecheck pr2_let pr2ty_let

View File

@ -2,22 +2,59 @@ module Main
import Core.Check import Core.Check
import Core.Term import Core.Term
import Core.Value
import Core.Normalize
import Core.Misc
import Parser.Parse import Parser.Parse
import Control.Monad.Either
import Data.Vect import Data.Vect
import Data.String import Data.String
import Data.IORef
import Data.IOArray
import System import System
import System.File import System.File
unwrap : {a : Type} -> Show a => Either a b -> IO b smartPrint : {a : Type} -> Show a => a -> IO ()
unwrap {a = a} = \case smartPrint {a = String} = putStrLn
smartPrint {a = _} = printLn
isTrue : String -> Bool -> IO ()
isTrue _ True = pure ()
isTrue str False = putStrLn str >> exitFailure
unwrapCC : {a : Type} -> Show a => IO b -> Either a b -> IO b
unwrapCC {a = a} iob = \case
Left e => do Left e => do
case a of smartPrint e
String => putStrLn e iob
_ => printLn e
exitFailure
Right s => pure s Right s => pure s
unwrap : {a : Type} -> Show a => Either a b -> IO b
unwrap = unwrapCC exitFailure
createNST : IO (Ref NST Nat)
createNST = do
nstIoRef <- newIORef 0
pure (MkRefP NST nstIoRef)
createDTX : (label : Type) -> Int -> IO (RefA label Value)
createDTX label n = do
arr <- newArray n
pure (MkRefP label arr)
typeCheck : {auto deftrs : RefA DTR Value}
-> {auto deftys : RefA DTY Value}
-> {auto frst : Ref NST Nat}
-> Int -> List (Term 0, Term 0) -> IO ()
typeCheck i [] = pure ()
typeCheck i ((ty, tr) :: defs) = do
vty <- unwrap =<< resolve (eval [] ty)
vtr <- unwrap =<< resolve (eval [] tr)
isTrue "putArr DTY" =<< putArr DTY i vty
isTrue "putArr DTR" =<< putArr DTR i vtr
typeCheck (i+1) defs
replRead : IO String replRead : IO String
replRead = do replRead = do
line <- getLine line <- getLine
@ -27,19 +64,40 @@ replRead = do
":exit" => exitSuccess ":exit" => exitSuccess
_ => pure line _ => pure line
repl : (n : Nat) -> Vect n String -> IO () repl : {auto deftrs : RefA DTR Value}
repl n env = do -> {auto deftys : RefA DTY Value}
-> {auto frst : Ref NST Nat}
-> List String -> IO a
repl strs = do
line <- replRead line <- replRead
printLn =<< unwrap (parseEnv n env line) term <- unwrapCC (repl strs) (parseEnv strs line)
repl n env type <- unwrapCC (repl strs) =<< resolve (whnf =<< infer [] [] term)
val <- unwrapCC (repl strs) =<< resolve (whnf =<< eval [] term)
putStr "inferred type: "
printLn type
putStr "weak head normal form: "
printLn val
repl strs
main : IO () main : IO ()
main = getArgs >>= \case main = getArgs >>= \case
(_ :: x :: _) => do (_ :: x :: xs) => do
putStr (x ++ ": ") putStrLn (x ++ ": ")
res <- readFile x >>= unwrap >>= unwrap . parsetoplevel putStr "Parsing: "
>>= unwrap . (`typecheck` TTop) (strs, res) <- readFile x >>= unwrap >>= unwrap . toplevel
if fst res putStrLn " OK!"
then putStrLn ("Success !") let rlen = cast (length res)
else unwrap (Left res) nst <- createNST
_ => repl 0 [] dtr <- createDTX DTR rlen
dty <- createDTX DTY rlen
putStr "Typechecking: "
typeCheck 0 res
putStrLn "OK!"
case xs of
("repl" :: _) => repl strs
_ => exitSuccess
_ => do
nst <- createNST
dtr <- createDTX DTR 0
dty <- createDTX DTY 0
repl []

View File

@ -211,40 +211,40 @@ lexPi str =
{- Basic idea, parsing has a list of the identifiers to convert to -} {- Basic idea, parsing has a list of the identifiers to convert to -}
{- de bruijn indecies, and a Nat to keep track of context size -} {- de bruijn indecies, and a Nat to keep track of context size -}
mutual mutual
expr : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) expr : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
expr n env = tpi n env expr defs n env = tpi defs n env
<|> tsigma n env <|> tsigma defs n env
<|> tarr n env <|> tarr defs n env
<|> (do <|> (do
e <- expr1 n env e <- expr1 defs n env
tapp n env e <|> pure e) tapp defs n env e <|> pure e)
expr1 : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) expr1 : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
expr1 n env = ttopind n env expr1 defs n env = ttopind defs n env
<|> tbotind n env <|> tbotind defs n env
<|> tsuc n env <|> tsuc defs n env
<|> tnatind n env <|> tnatind defs n env
<|> tsigind n env <|> tsigind defs n env
<|> tid n env <|> tid defs n env
<|> trefl n env <|> trefl defs n env
<|> tj n env <|> tj defs n env
<|> (do <|> (do
t <- term n env t <- term defs n env
tapp n env t <|> pure t) tapp defs n env t <|> pure t)
term : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) term : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
term n env = ttype term defs n env = ttype
<|> ttop <|> ttop
<|> tstar <|> tstar
<|> tbot <|> tbot
<|> tnat <|> tnat
<|> tnum <|> tnum
<|> tpair n env <|> tpair defs n env
<|> tlet n env <|> tlet defs n env
<|> tlam n env <|> tlam defs n env
<|> tvar n env <|> tvar defs n env
<|> paren n env <|> paren defs n env
ttype : Grammar () PiToken True (Term n) ttype : Grammar () PiToken True (Term n)
ttype = match PTType >> pure TType ttype = match PTType >> pure TType
@ -255,22 +255,22 @@ mutual
tstar : Grammar () PiToken True (Term n) tstar : Grammar () PiToken True (Term n)
tstar = match PTStar >> pure TStar tstar = match PTStar >> pure TStar
ttopind : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) ttopind : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
ttopind n env = do ttopind defs n env = do
match PTTopInd match PTTopInd
commit commit
c <- term n env c <- term defs n env
st <- term n env st <- term defs n env
pure (TTopInd c st) pure (TTopInd c st)
tbot : Grammar () PiToken True (Term n) tbot : Grammar () PiToken True (Term n)
tbot = match PTBot >> pure TBot tbot = match PTBot >> pure TBot
tbotind : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tbotind : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tbotind n env = do tbotind defs n env = do
match PTBotInd match PTBotInd
commit commit
c <- term n env c <- term defs n env
pure (TBotInd c) pure (TBotInd c)
tnat : Grammar () PiToken True (Term n) tnat : Grammar () PiToken True (Term n)
@ -285,162 +285,161 @@ mutual
conv 0 = TZero conv 0 = TZero
conv (S n) = TSuc (conv n) conv (S n) = TSuc (conv n)
tsuc : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tsuc : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tsuc n env = do tsuc defs n env = do
match PTSuc match PTSuc
commit commit
TSuc <$> term n env TSuc <$> term defs n env
tnatind : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tnatind : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tnatind n env = do tnatind defs n env = do
match PTNatInd match PTNatInd
commit commit
c <- term n env c <- term defs n env
z <- term n env z <- term defs n env
s <- term n env s <- term defs n env
pure (TNatInd c z s) pure (TNatInd c z s)
tsigma : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tsigma : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tsigma n env = do tsigma defs n env = do
match PTSigma match PTSigma
commit commit
match PTLParen match PTLParen
arg <- match PTIdentifier arg <- match PTIdentifier
match PTColon match PTColon
a <- expr n env a <- expr defs n env
match PTRParen match PTRParen
b <- expr (S n) (arg :: env) b <- expr defs (S n) (arg :: env)
pure (TSigma a (TLam b)) pure (TSigma a (TLam b))
tpair : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tpair : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tpair n env = do tpair defs n env = do
match PTLParen match PTLParen
x <- expr n env x <- expr defs n env
match PTComma match PTComma
commit commit
y <- expr n env y <- expr defs n env
match PTRParen match PTRParen
pure (TPair x y) pure (TPair x y)
tsigind : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tsigind : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tsigind n env = do tsigind defs n env = do
match PTSigInd match PTSigInd
commit commit
a <- term n env a <- term defs n env
b <- term n env b <- term defs n env
c <- term n env c <- term defs n env
f <- term n env f <- term defs n env
pure (TSigInd a b c f) pure (TSigInd a b c f)
tid : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tid : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tid n env = do tid defs n env = do
match PTId match PTId
commit commit
ty <- term n env ty <- term defs n env
a <- term n env a <- term defs n env
b <- term n env b <- term defs n env
pure (TId ty a b) pure (TId ty a b)
trefl : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) trefl : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
trefl n env = do trefl defs n env = do
match PTRefl match PTRefl
commit commit
ty <- term n env ty <- term defs n env
tr <- term n env tr <- term defs n env
pure (TRefl ty tr) pure (TRefl ty tr)
tj : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tj : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tj n env = do tj defs n env = do
match PTJ match PTJ
commit commit
ty <- term n env ty <- term defs n env
a <- term n env a <- term defs n env
b <- term n env b <- term defs n env
c <- term n env c <- term defs n env
d <- term n env d <- term defs n env
pure (TJ ty a b c d) pure (TJ ty a b c d)
tlet : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tlet : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tlet n env = do tlet defs n env = do
match PTLet match PTLet
commit commit
arg <- match PTIdentifier arg <- match PTIdentifier
match PTColon match PTColon
ty <- expr n env ty <- expr defs n env
match PTDefEq match PTDefEq
tr <- expr n env tr <- expr defs n env
match PTIn match PTIn
tri <- expr (S n) (arg :: env) tri <- expr defs (S n) (arg :: env)
pure (TLet ty tr tri) pure (TLet ty tr tri)
tlam : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tlam : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tlam n env = do tlam defs n env = do
match PTLambda match PTLambda
commit commit
arg <- match PTIdentifier arg <- match PTIdentifier
match PTDot match PTDot
e <- expr (S n) (arg :: env) e <- expr defs (S n) (arg :: env)
pure (TLam e) pure (TLam e)
tpi : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tpi : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tpi n env = do tpi defs n env = do
match PTPi match PTPi
commit commit
match PTLParen match PTLParen
arg <- match PTIdentifier arg <- match PTIdentifier
match PTColon match PTColon
a <- expr n env a <- expr defs n env
match PTRParen match PTRParen
b <- expr (S n) (arg :: env) b <- expr defs (S n) (arg :: env)
pure (TPi a b) pure (TPi a b)
tarr : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tarr : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tarr n env = do tarr defs n env = do
l <- expr1 n env l <- expr1 defs n env
match PTArrow match PTArrow
commit commit
r <- expr (S n) ("" :: env) r <- expr defs (S n) ("" :: env)
pure (TPi l r) pure (TPi l r)
tapp : (n : Nat) -> Vect n String -> Term n -> Grammar () PiToken True (Term n) tapp : List String -> (n : Nat) -> Vect n String -> Term n -> Grammar () PiToken True (Term n)
tapp n env e1 = do tapp defs n env e1 = do
e2 <- term n env e2 <- term defs n env
tapp1 n env (TApp e1 e2) tapp1 defs n env (TApp e1 e2)
tapp1 : (n : Nat) -> Vect n String -> Term n -> Grammar () PiToken False (Term n) tapp1 : List String -> (n : Nat) -> Vect n String -> Term n -> Grammar () PiToken False (Term n)
tapp1 n env e = tapp n env e <|> pure e tapp1 defs n env e = tapp defs n env e <|> pure e
tvar : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) tvar : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
tvar n env = do tvar defs n env = do
str <- match PTIdentifier str <- match PTIdentifier
commit commit
fromMaybe (fail ("'" ++ str ++ "' not in env")) (pure . TVar <$> findIndex (== str) env) fromMaybe (fromMaybe (fail ("'" ++ str ++ "' not idefs n env"))
(pure . TDef . cast . finToInteger <$> findIndex (== str) defs))
(pure . TVar <$> findIndex (== str) env)
paren : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) paren : List String -> (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n)
paren n env = do paren defs n env = do
match PTLParen match PTLParen
commit commit
e <- expr n env e <- expr defs n env
match PTRParen match PTRParen
pure e pure e
definitions : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) definitions : List String -> Grammar () PiToken True (List String, List (Term 0, Term 0))
definitions n env = do definitions defs = do
match PTLet match PTLet
commit commit
arg <- match PTIdentifier arg <- match PTIdentifier
match PTColon match PTColon
ty <- expr n env ty <- expr defs 0 []
match PTDefEq match PTDefEq
tr <- expr n env tr <- expr defs 0 []
next <- definitions (S n) (arg :: env) <|> pure TStar next <- definitions (arg :: defs) <|> pure ([], [])
pure (TLet ty tr next) pure (arg :: fst next, (ty, tr) :: snd next)
toplevel : Grammar () PiToken True (Term 0) parsePi : List String -> Grammar () PiToken True a -> List (WithBounds PiToken) -> Either String a
toplevel = definitions 0 [] parsePi defs parseEntry toks =
parsePi : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) -> List (WithBounds PiToken) -> Either String (Term n)
parsePi n env parseEntry toks =
case parse parseEntry $ filter (not . ignored) toks of case parse parseEntry $ filter (not . ignored) toks of
Right (l, []) => Right l Right (l, []) => Right l
Right (_, l) => Left ("contains tokens that were not consumed: " ++ show l) Right (_, l) => Left ("contains tokens that were not consumed: " ++ show l)
@ -452,20 +451,20 @@ parsePi n env parseEntry toks =
public export public export
parse : (n : Nat) -> Vect n String -> Grammar () PiToken True (Term n) -> String -> Either String (Term n) parse : List String -> Grammar () PiToken True a -> String -> Either String a
parse n env parseEntry x = parse defs parseEntry x =
case lexPi x of case lexPi x of
Just toks => parsePi n env parseEntry toks Just toks => parsePi defs parseEntry toks
Nothing => Left "Failed to lex." Nothing => Left "Failed to lex."
public export public export
parse0 : String -> Either String (Term 0) parse0 : String -> Either String (Term 0)
parse0 = parse 0 [] (expr 0 []) parse0 = parse [] (expr [] 0 [])
public export public export
parseEnv : (n : Nat) -> Vect n String -> String -> Either String (Term n) parseEnv : List String -> String -> Either String (Term 0)
parseEnv n env = parse n env (expr n env) parseEnv defs = parse defs (expr defs 0 [])
public export public export
parsetoplevel : String -> Either String (Term 0) toplevel : String -> Either String (List String, List (Term 0, Term 0))
parsetoplevel = parse 0 [] (toplevel) toplevel = parse [] (definitions [])

View File

@ -1,89 +0,0 @@
module Parser.Tests
import Core.Term
import Core.Check
import Core.Convert
import Core.Misc
import Core.Normalize
import Core.Value
import Control.Monad.RWS
import Control.Monad.Identity
import Control.Monad.Either
import Data.Fin
import Parser.Parse
%default total
convCheck : Term 0 -> Term 0 -> Either String (Bool, List String)
convCheck a b = resolve action
where
action : PI Bool
action = do
x <- eval ctx0 a
y <- eval ctx0 b
convert x y
{- λA. λx. x : ∏ (A : Type) → A → A -}
test_id : Either String (Bool, List String)
test_id = do
ty <- parse0 "Π ( A : Type ) A → A"
tr <- parse0 "λA.λx.x"
typecheck tr ty
{- λA. λB. λf. λx. f x : ∏ (A : Type) ∏ (B : A → Type) ∏ (f : ∏ (x : A) B x) ∏ (x : A) B x -}
test_app : Either String (Bool, List String)
test_app = do
ty <- parse0 "Π (A : Type) Π (B : A → Type) Π (f : Π (x : A) B x) Π (x : A) B x"
tr <- parse0 "λA. λB. λf. λx. f x"
typecheck tr ty
{- λf. f ≃ λf. λx. f x -}
eta_test : Either String (Bool, List String)
eta_test = do
a <- parse0 "λf. f"
b <- parse0 "λf. λx. f x"
convCheck a b
additionty_test : Either String (Bool, List String)
additionty_test = do
ty <- parse0 " → ℕ"
typecheck ty TType
addition_test : Either String (Bool, List String)
addition_test = do
ty <- parse0 " → ℕ"
tr <- parse0 "-ind (λ_. ) (λx.x) (λn.λnp.λm. suc (np m))"
typecheck tr ty
-- no, not that kind
unit_test : Either String (Bool, List String)
unit_test = do
ty <- parse0 ""
tr <- parse0 ""
typecheck tr ty
absurd_test : Either String (Bool, List String)
absurd_test = do
ty <- parse0 "Π(A : Type) ⊥ → A"
tr <- parse0 "λA. ⊥-ind (λ_. A)"
typecheck tr ty
pr1_test : Either String (Bool, List String)
pr1_test = do
tr <- parse0 $ "let pr1 : Π (A : Type) Π (B : A → Type) (Σ (a : A) B a) → A"
++ "≔ λA.λB. Σ-ind A B (λ_. A) (λa.λBa. a)"
++ "in ★"
typecheck tr TTop
pr1_pr2_test : Either String (Bool, List String)
pr1_pr2_test = do
tr <- parse0 $ "let pr1 : Π (A : Type) Π (B : A → Type) (Σ (a : A) B a) → A"
++ "≔ λA.λB. Σ-ind A B (λ_. A) (λa.λBa. a)"
++ "in let pr2 : Π (A : Type) Π (B : A → Type) Π (s : Σ (a : A) B a) B (pr1 A B s)"
++ "≔ λA.λB. Σ-ind A B (λs. B (pr1 A B s)) (λa.λBa. Ba)"
++ "in ★"
typecheck tr TTop

3
tests/id1.pi Normal file
View File

@ -0,0 +1,3 @@
let transport : Π (A : Type) Π (f : A → Type) Π (x : A) Π (y : A)
Id A x y → f x → f y
≔ λA.λf.λx.λy. J A x y (λa.λb.λ_. f a → f b) (λa.a)

3
tests/id2.pi Normal file
View File

@ -0,0 +1,3 @@
let ap : Π (A : Type) Π (B : Type) Π (f : A → B)
Π (x : A) Π (y : A) Id A x y → Id B (f x) (f y)
≔ λA.λB.λf.λx.λy. J A x y (λa.λb.λ_. Id B (f a) (f b)) (refl B (f x))