| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 backend_ast_emitter; | 5 library backend_ast_emitter; |
| 6 | 6 |
| 7 import '../tree_ir/tree_ir_nodes.dart' as tree; | 7 import '../tree_ir/tree_ir_nodes.dart' as tree; |
| 8 import 'backend_ast_nodes.dart'; | 8 import 'backend_ast_nodes.dart'; |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 // TODO(johnniwinther): Split into function/block state. | 22 // TODO(johnniwinther): Split into function/block state. |
| 23 class BuilderContext<T> { | 23 class BuilderContext<T> { |
| 24 /// Builder context for the enclosing function, or null if the current | 24 /// Builder context for the enclosing function, or null if the current |
| 25 /// function is not a local function. | 25 /// function is not a local function. |
| 26 BuilderContext<T> _parent; | 26 BuilderContext<T> _parent; |
| 27 | 27 |
| 28 /// Variables to be hoisted at the top of the current function. | 28 /// Variables to be hoisted at the top of the current function. |
| 29 final List<VariableDeclaration> variables = <VariableDeclaration>[]; | 29 final List<VariableDeclaration> variables = <VariableDeclaration>[]; |
| 30 | 30 |
| 31 /// Maps variables to their name. | 31 /// Maps variables to their name. |
| 32 final Map<tree.Variable, String> variableNames = <tree.Variable, String>{}; | 32 final Map<tree.Variable, String> variableNames; |
| 33 | 33 |
| 34 /// Maps local constants to their name. | 34 /// Maps local constants to their name. |
| 35 final Map<VariableElement, String> constantNames = | 35 final Map<VariableElement, String> constantNames = |
| 36 <VariableElement, String>{}; | 36 <VariableElement, String>{}; |
| 37 | 37 |
| 38 /// Variables that have had their declaration created. | 38 /// Variables that have had their declaration created. |
| 39 final Set<tree.Variable> declaredVariables = new Set<tree.Variable>(); | 39 final Set<tree.Variable> declaredVariables = new Set<tree.Variable>(); |
| 40 | 40 |
| 41 /// Variable names that have already been used. Used to avoid name clashes. | 41 /// Variable names that have already been used. Used to avoid name clashes. |
| 42 final Set<String> usedVariableNames; | 42 final Set<String> usedVariableNames; |
| 43 | 43 |
| 44 /// Statements emitted by the most recent call to [visitStatement]. | 44 /// Statements emitted by the most recent call to [visitStatement]. |
| 45 List<T> _statementBuffer = <T>[]; | 45 List<T> _statementBuffer = <T>[]; |
| 46 | 46 |
| 47 /// The element currently being emitted. | 47 /// The element currently being emitted. |
| 48 ExecutableElement currentElement; | 48 ExecutableElement currentElement; |
| 49 | 49 |
| 50 /// Bookkeeping object needed to synthesize a variable declaration. | 50 /// Bookkeeping object needed to synthesize a variable declaration. |
| 51 final modelx.VariableList variableList | 51 final modelx.VariableList variableList |
| 52 = new modelx.VariableList(tree.Modifiers.EMPTY); | 52 = new modelx.VariableList(tree.Modifiers.EMPTY); |
| 53 | 53 |
| 54 /// Input to [visitStatement]. Denotes the statement that will execute next | 54 /// Input to [visitStatement]. Denotes the statement that will execute next |
| 55 /// if the statements produced by [visitStatement] complete normally. | 55 /// if the statements produced by [visitStatement] complete normally. |
| 56 /// Set to null if control will fall over the end of the method. | 56 /// Set to null if control will fall over the end of the method. |
| 57 tree.Statement fallthrough = null; | 57 tree.Statement fallthrough = null; |
| 58 | 58 |
| 59 /// Labels that could not be eliminated using fallthrough. | 59 /// Labels that could not be eliminated using fallthrough. |
| 60 final Set<tree.Label> _usedLabels = new Set<tree.Label>(); | 60 final Set<tree.Label> _usedLabels = new Set<tree.Label>(); |
| 61 | 61 |
| 62 final bool inInitializer; |
| 63 |
| 62 /// The first dart_tree statement that is not converted to a variable | 64 /// The first dart_tree statement that is not converted to a variable |
| 63 /// initializer. | 65 /// initializer. |
| 64 tree.Statement firstStatement; | 66 tree.Statement firstStatement; |
| 65 | 67 |
| 66 BuilderContext() : usedVariableNames = new Set<String>(); | 68 BuilderContext() : usedVariableNames = new Set<String>(), |
| 69 inInitializer = false, |
| 70 variableNames = <tree.Variable, String>{}; |
| 67 | 71 |
| 68 BuilderContext.inner(BuilderContext<T> parent) | 72 BuilderContext.inner(BuilderContext<T> parent) |
| 69 : this._parent = parent, | 73 : this._parent = parent, |
| 70 usedVariableNames = parent.usedVariableNames; | 74 usedVariableNames = parent.usedVariableNames, |
| 75 inInitializer = false, |
| 76 variableNames = <tree.Variable, String>{}; |
| 77 |
| 78 BuilderContext.initializer(BuilderContext<T> parent) |
| 79 : this._parent = parent, |
| 80 usedVariableNames = parent.usedVariableNames, |
| 81 inInitializer = true, |
| 82 variableNames = |
| 83 new Map<tree.Variable, String>.from(parent.variableNames); |
| 71 | 84 |
| 72 // TODO(johnniwinther): Fully encapsulate handling of parameter, variable | 85 // TODO(johnniwinther): Fully encapsulate handling of parameter, variable |
| 73 // and local funciton declarations. | 86 // and local funciton declarations. |
| 74 void addDeclaration(tree.Variable variable, [Expression initializer]) { | 87 void addDeclaration(tree.Variable variable, [Expression initializer]) { |
| 75 assert(!declaredVariables.contains(variable)); | 88 assert(!declaredVariables.contains(variable)); |
| 76 String name = getVariableName(variable); | 89 String name = getVariableName(variable); |
| 77 VariableDeclaration decl = new VariableDeclaration(name, initializer); | 90 VariableDeclaration decl = new VariableDeclaration(name, initializer); |
| 78 decl.element = variable.element; | 91 decl.element = variable.element; |
| 79 declaredVariables.add(variable); | 92 declaredVariables.add(variable); |
| 80 variables.add(decl); | 93 variables.add(decl); |
| 81 } | 94 } |
| 82 | 95 |
| 83 /// Generates a name for the given variable and synthesizes an element for it, | 96 /// Generates a name for the given variable and synthesizes an element for it, |
| 84 /// if necessary. | 97 /// if necessary. |
| 85 String getVariableName(tree.Variable variable) { | 98 String getVariableName(tree.Variable variable) { |
| 86 // If the variable belongs to an enclosing function, ask the parent emitter | 99 // If the variable belongs to an enclosing function, ask the parent emitter |
| 87 // for the variable name. | 100 // for the variable name. |
| 88 if (variable.host != currentElement) { | 101 if (!inInitializer && variable.host != currentElement) { |
| 89 return _parent.getVariableName(variable); | 102 return _parent.getVariableName(variable); |
| 90 } | 103 } |
| 91 | 104 |
| 92 // Get the name if we already have one. | 105 // Get the name if we already have one. |
| 93 String name = variableNames[variable]; | 106 String name = variableNames[variable]; |
| 94 if (name != null) { | 107 if (name != null) { |
| 95 return name; | 108 return name; |
| 96 } | 109 } |
| 97 | 110 |
| 98 // Synthesize a variable name that isn't used elsewhere. | 111 // Synthesize a variable name that isn't used elsewhere. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 /// Translates the dart_tree IR to Dart backend AST. | 198 /// Translates the dart_tree IR to Dart backend AST. |
| 186 /// An instance of this class should only be used once; a fresh emitter | 199 /// An instance of this class should only be used once; a fresh emitter |
| 187 /// must be created for each function to be emitted. | 200 /// must be created for each function to be emitted. |
| 188 class ASTEmitter | 201 class ASTEmitter |
| 189 extends tree.Visitor1<dynamic, Expression, BuilderContext<Statement>> { | 202 extends tree.Visitor1<dynamic, Expression, BuilderContext<Statement>> { |
| 190 | 203 |
| 191 ExecutableDefinition emit(tree.ExecutableDefinition definition, | 204 ExecutableDefinition emit(tree.ExecutableDefinition definition, |
| 192 BuilderContext<Statement> context) { | 205 BuilderContext<Statement> context) { |
| 193 if (definition is tree.FieldDefinition) { | 206 if (definition is tree.FieldDefinition) { |
| 194 return emitField(definition, context); | 207 return emitField(definition, context); |
| 208 } else if (definition is tree.ConstructorDefinition) { |
| 209 return emitConstructor(definition, context); |
| 195 } | 210 } |
| 196 assert(definition is tree.FunctionDefinition); | 211 assert(definition is tree.FunctionDefinition); |
| 197 return emitFunction(definition, context); | 212 return emitFunction(definition, context); |
| 198 } | 213 } |
| 199 | 214 |
| 200 FieldDefinition emitField(tree.FieldDefinition definition, | 215 FieldDefinition emitField(tree.FieldDefinition definition, |
| 201 BuilderContext<Statement> context) { | 216 BuilderContext<Statement> context) { |
| 202 context.currentElement = definition.element; | 217 context.currentElement = definition.element; |
| 203 Expression initializer; | 218 Expression initializer; |
| 204 if (definition.hasInitializer) { | 219 if (definition.hasInitializer) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 232 return onlyStatement.expression; | 247 return onlyStatement.expression; |
| 233 } | 248 } |
| 234 } | 249 } |
| 235 Statement body = new Block(bodyParts); | 250 Statement body = new Block(bodyParts); |
| 236 FunctionExpression function = | 251 FunctionExpression function = |
| 237 new FunctionExpression(new Parameters([]), body); | 252 new FunctionExpression(new Parameters([]), body); |
| 238 function.element = null; | 253 function.element = null; |
| 239 return new CallFunction(function, []); | 254 return new CallFunction(function, []); |
| 240 } | 255 } |
| 241 | 256 |
| 257 FunctionExpression emitConstructor(tree.ConstructorDefinition definition, |
| 258 BuilderContext<Statement> context) { |
| 259 context.currentElement = definition.element; |
| 260 |
| 261 Parameters parameters = emitRootParameters(definition, context); |
| 262 |
| 263 // Declare parameters. |
| 264 for (tree.Variable param in definition.parameters) { |
| 265 context.variableNames[param] = param.element.name; |
| 266 context.usedVariableNames.add(param.element.name); |
| 267 context.declaredVariables.add(param); |
| 268 } |
| 269 |
| 270 List<Expression> initializers; |
| 271 Statement body; |
| 272 |
| 273 if (!definition.isAbstract) { |
| 274 initializers = |
| 275 definition.initializers.map((tree.Initializer initializer) { |
| 276 return visitExpression(initializer, context); |
| 277 }).toList(); |
| 278 |
| 279 context.firstStatement = definition.body; |
| 280 visitStatement(definition.body, context); |
| 281 context.removeTrailingReturn(_recognizeTrailingReturn); |
| 282 |
| 283 // Some of the variable declarations have already been added |
| 284 // if their first assignment could be pulled into the initializer. |
| 285 // Add the remaining variable declarations now. |
| 286 for (tree.Variable variable in context.variableNames.keys) { |
| 287 if (!context.declaredVariables.contains(variable)) { |
| 288 context.addDeclaration(variable); |
| 289 } |
| 290 } |
| 291 |
| 292 // Add constant declarations. |
| 293 List<VariableDeclaration> constants = <VariableDeclaration>[]; |
| 294 for (ConstDeclaration constDecl in definition.localConstants) { |
| 295 if (!context.constantNames.containsKey(constDecl.element)) { |
| 296 continue; // Discard unused constants declarations. |
| 297 } |
| 298 String name = context.getConstantName(constDecl.element); |
| 299 Expression value = emitConstant(constDecl.expression, context); |
| 300 VariableDeclaration decl = new VariableDeclaration(name, value); |
| 301 decl.element = constDecl.element; |
| 302 constants.add(decl); |
| 303 } |
| 304 |
| 305 List<Statement> bodyParts = []; |
| 306 if (constants.length > 0) { |
| 307 bodyParts.add(new VariableDeclarations(constants, isConst: true)); |
| 308 } |
| 309 if (context.variables.length > 0) { |
| 310 bodyParts.add(new VariableDeclarations(context.variables)); |
| 311 } |
| 312 bodyParts.addAll(context.statements); |
| 313 |
| 314 body = new Block(bodyParts); |
| 315 |
| 316 } |
| 317 FunctionType functionType = context.currentElement.type; |
| 318 |
| 319 return new ConstructorDefinition( |
| 320 parameters, |
| 321 body, |
| 322 initializers, |
| 323 context.currentElement.name, definition.isConst) |
| 324 ..element = context.currentElement; |
| 325 } |
| 326 |
| 242 FunctionExpression emitFunction(tree.FunctionDefinition definition, | 327 FunctionExpression emitFunction(tree.FunctionDefinition definition, |
| 243 BuilderContext<Statement> context) { | 328 BuilderContext<Statement> context) { |
| 244 context.currentElement = definition.element; | 329 context.currentElement = definition.element; |
| 245 | 330 |
| 246 Parameters parameters = emitRootParameters(definition, context); | 331 Parameters parameters = emitRootParameters(definition, context); |
| 247 | 332 |
| 248 // Declare parameters. | 333 // Declare parameters. |
| 249 for (tree.Variable param in definition.parameters) { | 334 for (tree.Variable param in definition.parameters) { |
| 250 context.variableNames[param] = param.element.name; | 335 context.variableNames[param] = param.element.name; |
| 251 context.usedVariableNames.add(param.element.name); | 336 context.usedVariableNames.add(param.element.name); |
| 252 context.declaredVariables.add(param); | 337 context.declaredVariables.add(param); |
| 253 } | 338 } |
| 254 | 339 |
| 255 Statement body; | 340 Statement body; |
| 256 if (definition.isAbstract) { | 341 if (definition.isAbstract) { |
| 257 body = new EmptyStatement(); | 342 body = new EmptyStatement(); |
| 258 } else { | 343 } else { |
| 259 context.firstStatement = definition.body; | 344 context.firstStatement = definition.body; |
| 260 visitStatement(definition.body, context); | 345 visitStatement(definition.body, context); |
| 261 context.removeTrailingReturn((Statement statement) { | 346 context.removeTrailingReturn(_recognizeTrailingReturn); |
| 262 if (statement is Return) { | |
| 263 Expression expr = statement.expression; | |
| 264 if (expr is Literal && expr.value.isNull) { | |
| 265 return true; | |
| 266 } | |
| 267 } | |
| 268 return false; | |
| 269 }); | |
| 270 | 347 |
| 271 // Some of the variable declarations have already been added | 348 // Some of the variable declarations have already been added |
| 272 // if their first assignment could be pulled into the initializer. | 349 // if their first assignment could be pulled into the initializer. |
| 273 // Add the remaining variable declarations now. | 350 // Add the remaining variable declarations now. |
| 274 for (tree.Variable variable in context.variableNames.keys) { | 351 for (tree.Variable variable in context.variableNames.keys) { |
| 275 if (!context.declaredVariables.contains(variable)) { | 352 if (!context.declaredVariables.contains(variable)) { |
| 276 context.addDeclaration(variable); | 353 context.addDeclaration(variable); |
| 277 } | 354 } |
| 278 } | 355 } |
| 279 | 356 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 306 return new FunctionExpression( | 383 return new FunctionExpression( |
| 307 parameters, | 384 parameters, |
| 308 body, | 385 body, |
| 309 name: context.currentElement.name, | 386 name: context.currentElement.name, |
| 310 returnType: emitOptionalType(functionType.returnType), | 387 returnType: emitOptionalType(functionType.returnType), |
| 311 isGetter: context.currentElement.isGetter, | 388 isGetter: context.currentElement.isGetter, |
| 312 isSetter: context.currentElement.isSetter) | 389 isSetter: context.currentElement.isSetter) |
| 313 ..element = context.currentElement; | 390 ..element = context.currentElement; |
| 314 } | 391 } |
| 315 | 392 |
| 393 bool _recognizeTrailingReturn(Statement statement) { |
| 394 if (statement is Return) { |
| 395 Expression expr = statement.expression; |
| 396 if (expr == null || expr is Literal && expr.value.isNull) { |
| 397 return true; |
| 398 } |
| 399 } |
| 400 return false; |
| 401 } |
| 402 |
| 316 /// TODO(johnniwinther): Remove this when issue 21283 has been resolved. | 403 /// TODO(johnniwinther): Remove this when issue 21283 has been resolved. |
| 317 int pseudoNameCounter = 0; | 404 int pseudoNameCounter = 0; |
| 318 | 405 |
| 319 Parameter emitParameter(DartType type, | 406 Parameter emitParameter(DartType type, |
| 320 BuilderContext<Statement> context, | 407 BuilderContext<Statement> context, |
| 321 {String name, | 408 {String name, |
| 322 Element element, | 409 Element element, |
| 323 ConstantExpression defaultValue}) { | 410 ConstantExpression defaultValue}) { |
| 324 if (name == null && element != null) { | 411 if (name == null && element != null) { |
| 325 name = element.name; | 412 name = element.name; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 | 616 |
| 530 context.addStatement(new ExpressionStatement(makeAssignment( | 617 context.addStatement(new ExpressionStatement(makeAssignment( |
| 531 visitVariable(stmt.variable, context), | 618 visitVariable(stmt.variable, context), |
| 532 definition))); | 619 definition))); |
| 533 visitStatement(stmt.next, context); | 620 visitStatement(stmt.next, context); |
| 534 } | 621 } |
| 535 | 622 |
| 536 @override | 623 @override |
| 537 void visitReturn(tree.Return stmt, | 624 void visitReturn(tree.Return stmt, |
| 538 BuilderContext<Statement> context) { | 625 BuilderContext<Statement> context) { |
| 539 Expression inner = visitExpression(stmt.value, context); | 626 if (context.currentElement.isGenerativeConstructor && |
| 540 context.addStatement(new Return(inner)); | 627 !context.inInitializer) { |
| 628 assert(() { |
| 629 tree.Expression value = stmt.value; |
| 630 return value is tree.Constant && value.value.isNull; |
| 631 }); |
| 632 context.addStatement(new Return(null)); |
| 633 } else { |
| 634 Expression inner = visitExpression(stmt.value, context); |
| 635 context.addStatement(new Return(inner)); |
| 636 } |
| 541 } | 637 } |
| 542 | 638 |
| 543 @override | 639 @override |
| 544 void visitBreak(tree.Break stmt, | 640 void visitBreak(tree.Break stmt, |
| 545 BuilderContext<Statement> context) { | 641 BuilderContext<Statement> context) { |
| 546 tree.Statement fall = context.fallthrough; | 642 tree.Statement fall = context.fallthrough; |
| 547 if (stmt.target.binding.next == fall) { | 643 if (stmt.target.binding.next == fall) { |
| 548 // Fall through to break target | 644 // Fall through to break target |
| 549 } else if (fall is tree.Break && fall.target == stmt.target) { | 645 } else if (fall is tree.Break && fall.target == stmt.target) { |
| 550 // Fall through to equivalent break | 646 // Fall through to equivalent break |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 } | 740 } |
| 645 | 741 |
| 646 @override | 742 @override |
| 647 Expression visitTypeOperator(tree.TypeOperator exp, | 743 Expression visitTypeOperator(tree.TypeOperator exp, |
| 648 BuilderContext<Statement> context) { | 744 BuilderContext<Statement> context) { |
| 649 return new TypeOperator(visitExpression(exp.receiver, context), | 745 return new TypeOperator(visitExpression(exp.receiver, context), |
| 650 exp.operator, | 746 exp.operator, |
| 651 createTypeAnnotation(exp.type)); | 747 createTypeAnnotation(exp.type)); |
| 652 } | 748 } |
| 653 | 749 |
| 654 List<Argument> emitArguments(tree.Invoke exp, | 750 List<Argument> emitArguments(List<Expression> arguments, |
| 655 BuilderContext<Statement> context) { | 751 Selector selector) { |
| 656 List<tree.Expression> args = exp.arguments; | 752 int positionalArgumentCount = selector.positionalArgumentCount; |
| 657 int positionalArgumentCount = exp.selector.positionalArgumentCount; | |
| 658 List<Argument> result = new List<Argument>.generate(positionalArgumentCount, | 753 List<Argument> result = new List<Argument>.generate(positionalArgumentCount, |
| 659 (i) => visitExpression(exp.arguments[i], context)); | 754 (i) => arguments[i]); |
| 660 for (int i = 0; i < exp.selector.namedArgumentCount; ++i) { | 755 for (int i = 0; i < selector.namedArgumentCount; ++i) { |
| 661 result.add(new NamedArgument(exp.selector.namedArguments[i], | 756 result.add(new NamedArgument(selector.namedArguments[i], |
| 662 visitExpression(exp.arguments[positionalArgumentCount + i], context)))
; | 757 arguments[positionalArgumentCount + i])); |
| 663 } | 758 } |
| 664 return result; | 759 return result; |
| 665 } | 760 } |
| 666 | 761 |
| 762 List<Expression> visitArgumentList(List<tree.Expression> arguments, |
| 763 BuilderContext context) { |
| 764 return arguments |
| 765 .map((tree.Expression argument) => visitExpression(argument, context)) |
| 766 .toList(); |
| 767 } |
| 768 |
| 667 @override | 769 @override |
| 668 Expression visitInvokeStatic(tree.InvokeStatic exp, | 770 Expression visitInvokeStatic(tree.InvokeStatic exp, |
| 669 BuilderContext<Statement> context) { | 771 BuilderContext<Statement> context) { |
| 670 switch (exp.selector.kind) { | 772 switch (exp.selector.kind) { |
| 671 case SelectorKind.GETTER: | 773 case SelectorKind.GETTER: |
| 672 return new Identifier(exp.target.name)..element = exp.target; | 774 return new Identifier(exp.target.name)..element = exp.target; |
| 673 | 775 |
| 674 case SelectorKind.SETTER: | 776 case SelectorKind.SETTER: |
| 675 return new Assignment( | 777 return new Assignment( |
| 676 new Identifier(exp.target.name)..element = exp.target, | 778 new Identifier(exp.target.name)..element = exp.target, |
| 677 '=', | 779 '=', |
| 678 visitExpression(exp.arguments[0], context)); | 780 visitExpression(exp.arguments[0], context)); |
| 679 | 781 |
| 680 case SelectorKind.CALL: | 782 case SelectorKind.CALL: |
| 681 return new CallStatic( | 783 return new CallStatic( |
| 682 null, exp.target.name, emitArguments(exp, context)) | 784 null, exp.target.name, |
| 683 ..element = exp.target; | 785 emitArguments(visitArgumentList(exp.arguments, context), |
| 786 exp.selector)) |
| 787 ..element = exp.target; |
| 684 | 788 |
| 685 default: | 789 default: |
| 686 throw "Unexpected selector kind: ${exp.selector.kind}"; | 790 throw "Unexpected selector kind: ${exp.selector.kind}"; |
| 687 } | 791 } |
| 688 } | 792 } |
| 689 | 793 |
| 690 Expression emitMethodCall(tree.Invoke exp, Receiver receiver, | 794 Expression emitMethodCall(tree.Invoke exp, Receiver receiver, |
| 691 BuilderContext<Statement> context) { | 795 BuilderContext<Statement> context) { |
| 692 List<Argument> args = emitArguments(exp, context); | 796 List<Argument> args = |
| 797 emitArguments(visitArgumentList(exp.arguments, context), exp.selector); |
| 693 switch (exp.selector.kind) { | 798 switch (exp.selector.kind) { |
| 694 case SelectorKind.CALL: | 799 case SelectorKind.CALL: |
| 695 if (exp.selector.name == "call") { | 800 if (exp.selector.name == "call") { |
| 696 return new CallFunction(receiver, args); | 801 return new CallFunction(receiver, args); |
| 697 } | 802 } |
| 698 return new CallMethod(receiver, exp.selector.name, args); | 803 return new CallMethod(receiver, exp.selector.name, args); |
| 699 | 804 |
| 700 case SelectorKind.OPERATOR: | 805 case SelectorKind.OPERATOR: |
| 701 if (args.length == 0) { | 806 if (args.length == 0) { |
| 702 String name = exp.selector.name; | 807 String name = exp.selector.name; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 | 841 |
| 737 @override | 842 @override |
| 738 Expression visitInvokeSuperMethod(tree.InvokeSuperMethod exp, | 843 Expression visitInvokeSuperMethod(tree.InvokeSuperMethod exp, |
| 739 BuilderContext<Statement> context) { | 844 BuilderContext<Statement> context) { |
| 740 return emitMethodCall(exp, new SuperReceiver(), context); | 845 return emitMethodCall(exp, new SuperReceiver(), context); |
| 741 } | 846 } |
| 742 | 847 |
| 743 @override | 848 @override |
| 744 Expression visitInvokeConstructor(tree.InvokeConstructor exp, | 849 Expression visitInvokeConstructor(tree.InvokeConstructor exp, |
| 745 BuilderContext<Statement> context) { | 850 BuilderContext<Statement> context) { |
| 746 List args = emitArguments(exp, context); | 851 List<Argument> args = |
| 852 emitArguments(visitArgumentList(exp.arguments, context), exp.selector); |
| 747 FunctionElement constructor = exp.target; | 853 FunctionElement constructor = exp.target; |
| 748 String name = constructor.name.isEmpty ? null : constructor.name; | 854 String name = constructor.name.isEmpty ? null : constructor.name; |
| 749 return new CallNew(createTypeAnnotation(exp.type), | 855 return new CallNew(createTypeAnnotation(exp.type), |
| 750 args, | 856 args, |
| 751 constructorName: name, | 857 constructorName: name, |
| 752 isConst: exp.constant != null) | 858 isConst: exp.constant != null) |
| 753 ..constructor = constructor | 859 ..constructor = constructor |
| 754 ..dartType = exp.type; | 860 ..dartType = exp.type; |
| 755 } | 861 } |
| 756 | 862 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 FunctionDeclaration decl = new FunctionDeclaration(inner); | 917 FunctionDeclaration decl = new FunctionDeclaration(inner); |
| 812 context.declaredVariables.add(node.variable); | 918 context.declaredVariables.add(node.variable); |
| 813 context.addStatement(decl); | 919 context.addStatement(decl); |
| 814 visitStatement(node.next, context); | 920 visitStatement(node.next, context); |
| 815 } | 921 } |
| 816 | 922 |
| 817 Expression emitConstant(ConstantExpression exp, | 923 Expression emitConstant(ConstantExpression exp, |
| 818 BuilderContext<Statement> context) { | 924 BuilderContext<Statement> context) { |
| 819 return const ConstantEmitter().visit(exp, context); | 925 return const ConstantEmitter().visit(exp, context); |
| 820 } | 926 } |
| 927 |
| 928 List<Statement> buildInInitializerContext(tree.Statement root, |
| 929 BuilderContext context) { |
| 930 BuilderContext inner = new BuilderContext<Statement>.initializer(context); |
| 931 inner.currentElement = context.currentElement; |
| 932 visitStatement(root, inner); |
| 933 List<Statement> bodyParts; |
| 934 for (tree.Variable variable in inner.variableNames.keys) { |
| 935 if (!context.declaredVariables.contains(variable)) { |
| 936 inner.addDeclaration(variable); |
| 937 } |
| 938 } |
| 939 if (inner.variables.length > 0) { |
| 940 bodyParts = new List<Statement>(); |
| 941 bodyParts.add(new VariableDeclarations(inner.variables)); |
| 942 bodyParts.addAll(inner.statements); |
| 943 } else { |
| 944 bodyParts = inner.statements; |
| 945 } |
| 946 return bodyParts; |
| 947 } |
| 948 |
| 949 @override |
| 950 Expression visitFieldInitializer(tree.FieldInitializer node, |
| 951 BuilderContext<Statement> context) { |
| 952 return new FieldInitializer(node.element, |
| 953 ensureExpression(buildInInitializerContext(node.body, context))); |
| 954 } |
| 955 |
| 956 @override |
| 957 Expression visitSuperInitializer(tree.SuperInitializer node, |
| 958 BuilderContext<Statement> context) { |
| 959 List<Argument> arguments = node.arguments.map((tree.Statement argument) { |
| 960 return ensureExpression(buildInInitializerContext(argument, context)); |
| 961 }).toList(); |
| 962 return new SuperInitializer(node.target, |
| 963 emitArguments(arguments, node.selector)); |
| 964 } |
| 821 } | 965 } |
| 822 | 966 |
| 823 /// Like [createTypeAnnotation] except the dynamic type is converted to null. | 967 /// Like [createTypeAnnotation] except the dynamic type is converted to null. |
| 824 TypeAnnotation emitOptionalType(DartType type) { | 968 TypeAnnotation emitOptionalType(DartType type) { |
| 825 if (type.treatAsDynamic) { | 969 if (type.treatAsDynamic) { |
| 826 return null; | 970 return null; |
| 827 } else { | 971 } else { |
| 828 return createTypeAnnotation(type); | 972 return createTypeAnnotation(type); |
| 829 } | 973 } |
| 830 } | 974 } |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); | 1222 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); |
| 1079 | 1223 |
| 1080 ExecutableElement get executableContext => enclosingElement; | 1224 ExecutableElement get executableContext => enclosingElement; |
| 1081 | 1225 |
| 1082 ExecutableElement get memberContext => executableContext.memberContext; | 1226 ExecutableElement get memberContext => executableContext.memberContext; |
| 1083 | 1227 |
| 1084 bool get isLocal => true; | 1228 bool get isLocal => true; |
| 1085 | 1229 |
| 1086 LibraryElement get implementationLibrary => enclosingElement.library; | 1230 LibraryElement get implementationLibrary => enclosingElement.library; |
| 1087 } | 1231 } |
| OLD | NEW |