OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library dart_backend.sexpr_test; | |
6 | |
7 import 'dart:async'; | |
8 | |
9 import 'package:async_helper/async_helper.dart'; | |
10 import 'package:compiler/src/compiler.dart'; | |
11 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart'; | |
12 import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart'; | |
13 import 'package:expect/expect.dart'; | |
14 | |
15 import '../compiler_helper.dart' hide compilerFor; | |
16 import 'sexpr_unstringifier.dart'; | |
17 import 'test_helper.dart'; | |
18 | |
19 const String CODE = """ | |
20 class Foo { | |
21 static int x = 1; | |
22 foo() => 42; | |
23 } | |
24 | |
25 class Bar extends Foo { | |
26 int y = 2; | |
27 Bar() { | |
28 Foo.x = 2; | |
29 } | |
30 foo() => this.y + super.foo(); | |
31 } | |
32 | |
33 class FooBar<T> { | |
34 bool foobar() => T is int; | |
35 } | |
36 | |
37 main() { | |
38 Foo foo; | |
39 if (foo is Foo) { | |
40 print("Surprise"); | |
41 } | |
42 | |
43 String inner() => "Inner function"; | |
44 print(inner()); | |
45 | |
46 int j = 42; | |
47 for (int i = 0; i < 2; i++) { | |
48 print(i.toString()); | |
49 } | |
50 | |
51 print(Foo.x); | |
52 | |
53 String recursive(int h) { | |
54 if (h < 1) { | |
55 return j.toString(); | |
56 } | |
57 j++; | |
58 return "h\$\{recursive(h - 1)\}"; | |
59 } | |
60 print(recursive(5)); | |
61 | |
62 Bar bar = new Bar(); | |
63 print(bar.foo().toString()); | |
64 | |
65 bar = foo as Bar; | |
66 if (bar == null) { | |
67 var list = [1, 2, 3, 4]; | |
68 var map = { 1: "one" | |
69 , 2: "two" | |
70 , 3: "three" | |
71 }; | |
72 var double = 3.14; | |
73 list.forEach((i) => print(i.toString())); | |
74 print("\$list \$map \$double"); | |
75 } | |
76 | |
77 print(new FooBar<int>().foobar()); | |
78 } | |
79 | |
80 """; | |
81 | |
82 bool shouldOutput(Element element) { | |
83 return (!element.library.isPlatformLibrary && | |
84 !element.isSynthesized && | |
85 element.kind == ElementKind.FUNCTION); | |
86 } | |
87 | |
88 /// Compiles the given dart code (which must include a 'main' function) and | |
89 /// returns a list of all generated CPS IR definitions. | |
90 Future<List<FunctionDefinition>> compile(String code) { | |
91 return compilerFor(code).then((Compiler compiler) { | |
92 return compiler.enqueuer.resolution.resolvedElements | |
93 .where(shouldOutput) | |
94 .map(compiler.irBuilder.getIr) | |
95 .toList(); | |
96 }); | |
97 } | |
98 | |
99 /// Returns an S-expression string for each compiled function. | |
100 List<String> stringifyAll(Iterable<FunctionDefinition> functions) { | |
101 final stringifier = new SExpressionStringifier(); | |
102 return functions.map((f) => stringifier.visitFunctionDefinition(f)).toList(); | |
103 } | |
104 | |
105 Future<List<String>> testStringifier(String code, | |
106 Iterable<String> expectedTokens) { | |
107 return compile(code) | |
108 .then((List<FunctionDefinition> functions) { | |
109 List<String> sexprs = stringifyAll(functions); | |
110 String combined = sexprs.join(); | |
111 String withoutNullConstants = combined.replaceAll("Constant null", ""); | |
112 Expect.isFalse(withoutNullConstants.contains("null")); | |
113 for (String token in expectedTokens) { | |
114 Expect.isTrue(combined.contains(token), | |
115 "'$combined' doesn't contain '$token' in test:\n$code"); | |
116 } | |
117 | |
118 return sexprs; | |
119 }); | |
120 } | |
121 | |
122 /// Checks if the generated S-expressions can be processed by the unstringifier, | |
123 /// returns the resulting definitions. | |
124 List<FunctionDefinition> testUnstringifier(List<String> sexprs) { | |
125 return sexprs.map((String sexpr) { | |
126 try { | |
127 final function = new SExpressionUnstringifier().unstringify(sexpr); | |
128 Expect.isNotNull(function, "Unstringification failed:\n\n$sexpr"); | |
129 return function; | |
130 } catch (e, s) { | |
131 print('$e\n$s'); | |
132 Expect.fail('Error unstringifying "$sexpr": $e'); | |
133 } | |
134 }).toList(); | |
135 } | |
136 | |
137 void main() { | |
138 final tokens = | |
139 [ "FunctionDefinition" | |
140 , "IsTrue" | |
141 | |
142 // Expressions | |
143 , "Branch" | |
144 , "ConcatenateStrings" | |
145 , "DeclareFunction" | |
146 , "InvokeConstructor" | |
147 , "InvokeContinuation" | |
148 , "InvokeMethod" | |
149 , "InvokeStatic" | |
150 , "InvokeMethodDirectly" | |
151 , "LetCont" | |
152 , "LetPrim" | |
153 , "SetMutableVariable" | |
154 , "TypeOperator" | |
155 | |
156 // Primitives | |
157 , "Constant" | |
158 , "CreateFunction" | |
159 , "GetMutableVariable" | |
160 , "LiteralList" | |
161 , "LiteralMap" | |
162 // Parameters are encoded by name only and hence are not in this list. | |
163 , "ReifyTypeVar" | |
164 | |
165 , "(this)" // 'this' Parameter declarations | |
166 , "this" // 'this' Parameter uses | |
167 | |
168 ]; | |
169 | |
170 asyncTest(() => testStringifier(CODE, tokens).then((List<String> sexprs) { | |
171 final functions = testUnstringifier(sexprs); | |
172 | |
173 // Ensure that | |
174 // stringified(CODE) == stringified(unstringified(stringified(CODE))) | |
175 Expect.listEquals(sexprs, stringifyAll(functions)); | |
176 })); | |
177 } | |
OLD | NEW |