diff --git a/moo/kernel/Apex.moo b/moo/kernel/Apex.moo index 93b30c2..c156104 100644 --- a/moo/kernel/Apex.moo +++ b/moo/kernel/Apex.moo @@ -8,17 +8,17 @@ class(#limited) Error(Apex) pooldic Error.Code { - ENOERR := error(0). - EGENERIC := error(1). - ENOIMPL := error(2). - ESYSERR := error(3). - EINTERN := error(4). - ESYSMEM := error(5). - EOOMEM := error(6). - EINVAL := error(7). - ENOENT := error(8). - EPERM := error(12). - ERANGE := error(20). + ENOERR := #\0. + EGENERIC := #\1. + ENOIMPL := #\2. + ESYSERR := #\3. + EINTERN := #\4. + ESYSMEM := #\5. + EOOMEM := #\6. + EINVAL := #\7. + ENOENT := #\8. + EPERM := #\12. + ERANGE := #\20. (* add more items... *) } @@ -170,7 +170,7 @@ extend Apex ## ^self ~= nil. ^true. } - + method(#dual) isError { ^false @@ -300,8 +300,8 @@ extend Error pooldic/const { - NONE := error(0). - GENERIC := error(1). + NONE := #\0. + GENERIC := #\1. } -------------------------------- *) diff --git a/moo/kernel/Magnitu.moo b/moo/kernel/Magnitu.moo index 351b6bd..15fbfd9 100644 --- a/moo/kernel/Magnitu.moo +++ b/moo/kernel/Magnitu.moo @@ -123,29 +123,38 @@ class(#limited) Number(Magnitude) self primitiveFailed. } - method quo: aNumber + method div: aNumber { - + ## integer division rounded toward zero + self primitiveFailed. } method rem: aNumber { + ## integer remainder rounded toward zero self primitiveFailed. } - method // aNumber + method mdiv: aNumber { - + ## integer division quotient + self primitiveFailed. } - - method \\ aNumber + + method mod: aNumber { - + ## integer division remainder + self primitiveFailed. } + + ##method / aNumber + ##{ + ## ## fraction? fixed-point decimal? floating-point? + ##} method = aNumber { diff --git a/moo/lib/comp.c b/moo/lib/comp.c index 0448776..701e30b 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -117,7 +117,6 @@ static struct voca_t { 4, { 'e','l','s','e' } }, { 5, { 'e','l','s','i','f' } }, { 6, { 'e','n','s','u','r','e', } }, - { 5, { 'e','r','r','o','r' } }, { 9, { 'e','x','c','e','p','t','i','o','n' } }, { 6, { 'e','x','t','e','n','d' } }, { 5, { 'f','a','l','s','e' } }, @@ -182,7 +181,6 @@ enum voca_id_t VOCA_ELSE, VOCA_ELSIF, VOCA_ENSURE, - VOCA_ERROR, VOCA_EXCEPTION, VOCA_EXTEND, VOCA_FALSE, @@ -260,7 +258,6 @@ static MOO_INLINE int is_spacechar (moo_ooci_t c) } } - static MOO_INLINE int is_alphachar (moo_ooci_t c) { /* TODO: support full unicode */ @@ -284,13 +281,14 @@ static MOO_INLINE int is_binselchar (moo_ooci_t c) /* * binary-selector-character := * '&' | '*' | '+' | '-' | '/' | - * '<' | '>' | '=' | '?' | '@' | - * '\' | '~' | '|' + * '<' | '>' | '=' | '@' | '~' | '|' * * - a comma is special in moo and doesn't form a binary selector. * - a percent sign is special in moo and doesn't form a binary selector. * - an exclamation mark is excluded intentioinally because i can't tell * the method symbol #! from the comment introducer #!. + * - a question mark forms a normal identifier. + * - a backslash is used to form an error literal combined with a hash sign. (e.g. #\10) */ switch (c) @@ -303,9 +301,7 @@ static MOO_INLINE int is_binselchar (moo_ooci_t c) case '<': case '>': case '=': - case '?': case '@': - case '\\': case '|': case '~': return 1; @@ -322,7 +318,7 @@ static MOO_INLINE int is_leadidentchar (moo_ooci_t c) static MOO_INLINE int is_identchar (moo_ooci_t c) { - return is_alnumchar(c) || c == '_'; + return is_alnumchar(c) || c == '_' || c == '?'; } #if 0 @@ -342,7 +338,7 @@ static MOO_INLINE int is_closing_char (moo_ooci_t c) default: return 0; } -} +}VOCA_ERROR, #endif static MOO_INLINE int is_word (const moo_oocs_t* oocs, voca_id_t id) @@ -360,7 +356,6 @@ static int is_reserved_word (const moo_oocs_t* ucs) VOCA_NIL, VOCA_TRUE, VOCA_FALSE, - VOCA_ERROR, VOCA_THIS_CONTEXT, VOCA_THIS_PROCESS, VOCA_SELFNS, @@ -642,7 +637,7 @@ static moo_oop_t string_to_num (moo_t* moo, moo_oocs_t* str, int radixed) return moo_strtoint (moo, ptr, end - ptr, base); } -static moo_oop_t string_to_error (moo_t* moo, moo_oocs_t* str) +static moo_oop_t string_to_error (moo_t* moo, moo_oocs_t* str, moo_ioloc_t* loc) { moo_ooi_t num = 0; const moo_ooch_t* ptr, * end; @@ -655,14 +650,25 @@ static moo_oop_t string_to_error (moo_t* moo, moo_oocs_t* str) * i just skip all non-digit letters for simplicity sake. */ while (ptr < end) { - if (is_digitchar(*ptr)) num = num * 10 + (*ptr - '0'); + if (is_digitchar(*ptr)) + { + moo_oow_t xnum; + + xnum = num * 10 + (*ptr - '0'); + if (xnum < num || xnum > MOO_ERROR_MAX) + { + /* overflowed */ + moo_setsynerr (moo, MOO_SYNERR_ERRLITINVAL, loc, str); + return MOO_NULL; + } + num = xnum; + } ptr++; } return MOO_ERROR_TO_OOP(num); } - /* --------------------------------------------------------------------- * SOME PRIVIATE UTILITILES * --------------------------------------------------------------------- */ @@ -1017,37 +1023,7 @@ static int get_ident (moo_t* moo, moo_ooci_t char_read_ahead) GET_CHAR_TO (moo, c); } - if (c == '(' && is_token_word(moo, VOCA_ERROR)) - { - /* error(NN) */ - ADD_TOKEN_CHAR (moo, c); - GET_CHAR_TO (moo, c); - if (!is_digitchar(c)) - { - ADD_TOKEN_CHAR (moo, c); - moo_setsynerr (moo, MOO_SYNERR_ERRLITINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); - return -1; - } - - do - { - ADD_TOKEN_CHAR (moo, c); - GET_CHAR_TO (moo, c); - } - while (is_digitchar(c)); - - if (c != ')') - { - moo_setsynerr (moo, MOO_SYNERR_RPAREN, LEXER_LOC(moo), MOO_NULL); - return -1; - } - -/* TODO: error number range check */ - - ADD_TOKEN_CHAR (moo, c); - SET_TOKEN_TYPE (moo, MOO_IOTOK_ERRLIT); - } - else if (c == ':') + if (c == ':') { #if 0 read_more_kwsym: @@ -1160,10 +1136,6 @@ static int get_ident (moo_t* moo, moo_ooci_t char_read_ahead) { SET_TOKEN_TYPE (moo, MOO_IOTOK_FALSE); } - else if (is_token_word(moo, VOCA_ERROR)) - { - SET_TOKEN_TYPE (moo, MOO_IOTOK_ERROR); - } else if (is_token_word(moo, VOCA_THIS_CONTEXT)) { SET_TOKEN_TYPE (moo, MOO_IOTOK_THIS_CONTEXT); @@ -1234,8 +1206,8 @@ static int get_numlit (moo_t* moo, int negated) */ moo_ooci_t c; - int radix = 0, r; - + moo_oow_t radix = 0; + int radix_overflowed = 0; c = moo->c->lxc.c; SET_TOKEN_TYPE (moo, MOO_IOTOK_NUMLIT); @@ -1243,18 +1215,24 @@ static int get_numlit (moo_t* moo, int negated) /*TODO: support a complex numeric literal */ do { - if (radix <= 36) + /* collect the potential radix specifier */ + if (!radix_overflowed) { - /* collect the potential radix specifier */ - r = CHAR_TO_NUM (c, 10); + int r; + moo_oow_t rv; + + r = CHAR_TO_NUM(c, 10); MOO_ASSERT (moo, r < 10); - radix = radix * 10 + r; + rv = radix * 10 + r; + if (rv < radix) radix_overflowed = 1; + radix = rv; } ADD_TOKEN_CHAR(moo, c); GET_CHAR_TO (moo, c); if (c == '_') { + /* i allow digit separation with _ as in 123_456. */ moo_iolxc_t underscore; underscore = moo->c->lxc; GET_CHAR_TO(moo, c); @@ -1273,9 +1251,9 @@ static int get_numlit (moo_t* moo, int negated) { /* radix specifier */ - if (radix < 2 || radix > 36) + if (radix_overflowed || radix < 2 || radix > 36) { - /* no digit after the radix specifier */ + /* radix too big */ moo_setsynerr (moo, MOO_SYNERR_RADIXINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); return -1; } @@ -1311,9 +1289,12 @@ static int get_numlit (moo_t* moo, int negated) while (CHAR_TO_NUM(c, radix) < radix); SET_TOKEN_TYPE (moo, MOO_IOTOK_RADNUMLIT); + unget_char (moo, &moo->c->lxc); + } + else + { + unget_char (moo, &moo->c->lxc); } - - unget_char (moo, &moo->c->lxc); /* * TODO: handle floating point number @@ -1743,7 +1724,6 @@ retry: ADD_TOKEN_CHAR(moo, c); SET_TOKEN_TYPE (moo, MOO_IOTOK_HASHBRACK); break; - break; case '\'': /* quoted symbol literal */ @@ -1751,6 +1731,27 @@ retry: SET_TOKEN_TYPE (moo, MOO_IOTOK_SYMLIT); /* change the symbol type to symbol */ break; + case '\\': + /* #\NNN - error literal - #\0, #\1234, etc */ + SET_TOKEN_TYPE(moo, MOO_IOTOK_ERRLIT); + ADD_TOKEN_CHAR(moo, c); + GET_CHAR_TO (moo, c); + if (!is_digitchar(c)) + { + ADD_TOKEN_CHAR(moo, c); /* to include it to the error messsage */ + moo_setsynerr (moo, MOO_SYNERR_ERRLITINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo)); + return -1; + } + + do + { + ADD_TOKEN_CHAR(moo, c); + GET_CHAR_TO (moo, c); + } + while (is_digitchar(c) || c == '_'); + unget_char (moo, &moo->c->lxc); + break; + default: /* symbol-literal := "#" symbol-body * symbol-body := identifier | keyword+ | binary-selector | string-literal @@ -4936,17 +4937,11 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons GET_TOKEN (moo); break; - case MOO_IOTOK_ERROR: - if (add_literal(moo, MOO_ERROR_TO_OOP(MOO_EGENERIC), &index) <= -1 || - emit_single_param_instruction(moo, BCODE_PUSH_LITERAL_0, index) <= -1) return -1; - GET_TOKEN (moo); - break; - case MOO_IOTOK_ERRLIT: { moo_oop_t tmp; - tmp = string_to_error (moo, TOKEN_NAME(moo)); + tmp = string_to_error (moo, TOKEN_NAME(moo), TOKEN_LOC(moo)); if (!tmp) return -1; if (add_literal(moo, tmp, &index) <= -1 || @@ -7783,11 +7778,8 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly) case MOO_IOTOK_FALSE: return moo->_false; - case MOO_IOTOK_ERROR: - return MOO_ERROR_TO_OOP(MOO_EGENERIC); - case MOO_IOTOK_ERRLIT: - return string_to_error (moo, TOKEN_NAME(moo)); + return string_to_error(moo, TOKEN_NAME(moo), TOKEN_LOC(moo)); case MOO_IOTOK_CHARLIT: MOO_ASSERT (moo, TOKEN_NAME_LEN(moo) == 1); diff --git a/moo/lib/exec.c b/moo/lib/exec.c index bccbc29..734f4c4 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2775,7 +2775,7 @@ static moo_pfrc_t pf_integer_mul (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } -static moo_pfrc_t pf_integer_quo (moo_t* moo, moo_ooi_t nargs) +static moo_pfrc_t pf_integer_div (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv, arg, quo; @@ -2809,7 +2809,7 @@ static moo_pfrc_t pf_integer_rem (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } -static moo_pfrc_t pf_integer_quo2 (moo_t* moo, moo_ooi_t nargs) +static moo_pfrc_t pf_integer_mdiv (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv, arg, quo; @@ -2826,7 +2826,7 @@ static moo_pfrc_t pf_integer_quo2 (moo_t* moo, moo_ooi_t nargs) return MOO_PF_SUCCESS; } -static moo_pfrc_t pf_integer_rem2 (moo_t* moo, moo_ooi_t nargs) +static moo_pfrc_t pf_integer_mod (moo_t* moo, moo_ooi_t nargs) { moo_oop_t rcv, arg, quo, rem; @@ -3523,19 +3523,19 @@ static pf_t pftab[] = { "_integer_bitor", { pf_integer_bitor, 1, 1 } }, { "_integer_bitshift", { pf_integer_bitshift, 1, 1 } }, { "_integer_bitxor", { pf_integer_bitxor, 1, 1 } }, + { "_integer_div", { pf_integer_div, 1, 1 } }, { "_integer_eq", { pf_integer_eq, 1, 1 } }, { "_integer_ge", { pf_integer_ge, 1, 1 } }, { "_integer_gt", { pf_integer_gt, 1, 1 } }, { "_integer_inttostr", { pf_integer_inttostr, 1, 1 } }, { "_integer_le", { pf_integer_le, 1, 1 } }, { "_integer_lt", { pf_integer_lt, 1, 1 } }, + { "_integer_mdiv", { pf_integer_mdiv, 1, 1 } }, + { "_integer_mod", { pf_integer_mod, 1, 1 } }, { "_integer_mul", { pf_integer_mul, 1, 1 } }, { "_integer_ne", { pf_integer_ne, 1, 1 } }, { "_integer_negated", { pf_integer_negated, 0, 0 } }, - { "_integer_quo", { pf_integer_quo, 1, 1 } }, - { "_integer_quo2", { pf_integer_quo2, 1, 1 } }, { "_integer_rem", { pf_integer_rem, 1, 1 } }, - { "_integer_rem2", { pf_integer_rem2, 1, 1 } }, { "_integer_sub", { pf_integer_sub, 1, 1 } } }; diff --git a/moo/lib/logfmt.c b/moo/lib/logfmt.c index 4b64a53..98a4d64 100644 --- a/moo/lib/logfmt.c +++ b/moo/lib/logfmt.c @@ -404,7 +404,7 @@ static int print_object (moo_t* moo, moo_oow_t mask, moo_oop_t oop, outbfmt_t ou } else if (MOO_OOP_IS_ERROR(oop)) { - if (outbfmt(moo, mask, "error(%zd)", MOO_OOP_TO_ERROR(oop)) <= -1) return -1; + if (outbfmt(moo, mask, "#\\%zd", MOO_OOP_TO_ERROR(oop)) <= -1) return -1; } else { diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index 7ab824b..723a1be 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -331,9 +331,8 @@ enum moo_iotok_type_t MOO_IOTOK_SYMLIT, MOO_IOTOK_NUMLIT, MOO_IOTOK_RADNUMLIT, - MOO_IOTOK_ERRLIT, /* error(NN) */ + MOO_IOTOK_ERRLIT, /* #\NN */ - MOO_IOTOK_ERROR, /* error */ MOO_IOTOK_NIL, MOO_IOTOK_SELF, MOO_IOTOK_SUPER, diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 9594eda..ef44477 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -1541,7 +1541,7 @@ enum moo_synerrnum_t MOO_SYNERR_CMTNC, /* comment not closed */ MOO_SYNERR_STRNC, /* string not closed */ MOO_SYNERR_CLTNT, /* character literal not terminated */ - MOO_SYNERR_HLTNT, /* hased literal not terminated */ + MOO_SYNERR_HLTNT, /* hashed literal not terminated */ MOO_SYNERR_CHARLITINVAL, /* wrong character literal */ MOO_SYNERR_COLON, /* : expected */ MOO_SYNERR_STRING, /* string expected */