From 6407d3c175e356ce45313e6863e3e97059eef8fa Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 6 Jul 2024 12:16:05 +0900 Subject: [PATCH] removed the option HCL_TRAIT_LANG_ENABLE_BLOCK, thus removing conditional codes for simplicity. changed the compiler to require a block expression as the class body --- bin/hcl.c | 10 +---- go/hcl.go | 1 - lib/comp.c | 114 +++++++++++++++---------------------------------- lib/hcl.h | 8 +--- lib/x-server.c | 1 - main.go | 2 +- pas/hcl.pas | 9 ++-- src/kernel.hcl | 19 ++++++++- t/Makefile.am | 4 +- t/Makefile.in | 4 +- 10 files changed, 64 insertions(+), 108 deletions(-) diff --git a/bin/hcl.c b/bin/hcl.c index 8f08fe4..9b08348 100644 --- a/bin/hcl.c +++ b/bin/hcl.c @@ -722,7 +722,7 @@ int main (int argc, char* argv[]) }; static hcl_bopt_t opt = { - "l:bnv", + "l:nv", lopt }; @@ -730,7 +730,6 @@ int main (int argc, char* argv[]) hcl_oow_t heapsize = DEFAULT_HEAPSIZE; int verbose = 0; int show_info = 0; - int enable_block = 0; int nl_terminator = 0; const char* modlibdirs = HCL_NULL; @@ -746,7 +745,6 @@ int main (int argc, char* argv[]) print_usage: fprintf (stderr, "Usage: %s [options] script-filename [output-filename]\n", argv[0]); fprintf (stderr, "Options are:\n"); - fprintf (stderr, " -b enable block construct with {}\n"); fprintf (stderr, " -n enable line-break as expression terminator\n"); return -1; } @@ -759,10 +757,6 @@ int main (int argc, char* argv[]) logopt = opt.arg; break; - case 'b': - enable_block = 1; - break; - case 'n': nl_terminator = 1; break; @@ -838,10 +832,8 @@ int main (int argc, char* argv[]) /*trait |= HCL_TRAIT_NOGC;*/ trait |= HCL_TRAIT_AWAIT_PROCS; #if 0 - if (enable_block) trait |= HCL_TRAIT_LANG_ENABLE_BLOCK; if (nl_terminator) trait |= HCL_TRAIT_LANG_ENABLE_EOL; #else - trait |= HCL_TRAIT_LANG_ENABLE_BLOCK; trait |= HCL_TRAIT_LANG_ENABLE_EOL; #endif hcl_setoption (hcl, HCL_TRAIT, &trait); diff --git a/go/hcl.go b/go/hcl.go index 7e570f1..65de131 100644 --- a/go/hcl.go +++ b/go/hcl.go @@ -67,7 +67,6 @@ type Ext struct { type BitMask C.hcl_bitmask_t -const TRAIT_LANG_ENABLE_BLOCK BitMask = C.HCL_TRAIT_LANG_ENABLE_BLOCK const TRAIT_LANG_ENABLE_EOL BitMask = C.HCL_TRAIT_LANG_ENABLE_EOL var inst_table InstanceTable diff --git a/lib/comp.c b/lib/comp.c index 08a90ca..b35e729 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -28,9 +28,10 @@ * no variable declaration if not enclosed in parentheses */ #define LANG_LIMIT_DO -#define FOR_NONE (0) -#define FOR_IF (1) -#define FOR_TRY (2) +#define FOR_NONE (0) +#define FOR_IF (1) +#define FOR_TRY (2) +#define FOR_CLASS (3) enum { @@ -469,8 +470,6 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl car = HCL_CNODE_CONS_CAR(c); if (!car || (HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_VLIST) || HCL_CNODE_IS_ELIST_CONCODED(car, HCL_CONCODE_VLIST))) - /*(!HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_BLOCK) && - !HCL_CNODE_IS_ELIST_CONCODED(car, HCL_CONCODE_BLOCK)))*/ { no_block: hcl_setsynerrbfmt ( @@ -480,6 +479,13 @@ static int check_block_expression_as_body (hcl_t* hcl, hcl_cnode_t* c, const hcl return -1; } + if (for_what == FOR_CLASS) + { + /* the class body must be enclosed in { .. }. e.g class X { ... } */ + if (!HCL_CNODE_IS_CONS_CONCODED(car, HCL_CONCODE_BLOCK) && + !HCL_CNODE_IS_ELIST_CONCODED(car, HCL_CONCODE_BLOCK)) goto no_block; + } + /* there are special words that can't start a new expression */ if (HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELIF) || HCL_CNODE_IS_SYMBOL_SYNCODED(car, HCL_SYNCODE_ELSE) || @@ -2331,10 +2337,7 @@ static HCL_INLINE int compile_else (hcl_t* hcl) return -1; } - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, obj, cmd, FOR_NONE) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, obj, cmd, FOR_NONE) <= -1) return -1; SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT_LIST, obj); @@ -2381,7 +2384,7 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src, int defclass) if (defclass) { - /* defun must be followed by an explicit function name */ + /* defclass must be followed by an explicit class name */ HCL_ASSERT (hcl, HCL_CNODE_IS_SYMBOL_SYNCODED(cmd, HCL_SYNCODE_DEFCLASS)); class_as_defclass: @@ -2426,16 +2429,9 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src, int defclass) class_name = HCL_CNODE_CONS_CAR(obj); if (HCL_CNODE_IS_SYMBOL(class_name)) { - #if 0 - hcl_setsynerrbfmt ( - hcl, HCL_SYNERR_BANNEDVARNAME, HCL_CNODE_GET_LOC(class_name), HCL_CNODE_GET_TOK(class_name), - "class name not allowed in %.*js", HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); - return -1; - #else /* to handle 'class' in place of 'defclass' */ defclass = 1; goto class_as_defclass; - #endif } } @@ -2447,7 +2443,7 @@ static int compile_class (hcl_t* hcl, hcl_cnode_t* src, int defclass) hcl_cnode_t* tmp, * dcl; tmp = HCL_CNODE_CONS_CAR(obj); - if (!HCL_CNODE_IS_DBLCOLONS(tmp)) goto no_superclass; + if (/*!HCL_CNODE_IS_COLON(tmp)*/!HCL_CNODE_IS_DBLCOLONS(tmp)) goto no_superclass; tmp = obj; obj = HCL_CNODE_CONS_CDR(obj); @@ -2537,7 +2533,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) ) */ tmp = HCL_CNODE_CONS_CAR(obj); - if (HCL_CNODE_IS_DBLCOLONS(tmp)) + if (/*HCL_CNODE_IS_COLON(tmp)|| */ HCL_CNODE_IS_DBLCOLONS(tmp)) { /* class variables */ hcl_oow_t checkpoint; @@ -2545,14 +2541,14 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) obj = HCL_CNODE_CONS_CDR(obj); if (!obj || !HCL_CNODE_IS_CONS(obj)) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no expression or declaration after triple colons"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no expression or declaration after colon"); return -1; } tmp = HCL_CNODE_CONS_CAR(obj); if (!HCL_CNODE_IS_CONS_CONCODED(tmp, HCL_CONCODE_VLIST)) { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no declaration after triple colons"); + hcl_setsynerrbfmt (hcl, HCL_SYNERR_EOX, HCL_CNODE_GET_LOC(tmp), HCL_NULL, "no declaration after colon"); return -1; } @@ -2624,10 +2620,7 @@ static HCL_INLINE int compile_class_p1 (hcl_t* hcl) if (emit_push_literal(hcl, tmp, &cf->u._class.start_loc) <= -1) goto oops; } - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, obj, cf->u._class.cmd_cnode, FOR_NONE) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, obj, cf->u._class.cmd_cnode, FOR_CLASS) <= -1) return -1; if (push_clsblk(hcl, &cf->u._class.start_loc, nivars, ncvars, &hcl->c->tv.s.ptr[ivar_start], ivar_len, &hcl->c->tv.s.ptr[cvar_start], cvar_len) <= -1) goto oops; if (push_cblk(hcl, &cf->u._class.start_loc, HCL_CBLK_TYPE_CLASS) <= -1) goto oops; /* the class block shall be treated as a control block, too */ @@ -3049,34 +3042,20 @@ static int compile_lambda (hcl_t* hcl, hcl_cnode_t* src, int defun) } HCL_ASSERT (hcl, nargs + nrvars == hcl->c->tv.wcount - saved_tv_wcount); - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - /* - * defun aa(a b) { ... }; - * (defun aa(a b) { ... }) - * - * the block expression must be the first and the only expression at the body position. - * the variable declaration can't be placed before the block expression. - * it is supported inside the block expression itself. - */ - hcl_cnode_t* blk; - blk = HCL_CNODE_CONS_CDR(obj); - if (check_block_expression_as_body(hcl, blk, cmd, FOR_NONE) <= -1) return -1; - obj = blk; - nlvars = 0; /* no known local variables until the actual block is processed */ - } - else - { - obj = HCL_CNODE_CONS_CDR(obj); - tv_dup_start = hcl->c->tv.s.len; - if (collect_vardcls(hcl, obj, &obj, tv_dup_start, &nlvars, "local") <= -1) return -1; - if (nlvars > MAX_CODE_NBLKLVARS) - { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARFLOOD, HCL_CNODE_GET_LOC(args), HCL_NULL, "too many(%zu) variables in %.*js", nlvars, HCL_CNODE_GET_TOKLEN(cmd), HCL_CNODE_GET_TOKPTR(cmd)); - return -1; - } - } + /* + * defun aa(a b) { ... }; + * (defun aa(a b) { ... }) + * + * the block expression must be the first and the only expression at the body position. + * the variable declaration can't be placed before the block expression. + * it is supported inside the block expression itself. + */ + hcl_cnode_t* blk; + blk = HCL_CNODE_CONS_CDR(obj); + if (check_block_expression_as_body(hcl, blk, cmd, FOR_NONE) <= -1) return -1; + obj = blk; + nlvars = 0; /* no known local variables until the actual block is processed */ HCL_ASSERT (hcl, nargs + nrvars + nlvars == hcl->c->tv.wcount - saved_tv_wcount); @@ -3468,10 +3447,7 @@ static int compile_try (hcl_t* hcl, hcl_cnode_t* src) jump_inst_pos = hcl->code.bc.len; if (emit_single_param_instruction(hcl, HCL_CODE_TRY_ENTER, MAX_CODE_JUMP, HCL_CNODE_GET_LOC(cmd)) <= -1) return -1; - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, obj, cmd, FOR_TRY) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, obj, cmd, FOR_TRY) <= -1) return -1; SWITCH_TOP_CFRAME (hcl, COP_COMPILE_TRY_OBJECT_LIST, obj); /* 1*/ PUSH_SUBCFRAME (hcl, COP_POST_TRY, cmd); /* 2 */ @@ -3598,10 +3574,7 @@ static HCL_INLINE int compile_catch (hcl_t* hcl) HCL_ASSERT (hcl, fbi->tmpr_nargs + fbi->tmpr_nrvars + fbi->tmpr_nlvars == fbi->tmprcnt - par_tmprcnt); obj = HCL_CNODE_CONS_CDR(obj); - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, obj, cmd, FOR_NONE) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, obj, cmd, FOR_NONE) <= -1) return -1; /* jump_inst_pos hold the instruction pointer that skips the catch block at the end of the try block */ patch_nearest_post_try (hcl, &jump_inst_pos); @@ -3748,10 +3721,7 @@ static int compile_while (hcl_t* hcl, hcl_cnode_t* src, int next_cop) cond = HCL_CNODE_CONS_CAR(obj); body = HCL_CNODE_CONS_CDR(obj); - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, body, cmd, FOR_NONE) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, body, cmd, FOR_NONE) <= -1) return -1; SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, cond); /* 1 */ @@ -4661,11 +4631,6 @@ redo: break; case HCL_CONCODE_BLOCK: - if (!(hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK)) - { - hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLOCKBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "block expression disallowed"); - return -1; - } if (compile_cons_block_expression(hcl, oprnd) <= -1) return -1; break; @@ -4721,12 +4686,6 @@ redo: return -1; case HCL_CONCODE_BLOCK: - if (!(hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK)) - { - /* this is treated the same as HCL_CNODE_CONS with CONCODE BLOCK */ - hcl_setsynerrbfmt (hcl, HCL_SYNERR_BLOCKBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "block expression disallowed"); - return -1; - } if (compile_cons_block_expression(hcl, oprnd) <= -1) return -1; break; @@ -5176,10 +5135,7 @@ static HCL_INLINE int post_if_cond (hcl_t* hcl) HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); body_pos = hcl->code.bc.len; - if (hcl->option.trait & HCL_TRAIT_LANG_ENABLE_BLOCK) - { - if (check_block_expression_as_body(hcl, cf->operand, cf->u.post_if.cmd_cnode, FOR_IF) <= -1) return -1; - } + if (check_block_expression_as_body(hcl, cf->operand, cf->u.post_if.cmd_cnode, FOR_IF) <= -1) return -1; SWITCH_TOP_CFRAME (hcl, COP_COMPILE_IF_OBJECT_LIST, cf->operand); /* 1 */ PUSH_SUBCFRAME (hcl, COP_POST_IF_BODY, cf->operand); /* 2 */ diff --git a/lib/hcl.h b/lib/hcl.h index dc68fae..6ec6814 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -236,9 +236,6 @@ enum hcl_trait_t /* return EOL as a token */ /* TODO: make this pragma controllable */ HCL_TRAIT_LANG_ENABLE_EOL = (((hcl_bitmask_t)1) << 14), - - /* enable block expression as mandatory argument to some expresions */ - HCL_TRAIT_LANG_ENABLE_BLOCK = (((hcl_bitmask_t)1) << 15), }; typedef enum hcl_trait_t hcl_trait_t; @@ -1566,10 +1563,7 @@ enum hcl_compile_flag_t HCL_COMPILE_CLEAR_CODE = (1 << 0), /* clear the top-level function block at the end of hcl_compile() */ - HCL_COMPILE_CLEAR_FNBLK = (1 << 1), - - /* enable the block {} mode */ - HCL_COMPILE_ENABLE_BLOCK = (1 << 2) /*TODO: make this #pragma controllable */ + HCL_COMPILE_CLEAR_FNBLK = (1 << 1) }; typedef enum hcl_compile_flag_t hcl_compile_flag_t; #endif diff --git a/lib/x-server.c b/lib/x-server.c index 2ce6cd8..d10974c 100644 --- a/lib/x-server.c +++ b/lib/x-server.c @@ -1522,7 +1522,6 @@ static int init_worker_hcl (hcl_server_worker_t* worker) if (server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_GC) trait |= HCL_TRAIT_DEBUG_GC; if (server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_BIGINT) trait |= HCL_TRAIT_DEBUG_BIGINT; #endif - trait |= HCL_TRAIT_LANG_ENABLE_BLOCK; trait |= HCL_TRAIT_LANG_ENABLE_EOL; hcl_setoption (hcl, HCL_TRAIT, &trait); diff --git a/main.go b/main.go index c77f319..57b2913 100644 --- a/main.go +++ b/main.go @@ -80,7 +80,7 @@ func main() { x.SetLogTarget("/dev/stderr") } - x.SetTrait(x.GetTrait() | hcl.TRAIT_LANG_ENABLE_EOL | hcl.TRAIT_LANG_ENABLE_BLOCK) + x.SetTrait(x.GetTrait() | hcl.TRAIT_LANG_ENABLE_EOL) err = x.Ignite(1000000) if err != nil { diff --git a/pas/hcl.pas b/pas/hcl.pas index 6575ee8..63088e8 100644 --- a/pas/hcl.pas +++ b/pas/hcl.pas @@ -16,13 +16,11 @@ type BitMask = longword; (* this must match hcl_bitmask_t in hcl.h *) (*const - TRAIT_LANG_ENABLE_EOF = (BitMask(1) shl 14); - TRAIT_LANG_ENABLE_BLOCK = (BitMask(1) shl 15);*) + TRAIT_LANG_ENABLE_EOL = (BitMask(1) shl 14); *) type TraitBit = ( (* this enum must follow hcl_trait_t in hcl.h *) - LANG_ENABLE_EOF = (BitMask(1) shl 14), - LANG_ENABLE_BLOCK = (BitMask(1) shl 15) + LANG_ENABLE_EOL = (BitMask(1) shl 14) ); Option = ( (* this enum must follow hcl_option_t in hcl.h *) @@ -171,8 +169,9 @@ begin raise Exception.Create(errmsg); end; + if hcl_getoption(h, Option.TRAIT, @tb) <= -1 then tb := 0; - tb := BitMask(TraitBit.LANG_ENABLE_EOF) or BitMask(TraitBit.LANG_ENABLE_BLOCK); + tb := tb or BitMask(TraitBit.LANG_ENABLE_EOL); if hcl_setoption(h, Option.TRAIT, @tb) <= -1 then begin hcl_errnum_to_errbcstr(errnum, @errmsg, length(errmsg)); hcl_close(h); diff --git a/src/kernel.hcl b/src/kernel.hcl index 037c331..355b339 100644 --- a/src/kernel.hcl +++ b/src/kernel.hcl @@ -1,7 +1,7 @@ class Object { } -class Collection: Object { +class Collection : Object { } class IndexedCollection: Collection { @@ -26,5 +26,22 @@ fun Collection:slice(index count) { +class String: Array (a b c) { +} + +class String: Array ( + monaco + duncan + falcon + :deuce + :canival + :pebble + :godzilla +) { + fun Collection:slice(index count) { + return (arr.slice self index count) + } +} + printf "string length %d\n" ("aaaa":length) diff --git a/t/Makefile.am b/t/Makefile.am index 37c8294..1d04131 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -32,8 +32,8 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) $(check_ERRORS) TEST_EXTENSIONS = .hcl .err -HCL_LOG_COMPILER = $(SHELL) $(abs_srcdir)/run.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -b -n +HCL_LOG_COMPILER = $(SHELL) $(abs_srcdir)/run.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -n AM_HCL_LOG_FLAGS = -ERR_LOG_COMPILER = $(SHELL) $(abs_srcdir)/err.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -b -n +ERR_LOG_COMPILER = $(SHELL) $(abs_srcdir)/err.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -n AM_ERR_LOG_FLAGS = diff --git a/t/Makefile.in b/t/Makefile.in index 47e8303..d84d018 100644 --- a/t/Makefile.in +++ b/t/Makefile.in @@ -497,9 +497,9 @@ check_ERRORS = \ EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) TEST_EXTENSIONS = .hcl .err -HCL_LOG_COMPILER = $(SHELL) $(abs_srcdir)/run.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -b -n +HCL_LOG_COMPILER = $(SHELL) $(abs_srcdir)/run.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -n AM_HCL_LOG_FLAGS = -ERR_LOG_COMPILER = $(SHELL) $(abs_srcdir)/err.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -b -n +ERR_LOG_COMPILER = $(SHELL) $(abs_srcdir)/err.sh ../bin/hcl --modlibdirs="@abs_top_builddir@/mod:@abs_top_builddir@/mod/.libs" --heapsize=0 -n AM_ERR_LOG_FLAGS = all: all-am