@@ -408,7 +408,34 @@ let main () =
408408 (* LLM interactive mode *)
409409 (* -------------------------------------------------------------------- *)
410410
411- let run_llm_repl (prvopts : prv_options ) =
411+ let llm_guide_path () =
412+ let (module Sites ) = EcRelocate. sites in
413+ match EcRelocate. sourceroot with
414+ | Some root ->
415+ Filename. concat (Filename. concat root " doc/llm" ) " CLAUDE.md"
416+ | None ->
417+ Filename. concat Sites. doc " llm-guide.md"
418+ in
419+
420+ let print_llm_guide () =
421+ let path = llm_guide_path () in
422+ try
423+ let ic = open_in path in
424+ begin try while true do
425+ print_char (input_char ic)
426+ done with End_of_file -> () end ;
427+ close_in ic
428+ with Sys_error e ->
429+ Printf. eprintf " cannot read LLM guide: %s\n %!" e
430+ in
431+
432+ let run_llm_repl (llmopts : llm_option ) =
433+ if llmopts.llmo_help then begin
434+ print_llm_guide () ;
435+ exit 0
436+ end ;
437+
438+ let prvopts = llmopts.llmo_provers in
412439 (* Initialize PRNG *)
413440 Random. self_init () ;
414441
@@ -510,8 +537,15 @@ let main () =
510537 in
511538
512539 let reply_error msg =
513- Printf. printf " ERROR [uuid:%d]\n %s\n <END>\n %!"
514- (EcCommands. uuid () ) msg;
540+ let goals = goals_to_string () in
541+ Printf. printf " ERROR [uuid:%d]\n %s\n " (EcCommands. uuid () ) msg;
542+ if goals <> " " then begin
543+ print_string goals;
544+ let len = String. length goals in
545+ if len > 0 && goals.[len - 1 ] <> '\n' then
546+ print_char '\n'
547+ end ;
548+ Printf. printf " <END>\n %!" ;
515549 Buffer. clear notices
516550 in
517551
@@ -592,16 +626,27 @@ let main () =
592626 | f :: rest -> (f, String. concat " " rest)
593627 in
594628
595- (* Parse optional LINE[:COL] *)
596- let upto =
597- if rest = " " then None
629+ (* Parse optional LINE[:COL] and flags (-nosmt) *)
630+ let upto, nosmt =
631+ if rest = " " then ( None , false )
598632 else
599- match String. split_on_char ':' rest with
600- | [line] ->
601- Some (int_of_string line, None )
602- | [line; col] ->
603- Some (int_of_string line, Some (int_of_string col))
604- | _ -> failwith " LOAD: invalid LINE[:COL] format"
633+ let words = String. split_on_char ' ' rest in
634+ let words = List. filter (fun s -> s <> " " ) words in
635+ let nosmt = List. mem " -nosmt" words in
636+ let words = List. filter (fun s -> s <> " -nosmt" ) words in
637+ let upto = match words with
638+ | [] -> None
639+ | [w] ->
640+ begin match String. split_on_char ':' w with
641+ | [line] ->
642+ Some (int_of_string line, None )
643+ | [line; col] ->
644+ Some (int_of_string line, Some (int_of_string col))
645+ | _ -> failwith " LOAD: invalid LINE[:COL] format"
646+ end
647+ | _ -> failwith " LOAD: unexpected arguments"
648+ in
649+ (upto, nosmt)
605650 in
606651
607652 (* Validate file extension *)
@@ -632,6 +677,9 @@ let main () =
632677
633678 let last_loc = ref None in
634679
680+ (* In -nosmt mode, admit all SMT calls during prefix loading *)
681+ if nosmt then EcCommands. pragma_check `WeakCheck ;
682+
635683 begin try while true do
636684 let (src, prog) = EcIo. xparse reader in
637685 let src = String. strip src in
@@ -653,10 +701,17 @@ let main () =
653701 EcCommands. doc_comment doc
654702 done with
655703 | Exit | End_of_file -> ()
656- | e -> EcIo. finalize reader; raise e
704+ | e ->
705+ EcIo. finalize reader;
706+ if nosmt then EcCommands. pragma_check `Check ;
707+ raise e
657708 end ;
658709
659710 EcIo. finalize reader;
711+
712+ (* Restore full SMT checking for interactive tactics *)
713+ if nosmt then EcCommands. pragma_check `Check ;
714+
660715 let tag =
661716 match ! last_loc with
662717 | None -> " "
@@ -685,14 +740,49 @@ let main () =
685740 (EcCommands. uuid () );
686741
687742 (* Main REPL loop *)
743+ let multi_buf = Buffer. create 256 in
744+ let in_multi = ref false in
745+
688746 begin try while true do
689747 let line = input_line stdin in
690748 let line = String. strip line in
691749
692- if line = " " then
750+ (* Multi-line input: <BEGIN> starts, <DONE> flushes *)
751+ if line = " <BEGIN>" then begin
752+ Buffer. clear multi_buf;
753+ in_multi := true
754+ end
755+ else if line = " <DONE>" && ! in_multi then begin
756+ let input = Buffer. contents multi_buf in
757+ Buffer. clear multi_buf;
758+ in_multi := false ;
759+ if input <> " " then process_ec_input input
760+ end
761+ else if ! in_multi then begin
762+ if Buffer. length multi_buf > 0 then
763+ Buffer. add_char multi_buf ' ' ;
764+ Buffer. add_string multi_buf line
765+ end
766+
767+ else if line = " " then
693768 ()
694769 else if line = " QUIT" then
695770 exit 0
771+ else if line = " HELP" then begin
772+ Buffer. clear notices;
773+ let buf = Buffer. create 4096 in
774+ let path = llm_guide_path () in
775+ begin try
776+ let ic = open_in path in
777+ begin try while true do
778+ Buffer. add_char buf (input_char ic)
779+ done with End_of_file -> () end ;
780+ close_in ic;
781+ reply_ok (Buffer. contents buf)
782+ with Sys_error e ->
783+ reply_error (Printf. sprintf " cannot read guide: %s" e)
784+ end
785+ end
696786 else if line = " UNDO" then begin
697787 Buffer. clear notices;
698788 let uuid = EcCommands. uuid () in
@@ -910,7 +1000,8 @@ let main () =
9101000
9111001 | `Llm llmopts ->
9121002 run_llm_repl
913- {llmopts.llmo_provers with prvo_iterate = true }
1003+ {llmopts with llmo_provers =
1004+ {llmopts.llmo_provers with prvo_iterate = true }}
9141005
9151006 | `Runtest _ ->
9161007 (* Eagerly executed *)
0 commit comments