Refactor: Use root_purity instead of global_purity
This commit refactors the purity analysis from using a `HashMap<GlobalIdx, Purity>` to a `Vec<Purity>` indexed by `GlobalIdx.0`. This change simplifies the data structure and makes purity lookups more efficient. The `Binder`'s `globals` field has also been removed as it was not being used.
This commit is contained in:
@@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Analyzer<'a> {
|
pub struct Analyzer<'a> {
|
||||||
global_purity: &'a HashMap<GlobalIdx, Purity>,
|
root_purity: &'a [Purity],
|
||||||
/// Stack of currently visiting lambdas to detect direct recursion.
|
/// Stack of currently visiting lambdas to detect direct recursion.
|
||||||
lambda_stack: Vec<crate::ast::types::Identity>,
|
lambda_stack: Vec<crate::ast::types::Identity>,
|
||||||
/// Map of global index to its Lambda identity if known.
|
/// Map of global index to its Lambda identity if known.
|
||||||
@@ -18,10 +18,10 @@ pub struct Analyzer<'a> {
|
|||||||
impl<'a> Analyzer<'a> {
|
impl<'a> Analyzer<'a> {
|
||||||
pub fn analyze(
|
pub fn analyze(
|
||||||
node: &TypedNode,
|
node: &TypedNode,
|
||||||
global_purity: &'a HashMap<GlobalIdx, Purity>,
|
root_purity: &'a [Purity],
|
||||||
) -> AnalyzedNode {
|
) -> AnalyzedNode {
|
||||||
let mut analyzer = Self {
|
let mut analyzer = Self {
|
||||||
global_purity,
|
root_purity,
|
||||||
lambda_stack: Vec::new(),
|
lambda_stack: Vec::new(),
|
||||||
globals_to_lambdas: HashMap::new(),
|
globals_to_lambdas: HashMap::new(),
|
||||||
recursive_identities: HashSet::new(),
|
recursive_identities: HashSet::new(),
|
||||||
@@ -70,7 +70,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
let p = match addr {
|
let p = match addr {
|
||||||
Address::Global(idx) => {
|
Address::Global(idx) => {
|
||||||
self.global_purity.get(idx).cloned().unwrap_or(Purity::Pure)
|
self.root_purity.get(idx.0 as usize).cloned().unwrap_or(Purity::Pure)
|
||||||
}
|
}
|
||||||
_ => Purity::Pure,
|
_ => Purity::Pure,
|
||||||
};
|
};
|
||||||
@@ -206,8 +206,8 @@ impl<'a> Analyzer<'a> {
|
|||||||
..
|
..
|
||||||
} = &callee.kind
|
} = &callee.kind
|
||||||
{
|
{
|
||||||
self.global_purity
|
self.root_purity
|
||||||
.get(idx)
|
.get(idx.0 as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Purity::Impure)
|
.unwrap_or(Purity::Impure)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use crate::ast::compiler::bound_nodes::{
|
|||||||
use crate::ast::diagnostics::Diagnostics;
|
use crate::ast::diagnostics::Diagnostics;
|
||||||
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
use crate::ast::nodes::{Node, Symbol, UntypedKind};
|
||||||
use crate::ast::types::{Identity, StaticType, Purity};
|
use crate::ast::types::{Identity, StaticType, Purity};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@@ -123,7 +122,6 @@ pub type BindingResult = (
|
|||||||
|
|
||||||
pub struct Binder {
|
pub struct Binder {
|
||||||
functions: Vec<FunctionCompiler>,
|
functions: Vec<FunctionCompiler>,
|
||||||
globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
|
|
||||||
capture_map: HashMap<Identity, std::collections::HashSet<Identity>>,
|
capture_map: HashMap<Identity, std::collections::HashSet<Identity>>,
|
||||||
fixed_scope_idx: i32,
|
fixed_scope_idx: i32,
|
||||||
}
|
}
|
||||||
@@ -133,11 +131,9 @@ impl Binder {
|
|||||||
initial_scopes: Vec<CompilerScope>,
|
initial_scopes: Vec<CompilerScope>,
|
||||||
initial_slot_count: u32,
|
initial_slot_count: u32,
|
||||||
fixed_scope_idx: i32,
|
fixed_scope_idx: i32,
|
||||||
globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut binder = Self {
|
let mut binder = Self {
|
||||||
functions: Vec::new(),
|
functions: Vec::new(),
|
||||||
globals,
|
|
||||||
capture_map: HashMap::new(),
|
capture_map: HashMap::new(),
|
||||||
fixed_scope_idx,
|
fixed_scope_idx,
|
||||||
};
|
};
|
||||||
@@ -156,11 +152,10 @@ impl Binder {
|
|||||||
initial_scopes: Vec<CompilerScope>,
|
initial_scopes: Vec<CompilerScope>,
|
||||||
initial_slot_count: u32,
|
initial_slot_count: u32,
|
||||||
fixed_scope_idx: i32,
|
fixed_scope_idx: i32,
|
||||||
globals: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
|
|
||||||
node: &Node<UntypedKind>,
|
node: &Node<UntypedKind>,
|
||||||
diagnostics: &mut Diagnostics,
|
diagnostics: &mut Diagnostics,
|
||||||
) -> Result<BindingResult, String> {
|
) -> Result<BindingResult, String> {
|
||||||
let mut binder = Self::new(initial_scopes, initial_slot_count, fixed_scope_idx, globals);
|
let mut binder = Self::new(initial_scopes, initial_slot_count, fixed_scope_idx);
|
||||||
let bound = binder.bind(node, ExprContext::Expression, diagnostics);
|
let bound = binder.bind(node, ExprContext::Expression, diagnostics);
|
||||||
|
|
||||||
let final_captures = binder
|
let final_captures = binder
|
||||||
@@ -580,13 +575,7 @@ impl Binder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Global Fallback
|
// 3. Global Fallback (search in root level with context removed)
|
||||||
let globals = self.globals.borrow();
|
|
||||||
if let Some((idx, _)) = globals.get(sym) {
|
|
||||||
return Some(Address::Global(*idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Global Fallback (search in root level with context removed)
|
|
||||||
if sym.context.is_some() {
|
if sym.context.is_some() {
|
||||||
let fallback_sym = Symbol {
|
let fallback_sym = Symbol {
|
||||||
name: sym.name.clone(),
|
name: sym.name.clone(),
|
||||||
@@ -600,9 +589,6 @@ impl Binder {
|
|||||||
return Some(info.addr);
|
return Some(info.addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some((idx, _)) = globals.get(&fallback_sym) {
|
|
||||||
return Some(Address::Global(*idx));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
diag.push_error(
|
diag.push_error(
|
||||||
@@ -719,9 +705,8 @@ mod tests {
|
|||||||
let mut parser = Parser::new(source);
|
let mut parser = Parser::new(source);
|
||||||
let untyped = parser.parse_expression();
|
let untyped = parser.parse_expression();
|
||||||
|
|
||||||
let globals = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
let (bound, captures, _scopes, _slots) = Binder::bind_root(vec![], 0, 0, globals, &untyped, &mut diagnostics).unwrap();
|
let (bound, captures, _scopes, _slots) = Binder::bind_root(vec![], 0, 0, &untyped, &mut diagnostics).unwrap();
|
||||||
|
|
||||||
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 {
|
||||||
@@ -749,9 +734,8 @@ mod tests {
|
|||||||
let mut parser = Parser::new(source);
|
let mut parser = Parser::new(source);
|
||||||
let untyped = parser.parse_expression();
|
let untyped = parser.parse_expression();
|
||||||
|
|
||||||
let globals = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
let (bound, captures, _scopes, _slots) = Binder::bind_root(vec![], 0, 0, globals, &untyped, &mut diagnostics).unwrap();
|
let (bound, captures, _scopes, _slots) = Binder::bind_root(vec![], 0, 0, &untyped, &mut diagnostics).unwrap();
|
||||||
|
|
||||||
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 {
|
||||||
@@ -779,9 +763,8 @@ mod tests {
|
|||||||
let mut parser = Parser::new(source);
|
let mut parser = Parser::new(source);
|
||||||
let untyped = parser.parse_expression();
|
let untyped = parser.parse_expression();
|
||||||
|
|
||||||
let globals = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
let _ = Binder::bind_root(vec![], 0, 0, globals, &untyped, &mut diagnostics);
|
let _ = Binder::bind_root(vec![], 0, 0, &untyped, &mut diagnostics);
|
||||||
|
|
||||||
assert!(diagnostics.has_errors());
|
assert!(diagnostics.has_errors());
|
||||||
assert!(diagnostics.items.iter().any(|i| i.message.contains("already defined")));
|
assert!(diagnostics.items.iter().any(|i| i.message.contains("already defined")));
|
||||||
@@ -789,18 +772,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_repro_global_redefinition() {
|
fn test_repro_global_redefinition() {
|
||||||
let globals = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
|
|
||||||
let source1 = "(def x 1) 1";
|
let source1 = "(def x 1) 1";
|
||||||
let untyped1 = Parser::new(source1).parse_expression();
|
let untyped1 = Parser::new(source1).parse_expression();
|
||||||
let mut diagnostics = Diagnostics::new();
|
let mut diagnostics = Diagnostics::new();
|
||||||
let (_, _, scopes1, slots1) = Binder::bind_root(vec![], 0, -1, globals.clone(), &untyped1, &mut diagnostics).unwrap();
|
let (_, _, scopes1, slots1) = Binder::bind_root(vec![], 0, -1, &untyped1, &mut diagnostics).unwrap();
|
||||||
|
|
||||||
let source2 = "(def x 2) 2";
|
let source2 = "(def x 2) 2";
|
||||||
let untyped2 = Parser::new(source2).parse_expression();
|
let untyped2 = Parser::new(source2).parse_expression();
|
||||||
let mut diagnostics2 = Diagnostics::new();
|
let mut diagnostics2 = Diagnostics::new();
|
||||||
// Here we simulate frozen scope by passing fixed_scope_idx = 0
|
// Here we simulate frozen scope by passing fixed_scope_idx = 0
|
||||||
let _ = Binder::bind_root(scopes1, slots1, 0, globals.clone(), &untyped2, &mut diagnostics2);
|
let _ = Binder::bind_root(scopes1, slots1, 0, &untyped2, &mut diagnostics2);
|
||||||
|
|
||||||
assert!(diagnostics2.has_errors());
|
assert!(diagnostics2.has_errors());
|
||||||
assert!(diagnostics2.items.iter().any(|i| i.message.contains("frozen/immutable")));
|
assert!(diagnostics2.items.iter().any(|i| i.message.contains("frozen/immutable")));
|
||||||
|
|||||||
@@ -627,7 +627,6 @@ mod tests {
|
|||||||
use crate::ast::compiler::Binder;
|
use crate::ast::compiler::Binder;
|
||||||
use crate::ast::parser::Parser;
|
use crate::ast::parser::Parser;
|
||||||
use crate::ast::types::{Object, Value};
|
use crate::ast::types::{Object, Value};
|
||||||
use std::cell::RefCell;
|
|
||||||
|
|
||||||
struct SimpleEvaluator;
|
struct SimpleEvaluator;
|
||||||
impl MacroEvaluator for SimpleEvaluator {
|
impl MacroEvaluator for SimpleEvaluator {
|
||||||
@@ -783,7 +782,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
||||||
// fixed_scope_idx = 0 means scope 0 is frozen (Global)
|
// fixed_scope_idx = 0 means scope 0 is frozen (Global)
|
||||||
let result = Binder::bind_root(initial_scopes, 1, 0, Rc::new(RefCell::new(HashMap::new())), &expanded, &mut diag);
|
let result = Binder::bind_root(initial_scopes, 1, 0, &expanded, &mut diag);
|
||||||
assert!(
|
assert!(
|
||||||
result.is_ok(),
|
result.is_ok(),
|
||||||
"Should find global '*' Error: {:?}",
|
"Should find global '*' Error: {:?}",
|
||||||
@@ -807,7 +806,7 @@ mod tests {
|
|||||||
let expanded = expander.expand(untyped).unwrap();
|
let expanded = expander.expand(untyped).unwrap();
|
||||||
|
|
||||||
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
||||||
let result = Binder::bind_root(vec![], 0, 0, Rc::new(RefCell::new(HashMap::new())), &expanded, &mut diag);
|
let result = Binder::bind_root(vec![], 0, 0, &expanded, &mut diag);
|
||||||
assert!(result.is_ok(), "Hygiene failed: {:?}", result.err());
|
assert!(result.is_ok(), "Hygiene failed: {:?}", result.err());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,7 +826,7 @@ mod tests {
|
|||||||
let expanded = expander.expand(untyped).unwrap();
|
let expanded = expander.expand(untyped).unwrap();
|
||||||
|
|
||||||
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
let mut diag = crate::ast::diagnostics::Diagnostics::new();
|
||||||
let result = Binder::bind_root(vec![], 0, 0, Rc::new(RefCell::new(HashMap::new())), &expanded, &mut diag);
|
let result = Binder::bind_root(vec![], 0, 0, &expanded, &mut diag);
|
||||||
assert!(
|
assert!(
|
||||||
result.is_ok(),
|
result.is_ok(),
|
||||||
"Explicit Hygiene with Backticks failed: {:?}",
|
"Explicit Hygiene with Backticks failed: {:?}",
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{
|
use crate::ast::compiler::bound_nodes::{
|
||||||
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, GlobalIdx, UpvalueIdx,
|
Address, AnalyzedNode, BoundKind, GlobalAnalyzedRegistry, UpvalueIdx,
|
||||||
};
|
};
|
||||||
use crate::ast::nodes::Node;
|
use crate::ast::nodes::Node;
|
||||||
use crate::ast::types::{Purity, Value};
|
use crate::ast::types::{Purity, Value};
|
||||||
use crate::ast::vm::Closure;
|
use crate::ast::vm::Closure;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::folder::Folder;
|
use super::folder::Folder;
|
||||||
@@ -17,7 +16,7 @@ pub struct Optimizer {
|
|||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
max_passes: usize,
|
max_passes: usize,
|
||||||
pub globals: Option<Rc<RefCell<Vec<Value>>>>,
|
pub globals: Option<Rc<RefCell<Vec<Value>>>>,
|
||||||
pub global_purity: Option<Rc<RefCell<HashMap<GlobalIdx, Purity>>>>,
|
pub root_purity: Option<Rc<RefCell<Vec<Purity>>>>,
|
||||||
pub lambda_registry: Option<Rc<RefCell<GlobalAnalyzedRegistry>>>,
|
pub lambda_registry: Option<Rc<RefCell<GlobalAnalyzedRegistry>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ impl Optimizer {
|
|||||||
enabled,
|
enabled,
|
||||||
max_passes: 5,
|
max_passes: 5,
|
||||||
globals: None,
|
globals: None,
|
||||||
global_purity: None,
|
root_purity: None,
|
||||||
lambda_registry: None,
|
lambda_registry: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +36,8 @@ impl Optimizer {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_purity(mut self, purity: Rc<RefCell<HashMap<GlobalIdx, Purity>>>) -> Self {
|
pub fn with_purity(mut self, purity: Rc<RefCell<Vec<Purity>>>) -> Self {
|
||||||
self.global_purity = Some(purity);
|
self.root_purity = Some(purity);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +78,7 @@ impl Optimizer {
|
|||||||
path: &mut PathTracker,
|
path: &mut PathTracker,
|
||||||
base_sub: Option<SubstitutionMap>,
|
base_sub: Option<SubstitutionMap>,
|
||||||
) -> Option<Rc<AnalyzedNode>> {
|
) -> Option<Rc<AnalyzedNode>> {
|
||||||
let inliner = Inliner::new(&self.globals, &self.global_purity);
|
let inliner = Inliner::new(&self.globals, &self.root_purity);
|
||||||
let mut inner_sub = base_sub.unwrap_or_else(|| sub.new_for_inlining());
|
let mut inner_sub = base_sub.unwrap_or_else(|| sub.new_for_inlining());
|
||||||
|
|
||||||
if inliner.prepare_beta_reduction(params, arg_nodes, body, &mut inner_sub).is_some() {
|
if inliner.prepare_beta_reduction(params, arg_nodes, body, &mut inner_sub).is_some() {
|
||||||
@@ -105,7 +104,7 @@ impl Optimizer {
|
|||||||
) -> Rc<AnalyzedNode> {
|
) -> Rc<AnalyzedNode> {
|
||||||
let node = &*node_rc;
|
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.root_purity);
|
||||||
|
|
||||||
let (new_kind, metrics) = match &node.kind {
|
let (new_kind, metrics) = match &node.kind {
|
||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
@@ -215,11 +214,13 @@ impl Optimizer {
|
|||||||
|
|
||||||
if let Address::Global(global_index) = addr
|
if let Address::Global(global_index) = addr
|
||||||
&& value_opt.ty.purity > Purity::Impure
|
&& value_opt.ty.purity > Purity::Impure
|
||||||
&& let Some(purity_rc) = &self.global_purity
|
&& let Some(purity_rc) = &self.root_purity
|
||||||
{
|
{
|
||||||
purity_rc
|
let mut pr = purity_rc.borrow_mut();
|
||||||
.borrow_mut()
|
let idx = global_index.0 as usize;
|
||||||
.insert(*global_index, value_opt.ty.purity);
|
if idx < pr.len() {
|
||||||
|
pr[idx] = value_opt.ty.purity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Rc::ptr_eq(&value_opt, value) {
|
if Rc::ptr_eq(&value_opt, value) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, GlobalIdx, LocalSlot};
|
use crate::ast::compiler::bound_nodes::{Address, AnalyzedNode, BoundKind, LocalSlot};
|
||||||
use crate::ast::types::{Purity, Value};
|
use crate::ast::types::{Purity, Value};
|
||||||
use crate::ast::vm::Closure;
|
use crate::ast::vm::Closure;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::substitution_map::SubstitutionMap;
|
use super::substitution_map::SubstitutionMap;
|
||||||
@@ -10,17 +10,17 @@ use super::utils::UsageInfo;
|
|||||||
|
|
||||||
pub struct Inliner<'a> {
|
pub struct Inliner<'a> {
|
||||||
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
|
pub globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
|
||||||
pub global_purity: &'a Option<Rc<RefCell<HashMap<GlobalIdx, Purity>>>>,
|
pub root_purity: &'a Option<Rc<RefCell<Vec<Purity>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Inliner<'a> {
|
impl<'a> Inliner<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
|
globals: &'a Option<Rc<RefCell<Vec<Value>>>>,
|
||||||
global_purity: &'a Option<Rc<RefCell<HashMap<GlobalIdx, Purity>>>>,
|
root_purity: &'a Option<Rc<RefCell<Vec<Purity>>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
globals,
|
globals,
|
||||||
global_purity,
|
root_purity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,10 +48,10 @@ impl<'a> Inliner<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Address::Global(idx) = addr {
|
if let Address::Global(idx) = addr {
|
||||||
if let Some(purity_rc) = &self.global_purity {
|
if let Some(purity_rc) = &self.root_purity {
|
||||||
let purity = purity_rc
|
let purity = purity_rc
|
||||||
.borrow()
|
.borrow()
|
||||||
.get(&idx)
|
.get(idx.0 as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(Purity::Impure);
|
.unwrap_or(Purity::Impure);
|
||||||
return purity >= Purity::Pure;
|
return purity >= Purity::Pure;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, GlobalIdx, TypedNode};
|
use crate::ast::compiler::bound_nodes::{Address, BoundKind, BoundNode, TypedNode};
|
||||||
use crate::ast::diagnostics::Diagnostics;
|
use crate::ast::diagnostics::Diagnostics;
|
||||||
use crate::ast::nodes::Node;
|
use crate::ast::nodes::Node;
|
||||||
use crate::ast::types::StaticType;
|
use crate::ast::types::StaticType;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Manages the types of locals and upvalues during a single type-checking pass.
|
/// Manages the types of locals and upvalues during a single type-checking pass.
|
||||||
@@ -12,8 +11,8 @@ struct TypeContext<'a> {
|
|||||||
slots: Vec<StaticType>,
|
slots: Vec<StaticType>,
|
||||||
/// Types of captured variables (passed from outer scope)
|
/// Types of captured variables (passed from outer scope)
|
||||||
upvalue_types: Vec<StaticType>,
|
upvalue_types: Vec<StaticType>,
|
||||||
/// Access to global types for unified resolution
|
/// Access to root types for unified resolution
|
||||||
global_types: &'a std::cell::RefCell<HashMap<GlobalIdx, StaticType>>,
|
root_types: &'a std::cell::RefCell<Vec<StaticType>>,
|
||||||
/// The expected parameters of the current function (for 'again' validation)
|
/// The expected parameters of the current function (for 'again' validation)
|
||||||
current_params_ty: Option<StaticType>,
|
current_params_ty: Option<StaticType>,
|
||||||
}
|
}
|
||||||
@@ -22,14 +21,14 @@ impl<'a> TypeContext<'a> {
|
|||||||
fn new(
|
fn new(
|
||||||
slot_count: u32,
|
slot_count: u32,
|
||||||
upvalue_types: Vec<StaticType>,
|
upvalue_types: Vec<StaticType>,
|
||||||
global_types: &'a std::cell::RefCell<HashMap<GlobalIdx, StaticType>>,
|
root_types: &'a std::cell::RefCell<Vec<StaticType>>,
|
||||||
parent: Option<&'a TypeContext<'a>>,
|
parent: Option<&'a TypeContext<'a>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
_parent: parent,
|
_parent: parent,
|
||||||
slots: vec![StaticType::Any; slot_count as usize],
|
slots: vec![StaticType::Any; slot_count as usize],
|
||||||
upvalue_types,
|
upvalue_types,
|
||||||
global_types,
|
root_types,
|
||||||
current_params_ty: None,
|
current_params_ty: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,9 +41,9 @@ impl<'a> TypeContext<'a> {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(StaticType::Any),
|
.unwrap_or(StaticType::Any),
|
||||||
Address::Global(idx) => self
|
Address::Global(idx) => self
|
||||||
.global_types
|
.root_types
|
||||||
.borrow()
|
.borrow()
|
||||||
.get(&idx)
|
.get(idx.0 as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(StaticType::Any),
|
.unwrap_or(StaticType::Any),
|
||||||
Address::Upvalue(idx) => self
|
Address::Upvalue(idx) => self
|
||||||
@@ -63,7 +62,10 @@ impl<'a> TypeContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Address::Global(idx) => {
|
Address::Global(idx) => {
|
||||||
self.global_types.borrow_mut().insert(idx, ty);
|
let mut rt = self.root_types.borrow_mut();
|
||||||
|
if (idx.0 as usize) < rt.len() {
|
||||||
|
rt[idx.0 as usize] = ty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -71,12 +73,12 @@ impl<'a> TypeContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeChecker {
|
pub struct TypeChecker {
|
||||||
global_types: Rc<std::cell::RefCell<HashMap<GlobalIdx, StaticType>>>,
|
root_types: Rc<std::cell::RefCell<Vec<StaticType>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeChecker {
|
impl TypeChecker {
|
||||||
pub fn new(global_types: Rc<std::cell::RefCell<HashMap<GlobalIdx, StaticType>>>) -> Self {
|
pub fn new(root_types: Rc<std::cell::RefCell<Vec<StaticType>>>) -> Self {
|
||||||
Self { global_types }
|
Self { root_types }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check(
|
pub fn check(
|
||||||
@@ -99,9 +101,9 @@ impl TypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Create the specialized context
|
// 2. Create the specialized context
|
||||||
let root_ctx = TypeContext::new(0, vec![], &self.global_types, None);
|
let root_ctx = TypeContext::new(0, vec![], &self.root_types, None);
|
||||||
let mut lambda_ctx =
|
let mut lambda_ctx =
|
||||||
TypeContext::new(64, upvalue_types, &self.global_types, Some(&root_ctx));
|
TypeContext::new(64, upvalue_types, &self.root_types, Some(&root_ctx));
|
||||||
|
|
||||||
// 3. INJECT specialized argument types into slots
|
// 3. INJECT specialized argument types into slots
|
||||||
let arg_tuple_ty = if arg_types.is_empty() {
|
let arg_tuple_ty = if arg_types.is_empty() {
|
||||||
@@ -141,7 +143,7 @@ impl TypeChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut root_ctx = TypeContext::new(0, vec![], &self.global_types, None);
|
let mut root_ctx = TypeContext::new(0, vec![], &self.root_types, None);
|
||||||
self.check_node(node, &mut root_ctx, diag)
|
self.check_node(node, &mut root_ctx, diag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -484,7 +486,7 @@ impl TypeChecker {
|
|||||||
|
|
||||||
// 2. Create nested context for lambda body
|
// 2. Create nested context for lambda body
|
||||||
let mut lambda_ctx =
|
let mut lambda_ctx =
|
||||||
TypeContext::new(64, upvalue_types, ctx.global_types, Some(ctx));
|
TypeContext::new(64, upvalue_types, ctx.root_types, Some(ctx));
|
||||||
|
|
||||||
// 3. Check parameters and body
|
// 3. Check parameters and body
|
||||||
let params_typed = self.check_params(
|
let params_typed = self.check_params(
|
||||||
|
|||||||
+68
-59
@@ -21,7 +21,7 @@ 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::rtl::intrinsics;
|
use crate::ast::rtl::intrinsics;
|
||||||
use crate::ast::types::{
|
use crate::ast::types::{
|
||||||
Identity, NodeIdentity, Object, Purity, SourceLocation, StaticType, Value,
|
NodeIdentity, Object, Purity, SourceLocation, StaticType, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics};
|
use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics};
|
||||||
@@ -71,10 +71,9 @@ impl CompilationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Environment {
|
pub struct Environment {
|
||||||
pub global_names: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
|
pub root_types: Rc<RefCell<Vec<StaticType>>>,
|
||||||
pub global_types: Rc<RefCell<HashMap<GlobalIdx, StaticType>>>,
|
pub root_purity: Rc<RefCell<Vec<Purity>>>,
|
||||||
pub global_purity: Rc<RefCell<HashMap<GlobalIdx, Purity>>>,
|
pub root_values: Rc<RefCell<Vec<Value>>>,
|
||||||
pub global_values: Rc<RefCell<Vec<Value>>>,
|
|
||||||
pub fixed_scope_idx: i32,
|
pub fixed_scope_idx: i32,
|
||||||
pub root_scopes: Rc<RefCell<Vec<crate::ast::compiler::binder::CompilerScope>>>,
|
pub root_scopes: Rc<RefCell<Vec<crate::ast::compiler::binder::CompilerScope>>>,
|
||||||
pub root_slot_count: Rc<RefCell<u32>>,
|
pub root_slot_count: Rc<RefCell<u32>>,
|
||||||
@@ -112,11 +111,11 @@ impl FunctionRegistry for EnvFunctionRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RuntimeMacroEvaluator {
|
struct RuntimeMacroEvaluator {
|
||||||
global_names: Rc<RefCell<HashMap<Symbol, (GlobalIdx, Identity)>>>,
|
|
||||||
root_scopes: Rc<RefCell<Vec<crate::ast::compiler::binder::CompilerScope>>>,
|
root_scopes: Rc<RefCell<Vec<crate::ast::compiler::binder::CompilerScope>>>,
|
||||||
root_slot_count: Rc<RefCell<u32>>,
|
root_slot_count: Rc<RefCell<u32>>,
|
||||||
global_types: Rc<RefCell<HashMap<GlobalIdx, StaticType>>>,
|
root_types: Rc<RefCell<Vec<StaticType>>>,
|
||||||
global_values: Rc<RefCell<Vec<Value>>>,
|
root_values: Rc<RefCell<Vec<Value>>>,
|
||||||
|
root_purity: Rc<RefCell<Vec<Purity>>>,
|
||||||
fixed_scope_idx: i32,
|
fixed_scope_idx: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,9 +135,9 @@ impl MacroEvaluator for RuntimeMacroEvaluator {
|
|||||||
let initial_scopes = self.root_scopes.borrow().clone();
|
let initial_scopes = self.root_scopes.borrow().clone();
|
||||||
let initial_slot_count = *self.root_slot_count.borrow();
|
let initial_slot_count = *self.root_slot_count.borrow();
|
||||||
|
|
||||||
let (bound_ast, captures, _, _) = Binder::bind_root(initial_scopes, initial_slot_count, self.fixed_scope_idx, self.global_names.clone(), node, &mut diag)?;
|
let (bound_ast, captures, _, _) = Binder::bind_root(initial_scopes, initial_slot_count, self.fixed_scope_idx, node, &mut diag)?;
|
||||||
let bound_ast = crate::ast::compiler::captures::CapturePass::apply(bound_ast, &captures);
|
let bound_ast = crate::ast::compiler::captures::CapturePass::apply(bound_ast, &captures);
|
||||||
let checker = TypeChecker::new(self.global_types.clone());
|
let checker = TypeChecker::new(self.root_types.clone());
|
||||||
let typed_ast = checker.check(&bound_ast, &[], &mut diag);
|
let typed_ast = checker.check(&bound_ast, &[], &mut diag);
|
||||||
|
|
||||||
if diag.has_errors() {
|
if diag.has_errors() {
|
||||||
@@ -150,9 +149,9 @@ impl MacroEvaluator for RuntimeMacroEvaluator {
|
|||||||
.join("\n"));
|
.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let exec_ast = Lowering::lower(Analyzer::analyze(&typed_ast, &HashMap::new())); // Minimal analysis for macro eval
|
let exec_ast = Lowering::lower(Analyzer::analyze(&typed_ast, &self.root_purity.borrow())); // Minimal analysis for macro eval
|
||||||
|
|
||||||
let mut vm = VM::new(self.global_values.clone());
|
let mut vm = VM::new(self.root_values.clone());
|
||||||
vm.run(&exec_ast)
|
vm.run(&exec_ast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,10 +165,9 @@ impl Default for Environment {
|
|||||||
impl Environment {
|
impl Environment {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let env = Self {
|
let env = Self {
|
||||||
global_names: Rc::new(RefCell::new(HashMap::new())),
|
root_types: Rc::new(RefCell::new(Vec::new())),
|
||||||
global_types: Rc::new(RefCell::new(HashMap::new())),
|
root_purity: Rc::new(RefCell::new(Vec::new())),
|
||||||
global_purity: Rc::new(RefCell::new(HashMap::new())),
|
root_values: Rc::new(RefCell::new(Vec::new())),
|
||||||
global_values: Rc::new(RefCell::new(Vec::new())),
|
|
||||||
fixed_scope_idx: -1,
|
fixed_scope_idx: -1,
|
||||||
root_scopes: Rc::new(RefCell::new(vec![crate::ast::compiler::binder::CompilerScope::new()])),
|
root_scopes: Rc::new(RefCell::new(vec![crate::ast::compiler::binder::CompilerScope::new()])),
|
||||||
root_slot_count: Rc::new(RefCell::new(0)),
|
root_slot_count: Rc::new(RefCell::new(0)),
|
||||||
@@ -226,11 +224,11 @@ impl Environment {
|
|||||||
|
|
||||||
fn get_expander(&self) -> MacroExpander<RuntimeMacroEvaluator> {
|
fn get_expander(&self) -> MacroExpander<RuntimeMacroEvaluator> {
|
||||||
let evaluator = RuntimeMacroEvaluator {
|
let evaluator = RuntimeMacroEvaluator {
|
||||||
global_names: self.global_names.clone(),
|
|
||||||
root_scopes: self.root_scopes.clone(),
|
root_scopes: self.root_scopes.clone(),
|
||||||
root_slot_count: self.root_slot_count.clone(),
|
root_slot_count: self.root_slot_count.clone(),
|
||||||
global_types: self.global_types.clone(),
|
root_types: self.root_types.clone(),
|
||||||
global_values: self.global_values.clone(),
|
root_values: self.root_values.clone(),
|
||||||
|
root_purity: self.root_purity.clone(),
|
||||||
fixed_scope_idx: self.fixed_scope_idx,
|
fixed_scope_idx: self.fixed_scope_idx,
|
||||||
};
|
};
|
||||||
MacroExpander::new(self.macro_registry.borrow().clone(), evaluator)
|
MacroExpander::new(self.macro_registry.borrow().clone(), evaluator)
|
||||||
@@ -459,7 +457,7 @@ impl Environment {
|
|||||||
let initial_slot_count = *self.root_slot_count.borrow();
|
let initial_slot_count = *self.root_slot_count.borrow();
|
||||||
|
|
||||||
let (bound_ast, captures, final_scopes, final_slot_count) =
|
let (bound_ast, captures, final_scopes, final_slot_count) =
|
||||||
match Binder::bind_root(initial_scopes, initial_slot_count, self.fixed_scope_idx, self.global_names.clone(), &expanded_ast, diagnostics) {
|
match Binder::bind_root(initial_scopes, initial_slot_count, self.fixed_scope_idx, &expanded_ast, diagnostics) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
diagnostics.push_error(e, None);
|
diagnostics.push_error(e, None);
|
||||||
@@ -475,7 +473,7 @@ impl Environment {
|
|||||||
|
|
||||||
// Pre-allocate global slots to prevent out-of-bounds during specialization/optimization
|
// Pre-allocate global slots to prevent out-of-bounds during specialization/optimization
|
||||||
{
|
{
|
||||||
let mut values = self.global_values.borrow_mut();
|
let mut values = self.root_values.borrow_mut();
|
||||||
let count = *self.root_slot_count.borrow();
|
let count = *self.root_slot_count.borrow();
|
||||||
if (count as usize) > values.len() {
|
if (count as usize) > values.len() {
|
||||||
values.resize(count as usize, Value::Void);
|
values.resize(count as usize, Value::Void);
|
||||||
@@ -484,7 +482,7 @@ impl Environment {
|
|||||||
|
|
||||||
LambdaCollector::collect(&bound_ast, &mut self.function_registry.borrow_mut());
|
LambdaCollector::collect(&bound_ast, &mut self.function_registry.borrow_mut());
|
||||||
|
|
||||||
let checker = TypeChecker::new(self.global_types.clone());
|
let checker = TypeChecker::new(self.root_types.clone());
|
||||||
let wrapped_ast = if let crate::ast::compiler::bound_nodes::BoundKind::Lambda { .. } = bound_ast.kind {
|
let wrapped_ast = if let crate::ast::compiler::bound_nodes::BoundKind::Lambda { .. } = bound_ast.kind {
|
||||||
bound_ast
|
bound_ast
|
||||||
} else {
|
} else {
|
||||||
@@ -529,19 +527,13 @@ impl Environment {
|
|||||||
ty: StaticType,
|
ty: StaticType,
|
||||||
func: Rc<crate::ast::types::NativeFunction>,
|
func: Rc<crate::ast::types::NativeFunction>,
|
||||||
) {
|
) {
|
||||||
let mut names = self.global_names.borrow_mut();
|
let mut types = self.root_types.borrow_mut();
|
||||||
let mut types = self.global_types.borrow_mut();
|
let mut values = self.root_values.borrow_mut();
|
||||||
let mut values = self.global_values.borrow_mut();
|
let mut purity = self.root_purity.borrow_mut();
|
||||||
let mut purity = self.global_purity.borrow_mut();
|
|
||||||
|
|
||||||
let idx = GlobalIdx(values.len() as u32);
|
|
||||||
let identity = NodeIdentity::new(SourceLocation { line: 0, col: 0 });
|
let identity = NodeIdentity::new(SourceLocation { line: 0, col: 0 });
|
||||||
names.insert(Symbol::from(name), (idx, identity.clone()));
|
|
||||||
types.insert(idx, ty.clone());
|
|
||||||
purity.insert(idx, func.purity);
|
|
||||||
values.push(Value::Function(func.clone()));
|
|
||||||
|
|
||||||
// Parallel mode: populate root_scopes[0]
|
// populate root_scopes[0]
|
||||||
let mut root_scopes = self.root_scopes.borrow_mut();
|
let mut root_scopes = self.root_scopes.borrow_mut();
|
||||||
let mut slot_count = self.root_slot_count.borrow_mut();
|
let mut slot_count = self.root_slot_count.borrow_mut();
|
||||||
let slot = crate::ast::compiler::bound_nodes::LocalSlot(*slot_count);
|
let slot = crate::ast::compiler::bound_nodes::LocalSlot(*slot_count);
|
||||||
@@ -550,11 +542,23 @@ impl Environment {
|
|||||||
crate::ast::compiler::binder::LocalInfo {
|
crate::ast::compiler::binder::LocalInfo {
|
||||||
addr: Address::Global(GlobalIdx(slot.0)),
|
addr: Address::Global(GlobalIdx(slot.0)),
|
||||||
identity,
|
identity,
|
||||||
_ty: ty,
|
_ty: ty.clone(),
|
||||||
purity: func.purity,
|
purity: func.purity,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
*slot_count += 1;
|
*slot_count += 1;
|
||||||
|
|
||||||
|
// Ensure arrays are large enough
|
||||||
|
let idx = slot.0 as usize;
|
||||||
|
if idx >= values.len() {
|
||||||
|
values.resize(idx + 1, Value::Void);
|
||||||
|
types.resize(idx + 1, StaticType::Any);
|
||||||
|
purity.resize(idx + 1, Purity::Impure);
|
||||||
|
}
|
||||||
|
|
||||||
|
types[idx] = ty;
|
||||||
|
purity[idx] = func.purity;
|
||||||
|
values[idx] = Value::Function(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_native_fn(
|
pub fn register_native_fn(
|
||||||
@@ -575,19 +579,13 @@ impl Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_constant(&self, name: &str, ty: StaticType, val: Value) {
|
pub fn register_constant(&self, name: &str, ty: StaticType, val: Value) {
|
||||||
let mut names = self.global_names.borrow_mut();
|
let mut types = self.root_types.borrow_mut();
|
||||||
let mut types = self.global_types.borrow_mut();
|
let mut values = self.root_values.borrow_mut();
|
||||||
let mut values = self.global_values.borrow_mut();
|
let mut purity = self.root_purity.borrow_mut();
|
||||||
let mut purity = self.global_purity.borrow_mut();
|
|
||||||
|
|
||||||
let idx = GlobalIdx(values.len() as u32);
|
|
||||||
let identity = NodeIdentity::new(SourceLocation { line: 0, col: 0 });
|
let identity = NodeIdentity::new(SourceLocation { line: 0, col: 0 });
|
||||||
names.insert(Symbol::from(name), (idx, identity.clone()));
|
|
||||||
types.insert(idx, ty.clone());
|
|
||||||
purity.insert(idx, Purity::Pure);
|
|
||||||
values.push(val);
|
|
||||||
|
|
||||||
// Parallel mode: populate root_scopes[0]
|
// populate root_scopes[0]
|
||||||
let mut root_scopes = self.root_scopes.borrow_mut();
|
let mut root_scopes = self.root_scopes.borrow_mut();
|
||||||
let mut slot_count = self.root_slot_count.borrow_mut();
|
let mut slot_count = self.root_slot_count.borrow_mut();
|
||||||
let slot = crate::ast::compiler::bound_nodes::LocalSlot(*slot_count);
|
let slot = crate::ast::compiler::bound_nodes::LocalSlot(*slot_count);
|
||||||
@@ -596,11 +594,22 @@ impl Environment {
|
|||||||
crate::ast::compiler::binder::LocalInfo {
|
crate::ast::compiler::binder::LocalInfo {
|
||||||
addr: Address::Global(GlobalIdx(slot.0)),
|
addr: Address::Global(GlobalIdx(slot.0)),
|
||||||
identity,
|
identity,
|
||||||
_ty: ty,
|
_ty: ty.clone(),
|
||||||
purity: Purity::Pure,
|
purity: Purity::Pure,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
*slot_count += 1;
|
*slot_count += 1;
|
||||||
|
|
||||||
|
let idx = slot.0 as usize;
|
||||||
|
if idx >= values.len() {
|
||||||
|
values.resize(idx + 1, Value::Void);
|
||||||
|
types.resize(idx + 1, StaticType::Any);
|
||||||
|
purity.resize(idx + 1, Purity::Impure);
|
||||||
|
}
|
||||||
|
|
||||||
|
types[idx] = ty;
|
||||||
|
purity[idx] = Purity::Pure;
|
||||||
|
values[idx] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -640,7 +649,7 @@ impl Environment {
|
|||||||
|
|
||||||
pub fn link(&self, node: TypedNode) -> ExecNode {
|
pub fn link(&self, node: TypedNode) -> ExecNode {
|
||||||
// 1. Analyze
|
// 1. Analyze
|
||||||
let analyzed = Analyzer::analyze(&node, &self.global_purity.borrow());
|
let analyzed = Analyzer::analyze(&node, &self.root_purity.borrow());
|
||||||
|
|
||||||
// 2. Collect Analyzed Lambdas
|
// 2. Collect Analyzed Lambdas
|
||||||
LambdaCollector::collect(&analyzed, &mut self.typed_function_registry.borrow_mut());
|
LambdaCollector::collect(&analyzed, &mut self.typed_function_registry.borrow_mut());
|
||||||
@@ -650,8 +659,8 @@ impl Environment {
|
|||||||
|
|
||||||
// 4. Optimize
|
// 4. Optimize
|
||||||
let optimizer = Optimizer::new(self.optimization)
|
let optimizer = Optimizer::new(self.optimization)
|
||||||
.with_globals(self.global_values.clone())
|
.with_globals(self.root_values.clone())
|
||||||
.with_purity(self.global_purity.clone())
|
.with_purity(self.root_purity.clone())
|
||||||
.with_registry(self.typed_function_registry.clone());
|
.with_registry(self.typed_function_registry.clone());
|
||||||
let optimized = optimizer.optimize(specialized);
|
let optimized = optimizer.optimize(specialized);
|
||||||
|
|
||||||
@@ -660,7 +669,7 @@ impl Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate(&self, node: ExecNode) -> Rc<crate::ast::types::NativeFunction> {
|
pub fn instantiate(&self, node: ExecNode) -> Rc<crate::ast::types::NativeFunction> {
|
||||||
let global_values = self.global_values.clone();
|
let root_values = self.root_values.clone();
|
||||||
if let BoundKind::Lambda {
|
if let BoundKind::Lambda {
|
||||||
params,
|
params,
|
||||||
upvalues,
|
upvalues,
|
||||||
@@ -683,7 +692,7 @@ impl Environment {
|
|||||||
return Rc::new(crate::ast::types::NativeFunction {
|
return Rc::new(crate::ast::types::NativeFunction {
|
||||||
purity: Purity::Impure,
|
purity: Purity::Impure,
|
||||||
func: Rc::new(move |args| {
|
func: Rc::new(move |args| {
|
||||||
let mut vm = VM::new(global_values.clone());
|
let mut vm = VM::new(root_values.clone());
|
||||||
match vm.run_with_args(closure_obj.clone(), args) {
|
match vm.run_with_args(closure_obj.clone(), args) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => panic!("Myc Runtime Error: {}", e),
|
Err(e) => panic!("Myc Runtime Error: {}", e),
|
||||||
@@ -696,7 +705,7 @@ impl Environment {
|
|||||||
Rc::new(crate::ast::types::NativeFunction {
|
Rc::new(crate::ast::types::NativeFunction {
|
||||||
purity: Purity::Impure,
|
purity: Purity::Impure,
|
||||||
func: Rc::new(move |args| {
|
func: Rc::new(move |args| {
|
||||||
let mut vm = VM::new(global_values.clone());
|
let mut vm = VM::new(root_values.clone());
|
||||||
let res = match vm.run(&exec_node) {
|
let res = match vm.run(&exec_node) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => panic!("Myc Runtime Error: {}", e),
|
Err(e) => panic!("Myc Runtime Error: {}", e),
|
||||||
@@ -729,9 +738,9 @@ impl Environment {
|
|||||||
let typed_reg = self.typed_function_registry.clone();
|
let typed_reg = self.typed_function_registry.clone();
|
||||||
let untyped_reg = self.function_registry.clone();
|
let untyped_reg = self.function_registry.clone();
|
||||||
let mono_cache = self.monomorph_cache.clone();
|
let mono_cache = self.monomorph_cache.clone();
|
||||||
let global_values = self.global_values.clone();
|
let root_values = self.root_values.clone();
|
||||||
let global_types = self.global_types.clone();
|
let root_types = self.root_types.clone();
|
||||||
let global_purity = self.global_purity.clone();
|
let root_purity = self.root_purity.clone();
|
||||||
let optimization = self.optimization;
|
let optimization = self.optimization;
|
||||||
|
|
||||||
let compiler = Rc::new(
|
let compiler = Rc::new(
|
||||||
@@ -739,7 +748,7 @@ impl Environment {
|
|||||||
arg_types: &[StaticType]|
|
arg_types: &[StaticType]|
|
||||||
-> Result<(Value, StaticType), String> {
|
-> Result<(Value, StaticType), String> {
|
||||||
let mut diag = Diagnostics::new();
|
let mut diag = Diagnostics::new();
|
||||||
let checker = TypeChecker::new(global_types.clone());
|
let checker = TypeChecker::new(root_types.clone());
|
||||||
let retyped_ast = checker.check(func_template.as_ref(), arg_types, &mut diag);
|
let retyped_ast = checker.check(func_template.as_ref(), arg_types, &mut diag);
|
||||||
|
|
||||||
if diag.has_errors() {
|
if diag.has_errors() {
|
||||||
@@ -751,7 +760,7 @@ impl Environment {
|
|||||||
.join("\n"));
|
.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let analyzed = Analyzer::analyze(&retyped_ast, &global_purity.borrow());
|
let analyzed = Analyzer::analyze(&retyped_ast, &root_purity.borrow());
|
||||||
|
|
||||||
let sub_registry = Rc::new(EnvFunctionRegistry {
|
let sub_registry = Rc::new(EnvFunctionRegistry {
|
||||||
registry: untyped_reg.clone(),
|
registry: untyped_reg.clone(),
|
||||||
@@ -770,12 +779,12 @@ impl Environment {
|
|||||||
let specialized_ast = sub_specializer.specialize(analyzed);
|
let specialized_ast = sub_specializer.specialize(analyzed);
|
||||||
|
|
||||||
let optimizer = Optimizer::new(optimization)
|
let optimizer = Optimizer::new(optimization)
|
||||||
.with_globals(global_values.clone())
|
.with_globals(root_values.clone())
|
||||||
.with_purity(global_purity.clone());
|
.with_purity(root_purity.clone());
|
||||||
let optimized_ast = optimizer.optimize(specialized_ast);
|
let optimized_ast = optimizer.optimize(specialized_ast);
|
||||||
|
|
||||||
let exec_ast = Lowering::lower(optimized_ast);
|
let exec_ast = Lowering::lower(optimized_ast);
|
||||||
let mut vm = VM::new(global_values.clone());
|
let mut vm = VM::new(root_values.clone());
|
||||||
let compiled_val = match vm.run(&exec_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)),
|
||||||
@@ -824,7 +833,7 @@ impl Environment {
|
|||||||
let compiled = self.compile(source).into_result()?;
|
let compiled = self.compile(source).into_result()?;
|
||||||
let linked = self.link(compiled);
|
let linked = self.link(compiled);
|
||||||
|
|
||||||
let mut vm = VM::new(self.global_values.clone());
|
let mut vm = VM::new(self.root_values.clone());
|
||||||
let mut observer = TracingObserver::new();
|
let mut observer = TracingObserver::new();
|
||||||
|
|
||||||
// 1. Run the script wrapper (returns a closure representing the script)
|
// 1. Run the script wrapper (returns a closure representing the script)
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ pub fn register(env: &Environment) {
|
|||||||
|
|
||||||
// (create-ticker condition-closure) -> StreamNode
|
// (create-ticker condition-closure) -> StreamNode
|
||||||
let ticker_generators = env.pipeline_generators.clone();
|
let ticker_generators = env.pipeline_generators.clone();
|
||||||
let globals = env.global_values.clone();
|
let globals = env.root_values.clone();
|
||||||
|
|
||||||
env.register_native_fn(
|
env.register_native_fn(
|
||||||
"create-ticker",
|
"create-ticker",
|
||||||
|
|||||||
Reference in New Issue
Block a user