grass/src/atrule/function.rs

89 lines
2.8 KiB
Rust
Raw Normal View History

2020-01-25 13:20:21 -05:00
use std::iter::Peekable;
use super::eat_stmts;
2020-02-17 09:23:24 -05:00
use crate::args::{eat_func_args, CallArgs, FuncArgs};
use crate::atrule::AtRule;
use crate::common::Symbol;
use crate::error::SassResult;
use crate::scope::Scope;
2020-02-22 15:34:32 -05:00
use crate::selector::Selector;
2020-01-25 13:20:21 -05:00
use crate::utils::devour_whitespace;
2020-01-25 21:02:22 -05:00
use crate::value::Value;
use crate::{Stmt, Token, TokenKind};
2020-01-25 13:20:21 -05:00
#[derive(Debug, Clone)]
pub(crate) struct Function {
scope: Scope,
args: FuncArgs,
body: Vec<Stmt>,
2020-01-25 13:20:21 -05:00
}
impl Function {
pub fn new(scope: Scope, args: FuncArgs, body: Vec<Stmt>) -> Self {
2020-01-25 13:20:21 -05:00
Function { scope, args, body }
}
pub fn decl_from_tokens<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>,
scope: Scope,
2020-03-01 12:03:14 -05:00
super_selector: &Selector,
2020-02-17 09:22:41 -05:00
) -> SassResult<(String, Function)> {
let Token { kind, .. } = toks
2020-01-25 13:20:21 -05:00
.next()
.expect("this must exist because we have already peeked");
devour_whitespace(toks);
let name = match kind {
TokenKind::Ident(s) => s,
2020-02-17 09:23:24 -05:00
_ => return Err("Expected identifier.".into()),
2020-01-25 13:20:21 -05:00
};
devour_whitespace(toks);
let args = match toks.next() {
Some(Token {
kind: TokenKind::Symbol(Symbol::OpenParen),
..
2020-03-01 12:03:14 -05:00
}) => eat_func_args(toks, &scope, super_selector)?,
2020-02-17 09:22:41 -05:00
_ => return Err("expected \"(\".".into()),
2020-01-25 13:20:21 -05:00
};
let body = eat_stmts(toks, &mut scope.clone(), super_selector)?;
devour_whitespace(toks);
2020-03-18 20:11:14 -04:00
Ok((name, Function::new(scope, args, body)))
2020-01-25 13:20:21 -05:00
}
pub fn args(mut self, args: &mut CallArgs) -> SassResult<Function> {
2020-01-25 21:02:22 -05:00
for (idx, arg) in self.args.0.iter().enumerate() {
let val = match args.remove(&format!("{}", idx)) {
Some(v) => v,
None => match args.remove(&arg.name) {
Some(v) => v,
None => match &arg.default {
Some(v) => v.clone(),
2020-02-17 09:23:24 -05:00
None => return Err(format!("Missing argument ${}.", &arg.name).into()),
},
2020-01-25 21:02:22 -05:00
},
};
self.scope.insert_var(&arg.name, val)?;
2020-01-25 21:02:22 -05:00
}
Ok(self)
2020-01-25 21:02:22 -05:00
}
2020-03-01 12:03:14 -05:00
pub fn call(&self, super_selector: &Selector) -> SassResult<Value> {
for stmt in &self.body {
match stmt {
Stmt::AtRule(AtRule::Return(toks)) => {
2020-01-25 21:02:22 -05:00
return Value::from_tokens(
&mut toks.clone().into_iter().peekable(),
&self.scope,
2020-03-01 12:03:14 -05:00
super_selector,
2020-01-25 21:02:22 -05:00
)
}
Stmt::AtRule(AtRule::For(..)) => todo!("@for in function"),
2020-03-01 17:06:55 -05:00
_ => return Err("This at-rule is not allowed here.".into()),
2020-01-25 21:02:22 -05:00
}
}
todo!()
}
}