mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 14:58:50 +00:00
gloal state
This commit is contained in:
parent
f5c7843942
commit
1df2624c25
4 changed files with 179 additions and 179 deletions
|
|
@ -7,94 +7,92 @@
|
||||||
|
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
extern struct State s;
|
||||||
|
|
||||||
extern size_t __gc_stack_top, __gc_stack_bottom;
|
extern size_t __gc_stack_top, __gc_stack_bottom;
|
||||||
|
|
||||||
static inline void **s_top(struct State *s) {
|
static inline void **s_top() {
|
||||||
return s->stack + STACK_SIZE - s->bf->global_area_size;
|
return s.stack + STACK_SIZE - s.bf->global_area_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool s_is_empty(struct State *s) {
|
static inline bool s_is_empty() {
|
||||||
if (s->sp == s_top(s) || (s->fp != NULL && s->sp == f_locals(s->fp))) {
|
if (s.sp == s_top() || (s.fp != NULL && s.sp == f_locals(s.fp))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void **s_nth(struct State *s, aint n) {
|
static inline void **s_nth(aint n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
s_failure(s, "can't access stack by negative index");
|
s_failure(&s, "can't access stack by negative index");
|
||||||
}
|
}
|
||||||
if (s->sp + n >= s_top(s)) {
|
if (s.sp + n >= s_top()) {
|
||||||
s_failure(s, "not enough elements in stack");
|
s_failure(&s, "not enough elements in stack");
|
||||||
}
|
}
|
||||||
if (s->fp != NULL && s->sp + n >= f_locals(s->fp)) {
|
if (s.fp != NULL && s.sp + n >= f_locals(s.fp)) {
|
||||||
s_failure(s, "not enough elements in function stack");
|
s_failure(&s, "not enough elements in function stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
return s->sp + n;
|
return s.sp + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void **s_peek(struct State *s) {
|
static inline void **s_peek() {
|
||||||
if (s->sp == s_top(s)) {
|
if (s.sp == s_top()) {
|
||||||
s_failure(s, "empty stack");
|
s_failure(&s, "empty stack");
|
||||||
}
|
}
|
||||||
if (s->fp != NULL && s->sp == f_locals(s->fp)) {
|
if (s.fp != NULL && s.sp == f_locals(s.fp)) {
|
||||||
s_failure(s, "empty function stack");
|
s_failure(&s, "empty function stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
return s->sp;
|
return s.sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline aint *s_peek_i(struct State *s) { return (aint *)s_peek(s); }
|
static inline aint *s_peek_i() { return (aint *)s_peek(); }
|
||||||
|
|
||||||
static inline void s_push(struct State *s, void *val) {
|
static inline void s_push(void *val) {
|
||||||
if (s->sp == s->stack) {
|
if (s.sp == s.stack) {
|
||||||
s_failure(s, "stack overflow");
|
s_failure(&s, "stack overflow");
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("--> push\n");
|
printf("--> push\n");
|
||||||
#endif
|
#endif
|
||||||
--s->sp;
|
--s.sp;
|
||||||
*s->sp = val;
|
*s.sp = val;
|
||||||
__gc_stack_top = (size_t)(s->sp);
|
__gc_stack_top = (size_t)(s.sp) - (size_t)(s.sp) & 0xF;
|
||||||
__gc_stack_top -= __gc_stack_top & 0xF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void s_push_i(struct State *s, aint val) {
|
static inline void s_push_i(aint val) { s_push((void *)val); }
|
||||||
s_push(s, (void *)val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void s_push_nil(struct State *s) { s_push(s, NULL); }
|
static inline void s_push_nil() { s_push(NULL); }
|
||||||
|
|
||||||
static inline void s_pushn_nil(struct State *s, size_t n) {
|
static inline void s_pushn_nil(size_t n) {
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
s_push(s, NULL);
|
s_push(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void *s_pop(struct State *s) {
|
static inline void *s_pop() {
|
||||||
if (s->sp == s_top(s)) {
|
if (s.sp == s_top()) {
|
||||||
s_failure(s, "empty stack");
|
s_failure(&s, "empty stack");
|
||||||
}
|
}
|
||||||
if (s->fp != NULL && s->sp == f_locals(s->fp)) {
|
if (s.fp != NULL && s.sp == f_locals(s.fp)) {
|
||||||
s_failure(s, "empty function stack");
|
s_failure(&s, "empty function stack");
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("--> pop\n");
|
printf("--> pop\n");
|
||||||
#endif
|
#endif
|
||||||
void *value = *s->sp;
|
void *value = *s.sp;
|
||||||
*s->sp = NULL;
|
*s.sp = NULL;
|
||||||
++s->sp;
|
++s.sp;
|
||||||
__gc_stack_top = (size_t)(s->sp);
|
__gc_stack_top = (size_t)(s.sp) - (size_t)(s.sp) & 0xF;
|
||||||
__gc_stack_top -= __gc_stack_top & 0xF;
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline aint s_pop_i(struct State *s) { return (aint)s_pop(s); }
|
static inline aint s_pop_i() { return (aint)s_pop(); }
|
||||||
|
|
||||||
static inline void s_popn(struct State *s, size_t n) {
|
static inline void s_popn(size_t n) {
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
s_pop(s);
|
s_pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,79 +104,79 @@ static inline void s_popn(struct State *s, size_t n) {
|
||||||
//
|
//
|
||||||
// where |> defines corresponding frame pointer, | is stack pointer
|
// where |> defines corresponding frame pointer, | is stack pointer
|
||||||
// location before / after new frame added
|
// location before / after new frame added
|
||||||
static inline void s_enter_f(struct State *s, char *rp, bool is_closure_call,
|
static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz,
|
||||||
auint args_sz, auint locals_sz) {
|
auint locals_sz) {
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("-> %i args sz\n", args_sz);
|
printf("-> %i args sz\n", args_sz);
|
||||||
printf("-> %i locals sz\n", locals_sz);
|
printf("-> %i locals sz\n", locals_sz);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check that params count is valid
|
// check that params count is valid
|
||||||
if (s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top(s)) {
|
if (s.sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top()) {
|
||||||
s_failure(s, "not enough parameters in stack");
|
s_failure(&s, "not enough parameters in stack");
|
||||||
}
|
}
|
||||||
if (s->fp != NULL &&
|
if (s.fp != NULL &&
|
||||||
s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s->fp)) {
|
s.sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s.fp)) {
|
||||||
s_failure(s, "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;
|
void *closure = is_closure_call ? s_nth(args_sz) : NULL;
|
||||||
|
|
||||||
// s_push_nil(s); // sp contains value, frame starts with next value
|
// s_push_nil(s); // sp contains value, frame starts with next value
|
||||||
s_pushn_nil(s, frame_sz());
|
s_pushn_nil(frame_sz());
|
||||||
|
|
||||||
// create frame
|
// create frame
|
||||||
struct Frame frame = {
|
struct Frame frame = {
|
||||||
.closure = closure,
|
.closure = closure,
|
||||||
.ret = NULL, // field in frame itself
|
.ret = NULL, // field in frame itself
|
||||||
.rp = rp,
|
.rp = rp,
|
||||||
.prev_fp = (void **)s->fp,
|
.prev_fp = (void **)s.fp,
|
||||||
.args_sz_box = BOX(args_sz),
|
.args_sz_box = BOX(args_sz),
|
||||||
.locals_sz_box = BOX(locals_sz),
|
.locals_sz_box = BOX(locals_sz),
|
||||||
};
|
};
|
||||||
|
|
||||||
// put frame on stack
|
// put frame on stack
|
||||||
s->fp = (struct Frame *)s->sp;
|
s.fp = (struct Frame *)s.sp;
|
||||||
(*s->fp) = frame;
|
(*s.fp) = frame;
|
||||||
|
|
||||||
s_pushn_nil(s, locals_sz);
|
s_pushn_nil(locals_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void s_exit_f(struct State *s) {
|
static inline void s_exit_f() {
|
||||||
if (s->fp == NULL) {
|
if (s.fp == NULL) {
|
||||||
s_failure(s, "exit: no func");
|
s_failure(&s, "exit: no func");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Frame frame = *s->fp;
|
struct Frame frame = *s.fp;
|
||||||
push_extra_root((void **)&frame.ret);
|
push_extra_root((void **)&frame.ret);
|
||||||
|
|
||||||
// drop stack entities, locals, frame
|
// drop stack entities, locals, frame
|
||||||
size_t to_pop = f_args(s->fp) - s->sp;
|
size_t to_pop = f_args(s.fp) - s.sp;
|
||||||
s->fp = (struct Frame *)f_prev_fp(&frame);
|
s.fp = (struct Frame *)f_prev_fp(&frame);
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("-> %zu to pop\n", to_pop);
|
printf("-> %zu to pop\n", to_pop);
|
||||||
#endif
|
#endif
|
||||||
s_popn(s, to_pop);
|
s_popn(to_pop);
|
||||||
|
|
||||||
// drop args
|
// drop args
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("-> + %zu to pop\n", f_args_sz(&frame));
|
printf("-> + %zu to pop\n", f_args_sz(&frame));
|
||||||
#endif
|
#endif
|
||||||
s_popn(s, f_args_sz(&frame));
|
s_popn(f_args_sz(&frame));
|
||||||
|
|
||||||
// save returned value, not in main
|
// save returned value, not in main
|
||||||
if (frame.prev_fp != 0) {
|
if (frame.prev_fp != 0) {
|
||||||
s_push(s, frame.ret);
|
s_push(frame.ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->ip = frame.rp;
|
s.ip = frame.rp;
|
||||||
|
|
||||||
pop_extra_root((void **)&frame.ret);
|
pop_extra_root((void **)&frame.ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void print_stack(struct State *s) {
|
static inline void print_stack() {
|
||||||
printf("stack (%i) is\n[", s->stack + STACK_SIZE - s->sp);
|
printf("stack (%i) is\n[", s.stack + STACK_SIZE - s.sp);
|
||||||
for (void **x = s->stack + STACK_SIZE - 1; x >= s->sp; --x) {
|
for (void **x = s.stack + STACK_SIZE - 1; x >= s.sp; --x) {
|
||||||
printf("%li ", (long)UNBOX(*x));
|
printf("%li ", (long)UNBOX(*x));
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
|
|
@ -186,60 +184,59 @@ static inline void print_stack(struct State *s) {
|
||||||
|
|
||||||
// --- category ---
|
// --- category ---
|
||||||
|
|
||||||
static inline void **var_by_category(struct State *s, enum VarCategory category,
|
static inline void **var_by_category(enum VarCategory category, int id) {
|
||||||
int id) {
|
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
s_failure(s, "can't read variable: negative id"); // %i", id);
|
s_failure(&s, "can't read variable: negative id"); // %i", id);
|
||||||
}
|
}
|
||||||
void **var = NULL;
|
void **var = NULL;
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case VAR_GLOBAL:
|
case VAR_GLOBAL:
|
||||||
if (s->bf->global_area_size <= id) {
|
if (s.bf->global_area_size <= id) {
|
||||||
s_failure(s,
|
s_failure(&s,
|
||||||
"can't read global: too big id"); //, %i >= %ul", id,
|
"can't read global: too big id"); //, %i >= %ul", id,
|
||||||
// s->bf->global_area_size);
|
// s.bf->global_area_size);
|
||||||
}
|
}
|
||||||
var = s->stack + STACK_SIZE - 1 - id;
|
var = s.stack + STACK_SIZE - 1 - id;
|
||||||
break;
|
break;
|
||||||
case VAR_LOCAL:
|
case VAR_LOCAL:
|
||||||
if (s->fp == NULL) {
|
if (s.fp == NULL) {
|
||||||
s_failure(s, "can't read local outside of function");
|
s_failure(&s, "can't read local outside of function");
|
||||||
}
|
}
|
||||||
if (f_locals_sz(s->fp) <= id) {
|
if (f_locals_sz(s.fp) <= id) {
|
||||||
s_failure(s, "can't read local: too big id"); //, %i >= %ul", id,
|
s_failure(&s, "can't read local: too big id"); //, %i >= %ul", id,
|
||||||
// f_locals_sz(s->fp));
|
// f_locals_sz(s.fp));
|
||||||
}
|
}
|
||||||
// printf("id is %i, local is %i, %i\n", id,
|
// printf("id is %i, local is %i, %i\n", id,
|
||||||
// UNBOX((auint)*((void**)f_locals(s->fp) + id)), f_locals(s->fp) - s->sp);
|
// 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);
|
var = f_locals(s.fp) + (f_locals_sz(s.fp) - id - 1);
|
||||||
break;
|
break;
|
||||||
case VAR_ARGUMENT:
|
case VAR_ARGUMENT:
|
||||||
if (s->fp == NULL) {
|
if (s.fp == NULL) {
|
||||||
s_failure(s, "can't read argument outside of function");
|
s_failure(&s, "can't read argument outside of function");
|
||||||
}
|
}
|
||||||
if (f_args_sz(s->fp) <= id) {
|
if (f_args_sz(s.fp) <= id) {
|
||||||
s_failure(s, "can't read arguments: too big id"); //, %i >= %ul", id,
|
s_failure(&s, "can't read arguments: too big id"); //, %i >= %ul", id,
|
||||||
// f_args_sz(s->fp));
|
// f_args_sz(s.fp));
|
||||||
}
|
}
|
||||||
var = f_args(s->fp) + (f_args_sz(s->fp) - id - 1);
|
var = f_args(s.fp) + (f_args_sz(s.fp) - id - 1);
|
||||||
break;
|
break;
|
||||||
case VAR_CLOSURE:
|
case VAR_CLOSURE:
|
||||||
if (s->fp == NULL) {
|
if (s.fp == NULL) {
|
||||||
s_failure(s, "can't read closure parameter outside of function");
|
s_failure(&s, "can't read closure parameter outside of function");
|
||||||
}
|
}
|
||||||
if (s->fp->closure == NULL) {
|
if (s.fp->closure == NULL) {
|
||||||
s_failure(s, "can't read closure parameter not in closure");
|
s_failure(&s, "can't read closure parameter not in closure");
|
||||||
}
|
}
|
||||||
if (UNBOXED(s->fp->closure)) {
|
if (UNBOXED(s.fp->closure)) {
|
||||||
s_failure(s, "not boxed value expected in closure index");
|
s_failure(&s, "not boxed value expected in closure index");
|
||||||
}
|
}
|
||||||
data *d = TO_DATA(s->fp->closure);
|
data *d = TO_DATA(s.fp->closure);
|
||||||
size_t count = get_len(d) - 1;
|
size_t count = get_len(d) - 1;
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("id is %i, count is %i\n", id, count);
|
printf("id is %i, count is %i\n", id, count);
|
||||||
#endif
|
#endif
|
||||||
if (count <= id) {
|
if (count <= id) {
|
||||||
s_failure(s,
|
s_failure(&s,
|
||||||
"can't read arguments: too big id"); //, %i >= %ul", id, count);
|
"can't read arguments: too big id"); //, %i >= %ul", id, count);
|
||||||
}
|
}
|
||||||
return (void **)d->contents + id; // order is not important
|
return (void **)d->contents + id; // order is not important
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ static inline void **f_args(struct Frame *fp) {
|
||||||
// ------ State ------
|
// ------ State ------
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
void *stack[STACK_SIZE + 1];
|
void **stack;
|
||||||
void **sp; // stack pointer
|
void **sp; // stack pointer
|
||||||
struct Frame *fp; // function frame pointer
|
struct Frame *fp; // function frame pointer
|
||||||
bytefile *bf;
|
bytefile *bf;
|
||||||
|
|
@ -65,7 +65,7 @@ struct State {
|
||||||
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_state(bytefile *bf, struct State *s);
|
void construct_state(bytefile *bf, struct State *s, void **stack);
|
||||||
void cleanup_state(struct State *state);
|
void cleanup_state(struct State *state);
|
||||||
|
|
||||||
static inline void s_failure(struct State *s, const char *msg) {
|
static inline void s_failure(struct State *s, const char *msg) {
|
||||||
|
|
@ -82,10 +82,11 @@ enum VarCategory {
|
||||||
VAR_CLOSURE = 3
|
VAR_CLOSURE = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline enum VarCategory to_var_category(struct State *s,
|
extern struct State s;
|
||||||
uint8_t category) {
|
|
||||||
|
static inline enum VarCategory to_var_category(uint8_t category) {
|
||||||
if (category > 3) {
|
if (category > 3) {
|
||||||
s_failure(s, "unexpected variable category");
|
s_failure(&s, "unexpected variable category");
|
||||||
}
|
}
|
||||||
return (enum VarCategory)category;
|
return (enum VarCategory)category;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,25 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int ip_read_int(char **ip) {
|
struct State s;
|
||||||
|
|
||||||
|
static inline int ip_read_int(char **ip) {
|
||||||
*ip += sizeof(int);
|
*ip += sizeof(int);
|
||||||
return *(int *)((*ip) - sizeof(int));
|
return *(int *)((*ip) - sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
char ip_read_byte(char **ip) { return *(*ip)++; }
|
static inline char ip_read_byte(char **ip) { return *(*ip)++; }
|
||||||
|
|
||||||
char *ip_read_string(char **ip, bytefile *bf) {
|
static inline char *ip_read_string(char **ip, bytefile *bf) {
|
||||||
return get_string(bf, ip_read_int(ip));
|
return get_string(bf, ip_read_int(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t BUFFER_SIZE = 1000;
|
const size_t BUFFER_SIZE = 1000;
|
||||||
|
|
||||||
void run(bytefile *bf, int argc, char **argv) {
|
void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
void *stack[STACK_SIZE];
|
||||||
void *buffer[BUFFER_SIZE];
|
void *buffer[BUFFER_SIZE];
|
||||||
struct State s;
|
construct_state(bf, &s, stack);
|
||||||
init_state(bf, &s);
|
|
||||||
|
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
printf("--- interpreter run ---\n");
|
printf("--- interpreter run ---\n");
|
||||||
|
|
@ -55,12 +57,12 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
|
||||||
// argc, argv
|
// argc, argv
|
||||||
{
|
{
|
||||||
s_push_i(&s, BOX(argc));
|
s_push_i(BOX(argc));
|
||||||
void **argv_strs = calloc(argc, sizeof(void *));
|
void **argv_strs = calloc(argc, sizeof(void *));
|
||||||
for (size_t i = 0; i < argc; ++i) {
|
for (size_t i = 0; i < argc; ++i) {
|
||||||
argv_strs[i] = Bstring((aint *)&argv[i]);
|
argv_strs[i] = Bstring((aint *)&argv[i]);
|
||||||
}
|
}
|
||||||
s_push(&s, Barray((aint *)&argv_strs, argc));
|
s_push(Barray((aint *)&argv_strs, argc));
|
||||||
free(argv_strs);
|
free(argv_strs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,20 +92,20 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
if (l < 1) {
|
if (l < 1) {
|
||||||
s_failure(&s, "negative binop type index");
|
s_failure(&s, "negative binop type index");
|
||||||
}
|
}
|
||||||
void *left = s_pop(&s);
|
void *left = s_pop();
|
||||||
void *right = s_pop(&s);
|
void *right = s_pop();
|
||||||
s_push(&s, (void *)ops_func[l - 1](right, left));
|
s_push((void *)ops_func[l - 1](right, left));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
switch (l) {
|
switch (l) {
|
||||||
case 0: // CONST %d
|
case 0: // CONST %d
|
||||||
s_push_i(&s, BOX(ip_read_int(&s.ip)));
|
s_push_i(BOX(ip_read_int(&s.ip)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: { // STRING %s
|
case 1: { // STRING %s
|
||||||
void *str = ip_read_string(&s.ip, bf);
|
void *str = ip_read_string(&s.ip, bf);
|
||||||
s_push(&s, Bstring((aint *)&str));
|
s_push(Bstring((aint *)&str));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,14 +125,14 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
void **opr_buffer = args_count >= BUFFER_SIZE ? calloc(args_count + 1, sizeof(void *)) : buffer;
|
void **opr_buffer = args_count >= BUFFER_SIZE ? calloc(args_count + 1, sizeof(void *)) : buffer;
|
||||||
|
|
||||||
for (size_t i = 1; i <= args_count; ++i) {
|
for (size_t i = 1; i <= args_count; ++i) {
|
||||||
opr_buffer[args_count - i] = s_pop(&s);
|
opr_buffer[args_count - i] = s_pop();
|
||||||
}
|
}
|
||||||
opr_buffer[args_count] = (void *)LtagHash((char *)name);
|
opr_buffer[args_count] = (void *)LtagHash((char *)name);
|
||||||
|
|
||||||
void *sexp = Bsexp((aint *)opr_buffer, BOX(args_count + 1));
|
void *sexp = Bsexp((aint *)opr_buffer, BOX(args_count + 1));
|
||||||
|
|
||||||
push_extra_root(sexp);
|
push_extra_root(sexp);
|
||||||
s_push(&s, sexp);
|
s_push(sexp);
|
||||||
pop_extra_root(sexp);
|
pop_extra_root(sexp);
|
||||||
|
|
||||||
if (args_count >= BUFFER_SIZE) {
|
if (args_count >= BUFFER_SIZE) {
|
||||||
|
|
@ -141,18 +143,18 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
|
||||||
case 3: { // STI - write by ref (?)
|
case 3: { // STI - write by ref (?)
|
||||||
// NOTE: example not found, no checks done
|
// NOTE: example not found, no checks done
|
||||||
void *elem = s_pop(&s);
|
void *elem = s_pop();
|
||||||
void **addr = (void **)s_pop(&s);
|
void **addr = (void **)s_pop();
|
||||||
*addr = elem;
|
*addr = elem;
|
||||||
s_push(&s, elem);
|
s_push(elem);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: { // STA - write to array elem
|
case 4: { // STA - write to array elem
|
||||||
void *elem = s_pop(&s);
|
void *elem = s_pop();
|
||||||
aint index = s_pop_i(&s);
|
aint index = s_pop_i();
|
||||||
void *data = s_pop(&s);
|
void *data = s_pop();
|
||||||
s_push(&s, Bsta(data, index, elem));
|
s_push(Bsta(data, index, elem));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,37 +169,37 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 6: // END
|
case 6: // END
|
||||||
if (!s_is_empty(&s) && s.fp->prev_fp != 0) {
|
if (!s_is_empty() && s.fp->prev_fp != 0) {
|
||||||
s.fp->ret = *s_peek(&s);
|
s.fp->ret = *s_peek();
|
||||||
s_pop(&s);
|
s_pop();
|
||||||
}
|
}
|
||||||
s_exit_f(&s);
|
s_exit_f();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: // RET
|
case 7: // RET
|
||||||
if (!s_is_empty(&s) && s.fp->prev_fp != 0) {
|
if (!s_is_empty() && s.fp->prev_fp != 0) {
|
||||||
s.fp->ret = *s_peek(&s);
|
s.fp->ret = *s_peek();
|
||||||
s_pop(&s);
|
s_pop();
|
||||||
}
|
}
|
||||||
s_exit_f(&s);
|
s_exit_f();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8: // DROP
|
case 8: // DROP
|
||||||
s_pop(&s);
|
s_pop();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9: // DUP
|
case 9: // DUP
|
||||||
{
|
{
|
||||||
s_push(&s, *s_peek(&s));
|
s_push(*s_peek());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 10: // SWAP
|
case 10: // SWAP
|
||||||
{
|
{
|
||||||
void* x = s_pop(&s);
|
void* x = s_pop();
|
||||||
void* y = s_pop(&s);
|
void* y = s_pop();
|
||||||
s_push(&s, y);
|
s_push(y);
|
||||||
s_push(&s, x);
|
s_push(x);
|
||||||
|
|
||||||
// if (s.sp + 1 >= s.stack + STACK_SIZE ||
|
// if (s.sp + 1 >= s.stack + STACK_SIZE ||
|
||||||
// (s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) {
|
// (s.fp != NULL && s.sp + 1 >= f_locals(s.fp))) {
|
||||||
|
|
@ -212,9 +214,9 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
|
||||||
case 11: // ELEM
|
case 11: // ELEM
|
||||||
{
|
{
|
||||||
aint index = s_pop_i(&s);
|
aint index = s_pop_i();
|
||||||
void *data = s_pop(&s);
|
void *data = s_pop();
|
||||||
s_push(&s, Belem(data, index));
|
s_push(Belem(data, index));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -224,21 +226,21 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
|
||||||
case 2: { // LD %d
|
case 2: { // LD %d
|
||||||
void **var_ptr =
|
void **var_ptr =
|
||||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
||||||
s_push(&s, *var_ptr);
|
s_push(*var_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: { // LDA %d
|
case 3: { // LDA %d
|
||||||
void **var_ptr =
|
void **var_ptr =
|
||||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
||||||
s_push(&s, var_ptr);
|
s_push(*var_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: { // ST %d
|
case 4: { // ST %d
|
||||||
void **var_ptr =
|
void **var_ptr =
|
||||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
||||||
*var_ptr = *s_peek(&s);
|
*var_ptr = *s_peek();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +252,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
if (jmp_p < 0) {
|
if (jmp_p < 0) {
|
||||||
s_failure(&s, "negative file offset jumps are not allowed");
|
s_failure(&s, "negative file offset jumps are not allowed");
|
||||||
}
|
}
|
||||||
if (UNBOX(s_pop_i(&s)) == 0) {
|
if (UNBOX(s_pop_i()) == 0) {
|
||||||
s.ip = bf->code_ptr + jmp_p;
|
s.ip = bf->code_ptr + jmp_p;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -262,7 +264,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
if (jmp_p < 0) {
|
if (jmp_p < 0) {
|
||||||
s_failure(&s, "negative file offset jumps are not allowed");
|
s_failure(&s, "negative file offset jumps are not allowed");
|
||||||
}
|
}
|
||||||
if (UNBOX(s_pop_i(&s)) != 0) {
|
if (UNBOX(s_pop_i()) != 0) {
|
||||||
s.ip = bf->code_ptr + jmp_p;
|
s.ip = bf->code_ptr + jmp_p;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -274,7 +276,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
if (s.fp != NULL && s.call_ip == NULL) {
|
if (s.fp != NULL && s.call_ip == NULL) {
|
||||||
s_failure(&s, "begin should only be called 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,
|
s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||||
locals_sz);
|
locals_sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +288,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
if (s.fp != NULL && s.call_ip == NULL) {
|
if (s.fp != NULL && s.call_ip == NULL) {
|
||||||
s_failure(&s, "begin should only be called 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,
|
s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||||
locals_sz);
|
locals_sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -300,16 +302,16 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
aint arg_id = ip_read_int(&s.ip);
|
aint arg_id = ip_read_int(&s.ip);
|
||||||
|
|
||||||
void **var_ptr =
|
void **var_ptr =
|
||||||
var_by_category(&s, to_var_category(&s, l), ip_read_int(&s.ip));
|
var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
||||||
s_push(&s, *var_ptr);
|
s_push(*var_ptr);
|
||||||
}
|
}
|
||||||
s_push(&s, bf->code_ptr + call_offset);
|
s_push(bf->code_ptr + call_offset);
|
||||||
|
|
||||||
void *closure = Bclosure((aint *)s.sp, args_count);
|
void *closure = Bclosure((aint *)s.sp, args_count);
|
||||||
|
|
||||||
push_extra_root(closure);
|
push_extra_root(closure);
|
||||||
s_popn(&s, args_count + 1);
|
s_popn(args_count + 1);
|
||||||
s_push(&s, closure);
|
s_push(closure);
|
||||||
pop_extra_root(closure);
|
pop_extra_root(closure);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +323,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
s.is_closure_call = true;
|
s.is_closure_call = true;
|
||||||
s.call_ip = s.ip;
|
s.call_ip = s.ip;
|
||||||
|
|
||||||
s.ip = Belem(*s_nth(&s, args_count), BOX(0)); // use offset instead ??
|
s.ip = Belem(*s_nth(args_count), BOX(0)); // use offset instead ??
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,18 +351,18 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
UNBOX(LtagHash((char *)name)), args_count, s_peek(&s));
|
UNBOX(LtagHash((char *)name)), args_count, s_peek(&s));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_push_i(&s, Btag(s_pop(&s), LtagHash((char *)name), BOX(args_count)));
|
s_push_i(Btag(s_pop(), LtagHash((char *)name), BOX(args_count)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: // ARRAY %d
|
case 8: // ARRAY %d
|
||||||
s_push_i(&s, Barray_patt(s_pop(&s), BOX(ip_read_int(&s.ip))));
|
s_push_i(Barray_patt(s_pop(), BOX(ip_read_int(&s.ip))));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9: { // FAIL %d %d
|
case 9: { // FAIL %d %d
|
||||||
int line = ip_read_int(&s.ip); // ??
|
int line = ip_read_int(&s.ip); // ??
|
||||||
int col = ip_read_int(&s.ip); // ??
|
int col = ip_read_int(&s.ip); // ??
|
||||||
Bmatch_failure(s_pop(&s), argv[0], BOX(line), BOX(col));
|
Bmatch_failure(s_pop(), argv[0], BOX(line), BOX(col));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -378,25 +380,25 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
// {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}
|
// {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"}
|
||||||
switch (l) {
|
switch (l) {
|
||||||
case 0: // =str
|
case 0: // =str
|
||||||
s_push_i(&s, Bstring_patt(s_pop(&s), s_pop(&s)));
|
s_push_i(Bstring_patt(s_pop(), s_pop()));
|
||||||
break;
|
break;
|
||||||
case 1: // #string
|
case 1: // #string
|
||||||
s_push_i(&s, Bstring_tag_patt(s_pop(&s)));
|
s_push_i(Bstring_tag_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
case 2: // #array
|
case 2: // #array
|
||||||
s_push_i(&s, Barray_tag_patt(s_pop(&s)));
|
s_push_i(Barray_tag_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
case 3: // #sexp
|
case 3: // #sexp
|
||||||
s_push_i(&s, Bsexp_tag_patt(s_pop(&s)));
|
s_push_i(Bsexp_tag_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
case 4: // #ref
|
case 4: // #ref
|
||||||
s_push_i(&s, Bunboxed_patt(s_pop(&s)));
|
s_push_i(Bunboxed_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
case 5: // #val
|
case 5: // #val
|
||||||
s_push_i(&s, Bboxed_patt(s_pop(&s)));
|
s_push_i(Bboxed_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
case 6: // #fun
|
case 6: // #fun
|
||||||
s_push_i(&s, Bclosure_tag_patt(s_pop(&s)));
|
s_push_i(Bclosure_tag_patt(s_pop()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||||
|
|
@ -406,21 +408,21 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
case 7: {
|
case 7: {
|
||||||
switch (l) {
|
switch (l) {
|
||||||
case 0: // CALL Lread
|
case 0: // CALL Lread
|
||||||
s_push_i(&s, Lread());
|
s_push_i(Lread());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: // CALL Lwrite
|
case 1: // CALL Lwrite
|
||||||
Lwrite(*s_peek_i(&s));
|
Lwrite(*s_peek_i());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // CALL Llength
|
case 2: // CALL Llength
|
||||||
s_push_i(&s, Llength(s_pop(&s)));
|
s_push_i(Llength(s_pop()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: { // CALL Lstring
|
case 3: { // CALL Lstring
|
||||||
void *val = s_pop(&s);
|
void *val = s_pop();
|
||||||
void *str = Lstring((aint *)&val);
|
void *str = Lstring((aint *)&val);
|
||||||
s_push(&s, str);
|
s_push(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -432,12 +434,12 @@ void run(bytefile *bf, int argc, char **argv) {
|
||||||
|
|
||||||
void **opr_buffer = elem_count > BUFFER_SIZE ? calloc(elem_count, sizeof(void *)) : buffer;
|
void **opr_buffer = elem_count > BUFFER_SIZE ? calloc(elem_count, sizeof(void *)) : buffer;
|
||||||
for (size_t i = 0; i < elem_count; ++i) {
|
for (size_t i = 0; i < elem_count; ++i) {
|
||||||
opr_buffer[elem_count - i - 1] = s_pop(&s);
|
opr_buffer[elem_count - i - 1] = s_pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *array =
|
void *array =
|
||||||
Barray((aint *)opr_buffer, BOX(elem_count)); // NOTE: not shure if elems should be added
|
Barray((aint *)opr_buffer, BOX(elem_count)); // NOTE: not shure if elems should be added
|
||||||
s_push(&s, array);
|
s_push(array);
|
||||||
|
|
||||||
if (elem_count > BUFFER_SIZE) {
|
if (elem_count > BUFFER_SIZE) {
|
||||||
free(opr_buffer);
|
free(opr_buffer);
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ extern size_t __gc_stack_top, __gc_stack_bottom;
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
|
|
||||||
static void alloc_state(bytefile *bf, struct State* s) {
|
static void init_state(bytefile *bf, struct State* s, void** stack) {
|
||||||
// s->stack = calloc(STACK_SIZE + 1, sizeof(void*));
|
s->stack = stack;
|
||||||
s->bf = bf;
|
s->bf = bf;
|
||||||
s->is_closure_call = false;
|
s->is_closure_call = false;
|
||||||
s->ip = bf->code_ptr;
|
s->ip = bf->code_ptr;
|
||||||
|
|
@ -28,13 +28,13 @@ static void alloc_state(bytefile *bf, struct State* s) {
|
||||||
s->fp = NULL;
|
s->fp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_state(bytefile *bf, struct State* s) {
|
void construct_state(bytefile *bf, struct State* s, void** stack) {
|
||||||
__init();
|
__init();
|
||||||
alloc_state(bf, s);
|
init_state(bf, s, stack);
|
||||||
__gc_stack_bottom = (size_t)s->sp;
|
__gc_stack_bottom = (size_t)s->sp;
|
||||||
__gc_stack_top = __gc_stack_bottom;
|
__gc_stack_top = __gc_stack_bottom;
|
||||||
|
|
||||||
s_pushn_nil(s, bf->global_area_size);
|
s_pushn_nil(bf->global_area_size);
|
||||||
|
|
||||||
#ifdef DEBUG_VERSION
|
#ifdef DEBUG_VERSION
|
||||||
print_stack(s);
|
print_stack(s);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue