added more code to handle block context

This commit is contained in:
hyunghwan.chung 2015-06-17 13:46:16 +00:00
parent af5e2a543b
commit 40c461f1f4
4 changed files with 162 additions and 42 deletions

View File

@ -1868,9 +1868,9 @@ static int compile_method_primitive (stix_t* stix)
while (ptr < end && is_digitchar(*ptr))
{
prim_no = prim_no * 10 + (*ptr - '0');
if (prim_no > 0xFFFF) /* TODO: replace 0xFFFF by a macro name */
if (prim_no > MAX_CODE_PRIMNO)
{
set_syntax_error (stix, STIX_SYNERR_PRIMITIVENO, &stix->c->tok.loc, &stix->c->tok.name);
set_syntax_error (stix, STIX_SYNERR_PRIMNO, &stix->c->tok.loc, &stix->c->tok.name);
return -1;
}
@ -2030,8 +2030,8 @@ static int compile_block_temporaries (stix_t* stix)
static int compile_block_expression (stix_t* stix)
{
stix_size_t jump_inst_pos;
stix_size_t saved_tmpr_count;
stix_size_t i, jump_inst_pos;
stix_size_t saved_tmpr_count, saved_tmprs_len;
stix_size_t block_arg_count;
stix_size_t block_code_size;
stix_ioloc_t block_loc, colon_loc;
@ -2047,6 +2047,7 @@ static int compile_block_expression (stix_t* stix)
block_loc = stix->c->tok.loc;
GET_TOKEN (stix);
saved_tmprs_len = stix->c->mth.tmprs.len;
saved_tmpr_count = stix->c->mth.tmpr_count;
if (stix->c->tok.type == STIX_IOTOK_COLON)
@ -2073,6 +2074,7 @@ static int compile_block_expression (stix_t* stix)
}
if (add_temporary_variable(stix, &stix->c->tok.name) <= -1) return -1;
stix->c->mth.tmpr_count++;
GET_TOKEN (stix);
}
@ -2090,20 +2092,36 @@ static int compile_block_expression (stix_t* stix)
block_arg_count = stix->c->mth.tmpr_count - saved_tmpr_count;
if (block_arg_count > MAX_CODE_NBLKARGS)
{
/* while an integer object is pused to indicate the number of
* block arguments, evaluation which is done by message passing
* limits the number of arguments that can be passed. so the
* check is implemented */
set_syntax_error (stix, STIX_SYNERR_BLKARGFLOOD, &colon_loc, STIX_NULL);
return -1;
}
printf ("push_context %d\n", (int)block_arg_count);
printf ("send_block_copy\n");
if (emit_byte_instruction(stix, CODE_PUSH_CONTEXT) <= -1 ||
emit_push_smint_literal(stix, block_arg_count) <= -1 ||
emit_byte_instruction(stix, CODE_SEND_BLOCK_COPY) <= -1) return -1;
printf ("jump\n");
/* insert dummy instructions before replacing them with a jump instruction */
jump_inst_pos = stix->c->mth.code.len;
if (emit_byte_instruction(stix, 0) <= -1 ||
if (emit_byte_instruction(stix, MAKE_CODE(CMD_EXTEND_DOUBLE, CMD_JUMP)) <= -1 ||
emit_byte_instruction(stix, 0) <= -1 ||
emit_byte_instruction(stix, 0) <= -1) return -1;
/* TODO: fix this part below */
for (i = 0; i < block_arg_count; i++)
{
/* arrange to store the top of the stack to a block argument
* when evaluation of a block begins */
if (emit_positional_instruction(stix, CMD_STORE_INTO_TEMPVAR, i) <= -1) return -1;
}
/* TODO: fix this part above */
if (compile_block_temporaries(stix) <= -1 ||
compile_block_statements(stix) <= -1) return -1;
@ -2113,17 +2131,22 @@ static int compile_block_expression (stix_t* stix)
return -1;
}
block_code_size = stix->c->mth.code.len - jump_inst_pos + 3;
block_code_size = stix->c->mth.code.len - jump_inst_pos - 3; /* -3 to exclude JUMP code */
if (block_code_size > MAX_CODE_BLKCODE)
{
set_syntax_error (stix, STIX_SYNERR_BLKFLOOD, &colon_loc, STIX_NULL);
set_syntax_error (stix, STIX_SYNERR_BLKFLOOD, &block_loc, STIX_NULL);
return -1;
}
/* TODO: use CMD_EXTEND if block_code_size is <= 255 */
stix->c->mth.code.ptr[jump_inst_pos] = MAKE_CODE(CMD_EXTEND_DOUBLE, CMD_JUMP);
stix->c->mth.code.ptr[jump_inst_pos + 1] = (block_code_size & 0xFF00u) >> 8;
stix->c->mth.code.ptr[jump_inst_pos + 2] = (block_code_size & 0x00FFu);
/* TODO: use CMD_EXTEND if block_code_size is > 127 or < -128 and shift code by 1 after having eliminated 1 byte.
stix->c->mth.code.ptr[jump_inst_pos + 1] = (stix_int8_t)block_code_size & 0xFF;*/
/* note that the jump offset is a signed number */
stix->c->mth.code.ptr[jump_inst_pos + 1] = ((stix_int16_t)block_code_size) >> 8;
stix->c->mth.code.ptr[jump_inst_pos + 2] = ((stix_int16_t)block_code_size & 0xFF);
/* restore the temporary count */
stix->c->mth.tmpr_count = saved_tmpr_count;
stix->c->mth.tmprs.len = saved_tmprs_len;
GET_TOKEN (stix);
@ -2578,6 +2601,7 @@ static int compile_method_statement (stix_t* stix)
/* handle the return statement */
GET_TOKEN (stix);
if (compile_method_expression(stix, 0) <= -1) return -1;
printf ("return_stacktop\n");
return emit_byte_instruction (stix, CODE_RETURN_STACKTOP);
}
else
@ -2593,6 +2617,7 @@ static int compile_method_statement (stix_t* stix)
n = compile_method_expression(stix, 1);
if (n <= -1) return -1;
if (n == 0) printf ("return_stacktop\n");
return (n == 0)? emit_byte_instruction (stix, CODE_POP_STACKTOP): 0;
}
}
@ -2634,6 +2659,7 @@ static int compile_method_statements (stix_t* stix)
/* arrange to return the receiver if execution reached
* the end of the method without explicit return */
printf ("return_receiver\n");
return emit_byte_instruction (stix, CODE_RETURN_RECEIVER);
}

View File

@ -372,6 +372,33 @@ int primitive_new_with_size (stix_t* stix, stix_ooi_t nargs)
return 1; /* success */
}
int primitive_block_context_value (stix_t* stix, stix_ooi_t nargs)
{
stix_ooi_t sp;
stix_oop_block_context_t blkctx;
LOAD_ACTIVE_SP (stix, sp);
blkctx = (stix_oop_block_context_t)STACK_GET(stix, sp - nargs);
STIX_ASSERT (STIX_CLASSOF(stix, blkctx) == stix->_block_context);
if (STIX_OOP_TO_SMINT(blkctx->nargs) != nargs)
{
/* the number of argument doesn't match */
printf ("PRIM BlockContext value FAIL - NARGS MISMATCH\n");
return 0;
}
sp -= nargs + 1; /* pop arguments and receiver */
STORE_ACTIVE_SP (stix, sp);
blkctx->ip = blkctx->iip;
blkctx->sp = STIX_OOP_FROM_SMINT(nargs);
blkctx->caller = (stix_oop_t)stix->active_context;
stix->active_context = (stix_oop_context_t)blkctx;
return 1;
}
typedef int (*primitive_handler_t) (stix_t* stix, stix_ooi_t nargs);
struct primitive_t
@ -385,7 +412,8 @@ static primitive_t primitives[] =
{
{ -1, primitive_dump },
{ 0, primitive_new },
{ 1, primitive_new_with_size }
{ 1, primitive_new_with_size },
{ -1, primitive_block_context_value }
};
int stix_execute (stix_t* stix)
@ -395,7 +423,7 @@ int stix_execute (stix_t* stix)
stix_ooi_t ip, sp;
stix_byte_t bc, cmd;
stix_oow_t b1;
stix_ooi_t b1;
STIX_ASSERT (stix->active_context != STIX_NULL);
ip = STIX_OOP_TO_SMINT(stix->active_context->ip);
@ -411,7 +439,11 @@ int stix_execute (stix_t* stix)
*/
while (1)
{
/* TODO: improve how to access method??? */
if (stix->active_context->unused == stix->_nil)
mth = stix->active_context->method;
else
mth = ((stix_oop_block_context_t)stix->active_context)->home->method;
code = mth->code;
printf ("IP => %d ", (int)ip);
@ -422,9 +454,22 @@ printf ("IP => %d ", (int)ip);
if (cmd == CMD_EXTEND)
{
cmd = bc & 0xF;
if (cmd == CMD_JUMP || cmd == CMD_JUMP_IF_FALSE)
b1 = (stix_int8_t)code->slot[ip++];
else
b1 = code->slot[ip++];
ip++;
}
else if (cmd == CMD_EXTEND_DOUBLE)
{
cmd = bc & 0xF;
b1 = code->slot[ip++];
if (cmd == CMD_JUMP || cmd == CMD_JUMP_IF_FALSE)
b1 = (stix_int16_t)((b1 << 8) | code->slot[ip++]); /* JUMP encodes a signed offset */
else
b1 = (b1 << 8) | code->slot[ip++];
}
/* TODO: handle CMD_EXTEND_DOUBLE */
else
{
b1 = bc & 0xF;
@ -463,8 +508,10 @@ printf ("STORE_TEMPVAR %d\n", (int)b1);
/* -------------------------------------------------------- */
/* TODO: CMD_JUMP_IF_FALSE */
case CMD_JUMP:
/* TODO: */
printf ("JUMP %d\n", (int)b1);
ip += b1;
break;
/* -------------------------------------------------------- */
@ -475,7 +522,10 @@ printf ("STORE_TEMPVAR %d\n", (int)b1);
/* b1 -> variable index */
stix_ooi_t obj_index;
stix_oop_oop_t obj;
obj_index = code->slot[ip++];
if (cmd == CMD_EXTEND_DOUBLE)
obj_index = (obj_index << 8) | code->slot[ip++];
obj = (stix_oop_oop_t)mth->slot[obj_index];
printf ("PUSH OBJVAR %d %d\n", (int)b1, (int)obj_index);
@ -490,6 +540,8 @@ printf ("PUSH OBJVAR %d %d\n", (int)b1, (int)obj_index);
stix_ooi_t obj_index;
stix_oop_oop_t obj;
obj_index = code->slot[ip++];
if (cmd == CMD_EXTEND_DOUBLE)
obj_index = (obj_index << 8) | code->slot[ip++];
printf ("STORE OBJVAR %d %d\n", (int)b1, (int)obj_index);
obj = (stix_oop_oop_t)mth->slot[obj_index];
@ -503,8 +555,8 @@ printf ("STORE OBJVAR %d %d\n", (int)b1, (int)obj_index);
case CMD_SEND_MESSAGE:
case CMD_SEND_MESSAGE_TO_SUPER:
{
/* TODO: tail call optimization */
/* b1 -> number of arguments
TODO: handle double extension
*/
stix_ucs_t mthname;
stix_oop_t newrcv;
@ -516,6 +568,8 @@ TODO: handle double extension
/* the next byte is the message selector index to the
* literal frame. */
selector_index = code->slot[ip++];
if (cmd == CMD_EXTEND_DOUBLE)
selector_index = (selector_index << 8) | code->slot[ip++];
/* get the selector from the literal frame */
selector = (stix_oop_char_t)mth->slot[selector_index];
@ -574,8 +628,10 @@ printf ("RETURN INSTVAR AT PREAMBLE\n");
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == b1))
{
stix_pushtmp (stix, (stix_oop_t*)&newmth);
STORE_ACTIVE_IP (stix, ip);
STORE_ACTIVE_SP (stix, sp);
n = primitives[prim_no].handler (stix, b1);
LOAD_ACTIVE_IP (stix, ip);
LOAD_ACTIVE_SP (stix, sp);
stix_poptmp (stix);
if (n <= -1) goto oops;
@ -624,14 +680,17 @@ printf ("PUSH_CONTEXT\n");
break;
case SUBCMD_PUSH_NEGONE:
printf ("PUSH_NEGONE\n");
STACK_PUSH (stix, STIX_OOP_FROM_SMINT(-1));
break;
case SUBCMD_PUSH_ZERO:
printf ("PUSH_ZERO\n");
STACK_PUSH (stix, STIX_OOP_FROM_SMINT(0));
break;
case SUBCMD_PUSH_ONE:
printf ("PUSH_SMINT\n");
STACK_PUSH (stix, STIX_OOP_FROM_SMINT(1));
break;
}
@ -664,6 +723,52 @@ printf ("RETURN_RECEIVER\n");
/*case CMD_RETURN_BLOCK_STACKTOP:*/
/* TODO: */
case SUBCMD_SEND_BLOCK_COPY:
{
printf ("SEND_BLOCK_COPY\n");
stix_ooi_t nargs;
stix_oop_t rctx;
stix_oop_block_context_t blkctx;
/* it emulates thisContext blockCopy: nargs */
STIX_ASSERT (sp >= 1);
STIX_ASSERT (STIX_CLASSOF(stix, stix->active_context->slot[sp]) == stix->_small_integer);
nargs = STIX_OOP_TO_SMINT(stix->active_context->slot[sp]);
STIX_ASSERT (nargs >= 0);
STIX_ASSERT (STIX_CLASSOF(stix, stix->active_context->slot[sp - 1]) == stix->_context);
blkctx = (stix_oop_block_context_t)stix_instantiate (stix, stix->_block_context, STIX_NULL, 255); /* TODO: proper stack size */
if (!blkctx) return -1;
--sp;
rctx = stix->active_context->slot[sp];
/* blkctx->caller is left to nil */
blkctx->ip = STIX_OOP_FROM_SMINT(ip + 3); /* skip the following JUMP */
blkctx->sp = 0;
blkctx->nargs = STIX_OOP_FROM_SMINT(nargs);
blkctx->iip = STIX_OOP_FROM_SMINT(ip + 3);
if (((stix_oop_block_context_t)rctx)->iip == stix->_nil)
{
/* the receiver context is a method context */
STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_context);
blkctx->home = stix->active_context;
}
else
{
/* block context is active */
STIX_ASSERT (STIX_CLASSOF(stix, rctx) == stix->_block_context);
blkctx->home = ((stix_oop_block_context_t)rctx)->home;
}
stix->active_context->slot[sp] = (stix_oop_t)blkctx;
break;
}
default:
stix->errnum = STIX_EINTERN;
break;

View File

@ -305,7 +305,7 @@ enum stix_synerrnum_t
STIX_SYNERR_ARGFLOOD, /* too many arguments */
STIX_SYNERR_BLKARGFLOOD, /* too many block arguments */
STIX_SYNERR_BLKFLOOD, /* too large block */
STIX_SYNERR_PRIMITIVENO /* wrong primitive number */
STIX_SYNERR_PRIMNO /* wrong primitive number */
};
typedef enum stix_synerrnum_t stix_synerrnum_t;
@ -442,10 +442,14 @@ struct stix_compiler_t
#define MAKE_CODE(x,y) (((x) << 4) | y)
#define MAX_CODE_INDEX 0xFFFFu
#define MAX_CODE_NARGS 0xFFFFu
#define MAX_CODE_NBLKARGS 0xFFFFu
#define MAX_CODE_BLKCODE 0xFFFFu
#define MAX_CODE_INDEX (0xFFFFu)
#define MAX_CODE_NARGS (0xFFFFu)
#define MAX_CODE_NBLKARGS (0xFFFFu)
#define MAX_CODE_PRIMNO (0xFFFFu)
#define MIN_CODE_JUMP (-0x8000)
#define MAX_CODE_JUMP (0x7FFF)
#define MAX_CODE_BLKCODE MAX_CODE_JUMP
enum stix_cmdcode_t
{

View File

@ -603,12 +603,12 @@ struct stix_context_t
{
STIX_OBJ_HEADER;
stix_oop_t sender;
stix_oop_t sender; /* message sending context - active context before new context activation*/
stix_oop_t ip; /* instruction pointer */
stix_oop_t sp; /* stack pointer */
stix_oop_method_t method; /* CompiledMethod */
stix_oop_t unused;
stix_oop_t receiver;
stix_oop_t receiver; /* receiver of the message. For a statement '#xxx do: #yyyy', #xxx is the receiver.*/
/* variable indexed part */
stix_oop_t slot[1]; /* stack contents */
@ -632,21 +632,6 @@ struct stix_block_context_t
stix_oop_t slot[1]; /* stack */
};
#if 0
#define STIX_PROCESS_NAMED_INSTVARS 4
typedef struct stix_process_t stix_process_t;
typedef struct stix_process_t* stix_oop_process_t;
struct stix_process_t
{
STIX_OBJ_HEADER;
stix_oop_context_t context;
stix_oop_t state; /* SmallInteger */
stix_oop_process_t prev;
stix_oop_process_t next;
};
#endif
/**
* The STIX_CLASSOF() macro return the class of an object including a numeric
* object encoded into a pointer.