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

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

Issue 2979353002: implement `Invocation.typeArguments` in DDC (Closed)
Patch Set: fix Created 3 years, 5 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 1376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 var type = element.type; 1387 var type = element.type;
1388 var virtualFields = _classProperties.virtualFields; 1388 var virtualFields = _classProperties.virtualFields;
1389 1389
1390 var jsMethods = <JS.Method>[]; 1390 var jsMethods = <JS.Method>[];
1391 bool hasJsPeer = findAnnotation(element, isJsPeerInterface) != null; 1391 bool hasJsPeer = findAnnotation(element, isJsPeerInterface) != null;
1392 bool hasIterator = false; 1392 bool hasIterator = false;
1393 1393
1394 if (type.isObject) { 1394 if (type.isObject) {
1395 // Dart does not use ES6 constructors. 1395 // Dart does not use ES6 constructors.
1396 // Add an error to catch any invalid usage. 1396 // Add an error to catch any invalid usage.
1397 jsMethods.add(new JS.Method( 1397 jsMethods.add(
1398 _propertyName('constructor'), 1398 new JS.Method(_propertyName('constructor'), js.call(r'''function() {
1399 js.call(
1400 r'''function() {
1401 throw Error("use `new " + #.typeName(#.getReifiedType(this)) + 1399 throw Error("use `new " + #.typeName(#.getReifiedType(this)) +
1402 ".new(...)` to create a Dart object"); 1400 ".new(...)` to create a Dart object");
1403 }''', 1401 }''', [_runtimeModule, _runtimeModule])));
1404 [_runtimeModule, _runtimeModule])));
1405 } 1402 }
1406 for (var m in node.members) { 1403 for (var m in node.members) {
1407 if (m is ConstructorDeclaration) { 1404 if (m is ConstructorDeclaration) {
1408 if (m.factoryKeyword != null && !_externalOrNative(m)) { 1405 if (m.factoryKeyword != null && !_externalOrNative(m)) {
1409 jsMethods.add(_emitFactoryConstructor(m)); 1406 jsMethods.add(_emitFactoryConstructor(m));
1410 } 1407 }
1411 } else if (m is MethodDeclaration) { 1408 } else if (m is MethodDeclaration) {
1412 jsMethods.add(_emitMethodDeclaration(type, m)); 1409 jsMethods.add(_emitMethodDeclaration(type, m));
1413 1410
1414 if (m.element is PropertyAccessorElement) { 1411 if (m.element is PropertyAccessorElement) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 1612
1616 positionalArgs = new JS.ArrayInitializer([]); 1613 positionalArgs = new JS.ArrayInitializer([]);
1617 } else if (property.isSetter) { 1614 } else if (property.isSetter) {
1618 addProperty('isSetter', js.boolean(true)); 1615 addProperty('isSetter', js.boolean(true));
1619 1616
1620 fnArgs.add(args); 1617 fnArgs.add(args);
1621 positionalArgs = new JS.ArrayInitializer([args]); 1618 positionalArgs = new JS.ArrayInitializer([args]);
1622 } 1619 }
1623 } 1620 }
1624 1621
1622 var typeParams = _emitTypeFormals(method.type.typeFormals);
1623 if (typeParams.isNotEmpty) {
1624 addProperty('typeArguments', new JS.ArrayInitializer(typeParams));
1625 }
1626
1625 var fnBody = 1627 var fnBody =
1626 js.call('this.noSuchMethod(new #.InvocationImpl.new(#, #, #))', [ 1628 js.call('this.noSuchMethod(new #.InvocationImpl.new(#, #, #))', [
1627 _runtimeModule, 1629 _runtimeModule,
1628 _declareMemberName(method), 1630 _declareMemberName(method),
1629 positionalArgs, 1631 positionalArgs,
1630 new JS.ObjectInitializer(invocationProps) 1632 new JS.ObjectInitializer(invocationProps)
1631 ]); 1633 ]);
1632 1634
1633 if (!method.returnType.isDynamic) { 1635 if (!method.returnType.isDynamic) {
1634 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); 1636 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]);
1635 } 1637 }
1636 1638
1637 var fn = _makeGenericFunction(new JS.Fun( 1639 var fn = _makeGenericFunction(new JS.Fun(
1638 fnArgs, js.statement('{ return #; }', [fnBody]), 1640 fnArgs, js.statement('{ return #; }', [fnBody]),
1639 typeParams: _emitTypeFormals(method.type.typeFormals))); 1641 typeParams: typeParams));
1640 1642
1641 // TODO(jmesserly): generic type arguments will get dropped.
1642 // We have a similar issue with `dgsend` helpers.
1643 return new JS.Method( 1643 return new JS.Method(
1644 _declareMemberName(method, 1644 _declareMemberName(method,
1645 useExtension: _extensionTypes.isNativeClass(type.element)), 1645 useExtension: _extensionTypes.isNativeClass(type.element)),
1646 fn, 1646 fn,
1647 isGetter: method is PropertyAccessorElement && method.isGetter, 1647 isGetter: method is PropertyAccessorElement && method.isGetter,
1648 isSetter: method is PropertyAccessorElement && method.isSetter, 1648 isSetter: method is PropertyAccessorElement && method.isSetter,
1649 isStatic: false); 1649 isStatic: false);
1650 } 1650 }
1651 1651
1652 /// This is called whenever a derived class needs to introduce a new field, 1652 /// This is called whenever a derived class needs to introduce a new field,
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
2172 2172
2173 return _finishConstructorFunction(params, body, isCallable); 2173 return _finishConstructorFunction(params, body, isCallable);
2174 } 2174 }
2175 2175
2176 JS.Expression _finishConstructorFunction( 2176 JS.Expression _finishConstructorFunction(
2177 List<JS.Parameter> params, JS.Block body, isCallable) { 2177 List<JS.Parameter> params, JS.Block body, isCallable) {
2178 // We consider a class callable if it inherits from anything with a `call` 2178 // We consider a class callable if it inherits from anything with a `call`
2179 // method. As a result, we can know the callable JS function was created 2179 // method. As a result, we can know the callable JS function was created
2180 // at the first constructor that was hit. 2180 // at the first constructor that was hit.
2181 if (!isCallable) return new JS.Fun(params, body); 2181 if (!isCallable) return new JS.Fun(params, body);
2182 return js.call( 2182 return js.call(r'''function callableClass(#) {
2183 r'''function callableClass(#) {
2184 if (typeof this !== "function") { 2183 if (typeof this !== "function") {
2185 function self(...args) { 2184 function self(...args) {
2186 return self.call.apply(self, args); 2185 return self.call.apply(self, args);
2187 } 2186 }
2188 self.__proto__ = this.__proto__; 2187 self.__proto__ = this.__proto__;
2189 callableClass.call(self, #); 2188 callableClass.call(self, #);
2190 return self; 2189 return self;
2191 } 2190 }
2192 # 2191 #
2193 }''', 2192 }''', [params, params, body]);
2194 [params, params, body]);
2195 } 2193 }
2196 2194
2197 JS.Expression _constructorName(ConstructorElement ctor) { 2195 JS.Expression _constructorName(ConstructorElement ctor) {
2198 var name = ctor.name; 2196 var name = ctor.name;
2199 if (name == '') { 2197 if (name == '') {
2200 // Default constructors (factory or not) use `new` as their name. 2198 // Default constructors (factory or not) use `new` as their name.
2201 return _propertyName('new'); 2199 return _propertyName('new');
2202 } 2200 }
2203 return _emitMemberName(name, isStatic: true); 2201 return _emitMemberName(name, isStatic: true);
2204 } 2202 }
(...skipping 3107 matching lines...) Expand 10 before | Expand all | Expand 10 after
5312 return js 5310 return js
5313 .call('#.new(#)', [_emitConstructorAccess(types.symbolType), name]); 5311 .call('#.new(#)', [_emitConstructorAccess(types.symbolType), name]);
5314 } 5312 }
5315 } 5313 }
5316 5314
5317 return _emitConst(emitSymbol); 5315 return _emitConst(emitSymbol);
5318 } 5316 }
5319 5317
5320 @override 5318 @override
5321 visitListLiteral(ListLiteral node) { 5319 visitListLiteral(ListLiteral node) {
5322 var isConst = node.constKeyword != null; 5320 var elementType = (node.staticType as InterfaceType).typeArguments[0];
5323 JS.Expression emitList() { 5321 if (node.constKeyword == null) {
5324 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); 5322 return _emitList(elementType, _visitList(node.elements));
5325 ParameterizedType type = node.staticType;
5326 var elementType = type.typeArguments.single;
5327 // TODO(jmesserly): analyzer will usually infer `List<Object>` because
5328 // that is the least upper bound of the element types. So we rarely
5329 // generate a plain `List<dynamic>` anymore.
5330 if (!elementType.isDynamic || isConst) {
5331 // dart.list helper internally depends on _interceptors.JSArray.
5332 _declareBeforeUse(_jsArray);
5333 if (isConst) {
5334 var typeRep = _emitType(elementType);
5335 list = _callHelper('constList(#, #)', [list, typeRep]);
5336 } else {
5337 // Call `new JSArray<E>.of(list)`
5338 var jsArrayType = _jsArray.type.instantiate(type.typeArguments);
5339 list = js.call('#.of(#)', [_emitType(jsArrayType), list]);
5340 }
5341 }
5342 return list;
5343 } 5323 }
5324 return _cacheConst(() {
5325 // dart.constList helper internally depends on _interceptors.JSArray.
5326 _declareBeforeUse(_jsArray);
5327 return _callHelper('constList(#, #)', [
5328 new JS.ArrayInitializer(_visitList(node.elements)),
5329 _emitType(elementType)
5330 ]);
5331 });
5332 }
5344 5333
5345 if (isConst) return _cacheConst(emitList); 5334 JS.Expression _emitList(DartType itemType, List<JS.Expression> items) {
5346 return emitList(); 5335 var list = new JS.ArrayInitializer(items);
5336
5337 // TODO(jmesserly): analyzer will usually infer `List<Object>` because
5338 // that is the least upper bound of the element types. So we rarely
5339 // generate a plain `List<dynamic>` anymore.
5340 if (itemType.isDynamic) return list;
5341
5342 // Call `new JSArray<E>.of(list)`
5343 var arrayType = _jsArray.type.instantiate([itemType]);
5344 return js.call('#.of(#)', [_emitType(arrayType), list]);
5347 } 5345 }
5348 5346
5349 @override 5347 @override
5350 visitMapLiteral(MapLiteral node) { 5348 visitMapLiteral(MapLiteral node) {
5351 // TODO(jmesserly): we can likely make these faster. 5349 // TODO(jmesserly): we can likely make these faster.
5352 JS.Expression emitMap() { 5350 JS.Expression emitMap() {
5353 var entries = node.entries; 5351 var entries = node.entries;
5354 Object mapArguments = null; 5352 Object mapArguments = null;
5355 var type = node.staticType as InterfaceType; 5353 var type = node.staticType as InterfaceType;
5356 var typeArgs = type.typeArguments; 5354 var typeArgs = type.typeArguments;
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
5978 if (targetIdentifier.staticElement is! PrefixElement) return false; 5976 if (targetIdentifier.staticElement is! PrefixElement) return false;
5979 var prefix = targetIdentifier.staticElement as PrefixElement; 5977 var prefix = targetIdentifier.staticElement as PrefixElement;
5980 5978
5981 // The library the prefix is referring to must come from a deferred import. 5979 // The library the prefix is referring to must come from a deferred import.
5982 var containingLibrary = resolutionMap 5980 var containingLibrary = resolutionMap
5983 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5981 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5984 .library; 5982 .library;
5985 var imports = containingLibrary.getImportsWithPrefix(prefix); 5983 var imports = containingLibrary.getImportsWithPrefix(prefix);
5986 return imports.length == 1 && imports[0].isDeferred; 5984 return imports.length == 1 && imports[0].isDeferred;
5987 } 5985 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698