added the local return byte code - BCODE_LOCAL_RETURN -> it returns to the origin of the active context
This commit is contained in:
parent
e80b2bc572
commit
6209b13410
@ -113,6 +113,9 @@ class MyObject(Object)
|
|||||||
method(#class) main
|
method(#class) main
|
||||||
{
|
{
|
||||||
|a k|
|
|a k|
|
||||||
|
|
||||||
|
|
||||||
|
'BEGINNING OF main...........' dump.
|
||||||
a :=
|
a :=
|
||||||
if ([System logNl: 'xxxx'. 'abcd' == 'bcde'. false] value)
|
if ([System logNl: 'xxxx'. 'abcd' == 'bcde'. false] value)
|
||||||
{
|
{
|
||||||
@ -145,6 +148,26 @@ class MyObject(Object)
|
|||||||
|
|
||||||
|
|
||||||
(if (false) {} else {1.} ) dump.
|
(if (false) {} else {1.} ) dump.
|
||||||
Processor sleepFor: 20.
|
|
||||||
|
'TESTING ^^....' dump.
|
||||||
|
a := 10.
|
||||||
|
([
|
||||||
|
a := a + 3.
|
||||||
|
if (a > 10) {^^99 }
|
||||||
|
] value) dump.
|
||||||
|
|
||||||
|
a := 5.
|
||||||
|
##((a < 20) ifTrue: [ 1. if (a < 20) { ^^50 }. 90. ]) dump.
|
||||||
|
([true] whileTrue: [
|
||||||
|
[
|
||||||
|
'aaa' dump.
|
||||||
|
if (a > 20) { ^^506070 }.
|
||||||
|
a := a + 1.
|
||||||
|
'bbb' dump.
|
||||||
|
] ensure: [('xxxxx' & a asString) dump].
|
||||||
|
]) dump.
|
||||||
|
|
||||||
|
'---------- END ------------' dump.
|
||||||
|
##Processor sleepFor: 20.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1432,21 +1432,18 @@ retry:
|
|||||||
case '^':
|
case '^':
|
||||||
SET_TOKEN_TYPE (moo, MOO_IOTOK_RETURN);
|
SET_TOKEN_TYPE (moo, MOO_IOTOK_RETURN);
|
||||||
ADD_TOKEN_CHAR(moo, c);
|
ADD_TOKEN_CHAR(moo, c);
|
||||||
#if 0
|
|
||||||
GET_CHAR_TO (moo, c);
|
GET_CHAR_TO (moo, c);
|
||||||
|
|
||||||
/* TODO: support explicit block return */
|
|
||||||
if (c == '^')
|
if (c == '^')
|
||||||
{
|
{
|
||||||
/* ^^ */
|
/* ^^ */
|
||||||
TOKEN_TYPE(moo) == MOO_IOTOK_BLKRET;
|
TOKEN_TYPE(moo) = MOO_IOTOK_LOCAL_RETURN;
|
||||||
ADD_TOKEN_CHAR (moo, c);
|
ADD_TOKEN_CHAR (moo, c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unget_char (moo, &moo->c->lxc);
|
unget_char (moo, &moo->c->lxc);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{': /* extension */
|
case '{': /* extension */
|
||||||
@ -4644,6 +4641,12 @@ static int compile_block_statement (moo_t* moo)
|
|||||||
if (compile_method_expression(moo, 0) <= -1) return -1;
|
if (compile_method_expression(moo, 0) <= -1) return -1;
|
||||||
return emit_byte_instruction (moo, BCODE_RETURN_STACKTOP);
|
return emit_byte_instruction (moo, BCODE_RETURN_STACKTOP);
|
||||||
}
|
}
|
||||||
|
else if (TOKEN_TYPE(moo) == MOO_IOTOK_LOCAL_RETURN)
|
||||||
|
{
|
||||||
|
GET_TOKEN (moo);
|
||||||
|
if (compile_method_expression(moo, 0) <= -1) return -1;
|
||||||
|
return emit_byte_instruction (moo, BCODE_LOCAL_RETURN);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return compile_method_expression(moo, 0);
|
return compile_method_expression(moo, 0);
|
||||||
@ -4664,6 +4667,12 @@ static int compile_method_statement (moo_t* moo)
|
|||||||
if (compile_method_expression(moo, 0) <= -1) return -1;
|
if (compile_method_expression(moo, 0) <= -1) return -1;
|
||||||
return emit_byte_instruction (moo, BCODE_RETURN_STACKTOP);
|
return emit_byte_instruction (moo, BCODE_RETURN_STACKTOP);
|
||||||
}
|
}
|
||||||
|
else if (TOKEN_TYPE(moo) == MOO_IOTOK_LOCAL_RETURN)
|
||||||
|
{
|
||||||
|
GET_TOKEN (moo);
|
||||||
|
if (compile_method_expression(moo, 0) <= -1) return -1;
|
||||||
|
return emit_byte_instruction (moo, BCODE_LOCAL_RETURN);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* TODO: optimization. if expresssion is a literal, no push and pop are required */
|
/* TODO: optimization. if expresssion is a literal, no push and pop are required */
|
||||||
|
@ -491,6 +491,10 @@ int moo_decode (moo_t* moo, moo_oop_method_t mth, const moo_oocs_t* classfqn)
|
|||||||
LOG_INST_0 (moo, "return_from_block");
|
LOG_INST_0 (moo, "return_from_block");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BCODE_LOCAL_RETURN:
|
||||||
|
LOG_INST_0 (moo, "local_return");
|
||||||
|
break;
|
||||||
|
|
||||||
case BCODE_MAKE_BLOCK:
|
case BCODE_MAKE_BLOCK:
|
||||||
/* b1 - number of block arguments
|
/* b1 - number of block arguments
|
||||||
* b2 - number of block temporaries */
|
* b2 - number of block temporaries */
|
||||||
|
@ -3887,6 +3887,9 @@ int moo_execute (moo_t* moo)
|
|||||||
{
|
{
|
||||||
/* returning from a method */
|
/* returning from a method */
|
||||||
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->active_context) == moo->_method_context);
|
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->active_context) == moo->_method_context);
|
||||||
|
|
||||||
|
/* mark that the context is dead. it will be
|
||||||
|
* save to the context object by SWITCH_ACTIVE_CONTEXT() */
|
||||||
moo->ip = -1;
|
moo->ip = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3927,13 +3930,24 @@ int moo_execute (moo_t* moo)
|
|||||||
|
|
||||||
non_local_return_ok:
|
non_local_return_ok:
|
||||||
/*MOO_DEBUG2 (moo, "NON_LOCAL RETURN OK TO... %p %p\n", moo->active_context->origin, moo->active_context->origin->sender);*/
|
/*MOO_DEBUG2 (moo, "NON_LOCAL RETURN OK TO... %p %p\n", moo->active_context->origin, moo->active_context->origin->sender);*/
|
||||||
moo->active_context->origin->ip = MOO_SMOOI_TO_OOP(-1);
|
if (bcode != BCODE_LOCAL_RETURN)
|
||||||
|
{
|
||||||
|
/* mark that the context is dead */
|
||||||
|
moo->active_context->origin->ip = MOO_SMOOI_TO_OOP(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->active_context->origin) == moo->_method_context);
|
MOO_ASSERT (moo, MOO_CLASSOF(moo, moo->active_context->origin) == moo->_method_context);
|
||||||
/* restore the stack pointer */
|
if (bcode == BCODE_LOCAL_RETURN && moo->active_context != moo->active_context->origin)
|
||||||
moo->sp = MOO_OOP_TO_SMOOI(moo->active_context->origin->sp);
|
{
|
||||||
SWITCH_ACTIVE_CONTEXT (moo, moo->active_context->origin->sender);
|
SWITCH_ACTIVE_CONTEXT (moo, moo->active_context->origin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* restore the stack pointer */
|
||||||
|
moo->sp = MOO_OOP_TO_SMOOI(moo->active_context->origin->sp);
|
||||||
|
SWITCH_ACTIVE_CONTEXT (moo, moo->active_context->origin->sender);
|
||||||
|
}
|
||||||
|
|
||||||
if (unwind_protect)
|
if (unwind_protect)
|
||||||
{
|
{
|
||||||
@ -3984,9 +3998,14 @@ int moo_execute (moo_t* moo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BCODE_LOCAL_RETURN:
|
||||||
|
LOG_INST_0 (moo, "local_return");
|
||||||
|
return_value = MOO_STACK_GETTOP(moo);
|
||||||
|
MOO_STACK_POP (moo);
|
||||||
|
goto handle_return;
|
||||||
|
|
||||||
case BCODE_RETURN_FROM_BLOCK:
|
case BCODE_RETURN_FROM_BLOCK:
|
||||||
LOG_INST_0 (moo, "return_from_block");
|
LOG_INST_0 (moo, "return_from_block");
|
||||||
|
|
||||||
@ -4129,29 +4148,22 @@ int moo_execute (moo_t* moo)
|
|||||||
blkctx->home = (moo_oop_t)rctx;
|
blkctx->home = (moo_oop_t)rctx;
|
||||||
blkctx->receiver_or_source = moo->_nil;
|
blkctx->receiver_or_source = moo->_nil;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (rctx->home == moo->_nil)
|
|
||||||
{
|
|
||||||
/* the context that receives the blockCopy message is a method context */
|
|
||||||
MOO_ASSERT (moo, MOO_CLASSOF(moo, rctx) == moo->_method_context);
|
|
||||||
MOO_ASSERT (moo, rctx == (moo_oop_t)moo->active_context);
|
|
||||||
blkctx->origin = (moo_oop_context_t)rctx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* a block context is active */
|
|
||||||
MOO_ASSERT (moo, MOO_CLASSOF(moo, rctx) == moo->_block_context);
|
|
||||||
blkctx->origin = ((moo_oop_block_context_t)rctx)->origin;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* [NOTE]
|
/* [NOTE]
|
||||||
* the origin of a method context is set to itself
|
* the origin of a method context is set to itself
|
||||||
* when it's created. so it's safe to simply copy
|
* when it's created. so it's safe to simply copy
|
||||||
* the origin field this way.
|
* the origin field this way.
|
||||||
|
*
|
||||||
|
* if the context that receives the blockCopy message
|
||||||
|
* is a method context, the following conditions are all true.
|
||||||
|
* rctx->home == moo->_nil
|
||||||
|
* MOO_CLASSOF(moo, rctx) == moo->_method_context
|
||||||
|
* rctx == (moo_oop_t)moo->active_context
|
||||||
|
* rctx == rctx->origin
|
||||||
|
*
|
||||||
|
* if it is a block context, the following condition is true.
|
||||||
|
* MOO_CLASSOF(moo, rctx) == moo->_block_context
|
||||||
*/
|
*/
|
||||||
blkctx->origin = rctx->origin;
|
blkctx->origin = rctx->origin;
|
||||||
#endif
|
|
||||||
|
|
||||||
MOO_STACK_SETTOP (moo, (moo_oop_t)blkctx);
|
MOO_STACK_SETTOP (moo, (moo_oop_t)blkctx);
|
||||||
break;
|
break;
|
||||||
|
@ -414,12 +414,12 @@ static int write_all (int fd, const char* ptr, moo_oow_t len)
|
|||||||
if (errno == EAGAIN) continue;
|
if (errno == EAGAIN) continue;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(EAGAIN)
|
#if defined(EAGAIN)
|
||||||
if (errno == EAGAIN) continue;
|
if (errno == EAGAIN) continue;
|
||||||
#endif
|
#endif
|
||||||
#if defined(EWOULDBLOCK)
|
#if defined(EWOULDBLOCK)
|
||||||
if (errno == EWOULDBLOCK) continue;
|
if (errno == EWOULDBLOCK) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
@ -456,15 +456,20 @@ if (mask & MOO_LOG_GC) return; /* don't show gc logs */
|
|||||||
#if defined(__DOS__)
|
#if defined(__DOS__)
|
||||||
tmp = localtime (&now);
|
tmp = localtime (&now);
|
||||||
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S ", tmp); /* no timezone info */
|
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S ", tmp); /* no timezone info */
|
||||||
|
if (tslen == 0)
|
||||||
|
{
|
||||||
|
strcpy (ts, "0000-00-00 00:00:00");
|
||||||
|
tslen = 19;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
tmp = localtime_r (&now, &tm);
|
tmp = localtime_r (&now, &tm);
|
||||||
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp);
|
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp);
|
||||||
#endif
|
|
||||||
if (tslen == 0)
|
if (tslen == 0)
|
||||||
{
|
{
|
||||||
strcpy (ts, "0000-00-00 00:00:00 +0000");
|
strcpy (ts, "0000-00-00 00:00:00 +0000");
|
||||||
tslen = 25;
|
tslen = 25;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
write_all (1, ts, tslen);
|
write_all (1, ts, tslen);
|
||||||
|
|
||||||
msgidx = 0;
|
msgidx = 0;
|
||||||
@ -582,7 +587,7 @@ static void setup_tick (void)
|
|||||||
|
|
||||||
sigemptyset (&act.sa_mask);
|
sigemptyset (&act.sa_mask);
|
||||||
act.sa_handler = arrange_process_switching;
|
act.sa_handler = arrange_process_switching;
|
||||||
act.sa_flags = 0;
|
act.sa_flags = SA_RESTART;
|
||||||
sigaction (SIGVTALRM, &act, MOO_NULL);
|
sigaction (SIGVTALRM, &act, MOO_NULL);
|
||||||
|
|
||||||
itv.it_interval.tv_sec = 0;
|
itv.it_interval.tv_sec = 0;
|
||||||
|
@ -315,7 +315,8 @@ struct moo_iotok_t
|
|||||||
MOO_IOTOK_KEYWORD,
|
MOO_IOTOK_KEYWORD,
|
||||||
MOO_IOTOK_ASSIGN,
|
MOO_IOTOK_ASSIGN,
|
||||||
MOO_IOTOK_COLON,
|
MOO_IOTOK_COLON,
|
||||||
MOO_IOTOK_RETURN,
|
MOO_IOTOK_RETURN, /* ^ */
|
||||||
|
MOO_IOTOK_LOCAL_RETURN, /* ^^ */
|
||||||
MOO_IOTOK_LBRACE,
|
MOO_IOTOK_LBRACE,
|
||||||
MOO_IOTOK_RBRACE,
|
MOO_IOTOK_RBRACE,
|
||||||
MOO_IOTOK_LBRACK,
|
MOO_IOTOK_LBRACK,
|
||||||
@ -813,11 +814,12 @@ enum moo_bcode_t
|
|||||||
|
|
||||||
/* -------------------------------------- */
|
/* -------------------------------------- */
|
||||||
|
|
||||||
BCODE_DUP_STACKTOP = 0xF8,
|
BCODE_DUP_STACKTOP = 0xF7,
|
||||||
BCODE_POP_STACKTOP = 0xF9,
|
BCODE_POP_STACKTOP = 0xF8,
|
||||||
BCODE_RETURN_STACKTOP = 0xFA, /* ^something */
|
BCODE_RETURN_STACKTOP = 0xF9, /* ^something */
|
||||||
BCODE_RETURN_RECEIVER = 0xFB, /* ^self */
|
BCODE_RETURN_RECEIVER = 0xFA, /* ^self */
|
||||||
BCODE_RETURN_FROM_BLOCK = 0xFC, /* return the stack top from a block */
|
BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */
|
||||||
|
BCODE_LOCAL_RETURN = 0xFC,
|
||||||
BCODE_MAKE_BLOCK = 0xFD,
|
BCODE_MAKE_BLOCK = 0xFD,
|
||||||
BCODE_SEND_BLOCK_COPY = 0xFE,
|
BCODE_SEND_BLOCK_COPY = 0xFE,
|
||||||
BCODE_NOOP = 0xFF
|
BCODE_NOOP = 0xFF
|
||||||
|
Loading…
Reference in New Issue
Block a user