Introduce closure AST node
The `Closure` struct has been moved from `ast/vm.rs` to a new module `ast/closure.rs`. This improves the organization of the AST nodes. The `Closure` struct represents a compiled function body along with its captured upvalues, which is a key feature for Myc Script.
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
use crate::ast::nodes::{AnalyzedNode, ExecNode};
|
||||||
|
use crate::ast::types::{Object, Value};
|
||||||
|
use std::any::Any;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/// A compiled closure: a function body together with its captured upvalues.
|
||||||
|
///
|
||||||
|
/// Closures are the primary callable value in Myc Script. They are created by
|
||||||
|
/// `fn`-expressions and stored as `Value::Closure`.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Closure {
|
||||||
|
/// The executable parameter pattern.
|
||||||
|
pub parameter_node: Rc<ExecNode>,
|
||||||
|
/// The analyzed body (before TCO transformation).
|
||||||
|
pub function_node: Rc<AnalyzedNode>,
|
||||||
|
/// The executable node (after TCO transformation).
|
||||||
|
pub exec_node: Rc<ExecNode>,
|
||||||
|
/// Captured variables from enclosing scopes.
|
||||||
|
pub upvalues: Vec<Rc<RefCell<Value>>>,
|
||||||
|
/// Number of positional parameters, if known statically.
|
||||||
|
pub positional_count: Option<u32>,
|
||||||
|
/// Number of stack slots required for this closure (set during compilation).
|
||||||
|
pub stack_size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Closure {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(
|
||||||
|
params: Rc<ExecNode>,
|
||||||
|
body: Rc<AnalyzedNode>,
|
||||||
|
exec: Rc<ExecNode>,
|
||||||
|
upvalues: Vec<Rc<RefCell<Value>>>,
|
||||||
|
positional_count: Option<u32>,
|
||||||
|
stack_size: u32,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
parameter_node: params,
|
||||||
|
function_node: body,
|
||||||
|
exec_node: exec,
|
||||||
|
upvalues,
|
||||||
|
positional_count,
|
||||||
|
stack_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for Closure {
|
||||||
|
fn type_name(&self) -> &'static str {
|
||||||
|
"closure"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_rc_any(self: Rc<Self>) -> Rc<dyn Any> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ use crate::ast::nodes::{
|
|||||||
IdentifierBinding, LambdaBinding, Node, NodeKind, UpvalueIdx, VirtualId,
|
IdentifierBinding, LambdaBinding, Node, NodeKind, UpvalueIdx, VirtualId,
|
||||||
};
|
};
|
||||||
use crate::ast::types::{Purity, Value};
|
use crate::ast::types::{Purity, Value};
|
||||||
use crate::ast::vm::Closure;
|
use crate::ast::closure::Closure;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::ast::nodes::{
|
|||||||
Address, AnalyzedNode, IdentifierBinding, NodeKind, VirtualId,
|
Address, AnalyzedNode, IdentifierBinding, NodeKind, VirtualId,
|
||||||
};
|
};
|
||||||
use crate::ast::types::{Purity, Value};
|
use crate::ast::types::{Purity, Value};
|
||||||
use crate::ast::vm::Closure;
|
use crate::ast::closure::Closure;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::ast::nodes::{
|
|||||||
NodeKind, VirtualId,
|
NodeKind, VirtualId,
|
||||||
};
|
};
|
||||||
use crate::ast::types::{Identity, Value};
|
use crate::ast::types::{Identity, Value};
|
||||||
use crate::ast::vm::Closure;
|
use crate::ast::closure::Closure;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
// --- PathTracker ---
|
// --- PathTracker ---
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use crate::ast::compiler::binder::{Binder, CompilerScope, LocalInfo};
|
|||||||
use crate::ast::compiler::{CapturePass, TypeChecker, TypedNode};
|
use crate::ast::compiler::{CapturePass, TypeChecker, TypedNode};
|
||||||
use crate::ast::nodes::{AnalyzedPhase, Symbol, SyntaxKind, SyntaxNode};
|
use crate::ast::nodes::{AnalyzedPhase, Symbol, SyntaxKind, SyntaxNode};
|
||||||
use crate::ast::parser::Parser;
|
use crate::ast::parser::Parser;
|
||||||
use crate::ast::vm::{Closure, TracingObserver, VM};
|
use crate::ast::closure::Closure;
|
||||||
|
use crate::ast::vm::{TracingObserver, VM};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod closure;
|
||||||
pub mod compiler;
|
pub mod compiler;
|
||||||
pub mod diagnostics;
|
pub mod diagnostics;
|
||||||
pub mod environment;
|
pub mod environment;
|
||||||
|
|||||||
+2
-49
@@ -1,58 +1,11 @@
|
|||||||
use crate::ast::nodes::{Address, AnalyzedNode, ExecNode, IdentifierBinding, NodeKind, StackOffset};
|
use crate::ast::closure::Closure;
|
||||||
|
use crate::ast::nodes::{Address, ExecNode, IdentifierBinding, NodeKind, StackOffset};
|
||||||
use crate::ast::rtl::series::{RecordSeries, SeriesView};
|
use crate::ast::rtl::series::{RecordSeries, SeriesView};
|
||||||
use crate::ast::rtl::streams::{build_map_stream, build_pipeline_node, StreamNode};
|
use crate::ast::rtl::streams::{build_map_stream, build_pipeline_node, StreamNode};
|
||||||
use crate::ast::types::{Object, PipeFn, Value};
|
use crate::ast::types::{Object, PipeFn, Value};
|
||||||
use std::any::Any;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Closure {
|
|
||||||
/// The executable parameter pattern.
|
|
||||||
pub parameter_node: Rc<ExecNode>,
|
|
||||||
/// The analyzed body (before TCO).
|
|
||||||
pub function_node: Rc<AnalyzedNode>,
|
|
||||||
/// The executable node (after TCO).
|
|
||||||
pub exec_node: Rc<ExecNode>,
|
|
||||||
pub upvalues: Vec<Rc<RefCell<Value>>>,
|
|
||||||
pub positional_count: Option<u32>,
|
|
||||||
/// The number of stack slots required for this closure (calculated late).
|
|
||||||
pub stack_size: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Closure {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(
|
|
||||||
params: Rc<ExecNode>,
|
|
||||||
body: Rc<AnalyzedNode>,
|
|
||||||
exec: Rc<ExecNode>,
|
|
||||||
upvalues: Vec<Rc<RefCell<Value>>>,
|
|
||||||
positional_count: Option<u32>,
|
|
||||||
stack_size: u32,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
parameter_node: params,
|
|
||||||
function_node: body,
|
|
||||||
exec_node: exec,
|
|
||||||
upvalues,
|
|
||||||
positional_count,
|
|
||||||
stack_size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Object for Closure {
|
|
||||||
fn type_name(&self) -> &'static str {
|
|
||||||
"closure"
|
|
||||||
}
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
fn into_rc_any(self: Rc<Self>) -> Rc<dyn Any> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CallFrame {
|
struct CallFrame {
|
||||||
stack_base: usize,
|
stack_base: usize,
|
||||||
|
|||||||
Reference in New Issue
Block a user