mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-26 05:01:34 +03:00
1786 lines
57 KiB
Idris
1786 lines
57 KiB
Idris
module Core.TT
|
|
|
|
import public Core.FC
|
|
import public Core.Name
|
|
|
|
import Data.List
|
|
import Data.Nat
|
|
import Data.Vect
|
|
import Decidable.Equality
|
|
|
|
import Libraries.Data.NameMap
|
|
import Libraries.Data.Primitives
|
|
import Libraries.Text.PrettyPrint.Prettyprinter
|
|
import Libraries.Text.PrettyPrint.Prettyprinter.Util
|
|
|
|
import public Algebra
|
|
|
|
%default covering
|
|
|
|
public export
|
|
data NameType : Type where
|
|
Bound : NameType
|
|
Func : NameType
|
|
DataCon : (tag : Int) -> (arity : Nat) -> NameType
|
|
TyCon : (tag : Int) -> (arity : Nat) -> NameType
|
|
|
|
export
|
|
covering
|
|
Show NameType where
|
|
showPrec d Bound = "Bound"
|
|
showPrec d Func = "Func"
|
|
showPrec d (DataCon tag ar) = showCon d "DataCon" $ showArg tag ++ showArg ar
|
|
showPrec d (TyCon tag ar) = showCon d "TyCon" $ showArg tag ++ showArg ar
|
|
|
|
export
|
|
isCon : NameType -> Maybe (Int, Nat)
|
|
isCon (DataCon t a) = Just (t, a)
|
|
isCon (TyCon t a) = Just (t, a)
|
|
isCon _ = Nothing
|
|
|
|
public export
|
|
record KindedName where
|
|
constructor MkKindedName
|
|
nameKind : Maybe NameType
|
|
fullName : Name -- fully qualified name
|
|
rawName : Name
|
|
|
|
export
|
|
defaultKindedName : Name -> KindedName
|
|
defaultKindedName nm = MkKindedName Nothing nm nm
|
|
|
|
export
|
|
Show KindedName where show = show . rawName
|
|
|
|
export
|
|
covering
|
|
[Raw] Show KindedName where
|
|
showPrec d (MkKindedName nm fn rn) =
|
|
showCon d "MkKindedName" $ showArg nm ++ showArg @{Raw} fn ++ showArg @{Raw} rn
|
|
|
|
public export
|
|
data PrimType
|
|
= IntType
|
|
| Int8Type
|
|
| Int16Type
|
|
| Int32Type
|
|
| Int64Type
|
|
| IntegerType
|
|
| Bits8Type
|
|
| Bits16Type
|
|
| Bits32Type
|
|
| Bits64Type
|
|
| StringType
|
|
| CharType
|
|
| DoubleType
|
|
| WorldType
|
|
|
|
public export
|
|
data Constant
|
|
= I Int
|
|
| I8 Int8
|
|
| I16 Int16
|
|
| I32 Int32
|
|
| I64 Int64
|
|
| BI Integer
|
|
| B8 Bits8
|
|
| B16 Bits16
|
|
| B32 Bits32
|
|
| B64 Bits64
|
|
| Str String
|
|
| Ch Char
|
|
| Db Double
|
|
| PrT PrimType
|
|
| WorldVal
|
|
|
|
export
|
|
isConstantType : Name -> Maybe PrimType
|
|
isConstantType (UN (Basic n)) = case n of
|
|
"Int" => Just IntType
|
|
"Int8" => Just Int8Type
|
|
"Int16" => Just Int16Type
|
|
"Int32" => Just Int32Type
|
|
"Int64" => Just Int64Type
|
|
"Integer" => Just IntegerType
|
|
"Bits8" => Just Bits8Type
|
|
"Bits16" => Just Bits16Type
|
|
"Bits32" => Just Bits32Type
|
|
"Bits64" => Just Bits64Type
|
|
"String" => Just StringType
|
|
"Char" => Just CharType
|
|
"Double" => Just DoubleType
|
|
"%World" => Just WorldType
|
|
_ => Nothing
|
|
isConstantType _ = Nothing
|
|
|
|
export
|
|
isPrimType : Constant -> Bool
|
|
isPrimType (PrT _) = True
|
|
isPrimType _ = False
|
|
|
|
export
|
|
primTypeEq : (x, y : PrimType) -> Maybe (x = y)
|
|
primTypeEq IntType IntType = Just Refl
|
|
primTypeEq Int8Type Int8Type = Just Refl
|
|
primTypeEq Int16Type Int16Type = Just Refl
|
|
primTypeEq Int32Type Int32Type = Just Refl
|
|
primTypeEq Int64Type Int64Type = Just Refl
|
|
primTypeEq IntegerType IntegerType = Just Refl
|
|
primTypeEq StringType StringType = Just Refl
|
|
primTypeEq CharType CharType = Just Refl
|
|
primTypeEq DoubleType DoubleType = Just Refl
|
|
primTypeEq WorldType WorldType = Just Refl
|
|
primTypeEq _ _ = Nothing
|
|
|
|
-- TODO : The `TempXY` instances can be removed after the next release
|
|
-- (see also `Libraries.Data.Primitives`)
|
|
export
|
|
constantEq : (x, y : Constant) -> Maybe (x = y)
|
|
constantEq (I x) (I y) = case decEq x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (I8 x) (I8 y) = case decEq @{TempI8} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (I16 x) (I16 y) = case decEq @{TempI16} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (I32 x) (I32 y) = case decEq @{TempI32} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (I64 x) (I64 y) = case decEq @{TempI64} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (B8 x) (B8 y) = case decEq @{TempB8} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (B16 x) (B16 y) = case decEq @{TempB16} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (B32 x) (B32 y) = case decEq @{TempB32} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (B64 x) (B64 y) = case decEq @{TempB64} x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (BI x) (BI y) = case decEq x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (Str x) (Str y) = case decEq x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (Ch x) (Ch y) = case decEq x y of
|
|
Yes Refl => Just Refl
|
|
No contra => Nothing
|
|
constantEq (Db x) (Db y) = Nothing -- no DecEq for Doubles!
|
|
constantEq (PrT x) (PrT y) = cong PrT <$> primTypeEq x y
|
|
constantEq WorldVal WorldVal = Just Refl
|
|
|
|
constantEq _ _ = Nothing
|
|
|
|
export
|
|
Show PrimType where
|
|
show IntType = "Int"
|
|
show Int8Type = "Int8"
|
|
show Int16Type = "Int16"
|
|
show Int32Type = "Int32"
|
|
show Int64Type = "Int64"
|
|
show IntegerType = "Integer"
|
|
show Bits8Type = "Bits8"
|
|
show Bits16Type = "Bits16"
|
|
show Bits32Type = "Bits32"
|
|
show Bits64Type = "Bits64"
|
|
show StringType = "String"
|
|
show CharType = "Char"
|
|
show DoubleType = "Double"
|
|
show WorldType = "%World"
|
|
|
|
export
|
|
Show Constant where
|
|
show (I x) = show x
|
|
show (I8 x) = show x
|
|
show (I16 x) = show x
|
|
show (I32 x) = show x
|
|
show (I64 x) = show x
|
|
show (BI x) = show x
|
|
show (B8 x) = show x
|
|
show (B16 x) = show x
|
|
show (B32 x) = show x
|
|
show (B64 x) = show x
|
|
show (Str x) = show x
|
|
show (Ch x) = show x
|
|
show (Db x) = show x
|
|
show (PrT x) = show x
|
|
show WorldVal = "%MkWorld"
|
|
|
|
export
|
|
Pretty PrimType where
|
|
pretty IntType = pretty "Int"
|
|
pretty Int8Type = pretty "Int8"
|
|
pretty Int16Type = pretty "Int16"
|
|
pretty Int32Type = pretty "Int32"
|
|
pretty Int64Type = pretty "Int64"
|
|
pretty IntegerType = pretty "Integer"
|
|
pretty Bits8Type = pretty "Bits8"
|
|
pretty Bits16Type = pretty "Bits16"
|
|
pretty Bits32Type = pretty "Bits32"
|
|
pretty Bits64Type = pretty "Bits64"
|
|
pretty StringType = pretty "String"
|
|
pretty CharType = pretty "Char"
|
|
pretty DoubleType = pretty "Double"
|
|
pretty WorldType = pretty "%World"
|
|
|
|
export
|
|
Pretty Constant where
|
|
pretty (I x) = pretty x
|
|
pretty (I8 x) = pretty x
|
|
pretty (I16 x) = pretty x
|
|
pretty (I32 x) = pretty x
|
|
pretty (I64 x) = pretty x
|
|
pretty (BI x) = pretty x
|
|
pretty (B8 x) = pretty x
|
|
pretty (B16 x) = pretty x
|
|
pretty (B32 x) = pretty x
|
|
pretty (B64 x) = pretty x
|
|
pretty (Str x) = dquotes (pretty x)
|
|
pretty (Ch x) = squotes (pretty x)
|
|
pretty (Db x) = pretty x
|
|
pretty (PrT x) = pretty x
|
|
pretty WorldVal = pretty "%MkWorld"
|
|
|
|
export
|
|
Eq PrimType where
|
|
IntType == IntType = True
|
|
Int8Type == Int8Type = True
|
|
Int16Type == Int16Type = True
|
|
Int32Type == Int32Type = True
|
|
Int64Type == Int64Type = True
|
|
IntegerType == IntegerType = True
|
|
Bits8Type == Bits8Type = True
|
|
Bits16Type == Bits16Type = True
|
|
Bits32Type == Bits32Type = True
|
|
Bits64Type == Bits64Type = True
|
|
StringType == StringType = True
|
|
CharType == CharType = True
|
|
DoubleType == DoubleType = True
|
|
WorldType == WorldType = True
|
|
_ == _ = False
|
|
|
|
export
|
|
Eq Constant where
|
|
(I x) == (I y) = x == y
|
|
(I8 x) == (I8 y) = x == y
|
|
(I16 x) == (I16 y) = x == y
|
|
(I32 x) == (I32 y) = x == y
|
|
(I64 x) == (I64 y) = x == y
|
|
(BI x) == (BI y) = x == y
|
|
(B8 x) == (B8 y) = x == y
|
|
(B16 x) == (B16 y) = x == y
|
|
(B32 x) == (B32 y) = x == y
|
|
(B64 x) == (B64 y) = x == y
|
|
(Str x) == (Str y) = x == y
|
|
(Ch x) == (Ch y) = x == y
|
|
(Db x) == (Db y) = x == y
|
|
(PrT x) == (PrT y) = x == y
|
|
WorldVal == WorldVal = True
|
|
_ == _ = False
|
|
|
|
-- for typecase
|
|
export
|
|
primTypeTag : PrimType -> Int
|
|
-- 1 = ->, 2 = Type
|
|
primTypeTag IntType = 3
|
|
primTypeTag IntegerType = 4
|
|
primTypeTag Bits8Type = 5
|
|
primTypeTag Bits16Type = 6
|
|
primTypeTag Bits32Type = 7
|
|
primTypeTag Bits64Type = 8
|
|
primTypeTag StringType = 9
|
|
primTypeTag CharType = 10
|
|
primTypeTag DoubleType = 11
|
|
primTypeTag WorldType = 12
|
|
primTypeTag Int8Type = 13
|
|
primTypeTag Int16Type = 14
|
|
primTypeTag Int32Type = 15
|
|
primTypeTag Int64Type = 16
|
|
|
|
||| Precision of integral types.
|
|
public export
|
|
data Precision = P Int | Unlimited
|
|
|
|
export
|
|
Eq Precision where
|
|
(P m) == (P n) = m == n
|
|
Unlimited == Unlimited = True
|
|
_ == _ = False
|
|
|
|
export
|
|
Ord Precision where
|
|
compare (P m) (P n) = compare m n
|
|
compare Unlimited Unlimited = EQ
|
|
compare Unlimited _ = GT
|
|
compare _ Unlimited = LT
|
|
|
|
-- so far, we only support limited precision
|
|
-- unsigned integers
|
|
public export
|
|
data IntKind = Signed Precision | Unsigned Int
|
|
|
|
public export
|
|
intKind : PrimType -> Maybe IntKind
|
|
intKind IntegerType = Just $ Signed Unlimited
|
|
intKind Int8Type = Just . Signed $ P 8
|
|
intKind Int16Type = Just . Signed $ P 16
|
|
intKind Int32Type = Just . Signed $ P 32
|
|
intKind Int64Type = Just . Signed $ P 64
|
|
intKind IntType = Just . Signed $ P 64
|
|
intKind Bits8Type = Just $ Unsigned 8
|
|
intKind Bits16Type = Just $ Unsigned 16
|
|
intKind Bits32Type = Just $ Unsigned 32
|
|
intKind Bits64Type = Just $ Unsigned 64
|
|
intKind _ = Nothing
|
|
|
|
public export
|
|
precision : IntKind -> Precision
|
|
precision (Signed p) = p
|
|
precision (Unsigned p) = P p
|
|
|
|
-- All the internal operators, parameterised by their arity
|
|
public export
|
|
data PrimFn : Nat -> Type where
|
|
Add : (ty : PrimType) -> PrimFn 2
|
|
Sub : (ty : PrimType) -> PrimFn 2
|
|
Mul : (ty : PrimType) -> PrimFn 2
|
|
Div : (ty : PrimType) -> PrimFn 2
|
|
Mod : (ty : PrimType) -> PrimFn 2
|
|
Neg : (ty : PrimType) -> PrimFn 1
|
|
ShiftL : (ty : PrimType) -> PrimFn 2
|
|
ShiftR : (ty : PrimType) -> PrimFn 2
|
|
|
|
BAnd : (ty : PrimType) -> PrimFn 2
|
|
BOr : (ty : PrimType) -> PrimFn 2
|
|
BXOr : (ty : PrimType) -> PrimFn 2
|
|
|
|
LT : (ty : PrimType) -> PrimFn 2
|
|
LTE : (ty : PrimType) -> PrimFn 2
|
|
EQ : (ty : PrimType) -> PrimFn 2
|
|
GTE : (ty : PrimType) -> PrimFn 2
|
|
GT : (ty : PrimType) -> PrimFn 2
|
|
|
|
StrLength : PrimFn 1
|
|
StrHead : PrimFn 1
|
|
StrTail : PrimFn 1
|
|
StrIndex : PrimFn 2
|
|
StrCons : PrimFn 2
|
|
StrAppend : PrimFn 2
|
|
StrReverse : PrimFn 1
|
|
StrSubstr : PrimFn 3
|
|
|
|
DoubleExp : PrimFn 1
|
|
DoubleLog : PrimFn 1
|
|
DoublePow : PrimFn 2
|
|
DoubleSin : PrimFn 1
|
|
DoubleCos : PrimFn 1
|
|
DoubleTan : PrimFn 1
|
|
DoubleASin : PrimFn 1
|
|
DoubleACos : PrimFn 1
|
|
DoubleATan : PrimFn 1
|
|
DoubleSqrt : PrimFn 1
|
|
DoubleFloor : PrimFn 1
|
|
DoubleCeiling : PrimFn 1
|
|
|
|
Cast : PrimType -> PrimType -> PrimFn 1
|
|
BelieveMe : PrimFn 3
|
|
Crash : PrimFn 2
|
|
|
|
export
|
|
Show (PrimFn arity) where
|
|
show (Add ty) = "+" ++ show ty
|
|
show (Sub ty) = "-" ++ show ty
|
|
show (Mul ty) = "*" ++ show ty
|
|
show (Div ty) = "/" ++ show ty
|
|
show (Mod ty) = "%" ++ show ty
|
|
show (Neg ty) = "neg " ++ show ty
|
|
show (ShiftL ty) = "shl " ++ show ty
|
|
show (ShiftR ty) = "shr " ++ show ty
|
|
show (BAnd ty) = "and " ++ show ty
|
|
show (BOr ty) = "or " ++ show ty
|
|
show (BXOr ty) = "xor " ++ show ty
|
|
show (LT ty) = "<" ++ show ty
|
|
show (LTE ty) = "<=" ++ show ty
|
|
show (EQ ty) = "==" ++ show ty
|
|
show (GTE ty) = ">=" ++ show ty
|
|
show (GT ty) = ">" ++ show ty
|
|
show StrLength = "op_strlen"
|
|
show StrHead = "op_strhead"
|
|
show StrTail = "op_strtail"
|
|
show StrIndex = "op_strindex"
|
|
show StrCons = "op_strcons"
|
|
show StrAppend = "++"
|
|
show StrReverse = "op_strrev"
|
|
show StrSubstr = "op_strsubstr"
|
|
show DoubleExp = "op_doubleExp"
|
|
show DoubleLog = "op_doubleLog"
|
|
show DoublePow = "op_doublePow"
|
|
show DoubleSin = "op_doubleSin"
|
|
show DoubleCos = "op_doubleCos"
|
|
show DoubleTan = "op_doubleTan"
|
|
show DoubleASin = "op_doubleASin"
|
|
show DoubleACos = "op_doubleACos"
|
|
show DoubleATan = "op_doubleATan"
|
|
show DoubleSqrt = "op_doubleSqrt"
|
|
show DoubleFloor = "op_doubleFloor"
|
|
show DoubleCeiling = "op_doubleCeiling"
|
|
show (Cast x y) = "cast-" ++ show x ++ "-" ++ show y
|
|
show BelieveMe = "believe_me"
|
|
show Crash = "crash"
|
|
|
|
public export
|
|
data PiInfo t = Implicit | Explicit | AutoImplicit | DefImplicit t
|
|
|
|
namespace PiInfo
|
|
|
|
export
|
|
isImplicit : PiInfo t -> Bool
|
|
isImplicit Explicit = False
|
|
isImplicit _ = True
|
|
|
|
export
|
|
eqPiInfoBy : (t -> u -> Bool) -> PiInfo t -> PiInfo u -> Bool
|
|
eqPiInfoBy eqT = go where
|
|
|
|
go : PiInfo t -> PiInfo u -> Bool
|
|
go Implicit Implicit = True
|
|
go Explicit Explicit = True
|
|
go AutoImplicit AutoImplicit = True
|
|
go (DefImplicit t) (DefImplicit t') = eqT t t'
|
|
go _ _ = False
|
|
|
|
-- There's few places where we need the default - it's just when checking if
|
|
-- there's a default during elaboration - so often it's easier just to erase it
|
|
-- to a normal implicit
|
|
export
|
|
forgetDef : PiInfo t -> PiInfo t'
|
|
forgetDef Explicit = Explicit
|
|
forgetDef Implicit = Implicit
|
|
forgetDef AutoImplicit = AutoImplicit
|
|
forgetDef (DefImplicit t) = Implicit
|
|
|
|
export
|
|
Show t => Show (PiInfo t) where
|
|
show Implicit = "Implicit"
|
|
show Explicit = "Explicit"
|
|
show AutoImplicit = "AutoImplicit"
|
|
show (DefImplicit t) = "DefImplicit " ++ show t
|
|
|
|
export
|
|
Eq t => Eq (PiInfo t) where
|
|
(==) = eqPiInfoBy (==)
|
|
|
|
public export
|
|
data Binder : Type -> Type where
|
|
-- Lambda bound variables with their implicitness
|
|
Lam : FC -> RigCount -> PiInfo type -> (ty : type) -> Binder type
|
|
-- Let bound variables with their value
|
|
Let : FC -> RigCount -> (val : type) -> (ty : type) -> Binder type
|
|
-- Forall/pi bound variables with their implicitness
|
|
Pi : FC -> RigCount -> PiInfo type -> (ty : type) -> Binder type
|
|
-- pattern bound variables. The PiInfo gives the implicitness at the
|
|
-- point it was bound (Explicit if it was explicitly named in the
|
|
-- program)
|
|
PVar : FC -> RigCount -> PiInfo type -> (ty : type) -> Binder type
|
|
-- variable bound for an as pattern (Like a let, but no computational
|
|
-- force, and only used on the lhs. Converted to a let on the rhs because
|
|
-- we want the computational behaviour.)
|
|
PLet : FC -> RigCount -> (val : type) -> (ty : type) -> Binder type
|
|
-- the type of pattern bound variables
|
|
PVTy : FC -> RigCount -> (ty : type) -> Binder type
|
|
|
|
export
|
|
isLet : Binder t -> Bool
|
|
isLet (Let _ _ _ _) = True
|
|
isLet _ = False
|
|
|
|
export
|
|
binderLoc : Binder tm -> FC
|
|
binderLoc (Lam fc _ x ty) = fc
|
|
binderLoc (Let fc _ val ty) = fc
|
|
binderLoc (Pi fc _ x ty) = fc
|
|
binderLoc (PVar fc _ p ty) = fc
|
|
binderLoc (PLet fc _ val ty) = fc
|
|
binderLoc (PVTy fc _ ty) = fc
|
|
|
|
export
|
|
binderType : Binder tm -> tm
|
|
binderType (Lam _ _ x ty) = ty
|
|
binderType (Let _ _ val ty) = ty
|
|
binderType (Pi _ _ x ty) = ty
|
|
binderType (PVar _ _ _ ty) = ty
|
|
binderType (PLet _ _ val ty) = ty
|
|
binderType (PVTy _ _ ty) = ty
|
|
|
|
export
|
|
multiplicity : Binder tm -> RigCount
|
|
multiplicity (Lam _ c x ty) = c
|
|
multiplicity (Let _ c val ty) = c
|
|
multiplicity (Pi _ c x ty) = c
|
|
multiplicity (PVar _ c p ty) = c
|
|
multiplicity (PLet _ c val ty) = c
|
|
multiplicity (PVTy _ c ty) = c
|
|
|
|
export
|
|
piInfo : Binder tm -> PiInfo tm
|
|
piInfo (Lam _ c x ty) = x
|
|
piInfo (Let _ c val ty) = Explicit
|
|
piInfo (Pi _ c x ty) = x
|
|
piInfo (PVar _ c p ty) = p
|
|
piInfo (PLet _ c val ty) = Explicit
|
|
piInfo (PVTy _ c ty) = Explicit
|
|
|
|
export
|
|
isImplicit : Binder tm -> Bool
|
|
isImplicit = PiInfo.isImplicit . piInfo
|
|
|
|
export
|
|
setMultiplicity : Binder tm -> RigCount -> Binder tm
|
|
setMultiplicity (Lam fc _ x ty) c = Lam fc c x ty
|
|
setMultiplicity (Let fc _ val ty) c = Let fc c val ty
|
|
setMultiplicity (Pi fc _ x ty) c = Pi fc c x ty
|
|
setMultiplicity (PVar fc _ p ty) c = PVar fc c p ty
|
|
setMultiplicity (PLet fc _ val ty) c = PLet fc c val ty
|
|
setMultiplicity (PVTy fc _ ty) c = PVTy fc c ty
|
|
|
|
Show ty => Show (Binder ty) where
|
|
show (Lam _ c _ t) = "\\" ++ showCount c ++ show t
|
|
show (Pi _ c _ t) = "Pi " ++ showCount c ++ show t
|
|
show (Let _ c v t) = "let " ++ showCount c ++ show v ++ " : " ++ show t
|
|
show (PVar _ c _ t) = "pat " ++ showCount c ++ show t
|
|
show (PLet _ c v t) = "plet " ++ showCount c ++ show v ++ " : " ++ show t
|
|
show (PVTy _ c t) = "pty " ++ showCount c ++ show t
|
|
|
|
export
|
|
setType : Binder tm -> tm -> Binder tm
|
|
setType (Lam fc c x _) ty = Lam fc c x ty
|
|
setType (Let fc c val _) ty = Let fc c val ty
|
|
setType (Pi fc c x _) ty = Pi fc c x ty
|
|
setType (PVar fc c p _) ty = PVar fc c p ty
|
|
setType (PLet fc c val _) ty = PLet fc c val ty
|
|
setType (PVTy fc c _) ty = PVTy fc c ty
|
|
|
|
export
|
|
Functor PiInfo where
|
|
map func Explicit = Explicit
|
|
map func Implicit = Implicit
|
|
map func AutoImplicit = AutoImplicit
|
|
map func (DefImplicit t) = (DefImplicit (func t))
|
|
|
|
export
|
|
Foldable PiInfo where
|
|
foldr f acc Implicit = acc
|
|
foldr f acc Explicit = acc
|
|
foldr f acc AutoImplicit = acc
|
|
foldr f acc (DefImplicit x) = f x acc
|
|
|
|
export
|
|
Traversable PiInfo where
|
|
traverse f Implicit = pure Implicit
|
|
traverse f Explicit = pure Explicit
|
|
traverse f AutoImplicit = pure AutoImplicit
|
|
traverse f (DefImplicit x) = map DefImplicit (f x)
|
|
|
|
export
|
|
Functor Binder where
|
|
map func (Lam fc c x ty) = Lam fc c (map func x) (func ty)
|
|
map func (Let fc c val ty) = Let fc c (func val) (func ty)
|
|
map func (Pi fc c x ty) = Pi fc c (map func x) (func ty)
|
|
map func (PVar fc c p ty) = PVar fc c (map func p) (func ty)
|
|
map func (PLet fc c val ty) = PLet fc c (func val) (func ty)
|
|
map func (PVTy fc c ty) = PVTy fc c (func ty)
|
|
|
|
export
|
|
Foldable Binder where
|
|
foldr f acc (Lam fc c x ty) = foldr f (f ty acc) x
|
|
foldr f acc (Let fc c val ty) = f val (f ty acc)
|
|
foldr f acc (Pi fc c x ty) = foldr f (f ty acc) x
|
|
foldr f acc (PVar fc c p ty) = foldr f (f ty acc) p
|
|
foldr f acc (PLet fc c val ty) = f val (f ty acc)
|
|
foldr f acc (PVTy fc c ty) = f ty acc
|
|
|
|
export
|
|
Traversable Binder where
|
|
traverse f (Lam fc c x ty) = Lam fc c <$> traverse f x <*> f ty
|
|
traverse f (Let fc c val ty) = Let fc c <$> f val <*> f ty
|
|
traverse f (Pi fc c x ty) = Pi fc c <$> traverse f x <*> f ty
|
|
traverse f (PVar fc c p ty) = PVar fc c <$> traverse f p <*> f ty
|
|
traverse f (PLet fc c val ty) = PLet fc c <$> f val <*> f ty
|
|
traverse f (PVTy fc c ty) = PVTy fc c <$> f ty
|
|
|
|
public export
|
|
data IsVar : Name -> Nat -> List Name -> Type where
|
|
First : IsVar n Z (n :: ns)
|
|
Later : IsVar n i ns -> IsVar n (S i) (m :: ns)
|
|
|
|
export
|
|
dropLater : IsVar nm (S idx) (v :: vs) -> IsVar nm idx vs
|
|
dropLater (Later p) = p
|
|
|
|
export
|
|
mkVar : (wkns : List Name) -> IsVar nm (length wkns) (wkns ++ nm :: vars)
|
|
mkVar [] = First
|
|
mkVar (w :: ws) = Later (mkVar ws)
|
|
|
|
public export
|
|
dropVar : (ns : List Name) -> {idx : Nat} -> (0 p : IsVar name idx ns) -> List Name
|
|
dropVar (n :: xs) First = xs
|
|
dropVar (n :: xs) (Later p) = n :: dropVar xs p
|
|
|
|
public export
|
|
data Var : List Name -> Type where
|
|
MkVar : {i : Nat} -> (0 p : IsVar n i vars) -> Var vars
|
|
|
|
namespace Var
|
|
|
|
export
|
|
later : Var ns -> Var (n :: ns)
|
|
later (MkVar p) = MkVar (Later p)
|
|
|
|
export
|
|
sameVar : Var xs -> Var xs -> Bool
|
|
sameVar (MkVar {i=x} _) (MkVar {i=y} _) = x == y
|
|
|
|
export
|
|
varIdx : Var xs -> Nat
|
|
varIdx (MkVar {i} _) = i
|
|
|
|
export
|
|
dropFirst : List (Var (v :: vs)) -> List (Var vs)
|
|
dropFirst [] = []
|
|
dropFirst (MkVar First :: vs) = dropFirst vs
|
|
dropFirst (MkVar (Later p) :: vs) = MkVar p :: dropFirst vs
|
|
|
|
export
|
|
Show (Var ns) where
|
|
show (MkVar {i} _) = show i
|
|
|
|
namespace HasLength
|
|
|
|
public export
|
|
data HasLength : Nat -> List a -> Type where
|
|
Z : HasLength Z []
|
|
S : HasLength n as -> HasLength (S n) (a :: as)
|
|
|
|
export
|
|
sucR : HasLength n xs -> HasLength (S n) (xs ++ [x])
|
|
sucR Z = S Z
|
|
sucR (S n) = S (sucR n)
|
|
|
|
export
|
|
hlAppend : HasLength m xs -> HasLength n ys -> HasLength (m + n) (xs ++ ys)
|
|
hlAppend Z ys = ys
|
|
hlAppend (S xs) ys = S (hlAppend xs ys)
|
|
|
|
export
|
|
mkHasLength : (xs : List a) -> HasLength (length xs) xs
|
|
mkHasLength [] = Z
|
|
mkHasLength (_ :: xs) = S (mkHasLength xs)
|
|
|
|
export
|
|
take : (n : Nat) -> (xs : Stream a) -> HasLength n (take n xs)
|
|
take Z _ = Z
|
|
take (S n) (x :: xs) = S (take n xs)
|
|
|
|
export
|
|
cast : {ys : _} -> List.length xs = List.length ys -> HasLength m xs -> HasLength m ys
|
|
cast {ys = []} eq Z = Z
|
|
cast {ys = y :: ys} eq (S p) = S (cast (succInjective _ _ eq) p)
|
|
where
|
|
succInjective : (0 l, r : Nat) -> S l = S r -> l = r
|
|
succInjective _ _ Refl = Refl
|
|
|
|
hlReverseOnto : HasLength m acc -> HasLength n xs -> HasLength (m + n) (reverseOnto acc xs)
|
|
hlReverseOnto p Z = rewrite plusZeroRightNeutral m in p
|
|
hlReverseOnto {n = S n} p (S q) = rewrite sym (plusSuccRightSucc m n) in hlReverseOnto (S p) q
|
|
|
|
export
|
|
hlReverse : HasLength m acc -> HasLength m (reverse acc)
|
|
hlReverse = hlReverseOnto Z
|
|
|
|
public export
|
|
record SizeOf {a : Type} (xs : List a) where
|
|
constructor MkSizeOf
|
|
size : Nat
|
|
0 hasLength : HasLength size xs
|
|
|
|
namespace SizeOf
|
|
|
|
export
|
|
0 theList : SizeOf {a} xs -> List a
|
|
theList _ = xs
|
|
|
|
export
|
|
zero : SizeOf []
|
|
zero = MkSizeOf Z Z
|
|
|
|
export
|
|
suc : SizeOf as -> SizeOf (a :: as)
|
|
suc (MkSizeOf n p) = MkSizeOf (S n) (S p)
|
|
|
|
-- ||| suc but from the right
|
|
export
|
|
sucR : SizeOf as -> SizeOf (as ++ [a])
|
|
sucR (MkSizeOf n p) = MkSizeOf (S n) (sucR p)
|
|
|
|
export
|
|
(+) : SizeOf xs -> SizeOf ys -> SizeOf (xs ++ ys)
|
|
MkSizeOf m p + MkSizeOf n q = MkSizeOf (m + n) (hlAppend p q)
|
|
|
|
export
|
|
mkSizeOf : (xs : List a) -> SizeOf xs
|
|
mkSizeOf xs = MkSizeOf (length xs) (mkHasLength xs)
|
|
|
|
export
|
|
reverse : SizeOf xs -> SizeOf (reverse xs)
|
|
reverse (MkSizeOf n p) = MkSizeOf n (hlReverse p)
|
|
|
|
export
|
|
map : SizeOf xs -> SizeOf (map f xs)
|
|
map (MkSizeOf n p) = MkSizeOf n (cast (sym $ lengthMap xs) p)
|
|
|
|
export
|
|
take : {n : Nat} -> {0 xs : Stream a} -> SizeOf (take n xs)
|
|
take = MkSizeOf n (take n xs)
|
|
|
|
namespace SizedView
|
|
|
|
public export
|
|
data SizedView : SizeOf as -> Type where
|
|
Z : SizedView (MkSizeOf Z Z)
|
|
S : (n : SizeOf as) -> SizedView (suc {a} n)
|
|
|
|
export
|
|
sizedView : (p : SizeOf as) -> SizedView p
|
|
sizedView (MkSizeOf Z Z) = Z
|
|
sizedView (MkSizeOf (S n) (S p)) = S (MkSizeOf n p)
|
|
|
|
namespace CList
|
|
-- A list correspoding to another list
|
|
public export
|
|
data CList : List a -> Type -> Type where
|
|
Nil : CList [] ty
|
|
(::) : (x : ty) -> CList cs ty -> CList (c :: cs) ty
|
|
|
|
-- Typechecked terms
|
|
-- These are guaranteed to be well-scoped wrt local variables, because they are
|
|
-- indexed by the names of local variables in scope
|
|
public export
|
|
data LazyReason = LInf | LLazy | LUnknown
|
|
|
|
-- For as patterns matching linear arguments, select which side is
|
|
-- consumed
|
|
public export
|
|
data UseSide = UseLeft | UseRight
|
|
|
|
public export
|
|
data Term : List Name -> Type where
|
|
Local : FC -> (isLet : Maybe Bool) ->
|
|
(idx : Nat) -> (0 p : IsVar name idx vars) -> Term vars
|
|
Ref : FC -> NameType -> (name : Name) -> Term vars
|
|
-- Metavariables and the scope they are applied to
|
|
Meta : FC -> Name -> Int -> List (Term vars) -> Term vars
|
|
Bind : FC -> (x : Name) ->
|
|
(b : Binder (Term vars)) ->
|
|
(scope : Term (x :: vars)) -> Term vars
|
|
App : FC -> (fn : Term vars) -> (arg : Term vars) -> Term vars
|
|
-- as patterns; since we check LHS patterns as terms before turning
|
|
-- them into patterns, this helps us get it right. When normalising,
|
|
-- we just reduce the inner term and ignore the 'as' part
|
|
-- The 'as' part should really be a Name rather than a Term, but it's
|
|
-- easier this way since it gives us the ability to work with unresolved
|
|
-- names (Ref) and resolved names (Local) without having to define a
|
|
-- special purpose thing. (But it'd be nice to tidy that up, nevertheless)
|
|
As : FC -> UseSide -> (as : Term vars) -> (pat : Term vars) -> Term vars
|
|
-- Typed laziness annotations
|
|
TDelayed : FC -> LazyReason -> Term vars -> Term vars
|
|
TDelay : FC -> LazyReason -> (ty : Term vars) -> (arg : Term vars) -> Term vars
|
|
TForce : FC -> LazyReason -> Term vars -> Term vars
|
|
PrimVal : FC -> (c : Constant) -> Term vars
|
|
Erased : FC -> (imp : Bool) -> -- True == impossible term, for coverage checker
|
|
Term vars
|
|
TType : FC -> Name -> -- universe variable
|
|
Term vars
|
|
|
|
-- Remove/restore the given namespace from all Refs. This is to allow
|
|
-- writing terms and case trees to disk without repeating the same namespace
|
|
-- all over the place.
|
|
public export
|
|
interface StripNamespace a where
|
|
trimNS : Namespace -> a -> a
|
|
restoreNS : Namespace -> a -> a
|
|
|
|
export
|
|
StripNamespace (Term vars) where
|
|
trimNS ns tm@(Ref fc x (NS tns n))
|
|
= if ns == tns then Ref fc x (NS (unsafeFoldNamespace []) n) else tm
|
|
-- ^ A blank namespace, rather than a UN, so we don't catch primitive
|
|
-- names which are represented as UN.
|
|
trimNS ns (Meta fc x y xs)
|
|
= Meta fc x y (map (trimNS ns) xs)
|
|
trimNS ns (Bind fc x b scope)
|
|
= Bind fc x (map (trimNS ns) b) (trimNS ns scope)
|
|
trimNS ns (App fc fn arg)
|
|
= App fc (trimNS ns fn) (trimNS ns arg)
|
|
trimNS ns (As fc s p tm)
|
|
= As fc s (trimNS ns p) (trimNS ns tm)
|
|
trimNS ns (TDelayed fc x y)
|
|
= TDelayed fc x (trimNS ns y)
|
|
trimNS ns (TDelay fc x t y)
|
|
= TDelay fc x (trimNS ns t) (trimNS ns y)
|
|
trimNS ns (TForce fc r y)
|
|
= TForce fc r (trimNS ns y)
|
|
trimNS ns tm = tm
|
|
|
|
restoreNS ns tm@(Ref fc x (NS tmns n))
|
|
= if isNil (unsafeUnfoldNamespace tmns)
|
|
then Ref fc x (NS ns n)
|
|
else tm
|
|
restoreNS ns (Meta fc x y xs)
|
|
= Meta fc x y (map (restoreNS ns) xs)
|
|
restoreNS ns (Bind fc x b scope)
|
|
= Bind fc x (map (restoreNS ns) b) (restoreNS ns scope)
|
|
restoreNS ns (App fc fn arg)
|
|
= App fc (restoreNS ns fn) (restoreNS ns arg)
|
|
restoreNS ns (As fc s p tm)
|
|
= As fc s (restoreNS ns p) (restoreNS ns tm)
|
|
restoreNS ns (TDelayed fc x y)
|
|
= TDelayed fc x (restoreNS ns y)
|
|
restoreNS ns (TDelay fc x t y)
|
|
= TDelay fc x (restoreNS ns t) (restoreNS ns y)
|
|
restoreNS ns (TForce fc r y)
|
|
= TForce fc r (restoreNS ns y)
|
|
restoreNS ns tm = tm
|
|
|
|
export
|
|
isErased : Term vars -> Bool
|
|
isErased (Erased _ _) = True
|
|
isErased _ = False
|
|
|
|
export
|
|
getLoc : Term vars -> FC
|
|
getLoc (Local fc _ _ _) = fc
|
|
getLoc (Ref fc _ _) = fc
|
|
getLoc (Meta fc _ _ _) = fc
|
|
getLoc (Bind fc _ _ _) = fc
|
|
getLoc (App fc _ _) = fc
|
|
getLoc (As fc _ _ _) = fc
|
|
getLoc (TDelayed fc _ _) = fc
|
|
getLoc (TDelay fc _ _ _) = fc
|
|
getLoc (TForce fc _ _) = fc
|
|
getLoc (PrimVal fc _) = fc
|
|
getLoc (Erased fc i) = fc
|
|
getLoc (TType fc _) = fc
|
|
|
|
export
|
|
Eq LazyReason where
|
|
(==) LInf LInf = True
|
|
(==) LLazy LLazy = True
|
|
(==) LUnknown LUnknown = True
|
|
(==) _ _ = False
|
|
|
|
export
|
|
Show LazyReason where
|
|
show LInf = "Inf"
|
|
show LLazy = "Lazy"
|
|
show LUnknown = "Unkown"
|
|
|
|
export
|
|
compatible : LazyReason -> LazyReason -> Bool
|
|
compatible LUnknown _ = True
|
|
compatible _ LUnknown = True
|
|
compatible x y = x == y
|
|
|
|
export
|
|
eqBinderBy : (t -> u -> Bool) -> (Binder t -> Binder u -> Bool)
|
|
eqBinderBy eqTU = go where
|
|
|
|
go : Binder t -> Binder u -> Bool
|
|
go (Lam _ c p ty) (Lam _ c' p' ty') = c == c' && eqPiInfoBy eqTU p p' && eqTU ty ty'
|
|
go (Let _ c v ty) (Let _ c' v' ty') = c == c' && eqTU v v' && eqTU ty ty'
|
|
go (Pi _ c p ty) (Pi _ c' p' ty') = c == c' && eqPiInfoBy eqTU p p' && eqTU ty ty'
|
|
go (PVar _ c p ty) (PVar _ c' p' ty') = c == c' && eqPiInfoBy eqTU p p' && eqTU ty ty'
|
|
go (PLet _ c v ty) (PLet _ c' v' ty') = c == c' && eqTU v v' && eqTU ty ty'
|
|
go (PVTy _ c ty) (PVTy _ c' ty') = c == c' && eqTU ty ty'
|
|
go _ _ = False
|
|
|
|
export
|
|
Eq a => Eq (Binder a) where
|
|
(==) = eqBinderBy (==)
|
|
|
|
export
|
|
total
|
|
Eq (Term vars) where
|
|
(==) (Local _ _ idx _) (Local _ _ idx' _) = idx == idx'
|
|
(==) (Ref _ _ n) (Ref _ _ n') = n == n'
|
|
(==) (Meta _ _ i args) (Meta _ _ i' args')
|
|
= i == i' && assert_total (args == args')
|
|
(==) (Bind _ _ b sc) (Bind _ _ b' sc')
|
|
= assert_total (b == b' && sc == believe_me sc')
|
|
(==) (App _ f a) (App _ f' a') = f == f' && a == a'
|
|
(==) (As _ _ a p) (As _ _ a' p') = a == a' && p == p'
|
|
(==) (TDelayed _ _ t) (TDelayed _ _ t') = t == t'
|
|
(==) (TDelay _ _ t x) (TDelay _ _ t' x') = t == t' && x == x'
|
|
(==) (TForce _ _ t) (TForce _ _ t') = t == t'
|
|
(==) (PrimVal _ c) (PrimVal _ c') = c == c'
|
|
(==) (Erased _ i) (Erased _ i') = i == i'
|
|
(==) (TType _ _) (TType _ _) = True
|
|
(==) _ _ = False
|
|
|
|
-- Check equality, ignoring variable naming and universes
|
|
export
|
|
total
|
|
eqTerm : Term vs -> Term vs' -> Bool
|
|
eqTerm (Local _ _ idx _) (Local _ _ idx' _) = idx == idx'
|
|
eqTerm (Ref _ _ n) (Ref _ _ n') = n == n'
|
|
eqTerm (Meta _ _ i args) (Meta _ _ i' args')
|
|
= i == i' && assert_total (all (uncurry eqTerm) (zip args args'))
|
|
eqTerm (Bind _ _ b sc) (Bind _ _ b' sc')
|
|
= assert_total (eqBinderBy eqTerm b b') && eqTerm sc sc'
|
|
eqTerm (App _ f a) (App _ f' a') = eqTerm f f' && eqTerm a a'
|
|
eqTerm (As _ _ a p) (As _ _ a' p') = eqTerm a a' && eqTerm p p'
|
|
eqTerm (TDelayed _ _ t) (TDelayed _ _ t') = eqTerm t t'
|
|
eqTerm (TDelay _ _ t x) (TDelay _ _ t' x') = eqTerm t t' && eqTerm x x'
|
|
eqTerm (TForce _ _ t) (TForce _ _ t') = eqTerm t t'
|
|
eqTerm (PrimVal _ c) (PrimVal _ c') = c == c'
|
|
eqTerm (Erased _ i) (Erased _ i') = i == i'
|
|
eqTerm (TType _ _) (TType _ _) = True
|
|
eqTerm _ _ = False
|
|
|
|
public export
|
|
interface Weaken tm where
|
|
weaken : {0 vars : List Name} -> tm vars -> tm (n :: vars)
|
|
weakenNs : SizeOf ns -> tm vars -> tm (ns ++ vars)
|
|
|
|
weakenNs p t = case sizedView p of
|
|
Z => t
|
|
S p => weaken (weakenNs p t)
|
|
|
|
weaken = weakenNs (suc zero)
|
|
|
|
public export
|
|
data Visibility = Private | Export | Public
|
|
|
|
export
|
|
Show Visibility where
|
|
show Private = "private"
|
|
show Export = "export"
|
|
show Public = "public export"
|
|
|
|
export
|
|
Pretty Visibility where
|
|
pretty Private = pretty "private"
|
|
pretty Export = pretty "export"
|
|
pretty Public = pretty "public" <+> pretty "export"
|
|
|
|
export
|
|
Eq Visibility where
|
|
Private == Private = True
|
|
Export == Export = True
|
|
Public == Public = True
|
|
_ == _ = False
|
|
|
|
export
|
|
Ord Visibility where
|
|
compare Private Export = LT
|
|
compare Private Public = LT
|
|
compare Export Public = LT
|
|
|
|
compare Private Private = EQ
|
|
compare Export Export = EQ
|
|
compare Public Public = EQ
|
|
|
|
compare Export Private = GT
|
|
compare Public Private = GT
|
|
compare Public Export = GT
|
|
|
|
public export
|
|
data TotalReq = Total | CoveringOnly | PartialOK
|
|
|
|
export
|
|
Eq TotalReq where
|
|
(==) Total Total = True
|
|
(==) CoveringOnly CoveringOnly = True
|
|
(==) PartialOK PartialOK = True
|
|
(==) _ _ = False
|
|
|
|
||| Bigger means more requirements
|
|
||| So if a definition was checked at b, it can be accepted at a <= b.
|
|
export
|
|
Ord TotalReq where
|
|
PartialOK <= _ = True
|
|
_ <= Total = True
|
|
a <= b = a == b
|
|
|
|
a < b = a <= b && a /= b
|
|
|
|
export
|
|
Show TotalReq where
|
|
show Total = "total"
|
|
show CoveringOnly = "covering"
|
|
show PartialOK = "partial"
|
|
|
|
public export
|
|
data PartialReason
|
|
= NotStrictlyPositive
|
|
| BadCall (List Name)
|
|
| RecPath (List Name)
|
|
|
|
export
|
|
Show PartialReason where
|
|
show NotStrictlyPositive = "not strictly positive"
|
|
show (BadCall [n])
|
|
= "possibly not terminating due to call to " ++ show n
|
|
show (BadCall ns)
|
|
= "possibly not terminating due to calls to " ++ showSep ", " (map show ns)
|
|
show (RecPath ns)
|
|
= "possibly not terminating due to recursive path " ++ showSep " -> " (map show ns)
|
|
|
|
export
|
|
Pretty PartialReason where
|
|
pretty NotStrictlyPositive = reflow "not strictly positive"
|
|
pretty (BadCall [n])
|
|
= reflow "possibly not terminating due to call to" <++> pretty n
|
|
pretty (BadCall ns)
|
|
= reflow "possibly not terminating due to calls to" <++> concatWith (surround (comma <+> space)) (pretty <$> ns)
|
|
pretty (RecPath ns)
|
|
= reflow "possibly not terminating due to recursive path" <++> concatWith (surround (pretty " -> ")) (pretty <$> ns)
|
|
|
|
public export
|
|
data Terminating
|
|
= Unchecked
|
|
| IsTerminating
|
|
| NotTerminating PartialReason
|
|
|
|
export
|
|
Show Terminating where
|
|
show Unchecked = "not yet checked"
|
|
show IsTerminating = "terminating"
|
|
show (NotTerminating p) = show p
|
|
|
|
export
|
|
Pretty Terminating where
|
|
pretty Unchecked = reflow "not yet checked"
|
|
pretty IsTerminating = pretty "terminating"
|
|
pretty (NotTerminating p) = pretty p
|
|
|
|
public export
|
|
data Covering
|
|
= IsCovering
|
|
| MissingCases (List (Term []))
|
|
| NonCoveringCall (List Name)
|
|
|
|
export
|
|
Show Covering where
|
|
show IsCovering = "covering"
|
|
show (MissingCases c) = "not covering all cases"
|
|
show (NonCoveringCall [f])
|
|
= "not covering due to call to function " ++ show f
|
|
show (NonCoveringCall cs)
|
|
= "not covering due to calls to functions " ++ showSep ", " (map show cs)
|
|
|
|
export
|
|
Pretty Covering where
|
|
pretty IsCovering = pretty "covering"
|
|
pretty (MissingCases c) = reflow "not covering all cases"
|
|
pretty (NonCoveringCall [f])
|
|
= reflow "not covering due to call to function" <++> pretty f
|
|
pretty (NonCoveringCall cs)
|
|
= reflow "not covering due to calls to functions" <++> concatWith (surround (comma <+> space)) (pretty <$> cs)
|
|
|
|
-- Totality status of a definition. We separate termination checking from
|
|
-- coverage checking.
|
|
public export
|
|
record Totality where
|
|
constructor MkTotality
|
|
isTerminating : Terminating
|
|
isCovering : Covering
|
|
|
|
export
|
|
Show Totality where
|
|
show tot
|
|
= let t = isTerminating tot
|
|
c = isCovering tot in
|
|
showTot t c
|
|
where
|
|
showTot : Terminating -> Covering -> String
|
|
showTot IsTerminating IsCovering = "total"
|
|
showTot IsTerminating c = show c
|
|
showTot t IsCovering = show t
|
|
showTot t c = show c ++ "; " ++ show t
|
|
|
|
export
|
|
Pretty Totality where
|
|
pretty (MkTotality IsTerminating IsCovering) = pretty "total"
|
|
pretty (MkTotality IsTerminating c) = pretty c
|
|
pretty (MkTotality t IsCovering) = pretty t
|
|
pretty (MkTotality t c) = pretty c <+> semi <++> pretty t
|
|
|
|
export
|
|
unchecked : Totality
|
|
unchecked = MkTotality Unchecked IsCovering
|
|
|
|
export
|
|
isTotal : Totality
|
|
isTotal = MkTotality Unchecked IsCovering
|
|
|
|
export
|
|
notCovering : Totality
|
|
notCovering = MkTotality Unchecked (MissingCases [])
|
|
|
|
public export
|
|
data NVar : Name -> List Name -> Type where
|
|
MkNVar : {i : Nat} -> (0 p : IsVar n i vars) -> NVar n vars
|
|
|
|
namespace NVar
|
|
export
|
|
later : NVar nm ns -> NVar nm (n :: ns)
|
|
later (MkNVar p) = MkNVar (Later p)
|
|
|
|
export
|
|
weakenNVar : SizeOf ns -> NVar name inner -> NVar name (ns ++ inner)
|
|
weakenNVar p x = case sizedView p of
|
|
Z => x
|
|
(S p) => later (weakenNVar p x)
|
|
|
|
export
|
|
insertNVar : SizeOf outer ->
|
|
NVar nm (outer ++ inner) ->
|
|
NVar nm (outer ++ n :: inner)
|
|
insertNVar p v = case sizedView p of
|
|
Z => later v
|
|
(S p) => case v of
|
|
MkNVar First => MkNVar First
|
|
MkNVar (Later v) => later (insertNVar p (MkNVar v))
|
|
|
|
export
|
|
insertVar : SizeOf outer ->
|
|
Var (outer ++ inner) ->
|
|
Var (outer ++ n :: inner)
|
|
insertVar p (MkVar v) = let MkNVar v' = insertNVar p (MkNVar v) in MkVar v'
|
|
|
|
|
|
||| The (partial) inverse to insertVar
|
|
export
|
|
removeVar : SizeOf outer ->
|
|
Var (outer ++ [x] ++ inner) ->
|
|
Maybe (Var (outer ++ inner))
|
|
removeVar out var = case sizedView out of
|
|
Z => case var of
|
|
MkVar First => Nothing
|
|
MkVar (Later p) => Just (MkVar p)
|
|
S out' => case var of
|
|
MkVar First => Just (MkVar First)
|
|
MkVar (Later p) => later <$> removeVar out' (MkVar p)
|
|
|
|
export
|
|
weakenVar : SizeOf ns -> Var inner -> Var (ns ++ inner)
|
|
weakenVar p (MkVar v) = let MkNVar v' = weakenNVar p (MkNVar v) in MkVar v'
|
|
|
|
export
|
|
insertNVarNames : SizeOf outer -> SizeOf ns ->
|
|
NVar name (outer ++ inner) ->
|
|
NVar name (outer ++ (ns ++ inner))
|
|
insertNVarNames p q v = case sizedView p of
|
|
Z => weakenNVar q v
|
|
(S p) => case v of
|
|
MkNVar First => MkNVar First
|
|
MkNVar (Later v') => later (insertNVarNames p q (MkNVar v'))
|
|
|
|
export
|
|
insertVarNames : SizeOf outer -> SizeOf ns ->
|
|
Var (outer ++ inner) ->
|
|
Var (outer ++ (ns ++ inner))
|
|
insertVarNames p q (MkVar v) = let MkNVar v' = insertNVarNames p q (MkNVar v) in MkVar v'
|
|
|
|
export
|
|
insertNames : SizeOf outer -> SizeOf ns ->
|
|
Term (outer ++ inner) ->
|
|
Term (outer ++ (ns ++ inner))
|
|
insertNames out ns (Local fc r idx prf)
|
|
= let MkNVar prf' = insertNVarNames out ns (MkNVar prf) in
|
|
Local fc r _ prf'
|
|
insertNames out ns (Ref fc nt name) = Ref fc nt name
|
|
insertNames out ns (Meta fc name idx args)
|
|
= Meta fc name idx (map (insertNames out ns) args)
|
|
insertNames out ns (Bind fc x b scope)
|
|
= Bind fc x (assert_total (map (insertNames out ns) b))
|
|
(insertNames (suc out) ns scope)
|
|
insertNames out ns (App fc fn arg)
|
|
= App fc (insertNames out ns fn) (insertNames out ns arg)
|
|
insertNames out ns (As fc s as tm)
|
|
= As fc s (insertNames out ns as) (insertNames out ns tm)
|
|
insertNames out ns (TDelayed fc r ty) = TDelayed fc r (insertNames out ns ty)
|
|
insertNames out ns (TDelay fc r ty tm)
|
|
= TDelay fc r (insertNames out ns ty) (insertNames out ns tm)
|
|
insertNames out ns (TForce fc r tm) = TForce fc r (insertNames out ns tm)
|
|
insertNames out ns (PrimVal fc c) = PrimVal fc c
|
|
insertNames out ns (Erased fc i) = Erased fc i
|
|
insertNames out ns (TType fc u) = TType fc u
|
|
|
|
export
|
|
Weaken Term where
|
|
weakenNs p tm = insertNames zero p tm
|
|
|
|
export
|
|
Weaken Var where
|
|
weaken = later
|
|
|
|
export
|
|
varExtend : IsVar x idx xs -> IsVar x idx (xs ++ ys)
|
|
-- What Could Possibly Go Wrong?
|
|
-- This relies on the runtime representation of the term being the same
|
|
-- after embedding! It is just an identity function at run time, though, and
|
|
-- we don't need its definition at compile time, so let's do it...
|
|
varExtend p = believe_me p
|
|
|
|
export
|
|
embed : Term vars -> Term (vars ++ more)
|
|
embed tm = believe_me tm
|
|
|
|
public export
|
|
ClosedTerm : Type
|
|
ClosedTerm = Term []
|
|
|
|
export
|
|
apply : FC -> Term vars -> List (Term vars) -> Term vars
|
|
apply loc fn [] = fn
|
|
apply loc fn (a :: args) = apply loc (App loc fn a) args
|
|
|
|
-- Creates a chain of `App` nodes, each with its own file context
|
|
export
|
|
applyWithFC : Term vars -> List (FC, Term vars) -> Term vars
|
|
applyWithFC fn [] = fn
|
|
applyWithFC fn ((fc, arg) :: args) = applyWithFC (App fc fn arg) args
|
|
|
|
-- Build a simple function type
|
|
export
|
|
fnType : {vars : _} -> FC -> Term vars -> Term vars -> Term vars
|
|
fnType fc arg scope = Bind emptyFC (MN "_" 0) (Pi fc top Explicit arg) (weaken scope)
|
|
|
|
export
|
|
linFnType : {vars : _} -> FC -> Term vars -> Term vars -> Term vars
|
|
linFnType fc arg scope = Bind emptyFC (MN "_" 0) (Pi fc linear Explicit arg) (weaken scope)
|
|
|
|
export
|
|
getFnArgs : Term vars -> (Term vars, List (Term vars))
|
|
getFnArgs tm = getFA [] tm
|
|
where
|
|
getFA : List (Term vars) -> Term vars ->
|
|
(Term vars, List (Term vars))
|
|
getFA args (App _ f a) = getFA (a :: args) f
|
|
getFA args tm = (tm, args)
|
|
|
|
export
|
|
getFn : Term vars -> Term vars
|
|
getFn (App _ f a) = getFn f
|
|
getFn tm = tm
|
|
|
|
export
|
|
getArgs : Term vars -> (List (Term vars))
|
|
getArgs = snd . getFnArgs
|
|
|
|
public export
|
|
data CompatibleVars : List Name -> List Name -> Type where
|
|
CompatPre : CompatibleVars xs xs
|
|
CompatExt : CompatibleVars xs ys -> CompatibleVars (n :: xs) (m :: ys)
|
|
|
|
export
|
|
areVarsCompatible : (xs : List Name) -> (ys : List Name) ->
|
|
Maybe (CompatibleVars xs ys)
|
|
areVarsCompatible [] [] = pure CompatPre
|
|
areVarsCompatible (x :: xs) (y :: ys)
|
|
= do compat <- areVarsCompatible xs ys
|
|
pure (CompatExt compat)
|
|
areVarsCompatible _ _ = Nothing
|
|
|
|
extendCompats : (args : List Name) ->
|
|
CompatibleVars xs ys ->
|
|
CompatibleVars (args ++ xs) (args ++ ys)
|
|
extendCompats [] prf = prf
|
|
extendCompats (x :: xs) prf = CompatExt (extendCompats xs prf)
|
|
|
|
renameLocalRef : CompatibleVars xs ys ->
|
|
{idx : Nat} ->
|
|
(0 p : IsVar name idx xs) ->
|
|
Var ys
|
|
renameLocalRef prf p = believe_me (MkVar p)
|
|
-- renameLocalRef CompatPre First = (MkVar First)
|
|
-- renameLocalRef (CompatExt x) First = (MkVar First)
|
|
-- renameLocalRef CompatPre (Later p) = (MkVar (Later p))
|
|
-- renameLocalRef (CompatExt y) (Later p)
|
|
-- = let (MkVar p') = renameLocalRef y p in MkVar (Later p')
|
|
|
|
renameVarList : CompatibleVars xs ys -> Var xs -> Var ys
|
|
renameVarList prf (MkVar p) = renameLocalRef prf p
|
|
|
|
export
|
|
renameVars : CompatibleVars xs ys -> Term xs -> Term ys
|
|
renameVars compat tm = believe_me tm -- no names in term, so it's identity
|
|
-- This is how we would define it:
|
|
-- renameVars CompatPre tm = tm
|
|
-- renameVars prf (Local fc r idx vprf)
|
|
-- = let MkVar vprf' = renameLocalRef prf vprf in
|
|
-- Local fc r _ vprf'
|
|
-- renameVars prf (Ref fc x name) = Ref fc x name
|
|
-- renameVars prf (Meta fc n i args)
|
|
-- = Meta fc n i (map (renameVars prf) args)
|
|
-- renameVars prf (Bind fc x b scope)
|
|
-- = Bind fc x (map (renameVars prf) b) (renameVars (CompatExt prf) scope)
|
|
-- renameVars prf (App fc fn arg)
|
|
-- = App fc (renameVars prf fn) (renameVars prf arg)
|
|
-- renameVars prf (As fc s as tm)
|
|
-- = As fc s (renameVars prf as) (renameVars prf tm)
|
|
-- renameVars prf (TDelayed fc r ty) = TDelayed fc r (renameVars prf ty)
|
|
-- renameVars prf (TDelay fc r ty tm)
|
|
-- = TDelay fc r (renameVars prf ty) (renameVars prf tm)
|
|
-- renameVars prf (TForce fc r x) = TForce fc r (renameVars prf x)
|
|
-- renameVars prf (PrimVal fc c) = PrimVal fc c
|
|
-- renameVars prf (Erased fc i) = Erased fc i
|
|
-- renameVars prf (TType fc) = TType fc
|
|
|
|
export
|
|
renameTop : (m : Name) -> Term (n :: vars) -> Term (m :: vars)
|
|
renameTop m tm = renameVars (CompatExt CompatPre) tm
|
|
|
|
public export
|
|
data SubVars : List Name -> List Name -> Type where
|
|
SubRefl : SubVars xs xs
|
|
DropCons : SubVars xs ys -> SubVars xs (y :: ys)
|
|
KeepCons : SubVars xs ys -> SubVars (x :: xs) (x :: ys)
|
|
|
|
export
|
|
subElem : {idx : Nat} -> (0 p : IsVar name idx xs) ->
|
|
SubVars ys xs -> Maybe (Var ys)
|
|
subElem prf SubRefl = Just (MkVar prf)
|
|
subElem First (DropCons p) = Nothing
|
|
subElem (Later x) (DropCons p)
|
|
= do MkVar prf' <- subElem x p
|
|
Just (MkVar prf')
|
|
subElem First (KeepCons p) = Just (MkVar First)
|
|
subElem (Later x) (KeepCons p)
|
|
= do MkVar prf' <- subElem x p
|
|
Just (MkVar (Later prf'))
|
|
|
|
export
|
|
subExtend : (ns : List Name) -> SubVars xs ys -> SubVars (ns ++ xs) (ns ++ ys)
|
|
subExtend [] sub = sub
|
|
subExtend (x :: xs) sub = KeepCons (subExtend xs sub)
|
|
|
|
export
|
|
subInclude : (ns : List Name) -> SubVars xs ys -> SubVars (xs ++ ns) (ys ++ ns)
|
|
subInclude ns SubRefl = SubRefl
|
|
subInclude ns (DropCons p) = DropCons (subInclude ns p)
|
|
subInclude ns (KeepCons p) = KeepCons (subInclude ns p)
|
|
|
|
mutual
|
|
export
|
|
shrinkPi : PiInfo (Term vars) -> SubVars newvars vars ->
|
|
Maybe (PiInfo (Term newvars))
|
|
shrinkPi Explicit prf = pure Explicit
|
|
shrinkPi Implicit prf = pure Implicit
|
|
shrinkPi AutoImplicit prf = pure AutoImplicit
|
|
shrinkPi (DefImplicit t) prf = pure (DefImplicit !(shrinkTerm t prf))
|
|
|
|
export
|
|
shrinkBinder : Binder (Term vars) -> SubVars newvars vars ->
|
|
Maybe (Binder (Term newvars))
|
|
shrinkBinder (Lam fc c p ty) prf
|
|
= Just (Lam fc c !(shrinkPi p prf) !(shrinkTerm ty prf))
|
|
shrinkBinder (Let fc c val ty) prf
|
|
= Just (Let fc c !(shrinkTerm val prf) !(shrinkTerm ty prf))
|
|
shrinkBinder (Pi fc c p ty) prf
|
|
= Just (Pi fc c !(shrinkPi p prf) !(shrinkTerm ty prf))
|
|
shrinkBinder (PVar fc c p ty) prf
|
|
= Just (PVar fc c !(shrinkPi p prf) !(shrinkTerm ty prf))
|
|
shrinkBinder (PLet fc c val ty) prf
|
|
= Just (PLet fc c !(shrinkTerm val prf) !(shrinkTerm ty prf))
|
|
shrinkBinder (PVTy fc c ty) prf
|
|
= Just (PVTy fc c !(shrinkTerm ty prf))
|
|
|
|
export
|
|
shrinkVar : Var vars -> SubVars newvars vars -> Maybe (Var newvars)
|
|
shrinkVar (MkVar x) prf = subElem x prf
|
|
|
|
export
|
|
shrinkTerm : Term vars -> SubVars newvars vars -> Maybe (Term newvars)
|
|
shrinkTerm (Local fc r idx loc) prf = (\(MkVar loc') => Local fc r _ loc') <$> subElem loc prf
|
|
shrinkTerm (Ref fc x name) prf = Just (Ref fc x name)
|
|
shrinkTerm (Meta fc x y xs) prf
|
|
= do xs' <- traverse (\x => shrinkTerm x prf) xs
|
|
Just (Meta fc x y xs')
|
|
shrinkTerm (Bind fc x b scope) prf
|
|
= Just (Bind fc x !(shrinkBinder b prf) !(shrinkTerm scope (KeepCons prf)))
|
|
shrinkTerm (App fc fn arg) prf
|
|
= Just (App fc !(shrinkTerm fn prf) !(shrinkTerm arg prf))
|
|
shrinkTerm (As fc s as tm) prf
|
|
= Just (As fc s !(shrinkTerm as prf) !(shrinkTerm tm prf))
|
|
shrinkTerm (TDelayed fc x y) prf
|
|
= Just (TDelayed fc x !(shrinkTerm y prf))
|
|
shrinkTerm (TDelay fc x t y) prf
|
|
= Just (TDelay fc x !(shrinkTerm t prf) !(shrinkTerm y prf))
|
|
shrinkTerm (TForce fc r x) prf
|
|
= Just (TForce fc r !(shrinkTerm x prf))
|
|
shrinkTerm (PrimVal fc c) prf = Just (PrimVal fc c)
|
|
shrinkTerm (Erased fc i) prf = Just (Erased fc i)
|
|
shrinkTerm (TType fc u) prf = Just (TType fc u)
|
|
|
|
varEmbedSub : SubVars small vars ->
|
|
{idx : Nat} -> (0 p : IsVar n idx small) ->
|
|
Var vars
|
|
varEmbedSub SubRefl y = MkVar y
|
|
varEmbedSub (DropCons prf) y
|
|
= let MkVar y' = varEmbedSub prf y in
|
|
MkVar (Later y')
|
|
varEmbedSub (KeepCons prf) First = MkVar First
|
|
varEmbedSub (KeepCons prf) (Later p)
|
|
= let MkVar p' = varEmbedSub prf p in
|
|
MkVar (Later p')
|
|
|
|
export
|
|
embedSub : SubVars small vars -> Term small -> Term vars
|
|
embedSub sub (Local fc x idx y)
|
|
= let MkVar y' = varEmbedSub sub y in Local fc x _ y'
|
|
embedSub sub (Ref fc x name) = Ref fc x name
|
|
embedSub sub (Meta fc x y xs)
|
|
= Meta fc x y (map (embedSub sub) xs)
|
|
embedSub sub (Bind fc x b scope)
|
|
= Bind fc x (map (embedSub sub) b) (embedSub (KeepCons sub) scope)
|
|
embedSub sub (App fc fn arg)
|
|
= App fc (embedSub sub fn) (embedSub sub arg)
|
|
embedSub sub (As fc s nm pat)
|
|
= As fc s (embedSub sub nm) (embedSub sub pat)
|
|
embedSub sub (TDelayed fc x y) = TDelayed fc x (embedSub sub y)
|
|
embedSub sub (TDelay fc x t y)
|
|
= TDelay fc x (embedSub sub t) (embedSub sub y)
|
|
embedSub sub (TForce fc r x) = TForce fc r (embedSub sub x)
|
|
embedSub sub (PrimVal fc c) = PrimVal fc c
|
|
embedSub sub (Erased fc i) = Erased fc i
|
|
embedSub sub (TType fc u) = TType fc u
|
|
|
|
namespace Bounds
|
|
public export
|
|
data Bounds : List Name -> Type where
|
|
None : Bounds []
|
|
Add : (x : Name) -> Name -> Bounds xs -> Bounds (x :: xs)
|
|
|
|
export
|
|
sizeOf : Bounds xs -> SizeOf xs
|
|
sizeOf None = zero
|
|
sizeOf (Add _ _ b) = suc (sizeOf b)
|
|
|
|
export
|
|
addVars : SizeOf outer -> Bounds bound ->
|
|
NVar name (outer ++ vars) ->
|
|
NVar name (outer ++ (bound ++ vars))
|
|
addVars p = insertNVarNames p . sizeOf
|
|
|
|
resolveRef : SizeOf outer -> SizeOf done -> Bounds bound -> FC -> Name ->
|
|
Maybe (Term (outer ++ (done ++ bound ++ vars)))
|
|
resolveRef p q None fc n = Nothing
|
|
resolveRef {outer} {done} p q (Add {xs} new old bs) fc n
|
|
= if n == old
|
|
then rewrite appendAssociative outer done (new :: xs ++ vars) in
|
|
let MkNVar p = weakenNVar (p + q) (MkNVar First) in
|
|
Just (Local fc Nothing _ p)
|
|
else rewrite appendAssociative done [new] (xs ++ vars)
|
|
in resolveRef p (sucR q) bs fc n
|
|
|
|
mkLocals : SizeOf outer -> Bounds bound ->
|
|
Term (outer ++ vars) -> Term (outer ++ (bound ++ vars))
|
|
mkLocals outer bs (Local fc r idx p)
|
|
= let MkNVar p' = addVars outer bs (MkNVar p) in Local fc r _ p'
|
|
mkLocals outer bs (Ref fc Bound name)
|
|
= maybe (Ref fc Bound name) id (resolveRef outer zero bs fc name)
|
|
mkLocals outer bs (Ref fc nt name)
|
|
= Ref fc nt name
|
|
mkLocals outer bs (Meta fc name y xs)
|
|
= maybe (Meta fc name y (map (mkLocals outer bs) xs))
|
|
id (resolveRef outer zero bs fc name)
|
|
mkLocals outer bs (Bind fc x b scope)
|
|
= Bind fc x (map (mkLocals outer bs) b)
|
|
(mkLocals (suc outer) bs scope)
|
|
mkLocals outer bs (App fc fn arg)
|
|
= App fc (mkLocals outer bs fn) (mkLocals outer bs arg)
|
|
mkLocals outer bs (As fc s as tm)
|
|
= As fc s (mkLocals outer bs as) (mkLocals outer bs tm)
|
|
mkLocals outer bs (TDelayed fc x y)
|
|
= TDelayed fc x (mkLocals outer bs y)
|
|
mkLocals outer bs (TDelay fc x t y)
|
|
= TDelay fc x (mkLocals outer bs t) (mkLocals outer bs y)
|
|
mkLocals outer bs (TForce fc r x)
|
|
= TForce fc r (mkLocals outer bs x)
|
|
mkLocals outer bs (PrimVal fc c) = PrimVal fc c
|
|
mkLocals outer bs (Erased fc i) = Erased fc i
|
|
mkLocals outer bs (TType fc u) = TType fc u
|
|
|
|
export
|
|
refsToLocals : Bounds bound -> Term vars -> Term (bound ++ vars)
|
|
refsToLocals None y = y
|
|
refsToLocals bs y = mkLocals zero bs y
|
|
|
|
-- Replace any reference to 'x' with a locally bound name 'new'
|
|
export
|
|
refToLocal : (x : Name) -> (new : Name) -> Term vars -> Term (new :: vars)
|
|
refToLocal x new tm = refsToLocals (Add new x None) tm
|
|
|
|
export
|
|
isNVar : (n : Name) -> (ns : List Name) -> Maybe (NVar n ns)
|
|
isNVar n [] = Nothing
|
|
isNVar n (m :: ms)
|
|
= case nameEq n m of
|
|
Nothing => map later (isNVar n ms)
|
|
Just Refl => pure (MkNVar First)
|
|
|
|
export
|
|
isVar : (n : Name) -> (ns : List Name) -> Maybe (Var ns)
|
|
isVar n ns = do
|
|
MkNVar v <- isNVar n ns
|
|
pure (MkVar v)
|
|
|
|
-- Replace any Ref Bound in a type with appropriate local
|
|
export
|
|
resolveNames : (vars : List Name) -> Term vars -> Term vars
|
|
resolveNames vars (Ref fc Bound name)
|
|
= case isNVar name vars of
|
|
Just (MkNVar prf) => Local fc (Just False) _ prf
|
|
_ => Ref fc Bound name
|
|
resolveNames vars (Meta fc n i xs)
|
|
= Meta fc n i (map (resolveNames vars) xs)
|
|
resolveNames vars (Bind fc x b scope)
|
|
= Bind fc x (map (resolveNames vars) b) (resolveNames (x :: vars) scope)
|
|
resolveNames vars (App fc fn arg)
|
|
= App fc (resolveNames vars fn) (resolveNames vars arg)
|
|
resolveNames vars (As fc s as pat)
|
|
= As fc s (resolveNames vars as) (resolveNames vars pat)
|
|
resolveNames vars (TDelayed fc x y)
|
|
= TDelayed fc x (resolveNames vars y)
|
|
resolveNames vars (TDelay fc x t y)
|
|
= TDelay fc x (resolveNames vars t) (resolveNames vars y)
|
|
resolveNames vars (TForce fc r x)
|
|
= TForce fc r (resolveNames vars x)
|
|
resolveNames vars tm = tm
|
|
|
|
-- Substitute some explicit terms for names in a term, and remove those
|
|
-- names from the scope
|
|
namespace SubstEnv
|
|
public export
|
|
data SubstEnv : List Name -> List Name -> Type where
|
|
Nil : SubstEnv [] vars
|
|
(::) : Term vars ->
|
|
SubstEnv ds vars -> SubstEnv (d :: ds) vars
|
|
|
|
findDrop : FC -> Maybe Bool ->
|
|
Var (dropped ++ vars) ->
|
|
SubstEnv dropped vars ->
|
|
Term vars
|
|
findDrop fc r (MkVar var) [] = Local fc r _ var
|
|
findDrop fc r (MkVar First) (tm :: env) = tm
|
|
findDrop fc r (MkVar (Later p)) (tm :: env)
|
|
= findDrop fc r (MkVar p) env
|
|
|
|
find : FC -> Maybe Bool ->
|
|
SizeOf outer ->
|
|
Var (outer ++ (dropped ++ vars)) ->
|
|
SubstEnv dropped vars ->
|
|
Term (outer ++ vars)
|
|
find fc r outer var env = case sizedView outer of
|
|
Z => findDrop fc r var env
|
|
S outer => case var of
|
|
MkVar First => Local fc r _ First
|
|
MkVar (Later p) => weaken (find fc r outer (MkVar p) env)
|
|
-- TODO: refactor to only weaken once?
|
|
|
|
substEnv : SizeOf outer ->
|
|
SubstEnv dropped vars ->
|
|
Term (outer ++ (dropped ++ vars)) ->
|
|
Term (outer ++ vars)
|
|
substEnv outer env (Local fc r _ prf)
|
|
= find fc r outer (MkVar prf) env
|
|
substEnv outer env (Ref fc x name) = Ref fc x name
|
|
substEnv outer env (Meta fc n i xs)
|
|
= Meta fc n i (map (substEnv outer env) xs)
|
|
substEnv outer env (Bind fc x b scope)
|
|
= Bind fc x (map (substEnv outer env) b)
|
|
(substEnv (suc outer) env scope)
|
|
substEnv outer env (App fc fn arg)
|
|
= App fc (substEnv outer env fn) (substEnv outer env arg)
|
|
substEnv outer env (As fc s as pat)
|
|
= As fc s (substEnv outer env as) (substEnv outer env pat)
|
|
substEnv outer env (TDelayed fc x y) = TDelayed fc x (substEnv outer env y)
|
|
substEnv outer env (TDelay fc x t y)
|
|
= TDelay fc x (substEnv outer env t) (substEnv outer env y)
|
|
substEnv outer env (TForce fc r x) = TForce fc r (substEnv outer env x)
|
|
substEnv outer env (PrimVal fc c) = PrimVal fc c
|
|
substEnv outer env (Erased fc i) = Erased fc i
|
|
substEnv outer env (TType fc u) = TType fc u
|
|
|
|
export
|
|
substs : SubstEnv dropped vars -> Term (dropped ++ vars) -> Term vars
|
|
substs env tm = substEnv zero env tm
|
|
|
|
export
|
|
subst : Term vars -> Term (x :: vars) -> Term vars
|
|
subst val tm = substs [val] tm
|
|
|
|
-- Replace an explicit name with a term
|
|
export
|
|
substName : Name -> Term vars -> Term vars -> Term vars
|
|
substName x new (Ref fc nt name)
|
|
= case nameEq x name of
|
|
Nothing => Ref fc nt name
|
|
Just Refl => new
|
|
substName x new (Meta fc n i xs)
|
|
= Meta fc n i (map (substName x new) xs)
|
|
-- ASSUMPTION: When we substitute under binders, the name has always been
|
|
-- resolved to a Local, so no need to check that x isn't shadowing
|
|
substName x new (Bind fc y b scope)
|
|
= Bind fc y (map (substName x new) b) (substName x (weaken new) scope)
|
|
substName x new (App fc fn arg)
|
|
= App fc (substName x new fn) (substName x new arg)
|
|
substName x new (As fc s as pat)
|
|
= As fc s as (substName x new pat)
|
|
substName x new (TDelayed fc y z)
|
|
= TDelayed fc y (substName x new z)
|
|
substName x new (TDelay fc y t z)
|
|
= TDelay fc y (substName x new t) (substName x new z)
|
|
substName x new (TForce fc r y)
|
|
= TForce fc r (substName x new y)
|
|
substName x new tm = tm
|
|
|
|
export
|
|
addMetas : (usingResolved : Bool) -> NameMap Bool -> Term vars -> NameMap Bool
|
|
addMetas res ns (Local fc x idx y) = ns
|
|
addMetas res ns (Ref fc x name) = ns
|
|
addMetas res ns (Meta fc n i xs)
|
|
= addMetaArgs (insert (ifThenElse res (Resolved i) n) False ns) xs
|
|
where
|
|
addMetaArgs : NameMap Bool -> List (Term vars) -> NameMap Bool
|
|
addMetaArgs ns [] = ns
|
|
addMetaArgs ns (t :: ts) = addMetaArgs (addMetas res ns t) ts
|
|
addMetas res ns (Bind fc x (Let _ c val ty) scope)
|
|
= addMetas res (addMetas res (addMetas res ns val) ty) scope
|
|
addMetas res ns (Bind fc x b scope)
|
|
= addMetas res (addMetas res ns (binderType b)) scope
|
|
addMetas res ns (App fc fn arg)
|
|
= addMetas res (addMetas res ns fn) arg
|
|
addMetas res ns (As fc s as tm) = addMetas res ns tm
|
|
addMetas res ns (TDelayed fc x y) = addMetas res ns y
|
|
addMetas res ns (TDelay fc x t y)
|
|
= addMetas res (addMetas res ns t) y
|
|
addMetas res ns (TForce fc r x) = addMetas res ns x
|
|
addMetas res ns (PrimVal fc c) = ns
|
|
addMetas res ns (Erased fc i) = ns
|
|
addMetas res ns (TType fc u) = ns
|
|
|
|
-- Get the metavariable names in a term
|
|
export
|
|
getMetas : Term vars -> NameMap Bool
|
|
getMetas tm = addMetas False empty tm
|
|
|
|
export
|
|
addRefs : (underAssert : Bool) -> (aTotal : Name) ->
|
|
NameMap Bool -> Term vars -> NameMap Bool
|
|
addRefs ua at ns (Local fc x idx y) = ns
|
|
addRefs ua at ns (Ref fc x name) = insert name ua ns
|
|
addRefs ua at ns (Meta fc n i xs)
|
|
= addRefsArgs ns xs
|
|
where
|
|
addRefsArgs : NameMap Bool -> List (Term vars) -> NameMap Bool
|
|
addRefsArgs ns [] = ns
|
|
addRefsArgs ns (t :: ts) = addRefsArgs (addRefs ua at ns t) ts
|
|
addRefs ua at ns (Bind fc x (Let _ c val ty) scope)
|
|
= addRefs ua at (addRefs ua at (addRefs ua at ns val) ty) scope
|
|
addRefs ua at ns (Bind fc x b scope)
|
|
= addRefs ua at (addRefs ua at ns (binderType b)) scope
|
|
addRefs ua at ns (App _ (App _ (Ref fc _ name) x) y)
|
|
= if name == at
|
|
then addRefs True at (insert name True ns) y
|
|
else addRefs ua at (addRefs ua at (insert name ua ns) x) y
|
|
addRefs ua at ns (App fc fn arg)
|
|
= addRefs ua at (addRefs ua at ns fn) arg
|
|
addRefs ua at ns (As fc s as tm) = addRefs ua at ns tm
|
|
addRefs ua at ns (TDelayed fc x y) = addRefs ua at ns y
|
|
addRefs ua at ns (TDelay fc x t y)
|
|
= addRefs ua at (addRefs ua at ns t) y
|
|
addRefs ua at ns (TForce fc r x) = addRefs ua at ns x
|
|
addRefs ua at ns (PrimVal fc c) = ns
|
|
addRefs ua at ns (Erased fc i) = ns
|
|
addRefs ua at ns (TType fc u) = ns
|
|
|
|
-- As above, but for references. Also flag whether a name is under an
|
|
-- 'assert_total' because we may need to know that in coverage/totality
|
|
-- checking
|
|
export
|
|
getRefs : (aTotal : Name) -> Term vars -> NameMap Bool
|
|
getRefs at tm = addRefs False at empty tm
|
|
|
|
|
|
export
|
|
nameAt : {vars : _} -> {idx : Nat} -> (0 p : IsVar n idx vars) -> Name
|
|
nameAt {vars = n :: ns} First = n
|
|
nameAt {vars = n :: ns} (Later p) = nameAt p
|
|
|
|
export
|
|
withPiInfo : Show t => PiInfo t -> String -> String
|
|
withPiInfo Explicit tm = "(" ++ tm ++ ")"
|
|
withPiInfo Implicit tm = "{" ++ tm ++ "}"
|
|
withPiInfo AutoImplicit tm = "{auto " ++ tm ++ "}"
|
|
withPiInfo (DefImplicit t) tm = "{default " ++ show t ++ " " ++ tm ++ "}"
|
|
|
|
|
|
export
|
|
covering
|
|
{vars : _} -> Show (Term vars) where
|
|
show tm = let (fn, args) = getFnArgs tm in showApp fn args
|
|
where
|
|
showApp : {vars : _} -> Term vars -> List (Term vars) -> String
|
|
showApp (Local _ c idx p) []
|
|
= show (nameAt p) ++ "[" ++ show idx ++ "]"
|
|
|
|
showApp (Ref _ _ n) [] = show n
|
|
showApp (Meta _ n _ args) []
|
|
= "?" ++ show n ++ "_" ++ show args
|
|
showApp (Bind _ x (Lam _ c info ty) sc) []
|
|
= "\\" ++ withPiInfo info (showCount c ++ show x ++ " : " ++ show ty) ++
|
|
" => " ++ show sc
|
|
showApp (Bind _ x (Let _ c val ty) sc) []
|
|
= "let " ++ showCount c ++ show x ++ " : " ++ show ty ++
|
|
" = " ++ show val ++ " in " ++ show sc
|
|
showApp (Bind _ x (Pi _ c info ty) sc) []
|
|
= withPiInfo info (showCount c ++ show x ++ " : " ++ show ty) ++
|
|
" -> " ++ show sc ++ ")"
|
|
showApp (Bind _ x (PVar _ c info ty) sc) []
|
|
= withPiInfo info ("pat " ++ showCount c ++ show x ++ " : " ++ show ty) ++
|
|
" => " ++ show sc
|
|
showApp (Bind _ x (PLet _ c val ty) sc) []
|
|
= "plet " ++ showCount c ++ show x ++ " : " ++ show ty ++
|
|
" = " ++ show val ++ " in " ++ show sc
|
|
showApp (Bind _ x (PVTy _ c ty) sc) []
|
|
= "pty " ++ showCount c ++ show x ++ " : " ++ show ty ++
|
|
" => " ++ show sc
|
|
showApp (App _ _ _) [] = "[can't happen]"
|
|
showApp (As _ _ n tm) [] = show n ++ "@" ++ show tm
|
|
showApp (TDelayed _ _ tm) [] = "%Delayed " ++ show tm
|
|
showApp (TDelay _ _ _ tm) [] = "%Delay " ++ show tm
|
|
showApp (TForce _ _ tm) [] = "%Force " ++ show tm
|
|
showApp (PrimVal _ c) [] = show c
|
|
showApp (Erased _ _) [] = "[__]"
|
|
showApp (TType _ u) [] = "Type"
|
|
showApp _ [] = "???"
|
|
showApp f args = "(" ++ assert_total (show f) ++ " " ++
|
|
assert_total (showSep " " (map show args))
|
|
++ ")"
|
|
|
|
export
|
|
{vars : _} -> Pretty (Term vars) where
|
|
pretty = pretty . show
|
|
-- TODO: prettier output
|