diff --git a/lib/cnode.c b/lib/cnode.c index 59c5d00..b57587a 100644 --- a/lib/cnode.c +++ b/lib/cnode.c @@ -24,7 +24,7 @@ #include "hcl-prv.h" -static hcl_cnode_t* make_cnode (hcl_t* hcl, hcl_cnode_type_t type, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) +hcl_cnode_t* hcl_makecnode (hcl_t* hcl, hcl_cnode_type_t type, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { hcl_cnode_t* cnode; hcl_oocs_t empty; @@ -53,67 +53,67 @@ static hcl_cnode_t* make_cnode (hcl_t* hcl, hcl_cnode_type_t type, int flags, co hcl_cnode_t* hcl_makecnodenil (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_NIL, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_NIL, flags, loc, tok); } hcl_cnode_t* hcl_makecnodetrue (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_TRUE, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_TRUE, flags, loc, tok); } hcl_cnode_t* hcl_makecnodefalse (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_FALSE, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_FALSE, flags, loc, tok); } hcl_cnode_t* hcl_makecnodeself (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_SELF, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_SELF, flags, loc, tok); } hcl_cnode_t* hcl_makecnodesuper (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_SUPER, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_SUPER, flags, loc, tok); } hcl_cnode_t* hcl_makecnodeellipsis (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_ELLIPSIS, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_ELLIPSIS, flags, loc, tok); } hcl_cnode_t* hcl_makecnodetrpcolons (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_TRPCOLONS, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_TRPCOLONS, flags, loc, tok); } hcl_cnode_t* hcl_makecnodedblcolons (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_DBLCOLONS, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_DBLCOLONS, flags, loc, tok); } hcl_cnode_t* hcl_makecnodecolon (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_COLON, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_COLON, flags, loc, tok); } hcl_cnode_t* hcl_makecnodecolongt (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_COLONGT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_COLONGT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodecolonlt (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_COLONLT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_COLONLT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodecolonstar (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_COLONSTAR, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_COLONSTAR, flags, loc, tok); } hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, hcl_ooch_t v) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_CHARLIT, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_CHARLIT, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.charlit.v = v; return c; @@ -121,7 +121,7 @@ hcl_cnode_t* hcl_makecnodecharlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_cnode_t* hcl_makecnodebchrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, hcl_oob_t v) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_BCHRLIT, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_BCHRLIT, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.bchrlit.v = v; return c; @@ -129,7 +129,7 @@ hcl_cnode_t* hcl_makecnodebchrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_SYMBOL, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_SYMBOL, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.symbol.syncode = hcl_getsyncodebyoocs_noseterr(hcl, tok); return c; @@ -137,7 +137,7 @@ hcl_cnode_t* hcl_makecnodesymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, c hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, int is_cla) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_DSYMBOL, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_DSYMBOL, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.dsymbol.is_cla = is_cla; return c; @@ -145,32 +145,32 @@ hcl_cnode_t* hcl_makecnodedsymbol (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_cnode_t* hcl_makecnodestrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_STRLIT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_STRLIT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodebstrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_BSTRLIT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_BSTRLIT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodenumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_NUMLIT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_NUMLIT, flags, loc, tok); } hcl_cnode_t* hcl_makecnoderadnumlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_RADNUMLIT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_RADNUMLIT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodefpdeclit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok) { - return make_cnode(hcl, HCL_CNODE_FPDECLIT, flags, loc, tok); + return hcl_makecnode(hcl, HCL_CNODE_FPDECLIT, flags, loc, tok); } hcl_cnode_t* hcl_makecnodesmptrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, hcl_oow_t v) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_SMPTRLIT, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_SMPTRLIT, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.smptrlit.v = v; return c; @@ -178,7 +178,7 @@ hcl_cnode_t* hcl_makecnodesmptrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_cnode_t* hcl_makecnodeerrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, hcl_ooi_t v) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_ERRLIT, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_ERRLIT, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.errlit.v = v; return c; @@ -186,7 +186,7 @@ hcl_cnode_t* hcl_makecnodeerrlit (hcl_t* hcl, int flags, const hcl_loc_t* loc, c hcl_cnode_t* hcl_makecnodecons (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok, hcl_cnode_t* car, hcl_cnode_t* cdr) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_CONS, flags, loc, tok); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_CONS, flags, loc, tok); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.cons.car = car; c->u.cons.cdr = cdr; @@ -195,7 +195,7 @@ hcl_cnode_t* hcl_makecnodecons (hcl_t* hcl, int flags, const hcl_loc_t* loc, con hcl_cnode_t* hcl_makecnodeelist (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_concode_t type) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_ELIST, flags, loc, HCL_NULL); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_ELIST, flags, loc, HCL_NULL); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.elist.concode = type; return c; @@ -203,7 +203,7 @@ hcl_cnode_t* hcl_makecnodeelist (hcl_t* hcl, int flags, const hcl_loc_t* loc, hc hcl_cnode_t* hcl_makecnodeshell (hcl_t* hcl, int flags, const hcl_loc_t* loc, hcl_cnode_t* obj) { - hcl_cnode_t* c = make_cnode(hcl, HCL_CNODE_SHELL, flags, loc, HCL_NULL); + hcl_cnode_t* c = hcl_makecnode(hcl, HCL_CNODE_SHELL, flags, loc, HCL_NULL); if (HCL_UNLIKELY(!c)) return HCL_NULL; c->u.shell.obj = obj; return c; diff --git a/lib/comp.c b/lib/comp.c index 137121d..36a5833 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -487,6 +487,12 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl } /* there are special words that can't start a new expression */ + if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELIF) || + HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELSE)) + { + goto no_block; + } + if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELIF) || HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELSE) || HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_CATCH)) @@ -506,6 +512,8 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl if (for_what == FOR_IF) { /* after the body for `if` or `elif`, there can come `elif` or `else` */ + if (HCL_CNODE_IS_TYPED(nxt, HCL_CNODE_ELIF) || + HCL_CNODE_IS_TYPED(nxt, HCL_CNODE_ELSE)) goto ok; if (HCL_CNODE_IS_SYMBOL(nxt)) { int syncode = HCL_CNODE_SYMBOL_SYNCODE(nxt); @@ -2297,7 +2305,7 @@ static int compile_if (hcl_t* hcl, hcl_cnode_t* src) hcl_cframe_t* cf; HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_IF)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_IF) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_IF)); /* (if (< 20 30) * (perform this) @@ -2407,7 +2415,7 @@ static HCL_INLINE int compile_elif (hcl_t* hcl) src = cf->operand; HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_ELIF)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_ELIF) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_ELIF)); cmd = HCL_CNODE_CONS_CAR(src); /* elif itself */ obj = HCL_CNODE_CONS_CDR(src); @@ -2448,7 +2456,7 @@ static HCL_INLINE int compile_else (hcl_t* hcl) src = cf->operand; HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(src)); - HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_ELSE)); + HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(HCL_CNODE_CONS_CAR(src), HCL_SYNCODE_ELSE) || HCL_CNODE_IS_TYPED(HCL_CNODE_CONS_CAR(src), HCL_CNODE_ELSE)); cmd = HCL_CNODE_CONS_CAR(src); /* else itself */ obj = HCL_CNODE_CONS_CDR(src); @@ -3891,7 +3899,21 @@ static int compile_cons_xlist_expression (hcl_t* hcl, hcl_cnode_t* obj, int nret HCL_ASSERT (hcl, HCL_CNODE_IS_CONS_CONCODED(obj, HCL_CONCODE_XLIST)); car = HCL_CNODE_CONS_CAR(obj); - if (HCL_CNODE_IS_SYMBOL(car) && (syncode = HCL_CNODE_SYMBOL_SYNCODE(car))) + if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_IF)) + { + if (compile_if(hcl, obj) <= -1) return -1; + } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELIF)) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELSE, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "else without if"); + return -1; + } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELSE)) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELIF, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "elif without if"); + return -1; + } + else if (HCL_CNODE_IS_SYMBOL(car) && (syncode = HCL_CNODE_SYMBOL_SYNCODE(car))) { if (nrets > 0) { @@ -3911,7 +3933,7 @@ static int compile_cons_xlist_expression (hcl_t* hcl, hcl_cnode_t* obj, int nret break; case HCL_SYNCODE_CATCH: - hcl_setsynerrbfmt (hcl, HCL_SYNERR_ELIF, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "catch without try"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_CATCH, HCL_CNODE_GET_LOC(car), HCL_CNODE_GET_TOK(car), "catch without try"); return -1; case HCL_SYNCODE_CLASS: @@ -4926,7 +4948,17 @@ static int compile_object_list (hcl_t* hcl) if (cop == COP_COMPILE_IF_OBJECT_LIST || cop == COP_COMPILE_IF_OBJECT_LIST_TAIL) { - if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELIF)) + if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELIF)) + { + SWITCH_TOP_CFRAME (hcl, COP_COMPILE_ELIF, oprnd); + goto done; + } + else if (HCL_CNODE_IS_TYPED(car, HCL_CNODE_ELSE)) + { + SWITCH_TOP_CFRAME (hcl, COP_COMPILE_ELSE, oprnd); + goto done; + } + else if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELIF)) { SWITCH_TOP_CFRAME (hcl, COP_COMPILE_ELIF, oprnd); goto done; diff --git a/lib/err.c b/lib/err.c index dfb33f8..22407c8 100644 --- a/lib/err.c +++ b/lib/err.c @@ -157,6 +157,7 @@ static char* synerrstr[] = "elif without if", "else without if", + "catch without try", "break outside loop", "invalid callable", diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 5b7b289..701ad9e 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -294,12 +294,17 @@ enum hcl_tok_type_t HCL_TOK_FPDECLIT, HCL_TOK_SMPTRLIT, HCL_TOK_ERRLIT, + HCL_TOK_NIL, HCL_TOK_TRUE, HCL_TOK_FALSE, HCL_TOK_SELF, HCL_TOK_SUPER, + HCL_TOK_IF, + HCL_TOK_ELIF, + HCL_TOK_ELSE, + HCL_TOK_BINOP, HCL_TOK_IDENT, HCL_TOK_IDENT_DOTTED, @@ -374,11 +379,16 @@ enum hcl_cnode_type_t HCL_CNODE_FPDECLIT, HCL_CNODE_SMPTRLIT, HCL_CNODE_ERRLIT, + HCL_CNODE_NIL, HCL_CNODE_TRUE, HCL_CNODE_FALSE, HCL_CNODE_SELF, HCL_CNODE_SUPER, + HCL_CNODE_IF, + HCL_CNODE_ELIF, + HCL_CNODE_ELSE, + HCL_CNODE_ELLIPSIS, HCL_CNODE_TRPCOLONS, HCL_CNODE_DBLCOLONS, /* :: */ @@ -406,6 +416,8 @@ typedef enum hcl_cnode_flag_t hcl_cnode_flag_t; #define HCL_CNODE_GET_TOKPTR(x) ((x)->cn_tok.ptr) #define HCL_CNODE_GET_TOKLEN(x) ((x)->cn_tok.len) +#define HCL_CNODE_IS_TYPED(x, _type) ((x)->cn_type == _type) + #define HCL_CNODE_IS_ELLIPSIS(x) ((x)->cn_type == HCL_CNODE_ELLIPSIS) #define HCL_CNODE_IS_TRPCOLONS(x) ((x)->cn_type == HCL_CNODE_TRPCOLONS) #define HCL_CNODE_IS_DBLCOLONS(x) ((x)->cn_type == HCL_CNODE_DBLCOLONS) @@ -1953,6 +1965,7 @@ int hcl_copy_string_to ( /* ========================================================================= */ /* cnode.c */ /* ========================================================================= */ +hcl_cnode_t* hcl_makecnode (hcl_t* hcl, hcl_cnode_type_t type, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodenil (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodetrue (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); hcl_cnode_t* hcl_makecnodefalse (hcl_t* hcl, int flags, const hcl_loc_t* loc, const hcl_oocs_t* tok); diff --git a/lib/hcl.h b/lib/hcl.h index 0f032cf..e1c3007 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -161,6 +161,7 @@ enum hcl_synerrnum_t HCL_SYNERR_ELIF, /* elif without if */ HCL_SYNERR_ELSE, /* else without if */ + HCL_SYNERR_CATCH, /* catch outside try */ HCL_SYNERR_BREAK, /* break outside loop */ HCL_SYNERR_CALLABLE, /* invalid callable */ diff --git a/lib/read.c b/lib/read.c index aff2b6c..bd7e0cd 100644 --- a/lib/read.c +++ b/lib/read.c @@ -58,6 +58,10 @@ static struct voca_t { 4, { 's','e','l','f' } }, { 5, { 's','u','p','e','r' } }, + { 2, { 'i','f' } }, + { 4, { 'e','l','i','f' } }, + { 4, { 'e','l','s','e' } }, + { 3, { 's','e','t' } }, { 5, { 's','e','t','-','r' } }, @@ -100,6 +104,10 @@ enum voca_id_t VOCA_KW_SELF, VOCA_KW_SUPER, + VOCA_KW_IF, + VOCA_KW_ELIF, + VOCA_KW_ELSE, + VOCA_SYM_SET, VOCA_SYM_SET_R, @@ -407,7 +415,11 @@ static hcl_tok_type_t classify_ident_token (hcl_t* hcl, const hcl_oocs_t* v) { VOCA_KW_TRUE, HCL_TOK_TRUE }, { VOCA_KW_FALSE, HCL_TOK_FALSE }, { VOCA_KW_SELF, HCL_TOK_SELF }, - { VOCA_KW_SUPER, HCL_TOK_SUPER } + { VOCA_KW_SUPER, HCL_TOK_SUPER }, + + { VOCA_KW_IF, HCL_TOK_IF }, + { VOCA_KW_ELIF, HCL_TOK_ELIF }, + { VOCA_KW_ELSE, HCL_TOK_ELSE } }; for (i = 0; i < HCL_COUNTOF(tab); i++) @@ -1215,6 +1227,23 @@ static int auto_forge_xlist_if_at_block_beginning (hcl_t* hcl, hcl_frd_t* frd) return 0; } +static hcl_cnode_type_t kw_to_cnode_type (int tok_type) +{ + static hcl_cnode_type_t mapping[] = { + HCL_CNODE_NIL, + HCL_CNODE_TRUE, + HCL_CNODE_FALSE, + HCL_CNODE_SELF, + HCL_CNODE_SUPER, + + HCL_CNODE_IF, + HCL_CNODE_ELIF, + HCL_CNODE_ELSE, + }; + + return mapping[tok_type - HCL_TOK_NIL]; +} + static int feed_process_token (hcl_t* hcl) { hcl_frd_t* frd = &hcl->c->feed.rd; @@ -1612,24 +1641,16 @@ static int feed_process_token (hcl_t* hcl) } case HCL_TOK_NIL: - frd->obj = hcl_makecnodenil(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); - goto auto_xlist; - case HCL_TOK_TRUE: - frd->obj = hcl_makecnodetrue(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); - goto auto_xlist; - case HCL_TOK_FALSE: - frd->obj = hcl_makecnodefalse(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); - goto auto_xlist; - case HCL_TOK_SELF: - frd->obj = hcl_makecnodeself(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); + case HCL_TOK_SUPER: + case HCL_TOK_IF: + case HCL_TOK_ELIF: + case HCL_TOK_ELSE: + frd->obj = hcl_makecnode(hcl, kw_to_cnode_type(TOKEN_TYPE(hcl)), 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); goto auto_xlist; - case HCL_TOK_SUPER: - frd->obj = hcl_makecnodesuper(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); - goto auto_xlist; case HCL_TOK_ELLIPSIS: frd->obj = hcl_makecnodeellipsis(hcl, 0, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); diff --git a/mod/core.c b/mod/core.c index 1df918f..3706f65 100644 --- a/mod/core.c +++ b/mod/core.c @@ -61,9 +61,56 @@ static hcl_pfrc_t pf_core_basic_new (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs return HCL_PF_SUCCESS; } -static hcl_oop_t unchecked_basic_at (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t index) +static hcl_pfrc_t __basic_at (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs, int span_fixed) { - hcl_oop_t val; + hcl_oop_t obj, val; + hcl_oop_t pos; + hcl_oow_t index; + hcl_oop_class_t _class; + + obj = HCL_STACK_GETARG(hcl, nargs, 0); + pos = HCL_STACK_GETARG(hcl, nargs, 1); + + if (!HCL_OOP_IS_POINTER(obj) || !HCL_OBJ_GET_FLAGS_FLEXI(obj)) + { + unindexable: + /* the receiver is a special numeric object or a non-indexable object */ + hcl_seterrbfmt (hcl, HCL_EINVAL, "receiver not indexable - %O", obj); + return HCL_PF_FAILURE; + } + + if (hcl_inttooow_noseterr(hcl, pos, &index) <= 0) + { + /* negative integer or not integer */ + hcl_seterrbfmt (hcl, HCL_EINVAL, "position not valid - %O", pos); + return HCL_PF_FAILURE; + } + + _class = (hcl_oop_class_t)HCL_CLASSOF(hcl, obj); + + if (span_fixed) + { + hcl_oow_t size; + size = HCL_OBJ_GET_SIZE(obj); + if (index >= size) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)size); + return HCL_PF_FAILURE; + } + } + else + { + hcl_oow_t fixed, flexi; + + fixed = HCL_CLASS_SPEC_NAMED_INSTVARS(_class->spec); + flexi = HCL_OBJ_GET_SIZE(obj) - fixed; + if (index >= flexi) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)flexi); + return HCL_PF_FAILURE; + } + index += fixed; + } switch (HCL_OBJ_GET_FLAGS_TYPE(obj)) { @@ -89,74 +136,39 @@ static hcl_oop_t unchecked_basic_at (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t index) case HCL_OBJ_TYPE_HALFWORD: val = hcl_oowtoint(hcl, HCL_OBJ_GET_HALFWORD_VAL(obj, index)); - if (HCL_UNLIKELY(!val)) return HCL_NULL; + if (HCL_UNLIKELY(!val)) return HCL_PF_FAILURE; break; case HCL_OBJ_TYPE_WORD: val = hcl_oowtoint(hcl, HCL_OBJ_GET_WORD_VAL(obj, index)); - if (HCL_UNLIKELY(!val)) return HCL_NULL; + if (HCL_UNLIKELY(!val)) return HCL_PF_FAILURE; break; default: - hcl_seterrbfmt (hcl, HCL_EINVAL, "receiver not indexable - %O", obj); - val = HCL_NULL; - break; + goto unindexable; } - return val; -} - - -static hcl_pfrc_t pf_core_basic_at (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) -{ - hcl_oop_t obj, val; - hcl_oop_t pos; - hcl_oow_t index; - hcl_oop_class_t _class; - hcl_oow_t fixed, flexi; - - obj = HCL_STACK_GETARG(hcl, nargs, 0); - pos = HCL_STACK_GETARG(hcl, nargs, 1); - - if (!HCL_OOP_IS_POINTER(obj) || !HCL_OBJ_GET_FLAGS_FLEXI(obj)) - { - unindexable: - /* the receiver is a special numeric object or a non-indexable object */ - hcl_seterrbfmt (hcl, HCL_EINVAL, "receiver not indexable - %O", obj); - return HCL_PF_FAILURE; - } - - if (hcl_inttooow_noseterr(hcl, pos, &index) <= 0) - { - /* negative integer or not integer */ - hcl_seterrbfmt (hcl, HCL_EINVAL, "position not valid - %O", pos); - return HCL_PF_FAILURE; - } - - _class = (hcl_oop_class_t)HCL_CLASSOF(hcl, obj); - fixed = HCL_CLASS_SPEC_NAMED_INSTVARS(_class->spec); - flexi = HCL_OBJ_GET_SIZE(obj) - fixed; - if (index >= flexi) - { - hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)HCL_OBJ_GET_SIZE(obj)); - return HCL_PF_FAILURE; - } - index += fixed; - - val = unchecked_basic_at(hcl, obj, index); - if (HCL_UNLIKELY(!val)) return HCL_PF_FAILURE; HCL_STACK_SETRET (hcl, nargs, val); return HCL_PF_SUCCESS; } -static hcl_pfrc_t pf_core_basic_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +static hcl_pfrc_t pf_core_basic_at (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + return __basic_at(hcl, mod, nargs, 0); +} + +static hcl_pfrc_t pf_core_prim_at (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + return __basic_at(hcl, mod, nargs, 1); +} + +static hcl_pfrc_t __basic_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs, int span_fixed) { hcl_oop_t obj, val; hcl_oop_t pos; hcl_oow_t index; hcl_oop_class_t _class; - hcl_oow_t fixed, flexi; obj = HCL_STACK_GETARG(hcl, nargs, 0); pos = HCL_STACK_GETARG(hcl, nargs, 1); @@ -177,18 +189,28 @@ static hcl_pfrc_t pf_core_basic_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t na } _class = (hcl_oop_class_t)HCL_CLASSOF(hcl, obj); - fixed = HCL_CLASS_SPEC_NAMED_INSTVARS(_class->spec); - flexi = HCL_OBJ_GET_SIZE(obj) - fixed; - if (index >= flexi) + if (span_fixed) { - hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)HCL_OBJ_GET_SIZE(obj)); - return HCL_PF_FAILURE; + hcl_oow_t size; + size = HCL_OBJ_GET_SIZE(obj); + if (index >= size) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)size); + return HCL_PF_FAILURE; + } } - index += fixed; - if (index >= HCL_OBJ_GET_SIZE(obj)) + else { - hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)HCL_OBJ_GET_SIZE(obj)); - return HCL_PF_FAILURE; + hcl_oow_t fixed, flexi; + + fixed = HCL_CLASS_SPEC_NAMED_INSTVARS(_class->spec); + flexi = HCL_OBJ_GET_SIZE(obj) - fixed; + if (index >= flexi) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "position(%zd) out of range - negative or greater than or equal to %zu", index, (hcl_ooi_t)HCL_OBJ_GET_SIZE(obj)); + return HCL_PF_FAILURE; + } + index += fixed; } switch (HCL_OBJ_GET_FLAGS_TYPE(obj)) @@ -241,13 +263,23 @@ static hcl_pfrc_t pf_core_basic_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t na default: goto unindexable; - break; } + HCL_STACK_SETRET (hcl, nargs, val); return HCL_PF_SUCCESS; } +static hcl_pfrc_t pf_core_basic_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + return __basic_at_put(hcl, mod, nargs, 0); +} + +static hcl_pfrc_t pf_core_prim_at_put (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + return __basic_at_put(hcl, mod, nargs, 1); +} + static hcl_pfrc_t pf_core_basic_size (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) { hcl_oop_oop_t src; @@ -417,6 +449,8 @@ static hcl_pfinfo_t pfinfos[] = { "className", { HCL_PFBASE_FUNC, pf_core_class_name, 1, 1 } }, { "classRespondsTo", { HCL_PFBASE_FUNC, pf_core_class_responds_to, 2, 2 } }, { "instRespondsTo", { HCL_PFBASE_FUNC, pf_core_inst_responds_to, 2, 2 } }, + { "primAt", { HCL_PFBASE_FUNC, pf_core_prim_at, 2, 2 } }, + { "primAtPut", { HCL_PFBASE_FUNC, pf_core_prim_at_put, 3, 3 } }, { "slice", { HCL_PFBASE_FUNC, pf_core_slice, 3, 3 } } }; diff --git a/src/kernel.hcl b/src/kernel.hcl index 7ff3740..c74cb62 100644 --- a/src/kernel.hcl +++ b/src/kernel.hcl @@ -11,6 +11,14 @@ class Apex { return (core.instRespondsTo self mth) } + fun primAt(pos) { + return (core.primAt self pos) + } + + fun primtAtPut(pos value) { + return (core.primAtPut self pos value) + } + fun basicAt(pos) { return (core.basicAt self pos) } @@ -158,15 +166,15 @@ printf "----------------------------------------\n" k := #[1 2 3] printf "%O\n" (k:basicAt 2) -class X :: Object [ a b c ] { +class Z :: Object [ a b c ] { fun :* new() { self.a := 10 self.b := 20 self.c := 30 } } -##k := (X:basicNew 0) -k := (X:new) +##k := (Z:basicNew 0) +k := (Z:new) printf "%O\n" (k:basicAt 2) diff --git a/t/call-5001.err b/t/call-5001.err index 61d5ddf..0917bb7 100644 --- a/t/call-5001.err +++ b/t/call-5001.err @@ -27,11 +27,11 @@ if (< 2 3) {} elif true else ##ERROR: syntax error - block expression expected --- -if else ##ERROR: syntax error - special symbol not to be used as variable name +if else ##ERROR: syntax error - prohibited in this context - else --- -if elif else ##ERROR: syntax error - special symbol not to be used as variable name +if elif else ##ERROR: syntax error - prohibited in this context - elif ---