use codemap::{Span, Spanned}; use peekmore::{PeekMore, PeekMoreIterator}; use super::{eat_stmts, AtRule}; use crate::error::SassResult; use crate::scope::Scope; use crate::selector::Selector; use crate::utils::{ devour_whitespace, read_until_closing_curly_brace, read_until_open_curly_brace, }; use crate::value::Value; use crate::{Stmt, Token}; #[derive(Debug, Clone)] pub(crate) struct While { pub cond: Vec, pub body: Vec, } impl While { pub fn ruleset_eval( self, scope: &mut Scope, super_selector: &Selector, at_root: bool, ) -> SassResult>> { let mut stmts = Vec::new(); let mut val = Value::from_vec(self.cond.clone(), scope, super_selector)?; let scope = &mut scope.clone(); while val.node.is_true(val.span)? { for stmt in eat_stmts( &mut self.body.clone().into_iter().peekmore(), scope, super_selector, at_root, )? { match stmt.node { Stmt::AtRule(AtRule::For(f)) => { stmts.extend(f.ruleset_eval(scope, super_selector)?) } Stmt::AtRule(AtRule::While(w)) => { stmts.extend(w.ruleset_eval(scope, super_selector, at_root)?) } Stmt::AtRule(AtRule::Include(s)) | Stmt::AtRule(AtRule::Each(s)) => { stmts.extend(s) } Stmt::AtRule(AtRule::If(i)) => stmts.extend(i.eval(scope, super_selector)?), _ => stmts.push(stmt), } } val = Value::from_vec(self.cond.clone(), scope, super_selector)?; } Ok(stmts) } } pub(crate) fn parse_while>( toks: &mut PeekMoreIterator, span: Span, ) -> SassResult> { devour_whitespace(toks); let cond = read_until_open_curly_brace(toks); if cond.is_empty() { return Err(("Expected expression.", span).into()); } toks.next(); let mut body = read_until_closing_curly_brace(toks); body.push(toks.next().unwrap()); devour_whitespace(toks); Ok(Spanned { node: AtRule::While(While { cond, body }), span, }) }