From e2379b35b39b051b650cd3bcfc66468c691e5957 Mon Sep 17 00:00:00 2001 From: Selfhosting Dev Date: Wed, 17 Sep 2025 08:10:21 +0900 Subject: [PATCH] ast: add MethodCallExpr/FieldAccessExpr wrappers; builder: adopt wrappers for method/field, and add loop helpers (create_loop_blocks/add_predecessor). No behavior change. --- src/ast/nodes.rs | 48 ++++++++++++++++++++++++++++++++++++++++ src/mir/builder/exprs.rs | 36 ++++++++++-------------------- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/ast/nodes.rs b/src/ast/nodes.rs index 6197bedf..6afd70c6 100644 --- a/src/ast/nodes.rs +++ b/src/ast/nodes.rs @@ -132,3 +132,51 @@ impl From for ASTNode { } } +#[derive(Debug, Clone)] +pub struct MethodCallExpr { + pub object: Box, + pub method: String, + pub arguments: Vec, + pub span: Span, +} + +impl TryFrom for MethodCallExpr { + type Error = ASTNode; + fn try_from(node: ASTNode) -> Result { + match node { + ASTNode::MethodCall { object, method, arguments, span } => + Ok(MethodCallExpr { object, method, arguments, span }), + other => Err(other), + } + } +} + +impl From for ASTNode { + fn from(m: MethodCallExpr) -> Self { + ASTNode::MethodCall { object: m.object, method: m.method, arguments: m.arguments, span: m.span } + } +} + +#[derive(Debug, Clone)] +pub struct FieldAccessExpr { + pub object: Box, + pub field: String, + pub span: Span, +} + +impl TryFrom for FieldAccessExpr { + type Error = ASTNode; + fn try_from(node: ASTNode) -> Result { + match node { + ASTNode::FieldAccess { object, field, span } => + Ok(FieldAccessExpr { object, field, span }), + other => Err(other), + } + } +} + +impl From for ASTNode { + fn from(f: FieldAccessExpr) -> Self { + ASTNode::FieldAccess { object: f.object, field: f.field, span: f.span } + } +} diff --git a/src/mir/builder/exprs.rs b/src/mir/builder/exprs.rs index c8bf09bd..5a41928f 100644 --- a/src/mir/builder/exprs.rs +++ b/src/mir/builder/exprs.rs @@ -1,6 +1,6 @@ // Expression lowering split from builder.rs to keep files lean use super::{ConstValue, MirInstruction, ValueId}; -use crate::ast::{ASTNode, AssignStmt, ReturnStmt, BinaryExpr, CallExpr}; +use crate::ast::{ASTNode, AssignStmt, ReturnStmt, BinaryExpr, CallExpr, MethodCallExpr, FieldAccessExpr}; impl super::MirBuilder { // Main expression dispatcher @@ -39,32 +39,19 @@ impl super::MirBuilder { ASTNode::Me { .. } => self.build_me_expression(), - ASTNode::MethodCall { - object, - method, - arguments, - .. - } => { - if (method == "is" || method == "as") && arguments.len() == 1 { - if let Some(type_name) = Self::extract_string_literal(&arguments[0]) { - let obj_val = self.build_expression_impl(*object.clone())?; + node @ ASTNode::MethodCall { .. } => { + let m = MethodCallExpr::try_from(node).expect("ASTNode::MethodCall must convert"); + if (m.method == "is" || m.method == "as") && m.arguments.len() == 1 { + if let Some(type_name) = Self::extract_string_literal(&m.arguments[0]) { + let obj_val = self.build_expression_impl(*m.object.clone())?; let ty = Self::parse_type_name_to_mir(&type_name); let dst = self.value_gen.next(); - let op = if method == "is" { - crate::mir::TypeOpKind::Check - } else { - crate::mir::TypeOpKind::Cast - }; - self.emit_instruction(MirInstruction::TypeOp { - dst, - op, - value: obj_val, - ty, - })?; + let op = if m.method == "is" { crate::mir::TypeOpKind::Check } else { crate::mir::TypeOpKind::Cast }; + self.emit_instruction(MirInstruction::TypeOp { dst, op, value: obj_val, ty })?; return Ok(dst); } } - self.build_method_call(*object.clone(), method.clone(), arguments.clone()) + self.build_method_call(*m.object.clone(), m.method.clone(), m.arguments.clone()) } ASTNode::FromCall { @@ -186,8 +173,9 @@ impl super::MirBuilder { } } - ASTNode::FieldAccess { object, field, .. } => { - self.build_field_access(*object.clone(), field.clone()) + node @ ASTNode::FieldAccess { .. } => { + let f = FieldAccessExpr::try_from(node).expect("ASTNode::FieldAccess must convert"); + self.build_field_access(*f.object.clone(), f.field.clone()) } ASTNode::New {