Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: pkg/analyzer/lib/src/summary/summarize_const_expr.dart

Issue 1674073002: Add UnlinkedConst.isValid and set it during summarizing. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Generate the 'isInvalid' property. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library serialization.summarize_const_expr; 5 library serialization.summarize_const_expr;
6 6
7 import 'package:analyzer/src/generated/ast.dart'; 7 import 'package:analyzer/src/generated/ast.dart';
8 import 'package:analyzer/src/generated/scanner.dart'; 8 import 'package:analyzer/src/generated/scanner.dart';
9 import 'package:analyzer/src/summary/format.dart'; 9 import 'package:analyzer/src/summary/format.dart';
10 import 'package:analyzer/src/summary/idl.dart'; 10 import 'package:analyzer/src/summary/idl.dart';
(...skipping 26 matching lines...) Expand all
37 } 37 }
38 throw new StateError('Unexpected initializer type ${node.runtimeType}'); 38 throw new StateError('Unexpected initializer type ${node.runtimeType}');
39 } 39 }
40 40
41 /** 41 /**
42 * Instances of this class keep track of intermediate state during 42 * Instances of this class keep track of intermediate state during
43 * serialization of a single constant [Expression]. 43 * serialization of a single constant [Expression].
44 */ 44 */
45 abstract class AbstractConstExprSerializer { 45 abstract class AbstractConstExprSerializer {
46 /** 46 /**
47 * See [UnlinkedConstBuilder.isInvalid].
48 */
49 bool isInvalid = false;
50
51 /**
47 * See [UnlinkedConstBuilder.operations]. 52 * See [UnlinkedConstBuilder.operations].
48 */ 53 */
49 final List<UnlinkedConstOperation> operations = <UnlinkedConstOperation>[]; 54 final List<UnlinkedConstOperation> operations = <UnlinkedConstOperation>[];
50 55
51 /** 56 /**
52 * See [UnlinkedConstBuilder.ints]. 57 * See [UnlinkedConstBuilder.ints].
53 */ 58 */
54 final List<int> ints = <int>[]; 59 final List<int> ints = <int>[];
55 60
56 /** 61 /**
(...skipping 14 matching lines...) Expand all
71 /** 76 /**
72 * Return `true` if a constructor initializer expression is being serialized 77 * Return `true` if a constructor initializer expression is being serialized
73 * and the given [name] is a constructor parameter reference. 78 * and the given [name] is a constructor parameter reference.
74 */ 79 */
75 bool isConstructorParameterName(String name); 80 bool isConstructorParameterName(String name);
76 81
77 /** 82 /**
78 * Serialize the given [expr] expression into this serializer state. 83 * Serialize the given [expr] expression into this serializer state.
79 */ 84 */
80 void serialize(Expression expr) { 85 void serialize(Expression expr) {
81 if (expr is IntegerLiteral) { 86 try {
82 _pushInt(expr.value); 87 _serialize(expr);
83 } else if (expr is DoubleLiteral) { 88 } on StateError {
84 operations.add(UnlinkedConstOperation.pushDouble); 89 isInvalid = true;
85 doubles.add(expr.value);
86 } else if (expr is BooleanLiteral) {
87 if (expr.value) {
88 operations.add(UnlinkedConstOperation.pushTrue);
89 } else {
90 operations.add(UnlinkedConstOperation.pushFalse);
91 }
92 } else if (expr is StringLiteral) {
93 _serializeString(expr);
94 } else if (expr is SymbolLiteral) {
95 strings.add(expr.components.map((token) => token.lexeme).join('.'));
96 operations.add(UnlinkedConstOperation.makeSymbol);
97 } else if (expr is NullLiteral) {
98 operations.add(UnlinkedConstOperation.pushNull);
99 } else if (expr is Identifier) {
100 if (expr is SimpleIdentifier && isConstructorParameterName(expr.name)) {
101 strings.add(expr.name);
102 operations.add(UnlinkedConstOperation.pushConstructorParameter);
103 } else {
104 references.add(serializeIdentifier(expr));
105 operations.add(UnlinkedConstOperation.pushReference);
106 }
107 } else if (expr is InstanceCreationExpression) {
108 serializeInstanceCreation(
109 serializeConstructorName(
110 expr.constructorName.type, expr.constructorName.name),
111 expr.argumentList);
112 } else if (expr is ListLiteral) {
113 _serializeListLiteral(expr);
114 } else if (expr is MapLiteral) {
115 _serializeMapLiteral(expr);
116 } else if (expr is MethodInvocation) {
117 String name = expr.methodName.name;
118 if (name != 'identical') {
119 throw new _ConstExprSerializationError(
120 'Only "identity" function invocation is allowed.');
121 }
122 if (expr.argumentList == null ||
123 expr.argumentList.arguments.length != 2) {
124 throw new _ConstExprSerializationError(
125 'The function "identity" requires exactly 2 arguments.');
126 }
127 expr.argumentList.arguments.forEach(serialize);
128 operations.add(UnlinkedConstOperation.identical);
129 } else if (expr is BinaryExpression) {
130 _serializeBinaryExpression(expr);
131 } else if (expr is ConditionalExpression) {
132 serialize(expr.condition);
133 serialize(expr.thenExpression);
134 serialize(expr.elseExpression);
135 operations.add(UnlinkedConstOperation.conditional);
136 } else if (expr is PrefixExpression) {
137 _serializePrefixExpression(expr);
138 } else if (expr is PropertyAccess) {
139 if (expr.target is! PrefixedIdentifier &&
140 expr.propertyName.name == 'length') {
141 serialize(expr.target);
142 operations.add(UnlinkedConstOperation.length);
143 } else {
144 references.add(serializePropertyAccess(expr));
145 operations.add(UnlinkedConstOperation.pushReference);
146 }
147 } else if (expr is ParenthesizedExpression) {
148 serialize(expr.expression);
149 } else {
150 throw new _ConstExprSerializationError('Unknown expression type: $expr');
151 } 90 }
152 } 91 }
153 92
154 /** 93 /**
155 * Serialize the given [annotation] into this serializer state. 94 * Serialize the given [annotation] into this serializer state.
156 */ 95 */
157 void serializeAnnotation(Annotation annotation); 96 void serializeAnnotation(Annotation annotation);
158 97
159 /** 98 /**
160 * Return [EntityRefBuilder] that corresponds to the constructor having name 99 * Return [EntityRefBuilder] that corresponds to the constructor having name
161 * [name] in the class identified by [type]. 100 * [name] in the class identified by [type].
162 */ 101 */
163 EntityRefBuilder serializeConstructorName( 102 EntityRefBuilder serializeConstructorName(
164 TypeName type, SimpleIdentifier name); 103 TypeName type, SimpleIdentifier name);
165 104
166 /** 105 /**
167 * Return [EntityRefBuilder] that corresponds to the given [identifier]. 106 * Return [EntityRefBuilder] that corresponds to the given [identifier].
168 */ 107 */
169 EntityRefBuilder serializeIdentifier(Identifier identifier); 108 EntityRefBuilder serializeIdentifier(Identifier identifier);
170 109
110 void serializeInstanceCreation(
111 EntityRefBuilder constructor, ArgumentList argumentList) {
112 List<Expression> arguments = argumentList.arguments;
113 // Serialize the arguments.
114 List<String> argumentNames = <String>[];
115 arguments.forEach((arg) {
116 if (arg is NamedExpression) {
117 argumentNames.add(arg.name.label.name);
118 _serialize(arg.expression);
119 } else {
120 _serialize(arg);
121 }
122 });
123 // Add the op-code and numbers of named and positional arguments.
124 operations.add(UnlinkedConstOperation.invokeConstructor);
125 ints.add(argumentNames.length);
126 strings.addAll(argumentNames);
127 ints.add(arguments.length - argumentNames.length);
128 // Serialize the reference.
129 references.add(constructor);
130 }
131
171 /** 132 /**
172 * Return [EntityRefBuilder] that corresponds to the given [access]. 133 * Return [EntityRefBuilder] that corresponds to the given [access].
173 */ 134 */
174 EntityRefBuilder serializePropertyAccess(PropertyAccess access); 135 EntityRefBuilder serializePropertyAccess(PropertyAccess access);
175 136
176 /** 137 /**
177 * Return [EntityRefBuilder] that corresponds to the given [type]. 138 * Return [EntityRefBuilder] that corresponds to the given [type].
178 */ 139 */
179 EntityRefBuilder serializeType(TypeName type); 140 EntityRefBuilder serializeType(TypeName type);
180 141
181 /** 142 /**
182 * Return the [UnlinkedConstBuilder] that corresponds to the state of this 143 * Return the [UnlinkedConstBuilder] that corresponds to the state of this
183 * serializer. 144 * serializer.
184 */ 145 */
185 UnlinkedConstBuilder toBuilder() { 146 UnlinkedConstBuilder toBuilder() {
147 if (isInvalid) {
148 return new UnlinkedConstBuilder(isInvalid: true);
149 }
186 return new UnlinkedConstBuilder( 150 return new UnlinkedConstBuilder(
187 operations: operations, 151 operations: operations,
188 ints: ints, 152 ints: ints,
189 doubles: doubles, 153 doubles: doubles,
190 strings: strings, 154 strings: strings,
191 references: references); 155 references: references);
192 } 156 }
193 157
194 void _pushInt(int value) { 158 void _pushInt(int value) {
195 assert(value >= 0); 159 assert(value >= 0);
196 if (value >= (1 << 32)) { 160 if (value >= (1 << 32)) {
197 int numOfComponents = 0; 161 int numOfComponents = 0;
198 ints.add(numOfComponents); 162 ints.add(numOfComponents);
199 void pushComponents(int value) { 163 void pushComponents(int value) {
200 if (value >= (1 << 32)) { 164 if (value >= (1 << 32)) {
201 pushComponents(value >> 32); 165 pushComponents(value >> 32);
202 } 166 }
203 numOfComponents++; 167 numOfComponents++;
204 ints.add(value & 0xFFFFFFFF); 168 ints.add(value & 0xFFFFFFFF);
205 } 169 }
206 pushComponents(value); 170 pushComponents(value);
207 ints[ints.length - 1 - numOfComponents] = numOfComponents; 171 ints[ints.length - 1 - numOfComponents] = numOfComponents;
208 operations.add(UnlinkedConstOperation.pushLongInt); 172 operations.add(UnlinkedConstOperation.pushLongInt);
209 } else { 173 } else {
210 operations.add(UnlinkedConstOperation.pushInt); 174 operations.add(UnlinkedConstOperation.pushInt);
211 ints.add(value); 175 ints.add(value);
212 } 176 }
213 } 177 }
214 178
179 /**
180 * Serialize the given [expr] expression into this serializer state.
181 */
182 void _serialize(Expression expr) {
183 if (expr is IntegerLiteral) {
184 _pushInt(expr.value);
185 } else if (expr is DoubleLiteral) {
186 operations.add(UnlinkedConstOperation.pushDouble);
187 doubles.add(expr.value);
188 } else if (expr is BooleanLiteral) {
189 if (expr.value) {
190 operations.add(UnlinkedConstOperation.pushTrue);
191 } else {
192 operations.add(UnlinkedConstOperation.pushFalse);
193 }
194 } else if (expr is StringLiteral) {
195 _serializeString(expr);
196 } else if (expr is SymbolLiteral) {
197 strings.add(expr.components.map((token) => token.lexeme).join('.'));
198 operations.add(UnlinkedConstOperation.makeSymbol);
199 } else if (expr is NullLiteral) {
200 operations.add(UnlinkedConstOperation.pushNull);
201 } else if (expr is Identifier) {
202 if (expr is SimpleIdentifier && isConstructorParameterName(expr.name)) {
203 strings.add(expr.name);
204 operations.add(UnlinkedConstOperation.pushConstructorParameter);
205 } else {
206 references.add(serializeIdentifier(expr));
207 operations.add(UnlinkedConstOperation.pushReference);
208 }
209 } else if (expr is InstanceCreationExpression) {
210 serializeInstanceCreation(
211 serializeConstructorName(
212 expr.constructorName.type, expr.constructorName.name),
213 expr.argumentList);
214 } else if (expr is ListLiteral) {
215 _serializeListLiteral(expr);
216 } else if (expr is MapLiteral) {
217 _serializeMapLiteral(expr);
218 } else if (expr is MethodInvocation) {
219 String name = expr.methodName.name;
220 if (name != 'identical') {
221 throw new StateError('Only "identity" function invocation is allowed.');
222 }
223 if (expr.argumentList == null ||
224 expr.argumentList.arguments.length != 2) {
225 throw new StateError(
226 'The function "identity" requires exactly 2 arguments.');
227 }
228 expr.argumentList.arguments.forEach(_serialize);
229 operations.add(UnlinkedConstOperation.identical);
230 } else if (expr is BinaryExpression) {
231 _serializeBinaryExpression(expr);
232 } else if (expr is ConditionalExpression) {
233 _serialize(expr.condition);
234 _serialize(expr.thenExpression);
235 _serialize(expr.elseExpression);
236 operations.add(UnlinkedConstOperation.conditional);
237 } else if (expr is PrefixExpression) {
238 _serializePrefixExpression(expr);
239 } else if (expr is PropertyAccess) {
240 if (expr.target is! PrefixedIdentifier &&
241 expr.propertyName.name == 'length') {
242 _serialize(expr.target);
243 operations.add(UnlinkedConstOperation.length);
244 } else {
245 references.add(serializePropertyAccess(expr));
246 operations.add(UnlinkedConstOperation.pushReference);
247 }
248 } else if (expr is ParenthesizedExpression) {
249 _serialize(expr.expression);
250 } else {
251 throw new StateError('Unknown expression type: $expr');
252 }
253 }
254
215 void _serializeBinaryExpression(BinaryExpression expr) { 255 void _serializeBinaryExpression(BinaryExpression expr) {
216 serialize(expr.leftOperand); 256 _serialize(expr.leftOperand);
217 serialize(expr.rightOperand); 257 _serialize(expr.rightOperand);
218 TokenType operator = expr.operator.type; 258 TokenType operator = expr.operator.type;
219 if (operator == TokenType.EQ_EQ) { 259 if (operator == TokenType.EQ_EQ) {
220 operations.add(UnlinkedConstOperation.equal); 260 operations.add(UnlinkedConstOperation.equal);
221 } else if (operator == TokenType.BANG_EQ) { 261 } else if (operator == TokenType.BANG_EQ) {
222 operations.add(UnlinkedConstOperation.notEqual); 262 operations.add(UnlinkedConstOperation.notEqual);
223 } else if (operator == TokenType.AMPERSAND_AMPERSAND) { 263 } else if (operator == TokenType.AMPERSAND_AMPERSAND) {
224 operations.add(UnlinkedConstOperation.and); 264 operations.add(UnlinkedConstOperation.and);
225 } else if (operator == TokenType.BAR_BAR) { 265 } else if (operator == TokenType.BAR_BAR) {
226 operations.add(UnlinkedConstOperation.or); 266 operations.add(UnlinkedConstOperation.or);
227 } else if (operator == TokenType.CARET) { 267 } else if (operator == TokenType.CARET) {
(...skipping 20 matching lines...) Expand all
248 operations.add(UnlinkedConstOperation.greater); 288 operations.add(UnlinkedConstOperation.greater);
249 } else if (operator == TokenType.LT) { 289 } else if (operator == TokenType.LT) {
250 operations.add(UnlinkedConstOperation.less); 290 operations.add(UnlinkedConstOperation.less);
251 } else if (operator == TokenType.GT_EQ) { 291 } else if (operator == TokenType.GT_EQ) {
252 operations.add(UnlinkedConstOperation.greaterEqual); 292 operations.add(UnlinkedConstOperation.greaterEqual);
253 } else if (operator == TokenType.LT_EQ) { 293 } else if (operator == TokenType.LT_EQ) {
254 operations.add(UnlinkedConstOperation.lessEqual); 294 operations.add(UnlinkedConstOperation.lessEqual);
255 } else if (operator == TokenType.PERCENT) { 295 } else if (operator == TokenType.PERCENT) {
256 operations.add(UnlinkedConstOperation.modulo); 296 operations.add(UnlinkedConstOperation.modulo);
257 } else { 297 } else {
258 throw new _ConstExprSerializationError('Unknown operator: $operator'); 298 throw new StateError('Unknown operator: $operator');
259 } 299 }
260 } 300 }
261 301
262 void serializeInstanceCreation(
263 EntityRefBuilder constructor, ArgumentList argumentList) {
264 List<Expression> arguments = argumentList.arguments;
265 // Serialize the arguments.
266 List<String> argumentNames = <String>[];
267 arguments.forEach((arg) {
268 if (arg is NamedExpression) {
269 argumentNames.add(arg.name.label.name);
270 serialize(arg.expression);
271 } else {
272 serialize(arg);
273 }
274 });
275 // Add the op-code and numbers of named and positional arguments.
276 operations.add(UnlinkedConstOperation.invokeConstructor);
277 ints.add(argumentNames.length);
278 strings.addAll(argumentNames);
279 ints.add(arguments.length - argumentNames.length);
280 // Serialize the reference.
281 references.add(constructor);
282 }
283
284 void _serializeListLiteral(ListLiteral expr) { 302 void _serializeListLiteral(ListLiteral expr) {
285 List<Expression> elements = expr.elements; 303 List<Expression> elements = expr.elements;
286 elements.forEach(serialize); 304 elements.forEach(_serialize);
287 ints.add(elements.length); 305 ints.add(elements.length);
288 if (expr.typeArguments != null && 306 if (expr.typeArguments != null &&
289 expr.typeArguments.arguments.length == 1) { 307 expr.typeArguments.arguments.length == 1) {
290 references.add(serializeType(expr.typeArguments.arguments[0])); 308 references.add(serializeType(expr.typeArguments.arguments[0]));
291 operations.add(UnlinkedConstOperation.makeTypedList); 309 operations.add(UnlinkedConstOperation.makeTypedList);
292 } else { 310 } else {
293 operations.add(UnlinkedConstOperation.makeUntypedList); 311 operations.add(UnlinkedConstOperation.makeUntypedList);
294 } 312 }
295 } 313 }
296 314
297 void _serializeMapLiteral(MapLiteral expr) { 315 void _serializeMapLiteral(MapLiteral expr) {
298 for (MapLiteralEntry entry in expr.entries) { 316 for (MapLiteralEntry entry in expr.entries) {
299 serialize(entry.key); 317 _serialize(entry.key);
300 serialize(entry.value); 318 _serialize(entry.value);
301 } 319 }
302 ints.add(expr.entries.length); 320 ints.add(expr.entries.length);
303 if (expr.typeArguments != null && 321 if (expr.typeArguments != null &&
304 expr.typeArguments.arguments.length == 2) { 322 expr.typeArguments.arguments.length == 2) {
305 references.add(serializeType(expr.typeArguments.arguments[0])); 323 references.add(serializeType(expr.typeArguments.arguments[0]));
306 references.add(serializeType(expr.typeArguments.arguments[1])); 324 references.add(serializeType(expr.typeArguments.arguments[1]));
307 operations.add(UnlinkedConstOperation.makeTypedMap); 325 operations.add(UnlinkedConstOperation.makeTypedMap);
308 } else { 326 } else {
309 operations.add(UnlinkedConstOperation.makeUntypedMap); 327 operations.add(UnlinkedConstOperation.makeUntypedMap);
310 } 328 }
311 } 329 }
312 330
313 void _serializePrefixExpression(PrefixExpression expr) { 331 void _serializePrefixExpression(PrefixExpression expr) {
314 serialize(expr.operand); 332 _serialize(expr.operand);
315 TokenType operator = expr.operator.type; 333 TokenType operator = expr.operator.type;
316 if (operator == TokenType.BANG) { 334 if (operator == TokenType.BANG) {
317 operations.add(UnlinkedConstOperation.not); 335 operations.add(UnlinkedConstOperation.not);
318 } else if (operator == TokenType.MINUS) { 336 } else if (operator == TokenType.MINUS) {
319 operations.add(UnlinkedConstOperation.negate); 337 operations.add(UnlinkedConstOperation.negate);
320 } else if (operator == TokenType.TILDE) { 338 } else if (operator == TokenType.TILDE) {
321 operations.add(UnlinkedConstOperation.complement); 339 operations.add(UnlinkedConstOperation.complement);
322 } else { 340 } else {
323 throw new _ConstExprSerializationError('Unknown operator: $operator'); 341 throw new StateError('Unknown operator: $operator');
324 } 342 }
325 } 343 }
326 344
327 void _serializeString(StringLiteral expr) { 345 void _serializeString(StringLiteral expr) {
328 if (expr is AdjacentStrings) { 346 if (expr is AdjacentStrings) {
329 if (expr.strings.every((string) => string is SimpleStringLiteral)) { 347 if (expr.strings.every((string) => string is SimpleStringLiteral)) {
330 operations.add(UnlinkedConstOperation.pushString); 348 operations.add(UnlinkedConstOperation.pushString);
331 strings.add(expr.stringValue); 349 strings.add(expr.stringValue);
332 } else { 350 } else {
333 expr.strings.forEach(_serializeString); 351 expr.strings.forEach(_serializeString);
334 operations.add(UnlinkedConstOperation.concatenate); 352 operations.add(UnlinkedConstOperation.concatenate);
335 ints.add(expr.strings.length); 353 ints.add(expr.strings.length);
336 } 354 }
337 } else if (expr is SimpleStringLiteral) { 355 } else if (expr is SimpleStringLiteral) {
338 operations.add(UnlinkedConstOperation.pushString); 356 operations.add(UnlinkedConstOperation.pushString);
339 strings.add(expr.value); 357 strings.add(expr.value);
340 } else { 358 } else {
341 StringInterpolation interpolation = expr as StringInterpolation; 359 StringInterpolation interpolation = expr as StringInterpolation;
342 for (InterpolationElement element in interpolation.elements) { 360 for (InterpolationElement element in interpolation.elements) {
343 if (element is InterpolationString) { 361 if (element is InterpolationString) {
344 operations.add(UnlinkedConstOperation.pushString); 362 operations.add(UnlinkedConstOperation.pushString);
345 strings.add(element.value); 363 strings.add(element.value);
346 } else { 364 } else {
347 serialize((element as InterpolationExpression).expression); 365 _serialize((element as InterpolationExpression).expression);
348 } 366 }
349 } 367 }
350 operations.add(UnlinkedConstOperation.concatenate); 368 operations.add(UnlinkedConstOperation.concatenate);
351 ints.add(interpolation.elements.length); 369 ints.add(interpolation.elements.length);
352 } 370 }
353 } 371 }
354 } 372 }
355
356 /**
357 * Error that describes a problem during a constant expression serialization.
358 */
359 class _ConstExprSerializationError {
360 final String message;
361
362 _ConstExprSerializationError(this.message);
363
364 @override
365 String toString() => message;
366 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698