292 |
292 |
293 (* get informed about files *) |
293 (* get informed about files *) |
294 |
294 |
295 val inform_file_retracted = ThyInfo.if_known_thy ThyInfo.remove_thy o thy_name; |
295 val inform_file_retracted = ThyInfo.if_known_thy ThyInfo.remove_thy o thy_name; |
296 val inform_file_processed = ThyInfo.if_known_thy ThyInfo.touch_child_thys o thy_name; |
296 val inform_file_processed = ThyInfo.if_known_thy ThyInfo.touch_child_thys o thy_name; |
297 val openfile_retract = Output.no_warnings (ThyInfo.if_known_thy ThyInfo.remove_thy) o thy_name; |
|
298 |
297 |
299 fun proper_inform_file_processed file state = |
298 fun proper_inform_file_processed file state = |
300 let val name = thy_name file in |
299 let val name = thy_name file in |
301 if Toplevel.is_toplevel state andalso ThyInfo.known_thy name then |
300 if Toplevel.is_toplevel state andalso ThyInfo.known_thy name then |
302 (ThyInfo.touch_child_thys name; |
301 (ThyInfo.touch_child_thys name; |
412 else Output.panic ("PGIP configuration file \"" ^ config_file() ^ "\" not found") |
411 else Output.panic ("PGIP configuration file \"" ^ config_file() ^ "\" not found") |
413 end; |
412 end; |
414 end |
413 end |
415 |
414 |
416 |
415 |
417 (* PGIP identifier tables (prover objects). [incomplete] *) |
|
418 |
|
419 local |
|
420 (* TODO: objtypes should be in pgip_types.ML *) |
|
421 val objtype_thy = "theory" |
|
422 val objtype_thm = "theorem" |
|
423 val objtype_term = "term" |
|
424 val objtype_type = "type" |
|
425 |
|
426 fun xml_idtable ty ctx ids = |
|
427 PgipOutput.output (Idtable {objtype=ty,context=ctx,ids=ids}) |
|
428 in |
|
429 |
|
430 fun setids t = issue_pgip (Setids {idtables = [t]}) |
|
431 fun addids t = issue_pgip (Addids {idtables = [t]}) |
|
432 fun delids t = issue_pgip (Delids {idtables = [t]}) |
|
433 |
|
434 fun delallids ty = setids (xml_idtable ty NONE []) |
|
435 |
|
436 fun send_thy_idtable ctx thys = setids (xml_idtable objtype_thy ctx thys) |
|
437 fun clear_thy_idtable () = delallids objtype_thy |
|
438 |
|
439 fun send_thm_idtable ctx thy = |
|
440 addids (xml_idtable objtype_thm ctx (map fst (PureThy.thms_of thy))); |
|
441 |
|
442 fun clear_thm_idtable () = delallids objtype_thm |
|
443 |
|
444 (* fun send_type_idtable thy = TODO, it's a bit low-level messy |
|
445 & maybe not so useful anyway *) |
|
446 |
|
447 end |
|
448 |
416 |
449 |
417 |
450 (* Sending commands to Isar *) |
418 (* Sending commands to Isar *) |
451 |
419 |
452 fun isarcmd s = |
420 fun isarcmd s = |
556 fun redostep vs = isarcmd "redo" |
524 fun redostep vs = isarcmd "redo" |
557 |
525 |
558 fun abortgoal vs = isarcmd "ProofGeneral.kill_proof" |
526 fun abortgoal vs = isarcmd "ProofGeneral.kill_proof" |
559 |
527 |
560 |
528 |
|
529 (*** PGIP identifier tables ***) |
|
530 |
|
531 fun setids t = issue_pgip (Setids {idtables = [t]}) |
|
532 fun addids t = issue_pgip (Addids {idtables = [t]}) |
|
533 fun delids t = issue_pgip (Delids {idtables = [t]}) |
|
534 |
|
535 (* |
|
536 fun delallids ty = |
|
537 issue_pgip (Setids {idtables = |
|
538 [{context=NONE,objtype=ty,ids=[]}]}) *) |
|
539 |
561 fun askids vs = |
540 fun askids vs = |
562 let |
541 let |
563 val thyname = #thyname vs |
542 val url = #url vs (* ask for identifiers within a file *) |
564 val objtype = #objtype vs |
543 val thyname = #thyname vs (* ask for identifiers within a theory *) |
|
544 val objtype = #objtype vs (* ask for identifiers of a particular type *) |
|
545 |
|
546 fun idtable ty ctx ids = {objtype=ty,context=ctx,ids=ids} |
|
547 |
|
548 val thms_of_thy = (map fst) o PureThy.thms_of o ThyInfo.get_theory |
565 in |
549 in |
|
550 (* case (url_attr,thyname,objtype) of |
|
551 (NONE,NONE,NONE) => |
|
552 *) (* top-level: return *) |
|
553 |
566 (* TODO: add askids for "file" here, which returns single theory with same name *) |
554 (* TODO: add askids for "file" here, which returns single theory with same name *) |
|
555 (* FIXME: objtypes on both sides *) |
567 case (thyname,objtype) of |
556 case (thyname,objtype) of |
568 (* only theories known in top context *) |
557 (* only files known in top context *) |
569 (NONE, NONE) => send_thy_idtable NONE (ThyInfo.names()) |
558 (NONE, NONE) => setids (idtable ObjFile NONE (ThyInfo.names())) (*FIXME: uris?*) |
570 | (NONE, SOME "theory") => send_thy_idtable NONE (ThyInfo.names()) |
559 | (NONE, SOME ObjFile) => setids (idtable ObjFile NONE (ThyInfo.names())) (* ditto *) |
571 | (SOME thy, SOME "theory") => send_thy_idtable (SOME thy) (ThyInfo.get_preds thy) |
560 | (SOME fi, SOME ObjFile) => setids (idtable ObjTheory (SOME fi) [fi]) (* FIXME: lookup file *) |
572 | (SOME thy, SOME "theorem") => send_thm_idtable (SOME thy) (ThyInfo.get_theory thy) |
561 | (NONE, SOME ObjTheory) => setids (idtable ObjTheory NONE (ThyInfo.names())) |
573 | (SOME thy, NONE) => (send_thy_idtable (SOME thy) (ThyInfo.get_preds thy); |
562 | (SOME thy, SOME ObjTheory) => setids (idtable ObjTheory (SOME thy) (ThyInfo.get_preds thy)) |
574 send_thm_idtable (SOME thy) (ThyInfo.get_theory thy)) |
563 | (SOME thy, SOME ObjTheorem) => setids (idtable ObjTheorem (SOME thy) (thms_of_thy thy)) |
575 | (_, SOME ot) => error ("No objects of type "^(quote ot)^" are available here.") |
564 (* next case is both of above. FIXME: cleanup this *) |
|
565 | (SOME thy, NONE) => (setids (idtable ObjTheory (SOME thy) (ThyInfo.get_preds thy)); |
|
566 setids (idtable ObjTheorem (SOME thy) (thms_of_thy thy))) |
|
567 | (_, SOME ot) => error ("No objects of type "^(PgipTypes.name_of_objtype ot)^" are available here.") |
576 end |
568 end |
577 |
569 |
578 local |
570 local |
579 (* accumulate printed output in a single PGIP response (inside <pgmltext>) *) |
571 (* accumulate printed output in a single PGIP response (inside <pgmltext>) *) |
580 fun with_displaywrap pgipfn dispfn = |
572 fun with_displaywrap pgipfn dispfn = |
588 in |
580 in |
589 fun showid vs = |
581 fun showid vs = |
590 let |
582 let |
591 val thyname = #thyname vs |
583 val thyname = #thyname vs |
592 val objtype = #objtype vs |
584 val objtype = #objtype vs |
593 val name = #objtype vs |
585 val name = #name vs |
594 val topthy = Toplevel.theory_of o Toplevel.get_state |
586 val topthy = Toplevel.theory_of o Toplevel.get_state |
595 |
587 |
596 fun idvalue objtype name strings = |
588 fun idvalue objtype name strings = |
597 Idvalue { name=name, objtype=objtype, |
589 Idvalue { name=name, objtype=objtype, |
598 text=[XML.Elem("pgmltext",[],map XML.Text strings)] } |
590 text=[XML.Elem("pgmltext",[],map XML.Text strings)] } |
599 |
591 |
600 fun pthm thy name = print_thm (get_thm thy (Name name)) |
592 fun pthm thy name = print_thm (get_thm thy (Name name)) |
601 in |
593 in |
602 case (thyname, objtype) of |
594 case (thyname, objtype) of |
603 (_,"theory") => |
595 (_,ObjTheory) => |
604 with_displaywrap (idvalue "theory" name) |
596 with_displaywrap (idvalue ObjTheory name) |
605 (fn ()=>(print_theory (ThyInfo.get_theory name))) |
597 (fn ()=>(print_theory (ThyInfo.get_theory name))) |
606 | (SOME thy, "theorem") => |
598 | (SOME thy, ObjTheorem) => |
607 with_displaywrap (idvalue "theorem" name) |
599 with_displaywrap (idvalue ObjTheorem name) |
608 (fn ()=>(pthm (ThyInfo.get_theory thy) name)) |
600 (fn ()=>(pthm (ThyInfo.get_theory thy) name)) |
609 | (NONE, "theorem") => |
601 | (NONE, ObjTheorem) => |
610 with_displaywrap (idvalue "theorem" name) |
602 with_displaywrap (idvalue ObjTheorem name) |
611 (fn ()=>pthm (topthy()) name) |
603 (fn ()=>pthm (topthy()) name) |
612 | (_, ot) => error ("Cannot show objects of type "^ot) |
604 | (_, ot) => error ("Cannot show objects of type "^(PgipTypes.name_of_objtype ot)) |
613 end |
605 end |
|
606 |
|
607 (*** Inspecting state ***) |
614 |
608 |
615 (* The file which is currently being processed interactively. |
609 (* The file which is currently being processed interactively. |
616 In the pre-PGIP code, this was informed to Isabelle and the theory loader |
610 In the pre-PGIP code, this was informed to Isabelle and the theory loader |
617 on completion, but that allows for circularity in case we read |
611 on completion, but that allows for circularity in case we read |
618 ourselves. So PGIP opens the filename at the start of a script. |
612 ourselves. So PGIP opens the filename at the start of a script. |
647 let |
641 let |
648 val text = #text vs |
642 val text = #text vs |
649 val systemdata = #systemdata vs |
643 val systemdata = #systemdata vs |
650 val location = #location vs (* TODO: extract position *) |
644 val location = #location vs (* TODO: extract position *) |
651 |
645 |
652 val _ = start_delay_msgs () (* gather parsing messages *) |
646 val _ = start_delay_msgs () (* gather parsing errs/warns *) |
653 val xmls = PgipParser.xmls_of_str text |
647 val doc = PgipParser.pgip_parser text |
654 val errs = end_delayed_msgs () |
648 val errs = end_delayed_msgs () |
655 |
649 |
656 val sysattrs = PgipTypes.opt_attr "systemdata" systemdata |
650 val sysattrs = PgipTypes.opt_attr "systemdata" systemdata |
657 val locattrs = PgipTypes.attrs_of_location location |
651 val locattrs = PgipTypes.attrs_of_location location |
658 in |
652 in |
659 issue_pgip (Parseresult { attrs= sysattrs@locattrs, |
653 issue_pgip (Parseresult { attrs= sysattrs@locattrs, |
660 content = (map PgipOutput.output errs)@xmls }) |
654 doc = doc, |
|
655 errs = (map PgipOutput.output errs) }) |
661 end |
656 end |
662 |
657 |
663 fun showproofstate vs = isarcmd "pr" |
658 fun showproofstate vs = isarcmd "pr" |
664 |
659 |
665 fun showctxt vs = isarcmd "print_theory" (* more useful than print_context *) |
660 fun showctxt vs = isarcmd "print_theory" (* more useful than print_context *) |
706 val thyname = #thyname vs |
703 val thyname = #thyname vs |
707 in |
704 in |
708 isarcmd ("kill_thy " ^ quote thyname) |
705 isarcmd ("kill_thy " ^ quote thyname) |
709 end |
706 end |
710 |
707 |
711 fun loadfile vs = |
708 |
|
709 (*** Files ***) |
|
710 |
|
711 (* Path management: we allow theory files to have dependencies in |
|
712 their own directory, but when we change directory for a new file we |
|
713 remove the path. Leaving it there can cause confusion with |
|
714 difference in batch mode. |
|
715 NB: PGIP does not assume that the prover has a load path. |
|
716 *) |
|
717 |
|
718 local |
|
719 val current_working_dir = ref (NONE : string option) |
|
720 in |
|
721 fun changecwd_dir newdirpath = |
|
722 let |
|
723 val newdir = File.platform_path newdirpath |
|
724 in |
|
725 (case (!current_working_dir) of |
|
726 NONE => () |
|
727 | SOME dir => ThyLoad.del_path dir; |
|
728 ThyLoad.add_path newdir; |
|
729 current_working_dir := SOME newdir) |
|
730 end |
|
731 end |
|
732 |
|
733 fun changecwd vs = |
712 let |
734 let |
713 val url = #url vs |
735 val url = #url vs |
714 in |
736 val newdir = PgipTypes.path_of_pgipurl url |
715 case !currently_open_file of |
737 in |
716 SOME f => raise PGIP ("<loadfile> when a file is open!") |
738 changecwd_dir url |
717 | NONE => use_thy_or_ml_file (File.platform_path url) |
|
718 end |
739 end |
719 |
740 |
720 fun openfile vs = |
741 fun openfile vs = |
721 let |
742 let |
722 val url = #url vs |
743 val url = #url vs |
|
744 val filepath = PgipTypes.path_of_pgipurl url |
|
745 val filedir = Path.dir filepath |
|
746 val thy_name = Path.implode o #1 o Path.split_ext o Path.base |
|
747 val openfile_retract = Output.no_warnings (ThyInfo.if_known_thy ThyInfo.remove_thy) o thy_name; |
723 in |
748 in |
724 case !currently_open_file of |
749 case !currently_open_file of |
725 SOME f => raise PGIP ("<openfile> when a file is already open! ") |
750 SOME f => raise PGIP ("<openfile> when a file is already open! ") |
726 | NONE => (openfile_retract (File.platform_path url); |
751 | NONE => (openfile_retract filepath; |
727 currently_open_file := SOME url) (*(File.platform_path url))*) |
752 changecwd_dir filedir; |
|
753 currently_open_file := SOME url) |
728 end |
754 end |
729 |
755 |
730 fun closefile vs = |
756 fun closefile vs = |
731 case !currently_open_file of |
757 case !currently_open_file of |
732 SOME f => (proper_inform_file_processed (File.platform_path f) |
758 SOME f => (proper_inform_file_processed (File.platform_path f) |
733 (Isar.state()); |
759 (Isar.state()); |
734 currently_open_file := NONE) |
760 currently_open_file := NONE) |
735 | NONE => raise PGIP ("<closefile> when no file is open!") |
761 | NONE => raise PGIP ("<closefile> when no file is open!") |
736 |
762 |
|
763 fun loadfile vs = |
|
764 let |
|
765 val url = #url vs |
|
766 in |
|
767 case !currently_open_file of |
|
768 SOME f => raise PGIP ("<loadfile> when a file is open!") |
|
769 | NONE => use_thy_or_ml_file (File.platform_path url) |
|
770 end |
|
771 |
737 fun abortfile vs = |
772 fun abortfile vs = |
738 case !currently_open_file of |
773 case !currently_open_file of |
739 SOME f => (isarcmd "init_toplevel"; |
774 SOME f => (isarcmd "init_toplevel"; |
740 currently_open_file := NONE) |
775 currently_open_file := NONE) |
741 | NONE => raise PGIP ("<abortfile> when no file is open!") |
776 | NONE => raise PGIP ("<abortfile> when no file is open!") |
747 case !currently_open_file of |
782 case !currently_open_file of |
748 SOME f => raise PGIP ("<retractfile> when a file is open!") |
783 SOME f => raise PGIP ("<retractfile> when a file is open!") |
749 | NONE => inform_file_retracted (File.platform_path url) |
784 | NONE => inform_file_retracted (File.platform_path url) |
750 end |
785 end |
751 |
786 |
752 (* Path management: we allow theory files to have dependencies in |
787 |
753 their own directory, but when we change directory for a new file we |
788 (*** System ***) |
754 remove the path. Leaving it there can cause confusion with |
|
755 difference in batch mode. |
|
756 NB: PGIP does not assume that the prover has a load path. |
|
757 *) |
|
758 |
|
759 local |
|
760 val current_working_dir = ref (NONE : string option) |
|
761 in |
|
762 fun changecwd vs = |
|
763 let |
|
764 val url = #url vs |
|
765 val newdir = File.platform_path url |
|
766 in |
|
767 (case (!current_working_dir) of |
|
768 NONE => () |
|
769 | SOME dir => ThyLoad.del_path dir; |
|
770 ThyLoad.add_path newdir; |
|
771 current_working_dir := SOME newdir) |
|
772 end |
|
773 end |
|
774 |
|
775 |
789 |
776 fun systemcmd vs = |
790 fun systemcmd vs = |
777 let |
791 let |
778 val arg = #arg vs |
792 val arg = #arg vs |
779 in |
793 in |