MathBus

[ Term Structure | Algebra | Geometry | Logic | Drawing ]
[ Language Bindings | C++ | Java | Lisp | ML ]


C++ Language Bindings

A complete C++ implementation of the MathBus term structure is provided. For many uses, the C++ implementation may yield the most efficient solution, but there are a few additional problems to which attention must be paid. For many computaions involving the MathBus term structure a nagging problem is storage management. Since C++ does not have a garbage collector, storage leaks and other problems often arise. For such problems the Java, ML or Lisp implementations may be preferable. However, to minimize the problems that do occur a reference counting mechanism is provided for MathBus nodes.

The basic objects used in the C++ implementation of the MathBus terms structure are 32-bit unsigned integers and MathBus nodes. The type MB32Bit is used to represent a 32-bit unsigned integer. Implementations on different machine architectures will use different typedef's to ensure that MB32Bit always refers to a 32-bit unsigned integer. The header files ensure that this type is declared properly for all machines.

Nodes

MathBus nodes are represented by class MBNode. References to instances of this class are represented by instances of class MBNodep. This class can also be used to represent references to MB32bit objects, so the sub-terms of a node are of this type. The MBNodep class is defined as follows

class MBNodep {
protected:
  union {
  MB32Bit intValue;
  MBNode *node;
  } v;

public:
  MBNodep();
  MBNodep(MB32bit);
  MBNodep(long val);
  MBNode(MBNode *);
  operator MB32bit();
  operator MBNode*();

  MB32bit operator=(MB32bit);
  MB32bit operator=(long val);
  MBNode* operator=(MBNode*);
  MBNode* operator->();
  MBNode& operator*();
}

Nothing within intances of this class indicates whether it represents a reference to an MB32bit number or a reference to node. The user must be know when it is used. The additional methods are provided so that the user does not need to explicitly refer to the components of the union.

Nodes themselves can be represented using the class MBNode, which is defined as follows:

class MBNode {
protected:
  unsigned long cntSubterms;
  MBNodep pSubterms[];
  int refCount;

public:
  MBNode();
  MBNode(MB32bit nodeLabel, MB32bit nSubterms);
  MBNode (char *nodeLabel, MB32bit nSubterms);

  ...
}

Constructors are provided for some of the simple cases.


MBNode::MBNode(MB32bit n)

MBNode::MBNode(MB32bit nodeLabel, MB32bit n)
MBNode::MBNode(char *nodeLabel, MB32bit n)

These are the primitive methods for creating nodes. When creating an MBNode one must at always provide the number of sub-terms to allow the creator to allocate space for the array of sub-terms. One can optionally also include the label for this node. This can be provided either as a 32-bit string identifier or as character string. In the later case the string identifier will be looked up in the registry. The sub-terms of the new node are initialized to NULL. Until the node label is specified, it is not possible to determine the types of the sub-terms. Thus, it is always preferable to specify the node label at creation time.

In addition, creators for some simple node types are also provided.


MBNode::MBNode(double d);
Creates a node labeled IEEEFloatingPoint and fills in the sub-terms appropriately to from the components of d.

The following method can be used to create LongIntegers, Strings or arbitrary Nodes. Which is created depends upon the value of cm, which is of type MBNodeConstructorMode. This is defined as follows:

enum MBNodeConstructorMode {eString, eLongInteger, ePareNode};

There are two forms of this constructor depending upon the type of the first argument. It can be either a string or a character array.


MBNode::MBNode(string s, MBNodeConstructorMode cm);
MBNode::MBNode(char *s, MBNodeConstructorMode cm);

If cm is equal to eString then a String node is created using the characters contained in s. These characters are converted to Unicode characters before being stored in the node. If cm is equal to eLongInteger then the characters of s are to be digits between 0 and 9 with possible leading spaces, a plus sign or a minus sign. Finally, if cm is equal to eParenNode then the characters of s are assumed to form a well formed parenthesized version of the MathBus node as described in the Notation section.

The following four methods (mblabel, nSubterms, subterm, and operator[]) can be used to examine the components of an MBNode. When any of these methods is applied to a Attributes node, they will recursively apply themselves to the node that possesses these attributes. Thus, the presence of attributes will be transparent to these routines.


MB32bit MBNode::mblabel()

Returns the numeric label of the node. This method should be named label, but label is a reserved word in C++. This method can never return the label Attributes.


MB32bit MBNode::nSubterms()

Returns the number of sub-terms of the node.


MBNodep MBNode::subterm(MB32bit
index)

Returns the index-th sub-term of the node. An index of zero corresponds returns the label of the node, an index of 1 corresponds to the first sub-term, 2 corresponds to the second, etc.


MBNode::operator[](MB32bit
index)

Returns the a reference to the indicated sub-term of the MBNode. This is the preferred approach to accessing sub-terms of a node since it can be used on both the left and right hand sides of an assignment.

When it is actually necessary to extract the sub-terms of an Attributes node, the following sub-primitives can be used.


MB32bit MBNode::mblabelq()
MB32bit MBNode::nSubtermsq()
MBNodep MBNode::subtermq(MB32bit
index)
MBNode::setSubterm(unsigned long
index, Mnodep value)

Storage Management

To facilitate storage management, a reference counting mechanism is provided. The two methods addRef() and release() are used to manage the reference counts of Nodes. Nodes are created with an initial refrence count of 0. Whenever additional references to a node are created, the reference should be increased using addRef(). This includes when the newly created node is returned from a function. Whenever an object is freed, its reference count should be decremented using release().


void MBNode::addRef()

This routine increments the reference count of the node.


void MBNode::release()

This routine decrements the reference count of the node. If the reference count is reduced to 0, then reference counts of the sub-terms of the node are decremented and the storage held by the node is freed.

Registry

There is only one registry in an address space. The implementation of this registry is hidden from the user. Instead, a set of C++ functions are provided that allow access to the information contained in the registry.


void ClearRegistry(bool global, bool local)

Resets the regisitry and removes the existing contents from the indicated parts of the registry.

The most common way for users to modify the registry to create new local labels. This can be done by the following routine. Note that one does not specify a the numeric label corresponding to the string. The numeric value is chosen automatically from the unassigned local numeric labels.


MB32bit NewLocalLabel(string ident)

MB32bit NewLocalLabel(char *dent)
Creates a new local label with string identifier ident. The new numeric label is returned.


void StoreGlobalRecord(string ident, RegistryType regType, long value)
void StoreGlobalRecord(char *ident, RegistryType regType, long value)
Can be used to add new values to the global registry. The regType field indicates whether a new string identifier is being defined or whether the Subterm Types of the string identifier.


The following four routines can be used to access the numeric string identifier, symbolic string identifier mapping. These routines first search for the identifier in the local registry and if that fails, in the global registry. No mechanism is provided to search only on part of the registry.


bool hasStringID(MB32bit ident)
Returns true if the registry already contains the numeric identifier ident.


string stringID(MB32bit ident)
Returns the symbolic identifier corresponding to the numeric identifier ident.


bool hasNumericLabel(string &identStr)
bool hasNumericLabel(char *identStr)
Returns true if the registry already contains the symbolic identifier identStr.


MB32bit numericLabel(string &identStr)
MB32bit numericLabel(char *identStr)
Returns the symbolic identifier corresponding to the symbolic identifier ident.


long subtermTypes(MB32bit ident)
Returns the the subterm types of nodes labeled ident. For an intepretation of the results of this routine see the SubTypes Registry Entries section.

When a new registry distribution file is received, or when the C++ implementation is being bootstrapped, the registry in the C++ implementation is initialized using the MBRegistry::LoadRegistryFile method. The C++ source code files that are used by the Java implementation can be generated by the WriteJavaRegistry method.


void
MBRegistry::LoadRegistryFile(char * filename)
Initializes the registry with the contents of the registry file specified. This is used to bootstrap the C++ implementation.


void
MBRegistry::WriteRegistryDecls(char * directory)
Using the current contents of the global registry, write C++ source files for initializing the registry into the directory directory.


void StoreLocal(String
ident, String regType, int value)

Associates value with the identifier ident and registry type regType.

To speed access of numeric string identifiers the mathbus.MBS object is defined. This object has only static members and the name of each is a global string and whose value is the corresponding numeric value.

Input/Output Routines


long subtermTypes(MB32bit ident)

Tools

The following three methods are useful when converting MathBus terms into structures used by other programs.


double MBNode::getIEEEFloat()
If the node's label is IEEEFloat, then this routine returns the floating point number represented by this node.


string MBNode::getLongInteger()
If the node's label is LongInteger, then this routine returns a string with the decimal digits of the represented long integer. If the number is negative, the first character of the string will be a minus sign.


double MBNode::getString()
If the node's label is String, then this routine returns the string represented by this node.

Iteration

The following should be done using C++ style iterators instead of passing functions around. (subtermIterate, index, type, nextSuterm)

The following routine returns an enumeration of the sub-terms of a node. The enumeration returned keeps track of the types of the sub-terms as well as the sub-term index itself. This is for what it is most frequently used.


Subterm Enumeration subterms(Node
node)
Returns a new SubtermEnumeration for the node. A SubtermEnumeration handles the four following methods.


MBNodep nextElement()
Advances the (internal) index that points at sub-terms and returns the sub-term which is currently being pointed to.


unsigned long thisIndex()

Returns the index of the current sub-term.


int thisSubtype()
Returns the subtype the current sub-term. The value returned is 0 if the sub-term is a node reference, 1 if the sub-term is a 32-bit integer and 2 if the sub-term is a string identifier.


boolean hasMoreElements()

Returns true if there are any more sub-terms.


Copyright Cornell University
For problems or questions regarding this web contact
[ SimLab project].
Last updated: November 03, 1997 by .