Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request microsoft#339 from MikhailArkhipov/15-2
Browse files Browse the repository at this point in the history
Handle named tuples
  • Loading branch information
Mikhail Arkhipov authored Nov 5, 2018
2 parents cc4700d + cb0be90 commit 62f76e1
Show file tree
Hide file tree
Showing 48 changed files with 1,095 additions and 897 deletions.
28 changes: 7 additions & 21 deletions src/Analysis/Engine/Impl/AnalysisValueSetExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,8 @@ public static IAnalysisSet Call(this IAnalysisSet self, Node node, AnalysisUnit
foreach (var ns in self) {
var call = ns.Call(node, unit, args, keywordArgNames);
Debug.Assert(call != null);

res = res.Union(call);
}

return res;
}

Expand All @@ -95,7 +93,6 @@ public static IAnalysisSet GetIterator(this IAnalysisSet self, Node node, Analys
foreach (var ns in self) {
res = res.Union(ns.GetIterator(node, unit));
}

return res;
}

Expand All @@ -109,7 +106,6 @@ public static IAnalysisSet GetAsyncIterator(this IAnalysisSet self, Node node, A
foreach (var ns in self) {
res = res.Union(ns.GetAsyncIterator(node, unit));
}

return res;
}

Expand All @@ -122,7 +118,6 @@ public static IAnalysisSet GetIndex(this IAnalysisSet self, Node node, AnalysisU
foreach (var ns in self) {
res = res.Union(ns.GetIndex(node, unit, index));
}

return res;
}

Expand All @@ -140,8 +135,7 @@ public static void SetIndex(this IAnalysisSet self, Node node, AnalysisUnit unit
/// Performs a delete index operation propagating the index types into
/// the provided object.
/// </summary>
public static void DeleteIndex(this IAnalysisSet self, Node node, AnalysisUnit unit, IAnalysisSet index) {
}
public static void DeleteIndex(this IAnalysisSet self, Node node, AnalysisUnit unit, IAnalysisSet index) { }

/// <summary>
/// Performs an augmented assignment propagating the value into the
Expand All @@ -163,7 +157,6 @@ public static IAnalysisSet GetEnumeratorTypes(this IAnalysisSet self, Node node,
foreach (var ns in self) {
res = res.Union(ns.GetEnumeratorTypes(node, unit));
}

return res;
}
/// <summary>
Expand All @@ -176,7 +169,6 @@ public static IAnalysisSet GetAsyncEnumeratorTypes(this IAnalysisSet self, Node
foreach (var ns in self) {
res = res.Union(ns.GetAsyncEnumeratorTypes(node, unit));
}

return res;
}

Expand All @@ -188,7 +180,6 @@ public static IAnalysisSet GetDescriptor(this IAnalysisSet self, Node node, Anal
foreach (var ns in self) {
res = res.Union(ns.GetDescriptor(node, instance, context, unit));
}

return res;
}

Expand All @@ -200,7 +191,6 @@ public static IAnalysisSet BinaryOperation(this IAnalysisSet self, Node node, An
foreach (var ns in self) {
res = res.Union(ns.BinaryOperation(node, unit, operation, rhs));
}

return res;
}

Expand All @@ -212,7 +202,6 @@ public static IAnalysisSet UnaryOperation(this IAnalysisSet self, Node node, Ana
foreach (var ns in self) {
res = res.Union(ns.UnaryOperation(node, unit, operation));
}

return res;
}

Expand All @@ -228,9 +217,8 @@ internal static AnalysisValue GetUnionType(this IAnalysisSet types) {
/// <summary>
/// Gets instance representations of all members of the set.
/// </summary>
public static IAnalysisSet GetInstanceType(this IAnalysisSet types) {
return AnalysisSet.Create(types.SelectMany(ns => ns.GetInstanceType()));
}
public static IAnalysisSet GetInstanceType(this IAnalysisSet types)
=> AnalysisSet.Create(types.SelectMany(ns => (ns.PythonType as IPythonType2)?.IsClass == true ? ns : ns.GetInstanceType()));

public static bool IsUnknown(this IAnalysisSet res) {
return res == null ||
Expand All @@ -241,17 +229,15 @@ public static bool IsUnknown(this IAnalysisSet res) {
/// <summary>
/// Returns true if the set contains no or only the object or unknown types
/// </summary>
public static bool IsObjectOrUnknown(this IAnalysisSet res) {
return res.IsUnknown() || res.All(v => v.TypeId == BuiltinTypeId.Object);
}
public static bool IsObjectOrUnknown(this IAnalysisSet res)
=> res.IsUnknown() || res.All(v => v.TypeId == BuiltinTypeId.Object);

/// <summary>
/// Returns true if the set contains no types, only the object or unknown
/// types, or None.
/// </summary>
public static bool IsObjectOrUnknownOrNone(this IAnalysisSet res) {
return res.IsObjectOrUnknown() || res.All(v => v.TypeId == BuiltinTypeId.NoneType);
}
public static bool IsObjectOrUnknownOrNone(this IAnalysisSet res)
=> res.IsObjectOrUnknown() || res.All(v => v.TypeId == BuiltinTypeId.NoneType);

/// <summary>
/// Returns a sequence of all recognized string values in the set.
Expand Down
2 changes: 1 addition & 1 deletion src/Analysis/Engine/Impl/Analyzer/ExpressionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ internal void AssignTo(Node assignStmt, Expression left, IAnalysisSet values) {
// list/tuple
var l = (SequenceExpression)left;
var valuesArr = values.ToArray();
for (int i = 0; i < l.Items.Count; i++) {
for (var i = 0; i < l.Items.Count; i++) {
if (valuesArr.Length > 0) {
foreach (var value in valuesArr) {
AssignTo(assignStmt, l.Items[i], value.GetIndex(assignStmt, _unit, ProjectState.GetConstant(i)));
Expand Down
3 changes: 1 addition & 2 deletions src/Analysis/Engine/Impl/Analyzer/FunctionAnalysisUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.PythonTools.Analysis.Infrastructure;
Expand Down
110 changes: 0 additions & 110 deletions src/Analysis/Engine/Impl/Interpreter/AnalysisOnlyInterpreterFactory.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.PythonTools.Analysis.Infrastructure;
using Microsoft.PythonTools.Parsing.Ast;

namespace Microsoft.PythonTools.Interpreter.Ast {
[DebuggerDisplay("{Target.Name}")]
class AstAnalysisFunctionWalker : PythonWalker {
private readonly FunctionDefinition _target;
private readonly NameLookupContext _scope;
private readonly AstPythonFunctionOverload _overload;
private AstPythonType _selfType;
Expand All @@ -33,12 +34,11 @@ public AstAnalysisFunctionWalker(
AstPythonFunctionOverload overload
) {
_scope = scope ?? throw new ArgumentNullException(nameof(scope));
_target = targetFunction ?? throw new ArgumentNullException(nameof(targetFunction));
Target = targetFunction ?? throw new ArgumentNullException(nameof(targetFunction));
_overload = overload ?? throw new ArgumentNullException(nameof(overload));
}

public IList<IPythonType> ReturnTypes => _overload.ReturnTypes;
public IPythonFunctionOverload Overload => _overload;
public FunctionDefinition Target { get; }

private void GetMethodType(FunctionDefinition node, out bool classmethod, out bool staticmethod) {
classmethod = false;
Expand All @@ -51,7 +51,7 @@ private void GetMethodType(FunctionDefinition node, out bool classmethod, out bo

var classmethodObj = _scope.Interpreter.GetBuiltinType(BuiltinTypeId.ClassMethod);
var staticmethodObj = _scope.Interpreter.GetBuiltinType(BuiltinTypeId.StaticMethod);
foreach (var d in (_target.Decorators?.Decorators).MaybeEnumerate().ExcludeDefault()) {
foreach (var d in (Target.Decorators?.Decorators).MaybeEnumerate().ExcludeDefault()) {
var m = _scope.GetValueFromExpression(d);
if (m == classmethodObj) {
classmethod = true;
Expand All @@ -65,21 +65,31 @@ public void Walk() {
var self = GetSelf();
_selfType = (self as AstPythonConstant)?.Type as AstPythonType;

_overload.ReturnTypes.AddRange(_scope.GetTypesFromAnnotation(_target.ReturnAnnotation).ExcludeDefault());

_overload.ReturnTypes.AddRange(_scope.GetTypesFromAnnotation(Target.ReturnAnnotation).ExcludeDefault());
_scope.PushScope();

// Declare self, if any
var skip = 0;
if (self != null) {
var p0 = _target.Parameters.FirstOrDefault();
var p0 = Target.Parameters.FirstOrDefault();
if (p0 != null && !string.IsNullOrEmpty(p0.Name)) {
_scope.SetInScope(p0.Name, self);
skip++;
}
}
_target.Walk(this);

// Declare parameters in scope
foreach(var p in Target.Parameters.Skip(skip).Where(p => !string.IsNullOrEmpty(p.Name))) {
var value = _scope.GetValueFromExpression(p.DefaultValue);
_scope.SetInScope(p.Name, value ?? _scope.UnknownType);
}

Target.Walk(this);
_scope.PopScope();
}

public override bool Walk(FunctionDefinition node) {
if (node != _target) {
if (node != Target) {
// Do not walk nested functions (yet)
return false;
}
Expand Down Expand Up @@ -163,19 +173,28 @@ public override bool Walk(IfStatement node) {
}

public override bool Walk(ReturnStatement node) {
foreach (var type in _scope.GetTypesFromValue(_scope.GetValueFromExpression(node.Expression)).ExcludeDefault()) {
var types = _scope.GetTypesFromValue(_scope.GetValueFromExpression(node.Expression)).ExcludeDefault();
foreach (var type in types) {
_overload.ReturnTypes.Add(type);
}

// Clean up: if there are None or Unknown types along with real ones, remove them.
var realTypes = _overload.ReturnTypes
.Where(t => t.TypeId != BuiltinTypeId.Unknown && t.TypeId != BuiltinTypeId.NoneType)
.ToList();

if (realTypes.Count > 0) {
_overload.ReturnTypes.Clear();
_overload.ReturnTypes.AddRange(realTypes);
}
return true; // We want to evaluate all code so all private variables in __new__ get defined
}

private IMember GetSelf() {
bool classmethod, staticmethod;
GetMethodType(_target, out classmethod, out staticmethod);
GetMethodType(Target, out var classmethod, out var staticmethod);
var self = _scope.LookupNameInScopes("__class__", NameLookupContext.LookupOptions.Local);
if (!staticmethod && !classmethod) {
var cls = self as IPythonType;
if (cls == null) {
if (!(self is IPythonType cls)) {
self = null;
} else {
self = new AstPythonConstant(cls, ((cls as ILocatedMember)?.Locations).MaybeEnumerate().ToArray());
Expand Down
Loading

0 comments on commit 62f76e1

Please sign in to comment.