home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / compiler / Mixture.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  6.5 KB  |  260 lines  |  [TEXT/R*ch]

  1. open BasicIO Nonstdio Fnlib Config PP;
  2.  
  3. exception Toplevel;
  4. exception EndOfFile;
  5. exception LexicalError of string * int * int;
  6.  
  7. val toplevel = ref false;
  8.  
  9. val pp_out = mk_ppstream
  10. {
  11.   linewidth = 79,
  12.   flush     = fn() => flush_out std_out,
  13.   consumer  = outputc std_out
  14. };
  15.  
  16. fun msgCBlock offset = begin_block pp_out CONSISTENT offset;
  17. fun msgIBlock offset = begin_block pp_out INCONSISTENT offset;
  18. fun msgEBlock() = end_block pp_out;
  19. fun msgBreak size_offset = add_break pp_out size_offset;
  20. fun msgClear() = clear_ppstream pp_out;
  21. fun msgFlush() = flush_ppstream pp_out;
  22.  
  23. val msgString = add_string pp_out;
  24.  
  25. fun msgChar (i : char) = msgString (String.str i);
  26. local 
  27.     prim_val sml_string_of_int    : int  -> string = 1 "sml_string_of_int";
  28.     prim_val sml_string_of_float  : real -> string = 1 "sml_string_of_float";
  29.     prim_val sml_hexstring_of_word : word -> string = 1 "sml_hexstring_of_word";
  30. in
  31.     fun msgInt  (i : int)  = msgString (sml_string_of_int i);
  32.     fun msgReal (r : real) = msgString (sml_string_of_float r);
  33.     fun msgWord (w : word) = msgString (sml_hexstring_of_word w);
  34. end
  35.  
  36. fun msgEOL() = add_newline pp_out;
  37.  
  38. fun msgPrompt s =
  39.   (if !toplevel then msgString toplevel_output_prompt
  40.                 else msgString batch_output_prompt;
  41.   msgString s)
  42. ;
  43.  
  44. fun msgContPrompt s =
  45.   (if !toplevel then msgString toplevel_output_cont_prompt
  46.                 else msgString batch_output_cont_prompt;
  47.   msgString s)
  48. ;
  49.  
  50. fun errPrompt s =
  51.   (if !toplevel then msgString toplevel_error_prompt
  52.                 else msgString batch_error_prompt;
  53.   msgString s)
  54. ;
  55.  
  56. (* Handling files and directories *)
  57.  
  58. val path_library = ref "";
  59. val load_path = ref ([] : string list);
  60.  
  61. (* This MUST be ref false; the default (value polymorphism/imperative types) 
  62.  * is set in files Mainc.sml and Maint.sml instead: 
  63.  *)
  64. val value_polymorphism = ref false;
  65.  
  66. fun cannot_find filename =
  67.   raise (Fail ("Cannot find file "^filename))
  68. ;
  69.  
  70. fun find_in_path filename =
  71.   if file_exists filename then
  72.     filename
  73.   else if Filename.is_absolute filename then
  74.     cannot_find filename
  75.   else
  76.     let fun h [] =
  77.               cannot_find filename
  78.           | h (a::rest) =
  79.               let val b = Filename.concat a filename in
  80.                 if file_exists b then b else h rest
  81.               end
  82.     in h (!load_path) end
  83. ;
  84.  
  85. fun remove_file f =
  86.   Miscsys.remove f
  87.     handle SysErr _ => ()
  88. ;
  89.  
  90. (* ---------- *)
  91.  
  92. datatype Lab =
  93.     INTlab of int
  94.   | STRINGlab of string
  95. ;
  96.  
  97. type 'a Row = (Lab * 'a) list;
  98.  
  99. fun printLab (STRINGlab s) = msgString s
  100.   | printLab (INTlab i) = msgInt i
  101. ;
  102.  
  103. val labOne = INTlab 1
  104. and labTwo = INTlab 2
  105. ;
  106.  
  107. fun isPairRow [(INTlab 1, _), (INTlab 2, _)] = true
  108.   | isPairRow [(INTlab 2, _), (INTlab 1, _)] = true
  109.   | isPairRow _ = false
  110. ;
  111.  
  112. fun isTupleRow' n [] = true
  113.   | isTupleRow' n (((INTlab i), _) :: fs) =
  114.       if n = i then isTupleRow' (n+1) fs else false
  115.   | isTupleRow' n _ = false
  116.  
  117. fun isTupleRow fs =
  118.   (List.length fs <> 1) andalso (isTupleRow' 1 fs)
  119. ;
  120.  
  121. fun mkPairRow x1 x2 = [(labOne, x1), (labTwo, x2)];
  122.  
  123. fun mkTupleRow' n [] = []
  124.   | mkTupleRow' n (x :: xs) =
  125.       (INTlab n, x) :: mkTupleRow' (n+1) xs
  126. ;
  127.  
  128. fun mkTupleRow xs = mkTupleRow' 1 xs;
  129.  
  130. fun lt_lab (STRINGlab s1) (STRINGlab s2)  = s1 < s2
  131.   | lt_lab (STRINGlab _)  (INTlab _)      = true
  132.   | lt_lab (INTlab _)     (STRINGlab _)   = false
  133.   | lt_lab (INTlab i1)    (INTlab i2)     = i1 < i2
  134. ;
  135.  
  136. fun insertField (lab, x) fields =
  137.   case fields of
  138.       [] => [(lab, x)]
  139.     | (lab', x') :: rest =>
  140.         if lt_lab lab lab' then
  141.           (lab, x) :: fields
  142.         else if lt_lab lab' lab then
  143.           (lab', x') :: insertField (lab, x) rest
  144.         else
  145.           fatalError "insertField"
  146. ;
  147.  
  148. fun sortRow row = foldL insertField [] row;
  149.  
  150. (* --- Local environments --- *)
  151.  
  152. datatype ('a, 'b) Env
  153.   = NILenv
  154.   | BNDenv of 'a * 'b * ('a, 'b) Env
  155.   | TOPenv of ('a, 'b) Hasht.t * ('a, 'b) Env
  156.   | COMPenv of ('a, 'b) Env * ('a, 'b) Env
  157. ;
  158.  
  159. fun plusEnv NILenv env2   = env2
  160.   | plusEnv env1   NILenv = env1
  161.   | plusEnv env1   (BNDenv(k, v, NILenv)) = BNDenv(k, v, env1)
  162.   | plusEnv env1   env2   = COMPenv(env2, env1)
  163. ;
  164.  
  165. fun lookupEnv env key =
  166.   let val rec search = fn
  167.        NILenv => raise Subscript
  168.      | BNDenv(k, v, env) =>
  169.        if key = k then v else search env
  170.      | TOPenv(x, env) =>
  171.        (Hasht.find x key handle Subscript => search env)
  172.      | COMPenv(env1, env2) =>
  173.        (search env1 handle Subscript => search env2)
  174.   in search env end
  175. ;
  176.  
  177. fun bindInEnv env k v = BNDenv(k, v, env);
  178. fun bindTopInEnv env x = TOPenv(x, env);
  179.  
  180. fun mk1Env k v = BNDenv(k, v, NILenv);
  181. fun mk1TopEnv x = TOPenv(x, NILenv);
  182.  
  183. fun revEnvAcc NILenv acc = acc
  184.   | revEnvAcc (BNDenv(k, v, env)) acc =
  185.       revEnvAcc env (BNDenv(k, v, acc))
  186.   | revEnvAcc (TOPenv(x, env)) acc =
  187.       revEnvAcc env (TOPenv(x, acc))
  188.   | revEnvAcc (COMPenv(env1, env2)) acc =
  189.       revEnvAcc env2 (revEnvAcc env1 acc)
  190. ;
  191.  
  192. fun revEnv env = revEnvAcc env NILenv;
  193.  
  194. fun traverseEnv action env =
  195.   let fun traverse NILenv = ()
  196.         | traverse (BNDenv(k, v, env)) =
  197.             (action k v; traverse env)
  198.         | traverse (TOPenv(x, env)) =
  199.             (Hasht.apply action x; traverse env)
  200.         | traverse (COMPenv(env1, env2)) =
  201.             (traverse env1; traverse env2)
  202.   in traverse env end
  203. ;
  204.  
  205. fun mapEnv f env0 =
  206.   case env0 of
  207.       NILenv => NILenv
  208.     | BNDenv(k, v, env) =>
  209.         BNDenv(k, f k v, mapEnv f env)
  210.     | TOPenv(x, env) =>
  211.     (* This can be improved by simply making a copy of the hash table *)
  212.     let val newx = Hasht.new 17
  213.         fun ins k v = Hasht.insert newx k (f k v)
  214.     in 
  215.             Hasht.apply ins x; 
  216.         TOPenv(newx, mapEnv f env) 
  217.     end
  218.     | COMPenv(env1, env2) =>
  219.         COMPenv(mapEnv f env1, mapEnv f env2)
  220. ;
  221.  
  222. fun foldEnv f u env0 =
  223.   case env0 of
  224.       NILenv => u
  225.     | BNDenv(k, v, env) =>
  226.         f k v (foldEnv f u env)
  227.     | TOPenv(x, env) =>
  228.     Hasht.fold f (foldEnv f u env) x
  229.     | COMPenv(env1, env2) =>
  230.         foldEnv f (foldEnv f u env2) env1
  231. ;
  232.  
  233. fun mkHashEnv n env =
  234.     if n < 7 then env
  235.     else
  236.     let val hashenv = Hasht.new n
  237.     in 
  238.         traverseEnv (Hasht.insert hashenv) (revEnv env);
  239.         mk1TopEnv hashenv
  240.     end
  241.  
  242. (* --- Stamps of compiled signatures --- *)
  243.  
  244. type SigStamp = string;
  245.  
  246. val char_star = Char.chr 42;
  247. val dummySigStamp = CharVector.tabulate(22, fn _ => char_star);
  248.  
  249. (* This table is used by `load' to prevent mismatching *)
  250. (* versions of compiled units from being loaded, and also *)
  251. (* to prevent the same unit from being loaded twice. *)
  252.  
  253. val watchDog = ref (Hasht.new 17 : (string, SigStamp) Hasht.t);
  254.  
  255. (* The list of automatically preloaded units. *)
  256. (* Some of them are also preopened. *)
  257.  
  258. val preloadedUnits = ref ([] : string list);
  259. val preopenedPreloadedUnits = ref ([] : string list);
  260.