Skip to content

Commit fa4ac0b

Browse files
committed
process recursively
1 parent 325a91c commit fa4ac0b

File tree

1 file changed

+50
-76
lines changed

1 file changed

+50
-76
lines changed

src/monomorph_pass.rs

Lines changed: 50 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::*;
2-
use std::collections::{HashMap, HashSet, VecDeque};
2+
use std::collections::HashMap;
33

44
/// Manages the monomorphization process, generating specialized versions
55
/// of generic functions and structs.
@@ -12,12 +12,6 @@ pub struct MonomorphPass {
1212

1313
/// Newly generated specialized declarations
1414
specialized_decls: Vec<Decl>,
15-
16-
/// Work queue of functions that need to be processed
17-
worklist: VecDeque<Name>,
18-
19-
/// Functions we've already processed (to avoid duplication)
20-
processed: HashSet<Name>,
2115
}
2216

2317
impl MonomorphPass {
@@ -26,8 +20,6 @@ impl MonomorphPass {
2620
instantiations: HashMap::new(),
2721
recursion_detector: RecursionDetector::new(),
2822
specialized_decls: Vec::new(),
29-
worklist: VecDeque::new(),
30-
processed: HashSet::new(),
3123
}
3224
}
3325

@@ -42,28 +34,16 @@ impl MonomorphPass {
4234
decls: &DeclTable,
4335
entry_point: Name,
4436
) -> Result<Vec<Decl>, String> {
45-
// Start with the entry point
46-
self.worklist.push_back(entry_point);
47-
48-
// Process the worklist until empty
49-
while let Some(func_name) = self.worklist.pop_front() {
50-
if self.processed.contains(&func_name) {
51-
continue;
52-
}
53-
self.processed.insert(func_name);
54-
55-
// Find the function declaration
56-
let func_decls = decls.find(func_name);
57-
if func_decls.is_empty() {
58-
// Built-in function or external function
59-
continue;
60-
}
37+
// Find the entry point function declaration
38+
let func_decls = decls.find(entry_point);
39+
if func_decls.is_empty() {
40+
return Err(format!("Entry point function '{}' not found", entry_point));
41+
}
6142

62-
// Process each overload
63-
for decl in func_decls {
64-
if let Decl::Func(fdecl) = decl {
65-
self.process_function(fdecl, decls)?;
66-
}
43+
// Process each overload of the entry point
44+
for decl in func_decls {
45+
if let Decl::Func(fdecl) = decl {
46+
self.process_function(fdecl, decls)?;
6747
}
6848
}
6949

@@ -192,8 +172,8 @@ impl MonomorphPass {
192172
)?;
193173

194174
if !type_args.is_empty() {
195-
// Create a specialized version
196-
self.instantiate_function(*fn_name, type_args, target_fdecl)?;
175+
// Create a specialized version and recursively process it
176+
self.instantiate_function(*fn_name, type_args, target_fdecl, decls)?;
197177
}
198178
}
199179
}
@@ -258,7 +238,8 @@ impl MonomorphPass {
258238
&mut self,
259239
name: Name,
260240
type_args: Vec<TypeID>,
261-
generic_fdecl: &FuncDecl
241+
generic_fdecl: &FuncDecl,
242+
decls: &DeclTable,
262243
) -> Result<Name, String> {
263244
let key = MonomorphKey::new(name, type_args.clone());
264245

@@ -307,8 +288,8 @@ impl MonomorphPass {
307288
// Add to specialized decls
308289
self.specialized_decls.push(Decl::Func(specialized.clone()));
309290

310-
// Add to worklist to process its body
311-
self.worklist.push_back(mangled_name);
291+
// Recursively process the specialized function's body immediately
292+
self.process_function(&specialized, decls)?;
312293

313294
self.recursion_detector.end_instantiation();
314295

@@ -336,15 +317,18 @@ mod tests {
336317
use super::*;
337318

338319
fn mk_simple_func(name: &str, typevars: Vec<&str>) -> FuncDecl {
320+
let mut arena = ExprArena::new();
321+
let body_expr = arena.add(Expr::Int(0), test_loc());
322+
339323
FuncDecl {
340324
name: Name::str(name),
341325
typevars: typevars.iter().map(|s| Name::str(s)).collect(),
342326
params: Vec::new(),
343327
constraints: Vec::new(),
344328
ret: mk_type(Type::Void),
345-
body: Some(0),
346-
arena: ExprArena::new(),
347-
types: Vec::new(),
329+
body: Some(body_expr),
330+
arena,
331+
types: vec![mk_type(Type::Int32)],
348332
loc: test_loc(),
349333
}
350334
}
@@ -360,12 +344,14 @@ mod tests {
360344
fn test_instantiate_simple_function() {
361345
let mut pass = MonomorphPass::new();
362346
let generic_func = mk_simple_func("id", vec!["T"]);
347+
let decls = DeclTable::new(vec![]);
363348

364349
let type_args = vec![mk_type(Type::Int32)];
365350
let result = pass.instantiate_function(
366351
Name::str("id"),
367352
type_args,
368353
&generic_func,
354+
&decls,
369355
);
370356

371357
assert!(result.is_ok());
@@ -378,6 +364,7 @@ mod tests {
378364
fn test_instantiate_same_function_twice() {
379365
let mut pass = MonomorphPass::new();
380366
let generic_func = mk_simple_func("id", vec!["T"]);
367+
let decls = DeclTable::new(vec![]);
381368

382369
let type_args = vec![mk_type(Type::Int32)];
383370

@@ -386,6 +373,7 @@ mod tests {
386373
Name::str("id"),
387374
type_args.clone(),
388375
&generic_func,
376+
&decls,
389377
);
390378
assert!(result1.is_ok());
391379

@@ -394,6 +382,7 @@ mod tests {
394382
Name::str("id"),
395383
type_args,
396384
&generic_func,
385+
&decls,
397386
);
398387
assert!(result2.is_ok());
399388
assert_eq!(result1.unwrap(), result2.unwrap());
@@ -406,12 +395,14 @@ mod tests {
406395
fn test_instantiate_different_type_args() {
407396
let mut pass = MonomorphPass::new();
408397
let generic_func = mk_simple_func("id", vec!["T"]);
398+
let decls = DeclTable::new(vec![]);
409399

410400
// id<i32>
411401
let result1 = pass.instantiate_function(
412402
Name::str("id"),
413403
vec![mk_type(Type::Int32)],
414404
&generic_func,
405+
&decls,
415406
);
416407
assert!(result1.is_ok());
417408
assert_eq!(result1.unwrap(), Name::str("id$i32"));
@@ -421,6 +412,7 @@ mod tests {
421412
Name::str("id"),
422413
vec![mk_type(Type::Bool)],
423414
&generic_func,
415+
&decls,
424416
);
425417
assert!(result2.is_ok());
426418
assert_eq!(result2.unwrap(), Name::str("id$bool"));
@@ -433,12 +425,14 @@ mod tests {
433425
fn test_instantiate_multiple_type_params() {
434426
let mut pass = MonomorphPass::new();
435427
let generic_func = mk_simple_func("map", vec!["T0", "T1"]);
428+
let decls = DeclTable::new(vec![]);
436429

437430
let type_args = vec![mk_type(Type::Int32), mk_type(Type::Bool)];
438431
let result = pass.instantiate_function(
439432
Name::str("map"),
440433
type_args,
441434
&generic_func,
435+
&decls,
442436
);
443437

444438
assert!(result.is_ok());
@@ -587,6 +581,7 @@ mod tests {
587581
fn test_get_instantiation() {
588582
let mut pass = MonomorphPass::new();
589583
let generic_func = mk_simple_func("id", vec!["T"]);
584+
let decls = DeclTable::new(vec![]);
590585

591586
let type_args = vec![mk_type(Type::Int32)];
592587
let key = MonomorphKey::new(Name::str("id"), type_args.clone());
@@ -595,7 +590,7 @@ mod tests {
595590
assert!(pass.get_instantiation(&key).is_none());
596591

597592
// After instantiation
598-
pass.instantiate_function(Name::str("id"), type_args, &generic_func)
593+
pass.instantiate_function(Name::str("id"), type_args, &generic_func, &decls)
599594
.unwrap();
600595
assert_eq!(pass.get_instantiation(&key), Some(Name::str("id$i32")));
601596
}
@@ -604,13 +599,15 @@ mod tests {
604599
fn test_specialized_declarations() {
605600
let mut pass = MonomorphPass::new();
606601
let generic_func = mk_simple_func("id", vec!["T"]);
602+
let decls = DeclTable::new(vec![]);
607603

608604
assert_eq!(pass.specialized_declarations().len(), 0);
609605

610606
pass.instantiate_function(
611607
Name::str("id"),
612608
vec![mk_type(Type::Int32)],
613609
&generic_func,
610+
&decls,
614611
).unwrap();
615612

616613
assert_eq!(pass.specialized_declarations().len(), 1);
@@ -619,6 +616,7 @@ mod tests {
619616
#[test]
620617
fn test_type_substitution_in_specialized_func() {
621618
let mut pass = MonomorphPass::new();
619+
let decls = DeclTable::new(vec![]);
622620

623621
// Create a generic function id<T>(x: T) -> T
624622
let t_var = typevar("T");
@@ -634,6 +632,7 @@ mod tests {
634632
Name::str("id"),
635633
vec![mk_type(Type::Int32)],
636634
&generic_func,
635+
&decls,
637636
).unwrap();
638637

639638
// Check the specialized declaration
@@ -659,40 +658,16 @@ mod tests {
659658
let decls = DeclTable::new(vec![]);
660659

661660
let result = pass.monomorphize(&decls, Name::str("main"));
662-
assert!(result.is_ok());
663-
assert_eq!(result.unwrap().len(), 0);
664-
}
665-
666-
#[test]
667-
fn test_worklist_processing() {
668-
let mut pass = MonomorphPass::new();
669-
670-
// Add some items to worklist
671-
pass.worklist.push_back(Name::str("func1"));
672-
pass.worklist.push_back(Name::str("func2"));
673-
674-
assert_eq!(pass.worklist.len(), 2);
675-
676-
// Simulate processing
677-
let func1 = pass.worklist.pop_front().unwrap();
678-
assert_eq!(func1, Name::str("func1"));
679-
assert_eq!(pass.worklist.len(), 1);
661+
// Should fail because the entry point doesn't exist
662+
assert!(result.is_err());
663+
assert!(result.unwrap_err().contains("not found"));
680664
}
681665

682-
#[test]
683-
fn test_processed_tracking() {
684-
let mut pass = MonomorphPass::new();
685-
686-
let name = Name::str("test");
687-
assert!(!pass.processed.contains(&name));
688-
689-
pass.processed.insert(name);
690-
assert!(pass.processed.contains(&name));
691-
}
692666

693667
#[test]
694668
fn test_instantiate_with_nested_generic() {
695669
let mut pass = MonomorphPass::new();
670+
let decls = DeclTable::new(vec![]);
696671

697672
// Create a generic function that works with nested types
698673
let mut generic_func = mk_simple_func("process", vec!["T"]);
@@ -709,6 +684,7 @@ mod tests {
709684
Name::str("process"),
710685
vec![mk_type(Type::Int32)],
711686
&generic_func,
687+
&decls,
712688
);
713689

714690
assert!(result.is_ok());
@@ -730,6 +706,7 @@ mod tests {
730706
#[test]
731707
fn test_multiple_instantiations_same_function() {
732708
let mut pass = MonomorphPass::new();
709+
let decls = DeclTable::new(vec![]);
733710

734711
let generic_func = mk_simple_func("id", vec!["T"]);
735712

@@ -745,6 +722,7 @@ mod tests {
745722
Name::str("id"),
746723
vec![ty],
747724
&generic_func,
725+
&decls,
748726
).unwrap();
749727
}
750728

@@ -792,6 +770,7 @@ mod tests {
792770
#[test]
793771
fn test_instantiate_function_with_constraints() {
794772
let mut pass = MonomorphPass::new();
773+
let decls = DeclTable::new(vec![]);
795774

796775
// Create a generic function with interface constraints
797776
let mut generic_func = mk_simple_func("add", vec!["T"]);
@@ -804,6 +783,7 @@ mod tests {
804783
Name::str("add"),
805784
vec![mk_type(Type::Int32)],
806785
&generic_func,
786+
&decls,
807787
);
808788

809789
assert!(result.is_ok());
@@ -836,6 +816,7 @@ mod tests {
836816
#[test]
837817
fn test_instantiation_deduplication() {
838818
let mut pass = MonomorphPass::new();
819+
let decls = DeclTable::new(vec![]);
839820

840821
let generic_func = mk_simple_func("id", vec!["T"]);
841822
let type_args = vec![mk_type(Type::Int32)];
@@ -846,6 +827,7 @@ mod tests {
846827
Name::str("id"),
847828
type_args.clone(),
848829
&generic_func,
830+
&decls,
849831
).unwrap();
850832

851833
assert_eq!(pass.specialized_decls.len(), 1);
@@ -855,6 +837,7 @@ mod tests {
855837
Name::str("id"),
856838
type_args.clone(),
857839
&generic_func,
840+
&decls,
858841
).unwrap();
859842

860843
assert_eq!(pass.specialized_decls.len(), 1);
@@ -920,9 +903,6 @@ mod tests {
920903

921904
// Should have 1 decl (just main, no specializations)
922905
assert_eq!(all_decls.len(), 1);
923-
924-
// The entry point should have been processed
925-
assert!(pass.processed.contains(&Name::str("main")));
926906
}
927907

928908
#[test]
@@ -1002,14 +982,8 @@ mod tests {
1002982
assert_eq!(*fdecl.ret, Type::Int32);
1003983
// Name should start with "id$"
1004984
assert!(fdecl.name.to_string().starts_with("id$"));
1005-
1006-
// The specialized id function should be in the processed set
1007-
assert!(pass.processed.contains(&fdecl.name));
1008985
} else {
1009986
panic!("Expected function declaration");
1010987
}
1011-
1012-
// Both main and the specialized id function should be processed
1013-
assert!(pass.processed.contains(&Name::str("main")));
1014988
}
1015989
}

0 commit comments

Comments
 (0)