summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--compiler.h1
-rw-r--r--lib.c25
-rw-r--r--vm.c123
-rw-r--r--vm.h6
5 files changed, 71 insertions, 89 deletions
diff --git a/README.md b/README.md
index 7ceb8df..549459e 100644
--- a/README.md
+++ b/README.md
@@ -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`.
diff --git a/compiler.h b/compiler.h
index 7b241ff..3dcb79a 100644
--- a/compiler.h
+++ b/compiler.h
@@ -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;
diff --git a/lib.c b/lib.c
index 93798b8..c1080e3 100644
--- a/lib.c
+++ b/lib.c
@@ -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 }
};
diff --git a/vm.c b/vm.c
index f567993..5f5f785 100644
--- a/vm.c
+++ b/vm.c
@@ -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;
}
diff --git a/vm.h b/vm.h
index 0f7b805..30844f7 100644
--- a/vm.h
+++ b/vm.h
@@ -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,