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

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart

Issue 787603003: Generative constructors in the new dart backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years 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: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
index e800a5c94fe28ee1d877dc305e3b87795dfaa1cc..cffa732445e5a42174feff6c628aa1deddc96805 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart
@@ -66,7 +66,9 @@ class IrBuilderTask extends CompilerTask {
assert(invariant(element, !element.isNative));
// TODO(kmillikin,sigurdm): Support constructors.
- if (element is ConstructorElement) return false;
+ if (element is ConstructorElement && !element.isGenerativeConstructor) {
+ return false;
+ }
} else if (element is! FieldElement) {
compiler.internalError(element, "Unexpected elementtype $element");
@@ -187,9 +189,91 @@ class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
defaults.add(getConstantForVariable(element));
});
- visit(node.body);
+ List<ir.Initializer> initializers;
+ if (element.isGenerativeConstructor) {
+ initializers = buildConstructorInitializers(node, element);
+ visit(node.body);
+ return irBuilder.makeConstructorDefinition(defaults, initializers);
+ } else {
+ visit(node.body);
+ return irBuilder.makeFunctionDefinition(defaults);
+ }
+ }
+
+ List<ir.Initializer> buildConstructorInitializers(
+ ast.FunctionExpression function, ConstructorElement element) {
+ List<ir.Initializer> result = new List<ir.Initializer>();
Kevin Millikin (Google) 2014/12/11 09:28:25 <ir.Initializer>[];
sigurdm 2014/12/17 10:20:56 Done.
+ FunctionSignature signature = element.functionSignature;
+
+ void tryAddInitializingFormal(ParameterElement parameterElement) {
+ if (parameterElement.isInitializingFormal) {
+ InitializingFormalElement initializingFormal = parameterElement;
+ withBuilder(new IrBuilder.delimited(irBuilder), () {
+ ir.Primitive value = irBuilder.buildLocalGet(parameterElement);
+ result.add(irBuilder.makeFieldInitializer(
+ initializingFormal.fieldElement,
+ irBuilder.makeRunnableBody(value)));
+ });
+ }
+ }
+
+ // TODO(sigurdm): Preserve initializing formals as initializing formals.
+ signature.orderedForEachParameter(tryAddInitializingFormal);
+
+ if (function.initializers == null) return result;
+ bool explicitSuperInitializer = false;
+ for(ast.Node initializer in function.initializers) {
+ if (initializer is ast.SendSet) {
+ // Field initializer.
+ FieldElement field = elements[initializer];
+ withBuilder(new IrBuilder.delimited(irBuilder), () {
+ ir.Primitive value = visit(initializer.arguments.head);
+ ir.RunnableBody body = irBuilder.makeRunnableBody(value);
+ result.add(irBuilder.makeFieldInitializer(field, body));
+ });
+ } else if (initializer is ast.Send) {
+ // Super or this initializer.
+ if (ast.Initializers.isConstructorRedirect(initializer)) {
+ giveup(initializer, "constructor redirect (this) initializer");
+ }
+ ConstructorElement constructor = elements[initializer].implementation;
+ Selector selector = elements.getSelector(initializer);
+ List<ir.RunnableBody> arguments =
+ initializer.arguments.mapToList((ast.Node argument) {
+ return withBuilder(new IrBuilder.delimited(irBuilder), () {
+ ir.Primitive value = visit(argument);
+ return irBuilder.makeRunnableBody(value);
+ });
+ });
+ result.add(irBuilder.makeSuperInitializer(constructor,
+ selector,
+ arguments));
+ explicitSuperInitializer = true;
+ } else {
+ compiler.internalError(initializer,
+ "Unexpected initializer type $initializer");
+ }
- return irBuilder.makeFunctionDefinition(defaults);
+ }
+ if (!explicitSuperInitializer) {
+ // No super initializer found. Try to find the default constructor if
+ // the class is not Object.
+ ClassElement enclosingClass = element.enclosingClass;
+ if (!enclosingClass.isObject) {
+ ClassElement superClass = enclosingClass.superclass;
+ Selector selector =
+ new Selector.callDefaultConstructor(enclosingClass.library);
Kevin Millikin (Google) 2014/12/11 09:28:25 Too much indentation here.
sigurdm 2014/12/17 10:20:56 Done.
+ FunctionElement target = superClass.lookupConstructor(selector);
+ if (target == null) {
+ compiler.internalError(superClass,
+ "No default constructor available.");
+ }
+ result.add(irBuilder.makeSuperInitializer(target,
+ selector,
+ <ir.RunnableBody>[]));
+ }
+ }
+ return result;
}
ir.FunctionDefinition buildFunction(FunctionElement element) {
@@ -897,6 +981,7 @@ class DetectClosureVariables extends ast.Visitor {
DetectClosureVariables(this.elements);
FunctionElement currentFunction;
+ bool insideInitializer = false;
Set<Local> usedFromClosure = new Set<Local>();
Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>();
@@ -923,9 +1008,28 @@ class DetectClosureVariables extends ast.Visitor {
node.visitChildren(this);
}
+ visitSendSet(ast.SendSet node) {
+ visitSend(node);
+ Element element = elements[node];
+ // Initializers in an initializer-list can communicate via parameters.
+ // If a parameter is stored in an initializer list we box it.
+ if (insideInitializer &&
+ Elements.isLocal(element) &&
+ element.isParameter) {
+ LocalElement local = element;
+ markAsClosureVariable(local);
Kevin Millikin (Google) 2014/12/11 09:28:25 For now this is OK, but I think later we will want
sigurdm 2014/12/17 10:20:56 Acknowledged.
+ }
+ node.visitChildren(this);
Kevin Millikin (Google) 2014/12/11 09:28:25 This function visits all the children twice (once
sigurdm 2014/12/17 10:20:56 Made a helper that both visitSend and visitSendSet
+ }
+
visitFunctionExpression(ast.FunctionExpression node) {
FunctionElement oldFunction = currentFunction;
currentFunction = elements[node];
+ if (node.initializers != null) {
+ insideInitializer = true;
+ visit(node.initializers);
+ insideInitializer = false;
+ }
visit(node.body);
currentFunction = oldFunction;
}

Powered by Google App Engine
This is Rietveld 408576698