From 8a2135897e405ffd4576fd3f4fcccae5ebc1f9cc Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Fri, 23 Oct 2026 20:14:15 +0800 Subject: [PATCH] feat: compile Endor await expressions through the source pipeline --- crates/compiler/src/analysis.rs | 4 +++- crates/compiler/src/codegen.rs | 4 ++++ crates/frontend/Endor.asdl | 1 + crates/frontend/editor/ast.schema.json | 20 ++++++++++++++++++-- crates/frontend/editor/ast.ts | 7 +++++-- crates/frontend/src/ast/generated.rs | 3 ++- crates/frontend/src/ast/visitor.rs | 3 +++ crates/frontend/src/grammar.peg | 3 +++ 8 files changed, 39 insertions(+), 6 deletions(-) diff --git a/crates/compiler/src/analysis.rs b/crates/compiler/src/analysis.rs index 80c5025..80ed0aa 100644 --- a/crates/compiler/src/analysis.rs +++ b/crates/compiler/src/analysis.rs @@ -332,7 +332,9 @@ impl Builder { binding, }); } - ExprKind::Unary { operand, .. } => self.expression(operand, globals)?, + ExprKind::Unary { operand, .. } | ExprKind::Await { operand } => { + self.expression(operand, globals)? + } ExprKind::Binary { left, right, .. } => { self.expression(left, globals)?; self.expression(right, globals)?; diff --git a/crates/compiler/src/codegen.rs b/crates/compiler/src/codegen.rs index 78e3ae5..6854569 100644 --- a/crates/compiler/src/codegen.rs +++ b/crates/compiler/src/codegen.rs @@ -300,6 +300,10 @@ impl<'a> Emitter<'a> { } self.emit(Opcode::Call, arguments.len())?; } + ExprKind::Await { operand } => { + self.expression(operand)?; + self.simple(Opcode::Await); + } ExprKind::Member { object, name } => { self.expression(object)?; self.emit(Opcode::LoadAttr, self.name_index(&name.text))?; diff --git a/crates/frontend/Endor.asdl b/crates/frontend/Endor.asdl index 04a44b4..395356a 100644 --- a/crates/frontend/Endor.asdl +++ b/crates/frontend/Endor.asdl @@ -35,6 +35,7 @@ module Endor { | Number(string spelling) | String(string value) | Symbol(Name name) + | Await(Expr operand) | Unary(UnaryOp operation, Expr operand) | Binary(BinaryOp operation, Expr left, Expr right) | Member(Expr object, Name name) diff --git a/crates/frontend/editor/ast.schema.json b/crates/frontend/editor/ast.schema.json index 72c4dba..d6c0f36 100644 --- a/crates/frontend/editor/ast.schema.json +++ b/crates/frontend/editor/ast.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "urn:endor:ast:sha256:ad2ac52943dd26e08395c0d2698861da98bb89c360241c4712c769de86709fd0", + "$id": "urn:endor:ast:sha256:c7c10c6a61158810fa55044f1aa79f3558ac18ca3be59cbf7f2499b5add8df5b", "$ref": "#/$defs/AstDocument", "$defs": { "Span": { @@ -27,7 +27,7 @@ "type": "object", "properties": { "schema": { - "const": "urn:endor:ast:sha256:ad2ac52943dd26e08395c0d2698861da98bb89c360241c4712c769de86709fd0" + "const": "urn:endor:ast:sha256:c7c10c6a61158810fa55044f1aa79f3558ac18ca3be59cbf7f2499b5add8df5b" }, "root": { "$ref": "#/$defs/AstRoot" @@ -591,6 +591,22 @@ ], "additionalProperties": false }, + { + "type": "object", + "properties": { + "kind": { + "const": "Await" + }, + "data": { + "$ref": "#/$defs/Expr" + } + }, + "required": [ + "kind", + "data" + ], + "additionalProperties": false + }, { "type": "object", "properties": { diff --git a/crates/frontend/editor/ast.ts b/crates/frontend/editor/ast.ts index 50e9516..f4a5f89 100644 --- a/crates/frontend/editor/ast.ts +++ b/crates/frontend/editor/ast.ts @@ -1,6 +1,6 @@ // Generated by scripts/generate_ast.py from Endor.asdl. Do not edit. -export const AST_SCHEMA_ID = "urn:endor:ast:sha256:ad2ac52943dd26e08395c0d2698861da98bb89c360241c4712c769de86709fd0" as const; +export const AST_SCHEMA_ID = "urn:endor:ast:sha256:c7c10c6a61158810fa55044f1aa79f3558ac18ca3be59cbf7f2499b5add8df5b" as const; export interface Span { start: number; end: number; } export type AstDocument = { schema: typeof AST_SCHEMA_ID; root: AstRoot; }; export type AstRoot = { kind: "Module"; data: Program; } | { kind: "Expression"; data: Expr; } | { kind: "Interactive"; data: InteractiveInput; }; @@ -20,7 +20,7 @@ export type MemberAssignment = { object: Expr; name: Name; value: Expr; span: Sp export type ReturnStatement = { value?: Expr | null; span: Span; }; export type InteractiveInput = { statements: Array; span: Span; }; export type Expr = { kind: ExprKind; span: Span; }; -export type ExprKind = { kind: "Name"; data: string; } | { kind: "Number"; data: string; } | { kind: "String"; data: string; } | { kind: "Symbol"; data: Name; } | { kind: "Unary"; data: { operation: UnaryOp; operand: Expr; }; } | { kind: "Binary"; data: { operation: BinaryOp; left: Expr; right: Expr; }; } | { kind: "Member"; data: { object: Expr; name: Name; }; } | { kind: "Call"; data: { callee: Expr; arguments: Array; }; }; +export type ExprKind = { kind: "Name"; data: string; } | { kind: "Number"; data: string; } | { kind: "String"; data: string; } | { kind: "Symbol"; data: Name; } | { kind: "Await"; data: Expr; } | { kind: "Unary"; data: { operation: UnaryOp; operand: Expr; }; } | { kind: "Binary"; data: { operation: BinaryOp; left: Expr; right: Expr; }; } | { kind: "Member"; data: { object: Expr; name: Name; }; } | { kind: "Call"; data: { callee: Expr; arguments: Array; }; }; export type UnaryOp = "Negate"; export type BinaryOp = "Add" | "Subtract" | "Multiply" | "Divide"; export interface Visitor { @@ -192,6 +192,9 @@ break; case "Symbol": walkName(node.data, visitor); break; +case "Await": +walkExpr(node.data, visitor); +break; case "Unary": walkUnaryOp(node.data.operation, visitor); walkExpr(node.data.operand, visitor); diff --git a/crates/frontend/src/ast/generated.rs b/crates/frontend/src/ast/generated.rs index d654a99..8350ce2 100644 --- a/crates/frontend/src/ast/generated.rs +++ b/crates/frontend/src/ast/generated.rs @@ -3,7 +3,7 @@ use super::Spanned; use crate::Span; pub const AST_SCHEMA_ID: &str = - "urn:endor:ast:sha256:ad2ac52943dd26e08395c0d2698861da98bb89c360241c4712c769de86709fd0"; + "urn:endor:ast:sha256:c7c10c6a61158810fa55044f1aa79f3558ac18ca3be59cbf7f2499b5add8df5b"; #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields)] pub struct AstDocument { @@ -234,6 +234,7 @@ pub enum ExprKind { Number(String), String(String), Symbol(Name), + Await(Box), Unary { operation: UnaryOp, operand: Box, diff --git a/crates/frontend/src/ast/visitor.rs b/crates/frontend/src/ast/visitor.rs index 285214a..b430f7d 100644 --- a/crates/frontend/src/ast/visitor.rs +++ b/crates/frontend/src/ast/visitor.rs @@ -316,6 +316,9 @@ pub fn walk_expr_kind( ExprKind::Symbol(value) => { visitor.visit_name(value)?; } + ExprKind::Await(value) => { + visitor.visit_expr(value)?; + } ExprKind::Unary { operation, operand, .. } => { diff --git a/crates/frontend/src/grammar.peg b/crates/frontend/src/grammar.peg index 97f9543..163b591 100644 --- a/crates/frontend/src/grammar.peg +++ b/crates/frontend/src/grammar.peg @@ -146,6 +146,9 @@ peg::parser! { left:(@) star() right:@ { binary(left, BinaryOp::Multiply, right) } left:(@) slash() right:@ { binary(left, BinaryOp::Divide, right) } -- + start:keyword("await") operand:@ { + Expr { span: start.through(operand.span), kind: ExprKind::Await { operand: Box::new(operand) } } + } start:minus() operand:@ { Expr { span: start.through(operand.span), kind: ExprKind::Unary { operation: UnaryOp::Negate, operand: Box::new(operand) } } }