| author | paulson <lp15@cam.ac.uk> | 
| Tue, 19 Sep 2017 16:37:19 +0100 | |
| changeset 66660 | bc3584f7ac0c | 
| parent 65477 | 64e61b0f6972 | 
| child 66963 | 1c3d0c12bb51 | 
| permissions | -rw-r--r-- | 
| 65477 | 1 | /* Title: Pure/ML/ml_console.scala | 
| 62559 | 2 | Author: Makarius | 
| 3 | ||
| 62588 
cd266473b81b
isabelle_process is superseded by "isabelle process" tool;
 wenzelm parents: 
62586diff
changeset | 4 | The raw ML process in interactive mode. | 
| 62559 | 5 | */ | 
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 62562 
905a5db3932d
back to external line editor, due to problems of JLine with multithreading of in vs. out;
 wenzelm parents: 
62561diff
changeset | 10 | import java.io.{IOException, BufferedReader, InputStreamReader}
 | 
| 62559 | 11 | |
| 12 | ||
| 13 | object ML_Console | |
| 14 | {
 | |
| 15 | /* command line entry point */ | |
| 16 | ||
| 17 | def main(args: Array[String]) | |
| 18 |   {
 | |
| 19 |     Command_Line.tool {
 | |
| 20 | var dirs: List[Path] = Nil | |
| 21 |       var logic = Isabelle_System.getenv("ISABELLE_LOGIC")
 | |
| 22 | var modes: List[String] = Nil | |
| 23 | var no_build = false | |
| 24 | var options = Options.init() | |
| 62643 | 25 | var raw_ml_system = false | 
| 62559 | 26 | var system_mode = false | 
| 27 | ||
| 28 |       val getopts = Getopts("""
 | |
| 29 | Usage: isabelle console [OPTIONS] | |
| 30 | ||
| 31 | Options are: | |
| 32 | -d DIR include session directory | |
| 33 | -l NAME logic session name (default ISABELLE_LOGIC=""" + quote(logic) + """) | |
| 34 | -m MODE add print mode for output | |
| 35 | -n no build of session image on startup | |
| 36 | -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) | |
| 62643 | 37 | -r bootstrap from raw Poly/ML | 
| 62559 | 38 | -s system build mode for session image | 
| 39 | ||
| 62588 
cd266473b81b
isabelle_process is superseded by "isabelle process" tool;
 wenzelm parents: 
62586diff
changeset | 40 | Build a logic session image and run the raw Isabelle ML process | 
| 
cd266473b81b
isabelle_process is superseded by "isabelle process" tool;
 wenzelm parents: 
62586diff
changeset | 41 | in interactive mode, with line editor ISABELLE_LINE_EDITOR=""" + | 
| 
cd266473b81b
isabelle_process is superseded by "isabelle process" tool;
 wenzelm parents: 
62586diff
changeset | 42 |   quote(Isabelle_System.getenv("ISABELLE_LINE_EDITOR")) + """.
 | 
| 62559 | 43 | """, | 
| 44 | "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), | |
| 45 | "l:" -> (arg => logic = arg), | |
| 46 | "m:" -> (arg => modes = arg :: modes), | |
| 47 | "n" -> (arg => no_build = true), | |
| 48 | "o:" -> (arg => options = options + arg), | |
| 62643 | 49 | "r" -> (_ => raw_ml_system = true), | 
| 62559 | 50 | "s" -> (_ => system_mode = true)) | 
| 51 | ||
| 52 | val more_args = getopts(args) | |
| 53 | if (!more_args.isEmpty) getopts.usage() | |
| 54 | ||
| 55 | ||
| 56 | // build | |
| 62643 | 57 | if (!no_build && !raw_ml_system && | 
| 62641 | 58 | !Build.build(options = options, build_heap = true, no_build = true, | 
| 59 | dirs = dirs, system_mode = system_mode, sessions = List(logic)).ok) | |
| 62559 | 60 |       {
 | 
| 64115 | 61 | val progress = new Console_Progress() | 
| 62559 | 62 |         progress.echo("Build started for Isabelle/" + logic + " ...")
 | 
| 63 |         progress.interrupt_handler {
 | |
| 62641 | 64 | val res = | 
| 62559 | 65 | Build.build(options = options, progress = progress, build_heap = true, | 
| 66 | dirs = dirs, system_mode = system_mode, sessions = List(logic)) | |
| 62641 | 67 | if (!res.ok) sys.exit(res.rc) | 
| 62559 | 68 | } | 
| 69 | } | |
| 70 | ||
| 71 | // process loop | |
| 72 | val process = | |
| 64598 | 73 |         ML_Process(options, logic = logic, args = List("-i"), dirs = dirs, redirect = true,
 | 
| 62643 | 74 |           modes = if (raw_ml_system) Nil else modes ::: List("ASCII"),
 | 
| 65431 
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
 wenzelm parents: 
64598diff
changeset | 75 | raw_ml_system = raw_ml_system, store = Sessions.store(system_mode), | 
| 
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
 wenzelm parents: 
64598diff
changeset | 76 | session_base = | 
| 
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
 wenzelm parents: 
64598diff
changeset | 77 | if (raw_ml_system) None | 
| 
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
 wenzelm parents: 
64598diff
changeset | 78 | else Some(Sessions.session_base(options, logic, dirs))) | 
| 62559 | 79 |       val process_output = Future.thread[Unit]("process_output") {
 | 
| 62561 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 80 |         try {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 81 | var result = new StringBuilder(100) | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 82 | var finished = false | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 83 |           while (!finished) {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 84 | var c = -1 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 85 | var done = false | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 86 |             while (!done && (result.length == 0 || process.stdout.ready)) {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 87 | c = process.stdout.read | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 88 | if (c >= 0) result.append(c.asInstanceOf[Char]) | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 89 | else done = true | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 90 | } | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 91 |             if (result.length > 0) {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 92 | System.out.print(result.toString) | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 93 | System.out.flush() | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 94 | result.length = 0 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 95 | } | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 96 |             else {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 97 | process.stdout.close() | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 98 | finished = true | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 99 | } | 
| 62559 | 100 | } | 
| 101 | } | |
| 62561 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 102 |         catch { case e: IOException => case Exn.Interrupt() => }
 | 
| 62559 | 103 | } | 
| 104 |       val process_input = Future.thread[Unit]("process_input") {
 | |
| 62562 
905a5db3932d
back to external line editor, due to problems of JLine with multithreading of in vs. out;
 wenzelm parents: 
62561diff
changeset | 105 | val reader = new BufferedReader(new InputStreamReader(System.in)) | 
| 62559 | 106 |         POSIX_Interrupt.handler { process.interrupt } {
 | 
| 62561 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 107 |           try {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 108 | var finished = false | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 109 |             while (!finished) {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 110 |               reader.readLine() match {
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 111 | case null => | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 112 | process.stdin.close() | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 113 | finished = true | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 114 | case line => | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 115 | process.stdin.write(line) | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 116 |                   process.stdin.write("\n")
 | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 117 | process.stdin.flush() | 
| 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 118 | } | 
| 62559 | 119 | } | 
| 120 | } | |
| 62561 
4bf00f54e4bc
ignore execeptions that usually occur due to shutdown;
 wenzelm parents: 
62559diff
changeset | 121 |           catch { case e: IOException => case Exn.Interrupt() => }
 | 
| 62559 | 122 | } | 
| 123 | } | |
| 124 |       val process_result = Future.thread[Int]("process_result") {
 | |
| 125 | val rc = process.join | |
| 126 | process_input.cancel | |
| 127 | rc | |
| 128 | } | |
| 129 | ||
| 130 | process_output.join | |
| 131 | process_input.join | |
| 62562 
905a5db3932d
back to external line editor, due to problems of JLine with multithreading of in vs. out;
 wenzelm parents: 
62561diff
changeset | 132 | process_result.join | 
| 62559 | 133 | } | 
| 134 | } | |
| 135 | } |