public void EvaluateClass() { // Open class scope chain using (Eval.OpenScope(Module, _classDef, out var outerScope)) { var instance = Eval.GetInScope(_classDef.Name, outerScope); if (!(instance?.GetPythonType() is PythonClassType classInfo)) { if (instance != null) { // TODO: warning that variable is already declared of a different type. } return; } // Evaluate inner classes, if any EvaluateInnerClasses(_classDef); _class = classInfo; var bases = ProcessBases(); _class.SetBases(bases, Eval.CurrentScope); _class.DecideGeneric(); // Declare __class__ variable in the scope. Eval.DeclareVariable("__class__", _class, VariableSource.Declaration); ProcessClassBody(); } }
private bool IsValidAssignment(string name, Location loc) { if (Eval.GetInScope(name) is ILocatedMember m) { // Class and function definition are processed first, so only override // if assignment happens after declaration if (loc.IndexSpan.Start < m.Location.IndexSpan.Start) { return(false); } } return(true); }
private void AssignImportedVariables(IPythonModule module, DottedName moduleImportExpression, NameExpression asNameExpression) { // "import fob.oar as baz" is handled as // baz = import_module('fob.oar') if (asNameExpression != null) { Eval.DeclareVariable(asNameExpression.Name, module, asNameExpression); return; } // "import fob.oar" is handled as // import_module('fob.oar') // fob = import_module('fob') var importNames = moduleImportExpression.Names; PythonPackage pythonPackage = null; var existingDepth = 0; var childPackage = Eval.GetInScope <PythonPackage>(importNames[0].Name); while (childPackage != null && existingDepth < importNames.Count - 1) { existingDepth++; pythonPackage = childPackage; childPackage = pythonPackage.GetMember <PythonPackage>(importNames[existingDepth].Name); } var child = module; for (var i = importNames.Count - 2; i >= existingDepth; i--) { var childName = importNames[i + 1].Name; var parentName = importNames[i].Name; var parent = new PythonPackage(parentName, Eval.Services); parent.AddChildModule(childName, child); child = parent; } if (pythonPackage == null) { Eval.DeclareVariable(importNames[0].Name, child, importNames[0]); } else { pythonPackage.AddChildModule(importNames[existingDepth].Name, child); } }
public async Task EvaluateClassAsync(CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); // Open class scope chain using (Eval.OpenScope(_classDef, out var outerScope)) { var instance = Eval.GetInScope(_classDef.Name, outerScope); if (!(instance?.GetPythonType() is PythonClassType classInfo)) { if (instance != null) { // TODO: warning that variable is already declared of a different type. } // May be odd case like class inside a class. return; } // Evaluate inner classes, if any await EvaluateInnerClassesAsync(_classDef, cancellationToken); _class = classInfo; // Set bases to the class. var bases = new List <IPythonType>(); foreach (var a in _classDef.Bases.Where(a => string.IsNullOrEmpty(a.Name))) { // We cheat slightly and treat base classes as annotations. var b = await Eval.GetTypeFromAnnotationAsync(a.Expression, cancellationToken); if (b != null) { bases.Add(b.GetPythonType()); } } _class.SetBases(Interpreter, bases); // Declare __class__ variable in the scope. Eval.DeclareVariable("__class__", _class, _classDef); await ProcessClassBody(cancellationToken); } }
public override bool Walk(PythonAst node) { Check.InvalidOperation(() => Ast == node, "walking wrong AST"); _cancellationToken.ThrowIfCancellationRequested(); // Collect basic information about classes and functions in order // to correctly process forward references. Does not determine // types yet since at this time imports or generic definitions // have not been processed. SymbolTable.Build(Eval); // There are cases (see typeshed datetime stub) with constructs // class A: // def __init__(self, x: Optional[B]): ... // // _A = A // // class B: // def func(self, x: Optional[_A]) // // so evaluation of A -> B ends up incomplete since _A is not known yet. // Thus, when A type is created, we need to go and evaluate all assignments // that might be referring to it in the right hand side. if (Ast.Body is SuiteStatement ste) { foreach (var statement in ste.Statements.OfType <AssignmentStatement>()) { if (statement.Left.Count == 1 && statement.Left[0] is NameExpression leftNex && statement.Right is NameExpression rightNex) { var m = Eval.GetInScope <IPythonClassType>(rightNex.Name); if (m != null) { Eval.DeclareVariable(leftNex.Name, m, VariableSource.Declaration, leftNex); } } } } return(base.Walk(node)); }
public void EvaluateClass() { // Open class scope chain using (Eval.OpenScope(Module, _classDef, out var outerScope)) { var instance = Eval.GetInScope(_classDef.Name, outerScope); if (!(instance?.GetPythonType() is PythonClassType classInfo)) { if (instance != null) { // TODO: warning that variable is already declared of a different type. } return; } // Evaluate inner classes, if any EvaluateInnerClasses(_classDef); _class = classInfo; // Set bases to the class. var bases = new List <IPythonType>(); foreach (var a in _classDef.Bases.Where(a => string.IsNullOrEmpty(a.Name))) { // We cheat slightly and treat base classes as annotations. var b = Eval.GetTypeFromAnnotation(a.Expression); if (b != null) { var t = b.GetPythonType(); bases.Add(t); t.AddReference(Eval.GetLocationOfName(a.Expression)); } } _class.SetBases(bases); // Declare __class__ variable in the scope. Eval.DeclareVariable("__class__", _class, VariableSource.Declaration); ProcessClassBody(); } }
private bool IsValidAssignment(string name, Location loc) => !Eval.GetInScope(name).IsDeclaredAfter(loc);