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

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10916002: Change switch to give errors when cases don't follow the newest syntax. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 3120 matching lines...) Expand 10 before | Expand all | Expand 10 after
3131 } 3131 }
3132 startBlock.setBlockFlow( 3132 startBlock.setBlockFlow(
3133 new HLabeledBlockInformation.implicit( 3133 new HLabeledBlockInformation.implicit(
3134 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)), 3134 new HSubGraphBlockInformation(new SubGraph(startBlock, lastBlock)),
3135 elements[node]), 3135 elements[node]),
3136 joinBlock); 3136 joinBlock);
3137 jumpHandler.close(); 3137 jumpHandler.close();
3138 } 3138 }
3139 3139
3140 bool tryBuildConstantSwitch(SwitchStatement node) { 3140 bool tryBuildConstantSwitch(SwitchStatement node) {
3141 // TODO(lrn): Move the constant resolution to the resolver, so
3142 // we can report an error before reaching the backend.
3141 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>(); 3143 Map<CaseMatch, Constant> constants = new Map<CaseMatch, Constant>();
3142 // First check whether all case expressions are compile-time constants. 3144 // First check whether all case expressions are compile-time constants,
3145 // and all have the same type that doesn't override operator==.
3146 Constant firstConstant = null;
3147 bool failure = false;
3143 for (SwitchCase switchCase in node.cases) { 3148 for (SwitchCase switchCase in node.cases) {
3144 for (Node labelOrCase in switchCase.labelsAndCases) { 3149 for (Node labelOrCase in switchCase.labelsAndCases) {
3145 if (labelOrCase is CaseMatch) { 3150 if (labelOrCase is CaseMatch) {
3146 CaseMatch match = labelOrCase; 3151 CaseMatch match = labelOrCase;
3147 Constant constant = 3152 Constant constant =
3148 compiler.constantHandler.tryCompileNodeWithDefinitions( 3153 compiler.constantHandler.tryCompileNodeWithDefinitions(
3149 match.expression, elements); 3154 match.expression, elements);
3150 if (constant === null) return false; 3155 if (constant === null) {
3156 compiler.reportWarning(match.expression,
3157 MessageKind.NOT_A_COMPILE_TIME_CONSTANT.error());
3158 failure = true;
3159 continue;
3160 }
3161 if (firstConstant == null) {
3162 firstConstant = constant;
3163 if (nonPrimitiveTypeOverridesEquals(constant)) {
3164 compiler.reportWarning(match.expression,
3165 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS.error());
3166 failure = true;
3167 }
3168 } else {
3169 if (!constant.isSameType(firstConstant)) {
3170 compiler.reportWarning(match.expression,
3171 MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL.error());
3172 failure = true;
3173 }
3174 }
3151 constants[labelOrCase] = constant; 3175 constants[labelOrCase] = constant;
3152 } else { 3176 } else {
3153 // We don't handle labels yet. 3177 compiler.reportWarning(node, "Unsupported: Labels on cases");
3154 return false; 3178 failure = true;
3155 } 3179 }
3156 } 3180 }
3157 } 3181 }
3182 if (failure) {
3183 return false;
3184 }
3185
3158 // TODO(ngeoffray): Handle switch-instruction in bailout code. 3186 // TODO(ngeoffray): Handle switch-instruction in bailout code.
3159 work.allowSpeculativeOptimization = false; 3187 work.allowSpeculativeOptimization = false;
3160 // Then build a switch structure. 3188 // Then build a switch structure.
3161 HBasicBlock expressionStart = openNewBlock(); 3189 HBasicBlock expressionStart = openNewBlock();
3162 visit(node.expression); 3190 visit(node.expression);
3163 HInstruction expression = pop(); 3191 HInstruction expression = pop();
3164 if (node.cases.isEmpty()) { 3192 if (node.cases.isEmpty()) {
3165 return true; 3193 return true;
3166 } 3194 }
3167 HBasicBlock expressionEnd = current; 3195 HBasicBlock expressionEnd = current;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3259 statements, 3287 statements,
3260 hasDefault, 3288 hasDefault,
3261 jumpHandler.target, 3289 jumpHandler.target,
3262 jumpHandler.labels()), 3290 jumpHandler.labels()),
3263 joinBlock); 3291 joinBlock);
3264 3292
3265 jumpHandler.close(); 3293 jumpHandler.close();
3266 return true; 3294 return true;
3267 } 3295 }
3268 3296
3297 bool nonPrimitiveTypeOverridesEquals(Constant constant) {
3298 // If constant is primitive, just return false. We know
3299 // about the equals methods of num/String classes.
3300 // [Map] and [List] does not override equals.
floitsch 2012/08/30 14:08:18 do not
Lasse Reichstein Nielsen 2012/09/03 09:12:56 Done.
3301 if (!constant.isConstructedObject()) return false;
3302
3303 ConstructedConstant constructedConstant = constant;
3304 Type type = constructedConstant.type;
3305 assert(type !== null);
3306 Element element = type.element;
ngeoffray 2012/08/30 07:29:13 The code below probably deserves to be in a helper
Lasse Reichstein Nielsen 2012/08/30 10:54:25 Any wish for the abstraction level? isOverridingEq
ngeoffray 2012/08/30 11:07:13 I like the three of them :) The first two are easy
Lasse Reichstein Nielsen 2012/09/03 09:12:56 I went with typeOverridesObjectEquals and lookup
3307 // If the type is not a class, we'll just assume it overrides
3308 // operator==. Typedefs do, since [Function] does.
3309 if (!element.isClass()) return true;
3310 ClassElement classElement = element;
3311 SourceString dartMethodName = Elements.constructOperatorName(
3312 const SourceString('operator'),
3313 const SourceString('=='));
3314 Element operatorEq = classElement.lookupMember(dartMethodName);
3315 if (operatorEq == null) return false;
3316 // If the operator== declaration is in Object, it's not overridden.
3317 return (operatorEq.getEnclosingClass() != compiler.objectClass);
3318 }
3319
3269 3320
3270 // Recursively build an if/else structure to match the cases. 3321 // Recursively build an if/else structure to match the cases.
3271 void buildSwitchCases(Link<Node> cases, HInstruction expression, 3322 void buildSwitchCases(Link<Node> cases, HInstruction expression,
3272 [int encounteredCaseTypes = 0]) { 3323 [int encounteredCaseTypes = 0]) {
3273 final int NO_TYPE = 0; 3324 final int NO_TYPE = 0;
3274 final int INT_TYPE = 1; 3325 final int INT_TYPE = 1;
3275 final int STRING_TYPE = 2; 3326 final int STRING_TYPE = 2;
3276 final int CONFLICT_TYPE = 3; 3327 final int CONFLICT_TYPE = 3;
3277 int combine(int type1, int type2) => type1 | type2; 3328 int combine(int type1, int type2) => type1 | type2;
3278 3329
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3319 Element equalsHelper = interceptors.getEqualsInterceptor(); 3370 Element equalsHelper = interceptors.getEqualsInterceptor();
3320 HInstruction target = new HStatic(equalsHelper); 3371 HInstruction target = new HStatic(equalsHelper);
3321 add(target); 3372 add(target);
3322 CaseMatch match = remainingCases.head; 3373 CaseMatch match = remainingCases.head;
3323 // TODO(lrn): Move the constant resolution to the resolver, so 3374 // TODO(lrn): Move the constant resolution to the resolver, so
3324 // we can report an error before reaching the backend. 3375 // we can report an error before reaching the backend.
3325 Constant constant = 3376 Constant constant =
3326 compiler.constantHandler.tryCompileNodeWithDefinitions( 3377 compiler.constantHandler.tryCompileNodeWithDefinitions(
3327 match.expression, elements); 3378 match.expression, elements);
3328 if (constant !== null) { 3379 if (constant !== null) {
3329 if (constant.isInt()) {
3330 // Report the first mixed-string/int type error only.
3331 if (encounteredCaseTypes == STRING_TYPE) {
3332 compiler.reportWarning(
3333 match, MessageKind.INVALID_CASE_EXPRESSION_TYPE);
3334 }
3335 encounteredCaseTypes = combine(encounteredCaseTypes, INT_TYPE);
3336 } else if (constant.isString()) {
3337 if (encounteredCaseTypes == INT_TYPE) {
3338 compiler.reportWarning(
3339 match, MessageKind.INVALID_CASE_EXPRESSION_TYPE);
3340 }
3341 encounteredCaseTypes = combine(encounteredCaseTypes, STRING_TYPE);
3342 } else {
3343 compiler.reportWarning(match,
3344 MessageKind.INVALID_CASE_EXPRESSION);
3345 encounteredCaseTypes = CONFLICT_TYPE;
3346 }
3347 stack.add(graph.addConstant(constant)); 3380 stack.add(graph.addConstant(constant));
3348 } else { 3381 } else {
3349 // TODO(lrn): Remove this else branch, and make the constant
3350 // evaluation mandatory when we are ready to break existing code using
3351 // non constant-int-or-string expressions.
3352 compiler.reportWarning(match,
3353 'case expressions not compile-time constant int or string.');
3354 visit(match.expression); 3382 visit(match.expression);
3355 encounteredCaseTypes = CONFLICT_TYPE;
3356 } 3383 }
3357 push(new HEquals(target, pop(), expression)); 3384 push(new HEquals(target, pop(), expression));
3358 } 3385 }
3359 3386
3360 // If this is the last expression, just return it. 3387 // If this is the last expression, just return it.
3361 Link<Node> tail = skipLabels(remainingCases.tail); 3388 Link<Node> tail = skipLabels(remainingCases.tail);
3362 if (tail.isEmpty()) { 3389 if (tail.isEmpty()) {
3363 left(); 3390 left();
3364 return; 3391 return;
3365 } 3392 }
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
3939 new HSubGraphBlockInformation(elseBranch.graph)); 3966 new HSubGraphBlockInformation(elseBranch.graph));
3940 3967
3941 HBasicBlock conditionStartBlock = conditionBranch.block; 3968 HBasicBlock conditionStartBlock = conditionBranch.block;
3942 conditionStartBlock.setBlockFlow(info, joinBlock); 3969 conditionStartBlock.setBlockFlow(info, joinBlock);
3943 SubGraph conditionGraph = conditionBranch.graph; 3970 SubGraph conditionGraph = conditionBranch.graph;
3944 HIf branch = conditionGraph.end.last; 3971 HIf branch = conditionGraph.end.last;
3945 assert(branch is HIf); 3972 assert(branch is HIf);
3946 branch.blockInformation = conditionStartBlock.blockFlow; 3973 branch.blockInformation = conditionStartBlock.blockFlow;
3947 } 3974 }
3948 } 3975 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698