@@ -66,6 +66,77 @@ let keys (json : Json.t) =
66
66
Output. return (`List (Json. keys json |> List. map (fun i -> `String i)))
67
67
| _ -> Error (make_error " keys" json)
68
68
69
+ let has (json : Json.t ) key =
70
+ match key with
71
+ | String key -> (
72
+ match json with
73
+ | `Assoc list -> Output. return (`Bool (List. mem_assoc key list ))
74
+ | _ -> Error (make_error " has" json))
75
+ | Number n -> (
76
+ match json with
77
+ | `List list ->
78
+ Output. return (`Bool (List. length list - 1 > = int_of_float n))
79
+ | _ -> Error (make_error " has" json))
80
+ | _ -> Error (make_error " has" json)
81
+
82
+ let in_ (json : Json.t ) expr =
83
+ match json with
84
+ | `Int n -> (
85
+ match expr with
86
+ | List list -> Output. return (`Bool (List. length list - 1 > = n))
87
+ | _ -> Error (make_error " in" json))
88
+ | `String key -> (
89
+ match expr with
90
+ | Object list ->
91
+ let cmp_literal_str key = function
92
+ | Literal (String s ) when s = key -> true
93
+ | _ -> false
94
+ in
95
+ let s = List. map fst list |> List. find_opt (cmp_literal_str key) in
96
+ Output. return (`Bool (Option. is_some s))
97
+ | _ -> Error (make_error " in" json))
98
+ | _ -> Error (make_error " in" json)
99
+
100
+ let range ?step from upto =
101
+ let rec range ?(step = 1 ) start stop =
102
+ if step = 0 then []
103
+ else if (step > 0 && start > = stop) || (step < 0 && start < = stop) then []
104
+ else start :: range ~step (start + step) stop
105
+ in
106
+ match upto with
107
+ | None ->
108
+ List. map (fun i -> Output. return (`Int i)) (range 1 from)
109
+ |> Output. collect
110
+ | Some upto ->
111
+ List. map (fun i -> Output. return (`Int i)) (range ?step from upto)
112
+ |> Output. collect
113
+
114
+ let split expr json =
115
+ match json with
116
+ | `String s ->
117
+ let * rcase =
118
+ match expr with
119
+ | Literal (String s ) -> Output. return s
120
+ | _ -> Error " split input should be a string"
121
+ in
122
+ Output. return
123
+ (`List (Str. split (Str. regexp rcase) s |> List. map (fun s -> `String s)))
124
+ | _ -> Error " input should be a JSON string"
125
+
126
+ let join expr json =
127
+ let * rcase =
128
+ match expr with
129
+ | Literal (String s ) -> Output. return s
130
+ | _ -> Error " join input should be a string"
131
+ in
132
+ match json with
133
+ | `List l ->
134
+ Output. return
135
+ (`String
136
+ (List. map (function `String s -> s | _ -> " " ) l
137
+ |> String. concat rcase))
138
+ | _ -> Error " input should be a list"
139
+
69
140
let length (json : Json.t ) =
70
141
match json with
71
142
| `List list -> Output. return (`Int (list |> List. length))
@@ -230,10 +301,20 @@ let rec compile expression json : (Json.t list, string) result =
230
301
| Length -> length json
231
302
| Not -> not json
232
303
| Map expr -> map expr json
233
- | Addition (left , right ) -> operation left right add json
234
- | Subtraction (left , right ) -> operation left right sub json
235
- | Multiply (left , right ) -> operation left right mult json
236
- | Division (left , right ) -> operation left right div json
304
+ | Operation (left , op , right ) -> (
305
+ match op with
306
+ | Add -> operation left right add json
307
+ | Sub -> operation left right sub json
308
+ | Mult -> operation left right mult json
309
+ | Div -> operation left right div json
310
+ | Gt -> operation left right gt json
311
+ | Ge -> operation left right gte json
312
+ | St -> operation left right lt json
313
+ | Se -> operation left right lte json
314
+ | Eq -> operation left right eq json
315
+ | Neq -> operation left right notEq json
316
+ | And -> operation left right and_ json
317
+ | Or -> operation left right or_ json)
237
318
| Literal literal -> (
238
319
match literal with
239
320
| Bool b -> Output. return (`Bool b)
@@ -248,20 +329,36 @@ let rec compile expression json : (Json.t list, string) result =
248
329
match res with
249
330
| `Bool b -> ( match b with true -> Output. return json | false -> empty)
250
331
| _ -> Error (make_error " select" res))
251
- | Greater (left , right ) -> operation left right gt json
252
- | GreaterEqual (left , right ) -> operation left right gte json
253
- | Lower (left , right ) -> operation left right lt json
254
- | LowerEqual (left , right ) -> operation left right lte json
255
- | Equal (left , right ) -> operation left right eq json
256
- | NotEqual (left , right ) -> operation left right notEq json
257
- | And (left , right ) -> operation left right and_ json
258
- | Or (left , right ) -> operation left right or_ json
259
332
| List exprs ->
260
333
Output. collect (List. map (fun expr -> compile expr json) exprs)
261
334
|> Result. map (fun x -> [ `List x ])
262
335
| Comma (leftR , rightR ) ->
263
336
Result. bind (compile leftR json) (fun left ->
264
337
Result. bind (compile rightR json) (fun right -> Ok (left @ right)))
338
+ | Object list -> handle_objects list json
339
+ | Has e -> (
340
+ match e with
341
+ | Literal ((String _ | Number _ ) as e ) -> has json e
342
+ | _ -> Error (show_expression e ^ " is not allowed" ))
343
+ | In e -> in_ json e
344
+ | Range (from , upto , step ) -> range ?step from upto
345
+ | Reverse -> (
346
+ match json with
347
+ | `List l -> Output. return (`List (List. rev l))
348
+ | _ -> Error (make_error " reverse" json))
349
+ | Split expr -> split expr json
350
+ | Join expr -> join expr json
351
+ | Abs -> (
352
+ match json with
353
+ | `Int n -> Output. return (`Int (if n < 0 then - n else n))
354
+ | `Float j -> Output. return (`Float (if j < 0. then -. j else j))
355
+ | _ -> Error (make_error " reverse" json))
356
+ | IfThenElse (cond , if_branch , else_branch ) -> (
357
+ let * cond = compile cond json in
358
+ match cond with
359
+ | `Bool b ->
360
+ if b then compile if_branch json else compile else_branch json
361
+ | json -> Error (make_error " if condition should be a bool" json))
265
362
| _ -> Error (show_expression expression ^ " is not implemented" )
266
363
267
364
and operation leftR rightR op json =
@@ -276,3 +373,35 @@ and map (expr : expression) (json : Json.t) =
276
373
|> Result. map (fun x -> [ `List x ])
277
374
| `List _list -> Error (make_empty_list_error " map" )
278
375
| _ -> Error (make_error " map" json)
376
+
377
+ and handle_objects list json =
378
+ List. map
379
+ (fun (left_expr , right_expr ) ->
380
+ match (left_expr, right_expr) with
381
+ | Literal (String n ), None ->
382
+ (* Search for this key in JSON *)
383
+ let r =
384
+ match json with
385
+ | `Null -> Output. return (`Assoc [ (n, `Null ) ])
386
+ | `Assoc l -> (
387
+ match List. assoc_opt n l with
388
+ | None -> Output. return (`Assoc [ (n, `Null ) ])
389
+ | Some v -> Output. return (`Assoc [ (n, v) ]))
390
+ | _ -> Error (Json. show json ^ " is not implemented" )
391
+ in
392
+ r
393
+ | Literal (String key ), Some right_expr -> (
394
+ match right_expr with
395
+ | Key (search_val , _ ) -> (
396
+ match json with
397
+ | `Assoc l -> (
398
+ match List. assoc_opt search_val l with
399
+ | None -> Output. return (`Assoc [ (key, `Null ) ])
400
+ | Some v -> Output. return (`Assoc [ (key, v) ]))
401
+ | _ -> assert false )
402
+ | rexp ->
403
+ let * rexp = compile rexp json in
404
+ Output. return (`Assoc [ (key, rexp) ]))
405
+ | _ -> Error (show_expression left_expr ^ " is not implemented" ))
406
+ list
407
+ |> Output. collect
0 commit comments