And add IVectorView<T> and IIterator<T> parameterized interfaces to windows.foundation.idl for illustration and future use. They won't generate any additional code until they are fully specialized.
This is a WIDL-specific feature, but MIDL has some magic knowledge of these Windows.Foundation.Collections interface templates, and we need a way to instruct WIDL about them too.
Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef is easier and more flexible than re-creating the types by hand in WIDL source.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.idl | 29 +++++++++++ tools/widl/expr.c | 2 + tools/widl/header.c | 8 +-- tools/widl/parser.y | 93 +++++++++++++++++++++++++++++----- tools/widl/typegen.c | 6 +++ tools/widl/typelib.c | 2 + tools/widl/typetree.c | 39 ++++++++++++++ tools/widl/typetree.h | 4 ++ tools/widl/widltypes.h | 9 ++++ 9 files changed, 177 insertions(+), 15 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 5e17062f399..ab7c4753c3b 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -111,5 +111,34 @@ namespace Windows { { HRESULT ToString([out, retval] HSTRING *value); } + +#ifdef __WIDL__ + namespace Collections + { + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(6a79e863-4300-459a-9966-cbb660963ee1) + ] + interface IIterator<T> : IInspectable + { + [propget] HRESULT Current([out, retval] T *value); + [propget] HRESULT HasCurrent([out, retval] BOOL *value); + HRESULT MoveNext([out, retval] BOOL *value); + HRESULT GetMany([in] UINT32 count, [out] T *items, [out, retval] UINT32 *value); + } + + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(bbe1fa4c-b0e3-4583-baef-1f1b2e483e56) + ] + interface IVectorView<T> : IInspectable + { + HRESULT GetAt([in] ULONG index, [out, retval] T *value); + [propget] HRESULT Size([out, retval] ULONG *value); + HRESULT IndexOf([in, optional] T element, [out] ULONG *index, [out, retval] BOOLEAN *value); + HRESULT GetMany([in] ULONG start_index, [out] T *items, [out, retval] ULONG *value); + } + } +#endif } } diff --git a/tools/widl/expr.c b/tools/widl/expr.c index 13bd5a889aa..c83e9aa5ec0 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -464,6 +464,8 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_BITFIELD: case TYPE_APICONTRACT: case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* nothing to do */ break; case TYPE_ALIAS: diff --git a/tools/widl/header.c b/tools/widl/header.c index e6394991317..8423756e060 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -488,6 +488,8 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i break; } case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* shouldn't be here */ assert(0); break; @@ -555,6 +557,8 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* not supposed to be here */ assert(0); break; @@ -1864,10 +1868,8 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons write_apicontract(header, stmt->u.type); else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS) write_runtimeclass(header, stmt->u.type); - else - { + else if (type_get_type(stmt->u.type) != TYPE_PARAMETERIZED_TYPE) write_type_definition(header, stmt->u.type, stmt->declonly); - } break; case STMT_TYPEREF: /* FIXME: shouldn't write out forward declarations for undefined diff --git a/tools/widl/parser.y b/tools/widl/parser.y index a6128074f2d..3250320648d 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -38,12 +38,6 @@ #include "expr.h" #include "typetree.h"
-typedef struct list typelist_t; -struct typenode { - type_t *type; - struct list entry; -}; - struct _import_t { char *name; @@ -51,6 +45,8 @@ 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, @@ -82,6 +78,8 @@ static var_t *reg_const(var_t *var);
static void push_namespace(const char *name); static void pop_namespace(const char *name); +static void push_parameters_namespace(const char *name); +static void pop_parameters_namespace(const char *name);
static void check_arg_attrs(const var_t *arg); static void check_statements(const statement_list_t *stmts, int is_inside_library); @@ -119,6 +117,7 @@ static struct namespace global_namespace = { };
static struct namespace *current_namespace = &global_namespace; +static struct namespace *parameters_namespace = NULL;
static typelib_t *current_typelib;
@@ -130,6 +129,7 @@ static typelib_t *current_typelib; expr_t *expr; expr_list_t *expr_list; type_t *type; + type_list_t *type_list; var_t *var; var_list_t *var_list; declarator_t *declarator; @@ -292,6 +292,8 @@ static typelib_t *current_typelib; %type <type> base_type int_std %type <type> enumdef structdef uniondef typedecl %type <type> type unqualified_type qualified_type +%type <type> type_parameter +%type <type_list> type_parameters %type <ifref> class_interface %type <ifref_list> class_interfaces %type <ifref_list> requires required_types @@ -966,7 +968,18 @@ inherit: { $$ = NULL; } | ':' qualified_type { $$ = $2; } ;
-interface: tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); } +type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } + ; + +type_parameters: + type_parameter { $$ = append_type(NULL, $1); } + | type_parameters ',' type_parameter { $$ = append_type($1, $3); } + ; + +interface: + tINTERFACE typename { $$ = type_interface_declare($2, current_namespace); } + | tINTERFACE typename '<' { push_parameters_namespace($2); } type_parameters { pop_parameters_namespace($2); } '>' + { $$ = type_parameterized_interface_declare($2, current_namespace, $5); } ;
required_types: @@ -977,9 +990,18 @@ requires: { $$ = NULL; } | tREQUIRES required_types { $$ = $2; } ;
-interfacedef: attributes interface inherit requires - '{' int_statements '}' semicolon_opt { $$ = type_interface_define($2, $1, $3, $6, $4); - check_async_uuid($$); +interfacedef: attributes interface { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) push_parameters_namespace($2->name); } + inherit requires '{' int_statements '}' semicolon_opt + { if ($2->type_type == TYPE_PARAMETERIZED_TYPE) + { + $$ = type_parameterized_interface_define($2, $1, $4, $7, $5); + pop_parameters_namespace($2->name); + } + else + { + $$ = type_interface_define($2, $1, $4, $7, $5); + check_async_uuid($$); + } } | dispinterfacedef semicolon_opt { $$ = $1; } ; @@ -1808,6 +1830,26 @@ static ifref_t *make_ifref(type_t *iface) return l; }
+static type_list_t *append_type(type_list_t *list, type_t *type) +{ + type_list_t *entry; + if (!type) return list; + entry = xmalloc( sizeof(*entry) ); + entry->type = type; + entry->next = list; + 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; @@ -1942,6 +1984,29 @@ static void pop_namespace(const char *name) current_namespace = current_namespace->parent; }
+static void push_parameters_namespace(const char *name) +{ + struct namespace *namespace; + + if (!(namespace = find_sub_namespace(current_namespace, name))) + { + namespace = xmalloc(sizeof(*namespace)); + namespace->name = xstrdup(name); + namespace->parent = current_namespace; + list_add_tail(¤t_namespace->children, &namespace->entry); + list_init(&namespace->children); + memset(namespace->type_hash, 0, sizeof(namespace->type_hash)); + } + + parameters_namespace = namespace; +} + +static void pop_parameters_namespace(const char *name) +{ + assert(!strcmp(parameters_namespace->name, name) && parameters_namespace->parent); + parameters_namespace = NULL; +} + struct rtype { const char *name; type_t *type; @@ -2054,7 +2119,8 @@ type_t *find_type(const char *name, struct namespace *namespace, int t) static type_t *find_type_or_error(struct namespace *namespace, const char *name) { type_t *type; - if (!(type = find_type(name, namespace, 0))) + if (!(type = find_type(name, namespace, 0)) && + !(type = find_type(name, parameters_namespace, 0))) { error_loc("type '%s' not found in %s namespace\n", name, namespace && namespace->name ? namespace->name : "global"); return NULL; @@ -2076,7 +2142,8 @@ static struct namespace *find_namespace_or_error(struct namespace *parent, const
int is_type(const char *name) { - return find_type(name, current_namespace, 0) != NULL; + return find_type(name, current_namespace, 0) != NULL || + find_type(name, parameters_namespace, 0); }
type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t) @@ -2568,6 +2635,8 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_RUNTIMECLASS: return FALSE; case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* not supposed to be here */ assert(0); break; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 2e9be0748c1..1b5fe16b6ec 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -377,6 +377,8 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_RUNTIMECLASS: break; case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* not supposed to be here */ assert(0); break; @@ -1974,6 +1976,8 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_BITFIELD: case TYPE_APICONTRACT: case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or @@ -2077,6 +2081,8 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_BITFIELD: case TYPE_APICONTRACT: case TYPE_RUNTIMECLASS: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* these types should not be encountered here due to language * restrictions (interface, void, coclass, module), logical * restrictions (alias - due to type_get_type call above) or diff --git a/tools/widl/typelib.c b/tools/widl/typelib.c index ace6424e3a0..6f6c5f3ccc8 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -226,6 +226,8 @@ unsigned short get_type_vt(type_t *t)
case TYPE_ALIAS: case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: /* not supposed to be here */ assert(0); break; diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 3c2f183eb13..f696d30a5f5 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -619,6 +619,45 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; }
+type_t *type_parameterized_interface_declare(char *name, struct namespace *namespace, type_list_t *params) +{ + type_t *type = get_type(TYPE_PARAMETERIZED_TYPE, name, namespace, 0); + if (type_get_type_detect_alias(type) != TYPE_PARAMETERIZED_TYPE) + error_loc("pinterface %s previously not declared a pinterface at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->details.parameterized.type = make_type(TYPE_INTERFACE); + type->details.parameterized.params = params; + return type; +} + +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 *iface; + if (type->defined) + error_loc("pinterface %s already defined at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + + /* The parameterized type UUID is actually a PIID that is then used as a seed to generate + * a new type GUID with the rules described in: + * https://docs.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#parameteri... + * TODO: store type signatures for generated interfaces, and generate their GUIDs + */ + type->attrs = check_interface_attrs(type->name, attrs); + + iface = type->details.parameterized.type; + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_props = NULL; + iface->details.iface->disp_methods = NULL; + iface->details.iface->stmts = stmts; + iface->details.iface->inherit = inherit; + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = requires; + + type->defined = TRUE; + return 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 9866d2a1e98..96b681e0379 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -62,6 +62,8 @@ type_t *type_coclass_define(type_t *coclass, attr_list_t *attrs, ifref_list_t *i type_t *type_runtimeclass_define(type_t *runtimeclass, attr_list_t *attrs, ifref_list_t *ifaces); 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); 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); @@ -246,6 +248,8 @@ static inline int type_is_complete(const type_t *type) case TYPE_RUNTIMECLASS: return TRUE; case TYPE_APICONTRACT: + case TYPE_PARAMETERIZED_TYPE: + case TYPE_PARAMETER: assert(0); break; } diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index e22d425e85b..7596577493d 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -436,6 +436,12 @@ struct runtimeclass_details ifref_list_t *ifaces; };
+struct parameterized_details +{ + type_t *type; + type_list_t *params; +}; + #define HASHMAX 64
struct namespace { @@ -464,6 +470,8 @@ enum type_type TYPE_BITFIELD, TYPE_APICONTRACT, TYPE_RUNTIMECLASS, + TYPE_PARAMETERIZED_TYPE, + TYPE_PARAMETER, };
struct _type_t { @@ -485,6 +493,7 @@ struct _type_t { struct bitfield_details bitfield; struct alias_details alias; struct runtimeclass_details runtimeclass; + struct parameterized_details parameterized; } details; const char *c_name; unsigned int typestring_offset;
And use it for format_namespace to grow buffer as needed.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/typetree.c | 46 ++++++++++++++----------------------------- tools/widl/utils.c | 37 ++++++++++++++++++++++++++++++++++ tools/widl/utils.h | 1 + 3 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index f696d30a5f5..203fffcdee6 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -89,41 +89,25 @@ const char *type_get_name(const type_t *type, enum name_type name_type) return NULL; }
-static char *append_namespace(char *ptr, struct namespace *namespace, const char *separator, const char *abi_prefix) +static size_t append_namespace(char **buf, size_t *len, size_t pos, struct namespace *namespace, const char *separator, const char *abi_prefix) { - if(is_global_namespace(namespace)) { - if(!abi_prefix) return ptr; - strcpy(ptr, abi_prefix); - strcat(ptr, separator); - return ptr + strlen(ptr); - } - - ptr = append_namespace(ptr, namespace->parent, separator, abi_prefix); - strcpy(ptr, namespace->name); - strcat(ptr, separator); - return ptr + strlen(ptr); + int nested = namespace && !is_global_namespace(namespace); + const char *name = nested ? namespace->name : abi_prefix; + size_t n = 0; + if (!name) return 0; + if (nested) n += append_namespace(buf, len, pos + n, namespace->parent, separator, abi_prefix); + n += strappend(buf, len, pos + n, "%s%s", name, separator); + return n; }
-char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, - const char *abi_prefix) +char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix, const char *abi_prefix) { - unsigned len = strlen(prefix) + strlen(suffix); - unsigned sep_len = strlen(separator); - struct namespace *iter; - char *ret, *ptr; - - if(abi_prefix) - len += strlen(abi_prefix) + sep_len; - - for(iter = namespace; !is_global_namespace(iter); iter = iter->parent) - len += strlen(iter->name) + sep_len; - - ret = xmalloc(len+1); - strcpy(ret, prefix); - ptr = append_namespace(ret + strlen(ret), namespace, separator, abi_prefix); - strcpy(ptr, suffix); - - return ret; + 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); + return buf; }
type_t *type_new_function(var_list_t *args) diff --git a/tools/widl/utils.c b/tools/widl/utils.c index ea92372c8c7..634bd12a0ba 100644 --- a/tools/widl/utils.c +++ b/tools/widl/utils.c @@ -245,6 +245,43 @@ char *strmake( const char* fmt, ... ) } }
+size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) +{ + size_t size; + va_list ap; + char *ptr; + int n; + + assert( buf && len ); + assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) ); + + if (*buf) + { + size = *len; + ptr = *buf; + } + else + { + size = 100; + ptr = xmalloc( size ); + } + + for (;;) + { + va_start( ap, fmt ); + n = vsnprintf( ptr + pos, size - pos, fmt, ap ); + va_end( ap ); + if (n == -1) size *= 2; + else if (pos + (size_t)n >= size) size = pos + n + 1; + else break; + ptr = xrealloc( ptr, size ); + } + + *len = size; + *buf = ptr; + return n; +} + char *xstrdup(const char *str) { char *s; diff --git a/tools/widl/utils.h b/tools/widl/utils.h index 37406656504..82e0a6ae489 100644 --- a/tools/widl/utils.h +++ b/tools/widl/utils.h @@ -45,6 +45,7 @@ void warning(const char *s, ...) __attribute__((format (printf, 1, 2))); void warning_loc_info(const loc_info_t *, const char *s, ...) __attribute__((format (printf, 2, 3))); void chat(const char *s, ...) __attribute__((format (printf, 1, 2))); char *strmake(const char* fmt, ...) __attribute__((__format__ (__printf__, 1, 2 ))); +size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...) __attribute__((__format__ (__printf__, 4, 5 )));
char *dup_basename(const char *name, const char *ext); size_t widl_getline(char **linep, size_t *lenp, FILE *fp);
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 --- include/windows.foundation.idl | 9 ++++++++ tools/widl/parser.y | 36 +++++++++++++++++++++++++++++ tools/widl/typetree.c | 41 +++++++++++++++++++++++++++++++--- tools/widl/typetree.h | 3 +++ tools/widl/widltypes.h | 1 + 5 files changed, 87 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 3250320648d..7ef16d90456 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -294,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_types %type <ifref> class_interface %type <ifref_list> class_interfaces %type <ifref_list> requires required_types @@ -910,6 +912,20 @@ qualified_type: | namespace_pfx typename { $$ = find_type_or_error($1, $2); } ;
+parameterized_type: qualified_type '<' parameterized_types '>' + { $$ = find_parameterized_type($1, $3); } + ; + +parameterized_types: + 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_types ',' parameterized_types + { $$ = append_types($1, $3); } + ; + coclass: tCOCLASS typename { $$ = type_coclass_declare($2); } ;
@@ -966,6 +982,7 @@ dispinterfacedef:
inherit: { $$ = NULL; } | ':' qualified_type { $$ = $2; } + | ':' parameterized_type { $$ = $2; } ;
type_parameter: typename { $$ = get_type(TYPE_PARAMETER, $1, parameters_namespace, 0); } @@ -984,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; } @@ -1208,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 @@ -3279,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) {
This allows parameterized interfaces to be instanciated in declare blocks, in the same way MIDL does, generating a new interface to the header from the parameterized type template, replacing its parameters with the given types.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.media.speechsynthesis.idl | 24 +++ tools/widl/header.c | 7 +- tools/widl/parser.l | 1 + tools/widl/parser.y | 63 +++++- tools/widl/typetree.c | 238 ++++++++++++++++++++++ tools/widl/typetree.h | 2 + 6 files changed, 330 insertions(+), 5 deletions(-)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 87497678f30..af4466681dc 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -35,11 +35,24 @@ namespace Windows { interface ISpeechSynthesizer; interface ISpeechSynthesizer2; interface IVoiceInformation; + runtimeclass SpeechSynthesizer; runtimeclass VoiceInformation; } } }
+namespace Windows { + namespace Media { + namespace SpeechSynthesis { + declare { + interface Windows.Foundation.Collections.IIterator<Windows.Media.SpeechSynthesis.VoiceInformation*>; + interface Windows.Foundation.Collections.IIterable<Windows.Media.SpeechSynthesis.VoiceInformation*>; + interface Windows.Foundation.Collections.IVectorView<Windows.Media.SpeechSynthesis.VoiceInformation*>; + } + } + } +} + namespace Windows { namespace Media { namespace SpeechSynthesis { @@ -64,6 +77,17 @@ namespace Windows { [propget] HRESULT Gender([out] [retval] VoiceGender* value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer), + uuid(7d526ecc-7533-4c3f-85be-888c2baeebdc) + ] + interface IInstalledVoicesStatic : IInspectable + { + [propget] HRESULT AllVoices([out, retval] Windows.Foundation.Collections.IVectorView<VoiceInformation*>** value); + [propget] HRESULT DefaultVoice([out, retval] VoiceInformation** value); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile) diff --git a/tools/widl/header.c b/tools/widl/header.c index 8423756e060..a4f1db56a01 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -1479,7 +1479,8 @@ static void write_forward(FILE *header, type_t *iface) fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name); fprintf(header, "#ifdef __cplusplus\n"); write_namespace_start(header, iface->namespace); - write_line(header, 0, "interface %s;", iface->name); + if (strchr(iface->name, '<')) write_line(header, 0, "template<> struct %s;", iface->name); + else write_line(header, 0, "interface %s;", iface->name); write_namespace_end(header, iface->namespace); fprintf(header, "#endif /* __cplusplus */\n"); fprintf(header, "#endif\n\n" ); @@ -1548,11 +1549,13 @@ static void write_com_interface_end(FILE *header, type_t *iface) write_namespace_start(header, iface->namespace); } if (uuid) { + if (strchr(iface->name, '<')) write_line(header, 0, "template<>"); write_line(header, 0, "MIDL_INTERFACE("%s")", uuid_string(uuid)); indent(header, 0); }else { indent(header, 0); - fprintf(header, "interface "); + if (strchr(iface->name, '<')) fprintf(header, "template<> struct "); + else fprintf(header, "interface "); } if (type_iface_get_inherit(iface)) { diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 946dba84cd6..d319954edd3 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -276,6 +276,7 @@ static const struct keyword keywords[] = { {"coclass", tCOCLASS, 0}, {"const", tCONST, 0}, {"cpp_quote", tCPPQUOTE, 0}, + {"declare", tDECLARE, 1}, {"default", tDEFAULT, 0}, {"dispinterface", tDISPINTERFACE, 0}, {"double", tDOUBLE, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 7ef16d90456..345530b495a 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -81,6 +81,7 @@ static void pop_namespace(const char *name); static void push_parameters_namespace(const char *name); static void pop_parameters_namespace(const char *name);
+static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts); static void check_arg_attrs(const var_t *arg); static void check_statements(const statement_list_t *stmts, int is_inside_library); static void check_all_user_types(const statement_list_t *stmts); @@ -108,6 +109,7 @@ static statement_t *make_statement_importlib(const char *str); static statement_t *make_statement_module(type_t *type); static statement_t *make_statement_typedef(var_list_t *names, int declonly); static statement_t *make_statement_import(const char *str); +static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params); static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); static statement_list_t *append_statements(statement_list_t *, statement_list_t *); static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); @@ -118,6 +120,7 @@ static struct namespace global_namespace = {
static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; +static statement_list_t *parameterized_type_stmts = NULL;
static typelib_t *current_typelib;
@@ -180,6 +183,7 @@ static typelib_t *current_typelib; %token tCONTRACTVERSION %token tCONTROL tCPPQUOTE %token tCUSTOM +%token tDECLARE %token tDECODE tDEFAULT tDEFAULTBIND %token tDEFAULTCOLLELEM %token tDEFAULTVALUE @@ -320,6 +324,8 @@ static typelib_t *current_typelib; %type <typelib> library_start librarydef %type <statement> statement typedef pragma_warning %type <stmt_list> gbl_statements imp_statements int_statements +%type <stmt_list> decl_block decl_statements +%type <stmt_list> imp_decl_block imp_decl_statements %type <warning_list> warnings %type <num> allocate_option_list allocate_option %type <namespace> namespace_pfx @@ -343,7 +349,8 @@ static typelib_t *current_typelib;
%%
-input: gbl_statements m_acf { check_statements($1, FALSE); +input: gbl_statements m_acf { $1 = append_parameterized_type_stmts($1); + check_statements($1, FALSE); check_all_user_types($1); write_header($1); write_id_data($1); @@ -359,6 +366,22 @@ input: gbl_statements m_acf { check_statements($1, FALSE);
m_acf: /* empty */ | aACF acf_statements
+decl_statements: { $$ = NULL; } + | decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';' + { parameterized_type_stmts = append_statement(parameterized_type_stmts, make_statement_parameterized_type($3, $5)); + $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); + } + ; + +decl_block: tDECLARE '{' decl_statements '}' { $$ = $3; } + +imp_decl_statements: { $$ = NULL; } + | imp_decl_statements tINTERFACE qualified_type '<' parameterized_types '>' ';' + { $$ = append_statement($1, make_statement_reference(type_parameterized_type_specialize_declare($3, $5))); } + ; + +imp_decl_block: tDECLARE '{' imp_decl_statements '}' { $$ = $3; } + gbl_statements: { $$ = NULL; } | gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}' { pop_namespace($2); $$ = append_statements($1, $5); } @@ -380,6 +403,7 @@ gbl_statements: { $$ = NULL; } | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements statement { $$ = append_statement($1, $2); } + | gbl_statements decl_block { $$ = append_statements($1, $2); } ;
imp_statements: { $$ = NULL; } @@ -402,6 +426,7 @@ imp_statements: { $$ = NULL; } | imp_statements statement { $$ = append_statement($1, $2); } | imp_statements importlib { $$ = append_statement($1, make_statement_importlib($2)); } | imp_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } + | imp_statements imp_decl_block { $$ = append_statements($1, $2); } ;
int_statements: { $$ = NULL; } @@ -3084,6 +3109,27 @@ static void check_async_uuid(type_t *iface) iface->details.iface->async_iface = async_iface->details.iface->async_iface = async_iface; }
+static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts) +{ + statement_t *stmt, *next; + if (stmts && parameterized_type_stmts) LIST_FOR_EACH_ENTRY_SAFE(stmt, next, parameterized_type_stmts, statement_t, entry) + { + switch(stmt->type) { + case STMT_TYPE: + stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type_list->type, stmt->u.type_list->next); + stmt->declonly = FALSE; + list_remove(&stmt->entry); + stmts = append_statement(stmts, stmt); + break; + default: + assert(0); /* should not be there */ + break; + } + } + + return stmts; +} + static void check_statements(const statement_list_t *stmts, int is_inside_library) { const statement_t *stmt; @@ -3265,6 +3311,15 @@ static statement_t *make_statement_typedef(declarator_list_t *decls, int declonl return stmt; }
+static statement_t *make_statement_parameterized_type(type_t *type, type_list_t *params) +{ + statement_t *stmt = make_statement(STMT_TYPE); + stmt->u.type_list = xmalloc(sizeof(type_list_t)); + stmt->u.type_list->type = type; + stmt->u.type_list->next = params; + return stmt; +} + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) { if (!l2) return l1; @@ -3309,8 +3364,10 @@ type_t *find_parameterized_type(type_t *type, type_list_t *params) 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); + else if ((type = find_type(name, type->namespace, 0))) + assert(type->type_type != TYPE_PARAMETERIZED_TYPE); + 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 22c75d32161..58b019cc090 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -137,6 +137,41 @@ char *format_parameterized_type_name(type_t *type, type_list_t *params) return buf; }
+static char const *parameterized_type_shorthands[][2] = { + {"Windows_CFoundation_CCollections_C", "__F"}, + {"Windows_CFoundation_C", "__F"}, +}; + +static char *format_parameterized_type_c_name(type_t *type, type_list_t *params) +{ + size_t len = 0, pos = 0; + char *buf = NULL, *tmp; + type_list_t *entry; + int i, count = 0; + + pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", type->name, use_abi_namespace ? "ABI" : NULL); + for (entry = params; entry; entry = entry->next) count++; + pos += strappend(&buf, &len, pos, "_%d", count); + 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, "_", "__C", type->name, NULL); + } + + for (i = 0; i < ARRAY_SIZE(parameterized_type_shorthands); ++i) + { + if ((tmp = strstr(buf, parameterized_type_shorthands[i][0])) && + (tmp - buf) == strlen(use_abi_namespace ? "__x_ABI_C" : "__x_C")) + { + tmp += strlen(parameterized_type_shorthands[i][0]); + strcpy(buf, parameterized_type_shorthands[i][1]); + memmove(buf + 3, tmp, len - (tmp - buf) + 1); + } + } + + return buf; +} + type_t *type_new_function(var_list_t *args) { var_t *arg; @@ -677,6 +712,209 @@ type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *pa return new_type; }
+static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl); + +static type_list_t *replace_type_parameters_in_type_list(type_list_t *type_list, type_list_t *orig, type_list_t *repl) +{ + type_list_t *entry, *new_entry, **next, *first = NULL; + + if (!type_list) return type_list; + + next = &first; + for (entry = type_list; entry; entry = entry->next) + { + new_entry = xmalloc(sizeof(*new_entry)); + new_entry->type = replace_type_parameters_in_type(entry->type, orig, repl); + new_entry->next = NULL; + *next = new_entry; + next = &new_entry->next; + } + + return first; +} + +static var_t *replace_type_parameters_in_var(var_t *var, type_list_t *orig, type_list_t *repl) +{ + var_t *new_var = xmalloc(sizeof(*new_var)); + *new_var = *var; + list_init(&new_var->entry); + new_var->declspec.type = replace_type_parameters_in_type(var->declspec.type, orig, repl); + return new_var; +} + +static var_list_t *replace_type_parameters_in_var_list(var_list_t *var_list, type_list_t *orig, type_list_t *repl) +{ + var_list_t *new_var_list; + var_t *var, *new_var; + + if (!var_list) return var_list; + + new_var_list = xmalloc(sizeof(*new_var_list)); + list_init(new_var_list); + + LIST_FOR_EACH_ENTRY(var, var_list, var_t, entry) + { + new_var = replace_type_parameters_in_var(var, orig, repl); + list_add_tail(new_var_list, &new_var->entry); + } + + return new_var_list; +} + +static statement_t *replace_type_parameters_in_statement(statement_t *stmt, type_list_t *orig, type_list_t *repl) +{ + statement_t *new_stmt = xmalloc(sizeof(*new_stmt)); + *new_stmt = *stmt; + list_init(&new_stmt->entry); + + switch (stmt->type) + { + case STMT_DECLARATION: + new_stmt->u.var = replace_type_parameters_in_var(stmt->u.var, orig, repl); + break; + case STMT_LIBRARY: + case STMT_TYPE: + case STMT_TYPEREF: + case STMT_MODULE: + case STMT_TYPEDEF: + new_stmt->u.type_list = replace_type_parameters_in_type_list(stmt->u.type_list, orig, repl); + break; + case STMT_IMPORT: + case STMT_IMPORTLIB: + case STMT_PRAGMA: + case STMT_CPPQUOTE: + fprintf(stderr, "%d\n", stmt->type); + assert(0); + break; + } + + return new_stmt; +} + +static statement_list_t *replace_type_parameters_in_statement_list(statement_list_t *stmt_list, type_list_t *orig, type_list_t *repl) +{ + statement_list_t *new_stmt_list; + statement_t *stmt, *new_stmt; + + if (!stmt_list) return stmt_list; + + new_stmt_list = xmalloc(sizeof(*new_stmt_list)); + list_init(new_stmt_list); + + LIST_FOR_EACH_ENTRY(stmt, stmt_list, statement_t, entry) + { + new_stmt = replace_type_parameters_in_statement(stmt, orig, repl); + list_add_tail(new_stmt_list, &new_stmt->entry); + } + + return new_stmt_list; +} + +static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, type_list_t *repl) +{ + type_list_t *o, *r; + type_t *t; + + if (!type) return type; + switch (type->type_type) + { + case TYPE_VOID: + case TYPE_BASIC: + case TYPE_ENUM: + case TYPE_BITFIELD: + case TYPE_INTERFACE: + case TYPE_RUNTIMECLASS: + return type; + case TYPE_PARAMETER: + for (o = orig, r = repl; o && r; o = o->next, r = r->next) + if (type == o->type) return r->type; + return type; + case TYPE_POINTER: + t = replace_type_parameters_in_type(type->details.pointer.ref.type, orig, repl); + if (t == type->details.pointer.ref.type) return type; + type = duptype(type, 0); + type->details.pointer.ref.type = t; + return type; + case TYPE_ALIAS: + t = replace_type_parameters_in_type(type->details.alias.aliasee.type, orig, repl); + if (t == type->details.alias.aliasee.type) return type; + type = duptype(type, 0); + type->details.alias.aliasee.type = t; + return type; + case TYPE_ARRAY: + t = replace_type_parameters_in_type(type->details.array.elem.type, orig, repl); + if (t == t->details.array.elem.type) return type; + type = duptype(type, 0); + t->details.array.elem.type = t; + return type; + case TYPE_FUNCTION: + t = duptype(type, 0); + t->details.function = xmalloc(sizeof(*t->details.function)); + t->details.function->args = replace_type_parameters_in_var_list(type->details.function->args, orig, repl); + t->details.function->retval = replace_type_parameters_in_var(type->details.function->retval, orig, repl); + return t; + case TYPE_PARAMETERIZED_TYPE: + t = type->details.parameterized.type; + if (t->type_type != TYPE_PARAMETERIZED_TYPE) return find_parameterized_type(type, repl); + repl = replace_type_parameters_in_type_list(type->details.parameterized.params, orig, repl); + return replace_type_parameters_in_type(t, t->details.parameterized.params, repl); + case TYPE_STRUCT: + case TYPE_ENCAPSULATED_UNION: + case TYPE_UNION: + case TYPE_MODULE: + case TYPE_COCLASS: + case TYPE_APICONTRACT: + assert(0); /* FIXME: implement when needed */ + break; + } + + return type; +} + +static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, type_list_t *orig, type_list_t *repl) +{ + iface->details.iface = xmalloc(sizeof(*iface->details.iface)); + iface->details.iface->disp_methods = NULL; + iface->details.iface->disp_props = NULL; + iface->details.iface->stmts = replace_type_parameters_in_statement_list(tmpl->details.iface->stmts, orig, repl); + iface->details.iface->inherit = replace_type_parameters_in_type(tmpl->details.iface->inherit, orig, repl); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; +} + +type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params) +{ + type_t *tmpl = type->details.parameterized.type; + type_t *new_type = duptype(tmpl, 0); + + new_type->namespace = type->namespace; + new_type->name = format_parameterized_type_name(type, params); + reg_type(new_type, new_type->name, new_type->namespace, 0); + new_type->c_name = format_parameterized_type_c_name(type, params); + + return new_type; +} + +type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *params) +{ + type_list_t *orig = type->details.parameterized.params; + type_t *tmpl = type->details.parameterized.type; + type_t *iface = find_parameterized_type(type, params); + + if (tmpl->type_type == TYPE_INTERFACE) + type_parameterized_interface_specialize(tmpl, iface, orig, params); + else + { + error_loc("Unsupported parameterized type template %d\n", tmpl->type_type); + return NULL; + } + + iface->defined = TRUE; + compute_method_indexes(iface); + return iface; +} + 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 52ae2ec8677..0dc75dff62e 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -67,6 +67,8 @@ 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); +type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params); +type_t *type_parameterized_type_specialize_define(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);
Hi Rémi,
On 10.02.2021 10:02, Rémi Bernon wrote:
And add IVectorView<T> and IIterator<T> parameterized interfaces to windows.foundation.idl for illustration and future use. They won't generate any additional code until they are fully specialized.
This is a WIDL-specific feature, but MIDL has some magic knowledge of these Windows.Foundation.Collections interface templates, and we need a way to instruct WIDL about them too.
Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef is easier and more flexible than re-creating the types by hand in WIDL source.
The general approach looks good to me, but it looks like splitting patches went wrong:
tools/widl/parser.y:1843:21: warning: ‘append_types’ defined but not used [-Wunused-function]
Thanks,
Jacek
On 2/11/21 4:26 PM, Jacek Caban wrote:
Hi Rémi,
On 10.02.2021 10:02, Rémi Bernon wrote:
And add IVectorView<T> and IIterator<T> parameterized interfaces to windows.foundation.idl for illustration and future use. They won't generate any additional code until they are fully specialized.
This is a WIDL-specific feature, but MIDL has some magic knowledge of these Windows.Foundation.Collections interface templates, and we need a way to instruct WIDL about them too.
Having these interfaces declared in the IDL, guarded with __WIDL__ ifdef is easier and more flexible than re-creating the types by hand in WIDL source.
The general approach looks good to me, but it looks like splitting patches went wrong:
tools/widl/parser.y:1843:21: warning: ‘append_types’ defined but not used [-Wunused-function]
Thanks,
Jacek
Oops yes, good catch thanks.
This helper was previously in the requires keyword patch. I moved it to later patches but missed the right one and missed the warning too. Sorry.
I'll send an update.