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

Side by Side Diff: runtime/vm/class_finalizer.cc

Issue 10964058: Support redirecting factory constructors in the VM (issue 3969). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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
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 #include "vm/class_finalizer.h" 5 #include "vm/class_finalizer.h"
6 6
7 #include "vm/flags.h" 7 #include "vm/flags.h"
8 #include "vm/heap.h" 8 #include "vm/heap.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 const Script& script = Script::Handle(interface.script()); 393 const Script& script = Script::Handle(interface.script());
394 ReportError(script, unresolved_factory_class.token_pos(), 394 ReportError(script, unresolved_factory_class.token_pos(),
395 "mismatch in number or names of type parameters between " 395 "mismatch in number or names of type parameters between "
396 "interface '%s' and default factory class '%s'", 396 "interface '%s' and default factory class '%s'",
397 interface_name.ToCString(), 397 interface_name.ToCString(),
398 factory_name.ToCString()); 398 factory_name.ToCString());
399 } 399 }
400 } 400 }
401 401
402 402
403 void ClassFinalizer::ResolveRedirectingFactoryTarget(
404 const Class& cls,
405 const Function& factory,
406 const GrowableObjectArray& visited_factories) {
407 ASSERT(factory.IsRedirectingFactory());
408
409 // Check for redirection cycle.
410 for (int i = 0; i < visited_factories.Length(); i++) {
411 if (visited_factories.At(i) == factory.raw()) {
412 // TODO(regis): Throw or report error?
413 const Script& script = Script::Handle(cls.script());
414 ReportError(script, factory.token_pos(),
415 "factory '%s' illegally redirects to itself",
416 String::Handle(factory.name()).ToCString());
417 }
418 }
419 visited_factories.Add(factory);
420
421 // Check if target is already resolved.
422 Type& type = Type::Handle(factory.RedirectionType());
423 Function& target = Function::Handle(factory.RedirectionTarget());
424 if (type.IsMalformed()) {
425 // Already resolved to a malformed type. Will throw on usage.
426 ASSERT(target.IsNull());
427 return;
428 }
429 if (!target.IsNull()) {
430 // Already resolved.
431 return;
432 }
433
434 // Target is not resolved yet.
435 if (FLAG_trace_class_finalization) {
436 OS::Print("Resolving redirecting factory: %s\n",
437 String::Handle(factory.name()).ToCString());
438 }
439 ResolveType(cls, type, kCanonicalize);
440 type ^= FinalizeType(cls, type, kCanonicalize);
441 factory.SetRedirectionType(type);
442 if (type.IsMalformed()) {
443 ASSERT(target.IsNull());
444 factory.SetRedirectionTarget(target);
445 return;
446 }
447 const Class& target_class = Class::Handle(type.type_class());
448 String& target_class_name = String::Handle(target_class.Name());
449 const String& period = String::Handle(Symbols::Dot());
450 String& target_name = String::Handle(
451 String::Concat(target_class_name, period));
452 const String& identifier = String::Handle(factory.RedirectionIdentifier());
453 if (!identifier.IsNull()) {
454 target_name = String::Concat(target_name, identifier);
455 }
456
457 // Verify that the target constructor of the redirection exists.
458 target = target_class.LookupConstructor(target_name);
459 if (target.IsNull()) {
460 target = target_class.LookupFactory(target_name);
461 }
462 if (target.IsNull()) {
463 const String& user_visible_target_name =
464 identifier.IsNull() ? target_class_name : target_name;
465 const Script& script = Script::Handle(cls.script());
466 // TODO(regis): Instead of reporting an error, should we replace the type
467 // with a malformed type and compile a throw? We should then also do it
468 // below for incompatible signatures. Wait for spec to stabilize.
469 ReportError(script, factory.token_pos(),
470 "class '%s' has no constructor or factory named '%s'",
471 target_class_name.ToCString(),
472 user_visible_target_name.ToCString());
473 }
474
475 // Verify that the target is compatible with the redirecting factory.
476 if (!target.HasCompatibleParametersWith(factory)) {
477 const Script& script = Script::Handle(cls.script());
478 ReportError(script, factory.token_pos(),
479 "constructor '%s' has incompatible parameters with redirecting "
480 "factory '%s'",
481 String::Handle(target.name()).ToCString(),
482 String::Handle(factory.name()).ToCString());
483 }
484
485 // Verify that the target is const if the the redirecting factory is const.
486 if (factory.is_const() && !target.is_const()) {
487 const Script& script = Script::Handle(cls.script());
488 ReportError(script, factory.token_pos(),
489 "constructor '%s' must be const as required by redirecting"
490 "const factory '%s'",
491 String::Handle(target.name()).ToCString(),
492 String::Handle(factory.name()).ToCString());
493 }
494
495 // Update redirection data with resolved target.
496 factory.SetRedirectionTarget(target);
497 factory.SetRedirectionIdentifier(String::Handle()); // Not needed anymore.
498 if (!target.IsRedirectingFactory()) {
499 return;
500 }
501
502 // The target is itself a redirecting factory. Recursively resolve its own
503 // target and update the current redirection data to point to the end target
504 // of the redirection chain.
505 ResolveRedirectingFactoryTarget(target_class, target, visited_factories);
506 Type& target_type = Type::Handle(target.RedirectionType());
507 const Function& target_target = Function::Handle(target.RedirectionTarget());
508 if (target_target.IsNull()) {
509 ASSERT(target_type.IsMalformed());
510 } else {
511 if (!target_type.IsInstantiated()) {
512 const AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(
513 type.arguments());
514 target_type ^= target_type.InstantiateFrom(type_args);
515 // TODO(regis): Do we need to check bounds?
516 target_type ^= FinalizeType(cls, target_type, kCanonicalize);
517 }
518 }
519 factory.SetRedirectionType(target_type);
520 factory.SetRedirectionTarget(target_target);
521 }
522
523
403 void ClassFinalizer::ResolveType(const Class& cls, 524 void ClassFinalizer::ResolveType(const Class& cls,
404 const AbstractType& type, 525 const AbstractType& type,
405 FinalizationKind finalization) { 526 FinalizationKind finalization) {
406 if (type.IsResolved() || type.IsFinalized()) { 527 if (type.IsResolved() || type.IsFinalized()) {
407 return; 528 return;
408 } 529 }
409 if (FLAG_trace_type_finalization) { 530 if (FLAG_trace_type_finalization) {
410 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString()); 531 OS::Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
411 } 532 }
412 533
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 const String& super_class_name = String::Handle(super_class.Name()); 1048 const String& super_class_name = String::Handle(super_class.Name());
928 const Script& script = Script::Handle(cls.script()); 1049 const Script& script = Script::Handle(cls.script());
929 ReportError(script, function.token_pos(), 1050 ReportError(script, function.token_pos(),
930 "static function '%s' of class '%s' conflicts with " 1051 "static function '%s' of class '%s' conflicts with "
931 "instance member '%s' of super class '%s'", 1052 "instance member '%s' of super class '%s'",
932 function_name.ToCString(), 1053 function_name.ToCString(),
933 class_name.ToCString(), 1054 class_name.ToCString(),
934 function_name.ToCString(), 1055 function_name.ToCString(),
935 super_class_name.ToCString()); 1056 super_class_name.ToCString());
936 } 1057 }
1058 if (function.IsRedirectingFactory()) {
1059 const GrowableObjectArray& redirecting_factories =
1060 GrowableObjectArray::Handle(GrowableObjectArray::New());
1061 ResolveRedirectingFactoryTarget(cls, function, redirecting_factories);
1062 }
937 } else { 1063 } else {
938 for (int i = 0; i < interfaces.Length(); i++) { 1064 for (int i = 0; i < interfaces.Length(); i++) {
939 super_class ^= interfaces.At(i); 1065 super_class ^= interfaces.At(i);
940 overridden_function = super_class.LookupDynamicFunction(function_name); 1066 overridden_function = super_class.LookupDynamicFunction(function_name);
941 if (!overridden_function.IsNull() && 1067 if (!overridden_function.IsNull() &&
942 !function.HasCompatibleParametersWith(overridden_function)) { 1068 !function.HasCompatibleParametersWith(overridden_function)) {
943 // Function types are purposely not checked for subtyping. 1069 // Function types are purposely not checked for subtyping.
944 const String& class_name = String::Handle(cls.Name()); 1070 const String& class_name = String::Handle(cls.Name());
945 const String& super_class_name = String::Handle(super_class.Name()); 1071 const String& super_class_name = String::Handle(super_class.Name());
946 const Script& script = Script::Handle(cls.script()); 1072 const Script& script = Script::Handle(cls.script());
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 void ClassFinalizer::ReportError(const char* format, ...) { 1532 void ClassFinalizer::ReportError(const char* format, ...) {
1407 va_list args; 1533 va_list args;
1408 va_start(args, format); 1534 va_start(args, format);
1409 const Error& error = Error::Handle( 1535 const Error& error = Error::Handle(
1410 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1536 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1411 va_end(args); 1537 va_end(args);
1412 ReportError(error); 1538 ReportError(error);
1413 } 1539 }
1414 1540
1415 } // namespace dart 1541 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698