use crate ::ast_emitter::AstEmitter;
use crate ::emitter::EmitError;
/// Struct for emitting bytecode for an array element.
pub struct ArrayElementEmitter<'a, F>
where
F: Fn (&mut AstEmitter) -> Result<(), EmitError>,
{
pub state: &'a mut ArrayEmitterState,
pub elem: F,
}
impl <'a, F> ArrayElementEmitter<' a, F>
where
F: Fn (&mut AstEmitter) -> Result<(), EmitError>,
{
pub fn emit(self , emitter: &mut AstEmitter) -> Result<(), EmitError> {
// [stack] ARRAY INDEX?
(self .elem)(emitter)?;
// [stack] ARRAY INDEX? ELEM
match &mut self .state.0 {
ArrayEmitterStateInternal::BeforeSpread { ref mut index } => {
emitter.emit.init_elem_array(*index);
// [stack] ARRAY
*index += 1 ;
}
ArrayEmitterStateInternal::AfterSpread => {
emitter.emit.init_elem_inc();
// [stack] ARRAY INDEX+1
}
}
// [stack] ARRAY INDEX?
Ok(())
}
}
/// Struct for emitting bytecode for an array element with hole.
pub struct ArrayElisionEmitter<'a> {
pub state: &'a mut ArrayEmitterState,
}
impl <'a> ArrayElisionEmitter<' a> {
pub fn emit(self , emitter: &mut AstEmitter) {
// [stack] ARRAY INDEX?
emitter.emit.hole();
// [stack] ARRAY INDEX? HOLE
match &mut self .state.0 {
ArrayEmitterStateInternal::BeforeSpread { ref mut index } => {
emitter.emit.init_elem_array(*index);
// [stack] ARRAY
*index += 1 ;
}
ArrayEmitterStateInternal::AfterSpread => {
emitter.emit.init_elem_inc();
// [stack] ARRAY INDEX+1
}
}
// [stack] ARRAY INDEX?
}
}
/// Struct for emitting bytecode for an array element with spread.
pub struct ArraySpreadEmitter<'a, F>
where
F: Fn (&mut AstEmitter) -> Result<(), EmitError>,
{
pub state: &'a mut ArrayEmitterState,
pub elem: F,
}
impl <'a, F> ArraySpreadEmitter<' a, F>
where
F: Fn (&mut AstEmitter) -> Result<(), EmitError>,
{
pub fn emit(self , emitter: &mut AstEmitter) -> Result<(), EmitError> {
// [stack] ARRAY INDEX?
match self .state.0 {
ArrayEmitterStateInternal::BeforeSpread { index } => {
emitter.emit.numeric(index as f64);
}
_ => {}
}
self .state.0 = ArrayEmitterStateInternal::AfterSpread;
// [stack] ARRAY INDEX
Err(EmitError::NotImplemented("TODO: spread element" ))
}
}
enum ArrayEmitterStateInternal {
BeforeSpread { index: u32 },
AfterSpread,
}
/// Opaque struct that can be created only by ArrayEmitter.
/// This guarantees that Array*Emitter structs cannot be used outside
/// of ArrayEmitter callback.
pub struct ArrayEmitterState(ArrayEmitterStateInternal);
impl ArrayEmitterState {
fn new() -> Self {
Self (ArrayEmitterStateInternal::BeforeSpread { index: 0 })
}
}
pub enum ArrayElementKind {
Normal,
Elision,
Spread,
}
/// Struct for emitting bytecode for an array expression.
pub struct ArrayEmitter<'a, ElemT, ElemKindF, ElemF>
where
ElemKindF: Fn (&ElemT) -> ArrayElementKind,
ElemF: Fn (&mut AstEmitter, &mut ArrayEmitterState, &'a ElemT) -> Result<(), EmitError>,
{
pub elements: std::slice::Iter<'a, ElemT>,
pub elem_kind: ElemKindF,
pub elem: ElemF,
}
impl <'a, ElemT, ElemKindF, ElemF> ArrayEmitter<' a, ElemT, ElemKindF, ElemF>
where
ElemKindF: Fn (&ElemT) -> ArrayElementKind,
ElemF: Fn (&mut AstEmitter, &mut ArrayEmitterState, &'a ElemT) -> Result<(), EmitError>,
{
pub fn emit(self , emitter: &mut AstEmitter) -> Result<(), EmitError> {
// [stack]
// Initialize the array to its minimum possible length.
let min_length = self
.elements
.clone()
.map(|e| match (self .elem_kind)(e) {
ArrayElementKind::Normal => 1 ,
ArrayElementKind::Elision => 1 ,
ArrayElementKind::Spread => 0 ,
})
.sum::<u32>();
emitter.emit.new_array(min_length);
// [stack] ARRAY
let mut state = ArrayEmitterState::new();
for element in self .elements {
(self .elem)(emitter, &mut state, element)?;
// [stack] ARRAY INDEX?
}
match state.0 {
ArrayEmitterStateInternal::AfterSpread => {
// [stack] ARRAY INDEX
emitter.emit.pop();
// [stack] ARRAY
}
_ => {}
}
// [stack] ARRAY
Ok(())
}
}
Messung V0.5 in Prozent C=86 H=100 G=93
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-23)
¤
*© Formatika GbR, Deutschland