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) {
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 0725332a736..9f5c12fd922 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_type_args '>' ';' + { 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_type_args '>' ';' + { $$ = 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);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- tools/widl/expr.c | 1 + tools/widl/header.c | 16 +++++++++----- tools/widl/parser.l | 1 + tools/widl/parser.y | 20 +++++++++++++++++ tools/widl/typegen.c | 4 ++++ tools/widl/typelib.c | 1 + tools/widl/typetree.c | 49 ++++++++++++++++++++++++++++++++++++++++++ tools/widl/typetree.h | 10 +++++++++ tools/widl/widltypes.h | 7 ++++++ 9 files changed, 104 insertions(+), 5 deletions(-)
diff --git a/tools/widl/expr.c b/tools/widl/expr.c index c83e9aa5ec0..88d59290d6b 100644 --- a/tools/widl/expr.c +++ b/tools/widl/expr.c @@ -466,6 +466,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type, case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* nothing to do */ break; case TYPE_ALIAS: diff --git a/tools/widl/header.c b/tools/widl/header.c index a4f1db56a01..7ab79d3b6e1 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -470,6 +470,9 @@ void write_type_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, i case TYPE_RUNTIMECLASS: fprintf(h, "%s", type_get_name(type_runtimeclass_get_default_iface(t), name_type)); break; + case TYPE_DELEGATE: + fprintf(h, "%s", type_get_name(type_delegate_get_iface(t), name_type)); + break; case TYPE_VOID: fprintf(h, "void"); break; @@ -555,6 +558,7 @@ void write_type_right(FILE *h, type_t *t, int is_field) case TYPE_COCLASS: case TYPE_INTERFACE: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: break; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -974,7 +978,7 @@ int has_out_arg_or_return(const var_t *func) int is_object(const type_t *iface) { const attr_t *attr; - if (type_is_defined(iface) && type_iface_get_inherit(iface)) + if (type_is_defined(iface) && (type_get_type(iface) == TYPE_DELEGATE || type_iface_get_inherit(iface))) return 1; if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry ) if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; @@ -1799,9 +1803,10 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts) switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { type_t *iface = stmt->u.type; + if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) { write_forward(header, iface); @@ -1841,10 +1846,11 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons switch (stmt->type) { case STMT_TYPE: - if (type_get_type(stmt->u.type) == TYPE_INTERFACE) + if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE) { - type_t *iface = stmt->u.type; - type_t *async_iface = type_iface_get_async_iface(iface); + type_t *iface = stmt->u.type, *async_iface; + if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface); + async_iface = type_iface_get_async_iface(iface); if (is_object(iface)) is_object_interface++; if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type)) { diff --git a/tools/widl/parser.l b/tools/widl/parser.l index d319954edd3..f5e91dc741a 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -278,6 +278,7 @@ static const struct keyword keywords[] = { {"cpp_quote", tCPPQUOTE, 0}, {"declare", tDECLARE, 1}, {"default", tDEFAULT, 0}, + {"delegate", tDELEGATE, 1}, {"dispinterface", tDISPINTERFACE, 0}, {"double", tDOUBLE, 0}, {"enum", tENUM, 0}, diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 9f5c12fd922..292090170e5 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -110,6 +110,7 @@ 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_t *make_statement_delegate(type_t *ret, var_list_t *args); 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 *); @@ -185,6 +186,7 @@ static typelib_t *current_typelib; %token tCUSTOM %token tDECLARE %token tDECODE tDEFAULT tDEFAULTBIND +%token tDELEGATE %token tDEFAULTCOLLELEM %token tDEFAULTVALUE %token tDEFAULTVTABLE @@ -283,6 +285,7 @@ static typelib_t *current_typelib; %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const %type <expr> contract_req %type <expr> static_attr +%type <type> delegatedef %type <stgclass> storage_cls_spec %type <type_qualifier> type_qualifier m_type_qual_list %type <function_specifier> function_specifier @@ -388,6 +391,7 @@ gbl_statements: { $$ = NULL; } | gbl_statements interface ';' { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements dispinterface ';' { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | gbl_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | gbl_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } @@ -412,6 +416,7 @@ imp_statements: { $$ = NULL; } | imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}' { pop_namespace($2); $$ = append_statements($1, $5); } | imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } + | imp_statements delegatedef { $$ = append_statement($1, make_statement_type_decl($2)); } | imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); } | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); reg_type($2, $2->name, current_namespace, 0); @@ -1024,6 +1029,12 @@ interface: { $$ = type_parameterized_interface_declare($2, current_namespace, $5); } ;
+delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt + { $$ = type_delegate_declare($4->name, current_namespace); + $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6))); + } + ; + required_types: qualified_type { $$ = append_ifref(NULL, make_ifref($1)); } | parameterized_type { $$ = append_ifref(NULL, make_ifref($1)); } @@ -2678,6 +2689,7 @@ static int is_allowed_conf_type(const type_t *type) case TYPE_INTERFACE: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return FALSE; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -3320,6 +3332,14 @@ static statement_t *make_statement_parameterized_type(type_t *type, type_list_t return stmt; }
+static statement_t *make_statement_delegate(type_t *ret, var_list_t *args) +{ + declarator_t *decl = make_declarator(make_var(xstrdup("Invoke"))); + decl_spec_t *spec = make_decl_spec(ret, NULL, NULL, STG_NONE, 0, 0); + append_chain_type(decl, type_new_function(args), 0); + return make_statement_declaration(declare_var(NULL, spec, decl, FALSE)); +} + static statement_list_t *append_statements(statement_list_t *l1, statement_list_t *l2) { if (!l2) return l1; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 1b5fe16b6ec..ec85f149da1 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -354,6 +354,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_POINTER: if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE || type_get_type(type_pointer_get_ref_type(type)) == TYPE_RUNTIMECLASS || + type_get_type(type_pointer_get_ref_type(type)) == TYPE_DELEGATE || (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) return TGT_IFACE_POINTER; else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE)) @@ -375,6 +376,7 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att case TYPE_ALIAS: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: break; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -1978,6 +1980,7 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* 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 @@ -2083,6 +2086,7 @@ static unsigned int type_buffer_alignment(const type_t *t) case TYPE_RUNTIMECLASS: case TYPE_PARAMETERIZED_TYPE: case TYPE_PARAMETER: + case TYPE_DELEGATE: /* 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 6f6c5f3ccc8..8b2a2401367 100644 --- a/tools/widl/typelib.c +++ b/tools/widl/typelib.c @@ -219,6 +219,7 @@ unsigned short get_type_vt(type_t *t) case TYPE_UNION: case TYPE_ENCAPSULATED_UNION: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return VT_USERDEFINED;
case TYPE_VOID: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 58b019cc090..1ab41a488ca 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -665,6 +665,54 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; }
+static void compute_delegate_iface_names(type_t *delegate) +{ + type_t *iface = delegate->details.delegate.iface; + iface->namespace = delegate->namespace; + iface->name = strmake("I%s", delegate->name); + iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL); +} + +type_t *type_delegate_declare(char *name, struct namespace *namespace) +{ + type_t *type = get_type(TYPE_DELEGATE, name, NULL, 0); + if (type_get_type_detect_alias(type) != TYPE_DELEGATE) + error_loc("delegate %s previously not declared a delegate at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + return type; +} + +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts) +{ + type_t *iface; + + if (delegate->defined) + error_loc("delegate %s already defined at %s:%d\n", + delegate->name, delegate->loc_info.input_name, delegate->loc_info.line_number); + + delegate->attrs = check_interface_attrs(delegate->name, attrs); + + iface = make_type(TYPE_INTERFACE); + iface->attrs = delegate->attrs; + 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 = find_type("IUnknown", NULL, 0); + if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; + iface->defined = TRUE; + compute_method_indexes(iface); + + delegate->details.delegate.iface = iface; + delegate->defined = TRUE; + compute_delegate_iface_names(delegate); + + return delegate; +} + 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); @@ -824,6 +872,7 @@ static type_t *replace_type_parameters_in_type(type_t *type, type_list_t *orig, case TYPE_BITFIELD: case TYPE_INTERFACE: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return type; case TYPE_PARAMETER: for (o = orig, r = repl; o && r; o = o->next, r = r->next) diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 0dc75dff62e..13d6a4d51fb 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -64,6 +64,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_delegate_declare(char *name, struct namespace *namespace); +type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts); 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); @@ -251,6 +253,7 @@ static inline int type_is_complete(const type_t *type) case TYPE_ARRAY: case TYPE_BITFIELD: case TYPE_RUNTIMECLASS: + case TYPE_DELEGATE: return TRUE; case TYPE_APICONTRACT: case TYPE_PARAMETERIZED_TYPE: @@ -373,6 +376,13 @@ static inline type_t *type_runtimeclass_get_default_iface(const type_t *type) return NULL; }
+static inline type_t *type_delegate_get_iface(const type_t *type) +{ + type = type_get_real_type(type); + assert(type_get_type(type) == TYPE_DELEGATE); + return type->details.delegate.iface; +} + static inline const decl_spec_t *type_pointer_get_ref(const type_t *type) { type = type_get_real_type(type); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index ce48567d583..69f95b9cbbe 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -442,6 +442,11 @@ struct parameterized_details type_list_t *params; };
+struct delegate_details +{ + type_t *iface; +}; + #define HASHMAX 64
struct namespace { @@ -472,6 +477,7 @@ enum type_type TYPE_RUNTIMECLASS, TYPE_PARAMETERIZED_TYPE, TYPE_PARAMETER, + TYPE_DELEGATE, };
struct _type_t { @@ -494,6 +500,7 @@ struct _type_t { struct alias_details alias; struct runtimeclass_details runtimeclass; struct parameterized_details parameterized; + struct delegate_details delegate; } details; const char *c_name; unsigned int typestring_offset;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- include/windows.foundation.idl | 6 +++ tools/widl/parser.y | 6 +++ tools/widl/typetree.c | 73 ++++++++++++++++++++++++++++++---- tools/widl/typetree.h | 2 + 4 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index 5f7a49c38e4..bb0fafcab77 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -113,6 +113,12 @@ namespace Windows { }
#ifdef __WIDL__ + [ + contract(Windows.Foundation.FoundationContract, 1.0), + uuid(9de1c535-6ae1-11e0-84e1-18a905bcc53f) + ] + delegate HRESULT EventHandler<T>([in] IInspectable *sender, [in] T args); + namespace Collections { [ diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 292090170e5..76ed1855f86 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -1033,6 +1033,12 @@ delegatedef: m_attributes tDELEGATE type ident '(' m_args ')' semicolon_opt { $$ = type_delegate_declare($4->name, current_namespace); $$ = type_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $6))); } + | m_attributes tDELEGATE type ident + '<' { push_parameters_namespace($4->name); } type_parameters '>' + '(' m_args ')' { pop_parameters_namespace($4->name); } semicolon_opt + { $$ = type_parameterized_delegate_declare($4->name, current_namespace, $7); + $$ = type_parameterized_delegate_define($$, $1, append_statement(NULL, make_statement_delegate($3, $10))); + } ;
required_types: diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index 1ab41a488ca..cd4bc6843fc 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -142,16 +142,16 @@ static char const *parameterized_type_shorthands[][2] = { {"Windows_CFoundation_C", "__F"}, };
-static char *format_parameterized_type_c_name(type_t *type, type_list_t *params) +static char *format_parameterized_type_c_name(type_t *type, type_list_t *params, const char *prefix) { 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); + pos += append_namespaces(&buf, &len, pos, type->namespace, "__x_", "_C", "", use_abi_namespace ? "ABI" : NULL); for (entry = params; entry; entry = entry->next) count++; - pos += strappend(&buf, &len, pos, "_%d", count); + pos += strappend(&buf, &len, pos, "%s%s_%d", prefix, type->name, count); for (entry = params; entry; entry = entry->next) { for (type = entry->type; type->type_type == TYPE_POINTER; type = type_pointer_get_ref_type(type)) {} @@ -665,12 +665,13 @@ type_t *type_apicontract_define(type_t *apicontract, attr_list_t *attrs) return apicontract; }
-static void compute_delegate_iface_names(type_t *delegate) +static void compute_delegate_iface_names(type_t *delegate, type_t *type, type_list_t *params) { type_t *iface = delegate->details.delegate.iface; iface->namespace = delegate->namespace; iface->name = strmake("I%s", delegate->name); - iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL); + if (type) iface->c_name = format_parameterized_type_c_name(type, params, "I"); + else iface->c_name = format_namespace(delegate->namespace, "__x_", "_C", iface->name, use_abi_namespace ? "ABI" : NULL); }
type_t *type_delegate_declare(char *name, struct namespace *namespace) @@ -708,7 +709,7 @@ type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_lis
delegate->details.delegate.iface = iface; delegate->defined = TRUE; - compute_delegate_iface_names(delegate); + compute_delegate_iface_names(delegate, NULL, NULL);
return delegate; } @@ -752,6 +753,46 @@ type_t *type_parameterized_interface_define(type_t *type, attr_list_t *attrs, ty return type; }
+type_t *type_parameterized_delegate_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("pdelegate %s previously not declared a pdelegate at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + type->details.parameterized.type = make_type(TYPE_DELEGATE); + type->details.parameterized.params = params; + return type; +} + +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts) +{ + type_t *iface, *delegate; + + if (type->defined) + error_loc("pdelegate %s already defined at %s:%d\n", + type->name, type->loc_info.input_name, type->loc_info.line_number); + + type->attrs = check_interface_attrs(type->name, attrs); + + delegate = type->details.parameterized.type; + delegate->attrs = type->attrs; + delegate->details.delegate.iface = make_type(TYPE_INTERFACE); + + iface = delegate->details.delegate.iface; + 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 = find_type("IUnknown", NULL, 0); + if (!iface->details.iface->inherit) error_loc("IUnknown is undefined\n"); + iface->details.iface->disp_inherit = NULL; + iface->details.iface->async_iface = NULL; + iface->details.iface->requires = NULL; + + type->defined = TRUE; + return type; +} + type_t *type_parameterized_type_specialize_partial(type_t *type, type_list_t *params) { type_t *new_type = duptype(type, 0); @@ -932,6 +973,11 @@ static void type_parameterized_interface_specialize(type_t *tmpl, type_t *iface, iface->details.iface->requires = NULL; }
+static void type_parameterized_delegate_specialize(type_t *tmpl, type_t *delegate, type_list_t *orig, type_list_t *repl) +{ + type_parameterized_interface_specialize(tmpl->details.delegate.iface, delegate->details.delegate.iface, orig, repl); +} + type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *params) { type_t *tmpl = type->details.parameterized.type; @@ -940,7 +986,13 @@ type_t *type_parameterized_type_specialize_declare(type_t *type, type_list_t *pa 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); + new_type->c_name = format_parameterized_type_c_name(type, params, ""); + + if (new_type->type_type == TYPE_DELEGATE) + { + new_type->details.delegate.iface = duptype(tmpl->details.delegate.iface, 0); + compute_delegate_iface_names(new_type, type, params); + }
return new_type; } @@ -953,6 +1005,8 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par
if (tmpl->type_type == TYPE_INTERFACE) type_parameterized_interface_specialize(tmpl, iface, orig, params); + else if (tmpl->type_type == TYPE_DELEGATE) + type_parameterized_delegate_specialize(tmpl, iface, orig, params); else { error_loc("Unsupported parameterized type template %d\n", tmpl->type_type); @@ -960,6 +1014,11 @@ type_t *type_parameterized_type_specialize_define(type_t *type, type_list_t *par }
iface->defined = TRUE; + if (iface->type_type == TYPE_DELEGATE) + { + iface = iface->details.delegate.iface; + iface->defined = TRUE; + } compute_method_indexes(iface); return iface; } diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h index 13d6a4d51fb..af0764b68b0 100644 --- a/tools/widl/typetree.h +++ b/tools/widl/typetree.h @@ -68,6 +68,8 @@ type_t *type_delegate_declare(char *name, struct namespace *namespace); type_t *type_delegate_define(type_t *delegate, attr_list_t *attrs, statement_list_t *stmts); 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_delegate_declare(char *name, struct namespace *namespace, type_list_t *params); +type_t *type_parameterized_delegate_define(type_t *type, attr_list_t *attrs, statement_list_t *stmts); 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);
Hi Rémi,
On 15.02.2021 11:09, Rémi Bernon wrote:
+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:
(...)
@@ -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;
+}
The usual practice in such cases would be to write grammatical rule (probably with a separate parameterized_type_arg rule) to append one element at a time to the list. This would avoid need for append_types (and its additional list traversal).
Thanks,
Jacek