consolidate arg evaluation for mixins and functions

This commit is contained in:
Connor Skees 2020-07-02 10:37:13 -04:00
parent a88f07da54
commit 8b907d4b67
3 changed files with 53 additions and 86 deletions

View File

@ -5,6 +5,7 @@ use codemap::{Span, Spanned};
use crate::{ use crate::{
args::{CallArg, CallArgs, FuncArg, FuncArgs}, args::{CallArg, CallArgs, FuncArg, FuncArgs},
error::SassResult, error::SassResult,
scope::Scope,
utils::{read_until_closing_paren, read_until_closing_quote, read_until_closing_square_brace}, utils::{read_until_closing_paren, read_until_closing_quote, read_until_closing_square_brace},
value::Value, value::Value,
Token, Token,
@ -298,4 +299,45 @@ impl<'a> Parser<'a> {
} }
Ok(vals) Ok(vals)
} }
pub(super) fn eval_args(
&mut self,
mut fn_args: FuncArgs,
mut args: CallArgs,
scope: &mut Scope,
) -> SassResult<()> {
self.scopes.push(self.scopes.last().clone());
for (idx, arg) in fn_args.0.iter_mut().enumerate() {
if arg.is_variadic {
let span = args.span();
// todo: does this get the most recent scope?
let arg_list = Value::ArgList(self.variadic_args(args)?);
scope.insert_var(
arg.name.clone(),
Spanned {
node: arg_list,
span,
},
)?;
break;
}
let val = match args.get(idx, arg.name.clone()) {
Some(v) => self.parse_value_from_vec(v)?,
None => match arg.default.as_mut() {
Some(v) => self.parse_value_from_vec(mem::take(v))?,
None => {
return Err(
(format!("Missing argument ${}.", &arg.name), args.span()).into()
)
}
},
};
self.scopes
.last_mut()
.insert_var(arg.name.clone(), val.clone())?;
scope.insert_var(mem::take(&mut arg.name), val)?;
}
self.scopes.pop();
Ok(())
}
} }

View File

@ -1,5 +1,3 @@
use std::mem;
use codemap::Spanned; use codemap::Spanned;
use peekmore::PeekMore; use peekmore::PeekMore;
@ -91,14 +89,21 @@ impl<'a> Parser<'a> {
Ok(Box::new(v.node)) Ok(Box::new(v.node))
} }
pub fn eval_function(&mut self, mut function: Function, args: CallArgs) -> SassResult<Value> { pub fn eval_function(&mut self, function: Function, args: CallArgs) -> SassResult<Value> {
self.eval_fn_args(&mut function, args)?; let Function {
mut scope,
body,
args: fn_args,
..
} = function;
self.eval_args(fn_args, args, &mut scope)?;
let mut return_value = Parser { let mut return_value = Parser {
toks: &mut function.body.into_iter().peekmore(), toks: &mut body.into_iter().peekmore(),
map: self.map, map: self.map,
path: self.path, path: self.path,
scopes: &mut NeverEmptyVec::new(function.scope), scopes: &mut NeverEmptyVec::new(scope),
global_scope: self.global_scope, global_scope: self.global_scope,
super_selectors: self.super_selectors, super_selectors: self.super_selectors,
span_before: self.span_before, span_before: self.span_before,
@ -121,39 +126,4 @@ impl<'a> Parser<'a> {
_ => todo!("should be unreachable"), _ => todo!("should be unreachable"),
} }
} }
fn eval_fn_args(&mut self, function: &mut Function, mut args: CallArgs) -> SassResult<()> {
self.scopes.push(self.scopes.last().clone());
for (idx, arg) in function.args.0.iter_mut().enumerate() {
if arg.is_variadic {
let span = args.span();
let arg_list = Value::ArgList(self.variadic_args(args)?);
function.scope.insert_var(
arg.name.clone(),
Spanned {
node: arg_list,
span,
},
)?;
break;
}
let val = match args.get(idx, arg.name.clone()) {
Some(v) => self.parse_value_from_vec(v)?,
None => match arg.default.as_mut() {
Some(v) => self.parse_value_from_vec(mem::take(v))?,
None => {
return Err(
(format!("Missing argument ${}.", &arg.name), args.span()).into()
)
}
},
};
self.scopes
.last_mut()
.insert_var(arg.name.clone(), val.clone())?;
function.scope.insert_var(mem::take(&mut arg.name), val)?;
}
self.scopes.pop();
Ok(())
}
} }

View File

@ -1,5 +1,3 @@
use std::mem;
use codemap::Spanned; use codemap::Spanned;
use peekmore::PeekMore; use peekmore::PeekMore;
@ -8,9 +6,7 @@ use crate::{
args::{CallArgs, FuncArgs}, args::{CallArgs, FuncArgs},
atrule::{Content, Mixin}, atrule::{Content, Mixin},
error::SassResult, error::SassResult,
scope::Scope,
utils::read_until_closing_curly_brace, utils::read_until_closing_curly_brace,
value::Value,
Token, Token,
}; };
@ -185,45 +181,4 @@ impl<'a> Parser<'a> {
.into()) .into())
} }
} }
fn eval_args(
&mut self,
mut fn_args: FuncArgs,
mut args: CallArgs,
scope: &mut Scope,
) -> SassResult<()> {
self.scopes.push(self.scopes.last().clone());
for (idx, arg) in fn_args.0.iter_mut().enumerate() {
if arg.is_variadic {
let span = args.span();
// todo: does this get the most recent scope?
let arg_list = Value::ArgList(self.variadic_args(args)?);
scope.insert_var(
arg.name.clone(),
Spanned {
node: arg_list,
span,
},
)?;
break;
}
let val = match args.get(idx, arg.name.clone()) {
Some(v) => self.parse_value_from_vec(v)?,
None => match arg.default.as_mut() {
Some(v) => self.parse_value_from_vec(mem::take(v))?,
None => {
return Err(
(format!("Missing argument ${}.", &arg.name), args.span()).into()
)
}
},
};
self.scopes
.last_mut()
.insert_var(arg.name.clone(), val.clone())?;
scope.insert_var(mem::take(&mut arg.name), val)?;
}
self.scopes.pop();
Ok(())
}
} }