qse/ase/stx/interp.c

381 lines
9.4 KiB
C
Raw Normal View History

2005-05-13 16:45:55 +00:00
/*
2005-10-02 15:45:09 +00:00
* $Id: interp.c,v 1.19 2005-10-02 15:45:09 bacon Exp $
2005-05-13 16:45:55 +00:00
*/
#include <xp/stx/interp.h>
2005-08-15 16:03:57 +00:00
#include <xp/stx/method.h>
#include <xp/stx/object.h>
#include <xp/stx/array.h>
2005-09-13 11:15:41 +00:00
#include <xp/stx/class.h>
2005-08-16 15:49:04 +00:00
#include <xp/bas/assert.h>
2005-09-13 11:15:41 +00:00
#include <xp/bas/memory.h>
2005-05-13 16:45:55 +00:00
2005-09-13 11:15:41 +00:00
/*
activation record
....
....
....
-------------------
previous stack_base
-------------------
method
-------------------
pc
-------------------
temporaries
-------------------
arguments
-------------------
receiver
------------------- <----- current stack_base
....
....
....
2005-05-15 18:37:00 +00:00
2005-09-13 11:15:41 +00:00
*/
2005-05-15 18:37:00 +00:00
2005-09-13 11:15:41 +00:00
struct process_t
2005-09-11 13:17:35 +00:00
{
xp_word_t* stack;
xp_word_t stack_size;
2005-09-13 11:15:41 +00:00
xp_word_t stack_base;
2005-09-11 13:17:35 +00:00
xp_word_t stack_top;
2005-09-13 11:15:41 +00:00
2005-09-30 12:19:00 +00:00
xp_word_t receiver;
2005-09-13 11:15:41 +00:00
xp_word_t method;
2005-09-11 13:17:35 +00:00
xp_word_t pc;
2005-09-13 11:15:41 +00:00
/* cached information about the method above */
xp_word_t* literals;
2005-09-11 13:17:35 +00:00
xp_byte_t* bytecodes;
xp_word_t bytecode_size;
2005-09-13 11:15:41 +00:00
xp_size_t argcount;
xp_size_t tmpcount;
2005-09-11 13:17:35 +00:00
};
2005-09-13 11:15:41 +00:00
typedef struct process_t process_t;
2005-09-11 13:17:35 +00:00
2005-09-13 15:56:23 +00:00
static int __run_process (xp_stx_t* stx, process_t* proc);
static int __push_to_stack (xp_stx_t* stx,
process_t* proc, xp_word_t what, xp_word_t index);
static int __store_from_stack (xp_stx_t* stx,
process_t* proc, xp_word_t what, xp_word_t index);
2005-10-02 10:44:49 +00:00
static int __send_message (xp_stx_t* stx, process_t* proc,
xp_word_t nargs, xp_word_t selector, xp_bool_t to_super);
2005-09-13 15:56:23 +00:00
static int __return_from_message (xp_stx_t* stx, process_t* proc);
2005-09-13 11:15:41 +00:00
static int __dispatch_primitive (xp_stx_t* stx, process_t* proc, xp_word_t no);
2005-09-11 13:17:35 +00:00
2005-09-13 15:56:23 +00:00
int xp_stx_interp (xp_stx_t* stx, xp_word_t receiver, xp_word_t method)
2005-09-12 15:55:13 +00:00
{
2005-09-13 15:56:23 +00:00
process_t proc;
2005-09-13 11:15:41 +00:00
xp_stx_method_t* mthobj;
2005-09-13 15:56:23 +00:00
xp_word_t i;
int n;
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
// TODO: size of process stack.
proc.stack = (xp_word_t*)xp_malloc (10000 * xp_sizeof(xp_word_t));
if (proc.stack == XP_NULL) {
xp_printf (XP_TEXT("out of memory in xp_stx_interp\n"));
return -1;
2005-09-12 15:55:13 +00:00
}
2005-09-13 15:56:23 +00:00
proc.stack_size = 10000;
proc.stack_base = 0;
proc.stack_top = 0;
2005-09-13 11:15:41 +00:00
mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method);
2005-09-13 15:56:23 +00:00
xp_assert (mthobj != XP_NULL);
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
proc.literals = mthobj->literals;
proc.bytecodes = XP_STX_DATA(stx, mthobj->bytecodes);
proc.bytecode_size = XP_STX_SIZE(stx, mthobj->bytecodes);
/* TODO: disable the method with arguments for start-up */
proc.argcount = XP_STX_FROM_SMALLINT(mthobj->argcount);
proc.tmpcount = XP_STX_FROM_SMALLINT(mthobj->tmpcount);
2005-09-13 11:15:41 +00:00
2005-09-30 12:19:00 +00:00
proc.receiver = receiver;
2005-09-13 15:56:23 +00:00
proc.method = method;
proc.pc = 0;
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
proc.stack_base = proc.stack_top;
2005-09-12 15:55:13 +00:00
2005-09-13 15:56:23 +00:00
/* push the receiver */
proc.stack[proc.stack_top++] = receiver;
2005-08-15 16:03:57 +00:00
2005-09-13 15:56:23 +00:00
/* push arguments */
for (i = 0; i < proc.argcount; i++) {
proc.stack[proc.stack_top++] = stx->nil;
2005-09-13 11:15:41 +00:00
}
2005-09-13 15:56:23 +00:00
/* secure space for temporaries */
for (i = 0; i < proc.tmpcount; i++)
proc.stack[proc.stack_top++] = stx->nil;
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
/* push dummy pc */
proc.stack[proc.stack_top++] = 0;
/* push dummy method */
proc.stack[proc.stack_top++] = stx->nil;
/* push dummy previous stack base */
proc.stack[proc.stack_top++] = 0;
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
n = __run_process (stx, &proc);
2005-09-11 13:17:35 +00:00
2005-09-13 15:56:23 +00:00
xp_free (proc.stack);
return n;
2005-09-13 11:15:41 +00:00
}
2005-08-15 16:03:57 +00:00
2005-09-13 11:15:41 +00:00
static int __run_process (xp_stx_t* stx, process_t* proc)
{
int code, next, next2;
2005-08-15 16:03:57 +00:00
2005-09-13 11:15:41 +00:00
while (proc->pc < proc->bytecode_size) {
code = proc->bytecodes[proc->pc++];
2005-08-15 16:03:57 +00:00
2005-09-11 15:43:14 +00:00
#ifdef DEBUG
2005-09-13 11:15:41 +00:00
xp_printf (XP_TEXT("code = 0x%x\n"), code);
2005-09-11 15:43:14 +00:00
#endif
2005-08-15 16:03:57 +00:00
if (code >= 0x00 && code <= 0x3F) {
/* stack - push */
2005-09-13 15:56:23 +00:00
__push_to_stack (stx, proc, code >> 4, code & 0x0F);
2005-05-13 16:45:55 +00:00
}
2005-08-15 16:03:57 +00:00
else if (code >= 0x40 && code <= 0x5F) {
/* stack - store */
int what = code >> 4;
int index = code & 0x0F;
2005-09-13 15:56:23 +00:00
__store_from_stack (stx, proc, code >> 4, code & 0x0F);
2005-09-30 12:19:00 +00:00
}
/* TODO: more here .... */
2005-08-15 16:03:57 +00:00
2005-10-02 15:45:09 +00:00
else if (code == 0x67) {
/* pop stack top */
proc->stack_top--;
}
/* TODO: more here .... */
2005-09-30 12:19:00 +00:00
else if (code == 0x6A) {
proc->stack[proc->stack_top++] = stx->nil;
}
else if (code == 0x6B) {
2005-10-01 05:33:06 +00:00
proc->stack[proc->stack_top++] = stx->true;
2005-09-30 12:19:00 +00:00
}
else if (code == 0x6C) {
2005-10-01 05:33:06 +00:00
proc->stack[proc->stack_top++] = stx->false;
2005-09-30 12:19:00 +00:00
}
else if (code == 0x6D) {
/* push receiver */
2005-10-01 05:33:06 +00:00
proc->stack[proc->stack_top++] = proc->receiver;
2005-05-13 16:45:55 +00:00
}
2005-09-11 13:17:35 +00:00
2005-09-30 12:19:00 +00:00
/* TODO: more here .... */
2005-09-11 17:01:56 +00:00
else if (code == 0x70) {
2005-10-02 10:44:49 +00:00
/* send message to self */
2005-09-13 11:15:41 +00:00
next = proc->bytecodes[proc->pc++];
2005-10-02 10:44:49 +00:00
if (__send_message (stx, proc, next >> 5,
proc->literals[next & 0x1F], xp_false) == -1) break;
2005-09-13 11:15:41 +00:00
}
2005-09-11 17:01:56 +00:00
else if (code == 0x71) {
2005-10-02 10:44:49 +00:00
/* send message to super */
2005-09-13 11:15:41 +00:00
next = proc->bytecodes[proc->pc++];
2005-10-02 10:44:49 +00:00
if (__send_message (stx, proc, next >> 5,
proc->literals[next & 0x1F], xp_true) == -1) break;
2005-09-11 17:01:56 +00:00
}
else if (code == 0x72) {
2005-10-02 10:44:49 +00:00
/* send message to self extended */
2005-09-13 11:15:41 +00:00
next = proc->bytecodes[proc->pc++];
next2 = proc->bytecodes[proc->pc++];
2005-10-02 10:44:49 +00:00
if (__send_message (stx, proc, next >> 5,
proc->literals[next2], xp_false) == -1) break;
2005-09-11 17:01:56 +00:00
}
else if (code == 0x73) {
2005-10-02 10:44:49 +00:00
/* send message to super extended */
2005-09-13 11:15:41 +00:00
next = proc->bytecodes[proc->pc++];
next2 = proc->bytecodes[proc->pc++];
2005-10-02 10:44:49 +00:00
if (__send_message (stx, proc, next >> 5,
proc->literals[next2], xp_true) == -1) break;
2005-09-11 17:01:56 +00:00
}
2005-09-11 13:17:35 +00:00
/* more code .... */
2005-10-01 05:33:06 +00:00
else if (code == 0x78) {
/* return receiver */
proc->stack[proc->stack_top++] = proc->receiver;
if (__return_from_message (stx, proc) == -1) break;
}
2005-09-13 11:15:41 +00:00
else if (code == 0x7C) {
/* return from message */
2005-09-13 15:56:23 +00:00
if (__return_from_message (stx, proc) == -1) break;
2005-09-13 11:15:41 +00:00
}
2005-09-11 13:17:35 +00:00
else if (code >= 0xF0 && code <= 0xFF) {
/* primitive */
2005-09-13 11:15:41 +00:00
next = proc->bytecodes[proc->pc++];
__dispatch_primitive (stx, proc, ((code & 0x0F) << 8) | next);
2005-09-11 13:17:35 +00:00
}
2005-10-01 05:33:06 +00:00
else {
xp_printf (XP_TEXT("INVALID OPCODE...........\n"));
break;
}
2005-08-15 16:03:57 +00:00
}
2005-05-13 16:45:55 +00:00
2005-09-13 11:15:41 +00:00
return 0;
2005-05-13 16:45:55 +00:00
}
2005-08-16 15:49:04 +00:00
2005-09-13 15:56:23 +00:00
static int __push_to_stack (xp_stx_t* stx,
process_t* proc, xp_word_t what, xp_word_t index)
2005-09-13 11:15:41 +00:00
{
2005-09-13 15:56:23 +00:00
switch (what) {
case 0: /* receiver variable */
proc->stack[proc->stack_top++] =
XP_STX_WORD_AT(stx, proc->stack[proc->stack_base], index);
break;
case 1: /* temporary variable */
proc->stack[proc->stack_top++] =
proc->stack[proc->stack_base + 1 + index];
break;
case 2: /* literal constant */
proc->stack[proc->stack_top++] = proc->literals[index];
break;
case 3: /* literal variable */
break;
}
return 0;
}
static int __store_from_stack (xp_stx_t* stx,
process_t* proc, xp_word_t what, xp_word_t index)
{
switch (what) {
case 4: /* receiver variable */
XP_STX_WORD_AT(stx,proc->stack[proc->stack_base],index) = proc->stack[--proc->stack_top];
break;
case 5: /* temporary location */
proc->stack[proc->stack_base + 1 + index] = proc->stack[--proc->stack_top];
break;
}
return 0;
}
2005-10-02 10:44:49 +00:00
static int __send_message (xp_stx_t* stx, process_t* proc,
xp_word_t nargs, xp_word_t selector, xp_bool_t to_super)
2005-09-13 15:56:23 +00:00
{
xp_word_t receiver, method;
xp_word_t i, tmpcount, argcount;
2005-09-13 11:15:41 +00:00
xp_stx_method_t* mthobj;
2005-09-13 15:56:23 +00:00
xp_assert (XP_STX_CLASS(stx,selector) == stx->class_symbol);
receiver = proc->stack[proc->stack_top - nargs - 1];
2005-10-02 15:45:09 +00:00
method = xp_stx_lookup_method (
stx, XP_STX_CLASS(stx,receiver),
XP_STX_DATA(stx,selector), to_super);
2005-09-13 15:56:23 +00:00
if (method == stx->nil) {
xp_printf (XP_TEXT("cannot find the method....\n"));
return -1;
}
2005-09-13 11:15:41 +00:00
mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method);
2005-09-13 15:56:23 +00:00
argcount = XP_STX_FROM_SMALLINT(mthobj->argcount);
tmpcount = XP_STX_FROM_SMALLINT(mthobj->tmpcount);
xp_assert (argcount == nargs);
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
/* secure space for temporaries */
for (i = 0; i < tmpcount; i++) {
proc->stack[proc->stack_top++] = stx->nil;
}
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
/* push pc */
proc->stack[proc->stack_top++] = proc->pc;
/* push method */
proc->stack[proc->stack_top++] = proc->method;
/* push previous stack base */
proc->stack[proc->stack_top++] = proc->stack_base;
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
proc->stack_base = proc->stack_top - 3 - tmpcount - argcount - 1;
xp_assert (proc->stack_base > 0);
2005-09-13 11:15:41 +00:00
2005-09-30 12:19:00 +00:00
proc->receiver = receiver;
2005-09-13 15:56:23 +00:00
proc->method = method;
proc->pc = 0;
proc->literals = mthobj->literals;
proc->bytecodes = XP_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = XP_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = argcount;
proc->tmpcount = tmpcount;
return 0;
}
static int __return_from_message (xp_stx_t* stx, process_t* proc)
{
xp_word_t method, pc, stack_base;
xp_stx_method_t* mthobj;
if (proc->stack_base == 0) {
/* return from the startup method */
return -1;
2005-09-13 11:15:41 +00:00
}
2005-09-13 15:56:23 +00:00
stack_base = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount + 2];
method = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount + 1];
pc = proc->stack[proc->stack_base + 1 + proc->tmpcount + proc->argcount];
2005-09-13 11:15:41 +00:00
2005-09-13 15:56:23 +00:00
mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method);
xp_assert (mthobj != XP_NULL);
2005-09-30 12:19:00 +00:00
/* return value is located on top of the previous stack */
proc->stack[proc->stack_base - 1] = proc->stack[proc->stack_top - 1];
/* restore the stack pointers */
2005-09-13 15:56:23 +00:00
proc->stack_top = proc->stack_base;
proc->stack_base = stack_base;
2005-09-30 12:19:00 +00:00
proc->receiver = proc->stack[stack_base];
2005-09-13 15:56:23 +00:00
proc->method = method;
proc->pc = pc;
proc->literals = mthobj->literals;
proc->bytecodes = XP_STX_DATA(stx, mthobj->bytecodes);
proc->bytecode_size = XP_STX_SIZE(stx, mthobj->bytecodes);
proc->argcount = XP_STX_FROM_SMALLINT(mthobj->argcount);
proc->tmpcount = XP_STX_FROM_SMALLINT(mthobj->tmpcount);
return 0;
2005-09-13 11:15:41 +00:00
}
static int __dispatch_primitive (xp_stx_t* stx, process_t* proc, xp_word_t no)
2005-09-11 13:17:35 +00:00
{
switch (no) {
case 0:
2005-09-13 11:15:41 +00:00
xp_printf (XP_TEXT("[[ hello stx smalltalk ]]\n"));
break;
case 1:
xp_printf (XP_TEXT("<< AMAZING STX SMALLTALK WORLD >>\n"));
break;
case 2:
xp_printf (XP_TEXT("<< FUNKY STX SMALLTALK >> %d\n"),
XP_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]));
2005-09-11 13:17:35 +00:00
break;
2005-09-13 12:10:23 +00:00
case 3:
xp_printf (XP_TEXT("<< HIGH STX SMALLTALK >> %d, %d\n"),
XP_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 1]),
XP_STX_FROM_SMALLINT(proc->stack[proc->stack_base + 2]));
break;
2005-10-02 15:45:09 +00:00
case 20:
xp_printf (XP_TEXT("<< PRIMITIVE 20 >>\n"));
break;
2005-09-11 13:17:35 +00:00
}
2005-09-13 15:56:23 +00:00
return 0;
2005-09-11 13:17:35 +00:00
}