Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 17941) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -1180,7 +1180,8 @@ |
| if (signature_class.IsNull()) { |
| signature_class = Class::NewSignatureClass(signature, |
| signature_function, |
| - script_); |
| + script_, |
| + parameter.name_pos); |
| // Record the function signature class in the current library. |
| library_.AddClass(signature_class); |
| } else { |
| @@ -2157,7 +2158,7 @@ |
| const Function& super_ctor = super_call->function(); |
| // Patch the initializer call so it only executes the super initializer. |
| initializer_args->SetNodeAt(1, |
| - new LiteralNode(TokenPos(), |
| + new LiteralNode(TokenPos(), |
| Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| ArgumentListNode* super_call_args = new ArgumentListNode(TokenPos()); |
| @@ -3126,6 +3127,7 @@ |
| OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); |
| } |
| Class& cls = Class::Handle(); |
| + TypeArguments& orig_type_parameters = TypeArguments::Handle(); |
| Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); |
| if (obj.IsNull()) { |
| if (is_patch) { |
| @@ -3141,6 +3143,9 @@ |
| } |
| cls ^= obj.raw(); |
| if (is_patch) { |
| + // Preserve and reuse the original type parameters and bounds since the |
| + // ones defined in the patch class will not be finalized. |
| + orig_type_parameters = cls.type_parameters(); |
| String& patch = String::Handle( |
| String::Concat(Symbols::PatchSpace(), class_name)); |
| patch = Symbols::New(patch); |
| @@ -3161,6 +3166,41 @@ |
| ASSERT(cls.functions() == Object::empty_array().raw()); |
| set_current_class(cls); |
| ParseTypeParameters(cls); |
| + if (is_patch) { |
| + // Check that the new type parameters are identical to the original ones. |
| + const TypeArguments& new_type_parameters = |
| + TypeArguments::Handle(cls.type_parameters()); |
| + const int new_type_params_count = |
| + new_type_parameters.IsNull() ? 0 : new_type_parameters.Length(); |
| + const int orig_type_params_count = |
| + orig_type_parameters.IsNull() ? 0 : orig_type_parameters.Length(); |
| + if (new_type_params_count != orig_type_params_count) { |
| + ErrorMsg(classname_pos, |
| + "class '%s' must be patched with identical type parameters", |
| + class_name.ToCString()); |
| + } |
| + TypeParameter& new_type_param = TypeParameter::Handle(); |
| + TypeParameter& orig_type_param = TypeParameter::Handle(); |
| + String& new_name = String::Handle(); |
| + String& orig_name = String::Handle(); |
| + for (int i = 0; i < new_type_params_count; i++) { |
| + new_type_param ^= new_type_parameters.TypeAt(i); |
| + orig_type_param ^= orig_type_parameters.TypeAt(i); |
| + new_name = new_type_param.name(); |
| + orig_name = orig_type_param.name(); |
| + if (!new_name.Equals(orig_name)) { |
| + ErrorMsg(new_type_param.token_pos(), |
| + "type parameter '%s' of patch class '%s' does not match " |
| + "original type parameter '%s'", |
| + new_name.ToCString(), |
| + class_name.ToCString(), |
| + orig_name.ToCString()); |
| + } |
| + // We do not check that the bounds are repeated. We use the original ones. |
| + // TODO(regis): Should we check? |
| + } |
| + cls.set_type_parameters(orig_type_parameters); |
| + } |
| Type& super_type = Type::Handle(); |
| if (CurrentToken() == Token::kEXTENDS) { |
| ConsumeToken(); |
| @@ -3218,8 +3258,10 @@ |
| if (!is_patch) { |
| pending_classes.Add(cls, Heap::kOld); |
| } else { |
| - // Lookup the patched class and apply the changes. |
| - obj = library_.LookupLocalObject(class_name); |
| + // Apply the changes to the patched class looked up above. |
| + ASSERT(obj.raw() == library_.LookupLocalObject(class_name)); |
| + // The patched class must not be finalized yet. |
| + ASSERT(!Class::Cast(obj).is_finalized()); |
| const char* err_msg = Class::Cast(obj).ApplyPatch(cls); |
| if (err_msg != NULL) { |
| ErrorMsg(classname_pos, "applying patch failed with '%s'", err_msg); |
| @@ -3330,15 +3372,6 @@ |
| TRACE_PARSER("ParseFunctionTypeAlias"); |
| ExpectToken(Token::kTYPEDEF); |
| - // Allocate an abstract class to hold the type parameters and their bounds. |
| - // Make it the owner of the function type descriptor. |
| - const Class& alias_owner = Class::Handle( |
| - Class::New(Symbols::AliasOwner(), Script::Handle(), TokenPos())); |
| - |
| - alias_owner.set_is_abstract(); |
| - alias_owner.set_library(library_); |
| - set_current_class(alias_owner); |
| - |
| // Parse the result type of the function type. |
| AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| if (CurrentToken() == Token::kVOID) { |
| @@ -3354,12 +3387,31 @@ |
| const String* alias_name = |
| ExpectUserDefinedTypeIdentifier("function alias name expected"); |
| + // Lookup alias name and report an error if it is already defined in |
| + // the library scope. |
| + const Object& obj = Object::Handle(library_.LookupLocalObject(*alias_name)); |
| + if (!obj.IsNull()) { |
| + ErrorMsg(alias_name_pos, |
| + "'%s' is already defined", alias_name->ToCString()); |
| + } |
| + |
| + // Create the function type alias signature class. It will be linked to its |
| + // signature function after it has been parsed. The type parameters, in order |
| + // to be properly finalized, need to be associated to this signature class as |
| + // they are parsed. |
| + Class& function_type_alias = Class::Handle( |
|
siva
2013/02/01 00:31:57
const Class& function_type......
regis
2013/02/01 02:03:44
Done.
|
| + Class::NewSignatureClass(*alias_name, |
| + Function::Handle(), |
| + script_, |
| + alias_name_pos)); |
| + library_.AddClass(function_type_alias); |
| + set_current_class(function_type_alias); |
| // Parse the type parameters of the function type. |
| - ParseTypeParameters(alias_owner); |
| + ParseTypeParameters(function_type_alias); |
| // At this point, the type parameters have been parsed, so we can resolve the |
| // result type. |
| if (!result_type.IsNull()) { |
| - ResolveTypeFromClass(alias_owner, |
| + ResolveTypeFromClass(function_type_alias, |
| ClassFinalizer::kTryResolve, |
| &result_type); |
| } |
| @@ -3377,6 +3429,7 @@ |
| const bool no_explicit_default_values = false; |
| ParseFormalParameterList(no_explicit_default_values, &func_params); |
| + ExpectSemicolon(); |
| // The field 'is_static' has no meaning for signature functions. |
| Function& signature_function = Function::Handle( |
| Function::New(*alias_name, |
| @@ -3385,10 +3438,14 @@ |
| /* is_const = */ false, |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| - alias_owner, |
| + function_type_alias, |
| alias_name_pos)); |
| signature_function.set_result_type(result_type); |
| AddFormalParamsToFunction(&func_params, signature_function); |
| + |
| + // Patch the signature function in the signature class. |
| + function_type_alias.PatchSignatureFunction(signature_function); |
| + |
| const String& signature = String::Handle(signature_function.Signature()); |
| if (FLAG_trace_parser) { |
| OS::Print("TopLevel parsing function type alias '%s'\n", |
| @@ -3402,35 +3459,21 @@ |
| if (signature_class.IsNull()) { |
| signature_class = Class::NewSignatureClass(signature, |
| signature_function, |
| - script_); |
| + script_, |
| + alias_name_pos); |
| // Record the function signature class in the current library. |
| library_.AddClass(signature_class); |
| } else { |
| // Forget the just created signature function and use the existing one. |
| signature_function = signature_class.signature_function(); |
| + function_type_alias.PatchSignatureFunction(signature_function); |
| } |
| ASSERT(signature_function.signature_class() == signature_class.raw()); |
| - // Lookup alias name and report an error if it is already defined in |
| - // the library scope. |
| - const Object& obj = Object::Handle(library_.LookupLocalObject(*alias_name)); |
| - if (!obj.IsNull()) { |
| - ErrorMsg(alias_name_pos, |
| - "'%s' is already defined", alias_name->ToCString()); |
| - } |
| - |
| - // Create the function type alias, but share the signature function of the |
| - // canonical signature class. |
| - Class& function_type_alias = Class::Handle( |
| - Class::NewSignatureClass(*alias_name, |
| - signature_function, |
| - script_)); |
| - // This alias should not be marked as finalized yet, since it needs to be |
| + // The alias should not be marked as finalized yet, since it needs to be |
| // checked in the class finalizer for illegal self references. |
| ASSERT(!function_type_alias.IsCanonicalSignatureClass()); |
| ASSERT(!function_type_alias.is_finalized()); |
| - library_.AddClass(function_type_alias); |
| - ExpectSemicolon(); |
| pending_classes.Add(function_type_alias, Heap::kOld); |
| } |
| @@ -4368,6 +4411,7 @@ |
| ParseClassDefinition(pending_classes); |
| } else if ((CurrentToken() == Token::kTYPEDEF) && |
| (LookaheadToken(1) != Token::kLPAREN)) { |
| + set_current_class(toplevel_class); |
| ParseFunctionTypeAlias(pending_classes); |
| } else if ((CurrentToken() == Token::kABSTRACT) && |
| (LookaheadToken(1) == Token::kCLASS)) { |
| @@ -4859,7 +4903,8 @@ |
| ASSERT(is_new_closure); |
| signature_class = Class::NewSignatureClass(signature, |
| function, |
| - script_); |
| + script_, |
| + function.token_pos()); |
| // Record the function signature class in the current library. |
| library_.AddClass(signature_class); |
| } else if (is_new_closure) { |
| @@ -7820,7 +7865,7 @@ |
| type_arguments = current_class().type_parameters(); |
| } |
| Type& type = Type::ZoneHandle( |
| - Type::New(current_class(), type_arguments, type_pos)); |
| + Type::New(current_class(), type_arguments, type_pos)); |
| if (!is_top_level_) { |
| type ^= ClassFinalizer::FinalizeType( |
| current_class(), type, ClassFinalizer::kCanonicalizeWellFormed); |