Setting enum values with calls to the C code.
This commit is contained in:
parent
bc0645ce2b
commit
e9b39797cc
2 changed files with 142 additions and 60 deletions
|
|
@ -73,7 +73,7 @@ function(name, .values, where = topenv(parent.frame()), suffix = "Value")
|
||||||
{
|
{
|
||||||
# Mirror the class definitions via the E analogous to .__C__
|
# Mirror the class definitions via the E analogous to .__C__
|
||||||
defName = paste(".__E__", name, sep = "")
|
defName = paste(".__E__", name, sep = "")
|
||||||
assign(defName, .values, envir = where)
|
delayedAssign(defName, .values, assign.env = where)
|
||||||
|
|
||||||
if(nchar(suffix))
|
if(nchar(suffix))
|
||||||
name = paste(name, suffix, sep = "")
|
name = paste(name, suffix, sep = "")
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,8 @@ public:
|
||||||
|
|
||||||
int classDeclaration(Node *n);
|
int classDeclaration(Node *n);
|
||||||
int enumDeclaration(Node *n);
|
int enumDeclaration(Node *n);
|
||||||
|
String *enumValue(Node *n);
|
||||||
|
virtual int enumvalueDeclaration(Node *n);
|
||||||
int membervariableHandler(Node *n);
|
int membervariableHandler(Node *n);
|
||||||
|
|
||||||
int typedefHandler(Node *n);
|
int typedefHandler(Node *n);
|
||||||
|
|
@ -392,6 +393,8 @@ protected:
|
||||||
|
|
||||||
// Strings into which we cumulate the generated code that is to be written
|
// Strings into which we cumulate the generated code that is to be written
|
||||||
//vto the files.
|
//vto the files.
|
||||||
|
String *enum_values;
|
||||||
|
String *enum_def_calls;
|
||||||
String *sfile;
|
String *sfile;
|
||||||
String *f_init;
|
String *f_init;
|
||||||
String *s_classes;
|
String *s_classes;
|
||||||
|
|
@ -456,6 +459,8 @@ R::R() :
|
||||||
copyStruct(false),
|
copyStruct(false),
|
||||||
memoryProfile(false),
|
memoryProfile(false),
|
||||||
aggressiveGc(false),
|
aggressiveGc(false),
|
||||||
|
enum_values(0),
|
||||||
|
enum_def_calls(0),
|
||||||
sfile(0),
|
sfile(0),
|
||||||
f_init(0),
|
f_init(0),
|
||||||
s_classes(0),
|
s_classes(0),
|
||||||
|
|
@ -756,6 +761,7 @@ void R::init() {
|
||||||
s_classes = NewString("");
|
s_classes = NewString("");
|
||||||
s_init = NewString("");
|
s_init = NewString("");
|
||||||
s_init_routine = 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_init);
|
||||||
Printf(scode, "%s\n\n", s_classes);
|
Printf(scode, "%s\n\n", s_classes);
|
||||||
Printf(scode, "%s\n", sfile);
|
Printf(scode, "%s\n", sfile);
|
||||||
|
Printf(scode, "%s\n", enum_def_calls);
|
||||||
|
|
||||||
Delete(scode);
|
Delete(scode);
|
||||||
String *outfile = Getattr(n,"outfile");
|
String *outfile = Getattr(n,"outfile");
|
||||||
|
|
@ -1198,75 +1205,103 @@ int R::OutputArrayMethod(String *className, List *el, File *out) {
|
||||||
tdname is the typedef of the enumeration, i.e. giving its name.
|
tdname is the typedef of the enumeration, i.e. giving its name.
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
int R::enumDeclaration(Node *n) {
|
int R::enumDeclaration(Node *n) {
|
||||||
if (getCurrentClass() && (cplus_mode != PUBLIC))
|
if (!ImportMode) {
|
||||||
return SWIG_NOWRAP;
|
if (getCurrentClass() && (cplus_mode != PUBLIC))
|
||||||
|
return SWIG_NOWRAP;
|
||||||
|
|
||||||
String *name = Getattr(n, "name");
|
String *symname = Getattr(n, "sym:name");
|
||||||
String *tdname = Getattr(n, "tdname");
|
|
||||||
|
|
||||||
/* Using name if tdname is empty. */
|
// TODO - deal with anonymous enumerations
|
||||||
|
// Previous enum code for R didn't wrap them
|
||||||
|
if (!symname || Getattr(n, "unnamedinstance"))
|
||||||
|
return SWIG_NOWRAP;
|
||||||
|
|
||||||
if(Len(tdname) == 0)
|
// create mangled name for the enum
|
||||||
tdname = name;
|
// 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;
|
||||||
|
|
||||||
|
String *name = Getattr(n, "name");
|
||||||
if(!tdname || Strcmp(tdname, "") == 0) {
|
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);
|
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);
|
Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
|
||||||
String *scode = NewString("");
|
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;
|
||||||
|
|
||||||
Printv(scode, "defineEnumeration('", mangled_tdname, "'",
|
// Strange hack from parent method
|
||||||
",\n", tab8, tab8, tab4, ".values = c(\n", NIL);
|
if (value)
|
||||||
|
tmpValue = NewString(value);
|
||||||
Node *c;
|
else
|
||||||
int value = -1; // First number is zero
|
tmpValue = NewString(name);
|
||||||
for (c = firstChild(n); c; c = nextSibling(c)) {
|
// Note that this is used in enumValue() amongst other places
|
||||||
// const char *tag = Char(nodeType(c));
|
Setattr(n, "value", tmpValue);
|
||||||
// if (Strcmp(tag,"cdecl") == 0) {
|
|
||||||
name = Getattr(c, "name");
|
// Deal with enum values that are not int
|
||||||
String *val = Getattr(c, "enumvalue");
|
int swigtype = SwigType_type(Getattr(n, "type"));
|
||||||
if(val && Char(val)) {
|
if (swigtype == T_BOOL) {
|
||||||
int inval;
|
const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
|
||||||
if (!getNumber(val, &inval)) {
|
Setattr(n, "enumvalue", val);
|
||||||
// Conversion failed - use the string value in val.
|
} else if (swigtype == T_CHAR) {
|
||||||
} else {
|
String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
|
||||||
val = NULL;
|
Setattr(n, "enumvalue", val);
|
||||||
value = inval;
|
Delete(val);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val = NULL;
|
|
||||||
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) ? ", " : "");
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Printv(scode, "))", NIL);
|
if (GetFlag(parent, "scopedenum")) {
|
||||||
Printf(sfile, "%s\n", scode);
|
newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
|
||||||
|
symname = newsymname;
|
||||||
|
}
|
||||||
|
|
||||||
Delete(scode);
|
{
|
||||||
Delete(mangled_tdname);
|
// 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
|
||||||
|
|
||||||
|
String *value = enumValue(n);
|
||||||
|
if (enum_values) {
|
||||||
|
Printf(enum_values, ",\n\"%s\" = %s", name, value);
|
||||||
|
} else {
|
||||||
|
enum_values=NewString("");
|
||||||
|
Printf(enum_values, "\"%s\" = %s", name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Delete(value);
|
||||||
|
}
|
||||||
|
|
||||||
return SWIG_OK;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue