if conditions are evaluated lazily

This commit is contained in:
ConnorSkees 2020-06-08 00:01:14 -04:00
parent 365325729a
commit 632d649fdb
3 changed files with 17 additions and 16 deletions

View File

@ -22,12 +22,12 @@ pub(crate) struct If {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct Branch { pub(crate) struct Branch {
pub cond: Spanned<Value>, pub cond: Vec<Token>,
pub toks: Vec<Token>, pub toks: Vec<Token>,
} }
impl Branch { impl Branch {
pub fn new(cond: Spanned<Value>, toks: Vec<Token>) -> Branch { pub fn new(cond: Vec<Token>, toks: Vec<Token>) -> Branch {
Branch { cond, toks } Branch { cond, toks }
} }
} }
@ -35,8 +35,6 @@ impl Branch {
impl If { impl If {
pub fn from_tokens<I: Iterator<Item = Token>>( pub fn from_tokens<I: Iterator<Item = Token>>(
toks: &mut PeekMoreIterator<I>, toks: &mut PeekMoreIterator<I>,
scope: &Scope,
super_selector: &Selector,
span_before: Span, span_before: Span,
) -> SassResult<If> { ) -> SassResult<If> {
devour_whitespace_or_comment(toks)?; devour_whitespace_or_comment(toks)?;
@ -49,7 +47,6 @@ impl If {
Some(t) => t.pos, Some(t) => t.pos,
None => return Err(("Expected expression.", span_before).into()), None => return Err(("Expected expression.", span_before).into()),
}; };
let init_cond = Value::from_vec(init_cond_toks, scope, super_selector, span_before)?;
devour_whitespace_or_comment(toks)?; devour_whitespace_or_comment(toks)?;
let mut init_toks = read_until_closing_curly_brace(toks)?; let mut init_toks = read_until_closing_curly_brace(toks)?;
if let Some(tok) = toks.next() { if let Some(tok) = toks.next() {
@ -59,7 +56,7 @@ impl If {
} }
devour_whitespace(toks); devour_whitespace(toks);
branches.push(Branch::new(init_cond, init_toks)); branches.push(Branch::new(init_cond_toks, init_toks));
let mut else_ = Vec::new(); let mut else_ = Vec::new();
@ -80,13 +77,8 @@ impl If {
devour_whitespace(toks); devour_whitespace(toks);
match tok.kind.to_ascii_lowercase() { match tok.kind.to_ascii_lowercase() {
'i' if toks.next().unwrap().kind.to_ascii_lowercase() == 'f' => { 'i' if toks.next().unwrap().kind.to_ascii_lowercase() == 'f' => {
let pos = toks.next().unwrap().pos; toks.next();
let cond = Value::from_vec( let cond = read_until_open_curly_brace(toks)?;
read_until_open_curly_brace(toks)?,
scope,
super_selector,
pos,
)?;
toks.next(); toks.next();
devour_whitespace(toks); devour_whitespace(toks);
branches.push(Branch::new(cond, read_until_closing_curly_brace(toks)?)); branches.push(Branch::new(cond, read_until_closing_curly_brace(toks)?));
@ -121,7 +113,9 @@ impl If {
let mut toks = Vec::new(); let mut toks = Vec::new();
let mut found_true = false; let mut found_true = false;
for branch in self.branches { for branch in self.branches {
if branch.cond.node.is_true(branch.cond.span)? { let span_before = branch.cond.first().unwrap().pos;
let cond = Value::from_vec(branch.cond, scope, super_selector, span_before)?;
if cond.node.is_true(cond.span)? {
toks = branch.toks; toks = branch.toks;
found_true = true; found_true = true;
break; break;

View File

@ -219,7 +219,7 @@ impl AtRule {
span: kind_span, span: kind_span,
}, },
AtRuleKind::If => Spanned { AtRuleKind::If => Spanned {
node: AtRule::If(If::from_tokens(toks, scope, super_selector, kind_span)?), node: AtRule::If(If::from_tokens(toks, kind_span)?),
span: kind_span, span: kind_span,
}, },
AtRuleKind::For => Spanned { AtRuleKind::For => Spanned {

View File

@ -125,9 +125,16 @@ error!(
"@if foo {", "Error: expected \"}\"." "@if foo {", "Error: expected \"}\"."
); );
error!( error!(
condition_is_evaluated_eagerly, first_condition_error,
"@if 1 + 1 =s {\n}", "Error: expected \"=\"." "@if 1 + 1 =s {\n}", "Error: expected \"=\"."
); );
test!(
conditions_evaluated_lazily,
"$p: null;
@if $p==null {}
@else if not comparable($p, 0) {}",
""
);
error!( error!(
nothing_after_escape, nothing_after_escape,
"@if \\", "Error: Expected expression." "@if \\", "Error: Expected expression."