blob: 15a4e579d6d4a0bb65eefc5da0cb15bb76bdcb90 [file] [log] [blame]
// 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.
import 'package:expect/expect.dart';
import "package:async_helper/async_helper.dart";
import 'memory_compiler.dart';
import 'compiler_helper.dart' show findElement;
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 {
await compileAndTest("AddAll.dart", (types, getType, compiler) {
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());
});
await compileAndTest("Union.dart", (types, getType, compiler) {
Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
Expect
.isTrue(getType('aString').containsOnlyString(compiler.closedWorld));
Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
});
await compileAndTest("ValueType.dart", (types, getType, compiler) {
Expect.equals(getType('knownDouble'), types.doubleType);
Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
Expect.equals(getType('justNull'), types.nullType);
});
await compileAndTest("Propagation.dart", (code) {
Expect.isFalse(code.contains("J.\$add\$ns"));
}, createCode: true);
await compileAndTest("Bailout.dart", (types, getType, compiler) {
Expect.equals(getType('notInt'), types.dynamicType);
Expect.equals(getType('alsoNotInt'), types.dynamicType);
Expect.isFalse(getType('dict').isDictionary);
});
});
}
compileAndTest(source, checker, {createCode: false}) async {
CompilationResult result = await runCompiler(
entryPoint: Uri.parse('memory:' + source),
memorySourceFiles: SOURCES,
beforeRun: (compiler) {
compiler.stopAfterTypeInference = !createCode;
});
var compiler = result.compiler;
var commonMasks = compiler.closedWorld.commonMasks;
var typesInferrer = compiler.globalInference.typesInferrerInternal;
getType(String name) {
var element = findElement(compiler, name);
return typesInferrer.getTypeOfElement(element);
}
if (!createCode) {
checker(commonMasks, getType, compiler);
} else {
var element = compiler.mainFunction;
var code = compiler.backend.getGeneratedCode(element);
checker(code);
}
}