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

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
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 respective type parameters of the mixin application
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());
1196 ASSERT(super_type.IsResolved());
1197 const Class& super_class = Class::Handle(super_type.type_class());
1198 const Type& mixin_type = Type::Handle(mixapp_class.mixin());
1199 const Class& mixin_class = Class::Handle(mixin_type.type_class());
1200 const int num_super_parameters = super_class.NumTypeParameters();
1201 const int num_mixin_parameters = mixin_class.NumTypeParameters();
1202 if ((num_super_parameters + num_mixin_parameters) == 0) {
1203 return;
1204 }
1205
1206 // First, clone the super class type parameters. Rename them so that
1207 // there can be no name conflict between the parameters of the super
1208 // class and the mixin class.
1209 const TypeArguments& cloned_type_params = TypeArguments::Handle(
1210 TypeArguments::New(num_super_parameters + num_mixin_parameters));
1211 TypeParameter& param = TypeParameter::Handle();
1212 TypeParameter& cloned_param = TypeParameter::Handle();
1213 String& param_name = String::Handle();
1214 AbstractType& param_bound = AbstractType::Handle();
1215 int cloned_index = 0;
1216 if (num_super_parameters > 0) {
1217 const TypeArguments& super_params =
1218 TypeArguments::Handle(super_class.type_parameters());
1219 const TypeArguments& super_type_args =
1220 TypeArguments::Handle(TypeArguments::New(num_super_parameters));
1221 for (int i = 0; i < num_super_parameters; i++) {
1222 param ^= super_params.TypeAt(i);
1223 param_name = param.name();
1224 param_bound = param.bound();
1225 // TODO(hausner): handle type bounds.
1226 if (!param_bound.IsObjectType()) {
1227 const Script& script = Script::Handle(mixapp_class.script());
1228 ReportError(script, param.token_pos(),
1229 "type parameter '%s': type bounds not yet"
1230 " implemented for mixins\n",
1231 param_name.ToCString());
1232 }
1233 param_name = String::Concat(param_name, Symbols::Backtick());
1234 param_name = Symbols::New(param_name);
1235 cloned_param = TypeParameter::New(mixapp_class,
1236 cloned_index,
1237 param_name,
1238 param_bound,
1239 param.token_pos());
1240 cloned_type_params.SetTypeAt(cloned_index, cloned_param);
1241 // Change the type arguments of the super type to refer to the
1242 // cloned type parameters of the mixin application class.
1243 super_type_args.SetTypeAt(cloned_index, cloned_param);
1244 cloned_index++;
1245 }
1246 // TODO(hausner): May need to handle BoundedType here.
1247 ASSERT(super_type.IsType());
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::CollectTypeArguments(const Class& cls,
1539 const Type& type,
1540 const GrowableObjectArray& collected_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 collected_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 collected_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 // TODO(hausner): May need to handle BoundedType here.
1579 ASSERT(type.IsType());
1580 CollectTypeArguments(cls, Type::Cast(type), type_args);
1581 const Array& mixins = Array::Handle(mixin_app.mixin_types());
1582 for (int i = 0; i < mixins.Length(); i++) {
1583 type ^= mixins.At(i);
1584 ASSERT(type.HasResolvedTypeClass()); // Newly created class in parser.
1585 const Class& mixin_app_class = Class::Handle(type.type_class());
1586 type = mixin_app_class.mixin();
1587 ASSERT(!type.IsNull());
1588 ResolveType(cls, type, kCanonicalizeWellFormed);
1589 ASSERT(type.HasResolvedTypeClass());
1590 ASSERT(type.IsType());
1591 CollectTypeArguments(cls, Type::Cast(type), type_args);
1592 }
1593 const TypeArguments& mixin_app_args =
1594 TypeArguments::Handle(TypeArguments::New(type_args.Length()));
1595 for (int i = 0; i < type_args.Length(); i++) {
1596 type ^= type_args.At(i);
1597 mixin_app_args.SetTypeAt(i, type);
1598 }
1599 if (FLAG_trace_class_finalization) {
1600 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n",
1601 mixin_app_args.ToCString());
1602 }
1603 // The last element in the mixins array is the lowest mixin application
1604 // type in the mixin chain. Build a new super type with its type class
1605 // and the collected type arguments from the super type and all
1606 // mixin types. This super type replaces the MixinAppType object
1607 // in the class that extends the mixin application.
1608 type ^= mixins.At(mixins.Length() - 1);
1609 const Class& resolved_mixin_app_class = Class::Handle(type.type_class());
1610 Type& resolved_mixin_app_type = Type::Handle();
1611 resolved_mixin_app_type = Type::New(resolved_mixin_app_class,
1612 mixin_app_args,
1613 mixin_app.token_pos());
1614 return resolved_mixin_app_type.raw();
1615 }
1616
1617
1454 // Recursively walks the graph of explicitly declared super type and 1618 // Recursively walks the graph of explicitly declared super type and
1455 // interfaces, resolving unresolved super types and interfaces. 1619 // interfaces, resolving unresolved super types and interfaces.
1456 // Reports an error if there is an interface reference that cannot be 1620 // 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 1621 // 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 1622 // remembering interfaces we've visited in each path through the
1459 // graph. If we visit an interface a second time on a given path, 1623 // graph. If we visit an interface a second time on a given path,
1460 // we found a loop. 1624 // we found a loop.
1461 void ClassFinalizer::ResolveSuperTypeAndInterfaces( 1625 void ClassFinalizer::ResolveSuperTypeAndInterfaces(
1462 const Class& cls, GrowableArray<intptr_t>* visited) { 1626 const Class& cls, GrowableArray<intptr_t>* visited) {
1463 ASSERT(visited != NULL); 1627 ASSERT(visited != NULL);
1464 const intptr_t cls_index = cls.id(); 1628 const intptr_t cls_index = cls.id();
1465 for (int i = 0; i < visited->length(); i++) { 1629 for (int i = 0; i < visited->length(); i++) {
1466 if ((*visited)[i] == cls_index) { 1630 if ((*visited)[i] == cls_index) {
1467 // We have already visited class 'cls'. We found a cycle. 1631 // We have already visited class 'cls'. We found a cycle.
1468 const String& class_name = String::Handle(cls.Name()); 1632 const String& class_name = String::Handle(cls.Name());
1469 const Script& script = Script::Handle(cls.script()); 1633 const Script& script = Script::Handle(cls.script());
1470 ReportError(script, cls.token_pos(), 1634 ReportError(script, cls.token_pos(),
1471 "cyclic reference found for class '%s'", 1635 "cyclic reference found for class '%s'",
1472 class_name.ToCString()); 1636 class_name.ToCString());
1473 } 1637 }
1474 } 1638 }
1475 1639
1476 // If the class/interface has no explicit super class/interfaces 1640 // If the class/interface has no explicit super class/interfaces
1477 // and is not a mixin application, we are done. 1641 // and is not a mixin application, we are done.
1478 AbstractType& super_type = AbstractType::Handle(cls.super_type()); 1642 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1479 Type& mixin_type = Type::Handle(cls.mixin());
1480 Array& super_interfaces = Array::Handle(cls.interfaces()); 1643 Array& super_interfaces = Array::Handle(cls.interfaces());
1481 if ((super_type.IsNull() || super_type.IsObjectType()) && 1644 if ((super_type.IsNull() || super_type.IsObjectType()) &&
1482 (super_interfaces.Length() == 0) && 1645 (super_interfaces.Length() == 0)) {
1483 (mixin_type.IsNull())) {
1484 return; 1646 return;
1485 } 1647 }
1486 1648
1487 if (!mixin_type.IsNull()) { 1649 if (super_type.IsMixinAppType()) {
1488 ResolveType(cls, mixin_type, kCanonicalizeWellFormed); 1650 const MixinAppType& mixin_app_type = MixinAppType::Cast(super_type);
1651 super_type = ResolveMixinAppType(cls, mixin_app_type);
1652 cls.set_super_type(super_type);
1489 } 1653 }
1490 1654
1491 // If cls belongs to core lib, restrictions about allowed interfaces 1655 // If cls belongs to core lib, restrictions about allowed interfaces
1492 // are lifted. 1656 // are lifted.
1493 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary(); 1657 const bool cls_belongs_to_core_lib = cls.library() == Library::CoreLibrary();
1494 1658
1495 // Resolve and check the super type and interfaces of cls. 1659 // Resolve and check the super type and interfaces of cls.
1496 visited->Add(cls_index); 1660 visited->Add(cls_index);
1497 AbstractType& interface = AbstractType::Handle(); 1661 AbstractType& interface = AbstractType::Handle();
1498 Class& interface_class = Class::Handle(); 1662 Class& interface_class = Class::Handle();
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 void ClassFinalizer::ReportError(const char* format, ...) { 1958 void ClassFinalizer::ReportError(const char* format, ...) {
1795 va_list args; 1959 va_list args;
1796 va_start(args, format); 1960 va_start(args, format);
1797 const Error& error = Error::Handle( 1961 const Error& error = Error::Handle(
1798 Parser::FormatError(Script::Handle(), -1, "Error", format, args)); 1962 Parser::FormatError(Script::Handle(), -1, "Error", format, args));
1799 va_end(args); 1963 va_end(args);
1800 ReportError(error); 1964 ReportError(error);
1801 } 1965 }
1802 1966
1803 } // namespace dart 1967 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698