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

Side by Side Diff: lib/compiler/implementation/emitter.dart

Issue 10344021: Create the JavaScript constructor dynamically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test. Created 8 years, 7 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/tests/leg/class_codegen_test.dart ('k') | tests/language/class_codegen_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 /** 5 /**
6 * A function element that represents a closure call. The signature is copied 6 * A function element that represents a closure call. The signature is copied
7 * from the given element. 7 * from the given element.
8 */ 8 */
9 class ClosureInvocationElement extends FunctionElement { 9 class ClosureInvocationElement extends FunctionElement {
10 ClosureInvocationElement(SourceString name, 10 ClosureInvocationElement(SourceString name,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 String get finishClassesName() 46 String get finishClassesName()
47 => '${namer.ISOLATE}.\$finishClasses'; 47 => '${namer.ISOLATE}.\$finishClasses';
48 String get finishIsolateConstructorName() 48 String get finishIsolateConstructorName()
49 => '${namer.ISOLATE}.\$finishIsolateConstructor'; 49 => '${namer.ISOLATE}.\$finishIsolateConstructor';
50 String get pendingClassesName() 50 String get pendingClassesName()
51 => '${namer.ISOLATE}.\$pendingClasses'; 51 => '${namer.ISOLATE}.\$pendingClasses';
52 String get isolatePropertiesName() 52 String get isolatePropertiesName()
53 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; 53 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}';
54 54
55 String get defineClassFunction() { 55 String get defineClassFunction() {
56 // First the class name, then the super class name, followed by the fields
57 // (in an array) and the members (inside an Object literal).
58 // The caller can also pass in the constructor as a function if needed.
ngeoffray 2012/05/07 09:42:30 Who needs that?
floitsch 2012/05/07 12:42:08 This is in preparation for a future CL. The idea i
59 //
56 // Example: 60 // Example:
57 // defineClass("A", "B", 61 // defineClass("A", "B", ["x", "y"], {
58 // function(x) { /* The JavaScript constructor. */
59 // this.x = x;
60 // }, { /* The members inside an Object literal. */
61 // foo$1: function(y) { 62 // foo$1: function(y) {
62 // print(this.x + y); 63 // print(this.x + y);
63 // }, 64 // },
64 // bar$2: function(t, v) { 65 // bar$2: function(t, v) {
65 // this.x = t - v; 66 // this.x = t - v;
66 // }, 67 // },
67 // }); 68 // });
68 return """ 69 return """
69 function(cls, superclass, constructor, prototype) { 70 function(cls, superclass, fields, prototype) {
71 var constructor;
72 if (typeof fields == 'function') {
ngeoffray 2012/05/07 09:42:30 Since we control the emission, why do we need to s
floitsch 2012/05/07 12:42:08 If you prefer I can remove the code for now. (it's
ngeoffray 2012/05/07 12:54:25 It's fine if you keep it but make sure you'll use
73 constructor = fields;
74 } else {
75 var str = "(function " + cls + "(";
76 var body = "";
77 for (var i = 0; i < fields.length; i++) {
78 if (i != 0) str += ", ";
79 str += fields[i];
80 body += "this." + fields[i] + " = " + fields[i] + ";\\n";
81 }
82 str += ") {" + body + "})";
83 constructor = eval(str);
84 }
70 $isolatePropertiesName[cls] = constructor; 85 $isolatePropertiesName[cls] = constructor;
71 constructor.prototype = prototype; 86 constructor.prototype = prototype;
72 if (superclass !== "") { 87 if (superclass !== "") {
73 $pendingClassesName[cls] = superclass; 88 $pendingClassesName[cls] = superclass;
74 } 89 }
75 }"""; 90 }""";
76 } 91 }
77 92
78 String get finishClassesFunction() { 93 String get finishClassesFunction() {
79 // 'defineClass' does not require the classes to be constructed in order. 94 // 'defineClass' does not require the classes to be constructed in order.
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 : namer.getName(member); 365 : namer.getName(member);
351 defineInstanceMember(getterName, "function() { return this.$name; }"); 366 defineInstanceMember(getterName, "function() { return this.$name; }");
352 } 367 }
353 } else { 368 } else {
354 compiler.internalError('unexpected kind: "${member.kind}"', 369 compiler.internalError('unexpected kind: "${member.kind}"',
355 element: member); 370 element: member);
356 } 371 }
357 emitExtraAccessors(member, defineInstanceMember); 372 emitExtraAccessors(member, defineInstanceMember);
358 } 373 }
359 374
360 bool generateFieldInits(ClassElement classElement, 375 List<String> generateFieldList(ClassElement classElement) {
361 StringBuffer argumentsBuffer, 376 List<String> result = <String>[];
362 StringBuffer bodyBuffer) { 377 void addField(ClassElement enclosingClass, Element member) {
363 bool isFirst = true; 378 result.add(namer.instanceFieldName(member.getLibrary(), member.name));
364 void generateFieldInit(ClassElement enclosingClass, Element member) {
365 // TODO(floitsch): make sure there are no name clashes.
366 String className = namer.getName(enclosingClass);
367 if (!isFirst) argumentsBuffer.add(', ');
368 isFirst = false;
369 String memberName = namer.instanceFieldName(member.getLibrary(),
370 member.name);
371 String parameter;
372 if (classElement === enclosingClass) {
373 parameter = memberName;
374 } else {
375 parameter = '${className}_$memberName';
376 }
377 argumentsBuffer.add(parameter);
378 bodyBuffer.add(' this.$memberName = $parameter;\n');
379 } 379 }
380 380
381 classElement.forEachInstanceField(generateFieldInit, 381 classElement.forEachInstanceField(addField,
382 includeBackendMembers: true, 382 includeBackendMembers: true,
383 includeSuperMembers: true); 383 includeSuperMembers: true);
384 return result;
384 } 385 }
385 386
386 void generateClass(ClassElement classElement, StringBuffer buffer) { 387 void generateClass(ClassElement classElement, StringBuffer buffer) {
387 needsDefineClass = true; 388 needsDefineClass = true;
388 389
389 if (classElement.isNative()) { 390 if (classElement.isNative()) {
390 nativeEmitter.generateNativeClass(classElement); 391 nativeEmitter.generateNativeClass(classElement);
391 return; 392 return;
392 } else { 393 } else {
393 // TODO(ngeoffray): Instead of switching between buffer, we 394 // TODO(ngeoffray): Instead of switching between buffer, we
394 // should create code sections, and decide where to emit them at 395 // should create code sections, and decide where to emit them at
395 // the end. 396 // the end.
396 buffer = mainBuffer; 397 buffer = mainBuffer;
397 } 398 }
398 399
399 String className = namer.getName(classElement); 400 String className = namer.getName(classElement);
400 ClassElement superclass = classElement.superclass; 401 ClassElement superclass = classElement.superclass;
401 String superName = ""; 402 String superName = "";
402 if (superclass !== null) { 403 if (superclass !== null) {
403 superName = namer.getName(superclass); 404 superName = namer.getName(superclass);
404 } 405 }
405 String constructorName = namer.safeName(classElement.name.slowToString()); 406 String constructorName = namer.safeName(classElement.name.slowToString());
406 buffer.add('$defineClassName("$className", "$superName", '); 407 buffer.add('$defineClassName("$className", "$superName", ');
407 buffer.add('function $constructorName(');
408 StringBuffer bodyBuffer = new StringBuffer();
409 // If the class is never instantiated we still need to set it up for 408 // If the class is never instantiated we still need to set it up for
410 // inheritance purposes, but we can leave its JavaScript constructor empty. 409 // inheritance purposes, but we can simplify its JavaScript constructor.
411 if (compiler.universe.instantiatedClasses.contains(classElement)) { 410 if (!compiler.universe.instantiatedClasses.contains(classElement)) {
412 generateFieldInits(classElement, buffer, bodyBuffer); 411 buffer.add("[]");
412 } else {
413 List<String> fields = generateFieldList(classElement);
414 buffer.add('[');
415 for (int i = 0; i < fields.length; i++) {
416 if (i != 0) buffer.add(", ");
417 buffer.add('"${fields[i]}"');
418 }
419 buffer.add(']');
413 } 420 }
414 buffer.add(') {\n'); 421 buffer.add(', {\n');
415 buffer.add(bodyBuffer);
416 buffer.add(' }, ');
417
418 buffer.add('{\n');
419 422
420 void defineInstanceMember(String name, String value) { 423 void defineInstanceMember(String name, String value) {
421 buffer.add(' $name: $value,\n'); 424 buffer.add(' $name: $value,\n');
422 } 425 }
423 426
424 classElement.forEachMember(includeBackendMembers: true, 427 classElement.forEachMember(includeBackendMembers: true,
425 f: (ClassElement enclosing, Element member) { 428 f: (ClassElement enclosing, Element member) {
426 if (member.isInstanceMember()) { 429 if (member.isInstanceMember()) {
427 addInstanceMember(member, defineInstanceMember); 430 addInstanceMember(member, defineInstanceMember);
428 } 431 }
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 mainBuffer.add('function init() {\n'); 896 mainBuffer.add('function init() {\n');
894 mainBuffer.add(' $isolateProperties = {};\n'); 897 mainBuffer.add(' $isolateProperties = {};\n');
895 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); 898 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
896 emitFinishIsolateConstructor(mainBuffer); 899 emitFinishIsolateConstructor(mainBuffer);
897 mainBuffer.add('}\n'); 900 mainBuffer.add('}\n');
898 compiler.assembledCode = mainBuffer.toString(); 901 compiler.assembledCode = mainBuffer.toString();
899 }); 902 });
900 return compiler.assembledCode; 903 return compiler.assembledCode;
901 } 904 }
902 } 905 }
OLDNEW
« no previous file with comments | « frog/tests/leg/class_codegen_test.dart ('k') | tests/language/class_codegen_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698