summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Nadlinger <code@klickverbot.at>2011-03-13 00:32:26 +0000
committerDavid Nadlinger <code@klickverbot.at>2011-03-13 00:32:26 +0000
commitce6516fb4ca0b749b6614dce67302d0cdf1e746e (patch)
tree14a27a24574ccaa1c5607ffbf4c7ca1ef1d58da7
parenta63cde3827e6c86ca4de28b25a7d3a29cbebc1ca (diff)
downloadswig-ce6516fb4ca0b749b6614dce67302d0cdf1e746e.tar.gz
[D] nspace support.
As for C# and Java, this doesn't work for free functions/variables yet. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12534 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r--Doc/Manual/D.html22
-rw-r--r--Examples/test-suite/csharp/nspace_runme.cs4
-rw-r--r--Examples/test-suite/d/Makefile.in4
-rw-r--r--Examples/test-suite/d/nspace_extend_runme.1.d32
-rw-r--r--Examples/test-suite/d/nspace_extend_runme.2.d32
-rw-r--r--Examples/test-suite/d/nspace_runme.1.d87
-rw-r--r--Examples/test-suite/d/nspace_runme.2.d77
-rw-r--r--Examples/test-suite/java/nspace_runme.java2
-rw-r--r--Examples/test-suite/nspace.i18
-rw-r--r--Examples/test-suite/nspace_extend.i10
-rw-r--r--Lib/d/boost_shared_ptr.i2
-rw-r--r--Lib/d/dclassgen.swg2
-rw-r--r--Source/Modules/d.cxx629
13 files changed, 757 insertions, 164 deletions
diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html
index 6f65db1e4..3e4ad9bc5 100644
--- a/Doc/Manual/D.html
+++ b/Doc/Manual/D.html
@@ -28,6 +28,7 @@
<li><a href="#D_directors">D Directors</a>
<li><a href="#D_other_features">Other features</a>
<ul>
+<li><a href="#D_nspace">Extended namespace support (<tt>nspace</tt>)</a></li>
<li><a href="#D_native_pointer_support">Native pointer support</a>
<li><a href="#D_operator_overloading">Operator overloading</a>
<li><a href="#D_test_suite">Running the test-suite</a>
@@ -187,6 +188,12 @@
<p>There are two other variants available, <tt>$&amp;dclassname</tt> and <tt>$*dclassname</tt>. The former adds a level of indirection, while the latter removes one. For instance, when wrapping <tt>Foo **</tt>, <tt>$*dclassname</tt> would be replaced by the proxy class name corresponding to <tt>Foo *</tt>.</p>
</dd>
+ <dt><tt>$dclazzname</tt> (C#: <tt>$csclazzname</tt>)</dt>
+ <dd>
+ <p>This special variable expands the fully qualified C++ class into the package name, if used by the <a href="SWIGPlus.html#SWIGPlus_nspace"><tt>nspace</tt> feature</a>, and the proxy class name, mangled for use as a function name. For example, <tt>Namespace1::Namespace2::Klass</tt> is expanded into <tt>Namespace1_Namespace2_Klass_</tt>.</p>
+ <p>This special variable might be useful for calling certain functions in the wrapper layer (e.g. upcast wrappers) which are mangled like this.</p>
+ </dd>
+
<dt><tt>$null</tt></dt>
<dd><p>In code inserted into the generated C/C++ wrapper functions, this variable is replaced by either <tt>0</tt> or nothing at all, depending on whether the function has a return value or not. It can be used to bail out early e.g. in case of errors (<tt>return $null;</tt>).</p></dd>
@@ -249,7 +256,7 @@ SomeClass bar() {
<p>This macro is only valid inside the <tt><a href="D.html#D_class_code_typemaps">dconstructor</a></tt> typemap and contains the value of the <tt>dconstructor</tt> typemap attribute if the currently wrapped class has directors enabled.</p>
<p>This is how the default <tt>dconstructor</tt> typemap looks like (you usually do not want to specify a custom one):</p>
<div class="code"><pre>
-%typemap(dconstructor, excode=SWIGEXCODE,
+%typemap(dconstructor, excode=SWIGEXCODE,
directorconnect="\n swigDirectorConnect();") SWIGTYPE {
this($imcall, true);$excode$directorconnect
}
@@ -331,7 +338,7 @@ struct A {
<dd><p>Additional code to be emitted to the imports section of the intermediary D module (the <a href="D.html#D_importtype">$importtype</a> macro can be used here). You probably want to use this in conjunction with the <tt>imdmodulecode</tt> pragma.</p></dd>
<dt><tt>%pragma(d) proxydmodulecode</tt></dt>
- <dd><p>Just like <tt>proxydmodulecode</tt>, the argument is copied to the proxy D module (if SWIG is in <a href="D.html#D_splitproxy">split proxy mode</a>, it is emitted to the main proxy D module only).</p></dd>
+ <dd><p>Just like <tt>proxydmodulecode</tt>, the argument is copied to the proxy D module (if SWIG is in <a href="D.html#D_splitproxy">split proxy mode</a> and/or the <tt>nspace</tt> feature is used, it is emitted to the main proxy D module only).</p></dd>
<dt><tt>%pragma(d) globalproxyimports</tt></dt>
<dd>
@@ -379,10 +386,13 @@ struct A {
<H2><a name="D_other_features"></a>20.8 Other features</H2>
-<p>The <a href="SWIGPlus.html#SWIGPlus_nspace"><tt>nspace</tt></a> feature of SWIG is not yet supported for D - all class modules are written to the same package, regardless of which C++ namespace they are in.</p>
+<H3><a name="D_nspace"></a>20.8.1 Extended namespace support (<tt>nspace</tt>)</H3>
+
+
+<p>By default, SWIG flattens all C++ namespaces into a single target language namespace, but as for Java and C#, the <a href="SWIGPlus.html#SWIGPlus_nspace"><tt>nspace</tt></a> feature is supported for D. If it is active, C++ namespaces are mapped to D packages/modules. Note, however, that like for the other languages, <em>free</em> variables and functions are not supported yet; currently, they are all allows written to the main proxy D module.</p>
-<H3><a name="D_native_pointer_support"></a>20.8.1 Native pointer support</H3>
+<H3><a name="D_native_pointer_support"></a>20.8.2 Native pointer support</H3>
<p>Contrary to many of the scripting languages supported by SWIG, D fully supports C-style pointers. The D module thus includes a custom mechanism to wrap C pointers directly as D pointers where applicable, that is, if the type that is pointed to is represented the same in C and D (on the bit-level), dubbed a »primtive type« below.</p>
@@ -394,7 +404,7 @@ struct A {
<p>To determine if a type should be considered primitive, the <tt>cprimitive</tt> attribute on its <tt>dtype</tt> attribute is used. For example, the <tt>dtype</tt> typemap for <tt>float</tt> has <tt>cprimitive="1"</tt>, so the code from the <tt>nativepointer</tt> attribute is taken into account e.g. for <tt>float **</tt> or the function pointer <tt>float (*)(float *)</tt>.</p>
-<H3><a name="D_operator_overloading"></a>20.8.2 Operator overloading</H3>
+<H3><a name="D_operator_overloading"></a>20.8.3 Operator overloading</H3>
<p>The D module comes with basic operator overloading support for both D1 and D2. There are, however, a few limitations arising from conceptual differences between C++ and D:</p>
@@ -406,7 +416,7 @@ struct A {
<p>There are also some cases where the operators can be translated to D, but the differences in the implementation details are big enough that a rather involved scheme would be required for automatic wrapping them, which has not been implemented yet. This affects, for example, the array subscript operator, <tt>[]</tt>, in combination with assignments - while <tt>operator []</tt> in C++ simply returns a reference which is then written to, D resorts to a separate <tt>opIndexAssign</tt> method -, or implicit casting (which was introduced in D2 via <tt>alias this</tt>). Despite the lack of automatic support, manually handling these cases should be perfectly possible.</p>
-<H3><a name="D_test_suite"></a>20.8.3 Running the test-suite</H3>
+<H3><a name="D_test_suite"></a>20.8.4 Running the test-suite</H3>
<p>As with any other language, the SWIG test-suite can be built for D using the <tt>*-d-test-suite</tt> targets of the top-level Makefile. By default, D1 is targeted, to build it with D2, use the optional <tt>D_VERSION</tt> variable, e.g. <tt>make check-d-test-suite D_VERSION=2</tt>.</p>
diff --git a/Examples/test-suite/csharp/nspace_runme.cs b/Examples/test-suite/csharp/nspace_runme.cs
index 9cf593857..fb6462541 100644
--- a/Examples/test-suite/csharp/nspace_runme.cs
+++ b/Examples/test-suite/csharp/nspace_runme.cs
@@ -2,7 +2,7 @@ using System;
public class runme
{
- static void Main()
+ static void Main()
{
// constructors and destructors
nspaceNamespace.Outer.Inner1.Color color1 = new nspaceNamespace.Outer.Inner1.Color();
@@ -62,7 +62,7 @@ public class runme
throw new ApplicationException("Transmission2 wrong");
// turn feature off / ignoring
- nspaceNamespace.Outer.nspace ns = new nspaceNamespace.Outer.nspace();
+ nspaceNamespace.Outer.namespce ns = new nspaceNamespace.Outer.namespce();
ns.Dispose();
nspaceNamespace.NoNSpacePlease nons = new nspaceNamespace.NoNSpacePlease();
nons.Dispose();
diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in
index 0f5bf8cbb..53b9f2859 100644
--- a/Examples/test-suite/d/Makefile.in
+++ b/Examples/test-suite/d/Makefile.in
@@ -65,13 +65,13 @@ run_testcase = \
cd $*$(VERSIONSUFFIX) && \
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile \
DFLAGS='-of$*_runme' \
- DSRCS='../$(srcdir)/$(TESTPREFIX)$*$(TESTSUFFIX) $*/*.d' d_compile && \
+ DSRCS='../$(srcdir)/$(TESTPREFIX)$*$(TESTSUFFIX) `find $* -name *.d`' d_compile && \
env LD_LIBRARY_PATH=".:$$LD_LIBRARY_PATH" $(RUNTOOL) ./$*_runme; \
else \
cd $*$(VERSIONSUFFIX) && \
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile \
DFLAGS='-c' \
- DSRCS='$*/*.d' d_compile && cd .. ; \
+ DSRCS='`find $* -name *.d`' d_compile && cd .. ; \
fi
# Clean: remove testcase directories
diff --git a/Examples/test-suite/d/nspace_extend_runme.1.d b/Examples/test-suite/d/nspace_extend_runme.1.d
new file mode 100644
index 000000000..82ccfec90
--- /dev/null
+++ b/Examples/test-suite/d/nspace_extend_runme.1.d
@@ -0,0 +1,32 @@
+module nspace_extend_runme;
+
+static import oi1c = nspace_extend.Outer.Inner1.Color;
+static import oi2c = nspace_extend.Outer.Inner2.Color;
+
+void main() {
+ {
+ // constructors and destructors
+ scope color1 = new oi1c.Color();
+ scope color = new oi1c.Color(color1);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi1c.Color.colorStaticMethod(20.0);
+ auto created = oi1c.Color.create();
+ }
+ {
+ // constructors and destructors
+ scope color2 = new oi2c.Color();
+ scope color = new oi2c.Color(color2);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi2c.Color.colorStaticMethod(20.0);
+ auto created = oi2c.Color.create();
+
+ // Same class different namespaces
+ auto col1 = new oi1c.Color();
+ auto col2 = oi2c.Color.create();
+ col2.colors(col1, col1, col2, col2, col2);
+ }
+}
diff --git a/Examples/test-suite/d/nspace_extend_runme.2.d b/Examples/test-suite/d/nspace_extend_runme.2.d
new file mode 100644
index 000000000..82ccfec90
--- /dev/null
+++ b/Examples/test-suite/d/nspace_extend_runme.2.d
@@ -0,0 +1,32 @@
+module nspace_extend_runme;
+
+static import oi1c = nspace_extend.Outer.Inner1.Color;
+static import oi2c = nspace_extend.Outer.Inner2.Color;
+
+void main() {
+ {
+ // constructors and destructors
+ scope color1 = new oi1c.Color();
+ scope color = new oi1c.Color(color1);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi1c.Color.colorStaticMethod(20.0);
+ auto created = oi1c.Color.create();
+ }
+ {
+ // constructors and destructors
+ scope color2 = new oi2c.Color();
+ scope color = new oi2c.Color(color2);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi2c.Color.colorStaticMethod(20.0);
+ auto created = oi2c.Color.create();
+
+ // Same class different namespaces
+ auto col1 = new oi1c.Color();
+ auto col2 = oi2c.Color.create();
+ col2.colors(col1, col1, col2, col2, col2);
+ }
+}
diff --git a/Examples/test-suite/d/nspace_runme.1.d b/Examples/test-suite/d/nspace_runme.1.d
new file mode 100644
index 000000000..8d3b81f76
--- /dev/null
+++ b/Examples/test-suite/d/nspace_runme.1.d
@@ -0,0 +1,87 @@
+module nspace_runme;
+
+import nspace.nspace;
+static import nspace.NoNSpacePlease;
+static import nspace.Outer.namespce;
+static import nspace.Outer.Inner1.Channel;
+static import oi1c = nspace.Outer.Inner1.Color;
+static import nspace.Outer.Inner2.Channel;
+static import nspace.Outer.Inner2.Color;
+static import nspace.Outer.Inner3.Blue;
+static import nspace.Outer.Inner4.Blue;
+static import nspace.Outer.SomeClass;
+
+void main() {
+ // constructors and destructors
+ auto color1 = new oi1c.Color();
+ auto color = new oi1c.Color(color1);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi1c.Color.colorStaticMethod(20.0);
+ auto created = oi1c.Color.create();
+
+ // class enums
+ auto someClass = new nspace.Outer.SomeClass.SomeClass();
+ auto channel = someClass.GetInner1ColorChannel();
+ if (channel != oi1c.Color.Channel.Transmission) {
+ throw new Exception("Transmission wrong");
+ }
+
+ // class anonymous enums
+ int val1 = oi1c.Color.ColorEnumVal1;
+ int val2 = oi1c.Color.ColorEnumVal2;
+ if (val1 != 0 || val2 != 0x22) {
+ throw new Exception("ColorEnumVal wrong");
+ }
+
+ // instance member variables
+ color.instanceMemberVariable = 123;
+ if (color.instanceMemberVariable != 123) {
+ throw new Exception("instance member variable failed");
+ }
+
+ // static member variables
+ oi1c.Color.staticMemberVariable = 789;
+ if (oi1c.Color.staticMemberVariable != 789) {
+ throw new Exception("static member variable failed");
+ }
+ if (oi1c.Color.staticConstMemberVariable != 222) {
+ throw new Exception("static const member variable failed");
+ }
+ if (oi1c.Color.staticConstEnumMemberVariable != oi1c.Color.Channel.Transmission) {
+ throw new Exception("static const enum member variable failed");
+ }
+
+ // check globals in a namespace don't get mangled with the nspace option
+ nspace.nspace.namespaceFunction(color);
+ nspace.nspace.namespaceVar = 111;
+ if (nspace.nspace.namespaceVar != 111) {
+ throw new Exception("global var failed");
+ }
+
+ // Same class different namespaces
+ auto col1 = new oi1c.Color();
+ auto col2 = nspace.Outer.Inner2.Color.Color.create();
+ col2.colors(col1, col1, col2, col2, col2);
+
+ // global enums
+ auto outerChannel1 = someClass.GetInner1Channel();
+ if (outerChannel1 != nspace.Outer.Inner1.Channel.Channel.Transmission1) {
+ throw new Exception("Transmission1 wrong");
+ }
+ auto outerChannel2 = someClass.GetInner2Channel();
+ if (outerChannel2 != nspace.Outer.Inner2.Channel.Channel.Transmission2) {
+ throw new Exception("Transmission2 wrong");
+ }
+
+ // turn feature off / ignoring
+ auto ns = new nspace.Outer.namespce.namespce();
+ auto nons = new nspace.NoNSpacePlease.NoNSpacePlease();
+
+ // Derived class
+ auto blue3 = new nspace.Outer.Inner3.Blue.Blue();
+ blue3.blueInstanceMethod();
+ auto blue4 = new nspace.Outer.Inner4.Blue.Blue();
+ blue4.blueInstanceMethod();
+}
diff --git a/Examples/test-suite/d/nspace_runme.2.d b/Examples/test-suite/d/nspace_runme.2.d
new file mode 100644
index 000000000..a86e4db9e
--- /dev/null
+++ b/Examples/test-suite/d/nspace_runme.2.d
@@ -0,0 +1,77 @@
+module nspace_runme;
+
+import std.exception;
+import nspace.nspace;
+static import nspace.NoNSpacePlease;
+static import nspace.Outer.namespce;
+static import nspace.Outer.Inner1.Channel;
+static import oi1c = nspace.Outer.Inner1.Color;
+static import nspace.Outer.Inner2.Channel;
+static import nspace.Outer.Inner2.Color;
+static import nspace.Outer.Inner3.Blue;
+static import nspace.Outer.Inner4.Blue;
+static import nspace.Outer.SomeClass;
+
+void main() {
+ // constructors and destructors
+ auto color1 = new oi1c.Color();
+ auto color = new oi1c.Color(color1);
+
+ // class methods
+ color.colorInstanceMethod(20.0);
+ oi1c.Color.colorStaticMethod(20.0);
+ auto created = oi1c.Color.create();
+
+ // class enums
+ auto someClass = new nspace.Outer.SomeClass.SomeClass();
+ auto channel = someClass.GetInner1ColorChannel();
+ enforce(channel == oi1c.Color.Channel.Transmission,
+ "Transmission wrong");
+
+ // class anonymous enums
+ int val1 = oi1c.Color.ColorEnumVal1;
+ int val2 = oi1c.Color.ColorEnumVal2;
+ enforce(val1 == 0 && val2 == 0x22, "ColorEnumVal wrong");
+
+ // instance member variables
+ color.instanceMemberVariable = 123;
+ enforce(color.instanceMemberVariable == 123,
+ "instance member variable failed");
+
+ // static member variables
+ oi1c.Color.staticMemberVariable = 789;
+ enforce(oi1c.Color.staticMemberVariable == 789,
+ "static member variable failed");
+ enforce(oi1c.Color.staticConstMemberVariable == 222,
+ "static const member variable failed");
+ enforce(oi1c.Color.staticConstEnumMemberVariable == oi1c.Color.Channel.Transmission,
+ "static const enum member variable failed");
+
+ // check globals in a namespace don't get mangled with the nspace option
+ nspace.nspace.namespaceFunction(color);
+ nspace.nspace.namespaceVar = 111;
+ enforce(nspace.nspace.namespaceVar == 111, "global var failed");
+
+ // Same class different namespaces
+ auto col1 = new oi1c.Color();
+ auto col2 = nspace.Outer.Inner2.Color.Color.create();
+ col2.colors(col1, col1, col2, col2, col2);
+
+ // global enums
+ auto outerChannel1 = someClass.GetInner1Channel();
+ enforce(outerChannel1 == nspace.Outer.Inner1.Channel.Channel.Transmission1,
+ "Transmission1 wrong");
+ auto outerChannel2 = someClass.GetInner2Channel();
+ enforce(outerChannel2 == nspace.Outer.Inner2.Channel.Channel.Transmission2,
+ "Transmission2 wrong");
+
+ // turn feature off / ignoring
+ auto ns = new nspace.Outer.namespce.namespce();
+ auto nons = new nspace.NoNSpacePlease.NoNSpacePlease();
+
+ // Derived class
+ auto blue3 = new nspace.Outer.Inner3.Blue.Blue();
+ blue3.blueInstanceMethod();
+ auto blue4 = new nspace.Outer.Inner4.Blue.Blue();
+ blue4.blueInstanceMethod();
+}
diff --git a/Examples/test-suite/java/nspace_runme.java b/Examples/test-suite/java/nspace_runme.java
index 9800e79cd..4b58c6b54 100644
--- a/Examples/test-suite/java/nspace_runme.java
+++ b/Examples/test-suite/java/nspace_runme.java
@@ -68,7 +68,7 @@ public class nspace_runme {
throw new RuntimeException("Transmission2 wrong");
// turn feature off / ignoring
- nspacePackage.Outer.nspace ns = new nspacePackage.Outer.nspace();
+ nspacePackage.Outer.namespce ns = new nspacePackage.Outer.namespce();
nspacePackage.NoNSpacePlease nons = new nspacePackage.NoNSpacePlease();
// Derived class
diff --git a/Examples/test-suite/nspace.i b/Examples/test-suite/nspace.i
index 4e4e461c0..89009b939 100644
--- a/Examples/test-suite/nspace.i
+++ b/Examples/test-suite/nspace.i
@@ -2,7 +2,7 @@
%module nspace
// nspace feature only supported by these languages
-#if defined(SWIGJAVA) || defined(SWIGCSHARP)
+#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD)
%nspace;
%nonspace Outer::Inner2::NoNSpacePlease;
@@ -15,7 +15,7 @@
%inline %{
namespace Outer {
- class nspace {
+ class namespce {
};
namespace Inner1 {
enum Channel { Diffuse, Specular = 0x10, Transmission1 };
@@ -33,12 +33,12 @@ namespace Outer {
static const Channel staticConstEnumMemberVariable = Transmission;
void colorInstanceMethod(double d) {}
static void colorStaticMethod(double d) {}
- }; // Color
+ }; // Color
int Color::staticMemberVariable = 0;
Color namespaceFunction(Color k) { return k; }
int namespaceVar = 0;
- } // Inner1
+ } // Inner1
namespace Inner2 {
enum Channel { Diffuse, Specular = 0x30, Transmission2 };
@@ -56,12 +56,12 @@ namespace Outer {
static const Channel staticConstEnumMemberVariable = Transmission;
void colorInstanceMethod(double d) {}
static void colorStaticMethod(double d) {}
- void colors(const Inner1::Color& col1a,
- const Outer::Inner1::Color& col1b,
- const Color &col2a,
- const Inner2::Color& col2b,
+ void colors(const Inner1::Color& col1a,
+ const Outer::Inner1::Color& col1b,
+ const Color &col2a,
+ const Inner2::Color& col2b,
const Outer::Inner2::Color& col2c) {}
- }; // Color
+ }; // Color
int Color::staticMemberVariable = 0;
class NoNSpacePlease {};
} // Inner2
diff --git a/Examples/test-suite/nspace_extend.i b/Examples/test-suite/nspace_extend.i
index 88f40bc69..47ede95d0 100644
--- a/Examples/test-suite/nspace_extend.i
+++ b/Examples/test-suite/nspace_extend.i
@@ -2,7 +2,7 @@
%module nspace_extend
// nspace feature only supported by these languages
-#if defined(SWIGJAVA) || defined(SWIGCSHARP)
+#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD)
%nspace;
@@ -39,10 +39,10 @@ namespace Outer {
void colorInstanceMethod(double d) {}
static void colorStaticMethod(double d) {}
- void colors(const Inner1::Color& col1a,
- const Outer::Inner1::Color& col1b,
- const Color &col2a,
- const Inner2::Color& col2b,
+ void colors(const Inner1::Color& col1a,
+ const Outer::Inner1::Color& col1b,
+ const Color &col2a,
+ const Inner2::Color& col2b,
const Outer::Inner2::Color& col2c) {}
}
diff --git a/Lib/d/boost_shared_ptr.i b/Lib/d/boost_shared_ptr.i
index 37ce26d00..bfa2aa646 100644
--- a/Lib/d/boost_shared_ptr.i
+++ b/Lib/d/boost_shared_ptr.i
@@ -162,7 +162,7 @@ private void* swigCPtr;
private bool swigCMemOwn;
public this(void* cObject, bool ownCObject) {
- super($imdmodule.$dclassnameSmartPtrUpcast(cObject), ownCObject);
+ super($imdmodule.$dclazznameSmartPtrUpcast(cObject), ownCObject);
swigCPtr = cObject;
swigCMemOwn = ownCObject;
}
diff --git a/Lib/d/dclassgen.swg b/Lib/d/dclassgen.swg
index 467621f4a..ceaf50727 100644
--- a/Lib/d/dclassgen.swg
+++ b/Lib/d/dclassgen.swg
@@ -84,7 +84,7 @@ mixin $imdmodule.SwigOperatorDefinitions;
private void* swigCPtr;
public this(void* cObject, bool ownCObject) {
- super($imdmodule.$dclassnameUpcast(cObject), ownCObject);
+ super($imdmodule.$dclazznameUpcast(cObject), ownCObject);
swigCPtr = cObject;
}
diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx
index 4b55d2b4d..e2ce9f384 100644
--- a/Source/Modules/d.cxx
+++ b/Source/Modules/d.cxx
@@ -131,23 +131,37 @@ class D : public Language {
// split proxy module mode, the proxy class modules) from
// %pragma(d) globalproxyimports.
String *global_proxy_imports;
-
- // Imports written to the proxy D module header from global_proxy_imports
- // and, if in split proxy module mode, from D::requireDType().
+
+ // The D code for the main proxy modules. nspace_proxy_dmodules is a hash from
+ // the namespace name as key to an {"imports", "code"}. If the nspace feature
+ // is not active, only proxy_dmodule_imports and proxy_dmodule_code are used,
+ // which contain the code for the root proxy module.
+ //
+ // These variables should not be accessed directly but rather via the
+ // proxy{Imports, Code}Buffer)() helper functions which return the right
+ // buffer for a given namespace. If not in split proxy mode, they contain the
+ // whole proxy code.
String *proxy_dmodule_imports;
-
- // The D code for proxy functions/classes which is written to the proxy D
- // module. If not in split proxy mode, this contains the whole proxy code.
String *proxy_dmodule_code;
-
+ Hash *nspace_proxy_dmodules;
+
// The D code generated for the currently processed enum.
String *proxy_enum_code;
/*
* D data for the current proxy class.
+ *
+ * These strings are mainly used to temporarily accumulate code from the
+ * various member handling functions while a single class is processed and are
+ * no longer relevant once that class has been finished, i.e. after
+ * classHandler() has returned.
*/
- // The name of the current proxy class.
+ // The unqualified name of the current proxy class.
String *proxy_class_name;
+
+ // The name of the current proxy class, qualified with the name of the
+ // namespace it is in, if any.
+ String *proxy_class_qname;
// The import directives for the current proxy class. They are written to the
// same D module the proxy class is written to.
@@ -243,8 +257,10 @@ public:
global_proxy_imports(NULL),
proxy_dmodule_imports(NULL),
proxy_dmodule_code(NULL),
+ nspace_proxy_dmodules(NULL),
proxy_enum_code(NULL),
proxy_class_name(NULL),
+ proxy_class_qname(NULL),
proxy_class_imports(NULL),
proxy_class_enums_code(NULL),
proxy_class_body_code(NULL),
@@ -439,6 +455,7 @@ public:
destructor_call = NewString("");
proxy_dmodule_code = NewString("");
proxy_dmodule_imports = NewString("");
+ nspace_proxy_dmodules = NewHash();
im_dmodule_imports = NewString("");
upcasts_code = NewString("");
global_proxy_imports = NewString("");
@@ -524,7 +541,7 @@ public:
Close(im_d_file);
}
- // Generate the D proxy module for the wrapped module.
+ // Generate the main D proxy module.
{
String *filen = NewStringf("%s%s.d", dmodule_directory, proxy_dmodule_name);
File *proxy_d_file = NewFile(filen, "w", SWIG_output_files());
@@ -556,6 +573,34 @@ public:
Close(proxy_d_file);
}
+
+ // Generate the additional proxy modules for nspace support.
+ for (Iterator it = First(nspace_proxy_dmodules); it.key; it = Next(it)) {
+ String *module_name = createLastNamespaceName(it.key);
+
+ String *filename = NewStringf("%s%s.d", outputDirectory(it.key), module_name);
+ File *file = NewFile(filename, "w", SWIG_output_files());
+ if (!file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(filename);
+
+ emitBanner(file);
+
+ Printf(file, "module %s%s.%s;\n", package, it.key, module_name);
+ Printf(file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(file, global_proxy_imports, NIL);
+ Printv(file, Getattr(it.item, "imports"), NIL);
+ Printv(file, "\n", NIL);
+
+ String *code = Getattr(it.item, "code");
+ replaceModuleVariables(code);
+ Printv(file, code, NIL);
+
+ Close(file);
+ Delete(module_name);
+ }
if (upcasts_code)
Printv(f_wrappers, upcasts_code, NIL);
@@ -613,6 +658,8 @@ public:
proxy_dmodule_code = NULL;
Delete(proxy_dmodule_imports);
proxy_dmodule_imports = NULL;
+ Delete(nspace_proxy_dmodules);
+ nspace_proxy_dmodules = NULL;
Delete(im_dmodule_imports);
im_dmodule_imports = NULL;
Delete(upcasts_code);
@@ -709,7 +756,7 @@ public:
Chop(strvalue);
Printf(im_dmodule_imports, "%s\n", strvalue);
} else if (Strcmp(code, "proxydmodulecode") == 0) {
- Printf(proxy_dmodule_code, "%s\n", strvalue);
+ Printf(proxyCodeBuffer(0), "%s\n", strvalue);
} else if (Strcmp(code, "globalproxyimports") == 0) {
replaceImportTypeMacros(strvalue);
Chop(strvalue);
@@ -798,7 +845,11 @@ public:
if (split_proxy_dmodule && typemap_lookup_type) {
assertClassNameValidity(proxy_class_name);
- String *filename = NewStringf("%s%s.d", dmodule_directory, symname);
+ String *nspace = Getattr(n, "sym:nspace");
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, symname);
+ Delete(output_directory);
+
File *class_file = NewFile(filename, "w", SWIG_output_files());
if (!class_file) {
FileErrorDisplay(filename);
@@ -808,7 +859,11 @@ public:
Delete(filename);
emitBanner(class_file);
- Printf(class_file, "module %s%s;\n", package, symname);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, symname);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, symname);
+ }
Printv(class_file, imports_trimmed, NIL);
Printv(class_file, proxy_enum_code, NIL);
@@ -816,8 +871,9 @@ public:
Close(class_file);
Delete(class_file);
} else {
- Printv(proxy_dmodule_imports, imports, NIL);
- Printv(proxy_dmodule_code, proxy_enum_code, NIL);
+ String *nspace = Getattr(n, "sym:nspace");
+ Printv(proxyImportsBuffer(nspace), imports, NIL);
+ Printv(proxyCodeBuffer(nspace), proxy_enum_code, NIL);
}
}
@@ -834,7 +890,7 @@ public:
virtual int enumvalueDeclaration(Node *n) {
if (getCurrentClass() && (cplus_mode != PUBLIC))
return SWIG_NOWRAP;
-
+
Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
String *value = Getattr(n, "value");
String *name = Getattr(n, "name");
@@ -850,14 +906,12 @@ public:
// Note that this is used in enumValue() amongst other places
Setattr(n, "value", tmpValue);
- String *proxy_name = Getattr(n, "sym:name");
-
// Emit the enum item.
{
if (!GetFlag(n, "firstenumitem"))
Printf(proxy_enum_code, ",\n");
- Printf(proxy_enum_code, " %s", proxy_name);
+ Printf(proxy_enum_code, " %s", Getattr(n, "sym:name"));
// Check for the %dconstvalue feature
String *value = Getattr(n, "feature:d:constvalue");
@@ -886,7 +940,7 @@ public:
String *overloaded_name = getOverloadedName(n);
String *intermediary_function_name =
- Swig_name_member(NSPACE_TODO,proxy_class_name, overloaded_name);
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
Setattr(n, "imfuncname", intermediary_function_name);
String *proxy_func_name = Getattr(n, "sym:name");
@@ -897,6 +951,7 @@ public:
// If we are in split proxy mode and the function is named like the
// target package, the D compiler is unable to resolve the ambiguity
// between the package name and an argument-less function call.
+ // TODO: This might occur with nspace as well, augment the check.
Swig_warning(WARN_D_NAME_COLLISION, input_file, line_number,
"%s::%s might collide with the package name, consider using %%rename to resolve the ambiguity.\n",
proxy_class_name, proxy_func_name);
@@ -935,7 +990,7 @@ public:
String *overloaded_name = getOverloadedName(n);
String *intermediary_function_name =
- Swig_name_member(NSPACE_TODO,proxy_class_name, overloaded_name);
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
Setattr(n, "imfuncname", intermediary_function_name);
writeProxyClassFunction(n);
@@ -1006,7 +1061,7 @@ public:
virtual int constructorHandler(Node *n) {
Language::constructorHandler(n);
- // Wrappers not wanted for some methods where the parameters cannot be overloaded in D.
+ // Wrappers not wanted for some methods where the parameters cannot be overloadedprocess in D.
if (Getattr(n, "overload:ignore")) {
return SWIG_OK;
}
@@ -1026,7 +1081,7 @@ public:
NewString("");
String *overloaded_name = getOverloadedName(n);
- String *mangled_overname = Swig_name_construct(NSPACE_TODO,overloaded_name);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
String *imcall = NewString("");
const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
@@ -1223,7 +1278,7 @@ public:
virtual int destructorHandler(Node *n) {
Language::destructorHandler(n);
String *symname = Getattr(n, "sym:name");
- Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(NSPACE_TODO,symname), "(cast(void*)swigCPtr)", NIL);
+ Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL);
return SWIG_OK;
}
@@ -1231,19 +1286,27 @@ public:
* D::classHandler()
* --------------------------------------------------------------------------- */
virtual int classHandler(Node *n) {
+ String *nspace = getNSpace();
File *class_file = NULL;
proxy_class_name = Copy(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
- if (!addSymbol(proxy_class_name, n)) {
+ if (!addSymbol(proxy_class_name, n, nspace)) {
return SWIG_ERROR;
}
assertClassNameValidity(proxy_class_name);
if (split_proxy_dmodule) {
- String *filename = NewStringf("%s%s.d", dmodule_directory, proxy_class_name);
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, proxy_class_name);
class_file = NewFile(filename, "w", SWIG_output_files());
+ Delete(output_directory);
if (!class_file) {
FileErrorDisplay(filename);
SWIG_exit(EXIT_FAILURE);
@@ -1252,7 +1315,11 @@ public:
Delete(filename);
emitBanner(class_file);
- Printf(class_file, "module %s%s;\n", package, proxy_class_name);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, proxy_class_name);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, proxy_class_name);
+ }
Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
}
@@ -1264,6 +1331,8 @@ public:
Clear(destructor_call);
+ // Traverse the tree for this class, using the *Handler()s to generate code
+ // to the proxy_class_* variables.
Language::classHandler(n);
@@ -1271,6 +1340,10 @@ public:
writeDirectorConnectWrapper(n);
Replaceall(proxy_class_code, "$dclassname", proxy_class_name);
+
+ String *dclazzname = Swig_name_member(getNSpace(), proxy_class_name, "");
+ Replaceall(proxy_class_code, "$dclazzname", dclazzname);
+ Delete(dclazzname);
if (split_proxy_dmodule) {
Printv(class_file, global_proxy_imports, NIL);
@@ -1282,10 +1355,12 @@ public:
Close(class_file);
Delete(class_file);
} else {
- Printv(proxy_dmodule_imports, proxy_class_imports, NIL);
- Printv(proxy_dmodule_code, proxy_class_code, NIL);
+ Printv(proxyImportsBuffer(getNSpace()), proxy_class_imports, NIL);
+ Printv(proxyCodeBuffer(getNSpace()), proxy_class_code, NIL);
}
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
Delete(proxy_class_name);
proxy_class_name = NULL;
@@ -1402,7 +1477,7 @@ public:
if (wrapping_member_flag) {
Printv(proxy_class_body_code, constants_code, NIL);
} else {
- Printv(proxy_dmodule_code, constants_code, NIL);
+ Printv(proxyCodeBuffer(getNSpace()), constants_code, NIL);
}
// Cleanup.
@@ -1780,10 +1855,18 @@ public:
* D::classDirector()
* --------------------------------------------------------------------------- */
virtual int classDirector(Node *n) {
+ String *nspace = Getattr(n, "sym:nspace");
proxy_class_name = NewString(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
int success = Language::classDirector(n);
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
Delete(proxy_class_name);
proxy_class_name = NULL;
@@ -1874,7 +1957,8 @@ public:
// we're consistent with the sym:overload name in functionWrapper. (?? when
// does the overloaded method name get set?)
- imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(NSPACE_TODO,classname, overloaded_name));
+ imclass_dmethod = NewStringf("SwigDirector_%s",
+ Swig_name_member(getNSpace(), classname, overloaded_name));
if (returntype) {
qualified_return = SwigType_rcaststr(returntype, "c_result");
@@ -2507,6 +2591,8 @@ private:
* intermediary D module.
*
* d_name - The name the function in the intermediary D module will get.
+ * return type - The return type of the function in the C wrapper.
+ * parameters - The parameter list of the C wrapper function.
* wrapper_function_name - The name of the exported function in the C wrapper
* (usually d_name prefixed by »D_«).
* --------------------------------------------------------------------------- */
@@ -2587,8 +2673,12 @@ private:
if (wrapping_member_flag) {
// Check if this is a setter method for a public member.
- setter_flag = (Cmp(Getattr(n, "sym:name"),
- Swig_name_set(NSPACE_TODO,Swig_name_member(NSPACE_TODO,proxy_class_name, variable_name))) == 0);
+ const String *setter_name = Swig_name_set(getNSpace(),
+ Swig_name_member(0, proxy_class_name, variable_name));
+
+ if (Cmp(Getattr(n, "sym:name"), setter_name) == 0) {
+ setter_flag = true;
+ }
}
// Write function modifiers.
@@ -2630,7 +2720,7 @@ private:
if (!static_flag) {
Printf(imcall, "cast(void*)swigCPtr");
}
-
+
String *proxy_param_types = NewString("");
// Write the parameter list for the proxy function declaration and the
@@ -2769,7 +2859,7 @@ private:
Node *explicit_n = Getattr(n, "explicitcallnode");
if (explicit_n) {
String *ex_overloaded_name = getOverloadedName(explicit_n);
- String *ex_intermediary_function_name = Swig_name_member(NSPACE_TODO,proxy_class_name, ex_overloaded_name);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, ex_overloaded_name);
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
@@ -2795,7 +2885,7 @@ private:
Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
"No dout typemap defined for %s\n", SwigType_str(t, 0));
}
-
+
Delete(proxy_param_types);
// The whole function body is now in stored tm (if there was a matching type
@@ -3003,7 +3093,7 @@ private:
// The whole function code is now stored in tm (if there was a matching
// type map, of course), so simply append it to the code buffer.
Printf(function_code, "%s\n", tm ? (const String *) tm : empty_string);
- Printv(proxy_dmodule_code, function_code, NIL);
+ Printv(proxyCodeBuffer(getNSpace()), function_code, NIL);
Delete(pre_code);
Delete(post_code);
@@ -3016,6 +3106,16 @@ private:
/* ---------------------------------------------------------------------------
* D::writeProxyClassAndUpcasts()
+ *
+ * Collects all the code fragments generated by the handler function while
+ * traversing the tree from the proxy_class_* variables and writes the
+ * class definition (including any epilogue code) to proxy_class_code.
+ *
+ * Also writes the upcast function to the wrapper layer when processing a
+ * derived class.
+ *
+ * Inputs:
+ * n – The class node currently processed.
* --------------------------------------------------------------------------- */
void writeProxyClassAndUpcasts(Node *n) {
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
@@ -3026,7 +3126,8 @@ private:
String *c_classname = SwigType_namestr(Getattr(n, "name"));
String *c_baseclass = NULL;
- String *baseclass = NULL;
+ Node *basenode = NULL;
+ String *basename = NULL;
String *c_baseclassname = NULL;
// Inheritance from pure D classes.
@@ -3046,9 +3147,10 @@ private:
base = Next(base);
}
if (base.item) {
+ basenode = base.item;
c_baseclassname = Getattr(base.item, "name");
- baseclass = Copy(getProxyName(c_baseclassname));
- if (baseclass)
+ basename = Copy(getProxyName(c_baseclassname));
+ if (basename)
c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
base = Next(base);
/* Warn about multiple inheritance for additional base class(es) */
@@ -3067,24 +3169,25 @@ private:
}
}
- bool derived = baseclass && getProxyName(c_baseclassname);
+ bool derived = (basename != NULL);
if (derived && purebase_notderived) {
pure_baseclass = empty_string;
}
- const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+ const String *wanted_base = basename ? basename : pure_baseclass;
if (purebase_replace) {
wanted_base = pure_baseclass;
derived = false;
- Delete(baseclass);
- baseclass = NULL;
+ basenode = NULL;
+ Delete(basename);
+ basename = NULL;
if (purebase_notderived) {
Swig_error(Getfile(n), Getline(n),
"The dbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n",
typemap_lookup_type);
}
- } else if (baseclass && Len(pure_baseclass) > 0) {
+ } else if (basename && Len(pure_baseclass) > 0) {
Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base class %s ignored. Multiple inheritance is not supported in D. "
"Perhaps you need one of the 'replace' or 'notderived' attributes in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
@@ -3101,14 +3204,10 @@ private:
// If this class is derived from a C++ class, we need to have the D class
// generated for it in scope.
if (derived) {
- requireDType(baseclass);
+ requireDType(Getattr(basenode, "sym:nspace"), Getattr(basenode, "sym:name"));
- if (split_proxy_dmodule) {
- // Fully qualify the baseclass name.
- String *module = NewStringf("%s%s.", package, baseclass);
- Insert(baseclass, 0, module);
- Delete(module);
- }
+ // Fully qualify the baseclass name.
+ Insert(basename, 0, package);
}
// Write any custom import statements to the proxy module header.
@@ -3238,8 +3337,8 @@ private:
// Write the class body and the curly bracket closing the class definition
// to the proxy module.
indentCode(body);
- Replaceall(body, "$dbaseclass", baseclass);
- Delete(baseclass);
+ Replaceall(body, "$dbaseclass", basename);
+ Delete(basename);
Printv(proxy_class_code, body, "\n}\n", NIL);
Delete(body);
@@ -3256,9 +3355,8 @@ private:
String* c_class_name, String* c_base_name) {
String *smartptr = Getattr(n, "feature:smartptr");
- String *upcast_name = NewString("");
- Printv(upcast_name, d_class_name,
- (smartptr != 0 ? "SmartPtrUpcast" : "Upcast"), NIL);
+ String *upcast_name = Swig_name_member(getNSpace(), d_class_name,
+ (smartptr != 0 ? "SmartPtrUpcast" : "Upcast"));
String *upcast_wrapper_name = Swig_name_wrapper(upcast_name);
@@ -3338,8 +3436,8 @@ private:
imports_target = NewString("");
code_target = NewString("");
} else {
- imports_target = proxy_dmodule_imports;
- code_target = proxy_dmodule_code;
+ imports_target = proxyImportsBuffer(0);
+ code_target = proxyCodeBuffer(0);
}
// Import statements.
@@ -3461,7 +3559,8 @@ private:
// Output the director connect method.
String *norm_name = SwigType_namestr(Getattr(n, "name"));
- String *connect_name = NewStringf("%s_director_connect", proxy_class_name);
+ String *connect_name = Swig_name_member(getNSpace(),
+ proxy_class_name, "director_connect");
String *sym_name = Getattr(n, "sym:name");
Wrapper *code_wrap;
@@ -3504,19 +3603,40 @@ private:
/* ---------------------------------------------------------------------------
* D::requireDType()
*
- * Adds an import statement for the given module to the header of current
- * module. This is only used for dependencies created in generated code, user-
- * (read: typemap-) specified import statements are handeled seperately.
+ * If the given type is not already in scope in the current module, adds an
+ * import statement for it. The name is considered relative to the global root
+ * package if one is set.
+ *
+ * This is only used for dependencies created in generated code, user-
+ * (i.e. typemap-) specified import statements are handeled seperately.
* --------------------------------------------------------------------------- */
- void requireDType(const String *dmodule_name) {
- String *import = createImportStatement(dmodule_name);
- Append(import, "\n");
- if (is_wrapping_class()) {
- addImportStatement(proxy_class_imports, import);
+ void requireDType(const String *nspace, const String *symname) {
+ String *dmodule;
+ if (nspace) {
+ dmodule = NewStringf("%s.", nspace);
} else {
- addImportStatement(proxy_dmodule_imports, import);
+ dmodule = NewString("");
}
- Delete(import);
+
+ if (split_proxy_dmodule) {
+ Printv(dmodule, symname, NIL);
+ } else {
+ String *inner = createLastNamespaceName(nspace);
+ Printv(dmodule, inner, NIL);
+ Delete(inner);
+ }
+
+ if (!inProxyModule(dmodule)) {
+ String *import = createImportStatement(dmodule);
+ Append(import, "\n");
+ if (is_wrapping_class()) {
+ addImportStatement(proxy_class_imports, import);
+ } else {
+ addImportStatement(proxyImportsBuffer(getNSpace()), import);
+ }
+ Delete(import);
+ }
+ Delete(dmodule);
}
/* ---------------------------------------------------------------------------
@@ -3550,46 +3670,41 @@ private:
/* ---------------------------------------------------------------------------
* D::createImportStatement()
*
- * Creates a string containing an import statement for the given module if it
- * is needed in the currently generated proxy D module (i.e. if it is not the
- * current module itself).
+ * Creates a string containing an import statement for the given module.
* --------------------------------------------------------------------------- */
String *createImportStatement(const String *dmodule_name,
bool static_import = true) const {
- if (inProxyModule(dmodule_name)) {
- return NewStringf("");
+ if (static_import) {
+ return NewStringf("static import %s%s;", package, dmodule_name);
} else {
- if (static_import) {
- return NewStringf("static import %s%s;", package, dmodule_name);
- } else {
- return NewStringf("import %s%s;", package, dmodule_name);
- }
+ return NewStringf("import %s%s;", package, dmodule_name);
}
}
/* ---------------------------------------------------------------------------
* D::inProxyModule()
*
- * Determines if the specified proxy class is decleared in the currently
+ * Determines if the specified proxy type is declared in the currently
* processed proxy D module.
*
* This function is used to determine if fully qualified type names have to be
- * used (package, module and type name). This is never the case if the split
- * proxy mode is not used, all proxy types are written to the same module then.
+ * used (package, module and type name). If the split proxy mode is not used,
+ * this solely depends on whether the type is in the current namespace or.
* --------------------------------------------------------------------------- */
bool inProxyModule(const String *type_name) const {
if (!split_proxy_dmodule) {
- // If we are not in split proxy module mode, proxy code is always written
- // to the same module.
- return true;
+ String *nspace = createOuterNamespaceNames(type_name);
+ bool result = (getNSpace() || !nspace) && (Strcmp(nspace, getNSpace()) == 0);
+ Delete(nspace);
+ return result;
}
- if (!Len(proxy_class_name)) {
+ if (!Len(proxy_class_qname)) {
return false;
}
- return (Strcmp(proxy_class_name, type_name) == 0);
+ return (Strcmp(proxy_class_qname, type_name) == 0);
}
/* ---------------------------------------------------------------------------
@@ -3637,17 +3752,57 @@ private:
* D::assertClassNameValidity()
* --------------------------------------------------------------------------- */
void assertClassNameValidity(const String* class_name) const {
+ // TODO: With nspace support, there could arise problems also when not in
+ // split proxy mode, warnings for these should be added.
if (split_proxy_dmodule) {
if (Cmp(class_name, im_dmodule_name) == 0) {
- Swig_error(input_file, line_number, "Class name cannot be equal to intermediary D module name: %s\n",
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to intermediary D module name: %s\n",
class_name);
SWIG_exit(EXIT_FAILURE);
}
- if (Cmp(class_name, proxy_dmodule_name) == 0) {
- Swig_error(input_file, line_number, "Class name cannot be equal to proxy D module name: %s\n",
- class_name);
- SWIG_exit(EXIT_FAILURE);
+ String *nspace = getNSpace();
+ if (nspace) {
+ // Check the root package/outermost namespace (a class A in module
+ // A.B leads to problems if another module A.C is also imported)…
+ if (Len(package) > 0) {
+ String *dotless_package = NewStringWithSize(package, Len(package) - 1);
+ if (Cmp(class_name, dotless_package) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the root package it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(dotless_package);
+ } else {
+ String *outer = createFirstNamespaceName(nspace);
+ if (Cmp(class_name, outer) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the outermost namespace it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(outer);
+ }
+
+ // … and the innermost one (because of the conflict with the main proxy
+ // module named like the namespace).
+ String *inner = createLastNamespaceName(nspace);
+ if (Cmp(class_name, inner) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the innermost namespace it is in: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Delete(inner);
+ } else {
+ if (Cmp(class_name, proxy_dmodule_name) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to proxy D module name: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
}
}
}
@@ -3927,48 +4082,69 @@ private:
// import when a type is used in another generated module. If we are not
// working in split proxy module mode, this is not relevant and the
// generated module name is discarded.
- String *import_name;
+ String *type_name;
- String *qualified_type_name;
if (SwigType_isenum(type)) {
// RESEARCH: Make sure that we really cannot get here for anonymous enums.
Node *n = enumLookup(type);
- const String *symname = Getattr(n, "sym:name");
-
- // Add in class scope when referencing enum if not a global enum.
- const String *parent_name = NULL;
- String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
- if (scopename_prefix) {
- parent_name = getProxyName(scopename_prefix);
- Delete(scopename_prefix);
- }
-
- if (parent_name) {
- qualified_type_name = createQualifiedName(parent_name);
- Printv(qualified_type_name, ".", symname, NIL);
+ String *enum_name = Getattr(n, "sym:name");
+
+ Node *p = parentNode(n);
+ if (p && !Strcmp(nodeType(p), "class")) {
+ // This is a nested enum.
+ String *parent_name = Getattr(p, "sym:name");
+ String *nspace = Getattr(p, "sym:nspace");
// An enum nested in a class is not written to a seperate module (this
// would not even be possible in D), so just import the parent.
- import_name = Copy(parent_name);
- } else {
- qualified_type_name = createQualifiedName(symname);
+ requireDType(nspace, parent_name);
+ String *module = createModuleName(nspace, parent_name);
+ if (inProxyModule(module)) {
+ type_name = NewStringf("%s.%s", parent_name, enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name);
+ }
+ } else {
// A non-nested enum is written to a seperate module, import it.
- import_name = Copy(symname);
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, enum_name);
+
+ String *module = createModuleName(nspace, enum_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, enum_name);
+ }
}
} else {
- const String *class_name = getProxyName(type);
- if (class_name) {
- // This is something wrapped as a proxy class (getProxyName() works for
- // pointers to classes too).
- qualified_type_name = createQualifiedName(class_name);
- import_name = Copy(class_name);
+ Node *n = classLookup(type);
+ if (n) {
+ String *class_name = Getattr(n, "sym:name");
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, class_name);
+
+ String *module = createModuleName(nspace, class_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(class_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, class_name);
+ }
} else {
// SWIG does not know anything about the type (after resolving typedefs).
// Just mangle the type name string like $descriptor(type) would do.
String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
- qualified_type_name = createQualifiedName(descriptor);
- import_name = Copy(descriptor);
+ requireDType(NULL, descriptor);
+
+ String *module = NULL;
+ if (split_proxy_dmodule) {
+ module = Copy(descriptor);
+ }
+ if (inProxyModule(module)) {
+ type_name = Copy(descriptor);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, descriptor);
+ }
// Add to hash table so that a type wrapper class can be created later.
Setattr(unknown_types, descriptor, type);
@@ -3977,23 +4153,36 @@ private:
}
}
- Replaceall(target, variable, qualified_type_name);
- Delete(qualified_type_name);
-
- requireDType(import_name);
- Delete(import_name);
+ Replaceall(target, variable, type_name);
+ Delete(type_name);
}
/* ---------------------------------------------------------------------------
- * D::createQualifiedName()
+ * D::createModuleName()
+ *
+ * Returns a string holding the name of the module to import to bring the
+ * given type in scope.
* --------------------------------------------------------------------------- */
- String *createQualifiedName(const String *class_name) const {
- if (inProxyModule(class_name)) {
- return Copy(class_name);
+ String *createModuleName(const String *nspace, const String *type_name) const {
+ String *module;
+ if (nspace) {
+ module = NewStringf("%s.", nspace);
+ if (split_proxy_dmodule) {
+ Printv(module, type_name, NIL);
+ } else {
+ String *inner = createLastNamespaceName(nspace);
+ Printv(module, inner, NIL);
+ Delete(inner);
+ }
} else {
- return NewStringf("%s%s.%s", package, class_name, class_name);
+ if (split_proxy_dmodule) {
+ module = Copy(type_name);
+ } else {
+ module = proxy_dmodule_name;
+ }
}
-}
+ return module;
+ }
/* ---------------------------------------------------------------------------
* D::replaceModuleVariables()
@@ -4070,9 +4259,14 @@ private:
String *current_macro = NewStringWithSize(start, (int)(end - start));
String *current_param = NewStringWithSize(param_start, (int)(param_end - param_start));
- String *import = createImportStatement(current_param, false);
- Replace(target, current_macro, import, DOH_REPLACE_ANY);
- Delete(import);
+
+ if (inProxyModule(current_param)) {
+ Replace(target, current_macro, "", DOH_REPLACE_ANY);
+ } else {
+ String *import = createImportStatement(current_param, false);
+ Replace(target, current_macro, import, DOH_REPLACE_ANY);
+ Delete(import);
+ }
Delete(current_param);
Delete(current_macro);
@@ -4107,13 +4301,35 @@ private:
* Returns the D class name if a type corresponds to something wrapped with a
* proxy class, NULL otherwise.
* --------------------------------------------------------------------------- */
- const String *getProxyName(SwigType *t) {
+ const String *getProxyName(SwigType *t) {
+ String *proxyname = NULL;
Node *n = classLookup(t);
if (n) {
- return Getattr(n, "sym:name");
- } else {
- return NULL;
+ proxyname = Getattr(n, "proxyname");
+ if (!proxyname) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Getattr(n, "sym:name");
+
+ if (nspace) {
+ proxyname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ proxyname = Copy(symname);
+ }
+ if (split_proxy_dmodule) {
+ Printf(proxyname, ".%s", symname);
+ } else {
+ if (!inProxyModule(proxyname)) {
+ Delete(proxyname);
+ String *inner = createLastNamespaceName(nspace);
+ proxyname = NewStringf("%s.%s.%s", nspace, inner, symname);
+ Delete(inner);
+ }
+ }
+ Setattr(n, "proxyname", proxyname);
+ Delete(proxyname); // Return value still valid because of the ref from n.
+ }
}
+ return proxyname;
}
/* ---------------------------------------------------------------------------
@@ -4324,6 +4540,145 @@ private:
Swig_banner_target_lang(f, " *");
Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
}
+
+ /* ---------------------------------------------------------------------------
+ * D::outputDirectory()
+ *
+ * Returns the directory to write the D modules for the given namespace to and
+ * and creates the subdirectory if it doesn't exist.
+ * --------------------------------------------------------------------------- */
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(dmodule_directory);
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write proxy code for the given namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyCodeBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_code;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "code");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write imports for the proxy code for the given
+ * namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyImportsBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_imports;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "imports");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createFirstNamespaceName()
+ *
+ * Returns a new string containing the name of the outermost namespace, e.g.
+ * »A« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createFirstNamespaceName(const String *nspace) const {
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "."))
+ return 0;
+
+ co = c + Len(nspace);
+
+ while (*c && (c != co)) {
+ if ((*c == '.')) {
+ break;
+ }
+ c++;
+ }
+ if (!*c || (c == tmp)) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(c - tmp));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createLastNamespaceName()
+ *
+ * Returns a new string containing the name of the innermost namespace, e.g.
+ * »C« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createLastNamespaceName(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *c = Char(nspace);
+ char *cc = c;
+ if (!strstr(c, "."))
+ return NewString(nspace);
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ return NewString(cc + 1);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createOuterNamespaceNames()
+ *
+ * Returns a new string containing the name of the outer namespace, e.g.
+ * »A.B« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createOuterNamespaceNames(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *cc = c;
+ if (!strstr(c, "."))
+ return NULL;
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ if (cc == tmp) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(cc - tmp));
+ }
};
static Language *new_swig_d() {