use ocelot_ast::expression::Expression;
use ocelot_ast::expression_kind::ExpressionKind;
use ocelot_ast::item::Item;
use ocelot_ast::item_kind::ItemKind;
use ocelot_ast::script::Script;
use ocelot_ast::statement::Statement;
use ocelot_ast::statement_kind::StatementKind;
use ocelot_base::result::OcelotResult;
use ocelot_pal::pal::Pal;
pub struct Interpreter<'a> {
pal: &'a dyn Pal,
}
impl<'a> Interpreter<'a> {
pub fn new(pal: &'a dyn Pal) -> Self {
Self { pal }
}
pub fn interpret_script(&self, script: &Script) -> OcelotResult<()> {
for item in &script.items {
self.interpret_item(item)?;
}
Ok(())
}
pub fn interpret_statements(&self, statements: &[Statement]) -> OcelotResult<()> {
for statement in statements {
self.interpret_statement(statement)?;
}
Ok(())
}
fn interpret_item(&self, item: &Item) -> OcelotResult<()> {
match &item.kind {
ItemKind::Statement(statement) => self.interpret_statement(statement),
ItemKind::Test(_) => Ok(()),
}
}
fn interpret_statement(&self, statement: &Statement) -> OcelotResult<()> {
match &statement.kind {
StatementKind::Println(println_statement) => {
let value = self.evaluate_expression(&println_statement.argument)?;
self.pal.print(&format!("{value}\n"))?;
Ok(())
}
}
}
fn evaluate_expression(&self, expression: &Expression) -> OcelotResult<String> {
match &expression.kind {
ExpressionKind::StringLiteral(string_literal) => Ok(string_literal.value.clone()),
ExpressionKind::Identifier(identifier) => {
ocelot_base::bail!("unresolved identifier `{}`", identifier.name)
}
}
}
}