improved the structure of primitive handlers
This commit is contained in:
parent
c052501f0c
commit
8e143685c9
@ -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_oop_class_t c;
|
||||||
stix_ucs_t s;
|
stix_ucs_t s;
|
||||||
|
int i;
|
||||||
|
|
||||||
printf ("%s: ", title);
|
for (i = 0; i < depth; i++) printf ("\t");
|
||||||
printf ("%p instance of ", oop);
|
printf ("%p instance of ", oop);
|
||||||
|
|
||||||
c = (stix_oop_class_t)STIX_CLASSOF(stix, 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);
|
s.len = STIX_OBJ_GET_SIZE(c->name);
|
||||||
print_ucs (&s);
|
print_ucs (&s);
|
||||||
printf ("\n");
|
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);
|
||||||
}
|
}
|
||||||
|
147
stix/lib/exec.c
147
stix/lib/exec.c
@ -265,6 +265,8 @@ TODO: overcome this problem
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: handle preamble */
|
||||||
|
|
||||||
/* the initial context starts the life of the entire VM
|
/* the initial context starts the life of the entire VM
|
||||||
* and is not really worked on except that it is used to call the
|
* 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.
|
* initial method. so it doesn't really require any extra stack space.
|
||||||
@ -286,46 +288,107 @@ TODO: overcome this problem
|
|||||||
(stix)->active_context->slot[sp] = v; \
|
(stix)->active_context->slot[sp] = v; \
|
||||||
} while (0)
|
} 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
|
stix_ooi_t i;
|
||||||
* push a return value when it's successful. otherwise, it must not touch
|
|
||||||
* the stack. */
|
|
||||||
stix_ooi_t sp;
|
stix_ooi_t sp;
|
||||||
|
|
||||||
|
STIX_ASSERT (nargs >= 0);
|
||||||
|
|
||||||
LOAD_SP (stix->active_context, sp);
|
LOAD_SP (stix->active_context, sp);
|
||||||
switch (prim_no)
|
dump_object (stix, stix->active_context->slot[sp - nargs], "receiver");
|
||||||
|
for (i = nargs; i > 0; )
|
||||||
{
|
{
|
||||||
case 0:
|
--i;
|
||||||
{
|
dump_object (stix, stix->active_context->slot[sp - i], "argument");
|
||||||
stix_ooi_t i;
|
|
||||||
|
|
||||||
dump_object (stix, stix->active_context->slot[sp - nargs], "receiver");
|
|
||||||
for (i = nargs; i > 0; )
|
|
||||||
{
|
|
||||||
--i;
|
|
||||||
dump_object (stix, stix->active_context->slot[sp - i], "argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
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....
|
sp -= nargs; /* pop off arguments */
|
||||||
* when it returns 0, it should not touch the stack */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
success:
|
|
||||||
STORE_SP (stix->active_context, sp);
|
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)
|
int stix_execute (stix_t* stix)
|
||||||
{
|
{
|
||||||
@ -448,7 +511,6 @@ TODO: handle double extension
|
|||||||
stix_ooi_t selector_index;
|
stix_ooi_t selector_index;
|
||||||
stix_ooi_t preamble;
|
stix_ooi_t preamble;
|
||||||
|
|
||||||
|
|
||||||
/* the next byte is the message selector index to the
|
/* the next byte is the message selector index to the
|
||||||
* literal frame. */
|
* literal frame. */
|
||||||
selector_index = code->slot[ip++];
|
selector_index = code->slot[ip++];
|
||||||
@ -503,17 +565,22 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
|
|||||||
case STIX_METHOD_PREAMBLE_PRIMITIVE:
|
case STIX_METHOD_PREAMBLE_PRIMITIVE:
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
stix_ooi_t prim_no;
|
||||||
|
|
||||||
printf ("JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\n");
|
prim_no = STIX_METHOD_GET_PREAMBLE_INDEX(preamble);
|
||||||
stix_pushtmp (stix, (stix_oop_t*)&newmth);
|
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
|
||||||
STORE_SP (stix->active_context, sp);
|
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1))
|
||||||
n = execute_primitive (stix, STIX_METHOD_GET_PREAMBLE_INDEX(preamble), b1);
|
{
|
||||||
LOAD_SP (stix->active_context, sp);
|
stix_pushtmp (stix, (stix_oop_t*)&newmth);
|
||||||
stix_poptmp (stix);
|
STORE_SP (stix->active_context, sp);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (n <= -1) goto oops;
|
/* primitive failed. fall through */
|
||||||
if (n >= 1) break;
|
|
||||||
/* primitive failed. fall thru */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user