mirror of
https://github.com/janet-lang/janet
synced 2025-01-12 16:40:27 +00:00
Add error handling and try catch expression.
This commit is contained in:
parent
6521ee69bd
commit
5ec6e46f1a
130
compile.c
130
compile.c
@ -86,7 +86,6 @@ static FormOptions form_options_default() {
|
|||||||
/* Create some helpers that allows us to push more than just raw bytes
|
/* Create some helpers that allows us to push more than just raw bytes
|
||||||
* to the byte buffer. This helps us create the byte code for the compiled
|
* to the byte buffer. This helps us create the byte code for the compiled
|
||||||
* functions. */
|
* functions. */
|
||||||
BUFFER_DEFINE(u32, uint32_t)
|
|
||||||
BUFFER_DEFINE(i32, int32_t)
|
BUFFER_DEFINE(i32, int32_t)
|
||||||
BUFFER_DEFINE(number, GstNumber)
|
BUFFER_DEFINE(number, GstNumber)
|
||||||
BUFFER_DEFINE(u16, uint16_t)
|
BUFFER_DEFINE(u16, uint16_t)
|
||||||
@ -254,7 +253,7 @@ static Slot compiler_realize_slot(GstCompiler *c, Slot slot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Helper to get a nil slot */
|
/* Helper to get a nil slot */
|
||||||
static Slot nil_slot() { Slot ret; ret.isNil = 1; return ret; }
|
static Slot nil_slot() { Slot ret; ret.isNil = 1; ret.hasReturned = 0; return ret; }
|
||||||
|
|
||||||
/* Writes all of the slots in the tracker to the compiler */
|
/* Writes all of the slots in the tracker to the compiler */
|
||||||
static void compiler_tracker_write(GstCompiler *c, SlotTracker *tracker, int reverse) {
|
static void compiler_tracker_write(GstCompiler *c, SlotTracker *tracker, int reverse) {
|
||||||
@ -320,9 +319,8 @@ static uint16_t compiler_add_literal(GstCompiler *c, GstScope *scope, GstValue x
|
|||||||
static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym) {
|
static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValue sym) {
|
||||||
GstValue x;
|
GstValue x;
|
||||||
uint16_t target;
|
uint16_t target;
|
||||||
if (sym.type != GST_STRING) {
|
if (sym.type != GST_STRING)
|
||||||
c_error(c, "Expected symbol");
|
c_error(c, "Expected symbol");
|
||||||
}
|
|
||||||
target = compiler_get_local(c, scope);
|
target = compiler_get_local(c, scope);
|
||||||
x.type = GST_NUMBER;
|
x.type = GST_NUMBER;
|
||||||
x.data.number = target;
|
x.data.number = target;
|
||||||
@ -676,7 +674,7 @@ static Slot compile_block(GstCompiler *c, FormOptions opts, GstArray *form, uint
|
|||||||
|
|
||||||
/* Extract the last n bytes from the buffer and use them to construct
|
/* Extract the last n bytes from the buffer and use them to construct
|
||||||
* a function definition. */
|
* a function definition. */
|
||||||
static GstFuncDef * compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uint32_t arity) {
|
static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uint32_t arity) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer *buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
GstFuncDef *def = gst_alloc(c->vm, sizeof(GstFuncDef));
|
GstFuncDef *def = gst_alloc(c->vm, sizeof(GstFuncDef));
|
||||||
@ -710,13 +708,13 @@ static GstFuncDef * compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, ui
|
|||||||
|
|
||||||
/* Compile a function from a function literal */
|
/* Compile a function from a function literal */
|
||||||
static Slot compile_function(GstCompiler *c, FormOptions opts, GstArray *form) {
|
static Slot compile_function(GstCompiler *c, FormOptions opts, GstArray *form) {
|
||||||
GstScope * scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer * buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
uint32_t current = 1;
|
uint32_t current = 1;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t sizeBefore; /* Size of buffer before compiling function */
|
uint32_t sizeBefore; /* Size of buffer before compiling function */
|
||||||
GstScope * subGstScope;
|
GstScope *subGstScope;
|
||||||
GstArray * params;
|
GstArray *params;
|
||||||
FormOptions subOpts = form_options_default();
|
FormOptions subOpts = form_options_default();
|
||||||
Slot ret;
|
Slot ret;
|
||||||
if (opts.resultUnused) return nil_slot();
|
if (opts.resultUnused) return nil_slot();
|
||||||
@ -763,8 +761,8 @@ static Slot compile_function(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
|
|
||||||
/* Branching special */
|
/* Branching special */
|
||||||
static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
||||||
GstScope * scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer * buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
FormOptions condOpts = opts;
|
FormOptions condOpts = opts;
|
||||||
FormOptions branchOpts = opts;
|
FormOptions branchOpts = opts;
|
||||||
Slot left, right, condition;
|
Slot left, right, condition;
|
||||||
@ -788,10 +786,7 @@ static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
/* Mark where the buffer is now so we can write the jump
|
/* Mark where the buffer is now so we can write the jump
|
||||||
* length later */
|
* length later */
|
||||||
countAtJumpIf = buffer->count;
|
countAtJumpIf = buffer->count;
|
||||||
/* Write jump instruction. Will later be replaced with correct index. */
|
buffer->count += sizeof(int32_t) + 2 * sizeof(uint16_t);
|
||||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_JIF);
|
|
||||||
gst_buffer_push_u16(c->vm, buffer, condition.index);
|
|
||||||
gst_buffer_push_u32(c->vm, buffer, 0);
|
|
||||||
/* Configure branch form options */
|
/* Configure branch form options */
|
||||||
branchOpts.canChoose = 0;
|
branchOpts.canChoose = 0;
|
||||||
branchOpts.target = condition.index;
|
branchOpts.target = condition.index;
|
||||||
@ -803,8 +798,7 @@ static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
/* If we need to jump again, do so */
|
/* If we need to jump again, do so */
|
||||||
if (form->count == 4) {
|
if (form->count == 4) {
|
||||||
countAtJump = buffer->count;
|
countAtJump = buffer->count;
|
||||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP);
|
buffer->count += sizeof(int32_t) + sizeof(uint16_t);
|
||||||
gst_buffer_push_u32(c->vm, buffer, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compiler_drop_slot(c, scope, left);
|
compiler_drop_slot(c, scope, left);
|
||||||
@ -813,7 +807,7 @@ static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
buffer->count = countAtJumpIf;
|
buffer->count = countAtJumpIf;
|
||||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_JIF);
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_JIF);
|
||||||
gst_buffer_push_u16(c->vm, buffer, condition.index);
|
gst_buffer_push_u16(c->vm, buffer, condition.index);
|
||||||
gst_buffer_push_u32(c->vm, buffer, (countAfterFirstBranch - countAtJumpIf) / 2);
|
gst_buffer_push_i32(c->vm, buffer, (countAfterFirstBranch - countAtJumpIf) / 2);
|
||||||
buffer->count = countAfterFirstBranch;
|
buffer->count = countAfterFirstBranch;
|
||||||
/* Compile false path */
|
/* Compile false path */
|
||||||
if (form->count == 4) {
|
if (form->count == 4) {
|
||||||
@ -828,7 +822,7 @@ static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
countAfterFirstBranch = buffer->count;
|
countAfterFirstBranch = buffer->count;
|
||||||
buffer->count = countAtJump;
|
buffer->count = countAtJump;
|
||||||
gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP);
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP);
|
||||||
gst_buffer_push_u32(c->vm, buffer, (countAfterFirstBranch - countAtJump) / 2);
|
gst_buffer_push_i32(c->vm, buffer, (countAfterFirstBranch - countAtJump) / 2);
|
||||||
buffer->count = countAfterFirstBranch;
|
buffer->count = countAfterFirstBranch;
|
||||||
}
|
}
|
||||||
if (opts.isTail)
|
if (opts.isTail)
|
||||||
@ -836,6 +830,84 @@ static Slot compile_if(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Special to throw an error */
|
||||||
|
static Slot compile_error(GstCompiler *c, FormOptions opts, GstArray *form) {
|
||||||
|
GstBuffer *buffer = c->buffer;
|
||||||
|
Slot ret;
|
||||||
|
GstValue x;
|
||||||
|
if (form->count != 2)
|
||||||
|
c_error(c, "error takes exactly 1 argument");
|
||||||
|
x = form->data[1];
|
||||||
|
ret = compiler_realize_slot(c, compile_value(c, opts, x));
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_ERR);
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, ret.index);
|
||||||
|
return nil_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try catch special */
|
||||||
|
static Slot compile_try(GstCompiler *c, FormOptions opts, GstArray *form) {
|
||||||
|
GstScope *scope = c->tail;
|
||||||
|
GstBuffer *buffer = c->buffer;
|
||||||
|
Slot body;
|
||||||
|
uint16_t errorIndex;
|
||||||
|
uint32_t countAtTry, countTemp, countAtJump;
|
||||||
|
/* Check argument count */
|
||||||
|
if (form->count < 3 || form->count > 4)
|
||||||
|
c_error(c, "try takes either 2 or 3 arguments");
|
||||||
|
/* Check for symbol to bind error to */
|
||||||
|
if (form->data[1].type != GST_STRING)
|
||||||
|
c_error(c, "expected symbol at start of try");
|
||||||
|
/* Add subscope for error variable */
|
||||||
|
GstScope *subScope = compiler_push_scope(c, 1);
|
||||||
|
errorIndex = compiler_declare_symbol(c, subScope, form->data[1]);
|
||||||
|
/* Leave space for try instruction */
|
||||||
|
countAtTry = buffer->count;
|
||||||
|
buffer->count += sizeof(uint32_t) + 2 * sizeof(uint16_t);
|
||||||
|
/* Compile the body */
|
||||||
|
body = compile_value(c, opts, form->data[2]);
|
||||||
|
if (opts.isTail) {
|
||||||
|
compiler_return(c, body);
|
||||||
|
} else {
|
||||||
|
/* If we need to jump over the catch, do so */
|
||||||
|
if (form->count == 4) {
|
||||||
|
countAtJump = buffer->count;
|
||||||
|
buffer->count += sizeof(int32_t) + sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Reinsert try jump with correct index */
|
||||||
|
countTemp = buffer->count;
|
||||||
|
buffer->count = countAtTry;
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_TRY);
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, errorIndex);
|
||||||
|
gst_buffer_push_i32(c->vm, buffer, (countTemp - countAtTry) / 2);
|
||||||
|
buffer->count = countTemp;
|
||||||
|
/* Compile catch path */
|
||||||
|
if (form->count == 4) {
|
||||||
|
Slot catch;
|
||||||
|
countAtJump = buffer->count;
|
||||||
|
catch = compile_value(c, opts, form->data[3]);
|
||||||
|
if (opts.isTail) compiler_return(c, catch);
|
||||||
|
compiler_drop_slot(c, scope, catch);
|
||||||
|
} else if (opts.isTail) {
|
||||||
|
compiler_return(c, nil_slot());
|
||||||
|
}
|
||||||
|
/* Reset the second jump length */
|
||||||
|
if (!opts.isTail && form->count == 4) {
|
||||||
|
countTemp = buffer->count;
|
||||||
|
buffer->count = countAtJump;
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_JMP);
|
||||||
|
gst_buffer_push_i32(c->vm, buffer, (countTemp - countAtJump) / 2);
|
||||||
|
buffer->count = countTemp;
|
||||||
|
}
|
||||||
|
/* Untry */
|
||||||
|
gst_buffer_push_u16(c->vm, buffer, GST_OP_UTY);
|
||||||
|
/* Pop the error scope */
|
||||||
|
compiler_pop_scope(c);
|
||||||
|
if (opts.isTail)
|
||||||
|
body.hasReturned = 1;
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
/* While special */
|
/* While special */
|
||||||
static Slot compile_while(GstCompiler *c, FormOptions opts, GstArray *form) {
|
static Slot compile_while(GstCompiler *c, FormOptions opts, GstArray *form) {
|
||||||
Slot cond;
|
Slot cond;
|
||||||
@ -891,7 +963,7 @@ static Slot compile_quote(GstCompiler *c, FormOptions opts, GstArray *form) {
|
|||||||
Slot ret;
|
Slot ret;
|
||||||
uint16_t literalIndex;
|
uint16_t literalIndex;
|
||||||
if (form->count != 2)
|
if (form->count != 2)
|
||||||
c_error(c, "Quote takes exactly 1 argument.");
|
c_error(c, "quote takes exactly 1 argument");
|
||||||
GstValue x = form->data[1];
|
GstValue x = form->data[1];
|
||||||
if (x.type == GST_NIL ||
|
if (x.type == GST_NIL ||
|
||||||
x.type == GST_BOOLEAN ||
|
x.type == GST_BOOLEAN ||
|
||||||
@ -969,6 +1041,16 @@ static SpecialFormHelper get_special(GstArray *form) {
|
|||||||
return compile_array;
|
return compile_array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case 'e':
|
||||||
|
{
|
||||||
|
if (gst_string_length(name) == 5 &&
|
||||||
|
name[1] == 'r' &&
|
||||||
|
name[2] == 'r' &&
|
||||||
|
name[3] == 'o' &&
|
||||||
|
name[4] == 'r') {
|
||||||
|
return compile_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
case 'g':
|
case 'g':
|
||||||
{
|
{
|
||||||
if (gst_string_length(name) == 3 &&
|
if (gst_string_length(name) == 3 &&
|
||||||
@ -1038,6 +1120,14 @@ static SpecialFormHelper get_special(GstArray *form) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
{
|
||||||
|
if (gst_string_length(name) == 3 &&
|
||||||
|
name[1] == 'r' &&
|
||||||
|
name[2] == 'y') {
|
||||||
|
return compile_try;
|
||||||
|
}
|
||||||
|
}
|
||||||
case 'w':
|
case 'w':
|
||||||
{
|
{
|
||||||
if (gst_string_length(name) == 5 &&
|
if (gst_string_length(name) == 5 &&
|
||||||
|
10
datatypes.h
10
datatypes.h
@ -160,9 +160,10 @@ struct Gst {
|
|||||||
GstValue *base;
|
GstValue *base;
|
||||||
GstStackFrame *frame;
|
GstStackFrame *frame;
|
||||||
/* Return state */
|
/* Return state */
|
||||||
const char *error;
|
const char *crash;
|
||||||
jmp_buf jump;
|
jmp_buf jump;
|
||||||
GstValue ret; /* Returned value from VMStart */
|
GstValue error;
|
||||||
|
GstValue ret; /* Returned value from VMStart. Also holds errors. */
|
||||||
/* Object definitions */
|
/* Object definitions */
|
||||||
GstValue metas[GST_OBJECT];
|
GstValue metas[GST_OBJECT];
|
||||||
};
|
};
|
||||||
@ -233,7 +234,10 @@ enum GstOpCode {
|
|||||||
GST_OP_DVM, /* 0x001f */
|
GST_OP_DVM, /* 0x001f */
|
||||||
GST_OP_RTN, /* 0x0020 */
|
GST_OP_RTN, /* 0x0020 */
|
||||||
GST_OP_SET, /* 0x0021 */
|
GST_OP_SET, /* 0x0021 */
|
||||||
GST_OP_GET /* 0x0022 */
|
GST_OP_GET, /* 0x0022 */
|
||||||
|
GST_OP_ERR, /* 0x0023 */
|
||||||
|
GST_OP_TRY, /* 0x0024 */
|
||||||
|
GST_OP_UTY /* 0x0025 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
12
disasm.c
12
disasm.c
@ -201,6 +201,18 @@ void gst_dasm(FILE * out, uint16_t *byteCode, uint32_t len) {
|
|||||||
break;
|
break;
|
||||||
case GST_OP_SET:
|
case GST_OP_SET:
|
||||||
current += dasm_fixed_op(out, current, "set", 3);
|
current += dasm_fixed_op(out, current, "set", 3);
|
||||||
|
break;
|
||||||
|
case GST_OP_ERR:
|
||||||
|
current += dasm_fixed_op(out, current, "error", 1);
|
||||||
|
break;
|
||||||
|
case GST_OP_TRY:
|
||||||
|
dasm_print_arg(out, "try");
|
||||||
|
dasm_print_slot(out, current[1]);
|
||||||
|
dasm_print_i32(out, *(int32_t *)(current + 2));
|
||||||
|
current += 4;
|
||||||
|
break;
|
||||||
|
case GST_OP_UTY:
|
||||||
|
current += dasm_fixed_op(out, current, "untry", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
|
12
main.c
12
main.c
@ -87,14 +87,20 @@ void debugRepl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Print asm */
|
/* Print asm */
|
||||||
printf("\n");
|
/* printf("\n");
|
||||||
gst_dasm_function(stdout, func.data.function);
|
gst_dasm_function(stdout, func.data.function);
|
||||||
printf("\n");
|
printf("\n");*/
|
||||||
|
|
||||||
/* Execute function */
|
/* Execute function */
|
||||||
gst_load(&vm, func);
|
gst_load(&vm, func);
|
||||||
if (gst_start(&vm)) {
|
if (gst_start(&vm)) {
|
||||||
printf("VM error: %s\n", vm.error);
|
if (vm.crash) {
|
||||||
|
printf("VM crash: %s\n", vm.crash);
|
||||||
|
} else {
|
||||||
|
printf("VM error: ");
|
||||||
|
string_put(gst_to_string(&vm, vm.error));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
reader = buffer;
|
reader = buffer;
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
continue;
|
continue;
|
||||||
|
28
vm.c
28
vm.c
@ -298,6 +298,7 @@ void gst_collect(Gst *vm) {
|
|||||||
gst_mark(vm, &thread);
|
gst_mark(vm, &thread);
|
||||||
}
|
}
|
||||||
gst_mark(vm, &vm->ret);
|
gst_mark(vm, &vm->ret);
|
||||||
|
gst_mark(vm, &vm->error);
|
||||||
gst_sweep(vm);
|
gst_sweep(vm);
|
||||||
vm->nextCollection = 0;
|
vm->nextCollection = 0;
|
||||||
}
|
}
|
||||||
@ -471,13 +472,15 @@ int gst_start(Gst *vm) {
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (n == 2) {
|
} else if (n == 2) {
|
||||||
/* Error. Handling TODO. */
|
/* Error. Handling TODO. */
|
||||||
do {
|
while (vm->thread->count && !vm->frame->errorJump) {
|
||||||
|
thread_pop(vm);
|
||||||
|
}
|
||||||
if (vm->thread->count == 0)
|
if (vm->thread->count == 0)
|
||||||
return n;
|
return n;
|
||||||
thread_pop(vm);
|
|
||||||
} while (!vm->frame->errorJump);
|
|
||||||
/* Jump to the error location */
|
/* Jump to the error location */
|
||||||
vm->pc = vm->frame->errorJump;
|
vm->pc = vm->frame->errorJump;
|
||||||
|
/* Set error */
|
||||||
|
vm->base[vm->frame->errorSlot] = vm->error;
|
||||||
vm->lock = 0;
|
vm->lock = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Crash. just return */
|
/* Crash. just return */
|
||||||
@ -737,6 +740,22 @@ int gst_start(Gst *vm) {
|
|||||||
vm->pc += 4;
|
vm->pc += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GST_OP_ERR:
|
||||||
|
vm->error = vm->base[vm->pc[1]];
|
||||||
|
longjmp(vm->jump, 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GST_OP_TRY:
|
||||||
|
vm->frame->errorSlot = vm->pc[1];
|
||||||
|
vm->frame->errorJump = vm->pc + *(uint32_t *)(vm->pc + 2);
|
||||||
|
vm->pc += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GST_OP_UTY:
|
||||||
|
vm->frame->errorJump = NULL;
|
||||||
|
vm->pc++;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gst_error(vm, "unknown opcode");
|
gst_error(vm, "unknown opcode");
|
||||||
break;
|
break;
|
||||||
@ -770,10 +789,11 @@ uint16_t gst_count_args(Gst *vm) {
|
|||||||
/* Initialize the VM */
|
/* Initialize the VM */
|
||||||
void gst_init(Gst *vm) {
|
void gst_init(Gst *vm) {
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
|
vm->error.type = GST_NIL;
|
||||||
vm->base = NULL;
|
vm->base = NULL;
|
||||||
vm->frame = NULL;
|
vm->frame = NULL;
|
||||||
vm->pc = NULL;
|
vm->pc = NULL;
|
||||||
vm->error = NULL;
|
vm->crash = NULL;
|
||||||
/* Garbage collection */
|
/* Garbage collection */
|
||||||
vm->blocks = NULL;
|
vm->blocks = NULL;
|
||||||
vm->nextCollection = 0;
|
vm->nextCollection = 0;
|
||||||
|
5
vm.h
5
vm.h
@ -2,15 +2,16 @@
|
|||||||
#define VM_H_C4OZU8CQ
|
#define VM_H_C4OZU8CQ
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "value.h"
|
||||||
|
|
||||||
/* Exit from the VM normally */
|
/* Exit from the VM normally */
|
||||||
#define gst_exit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1))
|
#define gst_exit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1))
|
||||||
|
|
||||||
/* Bail from the VM with an error. */
|
/* Bail from the VM with an error. */
|
||||||
#define gst_error(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2))
|
#define gst_error(vm, e) ((vm)->error = gst_load_cstring((vm), (e)), longjmp((vm)->jump, 2))
|
||||||
|
|
||||||
/* Crash. Not catchable, unlike error. */
|
/* Crash. Not catchable, unlike error. */
|
||||||
#define gst_crash(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 3))
|
#define gst_crash(vm, e) ((vm)->crash = (e), longjmp((vm)->jump, 3))
|
||||||
|
|
||||||
/* Error if the condition is false */
|
/* Error if the condition is false */
|
||||||
#define gst_assert(vm, cond, e) do \
|
#define gst_assert(vm, cond, e) do \
|
||||||
|
Loading…
Reference in New Issue
Block a user