Refactor AST nodes to use Rc

This commit refactors various AST node types to use `Rc` (Reference
Counting) instead of `Box`. This change is primarily driven by the need
for shared ownership and more efficient handling of potentially
recursive or shared data structures within the AST.

The main benefits of this change include:

- **Reduced cloning:** `Rc` allows multiple parts of the AST to refer to
  the same node without needing to clone the entire node. This is
  particularly beneficial for optimization passes where nodes might be
  visited multiple times.
- **Enabling sharing:** It makes it easier to represent scenarios where
  a single AST node might be a child of multiple parent nodes.
- **Performance improvements:** By avoiding unnecessary deep copies of
  AST nodes, this change can lead to performance gains, especially
  during complex compilation phases.
This commit is contained in:
Michael Schimmel
2026-03-03 16:07:42 +01:00
parent 78c36cf08d
commit 7c38dee243
12 changed files with 439 additions and 336 deletions
+32 -32
View File
@@ -86,11 +86,11 @@ impl<'a> Analyzer<'a> {
BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(*k), Purity::Pure), BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(*k), Purity::Pure),
BoundKind::GetField { rec, field } => { BoundKind::GetField { rec, field } => {
let rec_m = self.visit(Rc::new((**rec).clone())); let rec_m = self.visit(rec.clone());
let p = rec_m.ty.purity; let p = rec_m.ty.purity;
( (
BoundKind::GetField { BoundKind::GetField {
rec: Box::new(rec_m), rec: Rc::new(rec_m),
field: *field, field: *field,
}, },
p, p,
@@ -98,11 +98,11 @@ impl<'a> Analyzer<'a> {
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
let val_m = self.visit(Rc::new((**value).clone())); let val_m = self.visit(value.clone());
( (
BoundKind::Set { BoundKind::Set {
addr: *addr, addr: *addr,
value: Box::new(val_m), value: Rc::new(val_m),
}, },
Purity::Impure, Purity::Impure,
) )
@@ -115,14 +115,14 @@ impl<'a> Analyzer<'a> {
value, value,
captured_by, captured_by,
} => { } => {
let val_m = self.visit(Rc::new((**value).clone())); let val_m = self.visit(value.clone());
let p = val_m.ty.purity; let p = val_m.ty.purity;
( (
BoundKind::Define { BoundKind::Define {
name: name.clone(), name: name.clone(),
addr: *addr, addr: *addr,
kind: *kind, kind: *kind,
value: Box::new(val_m), value: Rc::new(val_m),
captured_by: captured_by.clone(), captured_by: captured_by.clone(),
}, },
p, p,
@@ -134,9 +134,9 @@ impl<'a> Analyzer<'a> {
then_br, then_br,
else_br, else_br,
} => { } => {
let cond_m = self.visit(Rc::new((**cond).clone())); let cond_m = self.visit(cond.clone());
let then_m = self.visit(Rc::new((**then_br).clone())); let then_m = self.visit(then_br.clone());
let else_m = else_br.as_ref().map(|e| self.visit(Rc::new((**e).clone()))); let else_m = else_br.as_ref().map(|e| self.visit(e.clone()));
let mut p = cond_m.ty.purity.min(then_m.ty.purity); let mut p = cond_m.ty.purity.min(then_m.ty.purity);
if let Some(ref em) = else_m { if let Some(ref em) = else_m {
@@ -144,9 +144,9 @@ impl<'a> Analyzer<'a> {
} }
( (
BoundKind::If { BoundKind::If {
cond: Box::new(cond_m), cond: Rc::new(cond_m),
then_br: Box::new(then_m), then_br: Rc::new(then_m),
else_br: else_m.map(Box::new), else_br: else_m.map(Rc::new),
}, },
p, p,
) )
@@ -176,20 +176,20 @@ impl<'a> Analyzer<'a> {
} }
BoundKind::Destructure { pattern, value } => { BoundKind::Destructure { pattern, value } => {
let pat_m = self.visit(Rc::new((**pattern).clone())); let pat_m = self.visit(pattern.clone());
let val_m = self.visit(Rc::new((**value).clone())); let val_m = self.visit(value.clone());
( (
BoundKind::Destructure { BoundKind::Destructure {
pattern: Box::new(pat_m), pattern: Rc::new(pat_m),
value: Box::new(val_m), value: Rc::new(val_m),
}, },
Purity::Impure, Purity::Impure,
) )
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
let callee_m = self.visit(Rc::new((**callee).clone())); let callee_m = self.visit(callee.clone());
let args_m = self.visit(Rc::new((**args).clone())); let args_m = self.visit(args.clone());
if let BoundKind::Get { if let BoundKind::Get {
addr: Address::Global(idx), addr: Address::Global(idx),
@@ -217,22 +217,22 @@ impl<'a> Analyzer<'a> {
let p = callee_m.ty.purity.min(args_m.ty.purity).min(p_func); let p = callee_m.ty.purity.min(args_m.ty.purity).min(p_func);
( (
BoundKind::Call { BoundKind::Call {
callee: Box::new(callee_m), callee: Rc::new(callee_m),
args: Box::new(args_m), args: Rc::new(args_m),
}, },
p, p,
) )
} }
BoundKind::Again { args } => { BoundKind::Again { args } => {
let args_m = self.visit(Rc::new((**args).clone())); let args_m = self.visit(args.clone());
if let Some(lambda_id) = self.lambda_stack.last() { if let Some(lambda_id) = self.lambda_stack.last() {
self.recursive_identities.insert(lambda_id.clone()); self.recursive_identities.insert(lambda_id.clone());
is_recursive = true; is_recursive = true;
} }
( (
BoundKind::Again { BoundKind::Again {
args: Box::new(args_m), args: Rc::new(args_m),
}, },
Purity::Impure, Purity::Impure,
) )
@@ -244,9 +244,9 @@ impl<'a> Analyzer<'a> {
} => { } => {
let mut analyzed_inputs = Vec::with_capacity(inputs.len()); let mut analyzed_inputs = Vec::with_capacity(inputs.len());
for input in inputs { for input in inputs {
analyzed_inputs.push(self.visit(Rc::new(input.clone()))); analyzed_inputs.push(Rc::new(self.visit(input.clone())));
} }
let a_lambda = Box::new(self.visit(Rc::new((**lambda).clone()))); let a_lambda = Rc::new(self.visit(lambda.clone()));
( (
BoundKind::Pipe { BoundKind::Pipe {
inputs: analyzed_inputs, inputs: analyzed_inputs,
@@ -261,9 +261,9 @@ impl<'a> Analyzer<'a> {
let mut new_exprs = Vec::with_capacity(exprs.len()); let mut new_exprs = Vec::with_capacity(exprs.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for e in exprs { for e in exprs {
let em = self.visit(Rc::new(e.clone())); let em = self.visit(e.clone());
p = p.min(em.ty.purity); p = p.min(em.ty.purity);
new_exprs.push(em); new_exprs.push(Rc::new(em));
} }
(BoundKind::Block { exprs: new_exprs }, p) (BoundKind::Block { exprs: new_exprs }, p)
} }
@@ -272,9 +272,9 @@ impl<'a> Analyzer<'a> {
let mut new_elements = Vec::with_capacity(elements.len()); let mut new_elements = Vec::with_capacity(elements.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for e in elements { for e in elements {
let em = self.visit(Rc::new(e.clone())); let em = self.visit(e.clone());
p = p.min(em.ty.purity); p = p.min(em.ty.purity);
new_elements.push(em); new_elements.push(Rc::new(em));
} }
( (
BoundKind::Tuple { BoundKind::Tuple {
@@ -288,9 +288,9 @@ impl<'a> Analyzer<'a> {
let mut new_values = Vec::with_capacity(values.len()); let mut new_values = Vec::with_capacity(values.len());
let mut p = Purity::Pure; let mut p = Purity::Pure;
for v in values { for v in values {
let vm = self.visit(Rc::new(v.clone())); let vm = self.visit(v.clone());
p = p.min(vm.ty.purity); p = p.min(vm.ty.purity);
new_values.push(vm); new_values.push(Rc::new(vm));
} }
( (
BoundKind::Record { BoundKind::Record {
@@ -305,11 +305,11 @@ impl<'a> Analyzer<'a> {
original_call, original_call,
bound_expanded, bound_expanded,
} => { } => {
let expanded_m = self.visit(Rc::new((**bound_expanded).clone())); let expanded_m = self.visit(bound_expanded.clone());
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call: original_call.clone(), original_call: original_call.clone(),
bound_expanded: Box::new(expanded_m.clone()), bound_expanded: Rc::new(expanded_m.clone()),
}, },
expanded_m.ty.purity, expanded_m.ty.purity,
) )
+22 -22
View File
@@ -215,14 +215,14 @@ impl Binder {
let then_br = self.bind(then_br, diag); let then_br = self.bind(then_br, diag);
let mut else_br_bound = None; let mut else_br_bound = None;
if let Some(e) = else_br { if let Some(e) = else_br {
else_br_bound = Some(Box::new(self.bind(e, diag))); else_br_bound = Some(Rc::new(self.bind(e, diag)));
} }
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::If { BoundKind::If {
cond: Box::new(cond), cond: Rc::new(cond),
then_br: Box::new(then_br), then_br: Rc::new(then_br),
else_br: else_br_bound, else_br: else_br_bound,
}, },
) )
@@ -246,7 +246,7 @@ impl Binder {
name: name.clone(), name: name.clone(),
addr, addr,
kind: crate::ast::compiler::bound_nodes::DeclarationKind::Variable, kind: crate::ast::compiler::bound_nodes::DeclarationKind::Variable,
value: Box::new(val_node), value: Rc::new(val_node),
captured_by: Vec::new(), // Will be filled by post-pass captured_by: Vec::new(), // Will be filled by post-pass
}, },
) )
@@ -263,8 +263,8 @@ impl Binder {
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Destructure { BoundKind::Destructure {
pattern: Box::new(target_node), pattern: Rc::new(target_node),
value: Box::new(val_node), value: Rc::new(val_node),
}, },
) )
} }
@@ -279,7 +279,7 @@ impl Binder {
node.identity.clone(), node.identity.clone(),
BoundKind::Set { BoundKind::Set {
addr, addr,
value: Box::new(val_node), value: Rc::new(val_node),
}, },
) )
} else { } else {
@@ -290,8 +290,8 @@ impl Binder {
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Destructure { BoundKind::Destructure {
pattern: Box::new(target_node), pattern: Rc::new(target_node),
value: Box::new(val_node), value: Rc::new(val_node),
}, },
) )
} }
@@ -300,9 +300,9 @@ impl Binder {
UntypedKind::Pipe { inputs, lambda } => { UntypedKind::Pipe { inputs, lambda } => {
let mut bound_inputs = Vec::with_capacity(inputs.len()); let mut bound_inputs = Vec::with_capacity(inputs.len());
for input in inputs { for input in inputs {
bound_inputs.push(self.bind(input, diag)); bound_inputs.push(Rc::new(self.bind(input, diag)));
} }
let bound_lambda = Box::new(self.bind(lambda.as_ref(), diag)); let bound_lambda = Rc::new(self.bind(lambda.as_ref(), diag));
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Pipe { BoundKind::Pipe {
@@ -365,8 +365,8 @@ impl Binder {
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Call { BoundKind::Call {
callee: Box::new(callee), callee: Rc::new(callee),
args: Box::new(args), args: Rc::new(args),
}, },
) )
} }
@@ -383,7 +383,7 @@ impl Binder {
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
BoundKind::Again { BoundKind::Again {
args: Box::new(args), args: Rc::new(args),
}, },
) )
} }
@@ -391,7 +391,7 @@ impl Binder {
UntypedKind::Block { exprs } => { UntypedKind::Block { exprs } => {
let mut bound_exprs = Vec::new(); let mut bound_exprs = Vec::new();
for expr in exprs { for expr in exprs {
bound_exprs.push(self.bind(expr, diag)); bound_exprs.push(Rc::new(self.bind(expr, diag)));
} }
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
@@ -402,7 +402,7 @@ impl Binder {
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(e, diag)); bound_elems.push(Rc::new(self.bind(e, diag)));
} }
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
@@ -433,7 +433,7 @@ impl Binder {
Some(key_node.identity.clone()), Some(key_node.identity.clone()),
); );
} }
bound_values.push(val_node); bound_values.push(Rc::new(val_node));
} }
let layout = crate::ast::types::RecordLayout::get_or_create(layout_fields); let layout = crate::ast::types::RecordLayout::get_or_create(layout_fields);
@@ -453,7 +453,7 @@ impl Binder {
node.identity.clone(), node.identity.clone(),
BoundKind::Expansion { BoundKind::Expansion {
original_call: Rc::from(call.as_ref().clone()), original_call: Rc::from(call.as_ref().clone()),
bound_expanded: Box::new(bound_expanded), bound_expanded: Rc::new(bound_expanded),
}, },
) )
} }
@@ -551,7 +551,7 @@ impl Binder {
name: sym.clone(), name: sym.clone(),
addr, addr,
kind, kind,
value: Box::new(self.make_node(node.identity.clone(), BoundKind::Nop)), value: Rc::new(self.make_node(node.identity.clone(), BoundKind::Nop)),
captured_by: Vec::new(), // Filled by post-pass captured_by: Vec::new(), // Filled by post-pass
}, },
) )
@@ -562,7 +562,7 @@ impl Binder {
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, kind, diag)); bound_elems.push(Rc::new(self.bind_pattern(e, kind, diag)));
} }
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
@@ -593,7 +593,7 @@ impl Binder {
node.identity.clone(), node.identity.clone(),
BoundKind::Set { BoundKind::Set {
addr, addr,
value: Box::new(self.make_node(node.identity.clone(), BoundKind::Nop)), value: Rc::new(self.make_node(node.identity.clone(), BoundKind::Nop)),
}, },
) )
} else { } else {
@@ -603,7 +603,7 @@ impl Binder {
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_assign_pattern(e, diag)); bound_elems.push(Rc::new(self.bind_assign_pattern(e, diag)));
} }
self.make_node( self.make_node(
node.identity.clone(), node.identity.clone(),
+39 -31
View File
@@ -54,7 +54,7 @@ impl<T> Clone for Box<dyn BoundExtension<T>> {
} }
} }
/// Type alias for a node that has been bound. Defaults to untyped (T = ()). /// A bound AST node, decorated with type or metric information T.
pub type BoundNode<T = ()> = Node<BoundKind<T>, T>; pub type BoundNode<T = ()> = Node<BoundKind<T>, T>;
/// Type alias for a node that has been fully type-checked. /// Type alias for a node that has been fully type-checked.
@@ -91,7 +91,7 @@ pub enum BoundKind<T = ()> {
// Variable Update (Assignment) // Variable Update (Assignment)
Set { Set {
addr: Address, addr: Address,
value: Box<BoundNode<T>>, value: Rc<BoundNode<T>>,
}, },
// Variable Declaration (Unified for Local/Global/Parameter) // Variable Declaration (Unified for Local/Global/Parameter)
@@ -99,7 +99,7 @@ pub enum BoundKind<T = ()> {
name: Symbol, name: Symbol,
addr: Address, addr: Address,
kind: DeclarationKind, kind: DeclarationKind,
value: Box<BoundNode<T>>, value: Rc<BoundNode<T>>,
captured_by: Vec<Identity>, captured_by: Vec<Identity>,
}, },
@@ -108,20 +108,20 @@ pub enum BoundKind<T = ()> {
/// Specialized field access (O(1) via RecordLayout) /// Specialized field access (O(1) via RecordLayout)
GetField { GetField {
rec: Box<BoundNode<T>>, rec: Rc<BoundNode<T>>,
field: crate::ast::types::Keyword, field: crate::ast::types::Keyword,
}, },
If { If {
cond: Box<BoundNode<T>>, cond: Rc<BoundNode<T>>,
then_br: Box<BoundNode<T>>, then_br: Rc<BoundNode<T>>,
else_br: Option<Box<BoundNode<T>>>, else_br: Option<Rc<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: Rc<BoundNode<T>>,
value: Box<BoundNode<T>>, value: Rc<BoundNode<T>>,
}, },
Lambda { Lambda {
@@ -134,29 +134,29 @@ pub enum BoundKind<T = ()> {
}, },
Call { Call {
callee: Box<BoundNode<T>>, callee: Rc<BoundNode<T>>,
args: Box<BoundNode<T>>, args: Rc<BoundNode<T>>,
}, },
Again { Again {
args: Box<BoundNode<T>>, args: Rc<BoundNode<T>>,
}, },
Pipe { Pipe {
inputs: Vec<BoundNode<T>>, inputs: Vec<Rc<BoundNode<T>>>,
lambda: Box<BoundNode<T>>, lambda: Rc<BoundNode<T>>,
out_type: crate::ast::types::StaticType, out_type: crate::ast::types::StaticType,
}, },
Block { Block {
exprs: Vec<BoundNode<T>>, exprs: Vec<Rc<BoundNode<T>>>,
}, },
Tuple { Tuple {
elements: Vec<BoundNode<T>>, elements: Vec<Rc<BoundNode<T>>>,
}, },
Record { Record {
layout: std::sync::Arc<crate::ast::types::RecordLayout>, layout: std::sync::Arc<crate::ast::types::RecordLayout>,
values: Vec<BoundNode<T>>, values: Vec<Rc<BoundNode<T>>>,
}, },
/// An expanded macro call, preserving the original call for debugging and UI. /// An expanded macro call, preserving the original call for debugging and UI.
@@ -164,7 +164,7 @@ pub enum BoundKind<T = ()> {
/// The original call from the untyped AST. /// The original call from the untyped AST.
original_call: Rc<Node<crate::ast::nodes::UntypedKind>>, original_call: Rc<Node<crate::ast::nodes::UntypedKind>>,
/// The result of binding the expanded AST. /// The result of binding the expanded AST.
bound_expanded: Box<BoundNode<T>>, bound_expanded: Rc<BoundNode<T>>,
}, },
/// A diagnostic poison node, allowing compilation to continue after an error. /// A diagnostic poison node, allowing compilation to continue after an error.
@@ -194,7 +194,7 @@ where
addr: ab, addr: ab,
value: vb, value: vb,
}, },
) => aa == ab && va == vb, ) => aa == ab && Rc::ptr_eq(va, vb),
( (
BoundKind::Define { BoundKind::Define {
name: na, name: na,
@@ -210,12 +210,12 @@ where
value: vb, value: vb,
captured_by: cb, captured_by: cb,
}, },
) => na == nb && aa == ab && ka == kb && va == vb && ca == cb, ) => na == nb && aa == ab && ka == kb && Rc::ptr_eq(va, vb) && ca == cb,
(BoundKind::FieldAccessor(a), BoundKind::FieldAccessor(b)) => a == b, (BoundKind::FieldAccessor(a), BoundKind::FieldAccessor(b)) => a == b,
( (
BoundKind::GetField { rec: ra, field: fa }, BoundKind::GetField { rec: ra, field: fa },
BoundKind::GetField { rec: rb, field: fb }, BoundKind::GetField { rec: rb, field: fb },
) => ra == rb && fa == fb, ) => Rc::ptr_eq(ra, rb) && fa == fb,
( (
BoundKind::If { BoundKind::If {
cond: ca, cond: ca,
@@ -227,7 +227,11 @@ where
then_br: tb, then_br: tb,
else_br: eb, else_br: eb,
}, },
) => ca == cb && ta == tb && ea == eb, ) => Rc::ptr_eq(ca, cb) && Rc::ptr_eq(ta, tb) && match (ea, eb) {
(Some(a), Some(b)) => Rc::ptr_eq(a, b),
(None, None) => true,
_ => false,
},
( (
BoundKind::Destructure { BoundKind::Destructure {
pattern: pa, pattern: pa,
@@ -237,7 +241,7 @@ where
pattern: pb, pattern: pb,
value: vb, value: vb,
}, },
) => pa == pb && va == vb, ) => Rc::ptr_eq(pa, pb) && Rc::ptr_eq(va, vb),
( (
BoundKind::Lambda { BoundKind::Lambda {
params: pa, params: pa,
@@ -251,7 +255,7 @@ where
body: bb, body: bb,
positional_count: pcb, positional_count: pcb,
}, },
) => pa == pb && ua == ub && ba == bb && pca == pcb, ) => Rc::ptr_eq(pa, pb) && ua == ub && Rc::ptr_eq(ba, bb) && pca == pcb,
( (
BoundKind::Call { BoundKind::Call {
callee: ca, callee: ca,
@@ -261,10 +265,14 @@ where
callee: cb, callee: cb,
args: ab, args: ab,
}, },
) => ca == cb && aa == ab, ) => Rc::ptr_eq(ca, cb) && Rc::ptr_eq(aa, ab),
(BoundKind::Again { args: aa }, BoundKind::Again { args: ab }) => aa == ab, (BoundKind::Again { args: aa }, BoundKind::Again { args: ab }) => Rc::ptr_eq(aa, ab),
(BoundKind::Block { exprs: ea }, BoundKind::Block { exprs: eb }) => ea == eb, (BoundKind::Block { exprs: ea }, BoundKind::Block { exprs: eb }) => {
(BoundKind::Tuple { elements: ea }, BoundKind::Tuple { elements: eb }) => ea == eb, ea.len() == eb.len() && ea.iter().zip(eb.iter()).all(|(a, b)| Rc::ptr_eq(a, b))
}
(BoundKind::Tuple { elements: ea }, BoundKind::Tuple { elements: eb }) => {
ea.len() == eb.len() && ea.iter().zip(eb.iter()).all(|(a, b)| Rc::ptr_eq(a, b))
}
( (
BoundKind::Record { BoundKind::Record {
layout: la, layout: la,
@@ -274,7 +282,7 @@ where
layout: lb, layout: lb,
values: vb, values: vb,
}, },
) => std::sync::Arc::ptr_eq(la, lb) && va == vb, ) => std::sync::Arc::ptr_eq(la, lb) && va.len() == vb.len() && va.iter().zip(vb.iter()).all(|(a, b)| Rc::ptr_eq(a, b)),
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call: ca, original_call: ca,
@@ -284,9 +292,9 @@ where
original_call: cb, original_call: cb,
bound_expanded: eb, bound_expanded: eb,
}, },
) => Rc::ptr_eq(ca, cb) && ea == eb, ) => Rc::ptr_eq(ca, cb) && Rc::ptr_eq(ea, eb),
(BoundKind::Error, BoundKind::Error) => true, (BoundKind::Error, BoundKind::Error) => true,
(BoundKind::Extension(_), BoundKind::Extension(_)) => false, // Currently no equality for extensions (BoundKind::Extension(_), BoundKind::Extension(_)) => false,
_ => false, _ => false,
} }
} }
+20 -19
View File
@@ -10,6 +10,7 @@ impl CapturePass {
} }
fn transform(mut node: BoundNode, capture_map: &HashMap<Identity, Vec<Identity>>) -> BoundNode { fn transform(mut node: BoundNode, capture_map: &HashMap<Identity, Vec<Identity>>) -> BoundNode {
use std::rc::Rc;
match node.kind { match node.kind {
BoundKind::Define { BoundKind::Define {
name, name,
@@ -23,7 +24,7 @@ impl CapturePass {
name, name,
addr, addr,
kind, kind,
value: Box::new(Self::transform(*value, capture_map)), value: Rc::new(Self::transform(value.as_ref().clone(), capture_map)),
captured_by, captured_by,
}; };
} }
@@ -34,16 +35,16 @@ impl CapturePass {
else_br, else_br,
} => { } => {
node.kind = BoundKind::If { node.kind = BoundKind::If {
cond: Box::new(Self::transform(*cond, capture_map)), cond: Rc::new(Self::transform(cond.as_ref().clone(), capture_map)),
then_br: Box::new(Self::transform(*then_br, capture_map)), then_br: Rc::new(Self::transform(then_br.as_ref().clone(), capture_map)),
else_br: else_br.map(|e| Box::new(Self::transform(*e, capture_map))), else_br: else_br.map(|e| Rc::new(Self::transform(e.as_ref().clone(), capture_map))),
}; };
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
node.kind = BoundKind::Set { node.kind = BoundKind::Set {
addr, addr,
value: Box::new(Self::transform(*value, capture_map)), value: Rc::new(Self::transform(value.as_ref().clone(), capture_map)),
}; };
} }
@@ -51,15 +52,15 @@ impl CapturePass {
BoundKind::GetField { rec, field } => { BoundKind::GetField { rec, field } => {
node.kind = BoundKind::GetField { node.kind = BoundKind::GetField {
rec: Box::new(Self::transform(*rec, capture_map)), rec: Rc::new(Self::transform(rec.as_ref().clone(), capture_map)),
field, field,
}; };
} }
BoundKind::Destructure { pattern, value } => { BoundKind::Destructure { pattern, value } => {
node.kind = BoundKind::Destructure { node.kind = BoundKind::Destructure {
pattern: Box::new(Self::transform(*pattern, capture_map)), pattern: Rc::new(Self::transform(pattern.as_ref().clone(), capture_map)),
value: Box::new(Self::transform(*value, capture_map)), value: Rc::new(Self::transform(value.as_ref().clone(), capture_map)),
}; };
} }
@@ -70,23 +71,23 @@ impl CapturePass {
positional_count, positional_count,
} => { } => {
node.kind = BoundKind::Lambda { node.kind = BoundKind::Lambda {
params: std::rc::Rc::new(Self::transform(params.as_ref().clone(), capture_map)), params: Rc::new(Self::transform(params.as_ref().clone(), capture_map)),
upvalues, upvalues,
body: std::rc::Rc::new(Self::transform(body.as_ref().clone(), capture_map)), body: Rc::new(Self::transform(body.as_ref().clone(), capture_map)),
positional_count, positional_count,
}; };
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
node.kind = BoundKind::Call { node.kind = BoundKind::Call {
callee: Box::new(Self::transform(*callee, capture_map)), callee: Rc::new(Self::transform(callee.as_ref().clone(), capture_map)),
args: Box::new(Self::transform(*args, capture_map)), args: Rc::new(Self::transform(args.as_ref().clone(), capture_map)),
}; };
} }
BoundKind::Again { args } => { BoundKind::Again { args } => {
node.kind = BoundKind::Again { node.kind = BoundKind::Again {
args: Box::new(Self::transform(*args, capture_map)), args: Rc::new(Self::transform(args.as_ref().clone(), capture_map)),
}; };
} }
BoundKind::Pipe { BoundKind::Pipe {
@@ -96,11 +97,11 @@ impl CapturePass {
} => { } => {
let mut t_inputs = Vec::with_capacity(inputs.len()); let mut t_inputs = Vec::with_capacity(inputs.len());
for input in inputs { for input in inputs {
t_inputs.push(Self::transform(input, capture_map)); t_inputs.push(Rc::new(Self::transform(input.as_ref().clone(), capture_map)));
} }
node.kind = BoundKind::Pipe { node.kind = BoundKind::Pipe {
inputs: t_inputs, inputs: t_inputs,
lambda: Box::new(Self::transform(*lambda, capture_map)), lambda: Rc::new(Self::transform(lambda.as_ref().clone(), capture_map)),
out_type: out_type.clone(), out_type: out_type.clone(),
}; };
} }
@@ -108,7 +109,7 @@ impl CapturePass {
node.kind = BoundKind::Block { node.kind = BoundKind::Block {
exprs: exprs exprs: exprs
.into_iter() .into_iter()
.map(|e| Self::transform(e, capture_map)) .map(|e| Rc::new(Self::transform(e.as_ref().clone(), capture_map)))
.collect(), .collect(),
}; };
} }
@@ -117,7 +118,7 @@ impl CapturePass {
node.kind = BoundKind::Tuple { node.kind = BoundKind::Tuple {
elements: elements elements: elements
.into_iter() .into_iter()
.map(|e| Self::transform(e, capture_map)) .map(|e| Rc::new(Self::transform(e.as_ref().clone(), capture_map)))
.collect(), .collect(),
}; };
} }
@@ -127,7 +128,7 @@ impl CapturePass {
layout, layout,
values: values values: values
.into_iter() .into_iter()
.map(|v| Self::transform(v, capture_map)) .map(|v| Rc::new(Self::transform(v.as_ref().clone(), capture_map)))
.collect(), .collect(),
}; };
} }
@@ -138,7 +139,7 @@ impl CapturePass {
} => { } => {
node.kind = BoundKind::Expansion { node.kind = BoundKind::Expansion {
original_call, original_call,
bound_expanded: Box::new(Self::transform(*bound_expanded, capture_map)), bound_expanded: Rc::new(Self::transform(bound_expanded.as_ref().clone(), capture_map)),
}; };
} }
+206 -130
View File
@@ -55,35 +55,40 @@ impl Optimizer {
return node; return node;
} }
let mut current = node; let mut current = Rc::new(node);
for _ in 0..self.max_passes { for _ in 0..self.max_passes {
let mut sub = SubstitutionMap::new(); let mut sub = SubstitutionMap::new();
let mut path = PathTracker::new(); let mut path = PathTracker::new();
let next = self.visit_node(current.clone(), &mut sub, &mut path); let next = self.visit_node(current.clone(), &mut sub, &mut path);
if next == current { if Rc::ptr_eq(&next, &current) {
break; break;
} }
current = next; current = next;
} }
current // Unwrap the final Rc if we are at the end, or return a clone of the inner node.
// Since AnalyzedNode is small now (header + Rcs), cloning is cheap.
(*current).clone()
} }
fn visit_node( fn visit_node(
&self, &self,
node: AnalyzedNode, node_rc: Rc<AnalyzedNode>,
sub: &mut SubstitutionMap, sub: &mut SubstitutionMap,
path: &mut PathTracker, path: &mut PathTracker,
) -> AnalyzedNode { ) -> Rc<AnalyzedNode> {
let node = &*node_rc;
let folder = Folder::new(&self.globals); let folder = Folder::new(&self.globals);
let inliner = Inliner::new(&self.globals, &self.global_purity); let inliner = Inliner::new(&self.globals, &self.global_purity);
let (new_kind, metrics) = match node.kind {
BoundKind::Get { addr, ref name } => { let (new_kind, metrics) = match &node.kind {
BoundKind::Get { addr, name } => {
let addr = *addr;
if !sub.assigned.contains(&addr) { if !sub.assigned.contains(&addr) {
// 1. Try inlining from current value substitution map (locals/globals/upvalues) // 1. Try inlining from current value substitution map (locals/globals/upvalues)
if let Some(val) = sub.get_value(&addr) if let Some(val) = sub.get_value(&addr)
&& inliner.is_inlinable_value(val, addr) && inliner.is_inlinable_value(val, addr)
{ {
return folder.make_constant_node(val.clone(), &node); return Rc::new(folder.make_constant_node(val.clone(), &node));
} }
// 2. Try inlining from AST substitution map (pure expressions) // 2. Try inlining from AST substitution map (pure expressions)
@@ -99,7 +104,7 @@ impl Optimizer {
if let Some(val) = globals.get(idx.0 as usize) if let Some(val) = globals.get(idx.0 as usize)
&& inliner.is_inlinable_value(val, addr) && inliner.is_inlinable_value(val, addr)
{ {
return folder.make_constant_node(val.clone(), &node); return Rc::new(folder.make_constant_node(val.clone(), &node));
} }
} }
} }
@@ -114,62 +119,71 @@ impl Optimizer {
) )
} }
BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(k), node.ty.clone()), BoundKind::FieldAccessor(k) => (BoundKind::FieldAccessor(*k), node.ty.clone()),
BoundKind::GetField { ref rec, field } => { BoundKind::GetField { rec, field } => {
let rec_opt = self.visit_node((**rec).clone(), sub, path); let rec_opt = self.visit_node(rec.clone(), sub, path);
// Constant folding for Field Access // Constant folding for Field Access
if let BoundKind::Constant(Value::Record(layout, values)) = &rec_opt.kind if let BoundKind::Constant(Value::Record(layout, values)) = &rec_opt.kind
&& let Some(idx) = layout.index_of(field) && let Some(idx) = layout.index_of(*field)
{ {
return folder.make_constant_node(values[idx].clone(), &node); return Rc::new(folder.make_constant_node(values[idx].clone(), &node));
}
if Rc::ptr_eq(&rec_opt, rec) {
return node_rc;
} }
( (
BoundKind::GetField { BoundKind::GetField {
rec: Box::new(rec_opt), rec: rec_opt,
field, field: *field,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
let value = Box::new(self.visit_node(*value, sub, path)); let value_opt = self.visit_node(value.clone(), sub, path);
if let BoundKind::Constant(val) = &value.kind { if let BoundKind::Constant(val) = &value_opt.kind {
sub.add_value(addr, val.clone()); sub.add_value(*addr, val.clone());
} else { } else {
sub.remove_value(&addr); sub.remove_value(addr);
} }
if Rc::ptr_eq(&value_opt, value) {
return node_rc;
}
( (
BoundKind::Set { BoundKind::Set {
addr: sub.map_address(addr), addr: sub.map_address(*addr),
value, value: value_opt,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::Define { BoundKind::Define {
ref name, name,
addr, addr,
kind, kind,
ref value, value,
ref captured_by, captured_by,
} => { } => {
let value_opt = Box::new(self.visit_node((**value).clone(), sub, path)); let value_opt = self.visit_node(value.clone(), sub, path);
if let Address::Local(slot) = addr if let Address::Local(slot) = addr
&& !captured_by.is_empty() && !captured_by.is_empty()
{ {
sub.captured_slots.insert(slot); sub.captured_slots.insert(*slot);
} }
if let BoundKind::Constant(val) = &value_opt.kind { if let BoundKind::Constant(val) = &value_opt.kind {
sub.add_value(addr, val.clone()); sub.add_value(*addr, val.clone());
} else { } else {
sub.remove_value(&addr); sub.remove_value(addr);
} }
if let Address::Global(global_index) = addr if let Address::Global(global_index) = addr
@@ -178,14 +192,18 @@ impl Optimizer {
{ {
purity_rc purity_rc
.borrow_mut() .borrow_mut()
.insert(global_index, value_opt.ty.purity); .insert(*global_index, value_opt.ty.purity);
}
if Rc::ptr_eq(&value_opt, value) {
return node_rc;
} }
( (
BoundKind::Define { BoundKind::Define {
name: name.clone(), name: name.clone(),
addr: sub.map_address(addr), addr: sub.map_address(*addr),
kind, kind: *kind,
value: value_opt, value: value_opt,
captured_by: captured_by.clone(), captured_by: captured_by.clone(),
}, },
@@ -194,41 +212,41 @@ impl Optimizer {
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
let callee = self.visit_node(*callee, sub, path); let callee_opt = self.visit_node(callee.clone(), sub, path);
let args = self.visit_node(*args, sub, path); let args_opt = self.visit_node(args.clone(), sub, path);
if self.enabled { if self.enabled {
// Optimized Field Access Transformation // Optimized Field Access Transformation
if let BoundKind::FieldAccessor(k) = &callee.kind if let BoundKind::FieldAccessor(k) = &callee_opt.kind
&& let BoundKind::Tuple { elements } = &args.kind && let BoundKind::Tuple { elements } = &args_opt.kind
&& elements.len() == 1 && elements.len() == 1
{ {
let rec = elements[0].clone(); let rec = elements[0].clone();
let metrics = node.ty.clone(); let metrics = node.ty.clone();
return Node { return Rc::new(Node {
identity: node.identity, identity: node.identity.clone(),
kind: BoundKind::GetField { kind: BoundKind::GetField {
rec: Box::new(rec), rec,
field: *k, field: *k,
}, },
ty: metrics, ty: metrics,
}; });
} }
let mut arg_nodes = Vec::new(); let mut arg_nodes = Vec::new();
self.flatten_tuple(args.clone(), &mut arg_nodes); self.flatten_tuple(args_opt.clone(), &mut arg_nodes);
if let BoundKind::Lambda { if let BoundKind::Lambda {
params, params,
body, body,
upvalues, upvalues,
positional_count, positional_count,
} = &callee.kind } = &callee_opt.kind
&& upvalues.is_empty() && upvalues.is_empty()
&& positional_count.is_some() && positional_count.is_some()
&& path.inlining_depth < 5 && path.inlining_depth < 5
&& !callee.ty.is_recursive && !callee_opt.ty.is_recursive
&& path.enter_lambda(&callee.identity) && path.enter_lambda(&callee_opt.identity)
{ {
path.inlining_depth += 1; path.inlining_depth += 1;
let mut inner_sub = sub.new_inner(); let mut inner_sub = sub.new_inner();
@@ -236,12 +254,12 @@ impl Optimizer {
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub) .prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
.is_some() .is_some()
{ {
Some(self.visit_node((**body).clone(), &mut inner_sub, path)) Some(self.visit_node(body.clone(), &mut inner_sub, path))
} else { } else {
None None
}; };
path.inlining_depth -= 1; path.inlining_depth -= 1;
path.exit_lambda(&callee.identity); path.exit_lambda(&callee_opt.identity);
if let Some(res) = collapsed { if let Some(res) = collapsed {
return res; return res;
@@ -251,7 +269,7 @@ impl Optimizer {
if let BoundKind::Get { if let BoundKind::Get {
addr: Address::Global(idx), addr: Address::Global(idx),
.. ..
} = &callee.kind } = &callee_opt.kind
&& let Some(registry_rc) = &self.lambda_registry && let Some(registry_rc) = &self.lambda_registry
&& path.inlining_depth < 5 && path.inlining_depth < 5
&& !path.inlining_stack.contains(idx) && !path.inlining_stack.contains(idx)
@@ -275,7 +293,7 @@ impl Optimizer {
.prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub) .prepare_beta_reduction(params, &arg_nodes, body, &mut inner_sub)
.is_some() .is_some()
{ {
Some(self.visit_node((**body).clone(), &mut inner_sub, path)) Some(self.visit_node(body.clone(), &mut inner_sub, path))
} else { } else {
None None
}; };
@@ -288,7 +306,7 @@ impl Optimizer {
} }
} }
if let BoundKind::Constant(Value::Object(ref obj)) = callee.kind if let BoundKind::Constant(Value::Object(ref obj)) = callee_opt.kind
&& path.inlining_depth < 5 && path.inlining_depth < 5
&& let Some(closure) = obj.as_any().downcast_ref::<Closure>() && let Some(closure) = obj.as_any().downcast_ref::<Closure>()
&& (closure.upvalues.is_empty() && (closure.upvalues.is_empty()
@@ -306,7 +324,7 @@ impl Optimizer {
path.inlining_depth += 1; path.inlining_depth += 1;
let inlined_body = self.visit_node( let inlined_body = self.visit_node(
(*closure.function_node).clone(), closure.function_node.clone(),
&mut closure_sub, &mut closure_sub,
path, path,
); );
@@ -332,57 +350,75 @@ impl Optimizer {
} }
} }
if let Some(folded) = folder.try_fold_pure(&callee, &arg_nodes) { if let Some(folded) = folder.try_fold_pure(&callee_opt, &arg_nodes) {
return folded; return Rc::new(folded);
} }
} }
if Rc::ptr_eq(&callee_opt, callee) && Rc::ptr_eq(&args_opt, args) {
return node_rc;
}
( (
BoundKind::Call { BoundKind::Call {
callee: Box::new(callee), callee: callee_opt,
args: Box::new(args), args: args_opt,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::Again { args } => { BoundKind::Again { args } => {
let args = self.visit_node(*args, sub, path); let args_opt = self.visit_node(args.clone(), sub, path);
if Rc::ptr_eq(&args_opt, args) {
return node_rc;
}
( (
BoundKind::Again { BoundKind::Again {
args: Box::new(args), args: args_opt,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::If { BoundKind::If {
ref cond, cond,
ref then_br, then_br,
ref else_br, else_br,
} => { } => {
let cond_opt = self.visit_node((**cond).clone(), sub, path); let cond_opt = self.visit_node(cond.clone(), sub, path);
if self.enabled if self.enabled
&& let BoundKind::Constant(ref val) = cond_opt.kind && let BoundKind::Constant(ref val) = cond_opt.kind
{ {
if val.is_truthy() { if val.is_truthy() {
return self.visit_node((**then_br).clone(), sub, path); return self.visit_node(then_br.clone(), sub, path);
} else if let Some(else_node) = else_br { } else if let Some(else_node) = else_br {
return self.visit_node((**else_node).clone(), sub, path); return self.visit_node(else_node.clone(), sub, path);
} else { } else {
return folder.make_nop_node(&node); return Rc::new(folder.make_nop_node(&node));
} }
} }
let then_br = Box::new(self.visit_node((**then_br).clone(), sub, path)); let then_br_opt = self.visit_node(then_br.clone(), sub, path);
let else_br = else_br let else_br_opt = else_br
.as_ref() .as_ref()
.map(|e| Box::new(self.visit_node((**e).clone(), sub, path))); .map(|e| self.visit_node(e.clone(), sub, path));
let unchanged = Rc::ptr_eq(&cond_opt, cond) && Rc::ptr_eq(&then_br_opt, then_br) && match (&else_br_opt, else_br) {
(Some(a), Some(b)) => Rc::ptr_eq(a, b),
(None, None) => true,
_ => false,
};
if unchanged {
return node_rc;
}
( (
BoundKind::If { BoundKind::If {
cond: Box::new(cond_opt), cond: cond_opt,
then_br, then_br: then_br_opt,
else_br, else_br: else_br_opt,
}, },
node.ty.clone(), node.ty.clone(),
) )
@@ -394,10 +430,20 @@ impl Optimizer {
out_type, out_type,
} => { } => {
let mut o_inputs = Vec::with_capacity(inputs.len()); let mut o_inputs = Vec::with_capacity(inputs.len());
let mut inputs_changed = false;
for input in inputs { for input in inputs {
o_inputs.push(self.visit_node(input, sub, path)); let opt = self.visit_node(input.clone(), sub, path);
if !Rc::ptr_eq(&opt, input) {
inputs_changed = true;
}
o_inputs.push(opt);
} }
let o_lambda = Box::new(self.visit_node(*lambda, sub, path)); let o_lambda = self.visit_node(lambda.clone(), sub, path);
if !inputs_changed && Rc::ptr_eq(&o_lambda, lambda) {
return node_rc;
}
( (
BoundKind::Pipe { BoundKind::Pipe {
inputs: o_inputs, inputs: o_inputs,
@@ -408,7 +454,7 @@ impl Optimizer {
) )
} }
BoundKind::Block { ref exprs } => { BoundKind::Block { exprs } => {
let mut info = UsageInfo::default(); let mut info = UsageInfo::default();
if !exprs.is_empty() { if !exprs.is_empty() {
for e in exprs { for e in exprs {
@@ -420,6 +466,7 @@ impl Optimizer {
let mut new_exprs = Vec::with_capacity(exprs.len()); let mut new_exprs = Vec::with_capacity(exprs.len());
let last_idx = exprs.len().saturating_sub(1); let last_idx = exprs.len().saturating_sub(1);
let mut block_changed = false;
for (i, e) in exprs.iter().enumerate() { for (i, e) in exprs.iter().enumerate() {
let is_last = i == last_idx; let is_last = i == last_idx;
@@ -448,20 +495,29 @@ impl Optimizer {
}; };
if removable { if removable {
block_changed = true;
continue; continue;
} }
} }
let opt = self.visit_node(e.clone(), sub, path); let opt = self.visit_node(e.clone(), sub, path);
if self.enabled && matches!(opt.kind, BoundKind::Nop) && !is_last { if self.enabled && matches!(opt.kind, BoundKind::Nop) && !is_last {
block_changed = true;
continue; continue;
} }
if !Rc::ptr_eq(&opt, e) {
block_changed = true;
}
new_exprs.push(opt); new_exprs.push(opt);
} }
if !block_changed {
return node_rc;
}
if self.enabled { if self.enabled {
if new_exprs.is_empty() { if new_exprs.is_empty() {
return folder.make_nop_node(&node); return Rc::new(folder.make_nop_node(&node));
} else if new_exprs.len() == 1 { } else if new_exprs.len() == 1 {
return new_exprs.pop().unwrap(); return new_exprs.pop().unwrap();
} }
@@ -470,20 +526,12 @@ impl Optimizer {
(BoundKind::Block { exprs: new_exprs }, node.ty.clone()) (BoundKind::Block { exprs: new_exprs }, node.ty.clone())
} }
BoundKind::Lambda { .. } => { BoundKind::Lambda {
let (params, original_upvalues, body, positional_count) = params,
if let BoundKind::Lambda { upvalues,
params, body,
upvalues, positional_count,
body, } => {
positional_count,
} = &node.kind
{
(params, upvalues, body, positional_count)
} else {
unreachable!()
};
let mut info = UsageInfo::default(); let mut info = UsageInfo::default();
info.collect(&node); info.collect(&node);
@@ -491,8 +539,9 @@ impl Optimizer {
let mut mapping = Vec::new(); let mut mapping = Vec::new();
let mut next_inner_subs = sub.new_inner(); let mut next_inner_subs = sub.new_inner();
next_inner_subs.assigned = info.assigned; next_inner_subs.assigned = info.assigned;
let mut upvalues_changed = false;
for (old_idx, capture_addr) in original_upvalues.iter().enumerate() { for (old_idx, capture_addr) in upvalues.iter().enumerate() {
let mut inlined_val = None; let mut inlined_val = None;
if !sub.assigned.contains(capture_addr) if !sub.assigned.contains(capture_addr)
&& let Some(val) = sub.get_value(capture_addr) && let Some(val) = sub.get_value(capture_addr)
@@ -508,40 +557,45 @@ impl Optimizer {
next_inner_subs next_inner_subs
.add_value(Address::Upvalue(UpvalueIdx(old_idx as u32)), val); .add_value(Address::Upvalue(UpvalueIdx(old_idx as u32)), val);
mapping.push(None); mapping.push(None);
upvalues_changed = true;
} else { } else {
mapping.push(Some(new_upvalues.len() as u32)); mapping.push(Some(new_upvalues.len() as u32));
new_upvalues.push(sub.map_address(*capture_addr)); let mapped = sub.map_address(*capture_addr);
if mapped != *capture_addr {
upvalues_changed = true;
}
new_upvalues.push(mapped);
} }
} }
let params_node = let params_opt = self.visit_node(params.clone(), &mut next_inner_subs, path);
self.visit_node(params.as_ref().clone(), &mut next_inner_subs, path); inliner.collect_parameter_slots(&params_opt, &mut next_inner_subs);
inliner.collect_parameter_slots(&params_node, &mut next_inner_subs);
let body_node = self.visit_node(body.as_ref().clone(), &mut next_inner_subs, path); let body_opt = self.visit_node(body.clone(), &mut next_inner_subs, path);
let reindexed_body = if new_upvalues.len() != original_upvalues.len() { let reindexed_body = if new_upvalues.len() != upvalues.len() {
sub.reindex_upvalues(body_node, &mapping) sub.reindex_upvalues(body_opt, &mapping)
} else { } else {
body_node body_opt
}; };
if !upvalues_changed && Rc::ptr_eq(&params_opt, params) && Rc::ptr_eq(&reindexed_body, body) {
return node_rc;
}
( (
BoundKind::Lambda { BoundKind::Lambda {
params: Rc::new(params_node), params: params_opt,
upvalues: new_upvalues, upvalues: new_upvalues,
body: Rc::new(reindexed_body), body: reindexed_body,
positional_count: *positional_count, positional_count: *positional_count,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::Destructure { BoundKind::Destructure { pattern, value } => {
ref pattern, let val_opt = self.visit_node(value.clone(), sub, path);
ref value, let pat_opt = self.visit_node(pattern.clone(), sub, path);
} => {
let val_opt = Box::new(self.visit_node((**value).clone(), sub, path));
let pat_opt = Box::new(self.visit_node((**pattern).clone(), sub, path));
let mut info = UsageInfo::default(); let mut info = UsageInfo::default();
info.collect_pattern(&pat_opt); info.collect_pattern(&pat_opt);
@@ -549,6 +603,10 @@ impl Optimizer {
sub.remove_value(&addr); sub.remove_value(&addr);
} }
if Rc::ptr_eq(&val_opt, value) && Rc::ptr_eq(&pat_opt, pattern) {
return node_rc;
}
( (
BoundKind::Destructure { BoundKind::Destructure {
pattern: pat_opt, pattern: pat_opt,
@@ -559,25 +617,39 @@ impl Optimizer {
} }
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let elements = elements let mut new_elements = Vec::with_capacity(elements.len());
.into_iter() let mut changed = false;
.map(|e| self.visit_node(e, sub, path)) for e in elements {
.collect(); let opt = self.visit_node(e.clone(), sub, path);
(BoundKind::Tuple { elements }, node.ty.clone()) if !Rc::ptr_eq(&opt, e) {
changed = true;
}
new_elements.push(opt);
}
if !changed {
return node_rc;
}
(BoundKind::Tuple { elements: new_elements }, node.ty.clone())
} }
BoundKind::Record { BoundKind::Record { layout, values } => {
ref layout, let mut mapped_values = Vec::with_capacity(values.len());
ref values, let mut changed = false;
} => { for v in values {
let mapped_values: Vec<_> = values let opt = self.visit_node(v.clone(), sub, path);
.iter() if !Rc::ptr_eq(&opt, v) {
.map(|v| self.visit_node(v.clone(), sub, path)) changed = true;
.collect(); }
mapped_values.push(opt);
}
if self.enabled if self.enabled
&& let Some(folded) = folder.try_fold_record(layout, &mapped_values, &node) && let Some(folded) = folder.try_fold_record(layout, &mapped_values, &node)
{ {
return folded; return Rc::new(folded);
}
if !changed {
return node_rc;
} }
( (
@@ -589,36 +661,40 @@ impl Optimizer {
) )
} }
BoundKind::Expansion { BoundKind::Expansion {
ref original_call, original_call,
ref bound_expanded, bound_expanded,
} => { } => {
path.inlining_depth += 1; path.inlining_depth += 1;
let bound_expanded = let expanded_opt = self.visit_node(bound_expanded.clone(), sub, path);
Box::new(self.visit_node((**bound_expanded).clone(), sub, path));
path.inlining_depth -= 1; path.inlining_depth -= 1;
if Rc::ptr_eq(&expanded_opt, bound_expanded) {
return node_rc;
}
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call: original_call.clone(), original_call: original_call.clone(),
bound_expanded, bound_expanded: expanded_opt,
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
k => (k, node.ty.clone()), k => (k.clone(), node.ty.clone()),
}; };
Node { Rc::new(Node {
identity: node.identity, identity: node.identity.clone(),
kind: new_kind, kind: new_kind,
ty: metrics, ty: metrics,
} })
} }
fn flatten_tuple(&self, node: AnalyzedNode, into: &mut Vec<AnalyzedNode>) { fn flatten_tuple(&self, node: Rc<AnalyzedNode>, into: &mut Vec<Rc<AnalyzedNode>>) {
match node.kind { match &node.kind {
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
for el in elements { for el in elements {
self.flatten_tuple(el, into); self.flatten_tuple(el.clone(), into);
} }
} }
BoundKind::Nop => {} BoundKind::Nop => {}
+2 -2
View File
@@ -51,7 +51,7 @@ impl<'a> Folder<'a> {
pub fn try_fold_record( pub fn try_fold_record(
&self, &self,
layout: &std::sync::Arc<RecordLayout>, layout: &std::sync::Arc<RecordLayout>,
values: &[AnalyzedNode], values: &[Rc<AnalyzedNode>],
template: &AnalyzedNode, template: &AnalyzedNode,
) -> Option<AnalyzedNode> { ) -> Option<AnalyzedNode> {
let mut constant_values = Vec::with_capacity(values.len()); let mut constant_values = Vec::with_capacity(values.len());
@@ -71,7 +71,7 @@ impl<'a> Folder<'a> {
pub fn try_fold_pure( pub fn try_fold_pure(
&self, &self,
callee: &AnalyzedNode, callee: &AnalyzedNode,
arg_nodes: &[AnalyzedNode], arg_nodes: &[Rc<AnalyzedNode>],
) -> Option<AnalyzedNode> { ) -> Option<AnalyzedNode> {
if callee.ty.purity < Purity::Pure { if callee.ty.purity < Purity::Pure {
return None; return None;
+4 -4
View File
@@ -65,7 +65,7 @@ impl<'a> Inliner<'a> {
pub fn prepare_beta_reduction( pub fn prepare_beta_reduction(
&self, &self,
params: &AnalyzedNode, params: &AnalyzedNode,
arg_vals: &[AnalyzedNode], arg_vals: &[Rc<AnalyzedNode>],
body: &AnalyzedNode, body: &AnalyzedNode,
sub: &mut SubstitutionMap, sub: &mut SubstitutionMap,
) -> Option<()> { ) -> Option<()> {
@@ -102,7 +102,7 @@ impl<'a> Inliner<'a> {
pub fn map_params_to_args( pub fn map_params_to_args(
&self, &self,
pattern: &AnalyzedNode, pattern: &AnalyzedNode,
args: &[AnalyzedNode], args: &[Rc<AnalyzedNode>],
offset: &mut usize, offset: &mut usize,
sub: &mut SubstitutionMap, sub: &mut SubstitutionMap,
body_usage: &UsageInfo, body_usage: &UsageInfo,
@@ -117,13 +117,13 @@ impl<'a> Inliner<'a> {
} else if let BoundKind::Lambda { upvalues, .. } = &arg.kind } else if let BoundKind::Lambda { upvalues, .. } = &arg.kind
&& upvalues.is_empty() && upvalues.is_empty()
{ {
sub.add_ast_substitution(*addr, arg.clone()); sub.add_ast_substitution(*addr, (**arg).clone());
} else if let BoundKind::Get { } else if let BoundKind::Get {
addr: Address::Global(_), addr: Address::Global(_),
.. ..
} = &arg.kind } = &arg.kind
{ {
sub.add_ast_substitution(*addr, arg.clone()); sub.add_ast_substitution(*addr, (**arg).clone());
} }
} }
+50 -32
View File
@@ -2,11 +2,12 @@ use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalS
use crate::ast::nodes::Node; use crate::ast::nodes::Node;
use crate::ast::types::Value; use crate::ast::types::Value;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::rc::Rc;
#[derive(Default)] #[derive(Default)]
pub struct SubstitutionMap { pub struct SubstitutionMap {
pub values: HashMap<Address, Value>, pub values: HashMap<Address, Value>,
pub ast_substitutions: HashMap<Address, AnalyzedNode>, pub ast_substitutions: HashMap<Address, Rc<AnalyzedNode>>,
pub slot_mapping: HashMap<LocalSlot, LocalSlot>, pub slot_mapping: HashMap<LocalSlot, LocalSlot>,
pub assigned: HashSet<Address>, pub assigned: HashSet<Address>,
pub next_slot: u32, pub next_slot: u32,
@@ -38,7 +39,7 @@ impl SubstitutionMap {
} }
pub fn add_ast_substitution(&mut self, addr: Address, node: AnalyzedNode) { pub fn add_ast_substitution(&mut self, addr: Address, node: AnalyzedNode) {
self.ast_substitutions.insert(addr, node); self.ast_substitutions.insert(addr, Rc::new(node));
} }
pub fn map_slot(&mut self, old_slot: LocalSlot) -> LocalSlot { pub fn map_slot(&mut self, old_slot: LocalSlot) -> LocalSlot {
@@ -81,12 +82,13 @@ impl SubstitutionMap {
} }
} }
pub fn reindex_upvalues(&self, node: AnalyzedNode, mapping: &[Option<u32>]) -> AnalyzedNode { pub fn reindex_upvalues(&self, node_rc: Rc<AnalyzedNode>, mapping: &[Option<u32>]) -> Rc<AnalyzedNode> {
let (new_kind, metrics) = match node.kind { let node = &*node_rc;
let (new_kind, metrics) = match &node.kind {
BoundKind::Get { addr, name } => ( BoundKind::Get { addr, name } => (
BoundKind::Get { BoundKind::Get {
addr: self.reindex_addr(addr, mapping), addr: self.reindex_addr(*addr, mapping),
name, name: name.clone(),
}, },
node.ty.clone(), node.ty.clone(),
), ),
@@ -98,14 +100,14 @@ impl SubstitutionMap {
} => { } => {
let mut next_upvalues = Vec::new(); let mut next_upvalues = Vec::new();
for addr in upvalues { for addr in upvalues {
next_upvalues.push(self.reindex_addr(addr, mapping)); next_upvalues.push(self.reindex_addr(*addr, mapping));
} }
( (
BoundKind::Lambda { BoundKind::Lambda {
params, params: params.clone(),
upvalues: next_upvalues, upvalues: next_upvalues,
body, body: body.clone(),
positional_count, positional_count: *positional_count,
}, },
node.ty.clone(), node.ty.clone(),
) )
@@ -115,9 +117,9 @@ impl SubstitutionMap {
then_br, then_br,
else_br, else_br,
} => { } => {
let cond = Box::new(self.reindex_upvalues(*cond, mapping)); let cond = self.reindex_upvalues(cond.clone(), mapping);
let then_br = Box::new(self.reindex_upvalues(*then_br, mapping)); let then_br = self.reindex_upvalues(then_br.clone(), mapping);
let else_br = else_br.map(|e| Box::new(self.reindex_upvalues(*e, mapping))); let else_br = else_br.as_ref().map(|e| self.reindex_upvalues(e.clone(), mapping));
( (
BoundKind::If { BoundKind::If {
cond, cond,
@@ -129,14 +131,14 @@ impl SubstitutionMap {
} }
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
let exprs = exprs let exprs = exprs
.into_iter() .iter()
.map(|e| self.reindex_upvalues(e, mapping)) .map(|e| self.reindex_upvalues(e.clone(), mapping))
.collect(); .collect();
(BoundKind::Block { exprs }, node.ty.clone()) (BoundKind::Block { exprs }, node.ty.clone())
} }
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
let callee = Box::new(self.reindex_upvalues(*callee, mapping)); let callee = self.reindex_upvalues(callee.clone(), mapping);
let args = Box::new(self.reindex_upvalues(*args, mapping)); let args = self.reindex_upvalues(args.clone(), mapping);
(BoundKind::Call { callee, args }, node.ty.clone()) (BoundKind::Call { callee, args }, node.ty.clone())
} }
BoundKind::Define { BoundKind::Define {
@@ -146,42 +148,58 @@ impl SubstitutionMap {
value, value,
captured_by, captured_by,
} => { } => {
let value = Box::new(self.reindex_upvalues(*value, mapping)); let value = self.reindex_upvalues(value.clone(), mapping);
( (
BoundKind::Define { BoundKind::Define {
name, name: name.clone(),
addr, addr: *addr,
kind, kind: *kind,
value, value,
captured_by, captured_by: captured_by.clone(),
}, },
node.ty.clone(), node.ty.clone(),
) )
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
let value = Box::new(self.reindex_upvalues(*value, mapping)); let value = self.reindex_upvalues(value.clone(), mapping);
(BoundKind::Set { addr, value }, node.ty.clone()) (
BoundKind::Set {
addr: *addr,
value,
},
node.ty.clone(),
)
} }
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let elements = elements let elements = elements
.into_iter() .iter()
.map(|e| self.reindex_upvalues(e, mapping)) .map(|e| self.reindex_upvalues(e.clone(), mapping))
.collect(); .collect();
(BoundKind::Tuple { elements }, node.ty.clone()) (BoundKind::Tuple { elements }, node.ty.clone())
} }
BoundKind::Record { layout, values } => { BoundKind::Record { layout, values } => {
let values = values let values = values
.into_iter() .iter()
.map(|v| self.reindex_upvalues(v, mapping)) .map(|v| self.reindex_upvalues(v.clone(), mapping))
.collect(); .collect();
(BoundKind::Record { layout, values }, node.ty.clone()) (BoundKind::Record { layout: layout.clone(), values }, node.ty.clone())
} }
k => (k, node.ty.clone()), BoundKind::Expansion { original_call, bound_expanded } => {
let bound_expanded = self.reindex_upvalues(bound_expanded.clone(), mapping);
(
BoundKind::Expansion {
original_call: original_call.clone(),
bound_expanded,
},
node.ty.clone(),
)
}
k => (k.clone(), node.ty.clone()),
}; };
Node { Rc::new(Node {
identity: node.identity.clone(), identity: node.identity.clone(),
kind: new_kind, kind: new_kind,
ty: metrics, ty: metrics,
} })
} }
} }
+20 -20
View File
@@ -53,13 +53,13 @@ impl Specializer {
let (new_kind, metrics) = match node.kind { let (new_kind, metrics) = match node.kind {
BoundKind::Call { callee, args } => { BoundKind::Call { callee, args } => {
let (new_callee, new_args, _ret_ty) = let (new_callee, new_args, _ret_ty) =
self.specialize_call_logic(*callee, *args, node.ty.original.ty.clone()); self.specialize_call_logic(callee, args, node.ty.original.ty.clone());
let new_metrics = node.ty.clone(); let new_metrics = node.ty.clone();
( (
BoundKind::Call { BoundKind::Call {
callee: Box::new(new_callee), callee: Rc::new(new_callee),
args: Box::new(new_args), args: Rc::new(new_args),
}, },
new_metrics, new_metrics,
) )
@@ -70,9 +70,9 @@ impl Specializer {
then_br, then_br,
else_br, else_br,
} => { } => {
let cond = Box::new(self.visit_node(*cond)); let cond = Rc::new(self.visit_node(cond.as_ref().clone()));
let then_br = Box::new(self.visit_node(*then_br)); let then_br = Rc::new(self.visit_node(then_br.as_ref().clone()));
let else_br = else_br.map(|e| Box::new(self.visit_node(*e))); let else_br = else_br.map(|e| Rc::new(self.visit_node(e.as_ref().clone())));
( (
BoundKind::If { BoundKind::If {
cond, cond,
@@ -83,7 +83,7 @@ impl Specializer {
) )
} }
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
let exprs = exprs.into_iter().map(|e| self.visit_node(e)).collect(); let exprs = exprs.into_iter().map(|e| Rc::new(self.visit_node(e.as_ref().clone()))).collect();
(BoundKind::Block { exprs }, node.ty.clone()) (BoundKind::Block { exprs }, node.ty.clone())
} }
BoundKind::Lambda { BoundKind::Lambda {
@@ -93,7 +93,7 @@ impl Specializer {
positional_count, positional_count,
} => { } => {
let params = Rc::new(self.visit_node(params.as_ref().clone())); let params = Rc::new(self.visit_node(params.as_ref().clone()));
let body = Rc::new(self.visit_node((*body).clone())); let body = Rc::new(self.visit_node(body.as_ref().clone()));
( (
BoundKind::Lambda { BoundKind::Lambda {
params, params,
@@ -111,7 +111,7 @@ impl Specializer {
value, value,
captured_by, captured_by,
} => { } => {
let value = Box::new(self.visit_node(*value)); let value = Rc::new(self.visit_node(value.as_ref().clone()));
( (
BoundKind::Define { BoundKind::Define {
name: name.clone(), name: name.clone(),
@@ -124,22 +124,22 @@ impl Specializer {
) )
} }
BoundKind::Set { addr, value } => { BoundKind::Set { addr, value } => {
let value = Box::new(self.visit_node(*value)); let value = Rc::new(self.visit_node(value.as_ref().clone()));
(BoundKind::Set { addr, value }, node.ty.clone()) (BoundKind::Set { addr, value }, node.ty.clone())
} }
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let elements = elements.into_iter().map(|e| self.visit_node(e)).collect(); let elements = elements.into_iter().map(|e| Rc::new(self.visit_node(e.as_ref().clone()))).collect();
(BoundKind::Tuple { elements }, node.ty.clone()) (BoundKind::Tuple { elements }, node.ty.clone())
} }
BoundKind::Record { layout, values } => { BoundKind::Record { layout, values } => {
let values = values.into_iter().map(|v| self.visit_node(v)).collect(); let values = values.into_iter().map(|v| Rc::new(self.visit_node(v.as_ref().clone()))).collect();
(BoundKind::Record { layout, values }, node.ty.clone()) (BoundKind::Record { layout, values }, node.ty.clone())
} }
BoundKind::Expansion { BoundKind::Expansion {
original_call, original_call,
bound_expanded, bound_expanded,
} => { } => {
let bound_expanded = Box::new(self.visit_node(*bound_expanded)); let bound_expanded = Rc::new(self.visit_node(bound_expanded.as_ref().clone()));
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call, original_call,
@@ -160,12 +160,12 @@ impl Specializer {
fn specialize_call_logic( fn specialize_call_logic(
&self, &self,
callee: AnalyzedNode, callee: Rc<AnalyzedNode>,
args: AnalyzedNode, args: Rc<AnalyzedNode>,
original_ty: StaticType, original_ty: StaticType,
) -> (AnalyzedNode, AnalyzedNode, StaticType) { ) -> (AnalyzedNode, AnalyzedNode, StaticType) {
let new_callee = self.visit_node(callee); let new_callee = self.visit_node(callee.as_ref().clone());
let new_args = self.visit_node(args); let new_args = self.visit_node(args.as_ref().clone());
let address = if let BoundKind::Get { addr, .. } = &new_callee.kind { let address = if let BoundKind::Get { addr, .. } = &new_callee.kind {
*addr *addr
@@ -233,9 +233,9 @@ impl Specializer {
self.cache self.cache
.borrow_mut() .borrow_mut()
.insert(key, (compiled_val.clone(), ret_ty.clone())); .insert(key, (compiled_val.clone(), ret_ty.clone()));
let flat_elements = match new_args.kind { let flat_elements = match &new_args.kind {
BoundKind::Tuple { elements } => elements, BoundKind::Tuple { elements } => elements.clone(),
_ => vec![new_args.clone()], _ => vec![Rc::new(new_args.clone())],
}; };
let flat_types = flat_elements let flat_types = flat_elements
.iter() .iter()
+21 -21
View File
@@ -36,8 +36,8 @@ impl TCO {
let node = &*node_rc; let node = &*node_rc;
let new_kind = match &node.kind { let new_kind = match &node.kind {
BoundKind::Call { callee, args } => BoundKind::Call { BoundKind::Call { callee, args } => BoundKind::Call {
callee: Box::new(Self::transform(Rc::new((**callee).clone()), false)), callee: Rc::new(Self::transform(callee.clone(), false)),
args: Box::new(Self::transform(Rc::new((**args).clone()), false)), args: Rc::new(Self::transform(args.clone(), false)),
}, },
BoundKind::Again { args } => { BoundKind::Again { args } => {
@@ -45,7 +45,7 @@ impl TCO {
panic!("'again' is only allowed in tail position to avoid dead code."); panic!("'again' is only allowed in tail position to avoid dead code.");
} }
BoundKind::Again { BoundKind::Again {
args: Box::new(Self::transform(Rc::new((**args).clone()), false)), args: Rc::new(Self::transform(args.clone(), false)),
} }
} }
BoundKind::Pipe { BoundKind::Pipe {
@@ -55,11 +55,11 @@ impl TCO {
} => { } => {
let mut t_inputs = Vec::with_capacity(inputs.len()); let mut t_inputs = Vec::with_capacity(inputs.len());
for input in inputs { for input in inputs {
t_inputs.push(Self::transform(Rc::new(input.clone()), false)); t_inputs.push(Rc::new(Self::transform(input.clone(), false)));
} }
BoundKind::Pipe { BoundKind::Pipe {
inputs: t_inputs, inputs: t_inputs,
lambda: Box::new(Self::transform(Rc::new((**lambda).clone()), false)), lambda: Rc::new(Self::transform(lambda.clone(), false)),
out_type: out_type.clone(), out_type: out_type.clone(),
} }
} }
@@ -69,14 +69,14 @@ impl TCO {
then_br, then_br,
else_br, else_br,
} => BoundKind::If { } => BoundKind::If {
cond: Box::new(Self::transform(Rc::new((**cond).clone()), false)), cond: Rc::new(Self::transform(cond.clone(), false)),
then_br: Box::new(Self::transform( then_br: Rc::new(Self::transform(
Rc::new((**then_br).clone()), then_br.clone(),
is_tail_position, is_tail_position,
)), )),
else_br: else_br else_br: else_br
.as_ref() .as_ref()
.map(|e| Box::new(Self::transform(Rc::new((**e).clone()), is_tail_position))), .map(|e| Rc::new(Self::transform(e.clone(), is_tail_position))),
}, },
BoundKind::Block { exprs } => { BoundKind::Block { exprs } => {
@@ -88,10 +88,10 @@ impl TCO {
for (i, expr) in exprs.iter().enumerate() { for (i, expr) in exprs.iter().enumerate() {
let is_last = i == last_idx; let is_last = i == last_idx;
new_exprs.push(Self::transform( new_exprs.push(Rc::new(Self::transform(
Rc::new(expr.clone()), expr.clone(),
is_tail_position && is_last, is_tail_position && is_last,
)); )));
} }
BoundKind::Block { exprs: new_exprs } BoundKind::Block { exprs: new_exprs }
} }
@@ -111,7 +111,7 @@ impl TCO {
BoundKind::Set { addr, value } => BoundKind::Set { BoundKind::Set { addr, value } => BoundKind::Set {
addr: *addr, addr: *addr,
value: Box::new(Self::transform(Rc::new((**value).clone()), false)), value: Rc::new(Self::transform(value.clone(), false)),
}, },
BoundKind::Define { BoundKind::Define {
name, name,
@@ -123,17 +123,17 @@ impl TCO {
name: name.clone(), name: name.clone(),
addr: *addr, addr: *addr,
kind: *kind, kind: *kind,
value: Box::new(Self::transform(Rc::new((**value).clone()), false)), value: Rc::new(Self::transform(value.clone(), false)),
captured_by: captured_by.clone(), captured_by: captured_by.clone(),
}, },
BoundKind::Destructure { pattern, value } => BoundKind::Destructure { BoundKind::Destructure { pattern, value } => BoundKind::Destructure {
pattern: Box::new(Self::transform(Rc::new((**pattern).clone()), false)), pattern: Rc::new(Self::transform(pattern.clone(), false)),
value: Box::new(Self::transform(Rc::new((**value).clone()), false)), value: Rc::new(Self::transform(value.clone(), false)),
}, },
BoundKind::Record { layout, values } => { BoundKind::Record { layout, values } => {
let new_values = values let new_values = values
.iter() .iter()
.map(|v| Self::transform(Rc::new(v.clone()), false)) .map(|v| Rc::new(Self::transform(v.clone(), false)))
.collect(); .collect();
BoundKind::Record { BoundKind::Record {
layout: layout.clone(), layout: layout.clone(),
@@ -143,7 +143,7 @@ impl TCO {
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let new_elements = elements let new_elements = elements
.iter() .iter()
.map(|e| Self::transform(Rc::new(e.clone()), false)) .map(|e| Rc::new(Self::transform(e.clone(), false)))
.collect(); .collect();
BoundKind::Tuple { BoundKind::Tuple {
elements: new_elements, elements: new_elements,
@@ -156,7 +156,7 @@ impl TCO {
}, },
BoundKind::FieldAccessor(k) => BoundKind::FieldAccessor(*k), BoundKind::FieldAccessor(k) => BoundKind::FieldAccessor(*k),
BoundKind::GetField { rec, field } => BoundKind::GetField { BoundKind::GetField { rec, field } => BoundKind::GetField {
rec: Box::new(Self::transform(Rc::new((**rec).clone()), false)), rec: Rc::new(Self::transform(rec.clone(), false)),
field: *field, field: *field,
}, },
BoundKind::Nop => BoundKind::Nop, BoundKind::Nop => BoundKind::Nop,
@@ -165,8 +165,8 @@ impl TCO {
bound_expanded, bound_expanded,
} => BoundKind::Expansion { } => BoundKind::Expansion {
original_call: original_call.clone(), original_call: original_call.clone(),
bound_expanded: Box::new(Self::transform( bound_expanded: Rc::new(Self::transform(
Rc::new((**bound_expanded).clone()), bound_expanded.clone(),
is_tail_position, is_tail_position,
)), )),
}, },
+22 -22
View File
@@ -182,7 +182,7 @@ impl TypeChecker {
name: name.clone(), name: name.clone(),
addr: *addr, addr: *addr,
kind: *decl_kind, kind: *decl_kind,
value: Box::new(Node { value: Rc::new(Node {
identity: node.identity.clone(), identity: node.identity.clone(),
kind: BoundKind::Nop, kind: BoundKind::Nop,
ty: specialized_ty.clone(), ty: specialized_ty.clone(),
@@ -203,7 +203,7 @@ impl TypeChecker {
( (
BoundKind::Set { BoundKind::Set {
addr: *addr, addr: *addr,
value: Box::new(Node { value: Rc::new(Node {
identity: node.identity.clone(), identity: node.identity.clone(),
kind: BoundKind::Nop, kind: BoundKind::Nop,
ty: specialized_ty.clone(), ty: specialized_ty.clone(),
@@ -256,7 +256,7 @@ impl TypeChecker {
}; };
let t = self.check_params(el, &sub_ty, ctx, diag); let t = self.check_params(el, &sub_ty, ctx, diag);
elem_types.push(t.ty.clone()); elem_types.push(t.ty.clone());
typed_elements.push(t); typed_elements.push(Rc::new(t));
} }
( (
BoundKind::Tuple { BoundKind::Tuple {
@@ -312,7 +312,7 @@ impl TypeChecker {
name: name.clone(), name: name.clone(),
addr: *addr, addr: *addr,
kind: *decl_kind, kind: *decl_kind,
value: Box::new(val_typed), value: Rc::new(val_typed),
captured_by: captured_by.clone(), captured_by: captured_by.clone(),
}, },
ty, ty,
@@ -364,7 +364,7 @@ impl TypeChecker {
}; };
( (
BoundKind::GetField { BoundKind::GetField {
rec: Box::new(rec_typed), rec: Rc::new(rec_typed),
field: *field, field: *field,
}, },
field_ty, field_ty,
@@ -379,7 +379,7 @@ impl TypeChecker {
( (
BoundKind::Set { BoundKind::Set {
addr: *addr, addr: *addr,
value: Box::new(val_typed), value: Rc::new(val_typed),
}, },
ty, ty,
) )
@@ -391,8 +391,8 @@ impl TypeChecker {
let ty = val_typed.ty.clone(); let ty = val_typed.ty.clone();
( (
BoundKind::Destructure { BoundKind::Destructure {
pattern: Box::new(pat_typed), pattern: Rc::new(pat_typed),
value: Box::new(val_typed), value: Rc::new(val_typed),
}, },
ty, ty,
) )
@@ -415,7 +415,7 @@ impl TypeChecker {
if et.ty != final_ty { if et.ty != final_ty {
final_ty = StaticType::Any; final_ty = StaticType::Any;
} }
else_typed = Some(Box::new(et)); else_typed = Some(Rc::new(et));
} else { } else {
// If without else returns Optional(Then) (T | Void) // If without else returns Optional(Then) (T | Void)
final_ty = StaticType::Optional(Box::new(then_typed.ty.clone())); final_ty = StaticType::Optional(Box::new(then_typed.ty.clone()));
@@ -423,8 +423,8 @@ impl TypeChecker {
( (
BoundKind::If { BoundKind::If {
cond: Box::new(cond_typed), cond: Rc::new(cond_typed),
then_br: Box::new(then_typed), then_br: Rc::new(then_typed),
else_br: else_typed, else_br: else_typed,
}, },
final_ty, final_ty,
@@ -443,7 +443,7 @@ impl TypeChecker {
StaticType::Any StaticType::Any
}; };
arg_types.push(arg_ty); arg_types.push(arg_ty);
typed_inputs.push(typed_input); typed_inputs.push(Rc::new(typed_input));
} }
// Specialized check for the lambda using the input types! // Specialized check for the lambda using the input types!
@@ -462,7 +462,7 @@ impl TypeChecker {
( (
BoundKind::Pipe { BoundKind::Pipe {
inputs: typed_inputs, inputs: typed_inputs,
lambda: Box::new(typed_lambda), lambda: Rc::new(typed_lambda),
out_type: ret_ty.clone(), out_type: ret_ty.clone(),
}, },
StaticType::Series(Box::new(ret_ty)), StaticType::Series(Box::new(ret_ty)),
@@ -476,7 +476,7 @@ impl TypeChecker {
for e in exprs { for e in exprs {
let t = self.check_node(e, ctx, diag); let t = self.check_node(e, ctx, diag);
last_ty = t.ty.clone(); last_ty = t.ty.clone();
typed_exprs.push(t); typed_exprs.push(Rc::new(t));
} }
(BoundKind::Block { exprs: typed_exprs }, last_ty) (BoundKind::Block { exprs: typed_exprs }, last_ty)
@@ -539,7 +539,7 @@ impl TypeChecker {
for e in elements { for e in elements {
let t = self.check_node(e, ctx, diag); let t = self.check_node(e, ctx, diag);
elem_types.push(t.ty.clone()); elem_types.push(t.ty.clone());
typed_elements.push(t); typed_elements.push(Rc::new(t));
} }
Node { Node {
identity: args.identity.clone(), identity: args.identity.clone(),
@@ -569,8 +569,8 @@ impl TypeChecker {
( (
BoundKind::Call { BoundKind::Call {
callee: Box::new(callee_typed), callee: Rc::new(callee_typed),
args: Box::new(args_typed), args: Rc::new(args_typed),
}, },
ret_ty, ret_ty,
) )
@@ -584,7 +584,7 @@ impl TypeChecker {
for e in elements { for e in elements {
let t = self.check_node(e, ctx, diag); let t = self.check_node(e, ctx, diag);
elem_types.push(t.ty.clone()); elem_types.push(t.ty.clone());
typed_elements.push(t); typed_elements.push(Rc::new(t));
} }
Node { Node {
identity: args.identity.clone(), identity: args.identity.clone(),
@@ -611,7 +611,7 @@ impl TypeChecker {
( (
BoundKind::Again { BoundKind::Again {
args: Box::new(args_typed), args: Rc::new(args_typed),
}, },
StaticType::Any, StaticType::Any,
) )
@@ -620,7 +620,7 @@ impl TypeChecker {
BoundKind::Tuple { elements } => { BoundKind::Tuple { elements } => {
let mut typed_elements = Vec::new(); let mut typed_elements = Vec::new();
for e in elements { for e in elements {
typed_elements.push(self.check_node(e, ctx, diag)); typed_elements.push(Rc::new(self.check_node(e, ctx, diag)));
} }
let ty = if typed_elements.is_empty() { let ty = if typed_elements.is_empty() {
@@ -663,7 +663,7 @@ impl TypeChecker {
for (i, v) in values.iter().enumerate() { for (i, v) in values.iter().enumerate() {
let vt = self.check_node(v, ctx, diag); let vt = self.check_node(v, ctx, diag);
fields_ty.push((layout.fields[i].0, vt.ty.clone())); fields_ty.push((layout.fields[i].0, vt.ty.clone()));
typed_values.push(vt); typed_values.push(Rc::new(vt));
} }
let new_layout = crate::ast::types::RecordLayout::get_or_create(fields_ty); let new_layout = crate::ast::types::RecordLayout::get_or_create(fields_ty);
@@ -685,7 +685,7 @@ impl TypeChecker {
( (
BoundKind::Expansion { BoundKind::Expansion {
original_call: original_call.clone(), original_call: original_call.clone(),
bound_expanded: Box::new(expanded_typed), bound_expanded: Rc::new(expanded_typed),
}, },
ty, ty,
) )
+1 -1
View File
@@ -893,7 +893,7 @@ impl VM {
fn eval_and_flatten_internal<O: VMObserver>( fn eval_and_flatten_internal<O: VMObserver>(
&mut self, &mut self,
obs: &mut O, obs: &mut O,
elements: &[ExecNode], elements: &[Rc<ExecNode>],
into: &mut Vec<Value>, into: &mut Vec<Value>,
) -> Result<(), String> { ) -> Result<(), String> {
for e in elements { for e in elements {