forked from IronLanguages/ironpython3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPythonVariable.cs
More file actions
100 lines (78 loc) · 3.4 KB
/
PythonVariable.cs
File metadata and controls
100 lines (78 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
#nullable enable
using MSAst = System.Linq.Expressions;
using System;
using System.Diagnostics;
using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Scripting.Utils;
using IronPython.Runtime;
namespace IronPython.Compiler.Ast {
using Ast = MSAst.Expression;
[DebuggerDisplay("{Kind} {Name} from {Scope.Name}")]
public class PythonVariable {
public PythonVariable(string name, VariableKind kind, ScopeStatement/*!*/ scope) {
Assert.NotNull(scope);
Debug.Assert(kind != VariableKind.Global || scope.IsGlobal);
Debug.Assert(kind != VariableKind.Nonlocal || !scope.IsGlobal);
Name = name;
Kind = kind;
Scope = scope;
}
/// <summary>
/// The name of the variable as used in Python code.
/// </summary>
public string Name { get; }
/// <summary>
/// The original scope in which the variable is defined.
/// </summary>
public ScopeStatement Scope { get; }
public VariableKind Kind { get; private set; }
/// <summary>
/// Transform a local kind of variable in a global scope (yes, they can be created)
/// into a global kind, hence explicitly accessible to nested local scopes.
/// </summary>
internal void LiftToGlobal() {
Debug.Assert(Scope.IsGlobal);
Debug.Assert(Kind is not VariableKind.Parameter and not VariableKind.Nonlocal);
Kind = VariableKind.Global;
}
/// <summary>
/// The actual variable represented by this variable instance.
/// For reference variables this may be null if the reference is not yet resolved.
/// </summary>
public virtual PythonVariable? LimitVariable => this;
/// <summary>
/// Gets a value indicating whether the variable gets deleted by a <c>del</c> statement in any scope.
/// </summary>
internal bool MaybeDeleted { get; private set; }
/// <summary>
/// Mark the variable as argument to a del statement in some scope.
/// </summary>
internal void RegisterDeletion() => MaybeDeleted = true;
/// <summary>
/// Gets the index used for tracking in the flow checker.
/// </summary>
internal int Index { get; set; }
/// <summary>
/// True iff there is a path in the control flow graph of a single scope
/// on which the variable is used before explicitly initialized (assigned or deleted)
/// in that scope.
/// </summary>
public bool ReadBeforeInitialized { get; set; }
/// <summary>
/// True iff the variable is referred to from an inner scope.
/// </summary>
public bool AccessedInNestedScope { get; set; }
}
internal class PythonReferenceVariable : PythonVariable {
internal PythonReferenceVariable(PythonReference reference, ScopeStatement scope)
: base(reference.Name, VariableKind.Nonlocal, scope) {
Reference = reference;
}
internal PythonReference Reference { get; }
public override PythonVariable? LimitVariable => Reference.PythonVariable?.LimitVariable;
}
}