diff --git a/lib/comp.c b/lib/comp.c index 50fc157..610decd 100644 --- a/lib/comp.c +++ b/lib/comp.c @@ -36,10 +36,10 @@ enum #define BLK_INFO_BUFFER_ALIGN 128 #define EMIT_BYTE_INSTRUCTION(hcl,code) \ - do { if (emit_byte_instruction(hcl,code) <= -1) return -1; } while(0) + do { if (emit_byte_instruction(hcl, code, HCL_NULL) <= -1) return -1; } while(0) #define EMIT_SINGLE_PARAM_INSTRUCTION(hcl,code) \ - do { if (emit_byte_instruction(hcl,code) <= -1) return -1; } while(0) + do { if (emit_byte_instruction(hcl, code, HCL_NULL) <= -1) return -1; } while(0) /* -------------------------------------------- @@ -193,7 +193,7 @@ static HCL_INLINE void patch_instruction (hcl_t* hcl, hcl_oow_t index, hcl_oob_t hcl->code.bc.ptr[index] = bc; } -static int emit_byte_instruction (hcl_t* hcl, hcl_oob_t bc) +static int emit_byte_instruction (hcl_t* hcl, hcl_oob_t bc, const hcl_ioloc_t* srcloc) { /* the context object has the ip field. it should be representable * in a small integer. for simplicity, limit the total byte code length @@ -208,24 +208,41 @@ static int emit_byte_instruction (hcl_t* hcl, hcl_oob_t bc) if (hcl->code.bc.len >= hcl->code.bc.capa) { - hcl_oob_t* tmp; hcl_oow_t newcapa; + hcl_oob_t* tmp; + hcl_oow_t* tmp2; newcapa = HCL_ALIGN(hcl->code.bc.capa + 1, HCL_BC_BUFFER_ALIGN); - tmp = hcl_reallocmem(hcl, hcl->code.bc.ptr, HCL_SIZEOF(*tmp) * newcapa); - if (!tmp) return -1; + tmp = (hcl_oob_t*)hcl_reallocmem(hcl, hcl->code.bc.ptr, HCL_SIZEOF(*tmp) * newcapa); + if (HCL_UNLIKELY(!tmp)) return -1; + + tmp2 = (hcl_oow_t*)hcl_reallocmem(hcl, hcl->code.locptr, HCL_SIZEOF(*tmp2) * newcapa); + if (HCL_UNLIKELY(!tmp2)) + { + hcl_freemem (hcl, tmp); + return -1; + } + HCL_MEMSET (&tmp2[hcl->code.bc.capa], 0, HCL_SIZEOF(*tmp2) * (newcapa - hcl->code.bc.capa)); hcl->code.bc.ptr = tmp; hcl->code.bc.capa = newcapa; + hcl->code.locptr = tmp2; } - hcl->code.bc.ptr[hcl->code.bc.len++] = bc; + hcl->code.bc.ptr[hcl->code.bc.len] = bc; + + if (srcloc) + { + hcl->code.locptr[hcl->code.bc.len] = srcloc->line; + } + + hcl->code.bc.len++; return 0; } int hcl_emitbyteinstruction (hcl_t* hcl, hcl_oob_t bc) { - return emit_byte_instruction(hcl, bc); + return emit_byte_instruction(hcl, bc, HCL_NULL); } static int emit_single_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1) @@ -313,7 +330,7 @@ static int emit_single_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1 return -1; write_short: - if (emit_byte_instruction(hcl, bc) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1) return -1; return 0; write_long: @@ -323,12 +340,12 @@ write_long: return -1; } #if (HCL_HCL_CODE_LONG_PARAM_SIZE == 2) - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF) <= -1 || - emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1 & 0xFF, HCL_NULL) <= -1) return -1; #else - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, param_1) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1, HCL_NULL) <= -1) return -1; #endif return 0; @@ -339,15 +356,15 @@ write_long2: return -1; } #if (HCL_HCL_CODE_LONG_PARAM_SIZE == 2) - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, (param_1 >> 24) & 0xFF) <= -1 || - emit_byte_instruction(hcl, (param_1 >> 16) & 0xFF) <= -1 || - emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF) <= -1 || - emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, (param_1 >> 24) & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, (param_1 >> 16) & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1 & 0xFF, HCL_NULL) <= -1) return -1; #else - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF) <= -1 || - emit_byte_instruction(hcl, param_1 & 0xFF) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, (param_1 >> 8) & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1 & 0xFF, HCL_NULL) <= -1) return -1; #endif return 0; } @@ -379,8 +396,12 @@ static int emit_double_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1 goto write_long; } - - case HCL_CODE_MAKE_FUNCTION: /* this is quad-param instruction. you should emit two more parameters after the call to this function */ + /* MAKE_FUNCTION is a quad-parameter instruction. + * The caller must emit two more parameters after the call to this function. + * however the instruction format is the same up to the second + * parameters between MAKE_FUNCTION and MAKE_BLOCK. + */ + case HCL_CODE_MAKE_FUNCTION: case HCL_CODE_MAKE_BLOCK: bc = cmd; goto write_long; @@ -390,8 +411,8 @@ static int emit_double_param_instruction (hcl_t* hcl, int cmd, hcl_oow_t param_1 return -1; write_short: - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, param_2) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_2, HCL_NULL) <= -1) return -1; return 0; write_long: @@ -401,15 +422,15 @@ write_long: return -1; } #if (HCL_HCL_CODE_LONG_PARAM_SIZE == 2) - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, param_1 >> 8) <= -1 || - emit_byte_instruction(hcl, param_1 & 0xFF) <= -1 || - emit_byte_instruction(hcl, param_2 >> 8) <= -1 || - emit_byte_instruction(hcl, param_2 & 0xFF) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1 >> 8, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1 & 0xFF, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_2 >> 8, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_2 & 0xFF, HCL_NULL) <= -1) return -1; #else - if (emit_byte_instruction(hcl, bc) <= -1 || - emit_byte_instruction(hcl, param_1) <= -1 || - emit_byte_instruction(hcl, param_2) <= -1) return -1; + if (emit_byte_instruction(hcl, bc, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_1, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param_2, HCL_NULL) <= -1) return -1; #endif return 0; } @@ -423,10 +444,10 @@ static HCL_INLINE int emit_long_param (hcl_t* hcl, hcl_oow_t param) } #if (HCL_HCL_CODE_LONG_PARAM_SIZE == 2) - return (emit_byte_instruction(hcl, param >> 8) <= -1 || - emit_byte_instruction(hcl, param & 0xFF) <= -1)? -1: 0; + return (emit_byte_instruction(hcl, param >> 8, HCL_NULL) <= -1 || + emit_byte_instruction(hcl, param & 0xFF, HCL_NULL) <= -1)? -1: 0; #else - return emit_byte_instruction(hcl, param_1); + return emit_byte_instruction(hcl, param_1, HCL_NULL); #endif } @@ -442,16 +463,16 @@ static int emit_push_literal (hcl_t* hcl, hcl_oop_t obj) switch (i) { case -1: - return emit_byte_instruction(hcl, HCL_CODE_PUSH_NEGONE); + return emit_byte_instruction(hcl, HCL_CODE_PUSH_NEGONE, HCL_NULL); case 0: - return emit_byte_instruction(hcl, HCL_CODE_PUSH_ZERO); + return emit_byte_instruction(hcl, HCL_CODE_PUSH_ZERO, HCL_NULL); case 1: - return emit_byte_instruction(hcl, HCL_CODE_PUSH_ONE); + return emit_byte_instruction(hcl, HCL_CODE_PUSH_ONE, HCL_NULL); case 2: - return emit_byte_instruction(hcl, HCL_CODE_PUSH_TWO); + return emit_byte_instruction(hcl, HCL_CODE_PUSH_TWO, HCL_NULL); } if (i >= 0 && i <= MAX_CODE_PARAM) @@ -657,6 +678,7 @@ enum COP_COMPILE_ARRAY_LIST, COP_COMPILE_BYTEARRAY_LIST, COP_COMPILE_DIC_LIST, + COP_COMPILE_QLIST, /* compile data list */ COP_SUBCOMPILE_ELIF, COP_SUBCOMPILE_ELSE, @@ -666,9 +688,11 @@ enum COP_EMIT_MAKE_ARRAY, COP_EMIT_MAKE_BYTEARRAY, COP_EMIT_MAKE_DIC, + COP_EMIT_MAKE_DLIST, COP_EMIT_POP_INTO_ARRAY, COP_EMIT_POP_INTO_BYTEARRAY, COP_EMIT_POP_INTO_DIC, + COP_EMIT_POP_INTO_DLIST, COP_EMIT_LAMBDA, COP_EMIT_POP_STACKTOP, @@ -800,7 +824,7 @@ static int compile_break (hcl_t* hcl, hcl_oop_t src) * function call, i generate PUSH_NIL so nil becomes a return value. * (set x (until #f (break))) * x will get nill. */ - if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL, HCL_NULL) <= -1) return -1; /* TODO: study if supporting expression after break is good like return. (break (+ 10 20)) */ HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); @@ -1072,8 +1096,8 @@ static int compile_lambda (hcl_t* hcl, hcl_oop_t src, int defun) /* make_function nargs ntmprs lfbase lfsize */ if (emit_double_param_instruction(hcl, HCL_CODE_MAKE_FUNCTION, nargs, ntmprs) <= -1) return -1; lfbase_pos = hcl->code.bc.len; - if (emit_long_param(hcl, hcl->code.lit.len - hcl->c->blk.info[hcl->c->blk.depth - 1].lfbase) <= -1) return -1; /* lfbase */ - lfsize_pos = hcl->code.bc.len; + if (emit_long_param(hcl, hcl->code.lit.len - hcl->c->blk.info[hcl->c->blk.depth - 1].lfbase) <= -1) return -1; /* literal frame base */ + lfsize_pos = hcl->code.bc.len; /* literal frame size */ if (emit_long_param(hcl, 0) <= -1) return -1; } else @@ -1408,6 +1432,40 @@ static int compile_cons_dic_expression (hcl_t* hcl, hcl_oop_t obj) return 0; } +static int compile_cons_qlist_expression (hcl_t* hcl, hcl_oop_t obj) +{ + /* #( 1 2 3 ) + * #(1 (+ 2 3) 5) + * */ + + hcl_ooi_t nargs; + hcl_cframe_t* cf; + + /* NOTE: cframe management functions don't use the object memory. + * many operations can be performed without taking GC into account */ + SWITCH_TOP_CFRAME (hcl, COP_EMIT_MAKE_DLIST, HCL_SMOOI_TO_OOP(0)); + + nargs = hcl_countcons(hcl, obj); + if (nargs > MAX_CODE_PARAM) + { + /* TODO: change to syntax error */ + hcl_setsynerrbfmt (hcl, HCL_SYNERR_ARGFLOOD, HCL_NULL, HCL_NULL, "too many(%zd) elements into array - %O", nargs, obj); + return -1; + } + + /* redundant cdr check is performed inside compile_object_list() */ + PUSH_SUBCFRAME (hcl, COP_COMPILE_QLIST, obj); + cf = GET_SUBCFRAME(hcl); +/* cf->u.qlist.index = 0;*/ + + /* patch the argument count in the operand field of the COP_EMIT_MAKE_ARRAY frame */ + cf = GET_TOP_CFRAME(hcl); + HCL_ASSERT (hcl, cf->opcode == COP_EMIT_MAKE_DLIST); + cf->operand = HCL_SMOOI_TO_OOP(nargs); + + return 0; +} + static int compile_cons_xlist_expression (hcl_t* hcl, hcl_oop_t obj) { hcl_oop_t car; @@ -1697,7 +1755,10 @@ static int compile_object (hcl_t* hcl) if (compile_cons_dic_expression(hcl, cf->operand) <= -1) return -1; break; - /* TODO: QLIST? */ + case HCL_CONCODE_QLIST: + if (compile_cons_qlist_expression(hcl, cf->operand) <= -1) return -1; + break; + default: if (compile_cons_xlist_expression(hcl, cf->operand) <= -1) return -1; break; @@ -1980,6 +2041,53 @@ static int compile_dic_list (hcl_t* hcl) return 0; } +static int compile_qlist (hcl_t* hcl) +{ + hcl_cframe_t* cf; + hcl_oop_t coperand; + + cf = GET_TOP_CFRAME(hcl); + HCL_ASSERT (hcl, cf->opcode == COP_COMPILE_QLIST); + + coperand = cf->operand; + + if (HCL_IS_NIL(hcl, coperand)) + { + POP_CFRAME (hcl); + } + else + { + hcl_oop_t car, cdr; + hcl_ooi_t oldidx; + + if (!HCL_IS_CONS(hcl, coperand)) + { + hcl_setsynerrbfmt ( + hcl, HCL_SYNERR_DOTBANNED, HCL_NULL, HCL_NULL, + "redundant cdr in the qlist list - %O", coperand); /* TODO: error location */ + return -1; + } + + car = HCL_CONS_CAR(coperand); + cdr = HCL_CONS_CDR(coperand); + + /*oldidx = cf->u.qlist.index;*/ + + SWITCH_TOP_CFRAME (hcl, COP_COMPILE_OBJECT, car); + if (!HCL_IS_NIL(hcl, cdr)) + { + PUSH_SUBCFRAME (hcl, COP_COMPILE_QLIST, cdr); + cf = GET_SUBCFRAME(hcl); + /*cf->u.qlist_list.index = oldidx + 1;*/ + } + + PUSH_SUBCFRAME (hcl, COP_EMIT_POP_INTO_DLIST, HCL_SMOOI_TO_OOP(oldidx)); + } + + return 0; +} + + /* ========================================================================= */ static HCL_INLINE int patch_nearest_post_if_body (hcl_t* hcl) @@ -1997,7 +2105,7 @@ static HCL_INLINE int patch_nearest_post_if_body (hcl_t* hcl) if (hcl->code.bc.len <= cf->u.post_if.body_pos) { /* the if body is empty. */ - if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL, HCL_NULL) <= -1) return -1; } HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); @@ -2021,7 +2129,7 @@ static HCL_INLINE int patch_nearest_post_if_body (hcl_t* hcl) /* beginning of the elif/else block code */ /* to drop the result of the conditional when the conditional is false */ - if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; /* this is the actual beginning */ HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); @@ -2132,7 +2240,7 @@ static HCL_INLINE int subcompile_and_expr (hcl_t* hcl) jump_inst_pos = hcl->code.bc.len; if (emit_single_param_instruction(hcl, HCL_CODE_JUMP_FORWARD_IF_FALSE, MAX_CODE_JUMP) <= -1) return -1; - if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; expr = HCL_CONS_CAR(obj); obj = HCL_CONS_CDR(obj); @@ -2199,7 +2307,7 @@ static HCL_INLINE int subcompile_or_expr (hcl_t* hcl) jump_inst_pos = hcl->code.bc.len; if (emit_single_param_instruction(hcl, HCL_CODE_JUMP_FORWARD_IF_TRUE, MAX_CODE_JUMP) <= -1) return -1; - if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; expr = HCL_CONS_CAR(obj); obj = HCL_CONS_CDR(obj); @@ -2252,7 +2360,7 @@ static HCL_INLINE int post_if_cond (hcl_t* hcl) if (emit_single_param_instruction (hcl, HCL_CODE_JUMP_FORWARD_IF_FALSE, MAX_CODE_JUMP) <= -1) return -1; /* to drop the result of the conditional when it is true */ - if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); body_pos = hcl->code.bc.len; @@ -2279,7 +2387,7 @@ static HCL_INLINE int post_if_body (hcl_t* hcl) if (hcl->code.bc.len <= cf->u.post_if.body_pos) { /* if body is empty */ - if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_PUSH_NIL, HCL_NULL) <= -1) return -1; } /* HCL_CODE_LONG_PARAM_SIZE + 1 => size of the long JUMP_FORWARD_IF_FALSE instruction */ @@ -2324,7 +2432,7 @@ static HCL_INLINE int post_while_cond (hcl_t* hcl) } if (emit_single_param_instruction (hcl, jump_inst, MAX_CODE_JUMP) <= -1) return -1; - if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); body_pos = hcl->code.bc.len; @@ -2359,7 +2467,7 @@ static HCL_INLINE int post_while_body (hcl_t* hcl) * pop_stacktop * this check prevents another pop_stacktop between 1) and 2) */ - if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) return -1; + if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) return -1; } HCL_ASSERT (hcl, hcl->code.bc.len < HCL_SMOOI_MAX); @@ -2470,6 +2578,21 @@ static HCL_INLINE int emit_make_dic (hcl_t* hcl) return n; } +static HCL_INLINE int emit_make_dlist (hcl_t* hcl) +{ + hcl_cframe_t* cf; + int n; + + cf = GET_TOP_CFRAME(hcl); + HCL_ASSERT (hcl, cf->opcode == COP_EMIT_MAKE_DLIST); + HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(cf->operand)); + + n = emit_single_param_instruction (hcl, HCL_CODE_MAKE_DLIST, HCL_OOP_TO_SMOOI(cf->operand)); + + POP_CFRAME (hcl); + return n; +} + static HCL_INLINE int emit_pop_into_array (hcl_t* hcl) { hcl_cframe_t* cf; @@ -2508,7 +2631,22 @@ static HCL_INLINE int emit_pop_into_dic (hcl_t* hcl) cf = GET_TOP_CFRAME(hcl); HCL_ASSERT (hcl, cf->opcode == COP_EMIT_POP_INTO_DIC); - n = emit_byte_instruction (hcl, HCL_CODE_POP_INTO_DIC); + n = emit_byte_instruction (hcl, HCL_CODE_POP_INTO_DIC, HCL_NULL); + + POP_CFRAME (hcl); + return n; +} + +static HCL_INLINE int emit_pop_into_dlist (hcl_t* hcl) +{ + hcl_cframe_t* cf; + int n; + + cf = GET_TOP_CFRAME(hcl); + HCL_ASSERT (hcl, cf->opcode == COP_EMIT_POP_INTO_DLIST); + HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(cf->operand)); + + n = emit_single_param_instruction (hcl, HCL_CODE_POP_INTO_DLIST, HCL_OOP_TO_SMOOI(cf->operand)); POP_CFRAME (hcl); return n; @@ -2539,11 +2677,11 @@ static HCL_INLINE int emit_lambda (hcl_t* hcl) { /* no body in lambda - (lambda (a b c)) */ /* TODO: is this correct??? */ - if (emit_byte_instruction(hcl, HCL_CODE_PUSH_NIL) <= -1) return -1; + if (emit_byte_instruction(hcl, HCL_CODE_PUSH_NIL, HCL_NULL) <= -1) return -1; block_code_size++; } - if (emit_byte_instruction(hcl, HCL_CODE_RETURN_FROM_BLOCK) <= -1) return -1; + if (emit_byte_instruction(hcl, HCL_CODE_RETURN_FROM_BLOCK, HCL_NULL) <= -1) return -1; block_code_size++; if (block_code_size > MAX_CODE_JUMP * 2) @@ -2570,7 +2708,7 @@ static HCL_INLINE int emit_pop_stacktop (hcl_t* hcl) HCL_ASSERT (hcl, cf->opcode == COP_EMIT_POP_STACKTOP); HCL_ASSERT (hcl, HCL_IS_NIL(hcl, cf->operand)); - n = emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP); + n = emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP, HCL_NULL); POP_CFRAME (hcl); return n; @@ -2585,7 +2723,7 @@ static HCL_INLINE int emit_return (hcl_t* hcl) HCL_ASSERT (hcl, cf->opcode == COP_EMIT_RETURN); HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(cf->operand)); - n = emit_byte_instruction(hcl, (HCL_OOP_TO_SMOOI(cf->operand) == 0? HCL_CODE_RETURN_FROM_BLOCK: HCL_CODE_RETURN_STACKTOP)); + n = emit_byte_instruction(hcl, (HCL_OOP_TO_SMOOI(cf->operand) == 0? HCL_CODE_RETURN_FROM_BLOCK: HCL_CODE_RETURN_STACKTOP), HCL_NULL); POP_CFRAME (hcl); return n; @@ -2632,7 +2770,6 @@ static HCL_INLINE int emit_set (hcl_t* hcl) /* ========================================================================= */ - int hcl_compile (hcl_t* hcl, hcl_oop_t obj) { hcl_oow_t saved_bc_len, saved_lit_len; @@ -2720,6 +2857,10 @@ int hcl_compile (hcl_t* hcl, hcl_oop_t obj) if (compile_dic_list(hcl) <= -1) goto oops; break; + case COP_COMPILE_QLIST: + if (compile_qlist(hcl) <= -1) goto oops; + break; + case COP_EMIT_CALL: if (emit_call(hcl) <= -1) goto oops; break; @@ -2736,6 +2877,10 @@ int hcl_compile (hcl_t* hcl, hcl_oop_t obj) if (emit_make_dic(hcl) <= -1) goto oops; break; + case COP_EMIT_MAKE_DLIST: + if (emit_make_dlist(hcl) <= -1) goto oops; + break; + case COP_EMIT_POP_INTO_ARRAY: if (emit_pop_into_array(hcl) <= -1) goto oops; break; @@ -2744,6 +2889,10 @@ int hcl_compile (hcl_t* hcl, hcl_oop_t obj) if (emit_pop_into_bytearray(hcl) <= -1) goto oops; break; + case COP_EMIT_POP_INTO_DLIST: + if (emit_pop_into_dlist(hcl) <= -1) goto oops; + break; + case COP_EMIT_POP_INTO_DIC: if (emit_pop_into_dic(hcl) <= -1) goto oops; break; @@ -2819,7 +2968,7 @@ int hcl_compile (hcl_t* hcl, hcl_oop_t obj) /* emit the pop instruction to clear the final result */ /* TODO: for interactive use, this value must be accessible by the executor... how to do it? */ - if (emit_byte_instruction (hcl, HCL_CODE_POP_STACKTOP) <= -1) goto oops; + if (emit_byte_instruction(hcl, HCL_CODE_POP_STACKTOP, HCL_NULL) <= -1) goto oops; HCL_ASSERT (hcl, GET_TOP_CFRAME_INDEX(hcl) < 0); HCL_ASSERT (hcl, hcl->c->tv.size == 0); diff --git a/lib/debug.c b/lib/debug.c index 3007be6..732d903 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -69,3 +69,200 @@ void hcl_dumpdic (hcl_t* hcl, hcl_oop_dic_t dic, const hcl_bch_t* title) + +/* TODO: hcl_loaddbgifromimage() -> load debug information from compiled image? +hcl_storedbgitoimage()? -> store debug information to compiled image? +hcl_compactdbgi()? -> compact debug information by scaning dbgi data. find class and method. if not found, drop the portion. +*/ + +int hcl_initdbgi (hcl_t* hcl, hcl_oow_t capa) +{ + hcl_dbgi_t* tmp; + + if (capa < HCL_SIZEOF(*tmp)) capa = HCL_SIZEOF(*tmp); + + tmp = (hcl_dbgi_t*)hcl_callocmem(hcl, capa); + if (!tmp) return -1; + + tmp->_capa = capa; + tmp->_len = HCL_SIZEOF(*tmp); + /* tmp->_last_file = 0; + tmp->_last_class = 0; + tmp->_last_text = 0; + tmp->_last_method = 0; */ + + hcl->dbgi = tmp; + return 0; +} + +void hcl_finidbgi (hcl_t* hcl) +{ + if (hcl->dbgi) + { + hcl_freemem (hcl, hcl->dbgi); + hcl->dbgi = HCL_NULL; + } +} + +static HCL_INLINE hcl_uint8_t* secure_dbgi_space (hcl_t* hcl, hcl_oow_t req_bytes) +{ + if (hcl->dbgi->_capa - hcl->dbgi->_len < req_bytes) + { + hcl_dbgi_t* tmp; + hcl_oow_t newcapa; + + newcapa = hcl->dbgi->_len + req_bytes; + newcapa = HCL_ALIGN_POW2(newcapa, 65536); /* TODO: make the align value configurable */ + tmp = hcl_reallocmem(hcl, hcl->dbgi, newcapa); + if (!tmp) return HCL_NULL; + + hcl->dbgi = tmp; + hcl->dbgi->_capa = newcapa; + } + + return &((hcl_uint8_t*)hcl->dbgi)[hcl->dbgi->_len]; +} + +int hcl_addfiletodbgi (hcl_t* hcl, const hcl_ooch_t* file_name, hcl_oow_t* start_offset) +{ + hcl_oow_t name_len, name_bytes, name_bytes_aligned, req_bytes; + hcl_dbgi_file_t* di; + + if (!hcl->dbgi) + { + if (start_offset) *start_offset = 0; + return 0; /* debug information is disabled*/ + } + + if (hcl->dbgi->_last_file > 0) + { + /* TODO: avoid linear search. need indexing for speed up */ + hcl_oow_t offset = hcl->dbgi->_last_file; + do + { + di = (hcl_dbgi_file_t*)&((hcl_uint8_t*)hcl->dbgi)[offset]; + if (hcl_comp_oocstr((hcl_ooch_t*)(di + 1), file_name) == 0) + { + if (start_offset) *start_offset = offset; + return 0; + } + offset = di->_next; + } + while (offset > 0); + } + + name_len = hcl_count_oocstr(file_name); + name_bytes = (name_len + 1) * HCL_SIZEOF(*file_name); + name_bytes_aligned = HCL_ALIGN_POW2(name_bytes, HCL_SIZEOF_OOW_T); + req_bytes = HCL_SIZEOF(hcl_dbgi_file_t) + name_bytes_aligned; + + di = (hcl_dbgi_file_t*)secure_dbgi_space(hcl, req_bytes); + if (!di) return -1; + + di->_type = HCL_DBGI_MAKE_TYPE(HCL_DBGI_TYPE_CODE_FILE, 0); + di->_len = req_bytes; + di->_next = hcl->dbgi->_last_file; + hcl_copy_oocstr ((hcl_ooch_t*)(di + 1), name_len + 1, file_name); + + hcl->dbgi->_last_file = hcl->dbgi->_len; + hcl->dbgi->_len += req_bytes; + + if (start_offset) *start_offset = hcl->dbgi->_last_file; + return 0; +} + +int hcl_addclasstodbgi (hcl_t* hcl, const hcl_ooch_t* class_name, hcl_oow_t file_offset, hcl_oow_t file_line, hcl_oow_t* start_offset) +{ + hcl_oow_t name_len, name_bytes, name_bytes_aligned, req_bytes; + hcl_dbgi_class_t* di; + + if (!hcl->dbgi) return 0; /* debug information is disabled*/ + + if (hcl->dbgi->_last_class > 0) + { + /* TODO: avoid linear search. need indexing for speed up */ + hcl_oow_t offset = hcl->dbgi->_last_class; + do + { + di = (hcl_dbgi_class_t*)&((hcl_uint8_t*)hcl->dbgi)[offset]; + if (hcl_comp_oocstr((hcl_ooch_t*)(di + 1), class_name) == 0 && di->_file == file_offset && di->_line == file_line) + { + if (start_offset) *start_offset = offset; + return 0; + } + offset = di->_next; + } + while (offset > 0); + } + + name_len = hcl_count_oocstr(class_name); + name_bytes = (name_len + 1) * HCL_SIZEOF(*class_name); + name_bytes_aligned = HCL_ALIGN_POW2(name_bytes, HCL_SIZEOF_OOW_T); + req_bytes = HCL_SIZEOF(hcl_dbgi_class_t) + name_bytes_aligned; + + di = (hcl_dbgi_class_t*)secure_dbgi_space(hcl, req_bytes); + if (!di) return -1; + + di->_type = HCL_DBGI_MAKE_TYPE(HCL_DBGI_TYPE_CODE_CLASS, 0); + di->_len = req_bytes; + di->_next = hcl->dbgi->_last_class; + di->_file = file_offset; + di->_line = file_line; + hcl_copy_oocstr ((hcl_ooch_t*)(di + 1), name_len + 1, class_name); + + hcl->dbgi->_last_class = hcl->dbgi->_len; + hcl->dbgi->_len += req_bytes; + + if (start_offset) *start_offset = hcl->dbgi->_last_class; + return 0; +} + +int hcl_addmethodtodbgi (hcl_t* hcl, hcl_oow_t file_offset, hcl_oow_t class_offset, const hcl_ooch_t* method_name, hcl_oow_t start_line, const hcl_oow_t* code_loc_ptr, hcl_oow_t code_loc_len, const hcl_ooch_t* text_ptr, hcl_oow_t text_len, hcl_oow_t* start_offset) +{ + hcl_oow_t name_len, name_bytes, name_bytes_aligned, code_loc_bytes, code_loc_bytes_aligned, text_bytes, text_bytes_aligned, req_bytes; + hcl_dbgi_method_t* di; + hcl_uint8_t* curptr; + + if (!hcl->dbgi) return 0; /* debug information is disabled*/ + + name_len = hcl_count_oocstr(method_name); + name_bytes = (name_len + 1) * HCL_SIZEOF(*method_name); + name_bytes_aligned = HCL_ALIGN_POW2(name_bytes, HCL_SIZEOF_OOW_T); + code_loc_bytes = code_loc_len * HCL_SIZEOF(*code_loc_ptr); + code_loc_bytes_aligned = HCL_ALIGN_POW2(code_loc_bytes, HCL_SIZEOF_OOW_T); + text_bytes = text_len * HCL_SIZEOF(*text_ptr); + text_bytes_aligned = HCL_ALIGN_POW2(text_bytes, HCL_SIZEOF_OOW_T); + req_bytes = HCL_SIZEOF(hcl_dbgi_method_t) + name_bytes_aligned + code_loc_bytes_aligned + text_bytes_aligned; + + di = (hcl_dbgi_method_t*)secure_dbgi_space(hcl, req_bytes); + if (HCL_UNLIKELY(!di)) return -1; + + di->_type = HCL_DBGI_MAKE_TYPE(HCL_DBGI_TYPE_CODE_METHOD, 0); + di->_len = req_bytes; + di->_next = hcl->dbgi->_last_method; + di->_file = file_offset; + di->_class = class_offset; + di->start_line = start_line; + di->code_loc_start = name_bytes_aligned; /* distance from the beginning of the variable payload */ + di->code_loc_len = code_loc_len; + di->text_start = name_bytes_aligned + code_loc_bytes_aligned; /* distance from the beginning of the variable payload */ + di->text_len = text_len; + + curptr = (hcl_uint8_t*)(di + 1); + hcl_copy_oocstr ((hcl_ooch_t*)curptr, name_len + 1, method_name); + + curptr += name_bytes_aligned; + HCL_MEMCPY (curptr, code_loc_ptr, code_loc_bytes); + + if (text_len > 0) + { + curptr += code_loc_bytes_aligned; + hcl_copy_oochars ((hcl_ooch_t*)curptr, text_ptr, text_len); + } + + hcl->dbgi->_last_method = hcl->dbgi->_len; + hcl->dbgi->_len += req_bytes; + + if (start_offset) *start_offset = hcl->dbgi->_last_method; + return 0; +} diff --git a/lib/decode.c b/lib/decode.c index 0657336..5f9fcc1 100644 --- a/lib/decode.c +++ b/lib/decode.c @@ -530,6 +530,14 @@ int hcl_decode (hcl_t* hcl, hcl_oow_t start, hcl_oow_t end) LOG_INST_0 (hcl, "pop_into_dic"); break; + case HCL_CODE_MAKE_DLIST: + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "make_dlist %zu", b1); + break; + + case HCL_CODE_POP_INTO_DLIST: + LOG_INST_0 (hcl, "pop_into_dlist"); + /* -------------------------------------------------------- */ case HCL_CODE_DUP_STACKTOP: diff --git a/lib/exec.c b/lib/exec.c index 5485f38..dc96fa9 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -3192,8 +3192,8 @@ static int execute (hcl_t* hcl) LOG_INST_1 (hcl, "make_array %zu", b1); /* create an empty array */ - t = hcl_makearray (hcl, b1, 0); - if (!t) goto oops; + t = hcl_makearray(hcl, b1, 0); + if (HCL_UNLIKELY(!t)) goto oops; HCL_STACK_PUSH (hcl, t); /* push the array created */ break; @@ -3219,8 +3219,8 @@ static int execute (hcl_t* hcl) LOG_INST_1 (hcl, "make_bytearray %zu", b1); /* create an empty array */ - t = hcl_makebytearray (hcl, HCL_NULL, b1); - if (!t) goto oops; + t = hcl_makebytearray(hcl, HCL_NULL, b1); + if (HCL_UNLIKELY(!t)) goto oops; HCL_STACK_PUSH (hcl, t); /* push the byte array created */ break; @@ -3253,8 +3253,8 @@ static int execute (hcl_t* hcl) FETCH_PARAM_CODE_TO (hcl, b1); LOG_INST_1 (hcl, "make_dic %zu", b1); - t = (hcl_oop_t)hcl_makedic (hcl, b1 + 10); - if (!t) goto oops; + t = (hcl_oop_t)hcl_makedic(hcl, b1 + 10); + if (HCL_UNLIKELY(!t)) goto oops; HCL_STACK_PUSH (hcl, t); break; } @@ -3269,7 +3269,33 @@ static int execute (hcl_t* hcl) t2 = HCL_STACK_GETTOP(hcl); /* key */ HCL_STACK_POP (hcl); t3 = HCL_STACK_GETTOP(hcl); /* dictionary */ - if (!hcl_putatdic (hcl, (hcl_oop_dic_t)t3, t2, t1)) goto oops; + if (!hcl_putatdic(hcl, (hcl_oop_dic_t)t3, t2, t1)) goto oops; + break; + } + + case HCL_CODE_MAKE_DLIST: + { + hcl_oop_t t; + + FETCH_PARAM_CODE_TO (hcl, b1); + LOG_INST_1 (hcl, "make_dlist %zu", b1); + + /* create an empty array */ + t = hcl_makedlist(hcl, b1, 0); + if (HCL_UNLIKELY(!t)) goto oops; + + HCL_STACK_PUSH (hcl, t); /* push the list created */ + break; + } + + case HCL_CODE_POP_INTO_DLIST: + { + hcl_oop_t t1, t2; + LOG_INST_0 (hcl, "pop_into_dlist"); + t1 = HCL_STACK_GETTOP(hcl); /* value to store */ + HCL_STACK_POP (hcl); + t2 = HCL_STACK_GETTOP(hcl); /* dlist */ + /* TODO: append t2 to the dlist */ break; } diff --git a/lib/gc.c b/lib/gc.c index 2594c2c..aa31569 100644 --- a/lib/gc.c +++ b/lib/gc.c @@ -176,7 +176,7 @@ static HCL_INLINE void gc_ms_mark (hcl_t* hcl, hcl_oop_t oop) HCL_OBJ_SET_FLAGS_MOVED(oop, 1); /* mark */ - gc_ms_mark (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop)); /* TODO: remove recursion */ + /*gc_ms_mark (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop));*/ /* TODO: remove recursion */ if (HCL_OBJ_GET_FLAGS_TYPE(oop) == HCL_OBJ_TYPE_OOP) { @@ -226,7 +226,7 @@ static HCL_INLINE void gc_ms_scan_stack (hcl_t* hcl) { oop = hcl->gci.stack.ptr[--hcl->gci.stack.len]; - gc_ms_mark_object (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop)); + /*gc_ms_mark_object (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop));*/ if (HCL_OBJ_GET_FLAGS_TYPE(oop) == HCL_OBJ_TYPE_OOP) { @@ -811,6 +811,21 @@ int hcl_ignite (hcl_t* hcl) hcl->code.bc.capa = HCL_BC_BUFFER_INIT; } + if (!hcl->code.locptr) + { + hcl->code.locptr = (hcl_oow_t*)hcl_allocmem(hcl, HCL_SIZEOF(*hcl->code.locptr) * HCL_BC_BUFFER_INIT); + if (HCL_UNLIKELY(!hcl->code.locptr)) + { + /* bc.ptr and locptr go together. so free bc.ptr if locptr allocation fails */ + hcl_freemem (hcl, hcl->code.bc.ptr); + hcl->code.bc.ptr = HCL_NULL; + hcl->code.bc.capa = 0; + return -1; + } + + HCL_MEMSET (hcl->code.locptr, 0, HCL_SIZEOF(*hcl->code.locptr) * HCL_BC_BUFFER_INIT); + } + /* TODO: move code.lit.arr creation to hcl_init() after swithching to hcl_allocmem? */ if (!hcl->code.lit.arr) { diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index e7b58bc..371ee55 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -50,7 +50,7 @@ #define HCL_DEBUG_LEXER 1 #define HCL_DEBUG_VM_PROCESSOR 1 #define HCL_DEBUG_VM_EXEC 1 -#define HCL_PROFILE_VM 1 +/*#define HCL_PROFILE_VM 1*/ #endif /* allow the caller to drive process switching by calling @@ -570,7 +570,7 @@ enum hcl_bcode_t HCL_CODE_PUSH_FALSE = 0x84, /* 132 */ HCL_CODE_PUSH_CONTEXT = 0x85, /* 133 */ HCL_CODE_PUSH_PROCESS = 0x86, /* 134 */ - /* UNUSED135 */ + /* UNUSED 135 */ HCL_CODE_POP_INTO_INSTVAR_X = 0x88, /* 136 ## */ @@ -616,16 +616,15 @@ enum hcl_bcode_t HCL_CODE_STORE_INTO_OBJVAR_X = 0xE8, /* 232 ## */ HCL_CODE_POP_INTO_OBJVAR_X = 0xEC, /* 236 ## */ - /* UNUSED 237 */ - HCL_CODE_MAKE_BYTEARRAY = 0xEE, /* 238 */ - HCL_CODE_POP_INTO_BYTEARRAY = 0xEF, /* 239 */ + HCL_CODE_MAKE_BYTEARRAY = 0xED, /* 237 */ + HCL_CODE_POP_INTO_BYTEARRAY = 0xEE, /* 238 */ + HCL_CODE_MAKE_DIC = 0xEF, /* 239 */ HCL_CODE_SEND_MESSAGE_X = 0xF0, /* 240 ## */ - /* UNUSED 241 */ - - HCL_CODE_MAKE_DIC = 0xF2, /* 242 */ - HCL_CODE_POP_INTO_DIC = 0xF3, /* 243 */ + HCL_CODE_POP_INTO_DIC = 0xF1, /* 241 */ + HCL_CODE_MAKE_DLIST = 0xF2, /* 242 */ + HCL_CODE_POP_INTO_DLIST = 0xF3, /* 243 */ HCL_CODE_SEND_MESSAGE_TO_SUPER_X = 0xF4, /* 244 ## */ /* -------------------------------------- */ @@ -639,7 +638,7 @@ enum hcl_bcode_t HCL_CODE_RETURN_RECEIVER = 0xFA, /* ^self */ HCL_CODE_RETURN_FROM_BLOCK = 0xFB, /* return the stack top from a block */ - HCL_CODE_MAKE_FUNCTION = 0xFC, /* 252 */ + HCL_CODE_MAKE_FUNCTION = 0xFC, /* 252 */ HCL_CODE_MAKE_BLOCK = 0xFD, /* 253 */ /* UNUSED 254 */ HCL_CODE_NOOP = 0xFF /* 255 */ diff --git a/lib/hcl.c b/lib/hcl.c index 7716194..e7d13b1 100644 --- a/lib/hcl.c +++ b/lib/hcl.c @@ -258,6 +258,12 @@ void hcl_fini (hcl_t* hcl) hcl->proc_map_free_last = -1; } + if (hcl->code.locptr) + { + hcl_freemem (hcl, hcl->code.locptr); + hcl->code.locptr = HCL_NULL; + } + if (hcl->code.bc.ptr) { hcl_freemem (hcl, hcl->code.bc.ptr); @@ -304,6 +310,7 @@ void hcl_fini (hcl_t* hcl) } hcl_killheap (hcl, hcl->heap); + hcl_finidbgi (hcl); if (hcl->log.ptr) { diff --git a/lib/hcl.h b/lib/hcl.h index 638ba56..043d590 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -384,7 +384,7 @@ typedef enum hcl_obj_type_t hcl_obj_type_t; #define HCL_OBJ_SET_FLAGS_BRAND(oop,v) HCL_SETBITS(hcl_oow_t, (oop)->_flags, HCL_OBJ_FLAGS_BRAND_SHIFT, HCL_OBJ_FLAGS_BRAND_BITS, v) #define HCL_OBJ_GET_SIZE(oop) ((oop)->_size) -#define HCL_OBJ_GET_CLASS(oop) ((oop)->_class) +/*#define HCL_OBJ_GET_CLASS(oop) ((oop)->_class)*/ #define HCL_OBJ_SET_SIZE(oop,v) ((oop)->_size = (v)) #define HCL_OBJ_SET_CLASS(oop,c) ((oop)->_class = (c)) @@ -415,8 +415,7 @@ typedef enum hcl_obj_type_t hcl_obj_type_t; #define HCL_OBJ_HEADER \ hcl_oow_t _flags; \ - hcl_oow_t _size; \ - hcl_oop_t _class + hcl_oow_t _size struct hcl_obj_t { @@ -819,6 +818,75 @@ struct hcl_heap_t hcl_mmgr_t xmmgr; }; +typedef struct hcl_dbgi_t hcl_dbgi_t; +struct hcl_dbgi_t +{ + hcl_oow_t _capa; + hcl_oow_t _len; + hcl_oow_t _last_file; /* offset to the last file element added */ + hcl_oow_t _last_class; /* offset to the last class element added */ + hcl_oow_t _last_text; /* offset to the last text element added */ + hcl_oow_t _last_method; + /* actual information is recorded here */ +}; + +enum hcl_dbgi_type_t +{ + /* bit 8 to bit 15 */ + HCL_DBGI_TYPE_CODE_FILE = 0, + HCL_DBGI_TYPE_CODE_CLASS = 1, + HCL_DBGI_TYPE_CODE_TEXT = 2, + /* TODO: interface? etc? */ + HCL_DBGI_TYPE_CODE_METHOD = 3, /* method instruction location information */ + + /* low 8 bits */ + HCL_DBGI_TYPE_FLAG_INVALID = (1 << 0) +}; +typedef enum hcl_dbgi_type_t hcl_dbgi_type_t; + +#define HCL_DBGI_MAKE_TYPE(code,flags) (((code) << 8) | (flags)) +#define HCL_DBGI_GET_TYPE_CODE(type) ((type) >> 8) +#define HCL_DBGI_GET_TYPE_FLAGS(type) ((type) & 0xFF) + +#define HCL_DBGI_GET_DATA(hcl, offset) ((hcl_uint8_t*)(hcl)->dbgi + (offset)) + +typedef struct hcl_dbgi_file_t hcl_dbgi_file_t; +struct hcl_dbgi_file_t +{ + hcl_oow_t _type; + hcl_oow_t _len; /* length of this record including the header and the file path payload */ + hcl_oow_t _next; + /* ... file path here ... */ +}; + +typedef struct hcl_dbgi_class_t hcl_dbgi_class_t; +struct hcl_dbgi_class_t +{ + hcl_oow_t _type; + hcl_oow_t _len; /* length of this record including the header and the class name payload */ + hcl_oow_t _next; /* offset to a previous class */ + hcl_oow_t _file; + hcl_oow_t _line; + /* ... class name here ... */ +}; + +typedef struct hcl_dbgi_method_t hcl_dbgi_method_t; +struct hcl_dbgi_method_t +{ + hcl_oow_t _type; + hcl_oow_t _len; /* length of this record including the header and the payload including method name and code line numbers */ + hcl_oow_t _next; + hcl_oow_t _file; + hcl_oow_t _class; + hcl_oow_t start_line; + hcl_oow_t code_loc_start; /* start offset from the payload beginning within this record */ + hcl_oow_t code_loc_len; + hcl_oow_t text_start; + hcl_oow_t text_len; + /* ... method name here ... */ + /* ... code line numbers here ... */ +}; + /* ========================================================================= * VM LOGGING * ========================================================================= */ @@ -1357,6 +1425,7 @@ struct hcl_t /* ========================= */ hcl_heap_t* heap; + hcl_dbgi_t* dbgi; /* ========================= */ hcl_oop_t _nil; /* pointer to the nil object */ @@ -1488,6 +1557,9 @@ struct hcl_t hcl_oop_oop_t arr; /* literal array - not part of object memory */ hcl_oow_t len; } lit; + + /* array that hold the location of the byte code emitted */ + hcl_oow_t* locptr; } code; /* == PRINTER == */ @@ -2004,6 +2076,24 @@ HCL_EXPORT void hcl_setsynerrufmt ( # define hcl_setsynerr(hcl,num,loc,tgt) hcl_setsynerrbfmt(hcl,num,loc,tgt,HCL_NULL) #endif +/* ========================================================================= + * DEBUG SUPPORT + * ========================================================================= */ + +HCL_EXPORT int hcl_initdbgi ( + hcl_t* hcl, + hcl_oow_t init_capa +); + +/** + * The hcl_finidbgi() function deletes the debug information. + * It is called by hcl_close(). Unless you want the debug information to + * be deleted earlier, you need not call this function explicitly. + */ +HCL_EXPORT void hcl_finidbgi ( + hcl_t* hcl +); + /* ========================================================================= * TEMPORARY OOP MANAGEMENT FUNCTIONS * ========================================================================= */ diff --git a/lib/obj.c b/lib/obj.c index 1c9bd93..57e749f 100644 --- a/lib/obj.c +++ b/lib/obj.c @@ -139,7 +139,7 @@ static HCL_INLINE hcl_oop_t alloc_oop_array (hcl_t* hcl, int brand, hcl_oow_t si hdr->_flags = HCL_OBJ_MAKE_FLAGS(HCL_OBJ_TYPE_OOP, HCL_SIZEOF(hcl_oop_t), 0, 0, 0, ngc, 0, 0); HCL_OBJ_SET_SIZE (hdr, size); - HCL_OBJ_SET_CLASS (hdr, hcl->_nil); + /*HCL_OBJ_SET_CLASS (hdr, hcl->_nil);*/ HCL_OBJ_SET_FLAGS_BRAND (hdr, brand); while (size > 0) hdr->slot[--size] = hcl->_nil; @@ -168,7 +168,7 @@ hcl_oop_t hcl_allocoopobjwithtrailer (hcl_t* hcl, int brand, hcl_oow_t size, con hdr->_flags = HCL_OBJ_MAKE_FLAGS(HCL_OBJ_TYPE_OOP, HCL_SIZEOF(hcl_oop_t), 0, 0, 0, 0, 1, 0); HCL_OBJ_SET_SIZE (hdr, size); - HCL_OBJ_SET_CLASS (hdr, hcl->_nil); + /*HCL_OBJ_SET_CLASS (hdr, hcl->_nil);*/ HCL_OBJ_SET_FLAGS_BRAND (hdr, brand); for (i = 0; i < size; i++) hdr->slot[i] = hcl->_nil; @@ -215,7 +215,7 @@ static HCL_INLINE hcl_oop_t alloc_numeric_array (hcl_t* hcl, int brand, const vo hdr->_flags = HCL_OBJ_MAKE_FLAGS(type, unit, extra, 0, 0, ngc, 0, 0); hdr->_size = len; HCL_OBJ_SET_SIZE (hdr, len); - HCL_OBJ_SET_CLASS (hdr, hcl->_nil); + //HCL_OBJ_SET_CLASS (hdr, hcl->_nil); HCL_OBJ_SET_FLAGS_BRAND (hdr, brand); if (ptr) @@ -321,6 +321,13 @@ hcl_oop_t hcl_makebytearray (hcl_t* hcl, const hcl_oob_t* ptr, hcl_oow_t size) return hcl_allocbyteobj(hcl, HCL_BRAND_BYTE_ARRAY, ptr, size); } +hcl_oop_t hcl_makedlist (hcl_t* hcl) +{ + //return hcl_allocoopobj(hcl, HCL_BRAND_DLIST); +hcl_seterrnum (hcl, HCL_ENOIMPL); +return HCL_NULL; +} + hcl_oop_t hcl_makestring (hcl_t* hcl, const hcl_ooch_t* ptr, hcl_oow_t len, int ngc) { /*return hcl_alloccharobj(hcl, HCL_BRAND_STRING, ptr, len);*/ diff --git a/lib/read.c b/lib/read.c index c03f757..bddf15f 100644 --- a/lib/read.c +++ b/lib/read.c @@ -780,7 +780,7 @@ static int get_sharp_token (hcl_t* hcl) * #\UHHHH unicode character * #\uHHHH unicode character * #[ ] byte array - * #{ } qlist + * #( ) qlist */ switch (c) @@ -1382,7 +1382,7 @@ static int end_include (hcl_t* hcl) /* if it is an included file, close it and * retry to read a character from an outer file */ - x = hcl->c->reader (hcl, HCL_IO_CLOSE, hcl->c->curinp); + x = hcl->c->reader(hcl, HCL_IO_CLOSE, hcl->c->curinp); /* if closing has failed, still destroy the * sio structure first as normal and return @@ -1855,12 +1855,16 @@ static int read_object (hcl_t* hcl) LIST_FLAG_SET_CONCODE (flagv, HCL_CONCODE_DIC); goto start_list; -#if 0 case HCL_IOTOK_QLPAREN: /* #() */ +#if 1 + hcl_setsynerr (hcl, HCL_SYNERR_ILTOK, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); + return -1; +#else flagv = 0; LIST_FLAG_SET_CONCODE (flagv, HCL_CONCODE_QLIST); goto start_list; #endif + case HCL_IOTOK_LPAREN: /* () */ flagv = 0; LIST_FLAG_SET_CONCODE (flagv, HCL_CONCODE_XLIST);