blob: 147cd0d535c8a9d96b77c4aaa3ed4c6e278ee34e [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// TODO(johnniwinther): Port this test to be frontend agnostic.
library type_representation_test;
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/js/js.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_backend/backend.dart' show JavaScriptBackend;
import 'package:compiler/src/js_backend/runtime_types.dart'
show TypeRepresentationGenerator;
import 'package:compiler/src/world.dart';
import 'package:expect/expect.dart';
import '../helpers/element_lookup.dart';
import '../memory_compiler.dart';
import '../type_test_helper.dart';
void main() {
asyncTest(() async {
print('--test from kernel------------------------------------------------');
await testAll();
print('--test from kernel (strong)---------------------------------------');
await testAll(strongMode: true);
});
}
testAll({bool strongMode: false}) async {
await testTypeRepresentations(strongMode: strongMode);
}
List<FunctionTypeData> signatures = const <FunctionTypeData>[
const FunctionTypeData("void", "1", "()"),
const FunctionTypeData("int", "2", "()"),
const FunctionTypeData("List<int>", "3", "()"),
const FunctionTypeData("dynamic", "4", "()"),
const FunctionTypeData("dynamic", "5", "(int a, String b)"),
const FunctionTypeData("dynamic", "6", "(int a, [String b])"),
const FunctionTypeData(
"dynamic", "7", "(int a, String b, [List<int> c, dynamic d])"),
const FunctionTypeData("dynamic", "8", "(int a, {String b})"),
const FunctionTypeData(
"dynamic", "9", "(int a, String b, {List<int> c, dynamic d})"),
const FunctionTypeData(
"dynamic", "10", "(void Function(int a, [dynamic b]) f)"),
const FunctionTypeData("FutureOr<int>", "11",
"<T extends num, S>(FutureOr<T> a, S b, List<void> c)"),
];
testTypeRepresentations({bool strongMode}) async {
String source = '''
import 'dart:async';
${createTypedefs(signatures, prefix: 'Typedef')}
${createMethods(signatures, prefix: 'm')}
main() {
${createUses(signatures, prefix: 'Typedef')}
${createUses(signatures, prefix: 'm')}
}
''';
CompilationResult result = await runCompiler(
memorySourceFiles: {'main.dart': source},
options: strongMode ? [Flags.strongMode] : [Flags.noPreviewDart2]);
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
JavaScriptBackend backend = compiler.backend;
TypeRepresentationGenerator typeRepresentation =
new TypeRepresentationGenerator(
backend.namer, compiler.backendClosedWorldForTesting.nativeData,
strongMode: strongMode);
Expression onVariable(TypeVariableType _variable) {
TypeVariableType variable = _variable;
return new VariableUse(variable.element.name);
}
String stringify(Expression expression) {
return prettyPrint(expression,
enableMinification: compiler.options.enableMinification);
}
void expect(DartType type, String expectedRepresentation,
[String expectedTypedefRepresentation]) {
bool encodeTypedefName = false;
Expression expression = typeRepresentation.getTypeRepresentation(
backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
Expect.stringEquals(expectedRepresentation, stringify(expression));
encodeTypedefName = true;
expression = typeRepresentation.getTypeRepresentation(
backend.emitter.emitter, type, onVariable, (x) => encodeTypedefName);
if (expectedTypedefRepresentation == null) {
expectedTypedefRepresentation = expectedRepresentation;
}
Expect.stringEquals(expectedTypedefRepresentation, stringify(expression));
}
String getJsName(Entity cls) {
Expression name =
typeRepresentation.getJavaScriptClassName(cls, backend.emitter.emitter);
return stringify(name);
}
JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
String func = backend.namer.functionTypeTag;
String ret = backend.namer.functionTypeReturnTypeTag;
String retvoid = strongMode
? '$ret: -1'
: '${backend.namer.functionTypeVoidReturnTag}: true';
String args = backend.namer.functionTypeRequiredParametersTag;
String opt = backend.namer.functionTypeOptionalParametersTag;
String named = backend.namer.functionTypeNamedParametersTag;
String bounds = backend.namer.functionTypeGenericBoundsTag;
String futureOr = backend.namer.futureOrTag;
String futureOrType = backend.namer.futureOrTypeTag;
ClassEntity List_ = findClass(closedWorld, 'List');
TypeVariableType List_E =
elementEnvironment.getThisType(List_).typeArguments[0];
ClassEntity Map_ = findClass(closedWorld, 'Map');
TypeVariableType Map_K =
elementEnvironment.getThisType(Map_).typeArguments[0];
TypeVariableType Map_V =
elementEnvironment.getThisType(Map_).typeArguments[1];
InterfaceType Object_ = closedWorld.commonElements.objectType;
InterfaceType num_ = closedWorld.commonElements.numType;
InterfaceType int_ = closedWorld.commonElements.intType;
InterfaceType String_ = closedWorld.commonElements.stringType;
DartType dynamic_ = closedWorld.commonElements.dynamicType;
DartType Typedef1_ = findFieldType(closedWorld, 'Typedef1');
DartType Typedef2_ = findFieldType(closedWorld, 'Typedef2');
DartType Typedef3_ = findFieldType(closedWorld, 'Typedef3');
DartType Typedef4_ = findFieldType(closedWorld, 'Typedef4');
DartType Typedef5_ = findFieldType(closedWorld, 'Typedef5');
DartType Typedef6_ = findFieldType(closedWorld, 'Typedef6');
DartType Typedef7_ = findFieldType(closedWorld, 'Typedef7');
DartType Typedef8_ = findFieldType(closedWorld, 'Typedef8');
DartType Typedef9_ = findFieldType(closedWorld, 'Typedef9');
DartType Typedef10_ = findFieldType(closedWorld, 'Typedef10');
DartType Typedef11_ = findFieldType(closedWorld, 'Typedef11');
String List_rep = getJsName(List_);
String List_E_rep = stringify(onVariable(List_E));
String Map_rep = getJsName(Map_);
String Map_K_rep = stringify(onVariable(Map_K));
String Map_V_rep = stringify(onVariable(Map_V));
String Object_rep = getJsName(Object_.element);
String num_rep = getJsName(num_.element);
String int_rep = getJsName(int_.element);
String String_rep = getJsName(String_.element);
String getTypedefTag(DartType type) {
// TODO(johnniwinther): Should/can we preserve typedef names from kernel?
//String typedefTag = backend.namer.typedefTag;
//TypedefType typedef = type;
//return ', $typedefTag: ${getJsName(typedef.element)}';
return '';
}
String Typedef1_tag = getTypedefTag(Typedef1_);
String Typedef2_tag = getTypedefTag(Typedef2_);
String Typedef3_tag = getTypedefTag(Typedef3_);
String Typedef4_tag = getTypedefTag(Typedef4_);
String Typedef5_tag = getTypedefTag(Typedef5_);
String Typedef6_tag = getTypedefTag(Typedef6_);
String Typedef7_tag = getTypedefTag(Typedef7_);
String Typedef8_tag = getTypedefTag(Typedef8_);
String Typedef9_tag = getTypedefTag(Typedef9_);
String Typedef10_tag = getTypedefTag(Typedef10_);
String Typedef11_tag = getTypedefTag(Typedef11_);
expect(int_, '$int_rep');
expect(String_, '$String_rep');
expect(dynamic_, 'null');
// List<E>
expect(elementEnvironment.getThisType(List_), '[$List_rep, $List_E_rep]');
// List
expect(elementEnvironment.getRawType(List_),
strongMode ? '[$List_rep,,]' : '$List_rep');
// List<dynamic>
expect(instantiate(List_, [dynamic_]),
strongMode ? '[$List_rep,,]' : '$List_rep');
// List<int>
expect(instantiate(List_, [int_]), '[$List_rep, $int_rep]');
// List<Typedef1>
expect(instantiate(List_, [Typedef1_]), '[$List_rep, {$func: 1, $retvoid}]',
'[$List_rep, {$func: 1, $retvoid$Typedef1_tag}]');
expect(
instantiate(List_, [Typedef2_]),
'[$List_rep, {$func: 1, $ret: $int_rep}]',
'[$List_rep, {$func: 1, $ret: $int_rep$Typedef2_tag}]');
expect(
instantiate(List_, [Typedef3_]),
'[$List_rep, {$func: 1, $ret: [$List_rep, $int_rep]}]',
'[$List_rep, {$func: 1, $ret: [$List_rep, $int_rep]$Typedef3_tag}]');
expect(instantiate(List_, [Typedef4_]), '[$List_rep, {$func: 1}]',
'[$List_rep, {$func: 1$Typedef4_tag}]');
expect(
instantiate(List_, [Typedef5_]),
'[$List_rep, {$func: 1,'
' $args: [$int_rep, $String_rep]}]',
'[$List_rep, {$func: 1,'
' $args: [$int_rep, $String_rep]$Typedef5_tag}]');
expect(
instantiate(List_, [Typedef6_]),
'[$List_rep, {$func: 1,'
' $args: [$int_rep], $opt: [$String_rep]}]',
'[$List_rep, {$func: 1,'
' $args: [$int_rep], $opt: [$String_rep]$Typedef6_tag}]');
expect(
instantiate(List_, [Typedef7_]),
'[$List_rep, {$func: 1, $args: '
'[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]}]',
'[$List_rep, {$func: 1, $args: '
'[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]'
'$Typedef7_tag}]');
expect(
instantiate(List_, [Typedef8_]),
'[$List_rep, {$func: 1, $args: [$int_rep],'
' $named: {b: $String_rep}}]',
'[$List_rep, {$func: 1, $args: [$int_rep],'
' $named: {b: $String_rep}$Typedef8_tag}]');
expect(
instantiate(List_, [Typedef9_]),
'[$List_rep, {$func: 1, '
'$args: [$int_rep, $String_rep], $named: '
'{c: [$List_rep, $int_rep], d: null}}]',
'[$List_rep, {$func: 1, '
'$args: [$int_rep, $String_rep], $named: {c: [$List_rep, $int_rep],'
' d: null}$Typedef9_tag}]');
expect(
instantiate(List_, [Typedef10_]),
'[$List_rep, {$func: 1, '
'$args: [{$func: 1, $retvoid, '
'$args: [$int_rep], $opt: [,]}]}]',
'[$List_rep, {$func: 1, '
'$args: [{$func: 1, $retvoid, '
'$args: [$int_rep], $opt: [,]}]$Typedef10_tag}]');
if (!strongMode) {
expect(
instantiate(List_, [Typedef11_]),
'[$List_rep, {$func: 1, $args: [,, [$List_rep,,]]}]',
'[$List_rep, {$func: 1, $args: [,, [$List_rep,,]]$Typedef11_tag}]');
} else {
expect(
instantiate(List_, [Typedef11_]),
'[$List_rep, {$func: 1, $bounds: [$num_rep, $Object_rep], '
'$ret: {$futureOr: 1, $futureOrType: $int_rep}, '
'$args: [{$futureOr: 1, $futureOrType: 0}, 1, [$List_rep, -1]]}]');
}
// Map<K,V>
expect(elementEnvironment.getThisType(Map_),
'[$Map_rep, $Map_K_rep, $Map_V_rep]');
// Map
expect(elementEnvironment.getRawType(Map_),
strongMode ? '[$Map_rep,,,]' : '$Map_rep');
// Map<dynamic,dynamic>
expect(instantiate(Map_, [dynamic_, dynamic_]),
strongMode ? '[$Map_rep,,,]' : '$Map_rep');
// Map<int,String>
expect(
instantiate(Map_, [int_, String_]), '[$Map_rep, $int_rep, $String_rep]');
// void m1() {}
expect(findFunctionType(closedWorld, 'm1'), '{$func: 1, $retvoid}');
// int m2() => 0;
expect(findFunctionType(closedWorld, 'm2'), '{$func: 1, $ret: $int_rep}');
// List<int> m3() => null;
expect(findFunctionType(closedWorld, 'm3'),
'{$func: 1, $ret: [$List_rep, $int_rep]}');
// m4() {}
expect(findFunctionType(closedWorld, 'm4'), '{$func: 1}');
// m5(int a, String b) {}
expect(findFunctionType(closedWorld, 'm5'),
'{$func: 1, $args: [$int_rep, $String_rep]}');
// m6(int a, [String b]) {}
expect(
findFunctionType(closedWorld, 'm6'),
'{$func: 1, $args: [$int_rep],'
' $opt: [$String_rep]}');
// m7(int a, String b, [List<int> c, d]) {}
expect(
findFunctionType(closedWorld, 'm7'),
'{$func: 1,'
' $args: [$int_rep, $String_rep],'
' $opt: [[$List_rep, $int_rep],,]}');
// m8(int a, {String b}) {}
expect(
findFunctionType(closedWorld, 'm8'),
'{$func: 1,'
' $args: [$int_rep], $named: {b: $String_rep}}');
// m9(int a, String b, {List<int> c, d}) {}
expect(
findFunctionType(closedWorld, 'm9'),
'{$func: 1,'
' $args: [$int_rep, $String_rep],'
' $named: {c: [$List_rep, $int_rep], d: null}}');
// m10(void f(int a, [b])) {}
expect(
findFunctionType(closedWorld, 'm10'),
'{$func: 1, $args:'
' [{$func: 1,'
' $retvoid, $args: [$int_rep], $opt: [,]}]}');
// FutureOr<int> m11<T, S>(FutureOr<T> a, S b, List<void> c) {}
if (!strongMode) {
expect(findFunctionType(closedWorld, 'm11'),
'{$func: 1, $args: [,, [$List_rep,,]]}');
} else {
expect(
findFunctionType(closedWorld, 'm11'),
'{$func: 1, $bounds: [$num_rep, $Object_rep], '
'$ret: {$futureOr: 1, $futureOrType: $int_rep}, '
'$args: [{$futureOr: 1, $futureOrType: 0}, 1, [$List_rep, -1]]}');
}
}