Change: String to Cow<'a, str>

This commit is contained in:
GreasySlug 2022-11-21 14:21:03 +09:00
parent 9611322533
commit cc9fa5a12e
3 changed files with 258 additions and 160 deletions

View file

@ -1,4 +1,4 @@
use std::borrow::Borrow; use std::borrow::{Borrow, Cow};
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::{Add, Deref}; use std::ops::{Add, Deref};
@ -61,6 +61,15 @@ impl From<Str> for String {
} }
} }
impl<'a> From<Str> for Cow<'a, str> {
fn from(s: Str) -> Self {
match s {
Str::Static(s) => Cow::Owned(s.to_owned()),
_ => unreachable!(),
}
}
}
// &'static str -> &strになってしまわないように // &'static str -> &strになってしまわないように
// あえて`impl<S: Into<Str>> From<S> for Str { ... }`はしない // あえて`impl<S: Into<Str>> From<S> for Str { ... }`はしない
impl From<&'static str> for Str { impl From<&'static str> for Str {

View file

@ -1,3 +1,5 @@
use std::borrow::Cow;
pub const ATTR_RESET: &str = "\x1b[0m"; pub const ATTR_RESET: &str = "\x1b[0m";
pub const BOLD: &str = "\x1b[1m"; pub const BOLD: &str = "\x1b[1m";
pub const UNDERLINE: &str = "\x1b[4m"; pub const UNDERLINE: &str = "\x1b[4m";
@ -315,9 +317,14 @@ pub struct StyledString {
} }
impl StyledString { impl StyledString {
pub fn new(s: &str, color: Option<Color>, attribute: Option<Attribute>) -> Self { pub fn new<'a, S: Into<Cow<'a, str>>>(
s: S,
color: Option<Color>,
attribute: Option<Attribute>,
) -> Self {
let text: Cow<'a, str> = s.into();
Self { Self {
text: String::from(s), text: text.into_owned(),
color, color,
attribute, attribute,
} }
@ -420,9 +427,10 @@ impl StyledStrings {
/// texts.push_str_with_color("\n If you want to add break lines, you should add `\n`.", Color::Magenta); /// texts.push_str_with_color("\n If you want to add break lines, you should add `\n`.", Color::Magenta);
/// println!("{}", texts); /// println!("{}", texts);
/// ``` /// ```
pub fn push_str_with_color(&mut self, s: &str, color: Color) { pub fn push_str_with_color<'a, S: Into<Cow<'a, str>>>(&mut self, s: S, color: Color) {
if self.is_same_color(color) { if self.is_same_color(color) {
self.texts.last_mut().unwrap().text.push_str(s); let text = s.into();
self.texts.last_mut().unwrap().text.push_str(&text);
} else { } else {
self.texts.push(StyledString::new(s, Some(color), None)); self.texts.push(StyledString::new(s, Some(color), None));
} }
@ -441,9 +449,15 @@ impl StyledStrings {
/// // texts.push_str_with_color_and_attribute("Must be specify the color and attribute", None, Attribute::Underline); /// // texts.push_str_with_color_and_attribute("Must be specify the color and attribute", None, Attribute::Underline);
/// println!("{}", texts); /// println!("{}", texts);
/// ``` /// ```
pub fn push_str_with_color_and_attribute(&mut self, s: &str, color: Color, attr: Attribute) { pub fn push_str_with_color_and_attribute<'a, S: Into<Cow<'a, str>>>(
&mut self,
s: S,
color: Color,
attr: Attribute,
) {
if self.is_same_color(color) && self.is_same_attribute(attr) { if self.is_same_color(color) && self.is_same_attribute(attr) {
self.texts.last_mut().unwrap().text.push_str(s); let text = s.into();
self.texts.last_mut().unwrap().text.push_str(&text);
} else { } else {
self.texts self.texts
.push(StyledString::new(s, Some(color), Some(attr))); .push(StyledString::new(s, Some(color), Some(attr)));

View file

@ -145,11 +145,25 @@ impl ErrorDisplay for CompileError {
} }
} }
// found, error
const ERR: Color = THEME.colors.error;
// name
const WARN: Color = THEME.colors.warning;
// expect, hint
const HINT: Color = THEME.colors.hint;
// url and var name
const ACCENT: Color = THEME.colors.accent; const ACCENT: Color = THEME.colors.accent;
// url and feature = pretty
const UNDERLINE: Attribute = Attribute::Underline;
#[cfg(not(feature = "pretty"))]
const ATTR: Attribute = Attribute::Bold;
#[cfg(feature = "pretty")]
const ATTR: Attribute = Attribute::Underline;
const URL: StyledStr = StyledStr::new( const URL: StyledStr = StyledStr::new(
"https://github.com/erg-lang/erg", "https://github.com/erg-lang/erg",
Some(ACCENT), Some(ACCENT),
Some(Attribute::Underline), Some(UNDERLINE),
); );
impl CompileError { impl CompileError {
@ -208,7 +222,7 @@ impl CompileError {
Erg ({URL})\n\ Erg ({URL})\n\
: {fn_name}"), : {fn_name}"),
"english" => format!("the number of elements in the stack is invalid (num of elems: {stack_len}, block id: {block_id})\n\ "english" => format!("the number of elements in the stack is invalid (num of elems: {stack_len}, block id: {block_id})\n\
this is a bug of the Erg compiler, please report it ({URL})\n\ this is a bug of the Erg compiler, please report it to {URL}\n\
caused from: {fn_name}"), caused from: {fn_name}"),
), ),
0, 0,
@ -261,10 +275,6 @@ impl CompileError {
pub type TyCheckError = CompileError; pub type TyCheckError = CompileError;
const ERR: Color = THEME.colors.error;
const WARN: Color = THEME.colors.warning;
const HINT: Color = THEME.colors.hint;
impl TyCheckError { impl TyCheckError {
pub fn dummy(input: Input, errno: usize) -> Self { pub fn dummy(input: Input, errno: usize) -> Self {
Self::new(ErrorCore::dummy(errno), input, "".into()) Self::new(ErrorCore::dummy(errno), input, "".into())
@ -377,11 +387,7 @@ impl TyCheckError {
), ),
None => "".into(), None => "".into(),
}; };
let name = StyledString::new( let name = StyledString::new(format!("{}{}", name, ord), Some(WARN), Some(ATTR));
&format!("{}{}", name, ord),
Some(WARN),
Some(Attribute::Bold),
);
let mut expct = StyledStrings::default(); let mut expct = StyledStrings::default();
switch_lang!( switch_lang!(
"japanese" => expct.push_str("予期した型: "), "japanese" => expct.push_str("予期した型: "),
@ -389,7 +395,7 @@ impl TyCheckError {
"traditional_chinese" => expct.push_str("預期: "), "traditional_chinese" => expct.push_str("預期: "),
"english" => expct.push_str("expected: "), "english" => expct.push_str("expected: "),
); );
expct.push_str_with_color_and_attribute(&format!("{}", expect), HINT, Attribute::Bold); expct.push_str_with_color_and_attribute(format!("{}", expect), HINT, ATTR);
let mut fnd = StyledStrings::default(); let mut fnd = StyledStrings::default();
switch_lang!( switch_lang!(
@ -398,12 +404,12 @@ impl TyCheckError {
"traditional_chinese" => fnd.push_str("但找到: "), "traditional_chinese" => fnd.push_str("但找到: "),
"english" =>fnd.push_str("but found: "), "english" =>fnd.push_str("but found: "),
); );
fnd.push_str_with_color_and_attribute(&format!("{}", found), ERR, Attribute::Bold); fnd.push_str_with_color_and_attribute(format!("{}", found), ERR, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
loc, loc,
vec![expct.into(), fnd.into()], vec![expct.to_string(), fnd.to_string()],
hint, hint,
)], )],
switch_lang!( switch_lang!(
@ -437,7 +443,7 @@ impl TyCheckError {
"traditional_chinese" => expct.push_str("預期: "), "traditional_chinese" => expct.push_str("預期: "),
"english" => expct.push_str("expected: "), "english" => expct.push_str("expected: "),
); );
expct.push_str_with_color_and_attribute(&format!("{}", expect), HINT, Attribute::Bold); expct.push_str_with_color_and_attribute(format!("{}", expect), HINT, ATTR);
let mut fnd = StyledStrings::default(); let mut fnd = StyledStrings::default();
switch_lang!( switch_lang!(
@ -446,13 +452,13 @@ impl TyCheckError {
"traditional_chinese" => fnd.push_str("但找到: "), "traditional_chinese" => fnd.push_str("但找到: "),
"english" =>fnd.push_str("but found: "), "english" =>fnd.push_str("but found: "),
); );
fnd.push_str_with_color_and_attribute(&format!("{}", found), ERR, Attribute::Bold); fnd.push_str_with_color_and_attribute(format!("{}", found), ERR, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
loc, loc,
vec![expct.into(), fnd.into()], vec![expct.to_string(), fnd.to_string()],
None, None,
)], )],
switch_lang!( switch_lang!(
@ -511,7 +517,7 @@ impl TyCheckError {
"traditional_chinese" => expct.push_str("預期: "), "traditional_chinese" => expct.push_str("預期: "),
"english" => expct.push_str("expected: "), "english" => expct.push_str("expected: "),
); );
expct.push_str_with_color_and_attribute(&format!("{}", expect), HINT, Attribute::Bold); expct.push_str_with_color_and_attribute(format!("{}", expect), HINT, ATTR);
let mut fnd = StyledStrings::default(); let mut fnd = StyledStrings::default();
switch_lang!( switch_lang!(
@ -520,11 +526,15 @@ impl TyCheckError {
"traditional_chinese" => fnd.push_str("但找到: "), "traditional_chinese" => fnd.push_str("但找到: "),
"english" =>fnd.push_str("but found: "), "english" =>fnd.push_str("but found: "),
); );
fnd.push_str_with_color_and_attribute(&format!("{}", found), ERR, Attribute::Bold); fnd.push_str_with_color_and_attribute(format!("{}", found), ERR, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::ambiguous_new(
loc,
vec![expct.to_string(), fnd.to_string()],
None,
)],
switch_lang!( switch_lang!(
"japanese" => format!("ポジショナル引数の数が違います"), "japanese" => format!("ポジショナル引数の数が違います"),
"simplified_chinese" => format!("正则参数的数量不匹配"), "simplified_chinese" => format!("正则参数的数量不匹配"),
@ -610,21 +620,9 @@ impl TyCheckError {
kw_args_len: usize, kw_args_len: usize,
) -> Self { ) -> Self {
let name = readable_name(callee_name); let name = readable_name(callee_name);
let expect = StyledString::new( let expect = StyledString::new(format!("{}", params_len), Some(HINT), Some(ATTR));
&format!("{}", params_len), let pos_args_len = StyledString::new(format!("{}", pos_args_len), Some(ERR), Some(ATTR));
Some(HINT), let kw_args_len = StyledString::new(format!("{}", kw_args_len), Some(ERR), Some(ATTR));
Some(Attribute::Bold),
);
let pos_args_len = StyledString::new(
&format!("{}", pos_args_len),
Some(ERR),
Some(Attribute::Bold),
);
let kw_args_len = StyledString::new(
&format!("{}", kw_args_len),
Some(ERR),
Some(Attribute::Bold),
);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -674,9 +672,8 @@ passed keyword args: {kw_args_len}"
missing_len: usize, missing_len: usize,
missing_params: Vec<Str>, missing_params: Vec<Str>,
) -> Self { ) -> Self {
let name = readable_name(callee_name); let name = StyledStr::new(readable_name(callee_name), Some(ACCENT), Some(ATTR));
let vec_cxt = let vec_cxt = StyledString::new(&fmt_vec(&missing_params), Some(WARN), Some(ATTR));
StyledString::new(&fmt_vec(&missing_params), Some(WARN), Some(Attribute::Bold));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -703,8 +700,8 @@ passed keyword args: {kw_args_len}"
caused_by: String, caused_by: String,
arg_name: &str, arg_name: &str,
) -> Self { ) -> Self {
let name = readable_name(callee_name); let name = StyledStr::new(readable_name(callee_name), Some(ACCENT), Some(ATTR));
let found = StyledString::new(arg_name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(arg_name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -731,8 +728,8 @@ passed keyword args: {kw_args_len}"
caused_by: String, caused_by: String,
param_name: &str, param_name: &str,
) -> Self { ) -> Self {
let name = readable_name(callee_name); let name = StyledStr::new(readable_name(callee_name), Some(ACCENT), Some(ATTR));
let found = StyledString::new(param_name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(param_name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -766,7 +763,7 @@ passed keyword args: {kw_args_len}"
"traditional_chinese" => lhs_typ.push_str("左邊: "), "traditional_chinese" => lhs_typ.push_str("左邊: "),
"english" => lhs_typ.push_str("lhs: "), "english" => lhs_typ.push_str("lhs: "),
); );
lhs_typ.push_str_with_color_and_attribute(&format!("{}", lhs_t), WARN, Attribute::Bold); lhs_typ.push_str_with_color_and_attribute(format!("{}", lhs_t), WARN, ATTR);
let mut rhs_typ = StyledStrings::default(); let mut rhs_typ = StyledStrings::default();
switch_lang!( switch_lang!(
"japanese" => rhs_typ.push_str("右辺: "), "japanese" => rhs_typ.push_str("右辺: "),
@ -774,12 +771,12 @@ passed keyword args: {kw_args_len}"
"traditional_chinese" => rhs_typ.push_str("右邊: "), "traditional_chinese" => rhs_typ.push_str("右邊: "),
"english" => rhs_typ.push_str("rhs: "), "english" => rhs_typ.push_str("rhs: "),
); );
rhs_typ.push_str_with_color_and_attribute(&format!("{}", rhs_t), WARN, Attribute::Bold); rhs_typ.push_str_with_color_and_attribute(format!("{}", rhs_t), WARN, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
loc, loc,
vec![lhs_typ.into(), rhs_typ.into()], vec![lhs_typ.to_string(), rhs_typ.to_string()],
None, None,
)], )],
switch_lang!( switch_lang!(
@ -805,16 +802,34 @@ passed keyword args: {kw_args_len}"
loc: Location, loc: Location,
caused_by: String, caused_by: String,
) -> Self { ) -> Self {
let lhs_t = StyledString::new(&format!("{}", lhs_t), Some(WARN), Some(Attribute::Bold)); let mut lhs_typ = StyledStrings::default();
let rhs_t = StyledString::new(&format!("{}", rhs_t), Some(WARN), Some(Attribute::Bold)); switch_lang!(
"japanese" => lhs_typ.push_str("左辺: "),
"simplified_chinese" => lhs_typ.push_str("左边: "),
"traditional_chinese" => lhs_typ.push_str("左邊: "),
"english" => lhs_typ.push_str("lhs: "),
);
lhs_typ.push_str_with_color_and_attribute(format!("{}", lhs_t), WARN, ATTR);
let mut rhs_typ = StyledStrings::default();
switch_lang!(
"japanese" => rhs_typ.push_str("右辺: "),
"simplified_chinese" => rhs_typ.push_str("右边: "),
"traditional_chinese" => rhs_typ.push_str("右邊: "),
"english" => rhs_typ.push_str("rhs: "),
);
rhs_typ.push_str_with_color_and_attribute(format!("{}", rhs_t), WARN, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::ambiguous_new(
loc,
vec![lhs_typ.to_string(), rhs_typ.to_string()],
None,
)],
switch_lang!( switch_lang!(
"japanese" => format!("型の再単一化に失敗しました\n\n左辺: {lhs_t}\n右辺: {rhs_t}"), "japanese" => format!("型の再単一化に失敗しました"),
"simplified_chinese" => format!("重新统一类型失败\n\n左边: {lhs_t}\n右边: {rhs_t}"), "simplified_chinese" => format!("重新统一类型失败"),
"traditional_chinese" => format!("重新統一類型失敗\n\n左邊: {lhs_t}\n右邊: {rhs_t}"), "traditional_chinese" => format!("重新統一類型失敗"),
"english" => format!("re-unification failed\n\nlhs: {lhs_t}\nrhs: {rhs_t}"), "english" => format!("re-unification failed"),
), ),
errno, errno,
TypeError, TypeError,
@ -838,9 +853,9 @@ passed keyword args: {kw_args_len}"
"japanese" => sub_type.push_str("部分型: "), "japanese" => sub_type.push_str("部分型: "),
"simplified_chinese" => sub_type.push_str("超类型: "), "simplified_chinese" => sub_type.push_str("超类型: "),
"simplified_chinese" =>sub_type.push_str("超類型: "), "simplified_chinese" =>sub_type.push_str("超類型: "),
"english" => sub_type.push_str("super type: "), "english" => sub_type.push_str("subtype: "),
); );
sub_type.push_str_with_color(&format!("{}", sub_t), WARN); sub_type.push_str_with_color_and_attribute(format!("{}", sub_t), WARN, ATTR);
let mut sup_type = StyledStrings::default(); let mut sup_type = StyledStrings::default();
switch_lang!( switch_lang!(
@ -849,20 +864,20 @@ passed keyword args: {kw_args_len}"
"simplified_chinese" => sup_type.push_str("超類型: "), "simplified_chinese" => sup_type.push_str("超類型: "),
"english" =>sup_type.push_str("supertype: "), "english" =>sup_type.push_str("supertype: "),
); );
sup_type.push_str_with_color(&format!("{}", sup_t), WARN); sup_type.push_str_with_color_and_attribute(format!("{}", sup_t), WARN, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
loc, loc,
vec![sub_type.into(), sup_type.into()], vec![sub_type.to_string(), sup_type.to_string()],
None, None,
)], )],
switch_lang!( switch_lang!(
"japanese" => format!("この式の部分型制約を満たせません"), "japanese" => format!("この式の部分型制約を満たせません"),
"simplified_chinese" => format!("无法满足此表达式中的子类型约束"), "simplified_chinese" => format!("无法满足此表达式中的子类型约束"),
"traditional_chinese" => format!("無法滿足此表達式中的子類型約束"), "traditional_chinese" => format!("無法滿足此表達式中的子類型約束"),
"english" => format!("the subtype constraint in this expression cannot be satisfied:"), "english" => format!("the subtype constraint in this expression cannot be satisfied"),
), ),
errno, errno,
TypeError, TypeError,
@ -887,7 +902,7 @@ passed keyword args: {kw_args_len}"
"traditional_chinese" => lhs_uni.push_str("左邊: "), "traditional_chinese" => lhs_uni.push_str("左邊: "),
"english" => lhs_uni.push_str("lhs: "), "english" => lhs_uni.push_str("lhs: "),
); );
lhs_uni.push_str_with_color_and_attribute(&format!("{}", lhs), WARN, Attribute::Bold); lhs_uni.push_str_with_color_and_attribute(format!("{}", lhs), WARN, ATTR);
let mut rhs_uni = StyledStrings::default(); let mut rhs_uni = StyledStrings::default();
switch_lang!( switch_lang!(
"japanese" => rhs_uni.push_str("右辺: "), "japanese" => rhs_uni.push_str("右辺: "),
@ -895,12 +910,12 @@ passed keyword args: {kw_args_len}"
"traditional_chinese" => rhs_uni.push_str("右邊: "), "traditional_chinese" => rhs_uni.push_str("右邊: "),
"english" => rhs_uni.push_str("rhs: "), "english" => rhs_uni.push_str("rhs: "),
); );
rhs_uni.push_str_with_color_and_attribute(&format!("{}", rhs), WARN, Attribute::Bold); rhs_uni.push_str_with_color_and_attribute(format!("{}", rhs), WARN, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
Location::Unknown, Location::Unknown,
vec![lhs_uni.into(), rhs_uni.into()], vec![lhs_uni.to_string(), rhs_uni.to_string()],
None, None,
)], )],
switch_lang!( switch_lang!(
@ -979,7 +994,7 @@ passed keyword args: {kw_args_len}"
name: &str, name: &str,
hint: Option<String>, hint: Option<String>,
) -> Self { ) -> Self {
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -1019,28 +1034,39 @@ passed keyword args: {kw_args_len}"
hint: Option<String>, hint: Option<String>,
) -> Self { ) -> Self {
let mut expct = StyledStrings::default(); let mut expct = StyledStrings::default();
expct.push_str_with_color_and_attribute(&format!("{}", trait_type), WARN, Attribute::Bold);
switch_lang!( switch_lang!(
"japanese" => expct.push_str("で宣言された型: "), "japanese" => {
"simplified_chinese" => expct.push_str("中声明的类型: "), expct.push_str_with_color_and_attribute(format!("{}", trait_type), ACCENT, ATTR);
"traditional_chinese" => expct.push_str("中聲明的類型: "), expct.push_str("で宣言された型: ");
"english" => expct.push_str("declared in: "), },
"simplified_chinese" => {
expct.push_str_with_color_and_attribute(format!("{}", trait_type), ACCENT, ATTR);
expct.push_str("中声明的类型: ");
},
"traditional_chinese" => {
expct.push_str_with_color_and_attribute(format!("{}", trait_type), ACCENT, ATTR);
expct.push_str("中聲明的類型: ");
},
"english" => {
expct.push_str("declared in ");
expct.push_str_with_color(format!("{}: ", trait_type), ACCENT);
},
); );
expct.push_str_with_color(&format!("{}", expect), HINT); expct.push_str_with_color(format!("{}", expect), HINT);
let mut fnd = StyledStrings::default(); let mut fnd = StyledStrings::default();
fnd.push_str_with_color_and_attribute(member_name, WARN, Attribute::Bold);
switch_lang!( switch_lang!(
"japanese" => expct.push_str("与えられた型: "), "japanese" => fnd.push_str("与えられた型: "),
"simplified_chinese" => expct.push_str("但找到: "), "simplified_chinese" => fnd.push_str("但找到: "),
"traditional_chinese" => expct.push_str("但找到: "), "traditional_chinese" => fnd.push_str("但找到: "),
"english" => expct.push_str("but found: "), "english" => fnd.push_str("but found: "),
); );
fnd.push_str_with_color(&format!("{}", found), ERR); fnd.push_str_with_color(format!("{}", found), ERR);
let member_name = StyledStr::new(member_name, Some(ACCENT), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
loc, loc,
vec![expct.into(), fnd.into()], vec![expct.to_string(), fnd.to_string()],
hint, hint,
)], )],
switch_lang!( switch_lang!(
@ -1068,7 +1094,7 @@ passed keyword args: {kw_args_len}"
class_type: &Type, class_type: &Type,
hint: Option<String>, hint: Option<String>,
) -> Self { ) -> Self {
let member_name = StyledString::new(member_name, Some(WARN), Some(Attribute::Bold)); let member_name = StyledString::new(member_name, Some(WARN), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(Location::Unknown, vec![], hint)], vec![SubMessage::ambiguous_new(Location::Unknown, vec![], hint)],
@ -1097,7 +1123,7 @@ passed keyword args: {kw_args_len}"
class_type: &Type, class_type: &Type,
hint: Option<String>, hint: Option<String>,
) -> Self { ) -> Self {
let member_name = StyledString::new(member_name, Some(WARN), Some(Attribute::Bold)); let member_name = StyledString::new(member_name, Some(WARN), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(Location::Unknown, vec![], hint)], vec![SubMessage::ambiguous_new(Location::Unknown, vec![], hint)],
@ -1123,7 +1149,7 @@ passed keyword args: {kw_args_len}"
loc: Location, loc: Location,
caused_by: String, caused_by: String,
) -> Self { ) -> Self {
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -1151,25 +1177,58 @@ passed keyword args: {kw_args_len}"
) -> Self { ) -> Self {
let hint = Some( let hint = Some(
switch_lang!( switch_lang!(
"japanese" => "多相関数の場合は`f|T := Int|`, 型属性の場合は`T|T <: Trait|.X`などのようにして型を指定してください", "japanese" => {
"simplified_chinese" => "如果是多态函数,请使用`f|T := Int|`,如果是类型属性,请使用`T|T <: Trait|.X`等方式指定类型", let mut s = StyledStrings::default();
"traditional_chinese" => "如果是多型函數,請使用`f|T := Int|`,如果是類型屬性,請使用`T|T <: Trait|.X`等方式指定類型", s.push_str("多相関数の場合は");
"english" => "if it is a polymorphic function, use `f|T := Int|`, or if it is a type attribute, use `T|T <: Trait|.X` etc. to specify the type", s.push_str_with_color("f|T := Int", ACCENT);
).into(), s.push_str(", 型属性の場合は");
s.push_str_with_color("f|T := Trait|.X", ACCENT);
s.push_str(", などのようにして型を指定してください");
s
},
"simplified_chinese" => {
let mut s = StyledStrings::default();
s.push_str("如果是多态函数,请使用");
s.push_str_with_color("f|T := Int", ACCENT);
s.push_str(",如果是类型属性,请使用");
s.push_str_with_color("f|T := Trait|.X", ACCENT);
s.push_str("等方式指定类型");
s
},
"traditional_chinese" => {
let mut s = StyledStrings::default();
s.push_str("如果是多型函數,請使用");
s.push_str_with_color("f|T := Int", ACCENT);
s.push_str(",如果是類型屬性,請使用");
s.push_str_with_color("f|T := Trait|.X", ACCENT);
s.push_str("等方式指定類型");
s
},
"english" => {
let mut s = StyledStrings::default();
s.push_str("if it is a polymorphic function, use ");
s.push_str_with_color("f|T := Int", ACCENT);
s.push_str(", or if it is a type attribute, use ");
s.push_str_with_color("f|T := Trait|.X", ACCENT);
s.push_str(" etc. to specify the type");
s
},
)
.to_string(),
); );
let mut candi = StyledStrings::default(); let mut candidate = StyledStrings::default();
switch_lang!( switch_lang!(
"japanese" => candi.push_str("候補: "), "japanese" => candidate.push_str("候補: "),
"simplified_chinese" => candi.push_str("候选: "), "simplified_chinese" => candidate.push_str("候选: "),
"traditional_chinese" => candi.push_str("候選: "), "traditional_chinese" => candidate.push_str("候選: "),
"english" => candi.push_str("candidates: "), "english" => candidate.push_str("candidates: "),
); );
candi.push_str_with_color_and_attribute(&fmt_vec(candidates), WARN, Attribute::Bold); candidate.push_str_with_color_and_attribute(&fmt_vec(candidates), WARN, ATTR);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
expr.loc(), expr.loc(),
vec![candi.into()], vec![candidate.into()],
hint, hint,
)], )],
switch_lang!( switch_lang!(
@ -1275,12 +1334,35 @@ impl EffectError {
) -> Self { ) -> Self {
let hint = Some( let hint = Some(
switch_lang!( switch_lang!(
"japanese" => "変数の末尾に`!`をつけてください", "japanese" => {
"simplified_chinese" => "请在变量名后加上`!`", let mut s = StyledStrings::default();
"traditional_chinese" => "請在變量名後加上`!`", s.push_str("変数の末尾に");
"english" => "add `!` to the end of the variable name", s.push_str_with_color_and_attribute("!", ACCENT, ATTR);
s.push_str("をつけてください");
s
},
"simplified_chinese" => {
let mut s = StyledStrings::default();
s.push_str("请在变量名后加上");
s.push_str_with_color_and_attribute("!", ACCENT, ATTR);
s
},
"traditional_chinese" => {
let mut s = StyledStrings::default();
s.push_str("請在變量名後加上");
s.push_str_with_color_and_attribute("!", ACCENT, ATTR);
s
},
"english" => {
let mut s = StyledStrings::default();
s.push_str("add ");
s.push_str_with_color_and_attribute("!", ACCENT, ATTR);
s.push_str(" to the end of the variable name");
s
},
) )
.into(), .to_string(),
); );
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
@ -1313,7 +1395,7 @@ impl OwnershipError {
moved_loc: Location, moved_loc: Location,
caused_by: S, caused_by: S,
) -> Self { ) -> Self {
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(name_loc)], vec![SubMessage::only_loc(name_loc)],
@ -1435,9 +1517,9 @@ impl LowerError {
spec_t: &Type, spec_t: &Type,
found_t: &Type, found_t: &Type,
) -> Self { ) -> Self {
let name = readable_name(name); let name = StyledString::new(readable_name(name), Some(ACCENT), None);
let expect = StyledString::new(&format!("{}", spec_t), Some(HINT), Some(Attribute::Bold)); let expect = StyledString::new(format!("{}", spec_t), Some(HINT), Some(ATTR));
let found = StyledString::new(&format!("{}", found_t), Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(format!("{}", found_t), Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -1466,7 +1548,7 @@ impl LowerError {
) -> Self { ) -> Self {
let name = readable_name(name); let name = readable_name(name);
let hint = similar_name.map(|n| { let hint = similar_name.map(|n| {
let n = StyledStr::new(n, Some(HINT), Some(Attribute::Bold)); let n = StyledStr::new(n, Some(HINT), Some(ATTR));
switch_lang!( switch_lang!(
"japanese" => format!("似た名前の変数があります: {n}"), "japanese" => format!("似た名前の変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称变量: {n}"), "simplified_chinese" => format!("存在相同名称变量: {n}"),
@ -1474,7 +1556,7 @@ impl LowerError {
"english" => format!("exists a similar name variable: {n}"), "english" => format!("exists a similar name variable: {n}"),
) )
}); });
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -1500,14 +1582,13 @@ impl LowerError {
caused_by: String, caused_by: String,
typ: &Type, typ: &Type,
) -> Self { ) -> Self {
let typ = StyledString::new(&typ.to_string(), Some(ERR), Some(Attribute::Bold)); let typ = StyledString::new(&typ.to_string(), Some(ERR), Some(ATTR));
let hint = Some(switch_lang!( let hint = Some(switch_lang!(
"japanese" => format!("恐らくこれはErgコンパイラのバグです、{URL}へ報告してください"), "japanese" => format!("恐らくこれはErgコンパイラのバグです、{URL}へ報告してください"),
"simplified_chinese" => format!("这可能是Erg编译器的错误请报告给{URL}"), "simplified_chinese" => format!("这可能是Erg编译器的错误请报告给{URL}"),
"traditional_chinese" => format!("這可能是Erg編譯器的錯誤請報告給{URL}"), "traditional_chinese" => format!("這可能是Erg編譯器的錯誤請報告給{URL}"),
"english" => format!("This may be a bug of Erg compiler, please report to {URL}"), "english" => format!("This may be a bug of Erg compiler, please report to {URL}"),
).into(), ));
);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -1543,7 +1624,7 @@ impl LowerError {
"english" => format!("has a similar name attribute: {n}"), "english" => format!("has a similar name attribute: {n}"),
) )
}); });
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -1574,7 +1655,7 @@ impl LowerError {
similar_name: Option<&str>, similar_name: Option<&str>,
) -> Self { ) -> Self {
let hint = similar_name.map(|n| { let hint = similar_name.map(|n| {
let n = StyledStr::new(n, Some(HINT), Some(Attribute::Bold)); let n = StyledStr::new(n, Some(HINT), Some(ATTR));
switch_lang!( switch_lang!(
"japanese" => format!("似た名前の属性があります: {n}"), "japanese" => format!("似た名前の属性があります: {n}"),
"simplified_chinese" => format!("具有相同名称的属性: {n}"), "simplified_chinese" => format!("具有相同名称的属性: {n}"),
@ -1582,7 +1663,7 @@ impl LowerError {
"english" => format!("has a similar name attribute: {n}"), "english" => format!("has a similar name attribute: {n}"),
) )
}); });
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@ -1608,7 +1689,7 @@ impl LowerError {
caused_by: String, caused_by: String,
name: &str, name: &str,
) -> Self { ) -> Self {
let name = StyledString::new(readable_name(name), Some(WARN), Some(Attribute::Bold)); let name = StyledStr::new(readable_name(name), Some(WARN), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -1634,7 +1715,7 @@ impl LowerError {
name: &str, name: &str,
caused_by: String, caused_by: String,
) -> Self { ) -> Self {
let name = StyledString::new(readable_name(name), Some(WARN), Some(Attribute::Bold)); let name = StyledString::new(readable_name(name), Some(WARN), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -1654,11 +1735,7 @@ impl LowerError {
} }
pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: String) -> Self { pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: String) -> Self {
let name = StyledString::new( let name = StyledString::new(readable_name(ident.inspect()), Some(WARN), Some(ATTR));
readable_name(ident.inspect()),
Some(WARN),
Some(Attribute::Bold),
);
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(ident.loc())], vec![SubMessage::only_loc(ident.loc())],
@ -1701,7 +1778,7 @@ impl LowerError {
"english" => "public", "english" => "public",
) )
}; };
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let found = StyledString::new(name, Some(ERR), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::only_loc(loc)], vec![SubMessage::only_loc(loc)],
@ -1728,12 +1805,8 @@ impl LowerError {
superclass: &Type, superclass: &Type,
caused_by: S, caused_by: S,
) -> Self { ) -> Self {
let name = StyledString::new(name, Some(ERR), Some(Attribute::Bold)); let name = StyledString::new(name, Some(ERR), Some(ATTR));
let superclass = StyledString::new( let superclass = StyledString::new(format!("{}", superclass), Some(WARN), Some(ATTR));
&format!("{}", superclass),
Some(WARN),
Some(Attribute::Bold),
);
let hint = Some( let hint = Some(
switch_lang!( switch_lang!(
"japanese" => "`Override`デコレータを使用してください", "japanese" => "`Override`デコレータを使用してください",
@ -1753,7 +1826,7 @@ impl LowerError {
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(
name_loc, name_loc,
vec![sub_msg.into()], vec![sub_msg.to_string()],
hint, hint,
)], )],
switch_lang!( switch_lang!(
@ -1853,24 +1926,23 @@ impl LowerError {
let mut erg_str = StyledStrings::default(); let mut erg_str = StyledStrings::default();
let mut py_str = StyledStrings::default(); let mut py_str = StyledStrings::default();
let hint = switch_lang!( let hint = switch_lang!(
"japanese" => { "japanese" => {
match (similar_erg_mod, similar_py_mod) { match (similar_erg_mod, similar_py_mod) {
(Some(erg), Some(py)) => { (Some(erg), Some(py)) => {
erg_str.push_str("似た名前のergモジュールが存在します: "); erg_str.push_str("似た名前のergモジュールが存在します: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
py_str.push_str("似た名前のpythonモジュールが存在します: "); py_str.push_str("似た名前のpythonモジュールが存在します: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("pythonのモジュールをインポートするためには`pyimport`を使用してください".to_string()) Some("pythonのモジュールをインポートするためには`pyimport`を使用してください".to_string())
} }
(Some(erg), None) => { (Some(erg), None) => {
erg_str.push_str("似た名前のergモジュールが存在します"); erg_str.push_str("似た名前のergモジュールが存在します");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
None None
} }
(None, Some(py)) => { (None, Some(py)) => {
py_str.push_str("似た名前のpythonモジュールが存在します"); py_str.push_str("似た名前のpythonモジュールが存在します");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("pythonのモジュールをインポートするためには`pyimport`を使用してください".to_string()) Some("pythonのモジュールをインポートするためには`pyimport`を使用してください".to_string())
} }
(None, None) => None, (None, None) => None,
@ -1880,19 +1952,19 @@ impl LowerError {
match (similar_erg_mod, similar_py_mod) { match (similar_erg_mod, similar_py_mod) {
(Some(erg), Some(py)) => { (Some(erg), Some(py)) => {
erg_str.push_str("存在相似名称的erg模块: "); erg_str.push_str("存在相似名称的erg模块: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
py_str.push_str("存在相似名称的python模块: "); py_str.push_str("存在相似名称的python模块: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("要导入python模块,请使用`pyimport`".to_string()) Some("要导入python模块,请使用`pyimport`".to_string())
} }
(Some(erg), None) => { (Some(erg), None) => {
erg_str.push_str("存在相似名称的erg模块: "); erg_str.push_str("存在相似名称的erg模块: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
None None
} }
(None, Some(py)) => { (None, Some(py)) => {
py_str.push_str("存在相似名称的python模块: "); py_str.push_str("存在相似名称的python模块: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("要导入python模块,请使用`pyimport`".to_string()) Some("要导入python模块,请使用`pyimport`".to_string())
} }
(None, None) => None, (None, None) => None,
@ -1902,19 +1974,19 @@ impl LowerError {
match (similar_erg_mod, similar_py_mod) { match (similar_erg_mod, similar_py_mod) {
(Some(erg), Some(py)) => { (Some(erg), Some(py)) => {
erg_str.push_str("存在類似名稱的erg模塊: "); erg_str.push_str("存在類似名稱的erg模塊: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
py_str.push_str("存在類似名稱的python模塊: "); py_str.push_str("存在類似名稱的python模塊: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("要導入python模塊, 請使用`pyimport`".to_string()) Some("要導入python模塊, 請使用`pyimport`".to_string())
} }
(Some(erg), None) => { (Some(erg), None) => {
erg_str.push_str("存在類似名稱的erg模塊: "); erg_str.push_str("存在類似名稱的erg模塊: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
None None
} }
(None, Some(py)) => { (None, Some(py)) => {
py_str.push_str("存在類似名稱的python模塊: "); py_str.push_str("存在類似名稱的python模塊: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("要導入python模塊, 請使用`pyimport`".to_string()) Some("要導入python模塊, 請使用`pyimport`".to_string())
} }
(None, None) => None, (None, None) => None,
@ -1924,32 +1996,35 @@ impl LowerError {
match (similar_erg_mod, similar_py_mod) { match (similar_erg_mod, similar_py_mod) {
(Some(erg), Some(py)) => { (Some(erg), Some(py)) => {
erg_str.push_str("similar name erg module exists: "); erg_str.push_str("similar name erg module exists: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
py_str.push_str("similar name python module exists: "); py_str.push_str("similar name python module exists: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("to import python modules, use `pyimport`".to_string()) Some("to import python modules, use `pyimport`".to_string())
} }
(Some(erg), None) => { (Some(erg), None) => {
erg_str.push_str("similar name erg module exists: "); erg_str.push_str("similar name erg module exists: ");
erg_str.push_str_with_color_and_attribute(&erg, WARN, Attribute::Bold); erg_str.push_str_with_color_and_attribute(erg, WARN, ATTR);
None None
} }
(None, Some(py)) => { (None, Some(py)) => {
py_str.push_str("similar name python module: "); py_str.push_str("similar name python module: ");
py_str.push_str_with_color_and_attribute(&py, WARN, Attribute::Bold); py_str.push_str_with_color_and_attribute(py, WARN, ATTR);
Some("to import python modules, use `pyimport`".to_string()) Some("to import python modules, use `pyimport`".to_string())
} }
(None, None) => None, (None, None) => None,
} }
}, },
); );
// .to_string().is_empty() is not necessarily empty because there are Color or Attribute that are not displayed
let msg = match (erg_str.is_empty(), py_str.is_empty()) {
(false, false) => vec![erg_str.to_string(), py_str.to_string()],
(false, true) => vec![erg_str.to_string()],
(true, false) => vec![py_str.to_string()],
(true, true) => vec![],
};
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new( vec![SubMessage::ambiguous_new(loc, msg, hint)],
loc,
vec![erg_str.into(), py_str.into()],
hint,
)],
desc, desc,
errno, errno,
ImportError, ImportError,
@ -2013,8 +2088,8 @@ impl LowerError {
cast_to: &Type, cast_to: &Type,
hint: Option<String>, hint: Option<String>,
) -> Self { ) -> Self {
let name = StyledString::new(name, Some(WARN), Some(Attribute::Bold)); let name = StyledString::new(name, Some(WARN), Some(ATTR));
let found = StyledString::new(&format!("{}", cast_to), Some(WARN), Some(Attribute::Bold)); let found = StyledString::new(format!("{}", cast_to), Some(WARN), Some(ATTR));
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)], vec![SubMessage::ambiguous_new(loc, vec![], hint)],