Refactor: Rename TCO module to lowering
The TCO (Tail Call Optimization) module has been renamed to `lowering`. This change better reflects the module's broader responsibility, which includes not only TCO but also general AST transformations and preparation for VM execution. The `optimize` function has been renamed to `lower` to align with the module's new name.
This commit is contained in:
@@ -1,288 +1,288 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
||||||
use crate::ast::nodes::Node;
|
use crate::ast::nodes::Node;
|
||||||
use crate::ast::types::StaticType;
|
use crate::ast::types::StaticType;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RuntimeMetadata {
|
pub struct RuntimeMetadata {
|
||||||
pub ty: StaticType,
|
pub ty: StaticType,
|
||||||
pub is_tail: bool,
|
pub is_tail: bool,
|
||||||
/// The analyzed node, containing metrics and a link to the original TypedNode.
|
/// The analyzed node, containing metrics and a link to the original TypedNode.
|
||||||
pub original: Rc<AnalyzedNode>,
|
pub original: Rc<AnalyzedNode>,
|
||||||
pub stack_size: u32,
|
pub stack_size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for RuntimeMetadata {
|
impl Debug for RuntimeMetadata {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Metadata")
|
f.debug_struct("Metadata")
|
||||||
.field("ty", &self.ty)
|
.field("ty", &self.ty)
|
||||||
.field("is_tail", &self.is_tail)
|
.field("is_tail", &self.is_tail)
|
||||||
.field("stack_size", &self.stack_size)
|
.field("stack_size", &self.stack_size)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ExecNode is the AST used by the VM. It carries TCO flags and links to metrics.
|
/// The ExecNode is the AST used by the VM. It carries TCO flags and links to metrics.
|
||||||
pub type ExecNode = Node<BoundKind<RuntimeMetadata>, RuntimeMetadata>;
|
pub type ExecNode = Node<BoundKind<RuntimeMetadata>, RuntimeMetadata>;
|
||||||
|
|
||||||
fn calc_stack_size<T>(root_node: &Node<BoundKind<T>, T>) -> u32 {
|
fn calc_stack_size<T>(root_node: &Node<BoundKind<T>, T>) -> u32 {
|
||||||
let mut max_slot = -1i32;
|
let mut max_slot = -1i32;
|
||||||
|
|
||||||
fn visit<T>(node: &Node<BoundKind<T>, T>, max_slot: &mut i32) {
|
fn visit<T>(node: &Node<BoundKind<T>, T>, max_slot: &mut i32) {
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::Get {
|
BoundKind::Get {
|
||||||
addr: Address::Local(slot),
|
addr: Address::Local(slot),
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| BoundKind::Set {
|
| BoundKind::Set {
|
||||||
addr: Address::Local(slot),
|
addr: Address::Local(slot),
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
| BoundKind::Define {
|
| BoundKind::Define {
|
||||||
addr: Address::Local(slot),
|
addr: Address::Local(slot),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if slot.0 as i32 > *max_slot {
|
if slot.0 as i32 > *max_slot {
|
||||||
*max_slot = slot.0 as i32;
|
*max_slot = slot.0 as i32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Lambda { .. } => {
|
BoundKind::Lambda { .. } => {
|
||||||
// Do NOT recurse into nested lambdas to prevent over-allocating outer stacks
|
// Do NOT recurse into nested lambdas to prevent over-allocating outer stacks
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic traversal
|
// Generic traversal
|
||||||
match &node.kind {
|
match &node.kind {
|
||||||
BoundKind::If {
|
BoundKind::If {
|
||||||
cond,
|
cond,
|
||||||
then_br,
|
then_br,
|
||||||
else_br,
|
else_br,
|
||||||
} => {
|
} => {
|
||||||
visit(cond, max_slot);
|
visit(cond, max_slot);
|
||||||
visit(then_br, max_slot);
|
visit(then_br, max_slot);
|
||||||
if let Some(e) = else_br {
|
if let Some(e) = else_br {
|
||||||
visit(e, max_slot);
|
visit(e, max_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Set { value, .. } | BoundKind::Define { value, .. } => {
|
BoundKind::Set { value, .. } | BoundKind::Define { value, .. } => {
|
||||||
visit(value, max_slot);
|
visit(value, max_slot);
|
||||||
}
|
}
|
||||||
BoundKind::Destructure { pattern, value } => {
|
BoundKind::Destructure { pattern, value } => {
|
||||||
visit(pattern, max_slot);
|
visit(pattern, max_slot);
|
||||||
visit(value, max_slot);
|
visit(value, max_slot);
|
||||||
}
|
}
|
||||||
BoundKind::Pipe { inputs, lambda, .. } => {
|
BoundKind::Pipe { inputs, lambda, .. } => {
|
||||||
for i in inputs {
|
for i in inputs {
|
||||||
visit(i, max_slot);
|
visit(i, max_slot);
|
||||||
}
|
}
|
||||||
visit(lambda, max_slot);
|
visit(lambda, max_slot);
|
||||||
}
|
}
|
||||||
BoundKind::Call { callee, args } => {
|
BoundKind::Call { callee, args } => {
|
||||||
visit(callee, max_slot);
|
visit(callee, max_slot);
|
||||||
visit(args, max_slot);
|
visit(args, max_slot);
|
||||||
}
|
}
|
||||||
BoundKind::Again { args } => visit(args, max_slot),
|
BoundKind::Again { args } => visit(args, max_slot),
|
||||||
BoundKind::Block { exprs } => {
|
BoundKind::Block { exprs } => {
|
||||||
for e in exprs {
|
for e in exprs {
|
||||||
visit(e, max_slot);
|
visit(e, max_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Tuple { elements } => {
|
BoundKind::Tuple { elements } => {
|
||||||
for e in elements {
|
for e in elements {
|
||||||
visit(e, max_slot);
|
visit(e, max_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Record { values, .. } => {
|
BoundKind::Record { values, .. } => {
|
||||||
for v in values {
|
for v in values {
|
||||||
visit(v, max_slot);
|
visit(v, max_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Expansion { bound_expanded, .. } => visit(bound_expanded, max_slot),
|
BoundKind::Expansion { bound_expanded, .. } => visit(bound_expanded, max_slot),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for root: if the node itself is a lambda, we DO want to visit its params and body,
|
// Special case for root: if the node itself is a lambda, we DO want to visit its params and body,
|
||||||
// but not any deeply nested lambdas.
|
// but not any deeply nested lambdas.
|
||||||
if let BoundKind::Lambda { params, body, .. } = &root_node.kind {
|
if let BoundKind::Lambda { params, body, .. } = &root_node.kind {
|
||||||
visit(params, &mut max_slot);
|
visit(params, &mut max_slot);
|
||||||
visit(body, &mut max_slot);
|
visit(body, &mut max_slot);
|
||||||
} else {
|
} else {
|
||||||
visit(root_node, &mut max_slot);
|
visit(root_node, &mut max_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
(max_slot + 1) as u32
|
(max_slot + 1) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TCO;
|
pub struct Lowering;
|
||||||
|
|
||||||
impl TCO {
|
impl Lowering {
|
||||||
/// Lowers an AnalyzedNode to an ExecNode and marks tail positions.
|
/// Lowers an AnalyzedNode to an ExecNode, marking tail positions and calculating stack sizes.
|
||||||
pub fn optimize(node: AnalyzedNode) -> ExecNode {
|
pub fn lower(node: AnalyzedNode) -> ExecNode {
|
||||||
let root_stack_size = calc_stack_size(&node);
|
let root_stack_size = calc_stack_size(&node);
|
||||||
let mut exec_node = Self::transform(Rc::new(node), true);
|
let mut exec_node = Self::transform(Rc::new(node), true);
|
||||||
exec_node.ty.stack_size = root_stack_size;
|
exec_node.ty.stack_size = root_stack_size;
|
||||||
exec_node
|
exec_node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform(node_rc: Rc<AnalyzedNode>, is_tail_position: bool) -> ExecNode {
|
fn transform(node_rc: Rc<AnalyzedNode>, is_tail_position: bool) -> ExecNode {
|
||||||
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: Rc::new(Self::transform(callee.clone(), false)),
|
callee: Rc::new(Self::transform(callee.clone(), false)),
|
||||||
args: Rc::new(Self::transform(args.clone(), false)),
|
args: Rc::new(Self::transform(args.clone(), false)),
|
||||||
},
|
},
|
||||||
|
|
||||||
BoundKind::Again { args } => {
|
BoundKind::Again { args } => {
|
||||||
if !is_tail_position {
|
if !is_tail_position {
|
||||||
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: Rc::new(Self::transform(args.clone(), false)),
|
args: Rc::new(Self::transform(args.clone(), false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Pipe {
|
BoundKind::Pipe {
|
||||||
inputs,
|
inputs,
|
||||||
lambda,
|
lambda,
|
||||||
out_type,
|
out_type,
|
||||||
} => {
|
} => {
|
||||||
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(Rc::new(Self::transform(input.clone(), false)));
|
t_inputs.push(Rc::new(Self::transform(input.clone(), false)));
|
||||||
}
|
}
|
||||||
BoundKind::Pipe {
|
BoundKind::Pipe {
|
||||||
inputs: t_inputs,
|
inputs: t_inputs,
|
||||||
lambda: Rc::new(Self::transform(lambda.clone(), false)),
|
lambda: Rc::new(Self::transform(lambda.clone(), false)),
|
||||||
out_type: out_type.clone(),
|
out_type: out_type.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::If {
|
BoundKind::If {
|
||||||
cond,
|
cond,
|
||||||
then_br,
|
then_br,
|
||||||
else_br,
|
else_br,
|
||||||
} => BoundKind::If {
|
} => BoundKind::If {
|
||||||
cond: Rc::new(Self::transform(cond.clone(), false)),
|
cond: Rc::new(Self::transform(cond.clone(), false)),
|
||||||
then_br: Rc::new(Self::transform(
|
then_br: Rc::new(Self::transform(
|
||||||
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| Rc::new(Self::transform(e.clone(), is_tail_position))),
|
.map(|e| Rc::new(Self::transform(e.clone(), is_tail_position))),
|
||||||
},
|
},
|
||||||
|
|
||||||
BoundKind::Block { exprs } => {
|
BoundKind::Block { exprs } => {
|
||||||
if exprs.is_empty() {
|
if exprs.is_empty() {
|
||||||
BoundKind::Block { exprs: vec![] }
|
BoundKind::Block { exprs: vec![] }
|
||||||
} else {
|
} else {
|
||||||
let last_idx = exprs.len() - 1;
|
let last_idx = exprs.len() - 1;
|
||||||
let mut new_exprs = Vec::with_capacity(exprs.len());
|
let mut new_exprs = Vec::with_capacity(exprs.len());
|
||||||
|
|
||||||
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(Rc::new(Self::transform(
|
new_exprs.push(Rc::new(Self::transform(
|
||||||
expr.clone(),
|
expr.clone(),
|
||||||
is_tail_position && is_last,
|
is_tail_position && is_last,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
BoundKind::Block { exprs: new_exprs }
|
BoundKind::Block { exprs: new_exprs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Lambda {
|
BoundKind::Lambda {
|
||||||
params,
|
params,
|
||||||
upvalues,
|
upvalues,
|
||||||
body,
|
body,
|
||||||
positional_count,
|
positional_count,
|
||||||
} => BoundKind::Lambda {
|
} => BoundKind::Lambda {
|
||||||
params: Rc::new(Self::transform(params.clone(), false)),
|
params: Rc::new(Self::transform(params.clone(), false)),
|
||||||
upvalues: upvalues.clone(),
|
upvalues: upvalues.clone(),
|
||||||
body: Rc::new(Self::transform(body.clone(), true)),
|
body: Rc::new(Self::transform(body.clone(), true)),
|
||||||
positional_count: *positional_count,
|
positional_count: *positional_count,
|
||||||
},
|
},
|
||||||
|
|
||||||
BoundKind::Set { addr, value } => BoundKind::Set {
|
BoundKind::Set { addr, value } => BoundKind::Set {
|
||||||
addr: *addr,
|
addr: *addr,
|
||||||
value: Rc::new(Self::transform(value.clone(), false)),
|
value: Rc::new(Self::transform(value.clone(), false)),
|
||||||
},
|
},
|
||||||
BoundKind::Define {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
addr,
|
addr,
|
||||||
kind,
|
kind,
|
||||||
value,
|
value,
|
||||||
captured_by,
|
captured_by,
|
||||||
} => BoundKind::Define {
|
} => BoundKind::Define {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
addr: *addr,
|
addr: *addr,
|
||||||
kind: *kind,
|
kind: *kind,
|
||||||
value: Rc::new(Self::transform(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: Rc::new(Self::transform(pattern.clone(), false)),
|
pattern: Rc::new(Self::transform(pattern.clone(), false)),
|
||||||
value: Rc::new(Self::transform(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| Rc::new(Self::transform(v.clone(), false)))
|
.map(|v| Rc::new(Self::transform(v.clone(), false)))
|
||||||
.collect();
|
.collect();
|
||||||
BoundKind::Record {
|
BoundKind::Record {
|
||||||
layout: layout.clone(),
|
layout: layout.clone(),
|
||||||
values: new_values,
|
values: new_values,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BoundKind::Tuple { elements } => {
|
BoundKind::Tuple { elements } => {
|
||||||
let new_elements = elements
|
let new_elements = elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| Rc::new(Self::transform(e.clone(), false)))
|
.map(|e| Rc::new(Self::transform(e.clone(), false)))
|
||||||
.collect();
|
.collect();
|
||||||
BoundKind::Tuple {
|
BoundKind::Tuple {
|
||||||
elements: new_elements,
|
elements: new_elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
},
|
},
|
||||||
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: Rc::new(Self::transform(rec.clone(), false)),
|
rec: Rc::new(Self::transform(rec.clone(), false)),
|
||||||
field: *field,
|
field: *field,
|
||||||
},
|
},
|
||||||
BoundKind::Nop => BoundKind::Nop,
|
BoundKind::Nop => BoundKind::Nop,
|
||||||
BoundKind::Expansion {
|
BoundKind::Expansion {
|
||||||
original_call,
|
original_call,
|
||||||
bound_expanded,
|
bound_expanded,
|
||||||
} => BoundKind::Expansion {
|
} => BoundKind::Expansion {
|
||||||
original_call: original_call.clone(),
|
original_call: original_call.clone(),
|
||||||
bound_expanded: Rc::new(Self::transform(
|
bound_expanded: Rc::new(Self::transform(
|
||||||
bound_expanded.clone(),
|
bound_expanded.clone(),
|
||||||
is_tail_position,
|
is_tail_position,
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
BoundKind::Extension(_) => BoundKind::Nop,
|
BoundKind::Extension(_) => BoundKind::Nop,
|
||||||
BoundKind::Error => BoundKind::Error,
|
BoundKind::Error => BoundKind::Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
let stack_size = match &new_kind {
|
let stack_size = match &new_kind {
|
||||||
BoundKind::Lambda { .. } => calc_stack_size(node),
|
BoundKind::Lambda { .. } => calc_stack_size(node),
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
identity: node.identity.clone(),
|
identity: node.identity.clone(),
|
||||||
kind: new_kind,
|
kind: new_kind,
|
||||||
ty: RuntimeMetadata {
|
ty: RuntimeMetadata {
|
||||||
ty: node.ty.original.ty.clone(),
|
ty: node.ty.original.ty.clone(),
|
||||||
is_tail: is_tail_position,
|
is_tail: is_tail_position,
|
||||||
original: node_rc,
|
original: node_rc,
|
||||||
stack_size,
|
stack_size,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ pub mod lambda_collector;
|
|||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod optimizer;
|
pub mod optimizer;
|
||||||
pub mod specializer;
|
pub mod specializer;
|
||||||
pub mod tco;
|
pub mod lowering;
|
||||||
pub mod type_checker;
|
pub mod type_checker;
|
||||||
|
|
||||||
pub use binder::*;
|
pub use binder::*;
|
||||||
@@ -17,5 +17,5 @@ pub use dumper::*;
|
|||||||
pub use macros::*;
|
pub use macros::*;
|
||||||
pub use optimizer::*;
|
pub use optimizer::*;
|
||||||
pub use specializer::*;
|
pub use specializer::*;
|
||||||
pub use tco::*;
|
pub use lowering::*;
|
||||||
pub use type_checker::*;
|
pub use type_checker::*;
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ use crate::ast::compiler::bound_nodes::{
|
|||||||
};
|
};
|
||||||
use crate::ast::compiler::dumper::Dumper;
|
use crate::ast::compiler::dumper::Dumper;
|
||||||
use crate::ast::compiler::lambda_collector::LambdaCollector;
|
use crate::ast::compiler::lambda_collector::LambdaCollector;
|
||||||
|
use crate::ast::compiler::lowering::{ExecNode, Lowering};
|
||||||
use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry};
|
use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry};
|
||||||
use crate::ast::compiler::optimizer::Optimizer;
|
use crate::ast::compiler::optimizer::Optimizer;
|
||||||
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer};
|
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer};
|
||||||
use crate::ast::compiler::tco::{ExecNode, TCO};
|
|
||||||
use crate::ast::rtl::intrinsics;
|
use crate::ast::rtl::intrinsics;
|
||||||
use crate::ast::types::{
|
use crate::ast::types::{
|
||||||
Identity, NodeIdentity, Object, Purity, SourceLocation, StaticType, Value,
|
Identity, NodeIdentity, Object, Purity, SourceLocation, StaticType, Value,
|
||||||
@@ -141,7 +141,7 @@ impl MacroEvaluator for RuntimeMacroEvaluator {
|
|||||||
.join("\n"));
|
.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let exec_ast = TCO::optimize(Analyzer::analyze(&typed_ast, &HashMap::new())); // Minimal analysis for macro eval
|
let exec_ast = Lowering::lower(Analyzer::analyze(&typed_ast, &HashMap::new())); // Minimal analysis for macro eval
|
||||||
|
|
||||||
let mut vm = VM::new(self.global_values.clone());
|
let mut vm = VM::new(self.global_values.clone());
|
||||||
vm.run(&exec_ast)
|
vm.run(&exec_ast)
|
||||||
@@ -586,8 +586,8 @@ impl Environment {
|
|||||||
.with_registry(self.typed_function_registry.clone());
|
.with_registry(self.typed_function_registry.clone());
|
||||||
let optimized = optimizer.optimize(specialized);
|
let optimized = optimizer.optimize(specialized);
|
||||||
|
|
||||||
// 5. TCO
|
// 5. Lowering
|
||||||
TCO::optimize(optimized)
|
Lowering::lower(optimized)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate(&self, node: ExecNode) -> Rc<crate::ast::types::NativeFunction> {
|
pub fn instantiate(&self, node: ExecNode) -> Rc<crate::ast::types::NativeFunction> {
|
||||||
@@ -705,14 +705,14 @@ impl Environment {
|
|||||||
.with_purity(global_purity.clone());
|
.with_purity(global_purity.clone());
|
||||||
let optimized_ast = optimizer.optimize(specialized_ast);
|
let optimized_ast = optimizer.optimize(specialized_ast);
|
||||||
|
|
||||||
let tco_ast = TCO::optimize(optimized_ast);
|
let exec_ast = Lowering::lower(optimized_ast);
|
||||||
let mut vm = VM::new(global_values.clone());
|
let mut vm = VM::new(global_values.clone());
|
||||||
let compiled_val = match vm.run(&tco_ast) {
|
let compiled_val = match vm.run(&exec_ast) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => return Err(format!("VM Error during specialization: {}", e)),
|
Err(e) => return Err(format!("VM Error during specialization: {}", e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_type = tco_ast.ty.ty.clone();
|
let ret_type = exec_ast.ty.ty.clone();
|
||||||
Ok((compiled_val, ret_type))
|
Ok((compiled_val, ret_type))
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -774,4 +774,3 @@ impl Environment {
|
|||||||
Ok((final_result, observer.logs))
|
Ok((final_result, observer.logs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind};
|
||||||
use crate::ast::compiler::tco::ExecNode;
|
use crate::ast::compiler::lowering::ExecNode;
|
||||||
use crate::ast::nodes::Node;
|
use crate::ast::nodes::Node;
|
||||||
use crate::ast::types::{Object, Value};
|
use crate::ast::types::{Object, Value};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|||||||
Reference in New Issue
Block a user