beb693a068
This commit introduces fundamental changes to Myc's language structure to enhance type safety and scoping clarity. Key changes include: - Introducing local scopes for `do` blocks. - Separating statements (`def`, `assign`) from expressions, where statements now have no return value and are only allowed within blocks. - A block now consists of multiple statements followed by a single final expression. - Stricter validation rules are enforced, such as disallowing redefinition of local symbols in the same scope while allowing shadowing of outer symbols. - Compiler errors are generated for statements used in expression contexts. The implementation involved modifications to the AST, parser, binder (scope-stack), and various compiler passes, along with VM runtime optimizations.
131 lines
3.5 KiB
Rust
131 lines
3.5 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),
|
|
/// A general identifier (used for both references and declarations in the untyped AST).
|
|
Identifier(Symbol),
|
|
/// A first-class field accessor (e.g. .name)
|
|
FieldAccessor(crate::ast::types::Keyword),
|
|
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>>,
|
|
},
|
|
Pipe {
|
|
inputs: Vec<Node<UntypedKind>>,
|
|
lambda: Box<Node<UntypedKind>>,
|
|
},
|
|
Block {
|
|
statements: Vec<Node<UntypedKind>>,
|
|
result: Box<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>>,
|
|
},
|
|
/// A diagnostic poison node, allowing compilation to continue after an error.
|
|
Error,
|
|
Extension(Box<dyn CustomNode>),
|
|
}
|