Refactor all object-realated manipulation to module object.
authorIlari Liusvaara <[email protected]>
Fri, 17 Aug 2007 21:03:52 +0000 (18 00:03 +0300)
committerIlari Liusvaara <[email protected]>
Fri, 17 Aug 2007 21:03:52 +0000 (18 00:03 +0300)
Makefile
capfuck.c
class.c
object.c [new file with mode: 0644]
object.h [new file with mode: 0644]
types.h

index e2f9506..2cb9b8b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,2 @@
-capfuck: capfuck.c sane-ctype.c class.c
+capfuck: capfuck.c sane-ctype.c class.c object.c
        gcc -Wall -o $@ -g -std=c99 $^
index 7917aa0..1f2e9ac 100644 (file)
--- a/capfuck.c
+++ b/capfuck.c
@@ -271,8 +271,7 @@ static unsigned prepare_context(struct context* ctx)
 
        /* Find suitable message. */
        ctx->c_message = ctx->c_vat->v_msgq_head;
-       while(ctx->c_message && ctx->c_message->m_target->o_flags == 
-                       OF_EXECUTING)
+       while(ctx->c_message && object_is_executing(ctx->c_message->m_target))
                ctx->c_message = ctx->c_message->m_next;
        if(!ctx->c_message) 
                return 0;
@@ -290,7 +289,7 @@ static unsigned prepare_context(struct context* ctx)
        ctx->c_message->m_next = NULL;
        
        /* Mark object as being executed. */
-       ctx->c_message->m_target->o_flags |= OF_EXECUTING;
+       object_set_executing(ctx->c_message->m_target);
 
        /* Set fields. */
        ctx->c_stacktop = NULL;
@@ -312,7 +311,7 @@ static void unprepare_context(struct context* ctx)
        mutex_lock(&ctx->c_vat->v_msgq_lock);
        mutex_lock(&ctx->c_lock);
 
-       ctx->c_message->m_target->o_flags &= ~OF_EXECUTING;
+       object_clear_executing(ctx->c_message->m_target);
 
        /* Kill the message. It is now handled. */
        free(ctx->c_message);
@@ -337,9 +336,7 @@ static void singlestep_context(struct context* ctx, struct message* msg,
        struct object* tmp2;
        struct stack* tmp3;
        struct message* tmp4;
-       struct class* tmp5;
        size_t parameters;
-       size_t fields;
 
        /* Grab context lock. */
        mutex_lock(&ctx->c_lock);
@@ -377,16 +374,10 @@ static void singlestep_context(struct context* ctx, struct message* msg,
                        ctx->c_alt_flag = 1;
                break;
        case 'f':
-               tmp1 = pop_stack(ctx);
-               if(ctx->c_numreg < class_field_count(tc)) 
-                       t->o_fields[ctx->c_numreg] = tmp1;
+               object_write_field(t, ctx->c_numreg, pop_stack(ctx));
                break;
        case 'F':
-               if(ctx->c_numreg < class_field_count(tc))
-                       tmp1 = t->o_fields[ctx->c_numreg];
-               else
-                       tmp1 = NULL;
-               push_stack(ctx, tmp1);
+               push_stack(ctx, object_read_field(t, ctx->c_numreg));
                break;
        case 'l':
                tmp1 = pop_stack(ctx);
@@ -441,25 +432,8 @@ static void singlestep_context(struct context* ctx, struct message* msg,
                push_stack(ctx, t);
                break;
        case 'N':
-               fields = 0;
-               tmp5 = class_search(ctx->c_numreg);
-               if(tmp5)
-                       fields = class_field_count(tmp5);
-               tmp1 = malloc(sizeof(struct object) + fields *
-                       sizeof(struct object*));
-               if(!tmp1) {
-                       fprintf(stderr, "Out of memory!\n");
-                       exit(1);
-               }
-               tmp1->o_flags = 0;
-               tmp1->o_class = tmp5;
-               tmp1->o_special = NULL;
-               tmp1->o_prev = NULL;
-               tmp1->o_next = ctx->c_vat->v_object_list;
-               ctx->c_vat->v_object_list->o_prev = tmp1;
-               ctx->c_vat->v_object_list = tmp1;
-               for(size_t i = 0; i < fields; i++)
-                       tmp1->o_fields[i] = NULL;                       
+               tmp1 = object_create_ordinary(class_search(ctx->c_numreg));
+               objectlist_add(ctx->c_vat->v_objectlist, tmp1);
                push_stack(ctx, tmp1);
                break;
        default:
@@ -479,10 +453,9 @@ static unsigned execute_msghandler(struct context* ctx)
 
        struct message* m = ctx->c_message;
        struct object* t = m->m_target;
-       struct class* tc = t->o_class;
+       struct class* tc = object_class(t);
 
-       if(t->o_special) {
-               t->o_special(ctx, m);
+       if(object_exec_special(t, ctx, m)) {
                unprepare_context(ctx);
                return 1;
        } else if(!tc) {
@@ -536,20 +509,18 @@ static void queue_message(struct vat* vat, struct message* message)
 /*****************************************************************************/
 static void recursive_mark_live(struct object* object)
 {
+       size_t fields;
+       struct class* class = object_class(object);
+
        /* Don't recurse twice to same object. */
-       if(!object || !(object->o_flags & OF_MARKED_FOR_GC))
+       if(!object || !object_is_gcmark(object))
                return;
+       object_clear_gcmark(object);
 
-       /* Clear the gc flag. */
-       object->o_flags &= ~OF_MARKED_FOR_GC;
 
-       /* These are pretty special. */
-       if(!object->o_class)
-               return;
-
-       /* Recurse. */
-       for(size_t i = 0; i < class_field_count(object->o_class); i++)
-               recursive_mark_live(object->o_fields[i]);
+       fields = class ? class_field_count(class) : 0;
+       for(size_t i = 0; i < fields; i++)
+               recursive_mark_live(object_read_field(object, i));
 }
 
 /*****************************************************************************/
@@ -566,48 +537,12 @@ static void mark_messages_live(struct message* queue)
 /*****************************************************************************/
 static unsigned perform_gc(struct vat* vat)
 {
-       struct object* object = vat->v_object_list;
-       struct object* tmp;
-
-       while(object) {
-               object->o_flags |= OF_MARKED_FOR_GC;
-               object = object->o_next;
-       }
+       objectlist_set_gcmark_all(vat->v_objectlist);
        mark_messages_live(vat->v_msgq_head);
-
-       object = vat->v_object_list;
-       while(object) {
-               if((object->o_flags & OF_MARKED_FOR_GC) == 0) {
-                       object = object->o_next;
-                       break;
-               }
-
-               tmp = object;
-               object = object->o_next;
-               if(tmp->o_prev)
-                       tmp->o_prev->o_next = tmp->o_next;
-               if(tmp->o_next)
-                       tmp->o_next->o_prev = tmp->o_prev;
-               if(vat->v_object_list == tmp)
-                       vat->v_object_list = tmp->o_next;
-               free(tmp);
-       }
-
-       return (vat->v_object_list != NULL);
-
+       return objectlist_kill_marked(vat->v_objectlist);
 }
 
 /*****************************************************************************/
-struct object capfuck_dummy = {
-       0,                      /* No flags. */
-       NULL,                   /* No class. */
-       NULL,                   /* Handler. */
-       NULL,                   /* Prev. */
-       NULL,                   /* Next. */
-       {}
-};
-
-/*****************************************************************************/
 void capfuck_stdin_h(struct context* ctx, struct message* msg)
 {
        if(msg->m_parameter_count == 0 || !msg->m_parameters[0])
@@ -624,10 +559,11 @@ void capfuck_stdin_h(struct context* ctx, struct message* msg)
                for(unsigned i = 0; i < 9; i++)
                        message->m_parameters[i] = NULL;
        } else {
-               message->m_parameters[0] = &capfuck_dummy;
+               struct object* dummy = object_read_field(msg->m_target, 0);
+               message->m_parameters[0] = dummy;
                for(unsigned i = 0; i < 8; i++)
                        message->m_parameters[i + 1] = ((c >> (7 - i)) & 1) ?
-                               &capfuck_dummy : NULL;
+                               dummy : NULL;
        }
        queue_message(ctx->c_vat, message);
 }
@@ -695,53 +631,47 @@ int main(int argc, char** argv)
                fprintf(stderr, "No classes defined.\n");
                exit(1);
        }
-       struct object* object = malloc(sizeof(struct object) + 
-               class_field_count(class) * sizeof(struct object*));
+
+       struct object* object;
+       struct object* capfuck_stdin;
+       struct object* capfuck_stdout;
+       struct object* capfuck_stderr;
+       struct object* capfuck_dummy;
+
        struct message* message = malloc(sizeof(struct message) +
                3 * sizeof(struct object*));
        struct vat* vat = malloc(sizeof(struct vat));
        struct context* context = malloc(sizeof(struct context) +
                parser.p_maxlocals * sizeof(struct object*));
-       struct object* capfuck_stdin = malloc(sizeof(struct object));
-       struct object* capfuck_stdout = malloc(sizeof(struct object));
-       struct object* capfuck_stderr = malloc(sizeof(struct object));
 
-       if(!object || !message || !vat || !context || !capfuck_stdin ||
-                       !capfuck_stdout || !capfuck_stderr) {
+       if(!message || !vat || !context) {
                fprintf(stderr, "Out of memory.\n");
                return 1;
        }
 
+       /* Create initial object complement. */
+       object = object_create_ordinary(class);
+       capfuck_dummy = object_create_special(NULL, 0);
+       capfuck_stdin = object_create_special(capfuck_stdin_h, 2);
+       capfuck_stdout = object_create_special(capfuck_stdout_h, 0);
+       capfuck_stderr = object_create_special(capfuck_stderr_h, 0);
+
+       /* Capfuck_stdin uses capfuck_dummy. Keep it from being GCd. */
+       object_write_field(capfuck_stdin, 0, capfuck_dummy);
+
        /* Initialize fields. */
-       object->o_flags = 0;
-       object->o_class = class;
-       object->o_special = NULL;
-       object->o_prev = NULL;
-       object->o_next = capfuck_stdin;
-       for(size_t i = 0; i < class_field_count(class); i++)
-               object->o_fields[i] = NULL;
-       capfuck_stdin->o_flags = 0;
-       capfuck_stdin->o_class = NULL;
-       capfuck_stdin->o_special = capfuck_stdin_h;
-       capfuck_stdin->o_prev = object;
-       capfuck_stdin->o_next = capfuck_stdout;
-       capfuck_stdout->o_flags = 0;
-       capfuck_stdout->o_class = NULL;
-       capfuck_stdout->o_special = capfuck_stdout_h;
-       capfuck_stdout->o_prev = capfuck_stdin;
-       capfuck_stdout->o_next = capfuck_stderr;
-       capfuck_stderr->o_flags = 0;
-       capfuck_stderr->o_class = NULL;
-       capfuck_stderr->o_special = capfuck_stderr_h;
-       capfuck_stderr->o_prev = capfuck_stdout;
-       capfuck_stderr->o_next = NULL;
        message->m_target = object;
        message->m_next = NULL;
        message->m_parameter_count = 3;
        message->m_parameters[0] = capfuck_stdin;
        message->m_parameters[1] = capfuck_stdout;
        message->m_parameters[2] = capfuck_stderr;
-       vat->v_object_list = object;
+       vat->v_objectlist = objectlist_create();
+       objectlist_add(vat->v_objectlist, capfuck_stdin);
+       objectlist_add(vat->v_objectlist, capfuck_stdout);
+       objectlist_add(vat->v_objectlist, capfuck_stderr);
+       objectlist_add(vat->v_objectlist, capfuck_dummy);
+       objectlist_add(vat->v_objectlist, object);
        vat->v_msgq_head = NULL;
        vat->v_msgq_tail = NULL;
        vat->v_max_locals = parser.p_maxlocals;
@@ -764,6 +694,7 @@ int main(int argc, char** argv)
        }
 
        mutex_unlock(&context->c_lock);
+       objectlist_destroy(vat->v_objectlist);
        free(vat);
        free(context);
 
diff --git a/class.c b/class.c
index cb8745f..7905b40 100644 (file)
--- a/class.c
+++ b/class.c
@@ -80,6 +80,7 @@ struct class* class_make(size_t fields, size_t locals,
        class->c_locals = locals;
        class->c_body = instructions;
        class->c_body_length = ins_len;
+       class->c_next = NULL;
        return class;
 }
 
diff --git a/object.c b/object.c
new file mode 100644 (file)
index 0000000..b741ba6
--- /dev/null
+++ b/object.c
@@ -0,0 +1,231 @@
+#include "object.h"
+#include <stdio.h>
+
+/* Object. */
+struct object
+{
+       /* Flags. */
+       unsigned o_flags;
+       /* Class of object. */
+       struct class* o_class;
+       /* Special receiver. */
+       void (*o_special)(struct context* ctx, struct message* msg);
+       /* Fields. */
+       struct object* o_fields[0];
+};
+
+
+/* Object list node. */
+struct objectlist_node
+{
+       /* Object pointed. */
+       struct object* oln_object;
+       /* Next node. */
+       struct objectlist_node* oln_next;
+};
+
+
+/* Object list. */
+struct objectlist
+{
+       /* Root of list. */
+       struct objectlist_node* ol_first;
+};
+
+
+/*****************************************************************************/
+struct object* object_read_field(struct object* object, size_t slot)
+{
+       if(slot < class_field_count(object->o_class))
+               return object->o_fields[slot];
+       else
+               return NULL;
+}
+
+/*****************************************************************************/
+void object_write_field(struct object* object, size_t slot, 
+       struct object* towrite)
+{
+       if(slot < class_field_count(object->o_class))
+               object->o_fields[slot] = towrite;
+}
+
+/*****************************************************************************/
+unsigned object_is_executing(struct object* object)
+{
+       return ((object->o_flags & OF_EXECUTING) ? 1 : 0);
+}
+
+/*****************************************************************************/
+void object_set_executing(struct object* object)
+{
+       object->o_flags |= OF_EXECUTING;
+}
+
+/*****************************************************************************/
+void object_clear_executing(struct object* object)
+{
+       object->o_flags &= ~OF_EXECUTING;
+}
+
+/*****************************************************************************/
+void object_set_gcmark(struct object* object)
+{
+       object->o_flags |= OF_MARKED_FOR_GC;
+}
+
+/*****************************************************************************/
+void object_clear_gcmark(struct object* object)
+{
+       object->o_flags &= ~OF_MARKED_FOR_GC;
+}
+
+/*****************************************************************************/
+unsigned object_is_gcmark(struct object* object)
+{
+       return ((object->o_flags & OF_MARKED_FOR_GC) ? 1 : 0);
+}
+
+
+
+/*****************************************************************************/
+struct objectlist* objectlist_create()
+{
+       struct objectlist* objectlist;
+       objectlist = malloc(sizeof(struct objectlist*));
+       if(!objectlist) {
+               fprintf(stderr, "Out of memory!\n");
+               exit(1);
+       }
+       objectlist->ol_first = NULL;
+       return objectlist;
+}
+
+/*****************************************************************************/
+void objectlist_destroy(struct objectlist* objectlist)
+{
+       while(objectlist->ol_first) {
+               struct objectlist_node* tmp = objectlist->ol_first;
+               objectlist->ol_first = tmp->oln_next;
+               free(tmp->oln_object);
+               free(tmp);
+       }
+       free(objectlist);
+}
+
+/*****************************************************************************/
+void objectlist_add(struct objectlist* objectlist, struct object* object)
+{
+       struct objectlist_node* node;
+       node = malloc(sizeof(struct objectlist_node));
+       if(!node) {
+               fprintf(stderr, "Out of memory!\n");
+               exit(1);
+       }
+       node->oln_object = object;
+       node->oln_next = objectlist->ol_first;
+       objectlist->ol_first = node;
+}
+
+/*****************************************************************************/
+unsigned objectlist_kill_marked(struct objectlist* objectlist)
+{
+       struct objectlist_node* tmp = objectlist->ol_first;
+       struct objectlist_node* tmp2;
+       while(tmp && tmp->oln_object->o_flags & OF_MARKED_FOR_GC)
+       {
+               objectlist->ol_first = tmp->oln_next;
+               free(tmp->oln_object);
+               free(tmp);
+               tmp = objectlist->ol_first;
+       }
+       if(!objectlist->ol_first)
+               return 0;
+
+       tmp = objectlist->ol_first;
+       while(tmp->oln_next) {
+               if(tmp->oln_next->oln_object->o_flags & OF_MARKED_FOR_GC) {
+                       tmp2 = tmp->oln_next;
+                       tmp->oln_next = tmp2->oln_next;
+                       free(tmp2->oln_object);
+                       free(tmp2);
+               }
+               tmp = tmp->oln_next;
+       }
+       return 1;
+}
+
+/*****************************************************************************/
+void objectlist_set_gcmark_all(struct objectlist* objectlist)
+{
+       struct objectlist_node* tmp = objectlist->ol_first;
+       while(tmp) {
+               object_set_gcmark(tmp->oln_object);
+               tmp = tmp->oln_next;
+       }
+}
+
+/*****************************************************************************/
+struct object* object_create_ordinary(struct class* class)
+{
+       size_t fields;
+       struct object* object;
+       
+       fields = class ? class_field_count(class) : 0;
+       object = malloc(sizeof(struct object) + fields *
+               sizeof(struct object*));
+       if(!object) {
+               fprintf(stderr, "Out of memory!\n");
+               exit(1);
+       }
+       object->o_flags = 0;
+       object->o_class = class;
+       object->o_special = NULL;
+       for(size_t i = 0; i < fields; i++)
+               object->o_fields[i] = NULL;                     
+       return object;
+}
+
+/*****************************************************************************/
+struct object* object_create_special(void (*handler)(struct context* ctx, 
+       struct message* msg), size_t fields)
+{
+       struct object* object;
+       struct class* class;
+       
+       object = malloc(sizeof(struct object) + fields *
+               sizeof(struct object*));
+       if(!object) {
+               fprintf(stderr, "Out of memory!\n");
+               exit(1);
+       }
+       object->o_flags = 0;
+       object->o_class = NULL;
+       object->o_special = handler;
+
+       if(fields > 0) {
+               class = class_make(fields, 0, NULL, 0);
+               class_register(class);
+               object->o_class = class;
+       }
+
+       return object;
+}
+
+/*****************************************************************************/
+struct class* object_class(struct object* object)
+{
+       return object->o_class;
+}
+
+/*****************************************************************************/
+unsigned object_exec_special(struct object* object, struct context* ctx,
+       struct message* msg)
+{
+       if(object->o_special) {
+               object->o_special(ctx, msg);
+               return 1;
+       } else
+               return 0;
+
+}
diff --git a/object.h b/object.h
new file mode 100644 (file)
index 0000000..0566efb
--- /dev/null
+++ b/object.h
@@ -0,0 +1,245 @@
+#ifndef _object__h__included__
+#define _object__h__included__
+
+#include "class.h"
+
+struct context;
+struct message;
+
+/* Object marked for garbage collection. */
+#define OF_MARKED_FOR_GC 1
+/* Already execuing message handler. */
+#define OF_EXECUTING 2
+
+/* Object. */
+struct object;
+
+/* Object list. */
+struct objectlist;
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Read object field.
+ *
+ * PARAMETERS:
+ *     object                  The object to read.
+ *     slot                    Field slot number.
+ *
+ * RETURN VALUE:
+ *     Read value, or NULL if slot is invalid.
+ *
+ *****************************************************************************/
+struct object* object_read_field(struct object* object, size_t slot);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Write object field. Writes to nonexistent slots are discarded.
+ *
+ * PARAMETERS:
+ *     object                  The object to write.
+ *     slot                    Field slot number.
+ *     towrite                 Refrence to write.
+ *
+ *****************************************************************************/
+void object_write_field(struct object* object, size_t slot, 
+       struct object* towrite);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Get class of object.
+ *
+ * PARAMETERS:
+ *     object                  The object to interrogate.
+ *
+ * RETURN VALUE:
+ *     Class of object.
+ *
+ *****************************************************************************/
+struct class* object_class(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Check object EXECUTING flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to interrogate.
+ *
+ * RETURN VALUE:
+ *     1 if object is executing, 0 otherwise.
+ *
+ *****************************************************************************/
+unsigned object_is_executing(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Set object EXECUTING flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to manipulate.
+ *
+ *****************************************************************************/
+void object_set_executing(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Clear object EXECUTING flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to manipulate.
+ *
+ *****************************************************************************/
+void object_clear_executing(struct object* object);
+
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Check object MARKED_FOR_GC flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to interrogate.
+ *
+ * RETURN VALUE:
+ *     1 if object is marked for GC, 0 otherwise.
+ *
+ *****************************************************************************/
+unsigned object_is_gcmark(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Set object MARKED_FOR_GC flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to manipulate.
+ *
+ *****************************************************************************/
+void object_set_gcmark(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Clear object MARKED_FOR_GC flag.
+ *
+ * PARAMETERS:
+ *     object                  The object to manipulate.
+ *
+ *****************************************************************************/
+void object_clear_gcmark(struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Create object of specified class.
+ *
+ * PARAMETERS:
+ *     class                   The class of new object.
+ *
+ * RETURN VALUE:
+ *     The newly created object.
+ *
+ *****************************************************************************/
+struct object* object_create_ordinary(struct class* class);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Create special object.
+ *
+ * PARAMETERS:
+ *     handler                 Handler object.
+ *     fields                  Fields for local object. Note that if this
+ *                             is nonzero, new class is created and
+ *                             registered.
+ *
+ * RETURN VALUE:
+ *     The newly created object.
+ *
+ *****************************************************************************/
+struct object* object_create_special(void (*handler)(struct context* ctx, 
+       struct message* msg), size_t fields);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Create object list.
+ *
+ * RETURN VALUE:
+ *     The newly created object list.
+ *
+ *****************************************************************************/
+struct objectlist* objectlist_create();
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Destroy object list and all objects in it.
+ *
+ * PARAMETERS:
+ *     objectlist              Object list to destroy.
+ *
+ *****************************************************************************/
+void objectlist_destroy(struct objectlist* objectlist);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Add object to object list.
+ *
+ * PARAMETERS:
+ *     objectlist              Object list to add object to.
+ *     object                  Object to add.
+ *
+ *****************************************************************************/
+void objectlist_add(struct objectlist* objectlist, struct object* object);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Kill all marked objects from list.
+ *
+ * PARAMETERS:
+ *     objectlist              Object list to manipulate.
+ *
+ * RETURN VALUE:
+ *     1 if more remain, 0 if all are gone.
+ *
+ *****************************************************************************/
+unsigned objectlist_kill_marked(struct objectlist* objectlist);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Set object MARKED_FOR_GC flag for all objects in list.
+ *
+ * PARAMETERS:
+ *     objectlist              The object list to manipulate.
+ *
+ *****************************************************************************/
+void objectlist_set_gcmark_all(struct objectlist* objectlist);
+
+/******************************************************************************
+ *
+ * DESCRIPTION:
+ *     Execute special action, if any.
+ *
+ * PARAMETERS:
+ *     object                  The object.
+ *     ctx                     Context to pass in.
+ *     msg                     Message to pass in.
+ *
+ * RETURN VALUE:
+ *     1 if special action was executed, 0 if there is none.
+ *
+ *****************************************************************************/
+unsigned object_exec_special(struct object* object, struct context* ctx,
+       struct message* msg);
+
+
+#endif
diff --git a/types.h b/types.h
index 504468c..5d2d89a 100644 (file)
--- a/types.h
+++ b/types.h
@@ -2,14 +2,9 @@
 #define _types__h__included__
 
 #include "class.h"
-
-struct context;
+#include "object.h"
 struct message;
 
-/* Object marked for garbage collection. */
-#define OF_MARKED_FOR_GC 1
-/* Already execuing message handler. */
-#define OF_EXECUTING 2
 /* on line, no non-whitespace yet. */
 #define PS_INITIAL 0
 /* Last was non-whitespace. */
@@ -32,23 +27,6 @@ struct lock
 {
 };
 
-/* Object. */
-struct object
-{
-       /* Flags. */
-       unsigned o_flags;
-       /* Class of object. */
-       struct class* o_class;
-       /* Special receiver. */
-       void (*o_special)(struct context* ctx, struct message* msg);
-       /* Previous object. */
-       struct object* o_prev;
-       /* Next object. */
-       struct object* o_next;
-       /* Fields. */
-       struct object* o_fields[0];
-};
-
 /* Message. */
 struct message
 {
@@ -76,6 +54,8 @@ struct stack
 /* Vat. */
 struct vat
 {
+       /* Object list. */
+       struct objectlist* v_objectlist;
        /* Object list head. */
        struct object* v_object_list;
        /* Message queue head. */