struct Compiler<'a> {
code: Vec<Op>,
consts: Vec<f64>,
ctx: &'a mut MilkContext,
}Fields§
§code: Vec<Op>§consts: Vec<f64>§ctx: &'a mut MilkContextBorrowed context — used to intern cold-variable names into the
slab so each LoadCold/StoreCold opcode carries a slab index
rather than a name.
Implementations§
Source§impl<'a> Compiler<'a>
impl<'a> Compiler<'a>
fn new(ctx: &'a mut MilkContext) -> Self
fn emit(&mut self, op: Op)
fn add_const(&mut self, f: f64) -> u32
Sourcefn add_cold(&mut self, name: &str) -> u32
fn add_cold(&mut self, name: &str) -> u32
Intern a cold-variable name into MilkContext::cold and return
its slab index. Subsequent references to the same name reuse the
existing slot; auto-seeded MD2 defaults (bass, zoom, …) hit
pre-existing slots without growing the slab.
fn finish(self) -> CompiledBytecode
Sourcefn compile_node(&mut self, node: &Node) -> Result<(), CompileError>
fn compile_node(&mut self, node: &Node) -> Result<(), CompileError>
Compile a node so that it leaves exactly one f64 on the stack.
Sourcefn emit_read(&mut self, name: &str)
fn emit_read(&mut self, name: &str)
Emit either LoadHot(i), LoadQ(i), or LoadCold(name_idx)
depending on which class the identifier falls into.
fn emit_write(&mut self, name: &str)
fn compile_unary( &mut self, children: &[Node], op: Op, ) -> Result<(), CompileError>
fn compile_binary( &mut self, children: &[Node], op: Op, ) -> Result<(), CompileError>
Sourcefn compile_assign(
&mut self,
children: &[Node],
compound: Option<Op>,
) -> Result<(), CompileError>
fn compile_assign( &mut self, children: &[Node], compound: Option<Op>, ) -> Result<(), CompileError>
Compile x = expr (when compound is None) or x op= expr
(when compound is Some(arith_op)). In both cases the
statement leaves a placeholder 0.0 on the stack so the outer
statement-discard Pop stays balanced.
Sourcefn compile_call(
&mut self,
name: &str,
children: &[Node],
) -> Result<(), CompileError>
fn compile_call( &mut self, name: &str, children: &[Node], ) -> Result<(), CompileError>
Lower a function call. evalexpr wraps every parenthesised
subexpression in a RootNode, so a call like pow(2, 5)
lands as FunctionIdentifier → RootNode → Tuple → [RootNode→2, RootNode→5]. We unwrap the outer RootNode, then either split
a Tuple into args or treat the whole thing as a single arg.