|
Packit |
bd2e5d |
(*************************************************************************)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* OCaml LablTk library *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Jacques Garrigue, Kyoto University RIMS *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Copyright 1999 Institut National de Recherche en Informatique et *)
|
|
Packit |
bd2e5d |
(* en Automatique and Kyoto University. All rights reserved. *)
|
|
Packit |
bd2e5d |
(* This file is distributed under the terms of the GNU Library *)
|
|
Packit |
bd2e5d |
(* General Public License, with the special exception on linking *)
|
|
Packit |
bd2e5d |
(* described in file ../../../LICENSE. *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(*************************************************************************)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* $Id$ *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
open StdLabels
|
|
Packit |
bd2e5d |
open Tk
|
|
Packit |
bd2e5d |
open Parsetree
|
|
Packit |
bd2e5d |
open Typedtree
|
|
Packit |
bd2e5d |
open Location
|
|
Packit |
bd2e5d |
open Jg_tk
|
|
Packit |
bd2e5d |
open Mytypes
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
(* Optionally preprocess a source file *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let preprocess ~pp ~ext text =
|
|
Packit |
bd2e5d |
let sourcefile = Filename.temp_file "caml" ext in
|
|
Packit |
bd2e5d |
begin try
|
|
Packit |
bd2e5d |
let oc = open_out_bin sourcefile in
|
|
Packit |
bd2e5d |
output_string oc text;
|
|
Packit |
bd2e5d |
flush oc;
|
|
Packit |
bd2e5d |
close_out oc
|
|
Packit |
bd2e5d |
with _ ->
|
|
Packit |
bd2e5d |
failwith "Preprocessing error"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
let tmpfile = Filename.temp_file "camlpp" ext in
|
|
Packit |
bd2e5d |
let comm = Printf.sprintf "%s %s > %s" pp sourcefile tmpfile in
|
|
Packit |
bd2e5d |
if Ccomp.command comm <> 0 then begin
|
|
Packit |
bd2e5d |
Sys.remove sourcefile;
|
|
Packit |
bd2e5d |
Sys.remove tmpfile;
|
|
Packit |
bd2e5d |
failwith "Preprocessing error"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
Sys.remove sourcefile;
|
|
Packit |
bd2e5d |
tmpfile
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
exception Outdated_version
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let parse_pp ~parse ~wrap ~ext text =
|
|
Packit |
bd2e5d |
Location.input_name := "";
|
|
Packit |
bd2e5d |
match !Clflags.preprocessor with
|
|
Packit |
bd2e5d |
None ->
|
|
Packit |
bd2e5d |
let buffer = Lexing.from_string text in
|
|
Packit |
bd2e5d |
Location.init buffer "";
|
|
Packit |
bd2e5d |
parse buffer
|
|
Packit |
bd2e5d |
| Some pp ->
|
|
Packit |
bd2e5d |
let tmpfile = preprocess ~pp ~ext text in
|
|
Packit |
bd2e5d |
let ast_magic =
|
|
Packit |
bd2e5d |
if ext = ".ml" then Config.ast_impl_magic_number
|
|
Packit |
bd2e5d |
else Config.ast_intf_magic_number in
|
|
Packit |
bd2e5d |
let ic = open_in_bin tmpfile in
|
|
Packit |
bd2e5d |
let ast =
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let buffer = really_input_string ic (String.length ast_magic) in
|
|
Packit |
bd2e5d |
if buffer = ast_magic then begin
|
|
Packit |
bd2e5d |
ignore (input_value ic);
|
|
Packit |
bd2e5d |
wrap (input_value ic)
|
|
Packit |
bd2e5d |
end else if String.sub buffer 0 9 = String.sub ast_magic 0 9 then
|
|
Packit |
bd2e5d |
raise Outdated_version
|
|
Packit |
bd2e5d |
else
|
|
Packit |
bd2e5d |
raise Exit
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
Outdated_version ->
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
Sys.remove tmpfile;
|
|
Packit |
bd2e5d |
failwith "OCaml and preprocessor have incompatible versions"
|
|
Packit |
bd2e5d |
| _ ->
|
|
Packit |
bd2e5d |
seek_in ic 0;
|
|
Packit |
bd2e5d |
let buffer = Lexing.from_channel ic in
|
|
Packit |
bd2e5d |
Location.init buffer "";
|
|
Packit |
bd2e5d |
parse buffer
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
close_in ic;
|
|
Packit |
bd2e5d |
Sys.remove tmpfile;
|
|
Packit |
bd2e5d |
ast
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let nowarnings = ref false
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let f txt =
|
|
Packit |
bd2e5d |
let error_messages = ref [] in
|
|
Packit |
bd2e5d |
let text = Jg_text.get_all txt.tw
|
|
Packit |
bd2e5d |
and env = ref (Compmisc.initial_env ()) in
|
|
Packit |
bd2e5d |
let tl, ew, end_message =
|
|
Packit |
bd2e5d |
Jg_message.formatted ~title:"Warnings" ~ppf:Format.err_formatter () in
|
|
Packit |
bd2e5d |
Text.tag_remove txt.tw ~tag:"error" ~start:tstart ~stop:tend;
|
|
Packit |
bd2e5d |
txt.structure <- [];
|
|
Packit |
bd2e5d |
txt.type_info <- [];
|
|
Packit |
bd2e5d |
txt.signature <- [];
|
|
Packit |
bd2e5d |
txt.psignature <- [];
|
|
Packit |
bd2e5d |
ignore (Stypes.get_info ());
|
|
Packit |
bd2e5d |
Clflags.annotations := true;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
begin try
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
if Filename.check_suffix txt.name ".mli" then
|
|
Packit |
bd2e5d |
let psign = parse_pp text ~ext:".mli"
|
|
Packit |
bd2e5d |
~parse:Parse.interface ~wrap:(fun x -> x) in
|
|
Packit |
bd2e5d |
txt.psignature <- psign;
|
|
Packit |
bd2e5d |
txt.signature <- (Typemod.transl_signature !env psign).sig_type;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
else (* others are interpreted as .ml *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let psl = parse_pp text ~ext:".ml"
|
|
Packit |
bd2e5d |
~parse:Parse.use_file ~wrap:(fun x -> [Parsetree.Ptop_def x]) in
|
|
Packit |
bd2e5d |
List.iter psl ~f:
|
|
Packit |
bd2e5d |
begin function
|
|
Packit |
bd2e5d |
Ptop_def pstr ->
|
|
Packit |
bd2e5d |
let str, sign, env' = Typemod.type_structure !env pstr Location.none in
|
|
Packit |
bd2e5d |
txt.structure <- txt.structure @ str.str_items;
|
|
Packit |
bd2e5d |
txt.signature <- txt.signature @ sign;
|
|
Packit |
bd2e5d |
env := env'
|
|
Packit |
bd2e5d |
| Ptop_dir _ -> ()
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
txt.type_info <- Stypes.get_info ();
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
with
|
|
Packit |
bd2e5d |
Lexer.Error _ | Syntaxerr.Error _
|
|
Packit |
bd2e5d |
| Typecore.Error _ | Typemod.Error _
|
|
Packit |
bd2e5d |
| Typeclass.Error _ | Typedecl.Error _
|
|
Packit |
bd2e5d |
| Typetexp.Error _ | Includemod.Error _
|
|
Packit |
bd2e5d |
| Env.Error _ | Ctype.Tags _ | Failure _ as exn ->
|
|
Packit |
bd2e5d |
txt.type_info <- Stypes.get_info ();
|
|
Packit |
bd2e5d |
let et, ew, end_message = Jg_message.formatted ~title:"Error !" () in
|
|
Packit |
bd2e5d |
error_messages := et :: !error_messages;
|
|
Packit |
bd2e5d |
let range = match exn with
|
|
Packit |
bd2e5d |
Lexer.Error (err, l) ->
|
|
Packit |
bd2e5d |
Lexer.report_error Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Syntaxerr.Error err ->
|
|
Packit |
bd2e5d |
Syntaxerr.report_error Format.std_formatter err;
|
|
Packit |
bd2e5d |
Syntaxerr.location_of_error err
|
|
Packit |
bd2e5d |
| Typecore.Error (l, env, err) ->
|
|
Packit |
bd2e5d |
Typecore.report_error env Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Typeclass.Error (l, env, err) ->
|
|
Packit |
bd2e5d |
Typeclass.report_error env Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Typedecl.Error (l, err) ->
|
|
Packit |
bd2e5d |
Typedecl.report_error Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Typemod.Error (l, env, err) ->
|
|
Packit |
bd2e5d |
Typemod.report_error env Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Typetexp.Error (l, env, err) ->
|
|
Packit |
bd2e5d |
Typetexp.report_error env Format.std_formatter err; l
|
|
Packit |
bd2e5d |
| Includemod.Error errl ->
|
|
Packit |
bd2e5d |
Includemod.report_error Format.std_formatter errl; Location.none
|
|
Packit |
bd2e5d |
| Env.Error err ->
|
|
Packit |
bd2e5d |
Env.report_error Format.std_formatter err; Location.none
|
|
Packit |
bd2e5d |
| Cmi_format.Error err ->
|
|
Packit |
bd2e5d |
Cmi_format.report_error Format.std_formatter err; Location.none
|
|
Packit |
bd2e5d |
| Ctype.Tags(l, l') ->
|
|
Packit |
bd2e5d |
Format.printf "In this program,@ variant constructors@ `%s and `%s@ have same hash value.@." l l';
|
|
Packit |
bd2e5d |
Location.none
|
|
Packit |
bd2e5d |
| Failure s ->
|
|
Packit |
bd2e5d |
Format.printf "%s.@." s; Location.none
|
|
Packit |
bd2e5d |
| _ -> assert false
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
end_message ();
|
|
Packit |
bd2e5d |
let s = range.loc_start.Lexing.pos_cnum in
|
|
Packit |
bd2e5d |
let e = range.loc_end.Lexing.pos_cnum in
|
|
Packit |
bd2e5d |
if s < e then
|
|
Packit |
bd2e5d |
Jg_text.tag_and_see txt.tw ~start:(tpos s) ~stop:(tpos e) ~tag:"error"
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
end_message ();
|
|
Packit |
bd2e5d |
if !nowarnings || Text.index ew ~index:tend = `Linechar (2,0)
|
|
Packit |
bd2e5d |
then destroy tl
|
|
Packit |
bd2e5d |
else begin
|
|
Packit |
bd2e5d |
error_messages := tl :: !error_messages;
|
|
Packit |
bd2e5d |
Text.configure ew ~state:`Disabled;
|
|
Packit |
bd2e5d |
bind ew ~events:[`Modified([`Double], `ButtonReleaseDetail 1)]
|
|
Packit |
bd2e5d |
~action:(fun _ ->
|
|
Packit |
bd2e5d |
try
|
|
Packit |
bd2e5d |
let start, ende = Text.tag_nextrange ew ~tag:"sel" ~start:(tpos 0) in
|
|
Packit |
bd2e5d |
let s = Text.get ew ~start:(start,[]) ~stop:(ende,[]) in
|
|
Packit |
bd2e5d |
let n = int_of_string s in
|
|
Packit |
bd2e5d |
Text.mark_set txt.tw ~index:(tpos n) ~mark:"insert";
|
|
Packit |
bd2e5d |
Text.see txt.tw ~index:(`Mark "insert", [])
|
|
Packit |
bd2e5d |
with _ -> ())
|
|
Packit |
bd2e5d |
end;
|
|
Packit |
bd2e5d |
!error_messages
|