mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
better failure reporting
This commit is contained in:
parent
34675f0cb7
commit
963e286f49
9 changed files with 184 additions and 63 deletions
|
|
@ -9,4 +9,4 @@
|
|||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run gcc -Iinclude/ -g %{main} %{parser} %{utils} %{runtime} -o %{target})))
|
||||
(run gcc -Iinclude/ -g -pg %{main} %{parser} %{utils} %{runtime} -o %{target})))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "utils.h"
|
||||
|
||||
const char *read_cmd(char *ip);
|
||||
|
||||
bytefile *read_file(char *fname);
|
||||
|
||||
void dump_file(FILE *f, bytefile *bf);
|
||||
|
|
|
|||
|
|
@ -49,13 +49,16 @@ struct State {
|
|||
|
||||
bool is_closure_call;
|
||||
|
||||
char *ip; // instruction pointer
|
||||
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
||||
char *ip; // instruction pointer
|
||||
char *instr_ip; // poiter to current instruction
|
||||
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
||||
};
|
||||
|
||||
void init_state(bytefile *bf, struct State *s);
|
||||
void cleanup_state(struct State *state);
|
||||
|
||||
void s_failure(struct State *state, const char *msg);
|
||||
|
||||
// ------ VarCategory ------
|
||||
|
||||
enum VarCategory {
|
||||
|
|
@ -65,6 +68,4 @@ enum VarCategory {
|
|||
VAR_CLOSURE = 3
|
||||
};
|
||||
|
||||
enum VarCategory to_var_category(uint8_t category);
|
||||
|
||||
void print_stack(struct State *s);
|
||||
enum VarCategory to_var_category(struct State *s, uint8_t category);
|
||||
|
|
|
|||
|
|
@ -27,4 +27,6 @@ char *get_public_name(bytefile *f, size_t i);
|
|||
/* Gets an offset for a public symbol */
|
||||
size_t get_public_offset(bytefile *f, size_t i);
|
||||
|
||||
void exec_failure(const char *cmd, int line, aint offset, const char *msg);
|
||||
|
||||
// ---
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ char *ip_read_string(char **ip, bytefile *bf) {
|
|||
}
|
||||
|
||||
void run(bytefile *bf, int argc, char **argv) {
|
||||
void *buffer[10000]; // FIXME: TODO: TMP
|
||||
struct State s;
|
||||
init_state(bf, &s);
|
||||
|
||||
|
|
@ -82,10 +83,10 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
/* BINOP */
|
||||
case 0: // BINOP ops[l-1]
|
||||
if (l > OPS_SIZE) {
|
||||
failure("BINOP: l > OPS_SIZE");
|
||||
s_failure(&s, "undefined binop type index");
|
||||
}
|
||||
if (l < 1) {
|
||||
failure("BINOP: l < 1");
|
||||
s_failure(&s, "negative binop type index");
|
||||
}
|
||||
void *left = s_pop(&s);
|
||||
void *right = s_pop(&s);
|
||||
|
|
@ -115,9 +116,9 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
#endif
|
||||
|
||||
if (args_count < 0) {
|
||||
failure("SEXP: args count should be >= 0");
|
||||
s_failure(&s, "args count should be >= 0");
|
||||
}
|
||||
void **buffer = calloc(args_count + 1, sizeof(void *));
|
||||
// void **buffer = calloc(args_count + 1, sizeof(void *));
|
||||
|
||||
for (size_t i = 1; i <= args_count; ++i) {
|
||||
buffer[args_count - i] = s_pop(&s);
|
||||
|
|
@ -130,7 +131,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
s_push(&s, sexp);
|
||||
pop_extra_root(sexp);
|
||||
|
||||
free(buffer);
|
||||
// free(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +156,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
int jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p < 0) {
|
||||
failure("negative file offset jumps are not allowed");
|
||||
s_failure(&s, "negative file offset jumps are not allowed");
|
||||
}
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
break;
|
||||
|
|
@ -183,21 +184,26 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
|
||||
case 9: // DUP
|
||||
{
|
||||
s_push(&s, *s.sp);
|
||||
s_push(&s, *s_peek(&s));
|
||||
break;
|
||||
}
|
||||
|
||||
case 10: // SWAP
|
||||
{
|
||||
if (s.sp + 1 >= s.stack + STACK_SIZE ||
|
||||
(s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) {
|
||||
failure("can't SWAP: < 2 values on stack");
|
||||
}
|
||||
void *v = *s.sp;
|
||||
push_extra_root(v);
|
||||
*s.sp = *(s.sp + 1);
|
||||
*(s.sp + 1) = v;
|
||||
pop_extra_root(v);
|
||||
void* x = s_pop(&s);
|
||||
void* y = s_pop(&s);
|
||||
s_push(&s, y);
|
||||
s_push(&s, x);
|
||||
|
||||
// if (s.sp + 1 >= s.stack + STACK_SIZE ||
|
||||
// (s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) {
|
||||
// s_failure(&s, "can't SWAP: < 2 values on stack");
|
||||
// }
|
||||
// void *v = *s.sp;
|
||||
// push_extra_root(v);
|
||||
// *s.sp = *(s.sp + 1);
|
||||
// *(s.sp + 1) = v;
|
||||
// pop_extra_root(v);
|
||||
} break;
|
||||
|
||||
case 11: // ELEM
|
||||
|
|
@ -208,26 +214,26 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
} break;
|
||||
|
||||
default:
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: { // LD %d
|
||||
void **var_ptr =
|
||||
var_by_category(&s, to_var_category(l), ip_read_int(&s.ip));
|
||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
||||
s_push(&s, *var_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: { // LDA %d
|
||||
void **var_ptr =
|
||||
var_by_category(&s, to_var_category(l), ip_read_int(&s.ip));
|
||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
||||
s_push(&s, var_ptr);
|
||||
break;
|
||||
}
|
||||
case 4: { // ST %d
|
||||
void **var_ptr =
|
||||
var_by_category(&s, to_var_category(l), ip_read_int(&s.ip));
|
||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
||||
*var_ptr = *s_peek(&s);
|
||||
break;
|
||||
}
|
||||
|
|
@ -238,7 +244,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
int jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p < 0) {
|
||||
failure("negative file offset jumps are not allowed");
|
||||
s_failure(&s, "negative file offset jumps are not allowed");
|
||||
}
|
||||
if (UNBOX(s_pop_i(&s)) == 0) {
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
|
|
@ -250,7 +256,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
int jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p < 0) {
|
||||
failure("negative file offset jumps are not allowed");
|
||||
s_failure(&s, "negative file offset jumps are not allowed");
|
||||
}
|
||||
if (UNBOX(s_pop_i(&s)) != 0) {
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
|
|
@ -262,7 +268,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
int args_sz = ip_read_int(&s.ip);
|
||||
int locals_sz = ip_read_int(&s.ip);
|
||||
if (s.fp != NULL && s.call_ip == NULL) {
|
||||
failure("BEGIN: not after call");
|
||||
s_failure(&s, "begin should only be called after call");
|
||||
}
|
||||
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||
locals_sz);
|
||||
|
|
@ -274,7 +280,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
int args_sz = ip_read_int(&s.ip);
|
||||
int locals_sz = ip_read_int(&s.ip);
|
||||
if (s.fp != NULL && s.call_ip == NULL) {
|
||||
failure("BEGIN: not after call");
|
||||
s_failure(&s, "begin should only be called after call");
|
||||
}
|
||||
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||
locals_sz);
|
||||
|
|
@ -290,7 +296,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
aint arg_id = ip_read_int(&s.ip);
|
||||
|
||||
void **var_ptr =
|
||||
var_by_category(&s, to_var_category(l), ip_read_int(&s.ip));
|
||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
||||
s_push(&s, *var_ptr);
|
||||
}
|
||||
s_push(&s, bf->code_ptr + call_offset);
|
||||
|
|
@ -324,7 +330,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
s.call_ip = s.ip;
|
||||
|
||||
if (call_p < 0) {
|
||||
failure("negative file offset jumps are not allowed");
|
||||
s_failure(&s, "negative file offset jumps are not allowed");
|
||||
}
|
||||
s.ip = bf->code_ptr + call_p;
|
||||
break;
|
||||
|
|
@ -360,7 +366,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
break;
|
||||
|
||||
default:
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -389,7 +395,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
s_push_i(&s, Bclosure_tag_patt(s_pop(&s)));
|
||||
break;
|
||||
default:
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -417,10 +423,10 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
case 4: { // CALL Barray %d
|
||||
size_t elem_count = ip_read_int(&s.ip);
|
||||
if (elem_count < 0) {
|
||||
failure("ARRAY: elements count should be >= 0");
|
||||
s_failure(&s, "elements count should be >= 0");
|
||||
}
|
||||
|
||||
void **buffer = calloc(elem_count, sizeof(void *));
|
||||
// void **buffer = calloc(elem_count, sizeof(void *));
|
||||
for (size_t i = 0; i < elem_count; ++i) {
|
||||
buffer[elem_count - i - 1] = s_pop(&s);
|
||||
}
|
||||
|
|
@ -430,17 +436,17 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
// s_popn(&s, elem_count);
|
||||
s_push(&s, array);
|
||||
|
||||
free(buffer);
|
||||
// free(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
|
||||
if (!call_happened) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ bytefile* read_file (char *fname) {
|
|||
file = (bytefile*) malloc (size + sizeof(void*) * 4);
|
||||
|
||||
if (file == 0) {
|
||||
failure ("*** FAILURE: unable to allocate memory.\n");
|
||||
failure ("unable to allocate memory to store file data\n");
|
||||
}
|
||||
|
||||
rewind (f);
|
||||
|
|
@ -48,6 +48,101 @@ bytefile* read_file (char *fname) {
|
|||
return file;
|
||||
}
|
||||
|
||||
const char *read_cmd(char *ip) {
|
||||
char x = (*ip++), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
||||
|
||||
switch (h) {
|
||||
case 15:
|
||||
return "END";
|
||||
case 0:
|
||||
return "BINOP";
|
||||
case 1:
|
||||
switch (l) {
|
||||
case 0:
|
||||
return "CONST";
|
||||
case 1:
|
||||
return "STRING";
|
||||
case 2:
|
||||
return "SEXP ";
|
||||
case 3:
|
||||
return "STI";
|
||||
case 4:
|
||||
return "STA";
|
||||
case 5:
|
||||
return "JMP";
|
||||
case 6:
|
||||
return "END";
|
||||
case 7:
|
||||
return "RET";
|
||||
case 8:
|
||||
return "DROP";
|
||||
case 9:
|
||||
return "DUP";
|
||||
case 10:
|
||||
return "SWAP";
|
||||
case 11:
|
||||
return "ELEM";
|
||||
default:
|
||||
return "_UNDEF_CMD1_";
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
return "LD";
|
||||
case 3:
|
||||
return "LDA";
|
||||
case 4:
|
||||
return "ST";
|
||||
case 5:
|
||||
switch (l) {
|
||||
case 0:
|
||||
return "CJMPz";
|
||||
case 1:
|
||||
return "CJMPnz";
|
||||
case 2:
|
||||
return "BEGIN";
|
||||
case 3:
|
||||
return "CBEGIN";
|
||||
case 4:
|
||||
return "CLOSURE";
|
||||
case 5:
|
||||
return "CALLC";
|
||||
case 6:
|
||||
return "CALL";
|
||||
case 7:
|
||||
return "TAG";
|
||||
case 8:
|
||||
return "ARRAY";
|
||||
case 9:
|
||||
return "FAIL";
|
||||
case 10:
|
||||
return "LINE";
|
||||
default:
|
||||
return "_UNDEF_CMD5_";
|
||||
}
|
||||
case 6:
|
||||
return "PATT";
|
||||
case 7: {
|
||||
switch (l) {
|
||||
case 0:
|
||||
return "CALL\tLread";
|
||||
case 1:
|
||||
return "CALL\tLwrite";
|
||||
case 2:
|
||||
return "CALL\tLlength";
|
||||
case 3:
|
||||
return "CALL\tLstring";
|
||||
case 4:
|
||||
return "CALL\tBarray\t%d";
|
||||
default:
|
||||
return "_UNDEF_CALL_";
|
||||
}
|
||||
}
|
||||
default:
|
||||
return "_UNDEF_CODE_";
|
||||
}
|
||||
}
|
||||
|
||||
/* Disassembles the bytecode pool */
|
||||
void disassemble (FILE *f, bytefile *bf) {
|
||||
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@ bool s_is_empty(struct State* s) {
|
|||
|
||||
void **s_nth(struct State *s, aint n) {
|
||||
if (n < 0) {
|
||||
failure("can't access stack by negative index");
|
||||
s_failure(s, "can't access stack by negative index");
|
||||
}
|
||||
if (s->sp + n >= s_top(s)) {
|
||||
failure("not enough elements in stack");
|
||||
s_failure(s, "not enough elements in stack");
|
||||
}
|
||||
if (s->fp != NULL && s->sp + n >= f_locals(s->fp)) {
|
||||
failure("not enough elements in function stack");
|
||||
s_failure(s, "not enough elements in function stack");
|
||||
}
|
||||
|
||||
return s->sp + n;
|
||||
|
|
@ -61,10 +61,10 @@ void **s_nth(struct State *s, aint n) {
|
|||
|
||||
void** s_peek(struct State* s) {
|
||||
if (s->sp == s_top(s)) {
|
||||
failure("empty stack");
|
||||
s_failure(s, "empty stack");
|
||||
}
|
||||
if (s->fp != NULL && s->sp == f_locals(s->fp)) {
|
||||
failure("empty function stack");
|
||||
s_failure(s, "empty function stack");
|
||||
}
|
||||
|
||||
return s->sp;
|
||||
|
|
@ -76,13 +76,14 @@ aint* s_peek_i(struct State* s) {
|
|||
|
||||
void s_push(struct State *s, void *val) {
|
||||
if (s->sp == s->stack) {
|
||||
failure("stack overflow");
|
||||
s_failure(s, "stack overflow");
|
||||
}
|
||||
#ifdef DEBUG_VERSION
|
||||
printf("--> push\n");
|
||||
#endif
|
||||
--s->sp;
|
||||
*s->sp = val;
|
||||
// __gc_stack_top= (size_t)(s->sp - 1);
|
||||
}
|
||||
|
||||
void s_push_i(struct State *s, aint val) {
|
||||
|
|
@ -101,10 +102,10 @@ void s_pushn_nil(struct State *s, size_t n) {
|
|||
|
||||
void* s_pop(struct State *s) {
|
||||
if (s->sp == s_top(s)) {
|
||||
failure("empty stack");
|
||||
s_failure(s, "empty stack");
|
||||
}
|
||||
if (s->fp != NULL && s->sp == f_locals(s->fp)) {
|
||||
failure("empty function stack");
|
||||
s_failure(s, "empty function stack");
|
||||
}
|
||||
#ifdef DEBUG_VERSION
|
||||
printf("--> pop\n");
|
||||
|
|
@ -112,7 +113,7 @@ void* s_pop(struct State *s) {
|
|||
void* value = *s->sp;
|
||||
*s->sp = NULL;
|
||||
++s->sp;
|
||||
|
||||
// __gc_stack_top = (size_t)(s->sp - 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
@ -136,10 +137,10 @@ void s_enter_f(struct State *s, char *rp, bool is_closure_call, auint args_sz, a
|
|||
|
||||
// check that params count is valid
|
||||
if (s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top(s)) {
|
||||
failure("not enough parameters in stack");
|
||||
s_failure(s, "not enough parameters in stack");
|
||||
}
|
||||
if (s->fp != NULL && s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s->fp)) {
|
||||
failure("not enough parameters in function stack");
|
||||
s_failure(s, "not enough parameters in function stack");
|
||||
}
|
||||
|
||||
void* closure = is_closure_call ? s_nth(s, args_sz) : NULL;
|
||||
|
|
@ -166,7 +167,7 @@ void s_enter_f(struct State *s, char *rp, bool is_closure_call, auint args_sz, a
|
|||
|
||||
void s_exit_f(struct State *s) {
|
||||
if (s->fp == NULL) {
|
||||
failure("exit: no func");
|
||||
s_failure(s, "exit: no func");
|
||||
}
|
||||
|
||||
struct Frame frame = *s->fp;
|
||||
|
|
@ -209,41 +210,41 @@ void print_stack(struct State* s) {
|
|||
void **var_by_category(struct State *s, enum VarCategory category,
|
||||
int id) {
|
||||
if (id < 0) {
|
||||
failure("can't read variable: negative id %i", id);
|
||||
s_failure(s, "can't read variable: negative id"); // %i", id);
|
||||
}
|
||||
void **var = NULL;
|
||||
switch (category) {
|
||||
case VAR_GLOBAL:
|
||||
if (s->bf->global_area_size <= id) {
|
||||
failure("can't read global: too big id, %i >= %ul", id, s->bf->global_area_size);
|
||||
s_failure(s, "can't read global: too big id"); //, %i >= %ul", id, s->bf->global_area_size);
|
||||
}
|
||||
var = s->stack + STACK_SIZE - 1 - id;
|
||||
break;
|
||||
case VAR_LOCAL:
|
||||
if (s->fp == NULL) {
|
||||
failure("can't read local outside of function");
|
||||
s_failure(s, "can't read local outside of function");
|
||||
}
|
||||
if (f_locals_sz(s->fp) <= id) {
|
||||
failure("can't read local: too big id, %i >= %ul", id, f_locals_sz(s->fp));
|
||||
s_failure(s, "can't read local: too big id"); //, %i >= %ul", id, f_locals_sz(s->fp));
|
||||
}
|
||||
// printf("id is %i, local is %i, %i\n", id, UNBOX((auint)*((void**)f_locals(s->fp) + id)), f_locals(s->fp) - s->sp);
|
||||
var = f_locals(s->fp) + (f_locals_sz(s->fp) - id - 1);
|
||||
break;
|
||||
case VAR_ARGUMENT:
|
||||
if (s->fp == NULL) {
|
||||
failure("can't read argument outside of function");
|
||||
s_failure(s, "can't read argument outside of function");
|
||||
}
|
||||
if (f_args_sz(s->fp) <= id) {
|
||||
failure("can't read arguments: too big id, %i >= %ul", id, f_args_sz(s->fp));
|
||||
s_failure(s, "can't read arguments: too big id"); //, %i >= %ul", id, f_args_sz(s->fp));
|
||||
}
|
||||
var = f_args(s->fp) + (f_args_sz(s->fp) - id - 1);
|
||||
break;
|
||||
case VAR_CLOSURE:
|
||||
if (s->fp == NULL) {
|
||||
failure("can't read closure parameter outside of function");
|
||||
s_failure(s, "can't read closure parameter outside of function");
|
||||
}
|
||||
if (s->fp->closure == NULL) {
|
||||
failure("can't read closure parameter not in closure");
|
||||
s_failure(s, "can't read closure parameter not in closure");
|
||||
}
|
||||
if (UNBOXED(s->fp->closure)) { ASSERT_BOXED(".elem:1", s->fp->closure); }
|
||||
data* d = TO_DATA(s->fp->closure);
|
||||
|
|
@ -252,7 +253,7 @@ void **var_by_category(struct State *s, enum VarCategory category,
|
|||
printf("id is %i, count is %i\n", id, count);
|
||||
#endif
|
||||
if (count <= id) {
|
||||
failure("can't read arguments: too big id, %i >= %ul", id, count);
|
||||
s_failure(s, "can't read arguments: too big id"); //, %i >= %ul", id, count);
|
||||
}
|
||||
return (void **)d->contents + id; // order is not important
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "types.h"
|
||||
|
||||
#include "stack.h"
|
||||
#include "utils.h"
|
||||
#include "parser.h"
|
||||
#include "../../runtime/gc.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
|
@ -29,6 +31,7 @@ static void alloc_state(bytefile *bf, struct State* s) {
|
|||
s->bf = bf;
|
||||
s->is_closure_call = false;
|
||||
s->ip = bf->code_ptr;
|
||||
s->instr_ip = bf->code_ptr;
|
||||
s->call_ip = NULL;
|
||||
s->current_line = 0;
|
||||
|
||||
|
|
@ -44,6 +47,7 @@ void init_state(bytefile *bf, struct State* s) {
|
|||
__init();
|
||||
alloc_state(bf, s);
|
||||
__gc_stack_bottom = (size_t)s->sp;
|
||||
__gc_stack_top = __gc_stack_bottom;
|
||||
|
||||
s_pushn_nil(s, bf->global_area_size);
|
||||
|
||||
|
|
@ -67,11 +71,15 @@ void cleanup_state(struct State* state) {
|
|||
__shutdown();
|
||||
}
|
||||
|
||||
void s_failure(struct State *s, const char *msg) {
|
||||
exec_failure(read_cmd(s->instr_ip), s->current_line, s->instr_ip - s->bf->code_ptr, msg);
|
||||
}
|
||||
|
||||
// --- VarCategory ---
|
||||
|
||||
enum VarCategory to_var_category(uint8_t category) {
|
||||
enum VarCategory to_var_category(struct State* s, uint8_t category) {
|
||||
if (category > 3) {
|
||||
failure("unexpected variable category");
|
||||
s_failure(s, "unexpected variable category");
|
||||
}
|
||||
return (enum VarCategory)category;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../../runtime/runtime.h"
|
||||
|
||||
/* Gets a string from a string table by an index */
|
||||
extern char* get_string(bytefile *f, size_t pos) {
|
||||
return &f->string_ptr[pos];
|
||||
|
|
@ -19,4 +21,8 @@ extern size_t get_public_offset (bytefile *f, size_t i) {
|
|||
return f->public_ptr[i*2+1];
|
||||
}
|
||||
|
||||
void exec_failure(const char *cmd, int line, aint offset, const char *msg) {
|
||||
failure("*** RUNTIME ERROR: %i(0x%.8x):%s error: %s\n", line, offset, cmd, msg);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue