2020-01-17 16:23:21 -05:00
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::vec::IntoIter;
|
|
|
|
|
2020-01-17 21:42:51 -05:00
|
|
|
use crate::common::{Pos, Scope};
|
2020-01-17 16:23:21 -05:00
|
|
|
use crate::function::{CallArgs, FuncArgs};
|
2020-01-17 08:14:10 -05:00
|
|
|
use crate::selector::Selector;
|
2020-01-17 10:43:03 -05:00
|
|
|
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,
|
2020-01-17 08:14:10 -05:00
|
|
|
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();
|
2020-01-17 08:14:10 -05:00
|
|
|
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 {
|
2020-01-18 19:00:49 -05:00
|
|
|
self.scope.vars.insert(
|
|
|
|
self.args
|
|
|
|
.0
|
|
|
|
.get(idx)
|
|
|
|
.expect("too many args passed to mixin")
|
|
|
|
.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)> {
|
2020-01-17 08:14:10 -05:00
|
|
|
let mut stmts = Vec::new();
|
2020-01-17 21:42:51 -05:00
|
|
|
while let Some(expr) = eat_expr(&mut self.body, scope, super_selector)? {
|
2020-01-17 08:14:10 -05:00
|
|
|
match expr {
|
|
|
|
Expr::Style(s) => stmts.push(Stmt::Style(s)),
|
2020-01-18 19:44:34 -05:00
|
|
|
Expr::Include(_)
|
|
|
|
| Expr::MixinDecl(_, _) => todo!(),
|
2020-01-17 08:14:10 -05:00
|
|
|
Expr::Selector(s) => {
|
|
|
|
self.nesting += 1;
|
2020-01-17 21:42:51 -05:00
|
|
|
let rules = self.eval(&super_selector.clone().zip(s.clone()), scope)?;
|
2020-01-17 08:14:10 -05:00
|
|
|
stmts.push(Stmt::RuleSet(RuleSet {
|
|
|
|
super_selector: super_selector.clone(),
|
|
|
|
selector: s,
|
|
|
|
rules,
|
|
|
|
}));
|
|
|
|
self.nesting -= 1;
|
2020-01-12 20:15:40 -05:00
|
|
|
}
|
2020-01-17 08:14:10 -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 {
|
2020-01-17 08:14:10 -05:00
|
|
|
scope.vars.insert(name, val);
|
2020-01-14 19:34:13 -05:00
|
|
|
}
|
|
|
|
}
|
2020-01-17 08:14:10 -05:00
|
|
|
Expr::MultilineComment(s) => stmts.push(Stmt::MultilineComment(s)),
|
2020-01-12 20:15:40 -05:00
|
|
|
}
|
|
|
|
}
|
2020-01-17 21:42:51 -05:00
|
|
|
Ok(stmts)
|
2020-01-12 20:15:40 -05:00
|
|
|
}
|
|
|
|
}
|