@@ -93,6 +93,13 @@ internal bool IsClosure {
9393 /// </summary>
9494 internal bool NeedsLocalsDictionary { get ; set ; }
9595
96+ /// <summary>
97+ /// True if this scope contains a parameterless call to super().
98+ ///
99+ /// It is used to ensure that the first argument is accessible through a closure cell.
100+ /// </summary>
101+ internal bool ContainsSuperCall { get ; set ; }
102+
96103 public virtual string Name {
97104 get {
98105 return "<unknown>" ;
@@ -124,7 +131,7 @@ internal virtual bool IsGlobal {
124131
125132 internal bool NeedsLocalContext {
126133 get {
127- return NeedsLocalsDictionary || ContainsNestedFreeVariables ;
134+ return NeedsLocalsDictionary || ContainsNestedFreeVariables || ContainsSuperCall ;
128135 }
129136 }
130137
@@ -350,6 +357,7 @@ internal virtual void FinishBind(PythonNameBinder binder) {
350357 Debug . Assert ( parentClosure != null ) ;
351358
352359 foreach ( var variable in FreeVariables ) {
360+ Debug . Assert ( ! HasClosureVariable ( closureVariables , variable ) ) ;
353361 for ( int i = 0 ; i < parentClosure . Length ; i ++ ) {
354362 if ( parentClosure [ i ] . Variable == variable ) {
355363 Ast prop = LocalParentTuple ;
@@ -362,22 +370,19 @@ internal virtual void FinishBind(PythonNameBinder binder) {
362370 }
363371 Debug . Assert ( _variableMapping . ContainsKey ( variable ) ) ;
364372
365- if ( closureVariables == null ) {
366- closureVariables = new List < ClosureInfo > ( ) ;
367- }
368- closureVariables . Add ( new ClosureInfo ( variable , ! ( this is ClassDefinition ) ) ) ;
373+ closureVariables ??= new List < ClosureInfo > ( ) ;
374+ closureVariables . Add ( new ClosureInfo ( variable , this is not ClassDefinition ) ) ;
369375 }
370376 }
371377
372378 if ( Variables != null ) {
373379 foreach ( PythonVariable variable in Variables . Values ) {
374- if ( ! HasClosureVariable ( closureVariables , variable ) &&
375- variable . Kind is VariableKind . Local or VariableKind . Parameter &&
380+ if ( variable . Kind is VariableKind . Local or VariableKind . Parameter &&
376381 ( variable . AccessedInNestedScope || ExposesLocalVariable ( variable ) ) ) {
377382
378- if ( closureVariables == null ) {
379- closureVariables = new List < ClosureInfo > ( ) ;
380- }
383+ Debug . Assert ( ! HasClosureVariable ( closureVariables , variable ) ) ;
384+
385+ closureVariables ??= new List < ClosureInfo > ( ) ;
381386 closureVariables . Add ( new ClosureInfo ( variable , true ) ) ;
382387 }
383388
@@ -390,7 +395,9 @@ variable.Kind is VariableKind.Local or VariableKind.Parameter &&
390395 _variableMapping [ variable ] = Ast . Parameter ( typeof ( object ) , variable . Name ) ;
391396 }
392397 } else if ( variable . Kind == VariableKind . Attribute ) {
393- _variableMapping [ variable ] = new LookupGlobalVariable ( LocalContext , variable . Name , isLocal : true ) ; // TODO: If no user-supplied dictionary is in place, optimize to use more efficient access, see CollectableCompilationMode
398+ // If no user-supplied dictionary is in place, a more efficient access is possible, see CollectableCompilationMode
399+ // However, this would probably have a negligible effect in this case.
400+ _variableMapping [ variable ] = new LookupGlobalVariable ( LocalContext , variable . Name , isLocal : true ) ;
394401 }
395402 }
396403 }
@@ -430,12 +437,12 @@ internal void AddGlobalVariable(PythonVariable variable) {
430437 }
431438
432439 internal PythonReference Reference ( string name ) {
433- if ( _references == null ) {
434- _references = new Dictionary < string , PythonReference > ( StringComparer . Ordinal ) ;
435- }
436- PythonReference reference ;
437- if ( ! _references . TryGetValue ( name , out reference ) ) {
440+ _references ??= new Dictionary < string , PythonReference > ( StringComparer . Ordinal ) ;
441+ if ( ! _references . TryGetValue ( name , out PythonReference reference ) ) {
438442 _references [ name ] = reference = new PythonReference ( name ) ;
443+ if ( name == "super" && this is not ClassDefinition ) {
444+ Reference ( "__class__" ) ;
445+ }
439446 }
440447 return reference ;
441448 }
@@ -670,16 +677,28 @@ internal MSAst.Expression FuncCodeExpr {
670677 }
671678 }
672679
673- internal MSAst . MethodCallExpression CreateLocalContext ( MSAst . Expression parentContext ) {
674- var closureVariables = _closureVariables ;
675- if ( _closureVariables == null ) {
676- closureVariables = new ClosureInfo [ 0 ] ;
680+ internal MSAst . MethodCallExpression CreateLocalContext ( MSAst . Expression parentContext , bool newNamespace = true ) {
681+ var closureVariables = _closureVariables ?? Array . Empty < ClosureInfo > ( ) ;
682+
683+ int numFreeVars = FreeVariables ? . Count ?? 0 ;
684+ int firstArgIdx = - 1 ;
685+ if ( ( NeedsLocalsDictionary || ContainsSuperCall ) && ArgCount > 0 ) {
686+ for ( int idx = numFreeVars ; idx < closureVariables . Length ; idx ++ ) {
687+ if ( closureVariables [ idx ] . Variable . Kind == VariableKind . Parameter ) {
688+ firstArgIdx = idx ;
689+ break ;
690+ }
691+ }
677692 }
693+
678694 return Ast . Call (
679695 AstMethods . CreateLocalContext ,
680696 parentContext ,
681697 MutableTuple . Create ( ArrayUtils . ConvertAll ( closureVariables , x => GetClosureCell ( x ) ) ) ,
682- Ast . Constant ( ArrayUtils . ConvertAll ( closureVariables , x => x . AccessedInScope ? x . Variable . Name : null ) )
698+ Ast . Constant ( ArrayUtils . ConvertAll ( closureVariables , x => x . AccessedInScope ? x . Variable . Name : null ) ) ,
699+ AstUtils . Constant ( numFreeVars ) ,
700+ AstUtils . Constant ( firstArgIdx ) ,
701+ AstUtils . Constant ( newNamespace )
683702 ) ;
684703 }
685704
0 commit comments