mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
WIP: trait implementation
This commit is contained in:
parent
abb6bcd320
commit
e4eed24a42
3 changed files with 86 additions and 32 deletions
|
@ -373,7 +373,7 @@ impl Context {
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
let spec_t = if let Some(s) = t_spec {
|
let spec_t = if let Some(s) = t_spec {
|
||||||
self.instantiate_typespec(s, &mut None, mode)?
|
self.instantiate_typespec(s, None, &mut None, mode)?
|
||||||
} else {
|
} else {
|
||||||
free_var(self.level, Constraint::new_type_of(Type))
|
free_var(self.level, Constraint::new_type_of(Type))
|
||||||
};
|
};
|
||||||
|
@ -388,23 +388,34 @@ impl Context {
|
||||||
sig: &ast::SubrSignature,
|
sig: &ast::SubrSignature,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
|
let opt_decl_sig_t = self
|
||||||
|
.rec_get_var_t(&sig.ident, &self.name)
|
||||||
|
.ok()
|
||||||
|
.map(|t| enum_unwrap!(t, Type::Subr));
|
||||||
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
|
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
|
||||||
let mut tv_ctx = TyVarContext::new(self.level, bounds, self);
|
let mut tv_ctx = TyVarContext::new(self.level, bounds, self);
|
||||||
let non_defaults = sig
|
let non_defaults = sig
|
||||||
.params
|
.params
|
||||||
.non_defaults
|
.non_defaults
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| {
|
.enumerate()
|
||||||
|
.map(|(n, p)| {
|
||||||
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|subr| subr.non_default_params.get(n));
|
||||||
ParamTy::pos(
|
ParamTy::pos(
|
||||||
p.inspect().cloned(),
|
p.inspect().cloned(),
|
||||||
self.instantiate_param_sig_t(p, None, &mut Some(&mut tv_ctx), mode)
|
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
|
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
|
||||||
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|subr| subr.var_params.as_ref().map(|v| v.as_ref()));
|
||||||
let va_t =
|
let va_t =
|
||||||
self.instantiate_param_sig_t(var_args, None, &mut Some(&mut tv_ctx), mode)?;
|
self.instantiate_param_sig_t(var_args, opt_decl_t, &mut Some(&mut tv_ctx), mode)?;
|
||||||
Some(ParamTy::pos(var_args.inspect().cloned(), va_t))
|
Some(ParamTy::pos(var_args.inspect().cloned(), va_t))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -413,16 +424,23 @@ impl Context {
|
||||||
.params
|
.params
|
||||||
.defaults
|
.defaults
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| {
|
.enumerate()
|
||||||
|
.map(|(n, p)| {
|
||||||
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|subr| subr.default_params.get(n));
|
||||||
ParamTy::kw(
|
ParamTy::kw(
|
||||||
p.inspect().unwrap().clone(),
|
p.inspect().unwrap().clone(),
|
||||||
self.instantiate_param_sig_t(p, None, &mut Some(&mut tv_ctx), mode)
|
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
||||||
self.instantiate_typespec(s, &mut Some(&mut tv_ctx), mode)?
|
let opt_decl_t = opt_decl_sig_t
|
||||||
|
.as_ref()
|
||||||
|
.map(|subr| ParamTy::anonymous(subr.return_t.as_ref().clone()));
|
||||||
|
self.instantiate_typespec(s, opt_decl_t.as_ref(), &mut Some(&mut tv_ctx), mode)?
|
||||||
} else {
|
} else {
|
||||||
// preregisterならouter scopeで型宣言(see inference.md)
|
// preregisterならouter scopeで型宣言(see inference.md)
|
||||||
let level = if mode == PreRegister {
|
let level = if mode == PreRegister {
|
||||||
|
@ -448,7 +466,7 @@ impl Context {
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
|
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
|
||||||
self.instantiate_typespec(&spec_with_op.t_spec, tv_ctx, mode)?
|
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tv_ctx, mode)?
|
||||||
} else {
|
} else {
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::ParamPattern::Lit(lit) => enum_t(set![eval_lit(lit)]),
|
ast::ParamPattern::Lit(lit) => enum_t(set![eval_lit(lit)]),
|
||||||
|
@ -478,10 +496,13 @@ impl Context {
|
||||||
pub(crate) fn instantiate_predecl_t(
|
pub(crate) fn instantiate_predecl_t(
|
||||||
&self,
|
&self,
|
||||||
predecl: &PreDeclTypeSpec,
|
predecl: &PreDeclTypeSpec,
|
||||||
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tv_ctx: &mut Option<&mut TyVarContext>,
|
tv_ctx: &mut Option<&mut TyVarContext>,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match predecl {
|
match predecl {
|
||||||
ast::PreDeclTypeSpec::Simple(simple) => self.instantiate_simple_t(simple, tv_ctx),
|
ast::PreDeclTypeSpec::Simple(simple) => {
|
||||||
|
self.instantiate_simple_t(simple, opt_decl_t, tv_ctx)
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,6 +510,7 @@ impl Context {
|
||||||
pub(crate) fn instantiate_simple_t(
|
pub(crate) fn instantiate_simple_t(
|
||||||
&self,
|
&self,
|
||||||
simple: &SimpleTypeSpec,
|
simple: &SimpleTypeSpec,
|
||||||
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tv_ctx: &mut Option<&mut TyVarContext>,
|
tv_ctx: &mut Option<&mut TyVarContext>,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match &simple.name.inspect()[..] {
|
match &simple.name.inspect()[..] {
|
||||||
|
@ -519,8 +541,21 @@ impl Context {
|
||||||
other if simple.args.is_empty() => {
|
other if simple.args.is_empty() => {
|
||||||
if let Some(tv_ctx) = tv_ctx {
|
if let Some(tv_ctx) = tv_ctx {
|
||||||
Self::instantiate_t(mono_q(Str::rc(other)), tv_ctx, simple.loc())
|
Self::instantiate_t(mono_q(Str::rc(other)), tv_ctx, simple.loc())
|
||||||
|
} else if let Some(decl_t) = opt_decl_t {
|
||||||
|
Ok(decl_t.typ().clone())
|
||||||
} else {
|
} else {
|
||||||
Ok(mono(Str::rc(other)))
|
let typ = mono(Str::rc(other));
|
||||||
|
if self.get_nominal_type_ctx(&typ).is_some() {
|
||||||
|
Ok(typ)
|
||||||
|
} else {
|
||||||
|
Err(TyCheckError::no_var_error(
|
||||||
|
line!() as usize,
|
||||||
|
simple.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
other,
|
||||||
|
self.get_similar_name(other),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
|
@ -560,10 +595,11 @@ impl Context {
|
||||||
fn instantiate_func_param_spec(
|
fn instantiate_func_param_spec(
|
||||||
&self,
|
&self,
|
||||||
p: &ParamTySpec,
|
p: &ParamTySpec,
|
||||||
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tv_ctx: &mut Option<&mut TyVarContext>,
|
tv_ctx: &mut Option<&mut TyVarContext>,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<ParamTy> {
|
) -> TyCheckResult<ParamTy> {
|
||||||
let t = self.instantiate_typespec(&p.ty, tv_ctx, mode)?;
|
let t = self.instantiate_typespec(&p.ty, opt_decl_t, tv_ctx, mode)?;
|
||||||
Ok(ParamTy::pos(
|
Ok(ParamTy::pos(
|
||||||
p.name.as_ref().map(|t| t.inspect().to_owned()),
|
p.name.as_ref().map(|t| t.inspect().to_owned()),
|
||||||
t,
|
t,
|
||||||
|
@ -573,29 +609,33 @@ impl Context {
|
||||||
pub(crate) fn instantiate_typespec(
|
pub(crate) fn instantiate_typespec(
|
||||||
&self,
|
&self,
|
||||||
spec: &TypeSpec,
|
spec: &TypeSpec,
|
||||||
|
opt_decl_t: Option<&ParamTy>,
|
||||||
tv_ctx: &mut Option<&mut TyVarContext>,
|
tv_ctx: &mut Option<&mut TyVarContext>,
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
match spec {
|
match spec {
|
||||||
TypeSpec::PreDeclTy(predecl) => self.instantiate_predecl_t(predecl, tv_ctx),
|
TypeSpec::PreDeclTy(predecl) => self.instantiate_predecl_t(predecl, opt_decl_t, tv_ctx),
|
||||||
// TODO: Flatten
|
// TODO: Flatten
|
||||||
TypeSpec::And(lhs, rhs) => Ok(and(
|
TypeSpec::And(lhs, rhs) => Ok(and(
|
||||||
self.instantiate_typespec(lhs, tv_ctx, mode)?,
|
self.instantiate_typespec(lhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(rhs, tv_ctx, mode)?,
|
self.instantiate_typespec(rhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Not(lhs, rhs) => Ok(not(
|
TypeSpec::Not(lhs, rhs) => Ok(not(
|
||||||
self.instantiate_typespec(lhs, tv_ctx, mode)?,
|
self.instantiate_typespec(lhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(rhs, tv_ctx, mode)?,
|
self.instantiate_typespec(rhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Or(lhs, rhs) => Ok(or(
|
TypeSpec::Or(lhs, rhs) => Ok(or(
|
||||||
self.instantiate_typespec(lhs, tv_ctx, mode)?,
|
self.instantiate_typespec(lhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
self.instantiate_typespec(rhs, tv_ctx, mode)?,
|
self.instantiate_typespec(rhs, opt_decl_t, tv_ctx, mode)?,
|
||||||
)),
|
)),
|
||||||
TypeSpec::Array { .. } => todo!(),
|
TypeSpec::Array { .. } => todo!(),
|
||||||
// FIXME: unwrap
|
// FIXME: unwrap
|
||||||
TypeSpec::Tuple(tys) => Ok(tuple(
|
TypeSpec::Tuple(tys) => Ok(tuple(
|
||||||
tys.iter()
|
tys.iter()
|
||||||
.map(|spec| self.instantiate_typespec(spec, tv_ctx, mode).unwrap())
|
.map(|spec| {
|
||||||
|
self.instantiate_typespec(spec, opt_decl_t, tv_ctx, mode)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
// TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる
|
// TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる
|
||||||
|
@ -629,19 +669,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
TypeSpec::Subr(subr) => {
|
TypeSpec::Subr(subr) => {
|
||||||
let non_defaults = try_map_mut(subr.non_defaults.iter(), |p| {
|
let non_defaults = try_map_mut(subr.non_defaults.iter(), |p| {
|
||||||
self.instantiate_func_param_spec(p, tv_ctx, mode)
|
self.instantiate_func_param_spec(p, opt_decl_t, tv_ctx, mode)
|
||||||
})?;
|
})?;
|
||||||
let var_args = subr
|
let var_args = subr
|
||||||
.var_args
|
.var_args
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| self.instantiate_func_param_spec(p, tv_ctx, mode))
|
.map(|p| self.instantiate_func_param_spec(p, opt_decl_t, tv_ctx, mode))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let defaults = try_map_mut(subr.defaults.iter(), |p| {
|
let defaults = try_map_mut(subr.defaults.iter(), |p| {
|
||||||
self.instantiate_func_param_spec(p, tv_ctx, mode)
|
self.instantiate_func_param_spec(p, opt_decl_t, tv_ctx, mode)
|
||||||
})?
|
})?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
let return_t = self.instantiate_typespec(&subr.return_t, tv_ctx, mode)?;
|
let return_t =
|
||||||
|
self.instantiate_typespec(&subr.return_t, opt_decl_t, tv_ctx, mode)?;
|
||||||
Ok(subr_t(
|
Ok(subr_t(
|
||||||
SubrKind::from(subr.arrow.kind),
|
SubrKind::from(subr.arrow.kind),
|
||||||
non_defaults,
|
non_defaults,
|
||||||
|
@ -668,12 +709,12 @@ impl Context {
|
||||||
let bound = match spec.op.kind {
|
let bound = match spec.op.kind {
|
||||||
TokenKind::SubtypeOf => TyBound::subtype_of(
|
TokenKind::SubtypeOf => TyBound::subtype_of(
|
||||||
mono_q(lhs.inspect().clone()),
|
mono_q(lhs.inspect().clone()),
|
||||||
self.instantiate_typespec(&spec.t_spec, &mut None, mode)?,
|
self.instantiate_typespec(&spec.t_spec, None, &mut None, mode)?,
|
||||||
),
|
),
|
||||||
TokenKind::SupertypeOf => todo!(),
|
TokenKind::SupertypeOf => todo!(),
|
||||||
TokenKind::Colon => TyBound::instance(
|
TokenKind::Colon => TyBound::instance(
|
||||||
lhs.inspect().clone(),
|
lhs.inspect().clone(),
|
||||||
self.instantiate_typespec(&spec.t_spec, &mut None, mode)?,
|
self.instantiate_typespec(&spec.t_spec, None, &mut None, mode)?,
|
||||||
),
|
),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -466,8 +466,12 @@ impl Context {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(spec) = sig.return_t_spec.as_ref() {
|
if let Some(spec) = sig.return_t_spec.as_ref() {
|
||||||
let spec_t =
|
let spec_t = self.instantiate_typespec(
|
||||||
self.instantiate_typespec(spec, &mut Some(&mut tv_ctx), PreRegister)?;
|
spec,
|
||||||
|
None,
|
||||||
|
&mut Some(&mut tv_ctx),
|
||||||
|
PreRegister,
|
||||||
|
)?;
|
||||||
self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?;
|
self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?;
|
||||||
}
|
}
|
||||||
self.register_gen_const(def.sig.ident().unwrap(), obj)?;
|
self.register_gen_const(def.sig.ident().unwrap(), obj)?;
|
||||||
|
@ -483,7 +487,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(spec) = sig.t_spec.as_ref() {
|
if let Some(spec) = sig.t_spec.as_ref() {
|
||||||
let spec_t = self.instantiate_typespec(spec, &mut None, PreRegister)?;
|
let spec_t = self.instantiate_typespec(spec, None, &mut None, PreRegister)?;
|
||||||
self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?;
|
self.sub_unify(&const_t, &spec_t, Some(def.body.loc()), None, None)?;
|
||||||
}
|
}
|
||||||
self.register_gen_const(sig.ident().unwrap(), obj)?;
|
self.register_gen_const(sig.ident().unwrap(), obj)?;
|
||||||
|
|
|
@ -696,6 +696,7 @@ impl ASTLowerer {
|
||||||
ast::Expr::TypeAsc(tasc) => (
|
ast::Expr::TypeAsc(tasc) => (
|
||||||
self.ctx.instantiate_typespec(
|
self.ctx.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec,
|
||||||
|
None,
|
||||||
&mut None,
|
&mut None,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
)?,
|
)?,
|
||||||
|
@ -704,14 +705,22 @@ impl ASTLowerer {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
self.ctx
|
self.ctx.instantiate_typespec(
|
||||||
.instantiate_typespec(spec, &mut None, RegistrationMode::Normal)?,
|
spec,
|
||||||
|
None,
|
||||||
|
&mut None,
|
||||||
|
RegistrationMode::Normal,
|
||||||
|
)?,
|
||||||
Some((impl_trait, loc)),
|
Some((impl_trait, loc)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
other => (
|
other => (
|
||||||
self.ctx
|
self.ctx.instantiate_typespec(
|
||||||
.instantiate_typespec(other, &mut None, RegistrationMode::Normal)?,
|
other,
|
||||||
|
None,
|
||||||
|
&mut None,
|
||||||
|
RegistrationMode::Normal,
|
||||||
|
)?,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue