mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:19:49 +00:00
Port inference tests, #5 of 5
Change-Id: I384056289dfa99991aa42fbe0baadedc6c208b6f Reviewed-on: https://dart-review.googlesource.com/34586 Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
0f70f94992
commit
94fc11388a
|
@ -115,7 +115,7 @@ abstract class InferrerEngine<T> {
|
|||
void setDefaultTypeOfParameter(Local parameter, TypeInformation type,
|
||||
{bool isInstanceMember});
|
||||
|
||||
Iterable<MemberEntity> getCallersOf(MemberEntity element);
|
||||
Iterable<MemberEntity> getCallersOfForTesting(MemberEntity element);
|
||||
|
||||
// TODO(johnniwinther): Make this private again.
|
||||
GlobalTypeInferenceElementData<T> dataOfMember(MemberEntity element);
|
||||
|
@ -250,6 +250,8 @@ abstract class InferrerEngine<T> {
|
|||
}
|
||||
|
||||
abstract class InferrerEngineImpl<T> extends InferrerEngine<T> {
|
||||
static bool retainDataForTesting = false;
|
||||
|
||||
final Map<Local, TypeInformation> defaultTypeOfParameter =
|
||||
new Map<Local, TypeInformation>();
|
||||
final WorkQueue workQueue = new WorkQueue();
|
||||
|
@ -1094,7 +1096,11 @@ abstract class InferrerEngineImpl<T> extends InferrerEngine<T> {
|
|||
}
|
||||
|
||||
void clear() {
|
||||
void cleanup(TypeInformation info) => info.cleanup();
|
||||
void cleanup(TypeInformation info) {
|
||||
if (!retainDataForTesting) {
|
||||
info.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
types.allocatedCalls.forEach(cleanup);
|
||||
types.allocatedCalls.clear();
|
||||
|
@ -1119,9 +1125,9 @@ abstract class InferrerEngineImpl<T> extends InferrerEngine<T> {
|
|||
types.allocatedLists.values.forEach(cleanup);
|
||||
}
|
||||
|
||||
Iterable<MemberEntity> getCallersOf(MemberEntity element) {
|
||||
Iterable<MemberEntity> getCallersOfForTesting(MemberEntity element) {
|
||||
MemberTypeInformation info = types.getInferredTypeOfMember(element);
|
||||
return info.callers;
|
||||
return info.callersForTesting;
|
||||
}
|
||||
|
||||
TypeInformation typeOfMemberWithSelector(
|
||||
|
|
|
@ -140,12 +140,12 @@ abstract class TypeGraphInferrer<T> implements TypesInferrer<T> {
|
|||
return result;
|
||||
}
|
||||
|
||||
Iterable<MemberEntity> getCallersOf(MemberEntity element) {
|
||||
Iterable<MemberEntity> getCallersOfForTesting(MemberEntity element) {
|
||||
if (_disableTypeInference) {
|
||||
throw new UnsupportedError(
|
||||
"Cannot query the type inferrer when type inference is disabled.");
|
||||
}
|
||||
return inferrer.getCallersOf(element);
|
||||
return inferrer.getCallersOfForTesting(element);
|
||||
}
|
||||
|
||||
bool isMemberCalledOnce(MemberEntity element) {
|
||||
|
|
|
@ -429,13 +429,8 @@ abstract class MemberTypeInformation extends ElementTypeInformation
|
|||
}
|
||||
}
|
||||
|
||||
Iterable<MemberEntity> get callers {
|
||||
// TODO(sra): This is called only from an unused API and a test. If it
|
||||
// becomes used, [cleanup] will need to copy `_caller.keys`.
|
||||
|
||||
// `simple_inferrer_callers_test.dart` ensures that cleanup has not
|
||||
// happened.
|
||||
return _callers.keys;
|
||||
Iterable<MemberEntity> get callersForTesting {
|
||||
return _callers?.keys;
|
||||
}
|
||||
|
||||
bool isCalledOnce() {
|
||||
|
|
|
@ -254,7 +254,7 @@ usedByTests() {
|
|||
closedWorld.getClassHierarchyNode(null);
|
||||
closedWorld.getClassSet(null);
|
||||
closedWorld.haveAnyCommonSubtypes(null, null);
|
||||
typeGraphInferrer.getCallersOf(null);
|
||||
typeGraphInferrer.getCallersOfForTesting(null);
|
||||
dart_types.Types.sorted(null);
|
||||
new dart_types.Types(null).copy(null);
|
||||
}
|
||||
|
|
|
@ -542,6 +542,12 @@ Spannable computeSpannable(
|
|||
if (id is NodeId) {
|
||||
return new SourceSpan(mainUri, id.value, id.value + 1);
|
||||
} else if (id is ElementId) {
|
||||
String memberName = id.memberName;
|
||||
bool isSetter = false;
|
||||
if (memberName != '[]=' && memberName.endsWith('=')) {
|
||||
isSetter = true;
|
||||
memberName = memberName.substring(0, memberName.length - 1);
|
||||
}
|
||||
LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
|
||||
if (id.className != null) {
|
||||
ClassEntity cls =
|
||||
|
@ -549,23 +555,22 @@ Spannable computeSpannable(
|
|||
if (cls == null) {
|
||||
throw new ArgumentError("No class '${id.className}' in $mainUri.");
|
||||
}
|
||||
MemberEntity member =
|
||||
elementEnvironment.lookupClassMember(cls, id.memberName);
|
||||
MemberEntity member = elementEnvironment
|
||||
.lookupClassMember(cls, memberName, setter: isSetter);
|
||||
if (member == null) {
|
||||
ConstructorEntity constructor =
|
||||
elementEnvironment.lookupConstructor(cls, id.memberName);
|
||||
elementEnvironment.lookupConstructor(cls, memberName);
|
||||
if (constructor == null) {
|
||||
throw new ArgumentError(
|
||||
"No class member '${id.memberName}' in $cls.");
|
||||
throw new ArgumentError("No class member '${memberName}' in $cls.");
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
return member;
|
||||
} else {
|
||||
MemberEntity member =
|
||||
elementEnvironment.lookupLibraryMember(library, id.memberName);
|
||||
MemberEntity member = elementEnvironment
|
||||
.lookupLibraryMember(library, memberName, setter: isSetter);
|
||||
if (member == null) {
|
||||
throw new ArgumentError("No member '${id.memberName}' in $mainUri.");
|
||||
throw new ArgumentError("No member '${memberName}' in $mainUri.");
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
|
|
@ -8,37 +8,40 @@ import 'dart:io';
|
|||
import 'package:args/args.dart';
|
||||
import 'package:compiler/src/commandline_options.dart';
|
||||
import 'package:compiler/src/filenames.dart';
|
||||
import 'package:compiler/src/inferrer/inferrer_engine.dart';
|
||||
import 'package:compiler/src/io/source_file.dart';
|
||||
import 'package:compiler/src/source_file_provider.dart';
|
||||
import '../kernel/test_helpers.dart';
|
||||
import 'id_equivalence_helper.dart';
|
||||
|
||||
show(List<String> args, ComputeMemberDataFunction computeAstData,
|
||||
ComputeMemberDataFunction computeKernelData) async {
|
||||
ArgParser createArgParser() {
|
||||
ArgParser argParser = new ArgParser(allowTrailingOptions: true);
|
||||
argParser.addFlag('verbose', negatable: true, defaultsTo: false);
|
||||
argParser.addFlag('colors', negatable: true);
|
||||
argParser.addFlag('all', negatable: false, defaultsTo: false);
|
||||
argParser.addFlag('use-kernel', negatable: false, defaultsTo: false);
|
||||
ArgResults argResults = argParser.parse(args);
|
||||
return argParser;
|
||||
}
|
||||
|
||||
show(ArgResults argResults, ComputeMemberDataFunction computeAstData,
|
||||
ComputeMemberDataFunction computeKernelData) async {
|
||||
if (argResults.wasParsed('colors')) {
|
||||
useColors = argResults['colors'];
|
||||
}
|
||||
bool verbose = argResults['verbose'];
|
||||
bool useKernel = argResults['use-kernel'];
|
||||
|
||||
InferrerEngineImpl.useSorterForTesting = true;
|
||||
String file = argResults.rest.first;
|
||||
Uri entryPoint = Uri.base.resolve(nativeToUriPath(file));
|
||||
List<String> show;
|
||||
if (argResults.rest.length > 1) {
|
||||
if (argResults['all']) {
|
||||
show = null;
|
||||
} else if (argResults.rest.length > 1) {
|
||||
show = argResults.rest.skip(1).toList();
|
||||
} else {
|
||||
show = [entryPoint.pathSegments.last];
|
||||
}
|
||||
|
||||
List<String> options = <String>[];
|
||||
List<String> options = <String>[stopAfterTypeInference];
|
||||
if (useKernel) {
|
||||
options.add(Flags.useKernel);
|
||||
}
|
||||
|
|
|
@ -1,297 +0,0 @@
|
|||
// 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 use the equivalence framework.
|
||||
/// Currently it only works with the mock compiler.
|
||||
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/elements/elements.dart';
|
||||
import 'package:compiler/src/types/masks.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'type_mask_test_helper.dart';
|
||||
import '../compiler_helper.dart';
|
||||
|
||||
void compileAndFind(String code, String className, String memberName,
|
||||
bool disableInlining, check(compiler, element)) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
ClassElement cls = findElement(compiler, className);
|
||||
var member = cls.lookupLocalMember(memberName);
|
||||
return check(compiler, member);
|
||||
}));
|
||||
}
|
||||
|
||||
const String TEST_1 = r"""
|
||||
class A {
|
||||
x(p) => p;
|
||||
}
|
||||
main() { new A().x("s"); }
|
||||
""";
|
||||
|
||||
const String TEST_2 = r"""
|
||||
class A {
|
||||
x(p) => p;
|
||||
}
|
||||
main() { new A().x(1); }
|
||||
""";
|
||||
|
||||
const String TEST_3 = r"""
|
||||
class A {
|
||||
x(p) => x(p - 1);
|
||||
}
|
||||
main() { new A().x(1); }
|
||||
""";
|
||||
|
||||
const String TEST_4 = r"""
|
||||
class A {
|
||||
x(p) => x(p - 1);
|
||||
}
|
||||
main() { new A().x(1.5); }
|
||||
""";
|
||||
|
||||
const String TEST_5 = r"""
|
||||
class A {
|
||||
x(p) => p;
|
||||
}
|
||||
main() {
|
||||
new A().x(1);
|
||||
new A().x(1.5);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_6 = r"""
|
||||
class A {
|
||||
x(p) => p;
|
||||
}
|
||||
main() {
|
||||
new A().x(1.5);
|
||||
new A().x(1);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_7a = r"""
|
||||
class A {
|
||||
x(p) => x("x");
|
||||
}
|
||||
main() {
|
||||
new A().x(1);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_7b = r"""
|
||||
class A {
|
||||
x(p) => x("x");
|
||||
}
|
||||
main() {
|
||||
new A().x({});
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_8 = r"""
|
||||
class A {
|
||||
x(p1, p2, p3) => x(p1, "x", {});
|
||||
}
|
||||
main() {
|
||||
new A().x(1, 2, 3);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_9 = r"""
|
||||
class A {
|
||||
x(p1, p2) => x(p1, p2);
|
||||
}
|
||||
main() {
|
||||
new A().x(1, 2);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_10 = r"""
|
||||
class A {
|
||||
x(p1, p2) => x(p1, p2);
|
||||
}
|
||||
void f(p) {
|
||||
p.x("x", "y");
|
||||
}
|
||||
main() {
|
||||
f(null);
|
||||
new A().x(1, 2);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_11 = r"""
|
||||
class A {
|
||||
x(p1, p2) => x(1, 2);
|
||||
}
|
||||
main() {
|
||||
new A().x("x", "y");
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_12 = r"""
|
||||
class A {
|
||||
x(p1, [p2 = 1]) => 1;
|
||||
}
|
||||
main() {
|
||||
new A().x("x", 1);
|
||||
new A().x("x");
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_13 = r"""
|
||||
class A {
|
||||
x(p) => 1;
|
||||
}
|
||||
f(p) => p.x(2.2);
|
||||
main() {
|
||||
new A().x(1);
|
||||
f(new A());
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_14 = r"""
|
||||
class A {
|
||||
x(p1, [p2 = "s"]) => 1;
|
||||
}
|
||||
main() {
|
||||
new A().x(1);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_15 = r"""
|
||||
class A {
|
||||
x(p1, [p2 = true]) => 1;
|
||||
}
|
||||
f(p) => p.a("x");
|
||||
main() {
|
||||
new A().x("x");
|
||||
new A().x("x", false);
|
||||
f(null);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_16 = r"""
|
||||
class A {
|
||||
x(p1, [p2 = 1, p3 = "s"]) => 1;
|
||||
}
|
||||
main() {
|
||||
new A().x(1);
|
||||
new A().x(1, 2);
|
||||
new A().x(1, 2, "x");
|
||||
new A().x(1, p2: 2);
|
||||
new A().x(1, p3: "x");
|
||||
new A().x(1, p3: "x", p2: 2);
|
||||
new A().x(1, p2: 2, p3: "x");
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_17 = r"""
|
||||
class A {
|
||||
x(p1, [p2 = 1, p3 = "s"]) => 1;
|
||||
}
|
||||
main() {
|
||||
new A().x(1, true, 1.1);
|
||||
new A().x(1, false, 2.2);
|
||||
new A().x(1, p3: 3.3, p2: true);
|
||||
new A().x(1, p2: false, p3: 4.4);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_18 = r"""
|
||||
class A {
|
||||
x(p1, p2) => x(p1, p2);
|
||||
}
|
||||
class B extends A {
|
||||
}
|
||||
main() {
|
||||
new B().x("a", "b");
|
||||
new A().x(1, 2);
|
||||
}
|
||||
""";
|
||||
|
||||
typedef List<TypeMask> TestCallback(CommonMasks masks);
|
||||
|
||||
void doTest(String test, bool enableInlining, TestCallback f) {
|
||||
compileAndFind(test, 'A', 'x', enableInlining, (compiler, element) {
|
||||
var inferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = inferrer.closedWorld;
|
||||
var expectedTypes = f(closedWorld.commonMasks);
|
||||
var signature = element.functionSignature;
|
||||
int index = 0;
|
||||
signature.forEachParameter((Element element) {
|
||||
Expect.equals(expectedTypes[index++],
|
||||
simplify(inferrer.getTypeOfParameter(element), closedWorld), test);
|
||||
});
|
||||
Expect.equals(index, expectedTypes.length);
|
||||
});
|
||||
}
|
||||
|
||||
void runTest(String test, TestCallback f) {
|
||||
doTest(test, false, f);
|
||||
doTest(test, true, f);
|
||||
}
|
||||
|
||||
void test() {
|
||||
runTest(TEST_1, (commonMasks) => [commonMasks.stringType]);
|
||||
runTest(TEST_2, (commonMasks) => [commonMasks.uint31Type]);
|
||||
runTest(TEST_3, (commonMasks) => [commonMasks.intType]);
|
||||
runTest(TEST_4, (commonMasks) => [commonMasks.numType]);
|
||||
runTest(TEST_5, (commonMasks) => [commonMasks.numType]);
|
||||
runTest(TEST_6, (commonMasks) => [commonMasks.numType]);
|
||||
runTest(TEST_7a, (commonMasks) => [commonMasks.interceptorType]);
|
||||
runTest(TEST_7b, (commonMasks) => [commonMasks.dynamicType.nonNullable()]);
|
||||
|
||||
runTest(
|
||||
TEST_8,
|
||||
(commonMasks) => [
|
||||
commonMasks.uint31Type,
|
||||
commonMasks.interceptorType,
|
||||
commonMasks.dynamicType.nonNullable()
|
||||
]);
|
||||
runTest(TEST_9,
|
||||
(commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
|
||||
runTest(TEST_10,
|
||||
(commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
|
||||
runTest(
|
||||
TEST_11,
|
||||
(commonMasks) =>
|
||||
[commonMasks.interceptorType, commonMasks.interceptorType]);
|
||||
|
||||
runTest(TEST_12,
|
||||
(commonMasks) => [commonMasks.stringType, commonMasks.uint31Type]);
|
||||
|
||||
runTest(TEST_13, (commonMasks) => [commonMasks.numType]);
|
||||
|
||||
runTest(TEST_14,
|
||||
(commonMasks) => [commonMasks.uint31Type, commonMasks.stringType]);
|
||||
|
||||
runTest(
|
||||
TEST_15, (commonMasks) => [commonMasks.stringType, commonMasks.boolType]);
|
||||
|
||||
runTest(
|
||||
TEST_16,
|
||||
(commonMasks) => [
|
||||
commonMasks.uint31Type,
|
||||
commonMasks.uint31Type,
|
||||
commonMasks.stringType
|
||||
]);
|
||||
|
||||
runTest(
|
||||
TEST_17,
|
||||
(commonMasks) => [
|
||||
commonMasks.uint31Type,
|
||||
commonMasks.boolType,
|
||||
commonMasks.doubleType
|
||||
]);
|
||||
|
||||
runTest(
|
||||
TEST_18,
|
||||
(commonMasks) =>
|
||||
[commonMasks.interceptorType, commonMasks.interceptorType]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
test();
|
||||
}
|
20
tests/compiler/dart2js/inference/callers/field_access.dart
Normal file
20
tests/compiler/dart2js/inference/callers/field_access.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
/*element: B.:[main]*/
|
||||
class A {
|
||||
/*element: A.field:[main]*/
|
||||
var field;
|
||||
}
|
||||
|
||||
/*element: A.:[main]*/
|
||||
class B {
|
||||
/*element: B.field:[main]*/
|
||||
var field;
|
||||
}
|
||||
|
||||
main() {
|
||||
new A().field;
|
||||
new B().field;
|
||||
}
|
145
tests/compiler/dart2js/inference/callers_test.dart
Normal file
145
tests/compiler/dart2js/inference/callers_test.dart
Normal file
|
@ -0,0 +1,145 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/closure.dart';
|
||||
import 'package:compiler/src/common.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
|
||||
import 'package:compiler/src/elements/elements.dart';
|
||||
import 'package:compiler/src/elements/entities.dart';
|
||||
import 'package:compiler/src/inferrer/inferrer_engine.dart';
|
||||
import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
|
||||
import 'package:compiler/src/kernel/element_map.dart';
|
||||
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
|
||||
import 'package:compiler/src/tree/nodes.dart' as ast;
|
||||
import 'package:kernel/ast.dart' as ir;
|
||||
import '../equivalence/id_equivalence.dart';
|
||||
import '../equivalence/id_equivalence_helper.dart';
|
||||
|
||||
main(List<String> args) {
|
||||
InferrerEngineImpl.retainDataForTesting = true;
|
||||
asyncTest(() async {
|
||||
Directory dataDir =
|
||||
new Directory.fromUri(Platform.script.resolve('callers'));
|
||||
await checkTests(dataDir, computeMemberAstCallers, computeMemberIrCallers,
|
||||
args: args, options: [stopAfterTypeInference]);
|
||||
});
|
||||
}
|
||||
|
||||
/// Compute callers data for [_member] as a [MemberElement].
|
||||
///
|
||||
/// Fills [actualMap] with the data.
|
||||
void computeMemberAstCallers(
|
||||
Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap,
|
||||
{bool verbose: false}) {
|
||||
MemberElement member = _member;
|
||||
ResolvedAst resolvedAst = member.resolvedAst;
|
||||
compiler.reporter.withCurrentElement(member.implementation, () {
|
||||
new CallersAstComputer(compiler.reporter, actualMap, resolvedAst,
|
||||
compiler.globalInference.typesInferrerInternal)
|
||||
.run();
|
||||
});
|
||||
}
|
||||
|
||||
abstract class ComputeValueMixin<T> {
|
||||
TypeGraphInferrer get inferrer;
|
||||
|
||||
String getMemberValue(MemberEntity member) {
|
||||
Iterable<MemberEntity> callers = inferrer.getCallersOfForTesting(member);
|
||||
if (callers != null) {
|
||||
List<String> names = callers.map((MemberEntity member) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (member.enclosingClass != null) {
|
||||
sb.write(member.enclosingClass.name);
|
||||
sb.write('.');
|
||||
}
|
||||
sb.write(member.name);
|
||||
if (member.isSetter) {
|
||||
sb.write('=');
|
||||
}
|
||||
return sb.toString();
|
||||
}).toList()
|
||||
..sort();
|
||||
return '[${names.join(',')}]';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// AST visitor for computing side effects data for a member.
|
||||
class CallersAstComputer extends AstDataExtractor
|
||||
with ComputeValueMixin<ast.Node> {
|
||||
final TypeGraphInferrer inferrer;
|
||||
|
||||
CallersAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
|
||||
ResolvedAst resolvedAst, this.inferrer)
|
||||
: super(reporter, actualMap, resolvedAst);
|
||||
|
||||
@override
|
||||
String computeElementValue(Id id, AstElement element) {
|
||||
if (element.isParameter) {
|
||||
return null;
|
||||
} else if (element.isLocal && element.isFunction) {
|
||||
LocalFunctionElement localFunction = element;
|
||||
return getMemberValue(localFunction.callMethod);
|
||||
} else {
|
||||
MemberElement member = element.declaration;
|
||||
return getMemberValue(member);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String computeNodeValue(Id id, ast.Node node, [AstElement element]) {
|
||||
if (element != null && element.isLocal && element.isFunction) {
|
||||
return computeElementValue(id, element);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute callers data for [member] from kernel based inference.
|
||||
///
|
||||
/// Fills [actualMap] with the data.
|
||||
void computeMemberIrCallers(
|
||||
Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
|
||||
{bool verbose: false}) {
|
||||
KernelBackendStrategy backendStrategy = compiler.backendStrategy;
|
||||
KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
|
||||
MemberDefinition definition = elementMap.getMemberDefinition(member);
|
||||
new CallersIrComputer(
|
||||
compiler.reporter,
|
||||
actualMap,
|
||||
elementMap,
|
||||
compiler.globalInference.typesInferrerInternal,
|
||||
backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
|
||||
.run(definition.node);
|
||||
}
|
||||
|
||||
/// AST visitor for computing side effects data for a member.
|
||||
class CallersIrComputer extends IrDataExtractor
|
||||
with ComputeValueMixin<ir.Node> {
|
||||
final TypeGraphInferrer inferrer;
|
||||
final KernelToElementMapForBuilding _elementMap;
|
||||
final ClosureDataLookup<ir.Node> _closureDataLookup;
|
||||
|
||||
CallersIrComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
|
||||
this._elementMap, this.inferrer, this._closureDataLookup)
|
||||
: super(reporter, actualMap);
|
||||
|
||||
@override
|
||||
String computeMemberValue(Id id, ir.Member node) {
|
||||
return getMemberValue(_elementMap.getMember(node));
|
||||
}
|
||||
|
||||
@override
|
||||
String computeNodeValue(Id id, ir.TreeNode node) {
|
||||
if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
|
||||
ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
|
||||
return getMemberValue(info.callMethod);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright (c) 2012, 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 use the equivalence framework.
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import '../compiler_helper.dart';
|
||||
|
||||
Future compileAndFind(String code, String name, check(compiler, element)) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(code, uri);
|
||||
return compiler.run(uri).then((_) {
|
||||
var element = findElement(compiler, name);
|
||||
check(compiler, element);
|
||||
});
|
||||
}
|
||||
|
||||
void checkPrintType(String expression, checkType(closedWorld, type)) {
|
||||
asyncTest(() => compileAndFind('main() { print($expression); }', 'print',
|
||||
(compiler, printElement) {
|
||||
var parameter = printElement.functionSignature.requiredParameters.first;
|
||||
checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
|
||||
_typeOf(compiler, parameter));
|
||||
}));
|
||||
|
||||
asyncTest(() =>
|
||||
compileAndFind('main() { var x = print; print($expression); }', 'print',
|
||||
(compiler, printElement) {
|
||||
var parameter = printElement.functionSignature.requiredParameters.first;
|
||||
checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
|
||||
_typeOf(compiler, parameter));
|
||||
}));
|
||||
|
||||
asyncTest(() => compileAndFind(
|
||||
'main() { print($expression); print($expression); }', 'print',
|
||||
(compiler, printElement) {
|
||||
var parameter = printElement.functionSignature.requiredParameters.first;
|
||||
checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
|
||||
_typeOf(compiler, parameter));
|
||||
}));
|
||||
}
|
||||
|
||||
void testBasicTypes() {
|
||||
checkPrintType('true', (closedWorld, type) {
|
||||
if (type.isForwarding) type = type.forwardTo;
|
||||
Expect.identical(closedWorld.commonMasks.boolType, type);
|
||||
});
|
||||
checkPrintType('1.5', (closedWorld, type) {
|
||||
Expect.identical(closedWorld.commonMasks.doubleType, type);
|
||||
});
|
||||
checkPrintType('1', (closedWorld, type) {
|
||||
Expect.identical(closedWorld.commonMasks.uint31Type, type);
|
||||
});
|
||||
checkPrintType('[]', (closedWorld, type) {
|
||||
if (type.isForwarding) type = type.forwardTo;
|
||||
Expect.identical(closedWorld.commonMasks.growableListType, type);
|
||||
});
|
||||
checkPrintType('null', (closedWorld, type) {
|
||||
Expect.identical(closedWorld.commonMasks.nullType, type);
|
||||
});
|
||||
checkPrintType('"foo"', (closedWorld, type) {
|
||||
Expect.isTrue(
|
||||
closedWorld.commonMasks.stringType.containsOnlyString(closedWorld));
|
||||
});
|
||||
}
|
||||
|
||||
void testOptionalParameters() {
|
||||
compileAndFind('fisk(a, [b, c]) {} main() { fisk(1); }', 'fisk',
|
||||
(compiler, fiskElement) {
|
||||
var firstParameter = fiskElement.functionSignature.requiredParameters[0];
|
||||
var secondParameter = fiskElement.functionSignature.optionalParameters[0];
|
||||
var thirdParameter = fiskElement.functionSignature.optionalParameters[1];
|
||||
var commonMasks =
|
||||
compiler.resolutionWorldBuilder.closedWorldForTesting.commonMasks;
|
||||
Expect.identical(commonMasks.uint31Type, _typeOf(compiler, firstParameter));
|
||||
Expect.identical(commonMasks.nullType, _typeOf(compiler, secondParameter));
|
||||
Expect.identical(commonMasks.nullType, _typeOf(compiler, thirdParameter));
|
||||
});
|
||||
}
|
||||
|
||||
void main() {
|
||||
testBasicTypes();
|
||||
testOptionalParameters();
|
||||
}
|
||||
|
||||
_typeOf(compiler, parameter) =>
|
||||
compiler.globalInference.results.resultOfParameter(parameter).type;
|
309
tests/compiler/dart2js/inference/data/call_site.dart
Normal file
309
tests/compiler/dart2js/inference/data/call_site.dart
Normal file
|
@ -0,0 +1,309 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
/*element: main:[null]*/
|
||||
main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test8();
|
||||
test9();
|
||||
test10();
|
||||
test11();
|
||||
test12();
|
||||
test13();
|
||||
test14();
|
||||
test15();
|
||||
test16();
|
||||
test17();
|
||||
test18();
|
||||
test19();
|
||||
}
|
||||
|
||||
/*element: A1.:[exact=A1]*/
|
||||
class A1 {
|
||||
/*element: A1.x1:Value([exact=JSString], value: "s")*/
|
||||
x1(
|
||||
/*Value([exact=JSString], value: "s")*/ p) =>
|
||||
p;
|
||||
}
|
||||
|
||||
/*element: test1:[null]*/
|
||||
test1() {
|
||||
new A1(). /*invoke: [exact=A1]*/ x1("s");
|
||||
}
|
||||
|
||||
/*element: A2.:[exact=A2]*/
|
||||
class A2 {
|
||||
/*element: A2.x2:[exact=JSUInt31]*/
|
||||
x2(/*[exact=JSUInt31]*/ p) => p;
|
||||
}
|
||||
|
||||
/*element: test2:[null]*/
|
||||
test2() {
|
||||
new A2(). /*invoke: [exact=A2]*/ x2(1);
|
||||
}
|
||||
|
||||
/*element: A3.:[exact=A3]*/
|
||||
class A3 {
|
||||
/*element: A3.x3:[empty]*/
|
||||
x3(/*[subclass=JSInt]*/ p) => /*invoke: [exact=A3]*/ x3(
|
||||
p /*invoke: [subclass=JSInt]*/ - 1);
|
||||
}
|
||||
|
||||
/*element: test3:[null]*/
|
||||
test3() {
|
||||
new A3(). /*invoke: [exact=A3]*/ x3(1);
|
||||
}
|
||||
|
||||
/*element: A4.:[exact=A4]*/
|
||||
class A4 {
|
||||
/*element: A4.x4:[empty]*/
|
||||
x4(/*[subclass=JSNumber]*/ p) => /*invoke: [exact=A4]*/ x4(
|
||||
p /*invoke: [subclass=JSNumber]*/ - 1);
|
||||
}
|
||||
|
||||
/*element: test4:[null]*/
|
||||
test4() {
|
||||
new A4(). /*invoke: [exact=A4]*/ x4(1.5);
|
||||
}
|
||||
|
||||
/*element: A5.:[exact=A5]*/
|
||||
class A5 {
|
||||
/*element: A5.x5:Union([exact=JSDouble], [exact=JSUInt31])*/
|
||||
x5(
|
||||
/*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
|
||||
p;
|
||||
}
|
||||
|
||||
/*element: test5:[null]*/
|
||||
test5() {
|
||||
new A5(). /*invoke: [exact=A5]*/ x5(1);
|
||||
new A5(). /*invoke: [exact=A5]*/ x5(1.5);
|
||||
}
|
||||
|
||||
/*element: A6.:[exact=A6]*/
|
||||
class A6 {
|
||||
/*element: A6.x6:Union([exact=JSDouble], [exact=JSUInt31])*/
|
||||
x6(
|
||||
/*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
|
||||
p;
|
||||
}
|
||||
|
||||
/*element: test6:[null]*/
|
||||
test6() {
|
||||
new A6(). /*invoke: [exact=A6]*/ x6(1.5);
|
||||
new A6(). /*invoke: [exact=A6]*/ x6(1);
|
||||
}
|
||||
|
||||
/*element: A7.:[exact=A7]*/
|
||||
class A7 {
|
||||
/*element: A7.x7:[empty]*/
|
||||
x7(
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p) => /*invoke: [exact=A7]*/ x7("x");
|
||||
}
|
||||
|
||||
/*element: test7:[null]*/
|
||||
test7() {
|
||||
new A7(). /*invoke: [exact=A7]*/ x7(1);
|
||||
}
|
||||
|
||||
/*element: A8.:[exact=A8]*/
|
||||
class A8 {
|
||||
/*element: A8.x8:[empty]*/
|
||||
x8(
|
||||
/*Union([exact=JSString], [subclass=JsLinkedHashMap])*/ p) =>
|
||||
/*invoke: [exact=A8]*/ x8("x");
|
||||
}
|
||||
|
||||
/*element: test8:[null]*/
|
||||
test8() {
|
||||
new A8(). /*invoke: [exact=A8]*/ x8({});
|
||||
}
|
||||
|
||||
/*element: A9.:[exact=A9]*/
|
||||
class A9 {
|
||||
/*element: A9.x9:[empty]*/ x9(
|
||||
/*[exact=JSUInt31]*/ p1,
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p2,
|
||||
/*Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ p3) =>
|
||||
/*invoke: [exact=A9]*/ x9(p1, "x", {});
|
||||
}
|
||||
|
||||
/*element: test9:[null]*/
|
||||
test9() {
|
||||
new A9(). /*invoke: [exact=A9]*/ x9(1, 2, 3);
|
||||
}
|
||||
|
||||
/*element: A10.:[exact=A10]*/
|
||||
class A10 {
|
||||
/*element: A10.x10:[empty]*/ x10(
|
||||
/*[exact=JSUInt31]*/ p1,
|
||||
/*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A10]*/ x10(p1, p2);
|
||||
}
|
||||
|
||||
/*element: test10:[null]*/
|
||||
test10() {
|
||||
new A10(). /*invoke: [exact=A10]*/ x10(1, 2);
|
||||
}
|
||||
|
||||
/*element: A11.:[exact=A11]*/
|
||||
class A11 {
|
||||
/*element: A11.x11:[empty]*/
|
||||
x11(
|
||||
/*[exact=JSUInt31]*/ p1,
|
||||
/*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A11]*/ x11(p1, p2);
|
||||
}
|
||||
|
||||
/*element: f11:[null]*/
|
||||
void f11(/*[null]*/ p) {
|
||||
p. /*invoke: [null]*/ x11("x", "y");
|
||||
}
|
||||
|
||||
/*element: test11:[null]*/
|
||||
test11() {
|
||||
f11(null);
|
||||
new A11(). /*invoke: [exact=A11]*/ x11(1, 2);
|
||||
}
|
||||
|
||||
/*element: A12.:[exact=A12]*/
|
||||
class A12 {
|
||||
/*element: A12.x12:[empty]*/
|
||||
x12(
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p1,
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
|
||||
/*invoke: [exact=A12]*/ x12(1, 2);
|
||||
}
|
||||
|
||||
/*element: test12:[null]*/
|
||||
test12() {
|
||||
new A12(). /*invoke: [exact=A12]*/ x12("x", "y");
|
||||
}
|
||||
|
||||
/*element: A13.:[exact=A13]*/
|
||||
class A13 {
|
||||
/*element: A13.x13:[exact=JSUInt31]*/
|
||||
x13(
|
||||
/*Value([exact=JSString], value: "x")*/ p1,
|
||||
[/*[exact=JSUInt31]*/ p2 = 1]) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: test13:[null]*/
|
||||
test13() {
|
||||
new A13(). /*invoke: [exact=A13]*/ x13("x", 1);
|
||||
new A13(). /*invoke: [exact=A13]*/ x13("x");
|
||||
}
|
||||
|
||||
/*element: A14.:[exact=A14]*/
|
||||
class A14 {
|
||||
/*element: A14.x14:[exact=JSUInt31]*/
|
||||
x14(
|
||||
/*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: f14:[exact=JSUInt31]*/
|
||||
f14(/*[exact=A14]*/ p) => p. /*invoke: [exact=A14]*/ x14(2.2);
|
||||
|
||||
/*element: test14:[null]*/
|
||||
test14() {
|
||||
new A14(). /*invoke: [exact=A14]*/ x14(1);
|
||||
f14(new A14());
|
||||
}
|
||||
|
||||
/*element: A15.:[exact=A15]*/
|
||||
class A15 {
|
||||
/*element: A15.x15:[exact=JSUInt31]*/
|
||||
x15(/*[exact=JSUInt31]*/ p1,
|
||||
[/*Value([exact=JSString], value: "s")*/ p2 = "s"]) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: test15:[null]*/
|
||||
test15() {
|
||||
new A15(). /*invoke: [exact=A15]*/ x15(1);
|
||||
}
|
||||
|
||||
/*element: A16.:[exact=A16]*/
|
||||
class A16 {
|
||||
/*element: A16.x16:[exact=JSUInt31]*/
|
||||
x16(
|
||||
/*Value([exact=JSString], value: "x")*/ p1,
|
||||
[/*[exact=JSBool]*/ p2 = true]) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: f16:[empty]*/
|
||||
f16(/*[null]*/ p) => p. /*invoke: [null]*/ a("x");
|
||||
|
||||
/*element: test16:[null]*/
|
||||
test16() {
|
||||
new A16(). /*invoke: [exact=A16]*/ x16("x");
|
||||
new A16(). /*invoke: [exact=A16]*/ x16("x", false);
|
||||
f16(null);
|
||||
}
|
||||
|
||||
/*element: A17.:[exact=A17]*/
|
||||
class A17 {
|
||||
/*element: A17.x17:[exact=JSUInt31]*/
|
||||
x17(/*[exact=JSUInt31]*/ p1,
|
||||
[/*[exact=JSUInt31]*/ p2 = 1, /*[exact=JSString]*/ p3 = "s"]) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: test17:[null]*/
|
||||
test17() {
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1);
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, 2);
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, 2, "x");
|
||||
// ignore: undefined_named_parameter
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2);
|
||||
// ignore: undefined_named_parameter
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x");
|
||||
// ignore: undefined_named_parameter
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x", p2: 2);
|
||||
// ignore: undefined_named_parameter
|
||||
new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2, p3: "x");
|
||||
}
|
||||
|
||||
/*element: A18.:[exact=A18]*/
|
||||
class A18 {
|
||||
/*element: A18.x18:[exact=JSUInt31]*/
|
||||
x18(/*[exact=JSUInt31]*/ p1,
|
||||
[/*[exact=JSBool]*/ p2 = 1, /*[exact=JSDouble]*/ p3 = "s"]) =>
|
||||
1;
|
||||
}
|
||||
|
||||
/*element: test18:[null]*/
|
||||
test18() {
|
||||
new A18(). /*invoke: [exact=A18]*/ x18(1, true, 1.1);
|
||||
new A18(). /*invoke: [exact=A18]*/ x18(1, false, 2.2);
|
||||
// ignore: undefined_named_parameter
|
||||
new A18(). /*invoke: [exact=A18]*/ x18(1, p3: 3.3, p2: true);
|
||||
// ignore: undefined_named_parameter
|
||||
new A18(). /*invoke: [exact=A18]*/ x18(1, p2: false, p3: 4.4);
|
||||
}
|
||||
|
||||
/*element: A19.:[exact=A19]*/
|
||||
class A19 {
|
||||
/*element: A19.x19:[empty]*/
|
||||
x19(
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p1,
|
||||
/*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
|
||||
/*invoke: [subclass=A19]*/ x19(p1, p2);
|
||||
}
|
||||
|
||||
/*element: B19.:[exact=B19]*/
|
||||
class B19 extends A19 {}
|
||||
|
||||
/*element: test19:[null]*/
|
||||
test19() {
|
||||
new B19(). /*invoke: [exact=B19]*/ x19("a", "b");
|
||||
new A19(). /*invoke: [exact=A19]*/ x19(1, 2);
|
||||
}
|
196
tests/compiler/dart2js/inference/data/dictionary_types.dart
Normal file
196
tests/compiler/dart2js/inference/data/dictionary_types.dart
Normal file
|
@ -0,0 +1,196 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
/*element: main:[null]*/
|
||||
main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
}
|
||||
|
||||
/*element: dictionaryA1:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
var dictionaryA1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
|
||||
|
||||
/*element: dictionaryB1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
|
||||
var dictionaryB1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
|
||||
|
||||
/*element: otherDict1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
|
||||
var otherDict1 = {'stringTwo': "anotherString", 'intTwo': 84};
|
||||
|
||||
/*element: int1:[exact=JSUInt31]*/
|
||||
var int1 = 0;
|
||||
|
||||
/*element: anotherInt1:[exact=JSUInt31]*/
|
||||
var anotherInt1 = 0;
|
||||
|
||||
/*element: nullOrInt1:[null|exact=JSUInt31]*/
|
||||
var nullOrInt1 = 0;
|
||||
|
||||
/*element: dynamic1:[null|subclass=Object]*/
|
||||
var dynamic1 = 0;
|
||||
|
||||
/*element: test1:[null]*/
|
||||
test1() {
|
||||
dictionaryA1
|
||||
. /*invoke: Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
addAll(otherDict1);
|
||||
dictionaryB1
|
||||
. /*invoke: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
|
||||
addAll({'stringTwo': "anotherString", 'intTwo': 84});
|
||||
int1 = dictionaryB1
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
|
||||
['int'];
|
||||
anotherInt1 = otherDict1
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
|
||||
['intTwo'];
|
||||
dynamic1 = dictionaryA1
|
||||
/*Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
|
||||
'int'];
|
||||
nullOrInt1 = dictionaryB1
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
|
||||
['intTwo'];
|
||||
}
|
||||
|
||||
/*element: dictionaryA2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
var dictionaryA2 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
|
||||
|
||||
/*element: dictionaryB2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
var dictionaryB2 = {'string': "aString", 'intTwo': 42, 'list': []};
|
||||
|
||||
/*element: nullOrInt2:[null|exact=JSUInt31]*/
|
||||
var nullOrInt2 = 0;
|
||||
|
||||
/*element: aString2:[exact=JSString]*/
|
||||
var aString2 = "";
|
||||
|
||||
/*element: doubleOrNull2:[null|exact=JSDouble]*/
|
||||
var doubleOrNull2 = 22.2;
|
||||
|
||||
/*element: test2:[null]*/
|
||||
test2() {
|
||||
var union = dictionaryA2
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
['foo']
|
||||
? dictionaryA2
|
||||
: dictionaryB2;
|
||||
nullOrInt2 = union
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
['intTwo'];
|
||||
aString2 = union
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
['string'];
|
||||
doubleOrNull2 = union
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
['double'];
|
||||
}
|
||||
|
||||
/*element: dictionary3:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
var dictionary3 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
|
||||
/*element: keyD3:Value([exact=JSString], value: "double")*/
|
||||
var keyD3 = 'double';
|
||||
|
||||
/*element: keyI3:Value([exact=JSString], value: "int")*/
|
||||
var keyI3 = 'int';
|
||||
|
||||
/*element: keyN3:Value([exact=JSString], value: "notFoundInMap")*/
|
||||
var keyN3 = 'notFoundInMap';
|
||||
|
||||
/*element: knownDouble3:[exact=JSDouble]*/
|
||||
var knownDouble3 = 42.2;
|
||||
|
||||
/*element: intOrNull3:[null|exact=JSUInt31]*/
|
||||
var intOrNull3 = dictionary3
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
[keyI3];
|
||||
|
||||
/*element: justNull3:[null]*/
|
||||
var justNull3 = dictionary3
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
[keyN3];
|
||||
|
||||
/*element: test3:[null]*/
|
||||
test3() {
|
||||
knownDouble3 = dictionary3
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
|
||||
[keyD3];
|
||||
// ignore: unused_local_variable
|
||||
var x = [intOrNull3, justNull3];
|
||||
}
|
||||
|
||||
class A4 {
|
||||
/*element: A4.:[exact=A4]*/
|
||||
A4();
|
||||
/*element: A4.foo4:[exact=JSUInt31]*/
|
||||
foo4(
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
|
||||
return value /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
|
||||
'anInt'];
|
||||
}
|
||||
}
|
||||
|
||||
class B4 {
|
||||
/*element: B4.:[exact=B4]*/
|
||||
B4();
|
||||
|
||||
/*element: B4.foo4:[exact=JSUInt31]*/
|
||||
foo4(
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*element: test4:[null]*/
|
||||
test4() {
|
||||
var dictionary = {'anInt': 42, 'aString': "theString"};
|
||||
var it;
|
||||
if ([true, false]
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSBool], length: 2)*/
|
||||
[0]) {
|
||||
it = new A4();
|
||||
} else {
|
||||
it = new B4();
|
||||
}
|
||||
print(it. /*invoke: Union([exact=A4], [exact=B4])*/ foo4(
|
||||
dictionary) /*invoke: [exact=JSUInt31]*/ +
|
||||
2);
|
||||
}
|
||||
|
||||
/*element: dict5:Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
var dict5 = makeMap5([1, 2]);
|
||||
|
||||
/*element: notInt5:[null|subclass=Object]*/
|
||||
var notInt5 = 0;
|
||||
|
||||
/*element: alsoNotInt5:[null|subclass=Object]*/
|
||||
var alsoNotInt5 = 0;
|
||||
|
||||
/*element: makeMap5:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
makeMap5(
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/ values) {
|
||||
return {
|
||||
'moo': values
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
|
||||
[0],
|
||||
'boo': values
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
|
||||
[1]
|
||||
};
|
||||
}
|
||||
|
||||
/*element: test5:[null]*/
|
||||
test5() {
|
||||
dict5
|
||||
/*update: Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
['goo'] = 42;
|
||||
var closure =
|
||||
/*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
() => dict5;
|
||||
notInt5 = closure()['boo'];
|
||||
alsoNotInt5 = dict5
|
||||
/*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
|
||||
['goo'];
|
||||
print("$notInt5 and $alsoNotInt5.");
|
||||
}
|
189
tests/compiler/dart2js/inference/data/map_tracer_keys.dart
Normal file
189
tests/compiler/dart2js/inference/data/map_tracer_keys.dart
Normal file
|
@ -0,0 +1,189 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
/*element: main:[null]*/
|
||||
main() {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
}
|
||||
|
||||
/*element: aDouble1:[null|exact=JSDouble]*/
|
||||
double aDouble1 = 42.5;
|
||||
|
||||
/*element: aList1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
List aList1 = [42];
|
||||
|
||||
/*element: consume1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
consume1(
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test1:[null]*/
|
||||
test1() {
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
|
||||
theMap
|
||||
/*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
|
||||
['d'] = 5.5;
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
|
||||
keys) {
|
||||
aDouble1 = theMap
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume1(aList1);
|
||||
}
|
||||
|
||||
/*element: aDouble2:[null|exact=JSDouble]*/
|
||||
double aDouble2 = 42.5;
|
||||
|
||||
/*element: aList2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
List aList2 = [42];
|
||||
|
||||
/*element: consume2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
consume2(
|
||||
/*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test2:[null]*/
|
||||
test2() {
|
||||
dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
|
||||
theMap
|
||||
/*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
|
||||
[aList2] = 5.5;
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
|
||||
keys) {
|
||||
aDouble2 = theMap
|
||||
/*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume2(aList2);
|
||||
}
|
||||
|
||||
/*element: aDouble3:Union([exact=JSDouble], [null|exact=JSExtendableArray])*/
|
||||
double aDouble3 = 42.5;
|
||||
|
||||
/*element: aList3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
List aList3 = [42];
|
||||
|
||||
/*element: consume3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
consume3(
|
||||
/*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test3:[null]*/
|
||||
test3() {
|
||||
dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
|
||||
theMap
|
||||
/*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
|
||||
['d'] = aList3;
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
|
||||
keys) {
|
||||
aDouble3 = theMap
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume3(aList3);
|
||||
}
|
||||
|
||||
/*element: aDouble4:[null|exact=JSDouble]*/
|
||||
double aDouble4 = 42.5;
|
||||
|
||||
/*element: aList4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
List aList4 = [42];
|
||||
|
||||
/*element: consume4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
consume4(
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test4:[null]*/
|
||||
test4() {
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': 5.5};
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
|
||||
keys) {
|
||||
aDouble4 = theMap
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume4(aList4);
|
||||
}
|
||||
|
||||
/*element: aDouble5:[null|exact=JSDouble]*/
|
||||
double aDouble5 = 42.5;
|
||||
|
||||
/*element: aList5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
List aList5 = [42];
|
||||
|
||||
/*element: consume5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
|
||||
consume5(
|
||||
/*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test5:[null]*/
|
||||
test5() {
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, aList5: 5.5};
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
|
||||
keys) {
|
||||
aDouble5 = theMap
|
||||
/*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume5(aList5);
|
||||
}
|
||||
|
||||
/*element: aDouble6:Union([null|exact=JSDouble], [null|exact=JSExtendableArray])*/
|
||||
double aDouble6 = 42.5;
|
||||
/*element: aList6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
List aList6 = [42];
|
||||
|
||||
/*element: consume6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
|
||||
consume6(
|
||||
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
|
||||
x;
|
||||
|
||||
/*element: test6:[null]*/
|
||||
test6() {
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': aList6};
|
||||
/*iterator: [exact=LinkedHashMapKeyIterable]*/
|
||||
/*current: [exact=LinkedHashMapKeyIterator]*/
|
||||
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
|
||||
for (var key in theMap.
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
|
||||
keys) {
|
||||
aDouble6 = theMap
|
||||
/*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([null|exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
|
||||
[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume6(aList6);
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
// Copyright (c) 2014, 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 use the equivalence framework.
|
||||
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/commandline_options.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import '../memory_compiler.dart';
|
||||
|
||||
var SOURCES = const {
|
||||
'AddAll.dart': """
|
||||
var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
|
||||
'list': []};
|
||||
var dictionaryB = {'string': "aString", 'int': 42, 'double': 21.5,
|
||||
'list': []};
|
||||
var otherDict = {'stringTwo' : "anotherString", 'intTwo' : 84};
|
||||
var int = 0;
|
||||
var anotherInt = 0;
|
||||
var nullOrInt = 0;
|
||||
var dynamic = 0;
|
||||
|
||||
main() {
|
||||
dictionaryA.addAll(otherDict);
|
||||
dictionaryB.addAll({'stringTwo' : "anotherString", 'intTwo' : 84});
|
||||
int = dictionaryB['int'];
|
||||
anotherInt = otherDict['intTwo'];
|
||||
dynamic = dictionaryA['int'];
|
||||
nullOrInt = dictionaryB['intTwo'];
|
||||
}
|
||||
""",
|
||||
'Union.dart': """
|
||||
var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
|
||||
'list': []};
|
||||
var dictionaryB = {'string': "aString", 'intTwo': 42, 'list': []};
|
||||
var nullOrInt = 0;
|
||||
var aString = "";
|
||||
var doubleOrNull = 22.2;
|
||||
var key = "string";
|
||||
|
||||
main() {
|
||||
var union = dictionaryA['foo'] ? dictionaryA : dictionaryB;
|
||||
nullOrInt = union['intTwo'];
|
||||
aString = union['string'];
|
||||
doubleOrNull = union['double'];
|
||||
}
|
||||
""",
|
||||
'ValueType.dart': """
|
||||
var dictionary = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
|
||||
var keyD = 'double';
|
||||
var keyI = 'int';
|
||||
var keyN = 'notFoundInMap';
|
||||
var knownDouble = 42.2;
|
||||
var intOrNull = dictionary[keyI];
|
||||
var justNull = dictionary[keyN];
|
||||
|
||||
main() {
|
||||
knownDouble = dictionary[keyD];
|
||||
var x = [intOrNull, justNull];
|
||||
}
|
||||
""",
|
||||
'Propagation.dart': """
|
||||
class A {
|
||||
A();
|
||||
foo(value) {
|
||||
return value['anInt'];
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
B();
|
||||
foo(value) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
var dictionary = {'anInt': 42, 'aString': "theString"};
|
||||
var it;
|
||||
if ([true, false][0]) {
|
||||
it = new A();
|
||||
} else {
|
||||
it = new B();
|
||||
}
|
||||
print(it.foo(dictionary) + 2);
|
||||
}
|
||||
""",
|
||||
'Bailout.dart': """
|
||||
var dict = makeMap([1,2]);
|
||||
var notInt = 0;
|
||||
var alsoNotInt = 0;
|
||||
|
||||
makeMap(values) {
|
||||
return {'moo': values[0], 'boo': values[1]};
|
||||
}
|
||||
|
||||
main () {
|
||||
dict['goo'] = 42;
|
||||
var closure = () => dict;
|
||||
notInt = closure()['boo'];
|
||||
alsoNotInt = dict['goo'];
|
||||
print("\$notInt and \$alsoNotInt.");
|
||||
}
|
||||
"""
|
||||
};
|
||||
|
||||
void main() {
|
||||
asyncTest(() async {
|
||||
print('--test from ast---------------------------------------------------');
|
||||
await runTests(useKernel: false);
|
||||
print('--test from kernel------------------------------------------------');
|
||||
await runTests(useKernel: true);
|
||||
});
|
||||
}
|
||||
|
||||
runTests({bool useKernel}) async {
|
||||
await compileAndTest("AddAll.dart", (types, getType, closedWorld) {
|
||||
Expect.equals(getType('int'), types.uint31Type);
|
||||
Expect.equals(getType('anotherInt'), types.uint31Type);
|
||||
Expect.equals(getType('dynamic'), types.dynamicType);
|
||||
Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
|
||||
}, useKernel: useKernel);
|
||||
await compileAndTest("Union.dart", (types, getType, closedWorld) {
|
||||
Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
|
||||
Expect.isTrue(getType('aString').containsOnlyString(closedWorld));
|
||||
Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
|
||||
}, useKernel: useKernel);
|
||||
await compileAndTest("ValueType.dart", (types, getType, closedWorld) {
|
||||
Expect.equals(getType('knownDouble'), types.doubleType);
|
||||
Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
|
||||
Expect.equals(getType('justNull'), types.nullType);
|
||||
}, useKernel: useKernel);
|
||||
await compileAndTest("Propagation.dart", (code) {
|
||||
Expect.isFalse(code.contains("J.\$add\$ns"));
|
||||
}, createCode: true, useKernel: useKernel);
|
||||
await compileAndTest("Bailout.dart", (types, getType, closedWorld) {
|
||||
Expect.equals(getType('notInt'), types.dynamicType);
|
||||
Expect.equals(getType('alsoNotInt'), types.dynamicType);
|
||||
Expect.isFalse(getType('dict').isDictionary);
|
||||
}, useKernel: useKernel);
|
||||
}
|
||||
|
||||
compileAndTest(source, checker,
|
||||
{bool createCode: false, bool useKernel}) async {
|
||||
CompilationResult result = await runCompiler(
|
||||
entryPoint: Uri.parse('memory:' + source),
|
||||
memorySourceFiles: SOURCES,
|
||||
beforeRun: (compiler) {
|
||||
compiler.stopAfterTypeInference = !createCode;
|
||||
},
|
||||
options: useKernel ? [Flags.useKernel] : []);
|
||||
var compiler = result.compiler;
|
||||
var typesInferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = typesInferrer.closedWorld;
|
||||
var elementEnvironment = closedWorld.elementEnvironment;
|
||||
var commonMasks = closedWorld.commonMasks;
|
||||
getType(String name) {
|
||||
var element = elementEnvironment.lookupLibraryMember(
|
||||
elementEnvironment.mainLibrary, name);
|
||||
Expect.isNotNull(element, "No class '$name' found.");
|
||||
return typesInferrer.getTypeOfMember(element);
|
||||
}
|
||||
|
||||
if (!createCode) {
|
||||
checker(commonMasks, getType, closedWorld);
|
||||
} else {
|
||||
var element = elementEnvironment.mainFunction;
|
||||
var code = compiler.backend.getGeneratedCode(element);
|
||||
checker(code);
|
||||
}
|
||||
}
|
|
@ -1,689 +0,0 @@
|
|||
// 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 use the equivalence framework.
|
||||
/// Currently it only works with the mock compiler.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/types/types.dart' show TypeMask;
|
||||
import 'package:compiler/src/world.dart' show ClosedWorld;
|
||||
|
||||
import 'type_mask_test_helper.dart';
|
||||
import '../compiler_helper.dart';
|
||||
|
||||
void compileAndFind(String code, String className, String memberName,
|
||||
bool disableInlining, check(compiler, element)) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
dynamic cls = findElement(compiler, className);
|
||||
var member = cls.lookupMember(memberName);
|
||||
check(compiler, member);
|
||||
}));
|
||||
}
|
||||
|
||||
const String TEST_1 = r"""
|
||||
class A {
|
||||
int f;
|
||||
}
|
||||
main() { new A(); }
|
||||
""";
|
||||
|
||||
const String TEST_2 = r"""
|
||||
class A {
|
||||
int f1;
|
||||
int f2 = 1;
|
||||
}
|
||||
main() { new A(); }
|
||||
""";
|
||||
|
||||
const String TEST_3 = r"""
|
||||
class A {
|
||||
int f1;
|
||||
int f2;
|
||||
A() : f1 = 1;
|
||||
}
|
||||
main() { new A().f2 = 2; }
|
||||
""";
|
||||
|
||||
const String TEST_4 = r"""
|
||||
class A {
|
||||
int f1;
|
||||
int f2;
|
||||
A() : f1 = 1;
|
||||
}
|
||||
main() {
|
||||
A a = new A();
|
||||
a.f1 = "a";
|
||||
a.f2 = "a";
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_5 = r"""
|
||||
class A {
|
||||
int f1 = 1;
|
||||
int f2 = 1;
|
||||
A(x) {
|
||||
f1 = "1";
|
||||
if (x) {
|
||||
f2 = "1";
|
||||
} else {
|
||||
f2 = "2";
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_6 = r"""
|
||||
class A {
|
||||
int f1 = 1;
|
||||
int f2 = 1;
|
||||
A(x) {
|
||||
f1 = "1";
|
||||
if (x) {
|
||||
f2 = "1";
|
||||
} else {
|
||||
f2 = "2";
|
||||
}
|
||||
if (x) {
|
||||
f2 = new List();
|
||||
} else {
|
||||
f2 = new List();
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_7 = r"""
|
||||
class A {
|
||||
int f1 = 1;
|
||||
int f2 = 1;
|
||||
A(x) {
|
||||
f1 = "1";
|
||||
if (x) {
|
||||
f2 = "1";
|
||||
} else {
|
||||
f2 = "2";
|
||||
}
|
||||
if (x) {
|
||||
f1 = new List();
|
||||
f2 = new List();
|
||||
} else {
|
||||
f2 = new List();
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_8 = r"""
|
||||
class A {
|
||||
int f;
|
||||
A(x) {
|
||||
if (x) {
|
||||
f = "1";
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_9 = r"""
|
||||
class A {
|
||||
int f;
|
||||
A(x) {
|
||||
if (x) {
|
||||
} else {
|
||||
f = "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_10 = r"""
|
||||
class A {
|
||||
int f;
|
||||
A() {
|
||||
f = 1;
|
||||
}
|
||||
m() => f + 1;
|
||||
}
|
||||
void f(x) { x.f = "2"; }
|
||||
main() {
|
||||
A a;
|
||||
f(a);
|
||||
a = new A();
|
||||
a.m();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_11 = r"""
|
||||
class S {
|
||||
int fs = 1;
|
||||
ms() { fs = 1; }
|
||||
}
|
||||
|
||||
class A extends S {
|
||||
m() { ms(); }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
a.m();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_12 = r"""
|
||||
class S {
|
||||
int fs = 1;
|
||||
S() { fs = "2"; }
|
||||
}
|
||||
|
||||
class A extends S {
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_13 = r"""
|
||||
class S {
|
||||
int fs;
|
||||
S() { fs = 1; }
|
||||
}
|
||||
|
||||
class A extends S {
|
||||
A() { fs = 1; }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_14 = r"""
|
||||
class A {
|
||||
var f;
|
||||
A() { f = 1; }
|
||||
A.other() { f = 2; }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
a = new A.other();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_15 = r"""
|
||||
class A {
|
||||
var f;
|
||||
A() { f = "1"; }
|
||||
A.other() { f = new List(); }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
a = new A.other();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_16 = r"""
|
||||
class A {
|
||||
var f;
|
||||
A() { f = "1"; }
|
||||
A.other() : f = 1 { }
|
||||
}
|
||||
|
||||
main() {
|
||||
A a = new A();
|
||||
a = new A.other();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_17 = r"""
|
||||
g([p]) => p.f = 1;
|
||||
class A {
|
||||
var f;
|
||||
A(x) {
|
||||
var a;
|
||||
if (x) {
|
||||
a = this;
|
||||
} else {
|
||||
a = g;
|
||||
}
|
||||
a(this);
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_18 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
var f3;
|
||||
A(x) {
|
||||
f1 = 1;
|
||||
var a;
|
||||
if (x) {
|
||||
f2 = "1";
|
||||
a = this;
|
||||
} else {
|
||||
a = 1;
|
||||
f2 = "1";
|
||||
}
|
||||
f3 = a;
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_19 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
var f3;
|
||||
A(x) {
|
||||
f1 = 1;
|
||||
var a;
|
||||
if (x) {
|
||||
f2 = "1";
|
||||
a = this;
|
||||
} else {
|
||||
a = 1;
|
||||
f2 = "1";
|
||||
}
|
||||
f3 = a;
|
||||
a();
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(true);
|
||||
new A(false);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_20 = r"""
|
||||
class A {
|
||||
var f;
|
||||
A() {
|
||||
for (f in this) {
|
||||
}
|
||||
}
|
||||
get iterator => this;
|
||||
get current => 42;
|
||||
bool moveNext() => false;
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_21 = r"""
|
||||
class A {
|
||||
var f;
|
||||
A() {
|
||||
for (var i in this) {
|
||||
}
|
||||
f = 42;
|
||||
}
|
||||
get iterator => null;
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_22 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
var f3;
|
||||
A() {
|
||||
f1 = 42;
|
||||
f2 = f1 == null ? 42 : f3 == null ? 41: 43;
|
||||
f3 = 'foo';
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_23 = r"""
|
||||
class A {
|
||||
var f1 = 42;
|
||||
var f2 = 42;
|
||||
var f3 = 42;
|
||||
var f4 = 42;
|
||||
A() {
|
||||
// Test string interpolation.
|
||||
'${f1 = null}';
|
||||
// Test string juxtaposition.
|
||||
''
|
||||
'${f2 = null}';
|
||||
// Test list literal.
|
||||
[f3 = null];
|
||||
// Test map literal.
|
||||
var c = {'foo': f4 = null };
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_24 = r"""
|
||||
class A {
|
||||
var f1 = 42;
|
||||
var f2 = 42;
|
||||
var f3 = 42;
|
||||
final f4;
|
||||
var f5;
|
||||
var f6 = null;
|
||||
A() : f4 = 42 {
|
||||
f1++;
|
||||
f2 += 42;
|
||||
var f6 = 'foo';
|
||||
this.f6 = f6;
|
||||
}
|
||||
A.foo(other) : f3 = other.f3, f4 = other.f4, f5 = other.bar();
|
||||
operator+(other) => 'foo';
|
||||
bar() => 42.5;
|
||||
}
|
||||
class B extends A {
|
||||
bar() => 42;
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
new A.foo(new A());
|
||||
new A.foo(new B());
|
||||
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_25 = r"""
|
||||
class A {
|
||||
var f1 = 42;
|
||||
}
|
||||
class B {
|
||||
var f1 = '42';
|
||||
}
|
||||
main() {
|
||||
new B();
|
||||
new A().f1 = new A().f1;
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_26 = r"""
|
||||
class A {
|
||||
var f1 = 42;
|
||||
}
|
||||
class B {
|
||||
var f1 = 54;
|
||||
}
|
||||
main() {
|
||||
new A().f1 = [new B(), new A()][0].f1 + 42;
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_27 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
A() {
|
||||
this.f1 = 42;
|
||||
this.f2 = 42;
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
set f2(value) {}
|
||||
}
|
||||
main() {
|
||||
new A();
|
||||
new B();
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_28 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
A(x) {
|
||||
this.f1 = x;
|
||||
if (x == 0) return;
|
||||
this.f2 = x;
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(0);
|
||||
new A(1);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_29 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
A(x) {
|
||||
this.f1 = x;
|
||||
if (x == 0) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
this.f2 = x;
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(0);
|
||||
new A(1);
|
||||
}
|
||||
""";
|
||||
|
||||
const String TEST_30 = r"""
|
||||
class A {
|
||||
var f1;
|
||||
var f2;
|
||||
var f3;
|
||||
A(x) {
|
||||
this.f1 = x;
|
||||
if (x == 0) {
|
||||
this.f2 = 1;
|
||||
} else {
|
||||
this.f2 = x;
|
||||
return;
|
||||
}
|
||||
this.f3 = x;
|
||||
}
|
||||
}
|
||||
main() {
|
||||
new A(0);
|
||||
new A(1);
|
||||
}
|
||||
""";
|
||||
|
||||
typedef TypeMask TestCallback(ClosedWorld closedWorld);
|
||||
|
||||
void doTest(
|
||||
String test, bool disableInlining, Map<String, TestCallback> fields) {
|
||||
fields.forEach((String name, TestCallback f) {
|
||||
compileAndFind(test, 'A', name, disableInlining, (compiler, field) {
|
||||
var inferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = inferrer.closedWorld;
|
||||
TypeMask type = f(closedWorld);
|
||||
TypeMask inferredType =
|
||||
simplify(inferrer.getTypeOfMember(field), closedWorld);
|
||||
Expect.equals(type, inferredType, '$name of:\n$test');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void runTest(String test, Map<String, TestCallback> fields) {
|
||||
doTest(test, false, fields);
|
||||
doTest(test, true, fields);
|
||||
}
|
||||
|
||||
void test() {
|
||||
runTest(TEST_1, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.nullType
|
||||
});
|
||||
runTest(TEST_2, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.nullType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
runTest(TEST_3, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_4, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
|
||||
});
|
||||
|
||||
// TODO(ngeoffray): We should try to infer that the initialization
|
||||
// code at the declaration site of the fields does not matter.
|
||||
runTest(TEST_5, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
});
|
||||
runTest(TEST_6, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
});
|
||||
runTest(TEST_7, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
|
||||
});
|
||||
|
||||
runTest(TEST_8, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
|
||||
});
|
||||
runTest(TEST_9, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
|
||||
});
|
||||
runTest(TEST_10, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
runTest(TEST_11, <String, TestCallback>{
|
||||
'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
|
||||
// TODO(ngeoffray): We should try to infer that the initialization
|
||||
// code at the declaration site of the fields does not matter.
|
||||
runTest(TEST_12, <String, TestCallback>{
|
||||
'fs': (closedWorld) => closedWorld.commonMasks.interceptorType
|
||||
});
|
||||
|
||||
runTest(TEST_13, <String, TestCallback>{
|
||||
'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
runTest(TEST_14, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
runTest(TEST_15, <String, TestCallback>{
|
||||
'f': (closedWorld) {
|
||||
ClassElement cls = closedWorld.commonElements.jsIndexableClass;
|
||||
return new TypeMask.nonNullSubtype(cls, closedWorld);
|
||||
}
|
||||
});
|
||||
runTest(TEST_16, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.interceptorType
|
||||
});
|
||||
runTest(TEST_17, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_18, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.stringType,
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
|
||||
});
|
||||
runTest(TEST_19, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.stringType,
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
|
||||
});
|
||||
runTest(TEST_20, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_21, <String, TestCallback>{
|
||||
'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
|
||||
runTest(TEST_22, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
|
||||
});
|
||||
|
||||
runTest(TEST_23, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
|
||||
'f4': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
|
||||
runTest(TEST_24, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.positiveIntType,
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f4': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f5': (closedWorld) => closedWorld.commonMasks.numType.nullable(),
|
||||
'f6': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
|
||||
});
|
||||
|
||||
runTest(TEST_25, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type
|
||||
});
|
||||
runTest(TEST_26, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType
|
||||
});
|
||||
runTest(TEST_27, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_28, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_29, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
runTest(TEST_30, <String, TestCallback>{
|
||||
'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
|
||||
'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
|
||||
});
|
||||
}
|
||||
|
||||
void main() {
|
||||
test();
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
// 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): Currently this only works with the mock compiler.
|
||||
/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
|
||||
/// works with the mock compiler.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "package:async_helper/async_helper.dart";
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
// 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): Currently this only works with the mock compiler.
|
||||
/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
|
||||
/// works with the mock compiler.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
import "package:async_helper/async_helper.dart";
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
/// TODO(johnniwinther): Port this test to use the equivalence framework.
|
||||
/// Currently it only works with the mock compiler.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import "package:async_helper/async_helper.dart";
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
|
||||
import 'package:compiler/src/commandline_options.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'type_mask_test_helper.dart';
|
||||
import '../compiler_helper.dart';
|
||||
import '../memory_compiler.dart';
|
||||
|
||||
String generateTest(String listAllocation) {
|
||||
return """
|
||||
|
@ -189,58 +190,76 @@ main() {
|
|||
}
|
||||
|
||||
void main() {
|
||||
doTest('[]', nullify: false); // Test literal list.
|
||||
doTest('new List()', nullify: false); // Test growable list.
|
||||
doTest('new List(1)', nullify: true); // Test fixed list.
|
||||
doTest('new List.filled(1, 0)', nullify: false); // Test List.filled.
|
||||
doTest('new List.filled(1, null)', nullify: true); // Test List.filled.
|
||||
runTest({bool useKernel}) async {
|
||||
// Test literal list.
|
||||
await doTest('[]', nullify: false, useKernel: useKernel);
|
||||
// Test growable list.
|
||||
await doTest('new List()', nullify: false, useKernel: useKernel);
|
||||
// Test fixed list.
|
||||
await doTest('new List(1)', nullify: true, useKernel: useKernel);
|
||||
// Test List.filled.
|
||||
await doTest('new List.filled(1, 0)', nullify: false, useKernel: useKernel);
|
||||
// Test List.filled.
|
||||
await doTest('new List.filled(1, null)',
|
||||
nullify: true, useKernel: useKernel);
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
print('--test from ast---------------------------------------------------');
|
||||
await runTest(useKernel: false);
|
||||
print('--test from kernel------------------------------------------------');
|
||||
await runTest(useKernel: true);
|
||||
});
|
||||
}
|
||||
|
||||
void doTest(String allocation, {bool nullify}) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(generateTest(allocation), uri,
|
||||
expectedErrors: 0, expectedWarnings: 1);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
var typesInferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = typesInferrer.closedWorld;
|
||||
var commonMasks = closedWorld.commonMasks;
|
||||
doTest(String allocation, {bool nullify, bool useKernel}) async {
|
||||
String source = generateTest(allocation);
|
||||
var result = await runCompiler(
|
||||
memorySourceFiles: {'main.dart': source},
|
||||
options: useKernel ? [Flags.useKernel] : []);
|
||||
Expect.isTrue(result.isSuccess);
|
||||
var compiler = result.compiler;
|
||||
var typesInferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = typesInferrer.closedWorld;
|
||||
var commonMasks = closedWorld.commonMasks;
|
||||
|
||||
checkType(String name, type) {
|
||||
MemberElement element = findElement(compiler, name);
|
||||
ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
|
||||
if (nullify) type = type.nullable();
|
||||
Expect.equals(type, simplify(mask.elementType, closedWorld), name);
|
||||
}
|
||||
checkType(String name, type) {
|
||||
var element = findMember(closedWorld, name);
|
||||
ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
|
||||
if (nullify) type = type.nullable();
|
||||
Expect.equals(type, simplify(mask.elementType, closedWorld), name);
|
||||
}
|
||||
|
||||
checkType('listInField', commonMasks.numType);
|
||||
checkType('listPassedToMethod', commonMasks.numType);
|
||||
checkType('listReturnedFromMethod', commonMasks.numType);
|
||||
checkType('listUsedWithCascade', commonMasks.numType);
|
||||
checkType('listUsedInClosure', commonMasks.numType);
|
||||
checkType('listPassedToSelector', commonMasks.numType);
|
||||
checkType('listReturnedFromSelector', commonMasks.numType);
|
||||
checkType('listUsedWithAddAndInsert', commonMasks.numType);
|
||||
checkType('listUsedWithConstraint', commonMasks.positiveIntType);
|
||||
checkType('listEscapingFromSetter', commonMasks.numType);
|
||||
checkType('listUsedInLocal', commonMasks.numType);
|
||||
checkType('listEscapingInSetterValue', commonMasks.numType);
|
||||
checkType('listEscapingInIndex', commonMasks.numType);
|
||||
checkType('listEscapingInIndexSet', commonMasks.uint31Type);
|
||||
checkType('listEscapingTwiceInIndexSet', commonMasks.numType);
|
||||
checkType('listSetInNonFinalField', commonMasks.numType);
|
||||
checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
|
||||
checkType('listInField', commonMasks.numType);
|
||||
checkType('listPassedToMethod', commonMasks.numType);
|
||||
checkType('listReturnedFromMethod', commonMasks.numType);
|
||||
checkType('listUsedWithCascade', commonMasks.numType);
|
||||
checkType('listUsedInClosure', commonMasks.numType);
|
||||
checkType('listPassedToSelector', commonMasks.numType);
|
||||
checkType('listReturnedFromSelector', commonMasks.numType);
|
||||
checkType('listUsedWithAddAndInsert', commonMasks.numType);
|
||||
checkType('listUsedWithConstraint', commonMasks.positiveIntType);
|
||||
checkType('listEscapingFromSetter', commonMasks.numType);
|
||||
checkType('listUsedInLocal', commonMasks.numType);
|
||||
checkType('listEscapingInSetterValue', commonMasks.numType);
|
||||
checkType('listEscapingInIndex', commonMasks.numType);
|
||||
checkType('listEscapingInIndexSet', commonMasks.uint31Type);
|
||||
// TODO(johnniwinther): Since Iterable.iterableToString is part of the closed
|
||||
// world we find the `dynamicType` instead of `numType`.
|
||||
checkType('listEscapingTwiceInIndexSet', commonMasks.dynamicType);
|
||||
checkType('listSetInNonFinalField', commonMasks.numType);
|
||||
checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
|
||||
|
||||
checkType('listPassedToClosure', commonMasks.dynamicType);
|
||||
checkType('listReturnedFromClosure', commonMasks.dynamicType);
|
||||
checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
|
||||
checkType('listPassedAsOptionalParameter', commonMasks.numType);
|
||||
checkType('listPassedAsNamedParameter', commonMasks.numType);
|
||||
checkType('listStoredInList', commonMasks.uint31Type);
|
||||
checkType('listStoredInListButEscapes', commonMasks.dynamicType);
|
||||
checkType('listPassedToClosure', commonMasks.dynamicType);
|
||||
checkType('listReturnedFromClosure', commonMasks.dynamicType);
|
||||
checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
|
||||
checkType('listPassedAsOptionalParameter', commonMasks.numType);
|
||||
checkType('listPassedAsNamedParameter', commonMasks.numType);
|
||||
checkType('listStoredInList', commonMasks.uint31Type);
|
||||
checkType('listStoredInListButEscapes', commonMasks.dynamicType);
|
||||
|
||||
if (!allocation.contains('filled')) {
|
||||
checkType('listUnset', new TypeMask.nonNullEmpty());
|
||||
checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
|
||||
}
|
||||
}));
|
||||
if (!allocation.contains('filled')) {
|
||||
checkType('listUnset', new TypeMask.nonNullEmpty());
|
||||
checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) 2014, 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 use the equivalence framework.
|
||||
/// Currently it only works with the mock compiler.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import "package:async_helper/async_helper.dart";
|
||||
import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
|
||||
|
||||
import '../compiler_helper.dart';
|
||||
|
||||
String generateTest(String key, String value, bool initial) {
|
||||
return """
|
||||
double aDouble = 42.5;
|
||||
List aList = [42];
|
||||
|
||||
consume(x) => x;
|
||||
|
||||
main() {
|
||||
""" +
|
||||
(initial
|
||||
? """
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, $key: $value};
|
||||
"""
|
||||
: """
|
||||
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
|
||||
theMap[$key] = $value;
|
||||
""") +
|
||||
"""
|
||||
for (var key in theMap.keys) {
|
||||
aDouble = theMap[key];
|
||||
}
|
||||
// We have to reference it somewhere, so that it always gets resolved.
|
||||
consume(aList);
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Test using keys without the list floating in
|
||||
doTest();
|
||||
// Test using keys with the list floating in as key
|
||||
doTest(key: "aList", bail: true);
|
||||
// Test using keys with the list floating in as value
|
||||
doTest(value: "aList");
|
||||
// And the above where we add the list as part of the map literal.
|
||||
doTest(initial: true);
|
||||
doTest(key: "aList", bail: true, initial: true);
|
||||
doTest(value: "aList", initial: true);
|
||||
}
|
||||
|
||||
void doTest(
|
||||
{String key: "'d'",
|
||||
String value: "5.5",
|
||||
bool bail: false,
|
||||
bool initial: false}) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(generateTest(key, value, initial), uri,
|
||||
expectedErrors: 0, expectedWarnings: 0);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
var typesInferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var commonMasks = typesInferrer.closedWorld.commonMasks;
|
||||
MemberElement aDouble = findElement(compiler, 'aDouble');
|
||||
var aDoubleType = typesInferrer.getTypeOfMember(aDouble);
|
||||
MemberElement aList = findElement(compiler, 'aList');
|
||||
var aListType = typesInferrer.getTypeOfMember(aList);
|
||||
|
||||
Expect.equals(aDoubleType, commonMasks.doubleType);
|
||||
Expect.isTrue(aListType is ContainerTypeMask);
|
||||
ContainerTypeMask container = aListType;
|
||||
TypeMask elementType = container.elementType;
|
||||
if (bail) {
|
||||
Expect.equals(elementType, commonMasks.dynamicType);
|
||||
} else {
|
||||
Expect.equals(elementType, commonMasks.uint31Type);
|
||||
}
|
||||
}));
|
||||
}
|
|
@ -5,12 +5,17 @@
|
|||
/// TODO(johnniwinther): Port this test to use the equivalence framework.
|
||||
/// Currently it only works with the mock compiler.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import "package:async_helper/async_helper.dart";
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:compiler/src/commandline_options.dart';
|
||||
import 'package:compiler/src/compiler.dart';
|
||||
import 'package:compiler/src/elements/entities.dart';
|
||||
import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
|
||||
import 'package:compiler/src/types/types.dart' show MapTypeMask, TypeMask;
|
||||
import 'package:compiler/src/world.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'type_mask_test_helper.dart';
|
||||
import '../compiler_helper.dart';
|
||||
import '../memory_compiler.dart';
|
||||
|
||||
String generateTest(String mapAllocation) {
|
||||
return """
|
||||
|
@ -119,6 +124,8 @@ takeNamed({map}) {
|
|||
}
|
||||
|
||||
main() {
|
||||
anInt++;
|
||||
|
||||
mapReturnedFromMethod[aKey] = anInt;
|
||||
bar()[aKey] = aDouble;
|
||||
|
||||
|
@ -202,90 +209,103 @@ main() {
|
|||
}
|
||||
|
||||
void main() {
|
||||
// Test empty literal map
|
||||
doTest('{}');
|
||||
// Test preset map of <String,uint32>
|
||||
doTest('{presetKey : anInt}', "presetKey", "anInt");
|
||||
// Test preset map of <Double,uint32>
|
||||
doTest('{aDouble : anInt}', "aDouble", "anInt");
|
||||
runTests({bool useKernel}) async {
|
||||
// Test empty literal map
|
||||
await doTest('{}', useKernel: useKernel);
|
||||
// Test preset map of <String,uint32>
|
||||
await doTest('{presetKey : anInt}',
|
||||
keyElementName: "presetKey",
|
||||
valueElementName: "anInt",
|
||||
useKernel: useKernel);
|
||||
// Test preset map of <Double,uint32>
|
||||
await doTest('{aDouble : anInt}',
|
||||
keyElementName: "aDouble",
|
||||
valueElementName: "anInt",
|
||||
useKernel: useKernel);
|
||||
}
|
||||
|
||||
asyncTest(() async {
|
||||
print('--test from ast---------------------------------------------------');
|
||||
await runTests(useKernel: false);
|
||||
print('--test from kernel------------------------------------------------');
|
||||
await runTests(useKernel: true);
|
||||
});
|
||||
}
|
||||
|
||||
void doTest(String allocation,
|
||||
[String keyElementName, String valueElementName]) {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(generateTest(allocation), uri,
|
||||
expectedErrors: 0, expectedWarnings: 1);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
var keyType, valueType;
|
||||
var typesInferrer = compiler.globalInference.typesInferrerInternal;
|
||||
var closedWorld = typesInferrer.closedWorld;
|
||||
var commonMasks = closedWorld.commonMasks;
|
||||
var emptyType = new TypeMask.nonNullEmpty();
|
||||
MemberElement aKey = findElement(compiler, 'aKey');
|
||||
var aKeyType = typesInferrer.getTypeOfMember(aKey);
|
||||
if (keyElementName != null) {
|
||||
MemberElement keyElement = findElement(compiler, keyElementName);
|
||||
keyType = typesInferrer.getTypeOfMember(keyElement);
|
||||
}
|
||||
if (valueElementName != null) {
|
||||
MemberElement valueElement = findElement(compiler, valueElementName);
|
||||
valueType = typesInferrer.getTypeOfMember(valueElement);
|
||||
}
|
||||
if (keyType == null) keyType = emptyType;
|
||||
if (valueType == null) valueType = emptyType;
|
||||
doTest(String allocation,
|
||||
{String keyElementName, String valueElementName, bool useKernel}) async {
|
||||
String source = generateTest(allocation);
|
||||
var result = await runCompiler(
|
||||
memorySourceFiles: {'main.dart': source},
|
||||
options: useKernel ? [Flags.useKernel] : []);
|
||||
Expect.isTrue(result.isSuccess);
|
||||
Compiler compiler = result.compiler;
|
||||
TypeMask keyType, valueType;
|
||||
TypeGraphInferrer typesInferrer =
|
||||
compiler.globalInference.typesInferrerInternal;
|
||||
ClosedWorld closedWorld = typesInferrer.closedWorld;
|
||||
CommonMasks commonMasks = closedWorld.commonMasks;
|
||||
TypeMask emptyType = new TypeMask.nonNullEmpty();
|
||||
MemberEntity aKey = findMember(closedWorld, 'aKey');
|
||||
TypeMask aKeyType = typesInferrer.getTypeOfMember(aKey);
|
||||
if (keyElementName != null) {
|
||||
MemberEntity keyElement = findMember(closedWorld, keyElementName);
|
||||
keyType = typesInferrer.getTypeOfMember(keyElement);
|
||||
}
|
||||
if (valueElementName != null) {
|
||||
MemberEntity valueElement = findMember(closedWorld, valueElementName);
|
||||
valueType = typesInferrer.getTypeOfMember(valueElement);
|
||||
}
|
||||
if (keyType == null) keyType = emptyType;
|
||||
if (valueType == null) valueType = emptyType;
|
||||
|
||||
checkType(String name, keyType, valueType) {
|
||||
MemberElement element = findElement(compiler, name);
|
||||
MapTypeMask mask = typesInferrer.getTypeOfMember(element);
|
||||
Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
|
||||
Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
|
||||
}
|
||||
checkType(String name, keyType, valueType) {
|
||||
MemberEntity element = findMember(closedWorld, name);
|
||||
MapTypeMask mask = typesInferrer.getTypeOfMember(element);
|
||||
Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
|
||||
Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
|
||||
}
|
||||
|
||||
K(TypeMask other) =>
|
||||
simplify(keyType.union(other, closedWorld), closedWorld);
|
||||
V(TypeMask other) =>
|
||||
simplify(valueType.union(other, closedWorld), closedWorld)
|
||||
.nullable();
|
||||
K(TypeMask other) => simplify(keyType.union(other, closedWorld), closedWorld);
|
||||
V(TypeMask other) =>
|
||||
simplify(valueType.union(other, closedWorld), closedWorld).nullable();
|
||||
|
||||
checkType('mapInField', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapUsedWithConstraint', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType(
|
||||
'mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapInField', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapUsedWithConstraint', K(aKeyType), V(commonMasks.positiveIntType));
|
||||
checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.positiveIntType));
|
||||
// TODO(johnniwinther): Reenable this when we don't bail out due to
|
||||
// (benign) JS calls.
|
||||
//checkType('mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
|
||||
|
||||
checkType('mapPassedToClosure', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapPassedAsOptionalParameter', K(aKeyType),
|
||||
V(commonMasks.numType));
|
||||
checkType(
|
||||
'mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapPassedToClosure', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType(
|
||||
'mapPassedAsOptionalParameter', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
|
||||
checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
|
||||
V(commonMasks.dynamicType));
|
||||
|
||||
checkType('mapUnset', K(emptyType), V(emptyType));
|
||||
checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
|
||||
}));
|
||||
checkType('mapUnset', K(emptyType), V(emptyType));
|
||||
checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
|
||||
}
|
||||
|
|
|
@ -4,9 +4,35 @@
|
|||
|
||||
/// Helper program that shows the inferrer data on a dart program.
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:compiler/src/inferrer/inferrer_engine.dart';
|
||||
import '../equivalence/id_equivalence_helper.dart';
|
||||
import '../equivalence/show_helper.dart';
|
||||
import 'inference_test_helper.dart';
|
||||
import 'side_effects_test.dart';
|
||||
import 'callers_test.dart';
|
||||
|
||||
main(List<String> args) async {
|
||||
await show(args, computeMemberAstTypeMasks, computeMemberIrTypeMasks);
|
||||
ArgParser argParser = createArgParser();
|
||||
argParser.addFlag('inference', defaultsTo: true);
|
||||
argParser.addFlag('side-effects', defaultsTo: false);
|
||||
argParser.addFlag('callers', defaultsTo: false);
|
||||
ArgResults results = argParser.parse(args);
|
||||
|
||||
ComputeMemberDataFunction astFunction;
|
||||
ComputeMemberDataFunction kernelFunction;
|
||||
if (results['side-effects']) {
|
||||
astFunction = computeMemberAstSideEffects;
|
||||
kernelFunction = computeMemberIrSideEffects;
|
||||
}
|
||||
if (results['callers']) {
|
||||
InferrerEngineImpl.retainDataForTesting = true;
|
||||
astFunction = computeMemberAstCallers;
|
||||
kernelFunction = computeMemberIrCallers;
|
||||
} else {
|
||||
InferrerEngineImpl.useSorterForTesting = true;
|
||||
astFunction = computeMemberAstTypeMasks;
|
||||
kernelFunction = computeMemberIrTypeMasks;
|
||||
}
|
||||
await show(results, astFunction, kernelFunction);
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
// 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 use the equivalence framework.
|
||||
|
||||
// Test that computation of callers of an element works when two
|
||||
// elements of the same name are being invoked in the same method.
|
||||
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:compiler/src/common_elements.dart';
|
||||
import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
|
||||
import 'package:compiler/src/world.dart' show ClosedWorld, ClosedWorldRefiner;
|
||||
|
||||
import '../compiler_helper.dart';
|
||||
|
||||
const String TEST = """
|
||||
class A {
|
||||
var field;
|
||||
}
|
||||
|
||||
class B {
|
||||
var field;
|
||||
}
|
||||
|
||||
main() {
|
||||
new A().field;
|
||||
new B().field;
|
||||
}
|
||||
""";
|
||||
|
||||
// Create our own type inferrer to avoid clearing out the internal
|
||||
// data structures.
|
||||
class MyInferrer extends AstTypeGraphInferrer {
|
||||
MyInferrer(compiler, closedWorld, closedWorldRefiner)
|
||||
: super(compiler, closedWorld, closedWorldRefiner);
|
||||
clear() {}
|
||||
}
|
||||
|
||||
void main() {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = mockCompilerFor(TEST, uri, analyzeOnly: true);
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
ElementEnvironment elementEnvironment =
|
||||
compiler.frontendStrategy.elementEnvironment;
|
||||
ClosedWorldRefiner closedWorldRefiner =
|
||||
compiler.closeResolution(elementEnvironment.mainFunction);
|
||||
ClosedWorld closedWorld =
|
||||
compiler.resolutionWorldBuilder.closedWorldForTesting;
|
||||
var inferrer =
|
||||
new MyInferrer(compiler, closedWorld, closedWorldRefiner);
|
||||
compiler.globalInference.typesInferrerInternal = inferrer;
|
||||
compiler.globalInference.runGlobalTypeInference(
|
||||
closedWorld.elementEnvironment.mainFunction,
|
||||
closedWorld,
|
||||
closedWorldRefiner);
|
||||
var mainElement = findElement(compiler, 'main');
|
||||
dynamic classA = findElement(compiler, 'A');
|
||||
var fieldA = classA.lookupLocalMember('field');
|
||||
dynamic classB = findElement(compiler, 'B');
|
||||
var fieldB = classB.lookupLocalMember('field');
|
||||
|
||||
Expect.isTrue(inferrer.getCallersOf(fieldA).contains(mainElement));
|
||||
Expect.isTrue(inferrer.getCallersOf(fieldB).contains(mainElement));
|
||||
}));
|
||||
}
|
|
@ -10,5 +10,6 @@ import 'inlining_test.dart';
|
|||
|
||||
main(List<String> args) async {
|
||||
JavaScriptBackend.cacheCodegenImpactForTesting = true;
|
||||
await show(args, computeMemberAstInlinings, computeMemberIrInlinings);
|
||||
await show(createArgParser().parse(args), computeMemberAstInlinings,
|
||||
computeMemberIrInlinings);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue