From 6209b1341004f7fd773eb57c6a7fea19d987f426 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sun, 22 Jan 2017 18:01:26 +0000 Subject: [PATCH] added the local return byte code - BCODE_LOCAL_RETURN -> it returns to the origin of the active context --- moo/kernel/Mill.moo | 25 ++++++++++++++++++- moo/lib/comp.c | 17 +++++++++---- moo/lib/decode.c | 4 ++++ moo/lib/exec.c | 58 +++++++++++++++++++++++++++------------------ moo/lib/main.c | 17 ++++++++----- moo/lib/moo-prv.h | 14 ++++++----- 6 files changed, 95 insertions(+), 40 deletions(-) diff --git a/moo/kernel/Mill.moo b/moo/kernel/Mill.moo index 7b634cb..97d6220 100644 --- a/moo/kernel/Mill.moo +++ b/moo/kernel/Mill.moo @@ -113,6 +113,9 @@ class MyObject(Object) method(#class) main { |a k| + + + 'BEGINNING OF main...........' dump. a := if ([System logNl: 'xxxx'. 'abcd' == 'bcde'. false] value) { @@ -145,6 +148,26 @@ class MyObject(Object) (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. } } diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 38ae78e..f78cc47 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -1432,21 +1432,18 @@ retry: case '^': SET_TOKEN_TYPE (moo, MOO_IOTOK_RETURN); ADD_TOKEN_CHAR(moo, c); -#if 0 GET_CHAR_TO (moo, c); -/* TODO: support explicit block return */ if (c == '^') { /* ^^ */ - TOKEN_TYPE(moo) == MOO_IOTOK_BLKRET; + TOKEN_TYPE(moo) = MOO_IOTOK_LOCAL_RETURN; ADD_TOKEN_CHAR (moo, c); } else { unget_char (moo, &moo->c->lxc); } -#endif break; case '{': /* extension */ @@ -4644,6 +4641,12 @@ static int compile_block_statement (moo_t* moo) if (compile_method_expression(moo, 0) <= -1) return -1; 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 { 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; 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 { /* TODO: optimization. if expresssion is a literal, no push and pop are required */ diff --git a/moo/lib/decode.c b/moo/lib/decode.c index cc8c50f..6039fac 100644 --- a/moo/lib/decode.c +++ b/moo/lib/decode.c @@ -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"); break; + case BCODE_LOCAL_RETURN: + LOG_INST_0 (moo, "local_return"); + break; + case BCODE_MAKE_BLOCK: /* b1 - number of block arguments * b2 - number of block temporaries */ diff --git a/moo/lib/exec.c b/moo/lib/exec.c index f61fa75..cbc3a46 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -3887,6 +3887,9 @@ int moo_execute (moo_t* moo) { /* returning from a method */ 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; } else @@ -3927,13 +3930,24 @@ int moo_execute (moo_t* moo) 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->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); - /* 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 (bcode == BCODE_LOCAL_RETURN && moo->active_context != moo->active_context->origin) + { + 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) { @@ -3984,9 +3998,14 @@ int moo_execute (moo_t* moo) } #endif - 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: LOG_INST_0 (moo, "return_from_block"); @@ -4129,29 +4148,22 @@ int moo_execute (moo_t* moo) blkctx->home = (moo_oop_t)rctx; 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] * the origin of a method context is set to itself * 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; -#endif MOO_STACK_SETTOP (moo, (moo_oop_t)blkctx); break; diff --git a/moo/lib/main.c b/moo/lib/main.c index 4a79a7d..b0a1a9c 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -414,12 +414,12 @@ static int write_all (int fd, const char* ptr, moo_oow_t len) if (errno == EAGAIN) continue; #else - #if defined(EAGAIN) + #if defined(EAGAIN) if (errno == EAGAIN) continue; - #endif - #if defined(EWOULDBLOCK) + #endif + #if defined(EWOULDBLOCK) if (errno == EWOULDBLOCK) continue; - #endif + #endif #endif return -1; @@ -456,15 +456,20 @@ if (mask & MOO_LOG_GC) return; /* don't show gc logs */ #if defined(__DOS__) tmp = localtime (&now); 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 tmp = localtime_r (&now, &tm); tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); -#endif if (tslen == 0) { strcpy (ts, "0000-00-00 00:00:00 +0000"); tslen = 25; } +#endif write_all (1, ts, tslen); msgidx = 0; @@ -582,7 +587,7 @@ static void setup_tick (void) sigemptyset (&act.sa_mask); act.sa_handler = arrange_process_switching; - act.sa_flags = 0; + act.sa_flags = SA_RESTART; sigaction (SIGVTALRM, &act, MOO_NULL); itv.it_interval.tv_sec = 0; diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 2dc9c05..82f94fd 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -315,7 +315,8 @@ struct moo_iotok_t MOO_IOTOK_KEYWORD, MOO_IOTOK_ASSIGN, MOO_IOTOK_COLON, - MOO_IOTOK_RETURN, + MOO_IOTOK_RETURN, /* ^ */ + MOO_IOTOK_LOCAL_RETURN, /* ^^ */ MOO_IOTOK_LBRACE, MOO_IOTOK_RBRACE, MOO_IOTOK_LBRACK, @@ -813,11 +814,12 @@ enum moo_bcode_t /* -------------------------------------- */ - BCODE_DUP_STACKTOP = 0xF8, - BCODE_POP_STACKTOP = 0xF9, - BCODE_RETURN_STACKTOP = 0xFA, /* ^something */ - BCODE_RETURN_RECEIVER = 0xFB, /* ^self */ - BCODE_RETURN_FROM_BLOCK = 0xFC, /* return the stack top from a block */ + BCODE_DUP_STACKTOP = 0xF7, + BCODE_POP_STACKTOP = 0xF8, + BCODE_RETURN_STACKTOP = 0xF9, /* ^something */ + BCODE_RETURN_RECEIVER = 0xFA, /* ^self */ + BCODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ + BCODE_LOCAL_RETURN = 0xFC, BCODE_MAKE_BLOCK = 0xFD, BCODE_SEND_BLOCK_COPY = 0xFE, BCODE_NOOP = 0xFF