renamed fnblk to funblk, cblk to ctlblk.
All checks were successful
continuous-integration/drone/push Build is passing

enhancing the compiler code to handle 'var' inside 'class'
This commit is contained in:
hyung-hwan 2024-10-12 00:24:02 +09:00
parent 42009d3cce
commit 17550d44c5
12 changed files with 881 additions and 235 deletions

View File

@ -529,7 +529,7 @@ static int on_fed_cnode_in_interactive_mode (hcl_t* hcl, hcl_cnode_t* obj)
{ {
/* the first expression in the current user input line. /* the first expression in the current user input line.
* arrange to clear byte-codes before compiling the expression. */ * arrange to clear byte-codes before compiling the expression. */
flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK; flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FUNBLK;
} }
if (hcl_compile(hcl, obj, flags) <= -1) if (hcl_compile(hcl, obj, flags) <= -1)

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.71]) AC_PREREQ([2.71])
AC_INIT([hcl],[0.1.0],[Chung, Hyung-Hwan (hyunghwan.chung@gmail.com)],[],[http://code.miflux.com/@hcl]) AC_INIT([hcl],[0.1.0],[Chung, Hyung-Hwan (hyunghwan.chung@gmail.com)],[],[http://code.miflux.com/hyung-hwan/hcl])
AC_CONFIG_HEADERS([lib/hcl-cfg.h]) AC_CONFIG_HEADERS([lib/hcl-cfg.h])
AC_CONFIG_AUX_DIR([ac]) AC_CONFIG_AUX_DIR([ac])

File diff suppressed because it is too large Load Diff

View File

@ -154,6 +154,7 @@ static const char* synerrstr[] =
"invalid class definition", "invalid class definition",
"invalid function definition", "invalid function definition",
"invalid variable declaration",
"elif without if", "elif without if",
"else without if", "else without if",
"catch without try", "catch without try",

View File

@ -4102,8 +4102,6 @@ static int execute (hcl_t* hcl)
#if 0 #if 0
hcl_logbfmt (hcl, HCL_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncvars=%d<<<\n", class_obj, class_obj->superclass, superclass, b2, b3, (int)HCL_CLASS_SPEC_NAMED_INSTVARS(spec), (int)HCL_CLASS_SELFSPEC_CLASSVARS(spec)); hcl_logbfmt (hcl, HCL_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncvars=%d<<<\n", class_obj, class_obj->superclass, superclass, b2, b3, (int)HCL_CLASS_SPEC_NAMED_INSTVARS(spec), (int)HCL_CLASS_SELFSPEC_CLASSVARS(spec));
#endif #endif
hcl_logbfmt (hcl, HCL_LOG_STDERR, " spec %d %d | selfspec %d %d\n", expected_spec, spec, expected_selfspec, selfspec);
if (class_obj->superclass != superclass || if (class_obj->superclass != superclass ||
expected_spec != spec || expected_spec != spec ||
expected_selfspec != selfspec || expected_selfspec != selfspec ||

View File

@ -1746,8 +1746,6 @@ oops:
int hcl_ignite (hcl_t* hcl, hcl_oow_t heapsize) int hcl_ignite (hcl_t* hcl, hcl_oow_t heapsize)
{ {
hcl_oow_t i;
if (!hcl->heap) if (!hcl->heap)
{ {
hcl->heap = hcl_makeheap(hcl, heapsize); hcl->heap = hcl_makeheap(hcl, heapsize);

View File

@ -308,6 +308,7 @@ enum hcl_tok_type_t
HCL_TOK_CLASS, HCL_TOK_CLASS,
HCL_TOK_FUN, HCL_TOK_FUN,
HCL_TOK_VAR,
HCL_TOK_DO, HCL_TOK_DO,
HCL_TOK_IF, HCL_TOK_IF,
HCL_TOK_ELIF, HCL_TOK_ELIF,
@ -420,6 +421,7 @@ enum hcl_cnode_type_t
* these represent syntactical elements of the language only. */ * these represent syntactical elements of the language only. */
HCL_CNODE_CLASS, /* first item for HCL_CNODE_IS_FOR_LANG */ HCL_CNODE_CLASS, /* first item for HCL_CNODE_IS_FOR_LANG */
HCL_CNODE_FUN, HCL_CNODE_FUN,
HCL_CNODE_VAR,
HCL_CNODE_DO, HCL_CNODE_DO,
HCL_CNODE_IF, HCL_CNODE_IF,
HCL_CNODE_ELIF, HCL_CNODE_ELIF,
@ -684,28 +686,29 @@ struct hcl_cframe_t
unsigned int indexed_type; unsigned int indexed_type;
hcl_loc_t start_loc; hcl_loc_t start_loc;
hcl_cnode_t* cmd_cnode; hcl_cnode_t* cmd_cnode;
hcl_cnode_t* class_name_cnode;
} _class; } _class;
} u; } u;
}; };
typedef struct hcl_cframe_t hcl_cframe_t; typedef struct hcl_cframe_t hcl_cframe_t;
enum hcl_cblk_type_t enum hcl_ctlblk_type_t
{ {
HCL_CBLK_TYPE_LOOP, HCL_CTLBLK_TYPE_LOOP,
HCL_CBLK_TYPE_TRY, HCL_CTLBLK_TYPE_TRY,
HCL_CBLK_TYPE_CLASS HCL_CTLBLK_TYPE_CLASS
}; };
typedef enum hcl_cblk_type_t hcl_cblk_type_t; typedef enum hcl_ctlblk_type_t hcl_ctlblk_type_t;
/* control block information for the compiler */ /* control block information for the compiler */
struct hcl_cblk_info_t struct hcl_ctlblk_info_t
{ {
hcl_cblk_type_t _type; hcl_ctlblk_type_t _type;
}; };
typedef struct hcl_cblk_info_t hcl_cblk_info_t; typedef struct hcl_ctlblk_info_t hcl_ctlblk_info_t;
/* function block information for the compiler */ /* function block information for the compiler */
struct hcl_fnblk_info_t struct hcl_funblk_info_t
{ {
unsigned int fun_type; unsigned int fun_type;
@ -720,7 +723,7 @@ struct hcl_fnblk_info_t
hcl_oow_t make_inst_pos; hcl_oow_t make_inst_pos;
hcl_oow_t lfbase; hcl_oow_t lfbase;
hcl_ooi_t cblk_base; hcl_ooi_t ctlblk_base;
hcl_ooi_t clsblk_base; hcl_ooi_t clsblk_base;
hcl_ooi_t clsblk_top; hcl_ooi_t clsblk_top;
@ -728,19 +731,21 @@ struct hcl_fnblk_info_t
unsigned int access_outer: 1; unsigned int access_outer: 1;
unsigned int accessed_by_inner: 1; unsigned int accessed_by_inner: 1;
}; };
typedef struct hcl_fnblk_info_t hcl_fnblk_info_t; typedef struct hcl_funblk_info_t hcl_funblk_info_t;
/* class block information for the compiler */ /* class block information for the compiler */
struct hcl_clsblk_info_t struct hcl_clsblk_info_t
{ {
hcl_cnode_t* class_name;
hcl_oow_t nivars; hcl_oow_t nivars;
hcl_oow_t ncvars; hcl_oow_t ncvars;
hcl_ooch_t* ivars_str; hcl_ooch_t* ivars_str;
hcl_ooch_t* cvars_str; hcl_ooch_t* cvars_str;
hcl_oow_t spec; /* TODO: byte indexed, word indexed? */ hcl_oow_t spec; /* TODO: byte indexed, word indexed? */
hcl_ooi_t fnblk_base; hcl_ooi_t funblk_base;
hcl_ooi_t class_start_inst_pos; /* the position of the first instruction in the class body after CLASS_ENTER */ hcl_ooi_t class_start_inst_pos; /* the position of the first instruction in the class body after CLASS_ENTER */
}; };
typedef struct hcl_clsblk_info_t hcl_clsblk_info_t; typedef struct hcl_clsblk_info_t hcl_clsblk_info_t;
@ -998,16 +1003,16 @@ struct hcl_compiler_t
struct struct
{ {
hcl_ooi_t depth; /* signed because it starts with -1 */ hcl_ooi_t depth; /* signed because it starts with -1 */
hcl_cblk_info_t* info; hcl_ctlblk_info_t* info;
hcl_oow_t info_capa; hcl_oow_t info_capa;
} cblk; /* control block - loop, try-catch */ } ctlblk; /* control block - loop, try-catch */
struct struct
{ {
hcl_ooi_t depth; /* signed because it starts with -1 */ hcl_ooi_t depth; /* signed because it starts with -1 */
hcl_fnblk_info_t* info; hcl_funblk_info_t* info;
hcl_oow_t info_capa; hcl_oow_t info_capa;
} fnblk; /* function block */ } funblk; /* function block */
struct struct
{ {

View File

@ -158,6 +158,7 @@ enum hcl_synerrnum_t
HCL_SYNERR_CLASS, /* invalid class definition */ HCL_SYNERR_CLASS, /* invalid class definition */
HCL_SYNERR_FUN, /* invalid function definition */ HCL_SYNERR_FUN, /* invalid function definition */
HCL_SYNERR_VAR, /* invalid variable declaration */
HCL_SYNERR_ELIF, /* elif without if */ HCL_SYNERR_ELIF, /* elif without if */
HCL_SYNERR_ELSE, /* else without if */ HCL_SYNERR_ELSE, /* else without if */
HCL_SYNERR_CATCH, /* catch outside try */ HCL_SYNERR_CATCH, /* catch outside try */
@ -1577,7 +1578,7 @@ enum hcl_compile_flag_t
HCL_COMPILE_CLEAR_CODE = (1 << 0), HCL_COMPILE_CLEAR_CODE = (1 << 0),
/* clear the top-level function block at the end of hcl_compile() */ /* clear the top-level function block at the end of hcl_compile() */
HCL_COMPILE_CLEAR_FNBLK = (1 << 1) HCL_COMPILE_CLEAR_FUNBLK = (1 << 1)
}; };
typedef enum hcl_compile_flag_t hcl_compile_flag_t; typedef enum hcl_compile_flag_t hcl_compile_flag_t;
#endif #endif

View File

@ -60,6 +60,7 @@ static struct voca_t
{ 5, { 'c','l','a','s','s' } }, { 5, { 'c','l','a','s','s' } },
{ 3, { 'f','u','n' } }, { 3, { 'f','u','n' } },
{ 3, { 'v','a','r' } },
{ 2, { 'd','o' } }, { 2, { 'd','o' } },
{ 2, { 'i','f' } }, { 2, { 'i','f' } },
{ 4, { 'e','l','i','f' } }, { 4, { 'e','l','i','f' } },
@ -120,6 +121,7 @@ enum voca_id_t
VOCA_KW_CLASS, VOCA_KW_CLASS,
VOCA_KW_FUN, VOCA_KW_FUN,
VOCA_KW_VAR,
VOCA_KW_DO, VOCA_KW_DO,
VOCA_KW_IF, VOCA_KW_IF,
VOCA_KW_ELIF, VOCA_KW_ELIF,
@ -470,6 +472,7 @@ static hcl_tok_type_t classify_ident_token (hcl_t* hcl, const hcl_oocs_t* v)
{ VOCA_KW_CLASS, HCL_TOK_CLASS }, { VOCA_KW_CLASS, HCL_TOK_CLASS },
{ VOCA_KW_FUN, HCL_TOK_FUN }, { VOCA_KW_FUN, HCL_TOK_FUN },
{ VOCA_KW_VAR, HCL_TOK_VAR },
{ VOCA_KW_DO, HCL_TOK_DO }, { VOCA_KW_DO, HCL_TOK_DO },
{ VOCA_KW_IF, HCL_TOK_IF }, { VOCA_KW_IF, HCL_TOK_IF },
{ VOCA_KW_ELIF, HCL_TOK_ELIF }, { VOCA_KW_ELIF, HCL_TOK_ELIF },
@ -861,14 +864,7 @@ static HCL_INLINE int can_comma_list (hcl_t* hcl)
if (rstl->flagv & (COMMAED | COLONED | COLONEQED | BINOPED)) return 0; if (rstl->flagv & (COMMAED | COLONED | COLONEQED | BINOPED)) return 0;
cc = (hcl_concode_t)LIST_FLAG_GET_CONCODE(rstl->flagv); cc = (hcl_concode_t)LIST_FLAG_GET_CONCODE(rstl->flagv);
if (cc == HCL_CONCODE_XLIST) if (cc == HCL_CONCODE_DIC)
{
/* fun f(a :: b c) { b := (a + 10); c := (a + 20) }
* [x y] := (f 9)
* [x,y] := (f 9) */
LIST_FLAG_SET_CONCODE(rstl->flagv, HCL_CONCODE_ALIST);
}
else if (cc == HCL_CONCODE_DIC)
{ {
if (rstl->count & 1) return 0; if (rstl->count & 1) return 0;
} }
@ -1443,6 +1439,7 @@ static hcl_cnode_type_t kw_to_cnode_type (int tok_type)
HCL_CNODE_CLASS, HCL_CNODE_CLASS,
HCL_CNODE_FUN, HCL_CNODE_FUN,
HCL_CNODE_VAR,
HCL_CNODE_DO, HCL_CNODE_DO,
HCL_CNODE_IF, HCL_CNODE_IF,
HCL_CNODE_ELIF, HCL_CNODE_ELIF,
@ -1882,6 +1879,7 @@ static int feed_process_token (hcl_t* hcl)
case HCL_TOK_CLASS: case HCL_TOK_CLASS:
case HCL_TOK_FUN: case HCL_TOK_FUN:
case HCL_TOK_VAR:
case HCL_TOK_DO: case HCL_TOK_DO:
case HCL_TOK_IF: case HCL_TOK_IF:
case HCL_TOK_ELIF: case HCL_TOK_ELIF:
@ -3926,12 +3924,12 @@ static void fini_compiler_cb (hcl_t* hcl)
HCL_ASSERT (hcl, hcl->c->tv.capa == 0); HCL_ASSERT (hcl, hcl->c->tv.capa == 0);
HCL_ASSERT (hcl, hcl->c->tv.wcount == 0); HCL_ASSERT (hcl, hcl->c->tv.wcount == 0);
if (hcl->c->cblk.info) if (hcl->c->ctlblk.info)
{ {
hcl_freemem (hcl, hcl->c->cblk.info); hcl_freemem (hcl, hcl->c->ctlblk.info);
hcl->c->cblk.info = HCL_NULL; hcl->c->ctlblk.info = HCL_NULL;
hcl->c->cblk.info_capa = 0; hcl->c->ctlblk.info_capa = 0;
hcl->c->cblk.depth = -1; hcl->c->ctlblk.depth = -1;
} }
if (hcl->c->clsblk.info) if (hcl->c->clsblk.info)
@ -3942,12 +3940,12 @@ static void fini_compiler_cb (hcl_t* hcl)
hcl->c->clsblk.depth = -1; hcl->c->clsblk.depth = -1;
} }
if (hcl->c->fnblk.info) if (hcl->c->funblk.info)
{ {
hcl_freemem (hcl, hcl->c->fnblk.info); hcl_freemem (hcl, hcl->c->funblk.info);
hcl->c->fnblk.info = HCL_NULL; hcl->c->funblk.info = HCL_NULL;
hcl->c->fnblk.info_capa = 0; hcl->c->funblk.info_capa = 0;
hcl->c->fnblk.depth = -1; hcl->c->funblk.depth = -1;
} }
clear_sr_names (hcl); clear_sr_names (hcl);
@ -3999,9 +3997,9 @@ static int init_compiler (hcl_t* hcl)
hcl->c->r.e = hcl->_nil; hcl->c->r.e = hcl->_nil;
hcl->c->cfs.top = -1; hcl->c->cfs.top = -1;
hcl->c->cblk.depth = -1; hcl->c->ctlblk.depth = -1;
hcl->c->clsblk.depth = -1; hcl->c->clsblk.depth = -1;
hcl->c->fnblk.depth = -1; hcl->c->funblk.depth = -1;
init_feed (hcl); init_feed (hcl);
hcl->c->cbp = cbp; hcl->c->cbp = cbp;

View File

@ -73,7 +73,7 @@ int hcl_marshalcode (hcl_t* hcl, const hcl_code_t* code, hcl_xchg_writer_t wrtr,
hcl_oow_t w; hcl_oow_t w;
hcl_xchg_hdr_t h; hcl_xchg_hdr_t h;
lfbase = (hcl->option.trait & HCL_TRAIT_INTERACTIVE)? hcl->c->fnblk.info[hcl->c->fnblk.depth].lfbase: 0; lfbase = (hcl->option.trait & HCL_TRAIT_INTERACTIVE)? hcl->c->funblk.info[hcl->c->funblk.depth].lfbase: 0;
/* start with a header */ /* start with a header */
h.ver = 1; h.ver = 1;

View File

@ -1,4 +1,7 @@
class Apex { class Apex {
fun isNil?() { return false }
fun notNil?() { return true }
fun(#class) basicNew(size) { fun(#class) basicNew(size) {
return (core.basicNew self size) return (core.basicNew self size)
} }
@ -30,9 +33,8 @@ class Apex {
fun basicSize() { fun basicSize() {
return (core.basicSize self) return (core.basicSize self)
} }
}
class Object: Apex { ## TODO: fun perform(name ...) {}
} }
class(#uncopyable #varying #limited #final) Class: Apex [ class(#uncopyable #varying #limited #final) Class: Apex [
@ -62,6 +64,14 @@ class(#uncopyable #varying #limited #final) Class: Apex [
} }
} }
class UndefinedObject: Apex {
fun isNil?() { return true }
fun notNil?() { return false }
}
class Object: Apex {
}
class Collection: Object { class Collection: Object {
fun length() { fun length() {
return (core.basicSize self) return (core.basicSize self)
@ -113,6 +123,455 @@ class(#char #varying) String: FixedSizedCollection {
} }
## ---------------------------------------------------------------------------------
## // TODO: consider if System can replace Apex itself.
## // System, being the top class, seems to give very natural way of
## // offering global system-level functions and interfaces.
## //
## // class System { ... }
## // class Object: System { .... }
## // System at: #
## // System logNl: 'xxxxx'.
## // System getUint8(ptr,offset)
##
## class System: Apex [
## [
## asyncsg ## async semaphore group
## gcfin_sem ## gc finalization semaphore
## gcfin_should_exit
## ossig_pid
## shr ## signal handler registry
## ]
##
## ] {
## ## var(#class) asyncsg.
## ## var(#class) gcfin_sem.
## ## var(#class) gcfin_should_exit := false.
## ## var(#class) ossig_pid.
## ## var(#class) shr. // signal handler registry
##
## ## pooldic Log
## ## {
## ## // -----------------------------------------------------------
## ## // defines log levels
## ## // these items must follow defintions in moo.h
## ## // -----------------------------------------------------------
## ##
## ## DEBUG := 1,
## ## INFO := 2,
## ## WARN := 4,
## ## ERROR := 8,
## ## FATAL := 16
## ## }
##
## ## initialize class variables
## shr := (OrderedCollection:new)
## asyncsg := (SemaphoreGroup:new)
##
## fun(#class) _initialize {
## self.shr := OrderedCollection new.
## self.asyncsg := SemaphoreGroup new.
## }
##
## fun(#class) addAsyncSemaphore: sem {
## return (self.asyncsg addSemaphore: sem)
## }
##
## fun(#class) removeAsyncSemaphore: sem {
## return (self.asyncsg removeSemaphore: sem)
## }
##
## fun(#class) handleAsyncEvent {
## return (self.asyncsg wait).
## }
##
## fun(#class) installSignalHandler: block {
## return (self.shr addLast: block)
## }
##
## fun(#class) uninstallSignalHandler: block {
## self.shr remove: block.
## }
##
## fun(#class) startup(class_name, fun_name) {
## | class ret gcfin_proc ossig_proc |
##
## System gc.
##
## class := self at: class_name. // System at: class_name.
## if (class isError)
## {
## self error: ("Unable to find the class - " & class_name).
## }.
##
## self _initialize.
##
## // start the gc finalizer process and os signal handler process
## //[ self __gc_finalizer ] fork.
## //[ self __os_sig_handler ] fork.
## gcfin_proc := [ self __gc_finalizer ] newSystemProcess.
## ossig_proc := [ :caller | self __os_sig_handler: caller ] newSystemProcess(thisProcess).
##
## self.ossig_pid := ossig_proc id.
##
## gcfin_proc resume.
## ossig_proc resume.
##
## [
## // TODO: change the fun signature to variadic and pass extra arguments to perform???
## ret := class perform: fun_name.
## ]
## ensure: [
## // signal end of the main process.
## // __os_sig_handler will terminate all running subprocesses.
## self _setSig: 16rFF.
## ].
##
## ^ret.
## }
##
## fun(#class) __gc_finalizer
## {
## | tmp gc |
##
## gc := false.
##
## self.gcfin_should_exit := false.
## self.gcfin_sem := Semaphore new.
## self.gcfin_sem signalOnGCFin. // tell VM to signal this semaphore when it schedules gc finalization.
##
## [
## while (true)
## {
## while ((tmp := self _popCollectable) notError)
## {
## if (tmp respondsTo: #finalize)
## {
## // finalize is protected with an exception handler.
## // the exception is ignored except it is logged.
## [ tmp finalize ] on: Exception do: [:ex | System longNl: "Exception in finalize - " & ex messageText ]
## }.
## }.
##
## //if (Processor total_count == 1)
## //if (Processor gcfin_should_exit)
## if (self.gcfin_should_exit)
## {
## // exit from this loop when there are no other processes running except this finalizer process
## if (gc)
## {
## System logNl: "Exiting the GC finalization process " & (thisProcess id) asString.
## break.
## }.
##
## System logNl: "Forcing garbage collection before termination in " & (thisProcess id) asString.
## self collectGarbage.
## gc := true.
## }
## else
## {
## gc := false.
## }.
##
## self.gcfin_sem wait.
## }
## ] ensure: [
## self.gcfin_sem signal. // in case the process is stuck in wait.
## self.gcfin_sem unsignal.
## System logNl: "End of GC finalization process " & (thisProcess id) asString.
## ].
## }
##
## fun(#class) __os_sig_handler: caller {
## | os_intr_sem signo sh |
##
## os_intr_sem := Semaphore new.
## os_intr_sem signalOnInput: System _getSigfd.
##
## [
## while (true) {
## until ((signo := self _getSig) isError) {
## // TODO: Do i have to protected this in an exception handler???
## //TODO: Execute Handler for signo.
##
## System logNl: "Interrupt detected - signal no - " & signo asString.
##
## //System logNl: "WWWWWWWWWWWWWWWWWWWWWWWWW ".
## // user-defined signal handler is not allowed for 16rFF
## if (signo == 16rFF) { goto done }.
## //System logNl: "OHHHHHHHHHHHHHH ".
##
## ifnot (self.shr isEmpty)
## {
## //System logNl: "About to execute handler for the signal detected - " & signo asString.
## self.shr do: [ :handler | handler value: signo ].
## }
## else
## {
## //System logNl: "Jumping to done detected - signal no - " & signo asString.
## if (signo == 2) { goto done }.
## }.
## }.
## //System logNl: "Waiting for signal on os_intr_sem...".
## os_intr_sem wait.
## }.
## done:
## //System logNl: "Jumped to done detected - signal no - " & signo asString.
## nil.
## ]
## ensure: [
## | pid proc oldps |
##
## //System logNl: "Aborting signal handler......".
## // stop subscribing to signals.
## os_intr_sem signal.
## os_intr_sem unsignal.
##
## // the caller must request to terminate all its child processes..
##
## // this disables autonomous process switching only.
## // TODO: check if the ensure block code can trigger process switching?
## // what happens if the ensure block creates new processes? this is likely to affect the termination loop below.
## // even the id of the terminated process may get reused....
## oldps := self _toggleProcessSwitching: false.
##
## /*
## 0 -> startup <--- this should also be stored in the "caller" variable.
## 1 -> __gc_finalizer
## 2 -> __os_sig_handler
## 3 .. -> other processes started by application.
##
## from the second run onwards, the starting pid may not be 0.
## */
## //proc := System _findNextProcess: self.ossig_pid.
## proc := System _findFirstProcess.
## while (proc notError)
## {
## pid := proc id.
## if (proc isNormal)
## {
## System logNl: ("Requesting to terminate process of id - " & pid asString).
## proc terminate.
## }.
## proc := System _findNextProcess: pid.
## }.
##
## System logNl: "Requesting to terminate the caller process of id " & (caller id) asString.
## caller terminate. // terminate the startup process.
## self _toggleProcessSwitching: oldps.
##
## System logNl: ">>>>End of OS signal handler process " & (thisProcess id) asString.
##
## self.gcfin_should_exit := true.
## self.gcfin_sem signal. // wake the gcfin process.
##
## self _halting. // inform VM that it should get ready for halting.
## ].
## }
##
## fun(#class,#primitive) _getSig.
## fun(#class,#primitive) _getSigfd.
## fun(#class,#primitive) _setSig: signo.
## fun(#class,#primitive) _halting.
## fun(#class,#primitive) _toggleProcessSwitching: v.
## fun(#class,#primitive,#lenient) _findProcessById: id.
## fun(#class,#primitive,#lenient) _findFirstProcess.
## fun(#class,#primitive,#lenient) _findLastProcess.
## fun(#class,#primitive,#lenient) _findPreviousProcess: p. // process id or process object
## fun(#class,#primitive,#lenient) _findNextProcess: p. // process id or process object
##
## fun(#class,#primitive) _popCollectable.
## fun(#class,#primitive) collectGarbage.
## fun(#class,#primitive) gc.
## fun(#class,#primitive) return: object to: context.
##
## // =======================================================================================
##
## fun(#class) sleepForSecs: secs {
## // -----------------------------------------------------
## // put the calling process to sleep for given seconds.
## // -----------------------------------------------------
## | s |
## s := Semaphore new.
## s signalAfterSecs: secs.
## s wait.
## }
##
## fun(#class) sleepForSecs: secs nanosecs: nanosecs
## {
## // -----------------------------------------------------
## // put the calling process to sleep for given seconds.
## // -----------------------------------------------------
## | s |
## s := Semaphore new.
## s signalAfterSecs: secs nanosecs: nanosecs.
## s wait.
## }
##
## // the following funs may not look suitable to be placed
## // inside a system dictionary. but they are here for quick and dirty
## // output production from the moo code.
## // System logNl: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'.
## //
## fun(#class,#variadic,#primitive) log(level,msg1).
##
## /*
## TODO: how to pass all variadic arguments to another variadic funs???
## fun(#class,#variadic) logInfo (msg1)
## {
## ^self log (System.Log.INFO,msg1)
## }
## */
## fun(#class) atLevel: level log: message
## {
## <primitive: #System_log>
## // do nothing upon logging failure
## }
##
## fun(#class) atLevel: level log: message and: message2
## {
## <primitive: #System_log>
## // do nothing upon logging failure
## }
##
## fun(#class) atLevel: level log: message and: message2 and: message3
## {
## <primitive: #System_log>
## // do nothing upon logging failure
## }
##
## fun(#class) atLevel: level logNl: message
## {
## // the #_log primitive accepts an array.
## // so the following lines should work also.
## // | x |
## // x := Array new: 2.
## // x at: 0 put: message.
## // x at: 1 put: "\n".
## // ^self atLevel: level log: x.
##
## ^self atLevel: level log: message and: "\n".
## }
##
## fun(#class) atLevel: level logNl: message and: message2
## {
## ^self atLevel: level log: message and: message2 and: "\n".
## }
##
## fun(#class) log: message
## {
## ^self atLevel: System.Log.INFO log: message.
## }
##
## fun(#class) log: message and: message2
## {
## ^self atLevel: System.Log.INFO log: message and: message2.
## }
##
## fun(#class) logNl
## {
## ^self atLevel: System.Log.INFO log: "\n".
## }
##
## fun(#class) logNl: message
## {
## ^self atLevel: System.Log.INFO logNl: message.
## }
##
## fun(#class) logNl: message and: message2
## {
## ^self atLevel: System.Log.INFO logNl: message and: message2.
## }
##
## fun(#class) backtrace
## {
## | ctx oldps |
## // TOOD: IMPROVE THIS EXPERIMENTAL BACKTRACE... MOVE THIS TO System>>backtrace and skip the first fun context for backtrace itself.
## // TODO: make this fun atomic? no other process should get scheduled while this function is running?
## // possible imementation funs:
## // 1. disable task switching? ->
## // 2. use a global lock.
## // 3. make this a primitive function. -> natually no callback.
## // 4. introduce a new fun attribute. e.g. #atomic -> vm disables task switching or uses a lock to achieve atomicity.
## // >>>> i think it should not be atomic as a while. only logging output should be produeced at one go.
##
## oldps := System _toggleProcessSwitching: false.
## System logNl: "== BACKTRACE ==".
##
## //ctx := thisContext.
## ctx := thisContext sender. // skip the current context. skip to the caller context.
## while (ctx notNil)
## {
## // if (ctx sender isNil) { break }. // to skip the fake top level call context...
##
## if (ctx class == MethodContext)
## {
## System log: " ";
## log: ctx fun owner name;
## log: ">>";
## log: ctx fun name;
## log: " (";
## log: ctx fun sourceFile;
## log: " ";
## log: (ctx fun ipSourceLine: (ctx pc)) asString;
## logNl: ")".
## //System logNl: (" " & ctx fun owner name & ">>" & ctx fun name &
## // " (" & ctx fun sourceFile & " " & (ctx fun ipSourceLine: (ctx pc)) asString & ")").
## }.
## // TODO: include blockcontext???
## ctx := ctx sender.
## }.
## System logNl: "== END OF BACKTRACE ==".
## System _toggleProcessSwitching: oldps.
## }
##
## ## /* nsdic access */
## ## fun(#class) at: key
## ## {
## ## ^self nsdic at: key
## ## }
## ##
## ## fun(#class) at: key put: value
## ## {
## ## ^self nsdic at: key put: value
## ## }
## ##
## ## /* raw memory allocation */
## ## fun(#class,#primitive) malloc (size).
## ## fun(#class,#primitive) calloc (size).
## ## fun(#class,#primitive) free (rawptr).
## ##
## ## fun(#class,#primitive) malloc: size.
## ## fun(#class,#primitive) calloc: size.
## ## fun(#class,#primitive) free: rawptr.
## ##
## ## /* raw memory access */
## ## fun(#class,#primitive) getInt8 (rawptr, offset). // <primitive: #System__getInt8>
## ## fun(#class,#primitive) getInt16 (rawptr, offset).
## ## fun(#class,#primitive) getInt32 (rawptr, offset).
## ## fun(#class,#primitive) getInt64 (rawptr, offset).
## ## fun(#class,#primitive) getUint8 (rawptr, offset). // <primitive: #System__getUint8>
## ## fun(#class,#primitive) getUint16 (rawptr, offset).
## ## fun(#class,#primitive) getUint32 (rawptr, offset).
## ## fun(#class,#primitive) getUint64 (rawptr, offset).
## ##
## ## fun(#class,#primitive) putInt8 (rawptr, offset, value).
## ## fun(#class,#primitive) putInt16 (rawptr, offset, value).
## ## fun(#class,#primitive) putInt32 (rawptr, offset, value).
## ## fun(#class,#primitive) putInt64 (rawptr, offset, value).
## ## fun(#class,#primitive) putUint8 (rawptr, offset, value).
## ## fun(#class,#primitive) putUint16 (rawptr, offset, value).
## ## fun(#class,#primitive) putUint32 (rawptr, offset, value).
## ## fun(#class,#primitive) putUint64 (rawptr, offset, value).
## ##
## ## fun(#class,#primitive) getBytes (rawptr, offset, byte_array, offset_in_buffer, len_in_buffer).
## ## fun(#class,#primitive) putBytes (rawptr, offset, byte_array, offset_in_buffer, len_in_buffer).
## }
## ---------------------------------------------------------------------------------
k := "abcdefghijklmn" k := "abcdefghijklmn"
printf "string length %d\n" ("aaaa":length) printf "string length %d\n" ("aaaa":length)
printf "substring [%s]\n" (k:slice 5 6) printf "substring [%s]\n" (k:slice 5 6)
@ -178,4 +637,3 @@ k := (Z:new)
printf "%O\n" (k:basicAt 2) printf "%O\n" (k:basicAt 2)

View File

@ -270,5 +270,5 @@ class(#byte #limited #final #limited) Kuduro { ##ERROR: syntax error - conflicti
--- ---
class(#byte #bytes) Kuduro { ##ERROR: syntax error - unrecognized class attribute name 'bytes' class(#byte #bytes) Kuduro { ##ERROR: syntax error - unrecognized class attribute name '#bytes'
} }