@tishlang/tish-format 1.0.12 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/Cargo.toml +49 -0
  2. package/LICENSE +13 -0
  3. package/README.md +138 -0
  4. package/bin/tish-format +0 -0
  5. package/crates/js_to_tish/Cargo.toml +11 -0
  6. package/crates/js_to_tish/README.md +18 -0
  7. package/crates/js_to_tish/src/error.rs +55 -0
  8. package/crates/js_to_tish/src/lib.rs +11 -0
  9. package/crates/js_to_tish/src/span_util.rs +35 -0
  10. package/crates/js_to_tish/src/transform/expr.rs +610 -0
  11. package/crates/js_to_tish/src/transform/stmt.rs +503 -0
  12. package/crates/js_to_tish/src/transform.rs +60 -0
  13. package/crates/tish/Cargo.toml +54 -0
  14. package/crates/tish/src/cargo_native_registry.rs +32 -0
  15. package/crates/tish/src/cli_help.rs +565 -0
  16. package/crates/tish/src/main.rs +781 -0
  17. package/crates/tish/src/repl_completion.rs +200 -0
  18. package/crates/tish/tests/cargo_example_compile.rs +67 -0
  19. package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
  20. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
  21. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
  22. package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
  23. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
  24. package/crates/tish/tests/integration_test.rs +1095 -0
  25. package/crates/tish/tests/run_optimize_stdout_parity.rs +50 -0
  26. package/crates/tish/tests/shortcircuit.rs +65 -0
  27. package/crates/tish_ast/Cargo.toml +9 -0
  28. package/crates/tish_ast/src/ast.rs +620 -0
  29. package/crates/tish_ast/src/lib.rs +5 -0
  30. package/crates/tish_build_utils/Cargo.toml +11 -0
  31. package/crates/tish_build_utils/src/lib.rs +577 -0
  32. package/crates/tish_builtins/Cargo.toml +20 -0
  33. package/crates/tish_builtins/src/array.rs +441 -0
  34. package/crates/tish_builtins/src/construct.rs +159 -0
  35. package/crates/tish_builtins/src/globals.rs +213 -0
  36. package/crates/tish_builtins/src/helpers.rs +35 -0
  37. package/crates/tish_builtins/src/lib.rs +16 -0
  38. package/crates/tish_builtins/src/math.rs +89 -0
  39. package/crates/tish_builtins/src/object.rs +36 -0
  40. package/crates/tish_builtins/src/string.rs +647 -0
  41. package/crates/tish_builtins/src/symbol.rs +83 -0
  42. package/crates/tish_bytecode/Cargo.toml +17 -0
  43. package/crates/tish_bytecode/src/chunk.rs +96 -0
  44. package/crates/tish_bytecode/src/compiler.rs +1760 -0
  45. package/crates/tish_bytecode/src/encoding.rs +100 -0
  46. package/crates/tish_bytecode/src/lib.rs +19 -0
  47. package/crates/tish_bytecode/src/opcode.rs +142 -0
  48. package/crates/tish_bytecode/src/peephole.rs +189 -0
  49. package/crates/tish_bytecode/src/serialize.rs +163 -0
  50. package/crates/tish_bytecode/tests/break_continue_bytecode.rs +44 -0
  51. package/crates/tish_bytecode/tests/constant_folding.rs +84 -0
  52. package/crates/tish_bytecode/tests/sort_optimization.rs +31 -0
  53. package/crates/tish_compile/Cargo.toml +26 -0
  54. package/crates/tish_compile/src/codegen.rs +5332 -0
  55. package/crates/tish_compile/src/infer.rs +292 -0
  56. package/crates/tish_compile/src/lib.rs +164 -0
  57. package/crates/tish_compile/src/resolve.rs +1388 -0
  58. package/crates/tish_compile/src/types.rs +501 -0
  59. package/crates/tish_compile_js/Cargo.toml +18 -0
  60. package/crates/tish_compile_js/examples/jsx_vdom_smoke.tish +8 -0
  61. package/crates/tish_compile_js/src/codegen.rs +871 -0
  62. package/crates/tish_compile_js/src/error.rs +20 -0
  63. package/crates/tish_compile_js/src/lib.rs +26 -0
  64. package/crates/tish_compile_js/src/tests_jsx.rs +350 -0
  65. package/crates/tish_compiler_wasm/Cargo.toml +21 -0
  66. package/crates/tish_compiler_wasm/src/lib.rs +57 -0
  67. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +473 -0
  68. package/crates/tish_core/Cargo.toml +26 -0
  69. package/crates/tish_core/src/console_style.rs +160 -0
  70. package/crates/tish_core/src/json.rs +387 -0
  71. package/crates/tish_core/src/lib.rs +17 -0
  72. package/crates/tish_core/src/macros.rs +36 -0
  73. package/crates/tish_core/src/uri.rs +118 -0
  74. package/crates/tish_core/src/value.rs +696 -0
  75. package/crates/tish_core/src/vmref.rs +178 -0
  76. package/crates/tish_cranelift/Cargo.toml +19 -0
  77. package/crates/tish_cranelift/src/lib.rs +43 -0
  78. package/crates/tish_cranelift/src/link.rs +117 -0
  79. package/crates/tish_cranelift/src/lower.rs +85 -0
  80. package/crates/tish_cranelift_runtime/Cargo.toml +25 -0
  81. package/crates/tish_cranelift_runtime/src/lib.rs +45 -0
  82. package/crates/tish_eval/Cargo.toml +45 -0
  83. package/crates/tish_eval/src/eval.rs +3717 -0
  84. package/crates/tish_eval/src/http.rs +188 -0
  85. package/crates/tish_eval/src/lib.rs +99 -0
  86. package/crates/tish_eval/src/natives.rs +399 -0
  87. package/crates/tish_eval/src/promise.rs +179 -0
  88. package/crates/tish_eval/src/regex.rs +299 -0
  89. package/crates/tish_eval/src/timers.rs +120 -0
  90. package/crates/tish_eval/src/value.rs +318 -0
  91. package/crates/tish_eval/src/value_convert.rs +111 -0
  92. package/crates/tish_fmt/Cargo.toml +16 -0
  93. package/crates/tish_fmt/src/bin/tish-fmt.rs +41 -0
  94. package/crates/tish_fmt/src/lib.rs +2101 -0
  95. package/crates/tish_jsx_web/Cargo.toml +9 -0
  96. package/crates/tish_jsx_web/README.md +5 -0
  97. package/crates/tish_jsx_web/src/lib.rs +2 -0
  98. package/crates/tish_lexer/Cargo.toml +9 -0
  99. package/crates/tish_lexer/src/lib.rs +716 -0
  100. package/crates/tish_lexer/src/token.rs +163 -0
  101. package/crates/tish_lint/Cargo.toml +18 -0
  102. package/crates/tish_lint/src/bin/tish-lint.rs +195 -0
  103. package/crates/tish_lint/src/lib.rs +289 -0
  104. package/crates/tish_llvm/Cargo.toml +13 -0
  105. package/crates/tish_llvm/src/lib.rs +115 -0
  106. package/crates/tish_lsp/Cargo.toml +25 -0
  107. package/crates/tish_lsp/README.md +26 -0
  108. package/crates/tish_lsp/src/builtin_goto.rs +362 -0
  109. package/crates/tish_lsp/src/import_goto.rs +562 -0
  110. package/crates/tish_lsp/src/main.rs +1046 -0
  111. package/crates/tish_native/Cargo.toml +16 -0
  112. package/crates/tish_native/src/build.rs +427 -0
  113. package/crates/tish_native/src/config.rs +48 -0
  114. package/crates/tish_native/src/lib.rs +416 -0
  115. package/crates/tish_opt/Cargo.toml +13 -0
  116. package/crates/tish_opt/src/lib.rs +943 -0
  117. package/crates/tish_parser/Cargo.toml +11 -0
  118. package/crates/tish_parser/src/lib.rs +332 -0
  119. package/crates/tish_parser/src/parser.rs +2304 -0
  120. package/crates/tish_pg/Cargo.toml +34 -0
  121. package/crates/tish_pg/README.md +38 -0
  122. package/crates/tish_pg/src/error.rs +52 -0
  123. package/crates/tish_pg/src/lib.rs +955 -0
  124. package/crates/tish_resolve/Cargo.toml +13 -0
  125. package/crates/tish_resolve/src/lib.rs +3561 -0
  126. package/crates/tish_resolve/src/pos.rs +141 -0
  127. package/crates/tish_runtime/Cargo.toml +96 -0
  128. package/crates/tish_runtime/src/http.rs +1298 -0
  129. package/crates/tish_runtime/src/http_fetch.rs +471 -0
  130. package/crates/tish_runtime/src/http_hyper.rs +418 -0
  131. package/crates/tish_runtime/src/http_prefork.rs +189 -0
  132. package/crates/tish_runtime/src/lib.rs +1192 -0
  133. package/crates/tish_runtime/src/native_promise.rs +15 -0
  134. package/crates/tish_runtime/src/promise.rs +248 -0
  135. package/crates/tish_runtime/src/promise_io.rs +38 -0
  136. package/crates/tish_runtime/src/timers.rs +166 -0
  137. package/crates/tish_runtime/src/ws.rs +761 -0
  138. package/crates/tish_runtime/tests/fetch_readable_stream.rs +102 -0
  139. package/crates/tish_ui/Cargo.toml +17 -0
  140. package/crates/tish_ui/src/jsx.rs +682 -0
  141. package/crates/tish_ui/src/lib.rs +20 -0
  142. package/crates/tish_ui/src/runtime/hooks.rs +569 -0
  143. package/crates/tish_ui/src/runtime/mod.rs +180 -0
  144. package/crates/tish_vm/Cargo.toml +47 -0
  145. package/crates/tish_vm/src/lib.rs +39 -0
  146. package/crates/tish_vm/src/vm.rs +2192 -0
  147. package/crates/tish_vm/tests/fixtures/or_string_cmd.tish +2 -0
  148. package/crates/tish_vm/tests/lexical_scope_declare.rs +34 -0
  149. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +150 -0
  150. package/crates/tish_wasm/Cargo.toml +15 -0
  151. package/crates/tish_wasm/src/lib.rs +424 -0
  152. package/crates/tish_wasm_runtime/Cargo.toml +37 -0
  153. package/crates/tish_wasm_runtime/src/gpu.rs +413 -0
  154. package/crates/tish_wasm_runtime/src/lib.rs +42 -0
  155. package/crates/tishlang_cargo_bindgen/Cargo.toml +26 -0
  156. package/crates/tishlang_cargo_bindgen/src/classify.rs +263 -0
  157. package/crates/tishlang_cargo_bindgen/src/discover.rs +125 -0
  158. package/crates/tishlang_cargo_bindgen/src/infer.rs +382 -0
  159. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  160. package/crates/tishlang_cargo_bindgen/src/main.rs +167 -0
  161. package/crates/tishlang_cargo_bindgen/src/metadata.rs +117 -0
  162. package/justfile +268 -0
  163. package/package.json +1 -1
  164. package/platform/darwin-arm64/tish-fmt +0 -0
@@ -0,0 +1,416 @@
1
+ //! Native code generation backend for Tish.
2
+ //!
3
+ //! - **`rust`:** `tishlang_compile` emits Rust calling **`tishlang_runtime`** (`Value`, etc.),
4
+ //! then `cargo build --release` links the user binary.
5
+ //! - **`cranelift`:** Embeds serialized bytecode in an object file and links **`tishlang_cranelift_runtime`**
6
+ //! — the executable runs **`tishlang_vm`** on that chunk (same as `tish run --backend vm`), not CLIF lowering.
7
+ //! - **`llvm`:** Same embedded-bytecode + VM link path via `tishlang_llvm` / shared linker.
8
+ //!
9
+ //! **Future:** Lower bytecode (or typed IR) through Cranelift/LLVM to real machine code where semantics allow;
10
+ //! emit Rust using `Vec<f64>` / fixed primitives instead of `Value` on hot paths.
11
+
12
+ mod build;
13
+ mod config;
14
+
15
+ pub use config::{ios_runtime_features, NativeArtifact, NativeBuildConfig};
16
+
17
+ use std::path::Path;
18
+ use tishlang_ast::Program;
19
+
20
+ /// Features for the embeddable VM (`cranelift` / `llvm` backends): merge CLI capability flags
21
+ /// (same set as `tish run` / `tish build --target native`) with features inferred from
22
+ /// `import … from 'tish:…'`. Programs that use globals only (`Promise`, `fetch`, `setTimeout`)
23
+ /// still need the former so [`tishlang_cranelift_runtime`] links `tishlang_vm` with matching gates.
24
+ fn merged_embed_runtime_features(cli: &[String], program: &Program) -> Vec<String> {
25
+ let mut out = cli.to_vec();
26
+ for f in tishlang_compile::extract_native_import_features(program) {
27
+ if !out.contains(&f) {
28
+ out.push(f);
29
+ }
30
+ }
31
+ out.sort();
32
+ out.dedup();
33
+ out
34
+ }
35
+
36
+ /// Error from native compilation.
37
+ #[derive(Debug)]
38
+ pub struct NativeError {
39
+ pub message: String,
40
+ }
41
+
42
+ impl std::fmt::Display for NativeError {
43
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44
+ write!(f, "{}", self.message)
45
+ }
46
+ }
47
+
48
+ impl std::error::Error for NativeError {}
49
+
50
+ /// Compile a Tish project to a native binary.
51
+ ///
52
+ /// - `native_backend == "rust"`: Rust source + `tishlang_runtime` + cargo (native imports).
53
+ /// - `native_backend == "cranelift"`: Embedded bytecode + VM binary (pure Tish only); not opcode AOT yet.
54
+ /// - `native_backend == "llvm"`: Embedded bytecode + VM via LLVM/clang link path.
55
+ pub fn compile_to_native(
56
+ entry_path: &Path,
57
+ project_root: Option<&Path>,
58
+ output_path: &Path,
59
+ features: &[String],
60
+ native_backend: &str,
61
+ optimize: bool,
62
+ ) -> Result<(), NativeError> {
63
+ compile_to_native_with_config(
64
+ entry_path,
65
+ project_root,
66
+ output_path,
67
+ features,
68
+ native_backend,
69
+ optimize,
70
+ &NativeBuildConfig::desktop(),
71
+ )
72
+ }
73
+
74
+ /// Compile a Tish project to a native binary or static library.
75
+ pub fn compile_to_native_with_config(
76
+ entry_path: &Path,
77
+ project_root: Option<&Path>,
78
+ output_path: &Path,
79
+ features: &[String],
80
+ native_backend: &str,
81
+ optimize: bool,
82
+ build_config: &NativeBuildConfig,
83
+ ) -> Result<(), NativeError> {
84
+ let backend = match native_backend {
85
+ "rust" => Backend::Rust,
86
+ "cranelift" => Backend::Cranelift,
87
+ "llvm" => Backend::Llvm,
88
+ _ => {
89
+ return Err(NativeError {
90
+ message: format!(
91
+ "Invalid native backend '{}'. Use 'rust', 'cranelift', or 'llvm'.",
92
+ native_backend
93
+ ),
94
+ });
95
+ }
96
+ };
97
+
98
+ match backend {
99
+ Backend::Rust => {
100
+ let ios_cap = build_config.cargo_target.as_ref().map(|_| {
101
+ ios_runtime_features(features)
102
+ .into_iter()
103
+ .collect::<std::collections::HashSet<_>>()
104
+ });
105
+ let compile_features = if ios_cap.is_some() {
106
+ ios_runtime_features(features)
107
+ } else {
108
+ features.to_vec()
109
+ };
110
+ let (rust_code, native_modules, effective_features, native_build) =
111
+ tishlang_compile::compile_project_full_emit(
112
+ entry_path,
113
+ project_root,
114
+ &compile_features,
115
+ optimize,
116
+ build_config.emit_mode,
117
+ ios_cap.as_ref(),
118
+ )
119
+ .map_err(|e| NativeError {
120
+ message: e.to_string(),
121
+ })?;
122
+
123
+ let features_for_cargo = if build_config.cargo_target.is_some() {
124
+ ios_runtime_features(&effective_features)
125
+ } else {
126
+ effective_features
127
+ };
128
+
129
+ crate::build::build_via_cargo_with_config(
130
+ &rust_code,
131
+ native_modules,
132
+ output_path,
133
+ &features_for_cargo,
134
+ &native_build.rust_dependencies_toml,
135
+ native_build.generated_native_rs.as_deref(),
136
+ project_root,
137
+ build_config,
138
+ )
139
+ .map_err(|e| NativeError { message: e })
140
+ }
141
+ Backend::Cranelift => {
142
+ let modules =
143
+ tishlang_compile::resolve_project(entry_path, project_root).map_err(|e| {
144
+ NativeError {
145
+ message: e.to_string(),
146
+ }
147
+ })?;
148
+ tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError {
149
+ message: e.to_string(),
150
+ })?;
151
+ let program = {
152
+ let prog = tishlang_compile::merge_modules(modules)
153
+ .map(|m| m.program)
154
+ .map_err(|e| NativeError {
155
+ message: e.to_string(),
156
+ })?;
157
+ if optimize {
158
+ tishlang_opt::optimize(&prog)
159
+ } else {
160
+ prog
161
+ }
162
+ };
163
+
164
+ if tishlang_compile::has_external_native_imports(&program) {
165
+ return Err(NativeError {
166
+ message: "Cranelift backend does not support external native imports (tish:…, cargo:…, @scope/pkg). Built-in tish:fs, tish:http, tish:process are supported. Use --native-backend rust for external modules.".to_string(),
167
+ });
168
+ }
169
+
170
+ let chunk = if optimize {
171
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
172
+ message: e.to_string(),
173
+ })?
174
+ } else {
175
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
176
+ message: e.to_string(),
177
+ })?
178
+ };
179
+
180
+ let cranelift_features = merged_embed_runtime_features(features, &program);
181
+ tishlang_cranelift::compile_chunk_to_native(&chunk, output_path, &cranelift_features)
182
+ .map_err(|e| NativeError {
183
+ message: e.to_string(),
184
+ })
185
+ }
186
+ Backend::Llvm => {
187
+ let modules =
188
+ tishlang_compile::resolve_project(entry_path, project_root).map_err(|e| {
189
+ NativeError {
190
+ message: e.to_string(),
191
+ }
192
+ })?;
193
+ tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError {
194
+ message: e.to_string(),
195
+ })?;
196
+ let program = {
197
+ let prog = tishlang_compile::merge_modules(modules)
198
+ .map(|m| m.program)
199
+ .map_err(|e| NativeError {
200
+ message: e.to_string(),
201
+ })?;
202
+ if optimize {
203
+ tishlang_opt::optimize(&prog)
204
+ } else {
205
+ prog
206
+ }
207
+ };
208
+ if tishlang_compile::has_external_native_imports(&program) {
209
+ return Err(NativeError {
210
+ message: "LLVM backend does not support external native imports (tish:…, cargo:…, @scope/pkg). Built-in tish:fs, tish:http, tish:process are supported.".to_string(),
211
+ });
212
+ }
213
+ let chunk = if optimize {
214
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
215
+ message: e.to_string(),
216
+ })?
217
+ } else {
218
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
219
+ message: e.to_string(),
220
+ })?
221
+ };
222
+ let llvm_features = merged_embed_runtime_features(features, &program);
223
+ tishlang_llvm::compile_chunk_to_native(&chunk, output_path, &llvm_features)
224
+ .map_err(|e| NativeError { message: e.message })
225
+ }
226
+ }
227
+ }
228
+
229
+ /// Compile a single Program (e.g. from tishlang_js_to_tish) to native.
230
+ pub fn compile_program_to_native(
231
+ program: &Program,
232
+ project_root: Option<&Path>,
233
+ output_path: &Path,
234
+ features: &[String],
235
+ native_backend: &str,
236
+ optimize: bool,
237
+ ) -> Result<(), NativeError> {
238
+ let backend = match native_backend {
239
+ "rust" => Backend::Rust,
240
+ "cranelift" => Backend::Cranelift,
241
+ "llvm" => Backend::Llvm,
242
+ _ => {
243
+ return Err(NativeError {
244
+ message: format!(
245
+ "Invalid native backend '{}'. Use 'rust', 'cranelift', or 'llvm'.",
246
+ native_backend
247
+ ),
248
+ });
249
+ }
250
+ };
251
+
252
+ match backend {
253
+ Backend::Rust => {
254
+ let program = if optimize {
255
+ tishlang_opt::optimize(program)
256
+ } else {
257
+ program.clone()
258
+ };
259
+ let root = project_root.unwrap_or_else(|| Path::new("."));
260
+ let native_modules = tishlang_compile::resolve_native_modules(&program, root)
261
+ .map_err(|e| NativeError { message: e })?;
262
+ let native_build =
263
+ tishlang_compile::compute_native_build_artifacts(&program, root, &native_modules)
264
+ .map_err(|e| NativeError { message: e })?;
265
+ let mut all_features = features.to_vec();
266
+ for f in tishlang_compile::extract_native_import_features(&program) {
267
+ if !all_features.contains(&f) {
268
+ all_features.push(f);
269
+ }
270
+ }
271
+ let rust_code = tishlang_compile::compile_with_native_modules(
272
+ &program,
273
+ project_root,
274
+ &all_features,
275
+ &native_modules,
276
+ &native_build.native_init,
277
+ optimize,
278
+ )
279
+ .map_err(|e| NativeError { message: e.message })?;
280
+ crate::build::build_via_cargo(
281
+ &rust_code,
282
+ native_modules,
283
+ output_path,
284
+ &all_features,
285
+ &native_build.rust_dependencies_toml,
286
+ native_build.generated_native_rs.as_deref(),
287
+ Some(root),
288
+ )
289
+ .map_err(|e| NativeError { message: e })
290
+ }
291
+ Backend::Cranelift => {
292
+ if tishlang_compile::has_external_native_imports(program) {
293
+ return Err(NativeError {
294
+ message: "Cranelift backend does not support external native imports (tish:…, cargo:…, @scope/pkg). Built-in tish:fs, tish:http, tish:process are supported.".to_string(),
295
+ });
296
+ }
297
+ let program = if optimize {
298
+ tishlang_opt::optimize(program)
299
+ } else {
300
+ program.clone()
301
+ };
302
+ let chunk = if optimize {
303
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
304
+ message: e.to_string(),
305
+ })?
306
+ } else {
307
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
308
+ message: e.to_string(),
309
+ })?
310
+ };
311
+ let cranelift_features = merged_embed_runtime_features(features, &program);
312
+ tishlang_cranelift::compile_chunk_to_native(&chunk, output_path, &cranelift_features)
313
+ .map_err(|e| NativeError {
314
+ message: e.to_string(),
315
+ })
316
+ }
317
+ Backend::Llvm => {
318
+ if tishlang_compile::has_external_native_imports(program) {
319
+ return Err(NativeError {
320
+ message: "LLVM backend does not support external native imports (tish:…, cargo:…, @scope/pkg).".to_string(),
321
+ });
322
+ }
323
+ let program = if optimize {
324
+ tishlang_opt::optimize(program)
325
+ } else {
326
+ program.clone()
327
+ };
328
+ let chunk = if optimize {
329
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
330
+ message: e.to_string(),
331
+ })?
332
+ } else {
333
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
334
+ message: e.to_string(),
335
+ })?
336
+ };
337
+ let llvm_features = merged_embed_runtime_features(features, &program);
338
+ tishlang_llvm::compile_chunk_to_native(&chunk, output_path, &llvm_features)
339
+ .map_err(|e| NativeError { message: e.message })
340
+ }
341
+ }
342
+ }
343
+
344
+ /// Compile multiple entry `.tish` files to native binaries in **one** nested Cargo build.
345
+ ///
346
+ /// Intended for integration tests and batch tooling; keeps production [`compile_to_native`] behavior
347
+ /// unchanged when `TISH_FAST_NATIVE_BUILD` is unset.
348
+ pub fn compile_many_to_native(
349
+ entries: &[(&Path, &Path)],
350
+ project_root: Option<&Path>,
351
+ features: &[String],
352
+ optimize: bool,
353
+ ) -> Result<(), NativeError> {
354
+ let mut bins: Vec<(String, String, Option<String>)> = Vec::with_capacity(entries.len());
355
+ let mut merged_native_modules: Vec<tishlang_compile::ResolvedNativeModule> = Vec::new();
356
+ let mut merged_features: Vec<String> = features.to_vec();
357
+ let mut merged_extra_deps = String::new();
358
+ let mut needs_tokio = false;
359
+ let mut needs_ui = false;
360
+
361
+ for (entry_path, _) in entries {
362
+ let (rust_code, native_modules, effective_features, native_build) =
363
+ tishlang_compile::compile_project_full(entry_path, project_root, features, optimize)
364
+ .map_err(|e| NativeError {
365
+ message: e.to_string(),
366
+ })?;
367
+ let stem = entry_path
368
+ .file_stem()
369
+ .and_then(|s| s.to_str())
370
+ .ok_or_else(|| NativeError {
371
+ message: format!("invalid entry path: {}", entry_path.display()),
372
+ })?
373
+ .to_string();
374
+
375
+ for f in &effective_features {
376
+ if !merged_features.contains(f) {
377
+ merged_features.push(f.clone());
378
+ }
379
+ }
380
+ for m in native_modules {
381
+ let dup = merged_native_modules
382
+ .iter()
383
+ .any(|x| x.package_name == m.package_name && x.crate_path == m.crate_path);
384
+ if !dup {
385
+ merged_native_modules.push(m);
386
+ }
387
+ }
388
+ let extra = native_build.rust_dependencies_toml.trim();
389
+ if !extra.is_empty() {
390
+ merged_extra_deps.push_str(extra);
391
+ merged_extra_deps.push('\n');
392
+ }
393
+ needs_tokio |= crate::build::rust_code_needs_tokio(&rust_code);
394
+ needs_ui |= rust_code.contains("tishlang_ui");
395
+ bins.push((stem, rust_code, native_build.generated_native_rs));
396
+ }
397
+
398
+ let merged_extra = merged_extra_deps.trim();
399
+ crate::build::build_many_via_cargo(
400
+ bins,
401
+ merged_native_modules,
402
+ &merged_features,
403
+ merged_extra,
404
+ needs_tokio,
405
+ needs_ui,
406
+ entries,
407
+ project_root,
408
+ )
409
+ .map_err(|e| NativeError { message: e })
410
+ }
411
+
412
+ enum Backend {
413
+ Rust,
414
+ Cranelift,
415
+ Llvm,
416
+ }
@@ -0,0 +1,13 @@
1
+ [package]
2
+ name = "tishlang_opt"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ description = "AST optimization pass for Tish (constant folding, short-circuit, etc.)"
6
+
7
+ license-file = { workspace = true }
8
+ repository = { workspace = true }
9
+ [dependencies]
10
+ tishlang_ast = { path = "../tish_ast", version = ">=0.1" }
11
+
12
+ [dev-dependencies]
13
+ tishlang_parser = { path = "../tish_parser", version = ">=0.1" }