OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 class CallFrame implements CallingContext { | |
6 CallFrame enclosingFrame; | |
7 | |
8 MethodAnalyzer analyzer; | |
9 | |
10 MemberSet findMembers(String name) => library._findMembers(name); | |
11 CounterLog get counters() => world.counters; | |
12 Library get library() => method.library; | |
13 MethodMember method; | |
14 | |
15 bool get needsCode() => false; | |
16 bool get showWarnings() => true; | |
17 | |
18 // TODO(jimhug): Shouldn't need these 5 methods below. | |
19 String _makeThisCode() => null; | |
20 | |
21 Value getTemp(Value value) => null; | |
22 VariableValue forceTemp(Value value) => null; | |
23 Value assignTemp(Value tmp, Value v) => null; | |
24 void freeTemp(VariableValue value) => null; | |
25 | |
26 bool get isStatic() => | |
27 enclosingFrame != null ? enclosingFrame.isStatic : method.isStatic; | |
28 | |
29 Value thisValue; | |
30 Arguments args; | |
31 | |
32 List<VariableSlot> _slots; | |
33 VariableSlot _returnSlot; | |
34 | |
35 AnalyzeScope _scope; | |
36 | |
37 | |
38 CallFrame(this.analyzer, this.method, this.thisValue, this.args, | |
39 this.enclosingFrame) { | |
40 _slots = []; | |
41 _scope = new AnalyzeScope(null, this, analyzer.body); | |
42 | |
43 _returnSlot = new VariableSlot(_scope, 'return', method.returnType, | |
44 analyzer.body, false); | |
45 | |
46 } | |
47 | |
48 void pushBlock(Node node) { | |
49 _scope = new AnalyzeScope(_scope, this, node); | |
50 } | |
51 | |
52 void popBlock(Node node) { | |
53 if (_scope.node != node) { | |
54 world.internalError('incorrect pop', node.span, _scope.node.span); | |
55 } | |
56 _scope = _scope.parent; | |
57 } | |
58 | |
59 Value getReturnValue() { | |
60 return _returnSlot.get(null); | |
61 } | |
62 | |
63 void returns(Value value) { | |
64 _returnSlot.set(value); | |
65 } | |
66 | |
67 VariableSlot lookup(String name) { | |
68 var slot = _scope._lookup(name); | |
69 if (slot == null && enclosingFrame != null) { | |
70 return enclosingFrame.lookup(name); | |
71 } | |
72 return slot; | |
73 } | |
74 | |
75 VariableSlot create(String name, Type staticType, Node node, bool isFinal, | |
76 Value value) { | |
77 // TODO(jimhug): Save mapping from node -> Slot. | |
78 | |
79 final slot = new VariableSlot(_scope, name, staticType, node, isFinal, | |
80 value); | |
81 final existingSlot = _scope._lookup(name); | |
82 if (existingSlot !== null) { | |
83 if (existingSlot.scope == this) { | |
84 world.error('duplicate name "$name"', node.span); | |
85 } else { | |
86 // TODO(jimhug): Confirm that we can enable this useful warning. | |
87 //world.warning('"$name" shadows variable from enclosing scope', | |
88 // node.span); | |
89 } | |
90 } | |
91 _slots.add(slot); | |
92 _scope._slots.add(slot); | |
93 } | |
94 | |
95 VariableSlot declareParameter(Parameter p, Value value) { | |
96 return create(p.name, p.type, p.definition, false, value); | |
97 } | |
98 | |
99 _makeValue(Type type, Node node) { | |
100 return new PureStaticValue(type, node == null ? null : node.span); | |
101 } | |
102 | |
103 | |
104 Value makeSuperValue(Node node) { | |
105 return _makeValue(thisValue.type.parent, node); | |
106 } | |
107 | |
108 Value makeThisValue(Node node) { | |
109 return _makeValue(thisValue.type, node); | |
110 } | |
111 | |
112 | |
113 void dump() { | |
114 print('**********${method.declaringType.name}.${method.name}***********'); | |
115 for (var slot in _slots) { | |
116 print(slot); | |
117 } | |
118 print(_returnSlot); | |
119 } | |
120 } | |
121 | |
122 class VariableSlot { | |
123 AnalyzeScope scope; | |
124 final String name; | |
125 Type staticType; | |
126 Node node; | |
127 bool isFinal; | |
128 Value value; | |
129 | |
130 VariableSlot(this.scope, this.name, this.staticType, this.node, | |
131 this.isFinal, [this.value]) { | |
132 if (value !== null) { | |
133 value = value.convertTo(scope.frame, staticType); | |
134 } | |
135 } | |
136 | |
137 Value get(Node position) { | |
138 return scope.frame._makeValue(staticType, position); | |
139 } | |
140 | |
141 void set(Value newValue) { | |
142 if (newValue !== null) { | |
143 newValue = newValue.convertTo(scope.frame, staticType); | |
144 } | |
145 | |
146 value = Value.union(value, newValue); | |
147 } | |
148 | |
149 String toString() { | |
150 var valueString = value !== null ? ' = ${value.type.name}' : ''; | |
151 return '${this.staticType.name} ${this.name}${valueString}'; | |
152 } | |
153 } | |
154 | |
155 class AnalyzeScope { | |
156 CallFrame frame; | |
157 AnalyzeScope parent; | |
158 | |
159 /** Tracks the node that this scope is associated with, for debugging */ | |
160 Node node; | |
161 | |
162 List<VariableSlot> _slots; | |
163 | |
164 AnalyzeScope(this.parent, this.frame, this.node): _slots = []; | |
165 | |
166 VariableSlot _lookup(String name) { | |
167 for (var s = this; s != null; s = s.parent) { | |
168 for (int i = 0; i < s._slots.length; i++) { | |
169 final ret = s._slots[i]; | |
170 if (ret.name == name) return ret; | |
171 } | |
172 } | |
173 return null; | |
174 } | |
175 } | |
OLD | NEW |