Refactor: Use generic Define bound kind
This commit consolidates `DefLocal` and `DefGlobal` into a single `Define` bound kind. This simplifies the AST and makes it more consistent. It also introduces `DeclarationKind` to differentiate between variable and parameter definitions.
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
;; Benchmark: 962ns
|
||||||
|
;; Benchmark-Repeat: 2089
|
||||||
(do
|
(do
|
||||||
(def pipe (fn [conf]
|
(def pipe (fn [conf]
|
||||||
(do
|
(do
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ impl<'a> Analyzer<'a> {
|
|||||||
|
|
||||||
fn collect_globals(&mut self, node: &TypedNode) {
|
fn collect_globals(&mut self, node: &TypedNode) {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::DefGlobal {
|
BoundKind::Define {
|
||||||
global_index,
|
addr: Address::Global(global_index),
|
||||||
value,
|
value,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
@@ -61,13 +61,6 @@ impl<'a> Analyzer<'a> {
|
|||||||
let (new_kind, purity) = match &node.kind {
|
let (new_kind, purity) = match &node.kind {
|
||||||
BoundKind::Constant(v) => (BoundKind::Constant(v.clone()), Purity::Pure),
|
BoundKind::Constant(v) => (BoundKind::Constant(v.clone()), Purity::Pure),
|
||||||
BoundKind::Nop => (BoundKind::Nop, Purity::Pure),
|
BoundKind::Nop => (BoundKind::Nop, Purity::Pure),
|
||||||
BoundKind::Parameter { name, slot } => (
|
|
||||||
BoundKind::Parameter {
|
|
||||||
name: name.clone(),
|
|
||||||
slot: *slot,
|
|
||||||
},
|
|
||||||
Purity::Pure,
|
|
||||||
),
|
|
||||||
|
|
||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
let p = match addr {
|
let p = match addr {
|
||||||
@@ -96,18 +89,20 @@ impl<'a> Analyzer<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => {
|
} => {
|
||||||
let val_m = self.visit(Rc::new((**value).clone()));
|
let val_m = self.visit(Rc::new((**value).clone()));
|
||||||
let p = val_m.ty.purity;
|
let p = val_m.ty.purity;
|
||||||
(
|
(
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
slot: *slot,
|
addr: *addr,
|
||||||
|
kind: *kind,
|
||||||
value: Box::new(val_m),
|
value: Box::new(val_m),
|
||||||
captured_by: captured_by.clone(),
|
captured_by: captured_by.clone(),
|
||||||
},
|
},
|
||||||
@@ -115,23 +110,6 @@ impl<'a> Analyzer<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
let val_m = self.visit(Rc::new((**value).clone()));
|
|
||||||
let p = val_m.ty.purity;
|
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name: name.clone(),
|
|
||||||
global_index: *global_index,
|
|
||||||
value: Box::new(val_m),
|
|
||||||
},
|
|
||||||
p,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::If {
|
BoundKind::If {
|
||||||
cond,
|
cond,
|
||||||
then_br,
|
then_br,
|
||||||
@@ -327,9 +305,7 @@ impl NodeExt for BoundKind<crate::ast::types::StaticType> {
|
|||||||
f(e);
|
f(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::DefLocal { value, .. }
|
BoundKind::Define { value, .. } | BoundKind::Set { value, .. } => {
|
||||||
| BoundKind::DefGlobal { value, .. }
|
|
||||||
| BoundKind::Set { value, .. } => {
|
|
||||||
f(value);
|
f(value);
|
||||||
}
|
}
|
||||||
BoundKind::Lambda { params, body, .. } => {
|
BoundKind::Lambda { params, body, .. } => {
|
||||||
|
|||||||
+76
-84
@@ -1,4 +1,4 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode};
|
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, DeclarationKind};
|
||||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||||
use crate::ast::types::{Identity, StaticType};
|
use crate::ast::types::{Identity, StaticType};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -110,6 +110,26 @@ impl Binder {
|
|||||||
binder.bind(node)
|
binder.bind(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn declare_variable(
|
||||||
|
&mut self,
|
||||||
|
name: &Symbol,
|
||||||
|
_kind: crate::ast::compiler::bound_nodes::DeclarationKind,
|
||||||
|
) -> Result<Address, String> {
|
||||||
|
if self.functions.len() == 1 {
|
||||||
|
let mut globals = self.globals.borrow_mut();
|
||||||
|
if globals.contains_key(name) {
|
||||||
|
return Err(format!("Global variable '{}' is already defined.", name.name));
|
||||||
|
}
|
||||||
|
let idx = globals.len() as u32;
|
||||||
|
globals.insert(name.clone(), idx);
|
||||||
|
Ok(Address::Global(idx))
|
||||||
|
} else {
|
||||||
|
let current_fn = self.functions.last_mut().unwrap();
|
||||||
|
let slot = current_fn.scope.define(name)?;
|
||||||
|
Ok(Address::Local(slot))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bind(&mut self, node: &Node<UntypedKind>) -> Result<BoundNode, String> {
|
pub fn bind(&mut self, node: &Node<UntypedKind>) -> Result<BoundNode, String> {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
UntypedKind::Nop => Ok(self.make_node(node.identity.clone(), BoundKind::Nop)),
|
UntypedKind::Nop => Ok(self.make_node(node.identity.clone(), BoundKind::Nop)),
|
||||||
@@ -157,55 +177,33 @@ impl Binder {
|
|||||||
UntypedKind::Def { target, value } => {
|
UntypedKind::Def { target, value } => {
|
||||||
// Special case: Single identifier (to support recursion)
|
// Special case: Single identifier (to support recursion)
|
||||||
if let UntypedKind::Parameter(ref name) = target.kind {
|
if let UntypedKind::Parameter(ref name) = target.kind {
|
||||||
let slot_or_idx = if self.functions.len() == 1 {
|
let addr = self.declare_variable(
|
||||||
let mut globals = self.globals.borrow_mut();
|
name,
|
||||||
if globals.contains_key(name) {
|
crate::ast::compiler::bound_nodes::DeclarationKind::Variable,
|
||||||
return Err(format!(
|
)?;
|
||||||
"Global variable '{}' is already defined.",
|
|
||||||
name.name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let idx = globals.len() as u32;
|
|
||||||
globals.insert(name.clone(), idx);
|
|
||||||
idx
|
|
||||||
} else {
|
|
||||||
let current_fn = self.functions.last_mut().unwrap();
|
|
||||||
current_fn.scope.define(name)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let val_node = self.bind(value)?;
|
let val_node = self.bind(value)?;
|
||||||
|
let captured_by = self
|
||||||
|
.capture_map
|
||||||
|
.get(&target.identity)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
if self.functions.len() == 1 {
|
Ok(self.make_node(
|
||||||
Ok(self.make_node(
|
node.identity.clone(),
|
||||||
node.identity.clone(),
|
BoundKind::Define {
|
||||||
BoundKind::DefGlobal {
|
name: name.clone(),
|
||||||
name: name.clone(),
|
addr,
|
||||||
global_index: slot_or_idx,
|
kind: crate::ast::compiler::bound_nodes::DeclarationKind::Variable,
|
||||||
value: Box::new(val_node),
|
value: Box::new(val_node),
|
||||||
},
|
captured_by,
|
||||||
))
|
},
|
||||||
} else {
|
))
|
||||||
let captured_by = self
|
|
||||||
.capture_map
|
|
||||||
.get(&target.identity)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_default();
|
|
||||||
Ok(self.make_node(
|
|
||||||
node.identity.clone(),
|
|
||||||
BoundKind::DefLocal {
|
|
||||||
name: name.clone(),
|
|
||||||
slot: slot_or_idx,
|
|
||||||
value: Box::new(val_node),
|
|
||||||
captured_by,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Complex Destructuring Pattern
|
// Complex Destructuring Pattern
|
||||||
// NOTE: Destructuring definitions are NOT recursive by default
|
// NOTE: Destructuring definitions are NOT recursive by default
|
||||||
// (the variables are only available AFTER the definition)
|
// (the variables are only available AFTER the definition)
|
||||||
let val_node = self.bind(value)?;
|
let val_node = self.bind(value)?;
|
||||||
let target_node = self.bind_pattern(target)?;
|
let target_node = self.bind_pattern(target, DeclarationKind::Variable)?;
|
||||||
|
|
||||||
Ok(self.make_node(
|
Ok(self.make_node(
|
||||||
node.identity.clone(),
|
node.identity.clone(),
|
||||||
@@ -246,7 +244,7 @@ impl Binder {
|
|||||||
self.functions.push(FunctionCompiler::new());
|
self.functions.push(FunctionCompiler::new());
|
||||||
|
|
||||||
// 1. Bind the parameter pattern/tuple
|
// 1. Bind the parameter pattern/tuple
|
||||||
let params_bound = self.bind_pattern(params)?;
|
let params_bound = self.bind_pattern(params, DeclarationKind::Parameter)?;
|
||||||
|
|
||||||
// 2. Bind the body
|
// 2. Bind the body
|
||||||
let body_bound = self.bind(body)?;
|
let body_bound = self.bind(body)?;
|
||||||
@@ -256,7 +254,10 @@ impl Binder {
|
|||||||
// 3. Static optimization: count total parameters needed in flat argument list
|
// 3. Static optimization: count total parameters needed in flat argument list
|
||||||
fn count_params(node: &BoundNode) -> Option<u32> {
|
fn count_params(node: &BoundNode) -> Option<u32> {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Parameter { .. } => Some(1),
|
BoundKind::Define {
|
||||||
|
kind: DeclarationKind::Parameter,
|
||||||
|
..
|
||||||
|
} => Some(1),
|
||||||
BoundKind::Tuple { elements } => {
|
BoundKind::Tuple { elements } => {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
for e in elements {
|
for e in elements {
|
||||||
@@ -411,46 +412,35 @@ impl Binder {
|
|||||||
Err(format!("Undefined variable '{}'", sym.name))
|
Err(format!("Undefined variable '{}'", sym.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_pattern(&mut self, node: &Node<UntypedKind>) -> Result<BoundNode, String> {
|
fn bind_pattern(
|
||||||
|
&mut self,
|
||||||
|
node: &Node<UntypedKind>,
|
||||||
|
kind: DeclarationKind,
|
||||||
|
) -> Result<BoundNode, String> {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
UntypedKind::Parameter(sym) => {
|
UntypedKind::Parameter(sym) => {
|
||||||
if self.functions.len() == 1 {
|
let addr = self.declare_variable(sym, kind)?;
|
||||||
// Global Definition in pattern
|
let captured_by = self
|
||||||
let mut globals = self.globals.borrow_mut();
|
.capture_map
|
||||||
if globals.contains_key(sym) {
|
.get(&node.identity)
|
||||||
return Err(format!(
|
.cloned()
|
||||||
"Global variable '{}' is already defined.",
|
.unwrap_or_default();
|
||||||
sym.name
|
|
||||||
));
|
Ok(self.make_node(
|
||||||
}
|
node.identity.clone(),
|
||||||
let idx = globals.len() as u32;
|
BoundKind::Define {
|
||||||
globals.insert(sym.clone(), idx);
|
name: sym.clone(),
|
||||||
// For Global Destructuring, we return a DefGlobal with Nop value as it's a pattern part
|
addr,
|
||||||
Ok(self.make_node(
|
kind,
|
||||||
node.identity.clone(),
|
value: Box::new(self.make_node(node.identity.clone(), BoundKind::Nop)),
|
||||||
BoundKind::DefGlobal {
|
captured_by,
|
||||||
name: sym.clone(),
|
},
|
||||||
global_index: idx,
|
))
|
||||||
value: Box::new(self.make_node(node.identity.clone(), BoundKind::Nop)),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
// Local Parameter/Definition in pattern
|
|
||||||
let current_fn = self.functions.last_mut().unwrap();
|
|
||||||
let slot = current_fn.scope.define(sym)?;
|
|
||||||
Ok(self.make_node(
|
|
||||||
node.identity.clone(),
|
|
||||||
BoundKind::Parameter {
|
|
||||||
name: sym.clone(),
|
|
||||||
slot,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
UntypedKind::Tuple { elements } => {
|
UntypedKind::Tuple { elements } => {
|
||||||
let mut bound_elems = Vec::new();
|
let mut bound_elems = Vec::new();
|
||||||
for e in elements {
|
for e in elements {
|
||||||
bound_elems.push(self.bind_pattern(e)?);
|
bound_elems.push(self.bind_pattern(e, kind)?);
|
||||||
}
|
}
|
||||||
Ok(self.make_node(
|
Ok(self.make_node(
|
||||||
node.identity.clone(),
|
node.identity.clone(),
|
||||||
@@ -518,18 +508,19 @@ mod tests {
|
|||||||
let globals = Rc::new(RefCell::new(HashMap::new()));
|
let globals = Rc::new(RefCell::new(HashMap::new()));
|
||||||
let bound = Binder::bind_root(globals, &untyped).unwrap();
|
let bound = Binder::bind_root(globals, &untyped).unwrap();
|
||||||
|
|
||||||
// Structure: Lambda -> Block -> [ DefLocal(x), DefLocal(f), Get(x) ]
|
// Structure: Lambda -> Block -> [ Define(x), Define(f), Get(x) ]
|
||||||
if let BoundKind::Lambda { body, .. } = &bound.kind {
|
if let BoundKind::Lambda { body, .. } = &bound.kind {
|
||||||
if let BoundKind::Block { exprs } = &body.kind {
|
if let BoundKind::Block { exprs } = &body.kind {
|
||||||
let x_decl = &exprs[0];
|
let x_decl = &exprs[0];
|
||||||
if let BoundKind::DefLocal { captured_by, .. } = &x_decl.kind {
|
if let BoundKind::Define { captured_by, addr, .. } = &x_decl.kind {
|
||||||
|
assert!(matches!(addr, Address::Local(_)));
|
||||||
assert!(
|
assert!(
|
||||||
!captured_by.is_empty(),
|
!captured_by.is_empty(),
|
||||||
"Variable 'x' should have capturers because it is used in lambda 'f'"
|
"Variable 'x' should have capturers because it is used in lambda 'f'"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"First expression in block should be DefLocal, got {:?}",
|
"First expression in block should be Define, got {:?}",
|
||||||
x_decl.kind
|
x_decl.kind
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -553,13 +544,14 @@ mod tests {
|
|||||||
if let BoundKind::Lambda { body, .. } = &bound.kind {
|
if let BoundKind::Lambda { body, .. } = &bound.kind {
|
||||||
if let BoundKind::Block { exprs } = &body.kind {
|
if let BoundKind::Block { exprs } = &body.kind {
|
||||||
let x_decl = &exprs[0];
|
let x_decl = &exprs[0];
|
||||||
if let BoundKind::DefLocal { captured_by, .. } = &x_decl.kind {
|
if let BoundKind::Define { captured_by, addr, .. } = &x_decl.kind {
|
||||||
|
assert!(matches!(addr, Address::Local(_)));
|
||||||
assert!(
|
assert!(
|
||||||
captured_by.is_empty(),
|
captured_by.is_empty(),
|
||||||
"Variable 'x' should NOT have any capturers"
|
"Variable 'x' should NOT have any capturers"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("First expression should be DefLocal");
|
panic!("First expression should be Define");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("Lambda body should be a Block");
|
panic!("Lambda body should be a Block");
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ pub enum Address {
|
|||||||
Global(u32), // Index in the global environment vector
|
Global(u32), // Index in the global environment vector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum DeclarationKind {
|
||||||
|
Variable,
|
||||||
|
Parameter,
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait for DSL-specific AST extensions (like Pipe, Series-Access, etc.)
|
/// Trait for DSL-specific AST extensions (like Pipe, Series-Access, etc.)
|
||||||
pub trait BoundExtension<T>: std::fmt::Debug {
|
pub trait BoundExtension<T>: std::fmt::Debug {
|
||||||
fn clone_box(&self) -> Box<dyn BoundExtension<T>>;
|
fn clone_box(&self) -> Box<dyn BoundExtension<T>>;
|
||||||
@@ -43,12 +49,6 @@ pub enum BoundKind<T = ()> {
|
|||||||
Nop,
|
Nop,
|
||||||
Constant(Value),
|
Constant(Value),
|
||||||
|
|
||||||
/// A positional parameter in a Lambda's parameter list.
|
|
||||||
Parameter {
|
|
||||||
name: Symbol,
|
|
||||||
slot: u32,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Variable Access (Resolved)
|
// Variable Access (Resolved)
|
||||||
Get {
|
Get {
|
||||||
addr: Address,
|
addr: Address,
|
||||||
@@ -61,10 +61,11 @@ pub enum BoundKind<T = ()> {
|
|||||||
value: Box<BoundNode<T>>,
|
value: Box<BoundNode<T>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Variable Declaration (Local)
|
// Variable Declaration (Unified for Local/Global/Parameter)
|
||||||
DefLocal {
|
Define {
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
slot: u32,
|
addr: Address,
|
||||||
|
kind: DeclarationKind,
|
||||||
value: Box<BoundNode<T>>,
|
value: Box<BoundNode<T>>,
|
||||||
captured_by: Vec<Identity>,
|
captured_by: Vec<Identity>,
|
||||||
},
|
},
|
||||||
@@ -75,13 +76,6 @@ pub enum BoundKind<T = ()> {
|
|||||||
else_br: Option<Box<BoundNode<T>>>,
|
else_br: Option<Box<BoundNode<T>>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Global Definition (Locals are implicit by stack position)
|
|
||||||
DefGlobal {
|
|
||||||
name: Symbol,
|
|
||||||
global_index: u32,
|
|
||||||
value: Box<BoundNode<T>>,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// A destructuring operation (can be a definition or an assignment depending on the pattern)
|
/// A destructuring operation (can be a definition or an assignment depending on the pattern)
|
||||||
Destructure {
|
Destructure {
|
||||||
pattern: Box<BoundNode<T>>,
|
pattern: Box<BoundNode<T>>,
|
||||||
@@ -138,10 +132,6 @@ where
|
|||||||
match (self, other) {
|
match (self, other) {
|
||||||
(BoundKind::Nop, BoundKind::Nop) => true,
|
(BoundKind::Nop, BoundKind::Nop) => true,
|
||||||
(BoundKind::Constant(a), BoundKind::Constant(b)) => a == b,
|
(BoundKind::Constant(a), BoundKind::Constant(b)) => a == b,
|
||||||
(
|
|
||||||
BoundKind::Parameter { name: na, slot: sa },
|
|
||||||
BoundKind::Parameter { name: nb, slot: sb },
|
|
||||||
) => na == nb && sa == sb,
|
|
||||||
(BoundKind::Get { addr: aa, name: na }, BoundKind::Get { addr: ab, name: nb }) => {
|
(BoundKind::Get { addr: aa, name: na }, BoundKind::Get { addr: ab, name: nb }) => {
|
||||||
aa == ab && na == nb
|
aa == ab && na == nb
|
||||||
}
|
}
|
||||||
@@ -156,19 +146,21 @@ where
|
|||||||
},
|
},
|
||||||
) => aa == ab && va == vb,
|
) => aa == ab && va == vb,
|
||||||
(
|
(
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name: na,
|
name: na,
|
||||||
slot: sa,
|
addr: aa,
|
||||||
|
kind: ka,
|
||||||
value: va,
|
value: va,
|
||||||
captured_by: ca,
|
captured_by: ca,
|
||||||
},
|
},
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name: nb,
|
name: nb,
|
||||||
slot: sb,
|
addr: ab,
|
||||||
|
kind: kb,
|
||||||
value: vb,
|
value: vb,
|
||||||
captured_by: cb,
|
captured_by: cb,
|
||||||
},
|
},
|
||||||
) => na == nb && sa == sb && va == vb && ca == cb,
|
) => na == nb && aa == ab && ka == kb && va == vb && ca == cb,
|
||||||
(
|
(
|
||||||
BoundKind::If {
|
BoundKind::If {
|
||||||
cond: ca,
|
cond: ca,
|
||||||
@@ -181,18 +173,6 @@ where
|
|||||||
else_br: eb,
|
else_br: eb,
|
||||||
},
|
},
|
||||||
) => ca == cb && ta == tb && ea == eb,
|
) => ca == cb && ta == tb && ea == eb,
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name: na,
|
|
||||||
global_index: ga,
|
|
||||||
value: va,
|
|
||||||
},
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name: nb,
|
|
||||||
global_index: gb,
|
|
||||||
value: vb,
|
|
||||||
},
|
|
||||||
) => na == nb && ga == gb && va == vb,
|
|
||||||
(
|
(
|
||||||
BoundKind::Destructure {
|
BoundKind::Destructure {
|
||||||
pattern: pa,
|
pattern: pa,
|
||||||
@@ -255,16 +235,16 @@ impl<T> BoundKind<T> {
|
|||||||
match self {
|
match self {
|
||||||
BoundKind::Nop => "NOP".to_string(),
|
BoundKind::Nop => "NOP".to_string(),
|
||||||
BoundKind::Constant(v) => format!("CONST({})", v),
|
BoundKind::Constant(v) => format!("CONST({})", v),
|
||||||
BoundKind::Parameter { name, slot } => format!("PARAM({}, Slot:{})", name.name, slot),
|
|
||||||
BoundKind::Get { addr, name } => format!("GET({}, {:?})", name.name, addr),
|
BoundKind::Get { addr, name } => format!("GET({}, {:?})", name.name, addr),
|
||||||
BoundKind::Set { addr, .. } => format!("SET({:?})", addr),
|
BoundKind::Set { addr, .. } => format!("SET({:?})", addr),
|
||||||
BoundKind::DefLocal { name, slot, .. } => {
|
BoundKind::Define { name, addr, kind, .. } => {
|
||||||
format!("DEF_LOCAL({}, Slot:{})", name.name, slot)
|
let k_str = match kind {
|
||||||
|
DeclarationKind::Variable => "VAR",
|
||||||
|
DeclarationKind::Parameter => "PARAM",
|
||||||
|
};
|
||||||
|
format!("DEF_{}({}, {:?})", k_str, name.name, addr)
|
||||||
}
|
}
|
||||||
BoundKind::If { .. } => "IF".to_string(),
|
BoundKind::If { .. } => "IF".to_string(),
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name, global_index, ..
|
|
||||||
} => format!("DEF_GLOBAL({}, Idx:{})", name.name, global_index),
|
|
||||||
BoundKind::Destructure { .. } => "DESTRUCTURE".to_string(),
|
BoundKind::Destructure { .. } => "DESTRUCTURE".to_string(),
|
||||||
BoundKind::Lambda {
|
BoundKind::Lambda {
|
||||||
params, upvalues, ..
|
params, upvalues, ..
|
||||||
|
|||||||
@@ -73,12 +73,17 @@ impl Dumper {
|
|||||||
self.indent -= 1;
|
self.indent -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => {
|
} => {
|
||||||
|
let k_str = match kind {
|
||||||
|
crate::ast::compiler::bound_nodes::DeclarationKind::Variable => "Variable",
|
||||||
|
crate::ast::compiler::bound_nodes::DeclarationKind::Parameter => "Parameter",
|
||||||
|
};
|
||||||
let capture_info = if captured_by.is_empty() {
|
let capture_info = if captured_by.is_empty() {
|
||||||
String::from("not captured")
|
String::from("not captured")
|
||||||
} else {
|
} else {
|
||||||
@@ -86,8 +91,8 @@ impl Dumper {
|
|||||||
};
|
};
|
||||||
self.log(
|
self.log(
|
||||||
&format!(
|
&format!(
|
||||||
"DefLocal (Name: '{}', Slot: {}, {})",
|
"Define {} (Name: '{}', Address: {:?}, {})",
|
||||||
name.name, slot, capture_info
|
k_str, name.name, addr, capture_info
|
||||||
),
|
),
|
||||||
node,
|
node,
|
||||||
);
|
);
|
||||||
@@ -106,20 +111,6 @@ impl Dumper {
|
|||||||
self.indent -= 1;
|
self.indent -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
self.log(
|
|
||||||
&format!("DefGlobal (Name: '{}', Index: {})", name.name, global_index),
|
|
||||||
node,
|
|
||||||
);
|
|
||||||
self.indent += 1;
|
|
||||||
self.visit(value);
|
|
||||||
self.indent -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::Destructure { pattern, value } => {
|
BoundKind::Destructure { pattern, value } => {
|
||||||
self.log("Destructure", node);
|
self.log("Destructure", node);
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
@@ -177,13 +168,6 @@ impl Dumper {
|
|||||||
self.indent -= 1;
|
self.indent -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Parameter { name, slot } => {
|
|
||||||
self.log(
|
|
||||||
&format!("Parameter (Name: '{}', Slot: {})", name.name, slot),
|
|
||||||
node,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::Call { callee, args } => {
|
BoundKind::Call { callee, args } => {
|
||||||
self.log("Call", node);
|
self.log("Call", node);
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
|
|||||||
@@ -22,13 +22,11 @@ impl<'a, T: Clone> LambdaCollector<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefGlobal {
|
BoundKind::Define { addr, value, .. } => {
|
||||||
global_index,
|
// Register global function definitions (lambdas)
|
||||||
value,
|
if let Address::Global(global_index) = addr
|
||||||
..
|
&& let BoundKind::Lambda { .. } = &value.kind
|
||||||
} => {
|
{
|
||||||
// Register the full Lambda node as the template.
|
|
||||||
if let BoundKind::Lambda { .. } = &value.kind {
|
|
||||||
self.registry
|
self.registry
|
||||||
.insert(*global_index, (*value).as_ref().clone());
|
.insert(*global_index, (*value).as_ref().clone());
|
||||||
}
|
}
|
||||||
@@ -63,10 +61,6 @@ impl<'a, T: Clone> LambdaCollector<'a, T> {
|
|||||||
self.visit(body);
|
self.visit(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefLocal { value, .. } => {
|
|
||||||
self.visit(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::Call { callee, args } => {
|
BoundKind::Call { callee, args } => {
|
||||||
self.visit(callee);
|
self.visit(callee);
|
||||||
self.visit(args);
|
self.visit(args);
|
||||||
|
|||||||
+77
-115
@@ -99,12 +99,15 @@ impl Optimizer {
|
|||||||
|
|
||||||
fn collect_pattern_usage(&self, node: &AnalyzedNode, info: &mut UsageInfo) {
|
fn collect_pattern_usage(&self, node: &AnalyzedNode, info: &mut UsageInfo) {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Parameter { slot, .. } => {
|
BoundKind::Define { addr, .. } => match addr {
|
||||||
info.assigned_locals.insert(*slot);
|
Address::Local(slot) => {
|
||||||
}
|
info.assigned_locals.insert(*slot);
|
||||||
BoundKind::DefGlobal { global_index, .. } => {
|
}
|
||||||
info.assigned_globals.insert(*global_index);
|
Address::Global(idx) => {
|
||||||
}
|
info.assigned_globals.insert(*idx);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
BoundKind::Set { addr, .. } => match addr {
|
BoundKind::Set { addr, .. } => match addr {
|
||||||
Address::Local(slot) => {
|
Address::Local(slot) => {
|
||||||
info.assigned_locals.insert(*slot);
|
info.assigned_locals.insert(*slot);
|
||||||
@@ -181,12 +184,40 @@ impl Optimizer {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Parameter { ref name, slot } => {
|
BoundKind::Define {
|
||||||
let new_slot = sub.map_slot(slot);
|
ref name,
|
||||||
|
addr,
|
||||||
|
kind,
|
||||||
|
ref value,
|
||||||
|
ref captured_by,
|
||||||
|
} => {
|
||||||
|
let value = Box::new(self.visit_node(*value.clone(), sub, path));
|
||||||
|
let new_addr = match addr {
|
||||||
|
Address::Local(slot) => {
|
||||||
|
if let BoundKind::Constant(val) = &value.kind {
|
||||||
|
sub.add_local(slot, val.clone());
|
||||||
|
} else {
|
||||||
|
sub.locals.remove(&slot);
|
||||||
|
}
|
||||||
|
Address::Local(sub.map_slot(slot))
|
||||||
|
}
|
||||||
|
Address::Global(idx) => {
|
||||||
|
if let BoundKind::Constant(val) = &value.kind {
|
||||||
|
sub.add_global(idx, val.clone());
|
||||||
|
} else {
|
||||||
|
sub.globals.remove(&idx);
|
||||||
|
}
|
||||||
|
Address::Global(idx)
|
||||||
|
}
|
||||||
|
_ => addr,
|
||||||
|
};
|
||||||
(
|
(
|
||||||
BoundKind::Parameter {
|
BoundKind::Define {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
slot: new_slot,
|
addr: new_addr,
|
||||||
|
kind,
|
||||||
|
value,
|
||||||
|
captured_by: captured_by.clone(),
|
||||||
},
|
},
|
||||||
node.ty.clone(),
|
node.ty.clone(),
|
||||||
)
|
)
|
||||||
@@ -407,20 +438,19 @@ impl Optimizer {
|
|||||||
let is_last = i == last_idx;
|
let is_last = i == last_idx;
|
||||||
if self.enabled && !is_last {
|
if self.enabled && !is_last {
|
||||||
let removable = match &e.kind {
|
let removable = match &e.kind {
|
||||||
BoundKind::DefLocal { slot, value, .. } => {
|
BoundKind::Define { addr, value, .. } => match addr {
|
||||||
!info.used_locals.contains(slot)
|
Address::Local(slot) => {
|
||||||
&& !sub.captured_slots.contains(slot)
|
!info.used_locals.contains(slot)
|
||||||
&& value.ty.purity >= Purity::SideEffectFree
|
&& !sub.captured_slots.contains(slot)
|
||||||
}
|
&& value.ty.purity >= Purity::SideEffectFree
|
||||||
BoundKind::DefGlobal {
|
}
|
||||||
global_index,
|
Address::Global(global_index) => {
|
||||||
value,
|
!info.used_globals.contains(global_index)
|
||||||
..
|
&& (value.ty.purity >= Purity::SideEffectFree
|
||||||
} => {
|
|| matches!(value.kind, BoundKind::Lambda { .. }))
|
||||||
!info.used_globals.contains(global_index)
|
}
|
||||||
&& (value.ty.purity >= Purity::SideEffectFree
|
_ => false,
|
||||||
|| matches!(value.kind, BoundKind::Lambda { .. }))
|
},
|
||||||
}
|
|
||||||
BoundKind::Set {
|
BoundKind::Set {
|
||||||
addr: Address::Local(slot),
|
addr: Address::Local(slot),
|
||||||
value,
|
value,
|
||||||
@@ -536,61 +566,6 @@ impl Optimizer {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefLocal {
|
|
||||||
ref name,
|
|
||||||
slot,
|
|
||||||
ref value,
|
|
||||||
ref captured_by,
|
|
||||||
} => {
|
|
||||||
if !captured_by.is_empty() {
|
|
||||||
sub.captured_slots.insert(slot);
|
|
||||||
}
|
|
||||||
let value_opt = Box::new(self.visit_node((**value).clone(), sub, path));
|
|
||||||
if let BoundKind::Constant(val) = &value_opt.kind {
|
|
||||||
sub.add_local(slot, val.clone());
|
|
||||||
} else {
|
|
||||||
sub.locals.remove(&slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_slot = sub.map_slot(slot);
|
|
||||||
(
|
|
||||||
BoundKind::DefLocal {
|
|
||||||
name: name.clone(),
|
|
||||||
slot: new_slot,
|
|
||||||
value: value_opt,
|
|
||||||
captured_by: captured_by.clone(),
|
|
||||||
},
|
|
||||||
node.ty.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
ref name,
|
|
||||||
global_index,
|
|
||||||
ref value,
|
|
||||||
} => {
|
|
||||||
let value_opt = Box::new(self.visit_node((**value).clone(), sub, path));
|
|
||||||
if let BoundKind::Constant(val) = &value_opt.kind
|
|
||||||
&& self.is_inlinable_value(val, Some(global_index))
|
|
||||||
{
|
|
||||||
sub.add_global(global_index, val.clone());
|
|
||||||
}
|
|
||||||
let p = value_opt.ty.purity;
|
|
||||||
if p > Purity::Impure
|
|
||||||
&& let Some(purity_rc) = &self.global_purity
|
|
||||||
{
|
|
||||||
purity_rc.borrow_mut().insert(global_index, p);
|
|
||||||
}
|
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name: name.clone(),
|
|
||||||
global_index,
|
|
||||||
value: value_opt,
|
|
||||||
},
|
|
||||||
node.ty.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::Destructure {
|
BoundKind::Destructure {
|
||||||
ref pattern,
|
ref pattern,
|
||||||
ref value,
|
ref value,
|
||||||
@@ -658,7 +633,7 @@ impl Optimizer {
|
|||||||
|
|
||||||
fn collect_parameter_slots(&self, node: &AnalyzedNode, sub: &mut SubstitutionMap) {
|
fn collect_parameter_slots(&self, node: &AnalyzedNode, sub: &mut SubstitutionMap) {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Parameter { slot, .. } => {
|
BoundKind::Define { addr: Address::Local(slot), .. } => {
|
||||||
sub.slot_mapping.insert(*slot, *slot);
|
sub.slot_mapping.insert(*slot, *slot);
|
||||||
sub.next_slot = sub.next_slot.max(*slot + 1);
|
sub.next_slot = sub.next_slot.max(*slot + 1);
|
||||||
}
|
}
|
||||||
@@ -805,7 +780,7 @@ impl Optimizer {
|
|||||||
|
|
||||||
fn collect_parameter_slots_set(&self, node: &AnalyzedNode, slots: &mut HashSet<u32>) {
|
fn collect_parameter_slots_set(&self, node: &AnalyzedNode, slots: &mut HashSet<u32>) {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Parameter { slot, .. } => {
|
BoundKind::Define { addr: Address::Local(slot), .. } => {
|
||||||
slots.insert(*slot);
|
slots.insert(*slot);
|
||||||
}
|
}
|
||||||
BoundKind::Tuple { elements } => {
|
BoundKind::Tuple { elements } => {
|
||||||
@@ -843,22 +818,22 @@ impl Optimizer {
|
|||||||
body_usage: &UsageInfo,
|
body_usage: &UsageInfo,
|
||||||
) {
|
) {
|
||||||
match &pattern.kind {
|
match &pattern.kind {
|
||||||
BoundKind::Parameter { slot, .. } => {
|
BoundKind::Define { addr: Address::Local(slot), .. } => {
|
||||||
if let Some(arg) = args.get(*offset) {
|
if let Some(arg) = args.get(*offset)
|
||||||
if !body_usage.assigned_locals.contains(slot) {
|
&& !body_usage.assigned_locals.contains(slot)
|
||||||
if let BoundKind::Constant(val) = &arg.kind {
|
{
|
||||||
sub.add_local(*slot, val.clone());
|
if let BoundKind::Constant(val) = &arg.kind {
|
||||||
} else if let BoundKind::Lambda { upvalues, .. } = &arg.kind {
|
sub.add_local(*slot, val.clone());
|
||||||
if upvalues.is_empty() {
|
} else if let BoundKind::Lambda { upvalues, .. } = &arg.kind {
|
||||||
sub.add_ast_local(*slot, arg.clone());
|
if upvalues.is_empty() {
|
||||||
}
|
|
||||||
} else if let BoundKind::Get {
|
|
||||||
addr: Address::Global(_),
|
|
||||||
..
|
|
||||||
} = &arg.kind
|
|
||||||
{
|
|
||||||
sub.add_ast_local(*slot, arg.clone());
|
sub.add_ast_local(*slot, arg.clone());
|
||||||
}
|
}
|
||||||
|
} else if let BoundKind::Get {
|
||||||
|
addr: Address::Global(_),
|
||||||
|
..
|
||||||
|
} = &arg.kind
|
||||||
|
{
|
||||||
|
sub.add_ast_local(*slot, arg.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sub.slot_mapping.insert(*slot, *slot);
|
sub.slot_mapping.insert(*slot, *slot);
|
||||||
@@ -1025,7 +1000,7 @@ impl Optimizer {
|
|||||||
self.collect_usage(v, info);
|
self.collect_usage(v, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::DefLocal { value, .. } | BoundKind::DefGlobal { value, .. } => {
|
BoundKind::Define { value, .. } => {
|
||||||
self.collect_usage(value, info);
|
self.collect_usage(value, info);
|
||||||
}
|
}
|
||||||
BoundKind::Expansion { bound_expanded, .. } => {
|
BoundKind::Expansion { bound_expanded, .. } => {
|
||||||
@@ -1171,38 +1146,25 @@ impl SubstitutionMap {
|
|||||||
let args = Box::new(self.reindex_upvalues(*args, mapping));
|
let args = Box::new(self.reindex_upvalues(*args, mapping));
|
||||||
(BoundKind::Call { callee, args }, node.ty.clone())
|
(BoundKind::Call { callee, args }, node.ty.clone())
|
||||||
}
|
}
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => {
|
} => {
|
||||||
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
||||||
(
|
(
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
},
|
},
|
||||||
node.ty.clone(),
|
node.ty.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
},
|
|
||||||
node.ty.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BoundKind::Set { addr, value } => {
|
BoundKind::Set { addr, value } => {
|
||||||
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
let value = Box::new(self.reindex_upvalues(*value, mapping));
|
||||||
(BoundKind::Set { addr, value }, node.ty.clone())
|
(BoundKind::Set { addr, value }, node.ty.clone())
|
||||||
|
|||||||
@@ -104,34 +104,21 @@ impl Specializer {
|
|||||||
node.ty.clone(),
|
node.ty.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => {
|
} => {
|
||||||
let value = Box::new(self.visit_node(*value));
|
let value = Box::new(self.visit_node(*value));
|
||||||
(
|
(
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name: name.clone(),
|
||||||
slot,
|
addr,
|
||||||
value,
|
kind,
|
||||||
captured_by,
|
|
||||||
},
|
|
||||||
node.ty.clone(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
let value = Box::new(self.visit_node(*value));
|
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
value,
|
||||||
|
captured_by: captured_by.clone(),
|
||||||
},
|
},
|
||||||
node.ty.clone(),
|
node.ty.clone(),
|
||||||
)
|
)
|
||||||
|
|||||||
+6
-17
@@ -98,26 +98,19 @@ impl TCO {
|
|||||||
addr: *addr,
|
addr: *addr,
|
||||||
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
||||||
},
|
},
|
||||||
BoundKind::DefLocal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
slot,
|
addr,
|
||||||
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => BoundKind::DefLocal {
|
} => BoundKind::Define {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
slot: *slot,
|
addr: *addr,
|
||||||
|
kind: *kind,
|
||||||
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
||||||
captured_by: captured_by.clone(),
|
captured_by: captured_by.clone(),
|
||||||
},
|
},
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => BoundKind::DefGlobal {
|
|
||||||
name: name.clone(),
|
|
||||||
global_index: *global_index,
|
|
||||||
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
|
||||||
},
|
|
||||||
BoundKind::Destructure { pattern, value } => BoundKind::Destructure {
|
BoundKind::Destructure { pattern, value } => BoundKind::Destructure {
|
||||||
pattern: Box::new(Self::transform(Rc::new((**pattern).clone()), false)),
|
pattern: Box::new(Self::transform(Rc::new((**pattern).clone()), false)),
|
||||||
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
value: Box::new(Self::transform(Rc::new((**value).clone()), false)),
|
||||||
@@ -143,10 +136,6 @@ impl TCO {
|
|||||||
elements: new_elements,
|
elements: new_elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Parameter { name, slot } => BoundKind::Parameter {
|
|
||||||
name: name.clone(),
|
|
||||||
slot: *slot,
|
|
||||||
},
|
|
||||||
BoundKind::Constant(v) => BoundKind::Constant(v.clone()),
|
BoundKind::Constant(v) => BoundKind::Constant(v.clone()),
|
||||||
BoundKind::Get { addr, name } => BoundKind::Get {
|
BoundKind::Get { addr, name } => BoundKind::Get {
|
||||||
addr: *addr,
|
addr: *addr,
|
||||||
|
|||||||
@@ -140,25 +140,33 @@ impl TypeChecker {
|
|||||||
ctx: &mut TypeContext,
|
ctx: &mut TypeContext,
|
||||||
) -> Result<TypedNode, String> {
|
) -> Result<TypedNode, String> {
|
||||||
let (kind, ty) = match node.kind {
|
let (kind, ty) = match node.kind {
|
||||||
BoundKind::Parameter { name, slot } => {
|
BoundKind::Define {
|
||||||
ctx.set_local_type(slot, specialized_ty.clone());
|
name,
|
||||||
(BoundKind::Parameter { name, slot }, specialized_ty.clone())
|
addr,
|
||||||
}
|
kind: decl_kind,
|
||||||
BoundKind::DefGlobal {
|
captured_by,
|
||||||
name, global_index, ..
|
..
|
||||||
} => {
|
} => {
|
||||||
self.global_types
|
match addr {
|
||||||
.borrow_mut()
|
Address::Local(slot) => ctx.set_local_type(slot, specialized_ty.clone()),
|
||||||
.insert(global_index, specialized_ty.clone());
|
Address::Global(global_index) => {
|
||||||
|
self.global_types
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(global_index, specialized_ty.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
(
|
(
|
||||||
BoundKind::DefGlobal {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
global_index,
|
addr,
|
||||||
|
kind: decl_kind,
|
||||||
value: Box::new(Node {
|
value: Box::new(Node {
|
||||||
identity: node.identity.clone(),
|
identity: node.identity.clone(),
|
||||||
kind: BoundKind::Nop,
|
kind: BoundKind::Nop,
|
||||||
ty: StaticType::Void,
|
ty: specialized_ty.clone(),
|
||||||
}),
|
}),
|
||||||
|
captured_by,
|
||||||
},
|
},
|
||||||
specialized_ty.clone(),
|
specialized_ty.clone(),
|
||||||
)
|
)
|
||||||
@@ -244,10 +252,37 @@ impl TypeChecker {
|
|||||||
(BoundKind::Constant(v), ty)
|
(BoundKind::Constant(v), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Parameter { name, slot } => (
|
BoundKind::Define {
|
||||||
BoundKind::Parameter { name, slot },
|
name,
|
||||||
ctx.get_type(Address::Local(slot)),
|
addr,
|
||||||
),
|
kind: decl_kind,
|
||||||
|
value,
|
||||||
|
captured_by,
|
||||||
|
} => {
|
||||||
|
let val_typed = self.check_node(*value, ctx)?;
|
||||||
|
let ty = val_typed.ty.clone();
|
||||||
|
|
||||||
|
match addr {
|
||||||
|
Address::Local(slot) => ctx.set_local_type(slot, ty.clone()),
|
||||||
|
Address::Global(global_index) => {
|
||||||
|
self.global_types
|
||||||
|
.borrow_mut()
|
||||||
|
.insert(global_index, ty.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
BoundKind::Define {
|
||||||
|
name,
|
||||||
|
addr,
|
||||||
|
kind: decl_kind,
|
||||||
|
value: Box::new(val_typed),
|
||||||
|
captured_by,
|
||||||
|
},
|
||||||
|
ty,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
let ty = if let Address::Global(idx) = addr {
|
let ty = if let Address::Global(idx) = addr {
|
||||||
@@ -259,7 +294,7 @@ impl TypeChecker {
|
|||||||
} else {
|
} else {
|
||||||
ctx.get_type(addr)
|
ctx.get_type(addr)
|
||||||
};
|
};
|
||||||
(BoundKind::Get { addr, name }, ty)
|
(BoundKind::Get { addr, name: name.clone() }, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Set { addr, value } => {
|
BoundKind::Set { addr, value } => {
|
||||||
@@ -281,48 +316,6 @@ impl TypeChecker {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::DefLocal {
|
|
||||||
name,
|
|
||||||
slot,
|
|
||||||
value,
|
|
||||||
captured_by,
|
|
||||||
} => {
|
|
||||||
let val_typed = self.check_node(*value, ctx)?;
|
|
||||||
let ty = val_typed.ty.clone();
|
|
||||||
ctx.set_local_type(slot, ty.clone());
|
|
||||||
|
|
||||||
(
|
|
||||||
BoundKind::DefLocal {
|
|
||||||
name,
|
|
||||||
slot,
|
|
||||||
value: Box::new(val_typed),
|
|
||||||
captured_by,
|
|
||||||
},
|
|
||||||
ty,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value,
|
|
||||||
} => {
|
|
||||||
let val_typed = self.check_node(*value, ctx)?;
|
|
||||||
let ty = val_typed.ty.clone();
|
|
||||||
self.global_types
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(global_index, ty.clone());
|
|
||||||
|
|
||||||
(
|
|
||||||
BoundKind::DefGlobal {
|
|
||||||
name,
|
|
||||||
global_index,
|
|
||||||
value: Box::new(val_typed),
|
|
||||||
},
|
|
||||||
ty,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BoundKind::Destructure { pattern, value } => {
|
BoundKind::Destructure { pattern, value } => {
|
||||||
let val_typed = self.check_node(*value, ctx)?;
|
let val_typed = self.check_node(*value, ctx)?;
|
||||||
let pat_typed = self.check_params(*pattern, &val_typed.ty, ctx)?;
|
let pat_typed = self.check_params(*pattern, &val_typed.ty, ctx)?;
|
||||||
|
|||||||
+13
-56
@@ -103,7 +103,7 @@ impl VMObserver for TracingObserver {
|
|||||||
self.indent = self.indent.saturating_sub(1);
|
self.indent = self.indent.saturating_sub(1);
|
||||||
let pad = self.pad();
|
let pad = self.pad();
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::DefLocal { .. } | BoundKind::Set { .. } | BoundKind::DefGlobal { .. } => {
|
BoundKind::Define { .. } | BoundKind::Set { .. } => {
|
||||||
let s_pad = format!("{}| ", pad);
|
let s_pad = format!("{}| ", pad);
|
||||||
self.logs.push(format!("{}--- Scope Status ---", s_pad));
|
self.logs.push(format!("{}--- Scope Status ---", s_pad));
|
||||||
self.logs.push(format!(
|
self.logs.push(format!(
|
||||||
@@ -266,20 +266,20 @@ impl VM {
|
|||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Nop => Ok(Value::Void),
|
BoundKind::Nop => Ok(Value::Void),
|
||||||
BoundKind::Constant(v) => Ok(v.clone()),
|
BoundKind::Constant(v) => Ok(v.clone()),
|
||||||
BoundKind::Parameter { .. } => Ok(Value::Void),
|
BoundKind::Define {
|
||||||
BoundKind::DefGlobal {
|
addr,
|
||||||
global_index,
|
|
||||||
value,
|
value,
|
||||||
|
captured_by,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let val = self.eval_internal(obs, value)?;
|
let val = self.eval_internal(obs, value)?;
|
||||||
let idx = *global_index as usize;
|
let final_val = if !captured_by.is_empty() && matches!(addr, Address::Local(_)) {
|
||||||
let mut globals = self.globals.borrow_mut();
|
Value::Cell(Rc::new(RefCell::new(val)))
|
||||||
if idx >= globals.len() {
|
} else {
|
||||||
globals.resize(idx + 1, Value::Void);
|
val
|
||||||
}
|
};
|
||||||
globals[idx] = val.clone();
|
self.set_value(*addr, final_val.clone())?;
|
||||||
Ok(val)
|
Ok(final_val)
|
||||||
}
|
}
|
||||||
BoundKind::Destructure { pattern, value } => {
|
BoundKind::Destructure { pattern, value } => {
|
||||||
let val = self.eval_internal(obs, value)?;
|
let val = self.eval_internal(obs, value)?;
|
||||||
@@ -299,29 +299,6 @@ impl VM {
|
|||||||
self.set_value(*addr, val.clone())?;
|
self.set_value(*addr, val.clone())?;
|
||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
BoundKind::DefLocal {
|
|
||||||
slot,
|
|
||||||
value,
|
|
||||||
captured_by,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let val = self.eval_internal(obs, value)?;
|
|
||||||
let final_val = if !captured_by.is_empty() {
|
|
||||||
Value::Cell(Rc::new(RefCell::new(val)))
|
|
||||||
} else {
|
|
||||||
val
|
|
||||||
};
|
|
||||||
let frame = self.frames.last().ok_or("No call frame")?;
|
|
||||||
let abs_index = frame.stack_base + (*slot as usize);
|
|
||||||
if abs_index == self.stack.len() {
|
|
||||||
self.stack.push(final_val.clone());
|
|
||||||
} else if abs_index < self.stack.len() {
|
|
||||||
self.stack[abs_index] = final_val.clone();
|
|
||||||
} else {
|
|
||||||
return Err(format!("Stack gap at local {}", slot));
|
|
||||||
}
|
|
||||||
Ok(final_val)
|
|
||||||
}
|
|
||||||
BoundKind::If {
|
BoundKind::If {
|
||||||
cond,
|
cond,
|
||||||
then_br,
|
then_br,
|
||||||
@@ -689,30 +666,10 @@ impl VM {
|
|||||||
offset: &mut usize,
|
offset: &mut usize,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
match &pattern.kind {
|
match &pattern.kind {
|
||||||
BoundKind::Parameter { slot, .. } => {
|
BoundKind::Define { addr, .. } => {
|
||||||
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
||||||
*offset += 1;
|
*offset += 1;
|
||||||
let frame = self.frames.last().ok_or("No call frame")?;
|
self.set_value(*addr, val)
|
||||||
let abs_index = frame.stack_base + (*slot as usize);
|
|
||||||
if abs_index == self.stack.len() {
|
|
||||||
self.stack.push(val);
|
|
||||||
} else if abs_index < self.stack.len() {
|
|
||||||
self.stack[abs_index] = val;
|
|
||||||
} else {
|
|
||||||
return Err(format!("Stack gap during unpack at slot {}", slot));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
BoundKind::DefGlobal { global_index, .. } => {
|
|
||||||
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
|
||||||
*offset += 1;
|
|
||||||
let idx = *global_index as usize;
|
|
||||||
let mut globals = self.globals.borrow_mut();
|
|
||||||
if idx >= globals.len() {
|
|
||||||
globals.resize(idx + 1, Value::Void);
|
|
||||||
}
|
|
||||||
globals[idx] = val;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
BoundKind::Set { addr, .. } => {
|
BoundKind::Set { addr, .. } => {
|
||||||
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
let val = values.get(*offset).cloned().unwrap_or(Value::Void);
|
||||||
|
|||||||
Reference in New Issue
Block a user