mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Implement subtype ascription
This commit is contained in:
parent
6613fd85c2
commit
cb4c2c7bbf
5 changed files with 120 additions and 48 deletions
|
@ -410,6 +410,12 @@ impl Context {
|
|||
set! { subtypeof(mono_q("Self"), mono("Writable!")) },
|
||||
);
|
||||
writable.register_builtin_py_decl("write!", t_write, Public, Some("write"));
|
||||
// TODO: Add required methods
|
||||
let mut filelike = Self::builtin_mono_trait("FileLike", 2);
|
||||
filelike.register_superclass(mono("Readable"), &readable);
|
||||
let mut filelike_mut = Self::builtin_mono_trait("FileLike!", 2);
|
||||
filelike_mut.register_superclass(mono("FileLike"), &filelike);
|
||||
filelike_mut.register_superclass(mono("Writable!"), &writable);
|
||||
/* Show */
|
||||
let mut show = Self::builtin_mono_trait("Show", 2);
|
||||
let t_show = fn0_met(ref_(mono_q("Self")), Str);
|
||||
|
@ -568,6 +574,8 @@ impl Context {
|
|||
Const,
|
||||
Some("Writable"),
|
||||
);
|
||||
self.register_builtin_type(mono("FileLike"), filelike, Private, Const, None);
|
||||
self.register_builtin_type(mono("FileLike!"), filelike_mut, Private, Const, None);
|
||||
self.register_builtin_type(mono("Show"), show, Private, Const, None);
|
||||
self.register_builtin_type(
|
||||
poly("Input", vec![ty_tp(mono_q("T"))]),
|
||||
|
@ -1385,6 +1393,8 @@ impl Context {
|
|||
Some("write"),
|
||||
);
|
||||
file_mut.register_trait(mono("File!"), file_mut_writable);
|
||||
file_mut.register_marker_trait(mono("FileLike"));
|
||||
file_mut.register_marker_trait(mono("FileLike!"));
|
||||
/* Array_mut */
|
||||
let array_mut_t = poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
||||
let mut array_mut_ = Self::builtin_poly_class(
|
||||
|
|
|
@ -1870,7 +1870,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_mut_type(&mut self, name: &str) -> Option<(&Type, &mut Context)> {
|
||||
pub(crate) fn get_mut_type(&mut self, name: &str) -> Option<(&Type, &mut Context)> {
|
||||
if let Some((t, ctx)) = self.mono_types.get_mut(name) {
|
||||
Some((t, ctx))
|
||||
} else if let Some((t, ctx)) = self.poly_types.get_mut(name) {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
.TarFile!: ClassType
|
||||
.TarFile! <: FileLike
|
||||
.TarFile! <: FileLike!
|
||||
.TarFile!.open!: (path: PathLike or NoneType := NoneType, mode := Str) => .TarFile!
|
||||
.TarFile!.add!: (self: RefMut(.TarFile!), name: PathLike, arcname: PathLike or NoneType := NoneType, recursive := Bool) => NoneType
|
||||
.TarFile!.close!: (self: .TarFile!,) => NoneType
|
||||
|
@ -6,5 +8,5 @@
|
|||
.TarFile!.getnames: (self: Ref(.TarFile!),) -> [Str; _]
|
||||
.TarFile!.list: (self: Ref(.TarFile!), verbose := Bool) -> [Str; _]
|
||||
|
||||
.open!: (path: PathLike or NoneType := NoneType, mode := Str) => .TarFile!
|
||||
.open!: (path: PathLike or NoneType := NoneType, mode := Str, fileobj: FileLike or NoneType := NoneType) => .TarFile!
|
||||
.is_tarfile: (name: Str or File!,) -> Bool
|
||||
|
|
|
@ -1413,6 +1413,7 @@ impl ASTLowerer {
|
|||
|
||||
fn lower_type_asc(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||
log!(info "entered {}({tasc})", fn_name!());
|
||||
let is_instance_ascription = tasc.is_instance_ascription();
|
||||
let t = self.ctx.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
None,
|
||||
|
@ -1420,13 +1421,33 @@ impl ASTLowerer {
|
|||
RegistrationMode::Normal,
|
||||
false,
|
||||
)?;
|
||||
let loc = tasc.loc();
|
||||
let expr = self.lower_expr(*tasc.expr)?;
|
||||
self.ctx.sub_unify(
|
||||
expr.ref_t(),
|
||||
&t,
|
||||
expr.loc(),
|
||||
Some(&Str::from(expr.to_string())),
|
||||
)?;
|
||||
if is_instance_ascription {
|
||||
self.ctx.sub_unify(
|
||||
expr.ref_t(),
|
||||
&t,
|
||||
expr.loc(),
|
||||
Some(&Str::from(expr.to_string())),
|
||||
)?;
|
||||
} else {
|
||||
let ctx = self
|
||||
.ctx
|
||||
.get_singular_ctx_by_hir_expr(&expr, &self.ctx.name)?;
|
||||
// REVIEW: need to use subtype_of?
|
||||
if ctx.super_traits.iter().all(|trait_| trait_ != &t)
|
||||
&& ctx.super_classes.iter().all(|class| class != &t)
|
||||
{
|
||||
return Err(LowerErrors::from(LowerError::subtyping_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
expr.ref_t(), // FIXME:
|
||||
&t,
|
||||
loc,
|
||||
self.ctx.caused_by(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(expr.type_asc(tasc.t_spec))
|
||||
}
|
||||
|
||||
|
@ -1559,6 +1580,7 @@ impl ASTLowerer {
|
|||
|
||||
fn declare_ident(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||
log!(info "entered {}({})", fn_name!(), tasc);
|
||||
let is_instance_ascription = tasc.is_instance_ascription();
|
||||
match *tasc.expr {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
|
||||
|
@ -1569,46 +1591,10 @@ impl ASTLowerer {
|
|||
RegistrationMode::Normal,
|
||||
false,
|
||||
)?;
|
||||
if ident.is_const() {
|
||||
let vi = VarInfo::new(
|
||||
t.clone(),
|
||||
Mutability::Const,
|
||||
ident.vis(),
|
||||
VarKind::Declared,
|
||||
None,
|
||||
None,
|
||||
Some(py_name.clone()),
|
||||
);
|
||||
self.ctx.decls.insert(ident.name.clone(), vi);
|
||||
}
|
||||
self.ctx.assign_var_sig(
|
||||
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
|
||||
&t,
|
||||
ast::DefId(0),
|
||||
Some(py_name),
|
||||
)?;
|
||||
match t {
|
||||
Type::ClassType => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Class,
|
||||
mono(format!("{}{ident}", self.ctx.path())),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(&ident, ty_obj);
|
||||
}
|
||||
Type::TraitType => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Trait,
|
||||
mono(format!("{}{ident}", self.ctx.path())),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(&ident, ty_obj);
|
||||
}
|
||||
_ => {}
|
||||
if is_instance_ascription {
|
||||
self.declare_instance(&ident, &t, py_name)?;
|
||||
} else {
|
||||
self.declare_subtype(&ident, &t)?;
|
||||
}
|
||||
let muty = Mutability::from(&ident.inspect()[..]);
|
||||
let vis = ident.vis();
|
||||
|
@ -1654,6 +1640,72 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
|
||||
fn declare_instance(
|
||||
&mut self,
|
||||
ident: &ast::Identifier,
|
||||
t: &Type,
|
||||
py_name: Str,
|
||||
) -> LowerResult<()> {
|
||||
if ident.is_const() {
|
||||
let vi = VarInfo::new(
|
||||
t.clone(),
|
||||
Mutability::Const,
|
||||
ident.vis(),
|
||||
VarKind::Declared,
|
||||
None,
|
||||
None,
|
||||
Some(py_name.clone()),
|
||||
);
|
||||
self.ctx.decls.insert(ident.name.clone(), vi);
|
||||
}
|
||||
self.ctx.assign_var_sig(
|
||||
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
|
||||
t,
|
||||
ast::DefId(0),
|
||||
Some(py_name),
|
||||
)?;
|
||||
match t {
|
||||
Type::ClassType => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Class,
|
||||
mono(format!("{}{ident}", self.ctx.path())),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(ident, ty_obj);
|
||||
}
|
||||
Type::TraitType => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Trait,
|
||||
mono(format!("{}{ident}", self.ctx.path())),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(ident, ty_obj);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn declare_subtype(&mut self, ident: &ast::Identifier, trait_: &Type) -> LowerResult<()> {
|
||||
if let Some((_, ctx)) = self.ctx.get_mut_type(ident.inspect()) {
|
||||
ctx.register_marker_trait(trait_.clone());
|
||||
Ok(())
|
||||
} else {
|
||||
Err(LowerErrors::from(LowerError::no_var_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
ident.loc(),
|
||||
self.ctx.caused_by(),
|
||||
ident.inspect(),
|
||||
self.ctx.get_similar_name(ident.inspect()),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match expr {
|
||||
|
|
|
@ -3011,6 +3011,14 @@ impl TypeAscription {
|
|||
t_spec,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_instance_ascription(&self) -> bool {
|
||||
self.op.is(TokenKind::Colon)
|
||||
}
|
||||
|
||||
pub fn is_subtype_ascription(&self) -> bool {
|
||||
self.op.is(TokenKind::SubtypeOf)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue