tangled
alpha
login
or
join now
futur.blue
/
pegasus
57
fork
atom
objective categorical abstract machine language personal data server
57
fork
atom
overview
issues
2
pulls
pipelines
hermes: Better names for union types
futur.blue
2 months ago
c9c049f2
befa211a
verified
This commit was signed with the committer's
known signature
.
futur.blue
SSH Key Fingerprint:
SHA256:QHGqHWNpqYyw9bt8KmPuJIyeZX9SZewBZ0PR1COtKQ0=
+47
-15
1 changed file
expand all
collapse all
unified
split
hermes-cli
lib
codegen.ml
+47
-15
hermes-cli/lib/codegen.ml
···
3
type output =
4
{ mutable imports: string list
5
; mutable generated_unions: string list
0
6
; buf: Buffer.t }
7
8
-
let make_output () = {imports= []; generated_unions= []; buf= Buffer.create 4096}
0
9
10
let add_import out module_name =
11
if not (List.mem module_name out.imports) then
···
16
out.generated_unions <- union_name :: out.generated_unions
17
18
let is_union_generated out union_name = List.mem union_name out.generated_unions
0
0
0
0
0
0
0
0
0
0
0
19
20
let emit out s = Buffer.add_string out.buf s
21
···
53
"object_todo"
54
| Ref {ref_; _} ->
55
gen_ref_type nsid out ref_
56
-
| Union {refs; _} ->
57
-
(* generate inline union reference *)
58
-
gen_union_type_name refs
0
0
0
0
59
| Token _ ->
60
"string"
61
| Unknown _ ->
···
97
(* external ref, use as-is *)
98
ref_str
99
100
-
(* collect inline union specs from object properties *)
101
-
let rec collect_inline_unions acc type_def =
102
match type_def with
103
| Union spec ->
104
-
(spec.refs, spec) :: acc
105
| Array {items; _} ->
106
-
collect_inline_unions acc items
0
107
| _ ->
108
acc
109
110
let collect_inline_unions_from_properties properties =
111
List.fold_left
112
-
(fun acc (_, (prop : property)) -> collect_inline_unions acc prop.type_def)
0
113
[] properties
114
115
(* generate inline union types that appear in object properties *)
116
let gen_inline_unions nsid out properties =
117
let inline_unions = collect_inline_unions_from_properties properties in
118
List.iter
119
-
(fun (refs, spec) ->
120
-
let type_name = Naming.union_type_name refs in
0
0
0
121
(* skip if already generated *)
122
if not (is_union_generated out type_name) then begin
123
mark_union_generated out type_name ;
···
162
let full_type_uri = gen_type_uri nsid ref_str in
163
let payload_type = gen_ref_type nsid out ref_str in
164
emitln out (Printf.sprintf " | %s v ->" variant_name) ;
165
-
emitln out (Printf.sprintf " (match %s_to_yojson v with" payload_type) ;
166
-
emitln out (Printf.sprintf " | `Assoc fields -> `Assoc ((\"$type\", `String \"%s\") :: fields)" full_type_uri) ;
0
0
0
0
0
167
emitln out " | other -> other)" )
168
refs ;
169
if not is_closed then emitln out " | Unknown j -> j" ;
···
253
let full_type_uri = gen_type_uri nsid ref_str in
254
let payload_type = gen_ref_type nsid out ref_str in
255
emitln out (Printf.sprintf " | %s v ->" variant_name) ;
256
-
emitln out (Printf.sprintf " (match %s_to_yojson v with" payload_type) ;
257
-
emitln out (Printf.sprintf " | `Assoc fields -> `Assoc ((\"$type\", `String \"%s\") :: fields)" full_type_uri) ;
0
0
0
0
0
258
emitln out " | other -> other)" )
259
spec.refs ;
260
if not is_closed then emitln out " | Unknown j -> j" ;
···
3
type output =
4
{ mutable imports: string list
5
; mutable generated_unions: string list
6
+
; mutable union_names: (string list * string) list (* refs -> context name *)
7
; buf: Buffer.t }
8
9
+
let make_output () =
10
+
{imports= []; generated_unions= []; union_names= []; buf= Buffer.create 4096}
11
12
let add_import out module_name =
13
if not (List.mem module_name out.imports) then
···
18
out.generated_unions <- union_name :: out.generated_unions
19
20
let is_union_generated out union_name = List.mem union_name out.generated_unions
21
+
22
+
(* register a context-based name for a union based on its refs *)
23
+
let register_union_name out refs context_name =
24
+
let sorted_refs = List.sort String.compare refs in
25
+
if not (List.exists (fun (r, _) -> r = sorted_refs) out.union_names) then
26
+
out.union_names <- (sorted_refs, context_name) :: out.union_names
27
+
28
+
(* look up a union's context-based name, or return None *)
29
+
let lookup_union_name out refs =
30
+
let sorted_refs = List.sort String.compare refs in
31
+
List.assoc_opt sorted_refs out.union_names
32
33
let emit out s = Buffer.add_string out.buf s
34
···
66
"object_todo"
67
| Ref {ref_; _} ->
68
gen_ref_type nsid out ref_
69
+
| Union {refs; _} -> (
70
+
(* generate inline union reference, using registered name if available *)
71
+
match lookup_union_name out refs with
72
+
| Some name ->
73
+
name
74
+
| None ->
75
+
gen_union_type_name refs )
76
| Token _ ->
77
"string"
78
| Unknown _ ->
···
114
(* external ref, use as-is *)
115
ref_str
116
117
+
(* collect inline union specs from object properties with context *)
118
+
let rec collect_inline_unions_with_context context acc type_def =
119
match type_def with
120
| Union spec ->
121
+
(context, spec.refs, spec) :: acc
122
| Array {items; _} ->
123
+
(* for array items, append _item to context *)
124
+
collect_inline_unions_with_context (context ^ "_item") acc items
125
| _ ->
126
acc
127
128
let collect_inline_unions_from_properties properties =
129
List.fold_left
130
+
(fun acc (prop_name, (prop : property)) ->
131
+
collect_inline_unions_with_context prop_name acc prop.type_def )
132
[] properties
133
134
(* generate inline union types that appear in object properties *)
135
let gen_inline_unions nsid out properties =
136
let inline_unions = collect_inline_unions_from_properties properties in
137
List.iter
138
+
(fun (context, refs, spec) ->
139
+
(* register and use context-based name *)
140
+
let context_name = Naming.type_name context in
141
+
register_union_name out refs context_name ;
142
+
let type_name = context_name in
143
(* skip if already generated *)
144
if not (is_union_generated out type_name) then begin
145
mark_union_generated out type_name ;
···
184
let full_type_uri = gen_type_uri nsid ref_str in
185
let payload_type = gen_ref_type nsid out ref_str in
186
emitln out (Printf.sprintf " | %s v ->" variant_name) ;
187
+
emitln out
188
+
(Printf.sprintf " (match %s_to_yojson v with" payload_type) ;
189
+
emitln out
190
+
(Printf.sprintf
191
+
" | `Assoc fields -> `Assoc ((\"$type\", `String \
192
+
\"%s\") :: fields)"
193
+
full_type_uri ) ;
194
emitln out " | other -> other)" )
195
refs ;
196
if not is_closed then emitln out " | Unknown j -> j" ;
···
280
let full_type_uri = gen_type_uri nsid ref_str in
281
let payload_type = gen_ref_type nsid out ref_str in
282
emitln out (Printf.sprintf " | %s v ->" variant_name) ;
283
+
emitln out
284
+
(Printf.sprintf " (match %s_to_yojson v with" payload_type) ;
285
+
emitln out
286
+
(Printf.sprintf
287
+
" | `Assoc fields -> `Assoc ((\"$type\", `String \"%s\") :: \
288
+
fields)"
289
+
full_type_uri ) ;
290
emitln out " | other -> other)" )
291
spec.refs ;
292
if not is_closed then emitln out " | Unknown j -> j" ;