open Types open Values type size = int32 type index = int32 type count = int32 type table = {mutable ty : table_type; mutable content : ref_ array} type t = table exception Type exception Bounds exception SizeOverflow exception SizeLimit exception OutOfMemory let valid_limits {min; max} = match max with | None -> true | Some m -> I32.le_u min m let create size r = try Lib.Array32.make size r with Out_of_memory | Invalid_argument _ -> raise OutOfMemory let alloc (TableType (lim, _) as ty) r = if not (valid_limits lim) then raise Type; {ty; content = create lim.min r} let size tab = Lib.Array32.length tab.content let type_of tab = tab.ty let grow tab delta r = let TableType (lim, t) = tab.ty in assert (lim.min = size tab); let old_size = lim.min in let new_size = Int32.add old_size delta in if I32.gt_u old_size new_size then raise SizeOverflow else let lim' = {lim with min = new_size} in if not (valid_limits lim') then raise SizeLimit else let after = create new_size r in Array.blit tab.content 0 after 0 (Array.length tab.content); tab.ty <- TableType (lim', t); tab.content <- after let load tab i = try Lib.Array32.get tab.content i with Invalid_argument _ -> raise Bounds let store tab i r = let TableType (lim, t) = tab.ty in if type_of_ref r <> t then raise Type; try Lib.Array32.set tab.content i r with Invalid_argument _ -> raise Bounds let blit tab offset rs = let data = Array.of_list rs in try Lib.Array32.blit data 0l tab.content offset (Lib.Array32.length data) with Invalid_argument _ -> raise Bounds