Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
| (...skipping 2929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2940 ErrorMsg(classname_pos, "'%s' is already defined", | 2940 ErrorMsg(classname_pos, "'%s' is already defined", |
| 2941 class_name.ToCString()); | 2941 class_name.ToCString()); |
| 2942 } | 2942 } |
| 2943 cls ^= obj.raw(); | 2943 cls ^= obj.raw(); |
| 2944 if (cls.is_interface()) { | 2944 if (cls.is_interface()) { |
| 2945 ErrorMsg(classname_pos, "'%s' %s", | 2945 ErrorMsg(classname_pos, "'%s' %s", |
| 2946 class_name.ToCString(), | 2946 class_name.ToCString(), |
| 2947 is_patch ? | 2947 is_patch ? |
| 2948 "is already defined as interface" : | 2948 "is already defined as interface" : |
| 2949 "interface cannot be patched"); | 2949 "interface cannot be patched"); |
| 2950 } else if (!is_patch && (cls.functions() != Object::empty_array())) { | |
| 2951 ErrorMsg(classname_pos, "class '%s' is already defined", | |
|
hausner
2012/08/15 16:39:27
Where is this duplicate class definition detected
| |
| 2952 class_name.ToCString()); | |
| 2953 } else if (is_patch) { | 2950 } else if (is_patch) { |
| 2954 String& patch = String::Handle(Symbols::New("patch ")); | 2951 String& patch = String::Handle(Symbols::New("patch ")); |
| 2955 patch = String::Concat(patch, class_name); | 2952 patch = String::Concat(patch, class_name); |
| 2956 patch = Symbols::New(patch); | 2953 patch = Symbols::New(patch); |
| 2957 cls = Class::New(patch, script_, classname_pos); | 2954 cls = Class::New(patch, script_, classname_pos); |
| 2958 } else { | 2955 } else { |
| 2959 // Not patching a class, but it has been found. This must be one of the | 2956 // Not patching a class, but it has been found. This must be one of the |
| 2960 // pre-registered classes from object.cc or a duplicate definition. | 2957 // pre-registered classes from object.cc or a duplicate definition. |
| 2961 if (cls.functions() != Object::empty_array()) { | 2958 if (cls.functions() != Object::empty_array()) { |
| 2962 ErrorMsg(classname_pos, "class '%s' is already defined", | 2959 ErrorMsg(classname_pos, "class '%s' is already defined", |
|
Ivan Posva
2012/08/15 16:42:33
Right here.
hausner
2012/08/15 17:01:09
Ah right, where it was before patch support. Thank
| |
| 2963 class_name.ToCString()); | 2960 class_name.ToCString()); |
| 2964 } | 2961 } |
| 2965 // Pre-registered classes need their scripts connected at this time. | 2962 // Pre-registered classes need their scripts connected at this time. |
| 2966 cls.set_script(script_); | 2963 cls.set_script(script_); |
| 2967 } | 2964 } |
| 2968 } | 2965 } |
| 2969 ASSERT(!cls.IsNull()); | 2966 ASSERT(!cls.IsNull()); |
| 2970 ASSERT(cls.functions() == Object::empty_array()); | 2967 ASSERT(cls.functions() == Object::empty_array()); |
| 2971 set_current_class(cls); | 2968 set_current_class(cls); |
| 2972 ParseTypeParameters(cls); | 2969 ParseTypeParameters(cls); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 3003 AddInterfaces(interfaces_pos, cls, interfaces); | 3000 AddInterfaces(interfaces_pos, cls, interfaces); |
| 3004 } | 3001 } |
| 3005 | 3002 |
| 3006 ExpectToken(Token::kLBRACE); | 3003 ExpectToken(Token::kLBRACE); |
| 3007 ClassDesc members(cls, class_name, false, class_pos); | 3004 ClassDesc members(cls, class_name, false, class_pos); |
| 3008 while (CurrentToken() != Token::kRBRACE) { | 3005 while (CurrentToken() != Token::kRBRACE) { |
| 3009 ParseClassMemberDefinition(&members); | 3006 ParseClassMemberDefinition(&members); |
| 3010 } | 3007 } |
| 3011 ExpectToken(Token::kRBRACE); | 3008 ExpectToken(Token::kRBRACE); |
| 3012 | 3009 |
| 3013 if (!is_patch) { | 3010 // Add an implicit constructor if no explicit constructor is present. No |
| 3014 // Do not install implicit constructors. | 3011 // implicit constructors are needed for patch classes. |
| 3015 CheckConstructors(&members); | 3012 if (!members.has_constructor() && !is_patch) { |
| 3013 AddImplicitConstructor(&members); | |
| 3016 } | 3014 } |
| 3015 CheckConstructorCycles(&members); | |
| 3017 | 3016 |
| 3018 Array& array = Array::Handle(); | 3017 Array& array = Array::Handle(); |
| 3019 array = Array::MakeArray(members.fields()); | 3018 array = Array::MakeArray(members.fields()); |
| 3020 cls.SetFields(array); | 3019 cls.SetFields(array); |
| 3021 | 3020 |
| 3022 // Creating a new array for functions marks the class as parsed. | 3021 // Creating a new array for functions marks the class as parsed. |
| 3023 array = Array::MakeArray(members.functions()); | 3022 array = Array::MakeArray(members.functions()); |
| 3024 cls.SetFunctions(array); | 3023 cls.SetFunctions(array); |
| 3025 | 3024 |
| 3026 if (!is_patch) { | 3025 if (!is_patch) { |
| 3027 pending_classes.Add(cls, Heap::kOld); | 3026 pending_classes.Add(cls, Heap::kOld); |
| 3028 } else { | 3027 } else { |
| 3029 // Lookup the patched class and apply the changes. | 3028 // Lookup the patched class and apply the changes. |
| 3030 obj = library_.LookupObject(class_name); | 3029 obj = library_.LookupObject(class_name); |
| 3031 Class::Cast(obj).ApplyPatch(cls); | 3030 Class::Cast(obj).ApplyPatch(cls); |
| 3032 } | 3031 } |
| 3033 } | 3032 } |
| 3034 | 3033 |
| 3035 | 3034 |
| 3036 // 1. Add an implicit constructor if no explicit constructor is present. | 3035 // Add an implicit constructor if no explicit constructor is present. |
| 3037 // 2. Check for cycles in constructor redirection. | 3036 void Parser::AddImplicitConstructor(ClassDesc* class_desc) { |
| 3038 void Parser::CheckConstructors(ClassDesc* class_desc) { | 3037 // The implicit constructor is unnamed, has no explicit parameter, |
| 3039 // Add an implicit constructor if no explicit constructor is present. | 3038 // and contains a supercall in the initializer list. |
| 3040 if (!class_desc->has_constructor()) { | 3039 String& ctor_name = String::ZoneHandle( |
| 3041 // The implicit constructor is unnamed, has no explicit parameter, | 3040 String::Concat(class_desc->class_name(), String::Handle(Symbols::Dot()))); |
| 3042 // and contains a supercall in the initializer list. | 3041 ctor_name = Symbols::New(ctor_name); |
| 3043 String& ctor_name = String::ZoneHandle( | 3042 // The token position for the implicit constructor is the 'class' |
| 3044 String::Concat(class_desc->class_name(), | 3043 // keyword of the constructor's class. |
| 3045 String::Handle(Symbols::Dot()))); | 3044 Function& ctor = Function::Handle( |
| 3046 ctor_name = Symbols::New(ctor_name); | 3045 Function::New(ctor_name, |
| 3047 // The token position for the implicit constructor is the 'class' | 3046 RawFunction::kConstructor, |
| 3048 // keyword of the constructor's class. | 3047 /* is_static = */ false, |
| 3049 Function& ctor = Function::Handle( | 3048 /* is_const = */ false, |
| 3050 Function::New(ctor_name, | 3049 /* is_abstract = */ false, |
| 3051 RawFunction::kConstructor, | 3050 /* is_external = */ false, |
| 3052 /* is_static = */ false, | 3051 current_class(), |
| 3053 /* is_const = */ false, | 3052 class_desc->token_pos())); |
| 3054 /* is_abstract = */ false, | 3053 ParamList params; |
| 3055 /* is_external = */ false, | 3054 // Add implicit 'this' parameter. |
| 3056 current_class(), | 3055 ASSERT(current_class().raw() == ctor.Owner()); |
| 3057 class_desc->token_pos())); | 3056 params.AddReceiver(ReceiverType(TokenPos())); |
| 3058 ParamList params; | 3057 // Add implicit parameter for construction phase. |
| 3059 // Add implicit 'this' parameter. | 3058 params.AddFinalParameter( |
| 3060 ASSERT(current_class().raw() == ctor.Owner()); | 3059 TokenPos(), |
|
Mads Ager (google)
2012/08/15 07:21:24
Move this argument to the line above or use 4-spac
Ivan Posva
2012/08/15 07:28:23
Done.
| |
| 3061 params.AddReceiver(ReceiverType(TokenPos())); | 3060 &String::ZoneHandle(Symbols::PhaseParameter()), |
| 3062 // Add implicit parameter for construction phase. | 3061 &Type::ZoneHandle(Type::IntInterface())); |
| 3063 params.AddFinalParameter( | |
| 3064 TokenPos(), | |
| 3065 &String::ZoneHandle(Symbols::PhaseParameter()), | |
| 3066 &Type::ZoneHandle(Type::IntInterface())); | |
| 3067 | 3062 |
| 3068 AddFormalParamsToFunction(¶ms, ctor); | 3063 AddFormalParamsToFunction(¶ms, ctor); |
| 3069 // The body of the constructor cannot modify the type of the constructed | 3064 // The body of the constructor cannot modify the type of the constructed |
| 3070 // instance, which is passed in as the receiver. | 3065 // instance, which is passed in as the receiver. |
| 3071 ctor.set_result_type(*((*params.parameters)[0].type)); | 3066 ctor.set_result_type(*((*params.parameters)[0].type)); |
| 3072 class_desc->AddFunction(ctor); | 3067 class_desc->AddFunction(ctor); |
| 3073 } | 3068 } |
| 3074 | 3069 |
| 3070 | |
| 3071 // Check for cycles in constructor redirection. | |
| 3072 void Parser::CheckConstructorCycles(ClassDesc* class_desc) { | |
| 3075 // Check for cycles in constructor redirection. | 3073 // Check for cycles in constructor redirection. |
| 3076 const GrowableArray<MemberDesc>& members = class_desc->members(); | 3074 const GrowableArray<MemberDesc>& members = class_desc->members(); |
| 3077 for (int i = 0; i < members.length(); i++) { | 3075 for (int i = 0; i < members.length(); i++) { |
| 3078 MemberDesc* member = &members[i]; | 3076 MemberDesc* member = &members[i]; |
| 3079 GrowableArray<MemberDesc*> ctors; | 3077 GrowableArray<MemberDesc*> ctors; |
| 3080 while ((member != NULL) && (member->redirect_name != NULL)) { | 3078 while ((member != NULL) && (member->redirect_name != NULL)) { |
| 3081 ASSERT(member->IsConstructor()); | 3079 ASSERT(member->IsConstructor()); |
| 3082 // Check whether we have already seen this member. | 3080 // Check whether we have already seen this member. |
| 3083 for (int i = 0; i < ctors.length(); i++) { | 3081 for (int i = 0; i < ctors.length(); i++) { |
| 3084 if (ctors[i] == member) { | 3082 if (ctors[i] == member) { |
| (...skipping 5997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9082 void Parser::SkipQualIdent() { | 9080 void Parser::SkipQualIdent() { |
| 9083 ASSERT(IsIdentifier()); | 9081 ASSERT(IsIdentifier()); |
| 9084 ConsumeToken(); | 9082 ConsumeToken(); |
| 9085 if (CurrentToken() == Token::kPERIOD) { | 9083 if (CurrentToken() == Token::kPERIOD) { |
| 9086 ConsumeToken(); // Consume the kPERIOD token. | 9084 ConsumeToken(); // Consume the kPERIOD token. |
| 9087 ExpectIdentifier("identifier expected after '.'"); | 9085 ExpectIdentifier("identifier expected after '.'"); |
| 9088 } | 9086 } |
| 9089 } | 9087 } |
| 9090 | 9088 |
| 9091 } // namespace dart | 9089 } // namespace dart |
| OLD | NEW |