use crate::{
Environment,
eval::pair::{PairType, eval_pair},
token::{Token, TokenType},
value::Value,
};
pub(crate) fn eval_expression(tokens: &[Token], env: Environment) -> Result<(Value, usize), std::sync::Arc<str>> {
let mut current_idx = 0;
let first_token = tokens.get(current_idx).ok_or_else(|| {
std::sync::Arc::from(concat!(
"Error[ksl::eval::sentence::eval_expression]: ",
"Unexpected end of tokens."
))
})?;
let mut val = match &first_token.value {
TokenType::Atom(a) => Value::Atom(std::sync::Arc::from(a.iter().collect::<String>())),
TokenType::String(s) => Value::String(std::sync::Arc::from(s.iter().collect::<String>())),
TokenType::Char(c) => Value::String(std::sync::Arc::from(String::from(*c))),
TokenType::Number(n) => Value::Number(*n),
TokenType::Symbol(sym) => Value::Symbol(std::sync::Arc::from(sym.iter().collect::<String>())),
TokenType::ListOpen => {
let (list_vals, bias) = eval_pair(&tokens[1..], env.clone(), PairType::List)?;
current_idx += bias;
Value::List(std::sync::Arc::from(list_vals))
}
_ => {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::eval::sentence::eval_expression]: ",
"Invalid token type `{:?}` at `({}, {})`."
),
first_token.value, first_token.location.0.0, first_token.location.0.1
)));
}
};
current_idx += 1;
while let Some(next_tok) = tokens.get(current_idx) {
if matches!(next_tok.value, TokenType::FuncListOpen) {
let (args, bias) = eval_pair(&tokens[current_idx + 1..], env.clone(), PairType::Function)?;
val = Value::Apply(args, std::sync::Arc::new(val));
current_idx += bias + 1;
} else {
break;
}
}
Ok((val, current_idx))
}
pub(crate) fn eval_sentence(tokens: &[Token], env: Environment) -> Result<Value, std::sync::Arc<str>> {
let (val, consumed) = eval_expression(tokens, env)?;
if let Some(extra) = tokens.get(consumed) {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::eval::sentence::eval_sentence]: ",
"Invalid token type `{:?}` at `({}, {})`."
),
extra.value, extra.location.0.0, extra.location.0.1
)));
}
Ok(val)
}