mod expr;
mod import;
mod node;
mod stmt;
use crate::{
ast::resolved::ResolvedTree, ast::source::*, ast::utils::Value, context::Context,
error::Result, module_resolver::ModuleResolver, registry::Registry,
};
use rustc_hash::FxHashMap;
use std::collections::HashSet;
use std::path::PathBuf;
use std::rc::Rc;
pub enum FlowControl {
None,
Return(Value),
}
#[derive(PartialEq)]
pub enum ScopeKind {
TopLevel,
Block, Function, Component, }
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct VariableBinding {
pub value: Value,
pub is_const: bool,
}
#[derive(PartialEq)]
pub(crate) struct Scope {
pub variables: FxHashMap<String, VariableBinding>,
pub kind: ScopeKind,
}
pub(crate) struct Evaluator {
registry: Registry,
scopes: Vec<Scope>,
loaded_files: HashSet<PathBuf>,
module_resolver: Rc<dyn ModuleResolver>,
flow: FlowControl,
call_stack_depth: usize,
max_depth: usize,
}
impl Scope {
pub fn new(kind: ScopeKind) -> Self {
Self { variables: FxHashMap::default(), kind }
}
}
impl Evaluator {
pub fn new(
registry: Registry,
module_resolver: Rc<dyn ModuleResolver>,
max_depth: usize,
) -> Self {
Self {
registry,
scopes: vec![Scope::new(ScopeKind::TopLevel)],
loaded_files: HashSet::new(),
module_resolver,
flow: FlowControl::None,
call_stack_depth: 0,
max_depth,
}
}
pub fn run(&mut self, file: File) -> Result<ResolvedTree> {
let mut root_nodes = Vec::new();
for item in &file.items {
match item {
TopLevelItem::Import(imp) => self.handle_import(imp.clone(), &mut root_nodes)?,
TopLevelItem::ComponentDef(def) => self.registry.register_component(def.clone()),
TopLevelItem::FnDef(def) => self.registry.register_function(def.clone()),
TopLevelItem::Stmt(Stmt::Const(name, expr)) => {
let val = self.eval_expr(expr)?;
self.registry.globals.insert(name.clone(), val);
}
_ => {}
}
}
for item in file.items {
match item {
TopLevelItem::Node(invocation) => {
let nodes = self.resolve_node(invocation)?;
root_nodes.extend(nodes);
}
TopLevelItem::Stmt(stmt) => {
self.execute_stmt(&stmt)?;
}
_ => {} }
}
Ok(ResolvedTree { root_nodes })
}
pub fn return_context(&self) -> Context {
Context(self.registry.clone())
}
}