1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//! # bytecode_lang
//!
//! LSB, the LexerSketch bytecode format: one register-machine instruction
//! set for every language and every execution tier, its module model, a
//! versioned binary encoding, a budgeted decoder, a deterministic
//! disassembler, and a builder that resolves branch labels.
//!
//! The VM (bvm-lang 2.0) executes LSB, code generators (codegen-lang 2.0)
//! emit it, program images (loader-lang) store it, and the debugger
//! (dap-lang) reads its line tables. This crate owns the format only; it
//! executes nothing.
//!
//! ## Quick start
//!
//! Build a function, encode the module, decode it back, and read the listing:
//!
//! ```
//! use bytecode_lang::{decode, disassemble, encode, Inst, IntOp, IntTy, ModuleBuilder, ValType};
//!
//! let mut m = ModuleBuilder::new();
//! let mut f = m.function("add", &[ValType::I64, ValType::I64], &[ValType::I64]);
//! let (a, b) = (f.param(0), f.param(1));
//! let sum = f.reg(ValType::I64);
//! f.emit(Inst::IAdd { dst: sum, lhs: a, rhs: b, op: IntOp::new(IntTy::I64) });
//! f.ret(sum);
//! m.add_function(f)?;
//! let module = m.finish()?;
//!
//! let bytes = encode(&module);
//! let back = decode(&bytes)?;
//! assert_eq!(back, module);
//! assert!(disassemble(&back).contains("iadd.i64 r2, r0, r1"));
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
//!
//! ## The model
//!
//! - **Registers, typed.** Every function has a frame of 64-bit registers,
//! each with a declared [`ValType`]: unboxed scalars for static languages,
//! [`ValType::Dyn`] for dynamic values, and references. Declared types make
//! GC roots exact and let the verifier check every operand.
//! - **Eight-byte instructions.** [`Inst`] is a `Copy` enum of eight bytes;
//! a function body is a flat `&[Inst]` that an interpreter walks without
//! re-parsing. Branch targets are resolved instruction indices.
//! - **Policies on every operation.** Integer instructions carry an
//! [`IntOp`]: the operand type plus the complete OPS policy set (overflow,
//! division by zero, shift range, float-to-int), so every tier computes the
//! same result or raises the same [`ErrorKind`].
//! - **Dynamic languages built in.** `dyn` arithmetic and comparisons with a
//! numeric fast path, ordered hash maps, property access, iteration, and
//! per-module [`Hook`]s that let a language supply its own semantics for
//! the slow path. `overflow = promote` gives PHP's int-to-float arithmetic.
//! - **Coroutines.** Stackful coroutines (`coro_new`, `yield`, `await`,
//! `resume`, `spawn`) for generators, fibers, and async tasks; see
//! [`CoroState`].
//!
//! The normative description of every instruction is `specs/LSB.md` in the
//! LexerSketch plan; `docs/API.md` documents every public item.
//!
//! ## Guarantees
//!
//! - [`decode`] never panics on any input, never recurses, and allocates no
//! more than its [`Limits`] and the input length justify.
//! - `decode(&encode(&m)) == Ok(m)` for every module, and
//! `encode(&decode(bytes)?) == bytes` for every accepted input: each module
//! has exactly one encoding.
//! - [`encode`] and [`disassemble`] are deterministic.
//! - A function produced by [`ModuleBuilder::add_function`] has no unresolved
//! or out-of-range branch target.
//!
//! What this release does **not** do: verify a module's meaning (index
//! ranges, register types, frame shapes). That is the v0.5 verifier, whose
//! rules are specified in `specs/LSB.md` ยง8. Until then a decoded module is
//! well-formed but unverified.
extern crate alloc;
use ;
use Vec;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// The four bytes every encoded module starts with: `LSB\0`.
///
/// # Examples
///
/// ```
/// use bytecode_lang::{encode, ModuleBuilder, MAGIC};
///
/// let bytes = encode(&ModuleBuilder::new().finish().unwrap());
/// assert_eq!(&bytes[..4], &MAGIC);
/// ```
pub const MAGIC: = *b"LSB\0";
/// The format version this crate writes and the only one it reads.
///
/// The version changes whenever the encoding or any instruction's meaning
/// changes; [`decode`] refuses every other version rather than guess.
///
/// # Examples
///
/// ```
/// use bytecode_lang::{encode, ModuleBuilder, FORMAT_VERSION};
///
/// let bytes = encode(&ModuleBuilder::new().finish().unwrap());
/// assert_eq!(bytes[4..8], FORMAT_VERSION.to_le_bytes());
/// ```
pub const FORMAT_VERSION: u32 = 1;
/// Encodes a module into its canonical bytes.
///
/// Infallible and deterministic: a [`Module`] can only be made by
/// [`ModuleBuilder::finish`] or [`decode`], both of which guarantee every
/// section fits its 32-bit length.
///
/// # Examples
///
/// ```
/// use bytecode_lang::{encode, ModuleBuilder};
///
/// let module = ModuleBuilder::new().finish().unwrap();
/// let bytes = encode(&module);
/// assert_eq!(bytes, encode(&module));
/// // A 12-byte header, ten 8-byte section headers, and the empty sections'
/// // counts and option flags.
/// assert_eq!(bytes.len(), 130);
/// ```
/// Decodes a module with the default [`Limits`].
///
/// # Errors
///
/// A [`DecodeError`] with the byte offset and the reason when the input is
/// not a well-formed module of this format version.
///
/// # Examples
///
/// ```
/// use bytecode_lang::{decode, encode, DecodeErrorKind, ModuleBuilder};
///
/// let module = ModuleBuilder::new().finish().unwrap();
/// let bytes = encode(&module);
/// assert_eq!(decode(&bytes).unwrap(), module);
///
/// let truncated = &bytes[..bytes.len() - 1];
/// assert_eq!(decode(truncated).unwrap_err().kind(), &DecodeErrorKind::UnexpectedEnd);
/// ```
/// Decodes a module with explicit budgets.
///
/// # Errors
///
/// As [`decode`], plus [`DecodeErrorKind::LimitExceeded`] when the input
/// exceeds one of `limits`.
///
/// # Examples
///
/// ```
/// use bytecode_lang::{decode_with, encode, DecodeErrorKind, Limit, Limits, ModuleBuilder};
///
/// let bytes = encode(&ModuleBuilder::new().finish().unwrap());
/// let mut tight = Limits::default();
/// tight.max_bytes = 16;
/// assert_eq!(
/// decode_with(&bytes, &tight).unwrap_err().kind(),
/// &DecodeErrorKind::LimitExceeded(Limit::Bytes),
/// );
/// ```
/// Compiles and runs the `rust` code blocks in `README.md` and `docs/API.md` as
/// part of `cargo test`, so the published examples cannot drift from the API.
///
/// Present only while collecting doctests (`#[cfg(doctest)]`); it is not part of
/// the public surface and does not appear in the built library or its docs.
;
/// The module's disassembly: a deterministic text listing of every table
/// and every function, with branch targets as labels and names resolved in
/// comments.
///
/// Never panics, including on unverified modules with out-of-range
/// references (they print as `<invalid>`).
///
/// # Examples
///
/// ```
/// use bytecode_lang::{disassemble, ModuleBuilder};
///
/// let mut m = ModuleBuilder::new();
/// let mut f = m.function("main", &[], &[]);
/// f.ret_void();
/// m.add_function(f).unwrap();
/// let text = disassemble(&m.finish().unwrap());
/// assert!(text.starts_with("lsb 1\n"));
/// assert!(text.contains("func f0 s0 \"main\" : t0"));
/// assert!(text.contains(" 0000 ret_void"));
/// ```