aboutsummaryrefslogtreecommitdiff
path: root/lib/Syntax.ml
diff options
context:
space:
mode:
authorMalte Voos <git@mal.tc>2024-06-17 17:41:38 +0200
committerMalte Voos <git@mal.tc>2024-06-17 17:41:38 +0200
commit04d62df9fdd42c603fad7bb1b5e3fb49bf8550c1 (patch)
tree0a11c38a9f7bfad5624f0821b3a7041a9d4ff4d8 /lib/Syntax.ml
parentedcd6c17b873b11b18016c9fe6efbe47576574ae (diff)
downloadtoytt-04d62df9fdd42c603fad7bb1b5e3fb49bf8550c1.tar.gz
toytt-04d62df9fdd42c603fad7bb1b5e3fb49bf8550c1.zip
implement typechecking
Diffstat (limited to 'lib/Syntax.ml')
-rw-r--r--lib/Syntax.ml114
1 files changed, 102 insertions, 12 deletions
diff --git a/lib/Syntax.ml b/lib/Syntax.ml
index 6cd988a..c4cf80d 100644
--- a/lib/Syntax.ml
+++ b/lib/Syntax.ml
@@ -1,19 +1,109 @@
-type tm =
+open Bwd
+
+type t = Data.syn =
| Var of int
- | Pi of tm * (* BINDS *) tm
- | Lam of (* BINDS *) tm
- | App of tm * tm
- | Sg of tm * (* BINDS *) tm
- | Pair of tm * tm
- | Fst of tm
- | Snd of tm
+ | Pi of t * (* BINDS *) t
+ | Lam of (* BINDS *) t
+ | App of t * t
+ | Sg of t * (* BINDS *) t
+ | Pair of t * t
+ | Fst of t
+ | Snd of t
| Type
| Bool
| True
| False
| BoolElim of {
- motive : (* BINDS *) tm;
- true_case : tm;
- false_case : tm;
- scrut : tm;
+ motive : (* BINDS *) t;
+ true_case : t;
+ false_case : t;
+ scrut : t;
}
+
+module Pretty =
+struct
+ type local_names = Yuujinchou.Trie.path option bwd
+ type tm_with_names = t * local_names
+
+ let pp_name fmt (id : Yuujinchou.Trie.path) = Format.pp_print_list
+ ~pp_sep:(fun fmt () -> Format.pp_print_char fmt '.')
+ Format.pp_print_string fmt id
+
+ module Internal =
+ struct
+ type env = {
+ prec : int;
+ }
+
+ module Eff = Algaeff.Reader.Make (struct type nonrec t = env end)
+
+ let with_prec (prec : int) (inner : 'a Fmt.t) (fmt : Format.formatter) (v : 'a) =
+ Eff.scope (fun _ -> { prec; }) (fun () -> inner fmt v)
+
+ let delimited inner = with_prec 0 inner
+
+ let parenthesize (prec : int) : 'a Fmt.t -> 'a Fmt.t =
+ if (Eff.read()).prec > prec then
+ Fmt.parens
+ else
+ Fun.id
+
+ let lassoc (prec : int)
+ ?(pre = "")
+ (pp_left : 'l Fmt.t)
+ ?(middle = " ")
+ (pp_right : 'r Fmt.t)
+ ?(post = "") : ('l * 'r) Fmt.t =
+ parenthesize prec @@ fun fmt v ->
+ Fmt.pf fmt "%s@[%a@]%s@[%a@]%s"
+ pre
+ (with_prec prec pp_left) (fst v)
+ middle
+ (with_prec (prec + 1) pp_right) (snd v)
+ post
+
+ let rassoc (prec : int)
+ ?(pre = "")
+ (pp_left : 'l Fmt.t)
+ ?(middle = " ")
+ (pp_right : 'r Fmt.t)
+ ?(post = "") : ('l * 'r) Fmt.t =
+ parenthesize prec @@ fun fmt v ->
+ Fmt.pf fmt "%s@[%a@]%s@[%a@]%s"
+ pre
+ (with_prec (prec + 1) pp_left) (fst v)
+ middle
+ (with_prec prec pp_right) (snd v)
+ post
+
+ let pp_var ix fmt = Fmt.pf fmt "%@%d" ix
+
+ let rec pp_pair fmt = (delimited @@ fun fmt (a, b) -> Fmt.pf fmt "@[(@[%a@], @[%a@])@]" pp a pp b) fmt
+
+ and pp_bool_elim fmt =
+ (delimited @@ fun fmt (motive, true_case, false_case, scrut) -> Fmt.pf fmt
+ "@[bool-elim @[%a@] at _ -> @[%a@] [ true => @[%a@], false => @[%a@] ]@]"
+ pp scrut pp motive pp true_case pp false_case
+ ) fmt
+
+ (* TODO: improve indentation *)
+ and pp fmt = function
+ | Var ix -> pp_var ix fmt
+ | Pi (base, fam) -> rassoc 1 ~pre:"(_ : " pp ~middle:") -> " pp fmt (base, fam)
+ | Lam body -> Fmt.pf fmt "@[\\_ -> @[%a@]@]" pp body
+ | Sg (base, fam) -> rassoc 2 ~pre:"(_ : " pp ~middle:") * " pp fmt (base, fam)
+ | App (a, b) -> lassoc 3 pp pp fmt (a, b)
+ | Pair (a, b) -> pp_pair fmt (a, b)
+ | Fst a -> lassoc 3 Fmt.string pp fmt ("fst", a)
+ | Snd a -> lassoc 3 Fmt.string pp fmt ("snd", a)
+ | Type -> Fmt.string fmt "type"
+ | Bool -> Fmt.string fmt "bool"
+ | True -> Fmt.string fmt "true"
+ | False -> Fmt.string fmt "false"
+ | BoolElim { motive; true_case; false_case; scrut } -> pp_bool_elim fmt (motive, true_case, false_case, scrut)
+ end
+
+ let pp fmt tm =
+ let env : Internal.env = { prec = 0; } in
+ Internal.Eff.run ~env (fun () -> Internal.pp fmt tm)
+end