diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index 01b5188f..3109b555 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -589,6 +589,10 @@ pub trait NestedDisplay { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result; } +pub trait NoTypeDisplay { + fn to_string_notype(&self) -> String; +} + /// `impl Display for T NestedDisplay`はorphan-ruleに違反するので個別定義する #[macro_export] macro_rules! impl_display_from_nested { @@ -605,7 +609,7 @@ macro_rules! impl_display_from_nested { #[macro_export] macro_rules! impl_nested_display_for_chunk_enum { ($Enum: ident; $($Variant: ident $(,)?)*) => { - impl NestedDisplay for $Enum { + impl $crate::traits::NestedDisplay for $Enum { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { write!(f, "{}", " ".repeat(level))?; match self { @@ -619,7 +623,7 @@ macro_rules! impl_nested_display_for_chunk_enum { #[macro_export] macro_rules! impl_nested_display_for_enum { ($Enum: ident; $($Variant: ident $(,)?)*) => { - impl NestedDisplay for $Enum { + impl $crate::traits::NestedDisplay for $Enum { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { match self { $($Enum::$Variant(v) => v.fmt_nest(f, level),)* @@ -629,6 +633,19 @@ macro_rules! impl_nested_display_for_enum { } } +#[macro_export] +macro_rules! impl_no_type_display_for_enum { + ($Enum: ident; $($Variant: ident $(,)?)*) => { + impl $crate::traits::NoTypeDisplay for $Enum { + fn to_string_notype(&self) -> String { + match self { + $($Enum::$Variant(v) => v.to_string_notype(),)* + } + } + } + } +} + /// Pythonではis演算子に相当 pub trait AddrEq { #[inline] diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index dd26b4ea..e0dd051b 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -7,9 +7,9 @@ use erg_common::env::{erg_pystd_path, erg_std_path}; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; use erg_common::levenshtein::get_similar_name; use erg_common::set::Set; -use erg_common::traits::{Locational, Stream}; +use erg_common::traits::{Locational, NoTypeDisplay, Stream}; use erg_common::vis::Visibility; -use erg_common::{enum_unwrap, fmt_option, fmt_slice, log, set}; +use erg_common::{enum_unwrap, fmt_option, fmt_slice, log, set, switch_lang}; use erg_common::{option_enum_unwrap, Str}; use Type::*; @@ -1106,6 +1106,16 @@ impl Context { } } other => { + let hint = if other == &ClassType { + Some(switch_lang! { + "japanese" => format!("インスタンスを生成したい場合は、{}.newを使用してください", obj.to_string_notype()), + "simplified_chinese" => format!("如果要生成实例,请使用 {}.new", obj.to_string_notype()), + "traditional_chinese" => format!("如果要生成實例,請使用 {}.new", obj.to_string_notype()), + "english" => format!("If you want to generate an instance, use {}.new", obj.to_string_notype()), + }) + } else { + None + }; if let Some(attr_name) = attr_name { Err(TyCheckErrors::from(TyCheckError::type_mismatch_error( self.cfg.input.clone(), @@ -1117,7 +1127,7 @@ impl Context { &mono("Callable"), other, self.get_candidates(other), - None, + hint, ))) } else { Err(TyCheckErrors::from(TyCheckError::type_mismatch_error( @@ -1130,7 +1140,7 @@ impl Context { &mono("Callable"), other, self.get_candidates(other), - None, + hint, ))) } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index a2dad602..67e5293a 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -5,14 +5,14 @@ use erg_common::dict::Dict as HashMap; use erg_common::error::Location; #[allow(unused_imports)] use erg_common::log; -use erg_common::traits::{Locational, NestedDisplay, Stream}; +use erg_common::traits::{Locational, NestedDisplay, NoTypeDisplay, Stream}; use erg_common::vis::{Field, Visibility}; -use erg_common::Str; use erg_common::{ enum_unwrap, fmt_option, fmt_vec, impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum, impl_stream_for_wrapper, }; +use erg_common::{impl_no_type_display_for_enum, Str}; use erg_parser::ast::{ fmt_lines, DefId, DefKind, NonDefaultParamSignature, OperationKind, TypeSpec, VarName, @@ -44,6 +44,12 @@ impl NestedDisplay for Literal { } } +impl NoTypeDisplay for Literal { + fn to_string_notype(&self) -> String { + format!("{}", self.token.content) + } +} + impl_display_from_nested!(Literal); impl Locational for Literal { @@ -94,6 +100,12 @@ impl NestedDisplay for PosArg { } } +impl NoTypeDisplay for PosArg { + fn to_string_notype(&self) -> String { + self.expr.to_string_notype() + } +} + impl_display_from_nested!(PosArg); impl Locational for PosArg { @@ -121,6 +133,16 @@ impl NestedDisplay for KwArg { } } +impl NoTypeDisplay for KwArg { + fn to_string_notype(&self) -> String { + format!( + "{} := {}", + self.keyword.content, + self.expr.to_string_notype() + ) + } +} + impl_display_from_nested!(KwArg); impl Locational for KwArg { @@ -159,6 +181,30 @@ impl NestedDisplay for Args { } } +impl NoTypeDisplay for Args { + fn to_string_notype(&self) -> String { + let mut s = String::new(); + if !self.pos_args.is_empty() { + s += &self + .pos_args + .iter() + .map(|x| x.to_string_notype()) + .fold("".to_string(), |acc, s| acc + &s + ", "); + } + if let Some(var_args) = &self.var_args { + s += &format!(", ...{}", var_args.to_string_notype()); + } + if !self.kw_args.is_empty() { + s += &self + .kw_args + .iter() + .map(|x| x.to_string_notype()) + .fold("".to_string(), |acc, s| acc + &s + ", "); + } + s + } +} + // do not implement From> to Args, because it will miss paren info (use `values`) impl_display_from_nested!(Args); @@ -349,6 +395,15 @@ impl NestedDisplay for Identifier { } } +impl NoTypeDisplay for Identifier { + fn to_string_notype(&self) -> String { + match &self.dot { + Some(_dot) => format!(".{}", self.name), + None => format!("::{}", self.name), + } + } +} + impl_display_from_nested!(Identifier); impl HasType for Identifier { @@ -473,6 +528,16 @@ impl NestedDisplay for Attribute { } } +impl NoTypeDisplay for Attribute { + fn to_string_notype(&self) -> String { + format!( + "({}){}", + self.obj.to_string_notype(), + self.ident.to_string_notype() + ) + } +} + impl_display_from_nested!(Attribute); impl_locational!(Attribute, obj, ident); @@ -511,6 +576,7 @@ pub enum Accessor { } impl_nested_display_for_enum!(Accessor; Ident, Attr); +impl_no_type_display_for_enum!(Accessor; Ident, Attr); impl_display_from_nested!(Accessor); impl_locational_for_enum!(Accessor; Ident, Attr); impl_t_for_enum!(Accessor; Ident, Attr); @@ -602,6 +668,16 @@ impl NestedDisplay for ArrayWithLength { } } +impl NoTypeDisplay for ArrayWithLength { + fn to_string_notype(&self) -> String { + format!( + "[{}; {}]", + self.elem.to_string_notype(), + self.len.to_string_notype() + ) + } +} + impl_display_from_nested!(ArrayWithLength); impl_locational!(ArrayWithLength, l_sqbr, r_sqbr); impl_t!(ArrayWithLength); @@ -634,6 +710,16 @@ impl NestedDisplay for ArrayComprehension { } } +impl NoTypeDisplay for ArrayComprehension { + fn to_string_notype(&self) -> String { + format!( + "[{} | {}]", + self.elem.to_string_notype(), + self.guard.to_string_notype() + ) + } +} + impl_display_from_nested!(ArrayComprehension); impl_locational!(ArrayComprehension, l_sqbr, r_sqbr); impl_t!(ArrayComprehension); @@ -654,6 +740,20 @@ impl NestedDisplay for NormalArray { } } +impl NoTypeDisplay for NormalArray { + fn to_string_notype(&self) -> String { + format!( + "[{}]", + self.elems + .pos_args + .iter() + .map(|arg| arg.to_string_notype()) + .collect::>() + .join(", ") + ) + } +} + impl_display_from_nested!(NormalArray); impl_locational!(NormalArray, l_sqbr, r_sqbr); impl_t!(NormalArray); @@ -682,6 +782,7 @@ pub enum Array { } impl_nested_display_for_enum!(Array; Normal, Comprehension, WithLength); +impl_no_type_display_for_enum!(Array; Normal, Comprehension, WithLength); impl_display_for_enum!(Array; Normal, Comprehension, WithLength); impl_locational_for_enum!(Array; Normal, Comprehension, WithLength); impl_t_for_enum!(Array; Normal, Comprehension, WithLength); @@ -700,6 +801,20 @@ impl NestedDisplay for NormalTuple { } } +impl NoTypeDisplay for NormalTuple { + fn to_string_notype(&self) -> String { + format!( + "({})", + self.elems + .pos_args + .iter() + .map(|arg| arg.to_string_notype()) + .collect::>() + .join(", ") + ) + } +} + impl_display_from_nested!(NormalTuple); impl_locational!(NormalTuple, elems); impl_t!(NormalTuple); @@ -718,6 +833,7 @@ pub enum Tuple { } impl_nested_display_for_enum!(Tuple; Normal); +impl_no_type_display_for_enum!(Tuple; Normal); impl_display_for_enum!(Tuple; Normal); impl_locational_for_enum!(Tuple; Normal); impl_t_for_enum!(Tuple; Normal); @@ -734,6 +850,16 @@ impl NestedDisplay for KeyValue { } } +impl NoTypeDisplay for KeyValue { + fn to_string_notype(&self) -> String { + format!( + "{}: {}", + self.key.to_string_notype(), + self.value.to_string_notype() + ) + } +} + impl_display_from_nested!(KeyValue); impl_locational!(KeyValue, key, value); @@ -759,6 +885,19 @@ impl NestedDisplay for NormalDict { } } +impl NoTypeDisplay for NormalDict { + fn to_string_notype(&self) -> String { + format!( + "{{{}}}", + self.kvs + .iter() + .map(|kv| kv.to_string_notype()) + .collect::>() + .join(", ") + ) + } +} + impl_display_from_nested!(NormalDict); impl_locational!(NormalDict, l_brace, r_brace); @@ -798,6 +937,17 @@ impl NestedDisplay for DictComprehension { } } +impl NoTypeDisplay for DictComprehension { + fn to_string_notype(&self) -> String { + format!( + "[{}: {} | {}]", + self.key.to_string_notype(), + self.value.to_string_notype(), + self.guard.to_string_notype() + ) + } +} + impl_display_from_nested!(DictComprehension); impl_locational!(DictComprehension, l_sqbr, r_sqbr); impl_t!(DictComprehension); @@ -809,6 +959,7 @@ pub enum Dict { } impl_nested_display_for_enum!(Dict; Normal, Comprehension); +impl_no_type_display_for_enum!(Dict; Normal, Comprehension); impl_display_for_enum!(Dict; Normal, Comprehension); impl_locational_for_enum!(Dict; Normal, Comprehension); impl_t_for_enum!(Dict; Normal, Comprehension); @@ -829,6 +980,20 @@ impl NestedDisplay for NormalSet { } } +impl NoTypeDisplay for NormalSet { + fn to_string_notype(&self) -> String { + format!( + "{{{}}}", + self.elems + .pos_args + .iter() + .map(|e| e.to_string_notype()) + .collect::>() + .join(", ") + ) + } +} + impl_display_from_nested!(NormalSet); impl_locational!(NormalSet, l_brace, r_brace); impl_t!(NormalSet); @@ -856,7 +1021,17 @@ pub struct SetWithLength { impl NestedDisplay for SetWithLength { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "[{}; {}](: {})", self.elem, self.len, self.t) + write!(f, "{{{}; {}}}(: {})", self.elem, self.len, self.t) + } +} + +impl NoTypeDisplay for SetWithLength { + fn to_string_notype(&self) -> String { + format!( + "{{{}; {}}}", + self.elem.to_string_notype(), + self.len.to_string_notype() + ) } } @@ -883,6 +1058,7 @@ pub enum Set { } impl_nested_display_for_enum!(Set; Normal, WithLength); +impl_no_type_display_for_enum!(Set; Normal, WithLength); impl_display_for_enum!(Set; Normal, WithLength); impl_locational_for_enum!(Set; Normal, WithLength); impl_t_for_enum!(Set; Normal, WithLength); @@ -896,6 +1072,16 @@ impl NestedDisplay for RecordAttrs { } } +impl NoTypeDisplay for RecordAttrs { + fn to_string_notype(&self) -> String { + self.0 + .iter() + .map(|a| a.to_string_notype()) + .collect::>() + .join("\n") + } +} + impl_display_from_nested!(RecordAttrs); impl_stream_for_wrapper!(RecordAttrs, Def); @@ -953,6 +1139,19 @@ impl NestedDisplay for Record { } } +impl NoTypeDisplay for Record { + fn to_string_notype(&self) -> String { + format!( + "{{{}}}", + self.attrs + .iter() + .map(|a| a.to_string_notype()) + .collect::>() + .join("; ") + ) + } +} + impl_display_from_nested!(Record); impl_locational!(Record, l_brace, r_brace); impl_t!(Record); @@ -996,6 +1195,17 @@ impl NestedDisplay for BinOp { } } +impl NoTypeDisplay for BinOp { + fn to_string_notype(&self) -> String { + format!( + "`{}`({}, {})", + self.op.content, + self.lhs.to_string_notype(), + self.rhs.to_string_notype() + ) + } +} + impl HasType for BinOp { #[inline] fn ref_t(&self) -> &Type { @@ -1076,6 +1286,12 @@ impl NestedDisplay for UnaryOp { } } +impl NoTypeDisplay for UnaryOp { + fn to_string_notype(&self) -> String { + format!("`{}`({})", self.op.content, self.expr.to_string_notype()) + } +} + impl_display_from_nested!(UnaryOp); impl_locational!(UnaryOp, op, expr); @@ -1108,6 +1324,17 @@ impl NestedDisplay for Call { } } +impl NoTypeDisplay for Call { + fn to_string_notype(&self) -> String { + format!( + "({}){}({})", + self.obj.to_string_notype(), + fmt_option!(self.attr_name), + self.args.to_string_notype() + ) + } +} + impl_display_from_nested!(Call); impl HasType for Call { @@ -1224,6 +1451,16 @@ impl NestedDisplay for Block { } } +impl NoTypeDisplay for Block { + fn to_string_notype(&self) -> String { + self.0 + .iter() + .map(|e| e.to_string_notype()) + .collect::>() + .join("; ") + } +} + impl_display_from_nested!(Block); impl_stream_for_wrapper!(Block, Expr); @@ -1293,6 +1530,12 @@ impl NestedDisplay for DefaultParamSignature { } } +impl NoTypeDisplay for DefaultParamSignature { + fn to_string_notype(&self) -> String { + format!("{} := {}", self.sig, self.default_val.to_string_notype()) + } +} + impl_display_from_nested!(DefaultParamSignature); impl Locational for DefaultParamSignature { @@ -1331,6 +1574,20 @@ impl fmt::Display for Params { } } +impl NoTypeDisplay for Params { + fn to_string_notype(&self) -> String { + format!( + "({}, {}, {})", + fmt_vec(&self.non_defaults), + fmt_option!(pre "...", &self.var_args), + self.defaults + .iter() + .map(|p| p.to_string_notype()) + .fold("".to_string(), |acc, e| acc + &e + ", ") + ) + } +} + impl Locational for Params { fn loc(&self) -> Location { // FIXME: varargs @@ -1416,13 +1673,23 @@ impl NestedDisplay for SubrSignature { write!( f, "{}{} (: {})", - self.ident.to_string_without_type(), + self.ident.to_string_notype(), self.params, self.ident.t() ) } } +impl NoTypeDisplay for SubrSignature { + fn to_string_notype(&self) -> String { + format!( + "{}{}", + self.ident.to_string_notype(), + self.params.to_string_notype() + ) + } +} + impl_display_from_nested!(SubrSignature); impl_locational!(SubrSignature, ident, params); @@ -1471,6 +1738,17 @@ impl NestedDisplay for Lambda { } } +impl NoTypeDisplay for Lambda { + fn to_string_notype(&self) -> String { + format!( + "{} {} {}", + self.params.to_string_notype(), + self.op.content, + self.body.to_string_notype() + ) + } +} + impl_display_from_nested!(Lambda); impl_locational!(Lambda, params, body); impl_t!(Lambda); @@ -1550,58 +1828,6 @@ impl Signature { } } -/// represents a declaration of a variable -/// necessary for type field declaration -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Decl { - pub sig: Signature, - pub t: Type, -} - -impl NestedDisplay for Decl { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "{}: {}", self.sig, self.t) - } -} - -impl_display_from_nested!(Decl); - -impl Locational for Decl { - #[inline] - fn loc(&self) -> Location { - self.sig.loc() - } -} - -impl HasType for Decl { - #[inline] - fn ref_t(&self) -> &Type { - Type::NONE - } - #[inline] - fn ref_mut_t(&mut self) -> &mut Type { - todo!() - } - #[inline] - fn signature_t(&self) -> Option<&Type> { - None - } - #[inline] - fn signature_mut_t(&mut self) -> Option<&mut Type> { - None - } -} - -impl Decl { - pub const fn spec_t(&self) -> &Type { - &self.t - } - - pub const fn is_sub(&self) -> bool { - self.sig.is_subr() - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct DefBody { pub op: Token, @@ -1630,6 +1856,17 @@ impl NestedDisplay for Def { } } +impl NoTypeDisplay for Def { + fn to_string_notype(&self) -> String { + format!( + "{} {} {}", + self.sig, + self.body.op.content, + self.body.block.to_string_notype() + ) + } +} + impl_display_from_nested!(Def); impl_locational!(Def, sig, body); @@ -1698,6 +1935,18 @@ impl NestedDisplay for Methods { } } +// TODO +impl NoTypeDisplay for Methods { + fn to_string_notype(&self) -> String { + format!( + "{}{} {}", + self.class, + self.vis.content, + self.defs.to_string_notype() + ) + } +} + impl_display_from_nested!(Methods); impl_locational!(Methods, class, defs); @@ -1745,6 +1994,13 @@ impl NestedDisplay for ClassDef { } } +// TODO +impl NoTypeDisplay for ClassDef { + fn to_string_notype(&self) -> String { + format!("{}: {}", self.sig, self.methods.to_string_notype()) + } +} + impl_display_from_nested!(ClassDef); impl_locational!(ClassDef, sig); @@ -1803,6 +2059,18 @@ impl NestedDisplay for PatchDef { } } +// TODO +impl NoTypeDisplay for PatchDef { + fn to_string_notype(&self) -> String { + format!( + "{} = Patch {}: {}", + self.sig, + self.base.to_string_notype(), + self.methods.to_string_notype() + ) + } +} + impl_display_from_nested!(PatchDef); impl_locational!(PatchDef, sig); @@ -1849,6 +2117,16 @@ impl NestedDisplay for AttrDef { } } +impl NoTypeDisplay for AttrDef { + fn to_string_notype(&self) -> String { + format!( + "{} = {}", + self.attr.to_string_notype(), + self.block.to_string_notype() + ) + } +} + impl_display_from_nested!(AttrDef); impl_locational!(AttrDef, attr, block); @@ -1889,6 +2167,12 @@ impl NestedDisplay for TypeAscription { } } +impl NoTypeDisplay for TypeAscription { + fn to_string_notype(&self) -> String { + format!("{}: {}", self.expr.to_string_notype(), self.spec) + } +} + impl_display_from_nested!(TypeAscription); impl_locational!(TypeAscription, expr, spec); @@ -1944,6 +2228,7 @@ pub enum Expr { } impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, AttrDef, Code, Compound, TypeAsc, Set, Import); +impl_no_type_display_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, AttrDef, Code, Compound, TypeAsc, Set, Import); impl_display_from_nested!(Expr); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, AttrDef, Code, Compound, TypeAsc, Set, Import); impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, AttrDef, Code, Compound, TypeAsc, Set, Import); @@ -1969,11 +2254,6 @@ impl Expr { } } - pub fn to_string_notype(&self) -> String { - let s = self.to_string(); - s.split("(:").next().unwrap_or("?").trim_end().to_string() - } - /// 参照するオブジェクト自体が持っている名前(e.g. Int.qual_name == Some("int"), Socket!.qual_name == Some("io.Socket!")) pub fn qual_name(&self) -> Option<&str> { match self { diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 07f95369..85e84244 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -7,7 +7,7 @@ use erg_common::dict; use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::set; use erg_common::set::Set; -use erg_common::traits::{Locational, Runnable, Stream}; +use erg_common::traits::{Locational, NoTypeDisplay, Runnable, Stream}; use erg_common::vis::Visibility; use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, Str};