WIP: impl Trait

This commit is contained in:
Shunsuke Shibayama 2022-09-17 01:42:49 +09:00
parent 346d00fcd8
commit aa527dcbc8
11 changed files with 227 additions and 51 deletions

View file

@ -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))
}

View file

@ -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,

View file

@ -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));
}

View file

@ -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

View file

@ -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,

View file

@ -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:?}"),
}
}

View file

@ -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)"),
}
}

View file

@ -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),