feat: Implement AST macros and templates

This commit introduces support for AST macros and templates, enabling
users to define and use custom, reusable components within the visual
DSL.

Key changes include:
- A new `MacroRegistry` to manage macro definitions.
- A `MacroExpander` to process macro calls and expand templates.
- A `MacroEvaluator` trait for evaluating expressions during expansion.
- The `Expansion` node in `BoundKind` to preserve the original macro
  call and its expanded form for debugging.
- Updates to the `Binder`, `Dumper`, and `UpvalueAnalyzer` to handle the
  new macro constructs.
- New examples demonstrating various macro functionalities like
  `unless`, splicing, and nested macros.
This commit is contained in:
Michael Schimmel
2026-02-18 12:51:07 +01:00
parent 98deb8f3fe
commit 94fc6bf56d
23 changed files with 798 additions and 67 deletions
+17 -2
View File
@@ -102,11 +102,12 @@ impl<'a> Lexer<'a> {
fn skip_whitespace(&mut self) {
while let Some(&c) = self.peek() {
if c.is_whitespace() {
if c.is_whitespace() || is_invisible(c) {
if c == '\n' {
self.line += 1;
self.col = 1;
} else {
} else if !is_invisible(c) {
// Only increment column for characters that actually take space
self.col += 1;
}
self.input.next();
@@ -175,3 +176,17 @@ fn is_ident_start(c: char) -> bool {
fn is_ident_char(c: char) -> bool {
is_ident_start(c) || c.is_ascii_digit()
}
/// Returns true if the character is an invisible control character
/// that should be ignored by the lexer (like BOM or Zero Width Space).
fn is_invisible(c: char) -> bool {
match c {
'\u{FEFF}' | // BOM
'\u{200B}' | // Zero Width Space
'\u{200C}' | // Zero Width Non-Joiner
'\u{200D}' | // Zero Width Joiner
'\u{2060}' // Word Joiner
=> true,
_ => false,
}
}