| 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 |