Experimental patch for abstract methods

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4385 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2003-02-25 03:26:01 +00:00
commit bcba55e6f0
3 changed files with 184 additions and 19 deletions

View file

@ -26,6 +26,31 @@ void Wrapper_virtual_elimination_mode_set(int flag) {
virtual_elimination_mode = flag;
}
/* Helper function to assist with abstract class checking.
This is a major hack. Sorry. */
static String *search_decl = 0; /* Declarator being searched */
static int check_implemented(Node *n) {
String *local_decl;
if (!n) return 0;
while (n) {
if (Strcmp(nodeType(n), "cdecl") == 0) {
local_decl = Getattr(n,"decl");
if (local_decl) local_decl = SwigType_typedef_resolve_all(local_decl);
if (local_decl && (Strcmp(local_decl, search_decl) == 0)) {
if (!Getattr(n,"abstract")) {
Delete(local_decl);
return 1;
}
}
Delete(local_decl);
}
n = Getattr(n,"csym:nextSibling");
}
return 0;
}
class Allocate : public Dispatcher {
Node *inclass;
enum AccessMode { PUBLIC, PRIVATE, PROTECTED };
@ -143,11 +168,16 @@ class Allocate : public Dispatcher {
if (base_decl) base_decl = SwigType_typedef_resolve_all(base_decl);
if (Strstr(name,"~")) continue; /* Don't care about destructors */
int implemented = 0;
Node *dn = Swig_symbol_clookup(name,0);
/* Node *dn = Swig_symbol_clookup_local(name,0);
if (!dn) {
Printf(stdout,"node: %x '%s'. base: %x '%s'. member '%s'\n", n, Getattr(n,"name"), base, Getattr(base,"name"), name);
}
assert(dn != 0); // Assertion of doom
*/
search_decl = base_decl;
Node *dn = Swig_symbol_clookup_local_check(name,0,check_implemented);
/*
while (dn && !implemented) {
String *local_decl = Getattr(dn,"decl");
if (local_decl) local_decl = SwigType_typedef_resolve_all(local_decl);
@ -158,10 +188,16 @@ class Allocate : public Dispatcher {
Delete(local_decl);
dn = Getattr(dn,"csym:nextSibling");
}
if (!implemented && (Getattr(nn,"abstract"))) {
*/
Delete(base_decl);
/* if (!implemented && (Getattr(nn,"abstract"))) {
return 1;
}
Delete(base_decl);
*/
if (!dn) return 1;
/*
if (dn && (Getattr(dn,"abstract"))) {
return 1;

View file

@ -281,8 +281,10 @@ extern Symtab *Swig_symbol_popscope();
extern Node *Swig_symbol_add(String_or_char *symname, Node *node);
extern void Swig_symbol_cadd(String_or_char *symname, Node *node);
extern Node *Swig_symbol_clookup(String_or_char *symname, Symtab *tab);
extern Node *Swig_symbol_clookup_check(String_or_char *symname, Symtab *tab, int (*check)(Node *));
extern Symtab *Swig_symbol_cscope(String_or_char *symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local(String_or_char *symname, Symtab *tab);
extern Node *Swig_symbol_clookup_local_check(String_or_char *symname, Symtab *tab, int (*check)(Node *));
extern String *Swig_symbol_qualified(Node *node);
extern Node *Swig_symbol_isoverloaded(Node *node);
extern void Swig_symbol_remove(Node *node);

View file

@ -648,10 +648,14 @@ Swig_symbol_add(String_or_char *symname, Node *n) {
* towards the global scope.
*
* This function operates in the C namespace, not the target namespace.
*
* The check function is an optional callback that can be used to verify a particular
* symbol match. This is only used in some of the more exotic parts of SWIG. For instance,
* verifying that a class hierarchy implements all pure virtual methods.
* ----------------------------------------------------------------------------- */
static Node *
symbol_lookup(String_or_char *name, Symtab *symtab) {
symbol_lookup(String_or_char *name, Symtab *symtab, int (*check)(Node *n)) {
Node *n;
List *inherit;
Hash *sym = Getattr(symtab,"csymtab");
@ -661,15 +665,30 @@ symbol_lookup(String_or_char *name, Symtab *symtab) {
n = Getattr(sym,name);
if (n) {
Setmark(symtab,0);
return n;
/* if a check-function is defined. Call it to determine a match */
if (check) {
int c = check(n);
if (c == 1) {
Setmark(symtab,0);
return n;
}
if (c < 0) {
/* Terminate the search right away */
Setmark(symtab,0);
return 0;
}
} else {
Setmark(symtab,0);
return n;
}
}
inherit = Getattr(symtab,"inherit");
if (inherit) {
int i,len;
len = Len(inherit);
for (i = 0; i < len; i++) {
n = symbol_lookup(name, Getitem(inherit,i));
n = symbol_lookup(name, Getitem(inherit,i),check);
if (n) {
Setmark(symtab,0);
return n;
@ -681,7 +700,7 @@ symbol_lookup(String_or_char *name, Symtab *symtab) {
}
static Node *
symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, int local) {
symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, int local, int (*checkfunc)(Node *n)) {
/* This is a little funky, we search by fully qualified names */
if (!symtab) return 0;
@ -691,7 +710,7 @@ symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, in
String *prefix;
bname = Swig_scopename_last(name);
prefix = Swig_scopename_prefix(name);
n = symbol_lookup_qualified(bname,symtab,prefix,local);
n = symbol_lookup_qualified(bname,symtab,prefix,local,checkfunc);
Delete(bname);
Delete(prefix);
return n;
@ -713,13 +732,13 @@ symbol_lookup_qualified(String_or_char *name, Symtab *symtab, String *prefix, in
/* Found a scope match */
if (st) {
if (!name) return st;
n = symbol_lookup(name, st);
n = symbol_lookup(name, st,checkfunc);
}
Delete(qname);
if (!n) {
if (!local) {
Node *pn = parentNode(symtab);
if (pn) n = symbol_lookup_qualified(name,pn, prefix, local);
if (pn) n = symbol_lookup_qualified(name,pn, prefix, local,checkfunc);
} else {
n = 0;
}
@ -757,12 +776,12 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) {
if (Strncmp(name,"::",2) == 0) {
String *nname = NewString(Char(name)+2);
if (Swig_scopename_check(nname)) {
s = symbol_lookup_qualified(nname,global_scope,0,0);
s = symbol_lookup_qualified(nname,global_scope,0,0,0);
}
} else {
String *prefix = Swig_scopename_prefix(name);
if (prefix) {
s = symbol_lookup_qualified(name,hsym,0,0);
s = symbol_lookup_qualified(name,hsym,0,0,0);
Delete(prefix);
if (!s) {
return 0;
@ -772,7 +791,7 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) {
}
if (!s) {
while (hsym) {
s = symbol_lookup(name,hsym);
s = symbol_lookup(name,hsym,0);
if (s) break;
hsym = parentNode(hsym);
if (!hsym) break;
@ -793,6 +812,73 @@ Swig_symbol_clookup(String_or_char *name, Symtab *n) {
return s;
}
/* -----------------------------------------------------------------------------
* Swig_symbol_clookup_check()
*
* This function is identical to Swig_symbol_clookup() except that it
* accepts a callback function that is invoked to determine a symbol match.
* The purpose of this function is to support complicated algorithms that need
* to examine multiple definitions of the same symbol that might appear in an
* inheritance hierarchy.
* ----------------------------------------------------------------------------- */
Node *
Swig_symbol_clookup_check(String_or_char *name, Symtab *n, int (*checkfunc)(Node *n)) {
Hash *hsym;
Node *s = 0;
if (!n) {
hsym = current_symtab;
} else {
if (Strcmp(nodeType(n),"symboltable")) {
n = Getattr(n,"sym:symtab");
}
assert(n);
if (n) {
hsym = n;
}
}
if (Swig_scopename_check(name)) {
if (Strncmp(name,"::",2) == 0) {
String *nname = NewString(Char(name)+2);
if (Swig_scopename_check(nname)) {
s = symbol_lookup_qualified(nname,global_scope,0,0,checkfunc);
}
} else {
String *prefix = Swig_scopename_prefix(name);
if (prefix) {
s = symbol_lookup_qualified(name,hsym,0,0,checkfunc);
Delete(prefix);
if (!s) {
return 0;
}
}
}
}
if (!s) {
while (hsym) {
s = symbol_lookup(name,hsym,checkfunc);
if (s) break;
hsym = parentNode(hsym);
if (!hsym) break;
}
}
if (!s) {
return 0;
}
/* Check if s is a 'using' node */
while (s && Strcmp(nodeType(s),"using") == 0) {
Node *ss;
ss = Swig_symbol_clookup(Getattr(s,"uname"), Getattr(s,"sym:symtab"));
if (!ss && !checkfunc) {
Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname"));
}
s = ss;
}
return s;
}
Node *
Swig_symbol_clookup_local(String_or_char *name, Symtab *n) {
Hash *h, *hsym;
@ -812,13 +898,13 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) {
if (Swig_scopename_check(name)) {
if (Strncmp(name,"::",2) == 0) {
s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0);
s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0,0);
} else {
s = symbol_lookup_qualified(name,hsym,0,0);
s = symbol_lookup_qualified(name,hsym,0,0,0);
}
}
if (!s) {
s = symbol_lookup(name,hsym);
s = symbol_lookup(name,hsym,0);
}
if (!s) return 0;
/* Check if s is a 'using' node */
@ -832,6 +918,47 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) {
return s;
}
Node *
Swig_symbol_clookup_local_check(String_or_char *name, Symtab *n, int (*checkfunc)(Node *)) {
Hash *h, *hsym;
Node *s = 0;
if (!n) {
hsym = current_symtab;
h = ccurrent;
} else {
if (Strcmp(nodeType(n),"symboltable")) {
n = Getattr(n,"sym:symtab");
}
assert(n);
hsym = n;
h = Getattr(n,"csymtab");
}
if (Swig_scopename_check(name)) {
if (Strncmp(name,"::",2) == 0) {
s = symbol_lookup_qualified(Char(name)+2,global_scope,0,0,checkfunc);
} else {
s = symbol_lookup_qualified(name,hsym,0,0,checkfunc);
}
}
if (!s) {
s = symbol_lookup(name,hsym,checkfunc);
}
if (!s) return 0;
/* Check if s is a 'using' node */
while (s && Strcmp(nodeType(s),"using") == 0) {
Node *ss = Swig_symbol_clookup_local_check(Getattr(s,"uname"), Getattr(s,"sym:symtab"),checkfunc);
if (!ss && !checkfunc) {
Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", Getattr(s,"uname"));
}
s = ss;
}
return s;
}
/* -----------------------------------------------------------------------------
* Swig_symbol_cscope()
*
@ -840,8 +967,8 @@ Swig_symbol_clookup_local(String_or_char *name, Symtab *n) {
Symtab *
Swig_symbol_cscope(String_or_char *name, Symtab *symtab) {
if (Strncmp(name,"::",2) == 0) return symbol_lookup_qualified(0, global_scope, name, 0);
return symbol_lookup_qualified(0,symtab,name,0);
if (Strncmp(name,"::",2) == 0) return symbol_lookup_qualified(0, global_scope, name, 0,0);
return symbol_lookup_qualified(0,symtab,name,0,0);
}
/* -----------------------------------------------------------------------------