mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
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:
@@ -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}`"))) }
|
||||
}
|
||||
|
||||
@@ -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")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user