diff --git a/src/ast/compiler/macros.rs b/src/ast/compiler/macros.rs index 9c1f985..1d347d5 100644 --- a/src/ast/compiler/macros.rs +++ b/src/ast/compiler/macros.rs @@ -588,29 +588,21 @@ impl MacroExpander { target: &mut Vec>, ) -> Result<(), String> { match val { - Value::Object(obj) => { - if let Some(node) = obj.as_any().downcast_ref::() { - match &node.kind { - SyntaxKind::Tuple { elements } => { - for e in elements { - target.push(e.clone()); - } - return Ok(()); - } - SyntaxKind::Block { exprs } => { - for e in exprs { - target.push(e.clone()); - } - return Ok(()); - } - _ => {} + Value::Quote(node) => match &node.kind { + SyntaxKind::Tuple { elements } => { + for e in elements { + target.push(e.clone()); } + Ok(()) } - Err(format!( - "Strict Splicing: Expected Tuple or Block node, but found {}", - obj.type_name() - )) - } + SyntaxKind::Block { exprs } => { + for e in exprs { + target.push(e.clone()); + } + Ok(()) + } + _ => Err("Strict Splicing: Expected Tuple or Block node".to_string()), + }, _ => Err(format!( "Strict Splicing: Expected sequence (Tuple/Block Node), but found Value: {}", val @@ -620,16 +612,7 @@ impl MacroExpander { fn value_to_node(&self, val: Value, identity: Identity) -> SyntaxNode { match val { - Value::Object(obj) => { - if let Some(node) = obj.as_any().downcast_ref::() { - return node.clone(); - } - SyntaxNode { - identity, - kind: SyntaxKind::Constant(Value::Object(obj)), - ty: (), - } - } + Value::Quote(rc) => rc.as_ref().clone(), _ => SyntaxNode { identity, kind: SyntaxKind::Constant(val), @@ -659,7 +642,7 @@ mod tests { if let SyntaxKind::Identifier { symbol: ref sym, .. } = node.kind && let Some(arg) = bindings.get(&sym.name) { - return Ok(Value::Object(Rc::new(arg.clone()) as Rc)); + return Ok(Value::Quote(Rc::new(arg.clone()))); } Err(format!( "SimpleEvaluator cannot evaluate complex expression: {:?}", diff --git a/src/ast/environment.rs b/src/ast/environment.rs index 6db7312..653e104 100644 --- a/src/ast/environment.rs +++ b/src/ast/environment.rs @@ -22,7 +22,7 @@ use crate::ast::compiler::optimizer::Optimizer; use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer}; use crate::ast::rtl::{self, intrinsics}; use crate::ast::types::{ - NativeFunction, NodeIdentity, Object, Purity, SourceLocation, StaticType, Value, + NativeFunction, NodeIdentity, Purity, SourceLocation, StaticType, Value, }; use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics}; @@ -121,7 +121,7 @@ impl MacroEvaluator for RuntimeMacroEvaluator { if let SyntaxKind::Identifier { symbol: sym, .. } = &node.kind && let Some(arg_node) = bindings.get(&sym.name) { - return Ok(Value::Object(Rc::new(arg_node.clone()) as Rc)); + return Ok(Value::Quote(Rc::new(arg_node.clone()))); } let mut diag = Diagnostics::new(); diff --git a/src/ast/nodes.rs b/src/ast/nodes.rs index 795ade7..356ac8b 100644 --- a/src/ast/nodes.rs +++ b/src/ast/nodes.rs @@ -1,5 +1,4 @@ -use crate::ast::types::{Identity, Keyword, Object, Purity, RecordLayout, StaticType, Value}; -use std::any::Any; +use crate::ast::types::{Identity, Keyword, Purity, RecordLayout, StaticType, Value}; use std::fmt::Debug; use std::rc::Rc; use std::sync::Arc; @@ -269,17 +268,6 @@ pub type SyntaxNode = Node; /// Type alias: the parser AST kind is now `NodeKind`. pub type SyntaxKind = NodeKind; -impl Object for Node { - fn type_name(&self) -> &'static str { - "ast-node" - } - fn as_any(&self) -> &dyn Any { - self - } - fn into_rc_any(self: Rc) -> Rc { - self - } -} pub type TypedNode = Node; diff --git a/src/ast/types.rs b/src/ast/types.rs index c85c3c7..80c607e 100644 --- a/src/ast/types.rs +++ b/src/ast/types.rs @@ -1,4 +1,5 @@ use crate::ast::closure::Closure; +use crate::ast::nodes::SyntaxNode; use chrono::{TimeZone, Utc}; use std::any::Any; use std::cell::RefCell; @@ -263,7 +264,8 @@ pub enum Value { FieldAccessor(Keyword), Function(Rc), Closure(Rc), // Compiled function with captured upvalues - Object(Rc), // For Series, Streams, SyntaxNodes, and custom extensions + Quote(Rc), // Quoted AST node (from 'expr or macro expansion) + Object(Rc), // RTL extensions: Series, Streams, and custom types Cell(Rc>), // Boxed value for captures } @@ -284,6 +286,7 @@ impl PartialEq for Value { (Value::FieldAccessor(a), Value::FieldAccessor(b)) => a == b, (Value::Function(a), Value::Function(b)) => Rc::ptr_eq(a, b), (Value::Closure(a), Value::Closure(b)) => Rc::ptr_eq(a, b), + (Value::Quote(a), Value::Quote(b)) => Rc::ptr_eq(a, b), (Value::Object(a), Value::Object(b)) => Rc::ptr_eq(a, b), (Value::Cell(a), Value::Cell(b)) => Rc::ptr_eq(a, b), _ => false, @@ -625,6 +628,7 @@ impl Value { Value::FieldAccessor(k) => StaticType::FieldAccessor(*k), Value::Function(_) => StaticType::Any, // Dynamic function Value::Closure(_) => StaticType::Object("closure"), + Value::Quote(_) => StaticType::Object("ast-node"), Value::Object(o) => StaticType::Object(o.type_name()), Value::Cell(c) => c.borrow().static_type(), } @@ -669,6 +673,7 @@ impl fmt::Display for Value { Value::FieldAccessor(k) => write!(f, ".{}", k.name()), Value::Function(f_meta) => write!(f, "", f_meta.purity), Value::Closure(_) => write!(f, ""), + Value::Quote(_) => write!(f, ""), Value::Object(o) => write!(f, "<{:?}>", o), Value::Cell(c) => write!(f, "{}", c.borrow()), } diff --git a/src/ast/vm.rs b/src/ast/vm.rs index b2b58f6..62b7893 100644 --- a/src/ast/vm.rs +++ b/src/ast/vm.rs @@ -710,6 +710,7 @@ impl VM { Value::FieldAccessor(_) => "FieldAccessor", Value::Function(_) => "Function", Value::Closure(_) => "Closure", + Value::Quote(_) => "Quote", Value::Object(_) => "Object", Value::Cell(_) => "Cell", };