src/Pure/Tools/ml_console.scala
author wenzelm
Wed, 09 Mar 2016 20:44:02 +0100
changeset 62577 7e2aa1d67dd8
parent 62562 905a5db3932d
child 62586 a522a5692832
permissions -rw-r--r--
clarified interactive mode, which is relevant for ML prompts;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Tools/ml_console.scala
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
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
     4
Run Isabelle process with raw ML console and line editor.
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()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    25
      var system_mode = false
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    26
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    27
      val getopts = Getopts("""
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    28
Usage: isabelle console [OPTIONS]
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    29
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    30
  Options are:
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    31
    -d DIR       include session directory
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    32
    -l NAME      logic session name (default ISABELLE_LOGIC=""" + quote(logic) + """)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    33
    -m MODE      add print mode for output
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    34
    -n           no build of session image on startup
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    35
    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    36
    -r           logic session is RAW_ML_SYSTEM
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    37
    -s           system build mode for session image
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    38
62562
905a5db3932d back to external line editor, due to problems of JLine with multithreading of in vs. out;
wenzelm
parents: 62561
diff changeset
    39
  Run Isabelle process with raw ML console and line editor
905a5db3932d back to external line editor, due to problems of JLine with multithreading of in vs. out;
wenzelm
parents: 62561
diff changeset
    40
  (ISABELLE_LINE_EDITOR=""" + quote(Isabelle_System.getenv("ISABELLE_LINE_EDITOR")) + """.
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    41
""",
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    42
        "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    43
        "l:" -> (arg => logic = arg),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    44
        "m:" -> (arg => modes = arg :: modes),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    45
        "n" -> (arg => no_build = true),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    46
        "o:" -> (arg => options = options + arg),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    47
        "r" -> (_ => logic = "RAW_ML_SYSTEM"),
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    48
        "s" -> (_ => system_mode = true))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    49
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    50
      val more_args = getopts(args)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    51
      if (!more_args.isEmpty) getopts.usage()
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    52
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    53
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    54
      // build
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    55
      if (!no_build && logic != "RAW_ML_SYSTEM" &&
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    56
          Build.build(options = options, build_heap = true, no_build = true,
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    57
            dirs = dirs, system_mode = system_mode, sessions = List(logic)) != 0)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    58
      {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    59
        val progress = new Console_Progress
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    60
        progress.echo("Build started for Isabelle/" + logic + " ...")
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    61
        progress.interrupt_handler {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    62
          val rc =
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    63
            Build.build(options = options, progress = progress, build_heap = true,
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    64
              dirs = dirs, system_mode = system_mode, sessions = List(logic))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    65
          if (rc != 0) sys.exit(rc)
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    66
        }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    67
      }
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
      // process loop
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    70
      val process =
62577
7e2aa1d67dd8 clarified interactive mode, which is relevant for ML prompts;
wenzelm
parents: 62562
diff changeset
    71
        ML_Process(options, heap = logic, args = List("-i"),
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    72
          modes = if (logic == "RAW_ML_SYSTEM") Nil else modes ::: List("ASCII"))
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    73
      val process_output = Future.thread[Unit]("process_output") {
62561
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    74
        try {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    75
          var result = new StringBuilder(100)
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    76
          var finished = false
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    77
          while (!finished) {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    78
            var c = -1
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    79
            var done = false
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    80
            while (!done && (result.length == 0 || process.stdout.ready)) {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    81
              c = process.stdout.read
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    82
              if (c >= 0) result.append(c.asInstanceOf[Char])
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    83
              else done = true
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    84
            }
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    85
            if (result.length > 0) {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    86
              System.out.print(result.toString)
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    87
              System.out.flush()
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    88
              result.length = 0
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    89
            }
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    90
            else {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    91
              process.stdout.close()
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    92
              finished = true
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    93
            }
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    94
          }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    95
        }
62561
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
    96
        catch { case e: IOException => case Exn.Interrupt() => }
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    97
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
    98
      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
    99
        val reader = new BufferedReader(new InputStreamReader(System.in))
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   100
        POSIX_Interrupt.handler { process.interrupt } {
62561
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   101
          try {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   102
            var finished = false
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   103
            while (!finished) {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   104
              reader.readLine() match {
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   105
                case null =>
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   106
                  process.stdin.close()
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   107
                  finished = true
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   108
                case line =>
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   109
                  process.stdin.write(line)
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   110
                  process.stdin.write("\n")
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   111
                  process.stdin.flush()
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   112
              }
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   113
            }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   114
          }
62561
4bf00f54e4bc ignore execeptions that usually occur due to shutdown;
wenzelm
parents: 62559
diff changeset
   115
          catch { case e: IOException => case Exn.Interrupt() => }
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   116
        }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   117
      }
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   118
      val process_result = Future.thread[Int]("process_result") {
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   119
        val rc = process.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   120
        process_input.cancel
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   121
        rc
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
      process_output.join
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   125
      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
   126
      process_result.join
62559
83e815849a91 isabelle console is based on Isabelle/Scala;
wenzelm
parents:
diff changeset
   127
    }
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
}