Compare commits

...

2 Commits

Author SHA1 Message Date
hyung-hwan 5819be7fa5 updating the compiler/reader to handle binops more specially 2025-09-21 17:13:47 +09:00
hyung-hwan 013dbb9e5c simple reformatting 2025-09-21 11:03:34 +09:00
16 changed files with 369 additions and 143 deletions
+7 -3
View File
@@ -579,7 +579,7 @@ static int on_fed_cnode_in_batch_mode (hak_t* hak, hak_cnode_t* obj)
#if defined(USE_ISOCLINE) #if defined(USE_ISOCLINE)
static int get_line (hak_t* hak, xtn_t* xtn, FILE* fp) static int get_line (hak_t* hak, xtn_t* xtn, FILE* fp)
{ {
char* inp, * p; char* inp;
static int inited = 0; static int inited = 0;
if (!inited) if (!inited)
@@ -742,9 +742,13 @@ static int feed_loop (hak_t* hak, xtn_t* xtn, int verbose)
} }
else else
{ {
HAK_ASSERT(hak, hak_getbclen(hak) == 0);
/* usually this part is reached if the input string is /* usually this part is reached if the input string is
* one or more whilespaces and/or comments only */ * one or more whilespaces and/or comments only.
* ------------------------------------------------------
* if the previous compiled code has not been cleared (e.g.
* hcl_compile() ever called with HCL_COMPILE_CLEAR_CODE
* or hcl_clearcode() explicitly called), hak_getbcllen(hak)
* may still return a positive number greater than 0. */
} }
show_prompt (hak, 0); /* show prompt after execution */ show_prompt (hak, 0); /* show prompt after execution */
} }
+5
View File
@@ -135,6 +135,11 @@ hak_cnode_t* hak_makecnodedsymbol (hak_t* hak, int flags, const hak_loc_t* loc,
return c; 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) 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); return hak_makecnode(hak, HAK_CNODE_STRLIT, flags, loc, tok);
+75 -58
View File
@@ -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) fun dummy(q) {
(printf "plus %d %d\n" x y) printf "%s\n" q
(fun minus(x y) }
(printf "minus %d %d\n" x y)
(- x y)
)
(+ x y)
)
(fun dummy(q) plus 10 20 ## minus is now available after plus is executed
(printf "%s\n" q) minus 10 1
)
(plus 10 20)
<---- minus is now available
(minus 10 1)
literals --> literals -->
// //
// characeter 'A' // character 'A'
// "string" // "string"
// B"byte string" <-- not yet implemented // B"byte string" <-- not yet implemented
// array ---> #[ ] or [ ] ? constant or not? dynamic??? // 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 /* this condition indicates that the current function level contains a class defintion
* and this variable is looked up inside the class defintion */ * and this variable is looked up inside the class defintion */
HAK_INFO2(hak, "CLASS NAMED VAR [%.*js]\n", name->len, name->ptr); 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->ctx_offset = 0;
vi->index_in_ctx = 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; 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; checkpoint = hak->c->tv.s.len;
n = add_temporary_variable(hak, var, tv_slen_saved, desc[enclosed], HAK_NULL); 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_POP_INTO_CONS_CDR,
COP_EMIT_FUN, COP_EMIT_FUN,
#if defined(USE_KW_PLUS)
COP_EMIT_PLUS, COP_EMIT_PLUS,
#endif
COP_EMIT_POP_STACKTOP, COP_EMIT_POP_STACKTOP,
COP_EMIT_RETURN, COP_EMIT_RETURN,
COP_EMIT_SET, 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 */ /* EXPERIMENT WITH BINOP */
static int compile_plus (hak_t* hak, hak_cnode_t* src) 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); POP_CFRAME(hak);
return 0; return 0;
} }
#endif
/* ========================================================================= */ /* ========================================================================= */
@@ -2819,7 +2822,7 @@ static int compile_class (hak_t* hak, hak_cnode_t* src)
check_class_name: check_class_name:
if (HAK_CNODE_IS_FOR_DATA_SIMPLE(tmp) || HAK_CNODE_IS_FOR_LANG(tmp)) 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_setsynerrbfmt(
hak, HAK_SYNERR_CLASS, HAK_CNODE_GET_LOC(tmp), HAK_NULL, 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); 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' followed by name */
fun_got_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); 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_setsynerrbfmt(
hak, HAK_SYNERR_FUN, HAK_CNODE_GET_LOC(tmp), HAK_NULL, 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 (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 :: 20) { }', '20' is not a valid return variable name.
* in 'fun x (x :: if) { }', 'if' 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; va = 1;
} }
else if (!HAK_CNODE_IS_SYMBOL_IDENT(arg)) else if (!HAK_CNODE_IS_SYMBOL(arg))
{ {
hak_setsynerrbfmt( hak_setsynerrbfmt(
hak, HAK_SYNERR_ARGNAME, HAK_CNODE_GET_LOC(arg), HAK_NULL, 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); 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 */ 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 /* 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); 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; 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); next = HAK_CNODE_CONS_CDR(next);
if (!next) break; if (!next) break;
tmp = HAK_CNODE_CONS_CAR(next); 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 else
@@ -4136,7 +4151,7 @@ static int compile_set_r (hak_t* hak, hak_cnode_t* src)
do do
{ {
var = HAK_CNODE_CONS_CAR(obj); 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; 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)); 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; if (compile_or(hak, obj) <= -1) return -1;
goto done; goto done;
#if defined(USE_KW_PLUS)
case HAK_CNODE_PLUS: case HAK_CNODE_PLUS:
if (compile_plus(hak, obj) <= -1) return -1; if (compile_plus(hak, obj) <= -1) return -1;
goto done; goto done;
#endif
case HAK_CNODE_SET: case HAK_CNODE_SET:
if (compile_set(hak, obj) <= -1) return -1; 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; 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_XLIST) ||
HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_MLIST) || HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_MLIST) ||
HAK_CNODE_IS_CONS_CONCODED(car, HAK_CONCODE_BLIST) || 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; 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; return -1;
} }
car = HAK_CNODE_CONS_CAR(cdr); 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); 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 else
{ {
/* TODO: more sanity check on what can be used as a method */ hak_setsynerrbfmt(hak, HAK_SYNERR_MESSAGE, HAK_CNODE_GET_LOC(car), HAK_NULL,
PUSH_CFRAME(hak, COP_COMPILE_OBJECT, car); "invalid message '%.*js'", HAK_CNODE_GET_TOKLEN(car), HAK_CNODE_GET_TOKPTR(car));
return -1;
} }
/* compile <operand1> ... etc */ /* compile <operand1> ... 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() */ /* redundant cdr check is performed inside compile_object_list() */
PUSH_SUBCFRAME(hak, COP_COMPILE_ARGUMENT_LIST, cdr); 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; hak_var_info_t vi;
int x; 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 */ /* check if a symbol is a local variable */
x = find_variable_backward_with_token(hak, obj, &vi); x = find_variable_backward_with_token(hak, obj, &vi);
@@ -5598,6 +5612,7 @@ redo:
lit = HAK_ERROR_TO_OOP(oprnd->u.errlit.v); lit = HAK_ERROR_TO_OOP(oprnd->u.errlit.v);
goto literal; 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 */ case HAK_CNODE_SYMBOL: /* symbol. but not a literal. usually a variable */
if (compile_symbol(hak, oprnd) <= -1) return -1; if (compile_symbol(hak, oprnd) <= -1) return -1;
goto done; goto done;
@@ -6626,7 +6641,7 @@ static HAK_INLINE int post_fun (hak_t* hak)
hak_var_info_t vi; hak_var_info_t vi;
int x; 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)) 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_oow_t index;
hak_oop_t cons, sym; 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)); sym = hak_makesymbol(hak, HAK_CNODE_GET_TOKPTR(cf->operand), HAK_CNODE_GET_TOKLEN(cf->operand));
if (HAK_UNLIKELY(!sym)) return -1; 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; if (emit_fun(hak) <= -1) goto oops;
break; break;
#if defined(USE_KW_PLUS)
case COP_EMIT_PLUS: case COP_EMIT_PLUS:
if (emit_plus(hak) <= -1) goto oops; if (emit_plus(hak) <= -1) goto oops;
break; break;
#endif
case COP_EMIT_POP_STACKTOP: case COP_EMIT_POP_STACKTOP:
if (emit_pop_stacktop(hak) <= -1) goto oops; if (emit_pop_stacktop(hak) <= -1) goto oops;
+2
View File
@@ -115,6 +115,7 @@ static const char* synerrstr[] =
"} expected", "} expected",
"| expected", "| expected",
"identifier expected",
"string expected", "string expected",
"byte too small or too large", "byte too small or too large",
"nesting level too deep", "nesting level too deep",
@@ -161,6 +162,7 @@ static const char* synerrstr[] =
"break outside loop", "break outside loop",
"invalid callable", "invalid callable",
"invalid message",
"unbalanced key/value pair", "unbalanced key/value pair",
"unbalanced parenthesis/brace/bracket", "unbalanced parenthesis/brace/bracket",
"unexpected semicolon", "unexpected semicolon",
+34 -20
View File
@@ -25,6 +25,8 @@
#include "hak-prv.h" #include "hak-prv.h"
#define ENABLE_SYSCMD
static const char* io_type_str[] = static const char* io_type_str[] =
{ {
"input", "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) 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); op_prim = (hak_oop_prim_t)HAK_STACK_GETOP(hak, nargs);
HAK_ASSERT(hak, HAK_IS_PRIM(hak, rcv)); HAK_ASSERT(hak, HAK_IS_PRIM(hak, op_prim));
HAK_ASSERT(hak, HAK_OBJ_GET_SIZE(rcv) == HAK_PRIM_NAMED_INSTVARS); 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... */ /* TODO: include a primitive name... */
HAK_LOG3(hak, HAK_LOG_IC | HAK_LOG_ERROR, HAK_LOG3(hak, HAK_LOG_IC | HAK_LOG_ERROR,
"Error - wrong number of arguments to a primitive - expecting %zd-%zd, got %zd\n", "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); hak_seterrnum(hak, HAK_ECALLARG);
return -1; 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)); HAK_ASSERT(hak, HAK_IS_BYTEARRAY(hak, hak->active_function->dbgi));
dbgi = (hak_dbgi_t*)HAK_OBJ_GET_BYTE_SLOT(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, hak_seterrbfmtloc(hak, orgnum, &orgloc, "%js (%js:%zu)", orgmsg,
(dbgi[ip].fname? dbgi[ip].fname: oocstr_dash), dbgi[ip].sline); (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 */ /* EXPERIMENTAL CODE INTEGRATING EXTERNAL COMMANDS */
#include <unistd.h> #include <unistd.h>
@@ -2595,29 +2598,29 @@ done:
static HAK_INLINE int exec_syscmd (hak_t* hak, hak_ooi_t nargs) 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* cmd = HAK_NULL;
hak_bch_t* xcmd = HAK_NULL; hak_bch_t* xcmd = HAK_NULL;
rcv = (hak_oop_word_t)HAK_STACK_GETOP(hak, nargs); op_cmd = (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_IS_STRING(hak, op_cmd) || HAK_IS_SYMBOL(hak, op_cmd));*/
HAK_ASSERT(hak, HAK_OBJ_IS_CHAR_POINTER(rcv)); 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 */ /* '\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; 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 (!cmd) goto oops;
if (hak_find_bchar_in_bcstr(cmd, '/')) if (hak_find_bchar_in_bcstr(cmd, '/'))
{ {
if (!is_regular_executable_file_by_me(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; goto oops;
} }
@@ -3636,7 +3639,7 @@ static int execute (hak_t* hak)
/* ------------------------------------------------- */ /* ------------------------------------------------- */
#if 0 #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_PUSH_TEMPVAR_X:
case HAK_CODE_STORE_INTO_TEMPVAR_X: case HAK_CODE_STORE_INTO_TEMPVAR_X:
case HAK_CODE_POP_INTO_TEMPVAR_X: case HAK_CODE_POP_INTO_TEMPVAR_X:
@@ -4007,6 +4010,17 @@ static int execute (hak_t* hak)
} }
break; 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: default:
goto cannot_call; 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 */ t2 = HAK_STACK_GETTOP(hak); /* key */
HAK_STACK_POP(hak); HAK_STACK_POP(hak);
t3 = HAK_STACK_GETTOP(hak); /* dictionary */ 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; 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); hak_pushvolat(hak, &t3);
t = hak_makecons(hak, t1, hak->_nil); t = hak_makecons(hak, t1, hak->_nil);
hak_popvolat(hak); 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_oop_oop_t)t3)->slot[1] = t;
HAK_STACK_PUSH(hak, 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); hak_pushvolat(hak, &t3);
t = hak_makecons(hak, t1, hak->_nil); t = hak_makecons(hak, t1, hak->_nil);
hak_popvolat(hak); 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_oop_oop_t)t3)->slot[1] = t;
} }
+11 -2
View File
@@ -326,7 +326,9 @@ enum hak_tok_type_t
HAK_TOK_REVERT, HAK_TOK_REVERT,
HAK_TOK_AND, HAK_TOK_AND,
HAK_TOK_OR, HAK_TOK_OR,
#if defined(USE_KW_PLUS)
HAK_TOK_PLUS, HAK_TOK_PLUS,
#endif
HAK_TOK_SET, HAK_TOK_SET,
HAK_TOK_SET_R, HAK_TOK_SET_R,
@@ -396,6 +398,7 @@ enum hak_cnode_type_t
HAK_CNODE_BCHRLIT, HAK_CNODE_BCHRLIT,
HAK_CNODE_SYMBOL, HAK_CNODE_SYMBOL,
HAK_CNODE_DSYMBOL, /* dotted symbol */ HAK_CNODE_DSYMBOL, /* dotted symbol */
HAK_CNODE_BINOP,
HAK_CNODE_STRLIT, HAK_CNODE_STRLIT,
HAK_CNODE_BSTRLIT, HAK_CNODE_BSTRLIT,
HAK_CNODE_SYMLIT, HAK_CNODE_SYMLIT,
@@ -439,7 +442,9 @@ enum hak_cnode_type_t
HAK_CNODE_REVERT, HAK_CNODE_REVERT,
HAK_CNODE_AND, HAK_CNODE_AND,
HAK_CNODE_OR, HAK_CNODE_OR,
#if defined(USE_KW_PLUS)
HAK_CNODE_PLUS, HAK_CNODE_PLUS,
#endif
HAK_CNODE_SET, HAK_CNODE_SET,
HAK_CNODE_SET_R, /* language item for HAK_CODE_IS_FOR_LANG */ 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_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(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_BINOP(x) ((x)->cn_type == HAK_CNODE_BINOP)
#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_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(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) #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 level;
int flagv; int flagv;
int expect_pragma_item;
int expect_include_file; int expect_include_file;
int expect_vlist_item; int expect_vlist_item;
int do_include_file; int do_include_file;
@@ -1357,6 +1364,7 @@ enum hak_bcode_t
HAK_CODE_PUSH_NEGINTLIT = 0xB3, /* 179 */ HAK_CODE_PUSH_NEGINTLIT = 0xB3, /* 179 */
HAK_CODE_PUSH_CHARLIT = 0xB4, /* 180 */ 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 */ HAK_CODE_PLUS = 0xB5, /* 181 TOOD: move it to a lower code number later after killing OBJVAR instructions */
/* UNUSED - 0xB6-0xB7 */ /* 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_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_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_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_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_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); hak_cnode_t* hak_makecnodesymlit (hak_t* hak, int flags, const hak_loc_t* loc, const hak_oocs_t* tok);
+2
View File
@@ -119,6 +119,7 @@ enum hak_synerrnum_t
HAK_SYNERR_RBRACE, /* } expected */ HAK_SYNERR_RBRACE, /* } expected */
HAK_SYNERR_VBAR, /* | expected */ HAK_SYNERR_VBAR, /* | expected */
HAK_SYNERR_IDENT, /* identifier expected */
HAK_SYNERR_STRING, /* string expected */ HAK_SYNERR_STRING, /* string expected */
HAK_SYNERR_BYTERANGE, /* byte too small or too large */ HAK_SYNERR_BYTERANGE, /* byte too small or too large */
HAK_SYNERR_NESTING, /* nesting level too deep */ HAK_SYNERR_NESTING, /* nesting level too deep */
@@ -165,6 +166,7 @@ enum hak_synerrnum_t
HAK_SYNERR_BREAK, /* break outside loop */ HAK_SYNERR_BREAK, /* break outside loop */
HAK_SYNERR_CALLABLE, /* invalid callable */ HAK_SYNERR_CALLABLE, /* invalid callable */
HAK_SYNERR_MESSAGE, /* invalid message */
HAK_SYNERR_UNBALKV, /* unbalanced key/value pair */ HAK_SYNERR_UNBALKV, /* unbalanced key/value pair */
HAK_SYNERR_UNBALPBB, /* unbalanced parenthesis/brace/bracket */ HAK_SYNERR_UNBALPBB, /* unbalanced parenthesis/brace/bracket */
HAK_SYNERR_SEMICOLON, /* unexpected semicolon */ HAK_SYNERR_SEMICOLON, /* unexpected semicolon */
+1 -1
View File
@@ -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; hak_oow_t n, i;
n = json->_gem.cmgr->uctobc(*ptr++, bcsbuf, HAK_COUNTOF(bcsbuf)); 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++) for (i = 0; i < n; i++)
{ {
+2
View File
@@ -957,7 +957,9 @@ void hak_dumpcnode (hak_t* hak, hak_cnode_t* cnode, int newline)
case HAK_CNODE_REVERT: case HAK_CNODE_REVERT:
case HAK_CNODE_AND: case HAK_CNODE_AND:
case HAK_CNODE_OR: case HAK_CNODE_OR:
#if defined(USE_KW_PLUS)
case HAK_CNODE_PLUS: case HAK_CNODE_PLUS:
#endif
case HAK_CNODE_SET: case HAK_CNODE_SET:
case HAK_CNODE_SET_R: case HAK_CNODE_SET_R:
+147 -27
View File
@@ -76,7 +76,9 @@ static struct voca_t
{ 6, { 'r','e','v','e','r','t' } }, { 6, { 'r','e','v','e','r','t' } },
{ 3, { 'a','n','d' } }, { 3, { 'a','n','d' } },
{ 2, { 'o','r', } }, { 2, { 'o','r', } },
#if defined(USE_KW_PLUS)
{ 4, { 'p','l','u','s' } }, { 4, { 'p','l','u','s' } },
#endif
{ 3, { 's','e','t' } }, { 3, { 's','e','t' } },
{ 5, { 's','e','t','-','r' } }, { 5, { 's','e','t','-','r' } },
@@ -137,7 +139,9 @@ enum voca_id_t
VOCA_KW_REVERT, VOCA_KW_REVERT,
VOCA_KW_AND, VOCA_KW_AND,
VOCA_KW_OR, VOCA_KW_OR,
#if defined(USE_KW_PLUS)
VOCA_KW_PLUS, VOCA_KW_PLUS,
#endif
VOCA_KW_SET, VOCA_KW_SET,
VOCA_KW_SET_R, 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; 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() */ 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 == '%' || 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) #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) static HAK_INLINE int is_lead_ident_char (hak_ooci_t c)
{ {
#if defined(STRICT_BINOP)
return hak_is_ooch_alpha(c) || c == '_'; 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) 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. * '-' is prohibited as the last character of an identifier or an identifier segment.
* see flx_plain_ident(). * see flx_plain_ident().
*/ */
#if defined(STRICT_BINOP)
return hak_is_ooch_alnum(c) || c == '_' || c == '-' || c == '?'; 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() */ /* 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) static hak_tok_type_t classify_ident_token (hak_t* hak, const hak_oocs_t* v)
{ {
hak_oow_t i; hak_oow_t i;
int is_binop;
static struct static struct
{ {
int voca_id; 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_REVERT, HAK_TOK_REVERT },
{ VOCA_KW_AND, HAK_TOK_AND }, { VOCA_KW_AND, HAK_TOK_AND },
{ VOCA_KW_OR, HAK_TOK_OR }, { VOCA_KW_OR, HAK_TOK_OR },
#if defined(USE_KW_PLUS)
{ VOCA_KW_PLUS, HAK_TOK_PLUS }, { VOCA_KW_PLUS, HAK_TOK_PLUS },
#endif
{ VOCA_KW_SET, HAK_TOK_SET }, { VOCA_KW_SET, HAK_TOK_SET },
{ VOCA_KW_SET_R, HAK_TOK_SET_R } { 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; 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) 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 */ /* check in advance if the array members are all plain symbols */
hak_cnode_t* lcar; hak_cnode_t* lcar;
lcar = HAK_CNODE_CONS_CAR(tmp); 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"); hak_setsynerrbfmt(hak, HAK_SYNERR_LVALUE, HAK_CNODE_GET_LOC(lval), HAK_CNODE_GET_TOK(lval), "bad lvalue - invalid element in tuple");
goto oops; goto oops;
@@ -718,7 +779,7 @@ static HAK_INLINE hak_cnode_t* leave_list (hak_t* hak, hak_loc_t* list_loc, int*
} }
else 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"); hak_setsynerrbfmt(hak, HAK_SYNERR_LVALUE, HAK_CNODE_GET_LOC(lval), HAK_CNODE_GET_TOK(lval), "bad lvalue - invalid element");
goto oops; goto oops;
@@ -1457,7 +1518,9 @@ static hak_cnode_type_t kw_to_cnode_type (int tok_type)
HAK_CNODE_REVERT, HAK_CNODE_REVERT,
HAK_CNODE_AND, HAK_CNODE_AND,
HAK_CNODE_OR, HAK_CNODE_OR,
#if defined(USE_KW_PLUS)
HAK_CNODE_PLUS, HAK_CNODE_PLUS,
#endif
HAK_CNODE_SET, HAK_CNODE_SET,
HAK_CNODE_SET_R HAK_CNODE_SET_R
}; };
@@ -1477,22 +1540,68 @@ static int feed_process_token (hak_t* hak)
* by manipulating its own stack. */ * 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);*/ /*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) if (frd->expect_include_file)
{ {
/* the #include directive is an exception to the general expression rule. /* the #include directive is an exception to the general expression rule.
* use this exceptional code block to divert the major token processing */ * use this exceptional code block to divert the major token processing */
if (TOKEN_TYPE(hak) == HAK_TOK_EOL) if (TOKEN_TYPE(hak) == HAK_TOK_EOL)
{ {
hak_setsynerrbfmt(hak, HAK_SYNERR_STRING, TOKEN_LOC(hak), HAK_NULL, 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); vocas[VOCA_INCLUDE].len, vocas[VOCA_INCLUDE].str);
goto oops; goto oops;
} }
else if (TOKEN_TYPE(hak) != HAK_TOK_STRLIT) else if (TOKEN_TYPE(hak) != HAK_TOK_STRLIT)
{ {
hak_setsynerrbfmt(hak, HAK_SYNERR_STRING, TOKEN_LOC(hak), HAK_NULL, 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, vocas[VOCA_INCLUDE].len, vocas[VOCA_INCLUDE].str,
TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak));
goto oops; goto oops;
@@ -1542,9 +1651,11 @@ static int feed_process_token (hak_t* hak)
goto ok; goto ok;
case HAK_TOK_PRAGMA: case HAK_TOK_PRAGMA:
/* TODO: implement this */ /*hak_setsynerr(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak));
hak_setsynerr(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak)); goto oops;*/
goto oops; /* TODO: check if pragma is the first word in the line */
frd->expect_pragma_item = 1;
goto ok;
case HAK_TOK_VBAR: case HAK_TOK_VBAR:
if (frd->expect_vlist_item) if (frd->expect_vlist_item)
@@ -1729,15 +1840,14 @@ static int feed_process_token (hak_t* hak)
goto oops; goto oops;
} }
else if (can <= -1) 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 1
HAK_ASSERT(hak, can == 1 || can == 2);
#if 0
/* TODO: ... */
frd->obj = hak_makecnodebinop(hak, 0, TOKEN_LOC(hak), TOKEN_NAME(hak)); frd->obj = hak_makecnodebinop(hak, 0, TOKEN_LOC(hak), TOKEN_NAME(hak));
goto ok; goto auto_xlist;
#else #else
if (can == 1) goto ident; /* if binop is the first in the list */
HAK_ASSERT(hak, can == 2);
goto ident; goto ident;
#endif #endif
} }
@@ -1897,7 +2007,9 @@ static int feed_process_token (hak_t* hak)
case HAK_TOK_REVERT: case HAK_TOK_REVERT:
case HAK_TOK_AND: case HAK_TOK_AND:
case HAK_TOK_OR: case HAK_TOK_OR:
#if defined(USE_KW_PLUS)
case HAK_TOK_PLUS: case HAK_TOK_PLUS:
#endif
case HAK_TOK_SET: case HAK_TOK_SET:
case HAK_TOK_SET_R: case HAK_TOK_SET_R:
frd->obj = hak_makecnode(hak, kw_to_cnode_type(TOKEN_TYPE(hak)), 0, TOKEN_LOC(hak), TOKEN_NAME(hak)); frd->obj = hak_makecnode(hak, kw_to_cnode_type(TOKEN_TYPE(hak)), 0, TOKEN_LOC(hak), TOKEN_NAME(hak));
@@ -2411,12 +2523,15 @@ static int flx_start (hak_t* hak, hak_ooci_t c)
goto consumed; goto consumed;
default: default:
#if defined(STRICT_BINOP)
if (is_binop_char(c)) if (is_binop_char(c))
{ {
init_flx_binop(FLX_BINOP(hak)); init_flx_binop(FLX_BINOP(hak));
FEED_CONTINUE(hak, HAK_FLX_BINOP); 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); FEED_CONTINUE(hak, HAK_FLX_PLAIN_IDENT);
@@ -2528,6 +2643,7 @@ static int flx_dollared_ident (hak_t* hak, hak_ooci_t c)
{ {
if (!is_lead_ident_char(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, hak_setsynerrbfmt(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), HAK_NULL,
"'%c' prohibited as first character after '%.*js'", "'%c' prohibited as first character after '%.*js'",
c, TOKEN_NAME_LEN(hak), TOKEN_NAME_PTR(hak)); 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 * #"..." symbol literal
*/ */
#if defined(STRICT_BINOP)
if (is_binop_char(c)) if (is_binop_char(c))
{ {
reset_flx_token(hak); reset_flx_token(hak);
FEED_CONTINUE_WITH_CHAR(hak, c, HAK_FLX_HMARKED_BINOP); FEED_CONTINUE_WITH_CHAR(hak, c, HAK_FLX_HMARKED_BINOP);
goto consumed; goto consumed;
} }
#endif
switch (c) switch (c)
{ {
@@ -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; start = TOKEN_NAME_LEN(hak) - pi->seg_len;
seg.ptr = &TOKEN_NAME_CHAR(hak, start); seg.ptr = &TOKEN_NAME_CHAR(hak, start);
seg.len = pi->seg_len; seg.len = pi->seg_len;
#if defined(STRICT_BINOP)
if (seg.ptr[seg.len - 1] == '-') if (seg.ptr[seg.len - 1] == '-')
{ {
hak_setsynerrbfmt(hak, HAK_SYNERR_ILTOK, TOKEN_LOC(hak), TOKEN_NAME(hak), 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]); seg.ptr[seg.len - 1]);
return -1; return -1;
} }
#endif
tok_type = classify_ident_token(hak, &seg); tok_type = classify_ident_token(hak, &seg);
if (tok_type != HAK_TOK_IDENT) if (tok_type != HAK_TOK_IDENT)
{ {
@@ -3328,7 +3448,16 @@ static int flx_signed_token (hak_t* hak, hak_ooci_t c)
} }
else 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)); init_flx_pi(FLX_PI(hak));
/* the sign is already in the token name buffer. /* 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 */ /* let refeeding of 'c' happen at the next iteration */
FEED_CONTINUE(hak, HAK_FLX_PLAIN_IDENT); FEED_CONTINUE(hak, HAK_FLX_PLAIN_IDENT);
goto not_consumed; 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 #endif
} }
+4 -4
View File
@@ -6,12 +6,12 @@ class Apex {
return (core.basicNew self size) return (core.basicNew self size)
} }
fun[#class] respondsTo(mth) { fun[#class] respondsTo(mthname) {
return (core.classRespondsTo self mth) return (core.classRespondsTo self mthname)
} }
fun respondsTo(mth) { fun respondsTo(mthname) {
return (core.instRespondsTo self mth) return (core.instRespondsTo self mthname)
} }
fun primAt(pos) { fun primAt(pos) {
+30
View File
@@ -105,3 +105,33 @@ core.basicAtPut "xbcdefghiklmnl" 4 k ##ERROR: exception not handled - "receiver
k := (core.basicAt #abcdefg 1) k := (core.basicAt #abcdefg 1)
core.basicAtPut #xbcdefghiklmnl 4 k ##ERROR: exception not handled - "receiver immutable - xbcdefghiklmnl" 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 #<BLOCK>
---
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 '+'
}
+1
View File
@@ -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 } else { printf "ERROR: i is not equal to %d\n" k }
## dictionary
a := #{ a := #{
(if (> 10 20) true else false ): 10, (if (> 10 20) true else false ): 10,
(if (< 10 20) true else false ): 20 (if (< 10 20) true else false ): 20
+1
View File
@@ -166,6 +166,7 @@ abc.? := 20 ##ERROR: syntax error - '?' prohibited as first character of identif
--- ---
- := 20 ##ERROR: syntax error - bad lvalue - invalid element - - - := 20 ##ERROR: syntax error - bad lvalue - invalid element - -
--- ---
+19
View File
@@ -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 fun k(x) (+ x 30) ## (+ x 30) is valid function body
v := (k 10) v := (k 10)
if (== v 40) { printf "OK - %d\n" v } else { printf "ERROR - %d, not 40\n" v }; 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 }