]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/matita/matitaScript.ml
More notation (up to where the open bugs allow me to put it without adding
[helm.git] / helm / matita / matitaScript.ml
index c2b9a7e93615d6120784a0f1dfdf34bf30fdfe0b..af7b02a82f70a9e6765562b44413ca125418a13d 100644 (file)
@@ -57,7 +57,7 @@ let prepend_text header base =
   if Pcre.pmatch ~rex:heading_nl_RE base then
     sprintf "\n%s%s" header base
   else
-    sprintf "%s\n%s" header base
+    sprintf "\n%s\n%s" header base
 
   (** creates a statement AST for the Goal tactic, e.g. "goal 7" *)
 let goal_ast n =
@@ -149,8 +149,7 @@ let eval_with_engine guistuff status user_goal parsed_text st =
   with
     MatitaEngine.UnableToInclude what as exc ->
       let compile_needed_and_go_on d =
-        let root = MatitamakeLib.root_for_development d in
-        let target = root ^ "/" ^ what in
+        let target = what in
         let refresh_cb () = 
           while Glib.Main.pending () do ignore(Glib.Main.iteration false); done
         in
@@ -334,10 +333,10 @@ let eval_executable guistuff status user_goal parsed_text script ex =
   match ex with
   | TA.Command (loc, _) | TA.Tactical (loc, _) ->
       (try 
-        (match ML.baseuri_of_baseuri_decl (TA.Executable (loc,ex)) with
+        (match MatitaMisc.baseuri_of_baseuri_decl (TA.Executable (loc,ex)) with
         | None -> ()
         | Some u -> 
-            if not (MatitacleanLib.is_empty u) then
+            if not (MatitaMisc.is_empty u) then
               match 
                 guistuff.ask_confirmation 
                   ~title:"Baseuri redefinition" 
@@ -355,9 +354,40 @@ let eval_executable guistuff status user_goal parsed_text script ex =
   | TA.Macro (_,mac) ->
       eval_macro guistuff status parsed_text script mac
 
-let rec eval_statement guistuff status user_goal script s =
+let rec eval_statement baseoffset parsedlen error_tag (buffer : GText.buffer)
+ guistuff status user_goal script s
+=
   if Pcre.pmatch ~rex:only_dust_RE s then raise Margin;
-  let st = GrafiteParser.parse_statement (Stream.of_string s) in
+  let st =
+   try
+    GrafiteParser.parse_statement (Stream.of_string s)
+   with
+    CicNotationParser.Parse_error (floc,err) as exc ->
+     let (x, y) = CicNotationPt.loc_of_floc floc in
+     let x = parsedlen + x in
+     let y = parsedlen + y in
+     let x' = baseoffset + x in
+     let y' = baseoffset + y in
+     let x_iter = buffer#get_iter (`OFFSET x') in
+     let y_iter = buffer#get_iter (`OFFSET y') in
+      buffer#apply_tag error_tag ~start:x_iter ~stop:y_iter;
+     let id = ref None in
+      id :=
+       Some
+        (buffer#connect#changed
+          ~callback:(
+            fun () ->
+             buffer#remove_tag error_tag ~start:buffer#start_iter
+              ~stop:buffer#end_iter;
+             match !id with
+                None -> assert false (* a race condition occurred *)
+              | Some id ->
+                 (new GObj.gobject_ops buffer#as_buffer)#disconnect id));
+      let flocb,floce = floc in
+      let floc =
+       {flocb with Lexing.pos_cnum = x}, {floce with Lexing.pos_cnum = y } in
+      raise (CicNotationParser.Parse_error (floc,err))
+  in
   let text_of_loc loc =
     let parsed_text_length = snd (CicNotationPt.loc_of_floc loc) in
     let parsed_text = safe_substring s 0 parsed_text_length in
@@ -369,7 +399,8 @@ let rec eval_statement guistuff status user_goal script s =
       let remain_len = String.length s - parsed_text_length in
       let s = String.sub s parsed_text_length remain_len in
       let s,len = 
-        eval_statement guistuff status user_goal script s 
+        eval_statement baseoffset (parsedlen + parsed_text_length) error_tag
+         buffer guistuff status user_goal script s 
       in
       (match s with
       | (status, text) :: tl ->
@@ -417,9 +448,7 @@ object (self)
        (fun _ -> if buffer#modified then 
           set_star self#ppFilename true 
         else 
-          set_star self#ppFilename false));
-    self#reset ();
-    self#template ()
+          set_star self#ppFilename false))
 
   val mutable statements = [];    (** executed statements *)
   val mutable history = [ init ];
@@ -435,6 +464,10 @@ object (self)
   val locked_mark =
     buffer#create_mark ~name:"locked" ~left_gravity:true buffer#start_iter
   val locked_tag = buffer#create_tag [`BACKGROUND "lightblue"; `EDITABLE false]
+  val error_tag = buffer#create_tag [`UNDERLINE `SINGLE; `FOREGROUND "red"]
+
+  method locked_mark = locked_mark
+  method locked_tag = locked_tag
 
     (* history can't be empty, the invariant above grant that it contains at
      * least the init status *)
@@ -444,25 +477,22 @@ object (self)
     let s = match statement with Some s -> s | None -> self#getFuture in
     MatitaLog.debug ("evaluating: " ^ first_line s ^ " ...");
     let (entries, parsed_len) = 
-      eval_statement guistuff self#status userGoal self s
+     eval_statement (buffer#get_iter_at_mark (`MARK locked_mark))#offset 0
+      error_tag buffer guistuff self#status userGoal self s
     in
     let (new_statuses, new_statements) = List.split entries in
-(*
-prerr_endline "evalStatement returned";
-List.iter (fun s -> prerr_endline ("'" ^ s ^ "'")) new_statements;
-*)
     history <- List.rev new_statuses @ history;
     statements <- List.rev new_statements @ statements;
     let start = buffer#get_iter_at_mark (`MARK locked_mark) in
     let new_text = String.concat "" new_statements in
-    if new_text <> String.sub s 0 parsed_len then
+    if statement <> None then
+     buffer#insert ~iter:start new_text
+    else
+     if new_text <> String.sub s 0 parsed_len then
       begin
-(*       prerr_endline ("new:" ^ new_text); *)
-(*       prerr_endline ("s:" ^ String.sub s 0 parsed_len); *)
-      let stop = start#copy#forward_chars parsed_len in
-      buffer#delete ~start ~stop;
-      buffer#insert ~iter:start new_text;
-(*       prerr_endline "AUTOMATICALLY MODIFIED!!!!!" *)
+       let stop = start#copy#forward_chars parsed_len in
+        buffer#delete ~start ~stop;
+        buffer#insert ~iter:start new_text;
       end;
     self#moveMark (String.length new_text)
 
@@ -543,8 +573,8 @@ List.iter (fun s -> prerr_endline ("'" ^ s ^ "'")) new_statements;
     let status = self#status in
     List.iter (fun o -> o status) observers
 
-  method loadFromFile () =
-    buffer#set_text (MatitaMisc.input_file self#getFilename);
+  method loadFromFile f =
+    buffer#set_text (MatitaMisc.input_file f);
     self#goto_top;
     buffer#set_modified false
     
@@ -594,53 +624,79 @@ List.iter (fun s -> prerr_endline ("'" ^ s ^ "'")) new_statements;
     set_star self#ppFilename false
 
   method goto (pos: [`Top | `Bottom | `Cursor]) () =
+    let old_locked_mark =
+     `MARK
+       (buffer#create_mark ~name:"old_locked_mark"
+         ~left_gravity:true (buffer#get_iter_at_mark (`MARK locked_mark))) in
     let getpos _ = buffer#get_iter_at_mark (`MARK locked_mark) in 
+    let getoldpos _ = buffer#get_iter_at_mark old_locked_mark in 
+    let dispose_old_locked_mark () = buffer#delete_mark old_locked_mark in
     match pos with
-    | `Top -> self#goto_top; self#notify
+    | `Top -> dispose_old_locked_mark (); self#goto_top; self#notify
     | `Bottom ->
         (try 
-          let rec dowhile pos =
+          let rec dowhile () =
             self#_advance ();
-            if pos#compare (getpos ()) < 0 then
-              dowhile (getpos ())
+            let newpos = getpos () in
+            if (getoldpos ())#compare newpos < 0 then
+              begin
+                buffer#move_mark old_locked_mark newpos;
+                dowhile ()
+              end
           in
-          dowhile (getpos ());
+          dowhile ();
+          dispose_old_locked_mark ();
           self#notify 
         with 
-        | Margin -> self#notify
-        | exc -> self#notify; raise exc)
+        | Margin -> dispose_old_locked_mark (); self#notify
+        | exc -> dispose_old_locked_mark (); self#notify; raise exc)
     | `Cursor ->
         let locked_iter () = buffer#get_iter_at_mark (`NAME "locked") in
-        let cursor_iter = buffer#get_iter_at_mark `INSERT in
-        let cmp = (locked_iter ())#offset - cursor_iter#offset in
+        let cursor_iter () = buffer#get_iter_at_mark `INSERT in
+        let remember =
+         `MARK
+           (buffer#create_mark ~name:"initial_insert"
+             ~left_gravity:true (cursor_iter ())) in
+        let dispose_remember () = buffer#delete_mark remember in
+        let remember_iter () =
+         buffer#get_iter_at_mark (`NAME "initial_insert") in
+        let cmp () = (locked_iter ())#offset - (remember_iter ())#offset in
+        let icmp = cmp () in
         let forward_until_cursor () = (* go forward until locked > cursor *)
-          let rec aux oldpos =
+          let rec aux () =
             self#_advance ();
-            if (locked_iter ())#compare cursor_iter < 0 &&
-               oldpos#compare (getpos ()) < 0 
+            if cmp () < 0 && (getoldpos ())#compare (getpos ()) < 0 
             then
-              aux (getpos ())
+             begin
+              buffer#move_mark old_locked_mark (getpos ());
+              aux ()
+             end
           in
-          aux (getpos ())
+          aux ()
         in
         let rec back_until_cursor len = (* go backward until locked < cursor *)
          function
             statements, (status::_ as history) when len <= 0 ->
-             self#_retract (cmp - len) status statements history
+             self#_retract (icmp - len) status statements history
           | statement::tl1, _::tl2 ->
              back_until_cursor (len - String.length statement) (tl1,tl2)
           | _,_ -> assert false
         in
         (try
-          if cmp < 0 then       (* locked < cursor *)
-            (forward_until_cursor (); self#notify)
-          else if cmp > 0 then  (* locked > cursor *)
-            (back_until_cursor cmp (statements,history); self#notify)
-          else                  (* cursor = locked *)
-              ()
+          begin
+           if icmp < 0 then       (* locked < cursor *)
+             (forward_until_cursor (); self#notify)
+           else if icmp > 0 then  (* locked > cursor *)
+             (back_until_cursor icmp (statements,history); self#notify)
+           else                  (* cursor = locked *)
+               ()
+          end ;
+          dispose_remember ();
+          dispose_old_locked_mark ();
         with 
-        | Margin -> self#notify
-        | exc -> self#notify; raise exc)
+        | Margin -> dispose_remember (); dispose_old_locked_mark (); self#notify
+        | exc -> dispose_remember (); dispose_old_locked_mark ();
+                 self#notify; raise exc)
               
   method onGoingProof () =
     match self#status.proof_status with