src/Pure/ML/ml_compiler_polyml-5.3.ML
author wenzelm
Thu, 04 Jun 2009 22:02:33 +0200
changeset 31441 70309dc3deac
parent 31438 1f9b6a5dc8cc
child 31475 85e864045497
permissions -rw-r--r--
removed unused location_of;
eval: actually pass location properties (via "file" field);
     1 (*  Title:      Pure/ML/ml_compiler_polyml-5.3.ML
     2     Author:     Makarius
     3 
     4 Advanced runtime compilation for Poly/ML 5.3 (SVN 762).
     5 *)
     6 
     7 signature ML_COMPILER =
     8 sig
     9   val exception_position: exn -> Position.T
    10   val eval: bool -> Position.T -> ML_Lex.token list -> unit
    11 end
    12 
    13 structure ML_Compiler: ML_COMPILER =
    14 struct
    15 
    16 (* source locations *)
    17 
    18 fun position_of (loc: PolyML.location) =
    19   let
    20     val {file = text, startLine = line, startPosition = offset,
    21       endLine = end_line, endPosition = end_offset} = loc;
    22     val loc_props =
    23       (case YXML.parse text of
    24         XML.Elem (e, atts, _) => if e = Markup.positionN then atts else []
    25       | XML.Text s => Position.file_name s);
    26   in
    27     Position.value Markup.lineN line @
    28     Position.value Markup.offsetN offset @
    29     Position.value Markup.end_lineN end_line @
    30     Position.value Markup.end_offsetN end_offset @
    31     loc_props
    32   end |> Position.of_properties;
    33 
    34 fun exception_position exn =
    35   (case PolyML.exceptionLocation exn of
    36     NONE => Position.none
    37   | SOME loc => position_of loc);
    38 
    39 
    40 (* parse trees *)
    41 
    42 fun report_parse_tree depth space =
    43   let
    44     fun report loc (PolyML.PTtype types) =
    45           PolyML.NameSpace.displayTypeExpression (types, depth, space)
    46           |> pretty_ml |> Pretty.from_ML |> Pretty.string_of
    47           |> Position.report_text Markup.ML_typing (position_of loc)
    48       | report loc (PolyML.PTdeclaredAt decl) =
    49           Markup.markup
    50             (Markup.properties (Position.properties_of (position_of decl)) Markup.ML_def) ""
    51           |> Position.report_text Markup.ML_ref (position_of loc)
    52       | report _ (PolyML.PTnextSibling tree) = report_tree (tree ())
    53       | report _ (PolyML.PTfirstChild tree) = report_tree (tree ())
    54       | report _ _ = ()
    55     and report_tree (loc, props) = List.app (report loc) props;
    56   in report_tree end;
    57 
    58 
    59 (* eval ML source tokens *)
    60 
    61 fun eval verbose pos toks =
    62   let
    63     val _ = Secure.secure_mltext ();
    64     val {name_space = space, print, error = err, ...} = ML_Env.local_context;
    65 
    66 
    67     (* input *)
    68 
    69     val location_props =
    70       Markup.markup (Markup.position |> Markup.properties
    71           (filter (member (op =) [Markup.idN, Markup.fileN] o #1) (Position.properties_of pos))) "";
    72 
    73     val input = toks |> maps (fn tok =>
    74       let
    75         val syms = Symbol.explode (ML_Lex.check_content_of tok);
    76         val (ps, _) = fold_map (fn s => fn p => (p, Position.advance s p)) syms
    77           (Position.reset_range (ML_Lex.pos_of tok));
    78       in ps ~~ map (String.explode o Symbol.esc) syms end);
    79 
    80     val input_buffer = ref input;
    81     val line = ref (the_default 1 (Position.line_of pos));
    82 
    83     fun get_offset () =
    84       the_default 0
    85         (get_first (fn (_, []) => NONE | (p, _) => Position.offset_of p) (! input_buffer));
    86 
    87     fun get () =
    88       (case ! input_buffer of
    89         [] => NONE
    90       | (_, []) :: rest => (input_buffer := rest; get ())
    91       | (p, c :: cs) :: rest =>
    92           (input_buffer := (p, cs) :: rest;
    93            if c = #"\n" then line := ! line + 1 else ();
    94            SOME c));
    95 
    96 
    97     (* output *)
    98 
    99     val output_buffer = ref Buffer.empty;
   100     fun output () = Buffer.content (! output_buffer);
   101     fun put s = change output_buffer (Buffer.add s);
   102 
   103     fun put_message {message, hard, location, context = _} =
   104      (put (if hard then "Error: " else "Warning: ");
   105       put (Pretty.string_of (Pretty.from_ML (pretty_ml message)));
   106       put (Position.str_of (position_of location) ^ "\n"));
   107 
   108 
   109     (* results *)
   110 
   111     val depth = get_print_depth ();
   112 
   113     fun apply_result {fixes, types, signatures, structures, functors, values} =
   114       let
   115         fun display disp x =
   116           if depth > 0 then
   117             (disp x |> pretty_ml |> Pretty.from_ML |> Pretty.string_of |> put; put "\n")
   118           else ();
   119 
   120         fun apply_fix (a, b) =
   121           (display PolyML.NameSpace.displayFix (a, b); #enterFix space (a, b));
   122         fun apply_type (a, b) =
   123           (display PolyML.NameSpace.displayType (b, depth, space); #enterType space (a, b));
   124         fun apply_sig (a, b) =
   125           (display PolyML.NameSpace.displaySig (b, depth, space); #enterSig space (a, b));
   126         fun apply_struct (a, b) =
   127           (display PolyML.NameSpace.displayStruct (b, depth, space); #enterStruct space (a, b));
   128         fun apply_funct (a, b) =
   129           (display PolyML.NameSpace.displayFunct (b, depth, space); #enterFunct space (a, b));
   130         fun apply_val (a, b) =
   131           (display PolyML.NameSpace.displayVal (b, depth, space); #enterVal space (a, b));
   132       in
   133         List.app apply_fix fixes;
   134         List.app apply_type types;
   135         List.app apply_sig signatures;
   136         List.app apply_struct structures;
   137         List.app apply_funct functors;
   138         List.app apply_val values
   139       end;
   140 
   141     fun result_fun (phase1, phase2) () =
   142      (case phase1 of NONE => ()
   143       | SOME parse_tree => report_parse_tree depth space parse_tree;
   144       case phase2 of NONE => err "Static Errors"
   145       | SOME code => apply_result (code ()));  (* FIXME cf. Toplevel.program *)
   146 
   147 
   148     (* compiler invocation *)
   149 
   150     val parameters =
   151      [PolyML.Compiler.CPOutStream put,
   152       PolyML.Compiler.CPNameSpace space,
   153       PolyML.Compiler.CPErrorMessageProc put_message,
   154       PolyML.Compiler.CPLineNo (fn () => ! line),
   155       PolyML.Compiler.CPFileName location_props,
   156       PolyML.Compiler.CPLineOffset get_offset,
   157       PolyML.Compiler.CPCompilerResultFun result_fun];
   158     val _ =
   159       (while not (List.null (! input_buffer)) do
   160         PolyML.compiler (get, parameters) ())
   161       handle exn =>
   162        (put ("Exception- " ^ General.exnMessage exn ^ " raised");
   163         err (output ()); raise exn);
   164   in if verbose then print (output ()) else () end;
   165 
   166 end;
   167