diff options
-rw-r--r-- | src/duk-libdom.c | 108 | ||||
-rw-r--r-- | src/interface-map.c | 269 | ||||
-rw-r--r-- | src/interface-map.h | 33 | ||||
-rw-r--r-- | src/webidl-ast.c | 22 | ||||
-rw-r--r-- | src/webidl-ast.h | 3 | ||||
-rw-r--r-- | src/webidl-lexer.l | 2 | ||||
-rw-r--r-- | src/webidl-parser.y | 14 |
7 files changed, 310 insertions, 141 deletions
diff --git a/src/duk-libdom.c b/src/duk-libdom.c index a2d65af..195f4a4 100644 --- a/src/duk-libdom.c +++ b/src/duk-libdom.c @@ -160,19 +160,13 @@ output_dump_stack(FILE* outf) static int output_add_method(FILE* outf, const char *class_name, - const char *method, - int argc) + const char *method) { fprintf(outf, "\t/* Add a method */\n"); fprintf(outf, "\tduk_dup(ctx, 0);\n"); fprintf(outf, "\tduk_push_string(ctx, \"%s\");\n", method); - fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s, ", + fprintf(outf, "\tduk_push_c_function(ctx, %s_%s_%s, DUK_VARARGS);\n", DLPFX, class_name, method); - if (argc == -1) { - fprintf(outf, "DUK_VARARGS);\n"); - } else { - fprintf(outf, "%d);\n", argc); - } output_dump_stack(outf); fprintf(outf, "\tduk_def_prop(ctx, -3,\n"); fprintf(outf, "\t DUK_DEFPROP_HAVE_VALUE |\n"); @@ -700,35 +694,6 @@ output_interface_fini(FILE* outf, /** - * count the number of arguments to an operation - * - * \todo this needs to consider multiple lists (overloaded calls?), varadic - * parameters. - * - * \retuen number of arguments or -1 if variable - */ -static int count_operation_arguments(struct webidl_node *node) -{ - int argc; - struct webidl_node *list_node; - list_node = webidl_node_find_type( - webidl_node_getnode(node), - NULL, - WEBIDL_NODE_TYPE_LIST); - if (list_node == NULL) { - /** \todo is having no argument list an error or a warning? */ - return 0; - } - argc = webidl_node_enumerate_type(webidl_node_getnode(list_node), - WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT); - if (argc != 0) { - return -1; - } - return webidl_node_enumerate_type(webidl_node_getnode(list_node), - WEBIDL_NODE_TYPE_ARGUMENT); -} - -/** * generate a prototype add for a single class method */ static int @@ -736,23 +701,12 @@ output_prototype_method(FILE* outf, struct interface_map_entry *interfacee, struct interface_map_operation_entry *operatione) { - int op_argc; - - if (operatione->overloadc > 1) { - /* only generate a method for the first occourance of an - * overloaded method - */ - return 0; - } if (operatione->name != NULL) { - /* normal method of prototype */ - op_argc = count_operation_arguments(operatione->node); - + /* normal method on prototype */ output_add_method(outf, interfacee->class_name, - operatione->name, - op_argc); + operatione->name); } else { /* special method on prototype */ fprintf(outf, @@ -929,44 +883,38 @@ output_interface_operation(FILE* outf, struct interface_map_entry *interfacee, struct interface_map_operation_entry *operatione) { - if (operatione->overloadc > 1) { - /* only generate a method for the first occourance of an - * overloaded method - */ + int cdatac; /* cdata blocks output */ + + if (operatione->name == NULL) { + /* special method definition */ + fprintf(outf, + "/* Special method definition - UNIMPLEMENTED */\n\n"); return 0; } - if (operatione->name != NULL) { - /* normal method definition */ + /* normal method definition */ - int cdatac; /* cdata blocks output */ + fprintf(outf, + "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", + DLPFX, interfacee->class_name, operatione->name); + fprintf(outf,"{\n"); - fprintf(outf, - "static duk_ret_t %s_%s_%s(duk_context *ctx)\n", - DLPFX, interfacee->class_name, operatione->name); - fprintf(outf,"{\n"); - - output_get_method_private(outf, interfacee->class_name); - - cdatac = output_cdata(outf, - operatione->method, - GENBIND_NODE_TYPE_CDATA); - - if (cdatac == 0) { - /* no implementation so generate default */ - WARN(WARNING_UNIMPLEMENTED, - "Unimplemented: method %s::%s();", - interfacee->name, operatione->name); - fprintf(outf,"\treturn 0;\n"); - } + output_get_method_private(outf, interfacee->class_name); - fprintf(outf, "}\n\n"); - } else { - /* special method definition */ - fprintf(outf, - "/* Special method definition - UNIMPLEMENTED */\n\n"); + cdatac = output_cdata(outf, + operatione->method, + GENBIND_NODE_TYPE_CDATA); + + if (cdatac == 0) { + /* no implementation so generate default */ + WARN(WARNING_UNIMPLEMENTED, + "Unimplemented: method %s::%s();", + interfacee->name, operatione->name); + fprintf(outf,"\treturn 0;\n"); } + fprintf(outf, "}\n\n"); + return 0; } diff --git a/src/interface-map.c b/src/interface-map.c index 29e9ec0..a5a672a 100644 --- a/src/interface-map.c +++ b/src/interface-map.c @@ -132,31 +132,149 @@ interface_topoligical_sort(struct interface_map_entry *srcinf, int infc) return dstinf; } -static int -count_operation_name(struct interface_map_operation_entry *operationv, +static struct interface_map_operation_entry * +find_operation_name(struct interface_map_operation_entry *operationv, int operationc, const char *name) { struct interface_map_operation_entry *cure; int opc; - int res = 0; for (opc = 0; opc < operationc; opc++) { cure = operationv + opc; if (cure->name == name) { /* check pointers for equivalence */ - res++; + return cure; } else { if ((cure->name != NULL) && (name != NULL) && (strcmp(cure->name, name) == 0)) { - res++; + return cure; } } } - return res; + return NULL; +} + +static int +argument_map_new(struct webidl_node *arg_list_node, + int *argumentc_out, + struct interface_map_operation_argument_entry **argumentv_out) +{ + int argumentc; + struct webidl_node *argument; + struct interface_map_operation_argument_entry *argumentv; + struct interface_map_operation_argument_entry *cure; + + argumentc = webidl_node_enumerate_type( + webidl_node_getnode(arg_list_node), + WEBIDL_NODE_TYPE_ARGUMENT); + if (argumentc == 0) { + *argumentc_out = 0; + *argumentv_out = NULL; + return 0; + } + + argumentv = calloc(argumentc, sizeof(*argumentv)); + cure = argumentv; + + /* iterate each argument node within the list */ + argument = webidl_node_find_type(webidl_node_getnode(arg_list_node), + NULL, + WEBIDL_NODE_TYPE_ARGUMENT); + + while (argument != NULL) { + + cure->name = webidl_node_gettext( + webidl_node_find_type( + webidl_node_getnode(argument), + NULL, + WEBIDL_NODE_TYPE_IDENT)); + + cure->node = argument; + + + cure->optionalc = webidl_node_enumerate_type( + webidl_node_getnode(argument), + WEBIDL_NODE_TYPE_OPTIONAL); + + cure->elipsisc = webidl_node_enumerate_type( + webidl_node_getnode(argument), + WEBIDL_NODE_TYPE_ELLIPSIS); + + cure++; + + argument = webidl_node_find_type( + webidl_node_getnode(arg_list_node), + argument, + WEBIDL_NODE_TYPE_ARGUMENT); + } + + *argumentc_out = argumentc; + *argumentv_out = argumentv; + + return 0; +} + +/** + * create a new overloaded parameter set on an operation + * + * each operation can be overloaded with multiple function signatures. By + * adding them to the operation as overloads duplicate operation enrtries is + * avoided. + */ +static int +overload_map_new(struct webidl_node *op_node, + int *overloadc_out, + struct interface_map_operation_overload_entry **overloadv_out) +{ + int overloadc = *overloadc_out; + struct interface_map_operation_overload_entry *overloadv; + struct interface_map_operation_overload_entry *cure; + struct webidl_node *arg_list_node; + int argc; + + /* update allocation */ + overloadc++; + overloadv = realloc(*overloadv_out, overloadc * sizeof(*overloadv)); + if (overloadv == NULL) { + return -1; + } + + /* get added entry */ + cure = overloadv + (overloadc - 1); + + /* clear entry */ + cure = memset(cure, 0, sizeof(*cure)); + + /* return type */ + cure->type = webidl_node_find_type(webidl_node_getnode(op_node), + NULL, + WEBIDL_NODE_TYPE_TYPE); + + arg_list_node = webidl_node_find_type(webidl_node_getnode(op_node), + NULL, + WEBIDL_NODE_TYPE_LIST); + if (arg_list_node != NULL) { + argument_map_new(arg_list_node, + &cure->argumentc, + &cure->argumentv); + } + + for (argc = 0; argc < cure->argumentc; argc++) { + struct interface_map_operation_argument_entry *arge; + arge = cure->argumentv + argc; + cure->optionalc += arge->optionalc; + cure->elipsisc += arge->elipsisc; + } + + /* return entry list */ + *overloadc_out = overloadc; + *overloadv_out = overloadv; + + return 0; } static int @@ -170,9 +288,8 @@ operation_map_new(struct webidl_node *interface, struct interface_map_operation_entry *cure; /* current entry */ struct interface_map_operation_entry *operationv; int operationc; - int opc; - /* enumerate operationss */ + /* enumerate operationss including overloaded members */ operationc = enumerate_interface_type(interface, WEBIDL_NODE_TYPE_OPERATION); @@ -204,25 +321,49 @@ operation_map_new(struct webidl_node *interface, WEBIDL_NODE_TYPE_OPERATION); while (op_node != NULL) { - cure->node = op_node; + const char *operation_name; + struct interface_map_operation_entry *finde; - cure->name = webidl_node_gettext( + /* get operation name */ + operation_name = webidl_node_gettext( webidl_node_find_type( webidl_node_getnode(op_node), NULL, WEBIDL_NODE_TYPE_IDENT)); + /* if this operation is already an entry in the list + * augment that entry else create a new one + */ + finde = find_operation_name(operationv, + operationc, + operation_name); + if (finde == NULL) { + /* operation does not already exist in list */ + + cure->name = operation_name; + + cure->node = op_node; - cure->method = genbind_node_find_method_ident( + cure->method = genbind_node_find_method_ident( class, NULL, GENBIND_METHOD_TYPE_METHOD, cure->name); - cure->overloadc = count_operation_name(operationv, - operationc, - cure->name); + overload_map_new(op_node, + &cure->overloadc, + &cure->overloadv); - cure++; + cure++; /* advance to next entry */ + } else { + overload_map_new(op_node, + &finde->overloadc, + &finde->overloadv); + /* Overloaded entry does not advance the + * current entry but does reduce list + * length. Do not bother shortening allocation. + */ + operationc--; + } /* move to next operation */ op_node = webidl_node_find_type( @@ -237,20 +378,6 @@ operation_map_new(struct webidl_node *interface, WEBIDL_NODE_TYPE_LIST); } - /* finally take a pass over the table to correct the overload count */ - for (opc = 0; opc < operationc; opc++) { - cure = operationv + opc; - if ((cure->overloadc == 1) && - (count_operation_name(operationv, - operationc, - cure->name) == 1)) { - /* if the "overloaded" member is itself it is not - * overloaded. - */ - cure->overloadc = 0; - } - } - *operationc_out = operationc; *operationv_out = operationv; /* resulting operations map */ @@ -567,46 +694,88 @@ int interface_map_dump(struct interface_map *index) for (eidx = 0; eidx < index->entryc; eidx++) { fprintf(dumpf, "%d %s\n", eidx, ecur->name); if (ecur->inherit_name != NULL) { - fprintf(dumpf, " inherit:%s\n", ecur->inherit_name); + fprintf(dumpf, "\tinherit:%s\n", ecur->inherit_name); } if (ecur->class != NULL) { - fprintf(dumpf, " class:%p\n", ecur->class); + fprintf(dumpf, "\tclass:%p\n", ecur->class); } + if (ecur->operationc > 0) { - int opc = ecur->operationc; - struct interface_map_operation_entry *ope; + int opc; - fprintf(dumpf, " %d operations\n", + fprintf(dumpf, "\t%d operations\n", ecur->operationc); - ope = ecur->operationv; - while (ope != NULL) { + for (opc = 0; opc < ecur->operationc; opc++) { + int ovlc; + struct interface_map_operation_entry *ope; + + ope = ecur->operationv + opc; + fprintf(dumpf, - " %s\n", + "\t\t%s\n", ope->name); fprintf(dumpf, - " method:%p\n", + "\t\t\tmethod:%p\n", ope->method); - fprintf(dumpf, - " overload:%d\n", - ope->overloadc); - ope++; - opc--; - if (opc == 0) { - break; + for(ovlc = 0; ovlc < ope->overloadc;ovlc++) { + int argc; + struct interface_map_operation_overload_entry *ovle; + ovle = ope->overloadv + ovlc; + + fprintf(dumpf, + "\t\t\toverload:%d\n", ovlc); + + fprintf(dumpf, + "\t\t\t\treturn type:%p\n", + ovle->type); + + fprintf(dumpf, + "\t\t\t\targuments:%d\n", + ovle->argumentc); + + fprintf(dumpf, + "\t\t\t\toptionals:%d\n", + ovle->optionalc); + + fprintf(dumpf, + "\t\t\t\telipsis:%d\n", + ovle->elipsisc); + + for (argc = 0; argc < ovle->argumentc; argc++) { + struct interface_map_operation_argument_entry *arge; + arge = ovle->argumentv + argc; + + fprintf(dumpf, + "\t\t\t\t\t%s\n", + arge->name); + + if (arge->optionalc != 0) { + fprintf(dumpf, + "\t\t\t\t\t\toptional:%d\n", + arge->optionalc); + } + + if (arge->elipsisc != 0) { + fprintf(dumpf, + "\t\t\t\t\t\telipsis:%d\n", + arge->elipsisc); + } + + } } } - } + if (ecur->attributec > 0) { int attrc = ecur->attributec; struct interface_map_attribute_entry *attre; - fprintf(dumpf, " %d attributes\n", attrc); + fprintf(dumpf, "\t%d attributes\n", attrc); attre = ecur->attributev; while (attre != NULL) { - fprintf(dumpf, " %s %p", + fprintf(dumpf, "\t\t%s %p", attre->name, attre->getter); if (attre->modifier == WEBIDL_TYPE_MODIFIER_NONE) { @@ -624,13 +793,13 @@ int interface_map_dump(struct interface_map *index) if (ecur->constantc > 0) { int idx; - fprintf(dumpf, " %d constants\n", + fprintf(dumpf, "\t%d constants\n", ecur->constantc); for (idx = 0; idx < ecur->constantc; idx++) { struct interface_map_constant_entry *cone; cone = ecur->constantv + idx; - fprintf(dumpf, " %s\n", + fprintf(dumpf, "\t\t%s\n", cone->name); } } diff --git a/src/interface-map.h b/src/interface-map.h index 04d9df1..5f1926e 100644 --- a/src/interface-map.h +++ b/src/interface-map.h @@ -12,12 +12,37 @@ struct genbind_node; struct webidl_node; +/** + *map entry for each argument of an overload on an operation + */ +struct interface_map_operation_argument_entry { + const char *name; + + int optionalc; /**< Number of parameters that are optional */ + int elipsisc; /**< Number of elipsis parameters */ + + struct webidl_node *node; +}; + +/** map entry for each overload of an operation */ +struct interface_map_operation_overload_entry { + struct webidl_node *type; /**< The return type of this overload */ + + int optionalc; /**< Number of parameters that are optional */ + int elipsisc; /**< Number of elipsis parameters */ + + int argumentc; /**< the number of parameters */ + struct interface_map_operation_argument_entry *argumentv; +}; + /** map entry for operations on an interface */ struct interface_map_operation_entry { const char *name; /** operation name */ struct webidl_node *node; /**< AST operation node */ - struct genbind_node *method; /**< method from binding (if any) */ - int overloadc; /**< Number of previous overloads of this operation */ + struct genbind_node *method; /**< method from binding */ + + int overloadc; /**< Number of overloads of this operation */ + struct interface_map_operation_overload_entry *overloadv; }; /** map entry for attributes on an interface */ @@ -25,8 +50,8 @@ struct interface_map_attribute_entry { const char *name; /** attribute name */ struct webidl_node *node; /**< AST attribute node */ enum webidl_type_modifier modifier; - struct genbind_node *getter; /**< getter from binding (if any) */ - struct genbind_node *setter; /**< getter from binding (if any) */ + struct genbind_node *getter; /**< getter from binding */ + struct genbind_node *setter; /**< getter from binding */ }; /** map entry for constants on an interface */ diff --git a/src/webidl-ast.c b/src/webidl-ast.c index 0e90767..87e3485 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -100,7 +100,7 @@ webidl_node_add(struct webidl_node *node, struct webidl_node *list) case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: case WEBIDL_NODE_TYPE_ATTRIBUTE: case WEBIDL_NODE_TYPE_OPERATION: - case WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT: + case WEBIDL_NODE_TYPE_OPTIONAL: case WEBIDL_NODE_TYPE_ARGUMENT: case WEBIDL_NODE_TYPE_TYPE: case WEBIDL_NODE_TYPE_CONST: @@ -267,6 +267,7 @@ char *webidl_node_gettext(struct webidl_node *node) case WEBIDL_NODE_TYPE_IDENT: case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: case WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS: + case WEBIDL_NODE_TYPE_LITERAL_STRING: return node->r.text; default: @@ -286,6 +287,7 @@ webidl_node_getint(struct webidl_node *node) case WEBIDL_NODE_TYPE_TYPE_BASE: case WEBIDL_NODE_TYPE_LITERAL_INT: case WEBIDL_NODE_TYPE_SPECIAL: + case WEBIDL_NODE_TYPE_LITERAL_BOOL: return &node->r.number; default: @@ -313,7 +315,7 @@ struct webidl_node *webidl_node_getnode(struct webidl_node *node) case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: case WEBIDL_NODE_TYPE_ATTRIBUTE: case WEBIDL_NODE_TYPE_OPERATION: - case WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT: + case WEBIDL_NODE_TYPE_OPTIONAL: case WEBIDL_NODE_TYPE_ARGUMENT: case WEBIDL_NODE_TYPE_TYPE: case WEBIDL_NODE_TYPE_CONST: @@ -354,8 +356,8 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_OPERATION: return "Operation"; - case WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT: - return "Argument(opt)"; + case WEBIDL_NODE_TYPE_OPTIONAL: + return "Optional"; case WEBIDL_NODE_TYPE_ARGUMENT: return "Argument"; @@ -381,9 +383,21 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_CONST: return "Const"; + case WEBIDL_NODE_TYPE_LITERAL_NULL: + return "Literal (null)"; + case WEBIDL_NODE_TYPE_LITERAL_INT: return "Literal (int)"; + case WEBIDL_NODE_TYPE_LITERAL_BOOL: + return "Literal (bool)"; + + case WEBIDL_NODE_TYPE_LITERAL_FLOAT: + return "Literal (string)"; + + case WEBIDL_NODE_TYPE_LITERAL_STRING: + return "Literal (string)"; + case WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE: return "Extended Attribute"; diff --git a/src/webidl-ast.h b/src/webidl-ast.h index c17a54b..25ef9a0 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -28,8 +28,8 @@ enum webidl_node_type { WEBIDL_NODE_TYPE_CONST, WEBIDL_NODE_TYPE_SPECIAL, - WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT, WEBIDL_NODE_TYPE_ARGUMENT, + WEBIDL_NODE_TYPE_OPTIONAL, WEBIDL_NODE_TYPE_ELLIPSIS, WEBIDL_NODE_TYPE_TYPE, WEBIDL_NODE_TYPE_TYPE_BASE, @@ -40,6 +40,7 @@ enum webidl_node_type { WEBIDL_NODE_TYPE_LITERAL_INT, WEBIDL_NODE_TYPE_LITERAL_BOOL, WEBIDL_NODE_TYPE_LITERAL_FLOAT, + WEBIDL_NODE_TYPE_LITERAL_STRING, WEBIDL_NODE_TYPE_EXTENDED_ATTRIBUTE, diff --git a/src/webidl-lexer.l b/src/webidl-lexer.l index e49b813..8c68fdf 100644 --- a/src/webidl-lexer.l +++ b/src/webidl-lexer.l @@ -228,7 +228,7 @@ legacyiterable return TOK_LEGACYITERABLE; {decimalfloat} yylval->text = strdup(yytext); return TOK_FLOAT_LITERAL; -\"{quotedstring}*\" yylval->text = strdup(yytext); return TOK_STRING_LITERAL; +\"{quotedstring}*\" yylval->text = strdup(yytext + 1); *(yylval->text + yyleng - 2) = 0; return TOK_STRING_LITERAL; {multicomment} { /* multicomment */ diff --git a/src/webidl-parser.y b/src/webidl-parser.y index 953388e..9cfd84e 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -170,6 +170,8 @@ webidl_error(YYLTYPE *locp, struct webidl_node **winbind_ast, const char *str) %type <node> Ellipsis %type <node> Iterable %type <node> OptionalType +%type <node> Default +%type <node> DefaultValue %type <node> Type %type <node> ReturnType @@ -450,8 +452,14 @@ PartialDictionary: /* [15] */ Default: /* empty */ + { + $$ = NULL; + } | '=' DefaultValue + { + $$ = $2; + } ; @@ -460,6 +468,9 @@ DefaultValue: ConstValue | TOK_STRING_LITERAL + { + $$ = webidl_node_new(WEBIDL_NODE_TYPE_LITERAL_STRING, NULL, $1); + } ; /* [17] */ @@ -874,8 +885,9 @@ OptionalOrRequiredArgument: { struct webidl_node *argument; argument = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, NULL, $3); + argument = webidl_node_new(WEBIDL_NODE_TYPE_OPTIONAL, argument, $4); argument = webidl_node_prepend(argument, $2); /* add type node */ - $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT, NULL, argument); + $$ = webidl_node_new(WEBIDL_NODE_TYPE_ARGUMENT, NULL, argument); } | Type Ellipsis ArgumentName |