diff --git a/lib/comp.c b/lib/comp.c index 1f38287..1a11eac 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -760,7 +760,7 @@ static int emit_variable_access (hcl_t* hcl, int mode, const hcl_var_info_t* vi, { { HCL_CODE_PUSH_CTXTEMPVAR_0, HCL_CODE_POP_INTO_CTXTEMPVAR_0, HCL_CODE_STORE_INTO_CTXTEMPVAR_0 }, { HCL_CODE_PUSH_INSTVAR_0, HCL_CODE_POP_INTO_INSTVAR_0, HCL_CODE_STORE_INTO_INSTVAR_0 }, - { HCL_CODE_PUSH_OBJVAR_0, HCL_CODE_POP_INTO_OBJVAR_0, HCL_CODE_STORE_INTO_OBJVAR_0 }, + { HCL_CODE_PUSH_CLSVAR_X, HCL_CODE_POP_INTO_CLSVAR_X, HCL_CODE_STORE_INTO_CLSVAR_X }, }; switch (vi->type) @@ -774,7 +774,7 @@ static int emit_variable_access (hcl_t* hcl, int mode, const hcl_var_info_t* vi, case VAR_CLASS: HCL_ASSERT (hcl, vi->ctx_offset == 0); - //return emit_double_param_instruction(hcl, inst_map[2][mode], vi->index_in_ctx, <>, srcloc); + return emit_single_param_instruction(hcl, inst_map[2][mode], vi->index_in_ctx, srcloc); } return -1; @@ -2091,25 +2091,28 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) { /* instance variables */ hcl_oow_t checkpoint; + if (!HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_VLIST)) break; checkpoint = hcl->c->tv.s.len; + if (collect_vardcl(hcl, obj, &obj, tv_dup_check_start, &dclcount, "instance") <= -1) return -1; nivars += dclcount; - if (ivar_len <= 0) ivar_start = checkpoint; + if (ivar_len <= 0) ivar_start = (cvar_len <= 0)? checkpoint: cvar_start; ivar_len += hcl->c->tv.s.len - checkpoint; if (cvar_len > 0) { + /* place the instance variables before the class variables + * if class variables "a b" has been collected before instance variables "cc dd ee" + * the rotation below manipulates the buffer to contain "cc dd ee a b". + */ hcl_rotate_oochars (&hcl->c->tv.s.ptr[cvar_start], hcl->c->tv.s.len - cvar_start, -1, cvar_len); - ivar_start = cvar_start; cvar_start += hcl->c->tv.s.len - checkpoint; } } } -//HCL_DEBUG4 (hcl, "AAAAAAAAAAAAAAAAAAAAAAA>>>> [%.*js] [%.*js]\n", ivar_len, &hcl->c->tv.s.ptr[ivar_start], cvar_len, &hcl->c->tv.s.ptr[cvar_start]); - if (nivars > 0) { hcl_oop_t tmp; @@ -3710,7 +3713,7 @@ redo: switch (HCL_CNODE_ELIST_CONCODE(oprnd)) { case HCL_CONCODE_XLIST: - hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARDCLBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty executable list"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty executable list"); return -1; case HCL_CONCODE_ARRAY: @@ -3730,7 +3733,7 @@ redo: goto done; case HCL_CONCODE_VLIST: - hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARDCLBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "variable declaration disallowed"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty variable declaration"); return -1; default: diff --git a/lib/err.c b/lib/err.c index 259df92..81b2c5f 100644 --- a/lib/err.c +++ b/lib/err.c @@ -77,6 +77,9 @@ static hcl_ooch_t errstr_35[] = {'a','r','g','u','m','e','n','t',' ','n','u','m' static hcl_ooch_t errstr_36[] = {'r','e','t','u','r','n',' ','c','o','u','n','t',' ','e','r','r','o','r','\0'}; static hcl_ooch_t errstr_37[] = {'t','o','o',' ','m','a','n','y',' ','s','e','m','a','p','h','o','r','e','s','\0'}; static hcl_ooch_t errstr_38[] = {'e','x','c','e','p','a','i','o','n',' ','n','o','t',' ','h','a','n','d','l','e','d','\0'}; +static hcl_ooch_t errstr_39[] = {'s','t','a','c','k',' ','u','n','d','e','r','f','l','o','w','\0'}; + +static hcl_ooch_t errstr_40[] = {'s','t','a','c','k',' ','o','v','e','r','f','l','o','w','\0'}; static hcl_ooch_t* errstr[] = { @@ -84,7 +87,8 @@ static hcl_ooch_t* errstr[] = errstr_8, errstr_9, errstr_10, errstr_11, errstr_12, errstr_13, errstr_14, errstr_15, errstr_16, errstr_17, errstr_18, errstr_19, errstr_20, errstr_21, errstr_22, errstr_23, errstr_24, errstr_25, errstr_26, errstr_27, errstr_28, errstr_29, errstr_30, errstr_31, - errstr_32, errstr_33, errstr_34, errstr_35, errstr_36, errstr_37, errstr_38 + errstr_32, errstr_33, errstr_34, errstr_35, errstr_36, errstr_37, errstr_38, errstr_39, + errstr_40 }; diff --git a/lib/exec.c b/lib/exec.c index 4639380..cc25eeb 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -3442,7 +3442,12 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) case HCL_CODE_CLASS_EXIT: { LOG_INST_0 (hcl, "class_exit"); - /* TODO: stack underflow check? */ + if (HCL_CLSTACK_IS_EMPTY(hcl)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "class stack underflow"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } HCL_CLSTACK_POP (hcl); break; } @@ -3452,7 +3457,13 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) hcl_oop_t c; LOG_INST_0 (hcl, "class_push_exit"); - /* TODO: stack underflow check? */ + + if (HCL_CLSTACK_IS_EMPTY(hcl)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "class stack underflow"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } HCL_CLSTACK_POP_TO (hcl, c); HCL_STACK_PUSH (hcl, c); @@ -3633,6 +3644,12 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) hcl_oop_class_t t; FETCH_PARAM_CODE_TO (hcl, b1); LOG_INST_1 (hcl, "store_into_clsvar %zu", b1); + if (HCL_CLSTACK_IS_EMPTY(hcl)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "empty class stack"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } HCL_CLSTACK_FETCH_TOP_TO(hcl, t); t->cvar[b1] = HCL_STACK_GETTOP(hcl); break; @@ -3643,6 +3660,12 @@ if (do_throw(hcl, hcl->_nil, fetched_instruction_pointer) <= -1) hcl_oop_class_t t; FETCH_PARAM_CODE_TO (hcl, b1); LOG_INST_1 (hcl, "pop_into_clsvar %zu", b1); + if (HCL_CLSTACK_IS_EMPTY(hcl)) + { + hcl_seterrbfmt (hcl, HCL_ESTKUNDFLW, "empty class stack"); + supplement_errmsg (hcl, fetched_instruction_pointer); + goto oops; + } HCL_CLSTACK_FETCH_TOP_TO(hcl, t); t->cvar[b1] = HCL_STACK_GETTOP(hcl); HCL_STACK_POP (hcl); diff --git a/lib/hcl.h b/lib/hcl.h index 84c728b..5482e6d 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -68,29 +68,31 @@ enum hcl_errnum_t HCL_EPIPE, HCL_EAGAIN, HCL_EBADHND, - HCL_EFRMFLOOD, /**< too many frames */ + HCL_EFRMFLOOD, /**< too many frames */ - HCL_EMSGRCV, /**< mesasge receiver error */ - HCL_EMSGSND, /**< message sending error. even doesNotUnderstand: is not found */ - HCL_ENUMARGS, /**< wrong number of arguments */ - HCL_ERANGE, /**< range error. overflow and underflow */ - HCL_EBCFULL, /**< byte-code full */ + HCL_EMSGRCV, /**< mesasge receiver error */ + HCL_EMSGSND, /**< message sending error. even doesNotUnderstand: is not found */ + HCL_ENUMARGS, /**< wrong number of arguments */ + HCL_ERANGE, /**< range error. overflow and underflow */ + HCL_EBCFULL, /**< byte-code full */ - HCL_EDFULL, /**< dictionary full */ - HCL_EPFULL, /**< processor full */ - HCL_EFINIS, /**< unexpected end of data/input/stream/etc */ - HCL_EFLOOD, /**< too many items/data */ - HCL_EDIVBY0, /**< divide by zero */ + HCL_EDFULL, /**< dictionary full */ + HCL_EPFULL, /**< processor full */ + HCL_EFINIS, /**< unexpected end of data/input/stream/etc */ + HCL_EFLOOD, /**< too many items/data */ + HCL_EDIVBY0, /**< divide by zero */ - HCL_EIOERR, /**< I/O error */ - HCL_EECERR, /**< encoding conversion error */ - HCL_EBUFFULL, /**< buffer full */ - HCL_ESYNERR, /**< syntax error */ - HCL_ECALL, /**< runtime error - cannot call */ - HCL_ECALLARG, /**< runtime error - wrong number of arguments to call */ - HCL_ECALLRET, /**< runtime error - wrong number of return variables to call */ - HCL_ESEMFLOOD, /**< runtime error - too many semaphores */ - HCL_EEXCEPT /**< runtime error - exception not handled */ + HCL_EIOERR, /**< I/O error */ + HCL_EECERR, /**< encoding conversion error */ + HCL_EBUFFULL, /**< buffer full */ + HCL_ESYNERR, /**< syntax error */ + HCL_ECALL, /**< runtime error - cannot call */ + HCL_ECALLARG, /**< runtime error - wrong number of arguments to call */ + HCL_ECALLRET, /**< runtime error - wrong number of return variables to call */ + HCL_ESEMFLOOD, /**< runtime error - too many semaphores */ + HCL_EEXCEPT, /**< runtime error - exception not handled */ + HCL_ESTKOVRFLW, /**< runtime error - stack overflow */ + HCL_ESTKUNDFLW /**< runtime error - stack overflow */ }; typedef enum hcl_errnum_t hcl_errnum_t; diff --git a/lib/obj.c b/lib/obj.c index 3bf0d92..c5bd1c5 100644 --- a/lib/obj.c +++ b/lib/obj.c @@ -360,7 +360,7 @@ hcl_oop_t hcl_makeclass (hcl_t* hcl, hcl_oop_t superclass, hcl_ooi_t nivars, hcl hcl_pushvolat (hcl, &superclass); hcl_pushvolat (hcl, &ivars_str); hcl_pushvolat (hcl, &cvars_str); - c = (hcl_oop_class_t)hcl_allocoopobj(hcl, HCL_BRAND_CLASS, HCL_CLASS_NAMED_INSTVARS); + c = (hcl_oop_class_t)hcl_allocoopobj(hcl, HCL_BRAND_CLASS, HCL_CLASS_NAMED_INSTVARS + ncvars); hcl_popvolats (hcl, 3); if (HCL_UNLIKELY(!c)) return HCL_NULL; diff --git a/lib/utf8.c b/lib/utf8.c index 2988833..b9666d8 100644 --- a/lib/utf8.c +++ b/lib/utf8.c @@ -26,6 +26,8 @@ #include "hcl-prv.h" +/*#define RETAIN_RFC2279 1*/ + /* * from RFC 2279 UTF-8, a transformation format of ISO 10646 * @@ -36,6 +38,12 @@ * 4:4 00010000-001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx * inv 00200000-03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx * inv 04000000-7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * RFC3629 limits the ranges like this: + * 1:2 00000000-0000007F 0xxxxxxx + * 2:2 00000080-000007FF 110xxxxx 10xxxxxx + * 3:2 00000800-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx + * 4:4 00010000-0010FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ struct __utf8_t @@ -55,9 +63,13 @@ static __utf8_t utf8_table[] = {0x00000000ul, 0x0000007Ful, 0x00, 0x80, 0x7F, 1}, {0x00000080ul, 0x000007FFul, 0xC0, 0xE0, 0x1F, 2}, {0x00000800ul, 0x0000FFFFul, 0xE0, 0xF0, 0x0F, 3}, +#if defined(RETAIN_RFC2279) {0x00010000ul, 0x001FFFFFul, 0xF0, 0xF8, 0x07, 4}, {0x00200000ul, 0x03FFFFFFul, 0xF8, 0xFC, 0x03, 5}, {0x04000000ul, 0x7FFFFFFFul, 0xFC, 0xFE, 0x01, 6} +#else + {0x00010000ul, 0x0010FFFFul, 0xF0, 0xF8, 0x07, 4} +#endif }; static HCL_INLINE __utf8_t* get_utf8_slot (hcl_uch_t uc) @@ -81,7 +93,7 @@ static HCL_INLINE __utf8_t* get_utf8_slot (hcl_uch_t uc) hcl_oow_t hcl_uc_to_utf8 (hcl_uch_t uc, hcl_bch_t* utf8, hcl_oow_t size) { - __utf8_t* cur = get_utf8_slot (uc); + __utf8_t* cur = get_utf8_slot(uc); if (cur == HCL_NULL) return 0; /* illegal character */