(*
   temp.ml
   15-411
   by Roland Flury
*)
(* @version $Id: temp.ml,v 1.2 2004/10/26 05:10:08 ajo Exp $ *)

module HA = Hashtbl
module A = Absyn

exception TempError of string

(*
   Overview:
   Temps are temporary registers that can be used in a program. We will 
   assume that we have an infinite number of registers until we do the
   register allocation, which is responsible for shrinking the number of 
   registers to the actually available number.
*)

(***********************************************************************)
(* Variables *)
(***********************************************************************)

(* Type of the indices representing temporary variables *)
type temp = int

(* Types of the look-up tables *)
type ty_name_temp = (string, temp) HA.t
type ty_temp_name = (temp, string) HA.t

(* Hashtables to store information about temps *)
let name_temp : ty_name_temp = HA.create 371
let temp_name : ty_temp_name = HA.create 317

(* The counter *)
let tmp_counter : temp ref = ref 0

(* Return a new temp, not bound to a variable-name *)
let simpTemp () =
  tmp_counter := !tmp_counter + 1;
  !tmp_counter

(* Return a temp for a variable given the variable's name *)
let namedTemp name =
  if(HA.mem name_temp name) then
    HA.find name_temp name
  else (
    let tmp = simpTemp () in
    HA.add name_temp name tmp;
    HA.add temp_name tmp name;
    tmp
   )

(* Returns a string representation of a temp *)
let temp2string t =
  Pervasives.string_of_int t

(*
   The function |listBindings| prints out all variable names bound inside 
   the current function, and their temp index values.
*)
let listBindings () =
  HA.iter (fun s i ->
    print_string (s ^ ":");
    print_int i;
    print_string "  ") name_temp

(*
   The function |nameOfTemp| returns the variable name associated with
   the given temp, or else "#" if it is a compiler temp.
*)
let nameOfTemp temp =
  (try
    HA.find temp_name temp
  with Not_found -> "#"
  )