diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | compiler.h | 1 | ||||
-rw-r--r-- | lib.c | 25 | ||||
-rw-r--r-- | vm.c | 123 | ||||
-rw-r--r-- | vm.h | 6 |
5 files changed, 71 insertions, 89 deletions
@@ -1108,3 +1108,8 @@ Throws an exception if the given prototype value is not an object. Pause execution for the given amount of milliseconds. Returns `false` if an invalid value was passed, otherwise `true`. + +#### 6.56. `assert(cond[, message])` + +Raise an exception with the given `message` parameter if the value in `cond` +is not truish. When `message` is omitted, the default value is `Assertion failed`. @@ -104,7 +104,6 @@ struct uc_compiler { uc_value_t *function; uc_parser *parser; size_t scope_depth, current_srcpos, last_insn; - bool statement_emitted; }; typedef struct uc_compiler uc_compiler; @@ -2338,6 +2338,28 @@ uc_sleep(uc_vm *vm, size_t nargs) return ucv_boolean_new(true); } +static uc_value_t * +uc_assert(uc_vm *vm, size_t nargs) +{ + uc_value_t *cond = uc_get_arg(0); + uc_value_t *msg = uc_get_arg(1); + bool freeable = false; + char *s; + + if (!uc_val_is_truish(cond)) { + s = msg ? uc_cast_string(vm, &msg, &freeable) : "Assertion failed"; + + uc_vm_raise_exception(vm, EXCEPTION_USER, "%s", s); + + if (freeable) + free(s); + + return NULL; + } + + return ucv_get(cond); +} + static const uc_cfunction_list functions[] = { { "chr", uc_chr }, { "delete", uc_delete }, @@ -2387,7 +2409,8 @@ static const uc_cfunction_list functions[] = { { "system", uc_system }, { "trace", uc_trace }, { "proto", uc_proto }, - { "sleep", uc_sleep } + { "sleep", uc_sleep }, + { "assert", uc_assert } }; @@ -32,82 +32,43 @@ static const char *insn_names[__I_MAX] = { __insns }; -static const uc_insn_definition insn_defs[__I_MAX] = { - [I_NOOP] = { 0, 0, 0 }, - - [I_LOAD] = { 0, 1, 4 }, - [I_LOAD8] = { 0, 1, -1 }, - [I_LOAD16] = { 0, 1, -2 }, - [I_LOAD32] = { 0, 1, -4 }, - - [I_LREXP] = { 0, 1, 4 }, - [I_LNULL] = { 0, 1, 0 }, - [I_LTRUE] = { 0, 1, 0 }, - [I_LFALSE] = { 0, 1, 0 }, - [I_LTHIS] = { 0, 1, 0 }, - - [I_LLOC] = { 0, 1, 4 }, - [I_LVAR] = { 0, 1, 4 }, - [I_LUPV] = { 0, 1, 4 }, - [I_LVAL] = { 2, 1, 0 }, - - [I_CLFN] = { 0, 1, 4 }, - [I_ARFN] = { 0, 1, 4 }, - - [I_SLOC] = { 0, 0, 4 }, - [I_SUPV] = { 0, 0, 4 }, - [I_SVAR] = { 0, 0, 4 }, - [I_SVAL] = { 3, 1, 0 }, - - [I_ULOC] = { 1, 0, 4 }, - [I_UUPV] = { 1, 0, 4 }, - [I_UVAR] = { 1, 0, 4 }, - [I_UVAL] = { 3, 1, 1 }, - - [I_NARR] = { 0, 1, 4 }, - [I_PARR] = { -1, 0, 4 }, - [I_MARR] = { 1, 0, 0 }, - - [I_NOBJ] = { 0, 1, 4 }, - [I_SOBJ] = { -1, 0, 4 }, - [I_MOBJ] = { 1, 0, 0 }, - - [I_ADD] = { 2, 1, 0 }, - [I_SUB] = { 2, 1, 0 }, - [I_MUL] = { 2, 1, 0 }, - [I_DIV] = { 2, 1, 0 }, - [I_MOD] = { 2, 1, 0 }, - [I_LSHIFT] = { 2, 1, 0 }, - [I_RSHIFT] = { 2, 1, 0 }, - [I_BAND] = { 2, 1, 0 }, - [I_BXOR] = { 2, 1, 0 }, - [I_BOR] = { 2, 1, 0 }, - [I_EQ] = { 2, 1, 0 }, - [I_NE] = { 2, 1, 0 }, - [I_EQS] = { 2, 1, 0 }, - [I_NES] = { 2, 1, 0 }, - [I_LT] = { 2, 1, 0 }, - [I_GT] = { 2, 1, 0 }, - [I_IN] = { 2, 1, 0 }, - - [I_JMP] = { 0, 0, -4 }, - [I_JMPZ] = { 1, 0, -4 }, - - [I_COPY] = { 0, 1, 1 }, - [I_POP] = { 1, 0, 0 }, - [I_CUPV] = { 1, 0, 0 }, - - [I_PLUS] = { 1, 1, 0 }, - [I_MINUS] = { 1, 1, 0 }, - - [I_RETURN] = { 1, 0, 0 }, - [I_CALL] = { -2, 1, 4 }, - [I_MCALL] = { -3, 1, 4 }, - - [I_NEXTK] = { 2, 2, 0 }, - [I_NEXTKV] = { 2, 3, 0 }, - - [I_PRINT] = { 1, 0, 0 } +static const int8_t insn_operand_bytes[__I_MAX] = { + [I_LOAD] = 4, + [I_LOAD8] = -1, + [I_LOAD16] = -2, + [I_LOAD32] = -4, + + [I_LREXP] = 4, + + [I_LLOC] = 4, + [I_LVAR] = 4, + [I_LUPV] = 4, + + [I_CLFN] = 4, + [I_ARFN] = 4, + + [I_SLOC] = 4, + [I_SUPV] = 4, + [I_SVAR] = 4, + + [I_ULOC] = 4, + [I_UUPV] = 4, + [I_UVAR] = 4, + [I_UVAL] = 1, + + [I_NARR] = 4, + [I_PARR] = 4, + + [I_NOBJ] = 4, + [I_SOBJ] = 4, + + [I_JMP] = -4, + [I_JMPZ] = -4, + + [I_COPY] = 1, + + [I_CALL] = 4, + [I_MCALL] = 4 }; static const char *exception_type_strings[] = { @@ -217,9 +178,9 @@ uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk) insn = frame->ip[0]; frame->ip++; - assert(frame->ip + abs(insn_defs[insn].operand_bytes) <= end); + assert(frame->ip + abs(insn_operand_bytes[insn]) <= end); - switch (insn_defs[insn].operand_bytes) { + switch (insn_operand_bytes[insn]) { case 0: break; @@ -262,7 +223,7 @@ uc_vm_decode_insn(uc_vm *vm, uc_callframe *frame, uc_chunk *chunk) break; default: - fprintf(stderr, "Unhandled operand format: %d\n", insn_defs[insn].operand_bytes); + fprintf(stderr, "Unhandled operand format: %" PRId8 "\n", insn_operand_bytes[insn]); abort(); } @@ -584,7 +545,7 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) fprintf(stderr, "%08zx %s", pos - chunk->entries, insn_names[insn]); - switch (insn_defs[insn].operand_bytes) { + switch (insn_operand_bytes[insn]) { case 0: break; @@ -617,7 +578,7 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) break; default: - fprintf(stderr, " (unknown operand format: %d)", insn_defs[insn].operand_bytes); + fprintf(stderr, " (unknown operand format: %" PRId8 ")", insn_operand_bytes[insn]); break; } @@ -98,12 +98,6 @@ enum insn_type { __I_MAX }; -typedef struct { - int8_t stack_pop; - int8_t stack_push; - int8_t operand_bytes; -} uc_insn_definition; - typedef enum { STATUS_OK, ERROR_COMPILE, |