open InterpreterAux.Wasm

let host_apply s tf hf vs =
	match hf with
	| ImplWrapperTypes.Hf f ->
  	try
  		Some (f s vs)
    with
  	| _ -> Printf.printf "HOST CRASH!"; None

let type_to_impl_type = function
  | T_i32 -> Types.I32Type
	| T_i64 -> Types.I64Type
  | T_f32 -> Types.F32Type
  | T_f64 -> Types.F64Type

let tp_to_impl_tp = function
	| Tp_i8 -> Memory.Mem8
	| Tp_i16 -> Memory.Mem16
	| Tp_i32 -> Memory.Mem32

let sx_to_impl_sx = function
	| S -> Memory.SX
	| U -> Memory.ZX

let size m = InterpreterAux.Arith.nat_of_integer (Big_int.big_int_of_int32 (Memory.size m))
let grow m n =
	try
		Memory.grow m (Big_int.int32_of_big_int (InterpreterAux.Arith.integer_of_nat n));
		Some m
	with
	| _ -> None

let load m i o l =
	try
		let ea = Memory.effective_address (Big_int.int64_of_big_int (InterpreterAux.Arith.integer_of_nat i)) (Big_int.int32_of_big_int (InterpreterAux.Arith.integer_of_nat o)) in
		Some (Memory.loadn m (Big_int.int_of_big_int (InterpreterAux.Arith.integer_of_nat l)) ea)
	with
	| _ -> None

let load_packed sx m i o l =
	try
		let ea = Memory.effective_address (Big_int.int64_of_big_int (InterpreterAux.Arith.integer_of_nat i)) (Big_int.int32_of_big_int (InterpreterAux.Arith.integer_of_nat o)) in
		match sx with
		| U -> Some (Memory.loadn m (Big_int.int_of_big_int (InterpreterAux.Arith.integer_of_nat l)) ea)
		| S -> Some (Memory.loadn_sx m (Big_int.int_of_big_int (InterpreterAux.Arith.integer_of_nat l)) ea)
	with
	| _ -> None

let store m i o v l =
	try
		let ea = Memory.effective_address (Big_int.int64_of_big_int (InterpreterAux.Arith.integer_of_nat i)) (Big_int.int32_of_big_int (InterpreterAux.Arith.integer_of_nat o)) in
		Memory.storen m (Big_int.int_of_big_int (InterpreterAux.Arith.integer_of_nat l)) ea v;
		Some m
  with
	| _ -> None

let store_packed m i o v l =
	try
		let ea = Memory.effective_address (Big_int.int64_of_big_int (InterpreterAux.Arith.integer_of_nat i)) (Big_int.int32_of_big_int (InterpreterAux.Arith.integer_of_nat o)) in
		Memory.storen m (Big_int.int_of_big_int (InterpreterAux.Arith.integer_of_nat l)) ea v;
		Some m
  with
	| _ -> None

let deserialise v t =
	match t with
	| T_i32 -> ConstInt32 (Int64.to_int32 v)
	| T_i64 -> ConstInt64 v
	| T_f32 -> ConstFloat32 (F32Wrapper.of_bits (Int64.to_int32 v))
	| T_f64 -> ConstFloat64 (F64Wrapper.of_bits v)

let bool b = (if b then 1l else 0l)
