summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-01-09 18:29:29 +0000
committerVincent Sanders <vince@kyllikki.org>2014-05-16 14:38:57 +0100
commit6031dd6e55216bd4d9a78c4869bb8b5e5f5aa3c3 (patch)
tree8776dc38c637434bae6ff1739ab6f6e774604c7f
parent74158664a1826e5763e7c6949a915c75c8c1a23d (diff)
downloadnsgenbind-6031dd6e55216bd4d9a78c4869bb8b5e5f5aa3c3.tar.gz
nsgenbind-6031dd6e55216bd4d9a78c4869bb8b5e5f5aa3c3.tar.bz2
Expand implements statements in the AST after it has been built
This greatly simplifies output generation because instead of dealing with implements on every traverse they are expanded once. Additionaly errors in expansion are found and generate error early.
-rw-r--r--src/jsapi-libdom-function.c24
-rw-r--r--src/jsapi-libdom-property.c47
-rw-r--r--src/jsapi-libdom.c4
-rw-r--r--src/webidl-ast.c125
-rw-r--r--src/webidl-ast.h3
5 files changed, 127 insertions, 76 deletions
diff --git a/src/jsapi-libdom-function.c b/src/jsapi-libdom-function.c
index 4970b48..5540b0e 100644
--- a/src/jsapi-libdom-function.c
+++ b/src/jsapi-libdom-function.c
@@ -45,13 +45,6 @@ static int webidl_func_spec_cb(struct webidl_node *node, void *ctx)
static int generate_function_spec(struct binding *binding, const char *interface);
-/* callback to emit implements operator spec */
-static int webidl_function_spec_implements_cb(struct webidl_node *node, void *ctx)
-{
- struct binding *binding = ctx;
-
- return generate_function_spec(binding, webidl_node_gettext(node));
-}
static int
generate_function_spec(struct binding *binding, const char *interface)
@@ -104,13 +97,6 @@ generate_function_spec(struct binding *binding, const char *interface)
webidl_node_gettext(inherit_node));
}
- if (res == 0) {
- res = webidl_node_for_each_type(webidl_node_getnode(interface_node),
- WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS,
- webidl_function_spec_implements_cb,
- binding);
- }
-
return res;
}
@@ -878,14 +864,6 @@ output_function_body(struct binding *binding,
res = webidl_implements_cb(inherit_node, binding);
}
- if (res == 0) {
- res = webidl_node_for_each_type(
- webidl_node_getnode(interface_node),
- WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS,
- webidl_implements_cb,
- binding);
- }
-
return res;
}
@@ -893,7 +871,7 @@ int
output_function_bodies(struct binding *binding)
{
int inf;
- int res;
+ int res = 0;
for (inf=0; inf < binding->interfacec; inf++) {
if (binding->interfaces[inf].inherit_idx == -1) {
diff --git a/src/jsapi-libdom-property.c b/src/jsapi-libdom-property.c
index df296cf..93ffcc5 100644
--- a/src/jsapi-libdom-property.c
+++ b/src/jsapi-libdom-property.c
@@ -131,14 +131,6 @@ webidl_property_tinyid_cb(struct webidl_node *node, void *ctx)
return 0;
}
-/* callback to emit implements property spec */
-static int
-webidl_property_tinyid_implements_cb(struct webidl_node *node, void *ctx)
-{
- struct binding *binding = ctx;
-
- return generate_property_tinyid(binding, webidl_node_gettext(node));
-}
static int
generate_property_tinyid(struct binding *binding, const char *interface)
@@ -190,13 +182,6 @@ generate_property_tinyid(struct binding *binding, const char *interface)
res = generate_property_tinyid(binding, webidl_node_gettext(inherit_node));
}
- if (res == 0) {
- res = webidl_node_for_each_type(webidl_node_getnode(interface_node),
- WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS,
- webidl_property_tinyid_implements_cb,
- binding);
- }
-
return res;
}
@@ -429,13 +414,6 @@ static int webidl_property_spec_cb(struct webidl_node *node, void *ctx)
}
-/* callback to emit implements property spec */
-static int webidl_property_spec_implements_cb(struct webidl_node *node, void *ctx)
-{
- struct binding *binding = ctx;
-
- return generate_property_spec(binding, webidl_node_gettext(node));
-}
static int
generate_property_spec(struct binding *binding, const char *interface)
@@ -488,13 +466,6 @@ generate_property_spec(struct binding *binding, const char *interface)
webidl_node_gettext(inherit_node));
}
- if (res == 0) {
- res = webidl_node_for_each_type(webidl_node_getnode(interface_node),
- WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS,
- webidl_property_spec_implements_cb,
- binding);
- }
-
return res;
}
@@ -954,17 +925,6 @@ static int webidl_property_body_cb(struct webidl_node *node, void *ctx)
}
-
-/* callback to emit implements property bodys */
-static int webidl_implements_cb(struct webidl_node *node, void *ctx)
-{
- struct binding *binding = ctx;
-
- return generate_property_body(binding, webidl_node_gettext(node));
-}
-
-
-
static int
generate_property_body(struct binding *binding, const char *interface)
{
@@ -1018,13 +978,6 @@ generate_property_body(struct binding *binding, const char *interface)
webidl_node_gettext(inherit_node));
}
- if (res == 0) {
- res = webidl_node_for_each_type(webidl_node_getnode(interface_node),
- WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS,
- webidl_implements_cb,
- binding);
- }
-
return res;
}
diff --git a/src/jsapi-libdom.c b/src/jsapi-libdom.c
index 1bb6d28..5e994b9 100644
--- a/src/jsapi-libdom.c
+++ b/src/jsapi-libdom.c
@@ -47,6 +47,10 @@ read_webidl(struct genbind_node *genbind_ast, struct webidl_node **webidl_ast)
webidl_file_cb,
webidl_ast);
+ if (res == 0) {
+ res = webidl_intercalate_implements(*webidl_ast);
+ }
+
/* debug dump of web idl AST */
if (options->verbose) {
webidl_ast_dump(*webidl_ast, 0);
diff --git a/src/webidl-ast.c b/src/webidl-ast.c
index 8acb2fb..945b5fa 100644
--- a/src/webidl-ast.c
+++ b/src/webidl-ast.c
@@ -21,8 +21,8 @@ extern void webidl_restart(FILE*);
extern int webidl_parse(struct webidl_node **webidl_ast);
struct webidl_node {
- enum webidl_node_type type;
- struct webidl_node *l;
+ enum webidl_node_type type; /* the type of the node */
+ struct webidl_node *l; /* link to the next sibling node */
union {
void *value;
struct webidl_node *node; /* node has a list of nodes */
@@ -223,6 +223,7 @@ webidl_node_find_type(struct webidl_node *node,
}
+/* exported interface defined in webidl-ast.h */
struct webidl_node *
webidl_node_find_type_ident(struct webidl_node *root_node,
enum webidl_node_type type,
@@ -250,6 +251,7 @@ webidl_node_find_type_ident(struct webidl_node *root_node,
}
+/* exported interface defined in webidl-ast.h */
char *webidl_node_gettext(struct webidl_node *node)
{
if (node != NULL) {
@@ -261,12 +263,13 @@ char *webidl_node_gettext(struct webidl_node *node)
return node->r.text;
default:
- break;
+ break;
}
}
return NULL;
}
+/* exported interface defined in webidl-ast.h */
int
webidl_node_getint(struct webidl_node *node)
{
@@ -285,12 +288,14 @@ webidl_node_getint(struct webidl_node *node)
}
+/* exported interface defined in webidl-ast.h */
enum webidl_node_type webidl_node_gettype(struct webidl_node *node)
{
return node->type;
}
+/* exported interface defined in webidl-ast.h */
struct webidl_node *webidl_node_getnode(struct webidl_node *node)
{
if (node != NULL) {
@@ -314,6 +319,7 @@ struct webidl_node *webidl_node_getnode(struct webidl_node *node)
}
+/* exported interface defined in webidl-ast.h */
static const char *webidl_node_type_to_str(enum webidl_node_type type)
{
switch(type) {
@@ -381,6 +387,7 @@ static const char *webidl_node_type_to_str(enum webidl_node_type type)
}
+/* exported interface defined in webidl-ast.h */
int webidl_ast_dump(struct webidl_node *node, int indent)
{
const char *SPACES=" "; char *txt;
@@ -408,18 +415,19 @@ int webidl_ast_dump(struct webidl_node *node, int indent)
return 0;
}
+/* exported interface defined in webidl-ast.h */
static FILE *idlopen(const char *filename)
{
FILE *idlfile;
char *fullname;
- int fulllen;
+ int fulllen;
if (options->idlpath == NULL) {
if (options->verbose) {
printf("Opening IDL file %s\n", filename);
}
return fopen(filename, "r");
- }
+ }
fulllen = strlen(options->idlpath) + strlen(filename) + 2;
fullname = malloc(fulllen);
@@ -429,10 +437,11 @@ static FILE *idlopen(const char *filename)
}
idlfile = fopen(fullname, "r");
free(fullname);
-
+
return idlfile;
}
+/* exported interface defined in webidl-ast.h */
int webidl_parsefile(char *filename, struct webidl_node **webidl_ast)
{
@@ -457,3 +466,107 @@ int webidl_parsefile(char *filename, struct webidl_node **webidl_ast)
/* parse the file */
return webidl_parse(webidl_ast);
}
+
+/* unlink a child node from a parent */
+static int
+webidl_unlink(struct webidl_node *parent, struct webidl_node *node)
+{
+ struct webidl_node *child;
+
+ child = webidl_node_getnode(parent);
+ if (child == NULL) {
+ /* parent does not have children to remove node from */
+ return -1;
+ }
+
+ if (child == node) {
+ /* parent is pointing at the node we want to remove */
+ parent->r.node = node->l; /* point parent at next sibing */
+ node->l = NULL;
+ return 0;
+ }
+
+ while (child->l != NULL) {
+ if (child->l == node) {
+ /* found node, unlink from list */
+ child->l = node->l;
+ node->l = NULL;
+ return 0;
+ }
+ child = child->l;
+ }
+ return -1; /* failed to remove node */
+}
+
+static int implements_copy_nodes(struct webidl_node *src_node,
+ struct webidl_node *dst_node)
+{
+ struct webidl_node *src;
+ struct webidl_node *dst;
+
+ src = webidl_node_getnode(src_node);
+ dst = webidl_node_getnode(dst_node);
+
+ while (src != NULL) {
+ if (src->type == WEBIDL_NODE_TYPE_LIST) {
+ /** @todo technicaly this should copy WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE */
+ dst = webidl_node_new(src->type, dst, src->r.text);
+ }
+ src = src->l;
+ }
+
+ dst_node->r.node = dst;
+
+ return 0;
+}
+
+static int
+intercalate_implements(struct webidl_node *interface_node, void *ctx)
+{
+ struct webidl_node *implements_node;
+ struct webidl_node *implements_interface_node;
+ struct webidl_node *webidl_ast = ctx;
+
+ implements_node = webidl_node_find_type(
+ webidl_node_getnode(interface_node),
+ NULL,
+ WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS);
+ while (implements_node != NULL) {
+
+ implements_interface_node = webidl_node_find_type_ident(
+ webidl_ast,
+ WEBIDL_NODE_TYPE_INTERFACE,
+ webidl_node_gettext(implements_node));
+
+ /* recurse, ensuring all subordinate interfaces have
+ * their implements intercalated first
+ */
+ intercalate_implements(implements_interface_node, webidl_ast);
+
+ implements_copy_nodes(implements_interface_node, interface_node);
+
+ /* once we have copied the implemntation remove entry */
+ webidl_unlink(interface_node, implements_node);
+
+ implements_node = webidl_node_find_type(
+ webidl_node_getnode(interface_node),
+ implements_node,
+ WEBIDL_NODE_TYPE_INTERFACE_IMPLEMENTS);
+ }
+ return 0;
+}
+
+/* exported interface defined in webidl-ast.h */
+int webidl_intercalate_implements(struct webidl_node *webidl_ast)
+{
+ /* for each interface:
+ * for each implements entry:
+ * find interface from implemets
+ * recusrse into that interface
+ * copy the interface into this one
+ */
+ return webidl_node_for_each_type(webidl_ast,
+ WEBIDL_NODE_TYPE_INTERFACE,
+ intercalate_implements,
+ webidl_ast);
+}
diff --git a/src/webidl-ast.h b/src/webidl-ast.h
index eaa8d44..a494f4e 100644
--- a/src/webidl-ast.h
+++ b/src/webidl-ast.h
@@ -120,4 +120,7 @@ int webidl_ast_dump(struct webidl_node *node, int indent);
/** parse web idl file */
int webidl_parsefile(char *filename, struct webidl_node **webidl_ast);
+/** perform replacement of implements elements with copies of ast data */
+int webidl_intercalate_implements(struct webidl_node *node);
+
#endif