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

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

Issue 12779008: Mixins with Generics (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 function_name.ToCString(), 1177 function_name.ToCString(),
1178 class_name.ToCString(), 1178 class_name.ToCString(),
1179 function_name.ToCString(), 1179 function_name.ToCString(),
1180 super_class_name.ToCString()); 1180 super_class_name.ToCString());
1181 } 1181 }
1182 } 1182 }
1183 } 1183 }
1184 } 1184 }
1185 1185
1186 1186
1187 // Copy the type parameters of the super and mixin classes to the
1188 // mixin application class. Change type arguments of super type to
1189 // refer to the respecive type parameters of the mixin application
regis 2013/03/14 23:40:34 respective
hausner 2013/03/15 00:36:32 Done.
1190 // class.
1191 void ClassFinalizer::CloneTypeParameters(const Class& mixapp_class) {
1192 ASSERT(mixapp_class.NumTypeParameters() == 0);
1193
1194 const AbstractType& super_type =
1195 AbstractType::Handle(mixapp_class.super_type());
regis 2013/03/14 23:40:34 I would assert that the super type is not a MixinA
hausner 2013/03/15 00:36:32 Done.
1196 const Class& super_class = Class::Handle(super_type.type_class());
1197
1198 const Type& mixin_type = Type::Handle(mixapp_class.mixin());
1199 const Class& mixin_class = Class::Handle(mixin_type.type_class());
1200
1201 const int num_super_parameters = super_class.NumTypeParameters();
1202 const int num_mixin_parameters = mixin_class.NumTypeParameters();
1203 if ((num_super_parameters + num_mixin_parameters) == 0) {
1204 return;
1205 }
1206
1207 // First, clone the super class type parameters. Rename them so that
1208 // there can be no name conflict between the parameters of the super
1209 // class and the mixin class.
1210 const TypeArguments& cloned_type_params = TypeArguments::Handle(
1211 TypeArguments::New(num_super_parameters + num_mixin_parameters));
1212 TypeParameter& param = TypeParameter::Handle();
1213 TypeParameter& cloned_param = TypeParameter::Handle();
1214 String& param_name = String::Handle();
1215 AbstractType& param_bound = AbstractType::Handle();
1216 int cloned_index = 0;
1217 if (num_super_parameters > 0) {
1218 const TypeArguments& super_params =
1219 TypeArguments::Handle(super_class.type_parameters());
1220 const TypeArguments& super_type_args =
1221 TypeArguments::Handle(TypeArguments::New(num_super_parameters));
1222 for (int i = 0; i < num_super_parameters; i++) {
1223 param ^= super_params.TypeAt(i);
1224 param_name = param.name();
1225 param_bound = param.bound();
1226 // TODO(hausner): handle type bounds.
1227 if (!param_bound.IsObjectType()) {
1228 const Script& script = Script::Handle(mixapp_class.script());
1229 ReportError(script, param.token_pos(),
1230 "type parameter '%s': type bounds not yet"
1231 " implemented for mixins\n",
1232 param_name.ToCString());
1233 }
1234 param_name = String::Concat(param_name, Symbols::Backtick());
1235 param_name = Symbols::New(param_name);
1236 cloned_param = TypeParameter::New(mixapp_class,
1237 cloned_index,
1238 param_name,
1239 param_bound,
1240 param.token_pos());
1241 cloned_type_params.SetTypeAt(cloned_index, cloned_param);
1242 // Change the type arguments of the super type to refer to the
1243 // cloned type parameters of the mixin application class.
1244 super_type_args.SetTypeAt(cloned_index, cloned_param);
1245 cloned_index++;
1246 }
1247 ASSERT(super_type.IsType());
regis 2013/03/14 23:40:34 This may fail if the super type is a BoundedType.
hausner 2013/03/15 00:36:32 Added a todo that I need to handle BoundedType her
1248 Type::Cast(super_type).set_arguments(super_type_args);
1249 }
1250
1251 // Second, clone the type parameters of the mixin class.
1252 // We need to retain the parameter names of the mixin class
1253 // since the code that will be compiled in the context of the
1254 // mixin application class may refer to the type parameters
1255 // with that name.
1256 if (num_mixin_parameters > 0) {
1257 const TypeArguments& mixin_params =
1258 TypeArguments::Handle(mixin_class.type_parameters());
1259 for (int i = 0; i < num_mixin_parameters; i++) {
1260 param ^= mixin_params.TypeAt(i);
1261 param_name = param.name();
1262 param_bound = param.bound();
1263
1264 // TODO(hausner): handle type bounds.
1265 if (!param_bound.IsObjectType()) {
1266 const Script& script = Script::Handle(mixapp_class.script());
1267 ReportError(script, param.token_pos(),
1268 "type parameter '%s': type bounds not yet"
1269 " implemented for mixins\n",
1270 param_name.ToCString());
1271 }
1272 cloned_param = TypeParameter::New(mixapp_class,
1273 cloned_index,
1274 param_name,
1275 param_bound,
1276 param.token_pos());
1277 cloned_type_params.SetTypeAt(cloned_index, cloned_param);
1278 cloned_index++;
1279 }
1280 }
1281 mixapp_class.set_type_parameters(cloned_type_params);
1282 }
1283
1284
1187 void ClassFinalizer::ApplyMixin(const Class& cls) { 1285 void ClassFinalizer::ApplyMixin(const Class& cls) {
1188 const Type& mixin_type = Type::Handle(cls.mixin()); 1286 const Type& mixin_type = Type::Handle(cls.mixin());
1189 ASSERT(!mixin_type.IsNull()); 1287 ASSERT(!mixin_type.IsNull());
1190 ASSERT(mixin_type.HasResolvedTypeClass()); 1288 ASSERT(mixin_type.HasResolvedTypeClass());
1191 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); 1289 const Class& mixin_cls = Class::Handle(mixin_type.type_class());
1192 1290
1193 if (FLAG_trace_class_finalization) { 1291 if (FLAG_trace_class_finalization) {
1194 OS::Print("Applying mixin '%s' to '%s'\n", 1292 OS::Print("Applying mixin '%s' to '%s' at pos %"Pd"\n",
1195 String::Handle(mixin_cls.Name()).ToCString(), 1293 String::Handle(mixin_cls.Name()).ToCString(),
1196 cls.ToCString()); 1294 cls.ToCString(),
1295 cls.token_pos());
1197 } 1296 }
1198 1297
1199 // Check that the super class of the mixin class is extending 1298 // Check that the super class of the mixin class is extending
1200 // class Object. 1299 // class Object.
1201 const AbstractType& mixin_super_type = 1300 const AbstractType& mixin_super_type =
1202 AbstractType::Handle(mixin_cls.super_type()); 1301 AbstractType::Handle(mixin_cls.super_type());
1203 if (!mixin_super_type.IsObjectType()) { 1302 if (!mixin_super_type.IsObjectType()) {
1204 const Script& script = Script::Handle(cls.script()); 1303 const Script& script = Script::Handle(cls.script());
1205 const String& class_name = String::Handle(mixin_cls.Name()); 1304 const String& class_name = String::Handle(mixin_cls.Name());
1206 ReportError(script, cls.token_pos(), 1305 ReportError(script, cls.token_pos(),
1207 "mixin class %s must extend class Object", 1306 "mixin class %s must extend class Object",
1208 class_name.ToCString()); 1307 class_name.ToCString());
1209 } 1308 }
1210 1309
1211 // Copy the type parameters of the mixin class to the mixin 1310 // Copy type parameters to mixin application class.
1212 // application class. 1311 CloneTypeParameters(cls);
1213 const int num_type_parameters = mixin_cls.NumTypeParameters();
1214 if (num_type_parameters > 0) {
1215 ASSERT(cls.NumTypeParameters() == 0);
1216 const TypeArguments& type_params =
1217 TypeArguments::Handle(mixin_cls.type_parameters());
1218 const TypeArguments& cloned_type_params =
1219 TypeArguments::Handle(TypeArguments::New(num_type_parameters));
1220 ASSERT(!type_params.IsNull());
1221 TypeParameter& param = TypeParameter::Handle();
1222 TypeParameter& cloned_param = TypeParameter::Handle();
1223 String& param_name = String::Handle();
1224 AbstractType& param_bound = AbstractType::Handle();
1225 for (int i = 0; i < num_type_parameters; i++) {
1226 param ^= type_params.TypeAt(i);
1227 param_name = param.name();
1228 param_bound = param.bound();
1229 cloned_param = TypeParameter::New(
1230 cls, i, param_name, param_bound, param.token_pos());
1231 cloned_type_params.SetTypeAt(i, cloned_param);
1232 }
1233 cls.set_type_parameters(cloned_type_params);
1234 }
1235 1312
1236 const GrowableObjectArray& cloned_funcs = 1313 const GrowableObjectArray& cloned_funcs =
1237 GrowableObjectArray::Handle(GrowableObjectArray::New()); 1314 GrowableObjectArray::Handle(GrowableObjectArray::New());
1238 Array& functions = Array::Handle(); 1315 Array& functions = Array::Handle();
1239 Function& func = Function::Handle(); 1316 Function& func = Function::Handle();
1240 // The parser creates the mixin application class and adds just 1317 // The parser creates the mixin application class and adds just
1241 // one function, the implicit constructor. 1318 // one function, the implicit constructor.
1242 functions = cls.functions(); 1319 functions = cls.functions();
1243 ASSERT(functions.Length() == 1); 1320 ASSERT(functions.Length() == 1);
1244 func ^= functions.At(0); 1321 func ^= functions.At(0);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 const intptr_t num_fields = fields.Length(); 1354 const intptr_t num_fields = fields.Length();
1278 for (int i = 0; i < num_fields; i++) { 1355 for (int i = 0; i < num_fields; i++) {
1279 field ^= fields.At(i); 1356 field ^= fields.At(i);
1280 if (!field.is_static()) { 1357 if (!field.is_static()) {
1281 field = field.Clone(cls); 1358 field = field.Clone(cls);
1282 cloned_fields.Add(field); 1359 cloned_fields.Add(field);
1283 } 1360 }
1284 } 1361 }
1285 fields = Array::MakeArray(cloned_fields); 1362 fields = Array::MakeArray(cloned_fields);
1286 cls.SetFields(fields); 1363 cls.SetFields(fields);
1364
1365 if (FLAG_trace_class_finalization) {
1366 OS::Print("done mixin appl %s %s extending %s\n",
1367 String::Handle(cls.Name()).ToCString(),
1368 TypeArguments::Handle(cls.type_parameters()).ToCString(),
1369 AbstractType::Handle(cls.super_type()).ToCString());
1370 }
1287 } 1371 }
1288 1372
1289 1373
1290 void ClassFinalizer::FinalizeClass(const Class& cls) { 1374 void ClassFinalizer::FinalizeClass(const Class& cls) {
1291 if (cls.is_finalized()) { 1375 if (cls.is_finalized()) {
1292 return; 1376 return;
1293 } 1377 }
1294 if (FLAG_trace_class_finalization) { 1378 if (FLAG_trace_class_finalization) {
1295 OS::Print("Finalize %s\n", cls.ToCString()); 1379 OS::Print("Finalize %s\n", cls.ToCString());
1296 } 1380 }
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1444 !IsAliasCycleFree(type_class, visited)) { 1528 !IsAliasCycleFree(type_class, visited)) {
1445 return false; 1529 return false;
1446 } 1530 }
1447 } 1531 }
1448 } 1532 }
1449 visited->RemoveLast(); 1533 visited->RemoveLast();
1450 return true; 1534 return true;
1451 } 1535 }
1452 1536
1453 1537
1538 void ClassFinalizer::CopyArgs(const Class& cls,
regis 2013/03/14 23:40:34 I would pick more meaningful names. What args are
hausner 2013/03/15 00:36:32 Done.
1539 const Type& type,
1540 const GrowableObjectArray& args) {
1541 ASSERT(type.HasResolvedTypeClass());
1542 Class& type_class = Class::Handle(type.type_class());
1543 AbstractTypeArguments& type_args =
1544 AbstractTypeArguments::Handle(type.arguments());
1545 intptr_t num_type_parameters = type_class.NumTypeParameters();
1546 intptr_t num_type_arguments = type_args.IsNull() ? 0 : type_args.Length();
1547 AbstractType& arg = AbstractType::Handle();
1548 if (num_type_arguments > 0) {
1549 if (num_type_arguments != num_type_parameters) {
1550 const Script& script = Script::Handle(cls.script());
1551 const String& type_class_name = String::Handle(type_class.Name());
1552 ReportError(script, type.token_pos(),
1553 "wrong number of type arguments for class '%s'",
1554 type_class_name.ToCString());
1555 }
1556 for (int i = 0; i < num_type_arguments; i++) {
1557 arg = type_args.TypeAt(i);
1558 args.Add(arg);
1559 }
1560 } else {
1561 // Fill arguments with type dynamic.
1562 for (int i = 0; i < num_type_parameters; i++) {
1563 arg = Type::DynamicType();
1564 args.Add(arg);
1565 }
1566 }
1567 }
1568
1569
1570 RawType* ClassFinalizer::ResolveMixinAppType(const Class& cls,
1571 const MixinAppType& mixin_app) {
1572 // Resolve super type and all mixin types.
1573 const GrowableObjectArray& type_args =
1574 GrowableObjectArray::Handle(GrowableObjectArray::New());
1575 AbstractType& type = AbstractType::Handle(mixin_app.super_type());
1576 ResolveType(cls, type, kCanonicalizeWellFormed);
1577 ASSERT(type.HasResolvedTypeClass());
1578 ASSERT(type.IsType());
regis 2013/03/14 23:40:34 Not necessarily. It could be a BoundedType. Add a
hausner 2013/03/15 00:36:32 Same reasoning as above: the parser does not put a
1579 CopyArgs(cls, Type::Cast(type), type_args);
1580 const Array& mixins = Array::Handle(mixin_app.mixin_types());
1581 for (int i = 0; i < mixins.Length(); i++) {
1582 type ^= mixins.At(i);
1583 ASSERT(type.HasResolvedTypeClass()); // Newly created class in parser.
1584 const Class& mixin_app_class = Class::Handle(type.type_class());
1585 type = mixin_app_class.mixin();
1586 ASSERT(!type.IsNull());
1587 ResolveType(cls, type, kCanonicalizeWellFormed);
1588 ASSERT(type.HasResolvedTypeClass());
1589 ASSERT(type.IsType());
1590 CopyArgs(cls, Type::Cast(type), type_args);
1591 }
1592 const TypeArguments& mixin_app_args =
1593 TypeArguments::Handle(TypeArguments::New(type_args.Length()));
1594 for (int i = 0; i < type_args.Length(); i++) {
1595 type ^= type_args.At(i);
1596 mixin_app_args.SetTypeAt(i, type);
1597 }
1598 if (FLAG_trace_class_finalization) {
1599 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n",
1600 mixin_app_args.ToCString());
1601 }
1602 type ^= mixins.At(mixins.Length() - 1);
regis 2013/03/14 23:40:34 Can you explain in a comment that the last type in
hausner 2013/03/15 00:36:32 Actually, all elements in the mixins array are mix
1603 const Class& resolved_mixin_app_class = Class::Handle(type.type_class());
1604 Type& resolved_mixin_app_type = Type::Handle();
1605 resolved_mixin_app_type = Type::New(resolved_mixin_app_class,
1606 mixin_app_args,
1607 mixin_app.token_pos());
1608 return resolved_mixin_app_type.raw();
1609 }
1610
1611
1454 // Recursively walks the graph of explicitly declared super type and 1612 // Recursively walks the graph of explicitly declared super type and
1455 // interfaces, resolving unresolved super types and interfaces. 1613 // interfaces, resolving unresolved super types and interfaces.
1456 // Reports an error if there is an interface reference that cannot be 1614 // Reports an error if there is an interface reference that cannot be
1457 // resolved, or if there is a cycle in the graph. We detect cycles by 1615 // resolved, or if there is a cycle in the graph. We detect cycles by
1458 // remembering interfaces we've visited in each path through the 1616 // remembering interfaces we've visited in each path through the
1459 // graph. If we visit an interface a second time on a given path, 1617 // graph. If we visit an interface a second time on a given path,
1460 // we found a loop. 1618 // we found a loop.
1461 void ClassFinalizer::ResolveSuperTypeAndInterfaces( 1619 void ClassFinalizer::ResolveSuperTypeAndInterfaces(
1462 const Class& cls, GrowableArray<intptr_t>* visited) { 1620 const Class& cls, GrowableArray<intptr_t>* visited) {
1463 ASSERT(visited != NULL); 1621 ASSERT(visited != NULL);
1464 const intptr_t cls_index = cls.id(); 1622 const intptr_t cls_index = cls.id();
1465 for (int i = 0; i < visited->length(); i++) { 1623 for (int i = 0; i < visited->length(); i++) {
1466 if ((*visited)[i] == cls_index) { 1624 if ((*visited)[i] == cls_index) {
1467 // We have already visited class 'cls'. We found a cycle. 1625 // We have already visited class 'cls'. We found a cycle.
1468 const String& class_name = String::Handle(cls.Name()); 1626 const String& class_name = String::Handle(cls.Name());
1469 const Script& script = Script::Handle(cls.script()); 1627 const Script& script = Script::Handle(cls.script());
1470 ReportError(script, cls.token_pos(), 1628 ReportError(script, cls.token_pos(),
1471 "cyclic reference found for class '%s'", 1629 "cyclic reference found for class '%s'",
1472 class_name.ToCString()); 1630 class_name.ToCString());
1473 } 1631 }
1474 } 1632 }
1475 1633
1476 // If the class/interface has no explicit super class/interfaces 1634 // If the class/interface has no explicit super class/interfaces
1477 // and is not a mixin application, we are done. 1635 // and is not a mixin application, we are done.
1478 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 1636 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1479 Type& mixin_type = Type::Handle(cls.mixin());
1480 Array& super_interfaces = Array::Handle(cls.interfaces()); 1637 Array& super_interfaces = Array::Handle(cls.interfaces());
1481 if ((super_type.IsNull() || super_type.IsObjectType()) && 1638 if ((super_type.IsNull() || super_type.IsObjectType()) &&
1482 (super_interfaces.Length() == 0) && 1639 (super_interfaces.Length() == 0)) {
1483 (mixin_type.IsNull())) {
1484 return; 1640 return;
1485 } 1641 }
1486 1642
1487 if (!mixin_type.IsNull()) { 1643 if (super_type.IsMixinAppType()) {
1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); 1644 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type);
1645 super_type = ResolveMixinAppType(cls, mixin_app_type);
1646 cls.set_super_type(super_type);
1489 } 1647 }
1490 1648
1491 // If cls belongs to core lib, restrictions about allowed interfaces 1649 // If cls belongs to core lib, restrictions about allowed interfaces
1492 // are lifted. 1650 // are lifted.
1493 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); 1651 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary();
1494 1652
1495 // Resolve and check the super type and interfaces of cls. 1653 // Resolve and check the super type and interfaces of cls.
1496 visited->Add(cls_index); 1654 visited->Add(cls_index);
1497 AbstractType& interface = AbstractType::Handle(); 1655 AbstractType& interface = AbstractType::Handle();
1498 Class& interface_class = Class::Handle(); 1656 Class& interface_class = Class::Handle();
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 void ClassFinalizer::ReportError(const char* format, ...) { 1952 void ClassFinalizer::ReportError(const char* format, ...) {
1795 va_list args; 1953 va_list args;
1796 va_start(args, format); 1954 va_start(args, format);
1797 const Error& error = Error::Handle( 1955 const Error& error = Error::Handle(
1798 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1956 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1799 va_end(args); 1957 va_end(args);
1800 ReportError(error); 1958 ReportError(error);
1801 } 1959 }
1802 1960
1803 } // namespace dart 1961 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698