mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04:33 +00:00
WIP: impl Trait
This commit is contained in:
parent
346d00fcd8
commit
aa527dcbc8
11 changed files with 227 additions and 51 deletions
|
@ -16,10 +16,12 @@ use erg_parser::token::{Token, TokenKind};
|
|||
use erg_type::constructors::{enum_t, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t};
|
||||
use erg_type::typaram::{OpKind, TyParam};
|
||||
use erg_type::value::ValueObj;
|
||||
use erg_type::{ConstSubr, HasType, Predicate, TyBound, Type, UserConstSubr, ValueArgs};
|
||||
use erg_type::{
|
||||
ConstSubr, HasType, ParamTy, Predicate, SubrKind, TyBound, Type, UserConstSubr, ValueArgs,
|
||||
};
|
||||
|
||||
use crate::context::instantiate::TyVarContext;
|
||||
use crate::context::{ClassDefType, Context};
|
||||
use crate::context::{ClassDefType, Context, RegistrationMode};
|
||||
use crate::error::{EvalError, EvalResult, TyCheckResult};
|
||||
|
||||
#[inline]
|
||||
|
@ -343,7 +345,7 @@ impl Context {
|
|||
fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult<ValueObj> {
|
||||
let mut attrs = vec![];
|
||||
// HACK: should avoid cloning
|
||||
let mut record_ctx = Context::instant(Str::ever("<unnamed record>"), 2, self.clone());
|
||||
let mut record_ctx = Context::instant(Str::ever("<unnamed record>"), 0, self.clone());
|
||||
for attr in record.attrs.iter() {
|
||||
let name = attr.sig.ident().map(|i| i.inspect());
|
||||
let elem = record_ctx.eval_const_block(&attr.body.block, name)?;
|
||||
|
@ -360,11 +362,63 @@ impl Context {
|
|||
}
|
||||
|
||||
fn eval_const_lambda(&self, lambda: &Lambda) -> EvalResult<ValueObj> {
|
||||
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
||||
for sig in lambda.sig.params.non_defaults.iter() {
|
||||
let t = self.instantiate_param_sig_t(sig, None, RegistrationMode::Normal)?;
|
||||
let pt = if let Some(name) = sig.inspect() {
|
||||
ParamTy::kw(name.clone(), t)
|
||||
} else {
|
||||
ParamTy::anonymous(t)
|
||||
};
|
||||
non_default_params.push(pt);
|
||||
}
|
||||
let var_params = if let Some(p) = lambda.sig.params.var_args.as_ref() {
|
||||
let t = self.instantiate_param_sig_t(p, None, RegistrationMode::Normal)?;
|
||||
let pt = if let Some(name) = p.inspect() {
|
||||
ParamTy::kw(name.clone(), t)
|
||||
} else {
|
||||
ParamTy::anonymous(t)
|
||||
};
|
||||
Some(pt)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
||||
for sig in lambda.sig.params.defaults.iter() {
|
||||
let t = self.instantiate_param_sig_t(sig, None, RegistrationMode::Normal)?;
|
||||
let pt = if let Some(name) = sig.inspect() {
|
||||
ParamTy::kw(name.clone(), t)
|
||||
} else {
|
||||
ParamTy::anonymous(t)
|
||||
};
|
||||
default_params.push(pt);
|
||||
}
|
||||
// HACK: should avoid cloning
|
||||
let mut lambda_ctx = Context::instant(Str::ever("<lambda>"), 0, self.clone());
|
||||
let return_t = lambda_ctx.eval_const_block(&lambda.body, None)?;
|
||||
// FIXME: lambda: i: Int -> Int
|
||||
// => sig_t: (i: Type) -> Type
|
||||
// => as_type: (i: Int) -> Int
|
||||
let sig_t = subr_t(
|
||||
SubrKind::from(lambda.op.kind),
|
||||
non_default_params.clone(),
|
||||
var_params.clone(),
|
||||
default_params.clone(),
|
||||
enum_t(set![return_t.clone()]),
|
||||
);
|
||||
let as_type = subr_t(
|
||||
SubrKind::from(lambda.op.kind),
|
||||
non_default_params,
|
||||
var_params,
|
||||
default_params,
|
||||
return_t.as_type().ok_or_else(|| todo!())?.into_typ(),
|
||||
);
|
||||
let subr = ConstSubr::User(UserConstSubr::new(
|
||||
Str::ever("<lambda>"),
|
||||
lambda.sig.params.clone(),
|
||||
lambda.body.clone(),
|
||||
Type::Uninited,
|
||||
sig_t,
|
||||
Some(as_type),
|
||||
));
|
||||
Ok(ValueObj::Subr(subr))
|
||||
}
|
||||
|
|
|
@ -7,24 +7,8 @@ use erg_common::color::{RED, RESET};
|
|||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||
use erg_type::constructors::{and, mono};
|
||||
use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj};
|
||||
use erg_type::Type;
|
||||
use erg_type::ValueArgs;
|
||||
|
||||
fn value_obj_to_t(value: ValueObj) -> TypeObj {
|
||||
match value {
|
||||
ValueObj::Type(t) => t,
|
||||
ValueObj::Record(rec) => TypeObj::Builtin(Type::Record(
|
||||
rec.into_iter()
|
||||
.map(|(k, v)| (k, value_obj_to_t(v).typ().clone()))
|
||||
.collect(),
|
||||
)),
|
||||
ValueObj::Subr(subr) => {
|
||||
todo!("{subr}")
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Requirement: Type, Impl := Type -> ClassType
|
||||
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
|
||||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
|
@ -36,9 +20,9 @@ pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult
|
|||
None,
|
||||
)
|
||||
})?;
|
||||
let require = value_obj_to_t(require);
|
||||
let require = require.as_type().unwrap();
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(value_obj_to_t);
|
||||
let impls = impls.map(|v| v.as_type().unwrap());
|
||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
|
||||
}
|
||||
|
@ -54,11 +38,11 @@ pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResu
|
|||
None,
|
||||
)
|
||||
})?;
|
||||
let sup = value_obj_to_t(sup);
|
||||
let sup = sup.as_type().unwrap();
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(value_obj_to_t);
|
||||
let impls = impls.map(|v| v.as_type().unwrap());
|
||||
let additional = args.remove_left_or_key("Additional");
|
||||
let additional = additional.map(value_obj_to_t);
|
||||
let additional = additional.map(|v| v.as_type().unwrap());
|
||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
Ok(ValueObj::gen_t(
|
||||
TypeKind::Subclass,
|
||||
|
@ -112,9 +96,9 @@ pub fn trait_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult
|
|||
None,
|
||||
)
|
||||
})?;
|
||||
let require = value_obj_to_t(require);
|
||||
let require = require.as_type().unwrap();
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(value_obj_to_t);
|
||||
let impls = impls.map(|v| v.as_type().unwrap());
|
||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
|
||||
}
|
||||
|
@ -130,11 +114,11 @@ pub fn subsume_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResu
|
|||
None,
|
||||
)
|
||||
})?;
|
||||
let sup = value_obj_to_t(sup);
|
||||
let sup = sup.as_type().unwrap();
|
||||
let impls = args.remove_left_or_key("Impl");
|
||||
let impls = impls.map(value_obj_to_t);
|
||||
let impls = impls.map(|v| v.as_type().unwrap());
|
||||
let additional = args.remove_left_or_key("Additional");
|
||||
let additional = additional.map(value_obj_to_t);
|
||||
let additional = additional.map(|v| v.as_type().unwrap());
|
||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
Ok(ValueObj::gen_t(
|
||||
TypeKind::Subtrait,
|
||||
|
|
|
@ -1486,7 +1486,7 @@ impl Context {
|
|||
vec![param_t("Impl", Type)],
|
||||
Class,
|
||||
);
|
||||
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t));
|
||||
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None));
|
||||
self.register_builtin_const("Class", ValueObj::Subr(class));
|
||||
let inherit_t = func(
|
||||
vec![param_t("Super", Class)],
|
||||
|
@ -1494,7 +1494,12 @@ impl Context {
|
|||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
||||
Class,
|
||||
);
|
||||
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t));
|
||||
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
"Inherit",
|
||||
inherit_func,
|
||||
inherit_t,
|
||||
None,
|
||||
));
|
||||
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
||||
let trait_t = func(
|
||||
vec![param_t("Requirement", Type)],
|
||||
|
@ -1502,7 +1507,7 @@ impl Context {
|
|||
vec![param_t("Impl", Type)],
|
||||
Trait,
|
||||
);
|
||||
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t));
|
||||
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None));
|
||||
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
|
||||
let subsume_t = func(
|
||||
vec![param_t("Super", Trait)],
|
||||
|
@ -1510,7 +1515,12 @@ impl Context {
|
|||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
||||
Trait,
|
||||
);
|
||||
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new("Subsume", subsume_func, subsume_t));
|
||||
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
"Subsume",
|
||||
subsume_func,
|
||||
subsume_t,
|
||||
None,
|
||||
));
|
||||
self.register_builtin_const("Subsume", ValueObj::Subr(subsume));
|
||||
// decorators
|
||||
let inheritable_t = func1(Class, Class);
|
||||
|
@ -1518,6 +1528,7 @@ impl Context {
|
|||
"Inheritable",
|
||||
inheritable_func,
|
||||
inheritable_t,
|
||||
None,
|
||||
));
|
||||
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
||||
}
|
||||
|
|
|
@ -1259,6 +1259,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
/// FIXME: if trait, returns a freevar
|
||||
pub(crate) fn rec_get_self_t(&self) -> Option<Type> {
|
||||
if self.kind.is_method_def() || self.kind.is_type() {
|
||||
// TODO: poly type
|
||||
|
|
|
@ -628,11 +628,7 @@ impl Context {
|
|||
.collect();
|
||||
let return_t = self.instantiate_typespec(&subr.return_t, mode)?;
|
||||
Ok(subr_t(
|
||||
if subr.arrow.is(TokenKind::FuncArrow) {
|
||||
SubrKind::Func
|
||||
} else {
|
||||
SubrKind::Proc
|
||||
},
|
||||
SubrKind::from(subr.arrow.kind),
|
||||
non_defaults,
|
||||
var_args,
|
||||
defaults,
|
||||
|
|
|
@ -649,6 +649,28 @@ impl Context {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
TypeKind::Trait => {
|
||||
if gen.t.is_monomorphic() {
|
||||
let ctx = Self::mono_trait(gen.t.name(), self.level);
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
TypeKind::Subtrait => {
|
||||
if gen.t.is_monomorphic() {
|
||||
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
||||
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx = Self::mono_trait(gen.t.name(), self.level);
|
||||
for sup in super_classes.into_iter() {
|
||||
let (_, sup_ctx) = self.get_nominal_type_ctx(&sup).unwrap();
|
||||
ctx.register_superclass(sup, sup_ctx);
|
||||
}
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
other => todo!("{other:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1027,6 +1027,9 @@ impl Context {
|
|||
(Type::MonoProj { .. }, _) => todo!(),
|
||||
(_, Type::MonoProj { .. }) => todo!(),
|
||||
(Refinement(_), Refinement(_)) => todo!(),
|
||||
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
|
||||
// TODO Tuple2, ...
|
||||
(Type::Poly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()),
|
||||
_ => todo!("{maybe_sub} can be a subtype of {maybe_sup}, but failed to semi-unify (or existential types are not supported)"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,7 +562,14 @@ impl ASTLowerer {
|
|||
name,
|
||||
));
|
||||
}
|
||||
self.ctx.grow(name, ContextKind::Instant, def.sig.vis())?;
|
||||
let kind = if def.is_class_def() {
|
||||
ContextKind::Class
|
||||
} else if def.is_trait_def() {
|
||||
ContextKind::Trait
|
||||
} else {
|
||||
ContextKind::Instant
|
||||
};
|
||||
self.ctx.grow(name, kind, def.sig.vis())?;
|
||||
let res = match def.sig {
|
||||
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),
|
||||
ast::Signature::Var(sig) => self.lower_var_def(sig, def.body),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue