refactor function eval

This commit is contained in:
ConnorSkees 2020-04-21 11:32:27 -04:00
parent a29d8aea7b
commit 38c45129d9
4 changed files with 32 additions and 15 deletions

View File

@ -9,7 +9,7 @@ use crate::atrule::AtRule;
use crate::error::SassResult; use crate::error::SassResult;
use crate::scope::Scope; use crate::scope::Scope;
use crate::selector::Selector; use crate::selector::Selector;
use crate::utils::{devour_whitespace, eat_ident}; use crate::utils::{devour_whitespace, eat_ident, read_until_closing_curly_brace};
use crate::value::Value; use crate::value::Value;
use crate::{Stmt, Token}; use crate::{Stmt, Token};
@ -17,7 +17,7 @@ use crate::{Stmt, Token};
pub(crate) struct Function { pub(crate) struct Function {
scope: Scope, scope: Scope,
args: FuncArgs, args: FuncArgs,
body: Vec<Spanned<Stmt>>, body: Vec<Token>,
pos: Span, pos: Span,
} }
@ -30,7 +30,7 @@ impl PartialEq for Function {
impl Eq for Function {} impl Eq for Function {}
impl Function { impl Function {
pub fn new(scope: Scope, args: FuncArgs, body: Vec<Spanned<Stmt>>, pos: Span) -> Self { pub fn new(scope: Scope, args: FuncArgs, body: Vec<Token>, pos: Span) -> Self {
Function { Function {
scope, scope,
args, args,
@ -54,18 +54,19 @@ impl Function {
devour_whitespace(toks); devour_whitespace(toks);
let body = eat_stmts(toks, &mut scope.clone(), super_selector)?; let mut body = read_until_closing_curly_brace(toks); //eat_stmts(toks, &mut scope.clone(), super_selector)?;
body.push(toks.next().unwrap());
devour_whitespace(toks); devour_whitespace(toks);
Ok((name, Function::new(scope, args, body, span))) Ok((name, Function::new(scope, args, body, span)))
} }
pub fn args( pub fn args(
mut self, &mut self,
mut args: CallArgs, mut args: CallArgs,
scope: &Scope, scope: &Scope,
super_selector: &Selector, super_selector: &Selector,
) -> SassResult<Function> { ) -> SassResult<()> {
for (idx, arg) in self.args.0.iter().enumerate() { for (idx, arg) in self.args.0.iter().enumerate() {
if arg.is_variadic { if arg.is_variadic {
let span = args.span(); let span = args.span();
@ -98,11 +99,26 @@ impl Function {
}; };
self.scope.insert_var(&arg.name, val)?; self.scope.insert_var(&arg.name, val)?;
} }
Ok(self) Ok(())
} }
pub fn body(&self) -> Vec<Spanned<Stmt>> { pub fn eval_body(&mut self, super_selector: &Selector) -> SassResult<Vec<Spanned<Stmt>>> {
self.body.clone() eat_stmts(
&mut std::mem::take(&mut self.body).into_iter().peekmore(),
&mut self.scope,
super_selector,
)
}
pub fn eval(
mut self,
args: CallArgs,
scope: &Scope,
super_selector: &Selector,
) -> SassResult<Value> {
self.args(args, scope, super_selector)?;
let stmts = self.eval_body(super_selector)?;
self.call(super_selector, stmts)
} }
pub fn call(&self, super_selector: &Selector, stmts: Vec<Spanned<Stmt>>) -> SassResult<Value> { pub fn call(&self, super_selector: &Selector, stmts: Vec<Spanned<Stmt>>) -> SassResult<Value> {

View File

@ -551,12 +551,11 @@ impl Value {
}; };
Ok(IntermediateValue::Value( Ok(IntermediateValue::Value(
func.clone() func.clone()
.args( .eval(
eat_call_args(toks, scope, super_selector)?, eat_call_args(toks, scope, super_selector)?,
scope, scope,
super_selector, super_selector,
)? )?
.call(super_selector, func.body())?
.span(span), .span(span),
)) ))
} }

View File

@ -60,10 +60,7 @@ impl SassFunction {
match self { match self {
Self::Builtin(f, ..) => f.0(args, scope, super_selector), Self::Builtin(f, ..) => f.0(args, scope, super_selector),
// todo: superselector // todo: superselector
Self::UserDefined(f, ..) => f Self::UserDefined(f, ..) => f.clone().eval(args, scope, super_selector),
.clone()
.args(args, scope, super_selector)?
.call(&Selector::new(), f.body()),
} }
} }
} }

View File

@ -78,3 +78,8 @@ test!(
"a {\n color: unquote(\"a, b, c, d\");\n}\n", "a {\n color: unquote(\"a, b, c, d\");\n}\n",
"a {\n color: a, b, c, d;\n}\n" "a {\n color: a, b, c, d;\n}\n"
); );
test!(
variable_declaration,
"@function str-replace($string, $search, $replace: \"\") {\n $index: $string;\n @return $index;\n}\n\na {\n color: str-replace(\"a#b#c\", \"#\", \":\");\n}",
"a {\n color: \"a#b#c\";\n}\n"
);