-
-
Save stevan/ce835d10395640410507 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* A polymorphic variant type to represent Perl values | |
in a more Ocaml-ish way, along with functions for | |
converting between representations *) | |
module Utils = | |
struct | |
exception Cannot_convert of string | |
type variant = [ `Null | |
| `String of string | |
| `Int of int | |
| `Float of float | |
| `Bool of bool | |
| `Array of variant list | |
| `Hash of (string * variant) list | |
] | |
(** Perl <-> Variant *) | |
let rec perl_of_variant = function | |
| `Null -> Scalar.sv_undef () | |
| `String s -> Scalar.sv_of_string s | |
| `Int i -> Scalar.sv_of_int i | |
| `Float f -> Scalar.sv_of_float f | |
| `Bool b -> Scalar.sv_of_bool b | |
| `Array xs -> Ref.ref_of_av | |
(Array.from_list (List.map perl_of_variant xs)) | |
| `Hash xs -> Ref.ref_of_hv | |
(let hv = Hash.create_empty () in | |
List.iter (fun (k, v) -> Hash.set hv k (perl_of_variant v)) xs; | |
hv) | |
let rec variant_of_perl x = | |
let is_scalar_ref s_ref = | |
try ignore(Ref.sv_of_ref(s_ref)); true | |
with Invalid_argument(_) -> false | |
in | |
let reftype s = | |
try ignore(Ref.av_of_ref s); Scalar.SVt_PVAV | |
with Invalid_argument(_) -> | |
try ignore(Ref.hv_of_ref s); Scalar.SVt_PVHV | |
with Invalid_argument(_) -> raise (Cannot_convert "Cannot convert unknown reftype") | |
in | |
let rec loop sv_type = | |
match sv_type with | |
| Scalar.SVt_NULL -> `Null | |
| Scalar.SVt_IV -> `Int(Scalar.int_of_sv x) | |
| Scalar.SVt_NV -> `Float(Scalar.float_of_sv x) | |
| Scalar.SVt_PV -> `String(Scalar.string_of_sv x) | |
| Scalar.SVt_PVAV -> `Array(Array.map variant_of_perl (Ref.av_of_ref x)) | |
| Scalar.SVt_PVHV -> `Hash(List.map | |
(fun (k,v) -> (k, (variant_of_perl v))) | |
(Hash.to_assoc (Ref.hv_of_ref x))) | |
| Scalar.SVt_RV | |
when is_scalar_ref(x) | |
-> variant_of_perl (Ref.sv_of_ref x) | |
| Scalar.SVt_RV -> loop (reftype x) | |
| Scalar.SVt_PVMG -> raise (Cannot_convert "Cannot convert magic value") | |
| Scalar.SVt_PVGV -> raise (Cannot_convert "Cannot convert Glob (possibly a file handle)") | |
| Scalar.SVt_PVCV -> raise (Cannot_convert "Cannot convert Code value") | |
in loop (Scalar.sv_type x) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment