blob: 54ef499092534133f682c12d78d8c6ab28f11a5f [file] [log] [blame] [edit]
open Types
open Value
type field =
| ValField of value ref
| PackField of packtype * int ref
type struct_ = Struct of deftype * field list
type array = Array of deftype * field list
type ref_ += StructRef of struct_
type ref_ += ArrayRef of array
let gap pt = 32 - 8 * pack_size pt
let wrap pt i = Int32.(to_int (logand i (shift_right_logical (-1l) (gap pt))))
let extend_u _pt i = Int32.of_int i
let extend_s pt i = Int32.(shift_right (shift_left (of_int i) (gap pt)) (gap pt))
let alloc_field ft v =
let FieldT (_mut, st) = ft in
match st, v with
| ValStorageT _, v -> ValField (ref v)
| PackStorageT sz, Num (I32 i) -> PackField (sz, ref (wrap sz i))
| _, _ -> failwith "alloc_field"
let write_field fld v =
match fld, v with
| ValField vr, v -> vr := v
| PackField (sz, ir), Num (I32 i) -> ir := wrap sz i
| _, _ -> failwith "write_field"
let read_field fld exto =
match fld, exto with
| ValField vr, None -> !vr
| PackField (sz, ir), Some Pack.U -> Num (I32 (extend_u sz !ir))
| PackField (sz, ir), Some Pack.S -> Num (I32 (extend_s sz !ir))
| _, _ -> failwith "read_field"
let array_length (Array (_, fs)) = Lib.List32.length fs
let alloc_struct dt vs =
assert Free.((deftype dt).types = Set.empty);
let fts = structtype_of_comptype (expand_deftype dt) in
Struct (dt, List.map2 alloc_field fts vs)
let alloc_array dt vs =
assert Free.((deftype dt).types = Set.empty);
let ft = arraytype_of_comptype (expand_deftype dt) in
Array (dt, List.map (alloc_field ft) vs)
let type_of_struct (Struct (dt, _)) = dt
let type_of_array (Array (dt, _)) = dt
let () =
let type_of_ref' = !Value.type_of_ref' in
Value.type_of_ref' := function
| StructRef s -> UseHT (Def (type_of_struct s))
| ArrayRef a -> UseHT (Def (type_of_array a))
| r -> type_of_ref' r
let string_of_field = function
| ValField vr -> string_of_value !vr
| PackField (_, ir) -> string_of_int !ir
let string_of_fields nest fs =
if fs = [] then "" else
if !nest > 0 then " ..." else
let fs', ell =
if List.length fs > 5
then Lib.List.take 5 fs, ["..."]
else fs, []
in " " ^ String.concat " " (List.map string_of_field fs' @ ell)
let string_of_aggr name nest fs =
Fun.protect (fun () -> incr nest; "(" ^ name ^ string_of_fields nest fs ^ ")")
~finally:(fun () -> decr nest)
let () =
let string_of_ref' = !Value.string_of_ref' in
let nest = ref 0 in
Value.string_of_ref' := function
| StructRef (Struct (_, fs)) -> string_of_aggr "struct" nest fs
| ArrayRef (Array (_, fs)) -> string_of_aggr "array" nest fs
| r -> string_of_ref' r