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