fix: range type definition bug

This commit is contained in:
Shunsuke Shibayama 2024-02-26 01:35:41 +09:00
parent ac80cbba87
commit f612340e80
8 changed files with 92 additions and 10 deletions

View file

@ -1984,7 +1984,7 @@ impl Context {
}
// sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
fn sup(&self, t: &Type) -> Option<TyParam> {
pub(crate) fn sup(&self, t: &Type) -> Option<TyParam> {
match t {
Int | Nat | Float => Some(TyParam::value(Inf)),
Refinement(refine) => {
@ -2011,7 +2011,7 @@ impl Context {
}
}
fn inf(&self, t: &Type) -> Option<TyParam> {
pub(crate) fn inf(&self, t: &Type) -> Option<TyParam> {
match t {
Int | Float => Some(TyParam::value(-Inf)),
Nat => Some(TyParam::value(0usize)),

View file

@ -667,7 +667,7 @@ impl Context {
&self,
subr: ConstSubr,
args: ValueArgs,
loc: Location,
loc: impl Locational,
) -> EvalResult<TyParam> {
match subr {
ConstSubr::User(user) => {
@ -695,7 +695,7 @@ impl Context {
}
ConstSubr::Builtin(builtin) => builtin.call(args, self).map_err(|mut e| {
if e.0.loc.is_unknown() {
e.0.loc = loc;
e.0.loc = loc.loc();
}
EvalErrors::from(EvalError::new(
*e.0,
@ -705,7 +705,7 @@ impl Context {
}),
ConstSubr::Gen(gen) => gen.call(args, self).map_err(|mut e| {
if e.0.loc.is_unknown() {
e.0.loc = loc;
e.0.loc = loc.loc();
}
EvalErrors::from(EvalError::new(
*e.0,
@ -1749,6 +1749,15 @@ impl Context {
}
};
}
if let Some(ValueObj::Subr(subr)) = self.rec_get_const_obj(&name) {
if let Ok(args) = self.convert_args(None, subr, params.clone(), t_loc) {
let ret = self.call(subr.clone(), args, t_loc);
if let Some(t) = ret.ok().and_then(|tp| self.convert_tp_into_type(tp).ok())
{
return Ok(t);
}
}
}
Ok(poly(name, params))
}
Type::And(l, r) => {

View file

@ -464,6 +464,10 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
Ok(TyParam::FreeVar(fv))
}
TyParam::Type(t) => Ok(TyParam::t(self.deref_tyvar(*t)?)),
TyParam::Value(ValueObj::Type(mut t)) => {
t.try_map_t(|t| self.deref_tyvar(t.clone()))?;
Ok(TyParam::Value(ValueObj::Type(t)))
}
TyParam::Erased(t) => Ok(TyParam::erased(self.deref_tyvar(*t)?)),
TyParam::App { name, mut args } => {
for param in args.iter_mut() {

View file

@ -9,6 +9,7 @@ use erg_common::traits::Stream;
use erg_common::{dict, set};
use crate::context::eval::UndoableLinkedList;
use crate::context::initialize::closed_range;
use crate::context::Context;
use crate::feature_error;
use crate::ty::constructors::{and, mono, tuple_t, v_enum};
@ -1522,3 +1523,45 @@ pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
}
Ok(TyParam::Value(ValueObj::Array(zipped.into())))
}
/// ```erg
/// derefine({X: T | ...}) == T
/// ```
pub(crate) fn derefine_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
let val = args
.remove_left_or_key("T")
.ok_or_else(|| not_passed("T"))?;
let t = match ctx.convert_value_into_type(val) {
Ok(t) => t.derefine(),
Err(val) => {
return Err(type_mismatch("Type", val, "T"));
}
};
Ok(TyParam::t(t))
}
/// ```erg
/// fill_ord({1, 4}) == {1, 2, 3, 4}
/// fill_ord({"a", "c"}) == {"a", "b", "c"}
/// ```
pub(crate) fn fill_ord_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
let val = args
.remove_left_or_key("T")
.ok_or_else(|| not_passed("T"))?;
let t = match ctx.convert_value_into_type(val) {
Ok(t) => {
let coerced = ctx.coerce(t.clone(), &()).unwrap_or(t);
let inf = ctx.inf(&coerced);
let sup = ctx.sup(&coerced);
let der = coerced.derefine();
match (inf, sup) {
(Some(inf), Some(sup)) => closed_range(der, inf, sup),
_ => coerced,
}
}
Err(val) => {
return Err(type_mismatch("Type", val, "T"));
}
};
Ok(TyParam::t(t))
}

View file

@ -856,6 +856,22 @@ impl Context {
let t_pred = nd_func(vec![kw(KW_N, Nat)], None, Nat);
let pred = ConstSubr::Builtin(BuiltinConstSubr::new(FUNC_PRED, pred_func, t_pred, None));
self.register_builtin_const(FUNC_PRED, vis.clone(), None, ValueObj::Subr(pred));
let t_derefine = nd_func(vec![kw(KW_T, Type)], None, Type);
let derefine = ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_DEREFINE,
derefine_func,
t_derefine,
None,
));
self.register_builtin_const(FUNC_DEREFINE, vis.clone(), None, ValueObj::Subr(derefine));
let t_fill_ord = nd_func(vec![kw(KW_T, Type)], None, Type);
let fill_ord = ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_FILL_ORD,
fill_ord_func,
t_fill_ord,
None,
));
self.register_builtin_const(FUNC_FILL_ORD, vis.clone(), None, ValueObj::Subr(fill_ord));
}
pub(super) fn init_builtin_py_specific_funcs(&mut self) {
@ -983,8 +999,8 @@ impl Context {
Some("eq"),
);
self.register_builtin_py_impl(OP_NE, op_t, Const, Visibility::BUILTIN_PRIVATE, Some("ne"));
let O = mono_q(TY_O, subtypeof(mono(PARTIAL_ORD)));
let op_t = bin_op(O.clone(), O.clone(), Bool).quantify();
let PO = mono_q(TY_O, subtypeof(mono(PARTIAL_ORD)));
let op_t = bin_op(PO.clone(), PO.clone(), Bool).quantify();
self.register_builtin_py_impl(
OP_LT,
op_t.clone(),
@ -1055,7 +1071,13 @@ impl Context {
Visibility::BUILTIN_PRIVATE,
Some("rshift"),
);
let op_t = bin_op(O.clone(), O.clone(), range(O)).quantify();
let O = mono_q(TY_O, subtypeof(mono(ORD)));
let op_t = bin_op(
O.clone(),
O.clone(),
range(poly(FUNC_FILL_ORD, vec![ty_tp(O)])),
)
.quantify();
self.register_builtin_erg_decl(OP_RNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_LORNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);
self.register_builtin_erg_decl(OP_RORNG, op_t.clone(), Visibility::BUILTIN_PRIVATE);

View file

@ -152,6 +152,8 @@ const MUT_RATIO: &str = "Ratio!";
const FUNC_ABS: &str = "abs";
const FUNC_SUCC: &str = "succ";
const FUNC_PRED: &str = "pred";
const FUNC_DEREFINE: &str = "derefine";
const FUNC_FILL_ORD: &str = "fill_ord";
const FUNC_BIT_LENGTH: &str = "bit_length";
const FUNC_BIT_COUNT: &str = "bit_count";
const FUNC_BYTEORDER: &str = "byteorder";
@ -535,6 +537,7 @@ const KW_C: &str = "c";
const KW_N: &str = "n";
const KW_S: &str = "s";
const KW_X: &str = "X";
const KW_T: &str = "T";
const KW_SELF: &str = "self";
const KW_LENGTH: &str = "length";
const KW_PROC: &str = "proc!";

View file

@ -2789,10 +2789,10 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
tasc.expr.loc(),
self.module.context.caused_by(),
switch_lang!(
"japanese" => "無効な型宣言です(左辺には記名型のみ使用出来ます)".to_string(),
"japanese" => "無効な型宣言です(左辺には変数のみ使用出来ます)".to_string(),
"simplified_chinese" => "无效的类型声明".to_string(),
"traditional_chinese" => "無效的型宣告".to_string(),
"english" => "Invalid type declaration (currently only nominal types are allowed at LHS)".to_string(),
"english" => "Invalid type declaration (currently only variables are allowed at LHS)".to_string(),
),
None,
)));

View file

@ -1258,6 +1258,7 @@ impl ValueObj {
}
(Self::Inf, n) | (n, Self::NegInf) if n.is_num() => Some(Ordering::Greater),
(n, Self::Inf) | (Self::NegInf, n) if n.is_num() => Some(Ordering::Less),
(Self::Str(l), Self::Str(r)) => Some(l.cmp(r)),
/* (Self::PlusEpsilon(l), r) => l.try_cmp(r)
.map(|o| if matches!(o, Ordering::Equal) { Ordering::Less } else { o }),
(l, Self::PlusEpsilon(r)) => l.try_cmp(r)