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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 }); 59 });
60 } 60 }
61 61
62 bool canBuild(Element element) { 62 bool canBuild(Element element) {
63 if (element is TypedefElement) return false; 63 if (element is TypedefElement) return false;
64 if (element is FunctionElement) { 64 if (element is FunctionElement) {
65 // TODO(sigurdm): Support native functions for dart2js. 65 // TODO(sigurdm): Support native functions for dart2js.
66 assert(invariant(element, !element.isNative)); 66 assert(invariant(element, !element.isNative));
67 67
68 // TODO(kmillikin,sigurdm): Support constructors. 68 // TODO(kmillikin,sigurdm): Support constructors.
69 if (element is ConstructorElement) return false; 69 if (element is ConstructorElement && !element.isGenerativeConstructor) {
70 return false;
71 }
70 72
71 } else if (element is! FieldElement) { 73 } else if (element is! FieldElement) {
72 compiler.internalError(element, "Unexpected elementtype $element"); 74 compiler.internalError(element, "Unexpected elementtype $element");
73 } 75 }
74 return compiler.backend.shouldOutput(element); 76 return compiler.backend.shouldOutput(element);
75 } 77 }
76 78
77 bool get inCheckedMode { 79 bool get inCheckedMode {
78 bool result = false; 80 bool result = false;
79 assert((result = true)); 81 assert((result = true));
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 FunctionSignature signature = element.functionSignature; 182 FunctionSignature signature = element.functionSignature;
181 signature.orderedForEachParameter((ParameterElement parameterElement) { 183 signature.orderedForEachParameter((ParameterElement parameterElement) {
182 irBuilder.createFunctionParameter(parameterElement); 184 irBuilder.createFunctionParameter(parameterElement);
183 }); 185 });
184 186
185 List<ConstantExpression> defaults = new List<ConstantExpression>(); 187 List<ConstantExpression> defaults = new List<ConstantExpression>();
186 signature.orderedOptionalParameters.forEach((ParameterElement element) { 188 signature.orderedOptionalParameters.forEach((ParameterElement element) {
187 defaults.add(getConstantForVariable(element)); 189 defaults.add(getConstantForVariable(element));
188 }); 190 });
189 191
190 visit(node.body); 192 List<ir.Initializer> initializers;
193 if (element.isGenerativeConstructor) {
194 initializers = buildConstructorInitializers(node, element);
195 visit(node.body);
196 return irBuilder.makeConstructorDefinition(defaults, initializers);
197 } else {
198 visit(node.body);
199 return irBuilder.makeFunctionDefinition(defaults);
200 }
201 }
191 202
192 return irBuilder.makeFunctionDefinition(defaults); 203 List<ir.Initializer> buildConstructorInitializers(
204 ast.FunctionExpression function, ConstructorElement element) {
205 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.
206 FunctionSignature signature = element.functionSignature;
207
208 void tryAddInitializingFormal(ParameterElement parameterElement) {
209 if (parameterElement.isInitializingFormal) {
210 InitializingFormalElement initializingFormal = parameterElement;
211 withBuilder(new IrBuilder.delimited(irBuilder), () {
212 ir.Primitive value = irBuilder.buildLocalGet(parameterElement);
213 result.add(irBuilder.makeFieldInitializer(
214 initializingFormal.fieldElement,
215 irBuilder.makeRunnableBody(value)));
216 });
217 }
218 }
219
220 // TODO(sigurdm): Preserve initializing formals as initializing formals.
221 signature.orderedForEachParameter(tryAddInitializingFormal);
222
223 if (function.initializers == null) return result;
224 bool explicitSuperInitializer = false;
225 for(ast.Node initializer in function.initializers) {
226 if (initializer is ast.SendSet) {
227 // Field initializer.
228 FieldElement field = elements[initializer];
229 withBuilder(new IrBuilder.delimited(irBuilder), () {
230 ir.Primitive value = visit(initializer.arguments.head);
231 ir.RunnableBody body = irBuilder.makeRunnableBody(value);
232 result.add(irBuilder.makeFieldInitializer(field, body));
233 });
234 } else if (initializer is ast.Send) {
235 // Super or this initializer.
236 if (ast.Initializers.isConstructorRedirect(initializer)) {
237 giveup(initializer, "constructor redirect (this) initializer");
238 }
239 ConstructorElement constructor = elements[initializer].implementation;
240 Selector selector = elements.getSelector(initializer);
241 List<ir.RunnableBody> arguments =
242 initializer.arguments.mapToList((ast.Node argument) {
243 return withBuilder(new IrBuilder.delimited(irBuilder), () {
244 ir.Primitive value = visit(argument);
245 return irBuilder.makeRunnableBody(value);
246 });
247 });
248 result.add(irBuilder.makeSuperInitializer(constructor,
249 selector,
250 arguments));
251 explicitSuperInitializer = true;
252 } else {
253 compiler.internalError(initializer,
254 "Unexpected initializer type $initializer");
255 }
256
257 }
258 if (!explicitSuperInitializer) {
259 // No super initializer found. Try to find the default constructor if
260 // the class is not Object.
261 ClassElement enclosingClass = element.enclosingClass;
262 if (!enclosingClass.isObject) {
263 ClassElement superClass = enclosingClass.superclass;
264 Selector selector =
265 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.
266 FunctionElement target = superClass.lookupConstructor(selector);
267 if (target == null) {
268 compiler.internalError(superClass,
269 "No default constructor available.");
270 }
271 result.add(irBuilder.makeSuperInitializer(target,
272 selector,
273 <ir.RunnableBody>[]));
274 }
275 }
276 return result;
193 } 277 }
194 278
195 ir.FunctionDefinition buildFunction(FunctionElement element) { 279 ir.FunctionDefinition buildFunction(FunctionElement element) {
196 assert(invariant(element, element.isImplementation)); 280 assert(invariant(element, element.isImplementation));
197 ast.FunctionExpression node = element.node; 281 ast.FunctionExpression node = element.node;
198 assert(node != null); 282 assert(node != null);
199 assert(elements[node] != null); 283 assert(elements[node] != null);
200 284
201 DetectClosureVariables closureLocals = new DetectClosureVariables(elements); 285 DetectClosureVariables closureLocals = new DetectClosureVariables(elements);
202 closureLocals.visit(node); 286 closureLocals.visit(node);
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 974 }
891 975
892 /// Classifies local variables and local functions as 'closure variables'. 976 /// Classifies local variables and local functions as 'closure variables'.
893 /// A closure variable is one that is accessed from an inner function nested 977 /// A closure variable is one that is accessed from an inner function nested
894 /// one or more levels inside the one that declares it. 978 /// one or more levels inside the one that declares it.
895 class DetectClosureVariables extends ast.Visitor { 979 class DetectClosureVariables extends ast.Visitor {
896 final TreeElements elements; 980 final TreeElements elements;
897 DetectClosureVariables(this.elements); 981 DetectClosureVariables(this.elements);
898 982
899 FunctionElement currentFunction; 983 FunctionElement currentFunction;
984 bool insideInitializer = false;
900 Set<Local> usedFromClosure = new Set<Local>(); 985 Set<Local> usedFromClosure = new Set<Local>();
901 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); 986 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>();
902 987
903 bool isClosureVariable(Entity entity) => usedFromClosure.contains(entity); 988 bool isClosureVariable(Entity entity) => usedFromClosure.contains(entity);
904 989
905 void markAsClosureVariable(Local local) { 990 void markAsClosureVariable(Local local) {
906 usedFromClosure.add(local); 991 usedFromClosure.add(local);
907 } 992 }
908 993
909 visit(ast.Node node) => node.accept(this); 994 visit(ast.Node node) => node.accept(this);
910 995
911 visitNode(ast.Node node) { 996 visitNode(ast.Node node) {
912 node.visitChildren(this); 997 node.visitChildren(this);
913 } 998 }
914 999
915 visitSend(ast.Send node) { 1000 visitSend(ast.Send node) {
916 Element element = elements[node]; 1001 Element element = elements[node];
917 if (Elements.isLocal(element) && 1002 if (Elements.isLocal(element) &&
918 !element.isConst && 1003 !element.isConst &&
919 element.enclosingElement != currentFunction) { 1004 element.enclosingElement != currentFunction) {
920 LocalElement local = element; 1005 LocalElement local = element;
921 markAsClosureVariable(local); 1006 markAsClosureVariable(local);
922 } 1007 }
923 node.visitChildren(this); 1008 node.visitChildren(this);
924 } 1009 }
925 1010
1011 visitSendSet(ast.SendSet node) {
1012 visitSend(node);
1013 Element element = elements[node];
1014 // Initializers in an initializer-list can communicate via parameters.
1015 // If a parameter is stored in an initializer list we box it.
1016 if (insideInitializer &&
1017 Elements.isLocal(element) &&
1018 element.isParameter) {
1019 LocalElement local = element;
1020 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.
1021 }
1022 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
1023 }
1024
926 visitFunctionExpression(ast.FunctionExpression node) { 1025 visitFunctionExpression(ast.FunctionExpression node) {
927 FunctionElement oldFunction = currentFunction; 1026 FunctionElement oldFunction = currentFunction;
928 currentFunction = elements[node]; 1027 currentFunction = elements[node];
1028 if (node.initializers != null) {
1029 insideInitializer = true;
1030 visit(node.initializers);
1031 insideInitializer = false;
1032 }
929 visit(node.body); 1033 visit(node.body);
930 currentFunction = oldFunction; 1034 currentFunction = oldFunction;
931 } 1035 }
932 } 1036 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698