use std::sync::Arc; use std::fmt::Debug; use crate::ast::types::{Identity, Value}; /// A generic AST Node wrapper to preserve identity and metadata #[derive(Debug, Clone)] pub struct Node { pub identity: Identity, pub kind: K, } /// The base for custom node types (extensions) pub trait CustomNode: Debug + Send + Sync { fn eval(&self, node: &Node, ctx: &mut Context) -> Value; fn display_name(&self) -> &'static str; } /// Evaluation Context (Scope management) pub struct Context { // Add variables, scope management here later } /// The core AST variant enum for performance and structure #[derive(Debug)] pub enum UntypedKind { /// The "..." placeholder for incomplete code Nop, Constant(Value), Identifier(Arc), If { cond: Box>, then_br: Box>, else_br: Option>>, }, Call { callee: Box>, args: Vec>, }, /// The "escape hatch" for decentralized node types Extension(Box), } impl Node { pub fn eval(&self, ctx: &mut Context) -> Value { match &self.kind { UntypedKind::Nop => Value::Void, UntypedKind::Constant(v) => v.clone(), UntypedKind::Identifier(_) => todo!("Lookup in Context"), UntypedKind::If { cond, then_br, else_br } => { if cond.eval(ctx).is_truthy() { then_br.eval(ctx) } else if let Some(eb) = else_br { eb.eval(ctx) } else { Value::Void } } UntypedKind::Call { callee, args } => { let _func = callee.eval(ctx); let _eval_args: Vec = args.iter().map(|a| a.eval(ctx)).collect(); todo!("Execute func with args") } UntypedKind::Extension(ext) => ext.eval(self, ctx), } } }