use super::environment::Environment;
use super::value::Value;
use crate::parser::{FunctionDecl, Item, Program};
use std::collections::HashMap;
pub(crate) enum ControlFlow {
Continue,
Return(Value),
Break,
LoopContinue,
}
pub(crate) struct FunctionDef<'a> {
pub(crate) decl: &'a FunctionDecl<'a>,
#[allow(dead_code)]
pub(crate) receiver_type: Option<String>,
}
#[derive(Debug, Clone)]
pub(crate) struct EnumVariantInfo {
pub(crate) enum_name: String,
pub(crate) variant_name: String,
pub(crate) data_kind: EnumVariantKind,
}
#[derive(Debug, Clone)]
pub(crate) enum EnumVariantKind {
Unit,
Tuple {
#[allow(dead_code)]
count: usize,
},
Struct {
#[allow(dead_code)]
field_names: Vec<String>,
},
}
#[derive(Default)]
pub struct Interpreter<'a> {
pub(crate) env: Environment,
pub(crate) functions: HashMap<String, Vec<FunctionDef<'a>>>,
pub(crate) struct_defs: HashMap<String, Vec<String>>,
pub(crate) enum_variants: HashMap<String, EnumVariantInfo>,
pub(crate) output: Vec<String>,
pub(crate) capture_output: bool,
}
impl<'a> Interpreter<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn new_capturing() -> Self {
Self {
env: Environment::new(),
functions: HashMap::new(),
struct_defs: HashMap::new(),
enum_variants: HashMap::new(),
output: Vec::new(),
capture_output: true,
}
}
pub fn get_output(&self) -> String {
self.output.join("")
}
pub fn run(&mut self, program: &'a Program<'a>) -> Result<Value, String> {
self.register_definitions(program);
if self.functions.contains_key("main") {
self.call_function("main", &[])
} else {
Err("No main() function found".to_string())
}
}
fn register_definitions(&mut self, program: &'a Program<'a>) {
for item in &program.items {
match item {
Item::Function { decl, .. } => {
let name = decl.name.clone();
self.functions.entry(name).or_default().push(FunctionDef {
decl,
receiver_type: None,
});
}
Item::Struct { decl, .. } => {
let field_names: Vec<String> =
decl.fields.iter().map(|f| f.name.clone()).collect();
self.struct_defs.insert(decl.name.clone(), field_names);
}
Item::Impl { block, .. } => {
let type_name = block.type_name.clone();
for method in &block.functions {
let method_key = format!("{}::{}", type_name, method.name);
self.functions
.entry(method_key)
.or_default()
.push(FunctionDef {
decl: method,
receiver_type: Some(type_name.clone()),
});
}
}
Item::Enum { decl, .. } => {
for variant in &decl.variants {
let key = format!("{}::{}", decl.name, variant.name);
let data_kind = match &variant.data {
crate::parser::EnumVariantData::Unit => EnumVariantKind::Unit,
crate::parser::EnumVariantData::Tuple(types) => {
EnumVariantKind::Tuple { count: types.len() }
}
crate::parser::EnumVariantData::Struct(fields) => {
EnumVariantKind::Struct {
field_names: fields
.iter()
.map(|(name, _)| name.clone())
.collect(),
}
}
};
self.enum_variants.insert(
key,
EnumVariantInfo {
enum_name: decl.name.clone(),
variant_name: variant.name.clone(),
data_kind,
},
);
}
}
Item::Const { name, value, .. } => {
let val = self.eval_expression(value);
self.env.define(name, val);
}
_ => {}
}
}
}
pub(crate) fn call_function(&mut self, name: &str, args: &[Value]) -> Result<Value, String> {
let decl = {
let func_defs = self
.functions
.get(name)
.ok_or_else(|| format!("Undefined function: {}", name))?;
let func_def = func_defs
.first()
.ok_or_else(|| format!("No definition for function: {}", name))?;
func_def.decl
};
self.env.push_scope();
let param_iter = decl.parameters.iter().filter(|p| p.name != "self");
for (param, arg) in param_iter.zip(args.iter()) {
self.env.define(¶m.name, arg.clone());
}
let result = self.exec_body(&decl.body);
self.env.pop_scope();
match result {
ControlFlow::Return(val) => Ok(val),
ControlFlow::Continue => Ok(Value::Unit),
_ => Ok(Value::Unit),
}
}
}