diff --git a/README.md b/README.md index 158cbf26..5e72cb0d 100644 --- a/README.md +++ b/README.md @@ -7,24 +7,23 @@ A general-purpose system programming language and compiler, designed to build hi - Lightweight, concise, and consistent syntax design, easy to master and get started quickly - Strong type system, static analysis and compilation, memory safety, exception handling, making it easy to write secure and reliable software - Built-in concurrency primitives: go/future/channel/select +- Comprehensive type system supporting generics, enum, tagged union, interface, nullable(?), errable(!) - Compiles directly to machine code for the target platform, does not rely on LLVM, and supports cross-compilation. - Simple deployment, efficient compilation, static linking based on musl libc with good cross-platform characteristics -- Comprehensive type system supporting generics, union types, interfaces, nullable(?), errable(!) +- High-performance C FFI implementation with zero-overhead calls to C standard library functions - High-performance GC implementation with very short STW (Stop The World) - High-performance memory allocator implementation, referencing tcmalloc - High-performance shared-stack coroutine implementation, capable of millions of coroutine switches per second - High-performance IO based on libuv implementation - High-performance runtime and compiler based on pure C implementation -- Built-in data structures vec/map/set/tup and common standard library implementations -- Function calls follow system ABI, built-in libc, c std functions are called without performance loss. +- Built-in data structures vec/string/map/set/tup and common standard library implementations +- Test as a first-class citizen, write test blocks directly in source files - Centralized package management system npkg - Editor LSP support ## Overview -The nature programming language has reached an early usable version, with a basically stable syntax API that will not change significantly before version 1.0. Future versions will add some necessary and commonly used syntax features such as enum, ternary operators, struct labels, etc. - -Key features to be completed include controllable memory allocator, LLM coding adaptation, DSL test framework, GUI adaptation, and WASM3.0 adaptation. +The nature programming language has reached an early usable version, and its core syntax features are now in place. Key features still to be completed include unsafe runtime mode, LLM coding adaptation, C target adaptation, and WASM3.0 target adaptation. The current version supports compilation for the following target architectures: linux_amd64, linux_arm64, linux_riscv64, darwin_amd64, darwin_arm64. diff --git a/README_CN.md b/README_CN.md index b4f740d3..6be8f34f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -8,24 +8,23 @@ - 轻量、简洁、一致性的语法设计,轻松掌握并快速上手使用 - 强类型、静态分析与编译、内存安全、异常处理,轻松编写安全可靠的软件 - 内置并发原语 go/future/channel/select +- 完善的类型系统,支持 generics、enum、tagged union、interface、nullable(?)、errable(!) - 直接编译为目标平台的机器码,不依赖 LLVM,并支持交叉编译 - 部署简单,高效编译,基于 musl libc 进行静态链接,具备良好的跨平台特性 -- 完善的类型系统,支持泛型、联合类型、interface、nullable(?)、errable(!) +- 高性能 C FFI 实现,无性能损耗调用 C 标准库函数 - 高性能 GC 实现,具有非常短暂的 STW (Stop The World) - 高性能内存分配器实现,参考 tcmalloc - 高性能共享栈协程实现,每秒能够进行数百万次的协程切换 - 基于 libuv 实现的高性能 IO - 纯 C 实现的高性能 runtime 和编译器 -- 内置数据结构 vec/map/set/tup 和常用标准库实现 -- 函数调用遵守 system ABI,内置 libc,无性能损耗调用 c 标准库函数 +- 内置数据结构 vec/string/map/set/tup 和常用标准库实现 +- test 作为一等公民,直接在源码文件中编写测试块 - 集中式包管理系统 npkg - 编辑器 lsp 支持 ## 概况 -nature 编程语言已经达到早期可用版本,语法 API 基本稳定,在 1.0 版本之前不会有大幅的变化,后续版本会添加一些必要的语法,如 enum,三元运算符,struct label 等。 - -待完成的关键特性有可控内存分配器,LLM 编码适配,DSL 测试框架,GUI 适配,WASM3.0 适配。 +nature 编程语言已经达到早期可用版本,核心语法功能以添加完成。待完成的关键特性有 unsafe 运行模式,LLM 编码适配,C target 适配,WASM3.0 target 适配。 当前版本编译目标架构包含 linux_amd64、linux_arm64、linux_riscv64、darwin_amd64、darwin_arm64。 @@ -33,7 +32,6 @@ nature 包含一组测试用例和标准库用来测试基本功能和语法的 官网 https://nature-lang.cn - ## 安装 从 [releases](https://github.com/nature-lang/nature/releases) 中下载并解压 nature 安装包(注意权限是否正确)。将解压后的 nature 文件夹移动到 `/usr/local/` 下,并将 `/usr/local/nature/bin` 目录加入到系统环境变量。 diff --git a/VERSION b/VERSION index f2afddf9..4d589978 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.7.3 \ No newline at end of file +v0.7.4 \ No newline at end of file diff --git a/nls/src/analyzer/common.rs b/nls/src/analyzer/common.rs index a9083359..df41cd7c 100644 --- a/nls/src/analyzer/common.rs +++ b/nls/src/analyzer/common.rs @@ -129,9 +129,10 @@ impl Type { err: false, }; - if Self::is_impl_builtin_type(&kind) { + if Self::is_origin_type(&kind) { t.ident = kind.to_string(); t.ident_kind = TypeIdentKind::Builtin; + t.args = Vec::new(); } return t; @@ -635,17 +636,13 @@ pub struct TypeFn { #[repr(u8)] pub enum ReductionStatus { Undo = 1, - Doing = 2, - Doing2 = 3, - Done = 4, + Done = 2, } impl Display for ReductionStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ReductionStatus::Undo => write!(f, "undo"), - ReductionStatus::Doing => write!(f, "doing"), - ReductionStatus::Doing2 => write!(f, "doing2"), ReductionStatus::Done => write!(f, "done"), } } diff --git a/nls/src/analyzer/semantic.rs b/nls/src/analyzer/semantic.rs index 360c37bb..58afe5a2 100644 --- a/nls/src/analyzer/semantic.rs +++ b/nls/src/analyzer/semantic.rs @@ -669,12 +669,19 @@ impl<'a> Semantic<'a> { let symbol_name = fndef.symbol_name.clone(); if fndef.impl_type.kind.is_exist() { + let mut impl_type_ident = fndef.impl_type.ident.clone(); + + if Type::is_impl_builtin_type(&fndef.impl_type.kind) { + impl_type_ident = fndef.impl_type.kind.to_string(); + } + // 非 builtin type 则进行 resolve type 查找 if !Type::is_impl_builtin_type(&fndef.impl_type.kind) { // resolve global ident if let Some(symbol_id) = self.resolve_typedef(&mut fndef.impl_type.ident) { // ident maybe change fndef.impl_type.symbol_id = symbol_id; + impl_type_ident = fndef.impl_type.ident.clone(); // 自定义泛型 impl type 必须显式给出类型参数(仅检查 impl_type.args) if let Some(symbol) = self.symbol_table.get_symbol(symbol_id) { @@ -704,7 +711,7 @@ impl<'a> Semantic<'a> { } } - fndef.symbol_name = format_impl_ident(fndef.impl_type.ident.clone(), symbol_name); + fndef.symbol_name = format_impl_ident(impl_type_ident, symbol_name); // register to global symbol table match self.symbol_table.define_symbol_in_scope( diff --git a/nls/src/analyzer/syntax.rs b/nls/src/analyzer/syntax.rs index 6822f965..bd5f7551 100644 --- a/nls/src/analyzer/syntax.rs +++ b/nls/src/analyzer/syntax.rs @@ -3212,10 +3212,7 @@ impl<'a> Syntax { t } else if (first_token.token_type == TokenType::Ident) && self.ident_is_builtin_type(first_token.clone()) { if self.next_is(1, TokenType::LeftAngle) { - let mut t = self.parser_single_type()?; - t.ident = first_token.literal.clone(); - t.ident_kind = TypeIdentKind::Builtin; - t + self.parser_single_type()? } else { self.must(TokenType::Ident)?; let mut t = Type::unknown(); @@ -3226,9 +3223,6 @@ impl<'a> Syntax { "tup" => TypeKind::Tuple(Vec::new(), 0), _ => TypeKind::Ident, }; - t.ident = first_token.literal.clone(); - t.ident_kind = TypeIdentKind::Builtin; - t.args = Vec::new(); t.start = first_token.start; t.end = first_token.end; t @@ -3237,9 +3231,6 @@ impl<'a> Syntax { self.must(TokenType::Chan)?; let mut t = Type::unknown(); t.kind = TypeKind::Chan(Box::new(Type::unknown())); - t.ident = "chan".to_string(); - t.ident_kind = TypeIdentKind::Builtin; - t.args = Vec::new(); t.start = first_token.start; t.end = first_token.end; t diff --git a/nls/src/analyzer/typesys.rs b/nls/src/analyzer/typesys.rs index 678250f7..143ce7ef 100644 --- a/nls/src/analyzer/typesys.rs +++ b/nls/src/analyzer/typesys.rs @@ -417,9 +417,6 @@ impl<'a> Typesys<'a> { if ident_kind != TypeIdentKind::Unknown { result.ident_kind = ident_kind; result.ident = ident; - } - - if args.len() > 0 { result.args = args; } @@ -428,11 +425,11 @@ impl<'a> Typesys<'a> { // recycle_check let mut visited = HashSet::new(); - let found = self.type_recycle_check(&t, &mut visited); + let found = self.type_recycle_check(&result, &mut visited); if found.is_some() { return Err(AnalyzerError { - start: t.start, - end: t.end, + start: result.start, + end: result.end, message: format!("recycle use type '{}'", found.unwrap()), }); } @@ -440,7 +437,16 @@ impl<'a> Typesys<'a> { return Ok(result); } - fn combination_interface(&mut self, typedef_stmt: &mut TypedefStmt) -> Result<(), AnalyzerError> { + fn reduction_ident_depth_leave(visited: &mut HashMap, ident: &str) { + let depth_now = visited.get(ident).copied().unwrap_or(0); + if depth_now <= 1 { + visited.remove(ident); + } else { + visited.insert(ident.to_string(), depth_now - 1); + } + } + + fn combination_interface(&mut self, typedef_stmt: &mut TypedefStmt, visited: &mut HashMap) -> Result<(), AnalyzerError> { // 确保类型表达式已完成归约且是接口类型 debug_assert!(typedef_stmt.type_expr.status == ReductionStatus::Done); @@ -466,7 +472,7 @@ impl<'a> Typesys<'a> { // 合并实现的接口 for impl_interface in &mut typedef_stmt.impl_interfaces { // 归约接口类型 - *impl_interface = match self.reduction_type(impl_interface.clone()) { + *impl_interface = match self.reduction_type_visited(impl_interface.clone(), visited) { Ok(r) => r, Err(_) => continue, }; @@ -498,7 +504,7 @@ impl<'a> Typesys<'a> { Ok(()) } - fn reduction_type_ident(&mut self, mut t: Type) -> Result { + fn reduction_type_ident(&mut self, mut t: Type, visited: &mut HashMap) -> Result { let start = t.start; let end = t.end; @@ -527,22 +533,63 @@ impl<'a> Typesys<'a> { }); }; + { + let typedef = typedef_mutex.lock().unwrap(); + if typedef.params.is_empty() { + if !t.args.is_empty() { + return Err(AnalyzerError { + start, + end, + message: format!("typedef '{}' args mismatch", t.ident), + }); + } + + // 非泛型 alias 已经 reduction 完成,直接复用 + if typedef.type_expr.status == ReductionStatus::Done { + t.kind = typedef.type_expr.kind.clone(); + t.status = typedef.type_expr.status; + return Ok(t); + } + } + } + + // 通过 ident 记录 reduction 路径深度,允许深度 2,第三层中断 + let mut reduction_ident_depth_entered = false; + if !t.ident.is_empty() { + let reduction_depth = visited.get(&t.ident).copied().unwrap_or(0) + 1; + visited.insert(t.ident.clone(), reduction_depth); + reduction_ident_depth_entered = true; + + if reduction_depth >= 3 { + Self::reduction_ident_depth_leave(visited, &t.ident); + return Ok(t); + } + } + let mut typedef = typedef_mutex.lock().unwrap(); - // let typedef_start = typedef.symbol_start; - // let typedef_end = typedef.symbol_end; // 处理泛型参数 - if typedef.params.len() > 0 { - // 检查是否提供了泛型参数 + if !typedef.params.is_empty() { + let mut generic_typedef = typedef.clone(); + drop(typedef); + if t.args.is_empty() { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(AnalyzerError { start, end, message: format!("typedef '{}' need params", t.ident), }); } - // 检查参数数量是否匹配 - if t.args.len() != typedef.params.len() { + + if t.args.len() != generic_typedef.params.len() { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(AnalyzerError { start, end, @@ -550,17 +597,25 @@ impl<'a> Typesys<'a> { }); } - // 创建参数表并压入栈 let mut args_table = HashMap::new(); let mut impl_args = Vec::new(); - for (i, undo_arg) in t.args.iter_mut().enumerate() { - // 先进行类型归约 - let arg = self.reduction_type(undo_arg.clone())?; - - let param = &mut typedef.params[i]; + for (i, undo_arg) in t.args.iter().enumerate() { + let arg = match self.reduction_type_visited(undo_arg.clone(), visited) { + Ok(arg) => arg, + Err(e) => { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(e); + } + }; - // 检查泛型约束 + let param = &mut generic_typedef.params[i]; if let Err(e) = self.generics_constrains_check(param, &arg) { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(AnalyzerError { start, end, @@ -569,99 +624,78 @@ impl<'a> Typesys<'a> { } impl_args.push(arg.clone()); - args_table.insert(param.ident.clone(), arg.clone()); + args_table.insert(param.ident.clone(), arg); } - // 压入参数表用于后续处理 self.generics_args_stack.push(args_table); + let reduction_result: Result = (|| { + if !generic_typedef.impl_interfaces.is_empty() { + if generic_typedef.is_interface { + debug_assert!(generic_typedef.type_expr.status == ReductionStatus::Done); + debug_assert!(matches!(generic_typedef.type_expr.kind, TypeKind::Interface(..))); + self.combination_interface(&mut generic_typedef, visited)?; + } else { + for impl_interface in &mut generic_typedef.impl_interfaces { + *impl_interface = self.reduction_type_visited(impl_interface.clone(), visited)?; + } - // 处理接口实现 - if typedef.impl_interfaces.len() > 0 { - if typedef.is_interface { - debug_assert!(typedef.type_expr.status == ReductionStatus::Done); - debug_assert!(matches!(typedef.type_expr.kind, TypeKind::Interface(..))); - self.combination_interface(&mut typedef)? - } else { - for impl_interface in &mut typedef.impl_interfaces { - *impl_interface = self.reduction_type(impl_interface.clone())?; - } - - for impl_interface in &typedef.impl_interfaces { - self.check_typedef_impl(impl_interface, t.ident.clone(), &typedef) - .map_err(|e| AnalyzerError { start, end, message: e })?; + for impl_interface in &generic_typedef.impl_interfaces { + self.check_typedef_impl(impl_interface, t.ident.clone(), &generic_typedef) + .map_err(|e| AnalyzerError { start, end, message: e })?; + } } } - } - // 处理右值表达式 - let mut right_type = typedef.type_expr.clone(); + let right_type = self.reduction_type_visited(generic_typedef.type_expr.clone(), visited)?; + Ok(right_type) + })(); + self.generics_args_stack.pop(); - right_type = self.reduction_type(right_type)?; + let right_type = match reduction_result { + Ok(right_type) => right_type, + Err(e) => { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(e); + } + }; - // 弹出参数表 - self.generics_args_stack.pop(); + { + let mut typedef = typedef_mutex.lock().unwrap(); + typedef.impl_interfaces = generic_typedef.impl_interfaces.clone(); + } t.args = impl_args; t.kind = right_type.kind; t.status = right_type.status; - return Ok(t); - } else { - // params == 0 - if !t.args.is_empty() { - return Err(AnalyzerError { - start, - end, - message: format!("typedef '{}' args mismatch", t.ident), - }); - } - } - - // 检查右值是否已完成归约 - if typedef.type_expr.status == ReductionStatus::Done { - t.kind = typedef.type_expr.kind.clone(); - t.status = typedef.type_expr.status; - return Ok(t); - } - // 处理循环引用 - if typedef.type_expr.status == ReductionStatus::Doing2 { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } return Ok(t); } - // 标记正在处理,避免循环引用 - if typedef.type_expr.status == ReductionStatus::Doing { - typedef.type_expr.status = ReductionStatus::Doing2; - } else { - typedef.type_expr.status = ReductionStatus::Doing; - } - - // 处理接口 + // interface 需要通过 ident 区分 if typedef.is_interface { typedef.type_expr.ident_kind = TypeIdentKind::Interface; typedef.type_expr.ident = t.ident.clone(); } - // 处理 enum if typedef.is_enum { typedef.type_expr.ident_kind = TypeIdentKind::Enum; typedef.type_expr.ident = t.ident.clone(); } let type_expr = typedef.type_expr.clone(); - - // 在递归调用前释放锁,避免死锁 drop(typedef); - // 归约类型表达式递归处理, 避免 typedef_mutex 锁定 - let type_expr = match self.reduction_type(type_expr) { + let type_expr = match self.reduction_type_visited(type_expr, visited) { Ok(type_expr) => type_expr, Err(e) => { - // change typedef status to undo - let mut typedef = typedef_mutex.lock().unwrap(); - if typedef.type_expr.status == ReductionStatus::Doing { - typedef.type_expr.status = ReductionStatus::Undo; + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); } - return Err(e); } }; @@ -669,30 +703,50 @@ impl<'a> Typesys<'a> { let mut typedef = typedef_mutex.lock().unwrap(); typedef.type_expr = type_expr; - // 处理接口实现 - if typedef.impl_interfaces.len() > 0 { + if !typedef.impl_interfaces.is_empty() { if typedef.is_interface { debug_assert!(typedef.type_expr.status == ReductionStatus::Done); debug_assert!(matches!(typedef.type_expr.kind, TypeKind::Interface(..))); - self.combination_interface(&mut typedef)? + if let Err(e) = self.combination_interface(&mut typedef, visited) { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(e); + } } else { for impl_interface in &mut typedef.impl_interfaces { - *impl_interface = self.reduction_type(impl_interface.clone())?; + *impl_interface = match self.reduction_type_visited(impl_interface.clone(), visited) { + Ok(impl_interface) => impl_interface, + Err(e) => { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(e); + } + }; } for impl_interface in &typedef.impl_interfaces { - self.check_typedef_impl(impl_interface, t.ident.clone(), &typedef) - .map_err(|e| AnalyzerError { start, end, message: e })?; + if let Err(e) = self.check_typedef_impl(impl_interface, t.ident.clone(), &typedef) { + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } + return Err(AnalyzerError { start, end, message: e }); + } } } } t.kind = typedef.type_expr.kind.clone(); t.status = typedef.type_expr.status; + + if reduction_ident_depth_entered { + Self::reduction_ident_depth_leave(visited, &t.ident); + } Ok(t) } - fn reduction_complex_type(&mut self, t: Type) -> Result { + fn reduction_complex_type(&mut self, t: Type, visited: &mut HashMap) -> Result { let mut result = t.clone(); let kind_str = result.kind.to_string(); @@ -700,17 +754,17 @@ impl<'a> Typesys<'a> { match &mut result.kind { // 处理指针类型 TypeKind::Ref(value_type) | TypeKind::Ptr(value_type) => { - *value_type = Box::new(self.reduction_type(*value_type.clone())?); + *value_type = Box::new(self.reduction_type_visited(*value_type.clone(), visited)?); } // 处理数组类型 TypeKind::Arr(_, _, element_type) => { - *element_type = Box::new(self.reduction_type(*element_type.clone())?); + *element_type = Box::new(self.reduction_type_visited(*element_type.clone(), visited)?); } // 处理通道类型 TypeKind::Chan(element_type) => { - *element_type = Box::new(self.reduction_type(*element_type.clone())?); + *element_type = Box::new(self.reduction_type_visited(*element_type.clone(), visited)?); result.ident_kind = TypeIdentKind::Builtin; result.ident = kind_str; @@ -719,7 +773,7 @@ impl<'a> Typesys<'a> { // 处理向量类型 TypeKind::Vec(element_type) => { - *element_type = Box::new(self.reduction_type(*element_type.clone())?); + *element_type = Box::new(self.reduction_type_visited(*element_type.clone(), visited)?); result.ident_kind = TypeIdentKind::Builtin; result.ident = kind_str; @@ -728,8 +782,8 @@ impl<'a> Typesys<'a> { // 处理映射类型 TypeKind::Map(key_type, value_type) => { - *key_type = Box::new(self.reduction_type(*key_type.clone())?); - *value_type = Box::new(self.reduction_type(*value_type.clone())?); + *key_type = Box::new(self.reduction_type_visited(*key_type.clone(), visited)?); + *value_type = Box::new(self.reduction_type_visited(*value_type.clone(), visited)?); // 检查键类型是否合法 if !Type::is_map_key_type(&key_type.kind) { @@ -747,7 +801,7 @@ impl<'a> Typesys<'a> { // 处理集合类型 TypeKind::Set(element_type) => { - *element_type = Box::new(self.reduction_type(*element_type.clone())?); + *element_type = Box::new(self.reduction_type_visited(*element_type.clone(), visited)?); // 检查元素类型是否合法 if !Type::is_map_key_type(&element_type.kind) { @@ -774,14 +828,14 @@ impl<'a> Typesys<'a> { } for element_type in elements.iter_mut() { - *element_type = self.reduction_type(element_type.clone())?; + *element_type = self.reduction_type_visited(element_type.clone(), visited)?; } } TypeKind::Fn(type_fn) => { - type_fn.return_type = self.reduction_type(type_fn.return_type.clone())?; + type_fn.return_type = self.reduction_type_visited(type_fn.return_type.clone(), visited)?; for formal_type in type_fn.param_types.iter_mut() { - *formal_type = self.reduction_type(formal_type.clone())?; + *formal_type = self.reduction_type_visited(formal_type.clone(), visited)?; } } @@ -789,7 +843,7 @@ impl<'a> Typesys<'a> { TypeKind::Struct(_ident, _align, properties) => { for property in properties.iter_mut() { if !property.type_.kind.is_unknown() { - property.type_ = self.reduction_type(property.type_.clone())?; + property.type_ = self.reduction_type_visited(property.type_.clone(), visited)?; } if let Some(right_value) = &mut property.value { @@ -836,15 +890,20 @@ impl<'a> Typesys<'a> { Ok(result) } - pub fn type_param_special(&mut self, t: Type, arg_table: HashMap) -> Type { + pub fn type_param_special(&mut self, t: Type, arg_table: HashMap, visited: &mut HashMap) -> Type { debug_assert!(t.kind == TypeKind::Ident); debug_assert!(t.ident_kind == TypeIdentKind::GenericsParam); let arg_type = arg_table.get(&t.ident).unwrap(); - return self.reduction_type(arg_type.clone()).unwrap(); + return self.reduction_type_visited(arg_type.clone(), visited).unwrap(); + } + + pub fn reduction_type(&mut self, t: Type) -> Result { + let mut visited = HashMap::new(); + self.reduction_type_visited(t, &mut visited) } - pub fn reduction_type(&mut self, mut t: Type) -> Result { + fn reduction_type_visited(&mut self, mut t: Type, visited: &mut HashMap) -> Result { let ident = t.ident.clone(); let ident_kind = t.ident_kind.clone(); let args = t.args.clone(); @@ -866,7 +925,7 @@ impl<'a> Typesys<'a> { } if Type::is_ident(&t) { - t = self.reduction_type_ident(t)?; + t = self.reduction_type_ident(t, visited)?; // 如果原来存在 t.args 则其经过了 reduction return self.finalize_type(t.clone(), ident, ident_kind, t.args); } @@ -877,7 +936,7 @@ impl<'a> Typesys<'a> { } let arg_table = self.generics_args_stack.last().unwrap(); - let result = self.type_param_special(t, arg_table.clone()); + let result = self.type_param_special(t, arg_table.clone(), visited); return self.finalize_type(result.clone(), result.ident.clone(), result.ident_kind, result.args); } @@ -889,28 +948,28 @@ impl<'a> Typesys<'a> { } for element in elements { - *element = self.reduction_type(element.clone())?; + *element = self.reduction_type_visited(element.clone(), visited)?; } return self.finalize_type(t, ident, ident_kind, args); } TypeKind::Interface(elements) => { for element in elements { - *element = self.reduction_type(element.clone())?; + *element = self.reduction_type_visited(element.clone(), visited)?; } return self.finalize_type(t, ident, ident_kind, args); } TypeKind::TaggedUnion(_, elements) => { for element in elements { - element.type_ = self.reduction_type(element.type_.clone())?; + element.type_ = self.reduction_type_visited(element.type_.clone(), visited)?; } return self.finalize_type(t, ident, ident_kind, args); } TypeKind::Enum(element_type, properties) => { // reduction element type - *element_type = Box::new(self.reduction_type(*element_type.clone())?); + *element_type = Box::new(self.reduction_type_visited(*element_type.clone(), visited)?); // enum 只支持 integer 类型 if !Type::is_integer(&element_type.kind) { @@ -963,7 +1022,7 @@ impl<'a> Typesys<'a> { } if Type::is_complex_type(&t.kind) { - let result = self.reduction_complex_type(t)?; + let result = self.reduction_complex_type(t, visited)?; return self.finalize_type(result, ident, ident_kind, args); } @@ -4452,6 +4511,20 @@ impl<'a> Typesys<'a> { self.type_compare_visited(dst, src, &mut visited) } + fn type_compare_ident_args_visited(&mut self, dst_args: &Vec, src_args: &Vec, visited: &mut HashSet) -> bool { + if dst_args.len() != src_args.len() { + return false; + } + + for (dst_arg, src_arg) in dst_args.iter().zip(src_args.iter()) { + if !self.type_compare_visited(dst_arg, src_arg, visited) { + return false; + } + } + + true + } + pub fn type_compare_visited(&mut self, dst: &Type, src: &Type, visited: &mut HashSet) -> bool { let dst = dst.clone(); if dst.err || src.err { @@ -4500,27 +4573,23 @@ impl<'a> Typesys<'a> { } } - // 即使 reduction 后,也需要通过 ident kind 进行判断, 其中 union_type 不受 type def 限制 - if dst.ident_kind == TypeIdentKind::Def && !matches!(dst.kind, TypeKind::Union(..)) { - debug_assert!(!dst.ident.is_empty()); - if src.ident.is_empty() { + // TYPE_IDENT_DEF 采用名义类型比较:ident + args + let dst_nominal = dst.ident_kind == TypeIdentKind::Def && !matches!(dst.kind, TypeKind::Union(..)); + let src_nominal = src.ident_kind == TypeIdentKind::Def && !matches!(src.kind, TypeKind::Union(..)); + if dst_nominal || src_nominal { + if dst.ident.is_empty() || src.ident.is_empty() { return false; } if dst.ident != src.ident { return false; } - } - if src.ident_kind == TypeIdentKind::Def && !matches!(src.kind, TypeKind::Union(..)) { - debug_assert!(!src.ident.is_empty()); - if dst.ident.is_empty() { + if !self.type_compare_ident_args_visited(&dst.args, &src.args, visited) { return false; } - if dst.ident != src.ident { - return false; - } + return true; } // ident 递归打断 diff --git a/src/rtype.h b/src/rtype.h index 90d65413..c8312214 100644 --- a/src/rtype.h +++ b/src/rtype.h @@ -37,7 +37,7 @@ static inline int64_t type_hash(type_t t) { return hash_string(str); } - if (is_origin_type(t)) { + if (is_origin_kind(t.kind)) { return hash_string(type_kind_str[t.kind]); } diff --git a/src/semantic/analyzer.c b/src/semantic/analyzer.c index f1c44e00..1707884c 100644 --- a/src/semantic/analyzer.c +++ b/src/semantic/analyzer.c @@ -2331,7 +2331,12 @@ static void analyzer_module(module_t *m, slice_t *stmt_list) { } } - fndef->symbol_name = str_connect_by(fndef->impl_type.ident, symbol_name, IMPL_CONNECT_IDENT); + char *impl_type_ident = fndef->impl_type.ident; + if (is_impl_builtin_type(fndef->impl_type.kind)) { + impl_type_ident = type_kind_str[fndef->impl_type.kind]; + } + + fndef->symbol_name = str_connect_by(impl_type_ident, symbol_name, IMPL_CONNECT_IDENT); symbol_t *s = symbol_table_set(fndef->symbol_name, SYMBOL_FN, fndef, false); ANALYZER_ASSERTF(s, "ident '%s' redeclared", fndef->symbol_name); diff --git a/src/semantic/infer.c b/src/semantic/infer.c index 3ca1dbee..e2354294 100644 --- a/src/semantic/infer.c +++ b/src/semantic/infer.c @@ -10,9 +10,11 @@ static void check_typedef_impl(module_t *m, type_t *impl_interface, char *typedef_ident, ast_typedef_stmt_t *typedef_stmt); -static type_t reduction_type_ident(module_t *m, type_t t); +static type_t reduction_type_visited(module_t *m, type_t t, struct sc_map_s64 *visited); -static type_t type_param_special(module_t *m, type_t t, table_t *arg_table); +static type_t reduction_type_ident(module_t *m, type_t t, struct sc_map_s64 *visited); + +static type_t type_param_special(module_t *m, type_t t, table_t *arg_table, struct sc_map_s64 *visited); static type_fn_t *infer_call_left(module_t *m, ast_call_t *call, type_t target_type); @@ -488,6 +490,26 @@ bool type_compare(type_t dst, type_t src) { return type_compare_visited(dst, src, visited); } +static bool type_compare_ident_args_visited(list_t *dst_args, list_t *src_args, table_t *visited) { + int dst_len = dst_args ? dst_args->length : 0; + int src_len = src_args ? src_args->length : 0; + + // NULL 与空列表视为等价 + if (dst_len != src_len) { + return false; + } + + for (int i = 0; i < dst_len; ++i) { + type_t *dst_arg = ct_list_value(dst_args, i); + type_t *src_arg = ct_list_value(src_args, i); + if (!type_compare_visited(*dst_arg, *src_arg, visited)) { + return false; + } + } + + return true; +} + /** * reduction 阶段就应该完成 cross left kind 的定位. * @param dst @@ -535,26 +557,23 @@ bool type_compare_visited(type_t dst, type_t src, table_t *visited) { } - // 即使 reduction 后,也需要通过 ident kind 进行判断, 其中 union_type 不受 type def 限制 - if (dst.ident_kind == TYPE_IDENT_DEF && dst.kind != TYPE_UNION) { - assert(dst.ident != NULL); - if (src.ident == NULL) { + // TYPE_IDENT_DEF 采用名义类型比较:ident + args + bool dst_nominal = (dst.ident_kind == TYPE_IDENT_DEF && dst.kind != TYPE_UNION); + bool src_nominal = (src.ident_kind == TYPE_IDENT_DEF && src.kind != TYPE_UNION); + if (dst_nominal || src_nominal) { + if (dst.ident == NULL || src.ident == NULL) { return false; } if (!str_equal(dst.ident, src.ident)) { return false; } - } - if (src.ident_kind == TYPE_IDENT_DEF && src.kind != TYPE_UNION) { - assert(src.ident != NULL); - if (dst.ident == NULL) { - return false; - } - if (!str_equal(dst.ident, src.ident)) { + if (!type_compare_ident_args_visited(dst.args, src.args, visited)) { return false; } + + return true; } // ident 递归打断 @@ -3706,7 +3725,7 @@ type_t infer_global_expr(module_t *m, ast_expr_t *expr, type_t target_type) { return result; } -static type_t reduction_struct(module_t *m, type_t t) { +static type_t reduction_struct(module_t *m, type_t t, struct sc_map_s64 *visited) { INFER_ASSERTF(t.kind == TYPE_STRUCT, "type kind=%s unexpect", type_format(t)); type_struct_t *s = t.struct_; @@ -3715,7 +3734,7 @@ static type_t reduction_struct(module_t *m, type_t t) { struct_property_t *p = ct_list_value(s->properties, i); if (p->type.kind != TYPE_UNKNOWN) { - p->type = reduction_type(m, p->type); + p->type = reduction_type_visited(m, p->type, visited); } if (p->right) { @@ -3739,16 +3758,16 @@ static type_t reduction_struct(module_t *m, type_t t) { return t; } -static type_t reduction_complex_type(module_t *m, type_t t) { +static type_t reduction_complex_type(module_t *m, type_t t, struct sc_map_s64 *visited) { if (t.kind == TYPE_REF || t.kind == TYPE_PTR) { type_ptr_t *type_pointer = t.ptr; - type_pointer->value_type = reduction_type(m, type_pointer->value_type); + type_pointer->value_type = reduction_type_visited(m, type_pointer->value_type, visited); return t; } if (t.kind == TYPE_ARR) { type_array_t *type_array = t.array; - type_array->element_type = reduction_type(m, type_array->element_type); + type_array->element_type = reduction_type_visited(m, type_array->element_type, visited); // not impl @@ -3757,7 +3776,7 @@ static type_t reduction_complex_type(module_t *m, type_t t) { if (t.kind == TYPE_CHAN) { type_chan_t *type_chan = t.chan; - type_chan->element_type = reduction_type(m, type_chan->element_type); + type_chan->element_type = reduction_type_visited(m, type_chan->element_type, visited); t.ident_kind = TYPE_IDENT_BUILTIN; @@ -3770,7 +3789,7 @@ static type_t reduction_complex_type(module_t *m, type_t t) { if (t.kind == TYPE_VEC) { type_vec_t *type_vec = t.vec; - type_vec->element_type = reduction_type(m, type_vec->element_type); + type_vec->element_type = reduction_type_visited(m, type_vec->element_type, visited); // vec.len 都是 impl fn 实现,但是如果是 type my_vec = [int] 这样的实现,impl_ident 应该使用默认的 ident。 t.ident_kind = TYPE_IDENT_BUILTIN; @@ -3782,8 +3801,8 @@ static type_t reduction_complex_type(module_t *m, type_t t) { } if (t.kind == TYPE_MAP) { - t.map->key_type = reduction_type(m, t.map->key_type); - t.map->value_type = reduction_type(m, t.map->value_type); + t.map->key_type = reduction_type_visited(m, t.map->key_type, visited); + t.map->value_type = reduction_type_visited(m, t.map->value_type, visited); t.ident_kind = TYPE_IDENT_BUILTIN; t.ident = type_kind_str[TYPE_MAP]; t.args = ct_list_new(sizeof(type_t)); @@ -3795,7 +3814,7 @@ static type_t reduction_complex_type(module_t *m, type_t t) { } if (t.kind == TYPE_SET) { - t.set->element_type = reduction_type(m, t.set->element_type); + t.set->element_type = reduction_type_visited(m, t.set->element_type, visited); t.ident_kind = TYPE_IDENT_BUILTIN; t.ident = type_kind_str[TYPE_SET]; t.args = ct_list_new(sizeof(type_t)); @@ -3809,37 +3828,37 @@ static type_t reduction_complex_type(module_t *m, type_t t) { INFER_ASSERTF(tuple->elements->length > 0, "tuple element empty"); for (int i = 0; i < tuple->elements->length; ++i) { type_t *element = ct_list_value(tuple->elements, i); - *element = reduction_type(m, *element); + *element = reduction_type_visited(m, *element, visited); } return t; } if (t.kind == TYPE_FN) { type_fn_t *fn = t.fn; - fn->return_type = reduction_type(m, fn->return_type); + fn->return_type = reduction_type_visited(m, fn->return_type, visited); for (int i = 0; i < fn->param_types->length; ++i) { type_t *formal_type = ct_list_value(fn->param_types, i); - *formal_type = reduction_type(m, *formal_type); + *formal_type = reduction_type_visited(m, *formal_type, visited); } return t; } if (t.kind == TYPE_STRUCT) { - return reduction_struct(m, t); + return reduction_struct(m, t, visited); } INFER_ASSERTF(false, "unknown type=%s", type_format(t)); exit(1); } -static type_t type_param_special(module_t *m, type_t t, table_t *arg_table) { +static type_t type_param_special(module_t *m, type_t t, table_t *arg_table, struct sc_map_s64 *visited) { assert(t.kind == TYPE_IDENT); assert(t.ident_kind == TYPE_IDENT_GENERICS_PARAM); // 实参可以没有 reduction type_t *arg_type = table_get(arg_table, t.ident); - return reduction_type(m, *arg_type); + return reduction_type_visited(m, *arg_type, visited); } /** @@ -4015,7 +4034,7 @@ check_typedef_impl(module_t *m, type_t *impl_interface, char *typedef_ident, ast } } -static void combination_interface(module_t *m, ast_typedef_stmt_t *typedef_stmt) { +static void combination_interface(module_t *m, ast_typedef_stmt_t *typedef_stmt, struct sc_map_s64 *visited) { assert(typedef_stmt->type_expr.status == REDUCTION_STATUS_DONE); assert(typedef_stmt->type_expr.kind == TYPE_INTERFACE); type_interface_t *origin_interface = typedef_stmt->type_expr.interface; @@ -4031,7 +4050,7 @@ static void combination_interface(module_t *m, ast_typedef_stmt_t *typedef_stmt) // combination for (int i = 0; i < typedef_stmt->impl_interfaces->length; ++i) { type_t *impl_interface = ct_list_value(typedef_stmt->impl_interfaces, i); - *impl_interface = reduction_type(m, *impl_interface); + *impl_interface = reduction_type_visited(m, *impl_interface, visited); assert(impl_interface->kind == TYPE_INTERFACE); for (int j = 0; j < impl_interface->interface->elements->length; ++j) { type_t *temp = ct_list_value(impl_interface->interface->elements, j); @@ -4102,7 +4121,19 @@ static void combination_interface(module_t *m, ast_typedef_stmt_t *typedef_stmt) * @param t * @return */ -static type_t reduction_type_ident(module_t *m, type_t t) { +static type_t reduction_type_ident(module_t *m, type_t t, struct sc_map_s64 *visited) { +#define REDUCTION_IDENT_LEAVE_DEPTH() \ + do { \ + if (reduction_ident_depth_entered && t.ident) { \ + uint64_t depth_now = sc_map_get_s64(visited, t.ident); \ + if (depth_now <= 1) { \ + sc_map_del_s64(visited, t.ident); \ + } else { \ + sc_map_put_s64(visited, t.ident, depth_now - 1); \ + } \ + } \ + } while (0) + symbol_t *symbol = symbol_table_get(t.ident); INFER_ASSERTF(symbol, "typedef '%s' not found", t.ident); INFER_ASSERTF(symbol->type == SYMBOL_TYPE, "'%s' is not a type", symbol->ident); @@ -4110,6 +4141,34 @@ static type_t reduction_type_ident(module_t *m, type_t t) { // 此时的 symbol 可能是其他 module 中声明的符号 ast_typedef_stmt_t *typedef_stmt = symbol->ast_value; + if (!typedef_stmt->params) { + INFER_ASSERTF(t.args == NULL, "typedef '%s' args mismatch", t.ident); + + // 检查右值是否 reduce 完成 + if (typedef_stmt->type_expr.status == REDUCTION_STATUS_DONE) { + type_t temp = type_copy(m, typedef_stmt->type_expr); + t.kind = temp.kind; + t.value = temp.value; + t.in_heap = temp.in_heap; + t.status = temp.status; + return t; + } + } + + // 通过 ident 记录当前 reduction 路径深度: depth=1/2 继续, depth=3 中断 + bool reduction_ident_depth_entered = false; + if (t.ident) { + uint64_t reduction_depth = sc_map_get_s64(visited, t.ident) + 1; + sc_map_put_s64(visited, t.ident, reduction_depth); + reduction_ident_depth_entered = true; + + if (reduction_depth >= 3) { + // depth=3 中断返回前需要 -1 + REDUCTION_IDENT_LEAVE_DEPTH(); + return t; + } + } + // 判断是否包含 args, 如果包含 args 则需要每一次 reduction 都进行处理 // 此时的 type alias 相当于重新定义了一个新的类型,并进行了 type_copy, 所以不会存在 reduction 冲突问题, 可以直接返回 if (typedef_stmt->params) { @@ -4121,7 +4180,7 @@ static type_t reduction_type_ident(module_t *m, type_t t) { table_t *args_table = table_new(); for (int i = 0; i < t.args->length; ++i) { type_t *arg = ct_list_value(t.args, i); - *arg = reduction_type(m, *arg); + *arg = reduction_type_visited(m, *arg, visited); ast_generics_param_t *param = ct_list_value(typedef_stmt->params, i); @@ -4139,11 +4198,11 @@ static type_t reduction_type_ident(module_t *m, type_t t) { if (typedef_stmt->is_interface) { assert(typedef_stmt->type_expr.status == REDUCTION_STATUS_DONE); assert(typedef_stmt->type_expr.kind == TYPE_INTERFACE); - combination_interface(m, typedef_stmt); + combination_interface(m, typedef_stmt, visited); } else { for (int i = 0; i < typedef_stmt->impl_interfaces->length; ++i) { type_t *impl_interface = ct_list_value(typedef_stmt->impl_interfaces, i); - *impl_interface = reduction_type(m, *impl_interface); + *impl_interface = reduction_type_visited(m, *impl_interface, visited); check_typedef_impl(m, impl_interface, t.ident, typedef_stmt); } } @@ -4155,7 +4214,7 @@ static type_t reduction_type_ident(module_t *m, type_t t) { // reduction 部分的 struct 的 right expr 如果是 struct,也只会进行到 infer_fn_decl 而不会处理 fn body 部分 // 所以 fn body 部分还是包含 type_param, 如果此时将 type_param_table 置空,会导致后续 infer_fndef 时解析 param 异常 // 更加正确的做法应该是将 type_param_table 赋值给相应的 ast_fndef - right_type_expr = reduction_type(m, right_type_expr); + right_type_expr = reduction_type_visited(m, right_type_expr, visited); if (m->infer_type_args_stack) { stack_pop(m->infer_type_args_stack); @@ -4165,37 +4224,10 @@ static type_t reduction_type_ident(module_t *m, type_t t) { t.value = right_type_expr.value; t.in_heap = right_type_expr.in_heap; t.status = right_type_expr.status; + REDUCTION_IDENT_LEAVE_DEPTH(); return t; - } else { - INFER_ASSERTF(t.args == NULL, "typedef '%s' args mismatch", - t.ident); } - - // 检查右值是否 reduce 完成 - if (typedef_stmt->type_expr.status == REDUCTION_STATUS_DONE) { - type_t temp = type_copy(m, typedef_stmt->type_expr); - t.kind = temp.kind; - t.value = temp.value; - t.in_heap = temp.in_heap; - t.status = temp.status; - return t; - } - - if (typedef_stmt->type_expr.status == REDUCTION_STATUS_DOING2) { - // doing2 打破循环 - return t; - } - - // 当前 ident 对应的 type 正在 reduction, 出现这种情况可能的原因是嵌套使用了 ident - if (typedef_stmt->type_expr.status == REDUCTION_STATUS_DOING) { - typedef_stmt->type_expr.status = REDUCTION_STATUS_DOING2; - } else { - // 打上正在进行的标记,避免进入死循环 - typedef_stmt->type_expr.status = REDUCTION_STATUS_DOING; - } - - // interface 需要通过 ident 进行区分,所以这里将 ident 赋值给 type_expr if (typedef_stmt->is_interface) { typedef_stmt->type_expr.ident_kind = TYPE_IDENT_INTERFACE; @@ -4207,44 +4239,46 @@ static type_t reduction_type_ident(module_t *m, type_t t) { typedef_stmt->type_expr.ident = t.ident; } - typedef_stmt->type_expr = reduction_type(m, typedef_stmt->type_expr); + typedef_stmt->type_expr = reduction_type_visited(m, typedef_stmt->type_expr, visited); // check impl if (typedef_stmt->impl_interfaces) { if (typedef_stmt->is_interface) { assert(typedef_stmt->type_expr.status == REDUCTION_STATUS_DONE); assert(typedef_stmt->type_expr.kind == TYPE_INTERFACE); - combination_interface(m, typedef_stmt); + combination_interface(m, typedef_stmt, visited); } else { for (int i = 0; i < typedef_stmt->impl_interfaces->length; ++i) { type_t *impl_interface = ct_list_value(typedef_stmt->impl_interfaces, i); - *impl_interface = reduction_type(m, *impl_interface); + *impl_interface = reduction_type_visited(m, *impl_interface, visited); check_typedef_impl(m, impl_interface, t.ident, typedef_stmt); } } } - // reduction_type 已经返回,现在这里可以直接修改为 done, 或者在外部的 reduction_type 中配置为 done type_t right_type_expr = type_copy(m, typedef_stmt->type_expr); t.kind = right_type_expr.kind; t.value = right_type_expr.value; t.in_heap = right_type_expr.in_heap; t.status = right_type_expr.status; + REDUCTION_IDENT_LEAVE_DEPTH(); return t; + +#undef REDUCTION_IDENT_LEAVE_DEPTH } -static type_t reduction_tagged_union_type(module_t *m, type_t t) { +static type_t reduction_tagged_union_type(module_t *m, type_t t, struct sc_map_s64 *visited) { type_tagged_union_t *tagged_union = t.tagged_union; for (int i = 0; i < tagged_union->elements->length; ++i) { tagged_union_element_t *temp = ct_list_value(tagged_union->elements, i); - temp->type = reduction_type(m, temp->type); + temp->type = reduction_type_visited(m, temp->type, visited); } return t; } -static type_t reduction_union_type(module_t *m, type_t t) { +static type_t reduction_union_type(module_t *m, type_t t, struct sc_map_s64 *visited) { type_union_t *type_union = t.union_; if (type_union->elements->length == 0) { return t; @@ -4252,15 +4286,15 @@ static type_t reduction_union_type(module_t *m, type_t t) { for (int i = 0; i < t.union_->elements->length; ++i) { type_t *temp = ct_list_value(t.union_->elements, i); - *temp = reduction_type(m, *temp); + *temp = reduction_type_visited(m, *temp, visited); } return t; } -static type_t reduction_enum(module_t *m, type_t t) { +static type_t reduction_enum(module_t *m, type_t t, struct sc_map_s64 *visited) { type_enum_t *enum_type = t.enum_; - enum_type->element_type = reduction_type(m, enum_type->element_type); + enum_type->element_type = reduction_type_visited(m, enum_type->element_type, visited); // enum 只支持 integer 类型作为 discriminant INFER_ASSERTF(is_integer(enum_type->element_type.kind), @@ -4299,26 +4333,26 @@ static type_t reduction_enum(module_t *m, type_t t) { return t; } -static type_t reduction_interface(module_t *m, type_t t) { +static type_t reduction_interface(module_t *m, type_t t, struct sc_map_s64 *visited) { type_interface_t *type_interface = t.interface; generics_interface_fill_builtin_alloc_types(t); for (int i = 0; i < type_interface->elements->length; ++i) { type_t *temp = ct_list_value(type_interface->elements, i); - *temp = reduction_type(m, *temp); + *temp = reduction_type_visited(m, *temp, visited); } if (type_interface->alloc_types && type_interface->alloc_types->length > 0) { for (int i = 0; i < type_interface->alloc_types->length; ++i) { type_t *alloc_type = ct_list_value(type_interface->alloc_types, i); - *alloc_type = reduction_type(m, *alloc_type); + *alloc_type = reduction_type_visited(m, *alloc_type, visited); } } if (type_interface->deny_types && type_interface->deny_types->length > 0) { for (int i = 0; i < type_interface->deny_types->length; ++i) { type_t *deny_type = ct_list_value(type_interface->deny_types, i); - *deny_type = reduction_type(m, *deny_type); + *deny_type = reduction_type_visited(m, *deny_type, visited); } } @@ -4326,6 +4360,14 @@ static type_t reduction_interface(module_t *m, type_t t) { } type_t reduction_type(module_t *m, type_t t) { + struct sc_map_s64 visited; + sc_map_init_s64(&visited, 0, 0); + t = reduction_type_visited(m, t, &visited); + sc_map_term_s64(&visited); + return t; +} + +static type_t reduction_type_visited(module_t *m, type_t t, struct sc_map_s64 *visited) { assert(t.kind > 0); char *ident = t.ident; @@ -4343,7 +4385,7 @@ type_t reduction_type(module_t *m, type_t t) { } if (type_is_ident(&t)) { - t = reduction_type_ident(m, t); + t = reduction_type_ident(m, t, visited); goto STATUS_DONE; } @@ -4355,7 +4397,7 @@ type_t reduction_type(module_t *m, type_t t) { table_t *arg_table = stack_top(m->infer_type_args_stack); assert(arg_table); - t = type_param_special(m, t, arg_table); + t = type_param_special(m, t, arg_table, visited); ident = t.ident; ident_kind = t.ident_kind; @@ -4365,27 +4407,27 @@ type_t reduction_type(module_t *m, type_t t) { } if (t.kind == TYPE_TAGGED_UNION) { - t = reduction_tagged_union_type(m, t); + t = reduction_tagged_union_type(m, t, visited); goto STATUS_DONE; } if (t.kind == TYPE_UNION) { - t = reduction_union_type(m, t); + t = reduction_union_type(m, t, visited); goto STATUS_DONE; } if (t.kind == TYPE_INTERFACE) { - t = reduction_interface(m, t); + t = reduction_interface(m, t, visited); goto STATUS_DONE; } if (t.kind == TYPE_ENUM) { - t = reduction_enum(m, t); + t = reduction_enum(m, t, visited); goto STATUS_DONE; } // 只有 typedef ident 才有中间状态的说法 - if (is_origin_type(t)) { + if (is_origin_kind(t.kind)) { t.status = REDUCTION_STATUS_DONE; t.ident = type_kind_str[t.kind]; t.ident_kind = TYPE_IDENT_BUILTIN; @@ -4395,7 +4437,7 @@ type_t reduction_type(module_t *m, type_t t) { // infer complex type if (is_complex_type(t)) { - t = reduction_complex_type(m, t); + t = reduction_complex_type(m, t, visited); goto STATUS_DONE; } @@ -4424,15 +4466,13 @@ type_t reduction_type(module_t *m, type_t t) { if (ident_kind > 0) { t.ident_kind = ident_kind; t.ident = ident; + t.args = args; // args 与 ident 绑定 } - if (args) { - t.args = args; - } - - struct sc_map_s64 visited; - sc_map_init_s64(&visited, 0, 0); - void *found = type_recycle_check(m, &t, &visited); + struct sc_map_s64 recycle_visited; + sc_map_init_s64(&recycle_visited, 0, 0); + void *found = type_recycle_check(m, &t, &recycle_visited); + sc_map_term_s64(&recycle_visited); if (found) { INFER_ASSERTF(false, "recycle use type '%s'", (char *) found); } diff --git a/src/syntax/parser.c b/src/syntax/parser.c index c146562f..39cbe057 100644 --- a/src/syntax/parser.c +++ b/src/syntax/parser.c @@ -1000,9 +1000,10 @@ static ast_stmt_t *parser_typedef_stmt(module_t *m) { if (parser_consume(m, TOKEN_OR)) { // union type_t union_type = { - .status = REDUCTION_STATUS_UNDO, - .kind = TYPE_UNION, - .union_ = NEW(type_union_t)}; + .status = REDUCTION_STATUS_UNDO, + .kind = TYPE_UNION, + .union_ = NEW(type_union_t) + }; union_type.union_->elements = ct_list_new(sizeof(type_t)); ct_list_push(union_type.union_->elements, &t); @@ -2848,21 +2849,21 @@ static ast_stmt_t *parser_fndef_stmt(module_t *m, ast_fndef_t *fndef) { // builtin ident without explicit generics if (parser_next_is(m, 1, TOKEN_LEFT_ANGLE)) { impl_type = parser_single_type(m); - impl_type.ident = type_kind_str[impl_type.kind]; - impl_type.ident_kind = TYPE_IDENT_BUILTIN; + // impl_type.ident = type_kind_str[impl_type.kind]; + // impl_type.ident_kind = TYPE_IDENT_BUILTIN; } else { parser_must(m, TOKEN_IDENT); impl_type = builtin_impl_type_new(builtin_ident_to_kind(first_token)); - impl_type.ident = first_token->literal; - impl_type.ident_kind = TYPE_IDENT_BUILTIN; - impl_type.args = NULL; + // impl_type.ident = first_token->literal; + // impl_type.ident_kind = TYPE_IDENT_BUILTIN; + // impl_type.args = NULL; } } else if (first_token->type == TOKEN_CHAN && !parser_next_is(m, 1, TOKEN_LEFT_ANGLE)) { parser_must(m, TOKEN_CHAN); impl_type = builtin_impl_type_new(TYPE_CHAN); - impl_type.ident = type_kind_str[TYPE_CHAN]; - impl_type.ident_kind = TYPE_IDENT_BUILTIN; - impl_type.args = NULL; + // impl_type.ident = type_kind_str[TYPE_CHAN]; + // impl_type.ident_kind = TYPE_IDENT_BUILTIN; + // impl_type.args = NULL; } else { // first_token 是 type // table 就绪的情况下可以正确的解析 param diff --git a/tests/features/20241230_00_signal.c b/tests/features/20241230_00_signal.c index c669a758..156bda23 100644 --- a/tests/features/20241230_00_signal.c +++ b/tests/features/20241230_00_signal.c @@ -15,9 +15,9 @@ static void child_kill_process(pid_t target_pid) { // 等待目标进程启动 sleep(1); - + assert(target_pid > 0); - + kill(target_pid, SIGUSR1); usleep(100 * 1000); kill(target_pid, SIGUSR2); @@ -31,20 +31,20 @@ static void child_kill_process(pid_t target_pid) { kill(target_pid, SIGUSR2); usleep(100 * 1000); kill(target_pid, SIGKILL); - + exit(0); } int main(int argc, char *argv[]) { feature_test_build(); - + // 创建管道用于获取目标进程的输出 int fd[2]; if (pipe(fd) == -1) { perror("pipe failed"); exit(1); } - + // 第一个子进程:执行目标程序 pid_t exec_pid = fork(); if (exec_pid == 0) { @@ -52,18 +52,18 @@ int main(int argc, char *argv[]) { close(fd[0]); // 关闭读端 dup2(fd[1], STDOUT_FILENO); // 重定向stdout到管道 close(fd[1]); - + // 修改工作目录 if (WORKDIR) { chdir(WORKDIR); } - + // 执行目标程序 char *argv[] = {BUILD_OUTPUT, NULL}; execvp(BUILD_OUTPUT, argv); exit(EXIT_FAILURE); } - + // 父进程:现在我们有了exec_pid,创建信号发送子进程 pid_t signal_pid = fork(); if (signal_pid == -1) { @@ -75,16 +75,16 @@ int main(int argc, char *argv[]) { close(fd[1]); child_kill_process(exec_pid); } - + // 父进程:关闭写端,从管道读取输出 close(fd[1]); - + char *buf = malloc(8192 * 2); if (buf == NULL) { perror("malloc failed"); exit(1); } - + // 读取目标进程的输出 ssize_t total_read = 0; ssize_t bytes_read; @@ -93,22 +93,22 @@ int main(int argc, char *argv[]) { if (total_read >= 8192 * 2 - 1) break; } buf[total_read] = '\0'; - + close(fd[0]); - + // 等待两个子进程结束 int exec_status, signal_status; waitpid(exec_pid, &exec_status, 0); waitpid(signal_pid, &signal_status, 0); - + char *str = dsprintf("received signal: %d\n" + "received signal: %d\n" + "received signal: %d\n" + "received signal: %d\n" + "received signal: %d\n" + "received signal: %d\n", SIGUSR1, SIGUSR2, SIGTERM, SIGINT, SIGUSR1, SIGUSR2); // 验证输出 - assert_string_equal(buf, dsprintf("received signal: %d\n" - "received signal: %d\n" - "received signal: %d\n" - "received signal: %d\n" - "received signal: %d\n" - "received signal: %d\n", SIGUSR1, SIGUSR2, SIGTERM, SIGINT, SIGUSR1, SIGUSR2)); - + assert_string_equal(buf, str); + free(buf); return 0; -} \ No newline at end of file +} diff --git a/tests/features/20250329_00_temp_test.c b/tests/features/20250329_00_temp_test.c index f489a7b7..ea1d8d00 100644 --- a/tests/features/20250329_00_temp_test.c +++ b/tests/features/20250329_00_temp_test.c @@ -7,8 +7,8 @@ int main(void) { // char *useld = "ld"; // strcpy(USE_LD, useld); - // chdir("/Users/weiwenhao/Code/emoji-api"); - // setenv("ENTRY_FILE", "main.n", 1); + // chdir("/Users/weiwenhao/Code/emoji-api"); + // setenv("ENTRY_FILE", "main.n", 1); feature_test_build(); sleep(1); diff --git a/tests/features/cases/20250329_00_temp_test.n b/tests/features/cases/20250329_00_temp_test.n index 4a44042d..3e26d584 100644 --- a/tests/features/cases/20250329_00_temp_test.n +++ b/tests/features/cases/20250329_00_temp_test.n @@ -1,3 +1,8 @@ +fn vec.temp(*self):int { + return self.len() // self 的类型推断出现了严重的问题?这可能源于? +} + fn main() { - println('hello world') + [int] a = [1, 2, 3] + a.temp() } \ No newline at end of file diff --git a/utils/helper.h b/utils/helper.h index 823130e3..fa9f5142 100644 --- a/utils/helper.h +++ b/utils/helper.h @@ -247,6 +247,13 @@ static inline char *utoa(uint64_t n) { } static inline bool str_equal(char *a, char *b) { + if (a == NULL && b != NULL) { + return false; + } + if (b == NULL && a != NULL) { + return false; + } + return strcmp(a, b) == 0; } diff --git a/utils/type.c b/utils/type.c index 7a15062a..da051165 100644 --- a/utils/type.c +++ b/utils/type.c @@ -553,17 +553,17 @@ char *type_origin_format(type_t t) { type_t type_kind_new(type_kind kind) { type_t result = { - .status = REDUCTION_STATUS_DONE, - .kind = kind, - .value = 0, - .ident = NULL, - .ident_kind = 0, + .status = REDUCTION_STATUS_DONE, + .kind = kind, + .value = 0, + .ident = NULL, + .ident_kind = 0, }; - // 不能直接填充 ident, 比如 vec ident 必须要有 args, 但是此时无法计算 args - if (is_impl_builtin_type(kind)) { + if (is_origin_kind(kind)) { result.ident = type_kind_str[kind]; result.ident_kind = TYPE_IDENT_BUILTIN; + result.args = NULL; } result.in_heap = kind_in_heap(kind); @@ -577,17 +577,18 @@ type_t type_kind_new(type_kind kind) { type_t type_new(type_kind kind, void *value) { type_t result = { - .kind = kind, - .value = value, - .in_heap = kind_in_heap(kind), - .status = REDUCTION_STATUS_DONE, - .ident = NULL, - .ident_kind = 0, + .kind = kind, + .value = value, + .in_heap = kind_in_heap(kind), + .status = REDUCTION_STATUS_DONE, + .ident = NULL, + .ident_kind = 0, }; - if (is_impl_builtin_type(kind)) { + if (is_origin_kind(kind)) { result.ident = type_kind_str[kind]; result.ident_kind = TYPE_IDENT_BUILTIN; + result.args = NULL; } result.storage_kind = type_storage_kind(result); diff --git a/utils/type.h b/utils/type.h index 88d1f7a1..2c78a708 100644 --- a/utils/type.h +++ b/utils/type.h @@ -64,9 +64,7 @@ typedef union { typedef enum { REDUCTION_STATUS_UNDO = 1, - REDUCTION_STATUS_DOING = 2, - REDUCTION_STATUS_DOING2 = 3, - REDUCTION_STATUS_DONE = 4 + REDUCTION_STATUS_DONE = 2 } reduction_status_t; typedef enum { @@ -1039,10 +1037,10 @@ static inline bool is_gc_alloc(type_kind kind) { * @param t * @return */ -static inline bool is_origin_type(type_t t) { - return is_integer(t.kind) || is_float(t.kind) || t.kind == TYPE_ANYPTR || t.kind == TYPE_VOID || - t.kind == TYPE_NULL || t.kind == TYPE_BOOL || t.kind == TYPE_ANY || - t.kind == TYPE_STRING || t.kind == TYPE_FN_T || t.kind == TYPE_ALL_T; +static inline bool is_origin_kind(type_kind kind) { + return is_integer(kind) || is_float(kind) || kind == TYPE_ANYPTR || kind == TYPE_VOID || + kind == TYPE_NULL || kind == TYPE_BOOL || kind == TYPE_ANY || + kind == TYPE_STRING || kind == TYPE_FN_T || kind == TYPE_ALL_T; } static inline bool is_clv_default_type(type_t t) {