From 624456a0eb8a9ff61e1283d04e1765e924867e33 Mon Sep 17 00:00:00 2001 From: ZhangYang <22307110257@m.fudan.edu.cn> Date: Fri, 5 Jun 2026 17:32:44 +0800 Subject: [PATCH] Move TryFrom<&FnDecl> for FunctionType from types.rs to conversions.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/ir/types.rs, the module that defines IR data structures, previously imported crate::ast solely to implement TryFrom<&ast::FnDecl> for FunctionType. This introduced a reverse dependency — the low-level IR type-definition layer had to know about AST nodes — and scattered the AST→IR conversion logic across two files. Unify all AST→IR type and signature conversions under src/ir/gen/conversions.rs. - Remove use crate::ast from types.rs - Move the TryFrom<&FnDecl> impl from types.rs to conversions.rs (no logic changed — the conversion and its validation rules are preserved verbatim) - Add FunctionType import to conversions.rs - Update module-level and section comments in conversions.rs to reflect the broader scope --- src/ir/gen/conversions.rs | 63 +++++++++++++++++++++++++++++++++++---- src/ir/types.rs | 51 ------------------------------- 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/src/ir/gen/conversions.rs b/src/ir/gen/conversions.rs index 62b3af7..0261dd9 100644 --- a/src/ir/gen/conversions.rs +++ b/src/ir/gen/conversions.rs @@ -3,10 +3,11 @@ //! This module provides trait implementations and helper functions to convert //! AST-level type representations (`ast::TypeSpecifier`, `ast::VarDecl`, //! `ast::VarDef`, `ast::VarDeclStmt`) into their corresponding IR-level -//! data types (`Dtype`). +//! data types (`Dtype`), and AST function declarations (`ast::FnDecl`) +//! into IR function signatures ([`FunctionType`]). use crate::ast; -use crate::ir::types::Dtype; +use crate::ir::types::{Dtype, FunctionType}; /// Converts an optional AST type specifier into the corresponding base IR data type (`Dtype`). /// @@ -79,11 +80,12 @@ impl From<&ast::TypeSpecifier> for Dtype { } // --------------------------------------------------------------------------- -// `TryFrom` trait implementations: AST declarations -> IR Dtype +// `TryFrom` trait implementations: AST declarations -> IR types // --------------------------------------------------------------------------- // -// These are fallible conversions because certain combinations (e.g., struct -// definitions with initializers) are not supported and produce an error. +// These are fallible conversions because certain combinations (e.g. struct +// definitions with initializers, array parameters in function signatures) +// are not supported and produce an error. /// Converts a variable declaration (`VarDecl`) to its IR data type. /// @@ -130,3 +132,54 @@ impl TryFrom<&ast::VarDeclStmt> for Dtype { } } } + +/// Lowers an AST function declaration into a [`FunctionType`]. +/// +/// Besides the straightforward type conversion, this enforces two +/// language rules that the back-end relies on: +/// +/// 1. Array parameters are rejected with +/// [`crate::ir::Error::ArrayParameterNotAllowed`] — TeaLang requires +/// arrays to be passed by reference (`&[T]`). +/// 2. Return types are whitelisted to `void` and `i32`. Struct returns +/// are grammatically legal but not yet implemented in the AArch64 +/// back-end; allowing them here would produce IR that can't be +/// lowered, so they are rejected up-front with +/// [`crate::ir::Error::UnsupportedReturnType`]. +impl TryFrom<&ast::FnDecl> for FunctionType { + type Error = crate::ir::Error; + + fn try_from(decl: &ast::FnDecl) -> Result { + let return_dtype = decl + .return_dtype + .as_ref() + .map_or(Dtype::Void, Dtype::from); + + match &return_dtype { + Dtype::Void | Dtype::I32 => {} + _ => { + return Err(crate::ir::Error::UnsupportedReturnType { + symbol: decl.identifier.clone(), + dtype: return_dtype, + }); + } + } + + let mut arguments = Vec::new(); + if let Some(params) = &decl.param_decl { + for p in ¶ms.decls { + let id = p.identifier.clone(); + let dtype = Dtype::try_from(p)?; + if matches!(&dtype, Dtype::Array { .. }) { + return Err(crate::ir::Error::ArrayParameterNotAllowed { symbol: id }); + } + arguments.push((id, dtype)); + } + } + + Ok(Self { + return_dtype, + arguments, + }) + } +} diff --git a/src/ir/types.rs b/src/ir/types.rs index bc98b4d..b393361 100644 --- a/src/ir/types.rs +++ b/src/ir/types.rs @@ -1,4 +1,3 @@ -use crate::ast; use std::fmt::{self, Display, Formatter}; #[derive(Clone, PartialEq, Debug)] @@ -79,53 +78,3 @@ pub struct FunctionType { pub arguments: Vec<(String, Dtype)>, } -impl TryFrom<&ast::FnDecl> for FunctionType { - type Error = crate::ir::Error; - - /// Lowers an AST function declaration into a [`FunctionType`]. - /// - /// Besides the straightforward type conversion, this enforces two - /// language rules that the back-end relies on: - /// - /// 1. Array parameters are rejected with - /// [`crate::ir::Error::ArrayParameterNotAllowed`] — TeaLang requires - /// arrays to be passed by reference (`&[T]`). - /// 2. Return types are whitelisted to `void` and `i32`. Struct returns - /// are grammatically legal but not yet implemented in the AArch64 - /// back-end; allowing them here would produce IR that can't be - /// lowered, so they are rejected up-front with - /// [`crate::ir::Error::UnsupportedReturnType`]. - fn try_from(decl: &ast::FnDecl) -> Result { - let return_dtype = decl - .return_dtype - .as_ref() - .map_or(Dtype::Void, Dtype::from); - - match &return_dtype { - Dtype::Void | Dtype::I32 => {} - _ => { - return Err(crate::ir::Error::UnsupportedReturnType { - symbol: decl.identifier.clone(), - dtype: return_dtype, - }); - } - } - - let mut arguments = Vec::new(); - if let Some(params) = &decl.param_decl { - for p in ¶ms.decls { - let id = p.identifier.clone(); - let dtype = Dtype::try_from(p)?; - if matches!(&dtype, Dtype::Array { .. }) { - return Err(crate::ir::Error::ArrayParameterNotAllowed { symbol: id }); - } - arguments.push((id, dtype)); - } - } - - Ok(Self { - return_dtype, - arguments, - }) - } -}