Instead of using a hash table to move from one partial representation of the register to another, have you thought about forcing yourself to always manipulate only the pointers to complete the descriptions so that you can access any aspect that you like (index, string representation, ...) with pointer dereferencing?
You can use the view (your regdescr type) as a register.
How often do you need to map a pattern to a register type?
If you do not, you can completely remove the reg field.
module Register : sig type t = private { name : string ; index : int } val r0 : t val at : t val equal : t -> t -> bool val hash : t -> int val compare : t -> t -> int end = struct type t = { name : string ; index : int } let r0 = { name = "R0" ; index = 0 } let at = { name = "AT" ; index = 1 } let equal r1 r2 = r1.index = r2.index let hash r1 = Hashtbl.hash (r1.index) let compare r1 r2 = Pervasives.compare r1.index r2.index end
Note. You can make it all more readable by using the register.ml and register.mli files to define the Register module.
If you sometimes need pattern matching, you can save the constructor field so that you can write good pattern mappings:
match r.reg with R0 -> ... | AT -> ...
But force yourself to write only functions that accept (and transmit their calls) the full Register.t .
EDIT: To index, first write a generic function below:
let all_registers = [ r0 ; at ] let index projection = let htbl = Hashtbl.create 32 in let fr = let key = projection r in Hashtbl.add htbl key r in List.iter f all_registers ; Hashtbl.find htbl
Then pass all the forecasts you need:
let of_int = index (fun r -> r.index) let of_name = index (fun r -> r.name)
source share