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

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2435163002: fix #27631, get/set methods no longer shadow index operator (Closed)
Patch Set: Created 4 years, 2 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 2
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 import 'dart:collection' show HashMap, HashSet; 6 import 'dart:collection' show HashMap, HashSet;
7 import 'dart:math' show min, max; 7 import 'dart:math' show min, max;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 4463 matching lines...) Expand 10 before | Expand all | Expand 10 after
4474 4474
4475 if (op.lexeme == '++' || op.lexeme == '--') { 4475 if (op.lexeme == '++' || op.lexeme == '--') {
4476 // Increment or decrement requires expansion. 4476 // Increment or decrement requires expansion.
4477 // Desugar `++x` as `x = x + 1`, ensuring that if `x` has subexpressions 4477 // Desugar `++x` as `x = x + 1`, ensuring that if `x` has subexpressions
4478 // (for example, x is IndexExpression) we evaluate those once. 4478 // (for example, x is IndexExpression) we evaluate those once.
4479 var one = AstBuilder.integerLiteral(1)..staticType = types.intType; 4479 var one = AstBuilder.integerLiteral(1)..staticType = types.intType;
4480 return _emitOpAssign(expr, one, op.lexeme[0], node.staticElement, 4480 return _emitOpAssign(expr, one, op.lexeme[0], node.staticElement,
4481 context: expr); 4481 context: expr);
4482 } 4482 }
4483 4483
4484 return _emitSend(expr, op.lexeme[0], []); 4484 var operatorName = op.lexeme;
4485 if (operatorName == '-') operatorName = 'unary-';
Bob Nystrom 2016/10/20 21:01:13 Is "unary-" just used as a magic string for _emitM
Jennifer Messerly 2016/10/20 22:45:04 it's not. It's defined by the Dart language spec a
4486 return _emitSend(expr, operatorName, []);
4485 } 4487 }
4486 4488
4487 // Cascades can contain [IndexExpression], [MethodInvocation] and 4489 // Cascades can contain [IndexExpression], [MethodInvocation] and
4488 // [PropertyAccess]. The code generation for those is handled in their 4490 // [PropertyAccess]. The code generation for those is handled in their
4489 // respective visit methods. 4491 // respective visit methods.
4490 @override 4492 @override
4491 JS.Node visitCascadeExpression(CascadeExpression node) { 4493 JS.Node visitCascadeExpression(CascadeExpression node) {
4492 var savedCascadeTemp = _cascadeTarget; 4494 var savedCascadeTemp = _cascadeTarget;
4493 4495
4494 var vars = <JS.MetaLetVariable, JS.Expression>{}; 4496 var vars = <JS.MetaLetVariable, JS.Expression>{};
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
4707 } 4709 }
4708 4710
4709 /// Emits a generic send, like an operator method. 4711 /// Emits a generic send, like an operator method.
4710 /// 4712 ///
4711 /// **Please note** this function does not support method invocation syntax 4713 /// **Please note** this function does not support method invocation syntax
4712 /// `obj.name(args)` because that could be a getter followed by a call. 4714 /// `obj.name(args)` because that could be a getter followed by a call.
4713 /// See [visitMethodInvocation]. 4715 /// See [visitMethodInvocation].
4714 JS.Expression _emitSend( 4716 JS.Expression _emitSend(
4715 Expression target, String name, List<Expression> args) { 4717 Expression target, String name, List<Expression> args) {
4716 var type = getStaticType(target); 4718 var type = getStaticType(target);
4717 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type); 4719 var memberName = _emitMemberName(name, type: type);
4718 if (isDynamicInvoke(target)) { 4720 if (isDynamicInvoke(target)) {
4719 if (_inWhitelistCode(target)) { 4721 if (_inWhitelistCode(target)) {
4720 var vars = <JS.MetaLetVariable, JS.Expression>{}; 4722 var vars = <JS.MetaLetVariable, JS.Expression>{};
4721 var l = _visit(_bindValue(vars, 'l', target)); 4723 var l = _visit(_bindValue(vars, 'l', target));
4722 return new JS.MetaLet(vars, [ 4724 return new JS.MetaLet(vars, [
4723 js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).call(#, #)', 4725 js.call('(#[(#[dart._extensionType]) ? dartx[#] : #]).call(#, #)',
4724 [l, l, memberName, memberName, l, _visitList(args)]) 4726 [l, l, memberName, memberName, l, _visitList(args)])
4725 ]); 4727 ]);
4726 } 4728 }
4727 // dynamic dispatch 4729 // dynamic dispatch
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
5219 /// directly rather than computing the relevant options for [_emitMemberName]. 5221 /// directly rather than computing the relevant options for [_emitMemberName].
5220 JS.Expression _elementMemberName(ExecutableElement e, {bool useExtension}) { 5222 JS.Expression _elementMemberName(ExecutableElement e, {bool useExtension}) {
5221 String name; 5223 String name;
5222 if (e is PropertyAccessorElement) { 5224 if (e is PropertyAccessorElement) {
5223 name = e.variable.name; 5225 name = e.variable.name;
5224 } else { 5226 } else {
5225 name = e.name; 5227 name = e.name;
5226 } 5228 }
5227 return _emitMemberName(name, 5229 return _emitMemberName(name,
5228 type: (e.enclosingElement as ClassElement).type, 5230 type: (e.enclosingElement as ClassElement).type,
5229 unary: e.parameters.isEmpty,
5230 isStatic: e.isStatic, 5231 isStatic: e.isStatic,
5231 useExtension: useExtension); 5232 useExtension: useExtension);
5232 } 5233 }
5233 5234
5234 /// This handles member renaming for private names and operators. 5235 /// This handles member renaming for private names and operators.
5235 /// 5236 ///
5236 /// Private names are generated using ES6 symbols: 5237 /// Private names are generated using ES6 symbols:
5237 /// 5238 ///
5238 /// // At the top of the module: 5239 /// // At the top of the module:
5239 /// let _x = Symbol('_x'); 5240 /// let _x = Symbol('_x');
(...skipping 19 matching lines...) Expand all
5259 /// 5260 ///
5260 /// There are three exceptions: [], []= and unary -. 5261 /// There are three exceptions: [], []= and unary -.
5261 /// The indexing operators we use `get` and `set` instead: 5262 /// The indexing operators we use `get` and `set` instead:
5262 /// 5263 ///
5263 /// x.get('hi') 5264 /// x.get('hi')
5264 /// x.set('hi', 123) 5265 /// x.set('hi', 123)
5265 /// 5266 ///
5266 /// This follows the same pattern as ECMAScript 6 Map: 5267 /// This follows the same pattern as ECMAScript 6 Map:
5267 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> 5268 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map>
5268 /// 5269 ///
5269 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed 5270 /// Unary minus looks like: `x._negate()`. Note that [unary] must be passed
Bob Nystrom 2016/10/20 21:01:13 Can you update the part of the doc around "[unary]
Jennifer Messerly 2016/10/20 22:45:04 Done.
5270 /// for this transformation to happen, otherwise binary minus is assumed. 5271 /// for this transformation to happen, otherwise binary minus is assumed.
5271 /// 5272 ///
5272 /// Equality is a bit special, it is generated via the Dart `equals` runtime 5273 /// Equality is a bit special, it is generated via the Dart `equals` runtime
5273 /// helper, that checks for null. The user defined method is called '=='. 5274 /// helper, that checks for null. The user defined method is called '=='.
5274 /// 5275 ///
5275 JS.Expression _emitMemberName(String name, 5276 JS.Expression _emitMemberName(String name,
5276 {DartType type, 5277 {DartType type, bool isStatic: false, bool useExtension}) {
5277 bool unary: false,
5278 bool isStatic: false,
5279 bool useExtension}) {
5280 // Static members skip the rename steps. 5278 // Static members skip the rename steps.
5281 if (isStatic) return _propertyName(name); 5279 if (isStatic) return _propertyName(name);
5282 5280
5283 if (name.startsWith('_')) { 5281 if (name.startsWith('_')) {
5284 return _emitPrivateNameSymbol(currentLibrary, name); 5282 return _emitPrivateNameSymbol(currentLibrary, name);
5285 } 5283 }
5286 5284
5285 // When generating synthetic names, we use _ as the prefix, since Dart names
5286 // won't have this (eliminated above), nor will static names reach here.
5287 if (name == '[]') { 5287 if (name == '[]') {
kevmoo 2016/10/20 20:06:03 better as a switch, no?
Jennifer Messerly 2016/10/20 20:12:14 I tend to find Dart's C-style switch clunky, e.g.
Bob Nystrom 2016/10/20 21:01:13 If it was my code, I'd probably use switch () to h
5288 name = 'get'; 5288 name = '_get';
5289 } else if (name == '[]=') { 5289 } else if (name == '[]=') {
5290 name = 'set'; 5290 name = '_set';
5291 } else if (name == '-' && unary) { 5291 } else if (name == 'unary-') {
5292 name = 'unary-'; 5292 name = '_negate';
5293 } else if (name == 'constructor' || name == 'prototype') { 5293 } else if (name == 'constructor' || name == 'prototype') {
5294 // This uses an illegal (in Dart) character for a member, avoiding the 5294 name = '_$name';
5295 // conflict. We could use practically any character for this.
5296 name = '+$name';
5297 } 5295 }
5298 5296
5299 var result = _propertyName(name); 5297 var result = _propertyName(name);
5300 5298
5301 if (useExtension == null) { 5299 if (useExtension == null) {
5302 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. 5300 // Dart "extension" methods. Used for JS Array, Boolean, Number, String.
5303 var baseType = type; 5301 var baseType = type;
5304 while (baseType is TypeParameterType) { 5302 while (baseType is TypeParameterType) {
5305 baseType = (baseType.element as TypeParameterElement).bound; 5303 baseType = (baseType.element as TypeParameterElement).bound;
5306 } 5304 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
5519 } 5517 }
5520 5518
5521 bool isLibraryPrefix(Expression node) => 5519 bool isLibraryPrefix(Expression node) =>
5522 node is SimpleIdentifier && node.staticElement is PrefixElement; 5520 node is SimpleIdentifier && node.staticElement is PrefixElement;
5523 5521
5524 LibraryElement _getLibrary(AnalysisContext c, String uri) => 5522 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
5525 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 5523 c.computeLibraryElement(c.sourceFactory.forUri(uri));
5526 5524
5527 bool _isDartRuntime(LibraryElement l) => 5525 bool _isDartRuntime(LibraryElement l) =>
5528 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 5526 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/js/legacy/dart_sdk.js ('k') | pkg/dev_compiler/test/codegen_expected/BenchmarkBase.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698