Skip to content

Commit a1011ab

Browse files
committed
Merge branch 'master' into 3.6
2 parents 6e10774 + 5444c39 commit a1011ab

18 files changed

Lines changed: 466 additions & 83 deletions

Src/IronPython/Compiler/Ast/AstMethods.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ internal static class AstMethods {
7272
public static readonly MethodInfo MakeSet = GetMethod((Func<object[], SetCollection>)PythonOps.MakeSet);
7373
public static readonly MethodInfo MakeEmptySet = GetMethod((Func<SetCollection>)PythonOps.MakeEmptySet);
7474
public static readonly MethodInfo MakeHomogeneousDictFromItems = GetMethod((Func<object[], PythonDictionary>)PythonOps.MakeHomogeneousDictFromItems);
75-
public static readonly MethodInfo CreateLocalContext = GetMethod((Func<CodeContext, MutableTuple, string[], CodeContext>)PythonOps.CreateLocalContext);
75+
public static readonly MethodInfo CreateLocalContext = GetMethod((Func<CodeContext, MutableTuple, string[], int, int, bool, CodeContext>)PythonOps.CreateLocalContext);
7676
public static readonly MethodInfo UpdateStackTrace = GetMethod((Action<Exception, CodeContext, FunctionCode, int>)PythonOps.UpdateStackTrace);
7777
public static readonly MethodInfo ForLoopDispose = GetMethod((Action<KeyValuePair<IEnumerator, IDisposable>>)PythonOps.ForLoopDispose);
7878
public static readonly MethodInfo GetClosureTupleFromContext = GetMethod((Func<CodeContext, MutableTuple>)PythonOps.GetClosureTupleFromContext);

Src/IronPython/Compiler/Ast/CallExpression.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ namespace IronPython.Compiler.Ast {
2424
public class CallExpression : Expression, IInstructionProvider {
2525
private readonly Expression[] _args;
2626
private readonly Keyword[] _kwargs;
27-
private Expression[]? _implicitArgs;
2827

2928
public CallExpression(Expression target, IReadOnlyList<Expression>? args, IReadOnlyList<Keyword>? kwargs) {
3029
Target = target;
@@ -38,10 +37,6 @@ public CallExpression(Expression target, IReadOnlyList<Expression>? args, IReadO
3837

3938
public IReadOnlyList<Keyword> Kwargs => _kwargs;
4039

41-
internal void SetImplicitArgs(params Expression[] args) {
42-
_implicitArgs = args;
43-
}
44-
4540
public bool NeedsLocalsDictionary() {
4641
if (!(Target is NameExpression nameExpr)) return false;
4742

@@ -61,10 +56,6 @@ public override MSAst.Expression Reduce() {
6156
ReadOnlySpan<Expression> args = _args;
6257
ReadOnlySpan<Keyword> kwargs = _kwargs;
6358

64-
if (args.Length == 0 && _implicitArgs != null) {
65-
args = _implicitArgs;
66-
}
67-
6859
// count splatted list args and find the lowest index of a list argument, if any
6960
ScanArgs(args, out var numList, out int firstListPos);
7061
Debug.Assert(numList == 0 || firstListPos < args.Length);
@@ -188,9 +179,6 @@ static MSAst.Expression UnpackDictHelper(MSAst.Expression context, ReadOnlySpan<
188179

189180
void IInstructionProvider.AddInstructions(LightCompiler compiler) {
190181
ReadOnlySpan<Expression> args = _args;
191-
if (args.Length == 0 && _implicitArgs != null) {
192-
args = _implicitArgs;
193-
}
194182

195183
if (Kwargs.Count > 0) {
196184
compiler.Compile(Reduce());
@@ -430,11 +418,6 @@ public override int Run(InterpretedFrame frame) {
430418
public override void Walk(PythonWalker walker) {
431419
if (walker.Walk(this)) {
432420
Target?.Walk(walker);
433-
if (_implicitArgs is not null) {
434-
foreach (var arg in _implicitArgs) {
435-
arg.Walk(walker);
436-
}
437-
}
438421
foreach (var arg in _args) {
439422
arg.Walk(walker);
440423
}

Src/IronPython/Compiler/Ast/ClassDefinition.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public class ClassDefinition : ScopeStatement {
3535

3636
private static int _classId;
3737

38-
private static readonly MSAst.ParameterExpression _parentContextParam = Ast.Parameter(typeof(CodeContext), "$parentContext");
39-
private static readonly MSAst.Expression _tupleExpression = MSAst.Expression.Call(AstMethods.GetClosureTupleFromContext, _parentContextParam);
38+
private static readonly MSAst.ParameterExpression _outerContextParam = Ast.Parameter(typeof(CodeContext), "$outerContext");
39+
private static readonly MSAst.Expression _tupleExpression = MSAst.Expression.Call(AstMethods.GetClosureTupleFromContext, _outerContextParam);
4040

4141
public ClassDefinition(string name, IReadOnlyList<Expression>? bases, IReadOnlyList<Keyword>? keywords, Statement? body = null) {
4242
_name = name;
@@ -128,6 +128,7 @@ internal override bool TryBindOuter(ScopeStatement from, PythonReference referen
128128
if (TryGetVariable(reference.Name, out variable)) {
129129
if (variable.Kind is VariableKind.Global) {
130130
AddReferencedGlobal(reference.Name);
131+
return variable;
131132
} else if (variable.Kind is VariableKind.Local) {
132133
// TODO: This results in doing a dictionary lookup to get/set the local,
133134
// when it should probably be an uninitialized check / global lookup for gets
@@ -271,13 +272,13 @@ private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>>
271272
locals.Add(LocalCodeContextVariable);
272273
locals.Add(PythonAst._globalContext);
273274

274-
init.Add(Ast.Assign(PythonAst._globalContext, new GetGlobalContextExpression(_parentContextParam)));
275+
init.Add(Ast.Assign(PythonAst._globalContext, new GetGlobalContextExpression(_outerContextParam)));
275276

276277
GlobalParent.PrepareScope(locals, init);
277278

278279
CreateVariables(locals, init);
279280

280-
var createLocal = CreateLocalContext(_parentContextParam);
281+
var createLocal = CreateLocalContext(_outerContextParam, newNamespace: false);
281282

282283
init.Add(Ast.Assign(LocalCodeContextVariable, createLocal));
283284

@@ -327,7 +328,7 @@ private Microsoft.Scripting.Ast.LightExpression<Func<CodeContext, CodeContext>>
327328
bodyStmt
328329
),
329330
Name + "$" + Interlocked.Increment(ref _classId),
330-
new[] { _parentContextParam }
331+
new[] { _outerContextParam }
331332
);
332333

333334
return lambda;

Src/IronPython/Compiler/Ast/FunctionDefinition.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,10 @@ internal override int KwOnlyArgCount {
145145
internal PythonVariable PythonVariable { get; set; }
146146

147147
internal override bool ExposesLocalVariable(PythonVariable variable) {
148-
return NeedsLocalsDictionary;
148+
return NeedsLocalsDictionary
149+
|| (ContainsSuperCall && variable.Kind is VariableKind.Parameter
150+
&& _parameters is not null && _parameters.Length > 0
151+
&& _parameters[0].PythonVariable == variable);
149152
}
150153

151154
internal override FunctionAttributes Flags {
@@ -258,7 +261,7 @@ internal override void Bind(PythonNameBinder binder) {
258261

259262
internal override void FinishBind(PythonNameBinder binder) {
260263
foreach (var param in _parameters) {
261-
_variableMapping[param.PythonVariable] = param.FinishBind(NeedsLocalsDictionary);
264+
_variableMapping[param.PythonVariable] = param.FinishBind(forceClosureCell: ExposesLocalVariable(param.PythonVariable));
262265
}
263266
base.FinishBind(binder);
264267
}

Src/IronPython/Compiler/Ast/Parameter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ public Expression DefaultValue {
6060

6161
internal PythonVariable PythonVariable { get; set; }
6262

63-
internal MSAst.Expression FinishBind(bool needsLocalsDictionary) {
64-
if (PythonVariable.AccessedInNestedScope || needsLocalsDictionary) {
63+
internal MSAst.Expression FinishBind(bool forceClosureCell) {
64+
if (PythonVariable.AccessedInNestedScope || forceClosureCell) {
6565
ParameterExpression = Expression.Parameter(typeof(object), Name);
6666
var cell = Ast.Parameter(typeof(ClosureCell), Name);
6767
return new ClosureExpression(PythonVariable, cell, ParameterExpression);

Src/IronPython/Compiler/Ast/PythonNameBinder.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -851,13 +851,13 @@ public override bool Walk(ComprehensionFor node) {
851851
public override bool Walk(CallExpression node) {
852852
node.Parent = _currentScope;
853853

854-
if (node.Target is NameExpression nameExpr && nameExpr.Name == "super" && _currentScope is FunctionDefinition func) {
855-
_currentScope.Reference("__class__");
856-
if (node.Args.Count == 0 && node.Kwargs.Count == 0 && func.ParameterNames.Length > 0) {
857-
node.SetImplicitArgs(new NameExpression("__class__"), new NameExpression(func.ParameterNames[0]));
858-
}
854+
if (node.Target is NameExpression nameExpr && nameExpr.Name == "super"
855+
&& _currentScope is not ClassDefinition
856+
&& node.Args.Count == 0 && node.Kwargs.Count == 0) {
857+
858+
_currentScope.ContainsSuperCall = true;
859859
}
860-
return base.Walk(node);
860+
return true;
861861
}
862862

863863
#endregion

Src/IronPython/Compiler/Ast/PythonReference.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
6+
57
namespace IronPython.Compiler.Ast {
68
/// <summary>
79
/// Represents a reference to a name. A PythonReference is created for each name
@@ -14,6 +16,6 @@ public PythonReference(string name) {
1416

1517
public string Name { get; }
1618

17-
internal PythonVariable PythonVariable { get; set; }
19+
internal PythonVariable? PythonVariable { get; set; }
1820
}
1921
}

Src/IronPython/Compiler/Ast/ScopeStatement.cs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Src/IronPython/Runtime/CommonDictionaryStorage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ internal class CommonDictionaryStorage : DictionaryStorage, ISerializable, IDese
6767
public CommonDictionaryStorage() { }
6868

6969
/// <summary>
70-
/// Creates a new dictionary storage with no buckets
70+
/// Creates a new dictionary storage with buckets
7171
/// </summary>
7272
public CommonDictionaryStorage(int count) {
7373
_buckets = new Bucket[(int)(count / Load + 2)];

Src/IronPython/Runtime/CustomDictionaryStorage.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,17 @@
1111

1212
namespace IronPython.Runtime {
1313
internal abstract class CustomDictionaryStorage : DictionaryStorage {
14-
private readonly CommonDictionaryStorage/*!*/ _storage = new CommonDictionaryStorage();
14+
private readonly CommonDictionaryStorage/*!*/ _storage;
15+
16+
public CustomDictionaryStorage() {
17+
_storage = new();
18+
}
19+
20+
protected CustomDictionaryStorage(CommonDictionaryStorage storage) {
21+
_storage = storage;
22+
}
23+
24+
public CommonDictionaryStorage Storage => _storage;
1525

1626
public override void Add(ref DictionaryStorage storage, object key, object value) {
1727
Add(key, value);

0 commit comments

Comments
 (0)