Add reporting of unimplemented conversions in generated code

R=sigmund@google.com

Review URL: https://chromereviews.googleplex.com/122037013
This commit is contained in:
Vijay Menon
2014-11-21 13:52:10 -08:00
parent 2116aa559b
commit 9da00a7add
3 changed files with 94 additions and 21 deletions
+90 -20
View File
@@ -66,7 +66,7 @@ class UnitGenerator extends GeneralizingAstVisitor {
UnitGenerator(
this.uri, this.unit, this.directory, this.libName, this.infoMap);
DynamicInvoke checkDynamicInvoke(AstNode node) {
DynamicInvoke _processDynamicInvoke(AstNode node) {
DynamicInvoke result = null;
if (infoMap.containsKey(node)) {
var infos = infoMap[node];
@@ -76,10 +76,22 @@ class UnitGenerator extends GeneralizingAstVisitor {
result = info;
}
}
if (result != null) infos.remove(result);
}
return result;
}
void _reportUnimplementedConversions(AstNode node) {
if (infoMap.containsKey(node) && infoMap[node].isNotEmpty) {
out.write('/* Unimplemented: [ ');
for (var info in infoMap[node]) {
assert(info is Conversion);
out.write('${info.description}');
}
out.write('] */ ');
}
}
String path() {
var tail = uri.pathSegments.last;
return directory.path + Platform.pathSeparator + tail + '.js';
@@ -101,6 +113,13 @@ var $libName;
bool isPublic(String name) => !name.startsWith('_');
visitFunctionTypeAlias(FunctionTypeAlias node) {
// TODO(vsm): Do we need to record type info the generated code for a
// typedef?
_reportUnimplementedConversions(node);
return node;
}
void generateInitializer(ClassDeclaration node) {
// TODO(vsm): Generate one per constructor?
// TODO(vsm): Ensure _initializer isn't used.
@@ -139,6 +158,8 @@ function $name() {
}
AstNode visitClassDeclaration(ClassDeclaration node) {
_reportUnimplementedConversions(node);
var name = node.name.name;
out.write("""
// Class $name
@@ -161,9 +182,10 @@ var $name = (function () {
}
AstNode visitFunctionDeclaration(FunctionDeclaration node) {
_reportUnimplementedConversions(node);
var name = node.name.name;
assert(node.parent is CompilationUnit);
var args = "";
out.write("// Function $name: ${node.element.type}\n");
out.write("function $name(");
node.functionExpression.parameters.accept(this);
@@ -175,12 +197,30 @@ var $name = (function () {
return node;
}
AstNode visitFunctionExpression(FunctionExpression node) {
_reportUnimplementedConversions(node);
// Bind all free variables.
out.write('/* Unimplemented: bind any free variables. */');
out.write("function (");
node.parameters.accept(this);
out.write(") {\n", 2);
node.body.accept(this);
out.write("}\n", -2);
return node;
}
AstNode visitSimpleIdentifier(SimpleIdentifier node) {
_reportUnimplementedConversions(node);
out.write(node.name);
return node;
}
AstNode visitExpressionFunctionBody(ExpressionFunctionBody node) {
_reportUnimplementedConversions(node);
out.write("return ");
// TODO(vsm): Check for conversion.
node.expression.accept(this);
@@ -190,14 +230,18 @@ var $name = (function () {
AstNode visitMethodInvocation(MethodInvocation node) {
// TODO(vsm): Check dynamic.
var name = qualifiedName(node.methodName);
out.write('$name(');
_reportUnimplementedConversions(node);
writeQualifiedName(node.target, node.methodName);
out.write('(');
node.argumentList.accept(this);
out.write(')');
return node;
}
AstNode visitArgumentList(ArgumentList node) {
_reportUnimplementedConversions(node);
// TODO(vsm): Optional parameters.
var arguments = node.arguments;
var length = arguments.length;
@@ -214,6 +258,8 @@ var $name = (function () {
}
AstNode visitFormalParameterList(FormalParameterList node) {
_reportUnimplementedConversions(node);
// TODO(vsm): Optional parameters.
var arguments = node.parameters;
var length = arguments.length;
@@ -228,18 +274,24 @@ var $name = (function () {
}
AstNode visitBlockFunctionBody(BlockFunctionBody node) {
_reportUnimplementedConversions(node);
var statements = node.block.statements;
for (var statement in statements) statement.accept(this);
return node;
}
AstNode visitExpressionStatement(ExpressionStatement node) {
_reportUnimplementedConversions(node);
node.expression.accept(this);
out.write(';\n');
return node;
}
AstNode visitVariableDeclarationStatement(VariableDeclarationStatement node) {
_reportUnimplementedConversions(node);
var declarations = node.variables.variables;
for (var declaration in declarations) {
var name = declaration.name.name;
@@ -257,6 +309,8 @@ var $name = (function () {
}
AstNode visitConstructorName(ConstructorName node) {
_reportUnimplementedConversions(node);
node.type.name.accept(this);
if (node.name != null) {
out.write('.');
@@ -266,6 +320,8 @@ var $name = (function () {
}
AstNode visitInstanceCreationExpression(InstanceCreationExpression node) {
_reportUnimplementedConversions(node);
out.write('new ');
node.constructorName.accept(this);
out.write('(');
@@ -275,13 +331,17 @@ var $name = (function () {
}
AstNode visitSimpleFormalParameter(SimpleFormalParameter node) {
_reportUnimplementedConversions(node);
node.identifier.accept(this);
return node;
}
AstNode visitPrefixedIdentifier(PrefixedIdentifier node) {
var info = checkDynamicInvoke(node);
if (info != null) {
var dynamicInvoke = _processDynamicInvoke(node);
_reportUnimplementedConversions(node);
if (dynamicInvoke != null) {
out.write('dart_runtime.dload(');
node.prefix.accept(this);
out.write(', "');
@@ -296,41 +356,51 @@ var $name = (function () {
}
AstNode visitIntegerLiteral(IntegerLiteral node) {
_reportUnimplementedConversions(node);
out.write('${node.value}');
return node;
}
AstNode visitStringLiteral(StringLiteral node) {
_reportUnimplementedConversions(node);
out.write('"${node.stringValue}"');
return node;
}
AstNode visitLibraryDirective(LibraryDirective node) {
AstNode visitDirective(Directive node) {
_reportUnimplementedConversions(node);
return node;
}
AstNode visitNode(AstNode node) {
out.write('/* Unimplemented: $node */');
return node;
_reportUnimplementedConversions(node);
out.write('/* Unimplemented ${node.runtimeType}: $node */');
}
static const Map<String, String> _builtins = const <String, String>{
'dart.core': 'dart_core',
};
String qualifiedName(SimpleIdentifier id) {
void writeQualifiedName(Expression target, SimpleIdentifier id) {
var prefix = "";
var name = id.name;
var element = id.staticElement;
if (element.enclosingElement is CompilationUnitElement) {
var library = element.enclosingElement.enclosingElement;
assert(library is LibraryElement);
var package = library.name;
var libname = _builtins
.containsKey(package) ? _builtins[package] : package;
prefix = '$libname.';
if (target != null) {
target.accept(this);
out.write('.');
} else {
var element = id.staticElement;
if (element.enclosingElement is CompilationUnitElement) {
var library = element.enclosingElement.enclosingElement;
assert(library is LibraryElement);
var package = library.name;
var libname = _builtins.containsKey(package) ?
_builtins[package] : package;
out.write('$libname.');
}
}
return "$prefix$name";
id.accept(this);
}
}
@@ -58,6 +58,9 @@ abstract class Conversion extends TypeMismatch {
bool get safe => false;
Level get level => safe ? Level.CONFIG : Level.INFO;
String get description =>
'${this.runtimeType}: $baseType to $convertedType';
}
class Box extends Conversion {
+1 -1
View File
@@ -13,7 +13,7 @@ void bar(a) {
}
void main() {
A a = new A();
var a = new A();
foo(a);
bar(a);
}