WIP: trait implementation

This commit is contained in:
Shunsuke Shibayama 2022-09-17 22:26:56 +09:00
parent abb6bcd320
commit e4eed24a42
3 changed files with 86 additions and 32 deletions

View file

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

View file

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

View file

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