Skip to content

Commit 5321940

Browse files
committed
Initial implementation of generics.
1 parent 19a2e9c commit 5321940

File tree

18 files changed

+2569
-68
lines changed

18 files changed

+2569
-68
lines changed

examples/features/FunctionArgument.vult

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/core/env.ml

Lines changed: 188 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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
6767
end
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+
69101
module type TSig = sig
70102
type t
71103

@@ -124,16 +156,27 @@ type f =
124156
type 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 *)
134175
type 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 *)
797857
let 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 *)
812872
let 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+
815989
type 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

Comments
 (0)