Chromium Code Reviews| Index: runtime/vm/dart_api_impl.cc |
| =================================================================== |
| --- runtime/vm/dart_api_impl.cc (revision 11702) |
| +++ runtime/vm/dart_api_impl.cc (working copy) |
| @@ -284,6 +284,29 @@ |
| } |
| +// When we want to return a handle to a type to the user, we handle |
| +// class-types differently than some other types. |
| +static Dart_Handle TypeToHandle(Isolate* isolate, |
| + const char* function_name, |
| + const AbstractType& type) { |
| + if (type.HasResolvedTypeClass()) { |
| + const Class& cls = Class::Handle(isolate, type.type_class()); |
| +#if defined(DEBUG) |
| + const Library& lib = Library::Handle(cls.library()); |
| + if (lib.IsNull()) { |
| + ASSERT(cls.IsDynamicClass() || cls.IsVoidClass()); |
| + } |
| +#endif |
| + return Api::NewHandle(isolate, cls.raw()); |
| + } else if (type.IsTypeParameter()) { |
| + return Api::NewHandle(isolate, type.raw()); |
| + } else { |
| + return Api::NewError("%s: unexpected type '%s' encountered.", |
| + function_name, type.ToCString()); |
| + } |
| +} |
| + |
| + |
| // --- Handles --- |
| @@ -2461,7 +2484,10 @@ |
| #if defined(DEBUG) |
| const Library& lib = Library::Handle(cls.library()); |
| if (lib.IsNull()) { |
| - ASSERT(cls.IsDynamicClass() || cls.IsVoidClass()); |
| + // ASSERT(cls.IsDynamicClass() || cls.IsVoidClass()); |
|
cshapiro
2012/09/12 18:52:07
This should have a TODO for the commented out code
|
| + if (!cls.IsDynamicClass() && !cls.IsVoidClass()) { |
| + fprintf(stderr, "NO LIBRARY: %s\n", cls.ToCString()); |
|
cshapiro
2012/09/12 18:52:07
fprintf? Why not use something in OS instead ?
|
| + } |
| } |
| #endif |
| @@ -2540,6 +2566,68 @@ |
| } |
| +DART_EXPORT bool Dart_ClassIsTypedef(Dart_Handle clazz) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + // For now, the only typedefs are non-canonical signature classes. |
|
cshapiro
2012/09/12 18:52:07
For now all typedefs are non-canonical signature c
turnidge
2012/09/12 21:39:30
Done.
|
| + return cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass(); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_ClassGetTypedefReferent(Dart_Handle clazz) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + |
| + if (!cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass()) { |
| + const String& cls_name = String::Handle(cls.UserVisibleName()); |
| + return Api::NewError("%s: class '%s' is not a typedef class. " |
| + "See Dart_ClassIsTypedef.", |
| + CURRENT_FUNC, cls_name.ToCString()); |
| + } |
| + |
| + const Function& func = Function::Handle(isolate, cls.signature_function()); |
| + return Api::NewHandle(isolate, func.signature_class()); |
| +} |
| + |
| + |
| +DART_EXPORT bool Dart_ClassIsFunctionType(Dart_Handle clazz) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + // A class represents a function type when it is a canonical |
| + // signature class. |
| + return cls.IsCanonicalSignatureClass(); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_ClassGetFunctionTypeSignature(Dart_Handle clazz) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + if (!cls.IsCanonicalSignatureClass()) { |
| + const String& cls_name = String::Handle(cls.UserVisibleName()); |
| + return Api::NewError("%s: class '%s' is not a function-type class. " |
| + "See Dart_ClassIsFunctionType.", |
| + CURRENT_FUNC, cls_name.ToCString()); |
| + } |
| + return Api::NewHandle(isolate, cls.signature_function()); |
| +} |
| + |
| + |
| // --- Function and Variable Reflection --- |
| @@ -2817,6 +2905,20 @@ |
| } |
| +DART_EXPORT Dart_Handle Dart_FunctionReturnType(Dart_Handle function) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| + if (func.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, function, Function); |
| + } |
| + |
| + const AbstractType& return_type = |
| + AbstractType::Handle(isolate, func.result_type()); |
| + return TypeToHandle(isolate, "Dart_FunctionReturnType", return_type); |
| +} |
| + |
| + |
| DART_EXPORT Dart_Handle Dart_FunctionParameterCounts( |
| Dart_Handle function, |
| int64_t* fixed_param_count, |
| @@ -2848,6 +2950,30 @@ |
| } |
| +DART_EXPORT Dart_Handle Dart_FunctionParameterType(Dart_Handle function, |
| + int parameter_index) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Function& func = Api::UnwrapFunctionHandle(isolate, function); |
| + if (func.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, function, Function); |
| + } |
| + |
| + const intptr_t num_implicit_params = func.NumberOfImplicitParameters(); |
| + const intptr_t num_params = func.NumberOfParameters() - num_implicit_params; |
| + if (parameter_index < 0 || parameter_index >= num_params) { |
| + return Api::NewError( |
| + "%s: argument 'parameter_index' out of range. " |
| + "Expected 0..%d but saw %d.", |
| + CURRENT_FUNC, num_params, parameter_index); |
| + } |
| + const AbstractType& param_type = |
| + AbstractType::Handle(isolate, func.ParameterTypeAt( |
| + num_implicit_params + parameter_index)); |
| + return TypeToHandle(isolate, "Dart_FunctionParameterType", param_type); |
| +} |
| + |
| + |
| DART_EXPORT Dart_Handle Dart_GetVariableNames(Dart_Handle target) { |
| Isolate* isolate = Isolate::Current(); |
| DARTSCOPE(isolate); |
| @@ -2971,6 +3097,122 @@ |
| return Api::Success(isolate); |
| } |
| + |
| +DART_EXPORT Dart_Handle Dart_VariableType(Dart_Handle variable) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Field& var = Api::UnwrapFieldHandle(isolate, variable); |
| + if (var.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, variable, Field); |
| + } |
| + |
| + const AbstractType& type = AbstractType::Handle(isolate, var.type()); |
| + return TypeToHandle(isolate, "Dart_VariableType", type); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_GetTypeVariableNames(Dart_Handle clazz) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + |
| + const intptr_t num_type_params = cls.NumTypeParameters(); |
| + const TypeArguments& type_params = |
| + TypeArguments::Handle(cls.type_parameters()); |
| + |
| + const GrowableObjectArray& names = |
| + GrowableObjectArray::Handle(isolate, GrowableObjectArray::New()); |
| + TypeParameter& type_param = TypeParameter::Handle(isolate); |
| + String& name = String::Handle(isolate); |
| + for (intptr_t i = 0; i < num_type_params; i++) { |
| + type_param ^= type_params.TypeAt(i); |
| + name = type_param.name(); |
| + names.Add(name); |
| + } |
| + return Api::NewHandle(isolate, Array::MakeArray(names)); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_LookupTypeVariable( |
| + Dart_Handle clazz, |
| + Dart_Handle type_variable_name) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const Class& cls = Api::UnwrapClassHandle(isolate, clazz); |
| + if (cls.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, clazz, Class); |
| + } |
| + const String& var_name = Api::UnwrapStringHandle(isolate, type_variable_name); |
| + if (var_name.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, type_variable_name, String); |
| + } |
| + |
| + const intptr_t num_type_params = cls.NumTypeParameters(); |
| + const TypeArguments& type_params = |
| + TypeArguments::Handle(cls.type_parameters()); |
| + |
| + TypeParameter& type_param = TypeParameter::Handle(isolate); |
| + String& name = String::Handle(isolate); |
| + for (intptr_t i = 0; i < num_type_params; i++) { |
| + type_param ^= type_params.TypeAt(i); |
| + name = type_param.name(); |
| + if (name.Equals(var_name)) { |
| + return Api::NewHandle(isolate, type_param.raw()); |
| + } |
| + } |
| + const String& cls_name = String::Handle(cls.UserVisibleName()); |
| + return Api::NewError( |
| + "%s: Could not find type variable named '%s' for class %s.\n", |
| + var_name.ToCString(), cls_name.ToCString()); |
| +} |
| + |
| + |
| +DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) { |
| + return Api::ClassId(handle) == kTypeParameterCid; |
| +} |
| + |
| +DART_EXPORT Dart_Handle Dart_TypeVariableName(Dart_Handle type_variable) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const TypeParameter& type_var = |
| + Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| + if (type_var.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| + } |
| + return Api::NewHandle(isolate, type_var.name()); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_TypeVariableOwner(Dart_Handle type_variable) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const TypeParameter& type_var = |
| + Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| + if (type_var.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| + } |
| + const Class& owner = Class::Handle(type_var.parameterized_class()); |
| + ASSERT(!owner.IsNull() && owner.IsClass()); |
| + return Api::NewHandle(isolate, owner.raw()); |
| +} |
| + |
| + |
| +DART_EXPORT Dart_Handle Dart_TypeVariableUpperBound(Dart_Handle type_variable) { |
| + Isolate* isolate = Isolate::Current(); |
| + DARTSCOPE(isolate); |
| + const TypeParameter& type_var = |
| + Api::UnwrapTypeParameterHandle(isolate, type_variable); |
| + if (type_var.IsNull()) { |
| + RETURN_TYPE_ERROR(isolate, type_variable, TypeParameter); |
| + } |
| + const AbstractType& bound = AbstractType::Handle(type_var.bound()); |
| + return TypeToHandle(isolate, "Dart_TypeVariableUpperBound", bound); |
| +} |
| + |
| + |
| // --- Constructors, Methods, and Fields --- |
| @@ -3976,11 +4218,15 @@ |
| String& name = String::Handle(); |
| while (it.HasNext()) { |
| cls = it.GetNextClass(); |
| - // For now we suppress the signature classes of closures. |
| - // |
| - // TODO(turnidge): Add this to the unit test. |
| - const Function& signature_func = Function::Handle(cls.signature_function()); |
| - if (signature_func.IsNull()) { |
| + if (cls.IsSignatureClass()) { |
| + if (!cls.IsCanonicalSignatureClass()) { |
| + // This is a typedef. Add it to the list of class names. |
| + name = cls.UserVisibleName(); |
| + names.Add(name); |
| + } else { |
| + // Skip canonical signature classes. These are not named. |
| + } |
| + } else { |
| name = cls.UserVisibleName(); |
| names.Add(name); |
| } |