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

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

Issue 2738273002: Add fasta-based summary generation code. (Closed)
Patch Set: Actually disable the test Created 3 years, 9 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
(Empty)
1 // Copyright (c) 2017, 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 /// Logic to build unlinked summaries.
6 library summary.src.summary_builder;
7
8 import 'expression_serializer.dart';
9 import 'model.dart';
10 import 'package:front_end/src/fasta/parser/class_member_parser.dart';
Siggi Cherem (dart-lang) 2017/03/09 21:02:14 I'm surprised that the sorting of imports doesn't
Paul Berry 2017/03/09 23:26:23 Oops--I added these imports in any old location be
11 import 'package:front_end/src/fasta/parser/identifier_context.dart';
12 import 'package:front_end/src/fasta/parser/parser.dart';
13 import 'package:front_end/src/fasta/scanner.dart';
14 import 'package:front_end/src/fasta/scanner/token_constants.dart';
15 import 'stack_listener.dart';
16
17 /// Create an unlinked summary given a null-terminated byte buffer with the
18 /// contents of a file.
19 UnlinkedUnit summarize(Uri uri, List<int> contents) {
20 var listener = new SummaryBuilder(uri);
21 var parser = new ClassMemberParser(listener);
22 parser.parseUnit(scan(contents).tokens);
23 return listener.topScope.unit;
24 }
25
26 /// A listener of parser events that builds summary information as parsing
27 /// progresses.
28 class SummaryBuilder extends StackListener {
29 /// Whether 'dart:core' was imported explicitly by the current unit.
30 bool isDartCoreImported = false;
31
32 /// Whether the current unit is part of 'dart:core'.
33 bool isCoreLibrary = false;
34
35 /// Topmost scope.
36 TopScope topScope;
37
38 /// Current scope where name references are resolved from.
39 Scope scope;
40
41 /// Helper to build constant expressions.
42 final ConstExpressionBuilder constBuilder;
43
44 /// Helper to build initializer expressions.
45 final InitializerBuilder initializerBuilder;
46
47 /// Whether the current initializer has a type declared.
48 ///
49 /// Because initializers are only used for strong-mode inference, we can skip
50 /// parsing and building initializer expressions when a type is declared.
51 bool typeSeen = false;
52
53 /// Whether we are currently in the context of a const expression.
54 bool inConstContext = false;
55
56 /// Whether we need to parse the initializer of a declaration.
57 bool get needInitializer => !typeSeen || inConstContext;
58
59 /// Uri of the file currently being processed, used for error reporting only.
60 final Uri uri;
61
62
63 /// Summaries preassign slots for computed information, this is the next
64 /// available slot.
65 int _slots = 0;
66
67 SummaryBuilder(Uri uri)
68 : uri = uri,
69 constBuilder = new ConstExpressionBuilder(uri),
70 initializerBuilder = new InitializerBuilder(uri);
71
72 void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
73 debugEvent("NoConstructorReferenceContinuationAfterTypeArguments");
74 }
75
76 void beginCompilationUnit(Token token) {
77 scope = topScope = new TopScope();
78 }
79
80 void endCompilationUnit(int count, Token token) {
81 if (!isDartCoreImported) {
82 topScope.unit.imports.add(new UnlinkedImportBuilder(isImplicit: true));
83 }
84
85 topScope.expandLazyReferences();
86
87 // TODO(sigmund): could this be be optional: done by whoever consumes it?
88 if (const bool.fromEnvironment('SKIP_API')) return;
89 var apiSignature = new ApiSignature();
90 topScope.unit.collectApiSignature(apiSignature);
91 topScope.unit.apiSignature = apiSignature.toByteList();
92 }
93
94 // Directives: imports, exports, parts
95
96 void endHide(_) {
97 // ignore: strong_mode_down_cast_composite
98 push(new UnlinkedCombinatorBuilder(hides: pop()));
99 }
100
101 void endShow(_) {
102 // ignore: strong_mode_down_cast_composite
103 push(new UnlinkedCombinatorBuilder(shows: pop()));
104 }
105
106 void endCombinators(int count) {
107 debugEvent("Combinators");
108 push(popList(count) ?? NullValue.Combinators);
109 }
110
111 void endConditionalUri(Token ifKeyword, Token equalitySign) {
112 String dottedName = pop();
113 String value = pop();
114 String uri = pop();
115 uri = uri.substring(1, uri.length - 1);
116 push(new UnlinkedConfigurationBuilder(
117 name: dottedName, value: value, uri: uri));
118 }
119
120 void endConditionalUris(int count) {
121 push(popList(count) ?? const <UnlinkedConfigurationBuilder>[]);
122 }
123
124 void endExport(Token exportKeyword, Token semicolon) {
125 debugEvent("Export");
126 // ignore: strong_mode_down_cast_composite
127 List<UnlinkedCombinator> combinators = pop();
128 // ignore: strong_mode_down_cast_composite
129 List<UnlinkedConfiguration> conditionalUris = pop();
130 String uri = pop();
131 // ignore: strong_mode_down_cast_composite
132 List<UnlinkedExpr> metadata = pop();
133 topScope.unit.exports.add(new UnlinkedExportNonPublicBuilder(annotations: me tadata));
134 topScope.publicNamespace.exports.add(new UnlinkedExportPublicBuilder(
135 uri: uri,
136 combinators: combinators,
137 configurations: conditionalUris));
138 checkEmpty();
139 }
140
141 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
142 Token semicolon) {
143 debugEvent("endImport");
144 // ignore: strong_mode_down_cast_composite
145 List<UnlinkedCombinator> combinators = pop();
146 String prefix = popIfNotNull(asKeyword);
147 int prefixIndex = prefix == null ? null
148 : topScope.serializeReference(null, prefix);
149 // ignore: strong_mode_down_cast_composite
150 List<UnlinkedConfiguration> conditionalUris = pop();
151 String uri = pop();
152 // ignore: strong_mode_down_cast_composite
153 List<UnlinkedExpr> metadata = pop(); // metadata
154
155 topScope.unit.imports.add(new UnlinkedImportBuilder(
156 uri: uri,
157 prefixReference: prefixIndex,
158 combinators: combinators,
159 configurations: conditionalUris,
160 isDeferred: deferredKeyword != null,
161 annotations: metadata,
162 ));
163 if (uri == 'dart:core') isDartCoreImported = true;
164 checkEmpty();
165 }
166
167 void endPart(Token partKeyword, Token semicolon) {
168 debugEvent("Part");
169 String uri = pop();
170 // ignore: strong_mode_down_cast_composite
171 List<UnlinkedExpr> metadata = pop();
172 topScope.unit.parts.add(new UnlinkedPartBuilder(annotations: metadata));
173 topScope.publicNamespace.parts.add(uri);
174 checkEmpty();
175 }
176
177 void endLibraryName(Token libraryKeyword, Token semicolon) {
178 debugEvent("endLibraryName");
179 String name = pop();
180 // ignore: strong_mode_down_cast_composite
181 List<UnlinkedExpr> metadata = pop(); // metadata
182
183 topScope.unit.libraryName = name;
184 topScope.unit.libraryAnnotations = metadata;
185 if (name == 'dart.core') isCoreLibrary = true;
186 }
187
188 void endPartOf(Token partKeyword, Token semicolon) {
189 debugEvent("endPartOf");
190 String name = pop();
191 pop(); // metadata
192 topScope.unit.isPartOf = true;
193 if (name == 'dart.core') isCoreLibrary = true;
194 }
195
196 // classes, enums, mixins, and typedefs.
197
198 void beginClassDeclaration(Token beginToken, Token name) {
199 debugEvent("beginClass");
200 var classScope = scope = new ClassScope(scope);
201 classScope.className = name.value;
202 }
203
204 void endClassBody(int memberCount, Token beginToken, Token endToken) {
205 debugEvent("ClassBody");
206 }
207
208 void endClassDeclaration(int interfacesCount, Token beginToken, Token classKey word,
209 Token extendsKeyword, Token implementsKeyword, Token endToken) {
210 debugEvent("endClassDeclaration");
211 // ignore: strong_mode_down_cast_composite
212 List<EntityRefBuilder> interfaces = popList(interfacesCount);
213 EntityRef supertype = pop();
214 // ignore: strong_mode_down_cast_composite
215 List<UnlinkedTypeParamBuilder> typeVariables = pop();
216 String name = pop();
217 int modifiers = pop();
218 List metadata = pop();
219 checkEmpty();
220
221 ClassScope s = scope;
222 s.className = name;
223 s.currentClass
224 ..name = name
225 ..isAbstract = modifiers & _abstract_flag != 0
226 // ignore: strong_mode_down_cast_composite
227 ..annotations = metadata
228 ..typeParameters = typeVariables
229 ..interfaces = interfaces;
230 if (supertype != null) {
231 s.currentClass.supertype = supertype;
232 } else {
233 s.currentClass.hasNoSupertype = isCoreLibrary && name == 'Object';
234 }
235 scope = scope.parent;
236 topScope.unit.classes.add(s.currentClass);
237 if (_isPrivate(name)) return;
238 s.publicName
239 ..name = name
240 ..kind = ReferenceKind.classOrEnum
241 ..numTypeParameters = typeVariables?.length;
242 topScope.publicNamespace.names.add(s.publicName);
243 }
244
245 void beginEnum(Token token) {
246 debugEvent("beginEnum");
247 scope = new EnumScope(scope);
248 }
249
250 void endEnum(Token enumKeyword, Token endBrace, int count) {
251 debugEvent("Enum");
252 // ignore: strong_mode_down_cast_composite
253 List<String> constants = popList(count);
254 String name = pop();
255 List metadata = pop();
256 checkEmpty();
257 EnumScope s = scope;
258 scope = s.parent;
259 s.currentEnum
260 ..name = name
261 // ignore: strong_mode_down_cast_composite
262 ..annotations = metadata;
263 s.top.unit.enums.add(s.currentEnum);
264
265 // public namespace:
266 var e = new UnlinkedPublicNameBuilder(
267 name: name,
268 kind: ReferenceKind.classOrEnum,
269 numTypeParameters: 0);
270 for (var s in constants) {
271 e.members.add(new UnlinkedPublicNameBuilder(
272 name: s,
273 kind: ReferenceKind.propertyAccessor,
274 numTypeParameters: 0));
275 }
276 topScope.publicNamespace.names.add(e);
277 }
278
279 void endMixinApplication(Token withKeyword) {
280 debugEvent("MixinApplication");
281 ClassScope s = scope;
282 // ignore: strong_mode_down_cast_composite
283 s.currentClass.mixins = pop();
284 }
285
286 void beginNamedMixinApplication(Token beginToken, Token name) {
287 debugEvent('beginNamedMixinApplication');
288 scope = new ClassScope(scope);
289 }
290
291 void endNamedMixinApplication(
292 Token begin, Token classKeyword, Token equals,
293 Token implementsKeyword, Token endToken) {
294 debugEvent("endNamedMixinApplication");
295 // ignore: strong_mode_down_cast_composite
296 List<EntityRef> interfaces = popIfNotNull(implementsKeyword);
297 EntityRef supertype = pop();
298 List typeVariables = pop();
299 String name = pop();
300 int modifiers = pop();
301 List metadata = pop();
302 // print('TODO: end mix, $name');
303 checkEmpty();
304
305 ClassScope s = scope;
306 s.currentClass
307 ..name = name
308 ..isAbstract = modifiers & _abstract_flag != 0
309 ..isMixinApplication = true
310 // ignore: strong_mode_down_cast_composite
311 ..annotations = metadata
312 // ignore: strong_mode_down_cast_composite
313 ..typeParameters = typeVariables
314 ..interfaces = interfaces;
315 if (supertype != null) {
316 s.currentClass.supertype = supertype;
317 } else {
318 s.currentClass.hasNoSupertype = isCoreLibrary && name == 'Object';
319 }
320 scope = scope.parent;
321 topScope.unit.classes.add(s.currentClass);
322
323 _addNameIfPublic(name, ReferenceKind.classOrEnum, typeVariables.length);
324 }
325
326 void beginFunctionTypeAlias(Token token) {
327 debugEvent('beginFunctionTypeAlias');
328 // TODO: use a single scope
329 scope = new TypeParameterScope(scope);
330 }
331
332 void endFunctionTypeAlias(Token typedefKeyword, Token equals, Token endToken) {
333 debugEvent("endFunctionTypeAlias");
334 List formals = pop();
335 List typeVariables = pop();
336 String name = pop();
337 EntityRef returnType = pop();
338 List metadata = pop();
339 // print('TODO: type alias $name');
340 checkEmpty();
341
342 scope = scope.parent;
343 topScope.unit.typedefs.add(new UnlinkedTypedefBuilder(
344 name: name,
345 // ignore: strong_mode_down_cast_composite
346 typeParameters: typeVariables,
347 returnType: returnType,
348 // ignore: strong_mode_down_cast_composite
349 parameters: formals,
350 // ignore: strong_mode_down_cast_composite
351 annotations: metadata));
352
353 _addNameIfPublic(name, ReferenceKind.typedef, typeVariables.length);
354 }
355
356 // members: fields, methods.
357
358 void beginTopLevelMember(Token token) {
359 typeSeen = false;
360 inConstContext = false;
361 }
362
363 void beginMember(Token token) {
364 typeSeen = false;
365 inConstContext = false;
366 }
367
368 void endMember() {
369 debugEvent("Member");
370 }
371
372 void handleType(Token beginToken, Token endToken) {
373 debugEvent("Type");
374 // ignore: strong_mode_down_cast_composite
375 List<EntityRef> arguments = pop();
376 String name = pop();
377
378 var type;
379 if (name.contains('.')) {
380 var parts = name.split('.');
381 for (var p in parts) {
382 type = type == null
383 ? new LazyEntityRef(p, scope)
384 : new NestedLazyEntityRef(type, p, scope);
385 }
386 } else {
387 type = new LazyEntityRef(name, scope);
388 }
389 type.typeArguments = arguments;
390 push(type);
391 typeSeen = true;
392 }
393
394 void endTypeList(int count) {
395 debugEvent("TypeList");
396 push(popList(count) ?? NullValue.TypeList);
397 }
398
399 static int parsed = 0;
400 static int total = 0;
401 beginInitializer(Token token) {
402 // TODO(paulberry): Add support for this.
403 }
404
405 beginFieldInitializer(Token token) {
406 // TODO(paulberry): Copied from beginFieldInitializer. Is all of this neede d?
Siggi Cherem (dart-lang) 2017/03/09 21:02:13 did you mean from beginInitializer?
Paul Berry 2017/03/09 23:26:23 Oops, yes. I've removed this TODO--it was a place
407 debugEvent("beginFieldInitializer");
408 total++;
409 if (needInitializer) {
410 parsed++;
411 if (inConstContext) {
412 push(constBuilder.computeExpression(token.next, scope));
413 } else {
414 push(initializerBuilder.computeExpression(token.next, scope));
415 }
416 }
417 }
418
419 void endInitializer(Token assignmentOperator) {
420 // TODO(paulberry): add support for this.
421 debugEvent("Initializer $typeSeen $assignmentOperator");
422 }
423
424 void endFieldInitializer(Token assignmentOperator) {
425 // TODO(paulberry): copied from endInitializer. Is all of this needed?
Siggi Cherem (dart-lang) 2017/03/09 21:02:14 just to make sure I follow - you are wondering if
Paul Berry 2017/03/09 23:26:23 At the time I wrote the TODO I didn't understand t
426 debugEvent("FieldInitializer $typeSeen $assignmentOperator");
427 // This is a variable initializer and it's ignored for now. May also be
428 // constructor initializer.
429 var initializer = needInitializer && assignmentOperator != null
430 ? pop() : null;
431 var name = pop();
432 push(new _InitializedName(name, new UnlinkedExecutableBuilder(
433 bodyExpr: initializer)));
434 }
435
436 void endTopLevelFields(int count, Token beginToken, Token endToken) {
437 debugEvent("endTopLevelFields");
438 _endFields(count, topScope.unit.variables, true);
439 checkEmpty();
440 }
441
442 void endFields(int count, Token covariantKeyword, Token beginToken, Token endT oken) {
443 debugEvent("Fields");
444 var s = scope;
445 if (s is ClassScope) {
446 _endFields(count, s.currentClass.fields, false);
447 } else {
448 throw new UnimplementedError(); // TODO(paulberry): does this ever occur?
Siggi Cherem (dart-lang) 2017/03/09 21:02:14 do you mean that we don't summarize enums altogeth
Paul Berry 2017/03/09 23:26:23 We do summarize enums, but the parsing of enums ne
449 // _endFields(count, s.currentEnum.values, false);
450 }
451 }
452
453 void _endFields(int count, List result, bool isTopLevel) {
454 debugEvent('EndFields: $count $isTopLevel');
455 // ignore: strong_mode_down_cast_composite
456 List<_InitializedName> fields = popList(count);
457 EntityRef type = pop();
458 int modifiers = pop();
459 List metadata = pop();
460
461 bool isStatic = modifiers & _static_flag != 0;
462 bool isFinal = modifiers & _final_flag != 0;
463 bool isConst = modifiers & _const_flag != 0;
464 bool isInstance = !isStatic && !isTopLevel;
465 for (var field in fields) {
466 var name = field.name;
467 var initializer = field.initializer;
468 bool needsPropagatedType = initializer != null && (isFinal || isConst);
469 bool needsInferredType =
470 type == null && (initializer != null || isInstance);
471 result.add(new UnlinkedVariableBuilder(
472 isFinal: isFinal,
473 isConst: isConst,
474 isStatic: isStatic,
475 name: name,
476 type: type,
477 // ignore: strong_mode_down_cast_composite
478 annotations: metadata,
479 initializer: initializer,
480 propagatedTypeSlot: slotIf(needsPropagatedType),
481 inferredTypeSlot: slotIf(needsInferredType)));
482
483 if (_isPrivate(name)) continue;
484 if (isTopLevel) {
485 _addPropertyName(name, includeSetter: !isFinal && !isConst);
486 } else if (isStatic) {
487 // Any reason setters are not added as well?
488 (scope as ClassScope).publicName.members.add(new UnlinkedPublicNameBuild er(
489 name: name,
490 kind: ReferenceKind.propertyAccessor,
491 numTypeParameters: 0));
492 }
493 }
494 }
495
496
497 void endTopLevelMethod(
498 Token beginToken, Token getOrSet, Token endToken) {
499 debugEvent("endTopLevelMethod");
500 int asyncModifier = pop();
501 List formals = pop();
502 List typeVariables = pop();
503 String name = pop();
504 EntityRef returnType = pop();
505 int modifiers = pop();
506 List metadata = pop();
507 checkEmpty();
508
509 topScope.unit.executables.add(new UnlinkedExecutableBuilder(
510 name: getOrSet == 'set' ? '$name=' : name,
511 kind: getOrSet == 'get'
512 ? UnlinkedExecutableKind.getter
513 : (getOrSet == 'set' ? UnlinkedExecutableKind.setter
514 : UnlinkedExecutableKind.functionOrMethod),
515 isExternal: modifiers & _external_flag != 0,
516 isAbstract: modifiers & _abstract_flag != 0,
517 isAsynchronous: asyncModifier & _async_flag != 0,
518 isGenerator: asyncModifier & _star_flag != 0,
519 isStatic: modifiers & _static_flag != 0,
520 typeParameters: [], // TODO
521 returnType: returnType,
522 // ignore: strong_mode_down_cast_composite
523 parameters: formals,
524 // ignore: strong_mode_down_cast_composite
525 annotations: metadata,
526 inferredReturnTypeSlot: null, // not needed for top-levels
527 // skip body.
528 ));
529
530 String normalizedName = getOrSet == 'set' ? '$name=' : name;
531 _addNameIfPublic(
532 normalizedName,
533 getOrSet != null ? ReferenceKind.topLevelPropertyAccessor : ReferenceKin d.topLevelFunction,
534 typeVariables?.length ?? 0 /* todo */);
535 }
536
537 void endMethod(Token getOrSet, Token beginToken, Token endToken) {
538 debugEvent("Method");
539 int asyncModifier = pop();
540 // ignore: strong_mode_down_cast_composite
541 List<UnlinkedParam> formals = pop();
542 // ignore: strong_mode_down_cast_composite
543 List<UnlinkedTypeParamBuilder> typeVariables = pop();
544 String name = pop();
545 EntityRef returnType = pop();
546 int modifiers = pop();
547 List metadata = pop();
548
549 ClassScope s = scope;
550 bool isStatic = modifiers & _static_flag != 0;
551 bool isConst = modifiers & _const_flag != 0;
552 bool isGetter = getOrSet == 'get';
553 bool isSetter = getOrSet == 'set';
554 bool isOperator = name == "operator"; // TODO
555 bool isConstructor =
556 name == s.className || name.startsWith('${s.className}.');
557
558 if (isConstructor) {
559 name = name == s.className ? '' : name.substring(name.indexOf('.') + 1);
560 }
561
562 name = isSetter ? '$name=' : name;
563 // Note: we don't include bodies for any method.
564 s.currentClass.executables.add(new UnlinkedExecutableBuilder(
565 name: name,
566 kind: isGetter
567 ? UnlinkedExecutableKind.getter
568 : (isSetter
569 ? UnlinkedExecutableKind.setter
570 : (isConstructor
571 ? UnlinkedExecutableKind.constructor
572 : UnlinkedExecutableKind.functionOrMethod)),
573 isExternal: modifiers & _external_flag != 0,
574 isAbstract: modifiers & _abstract_flag != 0,
575 isAsynchronous: asyncModifier & _async_flag != 0,
576 isGenerator: asyncModifier & _star_flag != 0,
577 isStatic: isStatic,
578 isConst: isConst,
579 constCycleSlot: slotIf(isConst),
580 typeParameters: typeVariables,
581 returnType: returnType,
582 parameters: formals, // TODO: add inferred slot to args
583 // ignore: strong_mode_down_cast_composite
584 annotations: metadata,
585 inferredReturnTypeSlot: slotIf(returnType == null && !isStatic &&
586 !isConstructor)));
587
588 if (isConstructor && name == '') return;
589 if (_isPrivate(name)) return;
590 if (isSetter || isOperator) return;
591 if (!isStatic && !isConstructor) return;
592 s.publicName.members.add(new UnlinkedPublicNameBuilder(
593 name: name,
594 kind: isGetter ? ReferenceKind.propertyAccessor :
595 (isConstructor ? ReferenceKind.constructor :
596 ReferenceKind.method),
597 numTypeParameters: typeVariables.length));
598 }
599
600 void endTypeArguments(int count, Token beginToken, Token endToken) {
601 debugEvent("TypeArguments");
602 push(popList(count) ?? const []);
603 }
604
605
606 void handleVoidKeyword(Token token) {
607 debugEvent("VoidKeyword");
608 // TODO: skip the lazy mechanism
609 push(new LazyEntityRef("void", scope.top));
610 }
611
612 void endFormalParameter(Token covariantKeyword, Token thisKeyword, FormalParam eterType kind) {
613 debugEvent("FormalParameter");
614 // TODO(sigmund): clean up?
615 var nameOrFormal = pop();
616 if (nameOrFormal is String) {
617 EntityRef type = pop();
618 pop(); // Modifiers
619 List metadata = pop();
620 push(new UnlinkedParamBuilder(
621 name: nameOrFormal,
622 kind: _nextParamKind,
623 inheritsCovariantSlot: slotIf(type == null),
624 // ignore: strong_mode_down_cast_composite
625 annotations: metadata,
626 isInitializingFormal: thisKeyword != null,
627 type: type));
628 } else {
629 push(nameOrFormal);
630 }
631 }
632
633 // TODO(sigmund): handle metadata (this code is incomplete).
634 void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
635 debugEvent("Metadata");
636 List arguments = pop();
637 var result = new UnlinkedExprBuilder();
638 // If arguments are null, this is an expression, otherwise a constructor
639 // reference.
640 if (arguments == null) {
641 /* String postfix = */ popIfNotNull(periodBeforeName);
642 /* String expression = */ pop();
643 //push([expression, postfix]); // @x or @p.x
644 } else {
645 /* String name = */ popIfNotNull(periodBeforeName);
646 // TODO(ahe): Type arguments are missing, eventually they should be
647 // available as part of [arguments].
648 // List<String> typeArguments = null;
649 /* EntityRef typeName = */ pop();
650 //push([typeName, typeArguments, name, arguments]);
651 }
652 push(result);
653 }
654
655 void endMetadataStar(int count, bool forParameter) {
656 debugEvent("MetadataStar");
657 push(popList(count) ?? NullValue.Metadata);
658 }
659
660 void handleStringPart(token) {
661 debugEvent("handleStringPart");
662 push(token.value.substring(1, token.value.length - 1));
663 }
664
665 void beginLiteralString(Token token) {
666 debugEvent("beginLiteralString");
667 push(token.value.substring(1, token.value.length - 1));
668 }
669
670 void endLiteralString(int count) {
671 assert(count == 0); // TODO(sigmund): handle interpolation
672 }
673
674 void handleQualified(Token period) {
675 debugEvent("handleQualified");
676 String name = pop();
677 String receiver = pop();
678 push("$receiver.$name");
679 }
680
681 void endDottedName(count, firstIdentifier) {
682 push(popList(count).join('.'));
683 }
684
685 void handleOperatorName(Token operatorKeyword, Token token) {
686 // TODO(sigmund): convert operator names to name used by summaries.
687 debugEvent("OperatorName");
688 push(operatorKeyword.value);
689 }
690
691 void endIdentifierList(int count) {
692 debugEvent("endIdentifierList");
693 push(popList(count) ?? NullValue.IdentifierList);
694 }
695
696 void handleModifier(Token token) {
697 debugEvent("Modifier");
698 var modifier = _modifierFlag[token.stringValue];
699 if (modifier & _const_flag != 0) inConstContext = true;
700 push(modifier);
701 }
702
703 void handleModifiers(int count) {
704 debugEvent("Modifiers");
705 push((popList(count) ?? const []).fold(0, (a, b) => a | b));
706 }
707
708 UnlinkedParamKind _nextParamKind;
709 void beginFormalParameters(Token begin) {
710 _nextParamKind = UnlinkedParamKind.required;
711 }
712 void beginOptionalFormalParameters(Token begin) {
713 _nextParamKind =
714 begin == '{' ? UnlinkedParamKind.named : UnlinkedParamKind.positional;
715 }
716
717 void handleValuedFormalParameter(Token equals, Token token) {
718 debugEvent("ValuedFormalParameter");
719 // TODO(sigmund): include default value on optional args.
720 }
721
722 void endFunctionTypedFormalParameter(Token covariantKeyword, Token thisKeyword , FormalParameterType kind) {
723 debugEvent("FunctionTypedFormalParameter");
724 // ignore: strong_mode_down_cast_composite
725 List<UnlinkedParamBuilder> formals = pop();
726 if (formals != null) formals.forEach((p) => p.inheritsCovariantSlot = null);
727
728 /* List typeVariables = */ pop();
729 String name = pop();
730 EntityRef returnType = pop();
731 /* int modifiers = */ pop();
732 List metadata = pop();
733
734 push(new UnlinkedParamBuilder(
735 name: name,
736 kind: _nextParamKind,
737 isFunctionTyped: true,
738 parameters: formals,
739 // ignore: strong_mode_down_cast_composite
740 annotations: metadata,
741 type: returnType));
742 }
743
744 void endOptionalFormalParameters(
745 int count, Token beginToken, Token endToken) {
746 debugEvent("OptionalFormalParameters");
747 push(popList(count));
748 }
749
750 void endFormalParameters(int count, Token beginToken, Token endToken) {
751 debugEvent("FormalParameters");
752 List formals = popList(count);
753 if (formals != null && formals.isNotEmpty) {
754 var last = formals.last;
755 if (last is List) {
756 var newList = new List(formals.length - 1 + last.length);
757 newList.setRange(0, formals.length - 1, formals);
758 newList.setRange(formals.length - 1, newList.length, last);
759 for (int i = 0; i < last.length; i++) {
760 newList[i + formals.length - 1] = last[i];
761 }
762 formals = newList;
763 }
764 }
765 push(formals ?? NullValue.FormalParameters);
766 }
767
768 void endTypeVariables(int count, Token beginToken, Token endToken) {
769 debugEvent("TypeVariables");
770 push(popList(count) ?? const []);
771 }
772
773 void endTypeVariable(Token token, Token extendsOrSuper) {
774 debugEvent("endTypeVariable");
775 EntityRef bound = pop();
776 String name = pop();
777
778 var s = scope;
779 if (s is TypeParameterScope) {
780 s.typeParameters.add(name);
781 } else {
782 throw new UnimplementedError(); // TODO(paulberry)
783 }
784 push(new UnlinkedTypeParamBuilder(
785 name: name,
786 bound: bound));
787 }
788
789 void endFactoryMethod(Token beginToken, Token endToken) {
790 debugEvent("FactoryMethod");
791 throw new UnimplementedError(); // TODO(paulberry)
792 // pop(); // async-modifiers
793 // /* List<FormalParameterBuilder> formals = */ pop();
794 // var name = pop();
795 // /* List<MetadataBuilder> metadata = */ pop();
796 }
797
798
799 void endRedirectingFactoryBody(Token beginToken, Token endToken) {
800 debugEvent("RedirectingFactoryBody");
801 pop(); // Discard ConstructorReferenceBuilder.
802 }
803
804 void endConstructorReference(
805 Token start, Token periodBeforeName, Token endToken) {
806 var ctorName = popIfNotNull(periodBeforeName);
807 var typeArguments = pop();
808 var className = pop();
809 push(['ctor-ref:', className, typeArguments, ctorName]);
810 }
811
812 void endInitializers(int count, Token beginToken, Token endToken) {
813 debugEvent("Initializers");
814 // TODO(sigmund): include const-constructor initializers
815 }
816
817 void handleNoFieldInitializer(Token token) {
818 debugEvent("NoFieldInitializer");
819 push(new _InitializedName(pop(), null));
820 }
821
822 void handleNoTypeVariables(Token token) {
823 debugEvent("NoTypeVariables");
824 push(const []);
825 }
826
827 void handleNoInitializers() {
828 debugEvent("NoInitializers");
829 // This is a constructor initializer and it's ignored for now.
830 }
831
832 void handleNoFunctionBody(Token token) {
833 debugEvent("NoFunctionBody");
834 // Ignored for now. We shouldn't see any function bodies.
835 }
836
837 void handleAsyncModifier(Token asyncToken, Token starToken) {
838 debugEvent("AsyncModifier");
839 int asyncModifier = 0;
840 if (asyncToken == "async") asyncModifier |= _async_flag;
841 if (asyncToken == "sync") asyncModifier |= _sync_flag;
842 if (starToken != null) asyncModifier |= _star_flag;
843 push(asyncModifier);
844 }
845
846 // helpers to work with the summary format.
847
848
849 /// Assign the next slot.
850 int assignSlot() => ++_slots;
851
852 /// Assign the next slot if [condition] is true.
853 int slotIf(bool condition) => condition ? assignSlot() : 0;
854
855 /// Whether a name is private and should be excluded from the public
856 /// namespace.
857 bool _isPrivate(String name) => name.startsWith('_');
858
859 /// Add [name] to the public namespace if it's public.
860 void _addNameIfPublic(
861 String name, ReferenceKind kind, int numTypeParameters) {
862 if (_isPrivate(name)) return null;
863 _addName(name, kind, numTypeParameters: numTypeParameters);
864 }
865
866 /// Add [name] to the public namespace.
867 void _addName(
868 String name, ReferenceKind kind, {int numTypeParameters: 0}) {
869 topScope.publicNamespace.names.add(new UnlinkedPublicNameBuilder(
870 name: name,
871 kind: kind,
872 numTypeParameters: numTypeParameters));
873 }
874
875 /// Add `name` and, if requested, `name=` to the public namespace.
876 void _addPropertyName(String name, {bool includeSetter: false}) {
877 _addName(name, ReferenceKind.topLevelPropertyAccessor);
878 if (includeSetter) {
879 _addName('$name=', ReferenceKind.topLevelPropertyAccessor);
880 }
881 }
882
883 /// If enabled, show a debug message.
884 void debugEvent(String name) {
885 if (const bool.fromEnvironment('DEBUG', defaultValue: false)) {
886 var s = stack.join(' :: ');
887 if (s == '') s = '<empty>';
888 var bits = 'type?: $typeSeen, const?: $inConstContext';
889 var prefix = "do $name on:";
890 prefix = '$prefix${" " * (30 - prefix.length)}';
891 print('$prefix $bits $s');
892 }
893 }
894
895 void handleFormalParameterWithoutValue(Token token) {
896 debugEvent("FormalParameterWithoutValue");
897 }
898 }
899
900 /// Internal representation of an initialized name.
901 class _InitializedName {
902 final String name;
903 final UnlinkedExecutableBuilder initializer;
904 _InitializedName(this.name, this.initializer);
905
906 toString() => "II:" + (initializer != null ? "$name = $initializer" : name);
907 }
908
909 /// Parser listener to build simplified AST expresions.
910 ///
911 /// The parser produces different trees depending on whether it is used for
912 /// constants or initializers, so subclasses specialize the logic accordingly.
913 abstract class ExpressionListener extends StackListener {
914 // Underlying parser that invokes this listener.
915 Parser get parser;
916
917 /// Whether to ignore the next reduction. Used to ignore nested expresions
918 /// that are either invalid (in constants) or unnecessary (for initializers).
919 bool get ignore => _withinFunction > 0 || _withinCascades > 0;
920
921 /// Whether this listener is used to build const expressions.
922 bool get forConst => false;
923
924 void push(Object o);
925
926 UnlinkedExprBuilder computeExpression(Token token, Scope scope) {
927 debugStart(token);
928 parser.parseExpression(token);
929 debugEvent('---- END ---');
930 Expression node = pop();
931 checkEmpty();
932 return new Serializer(scope, forConst).run(node);
933 }
934
935 void handleNoInitializer() {}
936
937 void handleIdentifier(Token token, IdentifierContext context) {
938 debugEvent("Identifier");
939 if (ignore) return;
940 push(new Ref(token.value));
941 }
942
943
944 void endFormalParameter(Token covariantKeyword, Token thisKeyword, FormalParam eterType kind) {
945 debugEvent("FormalParameter");
946 assert(ignore);
947 }
948
949 void endFunctionBody(int count, Token begin, Token end) {
950 debugEvent("FunctionBody");
951 assert(ignore);
952 }
953
954 void endFunctionName(Token token) {
955 debugEvent("FunctionName");
956 assert(ignore);
957 }
958
959 void endFormalParameters(int c, begin, end) {
960 debugEvent("FormalParameters");
961 assert(ignore);
962 }
963
964 void handleAsyncModifier(Token asyncToken, Token starToken) {
965 debugEvent("AsyncModifier");
966 assert(ignore);
967 }
968
969 void endReturnStatement(hasValue, Token begin, Token end) {
970 debugEvent("ReturnStatement");
971 assert(ignore);
972 }
973
974 void handleStringPart(token) {
975 debugEvent("handleStringPart");
976 if (ignore) return;
977 push(new StringLiteral(token.value));
978 }
979
980 void beginLiteralString(Token token) {
981 debugEvent("beginLiteralString");
982 if (ignore) return;
983 push(new StringLiteral(token.value));
984 }
985
986 void handleStringJuxtaposition(int count) {
987 debugEvent("StringJuxtaposition");
988 if (ignore) return;
989 popList(count);
990 push(new StringLiteral('<juxtapose $count>'));
991 }
992
993 void endLiteralString(int interpolationCount) {
994 debugEvent("endLiteralString");
995 if (interpolationCount != 0) {
996 popList(2 * interpolationCount + 1);
997 push(new StringLiteral("<interpolate $interpolationCount>"));
998 }
999 }
1000
1001 void endThrowExpression(throwToken, token) {
1002 debugEvent("Throw");
1003 assert(ignore);
1004 }
1005
1006 void handleNoType(Token token) {
1007 debugEvent("NoType");
1008 if (ignore) return;
1009 push(NullValue.Type);
1010 }
1011
1012 void handleNoFormalParameters(Token token) {
1013 debugEvent("NoFormalParameters");
1014 assert(ignore);
1015 }
1016
1017 void handleNoArguments(Token token) {
1018 debugEvent("NoArguments");
1019 if (ignore) return;
1020 var typeArguments = pop();
1021 assert(typeArguments == null);
1022 push(NullValue.Arguments);
1023 }
1024
1025 void handleNoFunctionBody(Token token) {
1026 debugEvent("NoFunctionBody");
1027 assert(ignore);
1028 }
1029
1030 void handleNoInitializers() {
1031 debugEvent("NoInitializers");
1032 assert(ignore);
1033 }
1034
1035 void handleNoTypeArguments(Token token) {
1036 debugEvent("NoTypeArguments");
1037 if (ignore) return;
1038 push(NullValue.TypeArguments);
1039 }
1040
1041 // type-arguments are expected to be type references passed to constructors
1042 // and generic methods, we need them to model instantiations.
1043 void endTypeArguments(int count, Token beginToken, Token endToken) {
1044 debugEvent("TypeArguments");
1045 if (ignore) return;
1046 push(popList(count) ?? const <TypeRef>[]);
1047 }
1048
1049 void handleVoidKeyword(Token token) {
1050 debugEvent("VoidKeyword");
1051 assert(ignore);
1052 }
1053
1054 void handleType(Token beginToken, Token endToken) {
1055 debugEvent("Type");
1056 if (ignore) return;
1057 // ignore: strong_mode_down_cast_composite
1058 List<TypeRef> arguments = pop();
1059 Ref name = pop();
1060 push(new TypeRef(name, arguments));
1061 }
1062
1063 void endTypeList(int count) {
1064 debugEvent("TypeList");
1065 push(popList(count) ?? const <TypeRef>[]);
1066 }
1067
1068 void handleBinaryExpression(Token operator) {
1069 debugEvent("BinaryExpression");
1070 if (ignore) return;
1071 Expression right = pop();
1072 Expression left = pop();
1073 var kind = operator.kind;
1074 if (kind == PERIOD_TOKEN) {
1075 if (left is Ref && right is Ref && right.prefix == null && left.prefixDept h < 2) {
1076 push(new Ref(right.name, left));
1077 return;
1078 }
1079 if (right is Ref) {
1080 push(new Load(left, right.name));
1081 return;
1082 }
1083 }
1084 push(new Binary(left, right, kind));
1085 }
1086
1087 void handleUnaryPrefixExpression(Token operator) {
1088 debugEvent("UnaryPrefix");
1089 if (ignore) return;
1090 push(new Unary(pop(), operator.kind));
1091 }
1092
1093 void handleLiteralNull(Token token) {
1094 debugEvent("LiteralNull");
1095 if (ignore) return;
1096 push(new NullLiteral());
1097 }
1098
1099 void handleConditionalExpression(Token question, Token colon) {
1100 debugEvent("ConditionalExpression");
1101 if (ignore) return;
1102 var falseBranch = pop();
1103 var trueBranch = pop();
1104 var cond = pop();
1105 push(new Conditional(cond, trueBranch, falseBranch));
1106 }
1107
1108 void handleLiteralInt(Token token) {
1109 debugEvent("LiteralInt");
1110 if (ignore) return;
1111 push(new IntLiteral(int.parse(token.value)));
1112 }
1113
1114 void handleLiteralDouble(Token token) {
1115 debugEvent("LiteralDouble");
1116 if (ignore) return;
1117 push(new DoubleLiteral(double.parse(token.value)));
1118 }
1119
1120 void handleLiteralBool(Token token) {
1121 debugEvent("LiteralBool");
1122 if (ignore) return;
1123 push(new BoolLiteral(token.value == 'true'));
1124 }
1125
1126 void handleIsOperator(Token operator, Token not, Token endToken) {
1127 debugEvent("Is");
1128 if (ignore) return;
1129 push(new Is(pop(), pop()));
1130 }
1131
1132 void handleConstExpression(Token token) {
1133 debugEvent("ConstExpression");
1134 if (ignore) return;
1135 List args = pop();
1136 var constructorName = pop();
1137 var positional = args.where((a) => a is! NamedArg).toList();
1138 var named = args.where((a) => a is NamedArg).toList();
1139 // ignore: strong_mode_down_cast_composite
1140 push(new ConstCreation(constructorName, positional, named));
1141 }
1142
1143 void handleLiteralList(count, begin, constKeyword, end) {
1144 debugEvent("LiteralList");
1145 if (ignore) return;
1146 var values = popList(count) ?? const <Expression>[];
1147 // ignore: strong_mode_down_cast_composite
1148 List<TypeRef> typeArguments = pop();
1149 var type = typeArguments?.single;
1150 // ignore: strong_mode_down_cast_composite
1151 push(new ListLiteral(type, values, constKeyword != null));
1152 }
1153
1154 void endLiteralMapEntry(colon, token) {
1155 debugEvent('MapEntry');
1156 if (ignore) return;
1157 var value = pop();
1158 var key = pop();
1159 push(new KeyValuePair(key, value));
1160 }
1161
1162 void handleLiteralMap(count, begin, constKeyword, end) {
1163 debugEvent('LiteralMap');
1164 if (ignore) return;
1165 var values = popList(count) ?? const <KeyValuePair>[];
1166 var typeArgs = pop() ?? const <TypeRef>[];
1167 // ignore: strong_mode_down_cast_composite
1168 push(new MapLiteral(typeArgs, values, constKeyword != null));
1169 }
1170
1171 void endLiteralSymbol(token, int dots) {
1172 debugEvent('LiteralSymbol');
1173 if (ignore) return;
1174 push(new SymbolLiteral(popList(dots).join('.')));
1175 }
1176
1177 void handleQualified(period) {
1178 debugEvent('Qualified');
1179 if (ignore) return;
1180 Ref name = pop();
1181 Ref prefix = pop();
1182 assert(name.prefix == null);
1183 assert(prefix.prefix == null);
1184 push(new Ref(name.name, prefix));
1185 }
1186
1187 int _withinFunction = 0;
1188 void beginFunctionDeclaration(token) {
1189 debugEvent("BeginFunctionDeclaration");
1190 _withinFunction++;
1191 }
1192
1193 // TODO(sigmund): remove
1194 static const _invariantCheckToken = "invariant check: starting a function";
1195 // type-variables are the declared parameters on declarations.
1196 void handleNoTypeVariables(Token token) {
1197 debugEvent("NoTypeVariables");
1198 if (ignore) return;
1199 push(_invariantCheckToken);
1200 }
1201
1202 void endTypeVariable(Token token, Token extendsOrSuper) {
1203 debugEvent("endTypeVariable");
1204 assert(ignore);
1205 }
1206
1207 void endTypeVariables(int count, Token beginToken, Token endToken) {
1208 debugEvent("TypeVariables");
1209 assert(ignore);
1210 }
1211
1212 void beginUnnamedFunction(token) {
1213 debugEvent("BeginUnnamedFunction");
1214 var check = pop();
1215 assert(check == _invariantCheckToken);
1216 _withinFunction++;
1217 }
1218
1219 void _endFunction();
1220 void endFunctionDeclaration(token) {
1221 debugEvent("FunctionDeclaration");
1222 _withinFunction--;
1223 if (ignore) return;
1224 _endFunction();
1225 }
1226 void endUnnamedFunction(token) {
1227 debugEvent("UnnamedFunction");
1228 _withinFunction--;
1229 if (ignore) return;
1230 _endFunction();
1231 }
1232
1233 int _withinCascades = 0;
1234 void beginCascade(Token token) {
1235 _withinCascades++;
1236 }
1237
1238 void endCascade() {
1239 _withinCascades--;
1240 throw new UnimplementedError(); // TODO(paulberry): fix the code below.
1241 // _endCascade();
1242 }
1243
1244 void endSend(Token beginToken, Token endToken) {
1245 debugEvent("EndSend");
1246 if (ignore) return;
1247 // ignore: strong_mode_down_cast_composite
1248 List<Expression> args = pop();
1249 if (args != null) {
1250 /* var typeArgs = */ pop();
1251 var receiver = pop();
1252 // TODO(sigmund): consider making identical a binary operator.
1253 if (receiver is Ref && receiver.name == 'identical') {
1254 assert(receiver.prefix == null);
1255 assert(args.length == 2);
1256 push(new Identical(args[0], args[1]));
1257 return;
1258 }
1259 _unhandledSend();
1260 }
1261 }
1262
1263 void _unhandledSend();
1264
1265 void endConstructorReference(
1266 Token start, Token periodBeforeName, Token endToken) {
1267 debugEvent("ConstructorReference $start $periodBeforeName");
1268 Ref ctorName = popIfNotNull(periodBeforeName);
1269 assert(ctorName?.prefix == null);
1270 // ignore: strong_mode_down_cast_composite
1271 List<TypeRef> typeArgs = pop();
1272 Ref type = pop();
1273 push(new ConstructorName(
1274 new TypeRef(type, typeArgs), ctorName?.name));
1275 }
1276
1277 void handleModifier(Token token) {
1278 debugEvent("Modifier");
1279 assert(ignore);
1280 }
1281
1282 void handleModifiers(int count) {
1283 debugEvent("Modifiers");
1284 assert(ignore);
1285 }
1286
1287 /// Overriden: the base class throws when something is not handled, we avoid
1288 /// implementing a few handlers when we know we can ignore them.
1289 @override
1290 void logEvent(e) {
1291 if (ignore) return;
1292 super.logEvent(e);
1293 }
1294
1295 // debug helpers
1296
1297 void debugEvent(String name) {
1298 if (const bool.fromEnvironment('CDEBUG', defaultValue: false)) {
1299 var s = stack.join(' :: ');
1300 if (s == '') s = '<empty>';
1301 var bits = '$_withinFunction,$_withinCascades';
1302 var prefix = ignore ? "ignore $name on:" : "do $name on:";
1303 prefix = '$prefix${" " * (30 - prefix.length)}';
1304 print('$prefix $bits $s');
1305 }
1306 }
1307
1308 void debugStart(Token token) {
1309 debugEvent('\n---- START: $runtimeType ---');
1310 if (const bool.fromEnvironment('CDEBUG', defaultValue: false)) {
1311 _printExpression(token);
1312 }
1313 }
1314
1315 void _printExpression(Token token) {
1316 var current = token;
1317 var end = new ClassMemberParser(this).skipExpression(current);
1318 var str = new StringBuffer();
1319 while (current != end) {
1320 if (!["(", ",", ")"].contains(current.value)) str.write(' ');
1321 str.write(current.value);
1322 current = current.next;
1323 }
1324 print('exp: $str');
1325 }
1326 }
1327
1328 /// Builder for constant expressions.
1329 ///
1330 /// Any invalid subexpression is denoted with [Invalid].
1331 class ConstExpressionBuilder extends ExpressionListener {
1332 bool get forConst => true;
1333 final Uri uri;
1334 Parser parser;
1335 ConstExpressionBuilder(this.uri) {
1336 parser = new Parser(this,
1337 asyncAwaitKeywordsEnabled: true);
1338 }
1339
1340 void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
1341 debugEvent("NoConstructorReferenceContinuationAfterTypeArguments");
1342 }
1343
1344 void handleAsOperator(Token op, Token next) {
1345 debugEvent("As");
1346 if (ignore) return;
1347 push(new As(pop(), pop()));
1348 }
1349
1350 void handleIndexedExpression(Token openSquareBracket, Token token) {
1351 debugEvent("Index");
1352 if (ignore) return;
1353 pop(); // receiver
1354 pop(); // index
1355 push(new Invalid(hint: "index"));
1356 }
1357
1358 void handleAssignmentExpression(Token operator) {
1359 pop(); // lhs
1360 pop(); // rhs
1361 push(new Invalid(hint: "assign"));
1362 }
1363
1364 void handleUnaryPrefixAssignmentExpression(Token operator) {
1365 pop();
1366 push(new Invalid(hint: "prefixOp"));
1367 }
1368
1369 void handleUnaryPostfixAssignmentExpression(Token operator) {
1370 pop();
1371 push(new Invalid(hint: "postfixOp"));
1372 }
1373
1374 void handleNamedArgument(colon) {
1375 debugEvent("NamedArg");
1376 if (ignore) return;
1377 var value = pop();
1378 Ref name = pop();
1379 push(new NamedArg(name.name, value));
1380 }
1381
1382 void endArguments(int count, Token begin, Token end) {
1383 debugEvent("Arguments");
1384 if (ignore) return;
1385 push(popList(count) ?? const []);
1386 }
1387
1388 void handleNewExpression(Token token) {
1389 debugEvent("NewExpression");
1390 if (ignore) return;
1391 pop(); // args
1392 pop(); // ctor
1393 push(new Invalid(hint: "new"));
1394 }
1395
1396 void _endFunction() {
1397 assert(_withinFunction >= 0);
1398 push(new Invalid(hint: 'function'));
1399 }
1400
1401 // TODO(paulberry): is this needed?
Siggi Cherem (dart-lang) 2017/03/09 21:02:14 really depends on how we want to handle recovery o
Paul Berry 2017/03/09 23:26:23 We *do* expect to run the summary builder on inval
1402 //void _endCascade() {
1403 // push(new Invalid(hint: 'cascades'));
1404 //}
1405
1406 void _unhandledSend() {
1407 push(new Invalid(hint: "call"));
1408 }
1409 }
1410
1411 /// Builder for initializer expressions. These expressions exclude any nested
1412 /// expression that is not needed to infer strong mode types.
1413 class InitializerBuilder extends ExpressionListener {
1414 final Uri uri;
1415 Parser parser;
1416
1417 InitializerBuilder(this.uri) {
1418 parser = new Parser(this,
1419 asyncAwaitKeywordsEnabled: true);
1420 }
1421
1422 void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
1423 debugEvent("NoConstructorReferenceContinuationAfterTypeArguments");
1424 }
1425
1426 bool get ignore => super.ignore || _inArguments > 0;
1427
1428 void handleAsOperator(Token op, Token next) {
1429 debugEvent("As");
1430 if (ignore) return;
1431 TypeRef type = pop();
1432 pop();
1433 push(new Opaque(type: type));
1434 }
1435
1436 // Not necessary, but we don't use the value, so we can abstract it:
1437 void handleIsOperator(Token operator, Token not, Token endToken) {
1438 debugEvent("Is");
1439 if (ignore) return;
1440 throw new UnimplementedError(); // TODO(paulberry): fix the code below.
Siggi Cherem (dart-lang) 2017/03/09 21:02:13 is the fix related to references in general?
Paul Berry 2017/03/09 23:26:23 I don't know what the proper fix is. The reason I
1441 // push(new Opaque(type: new TypeRef(new Ref('bool'))));
1442 }
1443
1444 void handleIndexedExpression(Token openSquareBracket, Token token) {
1445 debugEvent("Index");
1446 if (ignore) return;
1447 pop();
1448 pop();
1449 push(new Opaque());
1450 }
1451
1452 void handleAssignmentExpression(Token operator) {
1453 debugEvent("Assign");
1454 if (ignore) return;
1455 var left = pop();
1456 var right = pop();
1457 var kind = operator.kind;
1458 if (kind == EQ_TOKEN) {
1459 push(new OpaqueOp(right));
1460 } else {
1461 push(new OpaqueOp(new Binary(left, right, opForAssignOp(kind))));
1462 }
1463 }
1464
1465 void handleUnaryPrefixAssignmentExpression(Token operator) {
1466 debugEvent("Prefix");
1467 if (ignore) return;
1468 var kind = operator.kind == PLUS_PLUS_TOKEN ? PLUS_TOKEN : MINUS_TOKEN;
1469 push(new OpaqueOp(new Binary(pop(), new IntLiteral(1), kind)));
1470 }
1471
1472 void handleUnaryPostfixAssignmentExpression(Token operator) {
1473 debugEvent("PostFix");
1474 if (ignore) return;
1475 // the post-fix effect is not visible to the enclosing expression
1476 push(new OpaqueOp(pop()));
1477 }
1478
1479 int _inArguments = 0;
1480 void beginArguments(Token token) {
1481 // TODO(sigmund): determine if we can ignore arguments.
1482 //_inArguments++;
1483 }
1484
1485 void handleNamedArgument(colon) {
1486 debugEvent("NamedArg");
1487 if (ignore) return;
1488 pop();
1489 pop();
1490 push(NullValue.Arguments);
1491 }
1492
1493 void endArguments(int count, Token begin, Token end) {
1494 debugEvent("Arguments");
1495 //_inArguments--;
1496 if (ignore) return;
1497 push(popList(count) ?? const []);
1498 //push([new Opaque(hint: "arguments")]);
1499 }
1500
1501 void handleNewExpression(Token token) {
1502 debugEvent("NewExpression");
1503 if (ignore) return;
1504 pop(); // args
1505 /* var ctor = */ pop(); // ctor
1506 throw new UnimplementedError(); // TODO(paulberry): fix the code below.
1507 // push(new Opaque(type: ctor.type, hint: "new"));
1508 }
1509
1510 void _endFunction() {
1511 push(new Opaque(hint: "function"));
1512 }
1513
1514 // TODO(paulberry): is this needed?
1515 //void _endCascade() {
1516 // push(new OpaqueOp(pop(), hint: 'cascades'));
1517 //}
1518
1519 void _unhandledSend() {
1520 push(new Opaque(hint: "call"));
1521 }
1522 }
1523
1524 // bit-masks to encode modifiers as bits on an int.
1525
1526 /// Maps modifier names to their bit-mask.
1527 const _modifierFlag = const {
1528 'const': _const_flag,
1529 'abstract': _abstract_flag,
1530 'static': _static_flag,
1531 'external': _external_flag,
1532 'final': _final_flag,
1533 'var': _var_flag,
1534 };
1535
1536 const _var_flag = 0;
1537 const _final_flag = 1;
1538 const _const_flag = 1 << 1;
1539 const _abstract_flag = 1 << 2;
1540 const _static_flag = 1 << 3;
1541 const _external_flag = 1 << 4;
1542
1543 // bit-masks to encode async modifiers as bits on an int.
1544
1545 const _async_flag = 1;
1546 const _sync_flag = 1 << 1;
1547 const _star_flag = 1 << 2;
1548
1549 /// Retrieve the operator from an assignment operator (e.g. + from +=).
1550 /// Operators are encoded using the scanner token kind id.
1551 int opForAssignOp(int kind) {
1552 switch (kind) {
1553 case AMPERSAND_EQ_TOKEN: return AMPERSAND_TOKEN;
1554 // TODO(paulberry): add support for &&=
1555 // case AMPERSAND_AMPERSAND_EQ_TOKEN: return AMPERSAND_AMPERSAND_TOKEN;
1556 case BAR_EQ_TOKEN: return BAR_TOKEN;
1557 // TODO(paulberry): add support for ||=
1558 // case BAR_BAR_EQ_TOKEN: return BAR_BAR_TOKEN;
1559 case CARET_EQ_TOKEN: return CARET_TOKEN;
1560 case GT_GT_EQ_TOKEN: return GT_GT_TOKEN;
1561 case LT_LT_EQ_TOKEN: return LT_LT_TOKEN;
1562 case MINUS_EQ_TOKEN: return MINUS_TOKEN;
1563 case PERCENT_EQ_TOKEN: return PERCENT_TOKEN;
1564 case PLUS_EQ_TOKEN: return PLUS_TOKEN;
1565 case QUESTION_QUESTION_EQ_TOKEN: return QUESTION_QUESTION_TOKEN;
1566 case SLASH_EQ_TOKEN: return SLASH_TOKEN;
1567 case STAR_EQ_TOKEN: return STAR_TOKEN;
1568 case TILDE_SLASH_EQ_TOKEN: return TILDE_SLASH_TOKEN;
1569 case PLUS_EQ_TOKEN: return PLUS_TOKEN;
1570 default:
1571 throw "Unhandled kind $kind";
1572 }
1573 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/summary/fasta/stack_listener.dart ('k') | pkg/analyzer/lib/src/summary/fasta/visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698