use crate::error_handler::ErrorHandler;
use crate::function::{FunctionDefinition, FunctionType};
use crate::tokens::{Token, TokenType};
pub(crate) struct Resolver<'a> {
tokens: Vec<Token>,
current: usize,
functions: Vec<FunctionDefinition>,
error_handler: &'a mut ErrorHandler,
}
impl<'a> Resolver<'a> {
pub(crate) fn new(tokens: Vec<Token>, error_handler: &'a mut ErrorHandler) -> Self {
Self {
tokens,
current: 0,
functions: Vec::new(),
error_handler,
}
}
pub(crate) fn resolve(
&mut self,
function_definitions: &[FunctionDefinition],
) -> Option<Vec<FunctionDefinition>> {
self.functions = function_definitions.to_owned();
while !self.is_at_end() {
self.advance();
if self.previous().token_type == TokenType::Function {
if self.functions.len() >= 256 {
self.error_handler.error_token(
&self.previous().clone(),
"Cannot have more than 256 functions",
);
return None;
}
let func = self.function()?;
self.functions.push(func);
}
}
Some(self.functions.clone())
}
fn function(&mut self) -> Option<FunctionDefinition> {
let name = self.consume(TokenType::Identifier, "Expected identifier after FUNCTION.")?;
for func in &self.functions {
if func.name == name.lexeme {
self.error_handler.error_token(
&name,
&format!("Function is already defined on line {}.", func.line),
);
return None;
}
}
self.consume(TokenType::LeftParen, "Expected '(' after function name.")?;
let mut arity = 0;
if self.peek().token_type != TokenType::RightParen {
let mut another = true;
while !self.is_at_end() && another {
if arity == 255 {
self.error_handler
.error_token(&name, "Function cannot have more than 255 parameters.");
return None;
}
arity += 1;
self.consume(TokenType::Identifier, "Expected parameter name.")?;
another = self.match_type(TokenType::Comma);
}
}
self.consume(
TokenType::RightParen,
"Expected ')' after function parameters.",
)?;
while !self.is_at_end()
&& (self.peek().token_type != TokenType::End
|| self.peek_next().token_type != TokenType::Function)
{
self.advance();
}
self.consume(
TokenType::End,
"Expected END FUNCTION after function declaration.",
)?;
self.consume(
TokenType::Function,
"Expected END FUNCTION after function declaration.",
)?;
Some(FunctionDefinition::new(
name.lexeme,
arity,
name.line,
FunctionType::User,
))
}
fn consume(&mut self, token_type: TokenType, msg: &str) -> Option<Token> {
if self.peek().token_type == token_type {
self.advance();
Some(self.tokens[self.current - 1].clone())
} else {
self.error_handler
.error_token(&self.tokens[self.current], msg);
None
}
}
fn match_type(&mut self, token_type: TokenType) -> bool {
if self.peek().token_type == token_type {
self.advance();
true
} else {
false
}
}
fn is_at_end(&self) -> bool {
self.peek().token_type == TokenType::Eof
}
fn peek(&self) -> &Token {
&self.tokens[self.current]
}
fn peek_next(&self) -> &Token {
&self.tokens[self.current + 1]
}
fn previous(&self) -> &Token {
&self.tokens[self.current - 1]
}
fn advance(&mut self) {
if !self.is_at_end() {
self.current += 1;
}
}
}