Sunday, June 18, 2006

I now have a sourceforge page for xX at: http://sourceforge.net/projects/xxplatform/
I don't have much to place there yet though. I don't want to dump xX, but I'm starting to like the idea of Prototype C. Using a macro language like m4, it may be possible to add the appropriate syntax to C. Hmm.

About xX, I'm having a problem. Should I make standard data types such as integers and strings objects, or not? The problem with making them objects is that at some point, xX will need to get to the data, a standard C data type. Which is why I'm considering removing the typeless requirement of xX. But I really don't want to because I think having xX typeless will make it more flexible. But, how can I properly handle such datatypes? How can I make sure that when an add message is sent to an object which supports the operation, that it will act appropriately?

The other issue is xXe. I designed it to be quite high-level to have it easier to compile down to. But, I can image xXe programs will be very large and slow to execute compared to bytecode vms. So... now what? If I make the vm execute bytecode instead, can it handle objects?

Saturday, June 17, 2006

Ever heard of Objective-C? It's a very nice language. A strict superset of C. Anyway, I've thought about scraping the whole vm thing and implementing a small runtime (like Objective-C does) what will allow C to use prototype objects. I could call it pC for Prototype C! It would be a runtime library and a C preprocessor. Basically, I could run pC source code through a preprocessor which would convert the sourcecode to pure C code. Then, you would just have to compile the C code and link it with the pC library! Yummy!

Monday, June 12, 2006

I submitted an application at sourceforge.net to get a project page for xX. When typing the comprehensive description I realized it's quite a project! I've never created anything like this before. And I'm only a novice at C. HAHA! That's why I can't wait to create the dictionary object (most likely a btree). The dictionary will play an important part since it will be used by the vm to perform object definition lookups. I already have the stack object. After another sleepless night, mostly thinking about xX, I thought of more things...

Executable objects
Recently, I mentioned that I needed a way to determine whether an object in a slot is data or a pointer to a function. Well, I think I found a solution. First, make the slots store xxObjects and only xxObjects. Then, create what I like call executable objects. xX is typeless so an executable object is simply an object that responds to either the executeNative or executexXe (I will now refer to xXasm as xXe) message. If an object responds to executeNative, that means that it contains a pointer to a function that needs to be executed. This is how native (compiled) code will be executed. It an object reponds to executexXe, that means it contains a xXe code. I modified the messaging model. All messages simply execute a lookup in the current object's slots dictionary for an object. If an object is found, it is placed on the stack awaiting for more messages. The virtual machine will check every object to see if it is executable, and execute it if it it.

xXe Language
Yes, forgive, I changed the name to something I think is more appropriate since xX will execute this code directly. In addition, I improved the language syntax!
[object | object reference] [@|!][message]
That's it! It's extremely simple!
Symbols include:

  • @ - Sends a message to an object.

  • ! - Sends a message to an object, but prevents the vm from attempting to execute the object.

  • {} - Used to group together a collection of objects (I think)
  • "" - Used by the vm to create String objects. (I really didn't want to do this, but had no
    choice)


Here's an example of what xXe code may look like.The infamous "Hello World!"

"Hello World" IO @stdio

The first command is "Hello World" which intructs the vm to create a String object by making a copy of String and setting its value to "Hello World". The second command is IO, which is the object used to get data in and out of xX, like files, printing to the terminal, etc, gets placed in the stack. The IO object, like the String object is loaded by default by the vm. So now we have at least two objects in the stack. The third instruction is @stdio which instructs the vm to send the stdio message to the first object on the stack, which happens to be IO. IO, like any other object responding to a message, simply pushes an object on the stack. In this case, an native executable object. When the vm realizes this, it executes the native code. And bam! We get "Hello World" on the screen!

Now, for another sample

Object @copy
"Person" xxstack @swap @define
"My Name" "name" Person @define
Person @name IO @stdio

Can you guess what the code above does?
  1. Make a (shallow) copy of Object, the grandfather of all prototypes. It actually performs the copy operation!
  2. Create a string with value "Person", swap the two newest stack entries leaving the new object first, and send the define message. This grabs the first object on the stack (our copy of Object), uses the second object as a key (the string "name"), and the third object as the value (string "Person"), and create a new slot.
  3. Sends the "name" message to our newly-define object, Person. And then prints its value "My Name" on the screen.

Sunday, June 11, 2006

Message Passing Works!
Ok, so it's not complete yet. But I'm able to register a message handler (think callback function) with an object, and send the object a message what will use the handler. Below is a sample output of the test program.

$ ./test_xxobject
Starting xxobject test...
Sending 'getDescription' message to object...
Message accepted! Object description: xX object prototype.

And now for part of the source code (I need to figure out how to insert C source code properly into HTML)

int main()
{
xxObject *obj1;
const char *desc;

printf("Starting xxobject test...\n");
obj1 = xxObject_New();
printf("Sending 'getDescription' message to object...\n");
desc = (const char*)xxObject_SendMessage(obj1, "getDescription");
if(desc != NULL)
{
printf("Message accepted! Object description: %s\n", desc);
}
else
{
printf("Message rejected! Unsupported by object.\n");
}

return 0;
}

The problem is that so far, I could only insert functions into the object slots (implemented as two lists) because I don't have a way to distiguish which objects in the slots are callable functions and which are not. That's what I get for trying to implement a typeless system. Currently, in a lot of places I shouldn't. That, and I have yet to implement a dictionary object. I need one real bad! What if I add an 'isCallable' flag and a 'payload' void pointer to each of the objects in the slots. Then, I could use the flag to check if the payload is a pointer to a function, and if so, call it. If not, ... return the object? But that would identify an object as belonging to a particular type! I know I need to have some types. I need to think some more.

Saturday, June 10, 2006

More on the Implementation of xX

Prototype-Based Programming
I was thinking about how to implement objects in the VM and standard library, and I was completely focused on traditional class-based objects. But then, I remembered how it was like to use objects in JavaScript, and as I continued my research, I came to discover prototype-based programming. This class-less form of object-oriented programing provides pseudo-inheritence by simply making copies of exsisting objects. The object a new object is copied from is considered a prototype. What I like most about this technique is that objects can be effectively developed as-you-go. This will help a great deal when developing the standard library because I won't have to commit to an object hiarchy. Inheritance with prototypes is loose. This would essenstially make xX type-less! WHOO!

Objects
With prototypes, objects usually have something called slots. Slots are basically the members of an object. This includes both data members (variables) and methods (functions). So, I'm thinking about supporting this with xX objects. Or, something like it. An xX object struct would look something like this:

typedef struct xxObject_t
{
xxDictionary *slots;
} xxObject;

This is similar to how Python objects have the dictionary obj.__dict__ which holds basically everything the object has. I think this will aid to implement message passing.

Message Passing
Like Smalltalk, Objective-C, and some others, I would like to implement message passing to execute object functions. I think this goes great with a class-less (and somewhat type-less) system. This means, the VM knows nothing about primitive data types such as integers, strings (not always primitive), and the like. Actually, it will probably know a little about strings. This keeps the VM small, at the expense of a possible performance penalty. Such data can be off loaded into the standard library assisting with development. For example, the standard library would have a Number prototype that can be used to handle numerical operations. Most likely, such a module will have to be written in C, but it could be loaded into the VM and used to create numbers. The Number prototype will then respond to the add message. Somthing like that. Who knows. I also think message passing will help provide support for co-routines, an alternative to multi-threading.

Thursday, June 08, 2006

This make no sense! Blogger has been having issues, and for some reason, I can't set the title on postings of this particular blog! ARG!
Anyway I was thinking about the vm. Why not make it simply manipulate objects, and nothing else. By this I mean the vm will know nothing about object/data types and therefore, it won't support math and such. Instead, such operations will be stored in native-code modules that can be loaded into the vm. For example, consider what happens traditionally when adding two numbers. The numbers get pushed into the stack, and then the add operator is executed, which then pops the two numbers, adds them, and pushes the result into the stack:
5 4 add
But this means the vm contains the add operator and knows about numbers and how to add them. What if the vm is unaware of data types and only contains basic stack-manipulation operators. Since xX is object-oriented at the lowest level, it knows how to create objects. So, lets add the same two numbers:
math load 5 Number new 4 Number new add
In the code above, the math module is loaded, 5 is pushed into the stack, followed by Number, which is a class name, and followed by the new operator. The new operator creates an object using the provided class name as a template. When new is executed, it pops the stack to retrieve the class name. The class name is then looked up in the definition dictionary (think PostScript) to determine the coded needed to create the object. In this case, the code is native, so it's a pointer to a function. This function, which acts as an object constructor, is executed. In the case of the Number function, the stack is popped to retrieve the initial value for the number. The object is then created and pushed into the stack. The same process is used to create an object for the second number. When add is executed, it pops the stack to get the number object (4), and calls it's add method with the argument 5.

Anyway, that's my crazy idea. Somewhat cloudy still.

Tuesday, June 06, 2006

First Hack At It
Well, I figured the best place to start is with the stack. I've implemented a stack using a single-linked list. At first, I had trouble with it. When pushing objects into the stack, I realized I needed to get to the last node, and set its next pointer to the new node. That's not too complicated, but it is inefficient because of the need to scroll through all the nodes until the next pointer is NULL. To correct this, I resorted to keeping a pointer to the last node, and storing it in the head of the linked-list. Problem fixed? Not quite.

When poping the stack, access to the last node is quick because of the pointer in the head. But when the last node is popped, the previous node needs to become the last. Which means its next pointer needs to be NULLED, and the quick access pointer needs to modified. So, how do we get to the next-to-the-last node? Oops. Yes, you need to scroll through all the nodes! ARG! Unless, we have a quick access pointer to it too. But, do you see how ugly this can get?

A Better Way
So... how about... adding and deleteing nodes to the head of the list! I couldn't believe my tiny brain came up with this! Let me explain. Reference my ASCII diagram below (sorry, to lazy to use Inscape).
|H| --->|Na|
In the illustration above, H is the head of the list. The head contains a pointer to the first node and an int to store the length of the list. Na is a node. Pushing (adding) a node only takes 3 steps.
1. |Nb|
2. |H|--->|Na|
|Hb|-----^
3. |H|--->|Hb|--->|Ha|
First, a new node, Hb, is created. Then, the next pointer of Hb is pointed to Ha. So at this point, Ha has two pointers pointing at it, the head node H and the new node Nb. Finally, the head node is modified so that it points to the new node, Hb. And now we have an efficient method for pushing objects into the xX stack! Popping the stack is pretty easy to. But it does need a temporary pointer to the node to be deleted.

Below is part of the code.

xxstack.h
typedef struct xxStackNode_t
{
struct xxObject_t *obj;
struct xxStackNode_t *next;
} xxStackNode;

typedef struct xxStack_t
{
struct xxStackNode_t *node;
int length;
} xxStack;

xxStackNode* xxStackNode_New();
void xxStackNode_Delete(xxStackNode *node);

xxStack* xxStack_New();
int xxStack_GetLength(xxStack *stack);
int xxStack_Push(xxStack *stack, xxObject *obj);
xxObject* xxStack_Pop(xxStack *stack);


xxstack.c

xxStackNode* xxStackNode_New()
{
xxStackNode *node;
node = (xxStackNode *) malloc(sizeof(xxStackNode));
node->obj = NULL;
node->next = NULL;
return node;
}

void xxStackNode_Delete(xxStackNode *node)
{
node->obj = NULL;
node->next = NULL;
free(node);
}

/* xxStack functions */
xxStack* xxStack_New()
{
xxStack *stack;
stack = (xxStack *) malloc(sizeof(xxStack));
stack->node = NULL;
stack->length = 0;
return stack;
}

int xxStack_GetLength(xxStack *stack)
{
return stack->length;
}

int xxStack_Push(xxStack *stack, xxObject *obj)
{
xxStackNode *newNode;

newNode = xxStackNode_New();
newNode->obj = obj;

if(stack->node == NULL)
{
stack->node = newNode;
}
else
{
newNode->next = stack->node;
stack->node = newNode;
}

stack->length++;
return 0;
}

xxObject* xxStack_Pop(xxStack *stack)
{
xxObject *obj;
xxStackNode *node;

if(stack->node == NULL)
{
obj = NULL;
}
else
{
obj = stack->node->obj;
node = stack->node;

if(stack->node->next == NULL)
{
stack->node = NULL;
}
else
{
stack->node = stack->node->next;
xxStackNode_Delete(node);
}
stack->length--;
}

return obj;
}
<\pre>

PS: Sorry for the lame title. The title field in Blogger seems to have dissapeared. REALLY!