mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
WIP
This commit is contained in:
parent
ea0089f7df
commit
9454896d5a
8 changed files with 177 additions and 12 deletions
|
@ -525,6 +525,7 @@ impl Context {
|
|||
true
|
||||
}
|
||||
(Bool, Guard { .. }) => true,
|
||||
(Mono(n), NamedTuple(_)) => &n[..] == "GenericNamedTuple" || &n[..] == "GenericTuple",
|
||||
(Type, Subr(subr)) => self.supertype_of(&Type, &subr.return_t),
|
||||
(Type, Poly { name, params }) if &name[..] == "Array" || &name[..] == "Set" => {
|
||||
let elem_t = self.convert_tp_into_type(params[0].clone()).unwrap();
|
||||
|
|
|
@ -1688,9 +1688,71 @@ impl Context {
|
|||
/* record */
|
||||
let mut record = Self::builtin_mono_class(RECORD, 2);
|
||||
record.register_superclass(Obj, &obj);
|
||||
/* NamedTuple */
|
||||
let mut named_tuple = Self::builtin_mono_class(NAMED_TUPLE, 2);
|
||||
named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
||||
/* GenericNamedTuple */
|
||||
let mut generic_named_tuple = Self::builtin_mono_class(GENERIC_NAMED_TUPLE, 2);
|
||||
generic_named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
||||
let Slf = mono("Self");
|
||||
let input_t = tp_enum(Nat, set! {N.clone()});
|
||||
let return_t = proj_call(ty_tp(Slf.clone()), FUNDAMENTAL_GETITEM, vec![N.clone()]);
|
||||
let named_tuple_getitem =
|
||||
fn1_met(Slf.clone(), input_t.clone(), return_t.clone()).quantify();
|
||||
let mut named_tuple_indexable = Self::builtin_methods(
|
||||
Some(poly(INDEXABLE, vec![ty_tp(input_t), ty_tp(return_t)])),
|
||||
2,
|
||||
);
|
||||
named_tuple_indexable.register_builtin_py_impl(
|
||||
FUNDAMENTAL_TUPLE_GETITEM,
|
||||
named_tuple_getitem.clone(),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNDAMENTAL_GETITEM),
|
||||
);
|
||||
generic_named_tuple.register_trait(mono(GENERIC_NAMED_TUPLE), named_tuple_indexable);
|
||||
let get_item = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNDAMENTAL_GETITEM,
|
||||
__named_tuple_getitem__,
|
||||
named_tuple_getitem,
|
||||
None,
|
||||
)));
|
||||
generic_named_tuple.register_builtin_const(
|
||||
FUNDAMENTAL_GETITEM,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
get_item,
|
||||
);
|
||||
let mut named_tuple_iterable = Self::builtin_methods(
|
||||
Some(poly(
|
||||
ITERABLE,
|
||||
vec![ty_tp(proj_call(ty_tp(Slf.clone()), FUNC_UNION, vec![]))],
|
||||
)),
|
||||
2,
|
||||
);
|
||||
let named_tuple_iterator = poly(
|
||||
TUPLE_ITERATOR,
|
||||
vec![ty_tp(proj_call(ty_tp(Slf.clone()), FUNC_UNION, vec![]))],
|
||||
);
|
||||
let t = fn0_met(Slf.clone(), named_tuple_iterator.clone()).quantify();
|
||||
named_tuple_iterable.register_builtin_py_impl(
|
||||
FUNC_ITER,
|
||||
t,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNDAMENTAL_ITER),
|
||||
);
|
||||
named_tuple_iterable.register_builtin_const(
|
||||
ITERATOR,
|
||||
vis.clone(),
|
||||
ValueObj::builtin_class(named_tuple_iterator),
|
||||
);
|
||||
generic_named_tuple.register_trait(mono(GENERIC_NAMED_TUPLE), named_tuple_iterable);
|
||||
// union: (self: NamedTuple({...})) -> Type
|
||||
let named_tuple_union_t = fn0_met(Slf, Type).quantify();
|
||||
let union = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_UNION,
|
||||
named_tuple_union,
|
||||
named_tuple_union_t,
|
||||
None,
|
||||
)));
|
||||
generic_named_tuple.register_builtin_const(FUNC_UNION, Visibility::BUILTIN_PUBLIC, union);
|
||||
/* Or (true or type) */
|
||||
let or_t = poly(OR, vec![ty_tp(L), ty_tp(R)]);
|
||||
let mut or = Self::builtin_poly_class(OR, vec![PS::t_nd(TY_L), PS::t_nd(TY_R)], 2);
|
||||
|
@ -2472,11 +2534,11 @@ impl Context {
|
|||
self.register_builtin_type(_tuple_t, tuple_, vis.clone(), Const, Some(FUNC_TUPLE));
|
||||
self.register_builtin_type(mono(RECORD), record, vis.clone(), Const, Some(RECORD));
|
||||
self.register_builtin_type(
|
||||
mono(NAMED_TUPLE),
|
||||
named_tuple,
|
||||
mono(GENERIC_NAMED_TUPLE),
|
||||
generic_named_tuple,
|
||||
vis.clone(),
|
||||
Const,
|
||||
Some(NAMED_TUPLE),
|
||||
Some(GENERIC_NAMED_TUPLE),
|
||||
);
|
||||
self.register_builtin_type(or_t, or, vis.clone(), Const, Some(UNION));
|
||||
self.register_builtin_type(
|
||||
|
|
|
@ -450,3 +450,52 @@ pub(crate) fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValu
|
|||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn __named_tuple_getitem__(
|
||||
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::NamedTuple(fields)) => fields,
|
||||
Ok(other) => {
|
||||
return Err(type_mismatch("NamedTuple", other, "Self"));
|
||||
}
|
||||
Err(val) => {
|
||||
return Err(type_mismatch("NamedTuple", val, "Self"));
|
||||
}
|
||||
};
|
||||
let index = args
|
||||
.remove_left_or_key("Index")
|
||||
.ok_or_else(|| not_passed("Index"))?;
|
||||
let Ok(index) = usize::try_from(&index) else {
|
||||
return Err(type_mismatch("Nat", index, "Index"));
|
||||
};
|
||||
if let Some((_, t)) = fields.get(index) {
|
||||
Ok(TyParam::t(t.clone()))
|
||||
} else {
|
||||
Err(no_key(Type::NamedTuple(fields), index))
|
||||
}
|
||||
}
|
||||
|
||||
/// `NamedTuple({ .x = Int; .y = Str }).union() == Int or Str`
|
||||
pub(crate) fn named_tuple_union(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::NamedTuple(fields)) => fields,
|
||||
Ok(other) => {
|
||||
return Err(type_mismatch("NamedTuple", other, "Self"));
|
||||
}
|
||||
Err(val) => {
|
||||
return Err(type_mismatch("NamedTuple", val, "Self"));
|
||||
}
|
||||
};
|
||||
let union = fields
|
||||
.iter()
|
||||
.fold(Type::Never, |union, (_, t)| ctx.union(&union, t));
|
||||
Ok(ValueObj::builtin_type(union).into())
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ const GENERIC_TUPLE: &str = "GenericTuple";
|
|||
const TUPLE: &str = "Tuple";
|
||||
const TUPLE_ITERATOR: &str = "TupleIterator";
|
||||
const RECORD: &str = "Record";
|
||||
const NAMED_TUPLE: &str = "NamedTuple";
|
||||
const GENERIC_NAMED_TUPLE: &str = "GenericNamedTuple";
|
||||
const OR: &str = "Or";
|
||||
const RANGE_ITERATOR: &str = "RangeIterator";
|
||||
const ENUMERATE: &str = "Enumerate";
|
||||
|
|
|
@ -2422,7 +2422,7 @@ impl Context {
|
|||
return self
|
||||
.get_builtins()
|
||||
.unwrap_or(self)
|
||||
.rec_local_get_mono_type("NamedTuple");
|
||||
.rec_local_get_mono_type("GenericNamedTuple");
|
||||
}
|
||||
Type::Or(_l, _r) => {
|
||||
if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
|
||||
|
@ -3103,10 +3103,13 @@ impl Context {
|
|||
}
|
||||
|
||||
// TODO:
|
||||
/// ```erg
|
||||
/// Int.meta_type() == ClassType (<: Type)
|
||||
/// Show.meta_type() == TraitType (<: Type)
|
||||
/// [Int; 3].meta_type() == [ClassType; 3] (<: Type)
|
||||
/// Indexable(T).meta_type() == TraitType (<: Type)
|
||||
/// NamedTuple({ .x = Int; .y = Str }).meta_type() == NamedTuple({ .x = ClassType; .y = ClassType })
|
||||
/// ```
|
||||
pub fn meta_type(&self, typ: &Type) -> Type {
|
||||
match typ {
|
||||
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Set" => poly(
|
||||
|
@ -3122,6 +3125,12 @@ impl Context {
|
|||
})
|
||||
.collect(),
|
||||
),
|
||||
NamedTuple(tuple) => NamedTuple(
|
||||
tuple
|
||||
.iter()
|
||||
.map(|(name, tp)| (name.clone(), self.meta_type(tp)))
|
||||
.collect(),
|
||||
),
|
||||
_ => Type,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use ast::{
|
|||
TypeBoundSpecs, TypeSpec,
|
||||
};
|
||||
use erg_parser::ast::{
|
||||
self, ConstArray, ConstSet, Identifier, VarName, VisModifierSpec, VisRestriction,
|
||||
self, ConstArray, ConstExpr, ConstSet, Identifier, VarName, VisModifierSpec, VisRestriction,
|
||||
};
|
||||
use erg_parser::token::TokenKind;
|
||||
use erg_parser::Parser;
|
||||
|
@ -671,6 +671,50 @@ impl Context {
|
|||
)?;
|
||||
Ok(t.structuralize())
|
||||
}
|
||||
"NamedTuple" => {
|
||||
let mut args = poly_spec.args.pos_args();
|
||||
let Some(first) = args.next() else {
|
||||
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
poly_spec.args.loc(),
|
||||
"NamedTuple",
|
||||
self.caused_by(),
|
||||
vec![Str::from("Fields")],
|
||||
)));
|
||||
};
|
||||
let ConstExpr::Record(fields) = &first.expr else {
|
||||
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
first.expr.loc(),
|
||||
self.caused_by(),
|
||||
"NamedTuple",
|
||||
None,
|
||||
&mono("Record"),
|
||||
&self.instantiate_const_expr_as_type(
|
||||
&first.expr,
|
||||
None,
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?,
|
||||
None,
|
||||
None,
|
||||
)));
|
||||
};
|
||||
let mut ts = vec![];
|
||||
for def in fields.attrs.iter() {
|
||||
let t = self.instantiate_const_expr_as_type(
|
||||
&def.body.block[0],
|
||||
None,
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
let vis = self.instantiate_vis_modifier(&def.ident.vis)?;
|
||||
ts.push((Field::new(vis, def.ident.inspect().clone()), t));
|
||||
}
|
||||
Ok(Type::NamedTuple(ts))
|
||||
}
|
||||
other => {
|
||||
let Some((typ, ctx)) = self.get_type(&Str::rc(other)) else {
|
||||
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
.copyfile!: (src: PathLike, dst: PathLike,) => NoneType
|
||||
.copy!: (src: PathLike, dst: PathLike,) => NoneType
|
||||
.copytree!: (src: PathLike, dst: PathLike,) => NoneType
|
||||
.disk_usage!: (path: PathLike,) => {
|
||||
.disk_usage!: (path: PathLike,) => NamedTuple {
|
||||
.total = Nat
|
||||
.used = Nat
|
||||
.free = Nat
|
||||
|
|
|
@ -1115,7 +1115,7 @@ impl LimitedDisplay for Type {
|
|||
write!(f, "}}")
|
||||
}
|
||||
Self::NamedTuple(attrs) => {
|
||||
write!(f, "NamedTuple {{")?;
|
||||
write!(f, "NamedTuple({{")?;
|
||||
for (i, (field, t)) in attrs.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, "; ")?;
|
||||
|
@ -1130,7 +1130,7 @@ impl LimitedDisplay for Type {
|
|||
if attrs.is_empty() {
|
||||
write!(f, "=")?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
write!(f, "}})")
|
||||
}
|
||||
Self::Subr(sub) => sub.limited_fmt(f, limit),
|
||||
Self::Refinement(refinement) => refinement.limited_fmt(f, limit),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue