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
|
true
|
||||||
}
|
}
|
||||||
(Bool, Guard { .. }) => true,
|
(Bool, Guard { .. }) => true,
|
||||||
|
(Mono(n), NamedTuple(_)) => &n[..] == "GenericNamedTuple" || &n[..] == "GenericTuple",
|
||||||
(Type, Subr(subr)) => self.supertype_of(&Type, &subr.return_t),
|
(Type, Subr(subr)) => self.supertype_of(&Type, &subr.return_t),
|
||||||
(Type, Poly { name, params }) if &name[..] == "Array" || &name[..] == "Set" => {
|
(Type, Poly { name, params }) if &name[..] == "Array" || &name[..] == "Set" => {
|
||||||
let elem_t = self.convert_tp_into_type(params[0].clone()).unwrap();
|
let elem_t = self.convert_tp_into_type(params[0].clone()).unwrap();
|
||||||
|
|
|
@ -1688,9 +1688,71 @@ impl Context {
|
||||||
/* record */
|
/* record */
|
||||||
let mut record = Self::builtin_mono_class(RECORD, 2);
|
let mut record = Self::builtin_mono_class(RECORD, 2);
|
||||||
record.register_superclass(Obj, &obj);
|
record.register_superclass(Obj, &obj);
|
||||||
/* NamedTuple */
|
/* GenericNamedTuple */
|
||||||
let mut named_tuple = Self::builtin_mono_class(NAMED_TUPLE, 2);
|
let mut generic_named_tuple = Self::builtin_mono_class(GENERIC_NAMED_TUPLE, 2);
|
||||||
named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
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) */
|
/* Or (true or type) */
|
||||||
let or_t = poly(OR, vec![ty_tp(L), ty_tp(R)]);
|
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);
|
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(_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(RECORD), record, vis.clone(), Const, Some(RECORD));
|
||||||
self.register_builtin_type(
|
self.register_builtin_type(
|
||||||
mono(NAMED_TUPLE),
|
mono(GENERIC_NAMED_TUPLE),
|
||||||
named_tuple,
|
generic_named_tuple,
|
||||||
vis.clone(),
|
vis.clone(),
|
||||||
Const,
|
Const,
|
||||||
Some(NAMED_TUPLE),
|
Some(GENERIC_NAMED_TUPLE),
|
||||||
);
|
);
|
||||||
self.register_builtin_type(or_t, or, vis.clone(), Const, Some(UNION));
|
self.register_builtin_type(or_t, or, vis.clone(), Const, Some(UNION));
|
||||||
self.register_builtin_type(
|
self.register_builtin_type(
|
||||||
|
|
|
@ -450,3 +450,52 @@ pub(crate) fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValu
|
||||||
.into())
|
.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: &str = "Tuple";
|
||||||
const TUPLE_ITERATOR: &str = "TupleIterator";
|
const TUPLE_ITERATOR: &str = "TupleIterator";
|
||||||
const RECORD: &str = "Record";
|
const RECORD: &str = "Record";
|
||||||
const NAMED_TUPLE: &str = "NamedTuple";
|
const GENERIC_NAMED_TUPLE: &str = "GenericNamedTuple";
|
||||||
const OR: &str = "Or";
|
const OR: &str = "Or";
|
||||||
const RANGE_ITERATOR: &str = "RangeIterator";
|
const RANGE_ITERATOR: &str = "RangeIterator";
|
||||||
const ENUMERATE: &str = "Enumerate";
|
const ENUMERATE: &str = "Enumerate";
|
||||||
|
|
|
@ -2422,7 +2422,7 @@ impl Context {
|
||||||
return self
|
return self
|
||||||
.get_builtins()
|
.get_builtins()
|
||||||
.unwrap_or(self)
|
.unwrap_or(self)
|
||||||
.rec_local_get_mono_type("NamedTuple");
|
.rec_local_get_mono_type("GenericNamedTuple");
|
||||||
}
|
}
|
||||||
Type::Or(_l, _r) => {
|
Type::Or(_l, _r) => {
|
||||||
if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
|
if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
|
||||||
|
@ -3103,10 +3103,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
/// ```erg
|
||||||
/// Int.meta_type() == ClassType (<: Type)
|
/// Int.meta_type() == ClassType (<: Type)
|
||||||
/// Show.meta_type() == TraitType (<: Type)
|
/// Show.meta_type() == TraitType (<: Type)
|
||||||
/// [Int; 3].meta_type() == [ClassType; 3] (<: Type)
|
/// [Int; 3].meta_type() == [ClassType; 3] (<: Type)
|
||||||
/// Indexable(T).meta_type() == TraitType (<: 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 {
|
pub fn meta_type(&self, typ: &Type) -> Type {
|
||||||
match typ {
|
match typ {
|
||||||
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Set" => poly(
|
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Set" => poly(
|
||||||
|
@ -3122,6 +3125,12 @@ impl Context {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
|
NamedTuple(tuple) => NamedTuple(
|
||||||
|
tuple
|
||||||
|
.iter()
|
||||||
|
.map(|(name, tp)| (name.clone(), self.meta_type(tp)))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
_ => Type,
|
_ => Type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use ast::{
|
||||||
TypeBoundSpecs, TypeSpec,
|
TypeBoundSpecs, TypeSpec,
|
||||||
};
|
};
|
||||||
use erg_parser::ast::{
|
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::token::TokenKind;
|
||||||
use erg_parser::Parser;
|
use erg_parser::Parser;
|
||||||
|
@ -671,6 +671,50 @@ impl Context {
|
||||||
)?;
|
)?;
|
||||||
Ok(t.structuralize())
|
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 => {
|
other => {
|
||||||
let Some((typ, ctx)) = self.get_type(&Str::rc(other)) else {
|
let Some((typ, ctx)) = self.get_type(&Str::rc(other)) else {
|
||||||
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
return Err(TyCheckErrors::from(TyCheckError::no_type_error(
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
.copyfile!: (src: PathLike, dst: PathLike,) => NoneType
|
.copyfile!: (src: PathLike, dst: PathLike,) => NoneType
|
||||||
.copy!: (src: PathLike, dst: PathLike,) => NoneType
|
.copy!: (src: PathLike, dst: PathLike,) => NoneType
|
||||||
.copytree!: (src: PathLike, dst: PathLike,) => NoneType
|
.copytree!: (src: PathLike, dst: PathLike,) => NoneType
|
||||||
.disk_usage!: (path: PathLike,) => {
|
.disk_usage!: (path: PathLike,) => NamedTuple {
|
||||||
.total = Nat
|
.total = Nat
|
||||||
.used = Nat
|
.used = Nat
|
||||||
.free = Nat
|
.free = Nat
|
||||||
|
|
|
@ -1115,7 +1115,7 @@ impl LimitedDisplay for Type {
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
}
|
}
|
||||||
Self::NamedTuple(attrs) => {
|
Self::NamedTuple(attrs) => {
|
||||||
write!(f, "NamedTuple {{")?;
|
write!(f, "NamedTuple({{")?;
|
||||||
for (i, (field, t)) in attrs.iter().enumerate() {
|
for (i, (field, t)) in attrs.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
write!(f, "; ")?;
|
write!(f, "; ")?;
|
||||||
|
@ -1130,7 +1130,7 @@ impl LimitedDisplay for Type {
|
||||||
if attrs.is_empty() {
|
if attrs.is_empty() {
|
||||||
write!(f, "=")?;
|
write!(f, "=")?;
|
||||||
}
|
}
|
||||||
write!(f, "}}")
|
write!(f, "}})")
|
||||||
}
|
}
|
||||||
Self::Subr(sub) => sub.limited_fmt(f, limit),
|
Self::Subr(sub) => sub.limited_fmt(f, limit),
|
||||||
Self::Refinement(refinement) => refinement.limited_fmt(f, limit),
|
Self::Refinement(refinement) => refinement.limited_fmt(f, limit),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue