diff --git a/ase/stx/bootstrp.c b/ase/stx/bootstrp.c index 1a7abd1e..4a5ce5b0 100644 --- a/ase/stx/bootstrp.c +++ b/ase/stx/bootstrp.c @@ -1,5 +1,5 @@ /* - * $Id: bootstrp.c,v 1.32 2005-09-11 15:15:35 bacon Exp $ + * $Id: bootstrp.c,v 1.33 2005-09-13 11:15:41 bacon Exp $ */ #include @@ -122,7 +122,7 @@ static class_info_t class_info[] = { XP_TEXT("Method"), XP_TEXT("Object"), - XP_TEXT("text selector bytecodes tmpcount"), + XP_TEXT("text selector bytecodes tmpCount argCount"), XP_NULL, XP_NULL, XP_STX_SPEC_WORD_INDEXABLE diff --git a/ase/stx/bytecode.c b/ase/stx/bytecode.c index d44049f5..56575566 100644 --- a/ase/stx/bytecode.c +++ b/ase/stx/bytecode.c @@ -1,5 +1,5 @@ /* - * $Id: bytecode.c,v 1.12 2005-09-11 17:01:56 bacon Exp $ + * $Id: bytecode.c,v 1.13 2005-09-13 11:15:41 bacon Exp $ */ #include #include @@ -79,8 +79,10 @@ static void __decode1 (xp_stx_t* stx, xp_word_t idx, void* data) literal_count = XP_STX_SIZE(stx,value) - (XP_STX_FROM_SMALLINT(method_class_obj->spec) >> XP_STX_SPEC_INDEXABLE_BITS); - xp_printf (XP_TEXT("* Literal Count: %d, Temporary Count: %d\n"), - literal_count, XP_STX_FROM_SMALLINT(method_obj->tmpcount)); + xp_printf (XP_TEXT("* Literal Count: %d, Temporary Count: %d, Argument Count: %d\n"), + literal_count, + XP_STX_FROM_SMALLINT(method_obj->tmpcount), + XP_STX_FROM_SMALLINT(method_obj->argcount)); for (i = 0; i < literal_count; i++) { xp_printf (XP_TEXT("%d. ["), i); __dump_object (stx, literals[i]); diff --git a/ase/stx/interp.c b/ase/stx/interp.c index 44c15098..54036f0a 100644 --- a/ase/stx/interp.c +++ b/ase/stx/interp.c @@ -1,113 +1,173 @@ /* - * $Id: interp.c,v 1.12 2005-09-12 15:55:13 bacon Exp $ + * $Id: interp.c,v 1.13 2005-09-13 11:15:41 bacon Exp $ */ #include #include #include #include +#include #include +#include -#define XP_STX_CONTEXT_SIZE 5 -#define XP_STX_CONTEXT_STACK 0 -#define XP_STX_CONTEXT_STACK_TOP 1 -#define XP_STX_CONTEXT_RECEIVER 2 -#define XP_STX_CONTEXT_PC 3 -#define XP_STX_CONTEXT_METHOD 4 +/* +activation record -struct xp_stx_context_t +.... +.... +.... +------------------- +previous stack_base +------------------- +method +------------------- +pc +------------------- +temporaries +------------------- +arguments +------------------- +receiver +------------------- <----- current stack_base +.... +.... +.... + + */ + +struct process_t { - xp_stx_objhdr_t header; - xp_word_t stack; - xp_word_t stack_top; - xp_word_t receiver; - xp_word_t pc; - xp_word_t method; -}; - -typedef struct xp_stx_context_t xp_stx_context_t; - -/* data structure for internal vm operation */ -struct vmcontext_t -{ - /* from context */ xp_word_t* stack; xp_word_t stack_size; + xp_word_t stack_base; xp_word_t stack_top; - xp_word_t receiver; + + xp_word_t method; xp_word_t pc; - /* from method */ + /* cached information about the method above */ + xp_word_t* literals; xp_byte_t* bytecodes; xp_word_t bytecode_size; - xp_word_t* literals; + xp_size_t argcount; + xp_size_t tmpcount; }; -typedef struct vmcontext_t vmcontext_t; +typedef struct process_t process_t; -static int __dispatch_primitive (xp_stx_t* stx, int no, vmcontext_t* vmc); +static int __dispatch_primitive (xp_stx_t* stx, process_t* proc, xp_word_t no); -xp_word_t xp_stx_new_context (xp_stx_t* stx, xp_word_t receiver, xp_word_t method) +static int __init_process (process_t* proc, xp_word_t stack_size) { - xp_word_t context; - xp_stx_context_t* ctxobj; + /* don't use the object model for process */ + proc->stack = (xp_word_t*)xp_malloc (stack_size * xp_sizeof(xp_word_t)); + if (proc->stack == XP_NULL) return -1; + + proc->stack_size = stack_size; + proc->stack_base = 0; + proc->stack_top = 0; - context = xp_stx_alloc_word_object( - stx, XP_NULL, XP_STX_CONTEXT_SIZE, XP_NULL, 0); - XP_STX_CLASS(stx,context) = stx->class_context; - - ctxobj = (xp_stx_context_t*)XP_STX_OBJECT(stx,context); - ctxobj->stack = xp_stx_new_array (stx, 512); /* TODO: initial stack size */ - ctxobj->stack_top = XP_STX_TO_SMALLINT(0); - ctxobj->receiver = receiver; - ctxobj->pc = XP_STX_TO_SMALLINT(0); - ctxobj->method = method; - - return context; + return 0; } -static int __activate_method ( - xp_stx_t* stx, vmcontext_t* vmc, xp_word_t argcount) +static void __deinit_process (process_t* proc) { - /* TODO check stack overflow... - if (vmc->stack_top >= vmc->stack_size) PANIC - */ - - //tmpcount = ... - vmc->stack_top += argcount; - while (tmpcount-- > 0) { - vmc->stack[vmc->stack_top++] = stx->nil; - } + /* TODO: */ } -int xp_stx_interp (xp_stx_t* stx, xp_word_t context) + +static int __send_to_self (xp_stx_t* stx, + process_t* proc, xp_word_t nargs, xp_word_t selector) { - xp_stx_context_t* ctxobj; + xp_word_t receiver, method; + xp_word_t i, tmpcount, argcount; xp_stx_method_t* mthobj; - vmcontext_t vmc; + + xp_assert (XP_STX_CLASS(stx,selector) == stx->class_symbol); + + receiver = proc->stack[proc->stack_top - nargs - 1]; + method = xp_stx_lookup_method (stx, + XP_STX_CLASS(stx,receiver), XP_STX_DATA(stx,selector)); + if (method == stx->nil) { +xp_printf (XP_TEXT("cannot find the method....\n")); + return -1; + } + + mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method); + + argcount = XP_STX_FROM_SMALLINT(mthobj->argcount); + tmpcount = XP_STX_FROM_SMALLINT(mthobj->tmpcount); + xp_assert (argcount == nargs); + + /* secure space for temporaries */ + for (i = 0; i < tmpcount; i++) { + proc->stack[proc->stack_top++] = stx->nil; + } + + /* 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; + + proc->stack_base = proc->stack_top - 3 - tmpcount - argcount - 1; + xp_assert (proc->stack_base > 0); + + 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, int code) +{ + xp_word_t method, pc, stack_base; + xp_stx_method_t* mthobj; + + if (proc->stack_base == 0) { + /* return from the startup method */ + return -1; + } + + 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]; + + + mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method); + xp_assert (mthobj != XP_NULL); + + proc->stack_top = proc->stack_base; + proc->stack_base = stack_base; + + 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; +} + +static int __run_process (xp_stx_t* stx, process_t* proc) +{ int code, next, next2; - ctxobj = (xp_stx_context_t*)XP_STX_OBJECT(stx,context); - mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,ctxobj->method); - - vmc.stack = XP_STX_DATA(stx,ctxobj->stack); - vmc.stack_size = XP_STX_SIZE(stx,ctxobj->stack); - /* the beginning of the stack is reserved for temporaries */ - vmc.stack_top = - XP_STX_FROM_SMALLINT(ctxobj->stack_top) + - XP_STX_FROM_SMALLINT(mthobj->tmpcount); - vmc.receiver = ctxobj->receiver; - vmc.pc = XP_STX_FROM_SMALLINT(ctxobj->pc); - - vmc.literals = mthobj->literals; - vmc.bytecodes = XP_STX_DATA(stx, mthobj->bytecodes); - vmc.bytecode_size = XP_STX_SIZE(stx, mthobj->bytecodes); - - while (vmc.pc < vmc.bytecode_size) { - code = vmc.bytecodes[vmc.pc++]; + while (proc->pc < proc->bytecode_size) { + code = proc->bytecodes[proc->pc++]; #ifdef DEBUG - xp_printf (XP_TEXT("code = 0x%x, %x\n"), code); + xp_printf (XP_TEXT("code = 0x%x\n"), code); #endif if (code >= 0x00 && code <= 0x3F) { @@ -116,14 +176,16 @@ int xp_stx_interp (xp_stx_t* stx, xp_word_t context) int index = code & 0x0F; switch (what) { +#if 0 case 0: /* receiver variable */ - vmc.stack[vmc.stack_top++] = XP_STX_WORD_AT(stx, vmc.receiver, index); + proc->stack[proc->stack_top++] = XP_STX_WORD_AT(stx, proc->receiver, index); break; case 1: /* temporary variable */ - vmc.stack[vmc.stack_top++] = vmc.stack[index]; + proc->stack[proc->stack_top++] = proc->stack[index]; break; +#endif case 2: /* literal constant */ - vmc.stack[vmc.stack_top++] = vmc.literals[index]; + proc->stack[proc->stack_top++] = proc->literals[index]; break; case 3: /* literal variable */ break; @@ -134,69 +196,123 @@ int xp_stx_interp (xp_stx_t* stx, xp_word_t context) int what = code >> 4; int index = code & 0x0F; +#if 0 switch (what) { case 4: /* receiver variable */ - XP_STX_WORD_AT(stx,vmc.receiver,index) = vmc.stack[--vmc.stack_top]; + XP_STX_WORD_AT(stx,proc->receiver,index) = proc->stack[--proc->stack_top]; break; case 5: /* temporary location */ - vmc.stack[index] = vmc.stack[--vmc.stack_top]; + proc->stack[index] = proc->stack[--proc->stack_top]; break; } +#endif } /* more here .... */ else if (code == 0x70) { - /* send to self */ - int nargs, selector; - next = vmc.bytecodes[vmc.pc++]; - - nargs = next >> 5; - - /* - selector = vmc.literals[next & 0x1F]; - receiver = vmc.stack[--vmc.stack_top]; - - xp_stx_lookup_method (stx, class of receiver, ); - */ - } + next = proc->bytecodes[proc->pc++]; +//xp_printf (XP_TEXT("%d, %d\n"), next >> 5, next & 0x1F); + __send_to_self (stx, + proc, next >> 5, proc->literals[next & 0x1F]); +//xp_printf (XP_TEXT("done %d, %d\n"), next >> 5, next & 0x1F); + } else if (code == 0x71) { /* send to super */ - int nargs, selector; - next = vmc.bytecodes[vmc.pc++]; - - nargs = next >> 5; - selector = next & 0x1F; - + next = proc->bytecodes[proc->pc++]; + //__send_to_super (stx, + // proc, next >> 5, proc->literals[next & 0x1F]); } else if (code == 0x72) { /* send to self extended */ - next = vmc.bytecodes[vmc.pc++]; - next2 = vmc.bytecodes[vmc.pc++]; + next = proc->bytecodes[proc->pc++]; + next2 = proc->bytecodes[proc->pc++]; + __send_to_self (stx, + proc, next >> 5, proc->literals[next2]); } else if (code == 0x73) { /* send to super extended */ - next = vmc.bytecodes[vmc.pc++]; - next2 = vmc.bytecodes[vmc.pc++]; + next = proc->bytecodes[proc->pc++]; + next2 = proc->bytecodes[proc->pc++]; + //__send_to_super (stx, + // proc, next >> 5, proc->literals[next2]); } /* more code .... */ + else if (code == 0x7C) { + /* return from message */ + if (__return_from_message (stx, proc, code) == -1) break; + } else if (code >= 0xF0 && code <= 0xFF) { /* primitive */ - next = vmc.bytecodes[vmc.pc++]; - __dispatch_primitive (stx, ((code & 0x0F) << 8) | next, &vmc); + next = proc->bytecodes[proc->pc++]; + __dispatch_primitive (stx, proc, ((code & 0x0F) << 8) | next); } } - return 0; + return 0; } -static int __dispatch_primitive (xp_stx_t* stx, int no, vmcontext_t* vmc) +int xp_stx_interp (xp_stx_t* stx, xp_word_t receiver, xp_word_t method) +{ + process_t proc; + xp_stx_method_t* mthobj; + xp_word_t i; + + // TODO: size of process stack. + if (__init_process(&proc, 10000) == -1) return -1; + + mthobj = (xp_stx_method_t*)XP_STX_OBJECT(stx,method); + xp_assert (mthobj != XP_NULL); + + 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); + + proc.method = method; + proc.pc = 0; + + proc.stack_base = proc.stack_top; + + /* push the receiver */ + proc.stack[proc.stack_top++] = receiver; + + /* push arguments */ + for (i = 0; i < proc.argcount; i++) { + proc.stack[proc.stack_top++] = stx->nil; + } + + /* secure space for temporaries */ + for (i = 0; i < proc.tmpcount; i++) + proc.stack[proc.stack_top++] = stx->nil; + + /* 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; + + return __run_process (stx, &proc); +} + + +static int __dispatch_primitive (xp_stx_t* stx, process_t* proc, xp_word_t no) { switch (no) { case 0: - xp_printf (XP_TEXT("Hello, STX Smalltalk\n")); + 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])); break; } diff --git a/ase/stx/interp.h b/ase/stx/interp.h index 223733d6..00a4ff1a 100644 --- a/ase/stx/interp.h +++ b/ase/stx/interp.h @@ -1,5 +1,5 @@ /* - * $Id: interp.h,v 1.5 2005-09-11 15:15:35 bacon Exp $ + * $Id: interp.h,v 1.6 2005-09-13 11:15:41 bacon Exp $ */ #ifndef _XP_STX_INTERP_H_ @@ -11,8 +11,7 @@ extern "C" { #endif -xp_word_t xp_stx_new_context (xp_stx_t* stx, xp_word_t receiver, xp_word_t method); -int xp_stx_interp (xp_stx_t* stx, xp_word_t context); +int xp_stx_interp (xp_stx_t* stx, xp_word_t receiver, xp_word_t method); #ifdef __cplusplus } diff --git a/ase/stx/method.h b/ase/stx/method.h index 747bc25f..0e6a6b3b 100644 --- a/ase/stx/method.h +++ b/ase/stx/method.h @@ -1,5 +1,5 @@ /* - * $Id: method.h,v 1.7 2005-09-11 15:15:35 bacon Exp $ + * $Id: method.h,v 1.8 2005-09-13 11:15:41 bacon Exp $ */ #ifndef _XP_STX_METHOD_H_ @@ -7,11 +7,12 @@ #include -#define XP_STX_METHOD_SIZE 4 +#define XP_STX_METHOD_SIZE 5 #define XP_STX_METHOD_TEXT 0 #define XP_STX_METHOD_SELECTOR 1 #define XP_STX_METHOD_BYTECODES 2 #define XP_STX_METHOD_TMPCOUNT 3 +#define XP_STX_METHOD_ARGCOUNT 4 /* dolphin smalltalk's flags representation @@ -32,6 +33,7 @@ struct xp_stx_method_t xp_word_t selector; /* is this necessary? */ xp_word_t bytecodes; xp_word_t tmpcount; + xp_word_t argcount; xp_word_t literals[1]; }; diff --git a/ase/stx/parser.c b/ase/stx/parser.c index 569493f3..b3d82567 100644 --- a/ase/stx/parser.c +++ b/ase/stx/parser.c @@ -1,5 +1,5 @@ /* - * $Id: parser.c,v 1.71 2005-09-13 07:07:24 bacon Exp $ + * $Id: parser.c,v 1.72 2005-09-13 11:15:41 bacon Exp $ */ #include @@ -534,7 +534,8 @@ static int __finish_method (xp_stx_parser_t* parser) /* TODO: better way to store argument count & temporary count */ method_obj->tmpcount = - XP_STX_TO_SMALLINT(parser->temporary_count); + XP_STX_TO_SMALLINT(parser->temporary_count - parser->argument_count); + method_obj->argcount = XP_STX_TO_SMALLINT(parser->argument_count); xp_stx_dict_put (stx, class_obj->methods, selector, method); return 0; @@ -1166,8 +1167,8 @@ static int __parse_keyword_message (xp_stx_parser_t* parser) xp_stx_name_close (&name); return -1; } - /*EMIT_SEND_TO_SELF (parser, 0, pos);*/ - if (__emit_send_to_self(parser,0,pos) == -1) { + /*EMIT_SEND_TO_SELF (parser, nargs, pos);*/ + if (__emit_send_to_self(parser,nargs,pos) == -1) { xp_stx_name_close (&name); return -1; } diff --git a/ase/test/stx/parser.c b/ase/test/stx/parser.c index 9de83f27..2b08ee52 100644 --- a/ase/test/stx/parser.c +++ b/ase/test/stx/parser.c @@ -159,6 +159,18 @@ int xp_main (int argc, xp_char_t* argv[]) xp_stx_parser_error_string (&parser)); } + if (xp_stx_parser_parse_method (&parser, stx.class_symbol, + (void*)XP_TEXT("test2.st")) == -1) { + xp_printf (XP_TEXT("parser error <%s>\n"), + xp_stx_parser_error_string (&parser)); + } + + if (xp_stx_parser_parse_method (&parser, stx.class_symbol, + (void*)XP_TEXT("test3.st")) == -1) { + xp_printf (XP_TEXT("parser error <%s>\n"), + xp_stx_parser_error_string (&parser)); + } + xp_printf (XP_TEXT("== Decoded Methods ==\n")); if (xp_stx_decode(&stx, n) == -1) { xp_printf (XP_TEXT("parser error <%s>\n"), @@ -171,7 +183,7 @@ int xp_main (int argc, xp_char_t* argv[]) xp_printf (XP_TEXT("cannot lookup method main\n")); } else { - xp_stx_interp (&stx, xp_stx_new_context (&stx, n, m)); + xp_stx_interp (&stx, n, m); } } diff --git a/ase/test/stx/test.st b/ase/test/stx/test.st index bc125cde..328d701a 100644 --- a/ase/test/stx/test.st +++ b/ase/test/stx/test.st @@ -2,7 +2,7 @@ main | a b | - a := 10. - #abc xxx. - b := 3. + #abc prim1. + #def prim1. + #def prim2: 4512. ^nil