Source file piqobj_to_piq.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
module C = Piqi_common
open C
open Piqobj_common
let is_external_mode = ref false
let gen_float x = `float (x, "")
let gen_string ?piq_format s =
match piq_format with
| Some `text ->
`text s
| Some `word when Piq_lexer.is_valid_word s ->
`word s
| _ ->
`string (s, "")
let gen_binary s =
if Piq_lexer.is_ascii_string s
then
`string (s, "")
else
`binary (s, "")
let make_named name value =
`named Piq_ast.Named.({name = name; value = value})
let make_name name =
`name name
let make_typed typename ast :piq_ast =
let res = Piq_ast.Typed.({typename = typename; value = ast}) in
Piqloc.addref ast res;
`typed res
let order_record_fields t piqobj_fields =
let find_fields ft l =
List.partition (fun x -> x.F.t == ft) l
in
let res, _rem =
List.fold_left
(fun (accu, rem) x ->
let res, rem' = find_fields x rem in
(List.rev_append res accu, rem'))
([], piqobj_fields)
t.T.Record.field
in
List.rev res
let rec gen_obj0 ?(piq_format: T.piq_format option) (x:Piqobj.obj) :piq_ast =
match x with
| `int x -> `int (x, "")
| `uint x -> `uint (x, "")
| `float x -> gen_float x
| `bool x -> `bool x
| `string x -> gen_string x ?piq_format
| `binary x -> gen_binary x
| `any x -> gen_any x
| `record x -> gen_record x
| `variant x -> gen_variant x
| `enum x -> gen_enum x
| `list x -> gen_list x
| `alias x -> gen_alias x ?piq_format
and gen_obj ?piq_format x =
let res = gen_obj0 x ?piq_format in
match res with
| `any any ->
Piqloc.addrefret x res
| _ ->
Piq_parser.piq_addrefret x res
and gen_typed_obj x =
let name = Piqobj_common.full_typename x in
`typed Piq_ast.Typed.({typename = name; value = gen_obj x})
and gen_any x =
let open Any in
if not !is_external_mode
then
`any (Piqobj.put_any x)
else (
let ast = Piqobj.piq_of_any x in
match x.typename, ast with
| Some typename, Some ast ->
make_typed typename ast
| None, Some ast ->
ast
| Some _, None ->
assert false
| None, None -> (
match Piqobj.json_of_any x, Piqobj.xml_of_any x with
| None, None ->
assert false
| Some json_ast, _ ->
let s = !Piqobj.string_of_json json_ast in
`form (`word "json", [`text s])
| None, Some xml_elems ->
let s = !Piqobj.string_of_xml (`Elem ("value", xml_elems)) in
`form (`word "xml", [`text s])
)
)
and gen_record x =
let open R in
let fields = order_record_fields x.t x.field in
let encoded_fields = U.flatmap gen_field fields in
let encoded_fields =
match x.unparsed_piq_fields_ref with
| None -> encoded_fields
| Some ref ->
let unparsed_fields = Piqi_objstore.get ref in
encoded_fields @ unparsed_fields
in
`list encoded_fields
and gen_field x =
let open F in
let name = name_of_field x.t in
let is_bool_default default const =
match default with
| None ->
false
| Some piqi_any ->
let any = Piqobj.any_of_piqi_any piqi_any in
(match any.Piqobj.Any.obj with
| None -> false
| Some obj -> (Piqobj.unalias obj = `bool const)
)
in
let bool_value =
match x.obj with
| None -> None
| Some obj ->
(match Piqobj.unalias obj with
| `bool x -> Some x
| _ -> None
)
in
if bool_value = Some false && is_bool_default x.t.T.Field.default false
then
[]
else
let res =
match x.obj with
| None ->
make_name name
| Some obj ->
if bool_value = Some true && is_bool_default x.t.T.Field.piq_flag_default true
then
make_name name
else
make_named name (gen_obj obj ?piq_format:x.t.T.Field.piq_format)
in
let res = Piq_parser.piq_addrefret x res in
[res]
and gen_variant x =
let open V in
gen_option x.option
and gen_option x =
let open O in
let name = name_of_option x.t in
let res =
match x.obj with
| None -> make_name name
| Some obj -> make_named name (gen_obj obj ?piq_format:x.t.T.Option.piq_format)
in Piq_parser.piq_addrefret x res
and gen_enum x =
let open E in
gen_option x.option
and gen_list x =
let open L in
`list (List.map (fun obj -> gen_obj obj ?piq_format:x.t.T.Piqi_list.piq_format) x.obj)
and gen_alias ?(piq_format: T.piq_format option) x =
let open A in
let this_piq_format = x.t.T.Alias.piq_format in
let piq_format =
if this_piq_format <> None
then this_piq_format
else piq_format
in
match x.obj with
| `alias x ->
gen_alias x ?piq_format
| x ->
gen_obj x ?piq_format
let gen_obj obj = gen_obj obj
let _ =
Piqobj.to_piq := gen_obj