feat: const abs/all/any/len/map

This commit is contained in:
Shunsuke Shibayama 2024-01-29 13:29:39 +09:00
parent f0e47201bf
commit d59a4e82d3
5 changed files with 214 additions and 8 deletions

View file

@ -646,7 +646,12 @@ impl Context {
}
}
fn call(&self, subr: ConstSubr, args: ValueArgs, loc: Location) -> EvalResult<TyParam> {
pub(crate) fn call(
&self,
subr: ConstSubr,
args: ValueArgs,
loc: Location,
) -> EvalResult<TyParam> {
match subr {
ConstSubr::User(user) => {
// HACK: should avoid cloning

View file

@ -2089,8 +2089,10 @@ impl Context {
record.register_py_builtin_const(
FUNC_AS_DICT,
Visibility::BUILTIN_PUBLIC,
None,
as_dict,
Some("_asdict"),
None,
);
let mut record_meta_type = Self::builtin_mono_class(RECORD_META_TYPE, 2);
record_meta_type.register_superclass(mono(RECORD), &record);

View file

@ -5,6 +5,7 @@ use std::path::Path;
use erg_common::dict::Dict;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::traits::Stream;
use erg_common::{dict, set};
use crate::context::eval::UndoableLinkedList;
@ -799,6 +800,127 @@ pub(crate) fn as_record(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<T
Ok(ValueObj::builtin_type(Type::Record(dict)).into())
}
pub(crate) fn abs_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
let num = args
.remove_left_or_key("num")
.ok_or_else(|| not_passed("num"))?;
match num {
ValueObj::Nat(n) => Ok(ValueObj::Nat(n).into()),
ValueObj::Int(n) => Ok(ValueObj::Nat(n.unsigned_abs() as u64).into()),
ValueObj::Bool(b) => Ok(ValueObj::Nat(b as u64).into()),
ValueObj::Float(n) => Ok(ValueObj::Float(n.abs()).into()),
ValueObj::Inf => Ok(ValueObj::Inf.into()),
ValueObj::NegInf => Ok(ValueObj::Inf.into()),
_ => Err(type_mismatch("Num", num, "num")),
}
}
pub(crate) fn all_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(Bool)", iterable, "iterable"));
}
};
let mut all = true;
for v in arr.iter() {
match v {
ValueObj::Bool(b) => {
all &= *b;
}
_ => {
return Err(type_mismatch("Bool", v, "iterable.next()"));
}
}
}
Ok(ValueObj::Bool(all).into())
}
pub(crate) fn any_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(Bool)", iterable, "iterable"));
}
};
let mut any = false;
for v in arr.iter() {
match v {
ValueObj::Bool(b) => {
any |= *b;
}
_ => {
return Err(type_mismatch("Bool", v, "iterable.next()"));
}
}
}
Ok(ValueObj::Bool(any).into())
}
pub(crate) fn len_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
let container = args
.remove_left_or_key("iterable")
.ok_or_else(|| not_passed("iterable"))?;
let len = match container {
ValueObj::Array(a) => a.len(),
ValueObj::Tuple(t) => t.len(),
ValueObj::Set(s) => s.len(),
ValueObj::Dict(d) => d.len(),
ValueObj::Record(r) => r.len(),
ValueObj::Str(s) => s.len(),
_ => {
return Err(type_mismatch("Container", container, "container"));
}
};
Ok(ValueObj::Nat(len as u64).into())
}
pub(crate) fn map_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(Bool)", iterable, "iterable"));
}
};
let subr = match func {
ValueObj::Subr(f) => f,
_ => {
return Err(type_mismatch("Subr", func, "func"));
}
};
let mut mapped = vec![];
for v in arr.into_iter() {
let args = ValueArgs::pos_only(vec![v]);
match ctx.call(subr.clone(), args, Location::Unknown) {
Ok(res) => {
mapped.push(res);
}
Err(mut err) => {
return Err(EvalValueError::from(*err.remove(0).core));
}
}
}
Ok(TyParam::Array(mapped))
}
pub(crate) fn resolve_path_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
let path = args
.remove_left_or_key("Path")

View file

@ -24,16 +24,34 @@ impl Context {
let U = mono_q(TY_U, instanceof(Type));
let Path = mono_q_tp(PATH, instanceof(Str));
let t_abs = nd_func(vec![kw(KW_N, mono(NUM))], None, Nat);
let abs = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_ABS,
abs_func,
t_abs.clone(),
None,
)));
let t_all = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(Bool)]))],
vec![],
Bool,
);
let all = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_ALL,
all_func,
t_all.clone(),
None,
)));
let t_any = no_var_func(
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(Bool)]))],
vec![],
Bool,
);
let any = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_ANY,
any_func,
t_any.clone(),
None,
)));
let t_ascii = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
let t_array = no_var_func(
vec![],
@ -169,6 +187,12 @@ impl Context {
.structuralize();
func1(S, Nat)
};
let len = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_LEN,
len_func,
t_len.clone(),
None,
)));
let t_log = func(
vec![],
Some(kw(KW_OBJECTS, ref_(Obj))),
@ -190,6 +214,12 @@ impl Context {
poly(MAP, vec![ty_tp(U.clone())]),
)
.quantify();
let map = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
FUNC_MAP,
map_func,
t_map.clone(),
None,
)));
let O = mono_q(TY_O, subtypeof(mono(ORD)));
// TODO: iterable should be non-empty
let t_max = nd_func(
@ -286,9 +316,30 @@ impl Context {
poly(ZIP, vec![ty_tp(T.clone()), ty_tp(U.clone())]),
)
.quantify();
self.register_py_builtin(FUNC_ABS, t_abs, Some(FUNC_ABS), 11);
self.register_py_builtin(FUNC_ALL, t_all, Some(FUNC_ALL), 22);
self.register_py_builtin(FUNC_ANY, t_any, Some(FUNC_ANY), 33);
self.register_py_builtin_const(
FUNC_ABS,
vis.clone(),
Some(t_abs),
abs,
Some(FUNC_ABS),
Some(11),
);
self.register_py_builtin_const(
FUNC_ALL,
vis.clone(),
Some(t_all),
all,
Some(FUNC_ALL),
Some(22),
);
self.register_py_builtin_const(
FUNC_ANY,
vis.clone(),
Some(t_any),
any,
Some(FUNC_ANY),
Some(33),
);
self.register_py_builtin(FUNC_ARRAY, t_array, Some(FUNC_LIST), 215);
self.register_py_builtin(FUNC_ASCII, t_ascii, Some(FUNC_ASCII), 53);
// Leave as `Const`, as it may negatively affect assert casting.
@ -386,8 +437,22 @@ impl Context {
Some(FUNC_ISSUBCLASS),
);
self.register_builtin_py_impl(FUNC_ITER, t_iter, Immutable, vis.clone(), Some(FUNC_ITER));
self.register_builtin_py_impl(FUNC_LEN, t_len, Immutable, vis.clone(), Some(FUNC_LEN));
self.register_builtin_py_impl(FUNC_MAP, t_map, Immutable, vis.clone(), Some(FUNC_MAP));
self.register_py_builtin_const(
FUNC_LEN,
vis.clone(),
Some(t_len),
len,
Some(FUNC_LEN),
None,
);
self.register_py_builtin_const(
FUNC_MAP,
vis.clone(),
Some(t_map),
map,
Some(FUNC_MAP),
None,
);
self.register_builtin_py_impl(FUNC_MAX, t_max, Immutable, vis.clone(), Some(FUNC_MAX));
self.register_builtin_py_impl(
FUNC_MEMORYVIEW,

View file

@ -774,8 +774,10 @@ impl Context {
&mut self,
name: &str,
vis: Visibility,
t: Option<Type>,
obj: ValueObj,
py_name: Option<&'static str>,
lineno: Option<u32>,
) {
if self.rec_get_const_obj(name).is_some() {
panic!("already registered: {} {name}", self.name);
@ -791,16 +793,26 @@ impl Context {
}
}
}
let t = t.unwrap_or_else(|| v_enum(set! {obj.clone()}));
let loc = lineno
.map(|lineno| Location::range(lineno, 0, lineno, name.len() as u32))
.unwrap_or(Location::Unknown);
let module = if &self.name[..] == "<builtins>" {
builtins_path()
} else {
erg_core_decl_path().join(format!("{}.d.er", self.name))
};
let abs_loc = AbsLocation::new(Some(module.into()), loc);
// TODO: not all value objects are comparable
let vi = VarInfo::new(
v_enum(set! {obj.clone()}),
t,
Const,
vis,
Builtin,
None,
self.kind.clone(),
py_name.map(Str::ever),
AbsLocation::unknown(),
abs_loc,
);
self.consts.insert(VarName::from_str(Str::rc(name)), obj);
self.locals.insert(VarName::from_str(Str::rc(name)), vi);