@@ -21,38 +21,47 @@ pub struct Env {
2121}
2222
2323impl Env {
24+ /// Creates a new environment builder.
2425 pub fn builder ( ) -> EnvBuilder {
2526 EnvBuilder :: default ( )
2627 }
2728
29+ /// Looks up an identifier declaration by name.
2830 pub fn lookup_ident ( & self , name : & str ) -> Option < & IdentDecl > {
2931 self . identifiers . get ( name)
3032 }
3133
34+ /// Looks up a function declaration by name.
3235 pub fn lookup_function ( & self , name : & str ) -> Option < & FunctionDecl > {
3336 self . functions . get ( name)
3437 }
3538
39+ /// Looks up a named type by its type name.
3640 pub fn lookup_type ( & self , name : & TypeName ) -> Option < & NamedType > {
3741 self . type_registry . get ( name)
3842 }
3943
44+ /// Returns the type registry associated with the environment.
4045 pub fn types ( & self ) -> & TypeRegistry {
4146 & self . type_registry
4247 }
4348
49+ /// Returns all identifier declarations in the environment.
4450 pub fn idents ( & self ) -> & BTreeMap < String , IdentDecl > {
4551 & self . identifiers
4652 }
4753
54+ /// Returns all function declarations in the environment.
4855 pub fn functions ( & self ) -> & BTreeMap < String , FunctionDecl > {
4956 & self . functions
5057 }
5158
59+ /// Returns the macro registry associated with the environment.
5260 pub fn macros ( & self ) -> & MacroRegistry {
5361 & self . macros
5462 }
5563
64+ /// Compiles the given CEL source code into a typed AST using this environment.
5665 pub fn compile ( & self , src : & str ) -> Result < TypedExpr , CompileError > {
5766 let mut parser = Parser :: new ( src) ;
5867 let token_tree = parser. parse ( ) ?;
@@ -78,10 +87,11 @@ pub struct EnvBuilder {
7887
7988impl Default for EnvBuilder {
8089 fn default ( ) -> Self {
81- let mut builder = EnvBuilder :: new_empty ( ) ;
90+ let mut builder = EnvBuilder :: empty ( ) ;
8291 builder
8392 . install_builtin_function_decls ( )
8493 . expect ( "builtin declarations must register" ) ;
94+ builder. install_builtin_macros ( ) ;
8595 builder
8696 }
8797}
@@ -98,26 +108,30 @@ impl CelTypeRegistrar for EnvBuilder {
98108}
99109
100110impl EnvBuilder {
111+ /// Creates a new environment builder, with built-in functions and macros.
101112 pub fn new ( ) -> Self {
102113 Self :: default ( )
103114 }
104115
105- pub fn new_empty ( ) -> Self {
116+ /// Creates a new empty environment builder without built-in functions or macros.
117+ pub fn empty ( ) -> Self {
106118 Self {
107119 type_registry : TypeRegistry :: new ( ) ,
108120 identifiers : BTreeMap :: new ( ) ,
109121 functions : BTreeMap :: new ( ) ,
110- macros : MacroRegistry :: standard ( ) ,
122+ macros : MacroRegistry :: empty ( ) ,
111123 }
112124 }
113125
126+ /// Adds a named type to the environment being built.
114127 pub fn add_type ( & mut self , ty : NamedType ) -> Result < & mut Self , EnvError > {
115128 self . type_registry . register ( ty) . map_err ( |e| {
116129 EnvError :: new ( format ! ( "Type registration error: {}" , e) )
117130 } ) ?;
118131 Ok ( self )
119132 }
120133
134+ /// Adds an identifier declaration to the environment being built.
121135 pub fn add_ident (
122136 & mut self ,
123137 decl : IdentDecl ,
@@ -132,6 +146,7 @@ impl EnvBuilder {
132146 Ok ( self )
133147 }
134148
149+ /// Adds a function declaration to the environment being built.
135150 pub fn add_function (
136151 & mut self ,
137152 mut decl : FunctionDecl ,
@@ -153,48 +168,66 @@ impl EnvBuilder {
153168 Ok ( self )
154169 }
155170
171+ /// Returns the macro registry being built.
156172 pub fn macros ( & self ) -> & MacroRegistry {
157173 & self . macros
158174 }
159175
176+ /// Returns a mutable reference to the macro registry being built.
160177 pub fn macros_mut ( & mut self ) -> & mut MacroRegistry {
161178 & mut self . macros
162179 }
163180
181+ /// Looks up an identifier declaration by name.
164182 pub fn lookup_ident ( & self , name : & str ) -> Option < & IdentDecl > {
165183 self . identifiers . get ( name)
166184 }
167185
186+ /// Looks up a function declaration by name.
168187 pub fn lookup_function ( & self , name : & str ) -> Option < & FunctionDecl > {
169188 self . functions . get ( name)
170189 }
171190
191+ /// Sets the macro registry for the environment being built.
172192 pub fn set_macros ( & mut self , registry : MacroRegistry ) -> & mut Self {
173193 self . macros = registry;
174194 self
175195 }
176196
197+ /// Imports all types, identifiers and functions from the given environment.
177198 pub fn import_env ( & mut self , env : & Env ) -> Result < & mut Self , EnvError > {
178199 for ( _, ty) in env. types ( ) . iter ( ) {
179- self . type_registry . register ( ty. clone ( ) ) ?;
200+ self . add_type ( ty. clone ( ) ) ?;
180201 }
181202 for decl in env. idents ( ) . values ( ) {
182203 self . add_ident ( decl. clone ( ) ) ?;
183204 }
184205 for decl in env. functions ( ) . values ( ) {
185- match self . functions . entry ( decl. name . clone ( ) ) {
186- Entry :: Vacant ( entry) => {
187- entry. insert ( decl. clone ( ) ) ;
188- }
189- Entry :: Occupied ( mut entry) => {
190- merge_function_decl ( entry. get_mut ( ) , decl) ?;
191- }
192- }
206+ self . merge_function_shared ( decl) ?;
193207 }
194208 self . macros . merge ( env. macros ( ) ) ;
195209 Ok ( self )
196210 }
197211
212+ /// Imports all entries from an owned environment, reusing allocations when possible.
213+ pub fn import_env_owned (
214+ & mut self ,
215+ env : Env ,
216+ ) -> Result < & mut Self , EnvError > {
217+ let Env {
218+ type_registry,
219+ identifiers,
220+ functions,
221+ macros,
222+ } = env;
223+ self . absorb_type_registry ( type_registry) ?;
224+ self . absorb_identifiers ( identifiers) ?;
225+ self . absorb_functions ( functions) ?;
226+ self . absorb_macros ( macros) ;
227+ Ok ( self )
228+ }
229+
230+ /// Builds the environment.
198231 pub fn build ( self ) -> Env {
199232 Env {
200233 type_registry : Arc :: new ( self . type_registry ) ,
@@ -204,12 +237,110 @@ impl EnvBuilder {
204237 }
205238 }
206239
240+ fn absorb_type_registry (
241+ & mut self ,
242+ registry : Arc < TypeRegistry > ,
243+ ) -> Result < ( ) , EnvError > {
244+ match Arc :: try_unwrap ( registry) {
245+ Ok ( inner) => {
246+ for ty in inner. into_named_types ( ) {
247+ self . add_type ( ty) ?;
248+ }
249+ }
250+ Err ( shared) => {
251+ for ( _, ty) in shared. as_ref ( ) . iter ( ) {
252+ self . add_type ( ty. clone ( ) ) ?;
253+ }
254+ }
255+ }
256+ Ok ( ( ) )
257+ }
258+
259+ fn absorb_identifiers (
260+ & mut self ,
261+ idents : Arc < BTreeMap < String , IdentDecl > > ,
262+ ) -> Result < ( ) , EnvError > {
263+ match Arc :: try_unwrap ( idents) {
264+ Ok ( map) => {
265+ for decl in map. into_values ( ) {
266+ self . add_ident ( decl) ?;
267+ }
268+ }
269+ Err ( shared) => {
270+ for decl in shared. as_ref ( ) . values ( ) {
271+ self . add_ident ( decl. clone ( ) ) ?;
272+ }
273+ }
274+ }
275+ Ok ( ( ) )
276+ }
277+
278+ fn absorb_functions (
279+ & mut self ,
280+ functions : Arc < BTreeMap < String , FunctionDecl > > ,
281+ ) -> Result < ( ) , EnvError > {
282+ match Arc :: try_unwrap ( functions) {
283+ Ok ( map) => {
284+ for decl in map. into_values ( ) {
285+ self . merge_function_owned ( decl) ?;
286+ }
287+ }
288+ Err ( shared) => {
289+ for decl in shared. as_ref ( ) . values ( ) {
290+ self . merge_function_shared ( decl) ?;
291+ }
292+ }
293+ }
294+ Ok ( ( ) )
295+ }
296+
297+ fn merge_function_shared (
298+ & mut self ,
299+ decl : & FunctionDecl ,
300+ ) -> Result < ( ) , EnvError > {
301+ match self . functions . entry ( decl. name . clone ( ) ) {
302+ Entry :: Vacant ( entry) => {
303+ entry. insert ( decl. clone ( ) ) ;
304+ }
305+ Entry :: Occupied ( mut entry) => {
306+ merge_function_decl ( entry. get_mut ( ) , decl) ?;
307+ }
308+ }
309+ Ok ( ( ) )
310+ }
311+
312+ fn merge_function_owned (
313+ & mut self ,
314+ decl : FunctionDecl ,
315+ ) -> Result < ( ) , EnvError > {
316+ match self . functions . entry ( decl. name . clone ( ) ) {
317+ Entry :: Vacant ( entry) => {
318+ entry. insert ( decl) ;
319+ }
320+ Entry :: Occupied ( mut entry) => {
321+ merge_function_decl_owned ( entry. get_mut ( ) , decl) ?;
322+ }
323+ }
324+ Ok ( ( ) )
325+ }
326+
327+ fn absorb_macros ( & mut self , macros : Arc < MacroRegistry > ) {
328+ match Arc :: try_unwrap ( macros) {
329+ Ok ( registry) => self . macros . merge ( & registry) ,
330+ Err ( shared) => self . macros . merge ( shared. as_ref ( ) ) ,
331+ }
332+ }
333+
207334 fn install_builtin_function_decls ( & mut self ) -> Result < ( ) , EnvError > {
208335 for decl in builtin_function_decls ( ) {
209336 self . add_function ( decl) ?;
210337 }
211338 Ok ( ( ) )
212339 }
340+
341+ fn install_builtin_macros ( & mut self ) {
342+ self . macros = MacroRegistry :: new ( ) ;
343+ }
213344}
214345
215346fn merge_function_decl (
@@ -238,6 +369,32 @@ fn merge_function_decl(
238369 Ok ( ( ) )
239370}
240371
372+ fn merge_function_decl_owned (
373+ existing : & mut FunctionDecl ,
374+ mut incoming : FunctionDecl ,
375+ ) -> Result < ( ) , EnvError > {
376+ if existing. doc . is_none ( ) {
377+ existing. doc = incoming. doc . take ( ) ;
378+ }
379+ for overload in incoming. overloads . drain ( ..) {
380+ if let Some ( current) = existing
381+ . overloads
382+ . iter ( )
383+ . find ( |item| item. id == overload. id )
384+ {
385+ if current != & overload {
386+ return Err ( EnvError :: new ( format ! (
387+ "Function '{}' overload id '{}' conflicts with existing declaration" ,
388+ existing. name, overload. id
389+ ) ) ) ;
390+ }
391+ continue ;
392+ }
393+ existing. overloads . push ( overload) ;
394+ }
395+ Ok ( ( ) )
396+ }
397+
241398fn builtin_function_decls ( ) -> Vec < FunctionDecl > {
242399 vec ! [
243400 builtin_size_decl( ) ,
@@ -490,6 +647,35 @@ mod tests {
490647 assert ! ( merged. lookup_type( & scan. name) . is_some( ) ) ;
491648 }
492649
650+ #[ test]
651+ fn merge_existing_env_owned ( ) {
652+ let scan = build_scan_type ( ) ;
653+ let mut base = Env :: builder ( ) ;
654+ base. add_type ( NamedType :: Struct ( scan. clone ( ) ) ) . unwrap ( ) ;
655+ base. add_ident ( IdentDecl :: new ( "scan_total" , Type :: Int ) )
656+ . unwrap ( ) ;
657+ base. add_function ( {
658+ let mut func = FunctionDecl :: new ( "scan_owned_status" ) ;
659+ func. add_overload ( OverloadDecl :: new (
660+ "scan_owned_status_struct" ,
661+ vec ! [ Type :: struct_type( scan. name. clone( ) ) ] ,
662+ Type :: Bool ,
663+ ) )
664+ . unwrap ( ) ;
665+ func
666+ } )
667+ . unwrap ( ) ;
668+ let env = base. build ( ) ;
669+
670+ let mut derived = Env :: builder ( ) ;
671+ derived. import_env_owned ( env) . unwrap ( ) ;
672+ let merged = derived. build ( ) ;
673+
674+ assert ! ( merged. lookup_type( & scan. name) . is_some( ) ) ;
675+ assert ! ( merged. lookup_ident( "scan_total" ) . is_some( ) ) ;
676+ assert ! ( merged. lookup_function( "scan_owned_status" ) . is_some( ) ) ;
677+ }
678+
493679 #[ test]
494680 fn compile_supports_standard_macros ( ) {
495681 let mut builder = Env :: builder ( ) ;
0 commit comments