Re-organization of the interface feature common code
Move code to new feature.cxx file. Activate it in the allocate phase rather than in individual languages.
This commit is contained in:
parent
fa9d2687cb
commit
a1245ef398
7 changed files with 193 additions and 159 deletions
|
|
@ -47,6 +47,7 @@ eswig_SOURCES = CParse/cscanner.c \
|
|||
Modules/emit.cxx \
|
||||
Modules/go.cxx \
|
||||
Modules/guile.cxx \
|
||||
Modules/interface.cxx \
|
||||
Modules/java.cxx \
|
||||
Modules/javascript.cxx \
|
||||
Modules/lang.cxx \
|
||||
|
|
|
|||
|
|
@ -729,6 +729,8 @@ Allocate():
|
|||
}
|
||||
}
|
||||
|
||||
Swig_interface_propagate_methods(n);
|
||||
|
||||
/* Only care about default behavior. Remove temporary values */
|
||||
Setattr(n, "allocate:visit", "1");
|
||||
Swig_symbol_setscope(symtab);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
/* Hash type used for upcalls from C/C++ */
|
||||
typedef DOH UpcallData;
|
||||
// helper function used in feature:interface implementation
|
||||
void Swig_propagate_interface_methods(Node *n);
|
||||
|
||||
class CSHARP:public Language {
|
||||
static const char *usage;
|
||||
|
|
@ -276,6 +274,7 @@ public:
|
|||
SWIG_config_file("csharp.swg");
|
||||
|
||||
allow_overloading();
|
||||
Swig_interface_feature_enable();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
@ -4403,8 +4402,6 @@ public:
|
|||
String *old_director_delegate_instances = director_delegate_instances;
|
||||
String *old_director_method_types = director_method_types;
|
||||
String *old_director_connect_parms = director_connect_parms;
|
||||
if (proxy_flag)
|
||||
Swig_propagate_interface_methods(n);
|
||||
|
||||
int ret = Language::classDeclaration(n);
|
||||
|
||||
|
|
|
|||
181
Source/Modules/interface.cxx
Normal file
181
Source/Modules/interface.cxx
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* This file is part of SWIG, which is licensed as a whole under version 3
|
||||
* (or any later version) of the GNU General Public License. Some additional
|
||||
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
||||
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
||||
* included with the SWIG source code as distributed by the SWIG developers
|
||||
* and at http://www.swig.org/legal.html.
|
||||
*
|
||||
* interface.cxx
|
||||
*
|
||||
* This module contains support for the interface feature.
|
||||
* This feature is used in language modules where the target language does not
|
||||
* naturally support C++ style multiple inheritance, but does support inheritance
|
||||
* from multiple interfaces.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "swigmod.h"
|
||||
|
||||
static bool interface_feature_enabled = false;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_methods()
|
||||
*
|
||||
* Create a list of all the methods from the base classes of class n that are
|
||||
* marked as an interface. The resulting list is thus the list of methods that
|
||||
* need to be implemented in order for n to be non-abstract.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static List *collect_interface_methods(Node *n) {
|
||||
List *methods = NewList();
|
||||
if (Hash *bases = Getattr(n, "interface:bases")) {
|
||||
List *keys = Keys(bases);
|
||||
for (Iterator base = First(keys); base.item; base = Next(base)) {
|
||||
Node *cls = Getattr(bases, base.item);
|
||||
if (cls == n)
|
||||
continue;
|
||||
for (Node *child = firstChild(cls); child; child = nextSibling(child)) {
|
||||
if (Cmp(nodeType(child), "cdecl") == 0) {
|
||||
if (GetFlag(child, "feature:ignore") || Getattr(child, "interface:owner"))
|
||||
continue; // skip methods propagated to bases
|
||||
Node *m = Copy(child);
|
||||
set_nextSibling(m, NIL);
|
||||
set_previousSibling(m, NIL);
|
||||
Setattr(m, "interface:owner", cls);
|
||||
Append(methods, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_bases
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_bases(Hash *bases, Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *name = Getattr(n, "interface:name");
|
||||
if (!Getattr(bases, name))
|
||||
Setattr(bases, name, n);
|
||||
}
|
||||
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
if (Getattr(base.item, "feature:interface"))
|
||||
collect_interface_bases(bases, base.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_base_classes()
|
||||
*
|
||||
* Create a hash containing all the classes up the inheritance hierarchy
|
||||
* marked with feature:interface (including this class n).
|
||||
* Stops going up the inheritance chain as soon as a class is found without
|
||||
* feature:interface.
|
||||
* The idea is to find all the base interfaces that a class must implement.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_base_classes(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
// check all bases are also interfaces
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
if (!Getattr(base.item, "feature:interface")) {
|
||||
Swig_error(Getfile(n), Getline(n), "Base class '%s' of '%s' is not similarly marked as an interface.\n", SwigType_namestr(Getattr(base.item, "name")), SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hash *interface_bases = NewHash();
|
||||
collect_interface_bases(interface_bases, n);
|
||||
if (Len(interface_bases) == 0)
|
||||
Delete(interface_bases);
|
||||
else
|
||||
Setattr(n, "interface:bases", interface_bases);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* process_interface_name()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void process_interface_name(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *interface_name = Getattr(n, "feature:interface:name");
|
||||
if (!Len(interface_name)) {
|
||||
Swig_error(Getfile(n), Getline(n), "The interface feature for '%s' is missing the name attribute.\n", SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
if (Strchr(interface_name, '%')) {
|
||||
String *name = NewStringf(interface_name, Getattr(n, "sym:name"));
|
||||
Setattr(n, "interface:name", name);
|
||||
} else {
|
||||
Setattr(n, "interface:name", interface_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_interface_propagate_methods()
|
||||
*
|
||||
* Find all the base classes marked as an interface (with feature:interface) for
|
||||
* class node n. For each of these, add all of its methods as methods of n so that
|
||||
* n is not abstract. If class n is also marked as an interface, it will remain
|
||||
* abstract and not have any methods added.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_interface_propagate_methods(Node *n) {
|
||||
if (interface_feature_enabled) {
|
||||
process_interface_name(n);
|
||||
collect_interface_base_classes(n);
|
||||
List *methods = collect_interface_methods(n);
|
||||
bool is_interface = Getattr(n, "feature:interface") != 0;
|
||||
for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
|
||||
if (!is_interface && GetFlag(mi.item, "abstract"))
|
||||
continue;
|
||||
String *this_decl = Getattr(mi.item, "decl");
|
||||
String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
|
||||
bool overloaded = false;
|
||||
if (SwigType_isfunction(resolved_decl)) {
|
||||
String *name = Getattr(mi.item, "name");
|
||||
for (Node *child = firstChild(n); child; child = nextSibling(child)) {
|
||||
if (Getattr(child, "interface:owner"))
|
||||
break; // at the end of the list are newly appended methods
|
||||
if (checkAttribute(child, "name", name)) {
|
||||
String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
|
||||
overloaded = Strcmp(decl, this_decl) == 0;
|
||||
Delete(decl);
|
||||
if (overloaded)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(resolved_decl);
|
||||
if (!overloaded)
|
||||
appendChild(n, mi.item);
|
||||
else
|
||||
Delete(mi.item);
|
||||
}
|
||||
Delete(methods);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_interface_feature_enable()
|
||||
*
|
||||
* Turn on interface feature support
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_interface_feature_enable() {
|
||||
interface_feature_enabled = true;
|
||||
}
|
||||
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
/* Hash type used for upcalls from C/C++ */
|
||||
typedef DOH UpcallData;
|
||||
// helper function used in feature:interface implementation
|
||||
void Swig_propagate_interface_methods(Node *n);
|
||||
|
||||
class JAVA:public Language {
|
||||
static const char *usage;
|
||||
|
|
@ -307,6 +305,7 @@ public:
|
|||
SWIG_config_file("java.swg");
|
||||
|
||||
allow_overloading();
|
||||
Swig_interface_feature_enable();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
@ -2076,8 +2075,6 @@ public:
|
|||
* ---------------------------------------------------------------------- */
|
||||
|
||||
int classDeclaration(Node *n) {
|
||||
if (proxy_flag)
|
||||
Swig_propagate_interface_methods(n);
|
||||
return Language::classDeclaration(n);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3818,152 +3818,3 @@ Hash *Language::getClassHash() const {
|
|||
return classhash;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_methods()
|
||||
*
|
||||
* Create a list of all the methods from the base classes of class n that are
|
||||
* marked as an interface. The resulting list is thus the list of methods that
|
||||
* need to be implemented in order for n to be non-abstract.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static List *collect_interface_methods(Node *n) {
|
||||
List *methods = NewList();
|
||||
if (Hash *bases = Getattr(n, "interface:bases")) {
|
||||
List *keys = Keys(bases);
|
||||
for (Iterator base = First(keys); base.item; base = Next(base)) {
|
||||
Node *cls = Getattr(bases, base.item);
|
||||
if (cls == n)
|
||||
continue;
|
||||
for (Node *child = firstChild(cls); child; child = nextSibling(child)) {
|
||||
if (Cmp(nodeType(child), "cdecl") == 0) {
|
||||
if (GetFlag(child, "feature:ignore") || Getattr(child, "interface:owner"))
|
||||
continue; // skip methods propagated to bases
|
||||
Node *m = Copy(child);
|
||||
set_nextSibling(m, NIL);
|
||||
set_previousSibling(m, NIL);
|
||||
Setattr(m, "interface:owner", cls);
|
||||
Append(methods, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_bases
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_bases(Hash *bases, Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *name = Getattr(n, "interface:name");
|
||||
if (!Getattr(bases, name))
|
||||
Setattr(bases, name, n);
|
||||
}
|
||||
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
if (Getattr(base.item, "feature:interface"))
|
||||
collect_interface_bases(bases, base.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_base_classes()
|
||||
*
|
||||
* Create a hash containing all the classes up the inheritance hierarchy
|
||||
* marked with feature:interface (including this class n).
|
||||
* Stops going up the inheritance chain as soon as a class is found without
|
||||
* feature:interface.
|
||||
* The idea is to find all the base interfaces that a class must implement.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_base_classes(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
// check all bases are also interfaces
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
if (!Getattr(base.item, "feature:interface")) {
|
||||
Swig_error(Getfile(n), Getline(n), "Base class '%s' of '%s' is not similarly marked as an interface.\n", SwigType_namestr(Getattr(base.item, "name")), SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hash *interface_bases = NewHash();
|
||||
collect_interface_bases(interface_bases, n);
|
||||
if (Len(interface_bases) == 0)
|
||||
Delete(interface_bases);
|
||||
else
|
||||
Setattr(n, "interface:bases", interface_bases);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* process_interface_name()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void process_interface_name(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *interface_name = Getattr(n, "feature:interface:name");
|
||||
if (!Len(interface_name)) {
|
||||
Swig_error(Getfile(n), Getline(n), "The interface feature for '%s' is missing the name attribute.\n", SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
if (Strchr(interface_name, '%')) {
|
||||
String *name = NewStringf(interface_name, Getattr(n, "sym:name"));
|
||||
Setattr(n, "interface:name", name);
|
||||
} else {
|
||||
Setattr(n, "interface:name", interface_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_propagate_interface_methods()
|
||||
*
|
||||
* Find all the base classes marked as an interface (with feature:interface) for
|
||||
* class node n. For each of these, add all of its methods as methods of n so that
|
||||
* n is not abstract. If class n is also marked as an interface, it will remain
|
||||
* abstract and not have any methods added.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_propagate_interface_methods(Node *n) {
|
||||
process_interface_name(n);
|
||||
collect_interface_base_classes(n);
|
||||
List *methods = collect_interface_methods(n);
|
||||
bool is_interface = Getattr(n, "feature:interface") != 0;
|
||||
for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
|
||||
if (!is_interface && GetFlag(mi.item, "abstract"))
|
||||
continue;
|
||||
String *this_decl = Getattr(mi.item, "decl");
|
||||
String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
|
||||
bool overloaded = false;
|
||||
if (SwigType_isfunction(resolved_decl)) {
|
||||
String *name = Getattr(mi.item, "name");
|
||||
for (Node *child = firstChild(n); child; child = nextSibling(child)) {
|
||||
if (Getattr(child, "interface:owner"))
|
||||
break; // at the end of the list are newly appended methods
|
||||
if (checkAttribute(child, "name", name)) {
|
||||
String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
|
||||
overloaded = Strcmp(decl, this_decl) == 0;
|
||||
Delete(decl);
|
||||
if (overloaded)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(resolved_decl);
|
||||
if (!overloaded)
|
||||
appendChild(n, mi.item);
|
||||
else
|
||||
Delete(mi.item);
|
||||
}
|
||||
Delete(methods);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -422,19 +422,24 @@ extern "C" {
|
|||
}
|
||||
|
||||
/* Contracts */
|
||||
|
||||
void Swig_contracts(Node *n);
|
||||
void Swig_contract_mode_set(int flag);
|
||||
int Swig_contract_mode_get();
|
||||
|
||||
/* Browser */
|
||||
|
||||
void Swig_browser(Node *n, int);
|
||||
void Swig_default_allocators(Node *n);
|
||||
void Swig_process_types(Node *n);
|
||||
|
||||
/* Nested classes */
|
||||
void Swig_nested_process_classes(Node *n);
|
||||
void Swig_nested_name_unnamed_c_structs(Node *n);
|
||||
|
||||
/* Interface feature */
|
||||
void Swig_interface_feature_enable();
|
||||
void Swig_interface_propagate_methods(Node *n);
|
||||
|
||||
/* Miscellaneous */
|
||||
template <class T> class save_value {
|
||||
T _value;
|
||||
T& _value_ptr;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue