mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 03:05:31 -05:00
wip: ciclib: start checking types and inductive specs
This commit is contained in:
parent
401365e1bb
commit
8d70c10e18
10 changed files with 216 additions and 31 deletions
35
src/ciclib/inductive.ml
Normal file
35
src/ciclib/inductive.ml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
module T = Term
|
||||||
|
|
||||||
|
type cstor = Types_.cstor = { c_name: string; c_ty: T.t }
|
||||||
|
|
||||||
|
type spec = Types_.spec = {
|
||||||
|
name: string;
|
||||||
|
univ_params: Level.var list;
|
||||||
|
n_params: int;
|
||||||
|
ty: T.t;
|
||||||
|
cstors: cstor list;
|
||||||
|
}
|
||||||
|
(** Inductive spec *)
|
||||||
|
|
||||||
|
let pp_cstor out (c : cstor) : unit =
|
||||||
|
Fmt.fprintf out "(@[%s : %a@])" c.c_name T.pp_debug c.c_ty
|
||||||
|
|
||||||
|
let pp_spec out (self : spec) : unit =
|
||||||
|
Fmt.fprintf out "@[<2>@[%s %a@]:@ %a [%d params] :=@ %a@]" self.name
|
||||||
|
Fmt.Dump.(list string)
|
||||||
|
self.univ_params T.pp_debug self.ty self.n_params
|
||||||
|
Fmt.(hvbox @@ Dump.(list pp_cstor))
|
||||||
|
self.cstors
|
||||||
|
|
||||||
|
let cstor_is_valid (spec : spec) (self : cstor) : bool =
|
||||||
|
let rec loop (ty : T.t) : bool =
|
||||||
|
let hd, _args = T.unfold_app ty in
|
||||||
|
match T.view hd with
|
||||||
|
| T.E_const (c, _) when c.c_name = spec.name ->
|
||||||
|
(* TODO: check that [ty] is correct *)
|
||||||
|
true
|
||||||
|
| _ -> assert false (* TODO: handle recursive cases *)
|
||||||
|
in
|
||||||
|
loop self.c_ty
|
||||||
|
|
||||||
|
let is_valid self = List.for_all (cstor_is_valid self) self.cstors
|
||||||
18
src/ciclib/inductive.mli
Normal file
18
src/ciclib/inductive.mli
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
module T = Term
|
||||||
|
|
||||||
|
type cstor = Types_.cstor = { c_name: string; c_ty: T.t }
|
||||||
|
|
||||||
|
type spec = Types_.spec = {
|
||||||
|
name: string;
|
||||||
|
univ_params: Level.var list;
|
||||||
|
n_params: int;
|
||||||
|
ty: T.t;
|
||||||
|
cstors: cstor list;
|
||||||
|
}
|
||||||
|
(** Inductive spec *)
|
||||||
|
|
||||||
|
val pp_cstor : cstor Fmt.printer
|
||||||
|
val pp_spec : spec Fmt.printer
|
||||||
|
|
||||||
|
val is_valid : spec -> bool
|
||||||
|
(** Check for validity of the spec *)
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
open Types_
|
open Types_
|
||||||
|
|
||||||
|
type var = string
|
||||||
|
|
||||||
type t = level =
|
type t = level =
|
||||||
| L_zero
|
| L_zero
|
||||||
| L_succ of level
|
| L_succ of level
|
||||||
| L_var of string (** variable *)
|
| L_var of var (** variable *)
|
||||||
| L_max of level * level (** max *)
|
| L_max of level * level (** max *)
|
||||||
| L_imax of level * level (** impredicative max. *)
|
| L_imax of level * level (** impredicative max. *)
|
||||||
|
|
||||||
|
|
@ -94,16 +96,20 @@ let[@inline] is_zero l =
|
||||||
| L_zero -> true
|
| L_zero -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
|
|
||||||
|
type subst = t Util.Str_map.t
|
||||||
|
|
||||||
(** [subst_v store lvl v u] replaces [v] with [u] in [lvl] *)
|
(** [subst_v store lvl v u] replaces [v] with [u] in [lvl] *)
|
||||||
let subst_v (lvl : t) (v : string) (u : t) =
|
let subst (subst : subst) (lvl : t) : t =
|
||||||
let rec loop lvl : t =
|
let rec loop lvl : t =
|
||||||
if is_ground lvl then
|
if is_ground lvl then
|
||||||
lvl
|
lvl
|
||||||
else (
|
else (
|
||||||
match lvl with
|
match lvl with
|
||||||
| L_var v' when v = v' -> u
|
| L_var v ->
|
||||||
| L_var _ -> lvl
|
(match Util.Str_map.find v subst with
|
||||||
| L_zero -> assert false
|
| l -> l
|
||||||
|
| exception Not_found -> lvl)
|
||||||
|
| L_zero -> lvl
|
||||||
| L_succ a -> succ (loop a)
|
| L_succ a -> succ (loop a)
|
||||||
| L_max (a, b) -> max (loop a) (loop b)
|
| L_max (a, b) -> max (loop a) (loop b)
|
||||||
| L_imax (a, b) -> imax (loop a) (loop b)
|
| L_imax (a, b) -> imax (loop a) (loop b)
|
||||||
|
|
@ -111,6 +117,9 @@ let subst_v (lvl : t) (v : string) (u : t) =
|
||||||
in
|
in
|
||||||
loop lvl
|
loop lvl
|
||||||
|
|
||||||
|
let subst_v (lvl : t) (v : string) (u : t) =
|
||||||
|
subst (Util.Str_map.singleton v u) lvl
|
||||||
|
|
||||||
let is_one l =
|
let is_one l =
|
||||||
match l with
|
match l with
|
||||||
| L_succ a -> is_zero a
|
| L_succ a -> is_zero a
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
open Types_
|
open Types_
|
||||||
|
|
||||||
|
type var = string
|
||||||
|
|
||||||
type t = level =
|
type t = level =
|
||||||
| L_zero
|
| L_zero
|
||||||
| L_succ of level
|
| L_succ of level
|
||||||
| L_var of string (** variable *)
|
| L_var of var (** variable *)
|
||||||
| L_max of level * level (** max *)
|
| L_max of level * level (** max *)
|
||||||
| L_imax of level * level (** impredicative max. *)
|
| L_imax of level * level (** impredicative max. *)
|
||||||
|
|
||||||
|
|
@ -16,7 +18,7 @@ val as_offset : t -> t * int
|
||||||
|
|
||||||
val zero : t
|
val zero : t
|
||||||
val one : t
|
val one : t
|
||||||
val var : string -> t
|
val var : var -> t
|
||||||
val succ : t -> t
|
val succ : t -> t
|
||||||
val of_int : int -> t
|
val of_int : int -> t
|
||||||
val max : t -> t -> t
|
val max : t -> t -> t
|
||||||
|
|
@ -29,6 +31,12 @@ val is_one : t -> bool
|
||||||
val is_int : t -> bool
|
val is_int : t -> bool
|
||||||
val as_int : t -> int option
|
val as_int : t -> int option
|
||||||
|
|
||||||
|
(** {2 Substitutions} *)
|
||||||
|
|
||||||
|
type subst = t Util.Str_map.t
|
||||||
|
|
||||||
|
val subst : subst -> t -> t
|
||||||
|
|
||||||
(** {2 Judgements}
|
(** {2 Judgements}
|
||||||
|
|
||||||
These are little proofs of some symbolic properties of levels, even
|
These are little proofs of some symbolic properties of levels, even
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ module Bvar = Bvar
|
||||||
module Const = Const
|
module Const = Const
|
||||||
module Level = Level
|
module Level = Level
|
||||||
module Reduce = Reduce
|
module Reduce = Reduce
|
||||||
|
module Inductive = Inductive
|
||||||
|
|
|
||||||
|
|
@ -48,14 +48,16 @@ let as_type e : level option =
|
||||||
| E_type l -> Some l
|
| E_type l -> Some l
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
let string_of_binder = function
|
|
||||||
| BI -> "BI"
|
|
||||||
| BS -> "BS"
|
|
||||||
| BC -> "BC"
|
|
||||||
| BD -> "BD"
|
|
||||||
|
|
||||||
(* debug printer *)
|
(* debug printer *)
|
||||||
let expr_pp_with_ ~max_depth out (e : term) : unit =
|
let expr_pp_with_ ~max_depth out (e : term) : unit =
|
||||||
|
let pp_binder b name pp_ty ty out =
|
||||||
|
match b with
|
||||||
|
| BD -> Fmt.fprintf out "(@[%s : %a@])" name pp_ty ty
|
||||||
|
| BI -> Fmt.fprintf out "{@[%s : %a@]}" name pp_ty ty
|
||||||
|
| BS -> Fmt.fprintf out "{{@[%s : %a@]}}" name pp_ty ty
|
||||||
|
| BC -> Fmt.fprintf out "[@[%s : %a@]]" name pp_ty ty
|
||||||
|
in
|
||||||
|
|
||||||
let rec loop k ~depth names out e =
|
let rec loop k ~depth names out e =
|
||||||
let pp' = loop k ~depth:(depth + 1) names in
|
let pp' = loop k ~depth:(depth + 1) names in
|
||||||
match e.view with
|
match e.view with
|
||||||
|
|
@ -73,15 +75,15 @@ let expr_pp_with_ ~max_depth out (e : term) : unit =
|
||||||
| E_app _ ->
|
| E_app _ ->
|
||||||
let f, args = unfold_app e in
|
let f, args = unfold_app e in
|
||||||
Fmt.fprintf out "(%a@ %a)" pp' f (Util.pp_list pp') args
|
Fmt.fprintf out "(%a@ %a)" pp' f (Util.pp_list pp') args
|
||||||
| E_lam (binder, name, _ty, bod) ->
|
| E_lam (binder, name, ty, bod) ->
|
||||||
Fmt.fprintf out "(@[\\[%s]%s:@[%a@].@ %a@])" (string_of_binder binder)
|
Fmt.fprintf out "(@[fun %t.@ %a@])"
|
||||||
name pp' _ty
|
(pp_binder binder name pp' ty)
|
||||||
(loop (k + 1) ~depth:(depth + 1) ("" :: names))
|
(loop (k + 1) ~depth:(depth + 1) (name :: names))
|
||||||
bod
|
bod
|
||||||
| E_pi (binder, name, ty_arg, bod) ->
|
| E_pi (binder, name, ty_arg, bod) ->
|
||||||
Fmt.fprintf out "(@[Pi[%s] %s:@[%a@].@ %a@])" (string_of_binder binder)
|
Fmt.fprintf out "(@[@<1>∀ %t.@ %a@])"
|
||||||
name pp' ty_arg
|
(pp_binder binder name pp' ty_arg)
|
||||||
(loop (k + 1) ~depth:(depth + 1) ("" :: names))
|
(loop (k + 1) ~depth:(depth + 1) (name :: names))
|
||||||
bod
|
bod
|
||||||
in
|
in
|
||||||
Fmt.fprintf out "@[%a@]" (loop 0 ~depth:0 []) e
|
Fmt.fprintf out "@[%a@]" (loop 0 ~depth:0 []) e
|
||||||
|
|
@ -96,17 +98,14 @@ let as_type_exn e : level =
|
||||||
let iter_shallow ~f (e : term) : unit =
|
let iter_shallow ~f (e : term) : unit =
|
||||||
match e.view with
|
match e.view with
|
||||||
| E_type _ -> ()
|
| E_type _ -> ()
|
||||||
| _ ->
|
|
||||||
(match e.view with
|
|
||||||
| E_const _ -> ()
|
| E_const _ -> ()
|
||||||
| E_type _ -> assert false
|
|
||||||
| E_bound_var _ -> ()
|
| E_bound_var _ -> ()
|
||||||
| E_app (hd, a) ->
|
| E_app (hd, a) ->
|
||||||
f false hd;
|
f false hd;
|
||||||
f false a
|
f false a
|
||||||
| E_lam (_, _, tyv, bod) | E_pi (_, _, tyv, bod) ->
|
| E_lam (_, _, tyv, bod) | E_pi (_, _, tyv, bod) ->
|
||||||
f false tyv;
|
f false tyv;
|
||||||
f true bod)
|
f true bod
|
||||||
|
|
||||||
let[@inline] is_type e =
|
let[@inline] is_type e =
|
||||||
match e.view with
|
match e.view with
|
||||||
|
|
@ -249,6 +248,13 @@ let[@inline] app_l f l : term = List.fold_left app f l
|
||||||
let[@inline] lam b str ~var_ty bod : term = make_ (E_lam (b, str, var_ty, bod))
|
let[@inline] lam b str ~var_ty bod : term = make_ (E_lam (b, str, var_ty, bod))
|
||||||
let[@inline] pi b str ~var_ty bod : term = make_ (E_pi (b, str, var_ty, bod))
|
let[@inline] pi b str ~var_ty bod : term = make_ (E_pi (b, str, var_ty, bod))
|
||||||
|
|
||||||
|
let rec subst_level (s : Level.subst) (e : t) : t =
|
||||||
|
match view e with
|
||||||
|
| E_type u -> type_of_univ (Level.subst s u)
|
||||||
|
| E_const (_, []) -> e
|
||||||
|
| E_const (c, args) -> const c (List.map (Level.subst s) args)
|
||||||
|
| _ -> map_shallow e ~f:(fun _ e' -> subst_level s e')
|
||||||
|
|
||||||
module DB = struct
|
module DB = struct
|
||||||
let[@inline] subst_db0 e ~by : t = db_replace_ e [ by ]
|
let[@inline] subst_db0 e ~by : t = db_replace_ e [ by ]
|
||||||
let[@inline] subst_db_l e env : t = db_replace_ e env
|
let[@inline] subst_db_l e env : t = db_replace_ e env
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ val app_l : t -> t list -> t
|
||||||
val lam : binder -> string -> var_ty:t -> t -> t
|
val lam : binder -> string -> var_ty:t -> t -> t
|
||||||
val pi : binder -> string -> var_ty:t -> t -> t
|
val pi : binder -> string -> var_ty:t -> t -> t
|
||||||
|
|
||||||
|
val subst_level : Level.subst -> t -> t
|
||||||
|
(** Substitute level variables in a term *)
|
||||||
|
|
||||||
(** De bruijn indices *)
|
(** De bruijn indices *)
|
||||||
module DB : sig
|
module DB : sig
|
||||||
val subst_db0 : t -> by:t -> t
|
val subst_db0 : t -> by:t -> t
|
||||||
|
|
|
||||||
67
src/ciclib/ty_infer.ml
Normal file
67
src/ciclib/ty_infer.ml
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
open Types_
|
||||||
|
module T = Term
|
||||||
|
module Str_map = Util.Str_map
|
||||||
|
|
||||||
|
module Env = struct
|
||||||
|
type t = {
|
||||||
|
consts: T.t Str_map.t;
|
||||||
|
inductives: Inductive.spec Str_map.t;
|
||||||
|
cstors: Inductive.cstor Str_map.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pp_str_map ppx out (m : _ Str_map.t) =
|
||||||
|
Fmt.iter Fmt.Dump.(pair string ppx) out (Str_map.to_iter m)
|
||||||
|
|
||||||
|
let pp out (self : t) =
|
||||||
|
let { consts; inductives; cstors } = self in
|
||||||
|
Fmt.fprintf out "{ @[consts=%a;@ inductives=%a;@ cstors=%a@] }"
|
||||||
|
(pp_str_map T.pp_debug) consts
|
||||||
|
(pp_str_map Inductive.pp_spec)
|
||||||
|
inductives
|
||||||
|
(pp_str_map Inductive.pp_cstor)
|
||||||
|
cstors
|
||||||
|
|
||||||
|
let empty : t =
|
||||||
|
{
|
||||||
|
consts = Str_map.empty;
|
||||||
|
inductives = Str_map.empty;
|
||||||
|
cstors = Str_map.empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let add_def (self : t) name rhs : t =
|
||||||
|
{ self with consts = Str_map.add name rhs self.consts }
|
||||||
|
|
||||||
|
let add_inductive (self : t) (ind : Inductive.spec) : t =
|
||||||
|
{
|
||||||
|
self with
|
||||||
|
inductives = Str_map.add ind.name ind self.inductives;
|
||||||
|
cstors =
|
||||||
|
List.fold_left
|
||||||
|
(fun cstors c -> Str_map.add c.c_name c cstors)
|
||||||
|
self.cstors ind.cstors;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
module Stack = struct
|
||||||
|
type t = T.t list
|
||||||
|
|
||||||
|
let empty = []
|
||||||
|
let push t l : t = t :: l
|
||||||
|
let pp = Fmt.Dump.(list T.pp_debug)
|
||||||
|
end
|
||||||
|
|
||||||
|
let ty_check (env : Env.t) (st : Stack.t) (self : T.t) : T.t =
|
||||||
|
let rec loop (st : Stack.t) (self : T.t) : T.t =
|
||||||
|
match T.view self with
|
||||||
|
| E_type l -> T.type_of_univ (Level.succ l)
|
||||||
|
| E_bound_var v ->
|
||||||
|
(match List.nth st v.bv_idx with
|
||||||
|
| exception _ ->
|
||||||
|
Error.errorf "bound variable %a is not bound in env %a" Bvar.pp v
|
||||||
|
Stack.pp st
|
||||||
|
| ty -> ty)
|
||||||
|
| E_const (c, args) -> assert false (* TODO: check definition? *)
|
||||||
|
| E_app (_, _) | E_lam (_, _, _, _) | E_pi (_, _, _, _) ->
|
||||||
|
assert false (* TODO: *)
|
||||||
|
in
|
||||||
|
loop st self
|
||||||
27
src/ciclib/ty_infer.mli
Normal file
27
src/ciclib/ty_infer.mli
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
module T = Term
|
||||||
|
|
||||||
|
(** Env: definitions for constants and inductives *)
|
||||||
|
module Env : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
val pp : t Fmt.printer
|
||||||
|
|
||||||
|
val add_def : t -> string -> T.t -> t
|
||||||
|
(** [add_def env name c] defines [name := c] in [env] *)
|
||||||
|
|
||||||
|
val add_inductive : t -> Inductive.spec -> t
|
||||||
|
(** Define an inductive *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Stack: types for bound variables *)
|
||||||
|
module Stack : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val empty : t
|
||||||
|
val push : T.t -> t -> t
|
||||||
|
val pp : t Fmt.printer
|
||||||
|
end
|
||||||
|
|
||||||
|
val ty_check : Env.t -> Stack.t -> T.t -> T.t
|
||||||
|
(** [ty_check env stack t] infers the type of [t] *)
|
||||||
|
|
@ -25,3 +25,14 @@ and term = {
|
||||||
view: term_view;
|
view: term_view;
|
||||||
mutable flags: int; (** contains: [highest DB var | 1:has free vars] *)
|
mutable flags: int; (** contains: [highest DB var | 1:has free vars] *)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cstor = { c_name: string; c_ty: term }
|
||||||
|
|
||||||
|
type spec = {
|
||||||
|
name: string;
|
||||||
|
univ_params: string list;
|
||||||
|
n_params: int;
|
||||||
|
ty: term;
|
||||||
|
cstors: cstor list;
|
||||||
|
}
|
||||||
|
(** Inductive spec *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue