@@ -397,15 +397,28 @@ public Node declareIdentifier(ByteList byteName) {
397397 node = new LocalVarNode (lexer .tokline , slot , name );
398398 } else if (dyna_in_block () && id .equals ("it" )) {
399399 if (!hasArguments ()) {
400- int existing = currentScope .isDefined (id );
401- slot = existing == -1 ?
402- currentScope .addVariable (id ) : existing ;
400+ int existing = currentScope .isDefinedNotImplicit (id );
401+ boolean newIt = false ;
402+
403+ if (existing == -1 ) {
404+ slot = currentScope .addVariable (id );
405+ newIt = true ;
406+ } else if (existing == -2 ) { // We found an it either in this scope or above it
407+ if (it_id () != null ) { // It is the current scope
408+ slot = currentScope .isDefined (id ); // Get location of it
409+ } else {
410+ slot = currentScope .addVariable (id ); // Was above this scope so make one for it.
411+ newIt = true ;
412+ }
413+ } else {
414+ slot = existing ;
415+ }
403416 node = new DVarNode (lexer .tokline , slot , name );
404- if (existing == - 1 ) set_it_id (node );
417+ if (newIt ) set_it_id (node );
405418 } else {
406- slot = currentScope .isDefined (id );
419+ slot = currentScope .isDefinedNotImplicit (id );
407420 // A special it cannot exist without being marked as a special it.
408- if (it_id () == null && slot == - 1 ) compile_error ("`it` is not allowed when an ordinary parameter is defined" );
421+ if (it_id () != null ) compile_error ("`it` is not allowed when an ordinary parameter is defined" );
409422
410423 node = currentScope .declare (lexer .tokline , name );
411424 }
@@ -431,6 +444,16 @@ public AssignableNode assignableLabelOrIdentifier(ByteList byteName, Node value)
431444
432445 if (warnOnUnusedVariables ) addOrMarkVariable (name , currentScope .isDefined (name .idString ()));
433446
447+ String id = name .idString ();
448+ // This differs from MRI annd it is a special branch because I do not want to infect staticscope with 'it'
449+ // logic since it likely will be done differently in Prism (This will play out more once 10.1 updates
450+ // to latest Prism). If it is the same then we can reconsider whether this should be in staticscope or not.
451+ if (id .equals ("it" ) && currentScope .exists (id ) == -1 ) { // case: foo { it.bar { <<it = something>> } it }
452+ // we are assigning and there is no 'it' here so make it as a normal local
453+ int slot = currentScope .addVariableName (id );
454+ return new DAsgnNode (lexer .getRubySourceline (), name , slot , value );
455+ }
456+
434457 return currentScope .assign (lexer .getRubySourceline (), name , makeNullNil (value ));
435458 }
436459
0 commit comments