mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat: ref/ref!
with type specification
This commit is contained in:
parent
6d2c399d67
commit
1fe189e4d3
4 changed files with 65 additions and 15 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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" {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue