mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat: add const filter/max/min/not/str/zip
This commit is contained in:
parent
d1fa616aea
commit
d748333a0f
3 changed files with 242 additions and 8 deletions
|
@ -867,6 +867,49 @@ pub(crate) fn any_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
Ok(ValueObj::Bool(any).into())
|
||||
}
|
||||
|
||||
pub(crate) fn filter_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let iterable = args
|
||||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let func = args
|
||||
.remove_left_or_key("func")
|
||||
.ok_or_else(|| not_passed("func"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Iterable(T)", iterable, "iterable"));
|
||||
}
|
||||
};
|
||||
let subr = match func {
|
||||
ValueObj::Subr(f) => f,
|
||||
_ => {
|
||||
return Err(type_mismatch("Subr", func, "func"));
|
||||
}
|
||||
};
|
||||
let mut filtered = vec![];
|
||||
for v in arr.into_iter() {
|
||||
let args = ValueArgs::pos_only(vec![v.clone()]);
|
||||
match ctx.call(subr.clone(), args, Location::Unknown) {
|
||||
Ok(res) => match ctx.convert_tp_into_value(res) {
|
||||
Ok(res) => {
|
||||
if res.is_true() {
|
||||
filtered.push(v);
|
||||
}
|
||||
}
|
||||
Err(tp) => {
|
||||
return Err(type_mismatch("Bool", tp, "func"));
|
||||
}
|
||||
},
|
||||
Err(mut err) => {
|
||||
return Err(EvalValueError::from(*err.remove(0).core));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(TyParam::Value(ValueObj::Array(filtered.into())))
|
||||
}
|
||||
|
||||
pub(crate) fn len_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let container = args
|
||||
.remove_left_or_key("iterable")
|
||||
|
@ -921,6 +964,93 @@ pub(crate) fn map_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Ty
|
|||
Ok(TyParam::Array(mapped))
|
||||
}
|
||||
|
||||
pub(crate) fn max_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let iterable = args
|
||||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Iterable(Ord)", iterable, "iterable"));
|
||||
}
|
||||
};
|
||||
let mut max = ValueObj::NegInf;
|
||||
if arr.is_empty() {
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
"max() arg is an empty sequence",
|
||||
line!() as usize,
|
||||
ErrorKind::ValueError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into());
|
||||
}
|
||||
for v in arr.into_iter() {
|
||||
if v.is_num() {
|
||||
if max.clone().try_lt(v.clone()).is_some_and(|b| b.is_true()) {
|
||||
max = v;
|
||||
}
|
||||
} else {
|
||||
return Err(type_mismatch("Ord", v, "iterable.next()"));
|
||||
}
|
||||
}
|
||||
Ok(max.into())
|
||||
}
|
||||
|
||||
pub(crate) fn min_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let iterable = args
|
||||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Iterable(Ord)", iterable, "iterable"));
|
||||
}
|
||||
};
|
||||
let mut min = ValueObj::Inf;
|
||||
if arr.is_empty() {
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
"min() arg is an empty sequence",
|
||||
line!() as usize,
|
||||
ErrorKind::ValueError,
|
||||
Location::Unknown,
|
||||
)
|
||||
.into());
|
||||
}
|
||||
for v in arr.into_iter() {
|
||||
if v.is_num() {
|
||||
if min.clone().try_gt(v.clone()).is_some_and(|b| b.is_true()) {
|
||||
min = v;
|
||||
}
|
||||
} else {
|
||||
return Err(type_mismatch("Ord", v, "iterable.next()"));
|
||||
}
|
||||
}
|
||||
Ok(min.into())
|
||||
}
|
||||
|
||||
pub(crate) fn not_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("val")
|
||||
.ok_or_else(|| not_passed("val"))?;
|
||||
match val {
|
||||
ValueObj::Bool(b) => Ok(ValueObj::Bool(!b).into()),
|
||||
_ => Err(type_mismatch("Bool", val, "val")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn str_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("val")
|
||||
.ok_or_else(|| not_passed("val"))?;
|
||||
Ok(ValueObj::Str(val.to_string().into()).into())
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let path = args
|
||||
.remove_left_or_key("Path")
|
||||
|
@ -1003,3 +1133,34 @@ pub(crate) fn pred_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
|
|||
};
|
||||
Ok(val.into())
|
||||
}
|
||||
|
||||
// TODO: varargs
|
||||
pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let iterable1 = args
|
||||
.remove_left_or_key("iterable1")
|
||||
.ok_or_else(|| not_passed("iterable1"))?;
|
||||
let iterable2 = args
|
||||
.remove_left_or_key("iterable2")
|
||||
.ok_or_else(|| not_passed("iterable2"))?;
|
||||
let iterable1 = match iterable1 {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Iterable(T)", iterable1, "iterable1"));
|
||||
}
|
||||
};
|
||||
let iterable2 = match iterable2 {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Iterable(T)", iterable2, "iterable2"));
|
||||
}
|
||||
};
|
||||
let mut zipped = vec![];
|
||||
for (v1, v2) in iterable1.into_iter().zip(iterable2.into_iter()) {
|
||||
zipped.push(ValueObj::Tuple(vec![v1, v2].into()));
|
||||
}
|
||||
Ok(TyParam::Value(ValueObj::Array(zipped.into())))
|
||||
}
|
||||
|
|
|
@ -122,6 +122,12 @@ impl Context {
|
|||
poly(FILTER, vec![ty_tp(T.clone())]),
|
||||
)
|
||||
.quantify();
|
||||
let filter = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_FILTER,
|
||||
filter_func,
|
||||
t_filter.clone(),
|
||||
None,
|
||||
)));
|
||||
let t_format = no_var_func(vec![kw(KW_VALUE, Obj)], vec![kw(KW_SPEC, Str)], Str);
|
||||
let t_frozenset = nd_func(
|
||||
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
|
||||
|
@ -228,6 +234,12 @@ impl Context {
|
|||
O.clone(),
|
||||
)
|
||||
.quantify();
|
||||
let max = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_MAX,
|
||||
max_func,
|
||||
t_max.clone(),
|
||||
None,
|
||||
)));
|
||||
let t_memoryview = nd_func(
|
||||
vec![kw(
|
||||
KW_OBJ,
|
||||
|
@ -242,10 +254,22 @@ impl Context {
|
|||
O,
|
||||
)
|
||||
.quantify();
|
||||
let min = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_MIN,
|
||||
min_func,
|
||||
t_min.clone(),
|
||||
None,
|
||||
)));
|
||||
let t_nat = nd_func(vec![kw(KW_OBJ, Obj)], None, Nat);
|
||||
// e.g. not(b: Bool!): Bool!
|
||||
let B = mono_q(TY_B, subtypeof(Bool));
|
||||
let t_not = nd_func(vec![kw(KW_B, B.clone())], None, B).quantify();
|
||||
let not = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_NOT,
|
||||
not_func,
|
||||
t_not.clone(),
|
||||
None,
|
||||
)));
|
||||
let t_oct = nd_func(vec![kw(KW_X, Int)], None, Str);
|
||||
let t_ord = nd_func(vec![kw(KW_C, Str)], None, Nat);
|
||||
let t_panic = nd_func(vec![kw(KW_MSG, Str)], None, Never);
|
||||
|
@ -298,6 +322,12 @@ impl Context {
|
|||
.quantify();
|
||||
let t_staticmethod = nd_func(vec![kw(KW_FUNC, F.clone())], None, F.clone()).quantify();
|
||||
let t_str = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
|
||||
let str_ = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_STR,
|
||||
str_func,
|
||||
t_str.clone(),
|
||||
None,
|
||||
)));
|
||||
let A = mono_q(TY_A, Constraint::Uninited);
|
||||
let A = mono_q(TY_A, subtypeof(poly(ADD, vec![ty_tp(A)])));
|
||||
let t_sum = no_var_func(
|
||||
|
@ -316,6 +346,12 @@ impl Context {
|
|||
poly(ZIP, vec![ty_tp(T.clone()), ty_tp(U.clone())]),
|
||||
)
|
||||
.quantify();
|
||||
let zip = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_ZIP,
|
||||
zip_func,
|
||||
t_zip.clone(),
|
||||
None,
|
||||
)));
|
||||
self.register_py_builtin_const(
|
||||
FUNC_ABS,
|
||||
vis.clone(),
|
||||
|
@ -399,12 +435,13 @@ impl Context {
|
|||
vis.clone(),
|
||||
Some(FUNC_FORMAT),
|
||||
);
|
||||
self.register_builtin_py_impl(
|
||||
self.register_py_builtin_const(
|
||||
FUNC_FILTER,
|
||||
t_filter,
|
||||
Immutable,
|
||||
vis.clone(),
|
||||
Some(t_filter),
|
||||
filter,
|
||||
Some(FUNC_FILTER),
|
||||
None,
|
||||
);
|
||||
self.register_builtin_py_impl(FUNC_FROZENSET, t_frozenset, Immutable, vis.clone(), None);
|
||||
self.register_builtin_py_impl(
|
||||
|
@ -453,7 +490,14 @@ impl Context {
|
|||
Some(FUNC_MAP),
|
||||
None,
|
||||
);
|
||||
self.register_builtin_py_impl(FUNC_MAX, t_max, Immutable, vis.clone(), Some(FUNC_MAX));
|
||||
self.register_py_builtin_const(
|
||||
FUNC_MAX,
|
||||
vis.clone(),
|
||||
Some(t_max),
|
||||
max,
|
||||
Some(FUNC_MAX),
|
||||
None,
|
||||
);
|
||||
self.register_builtin_py_impl(
|
||||
FUNC_MEMORYVIEW,
|
||||
t_memoryview,
|
||||
|
@ -461,8 +505,15 @@ impl Context {
|
|||
vis.clone(),
|
||||
Some(FUNC_MEMORYVIEW),
|
||||
);
|
||||
self.register_builtin_py_impl(FUNC_MIN, t_min, Immutable, vis.clone(), Some(FUNC_MIN));
|
||||
self.register_builtin_py_impl(FUNC_NOT, t_not, Immutable, vis.clone(), None); // `not` is not a function in Python
|
||||
self.register_py_builtin_const(
|
||||
FUNC_MIN,
|
||||
vis.clone(),
|
||||
Some(t_min),
|
||||
min,
|
||||
Some(FUNC_MIN),
|
||||
None,
|
||||
);
|
||||
self.register_py_builtin_const(FUNC_NOT, vis.clone(), Some(t_not), not, None, None); // `not` is not a function in Python
|
||||
self.register_builtin_py_impl(FUNC_OCT, t_oct, Immutable, vis.clone(), Some(FUNC_OCT));
|
||||
self.register_builtin_py_impl(FUNC_ORD, t_ord, Immutable, vis.clone(), Some(FUNC_ORD));
|
||||
self.register_builtin_py_impl(FUNC_POW, t_pow, Immutable, vis.clone(), Some(FUNC_POW));
|
||||
|
@ -559,9 +610,23 @@ impl Context {
|
|||
vis.clone(),
|
||||
Some(FUNC_STATICMETHOD),
|
||||
);
|
||||
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis.clone(), Some(FUNC_STR__));
|
||||
self.register_py_builtin_const(
|
||||
FUNC_STR,
|
||||
vis.clone(),
|
||||
Some(t_str),
|
||||
str_,
|
||||
Some(FUNC_STR__),
|
||||
None,
|
||||
);
|
||||
self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis.clone(), Some(FUNC_SUM));
|
||||
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis.clone(), Some(FUNC_ZIP));
|
||||
self.register_py_builtin_const(
|
||||
FUNC_ZIP,
|
||||
vis.clone(),
|
||||
Some(t_zip),
|
||||
zip,
|
||||
Some(FUNC_ZIP),
|
||||
None,
|
||||
);
|
||||
let name = if PYTHON_MODE { FUNC_INT } else { FUNC_INT__ };
|
||||
self.register_builtin_py_impl(FUNC_INT, t_int, Immutable, vis.clone(), Some(name));
|
||||
if DEBUG_MODE {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue