Files
RustAst/src/ast/nodes.rs
T
Michael Schimmel 252b725677 Add support for destructuring def
This commit introduces the `DefDestructure` bound kind and modifies the
binder, analyzer, type checker, and VM to support destructuring in `def`
statements. This allows for pattern matching on the right-hand side of a
`def` to bind multiple variables.

The parser has been updated to accept patterns in `def` statements. The
binder now handles `UntypedKind::Def` with a `target` pattern, rather
than a simple `name`. This enables destructuring.

The `Gemini.md` documentation has been updated to include a new rule for
incremental development.
2026-02-24 08:40:45 +01:00

122 lines
3.1 KiB
Rust

use crate::ast::types::{Identity, Object, Value};
use std::any::Any;
use std::fmt::Debug;
use std::rc::Rc;
/// A name with an optional context for macro hygiene.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Symbol {
pub name: Rc<str>,
/// Points to the identity of the Expansion node if this symbol
/// was created/referenced inside a macro expansion.
pub context: Option<Identity>,
}
impl From<Rc<str>> for Symbol {
fn from(name: Rc<str>) -> Self {
Self {
name,
context: None,
}
}
}
impl From<&str> for Symbol {
fn from(name: &str) -> Self {
Self {
name: Rc::from(name),
context: None,
}
}
}
/// A generic AST Node wrapper to preserve identity and metadata
#[derive(Debug, Clone, PartialEq)]
pub struct Node<K, T = ()> {
pub identity: Identity,
pub kind: K,
pub ty: T,
}
impl Object for Node<UntypedKind> {
fn type_name(&self) -> &'static str {
"ast-node"
}
fn as_any(&self) -> &dyn Any {
self
}
}
/// The base for custom node types (extensions)
pub trait CustomNode: Debug {
fn display_name(&self) -> &'static str;
fn clone_box(&self) -> Box<dyn CustomNode>;
}
impl Clone for Box<dyn CustomNode> {
fn clone(&self) -> Self {
self.clone_box()
}
}
#[derive(Debug, Clone)]
pub enum UntypedKind {
Nop,
Constant(Value),
Identifier(Symbol),
Parameter(Symbol),
If {
cond: Box<Node<UntypedKind>>,
then_br: Box<Node<UntypedKind>>,
else_br: Option<Box<Node<UntypedKind>>>,
},
Def {
target: Box<Node<UntypedKind>>,
value: Box<Node<UntypedKind>>,
},
Assign {
target: Box<Node<UntypedKind>>,
value: Box<Node<UntypedKind>>,
},
Lambda {
params: Box<Node<UntypedKind>>,
body: Rc<Node<UntypedKind>>,
},
Call {
callee: Box<Node<UntypedKind>>,
args: Box<Node<UntypedKind>>,
},
Again {
args: Box<Node<UntypedKind>>,
},
Block {
exprs: Vec<Node<UntypedKind>>,
},
Tuple {
elements: Vec<Node<UntypedKind>>,
},
Record {
fields: Vec<(Node<UntypedKind>, Node<UntypedKind>)>,
},
/// A macro declaration that can be expanded at compile time.
MacroDecl {
name: Symbol,
params: Box<Node<UntypedKind>>,
body: Box<Node<UntypedKind>>,
},
/// A template for AST nodes, allowing for substitutions. (Quasiquote)
Template(Box<Node<UntypedKind>>),
/// A placeholder inside a template to be replaced by a node or value. (Unquote)
Placeholder(Box<Node<UntypedKind>>),
/// A placeholder that flattens a sequence or merges a record into its surroundings. (Splice)
Splice(Box<Node<UntypedKind>>),
/// Represents an expanded macro call, preserving the original call for debugging.
Expansion {
/// The original call from the source AST.
call: Box<Node<UntypedKind>>,
/// The resulting AST after macro expansion.
expanded: Box<Node<UntypedKind>>,
},
Extension(Box<dyn CustomNode>),
}