feat: async/await 语法支持(AWAIT 帧快照挂起/恢复 + 微任务驱动 + AsyncFunction intrinsics)
This commit is contained in:
@@ -98,18 +98,36 @@ impl Emitter {
|
||||
.map(|c| ("@@class_brand", *c))
|
||||
.into_iter()
|
||||
.collect();
|
||||
let mut method_module = self.compile_function_body_with_field_hooks(
|
||||
¶m_names,
|
||||
body_stmts,
|
||||
ctx,
|
||||
false,
|
||||
self_binding,
|
||||
FunctionBodyContext::ClassElement,
|
||||
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
|
||||
false,
|
||||
&[],
|
||||
&extra_uv,
|
||||
)?;
|
||||
let method_value = method.value.as_ref();
|
||||
let mut method_module = if method_value.r#async {
|
||||
self.compile_function_body_with_field_hooks_gen(
|
||||
¶m_names,
|
||||
body_stmts,
|
||||
ctx,
|
||||
false,
|
||||
self_binding,
|
||||
FunctionBodyContext::ClassElement,
|
||||
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
|
||||
false,
|
||||
&[],
|
||||
&extra_uv,
|
||||
false,
|
||||
true,
|
||||
)?
|
||||
} else {
|
||||
self.compile_function_body_with_field_hooks(
|
||||
¶m_names,
|
||||
body_stmts,
|
||||
ctx,
|
||||
false,
|
||||
self_binding,
|
||||
FunctionBodyContext::ClassElement,
|
||||
None::<fn(&Emitter, &mut CompileCtx) -> Result<(), String>>,
|
||||
false,
|
||||
&[],
|
||||
&extra_uv,
|
||||
)?
|
||||
};
|
||||
ctx.in_instance_method = saved_instance;
|
||||
ctx.in_static_method = saved_static;
|
||||
// 访问器函数名带 "get "/"set " 前缀(SetFunctionName 语义),普通方法裸属性名。
|
||||
|
||||
@@ -579,6 +579,11 @@ impl Emitter {
|
||||
self.collect_capture_names_expr(a, ref_set, shadow, out);
|
||||
}
|
||||
}
|
||||
// await 表达式:被等待的值里引用的父变量须纳入捕获(与 yield 同因——
|
||||
// 异步体挂起恢复后寄存器已被覆盖,只能经 cell 读取)。
|
||||
Expression::AwaitExpression(ae) => {
|
||||
self.collect_capture_names_expr(&ae.argument, ref_set, shadow, out);
|
||||
}
|
||||
Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out),
|
||||
_ => {}
|
||||
}
|
||||
@@ -891,6 +896,7 @@ impl Emitter {
|
||||
self.collect_captured_expr(a, own, out);
|
||||
}
|
||||
}
|
||||
Expression::AwaitExpression(ae) => self.collect_captured_expr(&ae.argument, own, out),
|
||||
Expression::ChainExpression(c) => self.collect_captured_chain(&c.expression, own, out),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ pub struct CompileCtx {
|
||||
pub(crate) in_static_method: bool,
|
||||
/// 本函数是否为生成器函数体(`function*`),`assemble_ir` 回写到 IR。
|
||||
pub(crate) is_generator: bool,
|
||||
/// 本函数是否为异步函数体(`async function` / async 箭头),`assemble_ir` 回写到 IR。
|
||||
pub(crate) is_async: bool,
|
||||
pub(crate) static_block_this_reg: Option<u8>,
|
||||
pub(crate) field_buffer: Option<FieldBuffer>,
|
||||
/// 类构造器模块中 `@@field_keys` upvalue 下标(实例字段 computed key 数组)。
|
||||
@@ -265,6 +267,7 @@ impl CompileCtx {
|
||||
in_instance_method: false,
|
||||
in_static_method: false,
|
||||
is_generator: false,
|
||||
is_async: false,
|
||||
static_block_this_reg: None,
|
||||
field_buffer: None,
|
||||
field_keys_uv: None,
|
||||
@@ -607,6 +610,7 @@ impl CompileCtx {
|
||||
is_derived_constructor: false,
|
||||
needs_home_object: false,
|
||||
is_generator: self.is_generator,
|
||||
is_async: self.is_async,
|
||||
captured_this_const_idx: 0,
|
||||
function_name: None,
|
||||
function_length: self.function_length,
|
||||
@@ -705,19 +709,36 @@ impl Emitter {
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
is_expression_body: bool, is_arrow: bool,
|
||||
) -> Result<IRFunction, String> {
|
||||
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, is_expression_body, is_arrow, false)
|
||||
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, is_expression_body, is_arrow, false, false)
|
||||
}
|
||||
|
||||
/// 编译函数体并显式指定生成器标志(`function*` 走此入口)。
|
||||
pub(crate) fn compile_generator_body<'a>(
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
) -> Result<IRFunction, String> {
|
||||
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true)
|
||||
self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, false)
|
||||
}
|
||||
|
||||
/// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使
|
||||
/// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。
|
||||
pub(crate) fn compile_async_body<'a>(
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
is_expression_body: bool, is_arrow: bool,
|
||||
) -> Result<IRFunction, String> {
|
||||
self.compile_function_body_with_flags(
|
||||
param_specs,
|
||||
body_stmts,
|
||||
parent_ctx,
|
||||
is_expression_body,
|
||||
is_arrow,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
fn compile_function_body_with_flags<'a>(
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
is_expression_body: bool, is_arrow: bool, is_generator: bool,
|
||||
is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool,
|
||||
) -> Result<IRFunction, String> {
|
||||
let body_context = if is_arrow {
|
||||
FunctionBodyContext::Arrow
|
||||
@@ -732,6 +753,7 @@ impl Emitter {
|
||||
&[],
|
||||
body_context,
|
||||
is_generator,
|
||||
is_async,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -739,7 +761,7 @@ impl Emitter {
|
||||
pub(crate) fn compile_function_body_with_bindings_gen<'a>(
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext,
|
||||
is_generator: bool,
|
||||
is_generator: bool, is_async: bool,
|
||||
) -> Result<IRFunction, String> {
|
||||
self.compile_function_body_with_field_hooks_gen(
|
||||
param_specs,
|
||||
@@ -753,6 +775,7 @@ impl Emitter {
|
||||
&[],
|
||||
&[],
|
||||
is_generator,
|
||||
is_async,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -785,6 +808,7 @@ impl Emitter {
|
||||
extra_capture_exprs,
|
||||
extra_upvalue_names,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -793,13 +817,14 @@ impl Emitter {
|
||||
&self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx,
|
||||
is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext,
|
||||
mut emit_fields: Option<E>, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>],
|
||||
extra_upvalue_names: &[(&str, u8)], is_generator: bool,
|
||||
extra_upvalue_names: &[(&str, u8)], is_generator: bool, is_async: bool,
|
||||
) -> Result<IRFunction, String>
|
||||
where
|
||||
E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>,
|
||||
{
|
||||
let mut ctx = CompileCtx::new();
|
||||
ctx.is_generator = is_generator;
|
||||
ctx.is_async = is_async;
|
||||
|
||||
// length = 第一个带默认值形参之前的形参数(解构默认与标识符默认同规则);
|
||||
// rest 参数不在 param_specs 中(独立字段),天然不计入。
|
||||
@@ -1158,6 +1183,7 @@ impl Emitter {
|
||||
| Expression::NewExpression(_) => self.emit_function_domain(expr, ctx),
|
||||
Expression::Identifier(ident) => self.emit_identifier_expression(ident, ctx),
|
||||
Expression::YieldExpression(ye) => self.emit_yield_expression(ye, ctx),
|
||||
Expression::AwaitExpression(ae) => self.emit_await_expression(ae, ctx),
|
||||
Expression::CallExpression(_) => self.emit_call_domain(expr, ctx),
|
||||
Expression::ThisExpression(_) => self.emit_this_expression(ctx),
|
||||
Expression::SequenceExpression(seq) => self.emit_sequence_expression(seq, ctx),
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//! `await` 表达式 emit:求值被等待的值后发 `AWAIT` 指令,结果经 reg 0 交付。
|
||||
|
||||
use crate::{CompileCtx, Emitter};
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_ir::inst::Inst;
|
||||
use oxide_ir::operand::Operand;
|
||||
use oxide_parser::AwaitExpression;
|
||||
|
||||
impl Emitter {
|
||||
pub(crate) fn emit_await_expression(
|
||||
&self, ae: &AwaitExpression, ctx: &mut CompileCtx,
|
||||
) -> Result<u32, String> {
|
||||
// 求值被等待的值(`await undefined` 时求值 undefined)。
|
||||
let value_reg = self.emit_expression(&ae.argument, ctx)?;
|
||||
ctx.inst(Inst::await_expr(Operand::Reg(value_reg)));
|
||||
// promise settle 后恢复值经 reg 0 交付(与 YIELD/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)
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,11 @@ impl Emitter {
|
||||
let body_stmts = &arrow.body.statements;
|
||||
let is_expr_body = arrow.expression;
|
||||
|
||||
let mut sub_module = self.compile_function_body(¶m_names, body_stmts, ctx, is_expr_body, true)?;
|
||||
let mut sub_module = if arrow.r#async {
|
||||
self.compile_async_body(¶m_names, body_stmts, ctx, is_expr_body, true)?
|
||||
} else {
|
||||
self.compile_function_body(¶m_names, body_stmts, ctx, is_expr_body, true)?
|
||||
};
|
||||
sub_module.is_arrow = true;
|
||||
|
||||
ctx.nested.push(sub_module);
|
||||
@@ -78,6 +82,8 @@ impl Emitter {
|
||||
|
||||
let mut sub_module = if fe.generator {
|
||||
self.compile_generator_body(¶m_names, body_stmts, ctx)?
|
||||
} else if fe.r#async {
|
||||
self.compile_async_body(¶m_names, body_stmts, ctx, false, false)?
|
||||
} else {
|
||||
self.compile_function_body(¶m_names, body_stmts, ctx, false, false)?
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::{CompileCtx, Emitter};
|
||||
use oxide_parser::Expression;
|
||||
|
||||
pub mod assignment;
|
||||
pub mod await_expr;
|
||||
pub mod call;
|
||||
pub mod function;
|
||||
pub mod identifier;
|
||||
|
||||
@@ -216,6 +216,12 @@ impl Emitter {
|
||||
self.pre_scan_builtin_chain(&chain.expression, ctx);
|
||||
}
|
||||
Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx),
|
||||
Expression::YieldExpression(ye) => {
|
||||
if let Some(a) = &ye.argument {
|
||||
self.pre_scan_builtin_expr(a, ctx);
|
||||
}
|
||||
}
|
||||
Expression::AwaitExpression(ae) => self.pre_scan_builtin_expr(&ae.argument, ctx),
|
||||
Expression::ArrowFunctionExpression(_)
|
||||
| Expression::FunctionExpression(_)
|
||||
| Expression::ClassExpression(_) => {}
|
||||
|
||||
@@ -35,6 +35,8 @@ impl Emitter {
|
||||
let body_stmts: &[Statement] = if let Some(body) = &fd.body { &body.statements } else { &[] };
|
||||
let mut sub_module = if fd.generator {
|
||||
self.compile_generator_body(¶m_names, body_stmts, ctx)?
|
||||
} else if fd.r#async {
|
||||
self.compile_async_body(¶m_names, body_stmts, ctx, false, false)?
|
||||
} else {
|
||||
self.compile_function_body(¶m_names, body_stmts, ctx, false, false)?
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user