| author | wenzelm | 
| Sat, 17 Aug 2019 19:04:03 +0200 | |
| changeset 70570 | d94456876f2d | 
| parent 69810 | a23d6ff31f79 | 
| child 70686 | 9cde8c4ea5a5 | 
| permissions | -rw-r--r-- | 
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/System/isabelle_tool.scala | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 63226 | 3 | Author: Lars Hupel | 
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 4 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 5 | Isabelle system tools: external executables or internal Scala functions. | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 6 | */ | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 7 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 8 | package isabelle | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 9 | |
| 63226 | 10 | import java.net.URLClassLoader | 
| 11 | import scala.reflect.runtime.universe | |
| 12 | import scala.tools.reflect.{ToolBox,ToolBoxError}
 | |
| 13 | ||
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 14 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 15 | object Isabelle_Tool | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 16 | {
 | 
| 63226 | 17 | /* Scala source tools */ | 
| 18 | ||
| 19 | abstract class Body extends Function[List[String], Unit] | |
| 20 | ||
| 21 | private def compile(path: Path): Body = | |
| 22 |   {
 | |
| 23 | def err(msg: String): Nothing = | |
| 24 | cat_error(msg, "The error(s) above occurred in Isabelle/Scala tool " + path) | |
| 25 | ||
| 26 | val source = File.read(path) | |
| 27 | ||
| 28 | val class_loader = new URLClassLoader(Array(), getClass.getClassLoader) | |
| 29 | val tool_box = universe.runtimeMirror(class_loader).mkToolBox() | |
| 30 | ||
| 31 |     try {
 | |
| 32 |       val symbol = tool_box.parse(source) match {
 | |
| 33 | case tree: universe.ModuleDef => tool_box.define(tree) | |
| 34 |         case _ => err("Source does not describe a module (Scala object)")
 | |
| 35 | } | |
| 36 |       tool_box.compile(universe.Ident(symbol))() match {
 | |
| 37 | case body: Body => body | |
| 38 |         case _ => err("Ill-typed source: Isabelle_Tool.Body expected")
 | |
| 39 | } | |
| 40 | } | |
| 63519 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 41 |     catch {
 | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 42 | case e: ToolBoxError => | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 43 |         if (tool_box.frontEnd.hasErrors) {
 | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 44 | val infos = tool_box.frontEnd.infos.toList | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 45 | val msgs = infos.map(info => "Error in line " + info.pos.line + ":\n" + info.msg) | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 46 |           err(msgs.mkString("\n"))
 | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 47 | } | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 48 | else | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 49 | err(e.toString) | 
| 
78401d628718
more precise error information for dynamic Scala tools
 Lars Hupel <lars.hupel@mytum.de> parents: 
63226diff
changeset | 50 | } | 
| 63226 | 51 | } | 
| 52 | ||
| 53 | ||
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 54 | /* external tools */ | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 55 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 56 |   private def dirs(): List[Path] = Path.split(Isabelle_System.getenv_strict("ISABELLE_TOOLS"))
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 57 | |
| 63226 | 58 | private def is_external(dir: Path, file_name: String): Boolean = | 
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 59 |   {
 | 
| 65450 
b0a73039ddaa
more robust: user could provide name with "/" etc.;
 wenzelm parents: 
65138diff
changeset | 60 | val file = (dir + Path.explode(file_name)).file | 
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 61 |     try {
 | 
| 63226 | 62 | file.isFile && file.canRead && | 
| 63 |         (file_name.endsWith(".scala") || file.canExecute) &&
 | |
| 64 |         !file_name.endsWith("~") && !file_name.endsWith(".orig")
 | |
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 65 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 66 |     catch { case _: SecurityException => false }
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 67 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 68 | |
| 62830 | 69 | private def list_external(): List[(String, String)] = | 
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 70 |   {
 | 
| 62830 | 71 | val Description = """.*\bDESCRIPTION: *(.*)""".r | 
| 72 |     for {
 | |
| 73 | dir <- dirs() if dir.is_dir | |
| 63226 | 74 | file_name <- File.read_dir(dir) if is_external(dir, file_name) | 
| 62830 | 75 |     } yield {
 | 
| 65450 
b0a73039ddaa
more robust: user could provide name with "/" etc.;
 wenzelm parents: 
65138diff
changeset | 76 | val source = File.read(dir + Path.explode(file_name)) | 
| 65606 | 77 |       val name = Library.perhaps_unsuffix(".scala", file_name)
 | 
| 62830 | 78 | val description = | 
| 79 |         split_lines(source).collectFirst({ case Description(s) => s }) getOrElse ""
 | |
| 80 | (name, description) | |
| 81 | } | |
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 82 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 83 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 84 | private def find_external(name: String): Option[List[String] => Unit] = | 
| 63226 | 85 |     dirs.collectFirst({
 | 
| 86 | case dir if is_external(dir, name + ".scala") => | |
| 65450 
b0a73039ddaa
more robust: user could provide name with "/" etc.;
 wenzelm parents: 
65138diff
changeset | 87 | compile(dir + Path.explode(name + ".scala")) | 
| 63226 | 88 | case dir if is_external(dir, name) => | 
| 89 | (args: List[String]) => | |
| 90 |           {
 | |
| 65450 
b0a73039ddaa
more robust: user could provide name with "/" etc.;
 wenzelm parents: 
65138diff
changeset | 91 | val tool = dir + Path.explode(name) | 
| 64304 | 92 | val result = Isabelle_System.bash(File.bash_path(tool) + " " + Bash.strings(args)) | 
| 63226 | 93 | sys.exit(result.print_stdout.rc) | 
| 94 | } | |
| 62830 | 95 | }) | 
| 96 | ||
| 97 | ||
| 98 | /* internal tools */ | |
| 99 | ||
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 100 | private lazy val internal_tools: List[Isabelle_Tool] = | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 101 |     Isabelle_System.init_classes[Isabelle_Scala_Tools]("ISABELLE_SCALA_TOOLS")
 | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 102 | .flatMap(_.tools.toList) | 
| 62830 | 103 | |
| 104 | private def list_internal(): List[(String, String)] = | |
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 105 | for (tool <- internal_tools.toList) | 
| 64161 | 106 | yield (tool.name, tool.description) | 
| 62830 | 107 | |
| 108 | private def find_internal(name: String): Option[List[String] => Unit] = | |
| 62960 
cfbb6a5b427c
simplified -- avoid odd mutable state, which potentially causes problems with module initialization;
 wenzelm parents: 
62838diff
changeset | 109 |     internal_tools.collectFirst({
 | 
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 110 | case tool if tool.name == name => | 
| 62960 
cfbb6a5b427c
simplified -- avoid odd mutable state, which potentially causes problems with module initialization;
 wenzelm parents: 
62838diff
changeset | 111 |         args => Command_Line.tool0 { tool.body(args) }
 | 
| 
cfbb6a5b427c
simplified -- avoid odd mutable state, which potentially causes problems with module initialization;
 wenzelm parents: 
62838diff
changeset | 112 | }) | 
| 62831 | 113 | |
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 114 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 115 | /* command line entry point */ | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 116 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 117 | def main(args: Array[String]) | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 118 |   {
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 119 |     Command_Line.tool0 {
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 120 |       args.toList match {
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 121 |         case Nil | List("-?") =>
 | 
| 62830 | 122 | val tool_descriptions = | 
| 123 | (list_external() ::: list_internal()).sortBy(_._1). | |
| 124 |               map({ case (a, "") => a case (a, b) => a + " - " + b })
 | |
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 125 |           Getopts("""
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 126 | Usage: isabelle TOOL [ARGS ...] | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 127 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 128 | Start Isabelle TOOL with ARGS; pass "-?" for tool-specific help. | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 129 | |
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 130 | Available tools:""" + tool_descriptions.mkString("\n  ", "\n  ", "\n")).usage
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 131 | case tool_name :: tool_args => | 
| 62830 | 132 |           find_external(tool_name) orElse find_internal(tool_name) match {
 | 
| 133 | case Some(tool) => tool(tool_args) | |
| 62829 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 134 |             case None => error("Unknown Isabelle tool: " + quote(tool_name))
 | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 135 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 136 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 137 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 138 | } | 
| 
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
 wenzelm parents: diff
changeset | 139 | } | 
| 62830 | 140 | |
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 141 | sealed case class Isabelle_Tool(name: String, description: String, body: List[String] => Unit) | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 142 | |
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 143 | class Isabelle_Scala_Tools(val tools: Isabelle_Tool*) | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 144 | |
| 69810 | 145 | class Tools extends Isabelle_Scala_Tools( | 
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 146 | Build.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 147 | Build_Docker.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 148 | Doc.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 149 | Dump.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 150 | Export.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 151 | Imports.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 152 | ML_Process.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 153 | Mkroot.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 154 | Options.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 155 | Present.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 156 | Profiling_Report.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 157 | Server.isabelle_tool, | 
| 69557 | 158 | Update.isabelle_tool, | 
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 159 | Update_Cartouches.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 160 | Update_Comments.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 161 | Update_Header.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 162 | Update_Then.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 163 | Update_Theorems.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 164 | isabelle.vscode.Grammar.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 165 | isabelle.vscode.Server.isabelle_tool) | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 166 | |
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 167 | class Admin_Tools extends Isabelle_Scala_Tools( | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 168 | Build_Cygwin.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 169 | Build_Doc.isabelle_tool, | 
| 69339 | 170 | Build_Fonts.isabelle_tool, | 
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 171 | Build_JDK.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 172 | Build_PolyML.isabelle_tool1, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 173 | Build_PolyML.isabelle_tool2, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 174 | Build_Status.isabelle_tool, | 
| 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 175 | Check_Sources.isabelle_tool, | 
| 69429 
dc5fbcb07c7b
replaced "isabelle components_checksum" shell script by "isabelle build_components" in Scala, with more functionality;
 wenzelm parents: 
69401diff
changeset | 176 | Components.isabelle_tool, | 
| 69277 
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
 wenzelm parents: 
69168diff
changeset | 177 | isabelle.vscode.Build_VSCode.isabelle_tool) |