byteflow/bytecode/macros.rs
1//! Thin, deliberately **non-duplicating** `macro_rules!` sugar over
2//! [`crate::ChunkBuilder`] methods that emit more than one instruction for
3//! a single conceptual operation.
4//!
5//! # Why a macro on top of a method that already does the job
6//!
7//! It doesn't add capability — [`ChunkBuilder::emit_native1_from`] and
8//! [`ChunkBuilder::emit_native_n`] are already complete methods, and calling
9//! them directly (`b.emit_native1_from(1, 0, native)`) works fine. The macros
10//! exist only for call sites that read better as a flat list of emit-macro
11//! invocations — e.g. unpacking four fields from one message register back
12//! to back in [`crate::samples::atomic_request_reply`].
13//!
14//! Every macro here is a **one-line forward** to the method of the same
15//! name. Neither contains logic, a register calculation, or an opcode
16//! literal of its own — if the method and the macro ever disagreed, that
17//! would be a bug in this file. See
18//! [`ChunkBuilder::emit_native1_from`] for the ISA contract (`CallNative`
19//! clobbers `r[a]`); this file only explains *why a macro form exists*.
20//!
21//! Styled after the crate-internal `trap!` pattern in `Vm::run`: small,
22//! named after the one thing it does, no general assembler DSL.
23
24/// `emit_native1_from!(builder, dest, src, native)` — sugar for
25/// [`crate::ChunkBuilder::emit_native1_from`].
26///
27/// # Example
28/// ```
29/// use byteflow::{emit_native1_from, ChunkBuilder};
30///
31/// let mut b = ChunkBuilder::new("example");
32/// b.begin_function("main", 0, 8);
33/// b.emit_receive(0);
34/// emit_native1_from!(b, 1, 0, /* msg_sender */ 3);
35/// emit_native1_from!(b, 2, 0, /* msg_tag */ 5);
36/// b.emit_return(0);
37/// let chunk = b.finish();
38/// assert_eq!(chunk.code.len(), 6); // Receive + (Move,CallNative)*2 + Return
39/// ```
40#[macro_export]
41macro_rules! emit_native1_from {
42 ($builder:expr, $dest:expr, $src:expr, $native:expr) => {
43 $builder.emit_native1_from($dest, $src, $native)
44 };
45}
46
47/// `emit_native_n!(builder, base, native, argc)` — sugar for
48/// [`crate::ChunkBuilder::emit_native_n`].
49///
50/// # Example
51/// ```
52/// use byteflow::{emit_native_n, ChunkBuilder};
53///
54/// let mut b = ChunkBuilder::new("example");
55/// b.begin_function("main", 0, 8);
56/// b.emit_load_imm(1, 7);
57/// b.emit_load_imm(2, 1);
58/// b.emit_load_imm(3, 0);
59/// b.emit_load_imm(4, 42);
60/// emit_native_n!(b, 1, /* make_msg */ 2, 4);
61/// b.emit_return(1);
62/// let chunk = b.finish();
63/// assert_eq!(chunk.code.len(), 6);
64/// ```
65#[macro_export]
66macro_rules! emit_native_n {
67 ($builder:expr, $base:expr, $native:expr, $argc:expr) => {
68 $builder.emit_native_n($base, $native, $argc)
69 };
70}
71
72/// Namespaced re-exports (`byteflow::asm_macros::emit_native1_from!`, …)
73/// for callers who prefer an explicit path over crate-root
74/// `#[macro_export]` placement.
75pub mod asm_macros {
76 pub use crate::emit_native1_from;
77 pub use crate::emit_native_n;
78}