Merge branch 'REnums2018'

* REnums2018:
  Fix R return by C++11 const ref enum classes
  Remove unused code in r.cxx
  extra doc on anonymous enums
  ENH:
  FIX: references to enums now functioning
  DOC: Extended documentation on enumeration support in R
  FIX: Corrected path to output from R tests
  Reformat comments in R module
  ENH: Run test for enum_thorough in R
  Code style changes post review
  ENH: R Module: Enumerations with values set by calls to C code, allowing arbitarily complex value expressions.
  Setting enum values with calls to the C code.
This commit is contained in:
William S Fulton 2019-03-18 18:03:20 +00:00
commit cfa7a4d4d0
7 changed files with 875 additions and 291 deletions

View file

@ -189,9 +189,48 @@ of the proxy class baggage you see in other languages.
<p>
enumerations are characters which are then converted back and forth to
ints before calling the C routines. All of the enumeration code is
done in R.
R doesn't have a native enumeration type. Enumerations are represented
as character strings in R, with calls to R functions that convert back
and forth between integers.
The details of enumeration names and contents are stored in hidden R
environments, which are named according the the enumeration name - for
example, an enumeration colour:
<div class="code"><pre>
enum colour { red=-1, blue, green = 10 };
</pre></div>
will be initialized by the following call in R:
<div class="code"><pre>
defineEnumeration("_colour",
.values=c("red" = .Call('R_swig_colour_red_get',FALSE, PACKAGE='enum_thorough'),
"blue" = .Call('R_swig_colour_blue_get',FALSE, PACKAGE='enum_thorough'),
"green" = .Call('R_swig_colour_green_get',FALSE, PACKAGE='enum_thorough')))
</pre></div>
which will create an environment named <tt>.__E___colour</tt>. The enumeration
values are initialised via calls to C/C++ code, allowing complex
values for enumerations to be used. Calls to the C/C++ code require
the compiled library to be loaded, so a <tt>delayedAssign</tt> is employed
within <tt>defineEnumeration</tt> in order to allow the code to be easily used in R
packages.
The user typically does not need to access the enumeration lookup
functions or know the name of the enumeration type used by
R. Attributes containing the type information are attached by swig to
functions requiring enumeration arguments or returning enumeration
values, and those attributes are used to identify and access the
appropriate environments and thus translate between characters
and integers.
The relevant functions, for debugging purposes, are <tt>enumToInteger</tt> and
</tt>enumFromInteger</tt>.
Anonymous enumerations are ignored by the binding generation process,
leaving no way of accessing the value of anonymous enumerations from R
code.
</p>
</body>

View file

@ -27,7 +27,6 @@ CPP_TEST_CASES += \
# arithmetic expressions
FAILING_CPP_TESTS = \
enum_thorough \
preproc_constants
FAILING_C_TESTS = \
@ -64,7 +63,7 @@ include $(srcdir)/../common.mk
# check for syntactic correctness
run_testcase = \
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) || (cat $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)out ; false); \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) || (cat ./$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)out ; false); \
else \
$(RUNTOOL) $(RUNR) ./$(SCRIPTPREFIX)$*$(WRAPSUFFIX) || (cat ./$(SCRIPTPREFIX)$*$(WRAPSUFFIX)out ; false); \
fi
@ -72,7 +71,7 @@ run_testcase = \
run_multitestcase = \
for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ]; then \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) || (cat $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX)out ; false); \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" $(RUNTOOL) $(RUNR) $(SCRIPTDIR)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) || (cat ./$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX)out ; false); \
else \
$(RUNTOOL) $(RUNR) ./$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX) || (cat ./$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX)out ; false); \
fi; \

View file

@ -0,0 +1,452 @@
clargs <- commandArgs(trailing=TRUE)
source(file.path(clargs[1], "unittest.R"))
dyn.load(paste("enum_thorough", .Platform$dynlib.ext, sep=""))
source("enum_thorough.R")
cacheMetaData(1)
## Anonymous enums are not wrapped by the R module
##
# Colours - string interface, various function signatures
unittest('red', colourTest1('red'))
unittest('blue', colourTest1('blue'))
unittest('green', colourTest1('green'))
unittest('red', colourTest2('red'))
unittest('blue', colourTest2('blue'))
unittest('green', colourTest2('green'))
unittest('red', colourTest3('red'))
unittest('blue', colourTest3('blue'))
unittest('green', colourTest3('green'))
unittest('red', colourTest4('red'))
unittest('blue', colourTest4('blue'))
unittest('green', colourTest4('green'))
## Colours - underlying integers
unittest(-1, enumToInteger('red', '_colour'))
unittest(0, enumToInteger('blue', '_colour'))
unittest(10, enumToInteger('green', '_colour'))
########
## enum variable, wrapped as a function
## Is initialization to 0 a "standard"
myColour()
## Test setting and retrieving
myColour('green')
unittest('green', myColour())
########
## SpeedClass
s <- SpeedClass()
v <- "medium"
unittest(v, s$speedTest1(v))
unittest(v, s$speedTest2(v))
unittest(v, s$speedTest3(v))
unittest(v, s$speedTest4(v))
unittest(v, s$speedTest5(v))
unittest(v, s$speedTest6(v))
unittest(v, s$speedTest7(v))
unittest(v, s$speedTest8(v))
## speedTest methods not in the class
unittest(v, speedTest1(v))
unittest(v, speedTest2(v))
unittest(v, speedTest3(v))
unittest(v, speedTest4(v))
# enum reference
unittest(v, speedTest5(v))
## member access
s <- SpeedClass()
unittest("slow", s$mySpeedtd1)
# check integer value
unittest(10, enumToInteger(s$mySpeedtd1, "_SpeedClass__speed"))
# set and check
s$mySpeedtd1 <- "lightning"
unittest("lightning", s$mySpeedtd1)
unittest(31, enumToInteger(s$mySpeedtd1, "_SpeedClass__speed"))
## Named anon - not wrapped nicely, but can be retrieved:
unittest("NamedAnon2", namedanon_NamedAnon2_get())
unittest(0, enumToInteger(namedanon_NamedAnon1_get(), "_namedanon"))
unittest(1, enumToInteger(namedanon_NamedAnon2_get(), "_namedanon"))
## Twonames
v <- "TwoNames1"
unittest(v, twonamesTest1(v))
unittest(v, twonamesTest2(v))
unittest(v, twonamesTest3(v))
unittest(33, enumToInteger("TwoNames3", "_twonamestag"))
tt <- TwoNamesStruct()
v <- "TwoNamesStruct1"
unittest(v, tt$twonamesTest1(v))
unittest(v, tt$twonamesTest2(v))
unittest(v, tt$twonamesTest3(v))
## Try the wrong name
unittest(TRUE, is.na(tt$twonamesTest3("TwoNames1")))
## Namedanonspace
## can get the values
v <- namedanonspace_NamedAnonSpace2_get()
unittest(v, namedanonspaceTest1(v))
unittest(v, namedanonspaceTest2(v))
unittest(v, namedanonspaceTest3(v))
unittest(v, namedanonspaceTest4(v))
## scientists
tt <- TemplateClassInt()
g <- "galileo"
unittest(g, tt$scientistsTest1(g))
unittest(g, tt$scientistsTest2(g))
unittest(g, tt$scientistsTest3(g))
unittest(g, tt$scientistsTest4(g))
unittest(g, tt$scientistsTest5(g))
unittest(g, tt$scientistsTest6(g))
unittest(g, tt$scientistsTest7(g))
unittest(g, tt$scientistsTest8(g))
unittest(g, tt$scientistsTest9(g))
## This one is commented out in csharp too
## unittest(g, tt$scientistsTestA(g))
unittest(g, tt$scientistsTestB(g))
## This one is commented out in csharp too
## unittest(g, tt$scientistsTestC(g))
unittest(g, tt$scientistsTestD(g))
unittest(g, tt$scientistsTestE(g))
unittest(g, tt$scientistsTestF(g))
unittest(g, tt$scientistsTestG(g))
unittest(g, tt$scientistsTestH(g))
unittest(g, tt$scientistsTestI(g))
# enum reference
unittest(g, tt$scientistsTestJ(g))
unittest(g, scientistsTest1(g))
unittest(g, scientistsTest2(g))
unittest(g, scientistsTest3(g))
unittest(g, scientistsTest4(g))
unittest(g, scientistsTest5(g))
unittest(g, scientistsTest6(g))
unittest(g, scientistsTest7(g))
## enum reference
unittest(g, scientistsTest8(g))
tt <- TClassInt()
b <- "bell"
unittest(b, tt$scientistsNameTest1(b))
unittest(b, tt$scientistsNameTest2(b))
unittest(b, tt$scientistsNameTest3(b))
unittest(b, tt$scientistsNameTest4(b))
unittest(b, tt$scientistsNameTest5(b))
unittest(b, tt$scientistsNameTest6(b))
unittest(b, tt$scientistsNameTest7(b))
unittest(b, tt$scientistsNameTest8(b))
unittest(b, tt$scientistsNameTest9(b))
## This one is commented out in csharp too
## unittest(b, tt$scientistsNameTestA(b))
unittest(b, tt$scientistsNameTestB(b))
## This one is commented out in csharp too
## unittest(b, tt$scientistsNameTestC(b))
unittest(b, tt$scientistsNameTestD(b))
unittest(b, tt$scientistsNameTestE(b))
unittest(b, tt$scientistsNameTestF(b))
unittest(b, tt$scientistsNameTestG(b))
unittest(b, tt$scientistsNameTestH(b))
unittest(b, tt$scientistsNameTestI(b))
unittest(b, tt$scientistsNameSpaceTest1(b))
unittest(b, tt$scientistsNameSpaceTest2(b))
unittest(b, tt$scientistsNameSpaceTest3(b))
unittest(b, tt$scientistsNameSpaceTest4(b))
unittest(b, tt$scientistsNameSpaceTest5(b))
unittest(b, tt$scientistsNameSpaceTest6(b))
unittest(b, tt$scientistsNameSpaceTest7(b))
unittest(g, tt$scientistsOtherTest1(g))
unittest(g, tt$scientistsOtherTest2(g))
unittest(g, tt$scientistsOtherTest3(g))
unittest(g, tt$scientistsOtherTest4(g))
unittest(g, tt$scientistsOtherTest5(g))
unittest(g, tt$scientistsOtherTest6(g))
unittest(g, tt$scientistsOtherTest7(g))
## Global
unittest(b, scientistsNameTest1(b))
unittest(b, scientistsNameTest2(b))
unittest(b, scientistsNameTest3(b))
unittest(b, scientistsNameTest4(b))
unittest(b, scientistsNameTest5(b))
unittest(b, scientistsNameTest6(b))
unittest(b, scientistsNameTest7(b))
unittest(b, scientistsNameSpaceTest1(b))
unittest(b, scientistsNameSpaceTest2(b))
unittest(b, scientistsNameSpaceTest3(b))
unittest(b, scientistsNameSpaceTest4(b))
unittest(b, scientistsNameSpaceTest5(b))
unittest(b, scientistsNameSpaceTest6(b))
unittest(b, scientistsNameSpaceTest7(b))
unittest(b, scientistsNameSpaceTest8(b))
unittest(b, scientistsNameSpaceTest9(b))
unittest(b, scientistsNameSpaceTestA(b))
unittest(b, scientistsNameSpaceTestB(b))
unittest(b, scientistsNameSpaceTestC(b))
unittest(b, scientistsNameSpaceTestD(b))
unittest(b, scientistsNameSpaceTestE(b))
unittest(b, scientistsNameSpaceTestF(b))
unittest(b, scientistsNameSpaceTestG(b))
unittest(b, scientistsNameSpaceTestH(b))
unittest(b, scientistsNameSpaceTestI(b))
unittest(b, scientistsNameSpaceTestJ(b))
unittest(b, scientistsNameSpaceTestK(b))
unittest(b, scientistsNameSpaceTestL(b))
## rename test
v <- "eek"
unittest(v, renameTest1(v))
unittest(v, renameTest2(v))
## NewName
N <- NewNameStruct()
## Only half works:
unittest("kerboom", NewNameStruct_bang_get())
## Can't put in "bang" in the call
## confirm with:
## get(".__E___OldNameStruct__enumeration")
## TreeClass
T <- TreesClass()
p <- "pine"
unittest(p, T$treesTest1(p))
unittest(p, T$treesTest2(p))
unittest(p, T$treesTest3(p))
unittest(p, T$treesTest4(p))
unittest(p, T$treesTest5(p))
unittest(p, T$treesTest6(p))
unittest(p, T$treesTest7(p))
unittest(p, T$treesTest8(p))
unittest(p, T$treesTest9(p))
unittest(p, T$treesTestA(p))
unittest(p, T$treesTestB(p))
unittest(p, T$treesTestC(p))
unittest(p, T$treesTestD(p))
unittest(p, T$treesTestE(p))
unittest(p, T$treesTestF(p))
unittest(p, T$treesTestG(p))
unittest(p, T$treesTestH(p))
unittest(p, T$treesTestI(p))
unittest(p, T$treesTestJ(p))
unittest(p, T$treesTestK(p))
unittest(p, T$treesTestL(p))
unittest(p, T$treesTestM(p))
unittest(p, T$treesTestN(p))
unittest(p, T$treesTestO(p))
unittest(p, treesTest1(p))
unittest(p, treesTest2(p))
unittest(p, treesTest3(p))
unittest(p, treesTest4(p))
unittest(p, treesTest5(p))
unittest(p, treesTest6(p))
unittest(p, treesTest7(p))
unittest(p, treesTest8(p))
unittest(p, treesTest9(p))
unittest(p, treesTestA(p))
unittest(p, treesTestB(p))
unittest(p, treesTestC(p))
unittest(p, treesTestD(p))
unittest(p, treesTestE(p))
unittest(p, treesTestF(p))
unittest(p, treesTestG(p))
unittest(p, treesTestH(p))
unittest(p, treesTestI(p))
unittest(p, treesTestJ(p))
unittest(p, treesTestK(p))
unittest(p, treesTestL(p))
unittest(p, treesTestM(p))
unittest(p, treesTestO(p))
unittest(p, treesTestP(p))
unittest(p, treesTestQ(p))
unittest(p, treesTestR(p))
## Hair
h <- HairStruct()
g <- "ginger"
unittest(g, h$hairTest1(g))
unittest(g, h$hairTest2(g))
unittest(g, h$hairTest3(g))
unittest(g, h$hairTest4(g))
unittest(g, h$hairTest5(g))
unittest(g, h$hairTest6(g))
unittest(g, h$hairTest7(g))
unittest(g, h$hairTest8(g))
unittest(g, h$hairTest9(g))
unittest(g, h$hairTestA(g))
unittest(g, h$hairTestB(g))
r <- "red"
unittest(r, h$colourTest1(r))
unittest(r, h$colourTest2(r))
nmA <- "NamedAnon1"
unittest(nmA, h$namedanonTest1(nmA))
unittest("NamedAnonSpace2", h$namedanonspaceTest1("NamedAnonSpace2"))
f <- "fir"
unittest(f, h$treesGlobalTest1(f))
unittest(f, h$treesGlobalTest2(f))
unittest(f, h$treesGlobalTest3(f))
unittest(f, h$treesGlobalTest4(f))
b <- "blonde"
unittest(b, hairTest1(b))
unittest(b, hairTest2(b))
unittest(b, hairTest3(b))
unittest(b, hairTest4(b))
unittest(b, hairTest5(b))
unittest(b, hairTest6(b))
unittest(b, hairTest7(b))
unittest(b, hairTest8(b))
unittest(b, hairTest9(b))
unittest(b, hairTestA(b))
unittest(b, hairTestB(b))
## enum reference
unittest(b, hairTestC(b))
unittest(b, hairTestA1(b))
unittest(b, hairTestA2(b))
unittest(b, hairTestA3(b))
unittest(b, hairTestA4(b))
unittest(b, hairTestA5(b))
unittest(b, hairTestA6(b))
unittest(b, hairTestA7(b))
unittest(b, hairTestA8(b))
unittest(b, hairTestA9(b))
unittest(b, hairTestAA(b))
unittest(b, hairTestAB(b))
## enum reference
unittest(b, hairTestAC(b))
unittest(b, hairTestB1(b))
unittest(b, hairTestB2(b))
unittest(b, hairTestB3(b))
unittest(b, hairTestB4(b))
unittest(b, hairTestB5(b))
unittest(b, hairTestB6(b))
unittest(b, hairTestB7(b))
unittest(b, hairTestB8(b))
unittest(b, hairTestB9(b))
unittest(b, hairTestBA(b))
unittest(b, hairTestBB(b))
## enum reference
unittest(b, hairTestBC(b))
f <- FirStruct()
b <- "blonde"
unittest(b, f$hairTestFir1(b))
unittest(b, f$hairTestFir2(b))
unittest(b, f$hairTestFir3(b))
unittest(b, f$hairTestFir4(b))
unittest(b, f$hairTestFir5(b))
unittest(b, f$hairTestFir6(b))
unittest(b, f$hairTestFir7(b))
unittest(b, f$hairTestFir8(b))
unittest(b, f$hairTestFir9(b))
unittest(b, f$hairTestFirA(b))
## Unnamed enum instance doesn't work
## Wrapper set/get exists, but there's
## no mapping between strings and integers
GlobalInstance(1)
unittest(1, GlobalInstance())
ii <- Instances()
ii$MemberInstance <- 1
unittest(1, ii$MemberInstance)
ii <- IgnoreTest()
## Testing integer values
unittest(0, enumToInteger(IgnoreTest_ignoreA_zero_get(), "_IgnoreTest__IgnoreA"))
unittest(3, enumToInteger(IgnoreTest_ignoreA_three_get(), "_IgnoreTest__IgnoreA"))
unittest(10, enumToInteger(IgnoreTest_ignoreA_ten_get(), "_IgnoreTest__IgnoreA"))
unittest(11, enumToInteger(IgnoreTest_ignoreA_eleven_get(), "_IgnoreTest__IgnoreA"))
unittest(14, enumToInteger(IgnoreTest_ignoreA_fourteen_get(), "_IgnoreTest__IgnoreA"))
unittest(20, enumToInteger(IgnoreTest_ignoreA_twenty_get(), "_IgnoreTest__IgnoreA"))
unittest(30, enumToInteger(IgnoreTest_ignoreA_thirty_get(), "_IgnoreTest__IgnoreA"))
unittest(32, enumToInteger(IgnoreTest_ignoreA_thirty_two_get(), "_IgnoreTest__IgnoreA"))
unittest(33, enumToInteger(IgnoreTest_ignoreA_thirty_three_get(), "_IgnoreTest__IgnoreA"))
unittest(11, enumToInteger(IgnoreTest_ignoreB_eleven_get(), "_IgnoreTest__IgnoreB"))
unittest(12, enumToInteger(IgnoreTest_ignoreB_twelve_get(), "_IgnoreTest__IgnoreB"))
unittest(31, enumToInteger(IgnoreTest_ignoreB_thirty_one_get(), "_IgnoreTest__IgnoreB"))
unittest(32, enumToInteger(IgnoreTest_ignoreB_thirty_two_get(), "_IgnoreTest__IgnoreB"))
unittest(41, enumToInteger(IgnoreTest_ignoreB_forty_one_get(), "_IgnoreTest__IgnoreB"))
unittest(42, enumToInteger(IgnoreTest_ignoreB_forty_two_get(), "_IgnoreTest__IgnoreB"))
unittest(10, enumToInteger(IgnoreTest_ignoreC_ten_get(), "_IgnoreTest__IgnoreC"))
unittest(12, enumToInteger(IgnoreTest_ignoreC_twelve_get(), "_IgnoreTest__IgnoreC"))
unittest(30, enumToInteger(IgnoreTest_ignoreC_thirty_get(), "_IgnoreTest__IgnoreC"))
unittest(32, enumToInteger(IgnoreTest_ignoreC_thirty_two_get(), "_IgnoreTest__IgnoreC"))
unittest(40, enumToInteger(IgnoreTest_ignoreC_forty_get(), "_IgnoreTest__IgnoreC"))
unittest(42, enumToInteger(IgnoreTest_ignoreC_forty_two_get(), "_IgnoreTest__IgnoreC"))
unittest(21, enumToInteger(IgnoreTest_ignoreD_twenty_one_get(), "_IgnoreTest__IgnoreD"))
unittest(22, enumToInteger(IgnoreTest_ignoreD_twenty_two_get(), "_IgnoreTest__IgnoreD"))
unittest(0, enumToInteger(IgnoreTest_ignoreE_zero_get(), "_IgnoreTest__IgnoreE"))
unittest(21, enumToInteger(IgnoreTest_ignoreE_twenty_one_get(), "_IgnoreTest__IgnoreE"))
unittest(22, enumToInteger(IgnoreTest_ignoreE_twenty_two_get(), "_IgnoreTest__IgnoreE"))
## confirm that an ignore directive is followed:
unittest(TRUE, is.na(ignoreCTest("ignoreC_eleven")))
## repeat test
unittest(1, enumToInteger(repeatTest("one"), "_RepeatSpace__repeat"))
unittest(1, enumToInteger(repeatTest("initial"), "_RepeatSpace__repeat"))
unittest(2, enumToInteger(repeatTest("two"), "_RepeatSpace__repeat"))
unittest(3, enumToInteger(repeatTest("three"), "_RepeatSpace__repeat"))
unittest(3, enumToInteger(repeatTest("llast"), "_RepeatSpace__repeat"))
unittest(3, enumToInteger(repeatTest("end"), "_RepeatSpace__repeat"))
## Macro test - nothing in csharp
## Note - this enum is set up with both entries the same
## This means that mapping back from the integer value to the
## string value isn't unique, so asking for "ABCD2" will return
## a string of "ABCD"
unittest("ABCD", enumWithMacroTest("ABCD"))
## Different types
unittest(10, enumToInteger(differentTypesTest("typeint"), "_DifferentSpace__DifferentTypes"))
unittest(0, enumToInteger(differentTypesTest("typeboolfalse"), "_DifferentSpace__DifferentTypes"))
unittest(1, enumToInteger(differentTypesTest("typebooltrue"), "_DifferentSpace__DifferentTypes"))
unittest(2, enumToInteger(differentTypesTest("typebooltwo"), "_DifferentSpace__DifferentTypes"))
unittest(utf8ToInt('C'), enumToInteger(differentTypesTest("typechar"), "_DifferentSpace__DifferentTypes"))
unittest(utf8ToInt('D'), enumToInteger(differentTypesTest("typedefaultint"), "_DifferentSpace__DifferentTypes"))
unittest(utf8ToInt('A') + 1, enumToInteger(differentTypesTest("typecharcompound"), "_DifferentSpace__DifferentTypes"))
## Global different types
## Test uses an anonymous type so the string mapping
## framework doesn't exist.

View file

@ -192,6 +192,11 @@ unsigned char *OUTPUT
free($1);
}
%typemap(in) const enum SWIGTYPE & ($*1_ltype temp)
%{ temp = ($*1_ltype)INTEGER($input)[0];
$1 = &temp; %}
%typemap(out) const enum SWIGTYPE & %{ $result = Rf_ScalarInteger((int)*$1); %}
%typemap(memberin) char[] %{
if ($input) strcpy($1, $input);

View file

@ -16,6 +16,7 @@
%typemap("rtype") enum SWIGTYPE * "character";
%typemap("rtype") enum SWIGTYPE *const "character";
%typemap("rtype") enum SWIGTYPE & "character";
%typemap("rtype") const enum SWIGTYPE & "character";
%typemap("rtype") enum SWIGTYPE && "character";
%typemap("rtype") SWIGTYPE * "$R_class";
%typemap("rtype") SWIGTYPE *const "$R_class";
@ -86,9 +87,7 @@
%typemap(scoercein) enum SWIGTYPE
%{ $input = enumToInteger($input, "$R_class"); %}
%typemap(scoercein) enum SWIGTYPE &
%{ $input = enumToInteger($input, "$R_class"); %}
%typemap(scoercein) enum SWIGTYPE &&
%{ $input = enumToInteger($input, "$R_class"); %}
%{ $input = enumToInteger($input, "$*R_class"); %}
%typemap(scoercein) enum SWIGTYPE *
%{ $input = enumToInteger($input, "$R_class"); %}
%typemap(scoercein) enum SWIGTYPE *const
@ -138,7 +137,7 @@ string &, std::string &
%{ $result = enumFromInteger($result, "$R_class"); %}
%typemap(scoerceout) enum SWIGTYPE &
%{ $result = enumFromInteger($result, "$R_class"); %}
%{ $result = enumFromInteger($result, "$*R_class"); %}
%typemap(scoerceout) enum SWIGTYPE &&
%{ $result = enumFromInteger($result, "$R_class"); %}

View file

@ -73,7 +73,7 @@ function(name, .values, where = topenv(parent.frame()), suffix = "Value")
{
# Mirror the class definitions via the E analogous to .__C__
defName = paste(".__E__", name, sep = "")
assign(defName, .values, envir = where)
delayedAssign(defName, .values, assign.env = where)
if(nchar(suffix))
name = paste(name, suffix, sep = "")

View file

@ -65,77 +65,38 @@ static String * getRTypeName(SwigType *t, int *outCount = NULL) {
*/
}
/*********************
Tries to get the name of the R class corresponding to the given type
e.g. struct A * is ARef, struct A** is ARefRef.
Now handles arrays, i.e. struct A[2]
****************/
/* --------------------------------------------------------------
* Tries to get the resolved name, with options of adding
* or removing a layer of references. Take care not
* to request both
* --------------------------------------------------------------*/
static String *getRClassName(String *retType, int /*addRef*/ = 1, int upRef=0) {
String *tmp = NewString("");
static String *getRClassName(String *retType, int deRef=0, int upRef=0) {
SwigType *resolved = SwigType_typedef_resolve_all(retType);
char *retName = Char(SwigType_manglestr(resolved));
int ispointer = SwigType_ispointer(resolved);
int isreference = SwigType_isreference(resolved);
if (upRef) {
Printf(tmp, "_p%s", retName);
} else{
Insert(tmp, 0, retName);
SwigType_add_pointer(resolved);
}
return tmp;
/*
#if 1
List *l = SwigType_split(retType);
int n = Len(l);
if(!l || n == 0) {
#ifdef R_SWIG_VERBOSE
if (debugMode)
Printf(stdout, "SwigType_split return an empty list for %s\n",
retType);
#endif
return(tmp);
}
String *el = Getitem(l, n-1);
char *ptr = Char(el);
if(strncmp(ptr, "struct ", 7) == 0)
ptr += 7;
Printf(tmp, "%s", ptr);
if(addRef) {
for(int i = 0; i < n; i++) {
if(Strcmp(Getitem(l, i), "p.") == 0 ||
Strncmp(Getitem(l, i), "a(", 2) == 0)
Printf(tmp, "Ref");
if (deRef) {
if (ispointer) {
SwigType_del_pointer(resolved);
}
}
#else
char *retName = Char(SwigType_manglestr(retType));
if(!retName)
return(tmp);
if(addRef) {
while(retName && strlen(retName) > 1 && strncmp(retName, "_p", 2) == 0) {
retName += 2;
Printf(tmp, "Ref");
if (isreference) {
SwigType_del_reference(resolved);
}
}
if(retName[0] == '_')
retName ++;
Insert(tmp, 0, retName);
#endif
return tmp;
*/
}
String *tmp = NewString("");
Insert(tmp, 0, Char(SwigType_manglestr(resolved)));
return(tmp);
}
/*********************
Tries to get the name of the R class corresponding to the given type
e.g. struct A * is ARef, struct A** is ARefRef.
Now handles arrays, i.e. struct A[2]
****************/
/* --------------------------------------------------------------
* Tries to get the name of the R class corresponding to the given type
* e.g. struct A * is ARef, struct A** is ARefRef.
* Now handles arrays, i.e. struct A[2]
* --------------------------------------------------------------*/
static String * getRClassNameCopyStruct(String *retType, int addRef) {
String *tmp = NewString("");
@ -188,12 +149,13 @@ static String * getRClassNameCopyStruct(String *retType, int addRef) {
}
/*********************************
Write the elements of a list to the File*, one element per line.
If quote is true, surround the element with "element".
This takes care of inserting a tab in front of each line and also
a comma after each element, except the last one.
**********************************/
/* -------------------------------------------------------------
* Write the elements of a list to the File*, one element per line.
* If quote is true, surround the element with "element".
* This takes care of inserting a tab in front of each line and also
* a comma after each element, except the last one.
* --------------------------------------------------------------*/
static void writeListByLine(List *l, File *out, bool quote = 0) {
int i, n = Len(l);
@ -222,9 +184,10 @@ R Options (available with -r)\n\
/************
Display the help for this module on the screen/console.
*************/
/* -------------------------------------------------------------
* Display the help for this module on the screen/console.
* --------------------------------------------------------------*/
static void showUsage() {
fputs(usage, stdout);
}
@ -238,10 +201,11 @@ static bool expandTypedef(SwigType *t) {
}
/*****
Determine whether we should add a .copy argument to the S function
that wraps/interfaces to the routine that returns the given type.
*****/
/* -------------------------------------------------------------
* Determine whether we should add a .copy argument to the S function
* that wraps/interfaces to the routine that returns the given type.
* --------------------------------------------------------------*/
static int addCopyParameter(SwigType *type) {
int ok = 0;
ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0;
@ -253,27 +217,15 @@ static int addCopyParameter(SwigType *type) {
}
static void replaceRClass(String *tm, SwigType *type) {
String *tmp = getRClassName(type);
String *tmp_base = getRClassName(type, 0);
String *tmp_ref = getRClassName(type, 1, 1);
String *tmp = getRClassName(type, 0, 0);
String *tmp_base = getRClassName(type, 1, 0);
String *tmp_ref = getRClassName(type, 0, 1);
Replaceall(tm, "$R_class", tmp);
Replaceall(tm, "$*R_class", tmp_base);
Replaceall(tm, "$&R_class", tmp_ref);
Delete(tmp); Delete(tmp_base); Delete(tmp_ref);
}
static bool getNumber(String *value, int* result) {
if(Char(value)) {
// Check the conversion processed the whole of value by having %c at
// the end of the format, and checking that only the first value is
// converted. We don't want to convert "3+7" -> 3.
char dummy;
if (sscanf(Char(value), "%i%c", result, &dummy) == 1)
return true;
}
return false;
}
class R : public Language {
public:
R();
@ -288,7 +240,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 +345,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 +411,8 @@ R::R() :
copyStruct(false),
memoryProfile(false),
aggressiveGc(false),
enum_values(0),
enum_def_calls(0),
sfile(0),
f_init(0),
s_classes(0),
@ -535,9 +492,10 @@ void R::addSMethodInfo(String *name, String *argType, int nargs) {
}
}
/*
Returns the name of the new routine.
*/
/* ----------------------------------------
* Returns the name of the new routine.
* ------------------------------------------ */
String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
String *funName = SwigType_manglestr(t);
@ -574,7 +532,6 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
for (i = 0; p; p = nextSibling(p), ++i) {
String *arg = Getattr(p, "name");
String *lname;
if (!arg && Cmp(Getattr(p, "type"), "void")) {
lname = NewStringf("arg%d", i+1);
Setattr(p, "name", lname);
@ -635,6 +592,9 @@ String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
}
Replaceall(tm, "$1", name);
Replaceall(tm, "$result", "r_tmp");
if (debugMode) {
Printf(stdout, "Calling Replace A: %s\n", Getattr(p,"type"));
}
replaceRClass(tm, Getattr(p,"type"));
Replaceall(tm,"$owner", "0");
Delete(lstr);
@ -756,6 +716,7 @@ void R::init() {
s_classes = NewString("");
s_init = NewString("");
s_init_routine = NewString("");
enum_def_calls = NewString("");
}
@ -771,14 +732,19 @@ int R::cDeclaration(Node *n) {
#endif
/**
Method from Language that is called to start the entire
processing off, i.e. the generation of the code.
It is called after the input has been read and parsed.
Here we open the output streams and generate the code.
***/
/* -------------------------------------------------------------
* Method from Language that is called to start the entire
* processing off, i.e. the generation of the code.
* It is called after the input has been read and parsed.
* Here we open the output streams and generate the code.
* ------------------------------------------------------------- */
int R::top(Node *n) {
String *module = Getattr(n, "name");
if (debugMode) {
Printf(stdout, "<Top> %s\n", module);
}
if(!Rpackage)
Rpackage = Copy(module);
if(!DllName)
@ -853,9 +819,9 @@ int R::top(Node *n) {
}
/*****************************************************
Write the generated code to the .S and the .c files.
****************************************************/
/* -------------------------------------------------------------
* Write the generated code to the .S and the .c files.
* ------------------------------------------------------------- */
int R::DumpCode(Node *n) {
String *output_filename = NewString("");
@ -878,6 +844,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");
@ -922,22 +889,23 @@ int R::DumpCode(Node *n) {
/*
We may need to do more.... so this is left as a
stub for the moment.
*/
/* -------------------------------------------------------------
* We may need to do more.... so this is left as a
* stub for the moment.
* -------------------------------------------------------------*/
int R::OutputClassAccessInfo(Hash *tb, File *out) {
int n = OutputClassMemberTable(tb, out);
OutputClassMethodsTable(out);
return n;
}
/************************************************************************
Currently this just writes the information collected about the
different methods of the C++ classes that have been processed
to the console.
This will be used later to define S4 generics and methods.
**************************************************************************/
/* -------------------------------------------------------------
* Currently this just writes the information collected about the
* different methods of the C++ classes that have been processed
* to the console.
* This will be used later to define S4 generics and methods.
* --------------------------------------------------------------*/
int R::OutputClassMethodsTable(File *) {
Hash *tb = ClassMethodsTable;
@ -966,20 +934,21 @@ int R::OutputClassMethodsTable(File *) {
}
/*
Iterate over the <class name>_set and <>_get
elements and generate the $ and $<- functions
that provide constrained access to the member
fields in these elements.
/* --------------------------------------------------------------
* Iterate over the <class name>_set and <>_get
* elements and generate the $ and $<- functions
* that provide constrained access to the member
* fields in these elements.
tb - a hash table that is built up in functionWrapper
as we process each membervalueHandler.
The entries are indexed by <class name>_set and
<class_name>_get. Each entry is a List *.
* tb - a hash table that is built up in functionWrapper
* as we process each membervalueHandler.
* The entries are indexed by <class name>_set and
* <class_name>_get. Each entry is a List *.
* out - the stram where the code is to be written. This is the S
* code stream as we generate only S code here.
* --------------------------------------------------------------*/
out - the stram where the code is to be written. This is the S
code stream as we generate only S code here..
*/
int R::OutputClassMemberTable(Hash *tb, File *out) {
List *keys = Keys(tb), *el;
@ -1019,17 +988,18 @@ int R::OutputClassMemberTable(Hash *tb, File *out) {
return n;
}
/*******************************************************************
Write the methods for $ or $<- for accessing a member field in an
struct or union (or class).
className - the name of the struct or union (e.g. Bar for struct Bar)
isSet - a logical value indicating whether the method is for
modifying ($<-) or accessing ($) the member field.
el - a list of length 2 * # accessible member elements + 1.
The first element is the name of the class.
The other pairs are member name and the name of the R function to access it.
out - the stream where we write the code.
********************************************************************/
/* --------------------------------------------------------------
* Write the methods for $ or $<- for accessing a member field in an
* struct or union (or class).
* className - the name of the struct or union (e.g. Bar for struct Bar)
* isSet - a logical value indicating whether the method is for
* modifying ($<-) or accessing ($) the member field.
* el - a list of length 2 * # accessible member elements + 1.
* The first element is the name of the class.
* The other pairs are member name and the name of the R function to access it.
* out - the stream where we write the code.
* --------------------------------------------------------------*/
int R::OutputMemberReferenceMethod(String *className, int isSet,
List *el, File *out) {
int numMems = Len(el), j;
@ -1153,15 +1123,16 @@ int R::OutputMemberReferenceMethod(String *className, int isSet,
return SWIG_OK;
}
/*******************************************************************
Write the methods for [ or [<- for accessing a member field in an
struct or union (or class).
className - the name of the struct or union (e.g. Bar for struct Bar)
el - a list of length 2 * # accessible member elements + 1.
The first element is the name of the class.
The other pairs are member name and the name of the R function to access it.
out - the stream where we write the code.
********************************************************************/
/* -------------------------------------------------------------
* Write the methods for [ or [<- for accessing a member field in an
* struct or union (or class).
* className - the name of the struct or union (e.g. Bar for struct Bar)
* el - a list of length 2 * # accessible member elements + 1.
* The first element is the name of the class.
* The other pairs are member name and the name of the R function to access it.
* out - the stream where we write the code.
* --------------------------------------------------------------*/
int R::OutputArrayMethod(String *className, List *el, File *out) {
int numMems = Len(el), j;
@ -1192,103 +1163,153 @@ int R::OutputArrayMethod(String *className, List *el, File *out) {
}
/************************************************************
Called when a enumeration is to be processed.
We want to call the R function defineEnumeration().
tdname is the typedef of the enumeration, i.e. giving its name.
*************************************************************/
/* -------------------------------------------------------------
* Called when a enumeration is to be processed.
* We want to call the R function defineEnumeration().
* 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;
if (!ImportMode) {
if (getCurrentClass() && (cplus_mode != PUBLIC))
return SWIG_NOWRAP;
String *name = Getattr(n, "name");
String *tdname = Getattr(n, "tdname");
String *symname = Getattr(n, "sym:name");
/* 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)
tdname = name;
// 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) {
Node *current_class = getCurrentClass();
String *cl = NewString("");
if (current_class) {
cl = getEnumClassPrefix();
}
Printf(stdout, "enumDeclaration: %s, %s, %s, %s, %s\n", name, symname, nspace, ename, cl);
}
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;
Printv(scode, "defineEnumeration('", mangled_tdname, "'",
",\n", tab8, tab8, tab4, ".values = c(\n", NIL);
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;
}
} 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) ? ", " : "");
}
// }
// 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);
}
Printv(scode, "))", NIL);
Printf(sfile, "%s\n", scode);
if (GetFlag(parent, "scopedenum")) {
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 ");
if (debugMode) {
Printf(stdout, "Setting type: %s\n", Copy(typemap_lookup_type));
}
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;
}
/*************************************************************
**************************************************************/
/* -------------------------------------------------------------
* Create accessor functions for variables.
* Does not create equivalent wrappers for enumerations,
* which are handled differently
* --------------------------------------------------------------*/
int R::variableWrapper(Node *n) {
String *name = Getattr(n, "sym:name");
if (debugMode) {
Printf(stdout, "variableWrapper %s\n", n);
}
processing_variable = 1;
Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
processing_variable = 0;
SwigType *ty = Getattr(n, "type");
String *nodeType = nodeType(n);
int addCopyParam = addCopyParameter(ty);
//XXX
processType(ty, n);
if(!SwigType_isconst(ty)) {
if (nodeType && !Strcmp(nodeType, "enumitem")) {
/* special wrapper for enums - don't want the R _set, _get functions*/
if (debugMode) {
Printf(stdout, "variableWrapper enum branch\n");
}
} else if(!SwigType_isconst(ty)) {
Wrapper *f = NewWrapper();
Printf(f->def, "%s = \nfunction(value%s)\n{\n",
name, addCopyParam ? ", .copy = FALSE" : "");
@ -1306,6 +1327,12 @@ int R::variableWrapper(Node *n) {
return SWIG_OK;
}
/* -------------------------------------------------------------
* Creates accessor functions for class members.
* ToDo - this version depends on naming conventions and needs
* to be replaced.
* --------------------------------------------------------------*/
void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
int isSet) {
@ -1708,9 +1735,10 @@ void R::dispatchFunction(Node *n) {
DelWrapper(f);
}
/******************************************************************
/*--------------------------------------------------------------
* --------------------------------------------------------------*/
*******************************************************************/
int R::functionWrapper(Node *n) {
String *fname = Getattr(n, "name");
String *iname = Getattr(n, "sym:name");
@ -1752,6 +1780,9 @@ int R::functionWrapper(Node *n) {
SwigType *resolved =
SwigType_typedef_resolve_all(resultType);
if (expandTypedef(resolved)) {
if (debugMode) {
Printf(stdout, "Setting type: %s\n", resolved);
}
Setattr(p, "type", Copy(resolved));
}
}
@ -1764,18 +1795,18 @@ int R::functionWrapper(Node *n) {
SwigType_istypedef(type)) {
SwigType *resolved =
SwigType_typedef_resolve_all(type);
if (debugMode)
Printf(stdout, "<functionWrapper> resolved %s\n", Copy(unresolved_return_type));
if (expandTypedef(resolved)) {
type = Copy(resolved);
Setattr(n, "type", type);
}
}
if (debugMode)
Printf(stdout, "<functionWrapper> unresolved_return_type %s\n",
unresolved_return_type);
Printf(stdout, "<functionWrapper> unresolved_return_type %s\n", unresolved_return_type);
if(processing_member_access_function) {
if (debugMode)
Printf(stdout, "<functionWrapper memberAccess> '%s' '%s' '%s' '%s'\n",
fname, iname, member_name, class_name);
Printf(stdout, "<functionWrapper memberAccess> '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name);
if(opaqueClassDeclaration)
return SWIG_OK;
@ -2067,14 +2098,12 @@ int R::functionWrapper(Node *n) {
/* Deal with the explicit return value. */
if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
SwigType *retType = Getattr(n, "type");
//Printf(stdout, "Return Value for %s, array? %s\n", retType, SwigType_isarray(retType) ? "yes" : "no");
/* if(SwigType_isarray(retType)) {
defineArrayAccessors(retType);
} */
Replaceall(tm,"$1", Swig_cresult_name());
Replaceall(tm,"$result", "r_ans");
if (debugMode){
Printf(stdout, "Calling replace D: %s, %s, %s\n", retType, n, tm);
}
replaceRClass(tm, retType);
if (GetFlag(n,"feature:new")) {
@ -2161,6 +2190,9 @@ int R::functionWrapper(Node *n) {
Delete(smartname);
}
}
if (debugMode) {
Printf(stdout, "Calling replace B: %s, %s, %s\n", Getattr(n, "type"), Getattr(n, "sym:name"), getNSpace());
}
replaceRClass(tm, Getattr(n, "type"));
Chop(tm);
}
@ -2196,6 +2228,9 @@ int R::functionWrapper(Node *n) {
tm = Swig_typemap_lookup("rtype", n, "", 0);
if(tm) {
SwigType *retType = Getattr(n, "type");
if (debugMode) {
Printf(stdout, "Calling replace C: %s\n", Copy(retType));
}
replaceRClass(tm, retType);
}
@ -2254,15 +2289,16 @@ int R::constantWrapper(Node *n) {
return SWIG_OK;
}
/*****************************************************
Add the specified routine name to the collection of
generated routines that are called from R functions.
This is used to register the routines with R for
resolving symbols.
/*--------------------------------------------------------------
* Add the specified routine name to the collection of
* generated routines that are called from R functions.
* This is used to register the routines with R for
* resolving symbols.
* rname - the name of the routine
* nargs - the number of arguments it expects.
* --------------------------------------------------------------*/
rname - the name of the routine
nargs - the number of arguments it expects.
******************************************************/
int R::addRegistrationRoutine(String *rname, int nargs) {
if(!registrationTable)
registrationTable = NewHash();
@ -2275,11 +2311,12 @@ int R::addRegistrationRoutine(String *rname, int nargs) {
return SWIG_OK;
}
/*****************************************************
Write the registration information to an array and
create the initialization routine for registering
these.
******************************************************/
/* -------------------------------------------------------------
* Write the registration information to an array and
* create the initialization routine for registering
* these.
* --------------------------------------------------------------*/
int R::outputRegistrationRoutines(File *out) {
int i, n;
if(!registrationTable)
@ -2322,11 +2359,11 @@ int R::outputRegistrationRoutines(File *out) {
/****************************************************************************
Process a struct, union or class declaration in the source code,
or an anonymous typedef struct
/* -------------------------------------------------------------
* Process a struct, union or class declaration in the source code,
* or an anonymous typedef struct
* --------------------------------------------------------------*/
*****************************************************************************/
//XXX What do we need to do here -
// Define an S4 class to refer to this.
@ -2433,9 +2470,7 @@ int R::classDeclaration(Node *n) {
class_member_set_functions = NULL;
}
if (Getattr(n, "has_destructor")) {
Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n",
getRClassName(Getattr(n, "name")),
getRClassName(Getattr(n, "name")));
Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(name), getRClassName(name));
}
if(!opaque && !Strcmp(kind, "struct") && copyStruct) {
@ -2509,12 +2544,13 @@ int R::classDeclaration(Node *n) {
/***************************************************************
Create the C routines that copy an S object of the class given
by the given struct definition in Node *n to the C value
and also the routine that goes from the C routine to an object
of this S class.
****************************************************************/
/* -------------------------------------------------------------
* Create the C routines that copy an S object of the class given
* by the given struct definition in Node *n to the C value
* and also the routine that goes from the C routine to an object
* of this S class.
* --------------------------------------------------------------*/
/*XXX
Clean up the toCRef - make certain the names are correct for the types, etc.
in all cases.
@ -2609,13 +2645,14 @@ int R::generateCopyRoutines(Node *n) {
/*****
Called when there is a typedef to be invoked.
/* -------------------------------------------------------------
* Called when there is a typedef to be invoked.
*
* XXX Needs to be enhanced or split to handle the case where we have a
* typedef within a classDeclaration emission because the struct/union/etc.
* is anonymous.
* --------------------------------------------------------------*/
XXX Needs to be enhanced or split to handle the case where we have a
typedef within a classDeclaration emission because the struct/union/etc.
is anonymous.
******/
int R::typedefHandler(Node *n) {
SwigType *tp = Getattr(n, "type");
String *type = Getattr(n, "type");
@ -2639,12 +2676,13 @@ int R::typedefHandler(Node *n) {
/*********************
Called when processing a field in a "class", i.e. struct, union or
actual class. We set a state variable so that we can correctly
interpret the resulting functionWrapper() call and understand that
it is for a field element.
**********************/
/* --------------------------------------------------------------
* Called when processing a field in a "class", i.e. struct, union or
* actual class. We set a state variable so that we can correctly
* interpret the resulting functionWrapper() call and understand that
* it is for a field element.
* --------------------------------------------------------------*/
int R::membervariableHandler(Node *n) {
SwigType *t = Getattr(n, "type");
processType(t, n, NULL);
@ -2679,12 +2717,14 @@ String * R::runtimeCode() {
}
/**
Called when SWIG wants to initialize this
We initialize anythin we want here.
Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module.
Use Swig_mark_arg() to tell SWIG that it is understood and not to throw an error.
**/
/* -----------------------------------------------------------------------
* Called when SWIG wants to initialize this
* We initialize anythin we want here.
* Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module.
* Use Swig_mark_arg() to tell SWIG that it is understood and not to
* throw an error.
* --------------------------------------------------------------*/
void R::main(int argc, char *argv[]) {
init();
Preprocessor_define("SWIGR 1", 0);
@ -2767,10 +2807,10 @@ void R::main(int argc, char *argv[]) {
}
}
/*
Could make this work for String or File and then just store the resulting string
rather than the collection of arguments and argc.
*/
/* -----------------------------------------------------------------------
* Could make this work for String or File and then just store the resulting string
* rather than the collection of arguments and argc.
* ----------------------------------------------------------------------- */
int R::outputCommandLineArguments(File *out)
{
if(Argc < 1 || !Argv || !Argv[0])
@ -2796,18 +2836,17 @@ Language *swig_r(void) {
/*************************************************************************************/
/*
Needs to be reworked.
*/
/* -----------------------------------------------------------------------
* Needs to be reworked.
*----------------------------------------------------------------------- */
String * R::processType(SwigType *t, Node *n, int *nargs) {
//XXX Need to handle typedefs, e.g.
// a type which is a typedef to a function pointer.
SwigType *tmp = Getattr(n, "tdname");
if (debugMode)
Printf(stdout, "processType %s (tdname = %s)\n", Getattr(n, "name"), tmp);
Printf(stdout, "processType %s (tdname = %s)(SwigType = %s)\n", Getattr(n, "name"), tmp, Copy(t));
SwigType *td = t;
if (expandTypedef(t) &&
@ -2852,4 +2891,55 @@ String * R::processType(SwigType *t, Node *n, int *nargs) {
return NULL;
}
/*************************************************************************************/
/* -----------------------------------------------------------------------
* 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");
// parent enumtype has namespace mangled in
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
if (debugMode) {
Printf(stdout, "<enumValue> type set: %s\n", etype);
}
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;
}