(* A polymorphic symbol table. *)

module SymTab

open System

(*
A symbol table is just a list of tuples identifiers and values. This allows for
easy shadowing, as a shadowing binding can be quickly placed at the head of the
list.
*)
type SymTab<'a> = SymTab of (string * 'a) list

let empty () = SymTab []

let rec lookup n tab =
  match tab with
    | SymTab [] -> None
    | SymTab ((n1,i1)::remtab) ->
        if n = n1
        then Some i1
        else lookup n (SymTab remtab)

let bind n i (SymTab stab) = SymTab ((n,i)::stab)

let remove n (SymTab stab) =
    SymTab (List.filter (fun (x, _) -> x <> n) stab)

let removeMany ns (SymTab stab) =
  SymTab (List.filter (fun (x, _) ->
            not (List.exists (fun y -> y = x) ns)) stab)

let combine (SymTab t1) (SymTab t2) = SymTab (t1 @ t2)

let fromList l = SymTab l

let toList (SymTab lst) = lst
