From f09b0cb293c034df8efccdce12235e74a5ae6d13 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 4 Oct 2012 19:08:39 +0100 Subject: fix polymorphism in teh AST generation --- src/webidl-ast.c | 75 ++++++++++++++++++++------- src/webidl-ast.h | 5 +- src/webidl-parser.y | 144 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 154 insertions(+), 70 deletions(-) diff --git a/src/webidl-ast.c b/src/webidl-ast.c index 8160d55..084c199 100644 --- a/src/webidl-ast.c +++ b/src/webidl-ast.c @@ -31,16 +31,24 @@ struct webidl_node { } r; }; -/* insert node at beginning of a list */ +/* insert node(s) at beginning of a list */ struct webidl_node * -webidl_node_prepend(struct webidl_node *list, struct webidl_node *node) +webidl_node_prepend(struct webidl_node *list, struct webidl_node *inst) { - if (node == NULL) { + struct webidl_node *end = inst; + + if (inst == NULL) { return list; /* no node to prepend - return existing list */ } - node->l = list; - return node; + /* find end of inserted node list */ + while (end->l != NULL) { + end = end->l; + } + + end->l = list; + + return inst; } /* append node at end of a list */ @@ -61,13 +69,33 @@ webidl_node_append(struct webidl_node *list, struct webidl_node *node) return list; } +/* prepend list to a nodes list + * + * inserts a list into the beginning of a nodes r list + * + * CAUTION: if the \a node element is not a node type the node will not be added + */ struct webidl_node * -webidl_add_interface_member(struct webidl_node *list, struct webidl_node *new) +webidl_node_add(struct webidl_node *node, struct webidl_node *list) { - return webidl_node_prepend(list, new); + struct webidl_node *node_list; + + node_list = webidl_node_getnode(node); + if (node_list == NULL) { + /* not a node type node */ + return list; + } + + node->r.node = webidl_node_prepend(node_list, list); + + return node; } -struct webidl_node *webidl_node_new(enum webidl_node_type type, struct webidl_node *l, void *r) + +struct webidl_node * +webidl_node_new(enum webidl_node_type type, + struct webidl_node *l, + void *r) { struct webidl_node *nn; nn = calloc(1, sizeof(struct webidl_node)); @@ -77,11 +105,11 @@ struct webidl_node *webidl_node_new(enum webidl_node_type type, struct webidl_no return nn; } -void +void webidl_node_set(struct webidl_node *node, enum webidl_node_type type, void *r) { node->type = type; - node->r.value = r; + node->r.value = r; } int @@ -117,7 +145,7 @@ webidl_node_find(struct webidl_node *node, { struct webidl_node *ret; - if ((node == NULL) || (node == prev)){ + if ((node == NULL) || (node == prev)) { return NULL; } @@ -143,8 +171,8 @@ int webidl_cmp_node_type(struct webidl_node *node, void *ctx) } struct webidl_node * -webidl_node_find_type_ident(struct webidl_node *root_node, - enum webidl_node_type type, +webidl_node_find_type_ident(struct webidl_node *root_node, + enum webidl_node_type type, const char *ident) { struct webidl_node *node; @@ -205,6 +233,13 @@ webidl_node_getint(struct webidl_node *node) return -1; } + +enum webidl_node_type webidl_node_gettype(struct webidl_node *node) +{ + return node->type; +} + + struct webidl_node *webidl_node_getnode(struct webidl_node *node) { if (node != NULL) { @@ -217,6 +252,7 @@ struct webidl_node *webidl_node_getnode(struct webidl_node *node) case WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT: case WEBIDL_NODE_TYPE_ARGUMENT: case WEBIDL_NODE_TYPE_TYPE: + case WEBIDL_NODE_TYPE_CONST: return node->r.node; default: break; @@ -268,6 +304,9 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type) case WEBIDL_NODE_TYPE_MODIFIER: return "Modifier"; + case WEBIDL_NODE_TYPE_CONST: + return "Const"; + default: return "Unknown"; } @@ -310,7 +349,7 @@ static FILE *idlopen(const char *filename) if (options->verbose) { printf("Opening IDL file %s\n", filename); } - idlfile = fopen(filename, "r"); + idlfile = fopen(filename, "r"); } else { char *fullname; int fulllen = strlen(options->idlpath) + strlen(filename) + 2; @@ -319,7 +358,7 @@ static FILE *idlopen(const char *filename) if (options->verbose) { printf("Opening IDL file %s\n", fullname); } - idlfile = fopen(fullname, "r"); + idlfile = fopen(fullname, "r"); free(fullname); } return idlfile; @@ -327,13 +366,13 @@ static FILE *idlopen(const char *filename) int webidl_parsefile(char *filename, struct webidl_node **webidl_ast) { - + FILE *idlfile; idlfile = idlopen(filename); if (!idlfile) { fprintf(stderr, "Error opening %s: %s\n", - filename, + filename, strerror(errno)); return 2; } @@ -345,7 +384,7 @@ int webidl_parsefile(char *filename, struct webidl_node **webidl_ast) /* set flex to read from file */ webidl_restart(idlfile); - + /* parse the file */ return webidl_parse(webidl_ast); } diff --git a/src/webidl-ast.h b/src/webidl-ast.h index 7f21df5..0e38b8c 100644 --- a/src/webidl-ast.h +++ b/src/webidl-ast.h @@ -23,6 +23,7 @@ enum webidl_node_type { WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, WEBIDL_NODE_TYPE_ATTRIBUTE, WEBIDL_NODE_TYPE_OPERATION, + WEBIDL_NODE_TYPE_CONST, WEBIDL_NODE_TYPE_OPTIONAL_ARGUMENT, WEBIDL_NODE_TYPE_ARGUMENT, WEBIDL_NODE_TYPE_ELLIPSIS, @@ -67,13 +68,13 @@ void webidl_node_set(struct webidl_node *node, enum webidl_node_type type, void struct webidl_node *webidl_node_prepend(struct webidl_node *list, struct webidl_node *node); struct webidl_node *webidl_node_append(struct webidl_node *list, struct webidl_node *node); -struct webidl_node *webidl_add_interface_member(struct webidl_node *list, struct webidl_node *new); +struct webidl_node *webidl_node_add(struct webidl_node *node, struct webidl_node *list); /* node contents acessors */ char *webidl_node_gettext(struct webidl_node *node); struct webidl_node *webidl_node_getnode(struct webidl_node *node); int webidl_node_getint(struct webidl_node *node); - +enum webidl_node_type webidl_node_gettype(struct webidl_node *node); /* node searches */ int webidl_node_for_each_type(struct webidl_node *node, diff --git a/src/webidl-parser.y b/src/webidl-parser.y index 81f0dfc..7d93a4e 100644 --- a/src/webidl-parser.y +++ b/src/webidl-parser.y @@ -236,40 +236,30 @@ Interface: { /* extend interface with additional members */ struct webidl_node *interface_node; + struct webidl_node *members = NULL; + + if ($3 != NULL) { + members = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, members, $3); + } + + members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, members, $5); + + interface_node = webidl_node_find_type_ident(*webidl_ast, WEBIDL_NODE_TYPE_INTERFACE, $2); if (interface_node == NULL) { - struct webidl_node *members; - struct webidl_node *ident; - struct webidl_node *inheritance = NULL; - - if ($3 != NULL) { - inheritance = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, NULL, $3); - } - - members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, inheritance, $5); + /* no existing interface - create one with ident */ + members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); - ident = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); - - $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, ident); + $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, members); } else { - struct webidl_node *members; - struct webidl_node *inheritance = webidl_node_getnode(interface_node); - - if ($3 != NULL) { - inheritance = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE, inheritance, $3); - } - - members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, - inheritance, - $5); + /* update the existing interface */ /* link member node into interfaces_node */ - webidl_node_set(interface_node, - WEBIDL_NODE_TYPE_INTERFACE, - members); - $$ = NULL; /* updated existing interface do not add it again */ + webidl_node_add(interface_node, members); + + $$ = NULL; /* updating so no need to add a new node */ } } ; @@ -294,33 +284,28 @@ PartialInterface: TOK_INTERFACE TOK_IDENTIFIER '{' InterfaceMembers '}' ';' { /* extend interface with additional members */ + struct webidl_node *members; struct webidl_node *interface_node; + interface_node = webidl_node_find_type_ident(*webidl_ast, WEBIDL_NODE_TYPE_INTERFACE, $2); - if (interface_node == NULL) { - /* doesnt already exist so create it */ - struct webidl_node *members; - struct webidl_node *ident; - members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $4); + members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, $4); - ident = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); + if (interface_node == NULL) { + /* doesnt already exist so create it */ - $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, ident); + members = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, members, $2); + $$ = webidl_node_new(WEBIDL_NODE_TYPE_INTERFACE, NULL, members); } else { - struct webidl_node *members; - members = webidl_node_new(WEBIDL_NODE_TYPE_LIST, - webidl_node_getnode(interface_node), - $4); + /* update the existing interface */ /* link member node into interfaces_node */ - webidl_node_set(interface_node, - WEBIDL_NODE_TYPE_INTERFACE, - members); + webidl_node_add(interface_node, members); - $$ = NULL; /* updated existing interface do not add it again */ + $$ = NULL; /* updating so no need to add a new node */ } } ; @@ -333,8 +318,54 @@ InterfaceMembers: } | InterfaceMembers ExtendedAttributeList InterfaceMember - { - $$ = webidl_add_interface_member($1, $3); + /* This needs to deal with members with the same identifier which + * indicate polymorphism. this is handled in the AST by adding the + * argument lists for each polymorphism to the same + * WEBIDL_NODE_TYPE_OPERATION + * + * @todo need to consider qualifer/stringifier compatibility + */ + { + struct webidl_node *member_node; + struct webidl_node *ident_node; + struct webidl_node *list_node; + + ident_node = webidl_node_find(webidl_node_getnode($3), + NULL, + webidl_cmp_node_type, + (void *)WEBIDL_NODE_TYPE_IDENT); + + list_node = webidl_node_find(webidl_node_getnode($3), + NULL, + webidl_cmp_node_type, + (void *)WEBIDL_NODE_TYPE_LIST); + + if (ident_node == NULL) { + /* something with no ident - possibly constructors? */ + /* @todo understand this abtter */ + + $$ = webidl_node_prepend($1, $3); + } else if (list_node == NULL) { + /* something with no argument list - cannot be polymorphic */ + $$ = webidl_node_prepend($1, $3); + } else { + /* has an arguemnt list so can be polymorphic */ + member_node = webidl_node_find_type_ident($1, + webidl_node_gettype($3), + webidl_node_gettext(ident_node)); + if (member_node == NULL) { + /* not a member with that ident already present */ + $$ = webidl_node_prepend($1, $3); + } else { + + fprintf(stderr, + "HERE: New polymorphic member %p, ident node %p (%s), list node %p\n", + (void *)$3, (void *)ident_node, webidl_node_gettext(ident_node), (void *)list_node); + + webidl_node_add(member_node, list_node); + $$ = $1; /* updated existing node do not add new one */ + } + } } ; @@ -462,7 +493,18 @@ ImplementsStatement: Const: TOK_CONST ConstType TOK_IDENTIFIER '=' ConstValue ';' { - $$ = NULL; + struct webidl_node *constant; + + constant = webidl_node_new(WEBIDL_NODE_TYPE_IDENT, NULL, $3); + + /* add constant type */ + //constant = webidl_node_prepend(constant, $2); + + /* add constant value */ + //constant = webidl_node_prepend(constant, $5); + + $$ = webidl_node_new(WEBIDL_NODE_TYPE_CONST, NULL, constant); + } ; @@ -512,6 +554,10 @@ StringifierAttributeOrOperation: Attribute | OperationRest + { + /* @todo deal with stringifier */ + $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $1); + } | ';' { @@ -570,7 +616,8 @@ ReadOnly: Operation: Qualifiers OperationRest { - $$=$2; + /* @todo fix qualifiers */ + $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, $2); } ; @@ -605,18 +652,15 @@ Special: OperationRest: ReturnType OptionalIdentifier '(' ArgumentList ')' ';' { - struct webidl_node *operation; struct webidl_node *arglist; /* put return type in argument list */ arglist = webidl_node_prepend($4, $1); /* argument list */ - operation = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, arglist); - - operation = webidl_node_prepend(operation, $2); /* identifier */ + $$ = webidl_node_new(WEBIDL_NODE_TYPE_LIST, NULL, arglist); - $$ = webidl_node_new(WEBIDL_NODE_TYPE_OPERATION, NULL, operation); + $$ = webidl_node_prepend($$, $2); /* identifier */ } ; -- cgit v1.2.3