291 lines · 8.1 KB · Standard ML
RawDownload
(* Symtable.sml : to assign numbers to global variables and so on *) local  open Misc Nonstdio Obj Fnlib Config Mixture Const;in (* Hashtables for numbering objects *) type 'a numtable ={  num_cnt: int ref,              (* The current number *)  num_tbl: ('a, int) Hasht.t     (* The table *)}; fun new_numtable size =  { num_cnt = ref 0, num_tbl = Hasht.new size }; fun find_in_numtable (nt : ''a numtable) =  Hasht.find (#num_tbl nt); fun enter_in_numtable (nt : ''_a numtable) key =  let val c = !(#num_cnt nt) in    #num_cnt nt := !(#num_cnt nt) + 1;    Hasht.insert (#num_tbl nt) key c;    c  end; fun remove_from_numtable (nt : ''a numtable) key =  Hasht.remove (#num_tbl nt) key; (* Global variables *) val global_table =  ref (new_numtable 1 : (QualifiedIdent * int) numtable) and literal_table =  ref ([] : (int * StructConstant) list); fun get_slot_for_variable (uid as (qualid, stamp)) =  find_in_numtable (!global_table) uid  handle Subscript =>    (let val {qual,id} = qualid	 val mid = longIdentAsIdent id "get_slot_for_variable"	 val (desc,s) = 	     case unmangle mid of		 ValId s => 		     ("Value ",s)	       | ModId s =>		     ("Structure ",s)	       | FunId s =>		     ("Functor ",s)     in	 msgIBlock 0;	 msgEOL();	 errPrompt desc;	 msgString qual; msgString "."; msgString s;	 if stamp <> 0 then (msgString "/"; msgInt stamp) else ();	 msgString " hasn't been defined yet"; msgEOL();	 msgEBlock();	 raise Toplevel     end); fun get_slot_for_defined_variable (uid as (qualid, stamp)) =  enter_in_numtable (!global_table) uid; fun get_slot_for_literal cst =  let val c = !(#num_cnt (!global_table)) in    #num_cnt(!global_table) := !(#num_cnt (!global_table)) + 1;    literal_table := (c, cst) :: !literal_table;    c  end; fun number_of_globals () =  !(#num_cnt (!global_table)); fun defineGlobalValueAlias uid uid' =  let val slot = get_slot_for_variable uid' in    Hasht.insert (#num_tbl (!global_table)) uid slot  end; (* The exception tags *) (* ps: val unknown_exn_name = ({qual="?", id=["?"]}, 0);val exn_tag_table = ref(new_numtable 1 : (QualifiedIdent * int) numtable);val tag_exn_table = ref(Array.fromList [] : (QualifiedIdent * int) Array.array ); *) (* cvr: fun fromShortTagExnTable a = Array.tabulate      ((Array.length a),      (fn i => case Array.sub (a, i) of               ({qual=qual,id = id},i) => ({qual=qual,id = [id]},i))); fun toShortTagExnTable a = Array.tabulate      ((Array.length a),      (fn i => case Array.sub (a, i) of               ({qual=qual,id = [id]},i) => ({qual=qual,id = id},i))); fun get_num_of_exn (name, stamp) =  Hasht.find (#num_tbl (!exn_tag_table)) (name, stamp)  handle Subscript =>    let val c = enter_in_numtable (!exn_tag_table) (name, stamp)        val len = Array.length (!tag_exn_table)    in      if c < len then () else        let val new_len = 2 * len            val new_tag_exn_table = Array.array(new_len, unknown_exn_name)        in          Array.copy {src = !tag_exn_table, si = 0, len = NONE,                      dst = new_tag_exn_table, di = 0};          tag_exn_table := new_tag_exn_table        end;      Array.update(!tag_exn_table, c, (name, stamp));      c    end; fun get_exn_of_num tag =  if tag >= Array.length (!tag_exn_table)  then unknown_exn_name  else Array.sub(!tag_exn_table, tag); fun defineGlobalExceptionAlias (q, (q', stamp')) =  let val tag = get_num_of_exn (q', stamp') in    Hasht.insert (#num_tbl (!exn_tag_table)) (q, 0) tag  end;*) fun intOfTag (CONtag(n,_)) = n(*  | intOfTag (EXNtag(id, stamp)) = fatalError "intOfTag" (* ps: get_num_of_exn(id, stamp) *) *); (* The C primitives *) val c_prim_table = ref (new_numtable 0 : string numtable); (* cvr: 144 merge fun set_c_primitives prim_vect =  (c_prim_table := new_numtable 31;   for (fn i => ignore          (enter_in_numtable (!c_prim_table) (Vector.sub(prim_vect, i))))       0 (Vector.length prim_vect - 1));*)fun set_c_primitives prim_vect =  (c_prim_table := new_numtable 67;   Vector.app (ignore o enter_in_numtable (!c_prim_table)) prim_vect); fun get_num_of_prim name =  find_in_numtable (!c_prim_table) name  handle Subscript =>    (msgIBlock 0;     errPrompt "Unavailable C primitive: ";     msgString name; msgEOL();     msgEBlock();     raise Toplevel); fun exportPublicNames uname excRenList valRenList =  ((* ps: List.app defineGlobalExceptionAlias excRenList; *)   List.app     (fn (id, stamp) =>         defineGlobalValueAlias           ({ qual=uname, id=[id] }, 0)           ({ qual=uname, id=[id] }, stamp))     valRenList); (* Initialization *) (* ps: val normalizeExnName = fn    {qual="sys", id=["Break"]}     => {qual="General", id=["Interrupt"]}  | {qual="sys", id=["Sys_error"]} => {qual="General", id=["SysErr"]}  | {qual="exc", id=["Not_found"]} => {qual="General", id=["Subscript"]}  | {qual="io",  id=["End_of_file"]} => {qual="General", id=["Size"]}  | {qual="exc", id=["Out_of_memory"]} => {qual="General", id=["Out_of_memory"]}  | {qual="exc", id=["Invalid_argument"]} =>       {qual="General", id=["Invalid_argument"]}  | {qual="exc", id=["Failure"]}   => {qual="General", id=["Fail"]}  | {qual="graphics", id=["Graphic_failure"]} =>                          {qual="General", id=["Graphic_failure"]}  | {qual="general", id=["Exception"]} => {qual="General", id=["(Exception)"]}  | {qual="general", id=[id]}      => {qual="General", id=[id]}  | qualid => qualid; *) fun reset_linker_tables () =(  global_table := new_numtable 263;  literal_table := [];  List.app    (fn {qual, id} =>       ignore( get_slot_for_defined_variable	      (* ps: ({qual="(global)", id=[id]}, 0) *)	      ({qual=qual, id=[id]}, 0) ))    Predef.predef_variables;(* ps: exn_tag_table := new_numtable 31;  tag_exn_table := Array.array(50, unknown_exn_name);  List.app    (fn ({qual,id}, stamp) =>         ignore(get_num_of_exn (normalizeExnName {qual=qual,id = [id]}, 0)))    Predef.predef_exn;*)  set_c_primitives Prim_c.primitives_table); fun save_linker_tables outstream =(  output_binary_int outstream (! (#num_cnt(!global_table)))(* cvr: removed  output_value outstream (!exn_tag_table);  output_value outstream (!tag_exn_table)*)(* cvr: added: *)(* ps:  ; output_value outstream (toShortExnTagTable(!exn_tag_table));  output_value outstream (toShortTagExnTable(!tag_exn_table))(* cvr: *) *)); (* To read linker tables from the executable file *) fun load_linker_tables () =  ( let      val is = open_in_bin (Vector.sub(Miscsys.command_line, 0))      (* The code, data, symb, and debug indexes are located 20 bytes          before the end of the bytecode file. *)      val () = seek_in is (in_stream_length is - 20)      val size_code = input_binary_int is      val size_data = input_binary_int is      val size_symb = input_binary_int is      val size_debug = input_binary_int is    in      seek_in is (in_stream_length is - 20 - size_debug - size_symb);      (* We don't need information about the internals *)      (* of Moscow ML system! *)      global_table := new_numtable 263;      #num_cnt (!global_table) := input_binary_int is    end  ) handle _ => fatalError "Unable to read linker tables from bytecode"; (* Initialization *) prim_val available_primitives : unit -> string Vector.vector                                  = 1 "available_primitives"; fun init_linker_tables () =(  load_linker_tables();  (* Hasht.clear (#num_tbl (!global_table)); *)  appFrom    (fn slot => fn {qual,id} =>       Hasht.insert (#num_tbl (!global_table)) ({qual=qual,id=[id]}, 0) slot)    0 Predef.predef_variables;  literal_table := [];  set_c_primitives (available_primitives())); (* added -- 07Sep95 e *) fun protect_linker_tables fct =  let val saved_global_table     = !global_table      and saved_literal_table    = !literal_table      and saved_c_prim_table     = !c_prim_table  in    (fct();     global_table  := saved_global_table;     literal_table := saved_literal_table;     c_prim_table  := saved_c_prim_table     )    handle x =>      (global_table  := saved_global_table;       literal_table := saved_literal_table;       c_prim_table  := saved_c_prim_table;       raise x)  end end;