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

Unified Diff: tests/compiler/dart2js/cpa_inference_test.dart

Issue 10907028: Standalone concrete type inference (not integrated in the compiler). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix tests Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/compiler/implementation/types/types.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/compiler/dart2js/cpa_inference_test.dart
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..d1b1e73be833cee9c549ad12e3fd32f5c0415e9b
--- /dev/null
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -0,0 +1,317 @@
+#import("dart:uri");
+#import("../../../lib/compiler/implementation/elements/elements.dart");
+#import('../../../lib/compiler/implementation/scanner/scannerlib.dart');
+#import('../../../lib/compiler/implementation/source_file.dart');
+#import('../../../lib/compiler/implementation/types/types.dart');
+#import('../../../lib/compiler/implementation/tree/tree.dart');
+#import("../../../lib/compiler/implementation/leg.dart", prefix: "leg");
+
+#import("parser_helper.dart");
+#import("compiler_helper.dart");
+#import("mock_compiler.dart");
+
+/**
+ * Finds the node corresponding to the last occurence of the substring
+ * [: identifier; :] in the program represented by the visited AST.
+ */
+class VariableFinderVisitor extends Visitor {
+ final String identifier;
+ Node result;
+
+ VariableFinderVisitor(this.identifier);
+
+ visitSend(Send node) {
+ if (node.isPropertyAccess
+ && node.selector.asIdentifier().source.slowToString() == identifier) {
+ result = node;
+ } else {
+ node.visitChildren(this);
+ }
+ }
+
+ visitNode(Node node) {
+ node.visitChildren(this);
+ }
+}
+
+class AnalysisResult {
+ MockCompiler compiler;
+ ConcreteTypesInferrer inferrer;
+ Node ast;
+
+ BaseType int;
+ BaseType double;
+ BaseType bool;
+ BaseType string;
+
+ AnalysisResult(MockCompiler compiler, ConcreteTypesInferrer inferrer)
+ : this.compiler = compiler,
+ this.inferrer = inferrer,
+ int = inferrer.baseTypes.intBaseType,
+ double = inferrer.baseTypes.doubleBaseType,
+ bool = inferrer.baseTypes.boolBaseType,
+ string = inferrer.baseTypes.stringBaseType {
+ Element mainElement = compiler.mainApp.find(buildSourceString('main'));
+ ast = mainElement.parseNode(compiler);
+ }
+
+ BaseType base(String className) {
+ final source = buildSourceString(className);
+ return new ClassBaseType(compiler.mainApp.find(source));
+ }
+
+ /**
+ * Finds the [Node] corresponding to the last occurence of the substring
+ * [: identifier; :] in the program represented by the visited AST. For
+ * instance, returns the AST node representing [: foo; :] in
+ * [: main() { foo = 1; foo; } :].
+ */
+ Node findNode(String identifier) {
+ VariableFinderVisitor finder = new VariableFinderVisitor(identifier);
+ ast.accept(finder);
+ return finder.result;
+ }
+
+ /**
+ * Finds the [Element] corresponding to [: className#fieldName :].
+ */
+ Element findField(String className, String fieldName) {
+ ClassElement element = compiler.mainApp.find(buildSourceString(className));
+ return element.lookupLocalMember(buildSourceString(fieldName));
+ }
+
+ static ConcreteType concreteFrom(List<BaseType> baseTypes) {
+ ConcreteType result = new ConcreteType.empty();
+ for (final baseType in baseTypes) {
+ result = result.union(new ConcreteType.singleton(baseType));
+ }
+ return result;
+ }
+
+ /**
+ * Checks that the inferred type of the node corresponding to the last
+ * occurence of [: variable; :] in the program is the concrete type
+ * made of [baseTypes].
+ */
+ void checkNodeHasType(String variable, List<BaseType> baseTypes) {
+ return Expect.equals(
+ concreteFrom(baseTypes),
+ inferrer.inferredTypes[findNode(variable)]);
+ }
+
+ /**
+ * Checks that [: className#fieldName :]'s inferred type is the concrete type
+ * made of [baseTypes].
+ */
+ void checkFieldHasType(String className, String fieldName,
+ List<BaseType> baseTypes) {
+ return Expect.equals(
+ concreteFrom(baseTypes),
+ inferrer.inferredFieldTypes[findField(className, fieldName)]);
+ }
+}
+
+AnalysisResult analyze(String code) {
+ Uri uri = new Uri.fromComponents(scheme: 'source');
+ MockCompiler compiler = new MockCompiler();
+ compiler.sourceFiles[uri.toString()] = new SourceFile(uri.toString(), code);
+ compiler.runCompiler(uri);
+ ConcreteTypesInferrer inferrer = new ConcreteTypesInferrer(compiler);
+ inferrer.analyzeMain(compiler.mainApp.find(const SourceString("main")));
+ return new AnalysisResult(compiler, inferrer);
+}
+
+testLiterals() {
+ final String source = r"""
+ main() {
+ var v1 = 42;
+ var v2 = 42.0;
+ var v3 = 'abc';
+ var v4 = true;
+ var v5 = null;
+ v1; v2; v3; v4; v5;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('v1', [result.int]);
+ result.checkNodeHasType('v2', [result.double]);
+ result.checkNodeHasType('v3', [result.string]);
+ result.checkNodeHasType('v4', [result.bool]);
+ result.checkNodeHasType('v5', [new NullBaseType()]);
+}
+
+testRedefinition() {
+ final String source = r"""
+ main() {
+ var foo = 42;
+ foo = 'abc';
+ foo;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.string]);
+}
+
+testIfThenElse() {
+ final String source = r"""
+ main() {
+ var foo = 42;
+ if (true) {
+ foo = 'abc';
+ } else {
+ foo = false;
+ }
+ foo;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.string, result.bool]);
+}
+
+testTernaryIf() {
+ final String source = r"""
+ main() {
+ var foo = 42;
+ foo = true ? 'abc' : false;
+ foo;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.string, result.bool]);
+}
+
+testWhile() {
+ final String source = r"""
+ class A { f() => new B(); }
+ class B { f() => new C(); }
+ class C { f() => new A(); }
+ main() {
+ var foo = new A();
+ while(true) {
+ foo = foo.f();
+ }
+ foo;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType(
+ 'foo',
+ [result.base('A'), result.base('B'), result.base('C')]);
+}
+
+testNonRecusiveFunction() {
+ final String source = r"""
+ f(x, y) => true ? x : y;
+ main() { var foo = f(42, "abc"); foo; }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.int, result.string]);
+}
+
+testRecusiveFunction() {
+ final String source = r"""
+ f(x) {
+ if (true) return x;
+ else return f(true ? x : "abc");
+ }
+ main() { var foo = f(42); foo; }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.int, result.string]);
+}
+
+testMutuallyRecusiveFunction() {
+ final String source = r"""
+ f() => true ? 42 : g();
+ g() => true ? "abc" : f();
+ main() { var foo = f(); foo; }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.int, result.string]);
+}
+
+testConstructor() {
+ final String source = r"""
+ class A {
+ var x, y, z;
+ A(this.x, a) : y = a { z = 'abc'; }
+ }
+ main() {
+ new A(42, 'abc');
+ new A(true, null);
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkFieldHasType('A', 'x', [result.int, result.bool]);
+ result.checkFieldHasType('A', 'y', [result.string, new NullBaseType()]);
+ result.checkFieldHasType('A', 'z', [result.string]);
+}
+
+testGetters() {
+ final String source = r"""
+ class A {
+ var x;
+ A(this.x);
+ get y() => x;
+ }
+ main() {
+ var a = new A(42);
+ var foo = a.x;
+ var bar = a.y;
+ foo; bar;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkNodeHasType('foo', [result.int]);
+ result.checkNodeHasType('bar', [result.int]);
+}
+
+testSetters() {
+ final String source = r"""
+ class A {
+ var x;
+ A(this.x);
+ set y(a) { x = a; }
+ }
+ main() {
+ var a = new A(42);
+ a.x = 'abc';
+ a.y = true;
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkFieldHasType('A', 'x', [result.int, result.string, result.bool]);
+}
+
+testNamedParameters() {
+ final String source = r"""
+ class A {
+ var x, y, z, w;
+ A(this.x, [this.y, this.z, this.w]);
+ }
+ main() {
+ new A(42);
+ new A('abc', w: true, z: 42.0);
+ }
+ """;
+ AnalysisResult result = analyze(source);
+ result.checkFieldHasType('A', 'x', [result.int, result.string]);
+ result.checkFieldHasType('A', 'y', [new NullBaseType()]);
+ result.checkFieldHasType('A', 'z', [new NullBaseType(), result.double]);
+ result.checkFieldHasType('A', 'w', [new NullBaseType(), result.bool]);
+}
+
+void main() {
+ testLiterals();
+ testRedefinition();
+ testIfThenElse();
+ testTernaryIf();
+ testWhile();
+ testNonRecusiveFunction();
+ testRecusiveFunction();
+ testMutuallyRecusiveFunction();
+ testConstructor();
+ testGetters();
+ testSetters();
+ testNamedParameters();
+}
« no previous file with comments | « lib/compiler/implementation/types/types.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698