renamed fnblk to funblk, cblk to ctlblk.
All checks were successful
continuous-integration/drone/push Build is passing
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:
parent
42009d3cce
commit
17550d44c5
@ -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)
|
||||||
|
@ -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])
|
||||||
|
561
lib/comp.c
561
lib/comp.c
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||||
|
@ -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 ||
|
||||||
|
2
lib/gc.c
2
lib/gc.c
@ -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);
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
38
lib/read.c
38
lib/read.c
@ -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;
|
||||||
|
@ -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;
|
||||||
|
464
src/kernel.hcl
464
src/kernel.hcl
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user