From 3ea6b92b5f7e0d7a959a8904ad9f062b308e1454 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 6 Jan 2024 13:15:15 +0900 Subject: [PATCH] attempt to implement the assignment expression using := --- lib/comp.c | 18 +++++++++++- lib/err.c | 3 +- lib/hcl-utl.h | 2 ++ lib/hcl.h | 6 ++-- lib/print.c | 8 ++++-- lib/read.c | 79 ++++++++++++++++++++++++++++++++++++++++----------- lib/std.c | 2 +- 7 files changed, 92 insertions(+), 26 deletions(-) diff --git a/lib/comp.c b/lib/comp.c index d762000..57570ab 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -3814,7 +3814,8 @@ static int compile_cons_xlist_expression (hcl_t* hcl, hcl_cnode_t* obj, int nret } else if (HCL_CNODE_IS_SYMBOL(car) || HCL_CNODE_IS_DSYMBOL(car) || HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_XLIST) || - HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_MLIST)) + HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_MLIST) /*TODO|| + HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_ALIST)*/) { /* normal function call * ( ...) */ @@ -4453,6 +4454,10 @@ redo: case HCL_CONCODE_MLIST: if (compile_cons_mlist_expression(hcl, oprnd, 0) <= -1) return -1; break; + /* TODO: + case HCL_CONCODE_ALIST: + break; + */ case HCL_CONCODE_BLOCK: if (!(hcl->c->flags & HCL_COMPILE_ENABLE_BLOCK)) @@ -4504,6 +4509,12 @@ redo: hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty message send list"); return -1; + /* TODO: + case HCL_CONCODE_ALIST: + hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty assignment list"); + return -1; + */ + case HCL_CONCODE_BLOCK: if (!(hcl->c->flags & HCL_COMPILE_ENABLE_BLOCK)) { @@ -4590,6 +4601,11 @@ static int compile_object_r (hcl_t* hcl) { return compile_cons_mlist_expression(hcl, oprnd, cf->u.obj_r.nrets); } +/* TODO: + else if (HCL_CNODE_IS_CONS_CONCODED(oprnd, HCL_CONCODE_ALIST)) + { + } +*/ hcl_setsynerrbfmt (hcl, HCL_SYNERR_BANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "non-function call/non-message send disallowed"); return -1; diff --git a/lib/err.c b/lib/err.c index 0ad2ea2..1c9f0d8 100644 --- a/lib/err.c +++ b/lib/err.c @@ -126,6 +126,7 @@ static char* synerrstr[] = ". disallowed", ", disallowed", ": disallowed", + ":= disallowed", "no value after ,", "no value after :", "no separator between array/dictionary elements", @@ -160,8 +161,6 @@ static char* synerrstr[] = "unbalanced key/value pair", "unbalanced parenthesis/brace/bracket", "unexpected semicolon", - "empty x-list", - "empty m-list", "block expression expected" "block expression disallowed" }; diff --git a/lib/hcl-utl.h b/lib/hcl-utl.h index 7c1aebe..8674c4d 100644 --- a/lib/hcl-utl.h +++ b/lib/hcl-utl.h @@ -380,10 +380,12 @@ typedef enum hcl_cmgr_id_t hcl_cmgr_id_t; # define HCL_DFL_PATH_SEP ('\\') # define HCL_ALT_PATH_SEP ('/') # define HCL_IS_PATH_SEP(c) ((c) == HCL_DFL_PATH_SEP || (c) == HCL_ALT_PATH_SEP) +# define HCL_HAVE_ALT_PATH_SEP 1 #else # define HCL_DFL_PATH_SEP ('/') # define HCL_ALT_PATH_SEP ('/') # define HCL_IS_PATH_SEP(c) ((c) == HCL_DFL_PATH_SEP) +# undef HCL_HAVE_ALT_PATH_SEP #endif diff --git a/lib/hcl.h b/lib/hcl.h index 0f23aa0..6579229 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -130,6 +130,7 @@ enum hcl_synerrnum_t HCL_SYNERR_DOTBANNED, /* . disallowed */ HCL_SYNERR_COMMABANNED, /* , disallowed */ HCL_SYNERR_COLONBANNED, /* : disallowed */ + HCL_SYNERR_COLONEQBANNED, /* := disallowed */ HCL_SYNERR_COMMANOVALUE, /* no value after , */ HCL_SYNERR_COLONNOVALUE, /* no value after : */ HCL_SYNERR_NOSEP, /* no separator between array/dictionary elements */ @@ -164,8 +165,6 @@ enum hcl_synerrnum_t HCL_SYNERR_UNBALKV, /* unbalanced key/value pair */ HCL_SYNERR_UNBALPBB, /* unbalanced parenthesis/brace/bracket */ HCL_SYNERR_SEMICOLON, /* unexpected semicolon */ - HCL_SYNERR_EMPTYXLIST, /* empty x-list */ - HCL_SYNERR_EMPTYMLIST, /* empty m-list */ HCL_SYNERR_BLOCK, /* block expression expected */ HCL_SYNERR_BLOCKBANNED /* block expression disallowed */ }; @@ -1913,7 +1912,8 @@ enum hcl_concode_t { /* these can be set in the SYNCODE flags for a cons cell */ HCL_CONCODE_XLIST = 0, /* ( ) - executable list */ - HCL_CONCODE_MLIST, /* (: ) - message send list */ + HCL_CONCODE_MLIST, /* (obj:message) - message send list */ + HCL_CONCODE_ALIST, /* (a := 20) assignment list */ HCL_CONCODE_BLOCK, /* { } */ HCL_CONCODE_ARRAY, /* [ ] */ HCL_CONCODE_BYTEARRAY, /* #[ ] */ diff --git a/lib/print.c b/lib/print.c index ef5b833..efa9299 100644 --- a/lib/print.c +++ b/lib/print.c @@ -216,7 +216,8 @@ int hcl_fmt_object_ (hcl_fmtout_t* fmtout, hcl_oop_t obj) { /* navtive json */ { "(", "(" }, /*HCL_CONCODE_XLIST */ - { "(:", "(" }, /*HCL_CONCODE_MLIST */ + { "(", "(" }, /*HCL_CONCODE_MLIST */ + { "(", "(" }, /*HCL_CONCODE_ALIST */ { "{", "{" }, /*HCL_CONCODE_BLOCK */ { "[", "[" }, /*HCL_CONCODE_ARRAY */ { "#[", "[" }, /*HCL_CONCODE_BYTEARRAY */ @@ -228,6 +229,7 @@ int hcl_fmt_object_ (hcl_fmtout_t* fmtout, hcl_oop_t obj) { { ")", ")" }, /*HCL_CONCODE_XLIST */ { ")", ")" }, /*HCL_CONCODE_MLIST */ + { ")", ")" }, /*HCL_CONCODE_ALIST */ { "}", "}" }, /*HCL_CONCODE_BLOCK */ { "]", "]" }, /*HCL_CONCODE_ARRAY */ { "]", "]" }, /*HCL_CONCODE_BYTEARRAY */ @@ -425,6 +427,8 @@ next: if (hcl_bfmt_out(fmtout, opening_parens[concode][0]) <= -1) return -1; cur = obj; + /* TODO: for MLIST, print : after the first element. + * for ALIST, print := after the first element */ do { int x; @@ -434,7 +438,7 @@ next: ps.type = PRINT_STACK_CONS; ps.obj = HCL_CONS_CDR(cur); ps.idx = concode; /* this is not an index but use this field to restore concode */ - x = push (hcl, &ps); + x = push(hcl, &ps); if (x <= -1) return -1; obj = HCL_CONS_CAR(cur); diff --git a/lib/read.c b/lib/read.c index d79cb10..05ded1a 100644 --- a/lib/read.c +++ b/lib/read.c @@ -92,6 +92,7 @@ enum voca_id_t VOCA_XLIST, VOCA_MLIST, + VOCA_ALIST, VOCA_BLOCK, VOCA_ARRAY, VOCA_BYTEARRAY, @@ -110,11 +111,12 @@ enum list_flag_t DOTTED = (1 << 1), COMMAED = (1 << 2), COLONED = (1 << 3), - CLOSED = (1 << 4), - JSON = (1 << 5), - DATA_LIST = (1 << 6), - AUTO_FORGED = (1 << 7), /* automatically added list. only applicable to XLIST */ - AT_BEGINNING = (1 << 8) + COLONEQED = (1 << 4), + CLOSED = (1 << 5), + JSON = (1 << 6), + DATA_LIST = (1 << 7), + AUTO_FORGED = (1 << 8), /* automatically added list. only applicable to XLIST */ + AT_BEGINNING = (1 << 9) /* TOTOAL 12 items are allowed for LIST_FLAG_GET_CONCODE and LIST_FLAG_SET_CONCODE(). * they reserve lower 12 bits as flag bits.*/ @@ -131,7 +133,8 @@ static struct } cons_info[] = { /*[HCL_CONCODE_XLIST] =*/ { HCL_TOK_RPAREN, HCL_SYNERR_RPAREN, VOCA_XLIST }, /* XLIST ( ) */ - /*[HCL_CONCODE_MLIST] =*/ { HCL_TOK_RPAREN, HCL_SYNERR_RPAREN, VOCA_MLIST }, /* MLIST (: ) */ + /*[HCL_CONCODE_MLIST] =*/ { HCL_TOK_RPAREN, HCL_SYNERR_RPAREN, VOCA_MLIST }, /* MLIST (obj:message) */ + /*[HCL_CONCODE_ALIST] =*/ { HCL_TOK_RPAREN, HCL_SYNERR_RPAREN, VOCA_ALIST }, /* ALIST (var:=value) */ /*[HCL_CONCODE_BLOCK] =*/ { HCL_TOK_RBRACE, HCL_SYNERR_RBRACE, VOCA_BLOCK }, /* BLOCK { } */ /*[HCL_CONCODE_ARRAY] =*/ { HCL_TOK_RBRACK, HCL_SYNERR_RBRACK, VOCA_ARRAY }, /* ARRAY [ ] */ /*[HCL_CONCODE_BYTEARRAY] =*/ { HCL_TOK_RBRACK, HCL_SYNERR_RBRACK, VOCA_BYTEARRAY }, /* BYTEARRAY #[ ] */ @@ -503,11 +506,15 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, hcl_loc_t* list_loc, int* hcl->c->r.st = rstl->prev; /* pop off */ hcl_freemem (hcl, rstl); /* dispose of the stack node */ - if (fv & (COMMAED | COLONED)) + if (fv & (COMMAED | COLONED | COLONEQED)) { if (concode == HCL_CONCODE_MLIST) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_CALLABLE, TOKEN_LOC(hcl), HCL_NULL, "missing message after colon"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_CALLABLE, TOKEN_LOC(hcl), HCL_NULL, "missing message after :"); + } + else if (concode == HCL_CONCODE_ALIST) + { + hcl_setsynerrbfmt (hcl, HCL_SYNERR_CALLABLE, TOKEN_LOC(hcl), HCL_NULL, "missing value after :="); } else { @@ -602,9 +609,9 @@ static HCL_INLINE int can_colon_list (hcl_t* hcl) HCL_ASSERT (hcl, hcl->c->r.st != HCL_NULL); rstl = hcl->c->r.st; - /* mark the state that a colon has appeared in the list */ if (rstl->count <= 0) return 0; /* not allowed at the list beginning */ + /* mark the state that a colon has appeared in the list */ if (rstl->count == 1) rstl->flagv |= JSON; /* mark that the first key is colon-delimited */ else if (!(rstl->flagv & JSON)) return 0; /* the first key is not colon-delimited. so not allowed to colon-delimit other keys */ @@ -630,12 +637,36 @@ static HCL_INLINE int can_colon_list (hcl_t* hcl) return 1; } +static HCL_INLINE int can_coloneq_list (hcl_t* hcl) +{ + hcl_rstl_t* rstl; + hcl_concode_t cc; + + HCL_ASSERT (hcl, hcl->c->r.st != HCL_NULL); + rstl = hcl->c->r.st; + + if (rstl->count <= 0 || rstl->count > 1) return 0; /* allowed after the first item only */ + + /* repeated delimiters - e.g (a := := ...) (a : := ... ) */ + if (rstl->flagv & (COMMAED | COLONED | COLONEQED)) return 0; + + cc = LIST_FLAG_GET_CONCODE(rstl->flagv); + + /* assignment only in XLIST */ + if (cc != HCL_CONCODE_XLIST) return 0; + + /* TODO: some transformation is required... */ + + rstl->flagv |= COLONEQED; + return 1; +} + static HCL_INLINE void clear_comma_colon_flag (hcl_t* hcl) { hcl_rstl_t* rstl; HCL_ASSERT (hcl, hcl->c->r.st != HCL_NULL); rstl = hcl->c->r.st; - rstl->flagv &= ~(COMMAED | COLONED); + rstl->flagv &= ~(COMMAED | COLONED | COLONEQED); } static int chain_to_list (hcl_t* hcl, hcl_cnode_t* obj, hcl_loc_t* loc) @@ -1073,6 +1104,15 @@ static int feed_process_token (hcl_t* hcl) goto ok; + case HCL_TOK_COLONEQ: + if (frd->level <= 0 || !can_coloneq_list(hcl)) + { + hcl_setsynerr (hcl, HCL_SYNERR_COLONEQBANNED, TOKEN_LOC(hcl), HCL_NULL); + goto oops; + } + + goto ok; + case HCL_TOK_COMMA: if (frd->level <= 0 || !can_comma_list(hcl)) { @@ -1102,7 +1142,7 @@ static int feed_process_token (hcl_t* hcl) } concode = LIST_FLAG_GET_CONCODE(rstl->flagv); - if (concode != HCL_CONCODE_XLIST && concode != HCL_CONCODE_MLIST) + if (concode != HCL_CONCODE_XLIST && concode != HCL_CONCODE_MLIST && concode != HCL_CONCODE_ALIST) { hcl_setsynerr (hcl, HCL_SYNERR_UNBALPBB, TOKEN_LOC(hcl), HCL_NULL); goto oops; @@ -1313,8 +1353,11 @@ static int feed_process_token (hcl_t* hcl) { int forged_flagv; + /* both MLIST and ALIST begin as XLIST and get converted to MLIST + * or ALIST after more tokens are processed. so handling of MLIST + * or ALIST is needed at this phase */ forged_flagv = AUTO_FORGED; - LIST_FLAG_SET_CONCODE (forged_flagv, HCL_CONCODE_XLIST); /* TODO: how can i have MLIST? */ + LIST_FLAG_SET_CONCODE (forged_flagv, HCL_CONCODE_XLIST); /* this portion is similar to the code below the start_list label */ if (frd->level >= HCL_TYPE_MAX(int)) /* the nesting level too deep */ @@ -1323,12 +1366,14 @@ static int feed_process_token (hcl_t* hcl) goto oops; } - /* since the actual list opener doesn't exist, the location of the first element wil be the location of the list */ + /* since the actual list opener doesn't exist, the location of the + * first element wil be the location of the list */ if (enter_list(hcl, TOKEN_LOC(hcl), forged_flagv) <= -1) goto oops; frd->level++; /* level after the forged list has been added */ - /* a new list has been created automatically. unlike normal list creation by an explicit symbol - * such as a left parenthesis, a left brace, etc, the first element opens up this new list. - * so the AT_BEGINNING bit is turned off here */ + /* a new list has been created automatically. unlike normal list creation + * by an explicit symbol such as a left parenthesis, a left brace, etc, + * the first element opens up this new list. so the AT_BEGINNING bit is + * turned off here */ frd->flagv &= ~AT_BEGINNING; } break; @@ -1454,7 +1499,7 @@ static delim_token_t delim_token_tab[] = { "...", 3, HCL_TOK_ELLIPSIS }, /* for variable arguments */ { ":", 1, HCL_TOK_COLON }, /* key-value separator in dictionary */ - { ":=", 2, HCL_TOK_COLONEQ }, + { ":=", 2, HCL_TOK_COLONEQ }, /* assignment */ { "::", 2, HCL_TOK_DBLCOLONS }, { "::*", 3, HCL_TOK_DCSTAR }, /* class instantiation method */ { ":::", 3, HCL_TOK_TRPCOLONS }, /* superclass, class variables, class methods */ diff --git a/lib/std.c b/lib/std.c index 9ad9383..558e6e8 100644 --- a/lib/std.c +++ b/lib/std.c @@ -2478,7 +2478,7 @@ static void* dlopen_pfmod (hcl_t* hcl, const hcl_ooch_t* name, const hcl_ooch_t* if (dlen > 0 && bufptr[dlen - 1] != HCL_DFL_PATH_SEP) { - #if defined(__DOS__) || defined(_WIN32) || defined(__OS2__) + #if defined(HCL_HAVE_ALT_PATH_SEP) if (hcl_find_bchar(bufptr, dlen, HCL_ALT_PATH_SEP) && !hcl_find_bchar(bufptr, dlen, HCL_DFL_PATH_SEP)) bufptr[dlen++] = HCL_ALT_PATH_SEP;