@@ -66,6 +66,38 @@ module Map = struct
6666 let fold (f : string -> 'a -> 'b -> 'b ) (s : 'b ) (t : 'a t ) : 'b = Map. fold f ! t s
6767end
6868
69+ (* Signature-based map for template instantiations *)
70+ module SignatureMap = struct
71+ module SignatureOrder = struct
72+ type t = Typed .instantiation_signature
73+
74+ let compare = Typed. compare_instantiation_signature
75+ end
76+
77+ module BaseMap = CCMap. Make (SignatureOrder )
78+
79+ type 'a t = 'a BaseMap .t ref
80+
81+ let empty () = ref BaseMap. empty
82+
83+ let update (report : 'a -> 'a -> 'a ) (key : Typed.instantiation_signature ) (value : 'a ) (t : 'a t ) : unit =
84+ t :=
85+ BaseMap. update
86+ key
87+ (fun a ->
88+ match a with
89+ | None -> Some value
90+ | Some b ->
91+ let c = report b value in
92+ Some c)
93+ ! t
94+
95+
96+ let find (key : Typed.instantiation_signature ) (t : 'a t ) : 'a option = BaseMap. find_opt key ! t
97+
98+ let is_empty (t : 'a t ) : bool = BaseMap. is_empty ! t
99+ end
100+
69101module type TSig = sig
70102 type t
71103
@@ -124,16 +156,27 @@ type f =
124156type m =
125157 { name : string
126158 ; functions : f Map .t
159+ ; generics : Typed .generic_function Map .t
160+ ; instantiated : Typed .generic_instantiation SignatureMap .t
127161 ; types : t Map .t
128162 ; mutable init : (path * path ) list
129163 ; enums : t Map .t
130164 ; mutable constants : var Map .t
165+ ; mutable pending_injections :
166+ (Typed .function_def
167+ * Pparser.Syntax .stmt
168+ * ((string * string ) list * (string * Pparser.Syntax .exp ) list )
169+ * (string * Typed .type_ ) list )
170+ list
171+ (* Functions to be injected with their syntax bodies, substitutions, and type parameter bindings *)
131172 }
132173
133174(* Generic lookup result variant *)
134175type lookup_result =
135176 | LookupVar of var
136177 | LookupFunction of f
178+ | LookupGeneric of Typed .generic_function
179+ | LookupInstantiation of Typed .generic_instantiation
137180 | LookupType of t
138181 | LookupEnum of (path * Loc .t * int ) (* path, location, index *)
139182 | LookupConstant of var
@@ -662,10 +705,13 @@ let enterModule (env : env) (name : string) : env =
662705 let m : m =
663706 { name
664707 ; functions = Map. empty ()
708+ ; generics = Map. empty ()
709+ ; instantiated = SignatureMap. empty ()
665710 ; types = Map. empty ()
666711 ; enums = Map. empty ()
667712 ; init = []
668713 ; constants = Map. empty ()
714+ ; pending_injections = []
669715 }
670716 in
671717 let () = Map. update report name m env.modules in
@@ -702,6 +748,11 @@ let lookupPath (env : env) (path : path) : lookup_result list =
702748 | None -> results)
703749 | _ -> results
704750 in
751+ let results =
752+ match Map. find id m.generics with
753+ | Some generic -> LookupGeneric generic :: results
754+ | None -> results
755+ in
705756 results
706757 in
707758 match path with
@@ -793,6 +844,15 @@ let findEnum (results : lookup_result list) : (path * Loc.t * int) option =
793844 find results
794845
795846
847+ let findGeneric (results : lookup_result list ) : Typed.generic_function option =
848+ let rec find = function
849+ | [] -> None
850+ | LookupGeneric generic :: _ -> Some generic
851+ | _ :: rest -> find rest
852+ in
853+ find results
854+
855+
796856(* Function lookup using the new generic lookup system *)
797857let lookFunctionCall (env : env ) (path : path ) (loc : Loc.t ) : f =
798858 match findFunction (lookupPath env path) with
@@ -811,17 +871,131 @@ let lookOperator (env : env) (op : string) : f =
811871(* Since operators are only builtins, this behaves the same as lookOperator *)
812872let lookOperatorInModule (env : env ) (op : string ) : f = lookOperator env op
813873
874+ (* Generic management functions *)
875+ let addGeneric (env : env ) (generic : Typed.generic_function ) : env =
876+ match env.location with
877+ | InModule name -> (
878+ let module_opt = Map. find name env.modules in
879+ match module_opt with
880+ | Some m ->
881+ let () =
882+ Map. update (fun _ _ -> failwith (" duplicate generic: " ^ generic.name)) generic.name generic m.generics
883+ in
884+ env
885+ | None -> failwith (" module not found: " ^ name))
886+ | _ -> failwith " addGeneric: not in a module"
887+
888+
889+ (* Generic lookup using the new generic lookup system *)
890+ let lookupGeneric (env : env ) (name : string ) : Typed.generic_function option =
891+ let generic_path : path = { id = name; n = None ; loc = Loc. default } in
892+ findGeneric (lookupPath env generic_path)
893+
894+
895+ let addInstantiation (env : env ) (instantiation : Typed.generic_instantiation ) : env =
896+ let module_name =
897+ match env.location with
898+ | InModule name -> name
899+ | InContext (name , _ ) -> name
900+ | InFunction (name , _ ) -> name
901+ | Top -> failwith " addInstantiation: not in any module context"
902+ in
903+ let module_opt = Map. find module_name env.modules in
904+ match module_opt with
905+ | Some m ->
906+ let () =
907+ SignatureMap. update
908+ (fun _ _ -> failwith (" duplicate instantiation: " ^ instantiation.specialized_name))
909+ instantiation.signature
910+ instantiation
911+ m.instantiated
912+ in
913+ env
914+ | None -> failwith (" module not found: " ^ module_name)
915+
916+
917+ let findInstantiation (env : env ) (signature : Typed.instantiation_signature ) : Typed.generic_instantiation option =
918+ let module_name =
919+ match env.location with
920+ | InModule name -> Some name
921+ | InContext (name , _ ) -> Some name
922+ | InFunction (name , _ ) -> Some name
923+ | Top -> None
924+ in
925+ match module_name with
926+ | Some module_name -> (
927+ let module_opt = Map. find module_name env.modules in
928+ match module_opt with
929+ | Some m -> SignatureMap. find signature m.instantiated
930+ | None -> None )
931+ | None -> None
932+
933+
934+ (* Backward compatibility function removed - now using signature-based lookup *)
935+
936+ (* Add a function to be injected into the current module *)
937+ let addPendingInjection (env : env )
938+ (func_def_syntax_subs :
939+ Typed.function_def
940+ * Pparser.Syntax.stmt
941+ * ((string * string) list * (string * Pparser.Syntax.exp) list )
942+ * (string * Typed. type_ ) list ) : env =
943+ let module_name =
944+ match env.location with
945+ | InModule name -> name
946+ | InContext (name , _ ) -> name
947+ | InFunction (name , _ ) -> name
948+ | Top -> failwith " addPendingInjection: not in any module context"
949+ in
950+ let module_opt = Map. find module_name env.modules in
951+ match module_opt with
952+ | Some m ->
953+ m.pending_injections < - func_def_syntax_subs :: m.pending_injections;
954+ env
955+ | None -> failwith (" module not found: " ^ module_name)
956+
957+
958+ (* Get and clear pending injections for a module *)
959+ let getPendingInjectionsAndClear (env : env ) :
960+ (Typed. function_def
961+ * Pparser.Syntax. stmt
962+ * ((string * string ) list * (string * Pparser.Syntax. exp ) list )
963+ * (string * Typed. type_ ) list )
964+ list =
965+ let module_name =
966+ match env.location with
967+ | InModule name -> name
968+ | InContext (name , _ ) -> name
969+ | InFunction (name , _ ) -> name
970+ | Top -> failwith " getPendingInjectionsAndClear: not in any module context"
971+ in
972+ let module_opt = Map. find module_name env.modules in
973+ match module_opt with
974+ | Some m ->
975+ let injections = List. rev m.pending_injections in
976+ (* Reverse to maintain order *)
977+ m.pending_injections < - [] ;
978+ injections
979+ | None -> failwith (" module not found: " ^ module_name)
980+
981+
814982(* Unified expression lookup for handling ambiguous symbols *)
983+ (* Expression evaluation context *)
984+ type expr_context =
985+ { in_constant : bool
986+ ; in_generic_arg : bool
987+ }
988+
815989type expression_symbol =
816990 | ExprVariable of var
817991 | ExprFunction of f
818992 | ExprType of t
819993 | ExprEnum of (path * Loc .t * int )
820994 | ExprNotFound
821995
822- let lookupExpressionSymbol (env : env ) (path : path ) (in_constant_context : bool ) : expression_symbol =
996+ let lookupExpressionSymbol (env : env ) (path : path ) (context : expr_context ) : expression_symbol =
823997 let results = lookupPath env path in
824- if in_constant_context then
998+ if context.in_constant then
825999 (* In constant context: constants first, then enums, then types *)
8261000 match findVar results with
8271001 | Some var when var.kind = Const -> ExprVariable var
@@ -832,8 +1006,19 @@ let lookupExpressionSymbol (env : env) (path : path) (in_constant_context : bool
8321006 match findType results with
8331007 | Some t -> ExprType t
8341008 | None -> ExprNotFound ))
1009+ else if context.in_generic_arg then
1010+ (* In generic argument context: variables first, then functions (allowed as references), then enums *)
1011+ match findVar results with
1012+ | Some var -> ExprVariable var
1013+ | None -> (
1014+ match findFunction results with
1015+ | Some f -> ExprFunction f (* Allow function references in generic context *)
1016+ | None -> (
1017+ match findEnum results with
1018+ | Some enum_data -> ExprEnum enum_data
1019+ | None -> ExprNotFound ))
8351020 else
836- (* In regular context: variables first, then functions, then enums *)
1021+ (* In regular context: variables first, then functions (require call) , then enums *)
8371022 match findVar results with
8381023 | Some var -> ExprVariable var
8391024 | None -> (
0 commit comments