Refactor interpolation

This commit is contained in:
ConnorSkees 2020-01-26 09:28:44 -05:00
parent 709ed5c6b5
commit 43866eb142
2 changed files with 14 additions and 44 deletions

View File

@ -1,4 +1,5 @@
use crate::common::{Pos, Symbol, Whitespace}; use crate::common::{Pos, Symbol};
use crate::value::Value;
use crate::{Scope, Token, TokenKind}; use crate::{Scope, Token, TokenKind};
use std::iter::{Iterator, Peekable}; use std::iter::{Iterator, Peekable};
@ -38,33 +39,6 @@ pub(crate) fn devour_whitespace_or_comment<I: Iterator<Item = W>, W: IsWhitespac
found_whitespace found_whitespace
} }
#[cfg_attr(feature = "nightly", track_caller)]
pub(crate) fn deref_variable(name: &str, scope: &Scope) -> Vec<Token> {
let mut toks = scope
.vars
.get(name)
.expect("todo! expected variable to exist")
.iter()
.peekable();
let mut val = Vec::with_capacity(toks.len());
while let Some(tok) = toks.next() {
match tok.kind {
TokenKind::Variable(ref v) => val.extend(deref_variable(v, scope)),
TokenKind::Whitespace(_) => {
devour_whitespace(&mut toks);
if toks.peek().is_some() {
val.push(Token {
kind: TokenKind::Whitespace(Whitespace::Space),
pos: tok.pos,
});
}
}
_ => val.push(tok.clone()),
}
}
val
}
pub(crate) fn eat_interpolation<I: Iterator<Item = Token>>( pub(crate) fn eat_interpolation<I: Iterator<Item = Token>>(
tokens: &mut I, tokens: &mut I,
scope: &Scope, scope: &Scope,
@ -76,7 +50,10 @@ pub(crate) fn eat_interpolation<I: Iterator<Item = Token>>(
TokenKind::Symbol(Symbol::OpenCurlyBrace) => { TokenKind::Symbol(Symbol::OpenCurlyBrace) => {
todo!("invalid character in interpolation") todo!("invalid character in interpolation")
} }
TokenKind::Variable(ref v) => val.extend(deref_variable(v, scope)), TokenKind::Variable(ref v) => val.push(Token {
pos: tok.pos,
kind: TokenKind::Ident(scope.vars.get(v).unwrap().to_string()),
}),
TokenKind::Interpolation => val.extend(eat_interpolation(tokens, scope)), TokenKind::Interpolation => val.extend(eat_interpolation(tokens, scope)),
_ => val.push(tok), _ => val.push(tok),
} }
@ -87,17 +64,12 @@ pub(crate) fn eat_interpolation<I: Iterator<Item = Token>>(
pub(crate) fn eat_variable_value<I: Iterator<Item = Token>>( pub(crate) fn eat_variable_value<I: Iterator<Item = Token>>(
toks: &mut Peekable<I>, toks: &mut Peekable<I>,
scope: &Scope, scope: &Scope,
) -> Result<Vec<Token>, (Pos, String)> { ) -> Result<Value, (Pos, String)> {
devour_whitespace(toks); devour_whitespace(toks);
// todo!(line might not end with semicolon) // todo!(line might not end with semicolon)
let iter1 = toks.take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon)); let iter1: Vec<Token> = toks
let mut iter2 = Vec::new(); .take_while(|x| x.kind != TokenKind::Symbol(Symbol::SemiColon))
for tok in iter1 { .collect();
match tok.kind {
TokenKind::Variable(ref name) => iter2.extend(deref_variable(name, scope)),
_ => iter2.push(tok),
};
}
devour_whitespace(toks); devour_whitespace(toks);
Ok(iter2) Ok(Value::from_tokens(&mut iter1.into_iter().peekable(), scope).unwrap())
} }

View File

@ -8,7 +8,7 @@ use crate::builtin::GLOBAL_FUNCTIONS;
use crate::color::Color; use crate::color::Color;
use crate::common::{Keyword, Op, Scope, Symbol}; use crate::common::{Keyword, Op, Scope, Symbol};
use crate::units::Unit; use crate::units::Unit;
use crate::utils::{deref_variable, devour_whitespace_or_comment, eat_interpolation}; use crate::utils::{devour_whitespace_or_comment, eat_interpolation};
use crate::{Token, TokenKind}; use crate::{Token, TokenKind};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -275,7 +275,7 @@ impl Value {
.. ..
}) => { }) => {
toks.next(); toks.next();
let args = eat_call_args(toks); let args = eat_call_args(toks, scope);
let func = match scope.functions.get(&s) { let func = match scope.functions.get(&s) {
Some(f) => f, Some(f) => f,
None => match GLOBAL_FUNCTIONS.get(&s) { None => match GLOBAL_FUNCTIONS.get(&s) {
@ -308,9 +308,7 @@ impl Value {
} }
Some(Value::Ident(s, QuoteKind::Single)) Some(Value::Ident(s, QuoteKind::Single))
} }
TokenKind::Variable(ref v) => { TokenKind::Variable(ref v) => Some(scope.vars.get(v).unwrap().clone()),
Value::from_tokens(&mut deref_variable(v, scope).into_iter().peekable(), scope)
}
TokenKind::Interpolation => { TokenKind::Interpolation => {
let mut s = eat_interpolation(toks, scope) let mut s = eat_interpolation(toks, scope)
.iter() .iter()