From 38c45129d99d6d446b7a2f8c7e9301c1620250d3 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Tue, 21 Apr 2020 11:32:27 -0400 Subject: [PATCH] refactor function eval --- src/atrule/function.rs | 34 +++++++++++++++++++++++++--------- src/value/parse.rs | 3 +-- src/value/sass_function.rs | 5 +---- tests/functions.rs | 5 +++++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/atrule/function.rs b/src/atrule/function.rs index 3eca18d..b56032f 100644 --- a/src/atrule/function.rs +++ b/src/atrule/function.rs @@ -9,7 +9,7 @@ use crate::atrule::AtRule; use crate::error::SassResult; use crate::scope::Scope; 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::{Stmt, Token}; @@ -17,7 +17,7 @@ use crate::{Stmt, Token}; pub(crate) struct Function { scope: Scope, args: FuncArgs, - body: Vec>, + body: Vec, pos: Span, } @@ -30,7 +30,7 @@ impl PartialEq for Function { impl Eq for Function {} impl Function { - pub fn new(scope: Scope, args: FuncArgs, body: Vec>, pos: Span) -> Self { + pub fn new(scope: Scope, args: FuncArgs, body: Vec, pos: Span) -> Self { Function { scope, args, @@ -54,18 +54,19 @@ impl Function { 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); Ok((name, Function::new(scope, args, body, span))) } pub fn args( - mut self, + &mut self, mut args: CallArgs, scope: &Scope, super_selector: &Selector, - ) -> SassResult { + ) -> SassResult<()> { for (idx, arg) in self.args.0.iter().enumerate() { if arg.is_variadic { let span = args.span(); @@ -98,11 +99,26 @@ impl Function { }; self.scope.insert_var(&arg.name, val)?; } - Ok(self) + Ok(()) } - pub fn body(&self) -> Vec> { - self.body.clone() + pub fn eval_body(&mut self, super_selector: &Selector) -> SassResult>> { + 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 { + 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>) -> SassResult { diff --git a/src/value/parse.rs b/src/value/parse.rs index a85d7d9..1134239 100644 --- a/src/value/parse.rs +++ b/src/value/parse.rs @@ -551,12 +551,11 @@ impl Value { }; Ok(IntermediateValue::Value( func.clone() - .args( + .eval( eat_call_args(toks, scope, super_selector)?, scope, super_selector, )? - .call(super_selector, func.body())? .span(span), )) } diff --git a/src/value/sass_function.rs b/src/value/sass_function.rs index 49cd21e..edaa8b2 100644 --- a/src/value/sass_function.rs +++ b/src/value/sass_function.rs @@ -60,10 +60,7 @@ impl SassFunction { match self { Self::Builtin(f, ..) => f.0(args, scope, super_selector), // todo: superselector - Self::UserDefined(f, ..) => f - .clone() - .args(args, scope, super_selector)? - .call(&Selector::new(), f.body()), + Self::UserDefined(f, ..) => f.clone().eval(args, scope, super_selector), } } } diff --git a/tests/functions.rs b/tests/functions.rs index 65df5bb..0da0a58 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -78,3 +78,8 @@ test!( "a {\n color: unquote(\"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" +);