Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ast_emitter.rs

  Sprache: Rust
 

//! High-level bytecode emitter.
//!
//! Converts AST nodes to bytecode.

use crate::array_emitter::*;
use crate::block_emitter::BlockEmitter;
use crate::compilation_info::CompilationInfo;
use crate::emitter::{EmitError, EmitOptions, InstructionWriter};
use crate::emitter_scope::{EmitterScopeStack, NameLocation};
use crate::expression_emitter::*;
use crate::function_declaration_emitter::{
    AnnexBFunctionDeclarationEmitter, LazyFunctionEmitter, LexicalFunctionDeclarationEmitter,
};
use crate::object_emitter::*;
use crate::reference_op_emitter::{
    AssignmentEmitter, CallEmitter, DeclarationEmitter, ElemReferenceEmitter, GetElemEmitter,
    GetNameEmitter, GetPropEmitter, GetSuperElemEmitter, GetSuperPropEmitter, NameReferenceEmitter,
    NewEmitter, PropReferenceEmitter,
};
use crate::script_emitter::ScriptEmitter;
use ast::source_atom_set::{CommonSourceAtomSetIndices, SourceAtomSetIndex};
use ast::types::*;
use stencil::opcode::Opcode;
use stencil::regexp::RegExpItem;
use stencil::result::EmitResult;
use stencil::script::ScriptStencil;

use crate::control_structures::{
    BreakEmitter, CForEmitter, ContinueEmitter, ControlStructureStack, DoWhileEmitter,
    ForwardJumpEmitter, JumpKind, LabelEmitter, WhileEmitter,
};

/// Emit a program, converting the AST directly to bytecode.
pub fn emit_program<'alloc>(
    ast: &Program,
    options: &EmitOptions,
    mut compilation_info: CompilationInfo<'alloc>,
) -> Result<EmitResult<'alloc>, EmitError> {
    let emitter = AstEmitter::new(options, &mut compilation_info);

    let script = match ast {
        Program::Script(script) => emitter.emit_script(script)?,
        _ => {
            return Err(EmitError::NotImplemented("TODO: modules"));
        }
    };

    compilation_info.scripts.set_top_level(script);

    Ok(EmitResult::new(
        compilation_info.atoms.into(),
        compilation_info.slices.into(),
        compilation_info.scope_data_map.into(),
        compilation_info.regexps.into(),
        compilation_info.scripts.into(),
        compilation_info.script_data_list.into(),
    ))
}

pub struct AstEmitter<'alloc, 'opt> {
    pub emit: InstructionWriter,
    pub scope_stack: EmitterScopeStack,
    pub options: &'opt EmitOptions,
    pub compilation_info: &'opt mut CompilationInfo<'alloc>,
    pub control_stack: ControlStructureStack,
}

impl<'alloc, 'opt> AstEmitter<'alloc, 'opt> {
    fn new(
        options: &'opt EmitOptions,
        compilation_info: &'opt mut CompilationInfo<'alloc>,
    ) -> Self {
        Self {
            emit: InstructionWriter::new(),
            scope_stack: EmitterScopeStack::new(),
            options,
            compilation_info,
            control_stack: ControlStructureStack::new(),
        }
    }

    pub fn lookup_name(&mut self, name: SourceAtomSetIndex) -> NameLocation {
        self.scope_stack.lookup_name(name)
    }

    pub fn lookup_name_in_var(&mut self, name: SourceAtomSetIndex) -> NameLocation {
        self.scope_stack.lookup_name_in_var(name)
    }

    fn emit_script(mut self, ast: &Script) -> Result<ScriptStencil, EmitError> {
        let scope_data_map = &self.compilation_info.scope_data_map;
        let function_declarations = &self.compilation_info.function_declarations;

        let scope_index = scope_data_map.get_global_index();
        let scope_data = scope_data_map.get_global_at(scope_index);

        let top_level_functions: Vec<&Function> = scope_data
            .functions
            .iter()
            .map(|key| {
                *function_declarations
                    .get(key)
                    .expect("function should exist")
            })
            .collect();

        ScriptEmitter {
            top_level_functions: top_level_functions.iter(),
            top_level_function: |emitter, fun| emitter.emit_top_level_function_declaration(fun),
            statements: ast.statements.iter(),
            statement: |emitter, statement| emitter.emit_statement(statement),
        }
        .emit(&mut self)?;

        let script = self.emit.into_stencil(
            &mut self.compilation_info.script_data_list,
            self.options.extent.clone(),
        )?;

        Ok(script)
    }

    fn emit_top_level_function_declaration(&mut self, fun: &Function) -> Result<(), EmitError> {
        if fun.is_generator {
            return Err(EmitError::NotImplemented("TODO: Generator"));
        }
        if fun.is_async {
            return Err(EmitError::NotImplemented("TODO: Async function"));
        }

        let stencil_index = *self
            .compilation_info
            .function_stencil_indices
            .get(fun)
            .expect("ScriptStencil should be created");

        // NOTE: GCIndex for the function is implicitly handled by
        //       global_or_eval_decl_instantiation.
        LazyFunctionEmitter { stencil_index }.emit(self);

        Ok(())
    }

    fn emit_non_top_level_function_declaration(&mut self, fun: &Function)&nbsp;-> Result<(), EmitError> {
        if fun.is_generator {
            return Err(EmitError::NotImplemented("TODO: Generator"));
        }
        if fun.is_async {
            return Err(EmitError::NotImplemented("TODO: Async function"));
        }

        let stencil_index = *self
            .compilation_info
            .function_stencil_indices
            .get(fun)
            .expect("ScriptStencil should be created");

        let is_annex_b = self
            .compilation_info
            .function_declaration_properties
            .is_annex_b(stencil_index);

        let fun_index = LazyFunctionEmitter { stencil_index }.emit(self);

        let name = self
            .compilation_info
            .scripts
            .get(stencil_index)
            .fun_name()
            .expect("Function declaration should have name");

        if is_annex_b {
            AnnexBFunctionDeclarationEmitter { fun_index, name }.emit(self)?;
        } else {
            LexicalFunctionDeclarationEmitter { fun_index, name }.emit(self)?;
        }

        Ok(())
    }

    fn emit_statement(&mut self, ast: &Statement) -> Result<(), EmitError> {
        match ast {
            Statement::ClassDeclaration(_) => {
                return Err(EmitError::NotImplemented("TODO: ClassDeclaration"));
            }
            Statement::BlockStatement { block, .. } => {
                let scope_data_map = &self.compilation_info.scope_data_map;
                let function_declarations = &self.compilation_info.function_declarations;

                let scope_index = scope_data_map.get_index(block);
                let scope_data = scope_data_map.get_lexical_at(scope_index);

                let functions: Vec<&Function> = scope_data
                    .functions
                    .iter()
                    .map(|key| {
                        *function_declarations
                            .get(key)
                            .expect("function should exist")
                    })
                    .collect();

                BlockEmitter {
                    scope_index: self.compilation_info.scope_data_map.get_index(block),
                    functions: functions.iter(),
                    function: |emitter, fun| emitter.emit_non_top_level_function_declaration(fun),
                    statements: block.statements.iter(),
                    statement: |emitter, statement| emitter.emit_statement(statement),
                }
                .emit(self)?;
            }
            Statement::BreakStatement { label, .. } => {
                BreakEmitter {
                    label: label.as_ref().map(|x| x.value),
                }
                .emit(self);
            }
            Statement::ContinueStatement { label, .. } => {
                ContinueEmitter {
                    label: label.as_ref().map(|x| x.value),
                }
                .emit(self);
            }
            Statement::DebuggerStatement { .. } => {
                self.emit.debugger();
            }
            Statement::DoWhileStatement { block, test, .. } => {
                DoWhileEmitter {
                    enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
                    block: |emitter| emitter.emit_statement(block),
                    test: |emitter| emitter.emit_expression(test),
                }
                .emit(self)?;
            }
            Statement::EmptyStatement { .. } => (),
            Statement::ExpressionStatement(ast) => {
                ExpressionEmitter {
                    expr: |emitter| emitter.emit_expression(ast),
                }
                .emit(self)?;
            }
            Statement::ForInStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: ForInStatement"));
            }
            Statement::ForOfStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: ForOfStatement"));
            }
            Statement::ForStatement {
                init,
                test,
                update,
                block,
                ..
            } => {
                CForEmitter {
                    enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
                    maybe_init: init,
                    maybe_test: test,
                    maybe_update: update,
                    init: |emitter, val| match val {
                        VariableDeclarationOrExpression::VariableDeclaration(ast) => {
                            emitter.emit_variable_declaration_statement(ast)
                        }
                        VariableDeclarationOrExpression::Expression(expr) => {
                            emitter.emit_expression(expr)?;
                            emitter.emit.pop();
                            Ok(())
                        }
                    },
                    test: |emitter, expr| emitter.emit_expression(expr),
                    update: |emitter, expr| {
                        emitter.emit_expression(expr)?;
                        emitter.emit.pop();
                        Ok(())
                    },
                    block: |emitter| emitter.emit_statement(block),
                }
                .emit(self)?;
            }
            Statement::IfStatement(if_statement) => {
                self.emit_if(if_statement)?;
            }
            Statement::LabelledStatement { label, body, .. } => {
                LabelEmitter {
                    enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
                    name: label.value,
                    body: |emitter| emitter.emit_statement(body),
                }
                .emit(self)?;
            }
            Statement::ReturnStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: ReturnStatement"));
            }
            Statement::SwitchStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: SwitchStatement"));
            }
            Statement::SwitchStatementWithDefault { .. } => {
                return Err(EmitError::NotImplemented(
                    "TODO: SwitchStatementWithDefault",
                ));
            }
            Statement::ThrowStatement { expression, .. } => {
                self.emit_expression(expression)?;
                self.emit.throw_();
            }
            Statement::TryCatchStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: TryCatchStatement"));
            }
            Statement::TryFinallyStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: TryFinallyStatement"));
            }
            Statement::VariableDeclarationStatement(ast) => {
                self.emit_variable_declaration_statement(ast)?;
            }
            Statement::WhileStatement { test, block, .. } => {
                WhileEmitter {
                    enclosing_emitter_scope_depth: self.scope_stack.current_depth(),
                    test: |emitter| emitter.emit_expression(test),
                    block: |emitter| emitter.emit_statement(block),
                }
                .emit(self)?;
            }
            Statement::WithStatement { .. } => {
                return Err(EmitError::NotImplemented("TODO: WithStatement"));
            }
            Statement::FunctionDeclaration(_) => {}
        };

        Ok(())
    }

    fn emit_variable_declaration_statement(
        &mut self,
        ast: &VariableDeclaration,
    ) -> Result<(), EmitError> {
        match ast.kind {
            VariableDeclarationKind::Var { .. } => {}
            VariableDeclarationKind::Let { .. } | VariableDeclarationKind::Const { .. } => {}
        }

        for decl in &ast.declarators {
            if let Some(init) = &decl.init {
                self.emit_declaration_assignment(&decl.binding, &init)?;
            }
        }

        Ok(())
    }

    fn emit_declaration_assignment(
        &mut self,
        binding: &Binding,
        init: &Expression,
    ) -> Result<(), EmitError> {
        match binding {
            Binding::BindingIdentifier(binding) => {
                let name = binding.name.value;
                DeclarationEmitter {
                    lhs: |emitter| Ok(NameReferenceEmitter { name }.emit_for_declaration(emitter)),
                    rhs: |emitter| emitter.emit_expression(init),
                }
                .emit(self)?;
                self.emit.pop();
            }
            _ => {
                return Err(EmitError::NotImplemented("BindingPattern"));
            }
        }

        Ok(())
    }

    fn emit_this(&mut self) -> Result<(), EmitError> {
        Err(EmitError::NotImplemented("TODO: this"))
    }

    fn emit_if(&mut self, if_statement: &IfStatement) -> Result<(), EmitError> {
        self.emit_expression(&if_statement.test)?;

        let alternate_jump = ForwardJumpEmitter {
            jump: JumpKind::JumpIfFalse,
        }
        .emit(self);

        // Then branch
        self.emit.jump_target();
        self.emit_statement(&if_statement.consequent)?;

        if let Some(alternate) = &if_statement.alternate {
            let then_jump = ForwardJumpEmitter {
                jump: JumpKind::Goto,
            }
            .emit(self);
            // ^^ part of then branch

            // Else branch
            alternate_jump.patch_not_merge(self);
            self.emit_statement(alternate)?;

            // Merge point after else
            then_jump.patch_merge(self);
        } else {
            // Merge point without else
            alternate_jump.patch_merge(self);
        }

        Ok(())
    }

    fn emit_expression(&mut self, ast: &Expression) -> Result<(), EmitError> {
        match ast {
            Expression::ClassExpression(_) => {
                return Err(EmitError::NotImplemented("TODO: ClassExpression"));
            }

            Expression::LiteralBooleanExpression { value, .. } => {
                self.emit.emit_boolean(*value);
            }

            Expression::LiteralInfinityExpression { .. } => {
                self.emit.double_(std::f64::INFINITY);
            }

            Expression::LiteralNullExpression { .. } => {
                self.emit.null();
            }

            Expression::LiteralNumericExpression(num) => {
                self.emit.numeric(num.value);
            }

            Expression::LiteralRegExpExpression {
                pattern,
                global,
                ignore_case,
                multi_line,
                dot_all,
                sticky,
                unicode,
                ..
            } => {
                let item = RegExpItem {
                    pattern: *pattern,
                    global: *global,
                    ignore_case: *ignore_case,
                    multi_line: *multi_line,
                    dot_all: *dot_all,
                    sticky: *sticky,
                    unicode: *unicode,
                };
                let regexp_index = self.compilation_info.regexps.push(item);
                let index = self.emit.get_regexp_gcthing_index(regexp_index);
                self.emit.reg_exp(index);
            }

            Expression::LiteralStringExpression { value, .. } => {
                let str_index = self.emit.get_atom_gcthing_index(*value);
                self.emit.string(str_index);
            }

            Expression::ArrayExpression(ast) => {
                self.emit_array_expression(ast)?;
            }

            Expression::ArrowExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: ArrowExpression"));
            }

            Expression::AssignmentExpression {
                binding,
                expression,
                ..
            } => {
                self.emit_assignment_expression(binding, expression)?;
            }

            Expression::BinaryExpression {
                operator,
                left,
                right,
                ..
            } => {
                self.emit_binary_expression(operator, left, right)?;
            }

            Expression::CallExpression(CallExpression {
                callee, arguments, ..
            }) => {
                self.emit_call_expression(callee, arguments)?;
            }

            Expression::CompoundAssignmentExpression { .. } => {
                return Err(EmitError::NotImplemented(
                    "TODO: CompoundAssignmentExpression",
                ));
            }

            Expression::ConditionalExpression {
                test,
                consequent,
                alternate,
                ..
            } => {
                self.emit_conditional_expression(test, consequent, alternate)?;
            }

            Expression::FunctionExpression(_) => {
                return Err(EmitError::NotImplemented("TODO: FunctionExpression"));
            }

            Expression::IdentifierExpression(ast) => {
                self.emit_identifier_expression(ast);
            }

            Expression::MemberExpression(ast) => {
                self.emit_member_expression(ast)?;
            }

            Expression::NewExpression {
                callee, arguments, ..
            } => {
                self.emit_new_expression(callee, arguments)?;
            }

            Expression::NewTargetExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: NewTargetExpression"));
            }

            Expression::ObjectExpression(ast) => {
                self.emit_object_expression(ast)?;
            }

            Expression::OptionalChain { .. } => {
                return Err(EmitError::NotImplemented("TODO: OptionalChain"));
            }

            Expression::OptionalExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: OptionalExpression"));
            }

            Expression::UnaryExpression {
                operator, operand, ..
            } => {
                let opcode = match operator {
                    UnaryOperator::Plus { .. } => Opcode::Pos,
                    UnaryOperator::Minus { .. } => Opcode::Neg,
                    UnaryOperator::LogicalNot { .. } => Opcode::Not,
                    UnaryOperator::BitwiseNot { .. } => Opcode::BitNot,
                    UnaryOperator::Void { .. } => Opcode::Void,
                    UnaryOperator::Typeof { .. } => {
                        return Err(EmitError::NotImplemented("TODO: Typeof"));
                    }
                    UnaryOperator::Delete { .. } => {
                        return Err(EmitError::NotImplemented("TODO: Delete"));
                    }
                };
                self.emit_expression(operand)?;
                self.emit.emit_unary_op(opcode);
            }

            Expression::TemplateExpression(_) => {
                return Err(EmitError::NotImplemented("TODO: TemplateExpression"));
            }

            Expression::ThisExpression { .. } => {
                self.emit_this()?;
            }

            Expression::UpdateExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: UpdateExpression"));
            }

            Expression::YieldExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: YieldExpression"));
            }

            Expression::YieldGeneratorExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: YieldGeneratorExpression"));
            }

            Expression::AwaitExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: AwaitExpression"));
            }

            Expression::ImportCallExpression { .. } => {
                return Err(EmitError::NotImplemented("TODO: ImportCallExpression"));
            }
        }

        Ok(())
    }

    fn emit_binary_expression(
        &mut self,
        operator: &BinaryOperator,
        left: &Expression,
        right: &Expression,
    ) -> Result<(), EmitError> {
        let opcode = match operator {
            BinaryOperator::Equals { .. } => Opcode::Eq,
            BinaryOperator::NotEquals { .. } => Opcode::Ne,
            BinaryOperator::StrictEquals { .. } => Opcode::StrictEq,
            BinaryOperator::StrictNotEquals { .. } => Opcode::StrictNe,
            BinaryOperator::LessThan { .. } => Opcode::Lt,
            BinaryOperator::LessThanOrEqual { .. } => Opcode::Le,
            BinaryOperator::GreaterThan { .. } => Opcode::Gt,
            BinaryOperator::GreaterThanOrEqual { .. } => Opcode::Ge,
            BinaryOperator::In { .. } => Opcode::In,
            BinaryOperator::Instanceof { .. } => Opcode::Instanceof,
            BinaryOperator::LeftShift { .. } => Opcode::Lsh,
            BinaryOperator::RightShift { .. } => Opcode::Rsh,
            BinaryOperator::RightShiftExt { .. } => Opcode::Ursh,
            BinaryOperator::Add { .. } => Opcode::Add,
            BinaryOperator::Sub { .. } => Opcode::Sub,
            BinaryOperator::Mul { .. } => Opcode::Mul,
            BinaryOperator::Div { .. } => Opcode::Div,
            BinaryOperator::Mod { .. } => Opcode::Mod,
            BinaryOperator::Pow { .. } => Opcode::Pow,
            BinaryOperator::BitwiseOr { .. } => Opcode::BitOr,
            BinaryOperator::BitwiseXor { .. } => Opcode::BitXor,
            BinaryOperator::BitwiseAnd { .. } => Opcode::BitAnd,

            BinaryOperator::Coalesce { .. } => {
                self.emit_short_circuit(JumpKind::Coalesce, left, right)?;
                return Ok(());
            }
            BinaryOperator::LogicalOr { .. } => {
                self.emit_short_circuit(JumpKind::LogicalOr, left, right)?;
                return Ok(());
            }
            BinaryOperator::LogicalAnd { .. } => {
                self.emit_short_circuit(JumpKind::LogicalAnd, left, right)?;
                return Ok(());
            }

            BinaryOperator::Comma { .. } => {
                self.emit_expression(left)?;
                self.emit.pop();
                self.emit_expression(right)?;
                return Ok(());
            }
        };

        self.emit_expression(left)?;
        self.emit_expression(right)?;
        self.emit.emit_binary_op(opcode);
        Ok(())
    }

    fn emit_short_circuit(
        &mut self,
        jump: JumpKind,
        left: &Expression,
        right: &Expression,
    ) -> Result<(), EmitError> {
        self.emit_expression(left)?;
        let jump = ForwardJumpEmitter { jump: jump }.emit(self);
        self.emit.pop();
        self.emit_expression(right)?;
        jump.patch_merge(self);
        return Ok(());
    }

    fn emit_object_expression(&mut self, object: &ObjectExpression) -> Result<(), EmitError> {
        ObjectEmitter {
            properties: object.properties.iter(),
            prop: |emitter, state, prop| emitter.emit_object_property(state, prop),
        }
        .emit(self)
    }

    fn emit_object_property(
        &mut self,
        state: &mut ObjectEmitterState,
        property: &ObjectProperty,
    ) -> Result<(), EmitError> {
        match property {
            ObjectProperty::NamedObjectProperty(NamedObjectProperty::DataProperty(
                DataProperty {
                    property_name,
                    expression: prop_value,
                    ..
                },
            )) => match property_name {
                PropertyName::StaticPropertyName(StaticPropertyName { value, .. }) => {
                    NamePropertyEmitter {
                        state,
                        key: *value,
                        value: |emitter| emitter.emit_expression(prop_value),
                    }
                    .emit(self)?;
                }
                PropertyName::StaticNumericPropertyName(NumericLiteral { value, .. }) => {
                    IndexPropertyEmitter {
                        state,
                        key: *value,
                        value: |emitter| emitter.emit_expression(prop_value),
                    }
                    .emit(self)?;
                }
                PropertyName::ComputedPropertyName(ComputedPropertyName {
                    expression: prop_key,
                    ..
                }) => {
                    ComputedPropertyEmitter {
                        state,
                        key: |emitter| emitter.emit_expression(prop_key),
                        value: |emitter| emitter.emit_expression(prop_value),
                    }
                    .emit(self)?;
                }
            },
            _ => return Err(EmitError::NotImplemented("TODO: non data property")),
        }
        Ok(())
    }

    fn emit_array_expression(&mut self, array: &ArrayExpression) -> Result<(), EmitError> {
        ArrayEmitter {
            elements: array.elements.iter(),
            elem_kind: |e| match e {
                ArrayExpressionElement::Expression(..) => ArrayElementKind::Normal,
                ArrayExpressionElement::Elision { .. } => ArrayElementKind::Elision,
                ArrayExpressionElement::SpreadElement(..) => ArrayElementKind::Spread,
            },
            elem: |emitter, state, elem| {
                match elem {
                    ArrayExpressionElement::Expression(expr) => {
                        ArrayElementEmitter {
                            state,
                            elem: |emitter| emitter.emit_expression(expr),
                        }
                        .emit(emitter)?;
                    }
                    ArrayExpressionElement::Elision { .. } => {
                        ArrayElisionEmitter { state }.emit(emitter);
                    }
                    ArrayExpressionElement::SpreadElement(expr) => {
                        ArraySpreadEmitter {
                            state,
                            elem: |emitter| emitter.emit_expression(expr),
                        }
                        .emit(emitter)?;
                    }
                }
                Ok(())
            },
        }
        .emit(self)
    }

    fn emit_conditional_expression(
        &mut self,
        test: &Expression,
        consequent: &Expression,
        alternate: &Expression,
    ) -> Result<(), EmitError> {
        self.emit_expression(test)?;

        let else_jump = ForwardJumpEmitter {
            jump: JumpKind::JumpIfFalse,
        }
        .emit(self);

        // Then branch
        self.emit.jump_target();
        self.emit_expression(consequent)?;

        let finally_jump = ForwardJumpEmitter {
            jump: JumpKind::Goto,
        }
        .emit(self);

        // Else branch
        else_jump.patch_not_merge(self);
        self.emit_expression(alternate)?;

        // Merge point
        finally_jump.patch_merge(self);

        Ok(())
    }

    fn emit_assignment_expression(
        &mut self,
        binding: &AssignmentTarget,
        expression: &Expression,
    ) -> Result<(), EmitError> {
        AssignmentEmitter {
            lhs: |emitter| match binding {
                AssignmentTarget::SimpleAssignmentTarget(
                    SimpleAssignmentTarget::AssignmentTargetIdentifier(
                        AssignmentTargetIdentifier { name, .. },
                    ),
                ) => Ok(NameReferenceEmitter { name: name.value }.emit_for_assignment(emitter)),
                _ => Err(EmitError::NotImplemented(
                    "non-identifier assignment target",
                )),
            },
            rhs: |emitter| emitter.emit_expression(expression),
        }
        .emit(self)
    }

    fn emit_identifier_expression(&mut self, ast: &IdentifierExpression) {
        let name = ast.name.value;
        GetNameEmitter { name }.emit(self);
    }

    fn emit_member_expression(&mut self, ast: &MemberExpression) -> Result<(), EmitError> {
        match ast {
            MemberExpression::ComputedMemberExpression(ComputedMemberExpression {
                object: ExpressionOrSuper::Expression(object),
                expression,
                ..
            }) => GetElemEmitter {
                obj: |emitter| emitter.emit_expression(object),
                key: |emitter| emitter.emit_expression(expression),
            }
            .emit(self),

            MemberExpression::ComputedMemberExpression(ComputedMemberExpression {
                object: ExpressionOrSuper::Super { .. },
                expression,
                ..
            }) => GetSuperElemEmitter {
                this: |emitter| emitter.emit_this(),
                key: |emitter| emitter.emit_expression(expression),
            }
            .emit(self),

            MemberExpression::StaticMemberExpression(StaticMemberExpression {
                object: ExpressionOrSuper::Expression(object),
                property,
                ..
            }) => GetPropEmitter {
                obj: |emitter| emitter.emit_expression(object),
                key: property.value,
            }
            .emit(self),

            MemberExpression::StaticMemberExpression(StaticMemberExpression {
                object: ExpressionOrSuper::Super { .. },
                property,
                ..
            }) => GetSuperPropEmitter {
                this: |emitter| emitter.emit_this(),
                key: property.value,
            }
            .emit(self),

            MemberExpression::PrivateFieldExpression(PrivateFieldExpression { .. }) => {
                Err(EmitError::NotImplemented("PrivateFieldExpression"))
            }
        }
    }

    fn emit_new_expression(
        &mut self,
        callee: &Expression,
        arguments: &Arguments,
    ) -> Result<(), EmitError> {
        for arg in &arguments.args {
            if let Argument::SpreadElement(_) = arg {
                return Err(EmitError::NotImplemented("TODO: SpreadNew"));
            }
        }

        NewEmitter {
            callee: |emitter| emitter.emit_expression(callee),
            arguments: |emitter| {
                emitter.emit_arguments(arguments)?;
                Ok(arguments.args.len())
            },
        }
        .emit(self)?;

        Ok(())
    }

    fn emit_call_expression(
        &mut self,
        callee: &ExpressionOrSuper,
        arguments: &Arguments,
    ) -> Result<(), EmitError> {
        // Don't do super handling in an emit_expresion_or_super because the bytecode heavily
        // depends on how you're using the super

        CallEmitter {
            callee: |emitter| match callee {
                ExpressionOrSuper::Expression(expr) => match &**expr {
                    Expression::IdentifierExpression(IdentifierExpression { name, .. }) => {
                        if name.value == CommonSourceAtomSetIndices::eval() {
                            return Err(EmitError::NotImplemented("TODO: direct eval"));
                        }
                        Ok(NameReferenceEmitter { name: name.value }.emit_for_call(emitter))
                    }

                    Expression::MemberExpression(MemberExpression::StaticMemberExpression(
                        StaticMemberExpression {
                            object: ExpressionOrSuper::Expression(object),
                            property,
                            ..
                        },
                    )) => PropReferenceEmitter {
                        obj: |emitter| emitter.emit_expression(object),
                        key: property.value,
                    }
                    .emit_for_call(emitter),

                    Expression::MemberExpression(MemberExpression::ComputedMemberExpression(
                        ComputedMemberExpression {
                            object: ExpressionOrSuper::Expression(object),
                            expression,
                            ..
                        },
                    )) => ElemReferenceEmitter {
                        obj: |emitter| emitter.emit_expression(object),
                        key: |emitter| emitter.emit_expression(expression),
                    }
                    .emit_for_call(emitter),

                    _ => {
                        return Err(EmitError::NotImplemented(
                            "TODO: Call (only global functions are supported)",
                        ));
                    }
                },
                _ => {
                    return Err(EmitError::NotImplemented("TODO: Super"));
                }
            },
            arguments: |emitter| {
                emitter.emit_arguments(arguments)?;
                Ok(arguments.args.len())
            },
        }
        .emit(self)?;

        Ok(())
    }

    fn emit_arguments(&mut self, ast: &Arguments) -> Result<(), EmitError> {
        for argument in &ast.args {
            self.emit_argument(argument)?;
        }

        Ok(())
    }

    fn emit_argument(&mut self, ast: &Argument) -> Result<(), EmitError> {
        match ast {
            Argument::Expression(ast) => self.emit_expression(ast)?,
            Argument::SpreadElement(_) => {
                return Err(EmitError::NotImplemented("TODO: SpreadElement"));
            }
        }

        Ok(())
    }
}

Messung V0.5 in Prozent
C=99 H=100 G=99

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik