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

  1. (* Compiler.sml *)
  2.  
  3. open List Obj BasicIO Nonstdio Fnlib Mixture Const Globals Location Units;
  4. open Types Smlperv Asynt Parser Ovlres Infixres Elab Sigmtch;
  5. open Tr_env Front Back Pr_zam Emit_phr;
  6.  
  7. (* Lexer of stream *)
  8.  
  9. fun createLexerStream (is : BasicIO.instream) =
  10.   Lexing.createLexer (fn buff => fn n => Nonstdio.buff_input is buff 0 n)
  11. ;
  12.  
  13. (* Parsing functions *)
  14.  
  15. fun parsePhrase parsingFun lexingFun lexbuf =
  16.   let fun skip() =
  17.     (case lexingFun lexbuf of
  18.         EOF => ()
  19.       | SEMICOLON => ()
  20.       | _ => skip())
  21.     handle LexicalError(_,_,_) =>
  22.       skip()
  23.   in
  24.     parsingFun lexingFun lexbuf
  25.     handle
  26.         Parsing.ParseError f =>
  27.            let val pos1 = Lexing.getLexemeStart lexbuf
  28.                val pos2 = Lexing.getLexemeEnd lexbuf
  29.            in
  30.              Lexer.resetLexerState();
  31.              if f (Obj.repr EOF) orelse
  32.                 f (Obj.repr SEMICOLON)
  33.              then () else skip();
  34.              msgIBlock 0;
  35.              errLocation (Loc(pos1, pos2));
  36.              errPrompt "Syntax error.";
  37.              msgEOL();
  38.              msgEBlock();
  39.              raise Toplevel
  40.            end
  41.        | LexicalError(msg, pos1, pos2) =>
  42.            (msgIBlock 0;
  43.             if pos1 >= 0 andalso pos2 >= 0 then
  44.               errLocation (Loc(pos1, pos2))
  45.             else ();
  46.             errPrompt "Lexical error: "; msgString msg;
  47.             msgString "."; msgEOL();
  48.             msgEBlock();
  49.             skip();
  50.             raise Toplevel)
  51.        | Toplevel =>
  52.            (skip ();
  53.             raise Toplevel)
  54.   end
  55. ;
  56.  
  57. fun parsePhraseAndClear parsingFun lexingFun lexbuf =
  58.   let val phr =
  59.     parsePhrase parsingFun lexingFun lexbuf
  60.     handle x => (Lexer.resetLexerState(); Parsing.clearParser(); raise x)
  61.   in
  62.     Lexer.resetLexerState();
  63.     Parsing.clearParser();
  64.     phr
  65.   end;
  66.  
  67. val parseToplevelPhrase =
  68.   parsePhraseAndClear Parser.ToplevelPhrase Lexer.Token
  69. ;
  70.  
  71. val parseStructFile =
  72.   parsePhraseAndClear Parser.StructFile Lexer.Token
  73. ;
  74.  
  75. val parseSigFile =
  76.   parsePhraseAndClear Parser.SigFile Lexer.Token
  77. ;
  78.  
  79. fun isInTable key tbl =
  80.   (Hasht.find tbl key; true)
  81.   handle Subscript => false
  82. ;
  83.  
  84. fun filter p xs =
  85.   rev(foldL (fn x => fn acc => if p x then x::acc else acc) [] xs)
  86. ;
  87.  
  88. fun filterExcRenList excRenList cBas =
  89.   filter (fn ({qual, id}, _) => isInTable id cBas) excRenList
  90. ;
  91.  
  92. fun filterValRenList valRenList cBas =
  93.   filter (fn (id, stamp) => isInTable id cBas) valRenList
  94. ;
  95.  
  96. fun cleanEnvAcc [] acc = acc
  97.   | cleanEnvAcc ((k, v) :: rest) acc =
  98.       if exists (fn (k', _) => k = k') acc then
  99.         cleanEnvAcc rest acc
  100.       else
  101.         cleanEnvAcc rest ((k, v) :: acc)
  102. ;
  103.  
  104. fun cleanEnv env =
  105.   cleanEnvAcc (foldEnv (fn a => fn x => fn acc => (a,x)::acc) [] env) []
  106. ;
  107.  
  108. (* Reporting the results of compiling a phrase *)
  109.  
  110. val verbose = ref false;
  111.  
  112. fun reportFixityResult (id, status) =
  113. (
  114.   (case status of
  115.        NONFIXst =>
  116.          msgString "nonfix "
  117.      | INFIXst i =>
  118.          (msgString "infix ";
  119.           msgInt i; msgString " ")
  120.      | INFIXRst i =>
  121.          (msgString "infixr ";
  122.           msgInt i; msgString " "));
  123.   msgString id
  124. );
  125.  
  126. fun reportEquOfType equ =
  127.   msgString
  128.     (case equ of
  129.          FALSEequ => ""
  130.        | TRUEequ => "eq"
  131.        | REFequ => "prim_EQ")
  132. ;
  133.  
  134. fun reportLhsOfTypeResult (tyname : TyName) =
  135.   let val vs = newTypeVars (#tnArity (!(#info tyname)))
  136.       val lhs = type_con (map TypeOfTypeVar vs) tyname
  137.   in printType lhs end
  138. ;
  139.  
  140. fun reportTypeResult (tyname : TyName) =
  141.   let val {qualid, info} = tyname
  142.       val {tnEqu, tnStr, ...} = !info
  143.   in
  144.     case tnStr of
  145.         NILts =>
  146.           (reportEquOfType tnEqu;
  147.            msgString "type ";
  148.            reportLhsOfTypeResult tyname)
  149.       | TYPEts(vs, tau) =>
  150.           let val lhs = type_con (map TypeOfTypeVar vs) tyname in
  151.             msgString "type ";
  152.             resetTypePrinter();
  153.             collectExplicitVars lhs;
  154.             collectExplicitVars tau;
  155.             printNextType lhs; msgString " ="; msgBreak(1, 2);
  156.             printNextType tau;
  157.             resetTypePrinter()
  158.           end
  159.       | DATATYPEts dt =>
  160.           let val uname = #qual qualid
  161.               val sign = if uname = currentUnitName()
  162.                         then (!currentSig)
  163.                         else findSig Location.nilLocation uname
  164.               val CE = findConstructors sign dt
  165.           in
  166.             if null CE then
  167.               (msgString "abstype ";
  168.                reportLhsOfTypeResult tyname)
  169.             else
  170.               (msgString "datatype ";
  171.                reportLhsOfTypeResult tyname)
  172.           end
  173.       | REAts _ =>
  174.              fatalError "reportTypeResult"
  175.   end
  176. ;
  177.  
  178. fun lookup_new_cBas cBas id =
  179.   (lookupEnv cBas id : ConStatus)
  180.   handle Subscript => fatalError "lookup_new_cBas"
  181. ;
  182.  
  183. fun report_comp_results iBas cBas static_VE static_TE =
  184. (
  185.   app (fn x =>
  186.          (msgIBlock 0; reportFixityResult x; msgEOL(); msgEBlock()))
  187.       (cleanEnv iBas);
  188.   app (fn (id, tn) =>
  189.          (msgIBlock 0; reportTypeResult tn; msgEOL(); msgEBlock()))
  190.       (cleanEnv static_TE);
  191.   app
  192.     (fn (id, sch) =>
  193.        let val status = lookup_new_cBas cBas id in
  194.          msgIBlock 0;
  195.          msgCBlock 0;
  196.          msgString
  197.            (case #info status of
  198.                VARname  _ => "val "
  199.              | PRIMname _ => "val "
  200.              | CONname  _ => "con "
  201.              | EXNname  _ => "exn "
  202.              | REFname    => "con ");
  203.          msgString id;
  204.          msgString " :"; msgBreak(1, 2); printScheme sch;
  205.          msgEBlock();
  206.          msgEOL();
  207.          msgEBlock()
  208.        end)
  209.     (cleanEnv static_VE);
  210.     msgFlush()
  211. );
  212.  
  213. (* To write the signature of the unit currently compiled *)
  214. (* The same value has to be written twice, because it's unclear *)
  215. (* how to `open` a file in "read/write" mode in a Caml Light program. *)
  216.  
  217. fun writeCompiledSignature filename_ui =
  218.   let val sigStamp = ref dummySigStamp
  219.       val sigLen = ref 0
  220.   in
  221.     let val os = open_out_bin filename_ui in
  222.       (output_value os (!currentSig);
  223.        sigLen := pos_out os;
  224.        close_out os)
  225.       handle x =>
  226.         (close_out os;
  227.          remove_file filename_ui;
  228.          raise x)
  229.     end;
  230.     let val is = open_in_bin filename_ui in
  231.       let val sigImage = input(is, !sigLen) 
  232.       prim_val md5sum_ : string -> string = 1 "md5sum"
  233.       in
  234.         if size sigImage < !sigLen then raise Size else ();
  235.         close_in is;
  236.         remove_file filename_ui;
  237.         sigStamp := md5sum_ sigImage
  238.       end
  239.       handle x =>
  240.         (close_in is;
  241.          remove_file filename_ui;
  242.          raise x)
  243.     end;
  244.     let val os = open_out_bin filename_ui in
  245.       (output(os, !sigStamp);
  246.        output_value os (!currentSig);
  247.        close_out os)
  248.       handle x =>
  249.         (close_out os;
  250.          remove_file filename_ui;
  251.          raise x)
  252.     end;
  253.     !sigStamp
  254.   end;
  255.  
  256. (* Checks and error messages for compiling units *)
  257.  
  258. fun checkUnitId msg (locid as (loc, id)) uname =
  259.     if id <> uname then
  260.     (msgIBlock 0;
  261.      errLocation loc;
  262.      errPrompt "Error: "; msgString msg; 
  263.      msgString " name and file name are incompatible";
  264.      msgEOL();
  265.      msgEBlock();
  266.      raise Toplevel)
  267.     else ();
  268.  
  269. fun checkExists filename_ui filename_sig filename_sml =
  270.     if not(file_exists filename_ui) then
  271.     (msgIBlock 0;
  272.      errPrompt "File "; msgString filename_sig;
  273.      msgString " must be compiled before ";
  274.      msgString filename_sml; msgEOL();
  275.      msgEBlock();
  276.      raise Toplevel)
  277.     else ();
  278.  
  279. fun checkNotExists filename_sig filename_sml =
  280.     if file_exists filename_sig then
  281.     (msgIBlock 0;
  282.      errPrompt "File "; msgString filename_sig;
  283.      msgString " exists, but there is no signature constraint in ";
  284.      msgString filename_sml; msgEOL();
  285.      msgEBlock();
  286.      raise Toplevel)
  287.     else ();
  288.  
  289. (* Compiling a signature *)
  290.  
  291. fun compileSpecPhrase spec =
  292.   let val (iBas, cBas) = resolveToplevelSpec spec
  293.       val (VE, TE) = elabToplevelSpec spec
  294.   in
  295.     updateCurrentInfixBasis iBas;
  296.     extendCurrentConBasis cBas;
  297.     extendCurrentStaticTE TE;
  298.     updateCurrentStaticVE VE;
  299.     if !verbose then
  300.       (report_comp_results iBas cBas VE TE;
  301.        msgFlush())
  302.     else ()
  303.   end
  304. ;
  305.  
  306. fun compileSignature uname filename =
  307.   let
  308.       val source_name = filename ^ ".sig"
  309.       val target_name = filename ^ ".ui"
  310.       (* val () = (msgIBlock 0;
  311.                    msgString "[compiling file \""; msgString source_name;
  312.                    msgString "\"]"; msgEOL(); msgEBlock();) *)
  313.       val () = startCompilingUnit uname
  314.       val () = initInitialEnvironments()
  315.       val is = open_in_bin source_name
  316.       val () = remove_file target_name;
  317.       val lexbuf = createLexerStream is
  318.       fun compileSig (AnonSig specs) = 
  319.       app compileSpecPhrase specs
  320.     | compileSig (NamedSig{locsigid, specs}) = 
  321.       (checkUnitId "signature" locsigid uname;
  322.        app compileSpecPhrase specs)
  323.   in
  324.        input_name   := source_name;
  325.        input_stream := is;
  326.        input_lexbuf := lexbuf;
  327.        (compileSig (parseSigFile lexbuf);
  328.         ignore (rectifySignature ());
  329.         ignore (writeCompiledSignature target_name);
  330.         close_in is)
  331.        handle x => (close_in is; raise x)
  332.   end
  333. ;
  334.  
  335. (* Compiling an implementation *)
  336.  
  337. (* This is written in tail-recursive form to ensure *)
  338. (* that the intermediate results will be discarded. *)
  339.  
  340. fun updateCurrentCompState ((iBas, cBas, VE, TE), RE) =
  341. (
  342.   updateCurrentInfixBasis iBas;
  343.   updateCurrentConBasis cBas;
  344.   updateCurrentStaticTE TE;
  345.   updateCurrentStaticVE VE;
  346.   updateCurrentRenEnv RE;
  347.   if !verbose then
  348.     (report_comp_results iBas cBas VE TE;
  349.      msgFlush())
  350.   else ()
  351. );
  352.  
  353. fun compLamPhrase os state (RE, lams) =
  354. (
  355.   app
  356.     (fn (is_pure, lam) =>
  357.        ((* msgIBlock 0; printLam lam; msgEOL(); msgEBlock(); *)
  358.        emit_phrase os
  359.          let val zam = compileLambda is_pure lam in
  360.            (* printZamPhrase zam; msgFlush(); *)
  361.            zam
  362.          end))
  363.     lams;
  364.     updateCurrentCompState (state, RE)
  365. );
  366.  
  367. fun compResolvedDecPhrase os (iBas, cBas, dec) =
  368.   let val (VE, TE) = elabToplevelDec dec in
  369.     resolveOvlDec dec;
  370.     compLamPhrase os (iBas, cBas, VE, TE) (translateToplevelDec dec)
  371.   end
  372. ;
  373.  
  374. fun compileImplPhrase os dec =
  375.   compResolvedDecPhrase os (resolveToplevelDec dec)
  376. ;
  377.  
  378. fun compileAndEmit uname filename specSig_opt decs =
  379.   let
  380.     val filename_ui  = filename ^ ".ui"
  381.     val filename_uo  = filename ^ ".uo"
  382.     (* val () = (msgIBlock 0;
  383.                  msgString "[compiling file \""; msgString filename_sml;
  384.                  msgString "\"]"; msgEOL(); msgEBlock()) *)
  385.     val () = startCompilingUnit uname
  386.     val () = initInitialEnvironments()
  387.     val os = open_out_bin filename_uo
  388.   in
  389.     ( start_emit_phrase os;
  390.       app (compileImplPhrase os) decs;
  391.       let val (excRenList, valRenList) = rectifySignature() in
  392.           (case specSig_opt of
  393.                NONE =>
  394.                  let val sigStamp = writeCompiledSignature filename_ui in
  395.                    end_emit_phrase
  396.                      excRenList valRenList
  397.                      sigStamp (#uMentions (!currentSig))
  398.                      os
  399.                  end
  400.              | SOME specSig =>
  401.                  let val {uConBasis, uStamp, ...} = specSig in
  402.                    matchSignature os (!currentSig) specSig;
  403.                    end_emit_phrase
  404.                      (filterExcRenList excRenList uConBasis)
  405.                      (filterValRenList valRenList uConBasis)
  406.                      (getOption (!uStamp)) (#uMentions (!currentSig))
  407.                      os
  408.                  end);
  409.           close_out os
  410.         end
  411.     )
  412.     handle x => (close_out os; remove_file filename_uo; raise x)
  413.   end;
  414.  
  415. fun compileUnitBody uname filename =
  416.   let val filename_sig = filename ^ ".sig"
  417.       val filename_ui  = filename ^ ".ui"
  418.       val filename_sml = filename ^ ".sml"
  419.       val is = open_in_bin filename_sml
  420.       val lexbuf = createLexerStream is
  421.       fun compileStruct (AnonStruct decs) = 
  422.       if file_exists filename_sig then
  423.           (hasSpecifiedSignature := true;
  424.            checkExists filename_ui filename_sig filename_sml;
  425.            compileAndEmit uname filename (SOME (readSig uname)) decs)
  426.       else 
  427.           (hasSpecifiedSignature := false;
  428.            remove_file filename_ui;
  429.            compileAndEmit uname filename NONE decs)
  430.     | compileStruct (NamedStruct{locstrid, locsigid = NONE, decs}) =
  431.       (checkUnitId "structure" locstrid uname;
  432.        checkNotExists filename_sig filename_sml;
  433.        hasSpecifiedSignature := false;
  434.        remove_file filename_ui;
  435.        compileAndEmit uname filename NONE decs)
  436.     | compileStruct (NamedStruct _) = fatalError "compileUnitBody"
  437.     | compileStruct (Abstraction{locstrid, locsigid, decs}) =
  438.       (checkUnitId "structure" locstrid uname;
  439.        checkUnitId "signature" locsigid uname;
  440.        checkExists filename_ui filename_sig filename_sml;
  441.        hasSpecifiedSignature := true;
  442.        compileAndEmit uname filename (SOME (readSig uname)) decs)
  443.   in
  444.       input_name := filename_sml;
  445.       input_stream := is;
  446.       input_lexbuf := lexbuf;
  447.       (compileStruct (parseStructFile lexbuf))
  448.       handle x => (close_in is; raise x)      
  449.   end;
  450.