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

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: 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
192 List<ir.Initializer> initializers;
193 if (element.isGenerativeConstructor) {
floitsch 2014/12/08 17:45:02 Make only one `if` if (element.isGenerativeConstr
sigurdm 2014/12/09 09:57:10 Done.
194 initializers = buildConstructorInitializers(node, element);
195 }
196
190 visit(node.body); 197 visit(node.body);
198 if (element.isGenerativeConstructor) {
199 return irBuilder.makeConstructorDefinition(defaults, initializers);
200 } else {
201 return irBuilder.makeFunctionDefinition(defaults);
202 }
203 }
191 204
192 return irBuilder.makeFunctionDefinition(defaults); 205 List<ir.Initializer> buildConstructorInitializers(
206 ast.FunctionExpression function, ConstructorElement element) {
207 List<ir.Initializer> result = new List<ir.Initializer>();
208 FunctionSignature signature = element.functionSignature;
209
210 void tryAddInitializingFormal(ParameterElement parameterElement) {
211 if (parameterElement.isInitializingFormal) {
212 InitializingFormalElement initializingFormal = parameterElement;
213 withBuilder(new IrBuilder.delimited(irBuilder), () {
214 ir.Primitive value = irBuilder.buildLocalGet(parameterElement);
215 result.add(irBuilder.makeFieldInitializer(
216 initializingFormal.fieldElement,
217 irBuilder.makeRunnableBody(value)));
218 });
219 }
220 }
221
222 // TODO(sigurdm): Preserve initializing formals as initializing formals.
223 signature.orderedForEachParameter(tryAddInitializingFormal);
224
225 if (function.initializers == null) return result;
226 bool explicitSuperInitializer = false;
227 for(ast.Node initializer in function.initializers) {
228 if (initializer is ast.SendSet) {
229 // Field initializer.
230 FieldElement field = elements[initializer];
231 withBuilder(new IrBuilder.delimited(irBuilder), () {
232 ir.Primitive value = visit(initializer.arguments.head);
233 ir.RunnableBody body = irBuilder.makeRunnableBody(value);
234 result.add(irBuilder.makeFieldInitializer(field, body));
235 });
236 } else if (initializer is ast.Send) {
237 // Super or this initializer.
238 if (ast.Initializers.isConstructorRedirect(initializer)) {
239 giveup(initializer, "constructor redirect (this) initializer");
240 }
241 ConstructorElement constructor = elements[initializer].implementation;
242 Selector selector = elements.getSelector(initializer);
243 List<ir.RunnableBody> arguments =
244 initializer.arguments.mapToList((ast.Node argument) {
245 return withBuilder(new IrBuilder.delimited(irBuilder), () {
246 ir.Primitive value = visit(argument);
247 return irBuilder.makeRunnableBody(value);
248 });
249 });
250 result.add(irBuilder.makeSuperInitializer(constructor,
251 selector,
252 arguments));
253 explicitSuperInitializer = true;
254 } else {
255 compiler.internalError(initializer,
256 "Unexpected initializer type $initializer");
257 }
258
259 }
260 if (!explicitSuperInitializer) {
261 // No super initializer found. Try to find the default constructor if
262 // the class is not Object.
263 ClassElement enclosingClass = element.enclosingClass;
264 if (!enclosingClass.isObject) {
265 ClassElement superClass = enclosingClass.superclass;
266 Selector selector =
267 new Selector.callDefaultConstructor(enclosingClass.library);
268 FunctionElement target = superClass.lookupConstructor(selector);
269 if (target == null) {
270 compiler.internalError(superClass,
271 "No default constructor available.");
272 }
273 result.add(irBuilder.makeSuperInitializer(target,
274 selector,
275 <ir.RunnableBody>[]));
276 }
277 }
278 return result;
193 } 279 }
194 280
195 ir.FunctionDefinition buildFunction(FunctionElement element) { 281 ir.FunctionDefinition buildFunction(FunctionElement element) {
196 assert(invariant(element, element.isImplementation)); 282 assert(invariant(element, element.isImplementation));
197 ast.FunctionExpression node = element.node; 283 ast.FunctionExpression node = element.node;
198 assert(node != null); 284 assert(node != null);
199 assert(elements[node] != null); 285 assert(elements[node] != null);
200 286
201 DetectClosureVariables closureLocals = new DetectClosureVariables(elements); 287 DetectClosureVariables closureLocals = new DetectClosureVariables(elements);
202 closureLocals.visit(node); 288 closureLocals.visit(node);
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 976 }
891 977
892 /// Classifies local variables and local functions as 'closure variables'. 978 /// Classifies local variables and local functions as 'closure variables'.
893 /// A closure variable is one that is accessed from an inner function nested 979 /// A closure variable is one that is accessed from an inner function nested
894 /// one or more levels inside the one that declares it. 980 /// one or more levels inside the one that declares it.
895 class DetectClosureVariables extends ast.Visitor { 981 class DetectClosureVariables extends ast.Visitor {
896 final TreeElements elements; 982 final TreeElements elements;
897 DetectClosureVariables(this.elements); 983 DetectClosureVariables(this.elements);
898 984
899 FunctionElement currentFunction; 985 FunctionElement currentFunction;
986 bool insideInitializer = false;
900 Set<Local> usedFromClosure = new Set<Local>(); 987 Set<Local> usedFromClosure = new Set<Local>();
901 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>(); 988 Set<FunctionElement> recursiveFunctions = new Set<FunctionElement>();
902 989
903 bool isClosureVariable(Entity entity) => usedFromClosure.contains(entity); 990 bool isClosureVariable(Entity entity) => usedFromClosure.contains(entity);
904 991
905 void markAsClosureVariable(Local local) { 992 void markAsClosureVariable(Local local) {
906 usedFromClosure.add(local); 993 usedFromClosure.add(local);
907 } 994 }
908 995
909 visit(ast.Node node) => node.accept(this); 996 visit(ast.Node node) => node.accept(this);
910 997
911 visitNode(ast.Node node) { 998 visitNode(ast.Node node) {
912 node.visitChildren(this); 999 node.visitChildren(this);
913 } 1000 }
914 1001
915 visitSend(ast.Send node) { 1002 visitSend(ast.Send node) {
916 Element element = elements[node]; 1003 Element element = elements[node];
917 if (Elements.isLocal(element) && 1004 if (Elements.isLocal(element) &&
918 !element.isConst && 1005 !element.isConst &&
919 element.enclosingElement != currentFunction) { 1006 element.enclosingElement != currentFunction) {
920 LocalElement local = element; 1007 LocalElement local = element;
921 markAsClosureVariable(local); 1008 markAsClosureVariable(local);
922 } 1009 }
923 node.visitChildren(this); 1010 node.visitChildren(this);
924 } 1011 }
925 1012
1013 visitSendSet(ast.SendSet node) {
1014 visitSend(node);
1015 Element element = elements[node];
1016 // Initializers in an initializer-list can communicate via parameters.
1017 // If a parameter is stored to in an initializer list we box it.
floitsch 2014/12/08 17:45:03 -to-
sigurdm 2014/12/09 09:57:10 Done.
1018 if (insideInitializer &&
1019 Elements.isLocal(element) &&
1020 element.isParameter) {
1021 LocalElement local = element;
1022 markAsClosureVariable(local);
1023 }
1024 node.visitChildren(this);
1025 }
1026
926 visitFunctionExpression(ast.FunctionExpression node) { 1027 visitFunctionExpression(ast.FunctionExpression node) {
927 FunctionElement oldFunction = currentFunction; 1028 FunctionElement oldFunction = currentFunction;
928 currentFunction = elements[node]; 1029 currentFunction = elements[node];
1030 if (node.initializers != null) {
1031 insideInitializer = true;
1032 visit(node.initializers);
1033 insideInitializer = false;
1034 }
929 visit(node.body); 1035 visit(node.body);
930 currentFunction = oldFunction; 1036 currentFunction = oldFunction;
931 } 1037 }
932 } 1038 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698