OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library fasta.analyzer.ast_builder; | |
6 | |
7 import 'package:dart_scanner/src/token.dart' show | |
8 BeginGroupToken, | |
9 Token; | |
10 | |
11 import 'package:analyzer/analyzer.dart'; | |
12 | |
13 import 'package:analyzer/dart/ast/token.dart' as analyzer show | |
14 Token; | |
15 | |
16 import 'package:analyzer/dart/element/element.dart' show | |
17 Element; | |
18 | |
19 import 'package:analyzer/dart/ast/ast_factory.dart' show | |
20 AstFactory; | |
21 | |
22 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard; | |
23 | |
24 import '../errors.dart' show | |
25 internalError; | |
26 | |
27 import '../source/scope_listener.dart' show | |
28 JumpTargetKind, | |
29 NullValue, | |
30 Scope, | |
31 ScopeListener; | |
32 | |
33 import '../kernel/kernel_builder.dart' show | |
34 Builder, | |
35 KernelLibraryBuilder, | |
36 ProcedureBuilder; | |
37 | |
38 import '../quote.dart'; | |
39 | |
40 import '../source/outline_builder.dart' show | |
41 asyncMarkerFromTokens; | |
42 | |
43 import 'element_store.dart' show | |
44 AnalyzerLocalVariableElemment, | |
45 AnalyzerParameterElement, | |
46 ElementStore, | |
47 KernelClassElement; | |
48 | |
49 import 'token_utils.dart' show | |
50 toAnalyzerToken; | |
51 | |
52 import 'analyzer.dart' show | |
53 toKernel; | |
54 | |
55 class AstBuilder extends ScopeListener { | |
56 final AstFactory ast = standard.astFactory; | |
57 | |
58 final KernelLibraryBuilder library; | |
59 | |
60 final Builder member; | |
61 | |
62 final ElementStore elementStore; | |
63 | |
64 bool isFirstIdentifier = false; | |
65 | |
66 AstBuilder(this.library, this.member, this.elementStore, Scope scope) | |
67 : super(scope); | |
68 | |
69 Uri get uri => library.uri; | |
70 | |
71 createJumpTarget(JumpTargetKind kind) { | |
72 // TODO(ahe): Implement jump targets. | |
73 return null; | |
74 } | |
75 | |
76 void beginLiteralString(Token token) { | |
77 debugEvent("beginLiteralString"); | |
78 push(token); | |
79 } | |
80 | |
81 void handleStringPart(Token token) { | |
82 debugEvent("StringPart"); | |
83 push(token); | |
84 } | |
85 | |
86 void doStringPart(Token token) { | |
87 push(ast.simpleStringLiteral(toAnalyzerToken(token), token.value)); | |
88 } | |
89 | |
90 void endLiteralString(int interpolationCount) { | |
91 debugEvent("endLiteralString"); | |
92 if (interpolationCount == 0) { | |
93 Token token = pop(); | |
94 String value = unescapeString(token.value); | |
95 push(ast.simpleStringLiteral(toAnalyzerToken(token), value)); | |
96 } else { | |
97 List parts = popList(1 + interpolationCount * 2); | |
98 Token first = parts.first; | |
99 Token last = parts.last; | |
100 Quote quote = analyzeQuote(first.value); | |
101 List<InterpolationElement> elements = <InterpolationElement>[]; | |
102 elements.add(ast.interpolationString( | |
103 toAnalyzerToken(first), | |
104 unescapeFirstStringPart(first.value, quote))); | |
105 for (int i = 1; i < parts.length - 1; i++) { | |
106 var part = parts[i]; | |
107 if (part is Token) { | |
108 elements.add(ast.interpolationString( | |
109 toAnalyzerToken(part), part.value)); | |
110 } else if (part is Expression) { | |
111 elements.add(ast.interpolationExpression(null, part, null)); | |
112 } else { | |
113 internalError( | |
114 "Unexpected part in string interpolation: ${part.runtimeType}"); | |
115 } | |
116 } | |
117 elements.add(ast.interpolationString( | |
118 toAnalyzerToken(last), unescapeLastStringPart(last.value, quote))) ; | |
asgerf
2017/01/19 10:13:26
Long line
ahe
2017/01/19 10:59:45
Done.
| |
119 push(ast.stringInterpolation(elements)); | |
120 } | |
121 } | |
122 | |
123 void handleStringJuxtaposition(int literalCount) { | |
124 debugEvent("StringJuxtaposition"); | |
125 push(ast.adjacentStrings(popList(literalCount))); | |
126 } | |
127 | |
128 void endArguments(int count, Token beginToken, Token endToken) { | |
129 debugEvent("Arguments"); | |
130 List expressions = popList(count); | |
131 ArgumentList arguments = ast.argumentList(toAnalyzerToken(beginToken), | |
132 expressions, toAnalyzerToken(endToken)); | |
133 push(ast.methodInvocation(null, null, null, null, arguments)); | |
134 } | |
135 | |
136 void beginExpression(Token token) { | |
137 isFirstIdentifier = true; | |
138 } | |
139 | |
140 void handleIdentifier(Token token) { | |
141 debugEvent("handleIdentifier"); | |
142 String name = token.value; | |
143 SimpleIdentifier identifier = ast.simpleIdentifier(toAnalyzerToken(token)); | |
144 if (isFirstIdentifier) { | |
145 Builder builder = scope.lookup(name); | |
146 if (builder != null) { | |
147 Element element = elementStore[builder]; | |
148 assert(element != null); | |
149 identifier.staticElement = element; | |
150 } | |
151 } | |
152 push(identifier); | |
153 isFirstIdentifier = false; | |
154 } | |
155 | |
156 void endSend(Token token) { | |
157 debugEvent("Send"); | |
158 MethodInvocation arguments = pop(); | |
159 TypeArgumentList typeArguments = pop(); | |
160 if (arguments != null) { | |
161 if (typeArguments != null) { | |
162 arguments.typeArguments = typeArguments; | |
163 } | |
164 doInvocation(token, arguments); | |
165 } else { | |
166 doPropertyGet(token); | |
167 } | |
168 } | |
169 | |
170 void doInvocation(Token token, MethodInvocation arguments) { | |
171 Expression receiver = pop(); | |
172 if (receiver is SimpleIdentifier) { | |
173 arguments.methodName = receiver; | |
174 push(arguments); | |
175 } else { | |
176 internalError("Unhandled receiver in send: ${receiver.runtimeType}"); | |
177 } | |
178 } | |
179 | |
180 void doPropertyGet(Token token) { | |
181 } | |
182 | |
183 void endExpressionStatement(Token token) { | |
184 debugEvent("ExpressionStatement"); | |
185 push(ast.expressionStatement(pop(), toAnalyzerToken(token))); | |
186 } | |
187 | |
188 void endFunctionBody(int count, Token beginToken, Token endToken) { | |
189 debugEvent("FunctionBody"); | |
190 List statements = popList(count); | |
191 if (beginToken != null) { | |
192 exitLocalScope(); | |
193 } | |
194 push(ast.block(toAnalyzerToken(beginToken), statements, | |
195 toAnalyzerToken(endToken))); | |
196 } | |
197 | |
198 void finishFunction(formals, asyncModifier, Statement body) { | |
199 debugEvent("finishFunction"); | |
200 print(""" | |
201 Analyzer AST: | |
202 $body | |
asgerf
2017/01/19 10:13:26
Please remove these prints.
ahe
2017/01/19 10:59:45
Done.
| |
203 """); | |
204 var kernel = toKernel(body, elementStore, library.library, scope); | |
205 print(""" | |
206 Kernel from analyzer AST: | |
207 $kernel"""); | |
208 if (member is ProcedureBuilder) { | |
209 ProcedureBuilder builder = member; | |
210 builder.body = kernel; | |
211 } else { | |
212 internalError("Internal error: expected procedure, but got: $member"); | |
213 } | |
214 } | |
215 | |
216 void beginCascade(Token token) { | |
217 debugEvent("beginCascade"); | |
218 Expression expression = pop(); | |
219 push(token); | |
220 if (expression is CascadeExpression) { | |
221 push(expression); | |
222 } else { | |
223 push(ast.cascadeExpression(expression, <Expression>[])); | |
224 } | |
225 push(NullValue.CascadeReceiver); | |
226 } | |
227 | |
228 void endCascade() { | |
229 debugEvent("Cascade"); | |
230 Expression expression = pop(); | |
231 CascadeExpression receiver = pop(); | |
232 pop(); // Token. | |
233 receiver.cascadeSections.add(expression); | |
234 push(receiver); | |
235 } | |
236 | |
237 void handleBinaryExpression(Token token) { | |
238 debugEvent("BinaryExpression"); | |
239 if (identical(".", token.stringValue) || | |
240 identical("..", token.stringValue)) { | |
241 doDotExpression(token); | |
242 } else { | |
243 Expression right = pop(); | |
244 Expression left = pop(); | |
245 push(ast.binaryExpression(left, toAnalyzerToken(token), right)); | |
246 } | |
247 } | |
248 | |
249 void doDotExpression(Token token) { | |
250 Expression identifierOrInvoke = pop(); | |
251 Expression receiver = pop(); | |
252 if (identifierOrInvoke is SimpleIdentifier) { | |
253 push(ast.propertyAccess(receiver, toAnalyzerToken(token), | |
254 identifierOrInvoke)); | |
255 } else if (identifierOrInvoke is MethodInvocation) { | |
256 assert(identifierOrInvoke.target == null); | |
257 identifierOrInvoke | |
258 ..target = receiver | |
259 ..operator = toAnalyzerToken(token); | |
260 push(identifierOrInvoke); | |
261 } else { | |
262 internalError("Unhandled property access: ${identifierOrInvoke.runtimeType }"); | |
asgerf
2017/01/19 10:13:26
Long Lineâ„¢
ahe
2017/01/19 10:59:45
Done.
| |
263 } | |
264 } | |
265 | |
266 void handleLiteralInt(Token token) { | |
267 debugEvent("LiteralInt"); | |
268 push(ast.integerLiteral(toAnalyzerToken(token), int.parse(token.value))); | |
269 } | |
270 | |
271 void endReturnStatement( | |
272 bool hasExpression, Token beginToken, Token endToken) { | |
273 debugEvent("ReturnStatement"); | |
274 Expression expression = hasExpression ? pop() : null; | |
275 push(ast.returnStatement(toAnalyzerToken(beginToken), expression, | |
276 toAnalyzerToken(endToken))); | |
277 } | |
278 | |
279 void endIfStatement(Token ifToken, Token elseToken) { | |
280 Statement elsePart = popIfNotNull(elseToken); | |
281 Statement thenPart = pop(); | |
282 Expression condition = pop(); | |
283 BeginGroupToken leftParenthesis = ifToken.next; | |
284 push(ast.ifStatement( | |
285 toAnalyzerToken(ifToken), toAnalyzerToken(ifToken.next), condition, | |
286 toAnalyzerToken(leftParenthesis.endGroup), thenPart, | |
287 toAnalyzerToken(elseToken), elsePart)); | |
288 } | |
289 | |
290 void prepareInitializers() { | |
291 debugEvent("prepareInitializers"); | |
292 } | |
293 | |
294 void handleNoInitializers() { | |
295 debugEvent("NoInitializers"); | |
296 } | |
297 | |
298 void endInitializers(int count, Token beginToken, Token endToken) { | |
299 debugEvent("Initializers"); | |
300 popList(count); | |
301 } | |
302 | |
303 void endInitializer(Token assignmentOperator) { | |
304 debugEvent("Initializer"); | |
305 assert(assignmentOperator.stringValue == "="); | |
306 Expression initializer = pop(); | |
307 Identifier identifier = pop(); | |
308 // TODO(ahe): Don't push initializers, instead install them. | |
309 push(ast.variableDeclaration( | |
310 identifier, toAnalyzerToken(assignmentOperator), initializer)); | |
311 } | |
312 | |
313 void endInitializedIdentifier() { | |
314 debugEvent("InitializedIdentifier"); | |
315 AstNode node = pop(); | |
316 VariableDeclaration variable; | |
317 if (node is VariableDeclaration) { | |
318 variable = node; | |
319 } else if (node is SimpleIdentifier) { | |
320 variable = ast.variableDeclaration(node, null, null); | |
321 } else { | |
322 internalError("unhandled identifier: ${node.runtimeType}"); | |
323 } | |
324 push(variable); | |
325 scope[variable.name.name] = variable.name.staticElement = | |
326 new AnalyzerLocalVariableElemment(variable); | |
327 } | |
328 | |
329 void endVariablesDeclaration(int count, Token endToken) { | |
330 debugEvent("VariablesDeclaration"); | |
331 List<VariableDeclaration> variables = popList(count); | |
332 TypeName type = pop(); | |
333 pop(); // Modifiers. | |
334 push(ast.variableDeclarationStatement( | |
335 ast.variableDeclarationList(null, null, null, type, variables), | |
336 toAnalyzerToken(endToken))); | |
337 } | |
338 | |
339 void handleAssignmentExpression(Token token) { | |
340 debugEvent("AssignmentExpression"); | |
341 Expression rhs = pop(); | |
342 Expression lhs = pop(); | |
343 push(ast.assignmentExpression(lhs, toAnalyzerToken(token), rhs)); | |
344 } | |
345 | |
346 void endBlock(int count, Token beginToken, Token endToken) { | |
347 debugEvent("Block"); | |
348 List<Statement> statements = popList(count) ?? <Statement>[]; | |
349 exitLocalScope(); | |
350 push(ast.block(toAnalyzerToken(beginToken), statements, | |
351 toAnalyzerToken(endToken))); | |
352 } | |
353 | |
354 void endForStatement( | |
355 int updateExpressionCount, Token beginToken, Token endToken) { | |
356 debugEvent("ForStatement"); | |
357 Statement body = pop(); | |
358 List<Expression> updates = popList(updateExpressionCount); | |
359 ExpressionStatement condition = pop(); | |
360 VariableDeclarationStatement variables = pop(); | |
361 exitContinueTarget(); | |
362 exitBreakTarget(); | |
363 exitLocalScope(); | |
364 BeginGroupToken leftParenthesis = beginToken.next; | |
365 push(ast.forStatement( | |
366 toAnalyzerToken(beginToken), | |
367 toAnalyzerToken(leftParenthesis), | |
368 variables?.variables, | |
369 null, // initialization. | |
370 variables?.semicolon, | |
371 condition.expression, | |
372 condition.semicolon, | |
373 updates, | |
374 toAnalyzerToken(leftParenthesis.endGroup), | |
375 body)); | |
376 } | |
377 | |
378 void handleLiteralList( | |
379 int count, Token beginToken, Token constKeyword, Token endToken) { | |
380 debugEvent("LiteralList"); | |
381 List<Expression> expressions = popList(count); | |
382 TypeArgumentList typeArguments = pop(); | |
383 push(ast.listLiteral( | |
384 toAnalyzerToken(constKeyword), | |
385 typeArguments, | |
386 toAnalyzerToken(beginToken), | |
387 expressions, | |
388 toAnalyzerToken(endToken))); | |
389 } | |
390 | |
391 void handleAsyncModifier(Token asyncToken, Token starToken) { | |
392 debugEvent("AsyncModifier"); | |
393 push(asyncMarkerFromTokens(asyncToken, starToken)); | |
394 } | |
395 | |
396 void endAwaitExpression(Token beginToken, Token endToken) { | |
397 debugEvent("AwaitExpression"); | |
398 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop())); | |
399 } | |
400 | |
401 void beginLiteralSymbol(Token token) { | |
402 isFirstIdentifier = false; | |
403 } | |
404 | |
405 void handleLiteralBool(Token token) { | |
406 debugEvent("LiteralBool"); | |
407 bool value = identical(token.stringValue, "true"); | |
408 assert(value || identical(token.stringValue, "false")); | |
409 push(ast.booleanLiteral(toAnalyzerToken(token), value)); | |
410 } | |
411 | |
412 void handleLiteralDouble(Token token) { | |
413 debugEvent("LiteralDouble"); | |
414 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.value))); | |
415 } | |
416 | |
417 void handleLiteralNull(Token token) { | |
418 debugEvent("LiteralNull"); | |
419 push(ast.nullLiteral(toAnalyzerToken(token))); | |
420 } | |
421 | |
422 void handleLiteralMap( | |
423 int count, Token beginToken, Token constKeyword, Token endToken) { | |
424 debugEvent("LiteralMap"); | |
425 List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[]; | |
426 TypeArgumentList typeArguments = pop(); | |
427 push(ast.mapLiteral(toAnalyzerToken(constKeyword), typeArguments, | |
428 toAnalyzerToken(beginToken), entries, toAnalyzerToken(endToken))); | |
429 } | |
430 | |
431 void endLiteralMapEntry(Token colon, Token endToken) { | |
432 debugEvent("LiteralMapEntry"); | |
433 Expression value = pop(); | |
434 Expression key = pop(); | |
435 push(ast.mapLiteralEntry(key, toAnalyzerToken(colon), value)); | |
436 } | |
437 | |
438 void endLiteralSymbol(Token hashToken, int identifierCount) { | |
439 debugEvent("LiteralSymbol"); | |
440 List<analyzer.Token> components = new List<analyzer.Token>(identifierCount); | |
441 for (int i = identifierCount - 1; i >= 0; i--) { | |
442 SimpleIdentifier identifier = pop(); | |
443 components[i] = identifier.token; | |
444 } | |
445 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components)); | |
446 } | |
447 | |
448 void endType(Token beginToken, Token endToken) { | |
449 debugEvent("Type"); | |
450 TypeArgumentList arguments = pop(); | |
451 SimpleIdentifier name = pop(); | |
452 KernelClassElement cls = name.staticElement; | |
453 if (cls == null) { | |
454 Builder builder = scope.lookup(name.name); | |
455 if (builder == null) { | |
456 internalError("Undefined name: $name"); | |
457 } | |
458 cls = elementStore[builder]; | |
459 assert(cls != null); | |
460 name.staticElement = cls; | |
461 } | |
462 push(ast.typeName(name, arguments)..type = cls.rawType); | |
463 } | |
464 | |
465 void handleAsOperator(Token operator, Token endToken) { | |
466 debugEvent("AsOperator"); | |
467 TypeName type = pop(); | |
468 Expression expression = pop(); | |
469 push(ast.asExpression(expression, toAnalyzerToken(operator), type)); | |
470 } | |
471 | |
472 void handleIsOperator(Token operator, Token not, Token endToken) { | |
473 debugEvent("IsOperator"); | |
474 TypeName type = pop(); | |
475 Expression expression = pop(); | |
476 push(ast.isExpression(expression, toAnalyzerToken(operator), | |
477 toAnalyzerToken(not), type)); | |
478 } | |
479 | |
480 void handleConditionalExpression(Token question, Token colon) { | |
481 debugEvent("ConditionalExpression"); | |
482 Expression elseExpression = pop(); | |
483 Expression thenExpression = pop(); | |
484 Expression condition = pop(); | |
485 push(ast.conditionalExpression(condition, toAnalyzerToken(question), | |
486 thenExpression, toAnalyzerToken(colon), elseExpression)); | |
487 } | |
488 | |
489 void endThrowExpression(Token throwToken, Token endToken) { | |
490 debugEvent("ThrowExpression"); | |
491 push(ast.throwExpression(toAnalyzerToken(throwToken), pop())); | |
492 } | |
493 | |
494 void endFormalParameter(Token thisKeyword) { | |
495 debugEvent("FormalParameter"); | |
496 if (thisKeyword != null) { | |
497 internalError("'this' can't be used here."); | |
498 } | |
499 SimpleIdentifier name = pop(); | |
500 TypeName type = pop(); | |
501 pop(); // Modifiers. | |
502 pop(); // Metadata. | |
503 SimpleFormalParameter node = ast.simpleFormalParameter(null, null, | |
504 toAnalyzerToken(thisKeyword), type, name); | |
505 scope[name.name] = name.staticElement = new AnalyzerParameterElement(node); | |
506 push(node); | |
507 } | |
508 | |
509 void endFormalParameters(int count, Token beginToken, Token endToken) { | |
510 debugEvent("FormalParameters"); | |
511 List<FormalParameter> parameters = popList(count) ?? <FormalParameter>[]; | |
512 push(ast.formalParameterList(toAnalyzerToken(beginToken), parameters, | |
513 null, null, toAnalyzerToken(endToken))); | |
514 } | |
515 | |
516 void handleCatchBlock(Token onKeyword, Token catchKeyword) { | |
517 debugEvent("CatchBlock"); | |
518 Block body = pop(); | |
519 FormalParameterList catchParameters = popIfNotNull(catchKeyword); | |
520 if (catchKeyword != null) { | |
521 exitLocalScope(); | |
522 } | |
523 TypeName type = popIfNotNull(onKeyword); | |
524 SimpleIdentifier exception; | |
525 SimpleIdentifier stackTrace; | |
526 if (catchParameters != null) { | |
527 if (catchParameters.length > 0) { | |
528 exception = catchParameters.parameters[0].identifier; | |
529 } | |
530 if (catchParameters.length > 1) { | |
531 stackTrace = catchParameters.parameters[1].identifier; | |
532 } | |
533 } | |
534 BeginGroupToken leftParenthesis = catchKeyword.next; | |
535 push(ast.catchClause(toAnalyzerToken(onKeyword), type, | |
536 toAnalyzerToken(catchKeyword), toAnalyzerToken(leftParenthesis), | |
537 exception, null, stackTrace, | |
538 toAnalyzerToken(leftParenthesis.endGroup), body)); | |
539 } | |
540 | |
541 void endTryStatement( | |
542 int catchCount, Token tryKeyword, Token finallyKeyword) { | |
543 Block finallyBlock = popIfNotNull(finallyKeyword); | |
544 List<CatchClause> catchClauses = popList(catchCount); | |
545 Block body = pop(); | |
546 push(ast.tryStatement(toAnalyzerToken(tryKeyword), body, catchClauses, | |
547 toAnalyzerToken(finallyKeyword), finallyBlock)); | |
548 } | |
549 | |
550 void handleNoExpression(Token token) { | |
551 debugEvent("NoExpression"); | |
552 push(NullValue.Expression); | |
553 } | |
554 | |
555 void handleIndexedExpression( | |
556 Token openCurlyBracket, Token closeCurlyBracket) { | |
557 debugEvent("IndexedExpression"); | |
558 Expression index = pop(); | |
559 Expression target = pop(); | |
560 if (target == null) { | |
561 CascadeExpression receiver = pop(); | |
562 Token token = peek(); | |
563 push(receiver); | |
564 IndexExpression expression = ast.indexExpressionForCascade( | |
565 toAnalyzerToken(token), toAnalyzerToken(openCurlyBracket), index, | |
566 toAnalyzerToken(closeCurlyBracket)); | |
567 assert(expression.isCascaded); | |
568 push(expression); | |
569 } else { | |
570 push(ast.indexExpressionForTarget(target, | |
571 toAnalyzerToken(openCurlyBracket), index, | |
572 toAnalyzerToken(closeCurlyBracket))); | |
573 } | |
574 } | |
575 | |
576 void handleUnaryPrefixExpression(Token token) { | |
577 debugEvent("UnaryPrefixExpression"); | |
578 push(ast.prefixExpression(toAnalyzerToken(token), pop())); | |
579 } | |
580 | |
581 void handleUnaryPrefixAssignmentExpression(Token token) { | |
582 debugEvent("UnaryPrefixAssignmentExpression"); | |
583 push(ast.prefixExpression(toAnalyzerToken(token), pop())); | |
584 } | |
585 | |
586 void handleUnaryPostfixAssignmentExpression(Token token) { | |
587 debugEvent("UnaryPostfixAssignmentExpression"); | |
588 push(ast.postfixExpression(pop(), toAnalyzerToken(token))); | |
589 } | |
590 | |
591 void handleModifier(Token token) { | |
592 debugEvent("Modifier"); | |
593 // TODO(ahe): Don't ignore modifiers. | |
594 } | |
595 | |
596 void handleModifiers(int count) { | |
597 debugEvent("Modifiers"); | |
598 // TODO(ahe): Don't ignore modifiers. | |
599 push(NullValue.Modifiers); | |
600 } | |
601 } | |
OLD | NEW |