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

Unified Diff: lib/src/compiler/code_generator.dart

Issue 1930323004: instantiate generic tear-offs, fixes #525 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: format Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/codegen/language/generic_tearoff_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/compiler/code_generator.dart
diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart
index b41844e62c8a963be1b1f0aae0e0f2e9d5d10ebc..1276c85eaeaeed3e9b6f4a7bbe8d4cff67e002fc 100644
--- a/lib/src/compiler/code_generator.dart
+++ b/lib/src/compiler/code_generator.dart
@@ -475,7 +475,11 @@ class CodeGenerator extends GeneralizingAstVisitor
}
@override
- JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type);
+ JS.Expression visitTypeName(TypeName node) {
+ // TODO(jmesserly): should only happen for erroneous code.
+ if (node.type == null) return js.call('dart.dynamic');
+ return _emitTypeName(node.type);
+ }
@override
JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
@@ -1479,7 +1483,7 @@ class CodeGenerator extends GeneralizingAstVisitor
for (var p in ctor.parameters.parameters) {
var element = p.element;
if (element is FieldFormalParameterElement) {
- fields[element.field] = visitSimpleIdentifier(p.identifier);
+ fields[element.field] = _emitSimpleIdentifier(p.identifier);
}
}
@@ -1542,7 +1546,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var body = <JS.Statement>[];
for (var param in parameters.parameters) {
- var jsParam = visitSimpleIdentifier(param.identifier);
+ var jsParam = _emitSimpleIdentifier(param.identifier);
if (!options.destructureNamedParams) {
if (param.kind == ParameterKind.NAMED) {
@@ -1978,10 +1982,18 @@ class CodeGenerator extends GeneralizingAstVisitor
]);
}
- /// Writes a simple identifier. This can handle implicit `this` as well as
- /// going through the qualified library name if necessary.
+ /// Emits a simple identifier, including handling an inferred generic
+ /// function instantiation.
@override
JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
+ return _applyFunctionTypeArguments(
+ _emitSimpleIdentifier(node), node.staticElement, node.staticType);
+ }
+
+ /// Emits a simple identifier, handling implicit `this` as well as
+ /// going through the qualified library name if necessary, but *not* handling
+ /// inferred generic function instantiation.
+ JS.Expression _emitSimpleIdentifier(SimpleIdentifier node) {
var accessor = node.staticElement;
if (accessor == null) {
return js.commentExpression(
@@ -2334,8 +2346,8 @@ class CodeGenerator extends GeneralizingAstVisitor
List<JS.Expression> args = _visit(node.argumentList);
if (DynamicInvoke.get(target)) {
if (typeArgs != null) {
- return js.call('dart.dgsend(#, [#], #, #)',
- [jsTarget, typeArgs, memberName, args]);
+ return js.call('dart.dgsend(#, #, #, #)',
+ [jsTarget, new JS.ArrayInitializer(typeArgs), memberName, args]);
} else {
return js.call('dart.dsend(#, #, #)', [jsTarget, memberName, args]);
}
@@ -2367,7 +2379,8 @@ class CodeGenerator extends GeneralizingAstVisitor
if (DynamicInvoke.get(node.function)) {
var typeArgs = _emitInvokeTypeArguments(node);
if (typeArgs != null) {
- return js.call('dart.dgcall(#, [#], #)', [fn, typeArgs, args]);
+ return js.call('dart.dgcall(#, #, #)',
+ [fn, new JS.ArrayInitializer(typeArgs), args]);
} else {
return js.call('dart.dcall(#, #)', [fn, args]);
}
@@ -2385,12 +2398,13 @@ class CodeGenerator extends GeneralizingAstVisitor
List<JS.Expression> _emitInvokeTypeArguments(InvocationExpression node) {
return _emitFunctionTypeArguments(
- node.function.staticType, node.staticInvokeType);
+ node.function.staticType, node.staticInvokeType, node.typeArguments);
}
/// If `g` is a generic function type, and `f` is an instantiation of it,
/// then this will return the type arguments to apply, otherwise null.
- List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f) {
+ List<JS.Expression> _emitFunctionTypeArguments(DartType g, DartType f,
+ [TypeArgumentList typeArgs]) {
if (g is FunctionType &&
g.typeFormals.isNotEmpty &&
f is FunctionType &&
@@ -2398,6 +2412,12 @@ class CodeGenerator extends GeneralizingAstVisitor
return _recoverTypeArguments(g, f)
.map(_emitTypeName)
.toList(growable: false);
+ } else if (typeArgs != null) {
+ // Dynamic calls may have type arguments, even though the function types
+ // are not known.
+ // TODO(jmesserly): seems to be mostly broken in Analyzer at the moment:
+ // https://github.com/dart-lang/sdk/issues/26368
+ return typeArgs.arguments.map(visitTypeName).toList(growable: false);
}
return null;
}
@@ -3365,7 +3385,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (isLibraryPrefix(node.prefix)) {
return _visit(node.identifier);
} else {
- return _emitAccess(node.prefix, node.identifier);
+ return _emitAccess(node.prefix, node.identifier, node.staticType);
}
}
@@ -3374,7 +3394,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (node.operator.lexeme == '?.') {
return _emitNullSafe(node);
}
- return _emitAccess(_getTarget(node), node.propertyName);
+ return _emitAccess(_getTarget(node), node.propertyName, node.staticType);
}
JS.Expression _emitNullSafe(Expression node) {
@@ -3451,8 +3471,9 @@ class CodeGenerator extends GeneralizingAstVisitor
}
/// Shared code for [PrefixedIdentifier] and [PropertyAccess].
- JS.Expression _emitAccess(Expression target, SimpleIdentifier memberId) {
- var member = memberId.staticElement;
+ JS.Expression _emitAccess(
+ Expression target, SimpleIdentifier memberId, DartType resultType) {
+ Element member = memberId.staticElement;
if (member is PropertyAccessorElement) {
member = (member as PropertyAccessorElement).variable;
}
@@ -3463,30 +3484,49 @@ class CodeGenerator extends GeneralizingAstVisitor
return js.call('dart.dload(#, #)', [_visit(target), name]);
}
- if (target is SuperExpression &&
- member is FieldElement &&
- !member.isSynthetic) {
+ var jsTarget = _visit(target);
+ bool isSuper = jsTarget is JS.Super;
+
+ if (isSuper && member is FieldElement && !member.isSynthetic) {
// If super.x is actually a field, then x is an instance property since
// subclasses cannot override x.
- return js.call('this.#', [name]);
+ jsTarget = new JS.This();
}
- String code;
+ JS.Expression result;
if (member != null && member is MethodElement && !isStatic) {
// Tear-off methods: explicitly bind it.
- if (target is SuperExpression) {
- return js.call('dart.bind(this, #, #.#)', [name, _visit(target), name]);
+ if (isSuper) {
+ result = js.call('dart.bind(this, #, #.#)', [name, jsTarget, name]);
} else if (_isObjectMemberCall(target, memberId.name)) {
- return js.call('dart.bind(#, #, dart.#)', [_visit(target), name, name]);
+ result = js.call('dart.bind(#, #, dart.#)', [jsTarget, name, name]);
+ } else {
+ result = js.call('dart.bind(#, #)', [jsTarget, name]);
}
- code = 'dart.bind(#, #)';
} else if (_isObjectMemberCall(target, memberId.name)) {
- return js.call('dart.#(#)', [name, _visit(target)]);
+ result = js.call('dart.#(#)', [name, jsTarget]);
} else {
- code = '#.#';
+ result = js.call('#.#', [jsTarget, name]);
+ }
+ return _applyFunctionTypeArguments(result, member, resultType);
+ }
+
+ /// If this is an inferred instantiation of a generic function/method, this
+ /// will add the inferred type arguments.
+ JS.Expression _applyFunctionTypeArguments(
+ JS.Expression result, Element member, DartType instantiated) {
+ DartType type;
+ if (member is ExecutableElement) {
+ type = member.type;
+ } else if (member is VariableElement) {
+ type = member.type;
}
- return js.call(code, [_visit(target), name]);
+ // TODO(jmesserly): handle explicitly passed type args.
+ if (type == null) return result;
+ var typeArgs = _emitFunctionTypeArguments(type, instantiated);
+ if (typeArgs == null) return result;
+ return js.call('dart.gbind(#, #)', [result, typeArgs]);
}
/// Emits a generic send, like an operator method.
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | test/codegen/language/generic_tearoff_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698