Skip to content

Commit 8965b37

Browse files
committed
process IDs instead of calls
1 parent 0489b09 commit 8965b37

File tree

1 file changed

+47
-96
lines changed

1 file changed

+47
-96
lines changed

src/monomorph_pass.rs

Lines changed: 47 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -94,29 +94,57 @@ impl MonomorphPass {
9494
let expr = fdecl.arena[expr_id].clone();
9595

9696
match &expr {
97+
Expr::Id(name) => {
98+
// Check if this identifier refers to a function
99+
// Get the solved type for this expression
100+
let solved_type = fdecl.types[expr_id];
101+
102+
// Look up the declaration
103+
let fn_decls = decls.find(*name);
104+
for decl in fn_decls {
105+
if let Decl::Func(target_fdecl) = decl {
106+
if !target_fdecl.typevars.is_empty() {
107+
// This is a generic function - compute type arguments from solved type
108+
let type_args = self.infer_type_arguments(
109+
target_fdecl,
110+
solved_type,
111+
fdecl,
112+
)?;
113+
114+
if !type_args.is_empty() {
115+
// Create a specialized version
116+
let mangled_name = self.instantiate_function(*name, type_args, target_fdecl, decls)?;
117+
118+
// Rewrite the identifier to use the mangled name
119+
fdecl.arena.exprs[expr_id] = Expr::Id(mangled_name);
120+
}
121+
} else {
122+
// Non-generic function - include it in outputs if not already there
123+
let already_included = self.out_decls.iter().any(|d| {
124+
if let Decl::Func(f) = d {
125+
f.name == target_fdecl.name
126+
} else {
127+
false
128+
}
129+
});
130+
131+
if !already_included {
132+
self.out_decls.push(decl.clone());
133+
}
134+
}
135+
}
136+
}
137+
}
97138
Expr::Call(fn_id, arg_ids) => {
98-
// Extract fn_name and fn_type before any mutable borrows
99-
let fn_name = if let Expr::Id(name) = &fdecl.arena[*fn_id] {
100-
Some(*name)
101-
} else {
102-
None
103-
};
104-
let fn_type = fdecl.types[*fn_id];
105-
let fn_id = *fn_id;
139+
// Process arguments first
106140
let arg_ids = arg_ids.clone();
107-
108-
// Process the function expression
109-
self.process_expr(fn_id, fdecl, decls)?;
110-
111-
// Process arguments
112141
for arg_id in &arg_ids {
113142
self.process_expr(*arg_id, fdecl, decls)?;
114143
}
115144

116-
// Check if this is a call to a generic function
117-
if let Some(name) = fn_name {
118-
self.process_call(&name, fn_type, fdecl, decls)?;
119-
}
145+
// Process the function expression (which handles Id rewriting)
146+
let fn_id = *fn_id;
147+
self.process_expr(fn_id, fdecl, decls)?;
120148
}
121149
Expr::Binop(_, lhs, rhs) => {
122150
self.process_expr(*lhs, fdecl, decls)?;
@@ -164,8 +192,8 @@ impl MonomorphPass {
164192
Expr::Lambda { body, .. } => {
165193
self.process_expr(*body, fdecl, decls)?;
166194
}
167-
// Leaf expressions
168-
Expr::Id(_) | Expr::Int(_) | Expr::UInt(_) | Expr::Real(_) |
195+
// Leaf expressions (note: Id is handled separately above)
196+
Expr::Int(_) | Expr::UInt(_) | Expr::Real(_) |
169197
Expr::String(_) | Expr::Char(_) | Expr::True | Expr::False |
170198
Expr::Return(_) | Expr::Enum(_) | Expr::Error | Expr::Cast |
171199
Expr::Tuple(_) | Expr::Arena(_) | Expr::Array(_, _) |
@@ -175,46 +203,6 @@ impl MonomorphPass {
175203
Ok(())
176204
}
177205

178-
/// Handle a call to a potentially generic function
179-
fn process_call(
180-
&mut self,
181-
fn_name: &Name,
182-
fn_type: TypeID,
183-
caller_fdecl: &mut FuncDecl,
184-
decls: &DeclTable,
185-
) -> Result<(), String> {
186-
// Look up the function declaration
187-
let fn_decls = decls.find(*fn_name);
188-
if fn_decls.is_empty() {
189-
// Built-in or external function
190-
return Ok(());
191-
}
192-
193-
// Check if any overload is generic
194-
for decl in fn_decls {
195-
if let Decl::Func(target_fdecl) = decl {
196-
if !target_fdecl.typevars.is_empty() {
197-
// This is a generic function - compute type arguments
198-
let type_args = self.infer_type_arguments(
199-
target_fdecl,
200-
fn_type,
201-
caller_fdecl,
202-
)?;
203-
204-
if !type_args.is_empty() {
205-
// Create a specialized version and recursively process it
206-
self.instantiate_function(*fn_name, type_args, target_fdecl, decls)?;
207-
}
208-
} else {
209-
// Non-generic function, output as is.
210-
self.out_decls.push(decl.clone());
211-
}
212-
}
213-
}
214-
215-
Ok(())
216-
}
217-
218206
/// Infer concrete type arguments for a generic function call
219207
fn infer_type_arguments(
220208
&self,
@@ -764,43 +752,6 @@ mod tests {
764752
assert_eq!(pass.instantiations.len(), 3);
765753
}
766754

767-
#[test]
768-
fn test_handle_generic_call_with_non_generic() {
769-
let mut pass = MonomorphPass::new();
770-
771-
// Create a non-generic function
772-
let non_generic = FuncDecl {
773-
name: Name::str("non_generic"),
774-
typevars: Vec::new(),
775-
params: Vec::new(),
776-
constraints: Vec::new(),
777-
ret: mk_type(Type::Void),
778-
body: Some(0),
779-
arena: ExprArena::new(),
780-
types: Vec::new(),
781-
loc: test_loc(),
782-
};
783-
784-
let decls = DeclTable::new(vec![Decl::Func(non_generic.clone())]);
785-
786-
let fn_type = mk_type(Type::Func(
787-
mk_type(Type::Tuple(Vec::new())),
788-
mk_type(Type::Void),
789-
));
790-
791-
// Call handle_generic_call - should not create any specializations
792-
let mut non_generic_mut = non_generic.clone();
793-
let result = pass.process_call(
794-
&Name::str("non_generic"),
795-
fn_type,
796-
&mut non_generic_mut,
797-
&decls,
798-
);
799-
800-
assert!(result.is_ok());
801-
assert_eq!(pass.out_decls.len(), 1);
802-
}
803-
804755
#[test]
805756
fn test_instantiate_function_with_constraints() {
806757
let mut pass = MonomorphPass::new();

0 commit comments

Comments
 (0)