A Better C Language

wang@hpax.cup.hp.com (Thomas Wang)
Wed, 8 Jun 1994 01:54:30 GMT

          From comp.compilers

Related articles
A Better C Language wang@hpax.cup.hp.com (1994-06-08)
Re: A Better C Language whatis@primus.com (1994-06-22)
Re: A Better C Language wang@hpax.cup.hp.com (1994-06-24)
Re: A Better C Language andy@research.canon.oz.au (1994-06-28)
| List of all articles for this month |

Newsgroups: comp.compilers
From: wang@hpax.cup.hp.com (Thomas Wang)
Keywords: C
Organization: Hewlett-Packard
Date: Wed, 8 Jun 1994 01:54:30 GMT

Hello all. I am seeking general feedbacks to this specification. After
the design phase, I will be able to start the implementation.


I have experience in memory management, and class library design, but
my experience in language design is limited. Any help would be appreciated.




    -Thomas Wang (Computing work increases system entropy.) wang@cup.hp.com


-----------------------------------------------------------------------------


1. Introduction to Better C


Better C is yet another object-oriented language based on C.


Better C supports automatic memory freeing, and the memory engine is a precise
copying garbage collector.


Better C is a super set of Ansi-C, and a sub set of C++.


Better C's exception handling system is identical to C++.


Better C supports inheritance, and late binding functions.


Better C generates portable C++ source codes as output.


Just what is Better C? You can imagine it as a value-added component to C.


The target audience is for organizations that want to produce programs without
memory bugs, and yet want to stay within the C programming platform.




2. Overview of Better C


2.1. Better C Data Model


Better C has types, objects, and functions. These are the standard
structures of any language.


Better C's type hierarchy looks like a tree root's diagram, with a
type being the most super type of all types. A type can have one super type,
and multiple sub types. An advanced feature of Better C is the ability to
inherit interfaces from more than one type. For example, you might declare
type 'TA' to be a subtype of 'person' with additional interfaces from
type 'teacher'.


Every Better C object knows which type it belongs to. Objects also contain
data, which the program uses to do computation.


Functions can be classified into three categories: specific functions,
generic functions , and other functions.


A specific function works on objects of a particular type. For example,
the function ccInt32Print(x) will print out the value of an integer object.


A generic function works on objects of any type. For example, the function
ccAnyPrint(x) will print out the value of an object of any type. The generic
function dispatches to the proper specific function by looking at the object's
type.


Better C automatically builds up a specific function dispatch table for each
generic function, making writing generic functions easy. Because generic
functions are programmer defined, the dispatching method can be tailored to
fit a generic function's specification. Programmers are no longer confined to
a 'one size fits all' dispatching philosophy.




2.2. Declaring a type


A type is defined by using the 'bctype' declaration.




/* Declares a subtype. */
bctype Int32 : public Obj
{
protected:
    long the_value;
};




What the above example do is to declare a type called 'Int32', with
immediate super type 'Obj'.




(Advanced)


A type can be declared to be inheriting interfaces from more than one type.


bctype Ta : public Person, public Teacher
{
protected:
    Teacher the_teacher;
};


Type 'Ta' is structure inherited from 'Person', and is promised to know
the interface of 'Teacher'. All the generic functions that accepts
Teacher objects would also accept Ta objects. Compiler will issue warnings
if this is not the case. Please note this is not the same as C++'s
multiple inheritance semantics. Interfaces are multiple inherited, not data.




2.3. Declaring Functions


We will expand out the 32 bit integer example to include some function
declarations.




extern int32 ccAnyCmp(Obj This, Obj second);


bctype Int32 : public Obj
{
protected:
    int32 the_value;


public:
    friend Int32 ccInt32Make(int32 num);
    friend int32 ccInt32Cmp(Int32 This, Int32 second) = ccAnyCmp;
};


The function ccAnyCmp() is a generic function. It calls the correct
specific function based on object's type. It's declaration is straight
forward. It's just an external declaration.


The function ccInt32Make() is a constructor function. It constructs an
integer object. Because it needs to access the internal data structure,
it is declared as a friend function. For those who knows C++, friend
functions replace member functions for all bctype objects. Member functions
are not friendly toward automatic memory management.


The function ccInt32Cmp() is a specific function. It is declared as friend
because it also needs to access the internal data structure. The assignment
statement maps the relationship between the specific function, and the generic
function.


This mapping mechanism serves similar purposes as C++'s virtual functions.




2.4. Implementing Functions


The first function shown below is a specific function. The second one is
a generic function.


int32 ccInt32Cmp(Int32 This, Int32 second)
{
    int32 result;


    if (This->the_value > second->the_value)
        result = 1;
    else if (This->the_value < second->the_value)
        result = -1;
    else
        result = 0;
    return(result);
}




int32 ccAnyCmp(Obj This, Obj second)
{
    int32 result;


    if (This == NULL)
    {
        if (second == NULL)
            result = 0;
        else
            result = -1;
    }
    else if (second == NULL)
    {
        result = 0;
    }
    else if (ccObjGetTag(This) > ccObjGetTag(second))
    {
        result = 1;
    }
    else if (ccObjGetTag(This) < ccObjGetTag(second))
    {
        result = -1;
    }
    else
    {
        funsigof(ccAnyCmp) fun_ptr;


        fun_ptr = funtable(ccAnyCmp) [ccObjGetTag(This)];
        if (fun_ptr != NULL)
            result = (*fun_ptr) (This, second); /* dispatch */
        else
            throw ccErrorDispatchMake();
    }
    return(result);
}


The keyword 'funsigof' declares a function pointer. The keyword 'funtable'
retrieves a function table.


The comparison function was a more complicated example, but it shows how a
generic function can do specialized dispatching based on input arguments.




2.5. Object Construction Functions


In Better C, Object construction functions have name ending with 'Make' by
convention.




extern Int32 ccInt32Make(long num);


Int32 ccInt32Make(long num)
{
    Int32 This;
    This = (Int32) uuMemMallocMovable(sizeof(*This)); /* allocates memory */
    This->the_value = num;
    ccObjInit(This, typecode(Int32));
    return(This);
}




2.6. Sample Main Program


The following program will print increasing numbers starting from 1.
It will forever stay in an endless loop, printing.


int main()
{
    Int32 a_number = NULL;
    long num = 0;


    uuMemInit(); /* do initialization, details not shown */


    for (;;)
    {
        a_number = ccInt32Make(++num);
        ccInt32Print(a_number);
    }
}




2.7. Freeing Memory


The programmer need not free bctype objects. This responsibility is taken
care by the Better C compiler. The object code generated by the compiler
will free the memory that are no longer used.


Therefore, the sample main program listed above will never run out of memory.




3. Code Generation


The main task of the compiler is to keep track of the root information for
the garbage collector. The output code must maintain the list of currently
active local gc variables and global gc variables.


<source>
void fun1(Int32 a)
{
    Int32 b;
    Int32 c = a;


    fun2();
}


<target>
void fun1(Int32 a)
{
    Int32 b = 0;
    Int32 c = a;
    RootTracker var00001(&a, &b, &c);


    fun2();
}


The constructor of RootTracker would push the address of 'a', 'b', and 'c'
onto the root stack. The destructor would pop them off the root stack.


Since we are taking the address of all the gc objects, there should be no
chance for the pointers to become mangled by the optimizer. We should be able
to optimize this code if we are inclined to do so.




4. Better C Class Library


The following list are some of the types in the class library.


Obj - common most supertype
Int32 - 32 bit integer
Boole - boolean value
Pstr - string
Lisp - Lisp con-cell
Array - expandable array
Slink - single linked list
Rlist - ring linked list
Keyval - Key and value pair
Index - unordered collection (dictionary)
Oindex - ordered collection (implemented by splayed tree)




5. Better C Object Model


Object ordering is strictly defined in the class library. Ordering can be
one of three possibilities: greater, equal, or less. The ordering between
any two objects must be permanent. All objects must be ordered.


The impact of this policy is good. The hashing functions are immune to
problems associated with changing states. In addition, operations with
unordered collections have non-random behavior.


The container class is designed to be able to handle having objects of
different types in them. You can even put Apples and Oranges in an ordered
collection. It may not be earth shattering, but it works. Generic operations
are a key concern in the design of the class library.




6. Availability


Not available right now.
--


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.