added more code to handle block context
This commit is contained in:
parent
af5e2a543b
commit
40c461f1f4
@ -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);
|
||||
}
|
||||
|
||||
|
123
stix/lib/exec.c
123
stix/lib/exec.c
@ -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
|
||||
@ -383,9 +410,10 @@ typedef struct primitive_t primitive_t;
|
||||
|
||||
static primitive_t primitives[] =
|
||||
{
|
||||
{ -1, primitive_dump },
|
||||
{ 0, primitive_new },
|
||||
{ 1, primitive_new_with_size }
|
||||
{ -1, primitive_dump },
|
||||
{ 0, primitive_new },
|
||||
{ 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)
|
||||
{
|
||||
mth = stix->active_context->method;
|
||||
/* 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;
|
||||
b1 = code->slot[ip++];
|
||||
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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user