Chromium Code Reviews| Index: tests/compiler/dart2js/field_type_inferer_test.dart |
| diff --git a/tests/compiler/dart2js/field_type_inferer_test.dart b/tests/compiler/dart2js/field_type_inferer_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..20dd8c26b13407ff7a99fc3a57086e490e4a1b30 |
| --- /dev/null |
| +++ b/tests/compiler/dart2js/field_type_inferer_test.dart |
| @@ -0,0 +1,358 @@ |
| +// 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. |
| + |
| +#import("dart:uri"); |
| + |
| +#import("../../../lib/compiler/implementation/js_backend/js_backend.dart"); |
| +#import("../../../lib/compiler/implementation/ssa/ssa.dart"); |
| +#import("../../../lib/compiler/implementation/scanner/scannerlib.dart"); |
| + |
| +#import('compiler_helper.dart'); |
| +#import('parser_helper.dart'); |
| + |
| +void compileAndFind(String code, |
| + String className, |
| + String memberName, |
| + bool disableInlining, |
| + check(compiler, element)) { |
| + Uri uri = new Uri.fromComponents(scheme: 'source'); |
| + var compiler = compilerFor(code, uri); |
| + compiler.runCompiler(uri); |
| + compiler.disableInlining = disableInlining; |
| + var cls = findElement(compiler, className); |
| + var member = cls.lookupMember(buildSourceString(memberName)); |
| + return check(compiler.backend, member); |
| +} |
| + |
| +const String TEST_1 = @""" |
| + class A { |
| + int f; |
| + } |
| + main() { new A(); } |
| +"""; |
| + |
| +const String TEST_2 = @""" |
| + class A { |
| + int f1; |
| + int f2 = 1; |
| + } |
| + main() { new A(); } |
| +"""; |
| + |
| +const String TEST_3 = @""" |
| + class A { |
| + int f1; |
| + int f2; |
| + A() : f1 = 1; |
| + } |
| + main() { new A().f2 = 2; } |
| +"""; |
| + |
| +const String TEST_4 = @""" |
| + class A { |
| + int f1; |
| + int f2; |
| + A() : f1 = 1; |
| + } |
| + main() { |
| + A a = new A(); |
| + a.f1 = "a"; |
| + a.f2 = "a"; |
| + } |
| +"""; |
| + |
| +const String TEST_5 = @""" |
| + 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 = @""" |
| + 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 = @""" |
| + 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 = @""" |
| + class A { |
| + int f; |
| + A(x) { |
| + if (x) { |
| + f = "1"; |
| + } else { |
| + } |
| + } |
| + } |
| + main() { |
| + new A(true); |
| + new A(false); |
| + } |
| +"""; |
| + |
| +const String TEST_9 = @""" |
| + class A { |
| + int f; |
| + A(x) { |
| + if (x) { |
| + } else { |
| + f = "1"; |
| + } |
| + } |
| + } |
| + main() { |
| + new A(true); |
| + new A(false); |
| + } |
| +"""; |
| + |
| +const String TEST_10 = @""" |
| + 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 = @""" |
| + 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 = @""" |
| + class S { |
| + int fs = 1; |
| + S() { fs = "2"; } |
| + } |
| + |
| + class A extends S { |
| + } |
| + |
| + main() { |
| + A a = new A(); |
| + } |
| +"""; |
| + |
| +const String TEST_13 = @""" |
| + class S { |
| + int fs; |
| + S() { fs = 1; } |
| + } |
| + |
| + class A extends S { |
| + A() { fs = 1; } |
| + } |
| + |
| + main() { |
| + A a = new A(); |
| + } |
| +"""; |
| + |
| +const String TEST_14 = @""" |
| + class A { |
| + var f; |
| + A() { f = 1; } |
| + A.other() { f = 2; } |
| + } |
| + |
| + main() { |
| + A a = new A(); |
| + a = new A.other(); |
| + } |
| +"""; |
| + |
| +const String TEST_15 = @""" |
| + 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 = @""" |
| + class A { |
| + var f; |
| + A() { f = "1"; } |
| + A.other() : f = 1 { } |
| + } |
| + |
| + main() { |
| + A a = new A(); |
| + a = new A.other(); |
| + } |
| +"""; |
| + |
| +const String TEST_17 = @""" |
| + g([p]) => p.f = 1; |
| + class A { |
| + var f; |
| + A(x) { |
| + var a; |
| + if (x) { |
| + a = this; |
| + } else { |
| + a = g; |
| + } |
| + a(); |
| + } |
| + } |
| + main() { |
| + new A(true); |
| + new A(false); |
| + } |
| +"""; |
| + |
| +const String TEST_18 = @""" |
| + class A { |
| + var f1; |
| + var f2; |
| + var f3; |
| + A(x) { |
|
ngeoffray
2012/09/27 12:35:46
Add a comment that 'this' is exposed in the constr
Søren Gjesse
2012/09/27 13:22:49
After changing the handling of Phis here this is n
|
| + f1 = 1; |
| + var a; |
| + if (x) { |
| + f2 = "1"; |
| + a = this; |
| + } else { |
| + a = 1; |
| + f2 = "1"; |
| + } |
| + f3 = a; |
| + } |
| + } |
| + main() { |
| + new A(true); |
| + new A(false); |
| + } |
| +"""; |
| + |
| +void doTest(String test, bool disableInlining, Map<String, HType> fields) { |
| + fields.forEach((String name, HType type) { |
| + compileAndFind( |
| + test, |
| + 'A', |
| + name, |
| + disableInlining, |
| + (backend, field) { |
| + print(field); |
| + HType inferredType = backend.optimisticFieldType(field); |
| + Expect.equals(type, inferredType); |
| + }); |
| + }); |
| +} |
| + |
| +void runTest(String test, Map<String, HType> fields) { |
| + doTest(test, false, fields); |
| + doTest(test, true, fields); |
| +} |
| + |
| +void test() { |
| + runTest(TEST_1, {'f': HType.NULL}); |
| + runTest(TEST_2, {'f1': HType.NULL, 'f2': HType.INTEGER}); |
| + runTest(TEST_3, {'f1': HType.INTEGER, 'f2': HType.INTEGER_OR_NULL}); |
| + runTest(TEST_4, {'f1': HType.UNKNOWN, 'f2': HType.STRING_OR_NULL}); |
| + runTest(TEST_5, {'f1': HType.STRING, 'f2': HType.STRING}); |
| + runTest(TEST_6, {'f1': HType.STRING, 'f2': HType.EXTENDABLE_ARRAY}); |
| + runTest(TEST_7, {'f1': HType.INDEXABLE_PRIMITIVE, |
| + 'f2': HType.EXTENDABLE_ARRAY}); |
| + runTest(TEST_8, {'f': HType.UNKNOWN}); |
| + runTest(TEST_9, {'f': HType.UNKNOWN}); |
| + runTest(TEST_10, {'f': HType.UNKNOWN}); |
| + runTest(TEST_11, {'fs': HType.INTEGER}); |
| + runTest(TEST_12, {'fs': HType.STRING}); |
| + // TODO(sgjesse): We should actually infer int. |
|
ngeoffray
2012/09/27 12:35:46
infer int for TEST_13 and TEST_14
Søren Gjesse
2012/09/27 13:22:49
Done.
|
| + runTest(TEST_13, {'fs': HType.UNKNOWN}); |
| + runTest(TEST_14, {'f': HType.UNKNOWN}); |
| + runTest(TEST_15, {'f': HType.UNKNOWN}); |
| + runTest(TEST_16, {'f': HType.UNKNOWN}); |
| + runTest(TEST_17, {'f': HType.UNKNOWN}); |
| + runTest(TEST_18, {'f1': HType.UNKNOWN, |
| + 'f2': HType.UNKNOWN, |
| + 'f3': HType.UNKNOWN}); |
| +} |
| + |
| +void main() { |
| + test(); |
| +} |