@@ -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