grass/src/mixin.rs

80 lines
2.4 KiB
Rust
Raw Normal View History

use std::iter::Peekable;
use std::vec::IntoIter;
use crate::common::{Pos, Scope};
use crate::function::{CallArgs, FuncArgs};
use crate::selector::Selector;
use crate::{eat_expr, Expr, RuleSet, Stmt, Token};
2020-01-12 20:15:40 -05:00
#[derive(Debug, Clone)]
pub struct Mixin {
scope: Scope,
args: FuncArgs,
body: Peekable<IntoIter<Token>>,
nesting: u32,
2020-01-12 20:15:40 -05:00
}
impl Mixin {
pub fn new(scope: Scope, args: FuncArgs, body: Vec<Token>) -> Self {
2020-01-17 21:20:56 -05:00
let body = body.into_iter().peekable();
Mixin {
scope,
args,
body,
nesting: 0,
}
2020-01-12 20:15:40 -05:00
}
2020-01-18 09:03:38 -05:00
pub fn args(&mut self, args: &CallArgs) -> &mut Mixin {
2020-01-17 14:44:55 -05:00
for (idx, arg) in args.0.iter().enumerate() {
if arg.is_named() {
todo!("keyword args")
} else {
self.scope
.vars
.insert(self.args.0[idx].name.clone(), arg.val.clone());
2020-01-17 14:44:55 -05:00
}
}
self
}
2020-01-18 09:52:21 -05:00
pub fn call(&mut self, super_selector: &Selector) -> Result<Vec<Stmt>, (Pos, &'static str)> {
2020-01-18 09:03:38 -05:00
self.eval(super_selector, &mut self.scope.clone())
}
2020-01-17 22:40:13 -05:00
pub fn eval(
&mut self,
super_selector: &Selector,
scope: &mut Scope,
) -> Result<Vec<Stmt>, (Pos, &'static str)> {
let mut stmts = Vec::new();
while let Some(expr) = eat_expr(&mut self.body, scope, super_selector)? {
match expr {
Expr::Style(s) => stmts.push(Stmt::Style(s)),
Expr::Include(_) => todo!(),
Expr::MixinDecl(_, _) => todo!(),
Expr::Selector(s) => {
self.nesting += 1;
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope)?;
stmts.push(Stmt::RuleSet(RuleSet {
super_selector: super_selector.clone(),
selector: s,
rules,
}));
self.nesting -= 1;
2020-01-12 20:15:40 -05:00
}
Expr::VariableDecl(name, val) => {
if self.nesting == 0 {
scope.vars.insert(name.clone(), val.clone());
self.scope.vars.insert(name, val);
2020-01-14 19:34:13 -05:00
} else {
scope.vars.insert(name, val);
2020-01-14 19:34:13 -05:00
}
}
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
2020-01-12 20:15:40 -05:00
}
}
Ok(stmts)
2020-01-12 20:15:40 -05:00
}
}