Add NoTypeDisplay trait

This commit is contained in:
Shunsuke Shibayama 2022-12-09 22:01:09 +09:00
parent 5830253d7b
commit ddd7abbaed
4 changed files with 375 additions and 68 deletions

View file

@ -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<T: NestedDisplay> 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]

View file

@ -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,
)))
}
}

View file

@ -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<Vec<Expr>> 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::<Vec<_>>()
.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::<Vec<_>>()
.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::<Vec<_>>()
.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::<Vec<_>>()
.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::<Vec<_>>()
.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::<Vec<_>>()
.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::<Vec<_>>()
.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 {

View file

@ -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};