diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/rust/jsparagus-emitter/src/array_emitter.rs | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/jsparagus-emitter/src/array_emitter.rs')
-rw-r--r-- | third_party/rust/jsparagus-emitter/src/array_emitter.rs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/third_party/rust/jsparagus-emitter/src/array_emitter.rs b/third_party/rust/jsparagus-emitter/src/array_emitter.rs new file mode 100644 index 0000000000..b44137182e --- /dev/null +++ b/third_party/rust/jsparagus-emitter/src/array_emitter.rs @@ -0,0 +1,176 @@ +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(()) + } +} |