This allows parameterized types to reference each other with a different set of parameters. This is required for instance for IIterable<T>, that needs to reference IIterator<T>.
The partial specialization is recorded by adding a new parameterized type, referencing the original one as its template. The parameterized type chain will be resolved all at once when the type is declared.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
Just changed parameterized_types name to parameterized_type_args, and adding the delegate patches in addition.
include/windows.foundation.idl | 9 +++++++ tools/widl/parser.y | 47 ++++++++++++++++++++++++++++++++++ tools/widl/typetree.c | 41 ++++++++++++++++++++++++++--- tools/widl/typetree.h | 3 +++ tools/widl/widltypes.h | 1 + 5 files changed, 98 insertions(+), 3 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index ab7c4753c3b..5f7a49c38e4 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -127,6 +127,15 @@ namespace Windows { HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); }
+ [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(faa585ea-6214-4217-afda-7f46de5869b3) + ] + interface IIterable<T> : IInspectable + { + HRESULT First([out, retval] Windows.Foundation.Collections.IIterator<T> **value); + } + [ contract(Windows.Foundation.FoundationContract, 1.0), uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 6ab4f83a0ad..0725332a736 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -46,6 +46,7 @@ struct _import_t
static str_list_t *append_str(str_list_t *list, char *str); static type_list_t *append_type(type_list_t *list, type_t *type); +static type_list_t *append_types(type_list_t *list, type_list_t *types); static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, @@ -293,6 +294,8 @@ static typelib_t *current_typelib; %type <type> type unqualified_type qualified_type %type <type> type_parameter %type <type_list> type_parameters +%type <type> parameterized_type +%type <type_list> parameterized_type_args %type <ifref> class_interface %type <ifref_list> class_interfaces %type <ifref_list> requires required_types @@ -909,6 +912,20 @@ qualified_type: | namespace_pfx typename { $$ = find_type_or_error($1, $2); } ;
+parameterized_type: qualified_type '<' parameterized_type_args '>' + { $$ = find_parameterized_type($1, $3); } + ; + +parameterized_type_args: + base_type { $$ = append_type(NULL, $1); } + | qualified_type { $$ = append_type(NULL, $1); } + | qualified_type '*' { $$ = append_type(NULL, type_new_pointer($1)); } + | parameterized_type { $$ = append_type(NULL, $1); } + | parameterized_type '*' { $$ = append_type(NULL, type_new_pointer($1)); } + | parameterized_type_args ',' parameterized_type_args + { $$ = append_types($1, $3); } + ; + coclass: tCOCLASS typename { $$ = type_coclass_declare($2); } ;
@@ -965,6 +982,7 @@ dispinterfacedef:
inherit: { $$ = NULL; } | ':' qualified_type { $$ = $2; } + | ':' parameterized_type { $$ = $2; } ;
type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } @@ -983,7 +1001,9 @@ interface:
required_types: qualified_type { $$ = append_ifref(NULL, make_ifref($1)); } + | parameterized_type { $$ = append_ifref(NULL, make_ifref($1)); } | required_types ',' qualified_type { $$ = append_ifref($1, make_ifref($3)); } + | required_types ',' parameterized_type { $$ = append_ifref($1, make_ifref($3)); }
requires: { $$ = NULL; } | tREQUIRES required_types { $$ = $2; } @@ -1207,6 +1227,7 @@ unqualified_type: type: unqualified_type | namespace_pfx typename { $$ = find_type_or_error($1, $2); } + | parameterized_type { $$ = $1; } ;
typedef: m_attributes tTYPEDEF m_attributes decl_spec declarator_list @@ -1839,6 +1860,16 @@ static type_list_t *append_type(type_list_t *list, type_t *type) return entry; }
+static type_list_t *append_types(type_list_t *list, type_list_t *types) +{ + type_list_t *entry; + if (!list) return types; + if (!types) return list; + for (entry = list; entry->next; entry = entry->next) {} + entry->next = types; + return list; +} + var_list_t *append_var(var_list_t *list, var_t *var) { if (!var) return list; @@ -3268,3 +3299,19 @@ void init_loc_info(loc_info_t *i) i->line_number = line_number; i->near_text = parser_text; } + +type_t *find_parameterized_type(type_t *type, type_list_t *params) +{ + char *name = format_parameterized_type_name(type, params); + + if (parameters_namespace) + { + assert(type->type_type == TYPE_PARAMETERIZED_TYPE); + type = type_parameterized_type_specialize_partial(type, params); + } + /* FIXME: If not in another parameterized type, we'll have to look for the declared specialization. */ + else error_loc("parameterized type '%s' not declared\n", name); + + free(name); + return type; +} diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 203fffcdee6..22c75d32161 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -100,13 +100,40 @@ static size_t append_namespace(char **buf, size_t *len, size_t pos, struct names return n; }
+static size_t append_namespaces(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *prefix, + const char *separator, const char *suffix, const char *abi_prefix) +{ + size_t n = 0; + n += strappend(buf, len, pos + n, "%s", prefix); + n += append_namespace(buf, len, pos + n, namespace, separator, abi_prefix); + n += strappend(buf, len, pos + n, "%s", suffix); + return n; +} + char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) +{ + size_t len = 0; + char *buf = NULL; + append_namespaces(&buf, &len, 0, namespace, prefix, separator, suffix, abi_prefix); + return buf; +} + +char *format_parameterized_type_name(type_t *type, type_list_t *params) { size_t len = 0, pos = 0; char *buf = NULL; - pos += strappend(&buf, &len, pos, "%s", prefix); - pos += append_namespace(&buf, &len, pos, namespace, separator, abi_prefix); - pos += strappend(&buf, &len, pos, "%s", suffix); + type_list_t *entry; + + pos += strappend(&buf, &len, pos, "%s<", type->name); + for (entry = params; entry; entry = entry->next) + { + for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} + pos += append_namespaces(&buf, &len, pos, type->namespace, "", "::", type->name, use_abi_namespace ? "ABI" : NULL); + for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) pos += strappend(&buf, &len, pos, "*"); + if (entry->next) pos += strappend(&buf, &len, pos, ","); + } + pos += strappend(&buf, &len, pos, ">"); + return buf; }
@@ -642,6 +669,14 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty return type; }
+type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params) +{ + type_t *new_type = duptype(type, 0); + new_type->details.parameterized.type = type; + new_type->details.parameterized.params = params; + return new_type; +} + int type_is_equal(const type_t *type1, const type_t *type2) { if (type1 == type2) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 96b681e0379..52ae2ec8677 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -36,6 +36,8 @@ attr_list_t *check_interface_attrs(const char *name, attr_list_t *attrs); attr_list_t *check_module_attrs(const char *name, attr_list_t *attrs); attr_list_t *check_runtimeclass_attrs(const char *name, attr_list_t *attrs);
+type_t *find_parameterized_type(type_t *type, type_list_t *params); + type_t *type_new_function(var_list_t *args); type_t *type_new_pointer(type_t *ref); type_t *type_new_alias(const decl_spec_t *t, const char *name); @@ -64,6 +66,7 @@ type_t *type_apicontract_declare(char *name, struct namespace *namespace); type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs); type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, type_list_t *params); type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, type_t *inherit, statement_list_t *stmts, ifref_list_t *requires); +type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params); int type_is_equal(const type_t *type1, const type_t *type2); const char *type_get_name(const type_t *type, enum name_type name_type); char *gen_name(void); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 7596577493d..ce48567d583 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -650,6 +650,7 @@ void init_loc_info(loc_info_t *);
char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix); +char *format_parameterized_type_name(type_t *type, type_list_t *params);
static inline enum type_type type_get_type_detect_alias(const type_t *type) {