Chromium Code Reviews| 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/source.dart'; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 | 23 |
| 24 class CpsGeneratingVisitor extends SemanticVisitor<ir.Node> | 24 class CpsGeneratingVisitor extends SemanticVisitor<ir.Node> |
| 25 with IrBuilderMixin { | 25 with IrBuilderMixin { |
| 26 final analyzer.Element element; | 26 final analyzer.Element element; |
| 27 final ElementConverter converter; | 27 final ElementConverter converter; |
| 28 | 28 |
| 29 CpsGeneratingVisitor(this.converter, this.element); | 29 CpsGeneratingVisitor(this.converter, this.element); |
| 30 | 30 |
| 31 Source get currentSource => element.source; | 31 Source get currentSource => element.source; |
| 32 | 32 |
| 33 ir.Node visit(AstNode node) => node != null ? node.accept(this) : null; | |
|
sigurdm
2014/10/20 10:48:32
This is not what I expect "visit" to do - it shoul
Johnni Winther
2014/10/20 12:25:13
Done.
| |
| 34 | |
| 35 /// Returns a closure that takes an [IrBuilder] and visits [node] in its | |
| 36 /// context. | |
| 37 build(AstNode node) { | |
|
sigurdm
2014/10/20 10:48:32
I don't really like the name - the function does n
Johnni Winther
2014/10/20 12:25:13
Done.
| |
| 38 return (IrBuilder builder) => withBuilder(builder, () => visit(node)); | |
| 39 } | |
| 40 | |
| 33 @override | 41 @override |
| 34 ir.FunctionDefinition visitFunctionDeclaration(FunctionDeclaration node) { | 42 ir.FunctionDefinition visitFunctionDeclaration(FunctionDeclaration node) { |
| 35 analyzer.FunctionElement function = node.element; | 43 analyzer.FunctionElement function = node.element; |
| 36 dart2js.FunctionElement element = converter.convertElement(function); | 44 dart2js.FunctionElement element = converter.convertElement(function); |
| 37 return withBuilder( | 45 return withBuilder( |
| 38 new IrBuilder(DART_CONSTANT_SYSTEM, | 46 new IrBuilder(DART_CONSTANT_SYSTEM, |
| 39 element, | 47 element, |
| 40 // TODO(johnniwinther): Supported closure variables. | 48 // TODO(johnniwinther): Supported closure variables. |
| 41 const <dart2js.Local>[]), | 49 const <dart2js.Local>[]), |
| 42 () { | 50 () { |
| 43 function.parameters.forEach((analyzer.ParameterElement parameter) { | 51 function.parameters.forEach((analyzer.ParameterElement parameter) { |
| 44 // TODO(johnniwinther): Support "closure variables", that is variables | 52 // TODO(johnniwinther): Support "closure variables", that is variables |
| 45 // accessed from an inner function. | 53 // accessed from an inner function. |
| 46 irBuilder.createParameter(converter.convertElement(parameter), | 54 irBuilder.createParameter(converter.convertElement(parameter), |
| 47 isClosureVariable: false); | 55 isClosureVariable: false); |
| 48 }); | 56 }); |
| 49 // Visit the body directly to avoid processing the signature as | 57 // Visit the body directly to avoid processing the signature as |
| 50 // expressions. | 58 // expressions. |
| 51 node.functionExpression.body.accept(this); | 59 visit(node.functionExpression.body); |
| 52 return irBuilder.buildFunctionDefinition(element, const []); | 60 return irBuilder.buildFunctionDefinition(element, const []); |
| 53 }); | 61 }); |
| 54 } | 62 } |
| 55 | 63 |
| 56 List<ir.Definition> visitArguments(ArgumentList argumentList) { | 64 List<ir.Definition> visitArguments(ArgumentList argumentList) { |
| 57 List<ir.Definition> arguments = <ir.Definition>[]; | 65 List<ir.Definition> arguments = <ir.Definition>[]; |
| 58 for (Expression argument in argumentList.arguments) { | 66 for (Expression argument in argumentList.arguments) { |
| 59 ir.Definition value = argument.accept(this); | 67 ir.Definition value = visit(argument); |
| 60 if (value == null) { | 68 if (value == null) { |
| 61 giveUp(argument, | 69 giveUp(argument, |
| 62 'Unsupported argument: $argument (${argument.runtimeType}).'); | 70 'Unsupported argument: $argument (${argument.runtimeType}).'); |
| 63 } | 71 } |
| 64 arguments.add(value); | 72 arguments.add(value); |
| 65 } | 73 } |
| 66 return arguments; | 74 return arguments; |
| 67 } | 75 } |
| 68 | 76 |
| 69 @override | 77 @override |
| 70 ir.Primitive visitDynamicInvocation(MethodInvocation node, | 78 ir.Primitive visitDynamicInvocation(MethodInvocation node, |
| 71 AccessSemantics semantics) { | 79 AccessSemantics semantics) { |
| 72 // TODO(johnniwinther): Handle implicit `this`. | 80 // TODO(johnniwinther): Handle implicit `this`. |
| 73 ir.Primitive receiver = semantics.target.accept(this); | 81 ir.Primitive receiver = visit(semantics.target); |
| 74 List<ir.Definition> arguments = visitArguments(node.argumentList); | 82 List<ir.Definition> arguments = visitArguments(node.argumentList); |
| 75 return irBuilder.buildDynamicInvocation( | 83 return irBuilder.buildDynamicInvocation( |
| 76 receiver, | 84 receiver, |
| 77 createSelectorFromMethodInvocation(node, node.methodName.name), | 85 createSelectorFromMethodInvocation(node, node.methodName.name), |
| 78 arguments); | 86 arguments); |
| 79 } | 87 } |
| 80 | 88 |
| 81 @override | 89 @override |
| 82 ir.Primitive visitStaticMethodInvocation(MethodInvocation node, | 90 ir.Primitive visitStaticMethodInvocation(MethodInvocation node, |
| 83 AccessSemantics semantics) { | 91 AccessSemantics semantics) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 return irBuilder.buildStringLiteral(node.value); | 132 return irBuilder.buildStringLiteral(node.value); |
| 125 } | 133 } |
| 126 | 134 |
| 127 @override | 135 @override |
| 128 visitStringInterpolation(StringInterpolation node) { | 136 visitStringInterpolation(StringInterpolation node) { |
| 129 giveUp(node, "String interpolation."); | 137 giveUp(node, "String interpolation."); |
| 130 } | 138 } |
| 131 | 139 |
| 132 @override | 140 @override |
| 133 visitReturnStatement(ReturnStatement node) { | 141 visitReturnStatement(ReturnStatement node) { |
| 134 if (node.expression != null) { | 142 irBuilder.buildReturn(visit(node.expression)); |
| 135 irBuilder.buildReturn(node.expression.accept(this)); | |
| 136 } else { | |
| 137 irBuilder.buildReturn(); | |
| 138 } | |
| 139 } | 143 } |
| 140 | 144 |
| 141 @override | 145 @override |
| 142 ir.Node visitLocalVariableAccess(AstNode node, AccessSemantics semantics) { | 146 ir.Node visitLocalVariableAccess(AstNode node, AccessSemantics semantics) { |
| 143 return handleLocalAccess(node, semantics); | 147 return handleLocalAccess(node, semantics); |
| 144 } | 148 } |
| 145 | 149 |
| 146 @override | 150 @override |
| 147 ir.Node visitParameterAccess(AstNode node, AccessSemantics semantics) { | 151 ir.Node visitParameterAccess(AstNode node, AccessSemantics semantics) { |
| 148 return handleLocalAccess(node, semantics); | 152 return handleLocalAccess(node, semantics); |
| 149 } | 153 } |
| 150 | 154 |
| 151 @override | 155 @override |
| 152 visitVariableDeclaration(VariableDeclaration node) { | 156 visitVariableDeclaration(VariableDeclaration node) { |
| 153 // TODO(johnniwinther): Handle constant local variables. | 157 // TODO(johnniwinther): Handle constant local variables. |
| 154 ir.Node initialValue; | 158 ir.Node initialValue = visit(node.initializer); |
| 155 if (node.initializer != null) { | |
| 156 initialValue = node.initializer.accept(this); | |
| 157 } | |
| 158 irBuilder.declareLocalVariable( | 159 irBuilder.declareLocalVariable( |
| 159 converter.convertElement(node.element), | 160 converter.convertElement(node.element), |
| 160 initialValue: initialValue); | 161 initialValue: initialValue); |
| 161 } | 162 } |
| 162 | 163 |
| 163 ir.Primitive handleLocalAccess(AstNode node, AccessSemantics semantics) { | 164 ir.Primitive handleLocalAccess(AstNode node, AccessSemantics semantics) { |
| 164 analyzer.Element element = semantics.element; | 165 analyzer.Element element = semantics.element; |
| 165 dart2js.Element target = converter.convertElement(element); | 166 dart2js.Element target = converter.convertElement(element); |
| 166 assert(invariant(node, target.isLocal, '$target expected to be local.')); | 167 assert(invariant(node, target.isLocal, '$target expected to be local.')); |
| 167 return irBuilder.buildLocalGet(target); | 168 return irBuilder.buildLocalGet(target); |
| 168 } | 169 } |
| 169 | 170 |
| 170 @override | 171 @override |
| 171 ir.Node visitDynamicAccess(AstNode node, AccessSemantics semantics) { | 172 ir.Node visitDynamicAccess(AstNode node, AccessSemantics semantics) { |
| 172 // TODO(johnniwinther): Handle implicit `this`. | 173 // TODO(johnniwinther): Handle implicit `this`. |
| 173 ir.Primitive receiver = semantics.target.accept(this); | 174 ir.Primitive receiver = visit(semantics.target); |
| 174 return irBuilder.buildDynamicGet(receiver, | 175 return irBuilder.buildDynamicGet(receiver, |
| 175 new Selector.getter(semantics.identifier.name, | 176 new Selector.getter(semantics.identifier.name, |
| 176 converter.convertElement(element.library))); | 177 converter.convertElement(element.library))); |
| 177 } | 178 } |
| 178 | 179 |
| 179 @override | 180 @override |
| 180 ir.Node visitStaticFieldAccess(AstNode node, AccessSemantics semantics) { | 181 ir.Node visitStaticFieldAccess(AstNode node, AccessSemantics semantics) { |
| 181 analyzer.Element element = semantics.element; | 182 analyzer.Element element = semantics.element; |
| 182 dart2js.Element target = converter.convertElement(element); | 183 dart2js.Element target = converter.convertElement(element); |
| 183 // TODO(johnniwinther): Selector information should be computed in the | 184 // TODO(johnniwinther): Selector information should be computed in the |
| 184 // [TreeShaker] and shared with the [CpsGeneratingVisitor]. | 185 // [TreeShaker] and shared with the [CpsGeneratingVisitor]. |
| 185 assert(invariant(node, target.isTopLevel || target.isStatic, | 186 assert(invariant(node, target.isTopLevel || target.isStatic, |
| 186 '$target expected to be top-level or static.')); | 187 '$target expected to be top-level or static.')); |
| 187 return irBuilder.buildStaticGet(target, | 188 return irBuilder.buildStaticGet(target, |
| 188 new Selector.getter(target.name, target.library)); | 189 new Selector.getter(target.name, target.library)); |
| 189 } | 190 } |
| 190 | 191 |
| 191 ir.Primitive handleBinaryExpression(BinaryExpression node, | 192 ir.Primitive handleBinaryExpression(BinaryExpression node, |
| 192 String op) { | 193 String op) { |
| 193 ir.Primitive left = node.leftOperand.accept(this); | 194 ir.Primitive left = visit(node.leftOperand); |
| 194 ir.Primitive right = node.rightOperand.accept(this); | 195 ir.Primitive right = visit(node.rightOperand); |
| 195 Selector selector = new Selector.binaryOperator(op); | 196 Selector selector = new Selector.binaryOperator(op); |
| 196 return irBuilder.buildDynamicInvocation( | 197 return irBuilder.buildDynamicInvocation( |
| 197 left, selector, <ir.Definition>[right]); | 198 left, selector, <ir.Definition>[right]); |
| 198 } | 199 } |
| 199 | 200 |
| 200 ir.Node handleLazyOperator(BinaryExpression node, {bool isLazyOr: false}) { | 201 ir.Node handleLazyOperator(BinaryExpression node, {bool isLazyOr: false}) { |
| 201 ir.Primitive left = node.leftOperand.accept(this); | |
| 202 ir.Primitive buildRightValue(IrBuilder builder) { | |
| 203 return withBuilder(builder, () => node.rightOperand.accept(this)); | |
| 204 } | |
| 205 return irBuilder.buildLogicalOperator( | 202 return irBuilder.buildLogicalOperator( |
| 206 left, buildRightValue, isLazyOr: isLazyOr); | 203 visit(node.leftOperand), |
| 204 build(node.rightOperand), | |
| 205 isLazyOr: isLazyOr); | |
| 207 } | 206 } |
| 208 | 207 |
| 209 @override | 208 @override |
| 210 ir.Node visitBinaryExpression(BinaryExpression node) { | 209 ir.Node visitBinaryExpression(BinaryExpression node) { |
| 211 // TODO(johnniwinther,paulberry,brianwilkerson): The operator should be | 210 // TODO(johnniwinther,paulberry,brianwilkerson): The operator should be |
| 212 // available through an enum. | 211 // available through an enum. |
| 213 String op = node.operator.lexeme; | 212 String op = node.operator.lexeme; |
| 214 switch (op) { | 213 switch (op) { |
| 215 case '||': | 214 case '||': |
| 216 case '&&': | 215 case '&&': |
| 217 return handleLazyOperator(node, isLazyOr: op == '||'); | 216 return handleLazyOperator(node, isLazyOr: op == '||'); |
| 218 case '!=': | 217 case '!=': |
| 219 return irBuilder.buildNegation(handleBinaryExpression(node, '==')); | 218 return irBuilder.buildNegation(handleBinaryExpression(node, '==')); |
| 220 default: | 219 default: |
| 221 return handleBinaryExpression(node, op); | 220 return handleBinaryExpression(node, op); |
| 222 } | 221 } |
| 223 } | 222 } |
| 224 | 223 |
| 225 @override | 224 @override |
| 225 ir.Node visitConditionalExpression(ConditionalExpression node) { | |
| 226 return irBuilder.buildConditional( | |
| 227 visit(node.condition), | |
| 228 build(node.thenExpression), | |
| 229 build(node.elseExpression)); | |
| 230 } | |
| 231 | |
| 232 @override | |
| 226 visitIfStatement(IfStatement node) { | 233 visitIfStatement(IfStatement node) { |
| 227 ir.Primitive condition = node.condition.accept(this); | 234 irBuilder.buildIf( |
| 228 | 235 visit(node.condition), |
| 229 void buildThenPart(IrBuilder thenBuilder) { | 236 build(node.thenStatement), |
| 230 withBuilder(thenBuilder, () => node.thenStatement.accept(this)); | 237 build(node.elseStatement)); |
| 231 } | |
| 232 | |
| 233 void buildElsePart(IrBuilder elseBuilder) { | |
| 234 if (node.elseStatement != null) { | |
| 235 withBuilder(elseBuilder, () => node.elseStatement.accept(this)); | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 irBuilder.buildIf(condition, buildThenPart, buildElsePart); | |
| 240 } | 238 } |
| 241 } | 239 } |
| OLD | NEW |