Add support for mutable variables

This commit is contained in:
Guillaume Gomez 2025-05-25 15:46:44 +02:00 committed by René Kijewski
parent c40e828f03
commit 9ee2afecfa
4 changed files with 20 additions and 5 deletions

View File

@ -961,6 +961,9 @@ impl<'a> Generator<'a, '_> {
let Some(val) = &l.val else { let Some(val) = &l.val else {
self.write_buf_writable(ctx, buf)?; self.write_buf_writable(ctx, buf)?;
buf.write("let "); buf.write("let ");
if l.is_mutable {
buf.write("mut ");
}
self.visit_target(buf, false, true, &l.var); self.visit_target(buf, false, true, &l.var);
buf.write(';'); buf.write(';');
return Ok(()); return Ok(());
@ -980,6 +983,9 @@ impl<'a> Generator<'a, '_> {
|| matches!(&l.var, Target::Name(name) if self.locals.get(name).is_none()) || matches!(&l.var, Target::Name(name) if self.locals.get(name).is_none())
{ {
buf.write("let "); buf.write("let ");
if l.is_mutable {
buf.write("mut ");
}
} }
self.visit_target(buf, true, true, &l.var); self.visit_target(buf, true, true, &l.var);

View File

@ -1204,6 +1204,7 @@ pub struct Let<'a> {
pub ws: Ws, pub ws: Ws,
pub var: Target<'a>, pub var: Target<'a>,
pub val: Option<WithSpan<'a, Expr<'a>>>, pub val: Option<WithSpan<'a, Expr<'a>>>,
pub is_mutable: bool,
} }
impl<'a> Let<'a> { impl<'a> Let<'a> {
@ -1212,6 +1213,7 @@ impl<'a> Let<'a> {
let mut p = ( let mut p = (
opt(Whitespace::parse), opt(Whitespace::parse),
ws(alt((keyword("let"), keyword("set")))), ws(alt((keyword("let"), keyword("set")))),
ws(opt(keyword("mut"))),
cut_node( cut_node(
Some("let"), Some("let"),
( (
@ -1224,7 +1226,7 @@ impl<'a> Let<'a> {
), ),
), ),
); );
let (pws, _, (var, val, nws)) = p.parse_next(i)?; let (pws, _, is_mut, (var, val, nws)) = p.parse_next(i)?;
if val.is_none() { if val.is_none() {
let kind = match &var { let kind = match &var {
Target::Name(_) => None, Target::Name(_) => None,
@ -1250,12 +1252,19 @@ impl<'a> Let<'a> {
))); )));
} }
} }
if is_mut.is_some() && !matches!(var, Target::Name(_)) {
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
"you can only use the `mut` keyword with a variable name",
start,
)));
}
Ok(WithSpan::new( Ok(WithSpan::new(
Let { Let {
ws: Ws(pws, nws), ws: Ws(pws, nws),
var, var,
val, val,
is_mutable: is_mut.is_some(),
}, },
start, start,
)) ))

View File

@ -45,7 +45,7 @@ test_kw!(Macro "{% let macro %}");
test_kw!(Match "{% let match %}"); test_kw!(Match "{% let match %}");
test_kw!(Mod "{% let mod %}"); test_kw!(Mod "{% let mod %}");
test_kw!(Move "{% let move %}"); test_kw!(Move "{% let move %}");
test_kw!(Mut "{% let mut %}"); test_kw!(Mut "{% let mut mut %}");
test_kw!(Override "{% let override %}"); test_kw!(Override "{% let override %}");
test_kw!(Priv "{% let priv %}"); test_kw!(Priv "{% let priv %}");
test_kw!(Pub "{% let pub %}"); test_kw!(Pub "{% let pub %}");

View File

@ -247,12 +247,12 @@ error: cannot use `move` as a name: it is a rust keyword
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: cannot use `mut` as a name: it is a rust keyword error: cannot use `mut` as a name: it is a rust keyword
--> <source attribute>:1:7 --> <source attribute>:1:11
"mut %}" "mut %}"
--> tests/ui/assign-to-askama.rs:48:14 --> tests/ui/assign-to-askama.rs:48:14
| |
48 | test_kw!(Mut "{% let mut %}"); 48 | test_kw!(Mut "{% let mut mut %}");
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: cannot use `override` as a name: it is a rust keyword error: cannot use `override` as a name: it is a rust keyword
--> <source attribute>:1:7 --> <source attribute>:1:7