summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-10-08 15:06:56 (GMT)
committer Vincent Sanders <vince@kyllikki.org>2015-10-08 15:06:56 (GMT)
commitf9e20153b0c162662f95c821a6f4b27e5d2d9aec (patch)
treeeba16317897a2ace9e073c68a69c489634f839cd
parente170ee146791061f4fcc9523a901cdc1c6c8525b (diff)
downloadnsgenbind-f9e20153b0c162662f95c821a6f4b27e5d2d9aec.tar.gz
nsgenbind-f9e20153b0c162662f95c821a6f4b27e5d2d9aec.tar.bz2
Add automatic generation of property getters and setters
This allows the binding to omit specifying code for class property getters and setters. The omitted code will be generated by genbind to directly call suitable libdom accessors. The type of the property (string, boolean etc.) is derived from the IDL. If this type is incorrect, or is a type the generator cannot automatically produce, then the property will be treated like it has no binding implementation and generate unimplemented warnings.
-rw-r--r--src/duk-libdom-interface.c262
-rw-r--r--src/ir.c16
-rw-r--r--src/ir.h13
3 files changed, 241 insertions, 50 deletions
diff --git a/src/duk-libdom-interface.c b/src/duk-libdom-interface.c
index 940292e..34a0db0 100644
--- a/src/duk-libdom-interface.c
+++ b/src/duk-libdom-interface.c
@@ -1193,34 +1193,181 @@ output_interface_operations(FILE* outf, struct ir_entry *ife)
/**
- * Generate class property setter for a single attribute
+ * Generate class property getter for a single attribute
*/
static int
-output_attribute_setter(FILE* outf,
+output_generated_attribute_getter(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *atributee)
+{
+ switch (atributee->base_type) {
+ case WEBIDL_TYPE_STRING:
+ fprintf(outf,
+ "\tdom_exception exc;\n"
+ "\tdom_string *str;\n"
+ "\n");
+ fprintf(outf,
+ "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &str);\n",
+ interfacee->class_name,
+ atributee->property_name,
+ interfacee->class_name);
+ fprintf(outf,
+ "\tif (exc != DOM_NO_ERR) {\n"
+ "\t\treturn 0;\n"
+ "\t}\n"
+ "\n"
+ "\tduk_push_lstring(ctx,\n"
+ "\t\tdom_string_data(str),\n"
+ "\t\tdom_string_length(str));\n"
+ "\tdom_string_unref(str);\n"
+ "\n"
+ "\treturn 1;\n");
+ break;
+
+ case WEBIDL_TYPE_BOOL:
+ fprintf(outf,
+ "\tdom_exception exc;\n"
+ "\tbool b;\n"
+ "\n");
+ fprintf(outf,
+ "\texc = dom_%s_get_%s((struct dom_%s *)((node_private_t*)priv)->node, &b);\n",
+ interfacee->class_name,
+ atributee->property_name,
+ interfacee->class_name);
+ fprintf(outf,
+ "\tif (exc != DOM_NO_ERR) {\n"
+ "\t\treturn 0;\n"
+ "\t}\n"
+ "\n"
+ "\tduk_push_boolean(ctx, b);\n"
+ "\n"
+ "\treturn 1;\n");
+ break;
+
+ default:
+ return -1;
+
+ }
+
+ WARN(WARNING_GENERATED,
+ "Generated: getter %s::%s();",
+ interfacee->name, atributee->name);
+
+ return 0;
+}
+
+/**
+ * Output class property getter for a single attribute
+ */
+static int
+output_attribute_getter(FILE* outf,
struct ir_entry *interfacee,
struct ir_attribute_entry *atributee)
{
- int cdatac;
-
- /* setter definition */
+ /* getter definition */
fprintf(outf,
- "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n",
+ "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n",
DLPFX, interfacee->class_name, atributee->name);
fprintf(outf,"{\n");
output_get_method_private(outf, interfacee->class_name);
- cdatac = output_ccode(outf, atributee->setter);
- if (cdatac == 0) {
- WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: setter %s::%s();",
- interfacee->name, atributee->name);
+ /* if binding available for this attribute getter process it */
+ if (atributee->getter != NULL) {
+ int res;
+ res = output_ccode(outf, atributee->getter);
+ if (res == 0) {
+ /* no code provided for this getter so generate */
+ res = output_generated_attribute_getter(outf,
+ interfacee,
+ atributee);
+ }
+ if (res >= 0) {
+ fprintf(outf, "}\n\n");
+ return res;
+ }
+ }
- /* no implementation so generate default */
- fprintf(outf,"\treturn 0;\n");
+ WARN(WARNING_UNIMPLEMENTED,
+ "Unimplemented: getter %s::%s();",
+ interfacee->name, atributee->name);
+
+ if (options->dbglog) {
+ fprintf(outf, "\tLOG(\"Unimplemented\");\n" );
}
- fprintf(outf, "}\n\n");
+ /* no implementation so generate default */
+ fprintf(outf,
+ "\treturn 0;\n"
+ "}\n\n");
+
+ return 0;
+}
+
+/**
+ * Generate class property setter for a single attribute
+ */
+static int
+output_generated_attribute_setter(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *atributee)
+{
+ switch (atributee->base_type) {
+ case WEBIDL_TYPE_STRING:
+ fprintf(outf,
+ "\tdom_exception exc;\n"
+ "\tdom_string *str;\n"
+ "\tduk_size_t slen;\n"
+ "\tconst char *s;\n"
+ "\ts = duk_safe_to_lstring(ctx, 0, &slen);\n"
+ "\n"
+ "\texc = dom_string_create((const uint8_t *)s, slen, &str);\n"
+ "\tif (exc != DOM_NO_ERR) {\n"
+ "\t\treturn 0;\n"
+ "\t}\n"
+ "\n");
+ fprintf(outf,
+ "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, str);\n",
+ interfacee->class_name,
+ atributee->property_name,
+ interfacee->class_name);
+ fprintf(outf,
+ "\tdom_string_unref(str);\n"
+ "\tif (exc != DOM_NO_ERR) {\n"
+ "\t\treturn 0;\n"
+ "\t}\n"
+ "\n"
+ "\treturn 0;\n");
+ break;
+
+ case WEBIDL_TYPE_BOOL:
+ fprintf(outf,
+ "\tdom_exception exc;\n"
+ "\tbool b;\n"
+ "\n"
+ "\tb = duk_get_boolean(ctx, 0);\n"
+ "\n");
+ fprintf(outf,
+ "\texc = dom_%s_set_%s((struct dom_%s *)((node_private_t*)priv)->node, b);\n",
+ interfacee->class_name,
+ atributee->property_name,
+ interfacee->class_name);
+ fprintf(outf,
+ "\tif (exc != DOM_NO_ERR) {\n"
+ "\t\treturn 0;\n"
+ "\t}\n"
+ "\n"
+ "\treturn 0;\n");
+ break;
+
+ default:
+ return -1;
+
+ }
+
+ WARN(WARNING_GENERATED,
+ "Generated: getter %s::%s();",
+ interfacee->name, atributee->name);
return 0;
}
@@ -1233,18 +1380,8 @@ output_putforwards_setter(FILE* outf,
struct ir_entry *interfacee,
struct ir_attribute_entry *atributee)
{
- /* use explicit implementation in bindings if present */
- if (atributee->setter != NULL) {
- return output_attribute_setter(outf, interfacee, atributee);
- }
-
/* generate autogenerated putforwards */
- fprintf(outf,
- "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n",
- DLPFX, interfacee->class_name, atributee->name);
- fprintf(outf,"{\n");
-
fprintf(outf,"\tduk_ret_t get_ret;\n\n");
fprintf(outf,
@@ -1268,51 +1405,82 @@ output_putforwards_setter(FILE* outf,
"\tduk_pop(ctx);\n\n"
"\treturn 0;\n");
- fprintf(outf, "}\n\n");
-
return 0;
}
/**
- * Generate class property getter/setter for a single attribute
+ * Generate class property setter for a single attribute
*/
static int
-output_interface_attribute(FILE* outf,
- struct ir_entry *interfacee,
- struct ir_attribute_entry *atributee)
+output_attribute_setter(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *atributee)
{
- int cdatac;
- int res = 0;
+ int res = -1;
- /* getter definition */
+ /* setter definition */
fprintf(outf,
- "static duk_ret_t %s_%s_%s_getter(duk_context *ctx)\n",
+ "static duk_ret_t %s_%s_%s_setter(duk_context *ctx)\n",
DLPFX, interfacee->class_name, atributee->name);
fprintf(outf,"{\n");
output_get_method_private(outf, interfacee->class_name);
- cdatac = output_ccode(outf, atributee->getter);
- if (cdatac == 0) {
+ /* if binding available for this attribute getter process it */
+ if (atributee->setter != NULL) {
+ res = output_ccode(outf, atributee->setter);
+ if (res == 0) {
+ /* no code provided for this setter so generate */
+ res = output_generated_attribute_setter(outf,
+ interfacee,
+ atributee);
+ }
+ } else if (atributee->putforwards != NULL) {
+ res = output_putforwards_setter(outf,
+ interfacee,
+ atributee);
+ }
+
+ /* implementation not generated from any other source */
+ if (res < 0) {
WARN(WARNING_UNIMPLEMENTED,
- "Unimplemented: getter %s::%s();",
+ "Unimplemented: setter %s::%s();",
interfacee->name, atributee->name);
+ if (options->dbglog) {
+ fprintf(outf, "\tLOG(\"Unimplemented\");\n" );
+ }
+
/* no implementation so generate default */
- fprintf(outf,"\treturn 0;\n");
+ fprintf(outf, "\treturn 0;\n");
}
fprintf(outf, "}\n\n");
- if (atributee->putforwards != NULL) {
- res = output_putforwards_setter(outf, interfacee, atributee);
- } else {
- /* readonly attributes have no setter */
- if (atributee->modifier != WEBIDL_TYPE_MODIFIER_READONLY) {
- res = output_attribute_setter(outf,
- interfacee,
- atributee);
- }
+ return res;
+}
+
+
+/**
+ * Generate class property getter/setter for a single attribute
+ */
+static int
+output_interface_attribute(FILE* outf,
+ struct ir_entry *interfacee,
+ struct ir_attribute_entry *atributee)
+{
+ int res;
+
+ if (atributee->property_name == NULL) {
+ atributee->property_name = gen_idl2c_name(atributee->name);
+ }
+
+ res = output_attribute_getter(outf, interfacee, atributee);
+
+ /* only read/write and putforward attributes have a setter */
+ if ((atributee->modifier != WEBIDL_TYPE_MODIFIER_READONLY) ||
+ (atributee->putforwards != NULL)) {
+ res = output_attribute_setter(outf, interfacee, atributee);
}
return res;
diff --git a/src/ir.c b/src/ir.c
index 6dc2d2a..2260d4f 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -469,6 +469,7 @@ attribute_map_new(struct webidl_node *interface,
WEBIDL_NODE_TYPE_ATTRIBUTE);
while (at_node != NULL) {
+ enum webidl_type *base_type;
enum webidl_type_modifier *modifier;
cure->node = at_node;
@@ -485,6 +486,21 @@ attribute_map_new(struct webidl_node *interface,
GENBIND_METHOD_TYPE_GETTER,
cure->name);
+ /* find attributes base type */
+ base_type = (enum webidl_type *)webidl_node_getint(
+ webidl_node_find_type(
+ webidl_node_getnode(
+ webidl_node_find_type(
+ webidl_node_getnode(at_node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE)),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE_BASE));
+ if (base_type != NULL) {
+ cure->base_type = *base_type;
+ }
+
+
/* check for readonly attributes */
modifier = (enum webidl_type_modifier *)webidl_node_getint(
webidl_node_find_type(
diff --git a/src/ir.h b/src/ir.h
index ecedc95..12f1e79 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -52,11 +52,18 @@ struct ir_attribute_entry {
const char *name; /** attribute name */
struct webidl_node *node; /**< AST attribute node */
- enum webidl_type_modifier modifier;
+ enum webidl_type base_type; /* type of attribute */
+ enum webidl_type_modifier modifier; /* type modifier */
const char *putforwards;
struct genbind_node *getter; /**< getter from binding */
struct genbind_node *setter; /**< getter from binding */
+
+ char *property_name; /**< the attribute name converted to output
+ * appropriate value. e.g. generators targetting c
+ * might lowercase the name or add underscores
+ * instead of caps
+ */
};
/** map entry for constants on an interface */
@@ -101,8 +108,8 @@ enum ir_entry_type {
/** top level entry info common to interfaces and dictionaries */
struct ir_entry {
- const char *name; /** dictionary name */
- struct webidl_node *node; /**< AST dictionary node */
+ const char *name; /** IDL name */
+ struct webidl_node *node; /**< AST node */
const char *inherit_name; /**< Name of interface inhertited from */
struct genbind_node *class; /**< class from binding (if any) */