dtlc

dependently-typed lambda calculus toy
git clone git://git.rr3.xyz/dtlc
Log | Files | Refs | README | LICENSE

commit 1b84163cd6506ed3c7efae7a18a656ea382cae49
parent a56d4e7da22851289923593d8fb4751ec4092128
Author: Robert Russell <robertrussell.72001@gmail.com>
Date:   Mon, 29 Jan 2024 19:25:44 -0800

Make tuples inferrable

Diffstat:
Mabstract.ml | 1+
Mdesugar.ml | 9++++++---
Melab.ml | 35+++++++++++++++++++++++++++++++++++
Mmain.ml | 2+-
Mpretty.ml | 28++++++++++++++++------------
5 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/abstract.ml b/abstract.ml @@ -18,6 +18,7 @@ and term' = | Fn of abstraction | FnType of abstraction | Data of tag_name * term array +| TupleData of term array (* Can be inferred, unlike regular Data. *) | DataType of multibinder Name.Tag.Map.t | Nat of Z.t | Var of var_name * int diff --git a/desugar.ml b/desugar.ml @@ -152,11 +152,14 @@ let rec term let ctors = Array.fold_left insert Name.Tag.Map.empty ctors in loc @$ A.DataType ctors | C.Tuple fields -> - let tag = synth_tag_name (string_of_int (Array.length fields)) in - loc @$ A.Data (tag, Array.map term fields) + loc @$ A.TupleData (Array.map term fields) | C.TupleType doms -> let tag = Name.Tag.Of (string_of_int (Array.length doms)) in - let binders = array_loc doms @$ Array.map domain doms in + let binders = + if Array.length doms = 0 then + Loc.Nowhere @$ [||] + else + array_loc doms @$ Array.map domain doms in loc @$ A.DataType (Name.Tag.Map.singleton tag binders) | C.Unit -> loc @$ A.Data (synth_tag_name "0", [||]) | C.Nat n -> loc @$ A.Nat n diff --git a/elab.ml b/elab.ml @@ -235,6 +235,41 @@ and elaborate' let typ = quote ctx.env vtyp in E.abort loc @@ E.ElabExpectedDataType typ +| A.TupleData args, Infer -> + let arity = Array.length args in + + (* Only needed so that the indices in the type are correct. *) + let vars = Uniq.fresh arity in + let clo = Env.bind ctx.env vars in + + let args' = Array.make arity garbage in + let binders = Array.make arity garbage in + for i = 0 to arity - 1 do + let (arg', vtyp) = infer' ctx args.(i) in + args'.(i) <- arg'; + let typ = quote clo vtyp in + binders.(i) <- { + I.plicity = Plicity.Ex; + I.patt = { + names = [||]; + disc = DWild typ; + }; + } + done; + + let tag = Name.Tag.Of (string_of_int arity) in + let datatype = { + I.ctors = [|{binders; order = Array.init arity Fun.id}|]; + I.names = Name.Tag.Map.singleton tag 0; + } in + (I.Data {tag; tagi = 0; args = args'; datatype}, + V.DataTypeClosure (clo, datatype)) + +| A.TupleData args, Check vtyp -> + (* XXX: Kinda hacky. *) + let tag = Name.Tag.Of (string_of_int (Array.length args)) in + elaborate' ctx (loc @$ A.Data (Loc.Nowhere @$ tag, args)) (Check vtyp) + | A.DataType ctors, Infer -> let next = ref 0 in let ctors' = Array.make (Name.Tag.Map.cardinal ctors) garbage in diff --git a/main.ml b/main.ml @@ -74,7 +74,7 @@ let buf = Lexing.from_string "\ Opt := fn A: Type => #{@some A; @none};\n\ div: [Nat, Nat] -> Opt Nat := fn m, n =>\n\ if n = 0 then @none else @some (m / n);\n\ - (div 3 0, div 12 3): #(Opt Nat, Opt Nat)\n\ + (div 3 0, div 12 3)\n\ " let ctx = diff --git a/pretty.ml b/pretty.ml @@ -13,7 +13,7 @@ let rec pp_print_with_parens F.fprintf ppf (* TODO: Fix precedences given recent parser changes *) -and pp_print_term +let rec pp_print_term : int -> F.formatter -> term -> unit = fun m ppf -> function | Let (definers, body) -> @@ -28,7 +28,7 @@ and pp_print_term pp_print_switch switch | App (fn, args) -> - pp_print_with_parens m 5 ppf "@[<4>%a%a@]" + pp_print_with_parens m 5 ppf "@[<4>%a@ %a@]" (pp_print_term 6) fn pp_print_args args @@ -45,10 +45,17 @@ and pp_print_term (pp_print_term 3) codomain | Data {tag; args; datatype; _} -> - pp_print_with_parens m 2 ppf "@[<hv>@[<4>%a%a@]:@;<1 4>%a@;<0 -4>@]" - Name.Tag.pp_print tag - pp_print_args args - (pp_print_term 2) (DataType datatype) + begin match args with + | [||] -> + pp_print_with_parens m 6 ppf "@[%a@]" + Name.Tag.pp_print tag + | args -> + (*pp_print_with_parens m 2 ppf "@[<hv 4>@[<4>%a%a@]:@ %a@;<0 -4>@]"*) + pp_print_with_parens m 2 ppf "@[<4>%a@ %a@]" + Name.Tag.pp_print tag + pp_print_args args + (*(pp_print_term 2) (DataType datatype)*) + end | DataType {ctors; names} -> pp_print_with_parens m 6 ppf "@[@[<hv 4>#{@,%a%t@]}@]" @@ -72,7 +79,7 @@ and pp_print_term and pp_print_definer : F.formatter -> definer -> unit = fun ppf {names; rhs; typ} -> - F.fprintf ppf "@[@[<hv 4>%a:@;<1 4>%a@;<1 -4>@]:=@;<1 4>%a@]" + F.fprintf ppf "@[@[<hv 4>%a:@ %a@;<1 -4>@]:=@;<1 4>%a@]" (pp_print_names 3) names (pp_print_term 2) typ (pp_print_term 1) rhs @@ -143,11 +150,8 @@ and pp_print_subswitches and pp_print_args : F.formatter -> term array -> unit -= fun ppf -> function -| [||] -> () (* This only happens for Data, not App. *) -| args -> - F.fprintf ppf "@ %a" - (F.pp_print_array ~pp_sep:F.pp_print_space (pp_print_term 6)) args += fun ppf args -> + F.pp_print_array ~pp_sep:F.pp_print_space (pp_print_term 6) ppf args and pp_print_binders : F.formatter -> binder array -> unit