Skip to content

Commit d379e6e

Browse files
committed
hmx: backport improvements from hmx_tc
1 parent f323f28 commit d379e6e

File tree

11 files changed

+558
-392
lines changed

11 files changed

+558
-392
lines changed

hmx/bin/main.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ let () =
1414
let e = Expr.parse_chan Stdio.stdin in
1515
match infer ~env e with
1616
| Ok e -> Caml.Format.printf "%s@." (Expr.show e)
17-
| Error err -> Caml.Format.printf "ERROR: %s@." (Error.show err)
17+
| Error err -> Caml.Format.printf "ERROR: %s@." (Type_error.show err)

hmx/constraint.ml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
(**
2+
3+
This module defines constraint language.
4+
5+
The constraint language has applicative structure (see [C_map] constructor)
6+
which is used for elaboration (the constraint solving algo computes a value).
7+
8+
*)
9+
10+
open Base
11+
open Syntax
12+
13+
type _ t =
14+
| C_trivial : unit t
15+
(** A trivial constraint, states nothing useful. Always can be solved. *)
16+
| C_eq : ty * ty -> unit t
17+
(** [C_eq (ty1, ty2)] states that the types [ty1] and [ty2] are equal. *)
18+
| C_inst : name * ty -> expr t
19+
(** [C_inst (name, ty)] states that [name] should be fetched from the
20+
environment, instantiated and equated to [ty]. *)
21+
| C_and : 'a t * 'b t -> ('a * 'b) t
22+
(** Conjuction of two constraints, possibly of different value type. *)
23+
| C_and_list : 'a t list -> 'a list t
24+
(** Conjuction of multiple constraints of the same value type. *)
25+
| C_exists : var list * 'a t -> 'a t
26+
(** [C_exists (vs, c)] existentially quantifies variables [vs] over [c]. *)
27+
| C_let :
28+
(name * var list * expr t * ty) list * 'b t
29+
-> ((expr * ty_sch) list * 'b) t
30+
(** [C_let (bindings, c)] works is a constraint abstraction fused with
31+
existential quantification. It adds [bindings] to the environment of
32+
the following constraint [c].
33+
34+
It allows to define multiple names at once to support n-ary functions. *)
35+
| C_map : 'a t * ('a -> 'b) -> 'b t
36+
(** Map operation, this gives an applicative structure. *)
37+
38+
let trivial = C_trivial
39+
40+
let return v = C_map (C_trivial, fun () -> v)
41+
42+
let ( =~ ) x y = C_eq (x, y)
43+
44+
let inst name cty = C_inst (name, cty)
45+
46+
let exists tys c =
47+
match tys with
48+
| [] -> c
49+
| tys -> (
50+
match c with
51+
| C_exists (tys', c) -> C_exists (tys @ tys', c)
52+
| c -> C_exists (tys, c))
53+
54+
let let_in bindings c = C_let (bindings, c)
55+
56+
let ( &~ ) x y = C_and (x, y)
57+
58+
let ( >>| ) c f = C_map (c, f)
59+
60+
let list cs = C_and_list cs
61+
62+
let rec layout' : type a. names:Names.t -> a t -> PPrint.document =
63+
fun ~names c ->
64+
let open PPrint in
65+
match c with
66+
| C_trivial -> string "TRUE"
67+
| C_eq (ty1, ty2) ->
68+
layout_ty' ~names ty1 ^^ string " = " ^^ layout_ty' ~names ty2
69+
| C_and (a, b) -> layout' ~names a ^^ string " & " ^^ layout' ~names b
70+
| C_and_list cs ->
71+
let sep = string " & " in
72+
separate sep (List.map cs ~f:(layout' ~names))
73+
| C_exists (vs, c) ->
74+
string ""
75+
^^ separate comma (List.map vs ~f:(layout_con_var' ~names))
76+
^^ dot
77+
^^ parens (layout' ~names c)
78+
| C_let (bindings, c) ->
79+
let layout_cty' : type a. a t * ty -> document = function
80+
| C_trivial, ty -> layout_ty' ~names ty
81+
| c, ty -> layout' ~names c ^^ string " => " ^^ layout_ty' ~names ty
82+
in
83+
let layout_binding : type a. string * var list * a t * ty -> document =
84+
fun (name, vs, c, ty) ->
85+
string name
86+
^^ string " : "
87+
^^
88+
match vs with
89+
| [] -> layout_cty' (c, ty)
90+
| vs ->
91+
let vs = layout_var_prenex' ~names vs in
92+
vs ^^ layout_cty' (c, ty)
93+
in
94+
let sep = comma ^^ blank 1 in
95+
string "let "
96+
^^ separate sep (List.map bindings ~f:layout_binding)
97+
^^ string " in "
98+
^^ layout' ~names c
99+
| C_inst (name, ty) -> string name ^^ string "" ^^ layout_ty' ~names ty
100+
| C_map (c, _f) -> layout' ~names c
101+
102+
include (
103+
struct
104+
type pack = P : _ t -> pack
105+
106+
include Showable (struct
107+
type t = pack
108+
109+
let layout (P c) =
110+
let names = Names.make () in
111+
layout' ~names c
112+
end)
113+
114+
let layout c = layout (P c)
115+
116+
let show c = show (P c)
117+
118+
let print ?label c = print ?label (P c)
119+
end :
120+
sig
121+
val layout : _ t -> PPrint.document
122+
123+
val show : _ t -> string
124+
125+
val print : ?label:string -> _ t -> unit
126+
end)

hmx/debug.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ let flags = Caml.Sys.getenv_opt "HMX_DEBUG" |> Option.value ~default:""
44

55
let log_levels = String.mem flags 'l'
66

7-
let log_solve = String.mem flags 's'
8-
97
let log_instantiate = String.mem flags 'i'
108

119
let log_generalize = String.mem flags 'g'
1210

1311
let log_unify = String.mem flags 'u'
12+
13+
let log_define = String.mem flags 'd'

hmx/hmx.ml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,13 @@ module Ty_sch = struct
3838
end)
3939
end
4040

41-
module C = struct
42-
include Syntax.C
43-
end
44-
45-
module Id = Syntax.Id
46-
module Error = Infer.Error
41+
module Type_error = Type_error
42+
module Var = Var
4743

4844
module Env = struct
4945
include Infer.Env
5046

51-
let assume_val name ty env = add env name (Ty_sch.parse_string ty)
47+
let assume_val name ty env = add_val env name (Ty_sch.parse_string ty)
5248
end
5349

5450
let infer = Infer.infer

0 commit comments

Comments
 (0)