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

Unified Diff: sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart

Issue 11602016: Emit classes using ASTs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 12 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
Index: sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
index 84e57f1402a2c844a2f8a37cdea20866df370c59..f51edba43a1a1d099484f37b7f686a6edce5b67c 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -125,45 +125,25 @@ function(cls, desc) {
}
void generateNativeClass(ClassElement classElement) {
- nativeClasses.add(classElement);
-
assert(classElement.backendMembers.isEmpty);
- String quotedName = classElement.nativeTagInfo.slowToString();
-
- CodeBuffer fieldBuffer = new CodeBuffer();
- CodeBuffer getterSetterBuffer = new CodeBuffer();
- CodeBuffer methodBuffer = new CodeBuffer();
+ nativeClasses.add(classElement);
- emitter.emitClassFields(classElement, fieldBuffer, false,
- classIsNative: true);
- emitter.emitClassGettersSetters(classElement, getterSetterBuffer, false);
- emitter.emitInstanceMembers(classElement, methodBuffer, false);
+ ClassBuilder builder = new ClassBuilder();
+ emitter.emitClassFields(classElement, builder, classIsNative: true);
+ emitter.emitClassGettersSetters(classElement, builder);
+ emitter.emitInstanceMembers(classElement, builder);
- if (methodBuffer.isEmpty
- && fieldBuffer.isEmpty
- && getterSetterBuffer.isEmpty) {
- return;
- }
+ // An empty native class may be omitted since the superclass methods can be
+ // located via the dispatch metadata.
+ if (builder.properties.isEmpty) return;
String nativeTag = toNativeTag(classElement);
- nativeBuffer.add("$defineNativeClassName('$nativeTag',$_");
- nativeBuffer.add('{');
- bool firstInMap = true;
- if (!fieldBuffer.isEmpty) {
- firstInMap = false;
- nativeBuffer.add(fieldBuffer);
- }
- if (!getterSetterBuffer.isEmpty) {
- if (!firstInMap) nativeBuffer.add(",");
- firstInMap = false;
- nativeBuffer.add("\n$_");
- nativeBuffer.add(getterSetterBuffer);
- }
- if (!methodBuffer.isEmpty) {
- if (!firstInMap) nativeBuffer.add(",");
- nativeBuffer.add(methodBuffer);
- }
- nativeBuffer.add('$n})$N$n');
+ js.Expression definition =
+ js.call(js.use(defineNativeClassName),
+ [js.string(nativeTag), builder.toObjectInitializer()]);
+
+ nativeBuffer.add(js.prettyPrint(definition, compiler));
+ nativeBuffer.add('$N$n');
classesWithDynamicDispatch.add(classElement);
}
@@ -196,11 +176,10 @@ function(cls, desc) {
statements.add(
new js.ExpressionStatement(
- new js.Assignment(
- new js.VariableUse(name),
- new js.VariableUse(closureConverter)
- .callWith([new js.VariableUse(name),
- new js.LiteralNumber('$arity')]))));
+ js.assign(
+ js.use(name),
+ js.use(closureConverter).callWith(
+ [js.use(name), new js.LiteralNumber('$arity')]))));
break;
}
}
@@ -224,7 +203,6 @@ function(cls, desc) {
// foo(null, y).
ClassElement classElement = member.enclosingElement;
- //String nativeTagInfo = classElement.nativeName.slowToString();
String nativeTagInfo = classElement.nativeTagInfo.slowToString();
List<js.Statement> statements = <js.Statement>[];
@@ -268,23 +246,16 @@ function(cls, desc) {
String methodName,
js.Statement body,
List<js.Parameter> parameters) {
- return new js.If(
- new js.VariableUse('Object')
- .dot('getPrototypeOf')
- .callWith([new js.VariableUse('this')])
- .dot('hasOwnProperty')
- .callWith([new js.LiteralString("'$methodName'")]),
+ return js.if_(
+ js.use('Object').dot('getPrototypeOf')
+ .callWith([js.use('this')])
+ .dot('hasOwnProperty').callWith([js.string(methodName)]),
body,
- new js.Block(
- <js.Statement>[
- new js.Return(
- new js.VariableUse('Object')
- .dot('prototype').dot(methodName).dot('call')
- .callWith(
- <js.Expression>[new js.VariableUse('this')]
- ..addAll(parameters.map((param) =>
- new js.VariableUse(param.name)))))
- ]));
+ js.return_(
+ js.use('Object').dot('prototype').dot(methodName).dot('call')
+ .callWith(
+ <js.Expression>[js.use('this')]..addAll(
+ parameters.map((param) => js.use(param.name))))));
}
js.Block generateMethodBodyWithPrototypeCheckForElement(
@@ -300,7 +271,7 @@ function(cls, desc) {
} else if (element.kind == ElementKind.SETTER) {
methodName = namer.setterName(element.getLibrary(), element.name);
} else {
- compiler.internalError('unexpected kind: "${element.kind}"',
+ compiler.internalError("unexpected kind: '${element.kind}'",
element: element);
}
@@ -400,17 +371,14 @@ function(cls, desc) {
walk(classElement);
if (!subtags.isEmpty) {
- expressions.add(
- new js.LiteralString("'${Strings.join(subtags, '|')}'"));
+ expressions.add(js.string(Strings.join(subtags, '|')));
}
js.Expression expression;
if (expressions.length == 1) {
expression = expressions[0];
} else {
js.Expression array = new js.ArrayInitializer.from(expressions);
- expression = new js.Call(
- new js.PropertyAccess.field(array, 'join'),
- [new js.LiteralString("'|'")]);
+ expression = js.call(array.dot('join'), [js.string('|')]);
}
return expression;
}
@@ -445,7 +413,7 @@ function(cls, desc) {
new js.ArrayInitializer.from(
preorderDispatchClasses.map((cls) =>
new js.ArrayInitializer.from([
- new js.LiteralString("'${toNativeTag(cls)}'"),
+ js.string(toNativeTag(cls)),
tagDefns[cls]])));
// $.dynamicSetMetadata(table);
@@ -491,67 +459,86 @@ function(cls, desc) {
return isSupertypeOfNativeClass(element);
}
- void emitIsChecks(Map<String, String> objectProperties) {
- for (Element element in emitter.checkedClasses) {
- if (!requiresNativeIsCheck(element)) continue;
- if (element.isObject(compiler)) continue;
- String name = backend.namer.operatorIs(element);
- objectProperties[name] = 'function()$_{${_}return false;$_}';
- }
- }
-
void assembleCode(CodeBuffer targetBuffer) {
if (nativeClasses.isEmpty) return;
emitDynamicDispatchMetadata();
targetBuffer.add('$defineNativeClassName = '
'$defineNativeClassFunction$N$n');
+ List<js.Property> objectProperties = <js.Property>[];
+
+ void addProperty(String name, js.Expression value) {
+ objectProperties.add(new js.Property(js.string(name), value));
+ }
+
// Because of native classes, we have to generate some is checks
// by calling a method, instead of accessing a property. So we
// attach to the JS Object prototype these methods that return
// false, and will be overridden by subclasses when they have to
// return true.
- Map<String, String> objectProperties = new Map<String, String>();
- emitIsChecks(objectProperties);
+ void emitIsChecks() {
+ for (Element element in
+ Elements.sortedByPosition(emitter.checkedClasses)) {
+ if (!requiresNativeIsCheck(element)) continue;
+ if (element.isObject(compiler)) continue;
+ String name = backend.namer.operatorIs(element);
+ addProperty(name,
+ js.fun([], js.block1(js.return_(new js.LiteralBool(false)))));
+ }
+ }
+ emitIsChecks();
+
+ js.Expression makeCallOnThis(String functionName) =>
+ js.fun([],
+ js.block1(
+ js.return_(
+ js.call(js.use(functionName), [js.use('this')]))));
// In order to have the toString method on every native class,
// we must patch the JS Object prototype with a helper method.
String toStringName = backend.namer.publicInstanceMethodNameByArity(
const SourceString('toString'), 0);
- objectProperties[toStringName] =
- 'function() { return $toStringHelperName(this); }';
+ addProperty(toStringName, makeCallOnThis(toStringHelperName));
// Same as above, but for hashCode.
String hashCodeName =
backend.namer.publicGetterName(const SourceString('hashCode'));
- objectProperties[hashCodeName] =
- 'function() { return $hashCodeHelperName(this); }';
+ addProperty(hashCodeName, makeCallOnThis(hashCodeHelperName));
// If the native emitter has been asked to take care of the
// noSuchMethod handlers, we do that now.
if (handleNoSuchMethod) {
- emitter.emitNoSuchMethodHandlers((String name, CodeBuffer buffer) {
- objectProperties[name] = buffer.toString();
- });
+ emitter.emitNoSuchMethodHandlers(addProperty);
}
// If we have any properties to add to Object.prototype, we run
// through them and add them using defineProperty.
if (!objectProperties.isEmpty) {
- if (emitter.compiler.enableMinification) targetBuffer.add(";");
- targetBuffer.add("(function(table) {\n"
- " for (var key in table) {\n"
- " $defPropName(Object.prototype, key, table[key]);\n"
- " }\n"
- "})({\n");
- bool first = true;
- objectProperties.forEach((String name, String function) {
- if (!first) targetBuffer.add(",\n");
- targetBuffer.add("$_$name:$_$function");
- first = false;
- });
- targetBuffer.add("\n})$N$n");
+ js.Expression init =
+ js.call(
+ js.fun(['table'],
+ js.block1(
+ new js.ForIn(
+ new js.VariableDeclarationList(
+ [new js.VariableInitialization(
+ new js.VariableDeclaration('key'),
+ null)]),
+ js.use('table'),
+ new js.ExpressionStatement(
+ js.call(
+ js.use(defPropName),
+ [js.use('Object').dot('prototype'),
+ js.use('key'),
+ new js.PropertyAccess(js.use('table'),
+ js.use('key'))]))))),
+ [new js.ObjectInitializer(objectProperties)]);
+
+ if (emitter.compiler.enableMinification) targetBuffer.add(';');
+ targetBuffer.add(js.prettyPrint(
+ new js.ExpressionStatement(init), compiler));
+ targetBuffer.add('\n');
}
+
targetBuffer.add(nativeBuffer);
targetBuffer.add('\n');
}

Powered by Google App Engine
This is Rietveld 408576698