/* * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include namespace JS { Optional ASTNode::generate_bytecode(Bytecode::Generator&) const { dbgln("Missing generate_bytecode()"); TODO(); } Optional ScopeNode::generate_bytecode(Bytecode::Generator& generator) const { generator.emit(*this); for (auto& child : children()) { [[maybe_unused]] auto reg = child.generate_bytecode(generator); } return {}; } Optional ExpressionStatement::generate_bytecode(Bytecode::Generator& generator) const { return m_expression->generate_bytecode(generator); } Optional BinaryExpression::generate_bytecode(Bytecode::Generator& generator) const { auto lhs_reg = m_lhs->generate_bytecode(generator); auto rhs_reg = m_rhs->generate_bytecode(generator); VERIFY(lhs_reg.has_value()); VERIFY(rhs_reg.has_value()); auto dst_reg = generator.allocate_register(); switch (m_op) { case BinaryOp::Addition: generator.emit(dst_reg, *lhs_reg, *rhs_reg); return dst_reg; case BinaryOp::Subtraction: generator.emit(dst_reg, *lhs_reg, *rhs_reg); return dst_reg; case BinaryOp::LessThan: generator.emit(dst_reg, *lhs_reg, *rhs_reg); return dst_reg; case BinaryOp::AbstractInequals: generator.emit(dst_reg, *lhs_reg, *rhs_reg); return dst_reg; case BinaryOp::AbstractEquals: generator.emit(dst_reg, *lhs_reg, *rhs_reg); return dst_reg; default: TODO(); } } Optional NumericLiteral::generate_bytecode(Bytecode::Generator& generator) const { auto dst = generator.allocate_register(); generator.emit(dst, m_value); return dst; } Optional StringLiteral::generate_bytecode(Bytecode::Generator& generator) const { auto dst = generator.allocate_register(); generator.emit(dst, m_value); return dst; } Optional Identifier::generate_bytecode(Bytecode::Generator& generator) const { auto reg = generator.allocate_register(); generator.emit(reg, m_string); return reg; } Optional AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) const { if (is(*m_lhs)) { auto& identifier = static_cast(*m_lhs); auto rhs_reg = m_rhs->generate_bytecode(generator); VERIFY(rhs_reg.has_value()); generator.emit(identifier.string(), *rhs_reg); return rhs_reg; } if (is(*m_lhs)) { auto& expression = static_cast(*m_lhs); auto object_reg = expression.object().generate_bytecode(generator); if (expression.is_computed()) { TODO(); } else { VERIFY(is(expression.property())); auto rhs_reg = m_rhs->generate_bytecode(generator); generator.emit(*object_reg, static_cast(expression.property()).string(), *rhs_reg); return rhs_reg; } } TODO(); } Optional WhileStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.begin_continuable_scope(); auto test_label = generator.make_label(); auto test_result_reg = m_test->generate_bytecode(generator); VERIFY(test_result_reg.has_value()); auto& test_jump = generator.emit(*test_result_reg); auto body_result_reg = m_body->generate_bytecode(generator); generator.emit(test_label); test_jump.set_target(generator.make_label()); generator.end_continuable_scope(); return body_result_reg; } Optional DoWhileStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.begin_continuable_scope(); auto head_label = generator.make_label(); auto body_result_reg = m_body->generate_bytecode(generator); generator.end_continuable_scope(); auto test_result_reg = m_test->generate_bytecode(generator); VERIFY(test_result_reg.has_value()); generator.emit(*test_result_reg, head_label); return body_result_reg; } Optional ObjectExpression::generate_bytecode(Bytecode::Generator& generator) const { auto reg = generator.allocate_register(); generator.emit(reg); if (!m_properties.is_empty()) { TODO(); } return reg; } Optional MemberExpression::generate_bytecode(Bytecode::Generator& generator) const { auto object_reg = object().generate_bytecode(generator); if (is_computed()) { TODO(); } else { VERIFY(is(property())); auto dst_reg = generator.allocate_register(); generator.emit(dst_reg, *object_reg, static_cast(property()).string()); return dst_reg; } } Optional FunctionDeclaration::generate_bytecode(Bytecode::Generator&) const { return {}; } Optional CallExpression::generate_bytecode(Bytecode::Generator& generator) const { auto callee_reg = m_callee->generate_bytecode(generator); // FIXME: Load the correct 'this' value into 'this_reg'. auto this_reg = generator.allocate_register(); generator.emit(this_reg, js_undefined()); Vector argument_registers; for (auto& arg : m_arguments) argument_registers.append(*arg.value->generate_bytecode(generator)); auto dst_reg = generator.allocate_register(); generator.emit(dst_reg, *callee_reg, this_reg, argument_registers); return dst_reg; } Optional ReturnStatement::generate_bytecode(Bytecode::Generator& generator) const { Optional argument_reg; if (m_argument) argument_reg = m_argument->generate_bytecode(generator); generator.emit(argument_reg); return argument_reg; } Optional IfStatement::generate_bytecode(Bytecode::Generator& generator) const { auto predicate_reg = m_predicate->generate_bytecode(generator); auto& if_jump = generator.emit(*predicate_reg); auto& else_jump = generator.emit(*predicate_reg); if_jump.set_target(generator.make_label()); (void)m_consequent->generate_bytecode(generator); auto& end_jump = generator.emit(); else_jump.set_target(generator.make_label()); if (m_alternate) { (void)m_alternate->generate_bytecode(generator); } end_jump.set_target(generator.make_label()); // FIXME: Do we need IfStatement to return the consequent/alternate result value? // (That's what the AST interpreter currently does) return {}; } Optional ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.emit(generator.nearest_continuable_scope()); return {}; } }