@@ -279,6 +279,12 @@ pub trait AstHostFunctions {
279279 /// Create a struct literal expression
280280 fn create_struct_literal ( & mut self , name : & str , fields : Vec < ( String , NodeHandle ) > ) -> NodeHandle ;
281281
282+ /// Store a struct field initialization (for later lookup by struct_init)
283+ fn store_struct_field_init ( & mut self , name : & str , value : NodeHandle ) -> NodeHandle ;
284+
285+ /// Get a stored struct field initialization
286+ fn get_struct_field_init ( & self , handle : NodeHandle ) -> Option < ( String , NodeHandle ) > ;
287+
282288 /// Create a cast expression
283289 fn create_cast ( & mut self , expr : NodeHandle , target_type : NodeHandle ) -> NodeHandle ;
284290
@@ -840,6 +846,8 @@ pub struct TypedAstBuilder {
840846 fields : HashMap < NodeHandle , TypedField > ,
841847 /// Stored variant nodes by handle
842848 variants : HashMap < NodeHandle , TypedVariant > ,
849+ /// Stored struct field initializers (name, value) by handle
850+ struct_field_inits : HashMap < NodeHandle , ( String , NodeHandle ) > ,
843851 /// Program declaration handles (in order)
844852 program_decls : Vec < NodeHandle > ,
845853}
@@ -861,6 +869,7 @@ impl TypedAstBuilder {
861869 declarations : HashMap :: new ( ) ,
862870 fields : HashMap :: new ( ) ,
863871 variants : HashMap :: new ( ) ,
872+ struct_field_inits : HashMap :: new ( ) ,
864873 program_decls : Vec :: new ( ) ,
865874 }
866875 }
@@ -1536,6 +1545,16 @@ impl AstHostFunctions for TypedAstBuilder {
15361545 self . store_expr ( expr)
15371546 }
15381547
1548+ fn store_struct_field_init ( & mut self , name : & str , value : NodeHandle ) -> NodeHandle {
1549+ let handle = self . alloc_handle ( ) ;
1550+ self . struct_field_inits . insert ( handle, ( name. to_string ( ) , value) ) ;
1551+ handle
1552+ }
1553+
1554+ fn get_struct_field_init ( & self , handle : NodeHandle ) -> Option < ( String , NodeHandle ) > {
1555+ self . struct_field_inits . get ( & handle) . cloned ( )
1556+ }
1557+
15391558 fn create_cast ( & mut self , expr_handle : NodeHandle , _target_type : NodeHandle ) -> NodeHandle {
15401559 let span = self . default_span ( ) ;
15411560
@@ -2225,6 +2244,47 @@ impl<'a, H: AstHostFunctions> CommandInterpreter<'a, H> {
22252244 Ok ( RuntimeValue :: Node ( handle) )
22262245 }
22272246
2247+ // Struct instantiation: Point{ .x = 10, .y = 20 }
2248+ "struct_init" => {
2249+ let type_name = match args. get ( "type_name" ) {
2250+ Some ( RuntimeValue :: String ( s) ) => s. clone ( ) ,
2251+ _ => "AnonymousStruct" . to_string ( ) ,
2252+ } ;
2253+ // Fields come as a list of struct_field_init results
2254+ // Each struct_field_init stores (name, value) in host's struct_init_fields map
2255+ let fields: Vec < ( String , NodeHandle ) > = match args. get ( "fields" ) {
2256+ Some ( RuntimeValue :: List ( list) ) => {
2257+ list. iter ( )
2258+ . filter_map ( |v| match v {
2259+ RuntimeValue :: Node ( h) => {
2260+ // Look up the field init data from host
2261+ self . host . get_struct_field_init ( * h)
2262+ }
2263+ _ => None ,
2264+ } )
2265+ . collect ( )
2266+ }
2267+ _ => vec ! [ ] ,
2268+ } ;
2269+ let handle = self . host . create_struct_literal ( & type_name, fields) ;
2270+ Ok ( RuntimeValue :: Node ( handle) )
2271+ }
2272+
2273+ // Struct field initialization: .x = 10
2274+ "struct_field_init" => {
2275+ let name = match args. get ( "name" ) {
2276+ Some ( RuntimeValue :: String ( s) ) => s. clone ( ) ,
2277+ _ => "field" . to_string ( ) ,
2278+ } ;
2279+ let value = match args. get ( "value" ) {
2280+ Some ( RuntimeValue :: Node ( h) ) => * h,
2281+ _ => return Err ( crate :: error:: ZynPegError :: CodeGenError ( "struct_field_init: missing value" . into ( ) ) ) ,
2282+ } ;
2283+ // Store field init and return a handle for later lookup
2284+ let handle = self . host . store_struct_field_init ( & name, value) ;
2285+ Ok ( RuntimeValue :: Node ( handle) )
2286+ }
2287+
22282288 "cast" => {
22292289 let expr = match args. get ( "expr" ) {
22302290 Some ( RuntimeValue :: Node ( h) ) => * h,
0 commit comments