I came up with the following. It works fine if I need to look up an id, know the type and need to fetch the value.
Is there a way to fetch the value by name, without knowing the type? The use case is finding an id when parsing. The type is not known at that point but a value may exist in the environment.
My find implementation below doesn’t work since I can only find out if the value exists and cannot unwrap it. Is there a better way than enumerating all the types with a given name by calling Type_env.lookup repeatedly?
module Type_env = struct
type 'n t =
| Nil
| Cons : string * ('a, 'n) Type.t * 'a * 'n t -> 'n t
type ('a, 'b, 'na, 'nb) eq = Refl : ('a, 'a, 'na, 'na) eq
let make () = Nil
let types_equal
: type a b n. (a, n) Type.t -> (b, n) Type.t -> (a, b, n, n) eq option
=
fun a b ->
let open Type in
match a, b with
| Register, Register -> Some Refl
| Register_index, Register_index -> Some Refl
| Bit_field, Bit_field -> Some Refl
| Macro, Macro -> Some Refl
| Memory_region', Memory_region' -> Some Refl
| _, _ -> None
;;
let append ~env ~name ~ty ~value = Cons (name, ty, value, env)
let rec lookup : type a n. n t -> string -> (a, n) Type.t -> a option =
fun env name ty ->
match env with
| Nil -> None
| Cons (xname, xty, value, rest) ->
if name = xname then (
match types_equal ty xty with
| Some Refl -> Some value
| None -> assert false
) else
lookup rest name ty
;;
type 'n value = Value : ('a * ('a, 'n) Type.t) -> 'n value [@@unboxed]
let rec find : 'n t -> string -> 'n value option =
fun env name ->
match env with
| Nil -> None
| Cons (xname, ty, value, rest) ->
if name = xname then
Some (Value (value, ty))
else
find rest name
;;
end