@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.
- package/Cargo.toml +4 -1
- package/bin/tish-format +0 -0
- package/crates/tish/src/cli_help.rs +28 -0
- package/crates/tish/src/main.rs +41 -5
- package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +21 -0
- package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/tish.d.tish +4 -0
- package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +5 -1
- package/crates/tish/tests/regr_typed_externs.rs +59 -0
- package/crates/tish/tests/scope_merge.rs +79 -0
- package/crates/tish_build_utils/src/lib.rs +27 -1
- package/crates/tish_builtins/Cargo.toml +14 -6
- package/crates/tish_builtins/src/array.rs +130 -54
- package/crates/tish_builtins/src/collections.rs +9 -5
- package/crates/tish_builtins/src/construct.rs +7 -1
- package/crates/tish_builtins/src/date.rs +15 -1
- package/crates/tish_builtins/src/globals.rs +65 -3
- package/crates/tish_builtins/src/helpers.rs +7 -3
- package/crates/tish_builtins/src/iterator.rs +5 -1
- package/crates/tish_builtins/src/lib.rs +3 -0
- package/crates/tish_builtins/src/math.rs +14 -0
- package/crates/tish_builtins/src/number.rs +72 -6
- package/crates/tish_builtins/src/object.rs +6 -1
- package/crates/tish_builtins/src/string.rs +13 -2
- package/crates/tish_builtins/src/symbol.rs +17 -17
- package/crates/tish_builtins/src/typedarrays.rs +9 -2
- package/crates/tish_bytecode/src/compiler.rs +76 -2
- package/crates/tish_bytecode/src/lib.rs +1 -1
- package/crates/tish_bytecode/src/opcode.rs +77 -2
- package/crates/tish_compile/src/codegen.rs +2154 -225
- package/crates/tish_compile/src/infer.rs +37 -41
- package/crates/tish_compile/src/lib.rs +13 -1
- package/crates/tish_compile/src/platform_resolve.rs +361 -0
- package/crates/tish_compile/src/resolve.rs +195 -11
- package/crates/tish_compile/src/schemes.rs +333 -0
- package/crates/tish_compile/src/types.rs +205 -34
- package/crates/tish_compile/tests/perf_codegen_320.rs +2 -2
- package/crates/tish_compile/tests/perf_codegen_module_const_forof.rs +3 -1
- package/crates/tish_compile/tests/platform_resolve_cli.rs +164 -0
- package/crates/tish_compile/tests/regr_556_param_name_collision.rs +40 -0
- package/crates/tish_compile/tests/regr_558_struct_array_write.rs +65 -0
- package/crates/tish_compile/tests/regr_558b_struct_field_read.rs +21 -0
- package/crates/tish_compile/tests/regr_558c_wrapped_struct_array.rs +64 -0
- package/crates/tish_compile/tests/regr_558d_native_vec_mutators.rs +156 -0
- package/crates/tish_compile/tests/regr_562_wrapped_struct_array_push.rs +50 -0
- package/crates/tish_compile/tests/regr_fixed_native_coercions.rs +69 -0
- package/crates/tish_compile/tests/regr_gba_numerics_gated.rs +58 -0
- package/crates/tish_compile/tests/regr_gba_struct_reflection.rs +106 -0
- package/crates/tish_compile/tests/regression/name_collision_lib.tish +6 -0
- package/crates/tish_compile/tests/regression/name_collision_main.tish +13 -0
- package/crates/tish_compile/tests/regression/struct_array_write.tish +22 -0
- package/crates/tish_compile/tests/regression/struct_field_return_read.tish +10 -0
- package/crates/tish_compiler_wasm/Cargo.toml +1 -0
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +56 -6
- package/crates/tish_core/Cargo.toml +39 -4
- package/crates/tish_core/src/compat.rs +506 -0
- package/crates/tish_core/src/console_style.rs +23 -1
- package/crates/tish_core/src/json.rs +42 -10
- package/crates/tish_core/src/lib.rs +121 -25
- package/crates/tish_core/src/macros.rs +1 -1
- package/crates/tish_core/src/shape.rs +4 -2
- package/crates/tish_core/src/uri.rs +8 -1
- package/crates/tish_core/src/value.rs +305 -54
- package/crates/tish_core/src/vmref.rs +17 -5
- package/crates/tish_eval/Cargo.toml +2 -0
- package/crates/tish_eval/src/eval.rs +90 -3
- package/crates/tish_eval/src/value.rs +8 -0
- package/crates/tish_eval/src/value_convert.rs +316 -21
- package/crates/tish_fmt/Cargo.toml +1 -1
- package/crates/tish_lsp/Cargo.toml +2 -0
- package/crates/tish_lsp/src/import_goto.rs +41 -14
- package/crates/tish_lsp/src/main.rs +18 -0
- package/crates/tish_native/src/build.rs +246 -0
- package/crates/tish_native/src/config.rs +20 -0
- package/crates/tish_native/src/lib.rs +16 -6
- package/crates/tish_parser/src/lib.rs +28 -0
- package/crates/tish_parser/src/parser.rs +25 -4
- package/crates/tish_runtime/src/lib.rs +55 -9
- package/crates/tish_runtime_gba/Cargo.lock +837 -0
- package/crates/tish_runtime_gba/Cargo.toml +16 -0
- package/crates/tish_runtime_gba/src/gba.rs +211 -0
- package/crates/tish_runtime_gba/src/lib.rs +804 -0
- package/crates/tish_vm/src/jit.rs +1446 -164
- package/crates/tish_vm/src/vm.rs +583 -173
- package/justfile +9 -0
- package/package.json +1 -1
- package/platform/darwin-arm64/tish-fmt +0 -0
- package/platform/darwin-x64/tish-fmt +0 -0
- package/platform/linux-arm64/tish-fmt +0 -0
- package/platform/linux-x64/tish-fmt +0 -0
- 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
|
+
}
|