mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 04:09:05 +00:00
feat: add Record.as_dict()
This commit is contained in:
parent
2966497ad6
commit
5e71bd7fd0
6 changed files with 96 additions and 4 deletions
|
@ -1338,6 +1338,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(TyParam::Set(new_set))
|
Ok(TyParam::Set(new_set))
|
||||||
}
|
}
|
||||||
|
TyParam::Record(dict) => {
|
||||||
|
let mut fields = dict! {};
|
||||||
|
for (name, tp) in dict.into_iter() {
|
||||||
|
fields.insert(name, self.eval_tp(tp)?);
|
||||||
|
}
|
||||||
|
Ok(TyParam::Record(fields))
|
||||||
|
}
|
||||||
TyParam::Type(t) => self
|
TyParam::Type(t) => self
|
||||||
.eval_t_params(*t, self.level, &())
|
.eval_t_params(*t, self.level, &())
|
||||||
.map(TyParam::t)
|
.map(TyParam::t)
|
||||||
|
@ -2345,6 +2352,14 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(set_t(union, len))
|
Ok(set_t(union, len))
|
||||||
}
|
}
|
||||||
|
TyParam::Record(dict) => {
|
||||||
|
let mut fields = dict! {};
|
||||||
|
for (name, tp) in dict.into_iter() {
|
||||||
|
let tp_t = self.get_tp_t(&tp)?;
|
||||||
|
fields.insert(name, tp_t);
|
||||||
|
}
|
||||||
|
Ok(Type::Record(fields))
|
||||||
|
}
|
||||||
dict @ TyParam::Dict(_) => Ok(dict_t(dict)),
|
dict @ TyParam::Dict(_) => Ok(dict_t(dict)),
|
||||||
TyParam::BinOp { op, lhs, rhs } => match op {
|
TyParam::BinOp { op, lhs, rhs } => match op {
|
||||||
OpKind::Or | OpKind::And => {
|
OpKind::Or | OpKind::And => {
|
||||||
|
|
|
@ -1808,6 +1808,21 @@ impl Context {
|
||||||
Visibility::BUILTIN_PUBLIC,
|
Visibility::BUILTIN_PUBLIC,
|
||||||
);
|
);
|
||||||
record.register_trait(mono(RECORD), record_eq);
|
record.register_trait(mono(RECORD), record_eq);
|
||||||
|
let Slf = mono_q("Self", subtypeof(mono(RECORD)));
|
||||||
|
let into_dict_t =
|
||||||
|
fn0_met(Slf.clone(), proj_call(ty_tp(Slf), FUNC_AS_DICT, vec![])).quantify();
|
||||||
|
let into_dict = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
FUNC_UNION,
|
||||||
|
as_dict,
|
||||||
|
into_dict_t,
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
record.register_py_builtin_const(
|
||||||
|
FUNC_AS_DICT,
|
||||||
|
Visibility::BUILTIN_PUBLIC,
|
||||||
|
into_dict,
|
||||||
|
Some("_asdict"),
|
||||||
|
);
|
||||||
/* GenericNamedTuple */
|
/* GenericNamedTuple */
|
||||||
let mut generic_named_tuple = Self::builtin_mono_class(GENERIC_NAMED_TUPLE, 2);
|
let mut generic_named_tuple = Self::builtin_mono_class(GENERIC_NAMED_TUPLE, 2);
|
||||||
generic_named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
generic_named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
||||||
|
|
|
@ -2,13 +2,13 @@ use std::fmt::Display;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::enum_unwrap;
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
|
use erg_common::{enum_unwrap, set};
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::feature_error;
|
use crate::feature_error;
|
||||||
use crate::ty::constructors::{and, mono, poly, tuple_t, ty_tp};
|
use crate::ty::constructors::{and, mono, poly, tuple_t, ty_tp, v_enum};
|
||||||
use crate::ty::value::{EvalValueError, EvalValueResult, GenTypeObj, TypeObj, ValueObj};
|
use crate::ty::value::{EvalValueError, EvalValueResult, GenTypeObj, TypeObj, ValueObj};
|
||||||
use crate::ty::{TyParam, Type, ValueArgs};
|
use crate::ty::{TyParam, Type, ValueArgs};
|
||||||
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
||||||
|
@ -499,3 +499,24 @@ pub(crate) fn named_tuple_union(mut args: ValueArgs, ctx: &Context) -> EvalValue
|
||||||
.fold(Type::Never, |union, (_, t)| ctx.union(&union, t));
|
.fold(Type::Never, |union, (_, t)| ctx.union(&union, t));
|
||||||
Ok(ValueObj::builtin_type(union).into())
|
Ok(ValueObj::builtin_type(union).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `{ .x = Int; .y = Str }.as_dict() == { "x": Int, "y": Str }`
|
||||||
|
pub(crate) fn as_dict(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||||
|
let slf = args
|
||||||
|
.remove_left_or_key("Self")
|
||||||
|
.ok_or_else(|| not_passed("Self"))?;
|
||||||
|
let fields = match ctx.convert_value_into_type(slf) {
|
||||||
|
Ok(Type::Record(fields)) => fields,
|
||||||
|
Ok(other) => {
|
||||||
|
return Err(type_mismatch("Record", other, "Self"));
|
||||||
|
}
|
||||||
|
Err(val) => {
|
||||||
|
return Err(type_mismatch("Record", val, "Self"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dict = fields
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (v_enum(set! { k.symbol.into() }), v))
|
||||||
|
.collect::<Dict<_, _>>();
|
||||||
|
Ok(ValueObj::builtin_type(Type::from(dict)).into())
|
||||||
|
}
|
||||||
|
|
|
@ -263,6 +263,7 @@ const SYMMETRIC_DIFFERENCE: &str = "symmetric_difference";
|
||||||
const MEMORYVIEW: &str = "MemoryView";
|
const MEMORYVIEW: &str = "MemoryView";
|
||||||
const FUNC_UNION: &str = "union";
|
const FUNC_UNION: &str = "union";
|
||||||
const FUNC_SHAPE: &str = "shape";
|
const FUNC_SHAPE: &str = "shape";
|
||||||
|
const FUNC_AS_DICT: &str = "as_dict";
|
||||||
const FUNC_INC: &str = "inc";
|
const FUNC_INC: &str = "inc";
|
||||||
const PROC_INC: &str = "inc!";
|
const PROC_INC: &str = "inc!";
|
||||||
const FUNC_DEC: &str = "dec";
|
const FUNC_DEC: &str = "dec";
|
||||||
|
@ -721,6 +722,37 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_py_builtin_const(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
vis: Visibility,
|
||||||
|
obj: ValueObj,
|
||||||
|
py_name: Option<&'static str>,
|
||||||
|
) {
|
||||||
|
if self.rec_get_const_obj(name).is_some() {
|
||||||
|
panic!("already registered: {} {name}", self.name);
|
||||||
|
} else {
|
||||||
|
let impl_of = if let ContextKind::MethodDefs(Some(tr)) = &self.kind {
|
||||||
|
Some(tr.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
// TODO: not all value objects are comparable
|
||||||
|
let vi = VarInfo::new(
|
||||||
|
v_enum(set! {obj.clone()}),
|
||||||
|
Const,
|
||||||
|
vis,
|
||||||
|
Builtin,
|
||||||
|
None,
|
||||||
|
impl_of,
|
||||||
|
py_name.map(Str::ever),
|
||||||
|
AbsLocation::unknown(),
|
||||||
|
);
|
||||||
|
self.consts.insert(VarName::from_str(Str::rc(name)), obj);
|
||||||
|
self.locals.insert(VarName::from_str(Str::rc(name)), vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn register_const_param_defaults(&mut self, name: &'static str, params: Vec<ConstTemplate>) {
|
fn register_const_param_defaults(&mut self, name: &'static str, params: Vec<ConstTemplate>) {
|
||||||
if self.const_param_defaults.get(name).is_some() {
|
if self.const_param_defaults.get(name).is_some() {
|
||||||
panic!("already registered: {} {name}", self.name);
|
panic!("already registered: {} {name}", self.name);
|
||||||
|
|
|
@ -2424,12 +2424,12 @@ impl Context {
|
||||||
Type::Poly { name, .. } => {
|
Type::Poly { name, .. } => {
|
||||||
return self.get_poly_type(name);
|
return self.get_poly_type(name);
|
||||||
}
|
}
|
||||||
Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => {
|
/*Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => {
|
||||||
return self
|
return self
|
||||||
.get_builtins()
|
.get_builtins()
|
||||||
.unwrap_or(self)
|
.unwrap_or(self)
|
||||||
.rec_local_get_mono_type("RecordType");
|
.rec_local_get_mono_type("RecordType");
|
||||||
}
|
}*/
|
||||||
Type::Record(_) => {
|
Type::Record(_) => {
|
||||||
return self
|
return self
|
||||||
.get_builtins()
|
.get_builtins()
|
||||||
|
@ -3149,6 +3149,11 @@ impl Context {
|
||||||
.map(|(name, tp)| (name.clone(), self.meta_type(tp)))
|
.map(|(name, tp)| (name.clone(), self.meta_type(tp)))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
|
Record(rec) => Record(
|
||||||
|
rec.iter()
|
||||||
|
.map(|(name, tp)| (name.clone(), self.meta_type(tp)))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
_ => Type,
|
_ => Type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,3 +22,7 @@ Person! = {
|
||||||
print! Person!.name
|
print! Person!.name
|
||||||
assert Person!.name == Str
|
assert Person!.name == Str
|
||||||
# assert john in Person!
|
# assert john in Person!
|
||||||
|
|
||||||
|
for! {.x = 1; .y = 2}.as_dict().items(), ((k, v),) =>
|
||||||
|
# k: Str, v: Int
|
||||||
|
print! k, v
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue