type t = | VUnit | VInt of int | VBool of bool | VString of string | VTuple of t list | VRecord of string * (string * t) list | VCollection of t Delta_runtime.Pure_map.t let rec to_string value = match value with | VUnit -> "unit" | VInt number -> string_of_int number | VBool true -> "true" | VBool false -> "false" | VString text -> Printf.sprintf "%S" text | VTuple items -> "(tuple " ^ Util.join " " (List.map to_string items) ^ ")" | VRecord (name, fields) -> Printf.sprintf "(record:%s %s)" name (Util.join " " (List.map (fun (label, field) -> "(" ^ label ^ " " ^ to_string field ^ ")") fields)) | VCollection map -> let entries = List.map (fun (key, item) -> Printf.sprintf "(%d %s)" key (to_string item)) (Delta_runtime.Pure_map.bindings map) in "(collection " ^ Util.join " " entries ^ ")" let collection_of_list entries = List.fold_left (fun map (key, value) -> if Delta_runtime.Pure_map.mem key map then Diagnostic.error Location.none "duplicate key %d in the initial input" key; Delta_runtime.Pure_map.add key value map) Delta_runtime.Pure_map.empty entries let collection_to_list map = Delta_runtime.Pure_map.bindings map let rec equal (left : t) (right : t) = match (left, right) with | VUnit, VUnit -> true | VInt a, VInt b -> a = b | VBool a, VBool b -> a = b | VString a, VString b -> a = b | VTuple a, VTuple b -> List.length a = List.length b && List.for_all2 equal a b | VRecord (name_a, fields_a), VRecord (name_b, fields_b) -> name_a = name_b && List.length fields_a = List.length fields_b && List.for_all2 (fun (label_a, value_a) (label_b, value_b) -> label_a = label_b && equal value_a value_b) fields_a fields_b | VCollection map_a, VCollection map_b -> Delta_runtime.Pure_map.equal equal map_a map_b | _ -> false let field record label = match record with | VRecord (_, fields) -> Util.assoc_opt label fields | _ -> None let is_collection = function VCollection _ -> true | _ -> false