Merge #1038: Keep literal true/false distinct from variables named true/false (@Silvertree2010)

# Conflicts:
#	crates/doc/src/proto_expr_parse_tests.rs
This commit is contained in:
bflatastic
2026-10-24 09:23:15 +07:00
2 changed files with 30 additions and 5 deletions
+8 -5
View File
@@ -459,16 +459,19 @@ impl Parser<'_> {
if self.at_keyword("mode") && self.next_after(4) == Some('(') {
return self.mode_of();
}
if let Some((id, n)) = self.variable_here() {
self.i += n;
return self.in_mode(id);
}
let var = self.variable_here();
// A bare `true`/`false` is the literal, also when a variable has that name (it reads
// as `{true}`); longer names that start with it ("true value") stay variables.
for (word, v) in [("true", true), ("false", false)] {
if self.at_keyword(word) {
if self.at_keyword(word) && var.as_ref().is_none_or(|(_, n)| *n <= word.len()) {
self.i += word.len();
return Ok(Expr::Value(VariableValue::Boolean(v)));
}
}
if let Some((id, n)) = var {
self.i += n;
return self.in_mode(id);
}
let word: String = self.s.iter().skip(self.i).take_while(|c| ident(**c)).collect();
if word.is_empty() { Err(self.err(format!("Unexpected {c}"))) } else { Err(self.err(format!("No variable `{word}`"))) }
}
+22
View File
@@ -219,3 +219,25 @@ fn not_of_a_variable_reads_back_when_a_name_starts_with_not() {
}
assert_eq!(Expr::op(Not, vec![Expr::var("b")]).display(&vars()), "not b-name", "plain names stay bare");
}
#[test]
fn literal_true_false_survive_variables_named_true_false() {
use ExprOp::*;
let lit = |x: bool| Expr::Value(VariableValue::Boolean(x));
for name in ["true", "false", "TRUE"] {
let mut v = vars();
if let Some(var) = v.variables.iter_mut().find(|x| x.id == "b") {
var.name = name.into();
}
for e in [
Expr::op(Equals, vec![Expr::var("b"), lit(true)]),
Expr::op(Equals, vec![Expr::var("b"), lit(false)]),
Expr::op(Not, vec![lit(false)]),
Expr::var("b"),
] {
let shown = e.display(&v);
assert_eq!(Expr::parse(&shown, &v), Ok(e.clone()), "{name:?} shown as {shown:?}");
}
assert_eq!(Expr::parse(&format!("{{{name}}}"), &v), Ok(Expr::var("b")));
}
}