Fixed try/catch to run finally again. exit() in catch if you want to stop execution. (0.37.62)
This commit is contained in:
parent
6648fa1e27
commit
869d68b992
4 changed files with 43 additions and 5 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(fun VERSION 0.37.61 LANGUAGES C)
|
project(fun VERSION 0.37.62 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
|
||||||
32
src/vm.c
32
src/vm.c
|
|
@ -235,6 +235,38 @@ static void fun_vm_exit(int code) {
|
||||||
/* Redirect exit inside this TU (affects included opcode handlers) */
|
/* Redirect exit inside this TU (affects included opcode handlers) */
|
||||||
#define exit(code) fun_vm_exit(code)
|
#define exit(code) fun_vm_exit(code)
|
||||||
|
|
||||||
|
/* Forward decl for stack push used by vm_raise_error */
|
||||||
|
static void push_value(VM *vm, Value v);
|
||||||
|
|
||||||
|
/* Raise a runtime error that respects try/catch/finally semantics.
|
||||||
|
* If a handler is installed for the current frame, jump to it and push
|
||||||
|
* an error string for the catch clause. Otherwise, print and stop VM. */
|
||||||
|
void vm_raise_error(VM *vm, const char *msg) {
|
||||||
|
if (!vm || vm->fp < 0) {
|
||||||
|
fprintf(stderr, "Runtime error: %s\n", msg ? msg : "<error>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Frame *f = &vm->frames[vm->fp];
|
||||||
|
if (f->try_sp >= 0) {
|
||||||
|
char buf[256];
|
||||||
|
if (msg) {
|
||||||
|
snprintf(buf, sizeof(buf), "Runtime error: %s", msg);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "Runtime error");
|
||||||
|
}
|
||||||
|
/* push error value and transfer control to handler target */
|
||||||
|
Value err = make_string(buf);
|
||||||
|
push_value(vm, err);
|
||||||
|
int try_idx = f->try_stack[f->try_sp--];
|
||||||
|
int target = f->fn->instructions[try_idx].operand;
|
||||||
|
f->ip = target;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* No handler: print annotated message and terminate VM */
|
||||||
|
fprintf(stderr, "Runtime error: %s\n", msg ? msg : "<error>");
|
||||||
|
vm->fp = -1; /* stop execution */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Opcode case include index (vm_case_*.inc):
|
Opcode case include index (vm_case_*.inc):
|
||||||
- Core/stack/frame:
|
- Core/stack/frame:
|
||||||
|
|
|
||||||
6
src/vm.h
6
src/vm.h
|
|
@ -122,6 +122,12 @@ void vm_dump_globals(VM *vm);
|
||||||
// run entry Bytecode (pushes first frame)
|
// run entry Bytecode (pushes first frame)
|
||||||
void vm_run(VM *vm, Bytecode *entry);
|
void vm_run(VM *vm, Bytecode *entry);
|
||||||
|
|
||||||
|
/* Raise a runtime error that respects try/catch/finally.
|
||||||
|
* If a try handler is active in the current frame, control jumps to it
|
||||||
|
* with an error string pushed on the stack. Otherwise, prints the error
|
||||||
|
* (annotated with location) and terminates execution. */
|
||||||
|
void vm_raise_error(VM *vm, const char *msg);
|
||||||
|
|
||||||
/* --- Debugger API --- */
|
/* --- Debugger API --- */
|
||||||
void vm_debug_reset(VM *vm);
|
void vm_debug_reset(VM *vm);
|
||||||
int vm_debug_add_breakpoint(VM *vm, const char *file, int line); // returns id >=0 or -1
|
int vm_debug_add_breakpoint(VM *vm, const char *file, int line); // returns id >=0 or -1
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ case OP_DIV: {
|
||||||
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
|
double da = (a.type == VAL_FLOAT) ? a.d : (double)a.i;
|
||||||
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
|
double db = (b.type == VAL_FLOAT) ? b.d : (double)b.i;
|
||||||
if (db == 0.0) {
|
if (db == 0.0) {
|
||||||
fprintf(stderr, "Runtime error: division by zero\n");
|
vm_raise_error(vm, "division by zero");
|
||||||
exit(1);
|
break;
|
||||||
}
|
}
|
||||||
Value res = make_float(da / db);
|
Value res = make_float(da / db);
|
||||||
free_value(a);
|
free_value(a);
|
||||||
|
|
@ -49,8 +49,8 @@ case OP_DIV: {
|
||||||
push_value(vm, res);
|
push_value(vm, res);
|
||||||
} else {
|
} else {
|
||||||
if (b.i == 0) {
|
if (b.i == 0) {
|
||||||
fprintf(stderr, "Runtime error: division by zero\n");
|
vm_raise_error(vm, "division by zero");
|
||||||
exit(1);
|
break;
|
||||||
}
|
}
|
||||||
Value res = make_int(a.i / b.i);
|
Value res = make_int(a.i / b.i);
|
||||||
free_value(a);
|
free_value(a);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue