feat: ref/ref! with type specification

This commit is contained in:
Shunsuke Shibayama 2024-12-27 02:46:58 +09:00
parent 6d2c399d67
commit 1fe189e4d3
4 changed files with 65 additions and 15 deletions

View file

@ -466,7 +466,7 @@ impl Context {
free_var(level, Constraint::new_type_of(Type)) free_var(level, Constraint::new_type_of(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 {
match self.instantiate_typespec_full( let t = match self.instantiate_typespec_full(
&spec_with_op.t_spec, &spec_with_op.t_spec,
opt_decl_t, opt_decl_t,
tmp_tv_cache, tmp_tv_cache,
@ -481,6 +481,11 @@ impl Context {
} }
t t
} }
};
match &sig.pat {
ast::ParamPattern::Ref(_) => ref_(t),
ast::ParamPattern::RefMut(_) => ref_mut(t, None),
_ => t,
} }
} else { } else {
match &sig.pat { match &sig.pat {

View file

@ -540,7 +540,8 @@ impl Context {
kind, kind,
false, false,
) { ) {
Ok(ty) => (ty, TyCheckErrors::empty()), Ok(ty @ Type::Ref(_)) => (ty, TyCheckErrors::empty()),
Ok(ty) => (ty.into_ref(), TyCheckErrors::empty()),
Err((ty, errs)) => (ty, errs), Err((ty, errs)) => (ty, errs),
}; };
if &name.inspect()[..] == "self" { if &name.inspect()[..] == "self" {
@ -592,7 +593,8 @@ impl Context {
kind, kind,
false, false,
) { ) {
Ok(ty) => (ty, TyCheckErrors::empty()), Ok(ty @ Type::RefMut { .. }) => (ty, TyCheckErrors::empty()),
Ok(ty) => (ty.into_ref_mut(None), TyCheckErrors::empty()),
Err((ty, errs)) => (ty, errs), Err((ty, errs)) => (ty, errs),
}; };
if &name.inspect()[..] == "self" { if &name.inspect()[..] == "self" {

View file

@ -521,27 +521,63 @@ impl Parser {
Expr::UnaryOp(unary) => match unary.op.kind { Expr::UnaryOp(unary) => match unary.op.kind {
TokenKind::RefOp => { TokenKind::RefOp => {
let var = unary.args.into_iter().next().unwrap(); let var = unary.args.into_iter().next().unwrap();
let Expr::Accessor(Accessor::Ident(var)) = *var else { let (var, t_spec) = match *var {
let err = ParseError::simple_syntax_error(line!() as usize, var.loc()); Expr::Accessor(Accessor::Ident(var)) => (var, None),
self.errs.push(err); Expr::TypeAscription(tasc) => {
debug_exit_info!(self); let var = match *tasc.expr {
return Err(()); Expr::Accessor(Accessor::Ident(var)) => var,
_ => {
let err = ParseError::simple_syntax_error(
line!() as usize,
tasc.loc(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
};
(var, Some(tasc.t_spec))
}
_ => {
let err = ParseError::simple_syntax_error(line!() as usize, var.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}; };
let pat = ParamPattern::Ref(var.name); let pat = ParamPattern::Ref(var.name);
let param = NonDefaultParamSignature::new(pat, None); let param = NonDefaultParamSignature::new(pat, t_spec);
debug_exit_info!(self); debug_exit_info!(self);
Ok(param) Ok(param)
} }
TokenKind::RefMutOp => { TokenKind::RefMutOp => {
let var = unary.args.into_iter().next().unwrap(); let var = unary.args.into_iter().next().unwrap();
let Expr::Accessor(Accessor::Ident(var)) = *var else { let (var, t_spec) = match *var {
let err = ParseError::simple_syntax_error(line!() as usize, var.loc()); Expr::Accessor(Accessor::Ident(var)) => (var, None),
self.errs.push(err); Expr::TypeAscription(tasc) => {
debug_exit_info!(self); let var = match *tasc.expr {
return Err(()); Expr::Accessor(Accessor::Ident(var)) => var,
_ => {
let err = ParseError::simple_syntax_error(
line!() as usize,
tasc.loc(),
);
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
};
(var, Some(tasc.t_spec))
}
_ => {
let err = ParseError::simple_syntax_error(line!() as usize, var.loc());
self.errs.push(err);
debug_exit_info!(self);
return Err(());
}
}; };
let pat = ParamPattern::RefMut(var.name); let pat = ParamPattern::RefMut(var.name);
let param = NonDefaultParamSignature::new(pat, None); let param = NonDefaultParamSignature::new(pat, t_spec);
debug_exit_info!(self); debug_exit_info!(self);
Ok(param) Ok(param)
} }

View file

@ -17,3 +17,10 @@ assert ss == "abc"
discard ss.remove! 0 discard ss.remove! 0
assert ss == "bc" assert ss == "bc"
assert ss.capitalize() == "Bc" assert ss.capitalize() == "Bc"
write1!(ref! x: Nat!) =
x.update! _ -> 1
n = !0
write1! n
assert n == 1