diff --git a/src/ast/nodes.rs b/src/ast/nodes.rs index b2b644c..31fe040 100644 --- a/src/ast/nodes.rs +++ b/src/ast/nodes.rs @@ -16,7 +16,7 @@ pub trait CustomNode: Debug + Send + Sync { fn display_name(&self) -> &'static str; } -/// Dynamic Scope for the interpreter (Temporary solution) +/// Dynamic Scope for the interpreter #[derive(Debug, Clone)] pub struct Scope { values: HashMap, @@ -54,10 +54,7 @@ pub struct Context { impl Context { pub fn new() -> Self { let mut root_scope = Scope::new(None); - - // Register standard library (built-ins) register_stdlib(&mut root_scope); - Self { scope: Arc::new(Mutex::new(root_scope)), } @@ -65,19 +62,15 @@ impl Context { } fn register_stdlib(scope: &mut Scope) { - // Helper macro to reduce boilerplate macro_rules! bin_op { ($name:expr, $op:tt) => { scope.define($name, Value::Function(Arc::new(|args| { - if args.len() < 2 { return Value::Void; } // Error handling later - - // Fold allow multi-arg: (+ 1 2 3) -> 6 + if args.len() < 2 { return Value::Void; } let mut acc = match &args[0] { Value::Int(i) => *i as f64, Value::Float(f) => *f, _ => return Value::Void, }; - for arg in &args[1..] { let val = match arg { Value::Int(i) => *i as f64, @@ -86,8 +79,6 @@ fn register_stdlib(scope: &mut Scope) { }; acc = acc $op val; } - - // Return Int if result is integer-like (simplified) if acc.fract() == 0.0 { Value::Int(acc as i64) } else { @@ -102,11 +93,9 @@ fn register_stdlib(scope: &mut Scope) { bin_op!("*", *); bin_op!("/", /); - // Logic scope.define(">", Value::Function(Arc::new(|args| { if args.len() != 2 { return Value::Void; } - let (v1, v2) = (&args[0], &args[1]); - match (v1, v2) { + match (&args[0], &args[1]) { (Value::Int(a), Value::Int(b)) => Value::Bool(a > b), (Value::Float(a), Value::Float(b)) => Value::Bool(a > b), (Value::Int(a), Value::Float(b)) => Value::Bool((*a as f64) > *b), @@ -116,11 +105,8 @@ fn register_stdlib(scope: &mut Scope) { }))); } - -/// The core AST variant enum for performance and structure #[derive(Debug)] pub enum UntypedKind { - /// The "..." placeholder for incomplete code Nop, Constant(Value), Identifier(Arc), @@ -129,11 +115,15 @@ pub enum UntypedKind { then_br: Box>, else_br: Option>>, }, + // CLOSURE SUPPORT + Lambda { + params: Vec>, + body: Arc>, // Arc for cheap cloning into closure + }, Call { callee: Box>, args: Vec>, }, - /// The "escape hatch" for decentralized node types Extension(Box), } @@ -160,10 +150,36 @@ impl Node { } } + // --- CLOSURE IMPLEMENTATION --- + UntypedKind::Lambda { params, body } => { + let captured_scope = ctx.scope.clone(); + let params = params.clone(); + let body = body.clone(); + + Ok(Value::Function(Arc::new(move |args| { + // 1. New Scope with captured parent + let mut new_scope = Scope::new(Some(captured_scope.clone())); + + // 2. Bind Args + for (i, param) in params.iter().enumerate() { + if i < args.len() { + new_scope.define(param, args[i].clone()); + } else { + new_scope.define(param, Value::Void); + } + } + + // 3. Eval Body + // Note: We swallow errors here because Value::Function signature is simple. + // In a full VM, we'd return Result. + let mut sub_ctx = Context { scope: Arc::new(Mutex::new(new_scope)) }; + body.eval(&mut sub_ctx).unwrap_or(Value::Void) + }))) + }, + UntypedKind::Call { callee, args } => { let func_val = callee.eval(ctx)?; - // Evaluate all arguments first (strict evaluation) let mut eval_args = Vec::with_capacity(args.len()); for arg in args { eval_args.push(arg.eval(ctx)?); diff --git a/src/ast/parser.rs b/src/ast/parser.rs index 53b1a84..44066e7 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use crate::ast::lexer::{Lexer, Token, TokenKind}; use crate::ast::types::{Identity, NodeIdentity, Value, Keyword}; -use crate::ast::nodes::{Node, UntypedKind}; +use crate::ast::nodes::{Node, UntypedKind, Context}; pub struct Parser<'a> { lexer: Lexer<'a>, @@ -27,13 +27,17 @@ impl<'a> Parser<'a> { pub fn parse_expression(&mut self) -> Result, String> { match self.peek() { TokenKind::LeftParen => self.parse_list(), - TokenKind::LeftBracket => self.parse_vector(), - // TokenKind::LeftBrace => self.parse_map(), // TODO + TokenKind::LeftBracket => self.parse_vector_literal(), TokenKind::Quote => { let identity = Arc::new(NodeIdentity { location: self.current_token.location }); - self.parse_reader_macro(UntypedKind::Call { - callee: Box::new(self.make_id_node("quote", identity)), - args: vec![], // will be filled + self.advance()?; // consume ' + let expr = self.parse_expression()?; + Ok(Node { + identity: identity.clone(), + kind: UntypedKind::Call { + callee: Box::new(self.make_id_node("quote", identity)), + args: vec![expr], + }, }) } _ => self.parse_atom(), @@ -65,21 +69,24 @@ impl<'a> Parser<'a> { fn parse_list(&mut self) -> Result, String> { let start_loc = self.advance()?.location; // consume '(' + let identity = Arc::new(NodeIdentity { location: start_loc }); if *self.peek() == TokenKind::RightParen { return Err(format!("Empty list () is not a valid expression at {:?}", start_loc)); } // Peek at head to check for special forms + // We parse the first expression to check if it's an identifier "if", "fn", etc. let head = self.parse_expression()?; let result = if let UntypedKind::Identifier(name) = &head.kind { match name.as_ref() { - "if" => self.parse_if(head.identity.clone()), - _ => self.parse_call(head), + "if" => self.parse_if(identity), + "fn" => self.parse_fn(identity), + _ => self.parse_call(head, identity), // Pass head + identity } } else { - self.parse_call(head) + self.parse_call(head, identity) }; self.expect(TokenKind::RightParen)?; @@ -87,6 +94,7 @@ impl<'a> Parser<'a> { } fn parse_if(&mut self, identity: Identity) -> Result, String> { + // 'if' was already consumed as head let cond = Box::new(self.parse_expression()?); let then_br = Box::new(self.parse_expression()?); let mut else_br = None; @@ -101,10 +109,41 @@ impl<'a> Parser<'a> { }) } - fn parse_call(&mut self, callee: Node) -> Result, String> { - let mut args = Vec::new(); - let identity = callee.identity.clone(); + fn parse_fn(&mut self, identity: Identity) -> Result, String> { + // 'fn' was consumed. Next must be [params] vector. + let params = self.parse_param_vector()?; + let body = self.parse_expression()?; + + Ok(Node { + identity, + kind: UntypedKind::Lambda { + params, + body: Arc::new(body), + }, + }) + } + fn parse_param_vector(&mut self) -> Result>, String> { + if *self.peek() != TokenKind::LeftBracket { + return Err(format!("Expected parameter vector [...] for fn, found {:?}", self.peek())); + } + self.advance()?; // consume '[' + + let mut params = Vec::new(); + while *self.peek() != TokenKind::RightBracket { + let token = self.advance()?; + match token.kind { + TokenKind::Identifier(name) => params.push(name), + _ => return Err(format!("Expected identifier in param vector, found {:?}", token.kind)), + } + } + self.expect(TokenKind::RightBracket)?; + Ok(params) + } + + fn parse_call(&mut self, callee: Node, identity: Identity) -> Result, String> { + let mut args = Vec::new(); + while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF { args.push(self.parse_expression()?); } @@ -115,17 +154,20 @@ impl<'a> Parser<'a> { }) } - fn parse_vector(&mut self) -> Result, String> { + fn parse_vector_literal(&mut self) -> Result, String> { let token = self.advance()?; // consume '[' let mut elements = Vec::new(); + // Temporary evaluation context for literals + let mut temp_ctx = Context::new(); + while *self.peek() != TokenKind::RightBracket && *self.peek() != TokenKind::EOF { - // Vector elements in Myc are usually just constants in a list let expr = self.parse_expression()?; - // Simple direct eval for literals (Context::new creates fresh scope) - match expr.eval(&mut crate::ast::nodes::Context::new()) { + // Simple direct eval for literals inside vectors (e.g. [1 2 3]) + // In a full compiler, we would return a VectorNode here instead of evaluating immediately. + match expr.eval(&mut temp_ctx) { Ok(val) => elements.push(val), - Err(e) => return Err(format!("Error evaluating vector element: {}", e)), + Err(e) => return Err(format!("Vector literal error: {}", e)), } } @@ -137,23 +179,6 @@ impl<'a> Parser<'a> { }) } - fn parse_reader_macro(&mut self, _template: UntypedKind) -> Result, String> { - let token = self.advance()?; // consume ' - let expr = self.parse_expression()?; - - // 'x -> (quote x) - let identity = Arc::new(NodeIdentity { location: token.location }); - let quote_id = self.make_id_node("quote", identity.clone()); - - Ok(Node { - identity, - kind: UntypedKind::Call { - callee: Box::new(quote_id), - args: vec![expr], - }, - }) - } - fn expect(&mut self, kind: TokenKind) -> Result<(), String> { let token = self.advance()?; if token.kind == kind {