author | wenzelm |
Tue, 04 May 2021 20:02:08 +0200 | |
changeset 73625 | f8f065e20837 |
parent 73565 | 1aa92bc4d356 |
child 73653 | d9823224fcfe |
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 |
|
72763 | 12 |
import scala.tools.reflect.{ToolBox, ToolBoxError} |
63226 | 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 { |
|
73369 | 32 |
val tree = tool_box.parse(source) |
33 |
val module = |
|
34 |
try { tree.asInstanceOf[universe.ModuleDef] } |
|
35 |
catch { |
|
36 |
case _: java.lang.ClassCastException => |
|
37 |
err("Source does not describe a module (Scala object)") |
|
38 |
} |
|
39 |
tool_box.compile(universe.Ident(tool_box.define(module)))() match { |
|
63226 | 40 |
case body: Body => body |
41 |
case _ => err("Ill-typed source: Isabelle_Tool.Body expected") |
|
42 |
} |
|
43 |
} |
|
63519
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
44 |
catch { |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
45 |
case e: ToolBoxError => |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
46 |
if (tool_box.frontEnd.hasErrors) { |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
47 |
val infos = tool_box.frontEnd.infos.toList |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
48 |
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:
63226
diff
changeset
|
49 |
err(msgs.mkString("\n")) |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
50 |
} |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
51 |
else |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
52 |
err(e.toString) |
78401d628718
more precise error information for dynamic Scala tools
Lars Hupel <lars.hupel@mytum.de>
parents:
63226
diff
changeset
|
53 |
} |
63226 | 54 |
} |
55 |
||
56 |
||
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
57 |
/* external tools */ |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
58 |
|
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
59 |
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
|
60 |
|
63226 | 61 |
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
|
62 |
{ |
65450
b0a73039ddaa
more robust: user could provide name with "/" etc.;
wenzelm
parents:
65138
diff
changeset
|
63 |
val file = (dir + Path.explode(file_name)).file |
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
64 |
try { |
63226 | 65 |
file.isFile && file.canRead && |
66 |
(file_name.endsWith(".scala") || file.canExecute) && |
|
67 |
!file_name.endsWith("~") && !file_name.endsWith(".orig") |
|
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
68 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
69 |
catch { case _: SecurityException => false } |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
70 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
71 |
|
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
72 |
private def find_external(name: String): Option[List[String] => Unit] = |
71383 | 73 |
dirs().collectFirst({ |
63226 | 74 |
case dir if is_external(dir, name + ".scala") => |
65450
b0a73039ddaa
more robust: user could provide name with "/" etc.;
wenzelm
parents:
65138
diff
changeset
|
75 |
compile(dir + Path.explode(name + ".scala")) |
63226 | 76 |
case dir if is_external(dir, name) => |
77 |
(args: List[String]) => |
|
78 |
{ |
|
65450
b0a73039ddaa
more robust: user could provide name with "/" etc.;
wenzelm
parents:
65138
diff
changeset
|
79 |
val tool = dir + Path.explode(name) |
64304 | 80 |
val result = Isabelle_System.bash(File.bash_path(tool) + " " + Bash.strings(args)) |
63226 | 81 |
sys.exit(result.print_stdout.rc) |
82 |
} |
|
62830 | 83 |
}) |
84 |
||
85 |
||
86 |
/* internal tools */ |
|
87 |
||
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
88 |
private lazy val internal_tools: List[Isabelle_Tool] = |
72159
40b5ee5889d2
clarified management of services: static declarations vs. dynamic instances (e.g. relevant for stateful Session.Protocol_Handler, notably Scala.Handler and session "System");
wenzelm
parents:
71808
diff
changeset
|
89 |
Isabelle_System.make_services(classOf[Isabelle_Scala_Tools]).flatMap(_.tools) |
62830 | 90 |
|
91 |
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:
62838
diff
changeset
|
92 |
internal_tools.collectFirst({ |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
93 |
case tool if tool.name == name => |
71632 | 94 |
args => Command_Line.tool { tool.body(args) } |
62960
cfbb6a5b427c
simplified -- avoid odd mutable state, which potentially causes problems with module initialization;
wenzelm
parents:
62838
diff
changeset
|
95 |
}) |
62831 | 96 |
|
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
97 |
|
72763 | 98 |
/* list tools */ |
99 |
||
100 |
abstract class Entry |
|
101 |
{ |
|
102 |
def name: String |
|
103 |
def position: Properties.T |
|
104 |
def description: String |
|
105 |
def print: String = |
|
106 |
description match { |
|
107 |
case "" => name |
|
108 |
case descr => name + " - " + descr |
|
109 |
} |
|
110 |
} |
|
111 |
||
112 |
sealed case class External(name: String, path: Path) extends Entry |
|
113 |
{ |
|
114 |
def position: Properties.T = Position.File(path.absolute.implode) |
|
115 |
def description: String = |
|
116 |
{ |
|
117 |
val Pattern = """.*\bDESCRIPTION: *(.*)""".r |
|
118 |
split_lines(File.read(path)).collectFirst({ case Pattern(s) => s }) getOrElse "" |
|
119 |
} |
|
120 |
} |
|
121 |
||
122 |
def external_tools(): List[External] = |
|
123 |
{ |
|
124 |
for { |
|
125 |
dir <- dirs() if dir.is_dir |
|
126 |
file_name <- File.read_dir(dir) if is_external(dir, file_name) |
|
127 |
} yield { |
|
128 |
val path = dir + Path.explode(file_name) |
|
129 |
val name = Library.perhaps_unsuffix(".scala", file_name) |
|
130 |
External(name, path) |
|
131 |
} |
|
132 |
} |
|
133 |
||
134 |
def isabelle_tools(): List[Entry] = |
|
135 |
(external_tools() ::: internal_tools).sortBy(_.name) |
|
136 |
||
73565 | 137 |
object Isabelle_Tools extends Scala.Fun_String("isabelle_tools") |
72763 | 138 |
{ |
139 |
val here = Scala_Project.here |
|
140 |
def apply(arg: String): String = |
|
141 |
if (arg.nonEmpty) error("Bad argument: " + quote(arg)) |
|
142 |
else { |
|
143 |
val result = isabelle_tools().map(entry => (entry.name, entry.position)) |
|
144 |
val body = { import XML.Encode._; list(pair(string, properties))(result) } |
|
145 |
YXML.string_of_body(body) |
|
146 |
} |
|
147 |
} |
|
148 |
||
149 |
||
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
150 |
/* command line entry point */ |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
151 |
|
73340 | 152 |
def main(args: Array[String]): Unit = |
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
153 |
{ |
71632 | 154 |
Command_Line.tool { |
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
155 |
args.toList match { |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
156 |
case Nil | List("-?") => |
72763 | 157 |
val tool_descriptions = isabelle_tools().map(_.print) |
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
158 |
Getopts(""" |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
159 |
Usage: isabelle TOOL [ARGS ...] |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
160 |
|
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
161 |
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
|
162 |
|
73367 | 163 |
Available tools:""" + tool_descriptions.mkString("\n ", "\n ", "\n")).usage() |
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
164 |
case tool_name :: tool_args => |
62830 | 165 |
find_external(tool_name) orElse find_internal(tool_name) match { |
166 |
case Some(tool) => tool(tool_args) |
|
62829
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
167 |
case None => error("Unknown Isabelle tool: " + quote(tool_name)) |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
168 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
169 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
170 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
171 |
} |
4141c2a8458b
clarified Isabelle tool wrapper: bash, Scala, no perl, no ML;
wenzelm
parents:
diff
changeset
|
172 |
} |
62830 | 173 |
|
72763 | 174 |
sealed case class Isabelle_Tool( |
175 |
name: String, |
|
176 |
description: String, |
|
177 |
here: Scala_Project.Here, |
|
178 |
body: List[String] => Unit) extends Isabelle_Tool.Entry |
|
179 |
{ |
|
180 |
def position: Position.T = here.position |
|
181 |
} |
|
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
182 |
|
71736 | 183 |
class Isabelle_Scala_Tools(val tools: Isabelle_Tool*) extends Isabelle_System.Service |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
184 |
|
69810 | 185 |
class Tools extends Isabelle_Scala_Tools( |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
186 |
Build.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
187 |
Build_Docker.isabelle_tool, |
72858
cb0c407fbc6e
added "isabelle log": print messages from build database;
wenzelm
parents:
72767
diff
changeset
|
188 |
Build_Job.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
189 |
Doc.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
190 |
Dump.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
191 |
Export.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
192 |
ML_Process.isabelle_tool, |
71312
937328d61436
added command hg_setup: setup remote vs. local Mercurial repository;
wenzelm
parents:
71109
diff
changeset
|
193 |
Mercurial.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
194 |
Mkroot.isabelle_tool, |
73399 | 195 |
Logo.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
196 |
Options.isabelle_tool, |
70967 | 197 |
Phabricator.isabelle_tool1, |
198 |
Phabricator.isabelle_tool2, |
|
71097 | 199 |
Phabricator.isabelle_tool3, |
71109
8c1c717a830b
configure SSH hosting via "isabelle phabricator_setup_ssh";
wenzelm
parents:
71097
diff
changeset
|
200 |
Phabricator.isabelle_tool4, |
72652 | 201 |
Presentation.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
202 |
Profiling_Report.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
203 |
Server.isabelle_tool, |
71808 | 204 |
Sessions.isabelle_tool, |
71378
820cf124dced
added "isabelle scala_project" to support e.g. IntelliJ IDEA;
wenzelm
parents:
71312
diff
changeset
|
205 |
Scala_Project.isabelle_tool, |
69557 | 206 |
Update.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
207 |
Update_Cartouches.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
208 |
Update_Comments.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
209 |
Update_Header.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
210 |
Update_Then.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
211 |
Update_Theorems.isabelle_tool, |
72767 | 212 |
isabelle.vscode.TextMate_Grammar.isabelle_tool, |
72761 | 213 |
isabelle.vscode.Language_Server.isabelle_tool) |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
214 |
|
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
215 |
class Admin_Tools extends Isabelle_Scala_Tools( |
72414
af24c0dd6975
build Isabelle CSDP component from official downloads;
wenzelm
parents:
72411
diff
changeset
|
216 |
Build_CSDP.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
217 |
Build_Cygwin.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
218 |
Build_Doc.isabelle_tool, |
72363
fc5f10691147
build Isabelle E prover component from official downloads;
wenzelm
parents:
72346
diff
changeset
|
219 |
Build_E.isabelle_tool, |
69339 | 220 |
Build_Fonts.isabelle_tool, |
73476
6b480efe1bc3
support for Java Chromium Embedded Framework (JCEF): still somewhat fragile;
wenzelm
parents:
73399
diff
changeset
|
221 |
Build_JCEF.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
222 |
Build_JDK.isabelle_tool, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
223 |
Build_PolyML.isabelle_tool1, |
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
224 |
Build_PolyML.isabelle_tool2, |
72411
b8cc129ece05
build Isabelle SPASS component from unofficial download;
wenzelm
parents:
72363
diff
changeset
|
225 |
Build_SPASS.isabelle_tool, |
72346
93e533198bf6
build Isabelle sqlite-jdbc component from official download;
wenzelm
parents:
72159
diff
changeset
|
226 |
Build_SQLite.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
227 |
Build_Status.isabelle_tool, |
72886
ac64b753a65f
build Isabelle Vampire component from repository;
wenzelm
parents:
72858
diff
changeset
|
228 |
Build_Vampire.isabelle_tool, |
72439
7f6800b2e8c2
build Isabelle veriT component from official download;
wenzelm
parents:
72414
diff
changeset
|
229 |
Build_VeriT.isabelle_tool, |
72466
04403e1ef176
build Isabelle Zipperposition component from OPAM repository;
wenzelm
parents:
72439
diff
changeset
|
230 |
Build_Zipperposition.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
231 |
Check_Sources.isabelle_tool, |
69429
dc5fbcb07c7b
replaced "isabelle components_checksum" shell script by "isabelle build_components" in Scala, with more functionality;
wenzelm
parents:
69401
diff
changeset
|
232 |
Components.isabelle_tool, |
69277
258bef08b31e
support for user-defined Isabelle/Scala command-line tools;
wenzelm
parents:
69168
diff
changeset
|
233 |
isabelle.vscode.Build_VSCode.isabelle_tool) |