@tishlang/tish-format 2.39.0 → 3.0.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 (90) hide show
  1. package/Cargo.toml +4 -1
  2. package/bin/tish-format +0 -0
  3. package/crates/tish/src/cli_help.rs +28 -0
  4. package/crates/tish/src/main.rs +41 -5
  5. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +21 -0
  6. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/tish.d.tish +4 -0
  7. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +5 -1
  8. package/crates/tish/tests/regr_typed_externs.rs +59 -0
  9. package/crates/tish/tests/scope_merge.rs +79 -0
  10. package/crates/tish_build_utils/src/lib.rs +27 -1
  11. package/crates/tish_builtins/Cargo.toml +14 -6
  12. package/crates/tish_builtins/src/array.rs +130 -54
  13. package/crates/tish_builtins/src/collections.rs +9 -5
  14. package/crates/tish_builtins/src/construct.rs +7 -1
  15. package/crates/tish_builtins/src/date.rs +15 -1
  16. package/crates/tish_builtins/src/globals.rs +65 -3
  17. package/crates/tish_builtins/src/helpers.rs +7 -3
  18. package/crates/tish_builtins/src/iterator.rs +5 -1
  19. package/crates/tish_builtins/src/lib.rs +3 -0
  20. package/crates/tish_builtins/src/math.rs +14 -0
  21. package/crates/tish_builtins/src/number.rs +72 -6
  22. package/crates/tish_builtins/src/object.rs +6 -1
  23. package/crates/tish_builtins/src/string.rs +13 -2
  24. package/crates/tish_builtins/src/symbol.rs +17 -17
  25. package/crates/tish_builtins/src/typedarrays.rs +9 -2
  26. package/crates/tish_bytecode/src/compiler.rs +76 -2
  27. package/crates/tish_bytecode/src/lib.rs +1 -1
  28. package/crates/tish_bytecode/src/opcode.rs +77 -2
  29. package/crates/tish_compile/src/codegen.rs +2154 -225
  30. package/crates/tish_compile/src/infer.rs +37 -41
  31. package/crates/tish_compile/src/lib.rs +13 -1
  32. package/crates/tish_compile/src/platform_resolve.rs +361 -0
  33. package/crates/tish_compile/src/resolve.rs +195 -11
  34. package/crates/tish_compile/src/schemes.rs +333 -0
  35. package/crates/tish_compile/src/types.rs +205 -34
  36. package/crates/tish_compile/tests/perf_codegen_320.rs +2 -2
  37. package/crates/tish_compile/tests/perf_codegen_module_const_forof.rs +3 -1
  38. package/crates/tish_compile/tests/platform_resolve_cli.rs +164 -0
  39. package/crates/tish_compile/tests/regr_556_param_name_collision.rs +40 -0
  40. package/crates/tish_compile/tests/regr_558_struct_array_write.rs +65 -0
  41. package/crates/tish_compile/tests/regr_558b_struct_field_read.rs +21 -0
  42. package/crates/tish_compile/tests/regr_558c_wrapped_struct_array.rs +64 -0
  43. package/crates/tish_compile/tests/regr_558d_native_vec_mutators.rs +156 -0
  44. package/crates/tish_compile/tests/regr_562_wrapped_struct_array_push.rs +50 -0
  45. package/crates/tish_compile/tests/regr_fixed_native_coercions.rs +69 -0
  46. package/crates/tish_compile/tests/regr_gba_numerics_gated.rs +58 -0
  47. package/crates/tish_compile/tests/regr_gba_struct_reflection.rs +106 -0
  48. package/crates/tish_compile/tests/regression/name_collision_lib.tish +6 -0
  49. package/crates/tish_compile/tests/regression/name_collision_main.tish +13 -0
  50. package/crates/tish_compile/tests/regression/struct_array_write.tish +22 -0
  51. package/crates/tish_compile/tests/regression/struct_field_return_read.tish +10 -0
  52. package/crates/tish_compiler_wasm/Cargo.toml +1 -0
  53. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +56 -6
  54. package/crates/tish_core/Cargo.toml +39 -4
  55. package/crates/tish_core/src/compat.rs +506 -0
  56. package/crates/tish_core/src/console_style.rs +23 -1
  57. package/crates/tish_core/src/json.rs +42 -10
  58. package/crates/tish_core/src/lib.rs +121 -25
  59. package/crates/tish_core/src/macros.rs +1 -1
  60. package/crates/tish_core/src/shape.rs +4 -2
  61. package/crates/tish_core/src/uri.rs +8 -1
  62. package/crates/tish_core/src/value.rs +305 -54
  63. package/crates/tish_core/src/vmref.rs +17 -5
  64. package/crates/tish_eval/Cargo.toml +2 -0
  65. package/crates/tish_eval/src/eval.rs +90 -3
  66. package/crates/tish_eval/src/value.rs +8 -0
  67. package/crates/tish_eval/src/value_convert.rs +316 -21
  68. package/crates/tish_fmt/Cargo.toml +1 -1
  69. package/crates/tish_lsp/Cargo.toml +2 -0
  70. package/crates/tish_lsp/src/import_goto.rs +41 -14
  71. package/crates/tish_lsp/src/main.rs +18 -0
  72. package/crates/tish_native/src/build.rs +246 -0
  73. package/crates/tish_native/src/config.rs +20 -0
  74. package/crates/tish_native/src/lib.rs +16 -6
  75. package/crates/tish_parser/src/lib.rs +28 -0
  76. package/crates/tish_parser/src/parser.rs +25 -4
  77. package/crates/tish_runtime/src/lib.rs +55 -9
  78. package/crates/tish_runtime_gba/Cargo.lock +837 -0
  79. package/crates/tish_runtime_gba/Cargo.toml +16 -0
  80. package/crates/tish_runtime_gba/src/gba.rs +211 -0
  81. package/crates/tish_runtime_gba/src/lib.rs +804 -0
  82. package/crates/tish_vm/src/jit.rs +1446 -164
  83. package/crates/tish_vm/src/vm.rs +583 -173
  84. package/justfile +9 -0
  85. package/package.json +1 -1
  86. package/platform/darwin-arm64/tish-fmt +0 -0
  87. package/platform/darwin-x64/tish-fmt +0 -0
  88. package/platform/linux-arm64/tish-fmt +0 -0
  89. package/platform/linux-x64/tish-fmt +0 -0
  90. package/platform/win32-x64/tish-fmt.exe +0 -0
@@ -0,0 +1,16 @@
1
+ [package]
2
+ name = "tishlang_runtime_gba"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ description = "no_std runtime facade for Tish compiled output on the Game Boy Advance (agb)"
6
+
7
+ # The GBA `Gba` emit mode declares the generated crate's dependency as
8
+ # tishlang_runtime = { package = "tishlang_runtime_gba", path = ... }
9
+ # so every emitted `tishlang_runtime::…` path resolves here (the package-rename
10
+ # zero-churn trick). This crate re-exports the portable prelude surface from
11
+ # tishlang_core / tishlang_builtins and adds the GBA `gba::{init, halt, hooks}`.
12
+
13
+ [dependencies]
14
+ tishlang_core = { path = "../tish_core", default-features = false, features = ["portable"] }
15
+ tishlang_builtins = { path = "../tish_builtins", default-features = false, features = ["portable"] }
16
+ agb = "0.25.0"
@@ -0,0 +1,211 @@
1
+ //! GBA runtime entry points, called by the generated `#[agb::entry] agb_main`.
2
+ //!
3
+ //! Contract (see tish-gba/CONTRACT.md §4):
4
+ //! ```ignore
5
+ //! #[agb::entry]
6
+ //! fn agb_main(gba: agb::Gba) -> ! {
7
+ //! tishlang_runtime::gba::init(gba);
8
+ //! let _ = run(); // P5: block_on(run())
9
+ //! tishlang_runtime::gba::halt()
10
+ //! }
11
+ //! ```
12
+
13
+ use alloc::vec::Vec;
14
+ use core::cell::RefCell;
15
+ use tishlang_core::SingleCore;
16
+
17
+ // The `agb::Gba` peripheral bundle, stashed at boot so the low-level binding
18
+ // crate (`tish-agb`) can take it and drive graphics/input/etc. Single-core, so a
19
+ // plain static behind the SingleCore `.with()` API is sound.
20
+ static GBA: SingleCore<RefCell<Option<agb::Gba>>> = SingleCore::new(RefCell::new(None));
21
+
22
+ /// Stash the `agb::Gba` peripheral bundle for the binding crate to claim via
23
+ /// [`take_gba`]. Called by the generated `agb_main` before the program body runs.
24
+ pub fn init(gba: agb::Gba) {
25
+ GBA.with(|c| {
26
+ *c.borrow_mut() = Some(gba);
27
+ });
28
+ }
29
+
30
+ /// Claim the `agb::Gba` peripheral bundle (once). `tish-agb` calls this on first
31
+ /// use to set up its graphics/input context. Returns `None` if already taken.
32
+ pub fn take_gba() -> Option<agb::Gba> {
33
+ GBA.with(|c| c.borrow_mut().take())
34
+ }
35
+
36
+ /// Divergent halt for the end of `agb_main` (after `run()` returns).
37
+ pub fn halt() -> ! {
38
+ loop {
39
+ agb::halt();
40
+ }
41
+ }
42
+
43
+ // ── Per-frame hooks ──────────────────────────────────────────────────────────
44
+ // `tish-agb`'s frame driver and (later) the engine pipeline register here; the
45
+ // frame loop runs them once per frame before `commit()`. Single-core, so a plain
46
+ // static with the SingleCore `.with()` API.
47
+ static PRE_COMMIT: SingleCore<RefCell<Vec<fn()>>> = SingleCore::new(RefCell::new(Vec::new()));
48
+
49
+ /// Register a callback to run once per frame, before the display commit.
50
+ pub fn register_pre_commit(f: fn()) {
51
+ PRE_COMMIT.with(|c| c.borrow_mut().push(f));
52
+ }
53
+
54
+ /// Run all registered pre-commit hooks (called by the frame driver / executor).
55
+ pub fn run_pre_commit() {
56
+ PRE_COMMIT.with(|c| {
57
+ // Clone out the fn pointers so a hook can register another without a
58
+ // nested borrow of the same RefCell.
59
+ let hooks: Vec<fn()> = c.borrow().clone();
60
+ for f in hooks {
61
+ f();
62
+ }
63
+ });
64
+ }
65
+
66
+ // ── Asset registry ───────────────────────────────────────────────────────────
67
+ // Sprite sheets from `asset:` imports. The generated `agb_main` calls
68
+ // `__asset_register_sheet` once per imported asset (in import order) BEFORE
69
+ // `run()`, handing over the `&'static [Sprite]` slice that agb's
70
+ // `include_aseprite_inner!` produced in the generated crate. The returned i32 is
71
+ // the handle a tish program passes to `tish-agb`'s sprite APIs; `tish-agb` reads
72
+ // the slice back with [`asset_sheet`]. The registry lives here (not in tish-agb)
73
+ // so the generated crate — which always depends on this facade as
74
+ // `tishlang_runtime` — can register without needing the `cargo:tish_agb` dep.
75
+
76
+ /// One registered sprite sheet: the frames of an `asset:` import.
77
+ static ASSET_SHEETS: SingleCore<RefCell<Vec<&'static [agb::display::object::Sprite]>>> =
78
+ SingleCore::new(RefCell::new(Vec::new()));
79
+
80
+ /// Register a sprite sheet, returning its i32 handle (= its registration order).
81
+ /// Called by the generated `agb_main`, in import order, before the program body.
82
+ pub fn __asset_register_sheet(sheet: &'static [agb::display::object::Sprite]) -> i32 {
83
+ ASSET_SHEETS.with(|c| {
84
+ let mut v = c.borrow_mut();
85
+ let idx = v.len() as i32;
86
+ v.push(sheet);
87
+ idx
88
+ })
89
+ }
90
+
91
+ /// Look up a registered sprite sheet by handle. `None` if out of range.
92
+ pub fn asset_sheet(handle: i32) -> Option<&'static [agb::display::object::Sprite]> {
93
+ ASSET_SHEETS.with(|c| c.borrow().get(handle as usize).copied())
94
+ }
95
+
96
+ /// One registered background: its palettes + full-screen tile data (agb
97
+ /// `include_background_gfx!` output). Registered by the generated `agb_main` for
98
+ /// each `background:` import; `tish-agb`'s `bg_new` builds a `RegularBackground`.
99
+ type BgAsset = (
100
+ &'static [agb::display::Palette16],
101
+ &'static agb::display::tile_data::TileData,
102
+ );
103
+
104
+ static ASSET_BGS: SingleCore<RefCell<Vec<BgAsset>>> = SingleCore::new(RefCell::new(Vec::new()));
105
+
106
+ /// Register a background (palettes + tile data), returning its i32 handle.
107
+ pub fn __asset_register_bg(bg: BgAsset) -> i32 {
108
+ ASSET_BGS.with(|c| {
109
+ let mut v = c.borrow_mut();
110
+ let idx = v.len() as i32;
111
+ v.push(bg);
112
+ idx
113
+ })
114
+ }
115
+
116
+ /// Look up a registered background by handle. `None` if out of range.
117
+ pub fn asset_bg(handle: i32) -> Option<BgAsset> {
118
+ ASSET_BGS.with(|c| c.borrow().get(handle as usize).copied())
119
+ }
120
+
121
+ /// Registered fonts (`font<N>:` imports) — a compile-time-baked `Font`. All `font<N>:` schemes share
122
+ /// this one arena via an IDENTICAL registration call (no baked-in size — the renderer sizes sprites
123
+ /// from the font's own `line_height`), so their handles number correctly across sizes. tish-agb's
124
+ /// `text_draw` looks them up by handle.
125
+ static ASSET_FONTS: SingleCore<RefCell<Vec<&'static agb::display::font::Font>>> =
126
+ SingleCore::new(RefCell::new(Vec::new()));
127
+
128
+ /// Register a baked font, returning its i32 handle.
129
+ pub fn __asset_register_font(font: &'static agb::display::font::Font) -> i32 {
130
+ ASSET_FONTS.with(|c| {
131
+ let mut v = c.borrow_mut();
132
+ let idx = v.len() as i32;
133
+ v.push(font);
134
+ idx
135
+ })
136
+ }
137
+
138
+ /// Look up a registered font by handle. `None` if out of range.
139
+ pub fn asset_font(handle: i32) -> Option<&'static agb::display::font::Font> {
140
+ ASSET_FONTS.with(|c| c.borrow().get(handle as usize).copied())
141
+ }
142
+
143
+ /// The single global emoji fallback atlas (`emoji:` import): the SerenityOS colour sprite frames plus
144
+ /// a codepoint→frame table sorted by codepoint. There is at most one — it is a fallback shared by
145
+ /// every font, so any font lacking a glyph for an emoji codepoint renders the matching colour sprite
146
+ /// instead of a tofu box. tish-agb's text renderer reads it via [`emoji_sprite`].
147
+ type EmojiAtlas = (
148
+ &'static [agb::display::object::Sprite],
149
+ &'static [(u32, u16)],
150
+ );
151
+
152
+ static ASSET_EMOJI: SingleCore<RefCell<Option<EmojiAtlas>>> = SingleCore::new(RefCell::new(None));
153
+
154
+ /// Register the emoji atlas (frames + codepoint→frame table). Called once by the generated `agb_main`
155
+ /// for the `emoji:` import; the handle is unused (the atlas is a global fallback, not addressed by id).
156
+ pub fn __asset_register_emoji(
157
+ sprites: &'static [agb::display::object::Sprite],
158
+ table: &'static [(u32, u16)],
159
+ ) -> i32 {
160
+ ASSET_EMOJI.with(|c| *c.borrow_mut() = Some((sprites, table)));
161
+ 0
162
+ }
163
+
164
+ /// The colour sprite frame for an emoji codepoint, if an emoji atlas is registered and contains it.
165
+ /// `None` ⇒ no emoji import, or this codepoint wasn't baked ⇒ the caller falls back to the font glyph.
166
+ pub fn emoji_sprite(cp: u32) -> Option<&'static agb::display::object::Sprite> {
167
+ ASSET_EMOJI.with(|c| {
168
+ let (sprites, table) = (*c.borrow())?;
169
+ let i = table.binary_search_by_key(&cp, |&(c, _)| c).ok()?;
170
+ sprites.get(table[i].1 as usize)
171
+ })
172
+ }
173
+
174
+ /// Registered maps (`map:` imports) — the raw ROM bytes of a baked map binary. Kept in ROM
175
+ /// (`include_bytes!`), never copied to the tish heap, so large maps don't blow EWRAM.
176
+ static ASSET_MAPS: SingleCore<RefCell<Vec<&'static [u8]>>> =
177
+ SingleCore::new(RefCell::new(Vec::new()));
178
+
179
+ /// Register a baked map's ROM bytes, returning its i32 handle.
180
+ pub fn __asset_register_map(data: &'static [u8]) -> i32 {
181
+ ASSET_MAPS.with(|c| {
182
+ let mut v = c.borrow_mut();
183
+ let idx = v.len() as i32;
184
+ v.push(data);
185
+ idx
186
+ })
187
+ }
188
+
189
+ /// Look up a registered map's ROM bytes by handle. `None` if out of range.
190
+ pub fn asset_map(handle: i32) -> Option<&'static [u8]> {
191
+ ASSET_MAPS.with(|c| c.borrow().get(handle as usize).copied())
192
+ }
193
+
194
+ /// Registered sounds (`wav:` imports). `SoundData` is `Copy` (a `&'static [u8]` handle).
195
+ static ASSET_WAVS: SingleCore<RefCell<Vec<agb::sound::mixer::SoundData>>> =
196
+ SingleCore::new(RefCell::new(Vec::new()));
197
+
198
+ /// Register a sound, returning its i32 handle.
199
+ pub fn __asset_register_wav(data: agb::sound::mixer::SoundData) -> i32 {
200
+ ASSET_WAVS.with(|c| {
201
+ let mut v = c.borrow_mut();
202
+ let idx = v.len() as i32;
203
+ v.push(data);
204
+ idx
205
+ })
206
+ }
207
+
208
+ /// Look up a registered sound by handle. `None` if out of range.
209
+ pub fn asset_wav(handle: i32) -> Option<agb::sound::mixer::SoundData> {
210
+ ASSET_WAVS.with(|c| c.borrow().get(handle as usize).copied())
211
+ }