public override bool Walk(AssignmentStatement node) { var value = Eval.GetValueFromExpression(node.Right) ?? Eval.UnknownType; foreach (var lhs in node.Left) { switch (lhs) { case MemberExpression memberExp when memberExp.Target is NameExpression nameExp1: if (_function.DeclaringType.GetPythonType() is PythonClassType t && nameExp1.Name == "self") { t.AddMembers(new[] { new KeyValuePair <string, IMember>(memberExp.Name, value) }, false); } continue; case NameExpression nameExp2 when nameExp2.Name == "self": // Only assign to 'self' if it is not declared yet. if (Eval.LookupNameInScopes(nameExp2.Name, out _) == null) { Eval.DeclareVariable(nameExp2.Name, value, VariableSource.Declaration); } return(true); } } return(base.Walk(node)); }
private void HandleNameExpression(NameExpression ne, IMember value) { IScope scope; if (Eval.CurrentScope.NonLocals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out scope, LookupOptions.Nonlocal); scope?.Variables[ne.Name].Assign(value, Eval.GetLocationOfName(ne)); return; } if (Eval.CurrentScope.Globals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out scope, LookupOptions.Global); scope?.Variables[ne.Name].Assign(value, Eval.GetLocationOfName(ne)); return; } var source = value.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; var location = Eval.GetLocationOfName(ne); if (IsValidAssignment(ne.Name, location)) { Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, location); } }
public override bool Walk(NonlocalStatement node) { foreach (var nex in node.Names) { var m = Eval.LookupNameInScopes(nex.Name, out _, LookupOptions.Nonlocal); if (m == null) { ReportUndefinedVariable(nex); } } return(false); }
private void HandleGlobal(GlobalStatement node) { foreach (var nex in node.Names) { var m = Eval.LookupNameInScopes(nex.Name, out _, LookupOptions.Global); if (m == null) { _diagnostics.Add(new DiagnosticsEntry( Resources.ErrorVariableNotDefinedGlobally.FormatInvariant(nex.Name), Eval.GetLocation(nex).Span, ErrorCodes.VariableNotDefinedGlobally, Severity.Warning, DiagnosticSource.Linter)); } } }
private void ExtendAll(Node location, IPythonCollection values) { Eval.LookupNameInScopes(AllVariableName, out var scope, LookupOptions.Global); if (scope == null) { return; } var all = scope.Variables[AllVariableName]?.Value as IPythonCollection; var list = PythonCollectionType.CreateConcatenatedList(Module.Interpreter, all, values); var source = list.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; Eval.DeclareVariable(AllVariableName, list, source, location); }
private void TryHandleClassVariable(MemberExpression mex, IMember value) { if (mex.Target is NameExpression nex && nex.Name == "self") { var m = Eval.LookupNameInScopes(nex.Name, out _, LookupOptions.Local); var cls = m.GetPythonType <IPythonClassType>(); if (cls != null) { using (Eval.OpenScope(Eval.Module, cls.ClassDefinition, out _)) { Eval.DeclareVariable(mex.Name, value, VariableSource.Declaration, Eval.GetLocationOfName(mex)); } } } }
public async Task HandleAnnotatedExpressionAsync(ExpressionWithAnnotation expr, IMember value, CancellationToken cancellationToken = default) { if (expr?.Annotation == null) { return; } var variableType = await Eval.GetTypeFromAnnotationAsync(expr.Annotation, cancellationToken); // If value is null, then this is a pure declaration like // x: List[str] // without a value. If value is provided, then this is // x: List[str] = [...] // Check value type for compatibility IMember instance = null; if (value != null) { var valueType = value.GetPythonType(); if (!variableType.IsUnknown() && !valueType.Equals(variableType)) { // TODO: warn incompatible value type. // TODO: verify values. Value may be list() while variable type is List[str]. // Leave it as variable type. } else { instance = value; } } instance = instance ?? variableType?.CreateInstance(variableType.Name, Eval.GetLoc(expr.Expression), ArgumentSet.Empty) ?? Eval.UnknownType; if (expr.Expression is NameExpression ne) { Eval.DeclareVariable(ne.Name, instance, expr.Expression); return; } if (expr.Expression is MemberExpression m) { // self.x : int = 42 var self = Eval.LookupNameInScopes("self", out var scope); var argType = self?.GetPythonType(); if (argType is PythonClassType cls && scope != null) { cls.AddMember(m.Name, instance, true); } } }
public bool HandleGlobal(GlobalStatement node) { foreach (var nex in node.Names) { var m = Eval.LookupNameInScopes(nex.Name, out _, out var v, LookupOptions.Global); if (m != null) { var location = Eval.GetLocationOfName(nex); Eval.CurrentScope.DeclareGlobal(nex.Name, location); v?.AddReference(location); } } return(false); }
private void TryHandleClassVariable(AssignmentStatement node, IMember value) { var mex = node.Left.OfType <MemberExpression>().FirstOrDefault(); if (!string.IsNullOrEmpty(mex?.Name) && mex.Target is NameExpression nex && nex.Name.EqualsOrdinal("self")) { var m = Eval.LookupNameInScopes(nex.Name, out _, LookupOptions.Local); var cls = m.GetPythonType <IPythonClassType>(); if (cls != null) { using (Eval.OpenScope(Eval.Module, cls.ClassDefinition, out _)) { Eval.DeclareVariable(mex.Name, value, VariableSource.Declaration, Eval.GetLocationOfName(mex)); } } } }
private void ExtendAll(Node declNode, IReadOnlyList <IMember> values) { Eval.LookupNameInScopes(AllVariableName, out var scope, LookupOptions.Normal); if (scope == null) { return; } var loc = Eval.GetLoc(declNode); var allContents = (scope.Variables[AllVariableName].Value as IPythonCollection)?.Contents; var list = PythonCollectionType.CreateConcatenatedList(Module.Interpreter, loc, allContents, values); var source = list.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; Eval.DeclareVariable(AllVariableName, list, source, loc); }
private void HandleTypedVariable(IPythonType variableType, IMember value, Expression expr) { // Check value type for compatibility IMember instance = null; if (value != null) { var valueType = value.GetPythonType(); if (!variableType.IsUnknown() && !valueType.Equals(variableType)) { // TODO: warn incompatible value type. // TODO: verify values. Value may be list() while variable type is List[str]. // Leave it as variable type. } else { instance = value; } } var args = ArgumentSet.Empty(expr, Eval); instance = instance ?? variableType?.CreateInstance(args) ?? Eval.UnknownType.CreateInstance(ArgumentSet.WithoutContext); if (expr is NameExpression ne) { Eval.DeclareVariable(ne.Name, instance, VariableSource.Declaration, ne); return; } if (expr is MemberExpression m) { // self.x : int = 42 var self = Eval.LookupNameInScopes("self", out var scope); var argType = self?.GetPythonType(); if (argType is PythonClassType cls && scope != null) { cls.AddMember(m.Name, instance, true); } } }
public void HandleAssignment(AssignmentStatement node) { if (node.Right is ErrorExpression) { return; } var value = Eval.GetValueFromExpression(node.Right) ?? Eval.UnknownType; // Check PEP hint first var valueType = Eval.GetTypeFromPepHint(node.Right); if (valueType != null) { HandleTypedVariable(valueType, value, node.Left.FirstOrDefault()); return; } if (value.IsUnknown()) { Log?.Log(TraceEventType.Verbose, $"Undefined value: {node.Right.ToCodeString(Ast).Trim()}"); } if (value?.GetPythonType().TypeId == BuiltinTypeId.Ellipsis) { value = Eval.UnknownType; } if (node.Left.FirstOrDefault() is SequenceExpression seq) { // Tuple = Tuple. Transfer values. var seqHandler = new SequenceExpressionHandler(Walker); seqHandler.HandleAssignment(seq.Items, node.Right, value); return; } // Process annotations, if any. foreach (var expr in node.Left.OfType <ExpressionWithAnnotation>()) { // x: List[str] = [...] HandleAnnotatedExpression(expr, value); } foreach (var ne in node.Left.OfType <NameExpression>()) { if (Eval.CurrentScope.NonLocals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out var scope, LookupOptions.Nonlocal); scope?.Variables[ne.Name].Assign(value, Eval.GetLocationOfName(ne)); continue; } if (Eval.CurrentScope.Globals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out var scope, LookupOptions.Global); scope?.Variables[ne.Name].Assign(value, Eval.GetLocationOfName(ne)); continue; } var source = value.IsGeneric() ? VariableSource.Generic : VariableSource.Declaration; var location = Eval.GetLocationOfName(ne); if (IsValidAssignment(ne.Name, location)) { Eval.DeclareVariable(ne.Name, value ?? Module.Interpreter.UnknownType, source, location); } } TryHandleClassVariable(node, value); }
public async Task HandleAssignmentAsync(AssignmentStatement node, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var value = await Eval.GetValueFromExpressionAsync(node.Right, cancellationToken); if (value.IsUnknown()) { Log?.Log(TraceEventType.Verbose, $"Undefined value: {node.Right.ToCodeString(Ast).Trim()}"); } if (value?.GetPythonType().TypeId == BuiltinTypeId.Ellipsis) { value = Eval.UnknownType; } if (node.Left.FirstOrDefault() is TupleExpression lhs) { // Tuple = Tuple. Transfer values. var texHandler = new TupleExpressionHandler(Walker); await texHandler.HandleTupleAssignmentAsync(lhs, node.Right, value, cancellationToken); return; } foreach (var expr in node.Left.OfType <ExpressionWithAnnotation>()) { // x: List[str] = [...] await HandleAnnotatedExpressionAsync(expr, value, cancellationToken); } foreach (var ne in node.Left.OfType <NameExpression>()) { if (Eval.CurrentScope.NonLocals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out var scope, LookupOptions.Nonlocal); if (scope != null) { scope.Variables[ne.Name].Value = value; } else { // TODO: report variable is not declared in outer scopes. } continue; } if (Eval.CurrentScope.Globals[ne.Name] != null) { Eval.LookupNameInScopes(ne.Name, out var scope, LookupOptions.Global); if (scope != null) { scope.Variables[ne.Name].Value = value; } else { // TODO: report variable is not declared in global scope. } continue; } Eval.DeclareVariable(ne.Name, value, Eval.GetLoc(ne)); } }