diff --git a/lib/cnode.c b/lib/cnode.c index fc8b41c..c366cdc 100644 --- a/lib/cnode.c +++ b/lib/cnode.c @@ -135,6 +135,11 @@ hak_cnode_t* hak_makecnodedsymbol (hak_t* hak, int flags, const hak_loc_t* loc, return c; } +hak_cnode_t* hak_makecnodebinop (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok) +{ + return hak_makecnode(hak, HAK_CNODE_BINOP, flags, loc, tok); +} + hak_cnode_t* hak_makecnodestrlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok) { return hak_makecnode(hak, HAK_CNODE_STRLIT, flags, loc, tok); diff --git a/lib/comp.c b/lib/comp.c index 640ae31..ab0b8b7 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -71,26 +71,25 @@ enum /* -------------------------------------------- +fun plus(x y) { + printf "plus %d %d\n" x y + fun minus(x y) { + printf "minus %d %d\n" x y + - x y + } + + x y +} -(fun plus(x y) - (printf "plus %d %d\n" x y) - (fun minus(x y) - (printf "minus %d %d\n" x y) - (- x y) - ) - (+ x y) -) +fun dummy(q) { + printf "%s\n" q +} -(fun dummy(q) - (printf "%s\n" q) -) +plus 10 20 ## minus is now available after plus is executed +minus 10 1 -(plus 10 20) - <---- minus is now available -(minus 10 1) literals --> // -// characeter 'A' +// character 'A' // "string" // B"byte string" <-- not yet implemented // array ---> #[ ] or [ ] ? constant or not? dynamic??? @@ -459,7 +458,7 @@ HAK_INFO6(hak, "FOUND CLASS VAR [%.*js]...[%.*js]................ ===> ctx_offse /* this condition indicates that the current function level contains a class defintion * and this variable is looked up inside the class defintion */ HAK_INFO2(hak, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); - vi->type = VAR_CLASS;//_NAMED; // TODO: create VAR_CLASS_NAMED??? + vi->type = VAR_CLASS;/*_NAMED;*/ // TODO: create VAR_CLASS_NAMED??? vi->ctx_offset = 0; vi->index_in_ctx = 0; } @@ -1546,7 +1545,7 @@ static int collect_vardcl_for_class (hak_t* hak, hak_cnode_t* obj, hak_cnode_t** goto next; } - if (!HAK_CNODE_IS_SYMBOL(var) || HAK_CNODE_IS_SYMBOL_BINOP(var)) goto synerr_varname; + if (!HAK_CNODE_IS_SYMBOL(var) /*|| HAK_CNODE_IS_SYMBOL_BINOP(var)*/) goto synerr_varname; checkpoint = hak->c->tv.s.len; n = add_temporary_variable(hak, var, tv_slen_saved, desc[enclosed], HAK_NULL); @@ -1790,7 +1789,9 @@ enum COP_EMIT_POP_INTO_CONS_CDR, COP_EMIT_FUN, +#if defined(USE_KW_PLUS) COP_EMIT_PLUS, +#endif COP_EMIT_POP_STACKTOP, COP_EMIT_RETURN, COP_EMIT_SET, @@ -2004,6 +2005,7 @@ static HAK_INLINE int compile_or_p2 (hak_t* hak) /* ========================================================================= */ +#if defined(USE_KW_PLUS) /* EXPERIMENT WITH BINOP */ static int compile_plus (hak_t* hak, hak_cnode_t* src) { @@ -2068,6 +2070,7 @@ static HAK_INLINE int emit_plus (hak_t* hak) POP_CFRAME(hak); return 0; } +#endif /* ========================================================================= */ @@ -2819,7 +2822,7 @@ static int compile_class (hak_t* hak, hak_cnode_t* src) check_class_name: if (HAK_CNODE_IS_FOR_DATA_SIMPLE(tmp) || HAK_CNODE_IS_FOR_LANG(tmp)) { - if (!HAK_CNODE_IS_SYMBOL_IDENT(tmp)) + if (!HAK_CNODE_IS_SYMBOL(tmp)) { hak_setsynerrbfmt( hak, HAK_SYNERR_CLASS, HAK_CNODE_GET_LOC(tmp), HAK_NULL, @@ -3295,7 +3298,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) tmp = HAK_CNODE_CONS_CAR(next); } - if (HAK_CNODE_IS_SYMBOL(tmp)) + if (HAK_CNODE_IS_SYMBOL(tmp) || HAK_CNODE_IS_BINOP(tmp)) { /* 'fun' followed by name */ fun_got_name: @@ -3332,7 +3335,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) } tmp = HAK_CNODE_CONS_CAR(next); - if (!HAK_CNODE_IS_SYMBOL(tmp)) + if (!HAK_CNODE_IS_SYMBOL(tmp) && !HAK_CNODE_IS_BINOP(tmp)) { hak_setsynerrbfmt( hak, HAK_SYNERR_FUN, HAK_CNODE_GET_LOC(tmp), HAK_NULL, @@ -3543,7 +3546,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) if (in_ret_args) { - if (!HAK_CNODE_IS_SYMBOL_IDENT(arg)) + if (!HAK_CNODE_IS_SYMBOL(arg)) { /* in 'fun x (x :: 20) { }', '20' is not a valid return variable name. * in 'fun x (x :: if) { }', 'if' is not a valid return variable name. */ @@ -3586,7 +3589,7 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) { va = 1; } - else if (!HAK_CNODE_IS_SYMBOL_IDENT(arg)) + else if (!HAK_CNODE_IS_SYMBOL(arg)) { hak_setsynerrbfmt( hak, HAK_SYNERR_ARGNAME, HAK_CNODE_GET_LOC(arg), HAK_NULL, @@ -3615,6 +3618,18 @@ static int compile_fun (hak_t* hak, hak_cnode_t* src) while (1); } + if ((fun_type & 0xFF) == FUN_IM && fun_name && HAK_CNODE_IS_BINOP(fun_name) && (is_in_class_init_scope(hak) || class_name) && nargs != 1) + { + hak_setsynerrbfmt( + hak, HAK_SYNERR_ARGCOUNT, HAK_CNODE_GET_LOC(arg_list), HAK_NULL, + "only one argument expected for '%.*js%hs%.*js'", + (class_name? HAK_CNODE_GET_TOKLEN(class_name): 0), + (class_name? HAK_CNODE_GET_TOKPTR(class_name): HAK_NULL), + (class_name? ":": ""), + HAK_CNODE_GET_TOKLEN(fun_name), HAK_CNODE_GET_TOKPTR(fun_name)); + return -1; + } + if (nargs > MAX_CODE_NBLKARGS) /*TODO: change this limit to max call argument count */ { /* while an integer object is pused to indicate the number of @@ -3860,7 +3875,7 @@ static int compile_var (hak_t* hak, hak_cnode_t* src) tmp = HAK_CNODE_CONS_CAR(next); } - if (HAK_CNODE_IS_SYMBOL_IDENT(tmp)) + if (HAK_CNODE_IS_SYMBOL(tmp)) { unsigned int var_type = VAR_INST; @@ -3901,7 +3916,7 @@ static int compile_var (hak_t* hak, hak_cnode_t* src) next = HAK_CNODE_CONS_CDR(next); if (!next) break; tmp = HAK_CNODE_CONS_CAR(next); - if (!HAK_CNODE_IS_SYMBOL_IDENT(tmp)) goto not_ident; + if (!HAK_CNODE_IS_SYMBOL(tmp)) goto not_ident; } } else @@ -4136,7 +4151,7 @@ static int compile_set_r (hak_t* hak, hak_cnode_t* src) do { var = HAK_CNODE_CONS_CAR(obj); - if (!HAK_CNODE_IS_SYMBOL(var)) /* TODO: should this be HAK_CNODE_IS_SYMBOL(var)?? */ + if (!HAK_CNODE_IS_SYMBOL(var)) { if (nvars > 0) break; hak_setsynerrbfmt(hak, HAK_SYNERR_VARNAME, HAK_CNODE_GET_LOC(var), HAK_CNODE_GET_TOK(var), "variable name not symbol in %.*js", HAK_CNODE_GET_TOKLEN(cmd), HAK_CNODE_GET_TOKPTR(cmd)); @@ -4883,9 +4898,11 @@ static int compile_cons_xlist_expression (hak_t* hak, hak_cnode_t* obj, int nret if (compile_or(hak, obj) <= -1) return -1; goto done; +#if defined(USE_KW_PLUS) case HAK_CNODE_PLUS: if (compile_plus(hak, obj) <= -1) return -1; goto done; +#endif case HAK_CNODE_SET: if (compile_set(hak, obj) <= -1) return -1; @@ -4896,7 +4913,9 @@ static int compile_cons_xlist_expression (hak_t* hak, hak_cnode_t* obj, int nret goto done; } - if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_DSYMBOL(car) || + if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_DSYMBOL(car) || HAK_CNODE_IS_BINOP(car) || + HAK_CNODE_IS_STRLIT(car) || /* this condition to represent an external program TODO: change this to a dedicated cnode */ + HAK_CNODE_IS_SYMLIT(car) || /* this condition to represent an external program TODO: change this to a dedicated cnode */ HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_XLIST) || HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_MLIST) || HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_BLIST) || @@ -4947,7 +4966,7 @@ static int compile_cons_xlist_expression (hak_t* hak, hak_cnode_t* obj, int nret } } - if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_DSYMBOL(car)) + if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_DSYMBOL(car) || HAK_CNODE_IS_BINOP(car)) { hak_oop_cons_t sdc; @@ -5038,14 +5057,34 @@ static int compile_cons_mlist_expression (hak_t* hak, hak_cnode_t* obj, hak_ooi_ return -1; } car = HAK_CNODE_CONS_CAR(cdr); - if (HAK_CNODE_IS_SYMBOL(car)) + if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_BINOP(car)) { + /* do not resolve the message itself to an associated value. + * treat it as if it's a literal. + * the actual message sending can be written with a symbol + * as well as a symbol literal in that sense. + * + * For this class definition + * class X { fun[#ci] new() {} } + * X:new is equivalent to X:#new + * + * If the method is a binop selector, + * class X { fun[#ci] +(a) {} } ## one argument is guaranteed by the reader + * the followings are equivalent. + * X + 20 + * X:#+ 20 + */ PUSH_CFRAME(hak, COP_EMIT_PUSH_SYMBOL, car); } + else if (HAK_CNODE_IS_SYMLIT(car) || HAK_CNODE_IS_STRLIT(car)) + { + PUSH_CFRAME(hak, COP_COMPILE_OBJECT, car); + } else { -/* TODO: more sanity check on what can be used as a method */ - PUSH_CFRAME(hak, COP_COMPILE_OBJECT, car); + hak_setsynerrbfmt(hak, HAK_SYNERR_MESSAGE, HAK_CNODE_GET_LOC(car), HAK_NULL, + "invalid message '%.*js'", HAK_CNODE_GET_TOKLEN(car), HAK_CNODE_GET_TOKPTR(car)); + return -1; } /* compile ... etc */ @@ -5071,31 +5110,6 @@ static int compile_cons_mlist_expression (hak_t* hak, hak_cnode_t* obj, hak_ooi_ } } -#if 0 - if (HAK_CNODE_IS_SYMBOL(car) || HAK_CNODE_IS_DSYMBOL(car)) - { - hak_oop_cons_t sdc; - - /* only symbols are added to the system dictionary. - * perform this lookup only if car is a symbol */ - sdc = hak_lookupsysdicforsymbol_noseterr(hak, HAK_CNODE_GET_TOK(car)); - if (sdc) - { - hak_oop_word_t sdv; - sdv = (hak_oop_word_t)HAK_CONS_CDR(sdc); - if (HAK_IS_PRIM(hak, sdv)) - { - if (nargs < sdv->slot[1] || nargs > sdv->slot[2]) - { - hak_setsynerrbfmt(hak, HAK_SYNERR_ARGCOUNT, HAK_CNODE_GET_LOC(car), HAK_NULL, - "parameters count(%zd) mismatch in function call - %.*js - expecting %zu-%zu parameters", nargs, HAK_CNODE_GET_TOKLEN(car), HAK_CNODE_GET_TOKPTR(car), sdv->slot[1], sdv->slot[2]); - return -1; - } - } - } - } -#endif - /* redundant cdr check is performed inside compile_object_list() */ PUSH_SUBCFRAME(hak, COP_COMPILE_ARGUMENT_LIST, cdr); @@ -5120,7 +5134,7 @@ static HAK_INLINE int compile_symbol (hak_t* hak, hak_cnode_t* obj) hak_var_info_t vi; int x; - HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(obj)); + HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(obj) || HAK_CNODE_IS_BINOP(obj)); /* check if a symbol is a local variable */ x = find_variable_backward_with_token(hak, obj, &vi); @@ -5598,6 +5612,7 @@ redo: lit = HAK_ERROR_TO_OOP(oprnd->u.errlit.v); goto literal; + case HAK_CNODE_BINOP: /* binop symbol. treat it like a normal symbol in the object context */ case HAK_CNODE_SYMBOL: /* symbol. but not a literal. usually a variable */ if (compile_symbol(hak, oprnd) <= -1) return -1; goto done; @@ -6626,7 +6641,7 @@ static HAK_INLINE int post_fun (hak_t* hak) hak_var_info_t vi; int x; - HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(fun_name)); + HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(fun_name) || HAK_CNODE_IS_BINOP(fun_name)); if (is_in_class_init_scope(hak)) { @@ -6804,7 +6819,7 @@ static HAK_INLINE int emit_set (hak_t* hak) hak_oow_t index; hak_oop_t cons, sym; - HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(cf->operand)); + HAK_ASSERT(hak, HAK_CNODE_IS_SYMBOL(cf->operand) || HAK_CNODE_IS_BINOP(cf->operand)); sym = hak_makesymbol(hak, HAK_CNODE_GET_TOKPTR(cf->operand), HAK_CNODE_GET_TOKLEN(cf->operand)); if (HAK_UNLIKELY(!sym)) return -1; @@ -7171,9 +7186,11 @@ int hak_compile (hak_t* hak, hak_cnode_t* obj, int flags) if (emit_fun(hak) <= -1) goto oops; break; +#if defined(USE_KW_PLUS) case COP_EMIT_PLUS: if (emit_plus(hak) <= -1) goto oops; break; +#endif case COP_EMIT_POP_STACKTOP: if (emit_pop_stacktop(hak) <= -1) goto oops; diff --git a/lib/err.c b/lib/err.c index d63695c..e3edd69 100644 --- a/lib/err.c +++ b/lib/err.c @@ -115,6 +115,7 @@ static const char* synerrstr[] = "} expected", "| expected", + "identifier expected", "string expected", "byte too small or too large", "nesting level too deep", @@ -161,6 +162,7 @@ static const char* synerrstr[] = "break outside loop", "invalid callable", + "invalid message", "unbalanced key/value pair", "unbalanced parenthesis/brace/bracket", "unexpected semicolon", diff --git a/lib/exec.c b/lib/exec.c index 5e1a016..599ec3c 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -25,6 +25,8 @@ #include "hak-prv.h" +#define ENABLE_SYSCMD + static const char* io_type_str[] = { "input", @@ -2145,23 +2147,23 @@ static HAK_INLINE int activate_function (hak_t* hak, hak_ooi_t nargs) /* ------------------------------------------------------------------------- */ static HAK_INLINE int call_primitive (hak_t* hak, hak_ooi_t nargs) { - hak_oop_prim_t rcv; + hak_oop_prim_t op_prim; - rcv = (hak_oop_prim_t)HAK_STACK_GETOP(hak, nargs); - HAK_ASSERT(hak, HAK_IS_PRIM(hak, rcv)); - HAK_ASSERT(hak, HAK_OBJ_GET_SIZE(rcv) == HAK_PRIM_NAMED_INSTVARS); + op_prim = (hak_oop_prim_t)HAK_STACK_GETOP(hak, nargs); + HAK_ASSERT(hak, HAK_IS_PRIM(hak, op_prim)); + HAK_ASSERT(hak, HAK_OBJ_GET_SIZE(op_prim) == HAK_PRIM_NAMED_INSTVARS); - if (nargs < rcv->min_nargs && nargs > rcv->max_nargs) + if (nargs < op_prim->min_nargs && nargs > op_prim->max_nargs) { /* TODO: include a primitive name... */ HAK_LOG3(hak, HAK_LOG_IC | HAK_LOG_ERROR, "Error - wrong number of arguments to a primitive - expecting %zd-%zd, got %zd\n", - rcv->min_nargs, rcv->max_nargs, nargs); + op_prim->min_nargs, op_prim->max_nargs, nargs); hak_seterrnum(hak, HAK_ECALLARG); return -1; } - return ((hak_pfimpl_t)rcv->impl)(hak, (hak_mod_t*)rcv->mod, nargs); + return ((hak_pfimpl_t)op_prim->impl)(hak, (hak_mod_t*)op_prim->mod, nargs); } /* ------------------------------------------------------------------------- */ @@ -2495,6 +2497,7 @@ static void supplement_errmsg (hak_t* hak, hak_ooi_t ip) HAK_ASSERT(hak, HAK_IS_BYTEARRAY(hak, hak->active_function->dbgi)); dbgi = (hak_dbgi_t*)HAK_OBJ_GET_BYTE_SLOT(hak->active_function->dbgi); + orgloc.line = dbgi[ip].sline; /* update the line of the location at least */ hak_seterrbfmtloc(hak, orgnum, &orgloc, "%js (%js:%zu)", orgmsg, (dbgi[ip].fname? dbgi[ip].fname: oocstr_dash), dbgi[ip].sline); @@ -2515,7 +2518,7 @@ static int do_throw_with_internal_errmsg (hak_t* hak, hak_ooi_t ip) /* ------------------------------------------------------------------------- */ -#if 0 +#if defined(ENABLE_SYSCMD) /* EXPERIMENTAL CODE INTEGRATING EXTERNAL COMMANDS */ #include @@ -2595,29 +2598,29 @@ done: static HAK_INLINE int exec_syscmd (hak_t* hak, hak_ooi_t nargs) { - hak_oop_word_t rcv; + hak_oop_word_t op_cmd; hak_bch_t* cmd = HAK_NULL; hak_bch_t* xcmd = HAK_NULL; - rcv = (hak_oop_word_t)HAK_STACK_GETOP(hak, nargs); - /*HAK_ASSERT(hak, HAK_IS_STRING(hak, rcv) || HAK_IS_SYMBOL(hak, rcv));*/ - HAK_ASSERT(hak, HAK_OBJ_IS_CHAR_POINTER(rcv)); + op_cmd = (hak_oop_word_t)HAK_STACK_GETOP(hak, nargs); + /*HAK_ASSERT(hak, HAK_IS_STRING(hak, op_cmd) || HAK_IS_SYMBOL(hak, op_cmd));*/ + HAK_ASSERT(hak, HAK_OBJ_IS_CHAR_POINTER(op_cmd)); - if (HAK_OBJ_GET_SIZE(rcv) == 0 || hak_count_oocstr(HAK_OBJ_GET_CHAR_SLOT(rcv)) != HAK_OBJ_GET_SIZE(rcv)) + if (HAK_OBJ_GET_SIZE(op_cmd) == 0 || hak_count_oocstr(HAK_OBJ_GET_CHAR_SLOT(op_cmd)) != HAK_OBJ_GET_SIZE(op_cmd)) { /* '\0' is contained in the middle */ - hak_seterrbfmt(hak, HAK_EINVAL, "invalid callable %O", rcv); + hak_seterrbfmt(hak, HAK_EINVAL, "invalid callable %O", op_cmd); goto oops; } - cmd = hak_dupootobcstr(hak, HAK_OBJ_GET_CHAR_SLOT(rcv), HAK_NULL); + cmd = hak_dupootobcstr(hak, HAK_OBJ_GET_CHAR_SLOT(op_cmd), HAK_NULL); if (!cmd) goto oops; if (hak_find_bchar_in_bcstr(cmd, '/')) { if (!is_regular_executable_file_by_me(cmd)) { - hak_seterrbfmt(hak, HAK_ECALL, "cannot execute %O", rcv); + hak_seterrbfmt(hak, HAK_ECALL, "cannot execute %O", op_cmd); goto oops; } @@ -3636,7 +3639,7 @@ static int execute (hak_t* hak) /* ------------------------------------------------- */ #if 0 - // the compiler never emits these instructions. reuse these instructions for other purposes + /* the compiler never emits these instructions. reuse these instructions for other purposes */ case HAK_CODE_PUSH_TEMPVAR_X: case HAK_CODE_STORE_INTO_TEMPVAR_X: case HAK_CODE_POP_INTO_TEMPVAR_X: @@ -4007,6 +4010,17 @@ static int execute (hak_t* hak) } break; +#if defined(ENABLE_SYSCMD) + case HAK_BRAND_STRING: + case HAK_BRAND_SYMBOL: + if (exec_syscmd(hak, b1) <= -1) + { + if (do_throw_with_internal_errmsg(hak, fetched_instruction_pointer) >= 0) break; + goto call_failed; + } + break; +#endif + default: goto cannot_call; } @@ -4786,7 +4800,7 @@ hak_logbfmt(hak, HAK_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncv t2 = HAK_STACK_GETTOP(hak); /* key */ HAK_STACK_POP(hak); t3 = HAK_STACK_GETTOP(hak); /* dictionary */ - if (!hak_putatdic(hak, (hak_oop_dic_t)t3, t2, t1)) goto oops; + if (!hak_putatdic(hak, (hak_oop_dic_t)t3, t2, t1)) goto oops_with_errmsg_supplement; break; } @@ -4834,7 +4848,7 @@ hak_logbfmt(hak, HAK_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncv hak_pushvolat(hak, &t3); t = hak_makecons(hak, t1, hak->_nil); hak_popvolat(hak); - if (HAK_UNLIKELY(!t)) goto oops; + if (HAK_UNLIKELY(!t)) goto oops_with_errmsg_supplement; ((hak_oop_oop_t)t3)->slot[1] = t; HAK_STACK_PUSH(hak, t); @@ -4872,7 +4886,7 @@ hak_logbfmt(hak, HAK_LOG_STDERR, ">>>%O c->sc=%O sc=%O b2=%d b3=%d nivars=%d ncv hak_pushvolat(hak, &t3); t = hak_makecons(hak, t1, hak->_nil); hak_popvolat(hak); - if (HAK_UNLIKELY(!t)) goto oops; + if (HAK_UNLIKELY(!t)) goto oops_with_errmsg_supplement; ((hak_oop_oop_t)t3)->slot[1] = t; } diff --git a/lib/gc.c b/lib/gc.c index 2103318..0afd539 100644 --- a/lib/gc.c +++ b/lib/gc.c @@ -1045,7 +1045,7 @@ void hak_gc_ms_sweep_lazy (hak_t* hak, hak_oow_t allocsize) if (HAK_OBJ_GET_FLAGS_MOVED(obj)) /* if marked */ { - HAK_OBJ_SET_FLAGS_MOVED (obj, 0); /* unmark */ + HAK_OBJ_SET_FLAGS_MOVED(obj, 0); /* unmark */ prev = curr; } else @@ -1380,15 +1380,15 @@ static hak_oop_class_t alloc_kernel_class (hak_t* hak, int class_flags, hak_oow_ c = (hak_oop_class_t)hak_allocoopobj(hak, HAK_CLASS_NAMED_INSTVARS + num_classvars); if (HAK_UNLIKELY(!c)) return HAK_NULL; - HAK_OBJ_SET_FLAGS_KERNEL (c, HAK_OBJ_FLAGS_KERNEL_IMMATURE); + HAK_OBJ_SET_FLAGS_KERNEL(c, HAK_OBJ_FLAGS_KERNEL_IMMATURE); cspec = kernel_classes[KCI_CLASS].class_spec_flags; - if (HAK_CLASS_SPEC_IS_IMMUTABLE(cspec)) HAK_OBJ_SET_FLAGS_RDONLY (c, 1); /* just for completeness of code. will never be true as it's not defined in the kernel class info table */ + if (HAK_CLASS_SPEC_IS_IMMUTABLE(cspec)) HAK_OBJ_SET_FLAGS_RDONLY(c, 1); /* just for completeness of code. will never be true as it's not defined in the kernel class info table */ #if 0 /* TODO extend the flags and uncomment this part */ - if (HAK_CLASS_SPEC_IS_UNCOPYABLE(cspec)) HAK_OBJ_SET_FLAGS_UNCOPYABLE (c, 1); /* class itself is uncopyable */ + if (HAK_CLASS_SPEC_IS_UNCOPYABLE(cspec)) HAK_OBJ_SET_FLAGS_UNCOPYABLE(c, 1); /* class itself is uncopyable */ #endif - HAK_OBJ_SET_CLASS (c, (hak_oop_t)hak->c_class); + HAK_OBJ_SET_CLASS(c, (hak_oop_t)hak->c_class); c->spec = HAK_SMOOI_TO_OOP(spec); c->selfspec = HAK_SMOOI_TO_OOP(HAK_CLASS_SELFSPEC_MAKE(num_classvars, 0, class_flags)); c->nivars_super = HAK_SMOOI_TO_OOP(nivars_super); /* TODO: encode it into spec? */ diff --git a/lib/hak-prv.h b/lib/hak-prv.h index 37bd998..5eb7084 100644 --- a/lib/hak-prv.h +++ b/lib/hak-prv.h @@ -326,7 +326,9 @@ enum hak_tok_type_t HAK_TOK_REVERT, HAK_TOK_AND, HAK_TOK_OR, +#if defined(USE_KW_PLUS) HAK_TOK_PLUS, +#endif HAK_TOK_SET, HAK_TOK_SET_R, @@ -396,6 +398,7 @@ enum hak_cnode_type_t HAK_CNODE_BCHRLIT, HAK_CNODE_SYMBOL, HAK_CNODE_DSYMBOL, /* dotted symbol */ + HAK_CNODE_BINOP, HAK_CNODE_STRLIT, HAK_CNODE_BSTRLIT, HAK_CNODE_SYMLIT, @@ -439,7 +442,9 @@ enum hak_cnode_type_t HAK_CNODE_REVERT, HAK_CNODE_AND, HAK_CNODE_OR, +#if defined(USE_KW_PLUS) HAK_CNODE_PLUS, +#endif HAK_CNODE_SET, HAK_CNODE_SET_R, /* language item for HAK_CODE_IS_FOR_LANG */ @@ -483,8 +488,9 @@ typedef enum hak_cnode_flag_t hak_cnode_flag_t; #define HAK_CNODE_IS_COLONLT(x) ((x)->cn_type == HAK_CNODE_COLONLT) #define HAK_CNODE_IS_SYMBOL(x) ((x)->cn_type == HAK_CNODE_SYMBOL) -#define HAK_CNODE_IS_SYMBOL_IDENT(x) (HAK_CNODE_IS_SYMBOL(x) && !hak_is_binop_char((x)->cn_tok.ptr[0])) -#define HAK_CNODE_IS_SYMBOL_BINOP(x) (HAK_CNODE_IS_SYMBOL(x) && hak_is_binop_char((x)->cn_tok.ptr[0])) +#define HAK_CNODE_IS_BINOP(x) ((x)->cn_type == HAK_CNODE_BINOP) +#define HAK_CNODE_IS_STRLIT(x) ((x)->cn_type == HAK_CNODE_STRLIT) +#define HAK_CNODE_IS_SYMLIT(x) ((x)->cn_type == HAK_CNODE_SYMLIT) #define HAK_CNODE_IS_DSYMBOL(x) ((x)->cn_type == HAK_CNODE_DSYMBOL) #define HAK_CNODE_IS_DSYMBOL_CLA(x) ((x)->cn_type == HAK_CNODE_DSYMBOL && (x)->u.dsymbol.is_cla) @@ -900,6 +906,7 @@ struct hak_frd_t { int level; int flagv; + int expect_pragma_item; int expect_include_file; int expect_vlist_item; int do_include_file; @@ -1357,6 +1364,7 @@ enum hak_bcode_t HAK_CODE_PUSH_NEGINTLIT = 0xB3, /* 179 */ HAK_CODE_PUSH_CHARLIT = 0xB4, /* 180 */ +/* TODO: generalize it to support binops, not just plus */ HAK_CODE_PLUS = 0xB5, /* 181 TOOD: move it to a lower code number later after killing OBJVAR instructions */ /* UNUSED - 0xB6-0xB7 */ @@ -2022,6 +2030,7 @@ hak_cnode_t* hak_makecnodecharlit (hak_t* hak, int flags, const hak_loc_t* loc, hak_cnode_t* hak_makecnodebchrlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok, hak_oob_t v); hak_cnode_t* hak_makecnodesymbol (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok); hak_cnode_t* hak_makecnodedsymbol (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok, int is_cla); +hak_cnode_t* hak_makecnodebinop (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok); hak_cnode_t* hak_makecnodestrlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok); hak_cnode_t* hak_makecnodebstrlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok); hak_cnode_t* hak_makecnodesymlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok); diff --git a/lib/hak.h b/lib/hak.h index abaf5f6..6566fad 100644 --- a/lib/hak.h +++ b/lib/hak.h @@ -119,6 +119,7 @@ enum hak_synerrnum_t HAK_SYNERR_RBRACE, /* } expected */ HAK_SYNERR_VBAR, /* | expected */ + HAK_SYNERR_IDENT, /* identifier expected */ HAK_SYNERR_STRING, /* string expected */ HAK_SYNERR_BYTERANGE, /* byte too small or too large */ HAK_SYNERR_NESTING, /* nesting level too deep */ @@ -165,6 +166,7 @@ enum hak_synerrnum_t HAK_SYNERR_BREAK, /* break outside loop */ HAK_SYNERR_CALLABLE, /* invalid callable */ + HAK_SYNERR_MESSAGE, /* invalid message */ HAK_SYNERR_UNBALKV, /* unbalanced key/value pair */ HAK_SYNERR_UNBALPBB, /* unbalanced parenthesis/brace/bracket */ HAK_SYNERR_SEMICOLON, /* unexpected semicolon */ diff --git a/lib/json.c b/lib/json.c index 1ecf8c5..a171036 100644 --- a/lib/json.c +++ b/lib/json.c @@ -891,7 +891,7 @@ static int feed_json_data_u (hak_json_t* json, const hak_uch_t* data, hak_oow_t hak_oow_t n, i; n = json->_gem.cmgr->uctobc(*ptr++, bcsbuf, HAK_COUNTOF(bcsbuf)); - if (n == 0) goto oops; // illegal character + if (n == 0) goto oops; /* illegal character */ for (i = 0; i < n; i++) { diff --git a/lib/print.c b/lib/print.c index 0766b43..0325bd3 100644 --- a/lib/print.c +++ b/lib/print.c @@ -957,7 +957,9 @@ void hak_dumpcnode (hak_t* hak, hak_cnode_t* cnode, int newline) case HAK_CNODE_REVERT: case HAK_CNODE_AND: case HAK_CNODE_OR: +#if defined(USE_KW_PLUS) case HAK_CNODE_PLUS: +#endif case HAK_CNODE_SET: case HAK_CNODE_SET_R: diff --git a/lib/read.c b/lib/read.c index 7ad63d9..9afda41 100644 --- a/lib/read.c +++ b/lib/read.c @@ -76,7 +76,9 @@ static struct voca_t { 6, { 'r','e','v','e','r','t' } }, { 3, { 'a','n','d' } }, { 2, { 'o','r', } }, +#if defined(USE_KW_PLUS) { 4, { 'p','l','u','s' } }, +#endif { 3, { 's','e','t' } }, { 5, { 's','e','t','-','r' } }, @@ -137,7 +139,9 @@ enum voca_id_t VOCA_KW_REVERT, VOCA_KW_AND, VOCA_KW_OR, +#if defined(USE_KW_PLUS) VOCA_KW_PLUS, +#endif VOCA_KW_SET, VOCA_KW_SET_R, @@ -285,7 +289,6 @@ static HAK_INLINE int is_delim_char (hak_ooci_t c) c == '#' || c == '\"' || c == '\'' || c == '\\' || is_spacechar(c) || c == HAK_OOCI_EOF; } - int hak_is_binop_char (hak_ooci_t c) /* not static HAK_INLINE for shared use with comp.c via HAK_CNODE_IS_SYMBOL() */ { return c == '&' || c == '*' || c == '+' || c == '-' || c == '/' || c == '%' || @@ -293,9 +296,23 @@ int hak_is_binop_char (hak_ooci_t c) /* not static HAK_INLINE for shared use wit } #define is_binop_char(c) hak_is_binop_char(c) +static HAK_INLINE int is_pure_lead_ident_char (hak_ooci_t c) +{ + return hak_is_ooch_alnum(c) || c == '_'; +} + +static HAK_INLINE int is_pure_ident_char (hak_ooci_t c) +{ + return hak_is_ooch_alnum(c) || c == '_' || c == '-'; +} + static HAK_INLINE int is_lead_ident_char (hak_ooci_t c) { +#if defined(STRICT_BINOP) return hak_is_ooch_alpha(c) || c == '_'; +#else + return hak_is_ooch_alnum(c) || c == '_' || c == '-' || c == '?' || is_binop_char(c); +#endif } static HAK_INLINE int is_ident_char (hak_ooci_t c) @@ -304,7 +321,11 @@ static HAK_INLINE int is_ident_char (hak_ooci_t c) * '-' is prohibited as the last character of an identifier or an identifier segment. * see flx_plain_ident(). */ +#if defined(STRICT_BINOP) return hak_is_ooch_alnum(c) || c == '_' || c == '-' || c == '?'; +#else + return hak_is_ooch_alnum(c) || c == '_' || c == '-' || c == '?' || is_binop_char(c); +#endif } /* TODO: remove GET_CHAR(), GET_CHAR_TO(), get_char(), _get_char() */ @@ -458,6 +479,7 @@ static int get_char (hak_t* hak) static hak_tok_type_t classify_ident_token (hak_t* hak, const hak_oocs_t* v) { hak_oow_t i; + int is_binop; static struct { int voca_id; @@ -488,7 +510,9 @@ static hak_tok_type_t classify_ident_token (hak_t* hak, const hak_oocs_t* v) { VOCA_KW_REVERT, HAK_TOK_REVERT }, { VOCA_KW_AND, HAK_TOK_AND }, { VOCA_KW_OR, HAK_TOK_OR }, +#if defined(USE_KW_PLUS) { VOCA_KW_PLUS, HAK_TOK_PLUS }, +#endif { VOCA_KW_SET, HAK_TOK_SET }, { VOCA_KW_SET_R, HAK_TOK_SET_R } }; @@ -499,7 +523,44 @@ static hak_tok_type_t classify_ident_token (hak_t* hak, const hak_oocs_t* v) if (hak_comp_oochars(v->ptr, v->len, vocas[vid].str, vocas[vid].len) == 0) return tab[i].type; } - return HAK_TOK_IDENT; + if (is_pure_lead_ident_char(v->ptr[0])) + { + /* check if the word conforms to pure identifier rules: + * begins with alnum or _ + * may contains a dash or dashes in between + * ends with alnum or _ or ? + */ + hak_oow_t wc = 1; + int q = 0; + for (i = 1; i < v->len; i++) + { + if (q && v->ptr[i] != '?') goto not_ident; + + if (v->ptr[i] == '-') + { + /*if (wc == 0) goto not_ident;*/ + wc = 0; + } + else if (v->ptr[i] == '?') q = 1; + else if (!is_pure_ident_char(v->ptr[i])) goto not_ident; + else wc++; + } + + if (wc > 0) return HAK_TOK_IDENT; + } + +not_ident: + is_binop = 1; + for (i = 0; i < v->len; i++) + { + if (!is_binop_char(v->ptr[i])) + { + is_binop = 0; + break; + } + } + + return is_binop? HAK_TOK_BINOP: HAK_TOK_SYMLIT; } static int is_sr_name_in_use (hak_t* hak, const hak_ooch_t* sr_name) @@ -692,7 +753,7 @@ static HAK_INLINE hak_cnode_t* leave_list (hak_t* hak, hak_loc_t* list_loc, int* /* check in advance if the array members are all plain symbols */ hak_cnode_t* lcar; lcar = HAK_CNODE_CONS_CAR(tmp); - if (!HAK_CNODE_IS_SYMBOL_IDENT(lcar) && !HAK_CNODE_IS_DSYMBOL_CLA(lcar)) + if (!HAK_CNODE_IS_SYMBOL(lcar) && !HAK_CNODE_IS_DSYMBOL_CLA(lcar)) { hak_setsynerrbfmt(hak, HAK_SYNERR_LVALUE, HAK_CNODE_GET_LOC(lval), HAK_CNODE_GET_TOK(lval), "bad lvalue - invalid element in tuple"); goto oops; @@ -718,7 +779,7 @@ static HAK_INLINE hak_cnode_t* leave_list (hak_t* hak, hak_loc_t* list_loc, int* } else { - if (!HAK_CNODE_IS_SYMBOL_IDENT(lval) && !HAK_CNODE_IS_DSYMBOL_CLA(lval)) + if (!HAK_CNODE_IS_SYMBOL(lval) && !HAK_CNODE_IS_DSYMBOL_CLA(lval)) { hak_setsynerrbfmt(hak, HAK_SYNERR_LVALUE, HAK_CNODE_GET_LOC(lval), HAK_CNODE_GET_TOK(lval), "bad lvalue - invalid element"); goto oops; @@ -1457,7 +1518,9 @@ static hak_cnode_type_t kw_to_cnode_type (int tok_type) HAK_CNODE_REVERT, HAK_CNODE_AND, HAK_CNODE_OR, +#if defined(USE_KW_PLUS) HAK_CNODE_PLUS, +#endif HAK_CNODE_SET, HAK_CNODE_SET_R }; @@ -1477,22 +1540,68 @@ static int feed_process_token (hak_t* hak) * by manipulating its own stack. */ /*hak_logbfmt(hak, HAK_LOG_STDERR, "TOKEN [%d] EOL[%d]=> [%.*js] type=%d LOC=%d.%d\n", TOKEN_TYPE(hak), HAK_TOK_EOL, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak), TOKEN_TYPE(hak), TOKEN_LOC(hak)->line, TOKEN_LOC(hak)->colm);*/ + if (frd->expect_pragma_item) + { + /* the pragmas changes the behavior of the reader and the compiler */ + if (frd->expect_pragma_item >= 3) /* eol expected */ + { + if (TOKEN_TYPE(hak) != HAK_TOK_EOL) + { + hak_setsynerrbfmt(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, + "redundant token '%.*js' for '%.*js'", + TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak), + vocas[VOCA_PRAGMA].len, vocas[VOCA_PRAGMA].str); + goto oops; + } + frd->expect_pragma_item = 0; + } + else + { + if (TOKEN_TYPE(hak) == HAK_TOK_EOL) + { + hak_setsynerrbfmt(hak, HAK_SYNERR_IDENT, TOKEN_LOC(hak), HAK_NULL, + "'%.*js' %hs not specified", + vocas[VOCA_PRAGMA].len, vocas[VOCA_PRAGMA].str, + (frd->expect_pragma_item == 1? "name": "value")); + goto oops; + } + else if (TOKEN_TYPE(hak) != HAK_TOK_IDENT) + { + hak_setsynerrbfmt(hak, HAK_SYNERR_IDENT, TOKEN_LOC(hak), HAK_NULL, + "'%.*js' %hs expected in place of '%.*js'", + vocas[VOCA_INCLUDE].len, vocas[VOCA_INCLUDE].str, + (frd->expect_pragma_item == 1? "name": "value"), + TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); + goto oops; + } + + if (frd->expect_pragma_item == 1) + { + frd->expect_pragma_item = 2; /* expect value */ + } + else + { + frd->expect_pragma_item = 3; /* expect eol */ + } + } + goto ok; + } + if (frd->expect_include_file) { /* the #include directive is an exception to the general expression rule. * use this exceptional code block to divert the major token processing */ - if (TOKEN_TYPE(hak) == HAK_TOK_EOL) { hak_setsynerrbfmt(hak, HAK_SYNERR_STRING, TOKEN_LOC(hak), HAK_NULL, - "%.*js target not specified", + "'%.*js' target not specified", vocas[VOCA_INCLUDE].len, vocas[VOCA_INCLUDE].str); goto oops; } else if (TOKEN_TYPE(hak) != HAK_TOK_STRLIT) { hak_setsynerrbfmt(hak, HAK_SYNERR_STRING, TOKEN_LOC(hak), HAK_NULL, - "%.*js target expected in place of '%.*js'", + "'%.*js' target expected in place of '%.*js'", vocas[VOCA_INCLUDE].len, vocas[VOCA_INCLUDE].str, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); goto oops; @@ -1542,9 +1651,11 @@ static int feed_process_token (hak_t* hak) goto ok; case HAK_TOK_PRAGMA: - /* TODO: implement this */ - hak_setsynerr(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak)); - goto oops; + /*hak_setsynerr(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak)); + goto oops;*/ +/* TODO: check if pragma is the first word in the line */ + frd->expect_pragma_item = 1; + goto ok; case HAK_TOK_VBAR: if (frd->expect_vlist_item) @@ -1729,15 +1840,14 @@ static int feed_process_token (hak_t* hak) goto oops; } else if (can <= -1) goto oops; - if (can == 1) goto ident; /* if binop is the first in the list */ - HAK_ASSERT(hak, can == 2); - - #if 0 -/* TODO: ... */ + #if 1 + HAK_ASSERT(hak, can == 1 || can == 2); frd->obj = hak_makecnodebinop(hak, 0, TOKEN_LOC(hak), TOKEN_NAME(hak)); - goto ok; + goto auto_xlist; #else + if (can == 1) goto ident; /* if binop is the first in the list */ + HAK_ASSERT(hak, can == 2); goto ident; #endif } @@ -1897,7 +2007,9 @@ static int feed_process_token (hak_t* hak) case HAK_TOK_REVERT: case HAK_TOK_AND: case HAK_TOK_OR: +#if defined(USE_KW_PLUS) case HAK_TOK_PLUS: +#endif case HAK_TOK_SET: case HAK_TOK_SET_R: frd->obj = hak_makecnode(hak, kw_to_cnode_type(TOKEN_TYPE(hak)), 0, TOKEN_LOC(hak), TOKEN_NAME(hak)); @@ -2360,7 +2472,7 @@ static int flx_start (hak_t* hak, hak_ooci_t c) */ case '$': - init_flx_di (FLX_DI(hak)); + init_flx_di(FLX_DI(hak)); FEED_CONTINUE_WITH_CHAR(hak, c, HAK_FLX_DOLLARED_IDENT); goto consumed; @@ -2370,35 +2482,35 @@ static int flx_start (hak_t* hak, hak_ooci_t c) goto consumed; case '\"': - init_flx_qt (FLX_QT(hak), HAK_TOK_STRLIT, HAK_SYNERR_STRLIT, c, '\\', 0, HAK_TYPE_MAX(hak_oow_t), 0); + init_flx_qt(FLX_QT(hak), HAK_TOK_STRLIT, HAK_SYNERR_STRLIT, c, '\\', 0, HAK_TYPE_MAX(hak_oow_t), 0); FEED_CONTINUE(hak, HAK_FLX_QUOTED_TOKEN); /* discard the quote itself. move on the the QUOTED_TOKEN state */ goto consumed; case '\'': - init_flx_qt (FLX_QT(hak), HAK_TOK_CHARLIT, HAK_SYNERR_CHARLIT, c, '\\', 1, 1, 0); + init_flx_qt(FLX_QT(hak), HAK_TOK_CHARLIT, HAK_SYNERR_CHARLIT, c, '\\', 1, 1, 0); FEED_CONTINUE(hak, HAK_FLX_QUOTED_TOKEN); /* discard the quote itself. move on the the QUOTED_TOKEN state */ goto consumed; #if defined(HAK_OOCH_IS_UCH) && defined(HAK_LANG_ENABLE_WIDE_DELIM) case L'\u201C': /* “ ” */ - init_flx_qt (FLX_QT(hak), HAK_TOK_STRLIT, HAK_SYNERR_STRLIT, L'\u201D', '\\', 0, HAK_TYPE_MAX(hak_oow_t), 0); + init_flx_qt(FLX_QT(hak), HAK_TOK_STRLIT, HAK_SYNERR_STRLIT, L'\u201D', '\\', 0, HAK_TYPE_MAX(hak_oow_t), 0); FEED_CONTINUE(hak, HAK_FLX_QUOTED_TOKEN); /* discard the quote itself. move on the the QUOTED_TOKEN state */ goto consumed; case L'\u2018': /* ‘ ’ */ - init_flx_qt (FLX_QT(hak), HAK_TOK_CHARLIT, HAK_SYNERR_CHARLIT, L'\u2019', '\\', 1, 1, 0); + init_flx_qt(FLX_QT(hak), HAK_TOK_CHARLIT, HAK_SYNERR_CHARLIT, L'\u2019', '\\', 1, 1, 0); FEED_CONTINUE(hak, HAK_FLX_QUOTED_TOKEN); /* discard the quote itself. move on the the QUOTED_TOKEN state */ goto consumed; #endif case '+': case '-': - init_flx_st (FLX_ST(hak), c); + init_flx_st(FLX_ST(hak), c); FEED_CONTINUE_WITH_CHAR(hak, c, HAK_FLX_SIGNED_TOKEN); goto consumed; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - init_flx_pn (FLX_PN(hak), c); + init_flx_pn(FLX_PN(hak), c); FEED_CONTINUE(hak, HAK_FLX_PLAIN_NUMBER); goto not_consumed; @@ -2411,14 +2523,17 @@ static int flx_start (hak_t* hak, hak_ooci_t c) goto consumed; default: +#if defined(STRICT_BINOP) if (is_binop_char(c)) { - init_flx_binop (FLX_BINOP(hak)); + init_flx_binop(FLX_BINOP(hak)); FEED_CONTINUE(hak, HAK_FLX_BINOP); } - else if (is_lead_ident_char(c)) + else +#endif + if (is_lead_ident_char(c)) { - init_flx_pi (FLX_PI(hak)); + init_flx_pi(FLX_PI(hak)); FEED_CONTINUE(hak, HAK_FLX_PLAIN_IDENT); } else @@ -2528,6 +2643,7 @@ static int flx_dollared_ident (hak_t* hak, hak_ooci_t c) { if (!is_lead_ident_char(c)) { + /* some character can't placed immediately after '$'. e.g '?' */ hak_setsynerrbfmt(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL, "'%c' prohibited as first character after '%.*js'", c, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); @@ -2586,12 +2702,14 @@ static int flx_hmarked_token (hak_t* hak, hak_ooci_t c) * #"..." symbol literal */ +#if defined(STRICT_BINOP) if (is_binop_char(c)) { reset_flx_token(hak); FEED_CONTINUE_WITH_CHAR(hak, c, HAK_FLX_HMARKED_BINOP); goto consumed; } +#endif switch (c) { @@ -2607,11 +2725,11 @@ static int flx_hmarked_token (hak_t* hak, hak_ooci_t c) #if 0 case 'x': /* hexadecimal number */ - init_flx_hn (FLX_HN(hak), HAK_TOK_RADNUMLIT, HAK_SYNERR_NUMLIT, 16); + init_flx_hn(FLX_HN(hak), HAK_TOK_RADNUMLIT, HAK_SYNERR_NUMLIT, 16); goto radixed_number; case 'o': /* octal number */ - init_flx_hn (FLX_HN(hak), HAK_TOK_RADNUMLIT, HAK_SYNERR_NUMLIT, 8); + init_flx_hn(FLX_HN(hak), HAK_TOK_RADNUMLIT, HAK_SYNERR_NUMLIT, 8); goto radixed_number; #endif @@ -2889,6 +3007,7 @@ static int flx_plain_ident (hak_t* hak, hak_ooci_t c) /* identifier */ start = TOKEN_NAME_LEN(hak) - pi->seg_len; seg.ptr = &TOKEN_NAME_CHAR(hak, start); seg.len = pi->seg_len; +#if defined(STRICT_BINOP) if (seg.ptr[seg.len - 1] == '-') { hak_setsynerrbfmt(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak), @@ -2896,6 +3015,7 @@ static int flx_plain_ident (hak_t* hak, hak_ooci_t c) /* identifier */ seg.ptr[seg.len - 1]); return -1; } +#endif tok_type = classify_ident_token(hak, &seg); if (tok_type != HAK_TOK_IDENT) { @@ -3328,7 +3448,16 @@ static int flx_signed_token (hak_t* hak, hak_ooci_t c) } else { - #if 0 + #if defined(STRICT_BINOP) + /* the leading sign must be + or - and must be one of the binop chars. */ + HAK_ASSERT(hak, is_binop_char(st->sign_c));/* must be + or - and they must be one of the binop chars. */ + + /* switch to binop mode */ + init_flx_binop(FLX_BINOP(hak)); + HAK_ASSERT(hak, TOKEN_NAME_LEN(hak) == 1); + FEED_CONTINUE(hak, HAK_FLX_BINOP); + goto not_consumed; + #else init_flx_pi(FLX_PI(hak)); /* the sign is already in the token name buffer. @@ -3340,15 +3469,6 @@ static int flx_signed_token (hak_t* hak, hak_ooci_t c) /* let refeeding of 'c' happen at the next iteration */ FEED_CONTINUE(hak, HAK_FLX_PLAIN_IDENT); goto not_consumed; - #else - /* the leading sign must be + or - and must be one of the binop chars. */ - HAK_ASSERT(hak, is_binop_char(st->sign_c));/* must be + or - and they must be one of the binop chars. */ - - /* switch to binop mode */ - init_flx_binop(FLX_BINOP(hak)); - HAK_ASSERT(hak, TOKEN_NAME_LEN(hak) == 1); - FEED_CONTINUE(hak, HAK_FLX_BINOP); - goto not_consumed; #endif } diff --git a/src/kernel.hak b/src/kernel.hak index cf7368e..84405fc 100644 --- a/src/kernel.hak +++ b/src/kernel.hak @@ -6,12 +6,12 @@ class Apex { return (core.basicNew self size) } - fun[#class] respondsTo(mth) { - return (core.classRespondsTo self mth) + fun[#class] respondsTo(mthname) { + return (core.classRespondsTo self mthname) } - fun respondsTo(mth) { - return (core.instRespondsTo self mth) + fun respondsTo(mthname) { + return (core.instRespondsTo self mthname) } fun primAt(pos) { diff --git a/t/call-5001.err b/t/call-5001.err index 6b4cc0b..df56eef 100644 --- a/t/call-5001.err +++ b/t/call-5001.err @@ -105,3 +105,33 @@ core.basicAtPut "xbcdefghiklmnl" 4 k ##ERROR: exception not handled - "receiver k := (core.basicAt #abcdefg 1) core.basicAtPut #xbcdefghiklmnl 4 k ##ERROR: exception not handled - "receiver immutable - xbcdefghiklmnl" + +--- + +## the compiler/runtime needs to improve on this although this is an error for now. +fun + (a b) {} +printf "%O\n" #{+: 20} ##ERROR: no builtin hash implemented for # + +--- + +class X { + fun + () {} ##ERROR: syntax error - only one argument expected for '+' +} + +--- + +## the binop method defined for a class must have one argument +class X { + fun + (t) {} + fun f1 (t1 t2) {} +} + +fun X:- (a b) {} ##ERROR: syntax error - only one argument expected for 'X:-' + +--- + +class X { + fun[#ci] +(a b c) { printf "jjj\n" } ## the one argument rule applies to binary instance methods only. + fun +(c d) { printf "jjj\n" } ##ERROR: syntax error - only one argument expected for '+' +} + diff --git a/t/feed-01.hak b/t/feed-01.hak index ddf6cd9..9ed9bb0 100644 --- a/t/feed-01.hak +++ b/t/feed-01.hak @@ -132,6 +132,7 @@ if (== i k) { printf "OK: i is %d\n" i k } \ else { printf "ERROR: i is not equal to %d\n" k } +## dictionary a := #{ (if (> 10 20) true else false ): 10, (if (< 10 20) true else false ): 20 diff --git a/t/feed-5001.err b/t/feed-5001.err index cf68713..f70f9de 100644 --- a/t/feed-5001.err +++ b/t/feed-5001.err @@ -166,6 +166,7 @@ abc.? := 20 ##ERROR: syntax error - '?' prohibited as first character of identif --- + - := 20 ##ERROR: syntax error - bad lvalue - invalid element - - --- diff --git a/t/fun-01.hak b/t/fun-01.hak index 0a16686..73004ff 100644 --- a/t/fun-01.hak +++ b/t/fun-01.hak @@ -126,3 +126,22 @@ if (== v 30) { printf "OK - %d\n" v } else { printf "ERROR - %d, not 30\n" v }; fun k(x) (+ x 30) ## (+ x 30) is valid function body v := (k 10) if (== v 40) { printf "OK - %d\n" v } else { printf "ERROR - %d, not 40\n" v }; + + +## ---------------------------------------- +fun plus(x y) { + ##printf "plus %d %d\n" x y + fun minus(x y) { + ##printf "minus %d %d\n" x y + - x y + } + + x y +} + +fun dummy(q) { + printf "%s\n" q +} + +plus 10 20 ## minus is now available after plus is executed +v := (minus 10 1) +if (== v 9) { printf "OK - %d\n" v } else { printf "ERROR - %d, not 9\n" v }