Add Program node kind
The `Program` node kind is introduced to represent top-level code blocks, distinguishing them from `Block` nodes which introduce new scopes. This commit updates various compiler passes to handle the `Program` node, ensuring correct AST traversal and processing. The `Program` node is similar to `Block`, but its definitions propagate to the enclosing scope, unlike `Block` which creates a new, isolated scope. This distinction is important for how variables and functions are resolved within the compiled code.
This commit is contained in:
+15
-10
@@ -266,22 +266,27 @@ impl VM {
|
||||
self.resolve_tail_calls(observer, result)
|
||||
}
|
||||
|
||||
pub fn run_with_observer<O: VMObserver>(
|
||||
&mut self,
|
||||
observer: &mut O,
|
||||
root: &ExecNode,
|
||||
) -> Result<Value, String> {
|
||||
self.stack.clear();
|
||||
pub fn eval_in_frame<O: VMObserver>(&mut self, observer: &mut O, root: &ExecNode, stack: Vec<Value>) -> Result<Value, String> {
|
||||
self.stack = stack;
|
||||
self.frames.clear();
|
||||
|
||||
self.stack.resize(root.ty.stack_size as usize, Value::Void);
|
||||
|
||||
self.frames.push(CallFrame {
|
||||
stack_base: 0,
|
||||
closure: None,
|
||||
});
|
||||
let result = self.eval_internal(observer, root);
|
||||
self.frames.pop();
|
||||
result
|
||||
}
|
||||
|
||||
pub fn run_with_observer<O: VMObserver>(
|
||||
&mut self,
|
||||
observer: &mut O,
|
||||
root: &ExecNode,
|
||||
) -> Result<Value, String> {
|
||||
let mut stack = Vec::new();
|
||||
stack.resize(root.ty.stack_size as usize, Value::Void);
|
||||
|
||||
let result = self.eval_in_frame(observer, root, stack);
|
||||
self.resolve_tail_calls(observer, result)
|
||||
}
|
||||
|
||||
@@ -438,7 +443,7 @@ impl VM {
|
||||
Ok(Value::Void)
|
||||
}
|
||||
}
|
||||
NodeKind::Block { exprs } => {
|
||||
NodeKind::Block { exprs } | NodeKind::Program { exprs } => {
|
||||
let mut last = Value::Void;
|
||||
for e in exprs {
|
||||
last = self.eval_internal(obs, e)?;
|
||||
|
||||
Reference in New Issue
Block a user