252b725677
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.
122 lines
3.1 KiB
Rust
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>),
|
|
}
|