Chromium Code Reviews| Index: runtime/vm/class_finalizer.cc |
| =================================================================== |
| --- runtime/vm/class_finalizer.cc (revision 18363) |
| +++ runtime/vm/class_finalizer.cc (working copy) |
| @@ -1245,6 +1245,61 @@ |
| } |
| +void ClassFinalizer::ApplyMixin(const Class& cls, const Type& mixin) { |
| + ASSERT(mixin.HasResolvedTypeClass()); |
| + const Class& mixin_cls = Class::Handle(mixin.type_class()); |
| + |
| + // Check that the super class of the mixin class is extending |
| + // class Object. |
| + const Type& mixin_super_type = Type::Handle(mixin_cls.super_type()); |
| + ResolveType(mixin_cls, mixin_super_type, kCanonicalizeWellFormed); |
| + if (!mixin_super_type.IsObjectType()) { |
| + const Script& script = Script::Handle(cls.script()); |
| + const String& class_name = String::Handle(mixin_cls.Name()); |
| + ReportError(script, cls.token_pos(), |
|
siva
2013/02/13 01:34:37
I am wondering if it would be more helpful if you
hausner
2013/02/13 19:58:14
I thought it makes more sense to report it where t
|
| + "mixin class %s must extend class Object", |
| + class_name.ToCString()); |
| + } |
| + |
| + const Array& functions = Array::Handle(mixin_cls.functions()); |
| + Function& func = Function::Handle(); |
| + const intptr_t num_functions = functions.Length(); |
| + for (int i = 0; i < num_functions; i++) { |
| + func ^= functions.At(i); |
| + if (func.IsConstructor()) { |
| + // A mixin class must not have explicit constructors. |
| + if (!func.IsImplicitConstructor()) { |
| + const Script& script = Script::Handle(cls.script()); |
| + ReportError(script, cls.token_pos(), |
|
siva
2013/02/13 01:34:37
Ditto.
hausner
2013/02/13 19:58:14
Ditto.
|
| + "mixin class %s must not have constructors\n", |
| + String::Handle(mixin_cls.Name()).ToCString()); |
| + } |
| + continue; // Skip the implicit constructor. |
| + } |
| + // TODO(hausner): must check whether the function contains |
| + // super calls. If so, report error. |
| + if (!func.is_static()) { |
| + func = func.Clone(cls); |
| + cls.AddFunction(func); |
|
siva
2013/02/13 01:34:37
Our AddFunction implementation is very inefficient
hausner
2013/02/13 19:58:14
I agree with what you suggest, but let me check it
|
| + } |
| + } |
| + Array& fields = Array::Handle(mixin_cls.fields()); |
| + Field& field = Field::Handle(); |
| + const GrowableObjectArray& cloned_fields = |
| + GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| + const intptr_t num_fields = fields.Length(); |
| + for (int i = 0; i < num_fields; i++) { |
| + field ^= fields.At(i); |
| + if (!field.is_static()) { |
| + field = field.Clone(cls); |
| + cloned_fields.Add(field); |
| + } |
| + } |
| + fields = Array::MakeArray(cloned_fields); |
|
siva
2013/02/13 01:34:37
Maybe we should assert here that
ASSERT(cls.fields
hausner
2013/02/13 19:58:14
Done.
|
| + cls.SetFields(fields); |
| +} |
| + |
| + |
| // Recursively walks the graph of explicitly declared super type and |
| // interfaces, resolving unresolved super types and interfaces. |
| // Reports an error if there is an interface reference that cannot be |
| @@ -1267,16 +1322,24 @@ |
| } |
| } |
| - // If the class/interface has no explicit super class/interfaces, we are done. |
| + // If the class/interface has no explicit super class/interfaces |
| + // and is not a mixin application, we are done. |
| Type& super_type = Type::Handle(cls.super_type()); |
| + Type& mixin_type = Type::Handle(cls.mixin()); |
| Array& super_interfaces = Array::Handle(cls.interfaces()); |
| if ((super_type.IsNull() || super_type.IsObjectType()) && |
| - (super_interfaces.Length() == 0)) { |
| + (super_interfaces.Length() == 0) && |
| + (mixin_type.IsNull())) { |
| return; |
| } |
| - // If cls belongs to core lib or to core lib's implementation, restrictions |
| - // about allowed interfaces are lifted. |
| + if (!mixin_type.IsNull()) { |
| + ResolveType(cls, mixin_type, kCanonicalizeWellFormed); |
| + ApplyMixin(cls, mixin_type); |
| + } |
| + |
| + // If cls belongs to core lib, restrictions about allowed interfaces |
| + // are lifted. |
| const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); |
| // Resolve and check the super type and interfaces of cls. |
| @@ -1287,7 +1350,6 @@ |
| // Resolve super type. Failures lead to a longjmp. |
| ResolveType(cls, super_type, kCanonicalizeWellFormed); |
| - // If cls belongs to core lib or to core lib's implementation, restrictions |
| interface_class = super_type.type_class(); |
| // If cls belongs to core lib or to core lib's implementation, restrictions |
| // about allowed interfaces are lifted. |