Skip to content

Commit 6479584

Browse files
committed
Use polymorphic methods instead of instantiated methods.
1 parent c7e0448 commit 6479584

12 files changed

+3177
-3019
lines changed

ast/cinaps/gen_conversion.ml

Lines changed: 206 additions & 132 deletions
Large diffs are not rendered by default.

ast/cinaps/gen_traverse.ml

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
open Stdppx
22

3-
let string_of_targ targ = Grammar.string_of_targ ~internal:false targ
4-
53
let parens x = Printf.sprintf "(%s)" x
64

75
type base_method =
86
{ method_name : string
9-
; params : string list
7+
; tvars : string list
108
; type_name : string
119
}
1210

1311
let base_methods =
14-
[ {method_name = "bool"; params = []; type_name = "bool"}
15-
; {method_name = "char"; params = []; type_name = "char"}
16-
; {method_name = "int"; params = []; type_name = "int"}
17-
; {method_name = "list"; params = ["a"]; type_name = "list"}
18-
; {method_name = "option"; params = ["a"]; type_name = "option"}
19-
; {method_name = "string"; params = []; type_name = "string"}
20-
; {method_name = "location"; params = []; type_name = "Astlib.Location.t"}
21-
; {method_name = "loc"; params = ["a"]; type_name = "Astlib.Loc.t"}
12+
[ {method_name = "bool"; tvars = []; type_name = "bool"}
13+
; {method_name = "char"; tvars = []; type_name = "char"}
14+
; {method_name = "int"; tvars = []; type_name = "int"}
15+
; {method_name = "list"; tvars = ["a"]; type_name = "list"}
16+
; {method_name = "option"; tvars = ["a"]; type_name = "option"}
17+
; {method_name = "string"; tvars = []; type_name = "string"}
18+
; {method_name = "location"; tvars = []; type_name = "Astlib.Location.t"}
19+
; {method_name = "loc"; tvars = ["a"]; type_name = "Astlib.Loc.t"}
2220
]
2321

24-
let poly_signature ~signature ~params ~type_name =
25-
let poly_type = Ml.poly_type ~tvars:params type_name in
26-
let poly_params = List.map ~f:Ml.tvar params in
27-
let fun_pre_args = List.map ~f:(fun t -> parens (signature t)) poly_params in
22+
let poly_signature ~signature ~tvars ~nodify ~type_name =
23+
let args =
24+
List.map tvars ~f:(fun tvar ->
25+
if nodify
26+
then Ml.poly_inst "node" ~args:[Ml.tvar tvar]
27+
else Ml.tvar tvar)
28+
in
29+
let poly_type = Ml.poly_inst ~args type_name in
30+
let poly_tvars = List.map ~f:Ml.tvar tvars in
31+
let fun_pre_args = List.map ~f:(fun arg -> parens (signature arg)) args in
2832
let fun_sig = Ml.arrow_type (fun_pre_args @ [signature poly_type]) in
29-
let universal_quantifiers = String.concat ~sep:" " poly_params in
33+
let universal_quantifiers = String.concat ~sep:" " poly_tvars in
3034
Printf.sprintf "%s . %s" universal_quantifiers fun_sig
3135

32-
let base_method_signature ~signature ~params ~type_name =
33-
match params with
36+
let method_signature ~signature ~tvars ~nodify ~type_name =
37+
match tvars with
3438
| [] -> signature type_name
35-
| params -> poly_signature ~signature ~params ~type_name
39+
| tvars -> poly_signature ~signature ~tvars ~nodify ~type_name
3640

37-
let declare_base_method ~signature {method_name; params; type_name} =
38-
let signature = base_method_signature ~signature ~params ~type_name in
41+
let declare_base_method ~signature {method_name; tvars; type_name} =
42+
let signature = method_signature ~signature ~tvars ~nodify:false ~type_name in
3943
Ml.declare_method ~virtual_:true ~signature ~name:method_name ()
4044

4145
(* This type describes a variables bound when deconstructing a value.
@@ -72,7 +76,7 @@ type deconstructed =
7276
(** This type describes the kind of value we're trying to traverse.
7377
- [Ast_type {node_name; targs}] means we are traversing a named type of
7478
the AST. [node_name] is the name of the AST node we
75-
want to traverse and [targs] are its type arguments if it is an
79+
want to traverse and [arity] is the number of type arguments if it is an
7680
instance of a polymorphic AST type.
7781
- [Abstract] means we're inside an anonymous function and want
7882
to traverse something that isn't a named type of the AST.
@@ -82,7 +86,7 @@ type deconstructed =
8286
in an [of_concrete] call in the [Ast_type _] case.
8387
Other traversal classes can ignore the context. *)
8488
type value_kind =
85-
| Ast_type of {node_name : string; targs : Astlib.Grammar.targ list}
89+
| Ast_type of {node_name : string; arity : int}
8690
| Abstract
8791

8892
(** The type used to describe the various traversal classes and how to generate
@@ -112,13 +116,10 @@ type traversal =
112116
; recurse : value_kind: value_kind -> deconstructed: deconstructed -> string list
113117
}
114118

115-
type type_ = Concrete | T
116-
117-
let node_type ~type_ ~args node_name =
118-
let type_name = match type_ with T -> "t" | Concrete -> "concrete" in
119-
let node_type = Printf.sprintf "%s.%s" (Ml.module_name node_name) type_name in
120-
let args = List.map args ~f:string_of_targ in
121-
Ml.poly_inst node_type ~args
119+
let concrete_type ~tvars node_name =
120+
let full_name = Printf.sprintf "%s.concrete" (Ml.module_name node_name) in
121+
let args = List.map tvars ~f:(fun (_ : string) -> "_") in
122+
Ml.poly_inst full_name ~args
122123

123124
let fun_arg type_name = Ml.id (Printf.sprintf "f%s" type_name)
124125

@@ -177,8 +178,13 @@ and recursive_call ?(nested=false) ~traversal (ty : Astlib.Grammar.ty) =
177178
let exprs = traversal.recurse ~value_kind:Abstract ~deconstructed in
178179
let args = String.concat ~sep:" " (traversal.args deconstructed.pattern) in
179180
Printf.sprintf "(fun %s -> %s)" args (String.concat ~sep:" " exprs)
180-
| Instance (n, tyl) ->
181-
Printf.sprintf "self#%s" (Name.make [n] tyl)
181+
| Instance (n, targs) ->
182+
Printf.sprintf "self#%s %s" (Name.make [n] [])
183+
(String.concat ~sep:" "
184+
(List.map targs ~f:(fun targ ->
185+
match (targ : Astlib.Grammar.targ) with
186+
| Tvar tvar -> fun_arg tvar
187+
| Tname tname -> Printf.sprintf "self#%s" (Ml.id tname))))
182188
| Loc ty -> parens (Printf.sprintf "self#loc %s" (recursive_call ~nested:true ty))
183189
| Location -> "self#location"
184190

@@ -200,22 +206,22 @@ let print_method_for_alias ~traversal ~value_kind ~var ty =
200206

201207
let print_method_body
202208
~traversal
203-
~targs
204209
~node_name
210+
~tvars
205211
~var
206212
(decl : Astlib.Grammar.decl)
207213
=
208-
let value_kind = Ast_type {node_name; targs} in
214+
let value_kind = Ast_type {node_name; arity = List.length tvars} in
209215
match decl with
210216
| Ty ty -> print_method_for_alias ~traversal ~value_kind ~var ty
211217
| Record fields ->
212218
let deconstructed = deconstruct_record ~traversal fields in
213-
let concrete_type = (node_type ~type_:Concrete ~args:targs node_name) in
219+
let concrete_type = concrete_type ~tvars node_name in
214220
let exprs = traversal.recurse ~value_kind ~deconstructed in
215221
Print.println "let %s : %s = %s in" deconstructed.pattern concrete_type var;
216222
List.iter exprs ~f:(Print.println "%s")
217223
| Variant variants ->
218-
let concrete_type = (node_type ~type_:Concrete ~args:targs node_name) in
224+
let concrete_type = concrete_type ~tvars node_name in
219225
Print.println "match (%s : %s) with" var concrete_type;
220226
List.iter variants
221227
~f:(fun variant ->
@@ -245,7 +251,7 @@ module Map = struct
245251
let return =
246252
match value_kind with
247253
| Abstract -> pattern
248-
| Ast_type {node_name; targs=_} ->
254+
| Ast_type {node_name;arity=_} ->
249255
Printf.sprintf "%s.%s %s"
250256
(Ml.module_name node_name)
251257
"of_concrete"
@@ -337,7 +343,7 @@ module Fold_map = struct
337343
let return =
338344
match value_kind with
339345
| Abstract -> Ml.tuple [pattern; acc_var]
340-
| Ast_type {node_name; targs=_} ->
346+
| Ast_type {node_name;arity=_} ->
341347
let mapped =
342348
Printf.sprintf "%s.%s %s"
343349
(Ml.module_name node_name)
@@ -378,7 +384,7 @@ module Map_with_context = struct
378384
let return =
379385
match value_kind with
380386
| Abstract -> pattern
381-
| Ast_type {node_name; targs=_} ->
387+
| Ast_type {node_name;arity=_} ->
382388
Printf.sprintf "%s.%s %s"
383389
(Ml.module_name node_name)
384390
"of_concrete"
@@ -440,8 +446,8 @@ module Lift = struct
440446
let make_node_arg ~value_kind =
441447
match value_kind with
442448
| Abstract -> "None"
443-
| Ast_type { node_name; targs } ->
444-
sprintf "(Some (%S, %d))" node_name (List.length targs)
449+
| Ast_type { node_name; arity } ->
450+
sprintf "(Some (%S, %d))" node_name arity
445451

446452
let recurse ~value_kind ~deconstructed =
447453
let {kind; vars; pattern} = deconstructed in
@@ -489,60 +495,54 @@ let print_to_concrete node_name =
489495
(Ml.module_name node_name)
490496
(Ml.id node_name)
491497

492-
let print_method_value ~traversal ~targs ~node_name decl =
493-
let args = traversal.args (Ml.id node_name) in
494-
Ml.define_anon_fun ~args (fun () ->
498+
let print_method_value ~traversal ~node_name ~tvars decl =
499+
let args = List.map tvars ~f:fun_arg @ traversal.args (Ml.id node_name) in
500+
Ml.print_anon_fun ~args (fun () ->
495501
print_to_concrete node_name;
496-
print_method_body ~traversal ~targs ~node_name ~var:"concrete" decl)
497-
498-
let declare_node_methods ~env_table ~signature (node_name, kind) =
499-
match (kind : Astlib.Grammar.kind) with
500-
| Mono _ ->
501-
let name = Name.make [node_name] [] in
502-
let signature = signature (node_type ~type_:T ~args:[] node_name) in
503-
Ml.declare_method ~signature ~name ()
504-
| Poly (_, _) ->
505-
let envs = Poly_env.find env_table node_name in
506-
List.iter envs ~f:(fun env ->
507-
let args = Poly_env.args env in
508-
let name = Name.make [node_name] args in
509-
let signature = signature (node_type ~type_:T ~args node_name) in
510-
Ml.declare_method ~signature ~name ())
511-
512-
let define_node_methods ~env_table ~traversal (node_name, kind) =
513-
match (kind : Astlib.Grammar.kind) with
514-
| Mono decl ->
515-
let name = Name.make [node_name] [] in
516-
let signature = traversal.signature (node_type ~type_:T ~args:[] node_name) in
517-
Ml.define_method ~signature name (fun () ->
518-
print_method_value ~traversal ~targs:[] ~node_name decl)
519-
| Poly (_, decl) ->
520-
let envs = Poly_env.find env_table node_name in
521-
List.iter envs ~f:(fun env ->
522-
let targs = Poly_env.args env in
523-
let name = Name.make [node_name] targs in
524-
let signature = traversal.signature (node_type ~type_:T ~args:targs node_name) in
525-
let subst_decl = Poly_env.subst_decl ~env decl in
526-
Ml.define_method ~signature name (fun () ->
527-
print_method_value ~traversal ~targs ~node_name subst_decl))
502+
print_method_body ~traversal ~node_name ~tvars ~var:"concrete" decl)
503+
504+
let declare_node_methods ~signature (node_name, kind) =
505+
let tvars =
506+
match (kind : Astlib.Grammar.kind) with
507+
| Mono _ -> []
508+
| Poly (tvars, _) -> tvars
509+
in
510+
let name = Name.make [node_name] [] in
511+
let signature =
512+
method_signature ~signature ~tvars ~nodify:true
513+
~type_name:(Ml.module_name node_name ^ ".t")
514+
in
515+
Ml.declare_method ~signature ~name ()
516+
517+
let define_node_methods ~traversal (node_name, kind) =
518+
let tvars, decl =
519+
match (kind : Astlib.Grammar.kind) with
520+
| Mono decl -> [], decl
521+
| Poly (tvars, decl) -> tvars, decl
522+
in
523+
let name = Name.make [node_name] [] in
524+
let signature =
525+
method_signature ~signature:traversal.signature ~tvars ~nodify:true
526+
~type_name:(Ml.module_name node_name ^ ".t")
527+
in
528+
Ml.define_method ~signature name (fun () ->
529+
print_method_value ~traversal ~node_name ~tvars decl)
528530

529531
let declare_virtual_traversal_class ~traversal grammar =
530-
let env_table = Poly_env.env_table grammar in
531532
let {class_name; params; signature; extra_methods; _} = traversal in
532533
Ml.declare_class ~virtual_:true ?params class_name (fun () ->
533534
Ml.declare_object (fun () ->
534535
Option.iter extra_methods ~f:(fun f -> f ());
535536
List.iter base_methods ~f:(declare_base_method ~signature);
536-
List.iter grammar ~f:(declare_node_methods ~env_table ~signature)))
537+
List.iter grammar ~f:(declare_node_methods ~signature)))
537538

538539
let define_virtual_traversal_class ~traversal grammar =
539-
let env_table = Poly_env.env_table grammar in
540540
let {class_name; params; signature; extra_methods; _} = traversal in
541541
Ml.define_class ~virtual_:true ?params class_name (fun () ->
542542
Ml.define_object ~bind_self:true (fun () ->
543543
Option.iter extra_methods ~f:(fun f -> f ());
544544
List.iter base_methods ~f:(declare_base_method ~signature);
545-
List.iter grammar ~f:(define_node_methods ~env_table ~traversal)))
545+
List.iter grammar ~f:(define_node_methods ~traversal)))
546546

547547
let declare_virtual_traversal_classes grammar =
548548
List.iter traversal_classes

ast/cinaps/ml.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ let declare_method ?(virtual_=false) ~name ~signature () =
161161
let qualifier = if virtual_ then "virtual " else "" in
162162
Print.println "method %s%s : %s" qualifier name signature
163163

164-
let define_anon_fun ~args f =
164+
let print_anon_fun ~args f =
165165
let args_str = String.concat ~sep:" " args in
166166
Print.println "fun %s ->" args_str;
167167
Print.indented f

ast/cinaps/ml.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,4 @@ val define_object : ?bind_self: bool -> (unit -> unit) -> unit
5858
val declare_method : ?virtual_: bool -> name: string -> signature: string -> unit -> unit
5959
val define_method : ?signature: string -> string -> (unit -> unit) -> unit
6060

61-
val define_anon_fun : args: string list -> (unit -> unit) -> unit
61+
val print_anon_fun : args: string list -> (unit -> unit) -> unit

ast/cinaps/poly_env.ml

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
open Stdppx
22

33
type env = (string * Astlib.Grammar.targ) list
4-
type env_table = (string, env list) Hashtbl.t
54

65
let empty_env = []
76

8-
let find env_table name =
9-
match Hashtbl.find env_table name with
10-
| Some list -> list
11-
| None -> failwith (Printf.sprintf "no monomorphic instances found for %s" name)
12-
137
let args env = List.map env ~f:snd
148

159
let create ~vars ~args = List.zip_exn vars args
@@ -65,67 +59,3 @@ let subst_decl decl ~env =
6559
| Ty ty -> Ty (subst_ty ~env ty)
6660
| Record fields -> Record (subst_fields ~env fields)
6761
| Variant variants -> Variant (subst_variants ~env variants)
68-
69-
let rec ty_instances ty =
70-
match (ty : Astlib.Grammar.ty) with
71-
| Var _ | Name _ | Bool | Char | Int | String | Location -> []
72-
| Loc ty | List ty | Option ty -> ty_instances ty
73-
| Tuple tuple -> tuple_instances tuple
74-
| Instance (poly, args) -> [(poly, args)]
75-
76-
and tuple_instances tuple =
77-
List.concat (List.map tuple ~f:ty_instances)
78-
79-
let record_instances record =
80-
List.concat (List.map record ~f:(fun (_, ty) -> ty_instances ty))
81-
82-
let clause_instances clause =
83-
match (clause : Astlib.Grammar.clause) with
84-
| Empty -> []
85-
| Tuple tuple -> tuple_instances tuple
86-
| Record record -> record_instances record
87-
88-
let variant_instances variant =
89-
List.concat (List.map variant ~f:(fun (_, clause) -> clause_instances clause))
90-
91-
let decl_instances decl =
92-
match (decl : Astlib.Grammar.decl) with
93-
| Ty ty -> ty_instances ty
94-
| Record record -> record_instances record
95-
| Variant variant -> variant_instances variant
96-
97-
let rec transitive_instances decl ~grammar_table =
98-
let instances = decl_instances decl in
99-
let transitive =
100-
List.map instances ~f:(fun (poly, args) ->
101-
match (Hashtbl.find_exn grammar_table poly : Astlib.Grammar.kind) with
102-
| Mono _ -> assert false
103-
| Poly (vars, decl) ->
104-
let instances = transitive_instances decl ~grammar_table in
105-
let env = List.combine vars args in
106-
List.map instances ~f:(fun (poly, args) ->
107-
(poly, subst_targs args ~env)))
108-
in
109-
instances @ List.concat transitive
110-
111-
let grammar_instances grammar ~grammar_table =
112-
List.concat
113-
(List.map grammar ~f:(fun (_, kind) ->
114-
match (kind : Astlib.Grammar.kind) with
115-
| Poly _ -> []
116-
| Mono decl -> transitive_instances decl ~grammar_table))
117-
118-
let grammar_envs grammar ~grammar_table =
119-
List.map (grammar_instances grammar ~grammar_table) ~f:(fun (poly, args) ->
120-
let vars =
121-
match (Hashtbl.find_exn grammar_table poly : Astlib.Grammar.kind) with
122-
| Mono _ -> []
123-
| Poly (vars, _) -> vars
124-
in
125-
poly, List.combine vars args)
126-
127-
let env_table grammar =
128-
let grammar_table = Hashtbl.of_list_exn grammar in
129-
Hashtbl.map ~f:(List.sort_uniq ~compare)
130-
(Hashtbl.of_list_multi
131-
(grammar_envs grammar ~grammar_table))

ast/cinaps/poly_env.mli

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
type env
2-
type env_table
3-
4-
val env_table : Astlib.Grammar.t -> env_table
5-
val find : env_table -> string -> env list
62

73
val create : vars:string list -> args:Astlib.Grammar.targ list -> env
84

0 commit comments

Comments
 (0)