| 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 analyzer2dart.cps_generator; | 5 library analyzer2dart.cps_generator; |
| 6 | 6 |
| 7 import 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
| 8 | 8 |
| 9 import 'package:compiler/implementation/elements/elements.dart' as dart2js; | 9 import 'package:compiler/implementation/elements/elements.dart' as dart2js; |
| 10 import 'package:analyzer/src/generated/source.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart' as analyzer; | 11 import 'package:analyzer/src/generated/element.dart' as analyzer; |
| 11 | 12 |
| 12 import 'package:compiler/implementation/cps_ir/cps_ir_nodes.dart' as ir; | 13 import 'package:compiler/implementation/cps_ir/cps_ir_nodes.dart' as ir; |
| 13 import 'package:compiler/implementation/cps_ir/cps_ir_builder.dart'; | 14 import 'package:compiler/implementation/cps_ir/cps_ir_builder.dart'; |
| 15 import 'package:compiler/implementation/universe/universe.dart'; |
| 14 | 16 |
| 17 import 'semantic_visitor.dart'; |
| 15 import 'element_converter.dart'; | 18 import 'element_converter.dart'; |
| 16 import 'tree_shaker.dart'; | 19 import 'util.dart'; |
| 20 import 'package:analyzer2dart/src/identifier_semantics.dart'; |
| 17 | 21 |
| 18 | 22 class CpsGeneratingVisitor extends SemanticVisitor<ir.Node> { |
| 19 class CpsGeneratingVisitor extends RecursiveAstVisitor<ir.Node> { | 23 final analyzer.Element element; |
| 20 final ElementConverter converter; | 24 final ElementConverter converter; |
| 21 final IrBuilder irBuilder = new IrBuilder(); | 25 final IrBuilder irBuilder = new IrBuilder(); |
| 22 | 26 |
| 23 CpsGeneratingVisitor(this.converter); | 27 CpsGeneratingVisitor(this.converter, this.element); |
| 24 | 28 |
| 25 giveUp(String reason) { | 29 Source get currentSource => element.source; |
| 26 throw new UnsupportedError(reason); | |
| 27 } | |
| 28 | 30 |
| 29 @override | 31 @override |
| 30 ir.FunctionDefinition visitFunctionDeclaration(FunctionDeclaration node) { | 32 ir.FunctionDefinition visitFunctionDeclaration(FunctionDeclaration node) { |
| 31 analyzer.FunctionElement function = node.element; | 33 analyzer.FunctionElement function = node.element; |
| 32 function.parameters.forEach((analyzer.ParameterElement parameter) { | 34 function.parameters.forEach((analyzer.ParameterElement parameter) { |
| 33 // TODO(johnniwinther): Support "closure variables", that is variables | 35 // TODO(johnniwinther): Support "closure variables", that is variables |
| 34 // accessed from an inner function. | 36 // accessed from an inner function. |
| 35 irBuilder.createParameter(converter.convertElement(parameter), | 37 irBuilder.createParameter(converter.convertElement(parameter), |
| 36 isClosureVariable: false); | 38 isClosureVariable: false); |
| 37 }); | 39 }); |
| 38 // Visit the body directly to avoid processing the signature as expressions. | 40 // Visit the body directly to avoid processing the signature as expressions. |
| 39 node.functionExpression.body.accept(this); | 41 node.functionExpression.body.accept(this); |
| 40 return irBuilder.buildFunctionDefinition( | 42 return irBuilder.buildFunctionDefinition( |
| 41 converter.convertElement(function), const [], const []); | 43 converter.convertElement(function), const [], const []); |
| 42 } | 44 } |
| 43 | 45 |
| 44 @override | 46 @override |
| 45 visitMethodInvocation(MethodInvocation node) { | 47 visitStaticMethodInvocation(MethodInvocation node, |
| 46 analyzer.Element staticElement = node.methodName.staticElement; | 48 AccessSemantics semantics) { |
| 47 if (staticElement != null) { | 49 analyzer.Element staticElement = semantics.element; |
| 48 dart2js.Element element = converter.convertElement(staticElement); | 50 dart2js.Element element = converter.convertElement(staticElement); |
| 49 List<ir.Definition> arguments = <ir.Definition>[]; | 51 List<ir.Definition> arguments = <ir.Definition>[]; |
| 50 for (Expression argument in node.argumentList.arguments) { | 52 for (Expression argument in node.argumentList.arguments) { |
| 51 ir.Definition value = argument.accept(this); | 53 ir.Definition value = argument.accept(this); |
| 52 if (value == null) { | 54 if (value == null) { |
| 53 giveUp('Unsupported argument: $argument (${argument.runtimeType}).'); | 55 giveUp(argument, |
| 54 } | 56 'Unsupported argument: $argument (${argument.runtimeType}).'); |
| 55 arguments.add(value); | |
| 56 } | 57 } |
| 57 return irBuilder.buildStaticInvocation( | 58 arguments.add(value); |
| 58 element, createSelectorFromMethodInvocation(node), arguments); | |
| 59 } | 59 } |
| 60 return irBuilder.buildStaticInvocation( |
| 61 element, |
| 62 createSelectorFromMethodInvocation(node, node.methodName.name), |
| 63 arguments); |
| 60 } | 64 } |
| 61 | 65 |
| 62 @override | 66 @override |
| 63 ir.Constant visitNullLiteral(NullLiteral node) { | 67 ir.Constant visitNullLiteral(NullLiteral node) { |
| 64 return irBuilder.buildNullLiteral(); | 68 return irBuilder.buildNullLiteral(); |
| 65 } | 69 } |
| 66 | 70 |
| 67 @override | 71 @override |
| 68 ir.Constant visitBooleanLiteral(BooleanLiteral node) { | 72 ir.Constant visitBooleanLiteral(BooleanLiteral node) { |
| 69 return irBuilder.buildBooleanLiteral(node.value); | 73 return irBuilder.buildBooleanLiteral(node.value); |
| 70 } | 74 } |
| 71 | 75 |
| 72 @override | 76 @override |
| 73 ir.Constant visitDoubleLiteral(DoubleLiteral node) { | 77 ir.Constant visitDoubleLiteral(DoubleLiteral node) { |
| 74 return irBuilder.buildDoubleLiteral(node.value); | 78 return irBuilder.buildDoubleLiteral(node.value); |
| 75 } | 79 } |
| 76 | 80 |
| 77 @override | 81 @override |
| 78 ir.Constant visitIntegerLiteral(IntegerLiteral node) { | 82 ir.Constant visitIntegerLiteral(IntegerLiteral node) { |
| 79 return irBuilder.buildIntegerLiteral(node.value); | 83 return irBuilder.buildIntegerLiteral(node.value); |
| 80 } | 84 } |
| 81 | 85 |
| 82 @override | 86 @override |
| 83 visitAdjacentStrings(AdjacentStrings node) { | 87 visitAdjacentStrings(AdjacentStrings node) { |
| 84 String value = node.stringValue; | 88 String value = node.stringValue; |
| 85 if (value != null) { | 89 if (value != null) { |
| 86 return irBuilder.buildStringLiteral(value); | 90 return irBuilder.buildStringLiteral(value); |
| 87 } | 91 } |
| 88 giveUp("Non constant adjacent strings."); | 92 giveUp(node, "Non constant adjacent strings."); |
| 89 } | 93 } |
| 90 | 94 |
| 91 @override | 95 @override |
| 92 ir.Constant visitSimpleStringLiteral(SimpleStringLiteral node) { | 96 ir.Constant visitSimpleStringLiteral(SimpleStringLiteral node) { |
| 93 return irBuilder.buildStringLiteral(node.value); | 97 return irBuilder.buildStringLiteral(node.value); |
| 94 } | 98 } |
| 95 | 99 |
| 96 @override | 100 @override |
| 97 visitStringInterpolation(StringInterpolation node) { | 101 visitStringInterpolation(StringInterpolation node) { |
| 98 giveUp("String interpolation."); | 102 giveUp(node, "String interpolation."); |
| 99 } | 103 } |
| 100 | 104 |
| 101 @override | 105 @override |
| 102 visitReturnStatement(ReturnStatement node) { | 106 visitReturnStatement(ReturnStatement node) { |
| 103 if (node.expression != null) { | 107 if (node.expression != null) { |
| 104 irBuilder.buildReturn(node.expression.accept(this)); | 108 irBuilder.buildReturn(node.expression.accept(this)); |
| 105 } else { | 109 } else { |
| 106 irBuilder.buildReturn(); | 110 irBuilder.buildReturn(); |
| 107 } | 111 } |
| 108 } | 112 } |
| 109 | 113 |
| 110 @override | 114 @override |
| 111 visitSimpleIdentifier(SimpleIdentifier node) { | 115 ir.Node visitLocalVariableAccess(AstNode node, AccessSemantics semantics) { |
| 112 analyzer.Element element = node.staticElement; | 116 return handleLocalAccess(node, semantics); |
| 113 if (element != null) { | 117 } |
| 114 dart2js.Element target = converter.convertElement(element); | 118 |
| 115 if (dart2js.Elements.isLocal(target)) { | 119 @override |
| 116 return irBuilder.buildGetLocal(target); | 120 ir.Node visitParameterAccess(AstNode node, AccessSemantics semantics) { |
| 117 } | 121 return handleLocalAccess(node, semantics); |
| 118 giveUp('Unhandled static reference: ' | 122 } |
| 119 '$node -> $target (${target.runtimeType})'); | 123 |
| 120 } | 124 ir.Primitive handleLocalAccess(AstNode node, AccessSemantics semantics) { |
| 121 giveUp('Unresolved identifier: $node.'); | 125 analyzer.Element element = semantics.element; |
| 126 dart2js.Element target = converter.convertElement(element); |
| 127 assert(invariant(node, target.isLocal, '$target expected to be local.')); |
| 128 return irBuilder.buildGetLocal(target); |
| 129 } |
| 130 |
| 131 @override |
| 132 ir.Node visitStaticFieldAccess(AstNode node, AccessSemantics semantics) { |
| 133 analyzer.Element element = semantics.element; |
| 134 dart2js.Element target = converter.convertElement(element); |
| 135 // TODO(johnniwinther): Selector information should be computed in the |
| 136 // [TreeShaker] and shared with the [CpsGeneratingVisitor]. |
| 137 assert(invariant(node, target.isTopLevel || target.isStatic, |
| 138 '$target expected to be top-level or static.')); |
| 139 return irBuilder.buildGetStatic(target, |
| 140 new Selector.getter(target.name, target.library)); |
| 122 } | 141 } |
| 123 } | 142 } |
| OLD | NEW |