use crate::{
Environment,
eval::sentence::eval_expression,
token::{Token, TokenType},
value::Value,
};
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum PairType {
Function,
List,
}
pub(crate) fn eval_pair(
tokens: &[Token],
env: Environment,
pair_type: PairType,
) -> Result<(Vec<Value>, usize), std::sync::Arc<str>> {
let mut token_index: usize = 0;
let mut vals: Vec<Value> = Vec::new();
let mut expect_element = true;
let close_type = match pair_type {
PairType::Function => TokenType::FuncListClose,
PairType::List => TokenType::ListClose,
};
while let Some(token) = tokens.get(token_index) {
if std::mem::discriminant(&token.value) == std::mem::discriminant(&close_type) {
return Ok((vals, token_index + 1));
}
if expect_element {
let (val, bias) = eval_expression(&tokens[token_index..], env.clone())?;
vals.push(val);
token_index += bias;
expect_element = false;
} else if matches!(token.value, TokenType::Seperator) {
token_index += 1;
expect_element = true;
} else {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::eval::pair::eval_pair]: ",
"Invalid token type `{:?}` at `({}, {})`."
),
token.value, token.location.0.0, token.location.0.1
)));
}
}
let last_pos = tokens.last().map_or((0, 0), |t| t.location.1);
Err(std::sync::Arc::from(format!(
"Error[ksl::eval::pair::eval_pair]: Unclosed pair `{:?}` at `({}, {})`.",
pair_type, last_pos.0, last_pos.1
)))
}