diff --git a/crates/erg_compiler/context/hint.rs b/crates/erg_compiler/context/hint.rs index 6524da7ae..138d66765 100644 --- a/crates/erg_compiler/context/hint.rs +++ b/crates/erg_compiler/context/hint.rs @@ -134,28 +134,36 @@ impl Context { switch_lang!( "japanese" => { hint.push_str("Floatは等価関係が定義されていません。"); - hint.push_str_with_color_and_attr("l == R", ERR, ATTR); + hint.push_str_with_color_and_attr("l == r", ERR, ATTR); hint.push_str("ではなく、"); hint.push_str_with_color_and_attr("l - r <= Float.EPSILON", HINT, ATTR); + hint.push_str("あるいは"); + hint.push_str_with_color_and_attr("l.nearly_eq(r)", HINT, ATTR); hint.push_str("を使用してください"); }, "simplified_chinese" => { hint.push_str("Float没有定义等价关系。你应该使用"); - hint.push_str_with_color_and_attr("l == R", ERR, ATTR); - hint.push_str("而不是"); hint.push_str_with_color_and_attr("l - r <= Float.EPSILON", HINT, ATTR); + hint.push_str("或者"); + hint.push_str_with_color_and_attr("l.nearly_eq(r)", HINT, ATTR); + hint.push_str("而不是"); + hint.push_str_with_color_and_attr("l == r", ERR, ATTR); }, "traditional_chinese" => { hint.push_str("Float沒有定義等價關係。你應該使用"); - hint.push_str_with_color_and_attr("l == R", ERR, ATTR); - hint.push_str(" instead of "); hint.push_str_with_color_and_attr("l - r <= Float.EPSILON", HINT, ATTR); + hint.push_str("或者"); + hint.push_str_with_color_and_attr("l.nearly_eq(r)", HINT, ATTR); + hint.push_str("而不是"); + hint.push_str_with_color_and_attr("l == r", ERR, ATTR); }, "english" => { - hint.push_str("Float has no equivalence relation defined. you should use "); - hint.push_str_with_color_and_attr("l == R", ERR, ATTR); - hint.push_str(" instead of "); + hint.push_str("Float has no equivalence relation defined. You should use "); hint.push_str_with_color_and_attr("l - r <= Float.EPSILON", HINT, ATTR); + hint.push_str(" or "); + hint.push_str_with_color_and_attr("l.nearly_eq(r)", HINT, ATTR); + hint.push_str(" instead of "); + hint.push_str_with_color_and_attr("l == r", ERR, ATTR); }, ); Some(hint.to_string()) diff --git a/crates/erg_compiler/context/initialize/classes.rs b/crates/erg_compiler/context/initialize/classes.rs index 0e2db2058..915d053d6 100644 --- a/crates/erg_compiler/context/initialize/classes.rs +++ b/crates/erg_compiler/context/initialize/classes.rs @@ -148,6 +148,19 @@ impl Context { float.register_py_builtin(OP_GE, fn1_met(Float, Float, Bool), Some(OP_GE), 0); float.register_py_builtin(OP_LT, fn1_met(Float, Float, Bool), Some(OP_LT), 0); float.register_py_builtin(OP_LE, fn1_met(Float, Float, Bool), Some(OP_LE), 0); + let t_nearly_eq = fn_met( + Float, + vec![kw(KW_OTHER, Float)], + None, + vec![kw(KW_EPSILON, Float)], + Bool, + ); + float.register_builtin_erg_impl( + FUNC_NEARLY_EQ, + t_nearly_eq, + Immutable, + Visibility::BUILTIN_PUBLIC, + ); let t_call = func1(Obj, Float); float.register_builtin_erg_impl( FUNDAMENTAL_CALL, diff --git a/crates/erg_compiler/context/initialize/mod.rs b/crates/erg_compiler/context/initialize/mod.rs index 4320c4c03..2e1b21f97 100644 --- a/crates/erg_compiler/context/initialize/mod.rs +++ b/crates/erg_compiler/context/initialize/mod.rs @@ -410,6 +410,7 @@ const FUNC_HASATTR: &str = "hasattr"; const FUNC_GETATTR: &str = "getattr"; const FUNC_SETATTR: &str = "setattr"; const FUNC_DELATTR: &str = "delattr"; +const FUNC_NEARLY_EQ: &str = "nearly_eq"; const OP_EQ: &str = "__eq__"; const OP_HASH: &str = "__hash__"; @@ -575,6 +576,7 @@ const KW_WHENCE: &str = "whence"; const KW_CHARS: &str = "chars"; const KW_OTHER: &str = "other"; const KW_CONFLICT_RESOLVER: &str = "conflict_resolver"; +const KW_EPSILON: &str = "epsilon"; pub fn builtins_path() -> PathBuf { erg_pystd_path().join("builtins.d.er") diff --git a/crates/erg_compiler/lib/std/_erg_float.py b/crates/erg_compiler/lib/std/_erg_float.py index a65ceb3c4..48b2fdb61 100644 --- a/crates/erg_compiler/lib/std/_erg_float.py +++ b/crates/erg_compiler/lib/std/_erg_float.py @@ -14,6 +14,9 @@ def try_new(i): # -> Result[Nat] def mutate(self): return FloatMut(self) + def __abs__(self): + return Float(float.__abs__(self)) + def __add__(self, other): return then__(float.__add__(self, other), Float) @@ -56,6 +59,8 @@ def __pos__(self): def __neg__(self): return then__(float.__neg__(self), Float) + def nearly_eq(self, other, epsilon=EPSILON): + return abs(self - other) < epsilon class FloatMut: # inherits Float value: Float