feat: Implement AST binder and VM

Adds a new `Binder` struct that traverses the AST and resolves variable
references to concrete `Address` types (Local, Upvalue, Global). This
information is crucial for the Virtual Machine's execution phase.

Introduces the `BoundKind` enum to represent the AST after binding.

The `VM` is updated to handle `BoundKind` nodes and execute the bound
AST.
It now manages a call stack, local variables, and closures for function
calls and upvalue capturing.

The `Environment` struct is enhanced to manage global variables and
provide
a unified interface for parsing, binding, and executing scripts. It also
includes basic standard library functions.
This commit is contained in:
Michael Schimmel
2026-02-17 02:00:51 +01:00
parent 874a6f39a4
commit 7042206ab6
8 changed files with 595 additions and 29 deletions
+56
View File
@@ -0,0 +1,56 @@
use std::sync::Arc;
use crate::ast::types::Value;
use crate::ast::nodes::{Node, CustomNode};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Address {
Local(u32), // Stack-Slot index (relative to frame base)
Upvalue(u32), // Index in the closure's upvalue array
Global(u32), // Index in the global environment vector
}
#[derive(Debug)]
pub enum BoundKind {
Nop,
Constant(Value),
// Variable Access (Resolved)
Get(Address),
// Variable Update (Resolved)
Set {
addr: Address,
value: Box<Node<BoundKind>>,
},
If {
cond: Box<Node<BoundKind>>,
then_br: Box<Node<BoundKind>>,
else_br: Option<Box<Node<BoundKind>>>,
},
// Global Definition (Locals are implicit by stack position)
DefGlobal {
global_index: u32,
value: Box<Node<BoundKind>>,
},
Lambda {
param_count: u32,
// The list of variables captured from enclosing scopes
upvalues: Vec<Address>,
body: Arc<Node<BoundKind>>,
},
Call {
callee: Box<Node<BoundKind>>,
args: Vec<Node<BoundKind>>,
},
Block {
exprs: Vec<Node<BoundKind>>,
},
// Extension points (need to be adapted for bound nodes if they use variables)
// For now, we assume extensions are self-contained or handled dynamically.
}