feat: 生成器基础支持(YIELD 帧快照挂起/恢复 + GeneratorPrototype next/return/throw)
- 新增 YIELD/SUSPEND_BODY opcode;function* 识别与 yield emit - GeneratorState 全量快照 VM 执行上下文(regs/pc/bytecode/spill/save/try/cell 栈段/迭代器) - 调用时参数初始化(默认值/解构副作用与异常在 g() 时刻生效) - %GeneratorPrototype%/%GeneratorFunction.prototype% 内建对象与 next/return/throw - session GC trace 生成器状态 JsValues;闭包捕获分析补 yield/赋值目标扫描
This commit is contained in:
@@ -76,7 +76,11 @@ impl Emitter {
|
||||
|
||||
let body_stmts: &[Statement] = if let Some(body) = &fe.body { &body.statements } else { &[] };
|
||||
|
||||
let mut sub_module = self.compile_function_body(¶m_names, body_stmts, ctx, false, false)?;
|
||||
let mut sub_module = if fe.generator {
|
||||
self.compile_generator_body(¶m_names, body_stmts, ctx)?
|
||||
} else {
|
||||
self.compile_function_body(¶m_names, body_stmts, ctx, false, false)?
|
||||
};
|
||||
if let Some(id) = &fe.id {
|
||||
sub_module.function_name = Some(id.name.to_string());
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub mod operator;
|
||||
pub mod parenthesized;
|
||||
pub mod template;
|
||||
pub mod this;
|
||||
pub mod yield_expr;
|
||||
|
||||
impl Emitter {
|
||||
pub(crate) fn emit_unsupported_expression(&self, expr: &Expression, ctx: &mut CompileCtx) -> Result<u32, String> {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//! `yield` 表达式 emit:求值被让出的值后发 `YIELD` 指令,结果经 reg 0 交付。
|
||||
|
||||
use crate::{CompileCtx, Emitter};
|
||||
use oxide_bytecode::module::Constant;
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_ir::inst::Inst;
|
||||
use oxide_ir::operand::Operand;
|
||||
use oxide_parser::YieldExpression;
|
||||
|
||||
impl Emitter {
|
||||
pub(crate) fn emit_yield_expression(&self, ye: &YieldExpression, ctx: &mut CompileCtx) -> Result<u32, String> {
|
||||
// 未支持:`yield*` 委托迭代,后续按 IteratorYield 协议实现。
|
||||
if ye.delegate {
|
||||
return Err("yield* not yet supported".into());
|
||||
}
|
||||
// 求值被让出的值(`yield` 无参数时让出 undefined)。
|
||||
let value_reg = if let Some(arg) = &ye.argument {
|
||||
self.emit_expression(arg, ctx)?
|
||||
} else {
|
||||
let undef_idx = ctx.add_constant(Constant::Undefined);
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(r), undef_idx));
|
||||
r
|
||||
};
|
||||
ctx.inst(Inst::yield_value(Operand::Reg(value_reg)));
|
||||
// 恢复时 `next(v)` 的 v 经 reg 0 交付(与 CALL 同协议)。
|
||||
let result_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::None, Operand::None));
|
||||
Ok(result_reg)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user