@@ -85,9 +85,9 @@ def _handle_fstring_print(joined_str, module, builder, func,
8585 if isinstance (value , ast .Constant ):
8686 _process_constant_in_fstring (value , fmt_parts , exprs )
8787 elif isinstance (value , ast .FormattedValue ):
88- _process_formatted_value (value , fmt_parts , exprs ,
89- local_sym_tab , struct_sym_tab ,
90- local_var_metadata )
88+ _process_fval (value , fmt_parts , exprs ,
89+ local_sym_tab , struct_sym_tab ,
90+ local_var_metadata )
9191
9292
9393def _process_constant_in_fstring (cst , fmt_parts , exprs ):
@@ -102,16 +102,77 @@ def _process_constant_in_fstring(cst, fmt_parts, exprs):
102102 f"Unsupported constant type in f-string: { type (cst .value )} " )
103103
104104
105- def _process_formatted_value (fval , fmt_parts , exprs ,
106- local_sym_tab , struct_sym_tab ,
107- local_var_metadata ):
105+ def _process_fval (fval , fmt_parts , exprs ,
106+ local_sym_tab , struct_sym_tab ,
107+ local_var_metadata ):
108108 """Process formatted values in f-string."""
109109 logger .debug (f"Processing formatted value: { ast .dump (fval )} " )
110110
111111 if isinstance (fval .value , ast .Name ):
112- pass
112+ _process_name_in_fval ( fval . value , fmt_parts , exprs , local_sym_tab )
113113 elif isinstance (fval .value , ast .Attribute ):
114- pass
114+ _process_attr_in_fval (fval .value , fmt_parts , exprs ,
115+ local_sym_tab , struct_sym_tab ,
116+ local_var_metadata )
115117 else :
116118 raise NotImplementedError (
117119 f"Unsupported formatted value type in f-string: { type (fval .value )} " )
120+
121+
122+ def _process_name_in_fval (name_node , fmt_parts , exprs , local_sym_tab ):
123+ """Process name nodes in formatted values."""
124+ if local_sym_tab and name_node .id in local_sym_tab :
125+ _ , var_type = local_sym_tab [name_node .id ]
126+ _populate_fval (var_type , name_node , fmt_parts , exprs )
127+
128+
129+ def _process_attr_in_fval (attr_node , fmt_parts , exprs ,
130+ local_sym_tab , struct_sym_tab ,
131+ local_var_metadata ):
132+ """Process attribute nodes in formatted values."""
133+ if (isinstance (attr_node .value , ast .Name ) and
134+ local_sym_tab and attr_node .value .id in local_sym_tab ):
135+ var_name = attr_node .value .id
136+ field_name = attr_node .attr
137+
138+ if not local_var_metadata or var_name not in local_var_metadata :
139+ raise ValueError (
140+ f"Variable metadata for '{ var_name } ' not found in local variable metadata" )
141+
142+ var_type = local_sym_tab [var_name ][1 ]
143+ if var_type not in struct_sym_tab :
144+ raise ValueError (
145+ f"Struct type '{ var_type } ' for variable '{ var_name } ' not found in struct symbol table" )
146+
147+ struct_info = struct_sym_tab [var_type ]
148+ if field_name not in struct_info .fields :
149+ raise ValueError (
150+ f"Field '{ field_name } ' not found in struct '{ var_type } '" )
151+
152+ field_type = struct_info .field_type (field_name )
153+ _populate_fval (field_type , attr_node , fmt_parts , exprs )
154+ else :
155+ raise NotImplementedError (
156+ "Only simple attribute access on local variables is supported in f-strings." )
157+
158+
159+ def _populate_fval (ftype , node , fmt_parts , exprs ):
160+ """Populate format parts and expressions based on field type."""
161+ if isinstance (ftype , ir .IntType ):
162+ # TODO: We print as signed integers only for now
163+ if ftype .width == 64 :
164+ fmt_parts .append ("%lld" )
165+ exprs .append (node )
166+ elif ftype .width == 32 :
167+ fmt_parts .append ("%d" )
168+ exprs .append (node )
169+ else :
170+ raise NotImplementedError (
171+ f"Unsupported integer width in f-string: { ftype .width } " )
172+ elif ftype == ir .PointerType (ir .IntType (8 )):
173+ # NOTE: We assume i8* is a string
174+ fmt_parts .append ("%s" )
175+ exprs .append (node )
176+ else :
177+ raise NotImplementedError (
178+ f"Unsupported field type in f-string: { ftype } " )
0 commit comments