(*
 * Emulation of (a subset of) the `env` module currently used by Binaryen,
 * so that we can run modules generated by Binaryen. This is a stopgap until
 * we have agreement on what libc should look like.
 *)

open Values
open Types
open Instance


let error msg = raise (Eval.Crash (Source.no_region, msg))

let type_error v t =
  error
    ("type error, expected " ^ string_of_value_type t ^
     ", got " ^ string_of_value_type (type_of v))

let empty = function
  | [] -> ()
  | vs -> error "type error, too many arguments"

let single = function
  | [] -> error "type error, missing arguments"
  | [v] -> v
  | vs -> error "type error, too many arguments"

let int = function
  | I32 i -> Int32.to_int i
  | v -> type_error v I32Type


let abort vs =
  empty vs;
  print_endline "Abort!";
  exit (-1)

let exit vs =
  exit (int (single vs))


let lookup name t =
  match Utf8.encode name, t with
  | "abort", ExternalFuncType t -> ExternalFunc (HostFunc (t, abort))
  | "exit", ExternalFuncType t -> ExternalFunc (HostFunc (t, exit))
  | _ -> raise Not_found
