@tishlang/tish 2.2.5 → 2.8.0

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 (53) hide show
  1. package/bin/tish +0 -0
  2. package/crates/js_to_tish/src/transform/expr.rs +5 -1
  3. package/crates/tish/Cargo.toml +1 -1
  4. package/crates/tish/src/cli_help.rs +12 -0
  5. package/crates/tish/src/main.rs +69 -11
  6. package/crates/tish_ast/src/ast.rs +12 -5
  7. package/crates/tish_build_utils/src/lib.rs +37 -0
  8. package/crates/tish_builtins/src/array.rs +82 -1
  9. package/crates/tish_builtins/src/globals.rs +50 -16
  10. package/crates/tish_builtins/src/math.rs +63 -9
  11. package/crates/tish_builtins/src/number.rs +20 -1
  12. package/crates/tish_builtins/src/string.rs +68 -4
  13. package/crates/tish_builtins/src/typedarrays.rs +23 -16
  14. package/crates/tish_bytecode/src/compiler.rs +94 -28
  15. package/crates/tish_bytecode/tests/break_continue_bytecode.rs +19 -0
  16. package/crates/tish_compile/src/check.rs +11 -10
  17. package/crates/tish_compile/src/codegen.rs +1386 -42
  18. package/crates/tish_compile/src/infer.rs +16 -16
  19. package/crates/tish_compile/src/lib.rs +38 -0
  20. package/crates/tish_compile/src/resolve.rs +3 -2
  21. package/crates/tish_compile/src/types.rs +26 -9
  22. package/crates/tish_compile_js/src/codegen.rs +55 -4
  23. package/crates/tish_compile_js/src/tests_jsx.rs +44 -0
  24. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +1 -0
  25. package/crates/tish_core/Cargo.toml +2 -0
  26. package/crates/tish_core/src/json.rs +135 -34
  27. package/crates/tish_core/src/lib.rs +23 -1
  28. package/crates/tish_core/src/value.rs +64 -11
  29. package/crates/tish_eval/src/eval.rs +144 -197
  30. package/crates/tish_eval/src/natives.rs +45 -45
  31. package/crates/tish_eval/src/regex.rs +35 -27
  32. package/crates/tish_eval/src/value.rs +8 -0
  33. package/crates/tish_fmt/src/lib.rs +46 -2
  34. package/crates/tish_lint/src/bin/tish-lint.rs +17 -8
  35. package/crates/tish_lint/src/lib.rs +197 -21
  36. package/crates/tish_lsp/Cargo.toml +7 -1
  37. package/crates/tish_lsp/src/import_goto.rs +52 -7
  38. package/crates/tish_lsp/src/main.rs +913 -145
  39. package/crates/tish_opt/src/lib.rs +5 -3
  40. package/crates/tish_parser/src/lib.rs +23 -5
  41. package/crates/tish_parser/src/parser.rs +35 -35
  42. package/crates/tish_resolve/src/lib.rs +567 -17
  43. package/crates/tish_runtime/src/lib.rs +58 -18
  44. package/crates/tish_ui/src/jsx.rs +2 -2
  45. package/crates/tish_vm/src/jit.rs +212 -10
  46. package/crates/tish_vm/src/vm.rs +39 -18
  47. package/crates/tish_wasm/src/lib.rs +116 -22
  48. package/package.json +1 -1
  49. package/platform/darwin-arm64/tish +0 -0
  50. package/platform/darwin-x64/tish +0 -0
  51. package/platform/linux-arm64/tish +0 -0
  52. package/platform/linux-x64/tish +0 -0
  53. package/platform/win32-x64/tish.exe +0 -0
@@ -88,6 +88,7 @@ pub fn compile_program_to_wasm(
88
88
  program: &Program,
89
89
  output_path: &Path,
90
90
  optimize: bool,
91
+ gpu: bool,
91
92
  ) -> Result<(), WasmError> {
92
93
  let program = if optimize {
93
94
  tishlang_opt::optimize(program)
@@ -103,10 +104,87 @@ pub fn compile_program_to_wasm(
103
104
  message: e.to_string(),
104
105
  })?
105
106
  };
106
- emit_wasm_from_chunk(&chunk, output_path)
107
+ emit_wasm_from_chunk(&chunk, output_path, gpu)
107
108
  }
108
109
 
109
- fn emit_wasm_from_chunk(chunk: &Chunk, output_path: &Path) -> Result<(), WasmError> {
110
+ /// The HTML loader emitted next to the wasm + JS glue. `gpu = false` imports `run` and calls
111
+ /// `run(chunk)` (plain VM). `gpu = true` (#277) imports `start`, bootstraps WebGPU into a `host`
112
+ /// env object, and calls `start(chunk, host)`. The GPU loader is a working default — edit
113
+ /// `buildHost()` to add app assets, pick a specific canvas, or change the surface configuration.
114
+ fn loader_html(stem: &str, chunk_b64: &str, gpu: bool) -> String {
115
+ let js_name = format!("{}.js", stem);
116
+ if gpu {
117
+ format!(
118
+ r#"<!DOCTYPE html>
119
+ <html>
120
+ <head><meta charset="utf-8"><title>{title}</title><style>html,body{{margin:0;height:100%}}#tish-canvas{{width:100vw;height:100vh;display:block}}</style></head>
121
+ <body>
122
+ <canvas id="tish-canvas"></canvas>
123
+ <script type="module">
124
+ const CHUNK_B64 = "{chunk}";
125
+ const chunk = Uint8Array.from(atob(CHUNK_B64), c => c.charCodeAt(0));
126
+ import init, {{ start }} from './{js}';
127
+
128
+ // The `host` global your tish program reads. Customize freely.
129
+ async function buildHost() {{
130
+ if (!navigator.gpu) throw new Error("WebGPU not available (use a WebGPU-capable browser / context).");
131
+ const adapter = await navigator.gpu.requestAdapter();
132
+ if (!adapter) throw new Error("No WebGPU adapter.");
133
+ const device = await adapter.requestDevice();
134
+ const canvas = document.getElementById("tish-canvas");
135
+ const dpr = self.devicePixelRatio || 1;
136
+ canvas.width = Math.floor(canvas.clientWidth * dpr);
137
+ canvas.height = Math.floor(canvas.clientHeight * dpr);
138
+ const context = canvas.getContext("webgpu");
139
+ const format = navigator.gpu.getPreferredCanvasFormat();
140
+ context.configure({{ device, format, alphaMode: "opaque" }});
141
+ return {{ gpu: navigator.gpu, adapter, device, queue: device.queue, context, format, canvas, assets: {{}} }};
142
+ }}
143
+
144
+ try {{
145
+ const host = await buildHost();
146
+ await init();
147
+ start(chunk, host);
148
+ }} catch (e) {{
149
+ document.body.innerHTML = "<pre style='color:#c00;padding:1rem;font:14px monospace'>" + (e && e.message || e) + "</pre>";
150
+ throw e;
151
+ }}
152
+ </script>
153
+ </body>
154
+ </html>
155
+ "#,
156
+ title = stem,
157
+ chunk = chunk_b64,
158
+ js = js_name
159
+ )
160
+ } else {
161
+ format!(
162
+ r#"<!DOCTYPE html>
163
+ <html>
164
+ <head><meta charset="utf-8"><title>{}</title></head>
165
+ <body>
166
+ <script type="module">
167
+ const CHUNK_B64 = "{}";
168
+ const chunk = Uint8Array.from(atob(CHUNK_B64), c => c.charCodeAt(0));
169
+ import init, {{ run }} from './{}';
170
+ await init();
171
+ run(chunk);
172
+ </script>
173
+ </body>
174
+ </html>
175
+ "#,
176
+ stem, chunk_b64, js_name
177
+ )
178
+ }
179
+ }
180
+
181
+ /// Build the wasm runtime + emit the JS/HTML loader for a serialized `chunk`.
182
+ ///
183
+ /// `gpu = false` → `--features browser`, plain `run(chunk)` VM entry (the default `--target wasm`).
184
+ /// `gpu = true` → `--features gpu`, the reflection WebGPU bridge ([`tishlang_wasm_runtime`]'s
185
+ /// `gpu.rs`) and a `start(chunk, host)` entry; the emitted HTML bootstraps WebGPU (adapter/device/
186
+ /// canvas/context) into the `host` global the tish program reads. (#277, `--target wasm-gpu`.)
187
+ fn emit_wasm_from_chunk(chunk: &Chunk, output_path: &Path, gpu: bool) -> Result<(), WasmError> {
110
188
  let chunk_bytes = serialize(chunk);
111
189
  let chunk_b64 = BASE64.encode(&chunk_bytes);
112
190
  let stem = output_path
@@ -139,7 +217,7 @@ fn emit_wasm_from_chunk(chunk: &Chunk, output_path: &Path) -> Result<(), WasmErr
139
217
  "wasm32-unknown-unknown",
140
218
  "--release",
141
219
  "--features",
142
- "browser",
220
+ if gpu { "gpu" } else { "browser" },
143
221
  ])
144
222
  .status()
145
223
  .map_err(|e| WasmError {
@@ -182,24 +260,7 @@ fn emit_wasm_from_chunk(chunk: &Chunk, output_path: &Path) -> Result<(), WasmErr
182
260
  message: "wasm-bindgen failed".to_string(),
183
261
  });
184
262
  }
185
- let js_name = format!("{}.js", stem);
186
- let html = format!(
187
- r#"<!DOCTYPE html>
188
- <html>
189
- <head><meta charset="utf-8"><title>{}</title></head>
190
- <body>
191
- <script type="module">
192
- const CHUNK_B64 = "{}";
193
- const chunk = Uint8Array.from(atob(CHUNK_B64), c => c.charCodeAt(0));
194
- import init, {{ run }} from './{}';
195
- await init();
196
- run(chunk);
197
- </script>
198
- </body>
199
- </html>
200
- "#,
201
- stem, chunk_b64, js_name
202
- );
263
+ let html = loader_html(stem, &chunk_b64, gpu);
203
264
  let html_path = out_dir_abs.join(format!("{}.html", stem));
204
265
  std::fs::write(&html_path, html).map_err(|e| WasmError {
205
266
  message: format!("Cannot write {}: {}", html_path.display(), e),
@@ -221,14 +282,17 @@ run(chunk);
221
282
  /// - `{output}.html` — loader (open in browser)
222
283
  ///
223
284
  /// Requires: `rustup target add wasm32-unknown-unknown`, `wasm-bindgen-cli`
285
+ /// `gpu = true` targets the WebGPU runtime (`--features gpu`, `start(chunk, host)` entry); see
286
+ /// [`emit_wasm_from_chunk`]. (#277, exposed as `--target wasm-gpu`.)
224
287
  pub fn compile_to_wasm(
225
288
  entry_path: &Path,
226
289
  project_root: Option<&Path>,
227
290
  output_path: &Path,
228
291
  optimize: bool,
292
+ gpu: bool,
229
293
  ) -> Result<(), WasmError> {
230
294
  let (chunk, _) = resolve_and_compile_to_chunk(entry_path, project_root, optimize)?;
231
- emit_wasm_from_chunk(&chunk, output_path)
295
+ emit_wasm_from_chunk(&chunk, output_path, gpu)
232
296
  }
233
297
 
234
298
  /// Compile a Tish project to a raw serialized bytecode chunk.
@@ -426,3 +490,33 @@ fn main() {
426
490
  );
427
491
  Ok(())
428
492
  }
493
+
494
+ #[cfg(test)]
495
+ mod tests {
496
+ use super::loader_html;
497
+
498
+ #[test]
499
+ fn gpu_loader_uses_start_and_bootstraps_webgpu() {
500
+ // #277: the wasm-gpu loader must call the `start(chunk, host)` entry (not `run`) and build
501
+ // the WebGPU `host` env (adapter/device/context) the tish program reads.
502
+ let html = loader_html("viz", "QkFTRTY0", true);
503
+ assert!(html.contains("import init, { start }"), "imports start");
504
+ assert!(html.contains("start(chunk, host)"), "calls start with host");
505
+ assert!(html.contains("navigator.gpu.requestAdapter()"), "bootstraps adapter");
506
+ assert!(html.contains("getContext(\"webgpu\")"), "configures the canvas context");
507
+ assert!(html.contains("device, queue: device.queue, context, format, canvas"), "host shape");
508
+ assert!(html.contains("from './viz.js'"), "imports the right glue");
509
+ assert!(!html.contains("run(chunk)"), "must NOT use the plain run() entry");
510
+ assert!(html.contains("QkFTRTY0"), "embeds the chunk");
511
+ }
512
+
513
+ #[test]
514
+ fn plain_loader_uses_run() {
515
+ let html = loader_html("app", "QkFTRTY0", false);
516
+ assert!(html.contains("import init, { run }"), "imports run");
517
+ assert!(html.contains("run(chunk)"), "calls run");
518
+ assert!(!html.contains("start("), "no gpu start entry");
519
+ assert!(!html.contains("requestAdapter"), "no webgpu bootstrap");
520
+ assert!(html.contains("from './app.js'"), "imports the right glue");
521
+ }
522
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tishlang/tish",
3
- "version": "2.2.5",
3
+ "version": "2.8.0",
4
4
  "description": "Tish - minimal TS/JS-compatible language. Run, REPL, build to native or other targets.",
5
5
  "license": "PIF",
6
6
  "repository": {
Binary file
Binary file
Binary file
Binary file
Binary file