improved the structure of primitive handlers

This commit is contained in:
hyunghwan.chung 2015-06-14 07:15:53 +00:00
parent c052501f0c
commit 8e143685c9
2 changed files with 124 additions and 42 deletions

View File

@ -83,12 +83,13 @@ void print_ucs (const stix_ucs_t* name)
}
void dump_object (stix_t* stix, stix_oop_t oop, const char* title)
void __dump_object (stix_t* stix, stix_oop_t oop, int depth)
{
stix_oop_class_t c;
stix_ucs_t s;
int i;
printf ("%s: ", title);
for (i = 0; i < depth; i++) printf ("\t");
printf ("%p instance of ", oop);
c = (stix_oop_class_t)STIX_CLASSOF(stix, oop);
@ -96,4 +97,18 @@ void dump_object (stix_t* stix, stix_oop_t oop, const char* title)
s.len = STIX_OBJ_GET_SIZE(c->name);
print_ucs (&s);
printf ("\n");
if (STIX_OBJ_GET_FLAGS_TYPE(oop) == STIX_OBJ_TYPE_OOP)
{
for (i = 0; i < STIX_OBJ_GET_SIZE(oop); i++)
{
__dump_object (stix, ((stix_oop_oop_t)oop)->slot[i], depth + 1);
}
}
}
void dump_object (stix_t* stix, stix_oop_t oop, const char* title)
{
printf ("[%s]\n", title);
__dump_object (stix, oop, 0);
}

View File

@ -265,6 +265,8 @@ TODO: overcome this problem
return -1;
}
/* TODO: handle preamble */
/* the initial context starts the life of the entire VM
* and is not really worked on except that it is used to call the
* initial method. so it doesn't really require any extra stack space.
@ -286,20 +288,17 @@ TODO: overcome this problem
(stix)->active_context->slot[sp] = v; \
} while (0)
static int execute_primitive (stix_t* stix, int prim_no, stix_ooi_t nargs)
#define STACK_GET(stix,v_sp) ((stix)->active_context->slot[v_sp])
#define STACK_PUT(stix,v_sp,v_obj) ((stix)->active_context->slot[v_sp] = v_obj)
int primitive_dump (stix_t* stix, stix_ooi_t nargs)
{
/* a primitive handler must pop off all arguments and the receiver and
* push a return value when it's successful. otherwise, it must not touch
* the stack. */
stix_ooi_t i;
stix_ooi_t sp;
LOAD_SP (stix->active_context, sp);
switch (prim_no)
{
case 0:
{
stix_ooi_t i;
STIX_ASSERT (nargs >= 0);
LOAD_SP (stix->active_context, sp);
dump_object (stix, stix->active_context->slot[sp - nargs], "receiver");
for (i = nargs; i > 0; )
{
@ -308,24 +307,88 @@ static int execute_primitive (stix_t* stix, int prim_no, stix_ooi_t nargs)
}
sp -= nargs; /* pop off arguments */
goto success;
}
default:
/* this is hard failure */
stix->errnum = STIX_ENOIMPL;
return -1;
}
/* TODO: when it returns 1, it should pop up receiver and argumetns....
* when it returns 0, it should not touch the stack */
return 0;
success:
STORE_SP (stix->active_context, sp);
return 1;
return 1; /* success */
}
int primitive_new (stix_t* stix, stix_ooi_t nargs)
{
stix_ooi_t sp;
stix_oop_t rcv, obj;
STIX_ASSERT (nargs == 0);
LOAD_SP (stix->active_context, sp);
rcv = STACK_GET(stix, sp);
if (STIX_CLASSOF(stix, rcv) != stix->_class)
{
/* the receiver is not a class object */
return 0;
}
obj = stix_instantiate (stix, rcv, STIX_NULL, 0);
if (!obj) return -1;
/* emulate 'pop receiver' and 'push result' */
STACK_PUT (stix, sp, obj);
return 1; /* success */
}
int primitive_new_with_size (stix_t* stix, stix_ooi_t nargs)
{
stix_ooi_t sp;
stix_oop_t rcv, szoop, obj;
stix_oow_t size;
STIX_ASSERT (nargs == 1);
LOAD_SP (stix->active_context, sp);
rcv = STACK_GET(stix, sp - 1);
if (STIX_CLASSOF(stix, rcv) != stix->_class)
{
/* the receiver is not a class object */
return 0;
}
szoop = STACK_GET(stix, sp);
if (STIX_OOP_IS_SMINT(szoop))
{
size = STIX_OOP_TO_SMINT(szoop);
}
/* TODO: support LargeInteger */
else
{
/* size is not a proper numeric object */
return 0;
}
obj = stix_instantiate (stix, rcv, STIX_NULL, size);
if (!obj) return -1; /* hard failure */
sp--;
STACK_PUT (stix, sp, obj);
STORE_SP (stix->active_context, sp);
return 1; /* success */
}
typedef int (*primitive_handler_t) (stix_t* stix, stix_ooi_t nargs);
struct primitive_t
{
stix_ooi_t nargs; /* expected number of arguments */
primitive_handler_t handler;
};
typedef struct primitive_t primitive_t;
static primitive_t primitives[] =
{
{ -1, primitive_dump },
{ 0, primitive_new },
{ 1, primitive_new_with_size }
};
int stix_execute (stix_t* stix)
{
@ -448,7 +511,6 @@ TODO: handle double extension
stix_ooi_t selector_index;
stix_ooi_t preamble;
/* the next byte is the message selector index to the
* literal frame. */
selector_index = code->slot[ip++];
@ -503,17 +565,22 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
case STIX_METHOD_PREAMBLE_PRIMITIVE:
{
int n;
stix_ooi_t prim_no;
printf ("JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n");
prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1))
{
stix_pushtmp (stix, (stix_oop_t*)&newmth);
STORE_SP (stix->active_context, sp);
n = execute_primitive (stix, STIX_METHOD_GET_PREAMBLE_INDEX(preamble), b1);
n = primitives[prim_no].handler (stix, b1);
LOAD_SP (stix->active_context, sp);
stix_poptmp (stix);
if (n <= -1) goto oops;
if (n >= 1) break;
/* primitive failed. fall thru */
}
/* primitive failed. fall through */
}
default: