author | wenzelm |
Thu, 23 Jan 2025 22:19:30 +0100 | |
changeset 81960 | 326ecfc079a6 |
parent 80462 | 7a1f9e571046 |
permissions | -rw-r--r-- |
65477 | 1 |
/* Title: Pure/ML/ml_process.scala |
62544 | 2 |
Author: Makarius |
3 |
||
62586 | 4 |
The raw ML process. |
62544 | 5 |
*/ |
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
73897 | 10 |
import java.util.{Map => JMap, HashMap} |
62573 | 11 |
|
12 |
||
75393 | 13 |
object ML_Process { |
80124 | 14 |
def make_shasum(ancestors: List[SHA1.Shasum]): SHA1.Shasum = |
15 |
if (ancestors.isEmpty) SHA1.shasum_meta_info(SHA1.digest(Path.explode("$POLYML_EXE"))) |
|
16 |
else SHA1.flat_shasum(ancestors) |
|
77650 | 17 |
|
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
18 |
def session_heaps( |
78178 | 19 |
store: Store, |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
20 |
session_background: Sessions.Background, |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
21 |
logic: String = "" |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
22 |
): List[Path] = { |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
23 |
val logic_name = Isabelle_System.default_logic(logic) |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
24 |
|
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
25 |
session_background.sessions_structure.selection(logic_name). |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
26 |
build_requirements(List(logic_name)). |
79674 | 27 |
map(name => store.get_session(name).the_heap) |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
28 |
} |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
29 |
|
76729 | 30 |
def apply( |
31 |
options: Options, |
|
76657 | 32 |
session_background: Sessions.Background, |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
33 |
session_heaps: List[Path], |
71639
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
34 |
use_prelude: List[String] = Nil, |
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
35 |
eval_main: String = "", |
62544 | 36 |
args: List[String] = Nil, |
62556
c115e69f457f
more abstract Session.start, without prover command-line;
wenzelm
parents:
62548
diff
changeset
|
37 |
modes: List[String] = Nil, |
80224
db92e0b6a11a
clarified signature: prefer symbolic isabelle.Path over physical java.io.File;
wenzelm
parents:
80124
diff
changeset
|
38 |
cwd: Path = Path.current, |
73897 | 39 |
env: JMap[String, String] = Isabelle_System.settings(), |
62557 | 40 |
redirect: Boolean = false, |
76655 | 41 |
cleanup: () => Unit = () => () |
75393 | 42 |
): Bash.Process = { |
79656
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
43 |
val ml_options = options.standard_ml() |
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
44 |
|
62637
0189fe0f6452
support for Poly/ML heap hierarchy, which saves a lot of disk space;
wenzelm
parents:
62634
diff
changeset
|
45 |
val eval_init = |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
46 |
if (session_heaps.isEmpty) { |
62544 | 47 |
List( |
62912 | 48 |
""" |
49 |
fun chapter (_: string) = (); |
|
50 |
fun section (_: string) = (); |
|
51 |
fun subsection (_: string) = (); |
|
52 |
fun subsubsection (_: string) = (); |
|
53 |
fun paragraph (_: string) = (); |
|
54 |
fun subparagraph (_: string) = (); |
|
55 |
val ML_file = PolyML.use; |
|
56 |
""", |
|
62544 | 57 |
if (Platform.is_windows) |
58 |
"fun exit 0 = OS.Process.exit OS.Process.success" + |
|
59 |
" | exit 1 = OS.Process.exit OS.Process.failure" + |
|
60 |
" | exit rc = OS.Process.exit (RunCall.unsafeCast (Word8.fromInt rc))" |
|
62560 | 61 |
else |
62 |
"fun exit rc = Posix.Process.exit (Word8.fromInt rc)", |
|
62629
1815513a57f1
clarified prompt: "ML" usually means Isabelle/ML;
wenzelm
parents:
62614
diff
changeset
|
63 |
"PolyML.Compiler.prompt1 := \"Poly/ML> \"", |
1815513a57f1
clarified prompt: "ML" usually means Isabelle/ML;
wenzelm
parents:
62614
diff
changeset
|
64 |
"PolyML.Compiler.prompt2 := \"Poly/ML# \"") |
62544 | 65 |
} |
77413 | 66 |
else { |
62637
0189fe0f6452
support for Poly/ML heap hierarchy, which saves a lot of disk space;
wenzelm
parents:
62634
diff
changeset
|
67 |
List( |
0189fe0f6452
support for Poly/ML heap hierarchy, which saves a lot of disk space;
wenzelm
parents:
62634
diff
changeset
|
68 |
"(PolyML.SaveState.loadHierarchy " + |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
69 |
ML_Syntax.print_list( |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
70 |
ML_Syntax.print_string_bytes)(session_heaps.map(File.platform_path)) + |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
71 |
"; PolyML.print_depth 0)") |
77413 | 72 |
} |
62544 | 73 |
|
74 |
val eval_modes = |
|
75 |
if (modes.isEmpty) Nil |
|
66782 | 76 |
else List("Print_Mode.add_modes " + ML_Syntax.print_list(ML_Syntax.print_string_bytes)(modes)) |
62544 | 77 |
|
73897 | 78 |
|
62544 | 79 |
// options |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
80 |
val eval_options = if (session_heaps.isEmpty) Nil else List("Options.load_default ()") |
62544 | 81 |
val isabelle_process_options = Isabelle_System.tmp_file("options") |
78161 | 82 |
File.restrict(File.path(isabelle_process_options)) |
79656
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
83 |
File.write(isabelle_process_options, YXML.string_of_body(ml_options.encode)) |
62544 | 84 |
|
76655 | 85 |
// session resources |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
86 |
val eval_init_session = if (session_heaps.isEmpty) Nil else List("Resources.init_session_env ()") |
72637 | 87 |
val init_session = Isabelle_System.tmp_file("init_session") |
78161 | 88 |
File.restrict(File.path(init_session)) |
80462
7a1f9e571046
clarified signature: more explicit XML.Body types, more uniform Symbol.encode_yxml;
wenzelm
parents:
80225
diff
changeset
|
89 |
File.write(init_session, YXML.string_of_body(new Resources(session_background).init_session_xml)) |
65431
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
wenzelm
parents:
65420
diff
changeset
|
90 |
|
4a3e6cda3b94
provide session base for "isabelle build" and "isabelle console" ML process;
wenzelm
parents:
65420
diff
changeset
|
91 |
// process |
62544 | 92 |
val eval_process = |
71639
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
93 |
proper_string(eval_main).getOrElse( |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
94 |
if (session_heaps.isEmpty) { |
79656
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
95 |
"PolyML.print_depth " + ML_Syntax.print_int(ml_options.int("ML_print_depth")) |
71639
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
96 |
} |
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
97 |
else "Isabelle_Process.init ()") |
62544 | 98 |
|
62601
a937889f0086
create ISABELLE_TMP in Scala (despite odd/obsolete chmod in d84b4d39bce1);
wenzelm
parents:
62600
diff
changeset
|
99 |
// ISABELLE_TMP |
a937889f0086
create ISABELLE_TMP in Scala (despite odd/obsolete chmod in d84b4d39bce1);
wenzelm
parents:
62600
diff
changeset
|
100 |
val isabelle_tmp = Isabelle_System.tmp_dir("process") |
71881 | 101 |
|
75393 | 102 |
val ml_runtime_options = { |
79654 | 103 |
val ml_options0 = Word.explode(Isabelle_System.getenv("ML_OPTIONS")) |
69702 | 104 |
val ml_options1 = |
79654 | 105 |
if (ml_options0.exists(_.containsSlice("gcthreads"))) ml_options0 |
79656
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
106 |
else ml_options0 ::: List("--gcthreads", ml_options.threads().toString) |
69702 | 107 |
val ml_options2 = |
79654 | 108 |
if (!Platform.is_windows || ml_options0.exists(_.containsSlice("codepage"))) ml_options1 |
69702 | 109 |
else ml_options1 ::: List("--codepage", "utf8") |
72112
3546dd4ade74
ML statistics via external process: allows monitoring RTS while ML program sleeps;
wenzelm
parents:
71881
diff
changeset
|
110 |
ml_options2 ::: List("--exportstats") |
64274 | 111 |
} |
112 |
||
62545
8ebffdaf2ce2
Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents:
62544
diff
changeset
|
113 |
// bash |
8ebffdaf2ce2
Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents:
62544
diff
changeset
|
114 |
val bash_args = |
64274 | 115 |
ml_runtime_options ::: |
72637 | 116 |
(eval_init ::: eval_modes ::: eval_options ::: eval_init_session).flatMap(List("--eval", _)) ::: |
71639
ec84f542e411
clarified signature of ML_Process vs. Isabelle_Process: proper support for "isabelle build -P -b";
wenzelm
parents:
71598
diff
changeset
|
117 |
use_prelude.flatMap(List("--use", _)) ::: List("--eval", eval_process) ::: args |
62546 | 118 |
|
73897 | 119 |
val bash_env = new HashMap(env) |
120 |
bash_env.put("ISABELLE_PROCESS_OPTIONS", File.standard_path(isabelle_process_options)) |
|
75590
99b7638d9177
clarified session resources for bootstrap, notably for Scala functions;
wenzelm
parents:
75394
diff
changeset
|
121 |
bash_env.put("ISABELLE_INIT_SESSION", File.standard_path(init_session)) |
73897 | 122 |
bash_env.put("ISABELLE_TMP", File.standard_path(isabelle_tmp)) |
123 |
bash_env.put("POLYSTATSDIR", isabelle_tmp.getAbsolutePath) |
|
124 |
||
79656
10e560f2f580
more robust default: Scala imposes explicit "threads" value on ML, both the Poly/ML RTS and Isabelle/ML;
wenzelm
parents:
79654
diff
changeset
|
125 |
val process_policy = ml_options.string("process_policy") |
77480 | 126 |
val process_prefix = if_proper(process_policy, process_policy + " ") |
77320 | 127 |
|
77482 | 128 |
Bash.process(process_prefix + "\"$POLYML_EXE\" -q " + Bash.strings(bash_args), |
62614 | 129 |
cwd = cwd, |
73897 | 130 |
env = bash_env, |
62614 | 131 |
redirect = redirect, |
75394 | 132 |
cleanup = { () => |
133 |
isabelle_process_options.delete |
|
134 |
init_session.delete |
|
135 |
Isabelle_System.rm_tree(isabelle_tmp) |
|
136 |
cleanup() |
|
137 |
}) |
|
62544 | 138 |
} |
62586 | 139 |
|
140 |
||
62835
1a9ce1b13b20
prefer internal tool -- assuming that ISABELLE_TMP_PREFIX is created properly by Isabelle_System.isabelle_tmp_prefix;
wenzelm
parents:
62712
diff
changeset
|
141 |
/* Isabelle tool wrapper */ |
62586 | 142 |
|
72763 | 143 |
val isabelle_tool = Isabelle_Tool("process", "raw ML process (batch mode)", |
75394 | 144 |
Scala_Project.here, |
145 |
{ args => |
|
146 |
var dirs: List[Path] = Nil |
|
147 |
var eval_args: List[String] = Nil |
|
148 |
var logic = Isabelle_System.getenv("ISABELLE_LOGIC") |
|
149 |
var modes: List[String] = Nil |
|
150 |
var options = Options.init() |
|
62586 | 151 |
|
75394 | 152 |
val getopts = Getopts(""" |
62634
aa3b47b32100
less physical "logic" argument, with option -l like "isabelle console" etc.;
wenzelm
parents:
62633
diff
changeset
|
153 |
Usage: isabelle process [OPTIONS] |
62586 | 154 |
|
155 |
Options are: |
|
62677 | 156 |
-T THEORY load theory |
62639 | 157 |
-d DIR include session directory |
62586 | 158 |
-e ML_EXPR evaluate ML expression on startup |
159 |
-f ML_FILE evaluate ML file on startup |
|
62634
aa3b47b32100
less physical "logic" argument, with option -l like "isabelle console" etc.;
wenzelm
parents:
62633
diff
changeset
|
160 |
-l NAME logic session name (default ISABELLE_LOGIC=""" + quote(logic) + """) |
62586 | 161 |
-m MODE add print mode for output |
162 |
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
|
163 |
||
62634
aa3b47b32100
less physical "logic" argument, with option -l like "isabelle console" etc.;
wenzelm
parents:
62633
diff
changeset
|
164 |
Run the raw Isabelle ML process in batch mode. |
62586 | 165 |
""", |
75394 | 166 |
"T:" -> (arg => |
167 |
eval_args = eval_args ::: List("--eval", "use_thy " + ML_Syntax.print_string_bytes(arg))), |
|
168 |
"d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))), |
|
169 |
"e:" -> (arg => eval_args = eval_args ::: List("--eval", arg)), |
|
170 |
"f:" -> (arg => eval_args = eval_args ::: List("--use", arg)), |
|
171 |
"l:" -> (arg => logic = arg), |
|
172 |
"m:" -> (arg => modes = arg :: modes), |
|
173 |
"o:" -> (arg => options = options + arg)) |
|
62586 | 174 |
|
75394 | 175 |
val more_args = getopts(args) |
176 |
if (args.isEmpty || more_args.nonEmpty) getopts.usage() |
|
62586 | 177 |
|
78178 | 178 |
val store = Store(options) |
76657 | 179 |
val session_background = Sessions.background(options, logic, dirs = dirs).check_errors |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
180 |
val session_heaps = ML_Process.session_heaps(store, session_background, logic = logic) |
75394 | 181 |
val result = |
77414
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
182 |
ML_Process(options, session_background, session_heaps, args = eval_args, modes = modes) |
0d5994eef9e6
clarified signature: allow to provide session_heaps by different means, e.g. from tmp directory or alternative session structure;
wenzelm
parents:
77413
diff
changeset
|
183 |
.result( |
75394 | 184 |
progress_stdout = Output.writeln(_, stdout = true), |
185 |
progress_stderr = Output.writeln(_)) |
|
72557 | 186 |
|
75394 | 187 |
sys.exit(result.rc) |
188 |
}) |
|
62544 | 189 |
} |