diff --git a/stix/aclocal.m4 b/stix/aclocal.m4 new file mode 100644 index 0000000..e69de29 diff --git a/stix/kernel/Context.st b/stix/kernel/Context.st index 4036644..f48ef20 100644 --- a/stix/kernel/Context.st +++ b/stix/kernel/Context.st @@ -63,21 +63,25 @@ #method value { + self primitiveFailed. } #method value: a { + self primitiveFailed. } #method value: a value: b { + self primitiveFailed. } #method value: a value: b value: c { + self primitiveFailed. } #method ifTrue: aBlock diff --git a/stix/kernel/test-005.st b/stix/kernel/test-005.st index 329ca7c..413460c 100644 --- a/stix/kernel/test-005.st +++ b/stix/kernel/test-005.st @@ -242,6 +242,12 @@ { g dump. } + + #method(#class) getABlock + { + ^ [ 'a block returned by getABlock' dump. ^ self] + } + #method(#class) main { " @@ -255,6 +261,17 @@ " + ## --------------------------------------------------------------- + ## getABlock has returned. + ## aBlock's home context is getABlock. getABlock has returned + ## when 'aBlock value' is executed. so when aBlock is really + ## executed, ^self is a double return attempt. should this be made + ## illegal?? + |aBlock| + aBlock := self getABlock. + aBlock value. + ## --------------------------------------------------------------- + " PROCESS TESTING | p | @@ -408,6 +425,23 @@ PROCESS TESTING ##self a: 1 b: 2 c: 3 d: 4 e: 5 f: 6 g: 7. ##self a: 1 b: 2 c: 3. +[1 + [100 + 200] value] value dump. + + +'====================' dump. +[ + | a b | + '--------------' dump. + [a := 20. b := [ a + 20 ]. b value.] value dump. + a dump. + b dump. +] value. +'====================' dump. +([ :a :b | "a := 20." b := [ a + 20 ]. b value.] value: 99 value: 100) dump. +'====================' dump. +[ :a :b | a dump. b dump. a := 20. b := [ a + 20 ]. b value.] value dump. ## not sufficient arguments. it must fail + + " FFI isNil dump. FFI notNil dump. @@ -416,7 +450,6 @@ PROCESS TESTING nil class dump. nil class class class dump. " - } } @@ -441,7 +474,7 @@ mc1 p1 -> bc1 is created based on mc1 (mc1 blockCopy:) bc1->source := nil. mc1 p2 -> bc2 is shallow-copied of bc1. (bc1 value) - bc2->caller := mc1. (mc1 is the active context at p2 time) + bc2->caller := mc1. (mc1 is the active context at p2 point) bc2->origin := bc1->origin. bc2->home := bc1->home. bc2->source := bc1. @@ -449,12 +482,11 @@ mc1 p2 -> bc2 is shallow-copied of bc1. (bc1 value) bc2 bc3 is created based on bc2. (bc2 blockCopy:) bc3->caller := nil bc3->origin := bc2->origin - //bc3->home := bc2. - bc3->home := bc2->source. (the active context is a block context. take from the block context's source */ + bc3->home := bc2. (the active context is a block context). bc3->source := nil. bc2 bc4 is shallow-copied of bc3. (bc3 value) - bc4->caller := bc2. (bc2 is the active context at p2 time) + bc4->caller := bc2. (bc2 is the active context at p2 point) bc4->origin := bc3->origin bc4->home := bc3->home bc4->source = bc3. diff --git a/stix/lib/comp.c b/stix/lib/comp.c index 4b3c43b..e6b9b82 100644 --- a/stix/lib/comp.c +++ b/stix/lib/comp.c @@ -2932,7 +2932,9 @@ static int store_tmpr_count_for_block (stix_t* stix, stix_oow_t tmpr_count) stix->c->mth.blk_tmprcnt = tmp; } - /* [NOTE] i don't increment blk_depth here */ + /* [NOTE] i don't increment blk_depth here. it's updated + * by the caller after this function has been called for + * a new block entered. */ stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth] = tmpr_count; return 0; } @@ -3027,23 +3029,24 @@ static int compile_block_expression (stix_t* stix) return -1; } - /* store the accumulated number of temporaries for the current block */ + /* store the accumulated number of temporaries for the current block. + * block depth is not rasised as it's not entering a new block but + * updating the temporaries count for the current block. */ if (store_tmpr_count_for_block (stix, stix->c->mth.tmpr_count) <= -1) return -1; #if defined(STIX_USE_MAKE_BLOCK) printf ("\tmake_block nargs %d ntmprs %d\n", (int)block_arg_count, (int)stix->c->mth.tmpr_count /*block_tmpr_count*/); if (emit_double_param_instruction(stix, BCODE_MAKE_BLOCK, block_arg_count, stix->c->mth.tmpr_count/*block_tmpr_count*/) <= -1) return -1; #else -printf ("\tpush_context nargs %d ntmprs %d\n", (int)block_arg_count, (int)stix->c->mth.tmpr_count /*block_tmpr_count*/); -printf ("\tpush smint %d\n", (int)block_arg_count); -printf ("\tpush smint %d\n", (int)stix->c->mth.tmpr_count /*block_tmpr_count*/); +printf ("\tpush_context\n"); +printf ("\tpush smint nargs=%d\n", (int)block_arg_count); +printf ("\tpush smint ntmprs=%d\n", (int)stix->c->mth.tmpr_count /*block_tmpr_count*/); printf ("\tsend_block_copy\n"); if (emit_byte_instruction(stix, BCODE_PUSH_CONTEXT) <= -1 || emit_push_smint_literal(stix, block_arg_count) <= -1 || emit_push_smint_literal(stix, stix->c->mth.tmpr_count/*block_tmpr_count*/) <= -1 || emit_byte_instruction(stix, BCODE_SEND_BLOCK_COPY) <= -1) return -1; #endif - printf ("\tjump\n"); /* insert dummy instructions before replacing them with a jump instruction */ @@ -3123,7 +3126,7 @@ printf ("\tfixed jump offset to %u\n", (unsigned int)jump_offset); } -static int add_to_balit_buffer (stix_t* stix, stix_oob_t b) +static int add_to_byte_array_literal_buffer (stix_t* stix, stix_oob_t b) { if (stix->c->mth.balit_count >= stix->c->mth.balit_capa) { @@ -3138,11 +3141,12 @@ static int add_to_balit_buffer (stix_t* stix, stix_oob_t b) stix->c->mth.balit = tmp; } +/* TODO: overflow check of stix->c->mth.balit_count itself */ stix->c->mth.balit[stix->c->mth.balit_count++] = b; return 0; } -static int add_to_arlit_buffer (stix_t* stix, stix_oop_t item) +static int add_to_array_literal_buffer (stix_t* stix, stix_oop_t item) { if (stix->c->mth.arlit_count >= stix->c->mth.arlit_capa) { @@ -3190,7 +3194,7 @@ static int __read_byte_array_literal (stix_t* stix, stix_oop_t* xlit) return -1; } - if (add_to_balit_buffer(stix, tmp) <= -1) return -1; + if (add_to_byte_array_literal_buffer(stix, tmp) <= -1) return -1; GET_TOKEN (stix); } @@ -3287,7 +3291,7 @@ static int __read_array_literal (stix_t* stix, stix_oop_t* xlit) goto done; } - if (!lit || add_to_arlit_buffer(stix, lit) <= -1) return -1; + if (!lit || add_to_array_literal_buffer(stix, lit) <= -1) return -1; info.len++; GET_TOKEN (stix); @@ -3397,6 +3401,8 @@ static int compile_expression_primary (stix_t* stix, const stix_oocs_t* ident, c { stix_oow_t i; + /* if a temporary variable is accessed inside a block, + * use a special instruction to indicate it */ STIX_ASSERT (var.pos < stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth]); for (i = stix->c->mth.blk_depth; i > 0; i--) { @@ -3935,6 +3941,8 @@ printf ("\n"); { stix_oow_t i; + /* if a temporary variable is accessed inside a block, + * use a special instruction to indicate it */ STIX_ASSERT (var.pos < stix->c->mth.blk_tmprcnt[stix->c->mth.blk_depth]); for (i = stix->c->mth.blk_depth; i > 0; i--) { @@ -4883,7 +4891,7 @@ printf ("\n"); while (stix->c->tok.type == STIX_IOTOK_SYMLIT) { lit = stix_makesymbol (stix, stix->c->tok.name.ptr, stix->c->tok.name.len); - if (!lit || add_to_arlit_buffer (stix, lit) <= -1) return -1; + if (!lit || add_to_array_literal_buffer (stix, lit) <= -1) return -1; GET_TOKEN (stix); @@ -4944,7 +4952,7 @@ printf ("\n"); /* * for this definition, #pooldic MyPoolDic { #a := 10. #b := 20 }, * arlit_buffer contains (#a 10 #b 20) when the 'while' loop is over. */ - if (add_to_arlit_buffer(stix, lit) <= -1) return -1; + if (add_to_array_literal_buffer(stix, lit) <= -1) return -1; GET_TOKEN (stix); break; diff --git a/stix/lib/exec.c b/stix/lib/exec.c index cf04396..70e2ccb 100644 --- a/stix/lib/exec.c +++ b/stix/lib/exec.c @@ -297,7 +297,7 @@ static STIX_INLINE int activate_new_method (stix_t* stix, stix_oop_method_t mth) ctx->sender = (stix_oop_t)stix->active_context; ctx->ip = STIX_SMOOI_TO_OOP(0); - /* the stack front has temporary variables including arguments. + /* the front part of a stack has temporary variables including arguments. * * New Context * @@ -919,6 +919,7 @@ static int __block_value (stix_t* stix, stix_ooi_t nargs, stix_ooi_t num_first_a org_blkctx = (stix_oop_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs); if (STIX_CLASSOF(stix, org_blkctx) != stix->_block_context) { + /* the receiver must be a block context */ #if defined(STIX_DEBUG_EXEC) printf ("PRIMITVE VALUE RECEIVER IS NOT A BLOCK CONTEXT\n"); #endif @@ -954,7 +955,7 @@ printf ("PRIM BlockContext value FAIL - NARGS MISMATCH\n"); blkctx = (stix_oop_context_t) stix_instantiate (stix, stix->_block_context, STIX_NULL, CONTEXT_STACK_SIZE); if (!blkctx) return -1; - /* getting org_blkctx again to be GC-safe for stix_instantiate() above */ + /* get org_blkctx again to be GC-safe for stix_instantiate() above */ org_blkctx = (stix_oop_context_t)ACTIVE_STACK_GET(stix, stix->sp - nargs); STIX_ASSERT (STIX_CLASSOF(stix, org_blkctx) == stix->_block_context); @@ -979,6 +980,8 @@ printf ("~~~~~~~~~~ BLOCK VALUING %p TO NEW BLOCK %p\n", org_blkctx, blkctx); /* TODO: check the stack size of a block context to see if it's large enough to hold arguments */ if (num_first_arg_elems > 0) { + /* the first argument should be an array. this function is ordered + * to pass array elements to the new block */ stix_oop_oop_t xarg; STIX_ASSERT (nargs == 1); xarg = (stix_oop_oop_t)ACTIVE_STACK_GETTOP (stix); @@ -2324,9 +2327,18 @@ printf ("BCODE = %x\n", bcode); handle_tempvar: #if defined(STIX_USE_CTXTEMPVAR) + /* when CTXTEMPVAR inststructions are used, the above + * instructions are used only for temporary access + * outside a block. i can assume that the temporary + * variable index is pointing to one of temporaries + * in the relevant method context */ ctx = stix->active_context->origin; bx = b1; + STIX_ASSERT (STIX_CLASSOF(stix, ctx) == stix->_method_context); #else + /* otherwise, the index may point to a temporaries + * declared inside a block */ + if (stix->active_context->home != stix->_nil) { /* this code assumes that the method context and @@ -2852,7 +2864,7 @@ printf ("<<>>\n"); case BCODE_RETURN_FROM_BLOCK: DBGOUT_EXEC_0 ("RETURN_FROM_BLOCK"); - STIX_ASSERT(STIX_CLASSOF(stix, stix->active_context) == stix->_block_context); + STIX_ASSERT(STIX_CLASSOF(stix, stix->active_context) == stix->_block_context); if (stix->active_context == stix->processor->active->initial_context) { @@ -2906,6 +2918,7 @@ printf ("TERMINATE A PROCESS............\n"); * the number of temporaries of a home context */ blkctx->ntmprs = STIX_SMOOI_TO_OOP(b2); + blkctx->home = (stix_oop_t)stix->active_context; blkctx->receiver_or_source = stix->_nil; /* no source */ @@ -2951,15 +2964,16 @@ printf ("TERMINATE A PROCESS............\n"); STIX_ASSERT (rctx == stix->active_context); /* [NOTE] - * blkctx->caller is left to nil. it is set to the + * blkctx->sender is left to nil. it is set to the * active context before it gets activated. see * prim_block_value(). * * blkctx->home is set here to the active context. * it's redundant to have them pushed to the stack * though it is to emulate the message sending of - * blockCopy:withNtmprs:. - * TODO: devise a new byte code to eliminate stack pushing. + * blockCopy:withNtmprs:. BCODE_MAKE_BLOCK has been + * added to replace BCODE_SEND_BLOCK_COPY and pusing + * arguments to the stack. * * blkctx->origin is set here by copying the origin * of the active context. diff --git a/stix/lib/stix-cfg.h.in b/stix/lib/stix-cfg.h.in index 4e67c02..adf5d81 100644 --- a/stix/lib/stix-cfg.h.in +++ b/stix/lib/stix-cfg.h.in @@ -15,30 +15,6 @@ /* Define to 1 if you have the `acosq' function. */ #undef HAVE_ACOSQ -/* Define to 1 if you have the `argz_add' function. */ -#undef HAVE_ARGZ_ADD - -/* Define to 1 if you have the `argz_append' function. */ -#undef HAVE_ARGZ_APPEND - -/* Define to 1 if you have the `argz_count' function. */ -#undef HAVE_ARGZ_COUNT - -/* Define to 1 if you have the `argz_create_sep' function. */ -#undef HAVE_ARGZ_CREATE_SEP - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARGZ_H - -/* Define to 1 if you have the `argz_insert' function. */ -#undef HAVE_ARGZ_INSERT - -/* Define to 1 if you have the `argz_next' function. */ -#undef HAVE_ARGZ_NEXT - -/* Define to 1 if you have the `argz_stringify' function. */ -#undef HAVE_ARGZ_STRINGIFY - /* Define to 1 if you have the `asin' function. */ #undef HAVE_ASIN @@ -93,9 +69,6 @@ /* Define to 1 if you have the `ceilq' function. */ #undef HAVE_CEILQ -/* Define to 1 if you have the `closedir' function. */ -#undef HAVE_CLOSEDIR - /* Define to 1 if you have the `connect' function. */ #undef HAVE_CONNECT @@ -129,13 +102,6 @@ /* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA -/* Define if c++ supports namespace std. */ -#undef HAVE_CXX_NAMESPACE_STD - -/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if - you don't. */ -#undef HAVE_DECL_CYGWIN_CONV_PATH - /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H @@ -149,24 +115,6 @@ /* Define to 1 if `d_fd' is a member of `DIR'. */ #undef HAVE_DIR_D_FD -/* Define if you have the GNU dld library. */ -#undef HAVE_DLD - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLD_H - -/* Define to 1 if you have the `dlerror' function. */ -#undef HAVE_DLERROR - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DL_H - -/* Define if you have the _dyld_func_lookup function. */ -#undef HAVE_DYLD - /* Define to 1 if you have the `ENGINE_cleanup' function. */ #undef HAVE_ENGINE_CLEANUP @@ -182,9 +130,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H -/* Define to 1 if the system has the type `error_t'. */ -#undef HAVE_ERROR_T - /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H @@ -308,12 +253,6 @@ /* Define to 1 if you have the `kqueue1' function. */ #undef HAVE_KQUEUE1 -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL - -/* Define if libdlloader will be built on this platform */ -#undef HAVE_LIBDLLOADER - /* Define to 1 if you have the `ltdl' library (-lltdl). */ #undef HAVE_LIBLTDL @@ -362,15 +301,9 @@ /* Define to 1 if you have the `lstat64' function. */ #undef HAVE_LSTAT64 -/* Define this if a modern libltdl is already installed */ -#undef HAVE_LTDL - /* Define to 1 if you have the `lutimes' function. */ #undef HAVE_LUTIMES -/* Define to 1 if you have the header file. */ -#undef HAVE_MACH_O_DYLD_H - /* Define to 1 if you have the `makecontext' function. */ #undef HAVE_MAKECONTEXT @@ -404,9 +337,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_H -/* Define to 1 if you have the `opendir' function. */ -#undef HAVE_OPENDIR - /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_ENGINE_H @@ -434,18 +364,12 @@ /* Define to 1 if you have the `prctl' function. */ #undef HAVE_PRCTL -/* Define if libtool can extract symbol lists from object files. */ -#undef HAVE_PRELOADED_SYMBOLS - /* Define to 1 if you have the header file. */ #undef HAVE_QUADMATH_H /* Define to 1 if you have the `quadmath_snprintf' function. */ #undef HAVE_QUADMATH_SNPRINTF -/* Define to 1 if you have the `readdir' function. */ -#undef HAVE_READDIR - /* Define to 1 if you have the `readdir64' function. */ #undef HAVE_READDIR64 @@ -485,9 +409,6 @@ /* Define to 1 if you have the `settimeofday' function. */ #undef HAVE_SETTIMEOFDAY -/* Define if you have the shl_load function. */ -#undef HAVE_SHL_LOAD - /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H @@ -557,12 +478,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strlcat' function. */ -#undef HAVE_STRLCAT - -/* Define to 1 if you have the `strlcpy' function. */ -#undef HAVE_STRLCPY - /* Define to 1 if you have the `strtoflt128' function. */ #undef HAVE_STRTOFLT128 @@ -615,9 +530,6 @@ */ #undef HAVE_SYS_DIR_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_DL_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_EPOLL_H @@ -763,9 +675,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WCTYPE_H -/* This value is set to 1 to indicate that the system argz facility works */ -#undef HAVE_WORKING_ARGZ - /* Define to 1 if you have the `_vsnprintf' function. */ #undef HAVE__VSNPRINTF @@ -787,41 +696,6 @@ /* __va_copy is available */ #undef HAVE___VA_COPY -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -#undef LTDL_DLOPEN_DEPLIBS - -/* Define to the system default library search path. */ -#undef LT_DLSEARCH_PATH - -/* The archive extension */ -#undef LT_LIBEXT - -/* The archive prefix */ -#undef LT_LIBPREFIX - -/* Define to the extension used for runtime loadable modules, say, ".so". */ -#undef LT_MODULE_EXT - -/* Define to the name of the environment variable that determines the run-time - module search path. */ -#undef LT_MODULE_PATH_VAR - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - -/* Define to the shared library suffix, say, ".dylib". */ -#undef LT_SHARED_EXT - -/* Define if dlsym() requires a leading underscore in symbol names. */ -#undef NEED_USCORE - -/* The size of `MB_LEN_MAX', as computed by valueof. */ -#undef NUMVALOF_MB_LEN_MAX - -/* Name of package */ -#undef PACKAGE - /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -1035,12 +909,6 @@ /* sizeof(__int8) */ #undef STIX_SIZEOF___INT8 -/* Define if socklen_t is signed */ -#undef STIX_SOCKLEN_T_IS_SIGNED - -/* Version number of package */ -#undef VERSION - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD @@ -1052,9 +920,3 @@ # undef WORDS_BIGENDIAN # endif #endif - -/* Define so that glibc/gnulib argp.h does not typedef error_t. */ -#undef __error_t_defined - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -#undef error_t diff --git a/stix/lib/stix.h b/stix/lib/stix.h index 777c0a8..8c9e7ec 100644 --- a/stix/lib/stix.h +++ b/stix/lib/stix.h @@ -483,40 +483,42 @@ struct stix_context_t * this context object has been activated. a new method context * is activated as a result of normal message sending and a block * context is activated when it is sent 'value'. it's set to - * nil if a block context created haven't received 'value'. */ + * nil if a block context created hasn't received 'value'. */ stix_oop_t sender; /* SmallInteger, instruction pointer */ stix_oop_t ip; /* SmallInteger, stack pointer */ - stix_oop_t sp; /* stack pointer */ + stix_oop_t sp; /* SmallInteger. Number of temporaries. * For a block context, it's inclusive of the temporaries * defined its 'home'. */ - stix_oop_t ntmprs; /* SmallInteger. */ + stix_oop_t ntmprs; /* CompiledMethod for a method context, * SmallInteger for a block context */ stix_oop_t method_or_nargs; /* it points to the receiver of the message for a method context. - * a block context created but not activated has nil in this field. - * if a block context is activated by 'value', it points to the - * block context object used as a base for shallow-copy. */ + * a block context created but not yet activated has nil in this + * field. if a block context is activated by 'value', it points + * to the block context object used as a base for shallow-copy. */ stix_oop_t receiver_or_source; /* it is set to nil for a method context. * for a block context, it points to the active context at the - * moment the block context was created. */ + * moment the block context was created. that is, it ponts to + * a method context where the block has been defined. an activated + * block context copies this field from the source. */ stix_oop_t home; /* when a method context is created, it is set to itself. * no change is made when the method context is activated. - * when a block context is created, it is set to nil. - * when the block context is shallow-copied for activation, - * it is set to the origin of the active context at that moment */ + * when a block context is created, it is set to the origin + * of the active context. when the block context is shallow-copied + * for activation, it is set to the origin of the source block contxt. */ stix_oop_context_t origin; /* variable indexed part */