summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorRichard Beare <richard.beare@monash.edu>2018-09-12 17:30:04 +1000
committerRichard Beare <richard.beare@monash.edu>2019-03-08 21:56:36 +1100
commite9b39797cc16842fff35e683623003b536cf96de (patch)
treee0f086bf904d75960e521f7d634e6d48e8440778 /Source
parentbc0645ce2bc5afb19c62e4c6246397b9c2080d37 (diff)
downloadswig-e9b39797cc16842fff35e683623003b536cf96de.tar.gz
Setting enum values with calls to the C code.
Diffstat (limited to 'Source')
-rw-r--r--Source/Modules/r.cxx196
1 files changed, 139 insertions, 57 deletions
diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
index 019d5dd66..099251d0d 100644
--- a/Source/Modules/r.cxx
+++ b/Source/Modules/r.cxx
@@ -288,7 +288,8 @@ public:
int classDeclaration(Node *n);
int enumDeclaration(Node *n);
-
+ String *enumValue(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
int membervariableHandler(Node *n);
int typedefHandler(Node *n);
@@ -392,6 +393,8 @@ protected:
// Strings into which we cumulate the generated code that is to be written
//vto the files.
+ String *enum_values;
+ String *enum_def_calls;
String *sfile;
String *f_init;
String *s_classes;
@@ -456,6 +459,8 @@ R::R() :
copyStruct(false),
memoryProfile(false),
aggressiveGc(false),
+ enum_values(0),
+ enum_def_calls(0),
sfile(0),
f_init(0),
s_classes(0),
@@ -756,6 +761,7 @@ void R::init() {
s_classes = NewString("");
s_init = NewString("");
s_init_routine = NewString("");
+ enum_def_calls = NewString("");
}
@@ -878,6 +884,7 @@ int R::DumpCode(Node *n) {
Printf(scode, "%s\n\n", s_init);
Printf(scode, "%s\n\n", s_classes);
Printf(scode, "%s\n", sfile);
+ Printf(scode, "%s\n", enum_def_calls);
Delete(scode);
String *outfile = Getattr(n,"outfile");
@@ -1198,76 +1205,104 @@ int R::OutputArrayMethod(String *className, List *el, File *out) {
tdname is the typedef of the enumeration, i.e. giving its name.
*************************************************************/
int R::enumDeclaration(Node *n) {
- if (getCurrentClass() && (cplus_mode != PUBLIC))
- return SWIG_NOWRAP;
-
- String *name = Getattr(n, "name");
- String *tdname = Getattr(n, "tdname");
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
- /* Using name if tdname is empty. */
+ String *symname = Getattr(n, "sym:name");
- if(Len(tdname) == 0)
- tdname = name;
+ // TODO - deal with anonymous enumerations
+ // Previous enum code for R didn't wrap them
+ if (!symname || Getattr(n, "unnamedinstance"))
+ return SWIG_NOWRAP;
+ // create mangled name for the enum
+ // This will have content if the %nspace feature is set on
+ // the input file
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ String * ename;
- if(!tdname || Strcmp(tdname, "") == 0) {
+ String *name = Getattr(n, "name");
+ ename = getRClassName(name);
+ if (debugMode) {
+ Printf(stdout, "enumDeclaration: %s, %s, %s, %s\n", name, symname, nspace, ename);
+ }
+ Delete(name);
+ // set up a call to create the R enum structure. The list of
+ // individual elements will be built in enum_code
+ enum_values=0;
+ // Emit each enum item
Language::enumDeclaration(n);
- return SWIG_OK;
+
+ Printf(enum_def_calls, "defineEnumeration(\"%s\",\n .values=c(%s))\n\n",
+ ename, enum_values);
+ Delete(enum_values);
+ Delete(ename);
+ //Delete(symname);
+ }
+ return SWIG_OK;
+}
+/*************************************************************
+**************************************************************/
+int R::enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC)) {
+ Printf(stdout , "evd: Not public\n");
+ return SWIG_NOWRAP;
}
- String *mangled_tdname = SwigType_manglestr(tdname);
- String *scode = NewString("");
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *parent_name = Getattr(parent, "name");
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_BOOL) {
+ const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
+ Setattr(n, "enumvalue", val);
+ } else if (swigtype == T_CHAR) {
+ String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+
+ if (GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
- Printv(scode, "defineEnumeration('", mangled_tdname, "'",
- ",\n", tab8, tab8, tab4, ".values = c(\n", NIL);
+ {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ Setattr(n, "type", typemap_lookup_type);
+
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
- Node *c;
- int value = -1; // First number is zero
- for (c = firstChild(n); c; c = nextSibling(c)) {
- // const char *tag = Char(nodeType(c));
- // if (Strcmp(tag,"cdecl") == 0) {
- name = Getattr(c, "name");
- String *val = Getattr(c, "enumvalue");
- if(val && Char(val)) {
- int inval;
- if (!getNumber(val, &inval)) {
- // Conversion failed - use the string value in val.
- } else {
- val = NULL;
- value = inval;
- }
+ String *value = enumValue(n);
+ if (enum_values) {
+ Printf(enum_values, ",\n\"%s\" = %s", name, value);
} else {
- val = NULL;
- value++;
+ enum_values=NewString("");
+ Printf(enum_values, "\"%s\" = %s", name, value);
}
- if (val != NULL) {
- // This won't work in general, but will at least handle cases like (3)
- // and 3+7, and when it doesn't work, it'll fail noisly rather than
- // quietly using the wrong enum value like we used to.
- if (!Strcmp(val, "true")) {
- Printf(scode, "%s%s%s'%s' = %s%s\n", tab8, tab8, tab8, name, "TRUE",
- nextSibling(c) ? ", " : "");
- } else if (!Strcmp(val, "false")) {
- Printf(scode, "%s%s%s'%s' = %s%s\n", tab8, tab8, tab8, name, "FALSE",
- nextSibling(c) ? ", " : "");
- } else {
- Printf(scode, "%s%s%s'%s' = %s%s\n", tab8, tab8, tab8, name, val,
- nextSibling(c) ? ", " : "");
- }
- } else {
- Printf(scode, "%s%s%s'%s' = %d%s\n", tab8, tab8, tab8, name, value,
- nextSibling(c) ? ", " : "");
- }
- // }
+ Delete(value);
}
- Printv(scode, "))", NIL);
- Printf(sfile, "%s\n", scode);
-
- Delete(scode);
- Delete(mangled_tdname);
-
return SWIG_OK;
}
@@ -2853,3 +2888,50 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
}
/*************************************************************************************/
+ /* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in from R when
+ * setting up an enum variable
+ * ------------------------------------------------------------------------ */
+
+String *R::enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *newsymname = 0;
+
+ Node *parent = parentNode(n);
+ symname = Getattr(n, "sym:name");
+
+ String *etype = Getattr(parent, "enumtype");
+ // we have to directly call the c wrapper function, as the
+ // R wrapper to the enum is designed to be used after the enum
+ // structures have been created on the R side. This means
+ // that we'll need to construct a .Call expression
+
+ // change the type for variableWrapper
+ Setattr(n, "type", etype);
+
+ if (!getCurrentClass()) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ } else {
+ String *enumClassPrefix = getEnumClassPrefix();
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ }
+ value = Swig_name_wrapper(value);
+ Replace(value, "_wrap", "R_swig", DOH_REPLACE_FIRST);
+
+ String *valuecall=NewString("");
+ Printv(valuecall, ".Call('", value, "',FALSE, PACKAGE='", Rpackage, "')", NIL);
+ Delete(value);
+ return valuecall;
+}