Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 } | 288 } |
| 289 | 289 |
| 290 | 290 |
| 291 void ClassFinalizer::ResolveRedirectingFactoryTarget( | 291 void ClassFinalizer::ResolveRedirectingFactoryTarget( |
| 292 const Class& cls, | 292 const Class& cls, |
| 293 const Function& factory, | 293 const Function& factory, |
| 294 const GrowableObjectArray& visited_factories) { | 294 const GrowableObjectArray& visited_factories) { |
| 295 ASSERT(factory.IsRedirectingFactory()); | 295 ASSERT(factory.IsRedirectingFactory()); |
| 296 | 296 |
| 297 // Check for redirection cycle. | 297 // Check for redirection cycle. |
| 298 for (int i = 0; i < visited_factories.Length(); i++) { | 298 for (intptr_t i = 0; i < visited_factories.Length(); i++) { |
| 299 if (visited_factories.At(i) == factory.raw()) { | 299 if (visited_factories.At(i) == factory.raw()) { |
| 300 // A redirection cycle is reported as a compile-time error. | 300 // A redirection cycle is reported as a compile-time error. |
| 301 const Script& script = Script::Handle(cls.script()); | 301 const Script& script = Script::Handle(cls.script()); |
| 302 ReportError(Error::Handle(), // No previous error. | 302 ReportError(Error::Handle(), // No previous error. |
| 303 script, factory.token_pos(), | 303 script, factory.token_pos(), |
| 304 "factory '%s' illegally redirects to itself", | 304 "factory '%s' illegally redirects to itself", |
| 305 String::Handle(factory.name()).ToCString()); | 305 String::Handle(factory.name()).ToCString()); |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 visited_factories.Add(factory); | 308 visited_factories.Add(factory); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 ResolveType(cls, type_argument, finalization); | 499 ResolveType(cls, type_argument, finalization); |
| 500 } | 500 } |
| 501 } | 501 } |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { | 505 void ClassFinalizer::FinalizeTypeParameters(const Class& cls) { |
| 506 if (cls.IsMixinApplication()) { | 506 if (cls.IsMixinApplication()) { |
| 507 // Copy the type parameters to the mixin application. | 507 // Copy the type parameters to the mixin application. |
| 508 ApplyMixinType(cls); | 508 ApplyMixinType(cls); |
| 509 // Finalize the mixin type. | |
| 510 Type& mixin_type = Type::Handle(cls.mixin()); | |
| 511 mixin_type ^= FinalizeType(cls, mixin_type, kCanonicalizeWellFormed); | |
| 512 // TODO(regis): Check for a malbounded mixin_type. | |
| 513 cls.set_mixin(mixin_type); | |
| 509 } | 514 } |
| 510 // The type parameter bounds are not finalized here. | 515 // The type parameter bounds are not finalized here. |
| 511 const TypeArguments& type_parameters = | 516 const TypeArguments& type_parameters = |
| 512 TypeArguments::Handle(cls.type_parameters()); | 517 TypeArguments::Handle(cls.type_parameters()); |
| 513 if (!type_parameters.IsNull()) { | 518 if (!type_parameters.IsNull()) { |
| 514 TypeParameter& type_parameter = TypeParameter::Handle(); | 519 TypeParameter& type_parameter = TypeParameter::Handle(); |
| 515 const intptr_t num_types = type_parameters.Length(); | 520 const intptr_t num_types = type_parameters.Length(); |
| 516 for (intptr_t i = 0; i < num_types; i++) { | 521 for (intptr_t i = 0; i < num_types; i++) { |
| 517 type_parameter ^= type_parameters.TypeAt(i); | 522 type_parameter ^= type_parameters.TypeAt(i); |
| 518 type_parameter ^= FinalizeType(cls, | 523 type_parameter ^= FinalizeType(cls, |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1194 Function& overridden_function = Function::Handle(); | 1199 Function& overridden_function = Function::Handle(); |
| 1195 const intptr_t num_functions = array.Length(); | 1200 const intptr_t num_functions = array.Length(); |
| 1196 Error& error = Error::Handle(); | 1201 Error& error = Error::Handle(); |
| 1197 for (intptr_t i = 0; i < num_functions; i++) { | 1202 for (intptr_t i = 0; i < num_functions; i++) { |
| 1198 function ^= array.At(i); | 1203 function ^= array.At(i); |
| 1199 ResolveAndFinalizeSignature(cls, function); | 1204 ResolveAndFinalizeSignature(cls, function); |
| 1200 name = function.name(); | 1205 name = function.name(); |
| 1201 if (FLAG_error_on_bad_override && // Report signature conflicts only. | 1206 if (FLAG_error_on_bad_override && // Report signature conflicts only. |
| 1202 !function.is_static() && !function.IsConstructor()) { | 1207 !function.is_static() && !function.IsConstructor()) { |
| 1203 // A constructor cannot override anything. | 1208 // A constructor cannot override anything. |
| 1204 for (int i = 0; i < interfaces.Length(); i++) { | 1209 for (intptr_t i = 0; i < interfaces.Length(); i++) { |
| 1205 super_class ^= interfaces.At(i); | 1210 super_class ^= interfaces.At(i); |
| 1206 overridden_function = super_class.LookupDynamicFunction(name); | 1211 overridden_function = super_class.LookupDynamicFunction(name); |
| 1207 if (!overridden_function.IsNull() && | 1212 if (!overridden_function.IsNull() && |
| 1208 !function.HasCompatibleParametersWith(overridden_function, | 1213 !function.HasCompatibleParametersWith(overridden_function, |
| 1209 &error)) { | 1214 &error)) { |
| 1210 const String& class_name = String::Handle(cls.Name()); | 1215 const String& class_name = String::Handle(cls.Name()); |
| 1211 const String& super_class_name = String::Handle(super_class.Name()); | 1216 const String& super_class_name = String::Handle(super_class.Name()); |
| 1212 const Script& script = Script::Handle(cls.script()); | 1217 const Script& script = Script::Handle(cls.script()); |
| 1213 ReportError(error, script, function.token_pos(), | 1218 ReportError(error, script, function.token_pos(), |
| 1214 "class '%s' overrides method '%s' of super class '%s' " | 1219 "class '%s' overrides method '%s' of super class '%s' " |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1299 } | 1304 } |
| 1300 } | 1305 } |
| 1301 } | 1306 } |
| 1302 } | 1307 } |
| 1303 | 1308 |
| 1304 | 1309 |
| 1305 // Copy the type parameters of the super and mixin classes to the | 1310 // Copy the type parameters of the super and mixin classes to the |
| 1306 // mixin application class. Change type arguments of super type and of | 1311 // mixin application class. Change type arguments of super type and of |
| 1307 // interfaces to refer to the respective type parameters of the mixin | 1312 // interfaces to refer to the respective type parameters of the mixin |
| 1308 // application class. | 1313 // application class. |
| 1309 void ClassFinalizer::CloneTypeParameters(const Class& mixin_app_class) { | 1314 void ClassFinalizer::CloneMixinAppTypeParameters(const Class& mixin_app_class) { |
| 1310 ASSERT(mixin_app_class.type_parameters() == AbstractTypeArguments::null()); | 1315 ASSERT(mixin_app_class.type_parameters() == AbstractTypeArguments::null()); |
| 1311 | 1316 const AbstractType& super_type = AbstractType::Handle( |
| 1312 const AbstractType& super_type = | 1317 mixin_app_class.super_type()); |
| 1313 AbstractType::Handle(mixin_app_class.super_type()); | |
| 1314 ASSERT(super_type.IsResolved()); | 1318 ASSERT(super_type.IsResolved()); |
| 1315 const Class& super_class = Class::Handle(super_type.type_class()); | 1319 const Class& super_class = Class::Handle(super_type.type_class()); |
| 1320 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | |
| 1316 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); | 1321 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); |
| 1317 const Class& mixin_class = Class::Handle(mixin_type.type_class()); | 1322 const Class& mixin_class = Class::Handle(mixin_type.type_class()); |
| 1318 const int num_super_parameters = super_class.NumTypeParameters(); | 1323 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); |
| 1319 const int num_mixin_parameters = mixin_class.NumTypeParameters(); | 1324 // The mixin class cannot be Object and this was checked earlier. |
| 1320 if ((num_super_parameters + num_mixin_parameters) == 0) { | 1325 ASSERT(!mixin_class.IsObjectClass()); |
| 1321 return; | 1326 |
| 1322 } | 1327 // Add the mixin type to the interfaces that the mixin application |
| 1323 | 1328 // class implements. This is necessary so that type tests work. |
| 1324 // First, clone the super class type parameters. Rename them so that | 1329 const Array& interfaces = Array::Handle(Array::New(1)); |
| 1325 // there can be no name conflict between the parameters of the super | 1330 const Type& interface = Type::Handle(Type::New( |
| 1326 // class and the mixin class. | 1331 mixin_class, |
| 1327 const TypeArguments& cloned_type_params = TypeArguments::Handle( | 1332 Object::null_abstract_type_arguments(), // Set again below if generic. |
| 1328 TypeArguments::New(num_super_parameters + num_mixin_parameters)); | 1333 mixin_app_class.token_pos())); |
| 1329 TypeParameter& param = TypeParameter::Handle(); | 1334 ASSERT(!interface.IsFinalized()); |
| 1330 TypeParameter& cloned_param = TypeParameter::Handle(); | 1335 interfaces.SetAt(0, interface); |
| 1331 String& param_name = String::Handle(); | 1336 mixin_app_class.set_interfaces(interfaces); |
| 1332 AbstractType& param_bound = AbstractType::Handle(); | 1337 |
| 1333 int cloned_index = 0; | 1338 // If both the super type and the mixin type are non generic, the mixin |
| 1334 if (num_super_parameters > 0) { | 1339 // application class is non generic as well and we can skip type parameter |
| 1335 const TypeArguments& super_params = | 1340 // cloning. |
| 1336 TypeArguments::Handle(super_class.type_parameters()); | 1341 if ((num_super_type_params + num_mixin_type_params) > 0) { |
| 1337 const TypeArguments& super_type_args = | 1342 // First, clone the super class type parameters. Rename them so that |
| 1338 TypeArguments::Handle(TypeArguments::New(num_super_parameters)); | 1343 // there can be no name conflict between the parameters of the super |
| 1339 for (int i = 0; i < num_super_parameters; i++) { | 1344 // class and the mixin class. |
| 1340 param ^= super_params.TypeAt(i); | 1345 const TypeArguments& cloned_type_params = TypeArguments::Handle( |
| 1341 param_name = param.name(); | 1346 TypeArguments::New(num_super_type_params + num_mixin_type_params)); |
| 1342 param_bound = param.bound(); | 1347 TypeParameter& param = TypeParameter::Handle(); |
| 1343 // TODO(hausner): handle type bounds. | 1348 TypeParameter& cloned_param = TypeParameter::Handle(); |
| 1344 if (!param_bound.IsObjectType()) { | 1349 String& param_name = String::Handle(); |
| 1345 const Script& script = Script::Handle(mixin_app_class.script()); | 1350 AbstractType& param_bound = AbstractType::Handle(); |
| 1346 ReportError(Error::Handle(), // No previous error. | 1351 intptr_t cloned_index = 0; |
| 1347 script, param.token_pos(), | 1352 if (num_super_type_params > 0) { |
| 1348 "type parameter '%s': type bounds not yet" | 1353 const TypeArguments& super_type_params = |
| 1349 " implemented for mixins\n", | 1354 TypeArguments::Handle(super_class.type_parameters()); |
| 1350 param_name.ToCString()); | 1355 const TypeArguments& super_type_args = |
| 1356 TypeArguments::Handle(TypeArguments::New(num_super_type_params)); | |
| 1357 for (intptr_t i = 0; i < num_super_type_params; i++) { | |
| 1358 param ^= super_type_params.TypeAt(i); | |
| 1359 param_name = param.name(); | |
| 1360 param_bound = param.bound(); | |
| 1361 // TODO(hausner): handle type bounds. | |
| 1362 if (!param_bound.IsObjectType()) { | |
| 1363 const Script& script = Script::Handle(mixin_app_class.script()); | |
| 1364 ReportError(Error::Handle(), // No previous error. | |
| 1365 script, param.token_pos(), | |
| 1366 "type parameter '%s': type bounds not yet" | |
| 1367 " implemented for mixins\n", | |
| 1368 param_name.ToCString()); | |
| 1369 } | |
| 1370 param_name = String::Concat(param_name, Symbols::Backtick()); | |
| 1371 param_name = Symbols::New(param_name); | |
| 1372 cloned_param = TypeParameter::New(mixin_app_class, | |
| 1373 cloned_index, | |
| 1374 param_name, | |
| 1375 param_bound, | |
| 1376 param.token_pos()); | |
| 1377 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | |
| 1378 // Change the type arguments of the super type to refer to the | |
| 1379 // cloned type parameters of the mixin application class. | |
| 1380 super_type_args.SetTypeAt(cloned_index, cloned_param); | |
| 1381 cloned_index++; | |
| 1351 } | 1382 } |
| 1352 param_name = String::Concat(param_name, Symbols::Backtick()); | 1383 // TODO(hausner): May need to handle BoundedType here. |
| 1353 param_name = Symbols::New(param_name); | 1384 ASSERT(super_type.IsType()); |
| 1354 cloned_param = TypeParameter::New(mixin_app_class, | 1385 Type::Cast(super_type).set_arguments(super_type_args); |
| 1355 cloned_index, | 1386 ASSERT(!super_type.IsFinalized()); |
| 1356 param_name, | 1387 } |
| 1357 param_bound, | 1388 |
| 1358 param.token_pos()); | 1389 // Second, clone the type parameters of the mixin class. |
| 1359 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1390 // We need to retain the parameter names of the mixin class |
| 1360 // Change the type arguments of the super type to refer to the | 1391 // since the code that will be compiled in the context of the |
| 1361 // cloned type parameters of the mixin application class. | 1392 // mixin application class may refer to the type parameters |
| 1362 super_type_args.SetTypeAt(cloned_index, cloned_param); | 1393 // with that name. |
| 1363 cloned_index++; | 1394 if (num_mixin_type_params > 0) { |
| 1364 } | 1395 const TypeArguments& mixin_params = |
| 1365 // TODO(hausner): May need to handle BoundedType here. | 1396 TypeArguments::Handle(mixin_class.type_parameters()); |
| 1366 ASSERT(super_type.IsType()); | 1397 const TypeArguments& interface_type_args = TypeArguments::Handle( |
| 1367 Type::Cast(super_type).set_arguments(super_type_args); | 1398 TypeArguments::New(num_mixin_type_params)); |
| 1368 ASSERT(!super_type.IsFinalized()); | 1399 for (intptr_t i = 0; i < num_mixin_type_params; i++) { |
| 1369 } | 1400 param ^= mixin_params.TypeAt(i); |
| 1370 | 1401 param_name = param.name(); |
| 1371 // Second, clone the type parameters of the mixin class. | 1402 param_bound = param.bound(); |
| 1372 // We need to retain the parameter names of the mixin class | 1403 |
| 1373 // since the code that will be compiled in the context of the | 1404 // TODO(hausner): handle type bounds. |
| 1374 // mixin application class may refer to the type parameters | 1405 if (!param_bound.IsObjectType()) { |
| 1375 // with that name. | 1406 const Script& script = Script::Handle(mixin_app_class.script()); |
| 1376 if (num_mixin_parameters > 0) { | 1407 ReportError(Error::Handle(), // No previous error. |
| 1377 const TypeArguments& mixin_params = | 1408 script, param.token_pos(), |
| 1378 TypeArguments::Handle(mixin_class.type_parameters()); | 1409 "type parameter '%s': type bounds not yet" |
| 1379 const TypeArguments& interface_type_args = TypeArguments::Handle( | 1410 " implemented for mixins\n", |
| 1380 TypeArguments::New(num_mixin_parameters)); | 1411 param_name.ToCString()); |
| 1381 for (int i = 0; i < num_mixin_parameters; i++) { | 1412 } |
| 1382 param ^= mixin_params.TypeAt(i); | 1413 cloned_param = TypeParameter::New(mixin_app_class, |
| 1383 param_name = param.name(); | 1414 cloned_index, |
| 1384 param_bound = param.bound(); | 1415 param_name, |
| 1385 | 1416 param_bound, |
| 1386 // TODO(hausner): handle type bounds. | 1417 param.token_pos()); |
| 1387 if (!param_bound.IsObjectType()) { | 1418 cloned_type_params.SetTypeAt(cloned_index, cloned_param); |
| 1388 const Script& script = Script::Handle(mixin_app_class.script()); | 1419 interface_type_args.SetTypeAt(i, cloned_param); |
| 1389 ReportError(Error::Handle(), // No previous error. | 1420 cloned_index++; |
| 1390 script, param.token_pos(), | |
| 1391 "type parameter '%s': type bounds not yet" | |
| 1392 " implemented for mixins\n", | |
| 1393 param_name.ToCString()); | |
| 1394 } | 1421 } |
| 1395 cloned_param = TypeParameter::New(mixin_app_class, | 1422 |
| 1396 cloned_index, | 1423 // Lastly, set the type arguments of the single interface type. |
| 1397 param_name, | 1424 ASSERT(!interface.IsFinalized()); |
| 1398 param_bound, | 1425 interface.set_arguments(interface_type_args); |
| 1399 param.token_pos()); | 1426 } |
| 1400 cloned_type_params.SetTypeAt(cloned_index, cloned_param); | 1427 mixin_app_class.set_type_parameters(cloned_type_params); |
| 1401 interface_type_args.SetTypeAt(i, cloned_param); | 1428 } |
| 1402 cloned_index++; | 1429 // If the mixin class is a mixin application typedef class, we insert a new |
| 1403 } | 1430 // synthesized mixin application class in the super chain of this mixin |
| 1404 | 1431 // application class. The new class will have the aliased mixin as actual |
| 1405 // Lastly, change the type arguments of the single interface type to | 1432 // mixin. |
| 1406 // refer to the cloned type parameters of the mixin application class. | 1433 if (mixin_class.is_mixin_typedef()) { |
| 1407 Array& interface_types = Array::Handle(mixin_app_class.interfaces()); | 1434 ApplyMixinTypedef(mixin_app_class); |
| 1408 ASSERT(interface_types.Length() == 1); | 1435 } |
| 1409 AbstractType& interface_type = AbstractType::Handle(); | |
| 1410 interface_type ^= interface_types.At(0); | |
| 1411 ASSERT(interface_type.IsResolved()); | |
| 1412 // TODO(hausner): May need to handle BoundedType here. | |
| 1413 ASSERT(interface_type.IsType()); | |
| 1414 Type::Cast(interface_type).set_arguments(interface_type_args); | |
| 1415 ASSERT(!interface_type.IsFinalized()); | |
| 1416 } | |
| 1417 mixin_app_class.set_type_parameters(cloned_type_params); | |
| 1418 } | 1436 } |
| 1419 | 1437 |
| 1420 | 1438 |
| 1439 void ClassFinalizer::ApplyMixinTypedef(const Class& mixin_app_class) { | |
| 1440 // If this mixin typedef is aliasing another mixin typedef, another class | |
| 1441 // will be inserted via recursion. No need to check here. | |
| 1442 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); | |
| 1443 const Class& mixin_class = Class::Handle(mixin_type.type_class()); | |
| 1444 ASSERT(mixin_class.is_mixin_typedef()); | |
| 1445 const Class& aliased_mixin_app_class = Class::Handle( | |
| 1446 mixin_class.SuperClass()); | |
| 1447 const Type& aliased_mixin_type = Type::Handle( | |
| 1448 aliased_mixin_app_class.mixin()); | |
| 1449 // The name of the inserted mixin application class is the name of mixin | |
| 1450 // class name with a backtick added. | |
| 1451 String& inserted_class_name = String::Handle(mixin_app_class.Name()); | |
| 1452 inserted_class_name = String::Concat(inserted_class_name, | |
| 1453 Symbols::Backtick()); | |
| 1454 inserted_class_name = Symbols::New(inserted_class_name); | |
| 1455 const Script& script = Script::Handle(mixin_app_class.script()); | |
| 1456 const Library& library = Library::Handle(mixin_app_class.library()); | |
| 1457 const Class& inserted_class = Class::Handle(Class::New( | |
| 1458 inserted_class_name, script, mixin_app_class.token_pos())); | |
| 1459 inserted_class.set_library(library); | |
| 1460 inserted_class.set_is_synthesized_class(); | |
| 1461 | |
| 1462 // The super type of the inserted class is identical to the super type of | |
| 1463 // this mixin application class, except that it must refer to the type | |
| 1464 // parameters of the inserted class rather than to those of the mixin | |
| 1465 // application class. | |
| 1466 // The type arguments of the super type will be set properly when calling | |
| 1467 // CloneMixinAppTypeParameters on the inserted class, as long as the super | |
| 1468 // type class is set properly. | |
| 1469 AbstractType& super_type = AbstractType::Handle(mixin_app_class.super_type()); | |
| 1470 inserted_class.set_super_type(super_type); // Super class only is used. | |
| 1471 | |
| 1472 // The mixin type must also be set before calling CloneMixinAppTypeParameters. | |
| 1473 // It refers to the type parameters of the mixin class typedef. | |
| 1474 inserted_class.set_mixin(aliased_mixin_type); // Mixin class only is used. | |
| 1475 | |
| 1476 // Finalize the types and call CloneMixinAppTypeParameters. | |
| 1477 FinalizeTypesInClass(inserted_class); | |
| 1478 | |
| 1479 // The super type of this mixin application class must point to the | |
|
hausner
2013/09/24 00:15:35
It might be helpful to have an example similar to
regis
2013/09/24 00:23:42
I will add a description in the next cl.
| |
| 1480 // inserted class. The super type arguments are the concatenation of the | |
| 1481 // old super type arguments (propagating type arguments to the super class) | |
| 1482 // with new type arguments providing type arguments to the mixin. | |
| 1483 // The appended type arguments are those of the aliased mixin type, except | |
| 1484 // that they must refer to the type parameters of the mixin application | |
| 1485 // class rather than to those of the aliased mixin class. | |
| 1486 // This type parameter substitution is performed by an instantiation step. | |
| 1487 // It is important that the type parameters of the mixin application class | |
| 1488 // are not finalized yet, because new type parameters may have been added | |
| 1489 // to the super class. | |
| 1490 Class& super_class = Class::Handle(super_type.type_class()); | |
| 1491 ASSERT(mixin_app_class.SuperClass() == super_class.raw()); | |
| 1492 while (super_class.IsMixinApplication()) { | |
| 1493 super_class = super_class.SuperClass(); | |
| 1494 } | |
| 1495 const intptr_t num_super_type_params = super_class.NumTypeParameters(); | |
| 1496 const intptr_t num_mixin_type_params = mixin_class.NumTypeParameters(); | |
| 1497 intptr_t offset = aliased_mixin_app_class.NumTypeArguments(); | |
| 1498 const TypeArguments& type_params = | |
| 1499 TypeArguments::Handle(mixin_app_class.type_parameters()); | |
| 1500 TypeArguments& instantiator = TypeArguments::Handle( | |
| 1501 TypeArguments::New(offset + num_mixin_type_params)); | |
| 1502 AbstractType& type = AbstractType::Handle(); | |
| 1503 for (intptr_t i = 0; i < num_mixin_type_params; i++) { | |
| 1504 type = type_params.TypeAt(num_super_type_params + i); | |
| 1505 instantiator.SetTypeAt(offset + i, type); | |
| 1506 } | |
| 1507 ASSERT(aliased_mixin_type.IsFinalized()); | |
| 1508 const Class& aliased_mixin_type_class = Class::Handle( | |
| 1509 aliased_mixin_type.type_class()); | |
| 1510 const intptr_t num_aliased_mixin_type_params = | |
| 1511 aliased_mixin_type_class.NumTypeParameters(); | |
| 1512 const intptr_t num_aliased_mixin_type_args = | |
| 1513 aliased_mixin_type_class.NumTypeArguments(); | |
| 1514 offset = num_aliased_mixin_type_args - num_aliased_mixin_type_params; | |
| 1515 ASSERT(inserted_class.NumTypeParameters() == | |
| 1516 (num_super_type_params + num_aliased_mixin_type_params)); | |
| 1517 // The aliased_mixin_type may be raw. | |
| 1518 const AbstractTypeArguments& aliased_mixin_type_args = | |
| 1519 AbstractTypeArguments::Handle(aliased_mixin_type.arguments()); | |
| 1520 TypeArguments& new_mixin_type_args = TypeArguments::Handle(); | |
| 1521 if ((num_aliased_mixin_type_params > 0) && | |
| 1522 !aliased_mixin_type_args.IsNull()) { | |
| 1523 new_mixin_type_args = TypeArguments::New(num_aliased_mixin_type_params); | |
| 1524 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { | |
| 1525 type = aliased_mixin_type_args.TypeAt(offset + i); | |
| 1526 new_mixin_type_args.SetTypeAt(i, type); | |
| 1527 } | |
| 1528 } | |
| 1529 if (!new_mixin_type_args.IsNull() && | |
| 1530 !new_mixin_type_args.IsInstantiated()) { | |
| 1531 Error& bound_error = Error::Handle(); | |
| 1532 new_mixin_type_args ^= | |
| 1533 new_mixin_type_args.InstantiateFrom(instantiator, &bound_error); | |
| 1534 // TODO(regis): Handle bound error. | |
| 1535 ASSERT(bound_error.IsNull()); | |
| 1536 } | |
| 1537 TypeArguments& new_super_type_args = TypeArguments::Handle(); | |
| 1538 if ((num_super_type_params + num_aliased_mixin_type_params) > 0) { | |
| 1539 new_super_type_args = TypeArguments::New(num_super_type_params + | |
| 1540 num_aliased_mixin_type_params); | |
| 1541 for (intptr_t i = 0; i < num_super_type_params; i++) { | |
| 1542 type = type_params.TypeAt(i); | |
| 1543 new_super_type_args.SetTypeAt(i, type); | |
| 1544 } | |
| 1545 for (intptr_t i = 0; i < num_aliased_mixin_type_params; i++) { | |
| 1546 if (new_mixin_type_args.IsNull()) { | |
| 1547 type = Type::DynamicType(); | |
| 1548 } else { | |
| 1549 type = new_mixin_type_args.TypeAt(i); | |
| 1550 } | |
| 1551 new_super_type_args.SetTypeAt(num_super_type_params + i, type); | |
| 1552 } | |
| 1553 } | |
| 1554 super_type = Type::New(inserted_class, | |
| 1555 new_super_type_args, | |
| 1556 mixin_app_class.token_pos()); | |
| 1557 mixin_app_class.set_super_type(super_type); | |
| 1558 // Mark this mixin application class as being a typedef. | |
| 1559 mixin_app_class.set_is_mixin_typedef(); | |
| 1560 ASSERT(!mixin_app_class.is_type_finalized()); | |
| 1561 if (FLAG_trace_class_finalization) { | |
| 1562 OS::Print("Inserting class %s to mixin typedef application %s " | |
| 1563 "with super type '%s'\n", | |
| 1564 inserted_class.ToCString(), | |
| 1565 mixin_app_class.ToCString(), | |
| 1566 String::Handle(super_type.Name()).ToCString()); | |
| 1567 } | |
| 1568 } | |
| 1569 | |
| 1570 | |
| 1421 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class) { | 1571 void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class) { |
| 1422 if (mixin_app_class.is_mixin_type_applied()) { | 1572 if (mixin_app_class.is_mixin_type_applied()) { |
| 1423 return; | 1573 return; |
| 1424 } | 1574 } |
| 1425 const Type& mixin_type = Type::Handle(mixin_app_class.mixin()); | 1575 Type& mixin_type = Type::Handle(mixin_app_class.mixin()); |
| 1426 ASSERT(!mixin_type.IsNull()); | 1576 ASSERT(!mixin_type.IsNull()); |
| 1427 ASSERT(mixin_type.HasResolvedTypeClass()); | 1577 ASSERT(mixin_type.HasResolvedTypeClass()); |
| 1428 const Class& mixin_cls = Class::Handle(mixin_type.type_class()); | 1578 const Class& mixin_class = Class::Handle(mixin_type.type_class()); |
| 1579 if (mixin_class.IsNullClass()) { | |
|
hausner
2013/09/24 00:15:35
As discussed offline, we probably have to check fo
regis
2013/09/24 00:23:42
Yes, good point. Let me address this in the next c
| |
| 1580 const Script& script = Script::Handle(mixin_app_class.script()); | |
| 1581 ReportError(Error::Handle(), // No previous error. | |
| 1582 script, mixin_app_class.token_pos(), | |
| 1583 "illegal mixin of 'Null'"); | |
| 1584 } | |
| 1585 // Check for illegal self references. | |
| 1586 GrowableArray<intptr_t> visited_mixins; | |
| 1587 if (!IsMixinCycleFree(mixin_class, &visited_mixins)) { | |
| 1588 const Script& script = Script::Handle(mixin_class.script()); | |
| 1589 const String& class_name = String::Handle(mixin_class.Name()); | |
| 1590 ReportError(Error::Handle(), // No previous error. | |
| 1591 script, mixin_class.token_pos(), | |
| 1592 "mixin class '%s' illegally refers to itself", | |
| 1593 class_name.ToCString()); | |
| 1594 } | |
| 1429 | 1595 |
| 1430 if (FLAG_trace_class_finalization) { | 1596 if (FLAG_trace_class_finalization) { |
| 1431 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n", | 1597 OS::Print("Applying mixin type '%s' to %s at pos %" Pd "\n", |
| 1432 String::Handle(mixin_type.Name()).ToCString(), | 1598 String::Handle(mixin_type.Name()).ToCString(), |
| 1433 mixin_app_class.ToCString(), | 1599 mixin_app_class.ToCString(), |
| 1434 mixin_app_class.token_pos()); | 1600 mixin_app_class.token_pos()); |
| 1435 } | 1601 } |
| 1436 | 1602 |
| 1437 // Check that the super class of the mixin class is extending | 1603 // Check that the super class of the mixin class is class Object. |
| 1438 // class Object. | 1604 Class& mixin_super_class = Class::Handle(mixin_class.SuperClass()); |
| 1439 const AbstractType& mixin_super_type = | 1605 // Skip over mixin application typedef classes, which are aliases (but are |
| 1440 AbstractType::Handle(mixin_cls.super_type()); | 1606 // implemented as subclasses) of the mixin application classes they name. |
| 1441 if (!mixin_super_type.IsObjectType()) { | 1607 if (!mixin_super_class.IsNull() && mixin_class.is_mixin_typedef()) { |
| 1608 while (mixin_super_class.is_mixin_typedef()) { | |
| 1609 mixin_super_class = mixin_super_class.SuperClass(); | |
| 1610 } | |
| 1611 mixin_super_class = mixin_super_class.SuperClass(); | |
| 1612 } | |
| 1613 if (mixin_super_class.IsNull() || !mixin_super_class.IsObjectClass()) { | |
| 1442 const Script& script = Script::Handle(mixin_app_class.script()); | 1614 const Script& script = Script::Handle(mixin_app_class.script()); |
| 1443 const String& class_name = String::Handle(mixin_cls.Name()); | 1615 const String& class_name = String::Handle(mixin_class.Name()); |
| 1444 ReportError(Error::Handle(), // No previous error. | 1616 ReportError(Error::Handle(), // No previous error. |
| 1445 script, mixin_app_class.token_pos(), | 1617 script, mixin_app_class.token_pos(), |
| 1446 "mixin class '%s' must extend class Object", | 1618 "mixin class '%s' must extend class 'Object'", |
| 1447 class_name.ToCString()); | 1619 class_name.ToCString()); |
| 1448 } | 1620 } |
| 1449 | 1621 |
| 1450 // Copy type parameters to mixin application class. | 1622 // Copy type parameters to mixin application class. |
| 1451 CloneTypeParameters(mixin_app_class); | 1623 CloneMixinAppTypeParameters(mixin_app_class); |
| 1452 | 1624 |
| 1453 if (FLAG_trace_class_finalization) { | 1625 if (FLAG_trace_class_finalization) { |
| 1454 OS::Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n", | 1626 OS::Print("Done applying mixin type '%s' to class '%s' %s extending '%s'\n", |
| 1455 String::Handle(mixin_type.Name()).ToCString(), | 1627 String::Handle(mixin_type.Name()).ToCString(), |
| 1456 String::Handle(mixin_app_class.Name()).ToCString(), | 1628 String::Handle(mixin_app_class.Name()).ToCString(), |
| 1457 TypeArguments::Handle( | 1629 TypeArguments::Handle( |
| 1458 mixin_app_class.type_parameters()).ToCString(), | 1630 mixin_app_class.type_parameters()).ToCString(), |
| 1459 AbstractType::Handle(mixin_app_class.super_type()).ToCString()); | 1631 AbstractType::Handle(mixin_app_class.super_type()).ToCString()); |
| 1460 } | 1632 } |
| 1461 mixin_app_class.set_is_mixin_type_applied(); | 1633 mixin_app_class.set_is_mixin_type_applied(); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1491 false, // Not abstract. | 1663 false, // Not abstract. |
| 1492 false, // Not external. | 1664 false, // Not external. |
| 1493 mixin_app, | 1665 mixin_app, |
| 1494 mixin_app.token_pos())); | 1666 mixin_app.token_pos())); |
| 1495 | 1667 |
| 1496 clone.set_num_fixed_parameters(func.num_fixed_parameters()); | 1668 clone.set_num_fixed_parameters(func.num_fixed_parameters()); |
| 1497 clone.SetNumOptionalParameters(func.NumOptionalParameters(), | 1669 clone.SetNumOptionalParameters(func.NumOptionalParameters(), |
| 1498 func.HasOptionalPositionalParameters()); | 1670 func.HasOptionalPositionalParameters()); |
| 1499 clone.set_result_type(dynamic_type); | 1671 clone.set_result_type(dynamic_type); |
| 1500 | 1672 |
| 1501 const int num_parameters = func.NumParameters(); | 1673 const intptr_t num_parameters = func.NumParameters(); |
| 1502 // The cloned ctor shares the parameter names array with the | 1674 // The cloned ctor shares the parameter names array with the |
| 1503 // original. | 1675 // original. |
| 1504 const Array& parameter_names = Array::Handle(func.parameter_names()); | 1676 const Array& parameter_names = Array::Handle(func.parameter_names()); |
| 1505 ASSERT(parameter_names.Length() == num_parameters); | 1677 ASSERT(parameter_names.Length() == num_parameters); |
| 1506 clone.set_parameter_names(parameter_names); | 1678 clone.set_parameter_names(parameter_names); |
| 1507 // The parameter types of the cloned constructor are 'dynamic'. | 1679 // The parameter types of the cloned constructor are 'dynamic'. |
| 1508 clone.set_parameter_types(Array::Handle(Array::New(num_parameters))); | 1680 clone.set_parameter_types(Array::Handle(Array::New(num_parameters))); |
| 1509 for (intptr_t n = 0; n < num_parameters; n++) { | 1681 for (intptr_t n = 0; n < num_parameters; n++) { |
| 1510 clone.SetParameterTypeAt(n, dynamic_type); | 1682 clone.SetParameterTypeAt(n, dynamic_type); |
| 1511 } | 1683 } |
| 1512 cloned_funcs.Add(clone); | 1684 cloned_funcs.Add(clone); |
| 1513 } | 1685 } |
| 1514 } | 1686 } |
| 1515 } | 1687 } |
| 1516 | 1688 |
| 1517 | 1689 |
| 1518 void ClassFinalizer::ApplyMixinMembers(const Class& cls) { | 1690 void ClassFinalizer::ApplyMixinMembers(const Class& cls) { |
| 1519 Isolate* isolate = Isolate::Current(); | 1691 Isolate* isolate = Isolate::Current(); |
| 1520 const Type& mixin_type = Type::Handle(isolate, cls.mixin()); | 1692 const Type& mixin_type = Type::Handle(isolate, cls.mixin()); |
| 1521 ASSERT(!mixin_type.IsNull()); | 1693 ASSERT(!mixin_type.IsNull()); |
| 1522 ASSERT(mixin_type.HasResolvedTypeClass()); | 1694 ASSERT(mixin_type.HasResolvedTypeClass()); |
| 1523 const Class& mixin_cls = Class::Handle(isolate, mixin_type.type_class()); | 1695 const Class& mixin_cls = Class::Handle(isolate, mixin_type.type_class()); |
| 1524 mixin_cls.EnsureIsFinalized(isolate); | 1696 mixin_cls.EnsureIsFinalized(isolate); |
| 1697 // If the mixin is a mixin application typedef class, there are no members to | |
| 1698 // apply here. A new synthesized class representing the aliased mixin | |
| 1699 // application class was inserted in the super chain of this mixin application | |
| 1700 // class. Members of the actual mixin class will be applied when visiting | |
| 1701 // the mixin application class referring to the actual mixin. | |
| 1702 ASSERT(!mixin_cls.is_mixin_typedef() || | |
| 1703 Class::Handle(isolate, cls.SuperClass()).IsMixinApplication()); | |
| 1704 // A default constructor will be created for the typedef class. | |
| 1525 | 1705 |
| 1526 if (FLAG_trace_class_finalization) { | 1706 if (FLAG_trace_class_finalization) { |
| 1527 OS::Print("Applying mixin members of %s to %s at pos %" Pd "\n", | 1707 OS::Print("Applying mixin members of %s to %s at pos %" Pd "\n", |
| 1528 mixin_cls.ToCString(), | 1708 mixin_cls.ToCString(), |
| 1529 cls.ToCString(), | 1709 cls.ToCString(), |
| 1530 cls.token_pos()); | 1710 cls.token_pos()); |
| 1531 } | 1711 } |
| 1532 | 1712 |
| 1533 const GrowableObjectArray& cloned_funcs = | 1713 const GrowableObjectArray& cloned_funcs = |
| 1534 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); | 1714 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 1535 | 1715 |
| 1536 CreateForwardingConstructors(cls, cloned_funcs); | 1716 CreateForwardingConstructors(cls, cloned_funcs); |
| 1537 | 1717 |
| 1538 Array& functions = Array::Handle(isolate); | 1718 Array& functions = Array::Handle(isolate); |
| 1539 Function& func = Function::Handle(isolate); | 1719 Function& func = Function::Handle(isolate); |
| 1540 // The parser creates the mixin application class with no functions. | 1720 // The parser creates the mixin application class with no functions. |
| 1541 ASSERT((functions = cls.functions(), functions.Length() == 0)); | 1721 ASSERT((functions = cls.functions(), functions.Length() == 0)); |
| 1542 // Now clone the functions from the mixin class. | 1722 // Now clone the functions from the mixin class. |
| 1543 functions = mixin_cls.functions(); | 1723 functions = mixin_cls.functions(); |
| 1544 const intptr_t num_functions = functions.Length(); | 1724 const intptr_t num_functions = functions.Length(); |
| 1545 for (int i = 0; i < num_functions; i++) { | 1725 for (intptr_t i = 0; i < num_functions; i++) { |
| 1546 func ^= functions.At(i); | 1726 func ^= functions.At(i); |
| 1547 if (func.IsConstructor()) { | 1727 if (func.IsConstructor()) { |
| 1548 // A mixin class must not have explicit constructors. | 1728 // A mixin class must not have explicit constructors. |
| 1549 if (!func.IsImplicitConstructor()) { | 1729 if (!func.IsImplicitConstructor()) { |
| 1550 const Script& script = Script::Handle(isolate, cls.script()); | 1730 const Script& script = Script::Handle(isolate, cls.script()); |
| 1551 ReportError(Error::Handle(), // No previous error. | 1731 ReportError(Error::Handle(), // No previous error. |
| 1552 script, cls.token_pos(), | 1732 script, cls.token_pos(), |
| 1553 "mixin class '%s' must not have constructors\n", | 1733 "mixin class '%s' must not have constructors\n", |
| 1554 String::Handle(isolate, mixin_cls.Name()).ToCString()); | 1734 String::Handle(isolate, mixin_cls.Name()).ToCString()); |
| 1555 } | 1735 } |
| 1556 continue; // Skip the implicit constructor. | 1736 continue; // Skip the implicit constructor. |
| 1557 } | 1737 } |
| 1558 if (!func.is_static()) { | 1738 if (!func.is_static()) { |
| 1559 func = func.Clone(cls); | 1739 func = func.Clone(cls); |
| 1560 cloned_funcs.Add(func); | 1740 cloned_funcs.Add(func); |
| 1561 } | 1741 } |
| 1562 } | 1742 } |
| 1563 functions = Array::MakeArray(cloned_funcs); | 1743 functions = Array::MakeArray(cloned_funcs); |
| 1564 cls.SetFunctions(functions); | 1744 cls.SetFunctions(functions); |
| 1565 | 1745 |
| 1566 // Now clone the fields from the mixin class. There should be no | 1746 // Now clone the fields from the mixin class. There should be no |
| 1567 // existing fields in the mixin application class. | 1747 // existing fields in the mixin application class. |
| 1568 ASSERT(Array::Handle(cls.fields()).Length() == 0); | 1748 ASSERT(Array::Handle(cls.fields()).Length() == 0); |
| 1569 Array& fields = Array::Handle(isolate, mixin_cls.fields()); | 1749 Array& fields = Array::Handle(isolate, mixin_cls.fields()); |
| 1570 Field& field = Field::Handle(isolate); | 1750 Field& field = Field::Handle(isolate); |
| 1571 const GrowableObjectArray& cloned_fields = | 1751 const GrowableObjectArray& cloned_fields = |
| 1572 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); | 1752 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| 1573 const intptr_t num_fields = fields.Length(); | 1753 const intptr_t num_fields = fields.Length(); |
| 1574 for (int i = 0; i < num_fields; i++) { | 1754 for (intptr_t i = 0; i < num_fields; i++) { |
| 1575 field ^= fields.At(i); | 1755 field ^= fields.At(i); |
| 1576 if (!field.is_static()) { | 1756 if (!field.is_static()) { |
| 1577 field = field.Clone(cls); | 1757 field = field.Clone(cls); |
| 1578 cloned_fields.Add(field); | 1758 cloned_fields.Add(field); |
| 1579 } | 1759 } |
| 1580 } | 1760 } |
| 1581 fields = Array::MakeArray(cloned_fields); | 1761 fields = Array::MakeArray(cloned_fields); |
| 1582 cls.SetFields(fields); | 1762 cls.SetFields(fields); |
| 1583 | 1763 |
| 1584 if (FLAG_trace_class_finalization) { | 1764 if (FLAG_trace_class_finalization) { |
| 1585 OS::Print("done applying mixin members of %s to %s\n", | 1765 OS::Print("Done applying mixin members of %s to %s\n", |
| 1586 mixin_cls.ToCString(), | 1766 mixin_cls.ToCString(), |
| 1587 cls.ToCString()); | 1767 cls.ToCString()); |
| 1588 } | 1768 } |
| 1589 } | 1769 } |
| 1590 | 1770 |
| 1591 | 1771 |
| 1592 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { | 1772 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { |
| 1593 HANDLESCOPE(Isolate::Current()); | 1773 HANDLESCOPE(Isolate::Current()); |
| 1594 if (cls.is_type_finalized()) { | 1774 if (cls.is_type_finalized()) { |
| 1595 return; | 1775 return; |
| 1596 } | 1776 } |
| 1597 if (FLAG_trace_class_finalization) { | 1777 if (FLAG_trace_class_finalization) { |
| 1598 OS::Print("Finalize types in %s\n", cls.ToCString()); | 1778 OS::Print("Finalize types in %s\n", cls.ToCString()); |
| 1599 } | 1779 } |
| 1600 if (!IsSuperCycleFree(cls)) { | 1780 if (!IsSuperCycleFree(cls)) { |
| 1601 const String& name = String::Handle(cls.Name()); | 1781 const String& name = String::Handle(cls.Name()); |
| 1602 const Script& script = Script::Handle(cls.script()); | 1782 const Script& script = Script::Handle(cls.script()); |
| 1603 ReportError(Error::Handle(), // No previous error. | 1783 ReportError(Error::Handle(), // No previous error. |
| 1604 script, cls.token_pos(), | 1784 script, cls.token_pos(), |
| 1605 "class '%s' has a cycle in its superclass relationship", | 1785 "class '%s' has a cycle in its superclass relationship", |
| 1606 name.ToCString()); | 1786 name.ToCString()); |
| 1607 } | 1787 } |
| 1608 // Finalize super class. | 1788 // Finalize super class. |
| 1609 const Class& super_class = Class::Handle(cls.SuperClass()); | 1789 Class& super_class = Class::Handle(cls.SuperClass()); |
| 1610 if (!super_class.IsNull()) { | 1790 if (!super_class.IsNull()) { |
| 1611 FinalizeTypesInClass(super_class); | 1791 FinalizeTypesInClass(super_class); |
| 1612 } | 1792 } |
| 1613 // Finalize type parameters before finalizing the super type. | 1793 // Finalize type parameters before finalizing the super type. |
| 1614 FinalizeTypeParameters(cls); | 1794 FinalizeTypeParameters(cls); // May change super type. |
| 1795 super_class = cls.SuperClass(); | |
| 1796 ASSERT(super_class.IsNull() || super_class.is_type_finalized()); | |
| 1615 ResolveUpperBounds(cls); | 1797 ResolveUpperBounds(cls); |
| 1616 // Finalize super type. | 1798 // Finalize super type. |
| 1617 AbstractType& super_type = AbstractType::Handle(cls.super_type()); | 1799 AbstractType& super_type = AbstractType::Handle(cls.super_type()); |
| 1618 if (!super_type.IsNull()) { | 1800 if (!super_type.IsNull()) { |
| 1619 // In case of a bound error in the super type in production mode, the | 1801 // In case of a bound error in the super type in production mode, the |
| 1620 // finalized super type will be a BoundedType with a malformed bound. | 1802 // finalized super type will be a BoundedType with a malformed bound. |
| 1621 // It should not be a problem if the class is written to a snapshot and | 1803 // It should not be a problem if the class is written to a snapshot and |
| 1622 // later executed in checked mode. Note that the finalized type argument | 1804 // later executed in checked mode. Note that the finalized type argument |
| 1623 // vector of any type of the base class will contain a BoundedType for the | 1805 // vector of any type of the base class will contain a BoundedType for the |
| 1624 // out of bound type argument. | 1806 // out of bound type argument. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1727 ApplyMixinMembers(cls); | 1909 ApplyMixinMembers(cls); |
| 1728 } | 1910 } |
| 1729 // Ensure super class is finalized. | 1911 // Ensure super class is finalized. |
| 1730 const Class& super = Class::Handle(cls.SuperClass()); | 1912 const Class& super = Class::Handle(cls.SuperClass()); |
| 1731 if (!super.IsNull()) { | 1913 if (!super.IsNull()) { |
| 1732 FinalizeClass(super); | 1914 FinalizeClass(super); |
| 1733 } | 1915 } |
| 1734 // Mark as parsed and finalized. | 1916 // Mark as parsed and finalized. |
| 1735 cls.Finalize(); | 1917 cls.Finalize(); |
| 1736 // Mixin typedef classes may still lack their implicit constructor. | 1918 // Mixin typedef classes may still lack their implicit constructor. |
| 1737 // TODO(regis): Implement mixin typedefs with an alias class. | |
| 1738 if (cls.is_mixin_typedef() && | 1919 if (cls.is_mixin_typedef() && |
| 1739 (cls.functions() == Object::empty_array().raw())) { | 1920 (cls.functions() == Object::empty_array().raw())) { |
| 1740 Parser::AddImplicitConstructor(cls); | 1921 Parser::AddImplicitConstructor(cls); |
| 1741 } | 1922 } |
| 1742 // Every class should have at least a constructor, unless it is a top level | 1923 // Every class should have at least a constructor, unless it is a top level |
| 1743 // class or a signature class. | 1924 // class or a signature class. |
| 1744 ASSERT(cls.IsTopLevel() || | 1925 ASSERT(cls.IsTopLevel() || |
| 1745 cls.IsSignatureClass() || | 1926 cls.IsSignatureClass() || |
| 1746 (Array::Handle(cls.functions()).Length() > 0)); | 1927 (Array::Handle(cls.functions()).Length() > 0)); |
| 1747 // Resolve and finalize all member types. | 1928 // Resolve and finalize all member types. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1805 } | 1986 } |
| 1806 | 1987 |
| 1807 | 1988 |
| 1808 // Returns false if the function type alias illegally refers to itself. | 1989 // Returns false if the function type alias illegally refers to itself. |
| 1809 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, | 1990 bool ClassFinalizer::IsAliasCycleFree(const Class& cls, |
| 1810 GrowableArray<intptr_t>* visited) { | 1991 GrowableArray<intptr_t>* visited) { |
| 1811 ASSERT(cls.IsSignatureClass()); | 1992 ASSERT(cls.IsSignatureClass()); |
| 1812 ASSERT(!cls.is_type_finalized()); | 1993 ASSERT(!cls.is_type_finalized()); |
| 1813 ASSERT(visited != NULL); | 1994 ASSERT(visited != NULL); |
| 1814 const intptr_t cls_index = cls.id(); | 1995 const intptr_t cls_index = cls.id(); |
| 1815 for (int i = 0; i < visited->length(); i++) { | 1996 for (intptr_t i = 0; i < visited->length(); i++) { |
| 1816 if ((*visited)[i] == cls_index) { | 1997 if ((*visited)[i] == cls_index) { |
| 1817 // We have already visited alias 'cls'. We found a cycle. | 1998 // We have already visited alias 'cls'. We found a cycle. |
| 1818 return false; | 1999 return false; |
| 1819 } | 2000 } |
| 1820 } | 2001 } |
| 1821 | 2002 |
| 1822 // Visit the result type and parameter types of this signature type. | 2003 // Visit the result type and parameter types of this signature type. |
| 1823 visited->Add(cls.id()); | 2004 visited->Add(cls.id()); |
| 1824 const Function& function = Function::Handle(cls.signature_function()); | 2005 const Function& function = Function::Handle(cls.signature_function()); |
| 1825 // Check class of result type. | 2006 // Check class of result type. |
| 1826 AbstractType& type = AbstractType::Handle(function.result_type()); | 2007 AbstractType& type = AbstractType::Handle(function.result_type()); |
| 1827 if (!IsParameterTypeCycleFree(cls, type, visited)) { | 2008 if (!IsParameterTypeCycleFree(cls, type, visited)) { |
| 1828 return false; | 2009 return false; |
| 1829 } | 2010 } |
| 1830 // Check classes of formal parameter types. | 2011 // Check classes of formal parameter types. |
| 1831 const intptr_t num_parameters = function.NumParameters(); | 2012 const intptr_t num_parameters = function.NumParameters(); |
| 1832 for (intptr_t i = 0; i < num_parameters; i++) { | 2013 for (intptr_t i = 0; i < num_parameters; i++) { |
| 1833 type = function.ParameterTypeAt(i); | 2014 type = function.ParameterTypeAt(i); |
| 1834 if (!IsParameterTypeCycleFree(cls, type, visited)) { | 2015 if (!IsParameterTypeCycleFree(cls, type, visited)) { |
| 1835 return false; | 2016 return false; |
| 1836 } | 2017 } |
| 1837 } | 2018 } |
| 1838 visited->RemoveLast(); | 2019 visited->RemoveLast(); |
| 1839 return true; | 2020 return true; |
| 1840 } | 2021 } |
| 1841 | 2022 |
| 1842 | 2023 |
| 2024 // Returns false if the mixin illegally refers to itself. | |
| 2025 bool ClassFinalizer::IsMixinCycleFree(const Class& cls, | |
| 2026 GrowableArray<intptr_t>* visited) { | |
| 2027 ASSERT(visited != NULL); | |
| 2028 const intptr_t cls_index = cls.id(); | |
| 2029 for (intptr_t i = 0; i < visited->length(); i++) { | |
| 2030 if ((*visited)[i] == cls_index) { | |
| 2031 // We have already visited mixin 'cls'. We found a cycle. | |
| 2032 return false; | |
| 2033 } | |
| 2034 } | |
| 2035 | |
| 2036 // Visit the super chain of cls. | |
| 2037 visited->Add(cls.id()); | |
| 2038 Class& super_class = Class::Handle(cls.raw()); | |
| 2039 do { | |
| 2040 if (super_class.IsMixinApplication()) { | |
| 2041 const Type& mixin_type = Type::Handle(super_class.mixin()); | |
| 2042 ASSERT(!mixin_type.IsNull()); | |
| 2043 ASSERT(mixin_type.HasResolvedTypeClass()); | |
| 2044 const Class& mixin_class = Class::Handle(mixin_type.type_class()); | |
| 2045 if (!IsMixinCycleFree(mixin_class, visited)) { | |
| 2046 return false; | |
| 2047 } | |
| 2048 } | |
| 2049 super_class = super_class.SuperClass(); | |
| 2050 } while (!super_class.IsNull()); | |
| 2051 visited->RemoveLast(); | |
| 2052 return true; | |
| 2053 } | |
| 2054 | |
| 2055 | |
| 1843 void ClassFinalizer::CollectTypeArguments( | 2056 void ClassFinalizer::CollectTypeArguments( |
| 1844 const Class& cls, | 2057 const Class& cls, |
| 1845 const Type& type, | 2058 const Type& type, |
| 1846 const GrowableObjectArray& collected_args) { | 2059 const GrowableObjectArray& collected_args) { |
| 1847 ASSERT(type.HasResolvedTypeClass()); | 2060 ASSERT(type.HasResolvedTypeClass()); |
| 1848 Class& type_class = Class::Handle(type.type_class()); | 2061 Class& type_class = Class::Handle(type.type_class()); |
| 1849 AbstractTypeArguments& type_args = | 2062 AbstractTypeArguments& type_args = |
| 1850 AbstractTypeArguments::Handle(type.arguments()); | 2063 AbstractTypeArguments::Handle(type.arguments()); |
| 1851 const intptr_t num_type_parameters = type_class.NumTypeParameters(); | 2064 const intptr_t num_type_parameters = type_class.NumTypeParameters(); |
| 1852 const intptr_t num_type_arguments = | 2065 const intptr_t num_type_arguments = |
| 1853 type_args.IsNull() ? 0 : type_args.Length(); | 2066 type_args.IsNull() ? 0 : type_args.Length(); |
| 1854 AbstractType& arg = AbstractType::Handle(); | 2067 AbstractType& arg = AbstractType::Handle(); |
| 1855 if (num_type_arguments > 0) { | 2068 if (num_type_arguments > 0) { |
| 1856 if (num_type_arguments == num_type_parameters) { | 2069 if (num_type_arguments == num_type_parameters) { |
| 1857 for (int i = 0; i < num_type_arguments; i++) { | 2070 for (intptr_t i = 0; i < num_type_arguments; i++) { |
| 1858 arg = type_args.TypeAt(i); | 2071 arg = type_args.TypeAt(i); |
| 1859 collected_args.Add(arg); | 2072 collected_args.Add(arg); |
| 1860 } | 2073 } |
| 1861 return; | 2074 return; |
| 1862 } | 2075 } |
| 1863 if (FLAG_error_on_bad_type) { | 2076 if (FLAG_error_on_bad_type) { |
| 1864 const Script& script = Script::Handle(cls.script()); | 2077 const Script& script = Script::Handle(cls.script()); |
| 1865 const String& type_class_name = String::Handle(type_class.Name()); | 2078 const String& type_class_name = String::Handle(type_class.Name()); |
| 1866 ReportError(Error::Handle(), // No previous error. | 2079 ReportError(Error::Handle(), // No previous error. |
| 1867 script, type.token_pos(), | 2080 script, type.token_pos(), |
| 1868 "wrong number of type arguments for class '%s'", | 2081 "wrong number of type arguments for class '%s'", |
| 1869 type_class_name.ToCString()); | 2082 type_class_name.ToCString()); |
| 1870 } | 2083 } |
| 1871 // Discard provided type arguments and treat type as raw. | 2084 // Discard provided type arguments and treat type as raw. |
| 1872 } | 2085 } |
| 1873 // Fill arguments with type dynamic. | 2086 // Fill arguments with type dynamic. |
| 1874 for (int i = 0; i < num_type_parameters; i++) { | 2087 for (intptr_t i = 0; i < num_type_parameters; i++) { |
| 1875 arg = Type::DynamicType(); | 2088 arg = Type::DynamicType(); |
| 1876 collected_args.Add(arg); | 2089 collected_args.Add(arg); |
| 1877 } | 2090 } |
| 1878 } | 2091 } |
| 1879 | 2092 |
| 1880 | 2093 |
| 1881 RawType* ClassFinalizer::ResolveMixinAppType(const Class& cls, | 2094 RawType* ClassFinalizer::ResolveMixinAppType(const Class& cls, |
| 1882 const MixinAppType& mixin_app) { | 2095 const MixinAppType& mixin_app) { |
| 1883 // Resolve super type and all mixin types. | 2096 // Resolve super type and all mixin types. |
| 1884 const GrowableObjectArray& type_args = | 2097 const GrowableObjectArray& type_args = |
| 1885 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 2098 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 1886 AbstractType& type = AbstractType::Handle(mixin_app.SuperType()); | 2099 AbstractType& type = AbstractType::Handle(mixin_app.SuperType()); |
| 1887 ResolveType(cls, type, kCanonicalizeWellFormed); | 2100 ResolveType(cls, type, kCanonicalizeWellFormed); |
| 1888 ASSERT(type.HasResolvedTypeClass()); | 2101 ASSERT(type.HasResolvedTypeClass()); |
| 1889 // TODO(hausner): May need to handle BoundedType here. | 2102 // TODO(hausner): May need to handle BoundedType here. |
| 1890 ASSERT(type.IsType()); | 2103 ASSERT(type.IsType()); |
| 1891 CollectTypeArguments(cls, Type::Cast(type), type_args); | 2104 CollectTypeArguments(cls, Type::Cast(type), type_args); |
| 1892 Class& mixin_app_class = Class::Handle(); | 2105 Class& mixin_app_class = Class::Handle(); |
| 1893 const intptr_t depth = mixin_app.Depth(); | 2106 const intptr_t depth = mixin_app.Depth(); |
| 1894 for (int i = 0; i < depth; i++) { | 2107 for (intptr_t i = 0; i < depth; i++) { |
| 1895 mixin_app_class = mixin_app.MixinAppAt(i); | 2108 mixin_app_class = mixin_app.MixinAppAt(i); |
| 1896 type = mixin_app_class.mixin(); | 2109 type = mixin_app_class.mixin(); |
| 1897 ASSERT(!type.IsNull()); | 2110 ASSERT(!type.IsNull()); |
| 1898 ResolveType(cls, type, kCanonicalizeWellFormed); | 2111 ResolveType(cls, type, kCanonicalizeWellFormed); |
| 1899 ASSERT(type.HasResolvedTypeClass()); | 2112 ASSERT(type.HasResolvedTypeClass()); |
| 1900 ASSERT(type.IsType()); | 2113 ASSERT(type.IsType()); |
| 1901 CollectTypeArguments(cls, Type::Cast(type), type_args); | 2114 CollectTypeArguments(cls, Type::Cast(type), type_args); |
| 1902 } | 2115 } |
| 1903 const TypeArguments& mixin_app_args = | 2116 const TypeArguments& mixin_app_args = |
| 1904 TypeArguments::Handle(TypeArguments::New(type_args.Length())); | 2117 TypeArguments::Handle(TypeArguments::New(type_args.Length())); |
| 1905 for (int i = 0; i < type_args.Length(); i++) { | 2118 for (intptr_t i = 0; i < type_args.Length(); i++) { |
| 1906 type ^= type_args.At(i); | 2119 type ^= type_args.At(i); |
| 1907 mixin_app_args.SetTypeAt(i, type); | 2120 mixin_app_args.SetTypeAt(i, type); |
| 1908 } | 2121 } |
| 1909 if (FLAG_trace_class_finalization) { | 2122 if (FLAG_trace_class_finalization) { |
| 1910 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", | 2123 OS::Print("ResolveMixinAppType: mixin appl type args: %s\n", |
| 1911 mixin_app_args.ToCString()); | 2124 mixin_app_args.ToCString()); |
| 1912 } | 2125 } |
| 1913 // The mixin application class at depth k is a subclass of mixin application | 2126 // The mixin application class at depth k is a subclass of mixin application |
| 1914 // class at depth k - 1. Build a new super type with the class at the highest | 2127 // class at depth k - 1. Build a new super type with the class at the highest |
| 1915 // depth (the last one processed by the loop above) as the type class and the | 2128 // depth (the last one processed by the loop above) as the type class and the |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1927 // remembering interfaces we've visited in each path through the | 2140 // remembering interfaces we've visited in each path through the |
| 1928 // graph. If we visit an interface a second time on a given path, | 2141 // graph. If we visit an interface a second time on a given path, |
| 1929 // we found a loop. | 2142 // we found a loop. |
| 1930 void ClassFinalizer::ResolveSuperTypeAndInterfaces( | 2143 void ClassFinalizer::ResolveSuperTypeAndInterfaces( |
| 1931 const Class& cls, GrowableArray<intptr_t>* visited) { | 2144 const Class& cls, GrowableArray<intptr_t>* visited) { |
| 1932 ASSERT(visited != NULL); | 2145 ASSERT(visited != NULL); |
| 1933 if (FLAG_trace_class_finalization) { | 2146 if (FLAG_trace_class_finalization) { |
| 1934 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); | 2147 OS::Print("Resolving super and interfaces: %s\n", cls.ToCString()); |
| 1935 } | 2148 } |
| 1936 const intptr_t cls_index = cls.id(); | 2149 const intptr_t cls_index = cls.id(); |
| 1937 for (int i = 0; i < visited->length(); i++) { | 2150 for (intptr_t i = 0; i < visited->length(); i++) { |
| 1938 if ((*visited)[i] == cls_index) { | 2151 if ((*visited)[i] == cls_index) { |
| 1939 // We have already visited class 'cls'. We found a cycle. | 2152 // We have already visited class 'cls'. We found a cycle. |
| 1940 const String& class_name = String::Handle(cls.Name()); | 2153 const String& class_name = String::Handle(cls.Name()); |
| 1941 const Script& script = Script::Handle(cls.script()); | 2154 const Script& script = Script::Handle(cls.script()); |
| 1942 ReportError(Error::Handle(), // No previous error. | 2155 ReportError(Error::Handle(), // No previous error. |
| 1943 script, cls.token_pos(), | 2156 script, cls.token_pos(), |
| 1944 "cyclic reference found for class '%s'", | 2157 "cyclic reference found for class '%s'", |
| 1945 class_name.ToCString()); | 2158 class_name.ToCString()); |
| 1946 } | 2159 } |
| 1947 } | 2160 } |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2316 expected_name ^= String::New("_offset"); | 2529 expected_name ^= String::New("_offset"); |
| 2317 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); | 2530 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); |
| 2318 field ^= fields_array.At(2); | 2531 field ^= fields_array.At(2); |
| 2319 ASSERT(field.Offset() == TypedDataView::length_offset()); | 2532 ASSERT(field.Offset() == TypedDataView::length_offset()); |
| 2320 name ^= field.name(); | 2533 name ^= field.name(); |
| 2321 ASSERT(name.Equals("length")); | 2534 ASSERT(name.Equals("length")); |
| 2322 #endif | 2535 #endif |
| 2323 } | 2536 } |
| 2324 | 2537 |
| 2325 } // namespace dart | 2538 } // namespace dart |
| OLD | NEW |