A lot of work on the type system. Experimental language module.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@516 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-07-05 04:04:17 +00:00
commit 765ad025b9
8 changed files with 609 additions and 96 deletions

View file

@ -5,8 +5,8 @@
srcdir = @srcdir@
VPATH = @srcdir@
SRCS = naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
OBJS = naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
prefix = @prefix@
exec_prefix = @exec_prefix@

200
Source/Swig/map.c Normal file
View file

@ -0,0 +1,200 @@
/* -----------------------------------------------------------------------------
* map.c
*
* This file provides support for defining %map rules that match lists of
* parameters to objects defining code generation rules.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#include "swig.h"
/* -----------------------------------------------------------------------------
* Synopsis
*
* One of the biggest problems in wrapper generation is that of defining
* the handling of various datatypes and function parameters. This module
* provides support for a generic object known as a 'mapping rule' that is
* defined using the %map directive like this:
*
* %map rulename(typelist) {
* vars;
* rule1 { ... }
* rule2 { ... }
* rule3 { ... }
* rule4 { ... }
* ...
* }
*
* A mapping rule is somewhat similar to a class or structure definition. The
* "vars" field is a list of variable declarations that will be local to the
* mapping rule when it is used. The "rulen" fields simply define code
* fragments and other information that language specific modules can examine
* for their own nefarious purposes.
*
* ----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
* Swig_map_add()
*
* Adds a new mapping rule. The parms input to this function should be a
* properly constructed parameter list with associated attributes. The rules
* field can technically be any valid object.
*
* The structure of how data is stored is as follows:
*
* ruleset (hash)
* --------------
* rulename ------> nameset (hash)
* --------------
* parm1 ---------> rule (hash)
* -------------
* parm2 -----------> rule (hash)
* *obj* --> obj
*
*
* For multiple arguments, we end up building a large tree of hash tables.
* The object will be stored in the *obj* attribute of the last hash table.
* ----------------------------------------------------------------------------- */
void
Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj)
{
DOHHash *nameset;
DOHHash *p, *n;
/* Locate the appropriate nameset */
nameset = Getattr(ruleset,rulename);
if (!nameset) {
/* Hmmm. First time we've seen this. Let's add it to our mapping table */
nameset = NewHash();
Setattr(ruleset,rulename,nameset);
}
/* Now, we walk down the parms list and create a series of hash tables */
p = parms;
n = nameset;
while (p) {
DOHString *ty, *name, *key;
DOHHash *nn;
ty = Getattr(p,"type");
name = Getattr(p,"name");
/* Create a hash table key */
key = NewStringf("%s-%s",name,ty);
/* See if there is already a entry with this type in the table */
nn = Getattr(n,key);
if (!nn) {
/* No. Go ahead and create it */
nn = NewHash();
Setattr(n,key,nn);
}
Delete(key);
n = nn;
p = Swig_next(p);
}
/* No more parameters. At this point, n points to the very last hash table in our search.
We'll stick our object there */
Setattr(n,"*obj*",obj);
return;
}
/* -----------------------------------------------------------------------------
* Swig_map_match()
*
* Perform a longest map for a list of parameters and a set of mapping rules.
* Returns the corresponding rule object and the number of parameters that
* were matched.
* ----------------------------------------------------------------------------- */
/* Internal function used for recursively searching rulesets */
static DOH *
Swig_map_match_internal(DOHHash *nameset, DOHHash *parms, int *nmatch) {
DOHHash *nn1, *nn2;
DOHString *ty;
DOHString *name;
DOHString *key;
int mlen1 = 0, mlen2 = 0, bestlen = 0;
DOH *obj1 = 0, *obj2 = 0;
DOH *bestobj, *bestn;
DOHHash *nextp;
if (!parms) {
bestobj = Getattr(nameset,"*obj*");
if (bestobj) *nmatch++;
return bestobj;
}
ty = Getattr(parms,"type");
name = Getattr(parms,"name");
key = NewStringf("%s-%s",name,ty);
/* See if there is an exact name match */
nn1 = Getattr(nameset,key);
if (nn1) {
mlen1++;
obj1 = Swig_map_match_internal(nn1,Swig_next(parms), &mlen1);
}
/* See if there is a generic name match */
Clear(key);
Printf(key,"-%s",ty);
nn2 = Getattr(nameset,key);
if (nn2) {
mlen2++;
obj2 = Swig_map_match_internal(nn2, Swig_next(parms), &mlen2);
}
/* Pick the best match. Note: an exact name match is preferred */
if (obj1 && obj2) {
if (mlen2 > mlen1) {
bestlen = mlen2;
bestobj = obj2;
} else {
bestlen = mlen1;
bestobj = obj1;
}
} else if (obj1) {
bestobj = obj1;
bestlen = mlen1;
} else if (obj2) {
bestobj = obj2;
bestlen = mlen2;
}
if (!bestobj) {
bestobj = Getattr(nameset,"*obj*");
if (bestobj) bestlen = 1;
}
Delete(key);
*nmatch = *nmatch + bestlen;
return bestobj;
}
DOH *
Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch)
{
DOHHash *nameset;
int mlen = 0;
DOH *best;
/* Get the nameset */
nameset = Getattr(ruleset,rulename);
if (!nameset) return 0;
best = Swig_map_match_internal(nameset,parms,&mlen);
*nmatch = mlen;
return best;
}

View file

@ -418,6 +418,40 @@ DOHString *SwigType_prefix(DOHString *t) {
return NewString("");
}
/* -----------------------------------------------------------------------------
* SwigType_array_ndim()
*
* Returns the number of dimensions of an array.
* ----------------------------------------------------------------------------- */
int SwigType_array_ndim(DOHString_or_char *id) {
int ndim = 0;
char *c = Char(id);
while (c && SwigType_isarray(c)) {
c = strchr(c,'.');
ndim++;
}
return ndim;
}
/* -----------------------------------------------------------------------------
* SwigType_array_getdim()
*
* Get the value of the nth dimension.
* ----------------------------------------------------------------------------- */
DOHString *SwigType_array_getdim(DOHString_or_char *id, int n) {
char *c = Char(id);
while (c && SwigType_isarray(c) && (n > 0)) {
c = strchr(c,'.');
n--;
}
if (n == 0) return SwigType_parm(c);
return 0;
}
/* -----------------------------------------------------------------------------
* SwigType_cstr(DOH *s, DOH *id)
*
@ -705,25 +739,3 @@ int SwigType_cmp(DOHString_or_char *tpat, DOHString_or_char *type) {
}
return 1;
}
#ifdef DEBUG
int main() {
DOHString *a,*b,*c,*d;
a = NewString("int");
SwigType_add_pointer(a);
SwigType_typedef(a,"IntPtr");
b = NewString("IntPtr");
SwigType_add_array(b,"1000");
Printf(stdout,"b = '%s'\n", b);
c = SwigType_typedef_resolve(b);
Printf(stdout,"c = '%s'\n", c);
Printf(stdout,"cmp = %d\n", SwigType_cmp("a(1000).p.p.int",b));
}
#endif

View file

@ -146,6 +146,8 @@ extern DOHHash *SwigType_pop_scope();
extern DOHString *SwigType_typedef_resolve(DOHString_or_char *t);
extern int SwigType_istypedef(DOHString_or_char *t);
extern int SwigType_cmp(DOHString_or_char *pat, DOHString_or_char *t);
extern int SwigType_array_ndim(DOHString_or_char *t);
extern DOHString *SwigType_array_getdim(DOHString_or_char *t, int n);
/* --- Parse tree support --- */
@ -159,6 +161,9 @@ extern void Swig_add_rule(DOHString_or_char *, int (*action)(DOH *, void *));
extern void Swig_add_rules(SwigRule ruleset[]);
extern void Swig_clear_rules();
extern int Swig_emit(DOH *obj, void *clientdata);
extern void Swig_cut_node(DOH *obj);
extern DOH *Swig_next(DOH *obj);
extern DOH *Swig_prev(DOH *obj);
/* -- Wrapper function Object */
@ -186,6 +191,11 @@ extern char *Swig_name_set(DOHString_or_char *vname);
extern char *Swig_name_construct(DOHString_or_char *classname);
extern char *Swig_name_destroy(DOHString_or_char *classname);
/* --- Mapping interface --- */
extern void Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj);
extern DOH *Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch);
/* --- Misc --- */
extern char *Swig_copy_string(const char *c);
extern void Swig_banner(DOHFile *f);

View file

@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
* tree.c
*
* This file provides some general purpose functions for walking through
* This file provides some general purpose functions for manipulating
* parse trees.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
@ -16,6 +16,21 @@ static char cvsroot[] = "$Header$";
static DOHHash *rules = 0;
/* -----------------------------------------------------------------------------
* Swig_next()
* Swig_prev()
*
* Return next/prev node in a parse tree
* ----------------------------------------------------------------------------- */
DOH *Swig_next(DOH *obj) {
return Getattr(obj,"next");
}
DOH *Swig_prev(DOH *obj) {
return Getattr(obj,"prev");
}
/* -----------------------------------------------------------------------------
* Swig_dump_tags()
*
@ -38,7 +53,7 @@ Swig_dump_tags(DOH *obj, DOH *root) {
Swig_dump_tags(cobj,newroot);
Delete(newroot);
}
obj = Getattr(obj,"sibling");
obj = Swig_next(obj);
}
if (!root)
Delete(croot);
@ -115,10 +130,62 @@ Swig_emit(DOH *obj, void *clientdata) {
} else {
Printf(stderr,"warning: no action defined for '%s'\n", tag);
}
obj = Getattr(obj,"sibling");
obj = Swig_next(obj);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_cut_node(DOH *obj)
*
* This function cuts an object out of a parse tree. To do this, the object
* MUST be properly initialized with "next", "prev", and "parent" attributes.
* ----------------------------------------------------------------------------- */
void Swig_cut_node(DOH *obj) {
DOH *parent;
DOH *next;
DOH *prev;
parent = Getattr(obj,"parent");
assert(parent);
next = Getattr(obj,"next");
prev = Getattr(obj,"prev");
DohIncref(obj); /* Make sure object doesn't go away */
Delattr(obj,"parent"); /* Disassociate from my parent */
if (!next && !prev) {
/* Well, this is a single child. Guess we'll just update the parent their child is gone */
Delattr(parent,"child");
return;
}
/* If no next node, then this must be at the end of a list */
if (!next) {
Delattr(prev,"next"); /* Break the 'next' link in the previous node */
Delattr(obj,"prev"); /* Break my link back to the previous object */
return;
}
/* No previous node. This must be the beginning of a list */
if (!prev) {
Delattr(next,"prev"); /* Break the 'prev' link of the next node */
Setattr(parent,"child",next); /* Update parent to point at next node */
Delattr(obj,"next"); /* Break my link to the next object */
return;
}
/* In the middle of a list someplace */
Setattr(prev,"next",next); /* Update previous node to my next node */
Setattr(next,"prev",prev); /* Update next node to my previous node */
Delattr(obj,"next");
Delattr(obj,"prev");
return;
}