@@ -187,7 +187,9 @@ class Chalk::Grammar::Chalk::Rule::SubroutineDeclaration :isa(Chalk::GrammarRule
187187 if (ref ($node ) eq ' HASH' && $node -> {statements }) {
188188 my @new_stmts ;
189189 my $changed = 0;
190- for my $stmt ($node -> {statements }-> @*) {
190+ my $statements = $node -> {statements };
191+ for my $i (0 .. $# $statements ) {
192+ my $stmt = $statements -> [$i ];
191193 my $new_stmt = $self -> _replace_unbound_variables($stmt , $param_map );
192194 push @new_stmts , $new_stmt ;
193195 $changed = 1 if refaddr($new_stmt ) != refaddr($stmt );
@@ -259,6 +261,30 @@ class Chalk::Grammar::Chalk::Rule::SubroutineDeclaration :isa(Chalk::GrammarRule
259261 return $node ;
260262 }
261263
264+ # Handle Load nodes (name/value pattern)
265+ if ($op eq ' Load' && $node -> can(' name' ) && $node -> can(' value' )) {
266+ my $value = $node -> value;
267+ my $new_value = defined ($value ) ? $self -> _replace_unbound_variables($value , $param_map ) : $value ;
268+
269+ my $val_changed = defined ($value ) && defined ($new_value ) && refaddr($new_value ) != refaddr($value );
270+
271+ if ($val_changed ) {
272+ use Chalk::IR::Node::Load;
273+ # Compute inputs from the new value
274+ my $inputs = [];
275+ if (defined ($new_value ) && ref ($new_value ) && $new_value -> can(' id' )) {
276+ $inputs = [$new_value -> id];
277+ }
278+ return Chalk::IR::Node::Load-> new(
279+ inputs => $inputs ,
280+ name => $node -> name,
281+ value => $new_value ,
282+ source_info => $node -> can(' source_info' ) ? $node -> source_info : undef ,
283+ );
284+ }
285+ return $node ;
286+ }
287+
262288 # Handle unary operators (value pattern for Negate, Not, etc.)
263289 if ($node -> can(' value' ) && !$node -> can(' control' )) {
264290 my $value = $node -> value;
@@ -271,28 +297,37 @@ class Chalk::Grammar::Chalk::Rule::SubroutineDeclaration :isa(Chalk::GrammarRule
271297 }
272298 if ($changed ) {
273299 my $class = ref ($node );
300+ warn " DEBUG: Rebuilding unary node type: $class , op: " , $node -> op, " \n " if $ENV {CHALK_DEBUG };
274301 my %attrs = (value => $new_value );
275302 $attrs {source_info } = $node -> source_info if $node -> can(' source_info' );
303+ # Add inputs if the node has it (for nodes inheriting from Base)
304+ $attrs {inputs } = $node -> inputs if $node -> can(' inputs' );
276305 return $class -> new(%attrs );
277306 }
278307 return $node ;
279308 }
280309
281- # Handle Call nodes (callee + args)
310+ # Handle Call nodes (callee + args + receiver )
282311 if ($op eq ' Call' && $node -> can(' args' )) {
283312 my $call_args = $node -> args // [];
284313 my @new_args ;
285- my $changed = 0;
314+ my $args_changed = 0;
286315 for my $arg ($call_args -> @*) {
287316 my $new_arg = $self -> _replace_unbound_variables($arg , $param_map );
288317 push @new_args , $new_arg ;
289- $changed = 1 if defined ($arg ) && defined ($new_arg ) && refaddr($new_arg ) != refaddr($arg );
318+ $args_changed = 1 if defined ($arg ) && defined ($new_arg ) && refaddr($new_arg ) != refaddr($arg );
290319 }
291- if ($changed ) {
320+
321+ # Also process the receiver (for method calls)
322+ my $receiver = $node -> can(' receiver' ) ? $node -> receiver : undef ;
323+ my $new_receiver = defined ($receiver ) ? $self -> _replace_unbound_variables($receiver , $param_map ) : undef ;
324+ my $receiver_changed = defined ($receiver ) && defined ($new_receiver ) && refaddr($new_receiver ) != refaddr($receiver );
325+
326+ if ($args_changed || $receiver_changed ) {
292327 return Chalk::IR::Node::Call-> new(
293328 callee => $node -> callee,
294329 args => \@new_args ,
295- receiver => $node -> can( ' receiver ' ) ? $node -> receiver : undef ,
330+ receiver => $new_receiver ,
296331 source_info => $node -> can(' source_info' ) ? $node -> source_info : undef ,
297332 );
298333 }
@@ -313,6 +348,32 @@ class Chalk::Grammar::Chalk::Rule::SubroutineDeclaration :isa(Chalk::GrammarRule
313348 return $node ;
314349 }
315350
351+ # Handle Store nodes (for state variables with parameter references)
352+ # Store has: control (IR node), var (string), value (IR node)
353+ if ($op eq ' Store' && $node -> can(' control' ) && $node -> can(' value' )) {
354+ my $control = $node -> control;
355+ my $value = $node -> value;
356+
357+ # Recursively process both control and value
358+ my $new_control = $self -> _replace_unbound_variables($control , $param_map );
359+ my $new_value = $self -> _replace_unbound_variables($value , $param_map );
360+
361+ # Check if anything changed
362+ my $ctrl_changed = refaddr($new_control ) != refaddr($control );
363+ my $val_changed = refaddr($new_value ) != refaddr($value );
364+
365+ if ($ctrl_changed || $val_changed ) {
366+ use Chalk::IR::Node::Store;
367+ return Chalk::IR::Node::Store-> new(
368+ control => $new_control ,
369+ var => $node -> var,
370+ value => $new_value ,
371+ source_info => $node -> can(' source_info' ) ? $node -> source_info : undef ,
372+ );
373+ }
374+ return $node ;
375+ }
376+
316377 # Nodes without children or unhandled patterns - return unchanged
317378 return $node ;
318379 }
0 commit comments