mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 14:58:50 +00:00
basically initial impl of all except sti. sexp with params not working, some bugs in closure impl
This commit is contained in:
parent
1e38ffaefb
commit
bd27e79b22
5 changed files with 186 additions and 74 deletions
|
|
@ -29,8 +29,11 @@ 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
|
||||||
void s_enter_f(struct State *s, char *rp, auint args_sz, auint locals_sz);
|
void s_enter_f(struct State *s, char *rp, bool is_closure_call, auint args_sz,
|
||||||
|
auint locals_sz);
|
||||||
|
|
||||||
void s_exit_f(struct State *s);
|
void s_exit_f(struct State *s);
|
||||||
|
|
||||||
|
// ---- category ---
|
||||||
|
|
||||||
void **var_by_category(struct State *s, enum VarCategory category, int id);
|
void **var_by_category(struct State *s, enum VarCategory category, int id);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "../../runtime/runtime.h"
|
#include "../../runtime/runtime.h"
|
||||||
#include "../../runtime/runtime_common.h"
|
#include "../../runtime/runtime_common.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// ------ General ------
|
// ------ General ------
|
||||||
|
|
@ -21,6 +22,7 @@ static const size_t MAX_ARRAY_SIZE = 0x11111110;
|
||||||
// ------ Frame ------
|
// ------ Frame ------
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
|
void *closure; // where closure value stored if needed
|
||||||
void *ret; // store returned value [gc pointer]
|
void *ret; // store returned value [gc pointer]
|
||||||
char *rp; // ret instruction pointer [not gc pointer]
|
char *rp; // ret instruction pointer [not gc pointer]
|
||||||
void **prev_fp; // ret function frame pointer [boxed value, not gc
|
void **prev_fp; // ret function frame pointer [boxed value, not gc
|
||||||
|
|
@ -39,16 +41,18 @@ void **f_args(struct Frame *fp);
|
||||||
// ------ State ------
|
// ------ State ------
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
void **stack;
|
void *stack[STACK_SIZE + 1];
|
||||||
void **sp; // stack pointer
|
void **sp; // stack pointer
|
||||||
struct Frame *fp; // function frame pointer
|
struct Frame *fp; // function frame pointer
|
||||||
bytefile *bf;
|
bytefile *bf;
|
||||||
|
|
||||||
|
bool is_closure_call;
|
||||||
|
|
||||||
char *ip; // instruction pointer
|
char *ip; // instruction pointer
|
||||||
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State init_state(bytefile *bf);
|
void init_state(bytefile *bf, struct State *s);
|
||||||
void cleanup_state(struct State *state);
|
void cleanup_state(struct State *state);
|
||||||
|
|
||||||
// ------ VarCategory ------
|
// ------ VarCategory ------
|
||||||
|
|
@ -57,7 +61,7 @@ enum VarCategory {
|
||||||
VAR_GLOBAL = 0,
|
VAR_GLOBAL = 0,
|
||||||
VAR_LOCAL = 1,
|
VAR_LOCAL = 1,
|
||||||
VAR_ARGUMENT = 2,
|
VAR_ARGUMENT = 2,
|
||||||
VAR_C = 3 // TODO: constants ??
|
VAR_CLOSURE = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VarCategory to_var_category(uint8_t category);
|
enum VarCategory to_var_category(uint8_t category);
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,9 @@ char *ip_read_string(char **ip, bytefile *bf) {
|
||||||
return get_string(bf, ip_read_int(ip));
|
return get_string(bf, ip_read_int(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: store globals in some way ?? // maybe some first vars ??
|
|
||||||
|
|
||||||
void run(bytefile *bf) {
|
void run(bytefile *bf) {
|
||||||
struct State s = init_state(bf);
|
struct State s;
|
||||||
|
init_state(bf, &s);
|
||||||
print_stack(&s);
|
print_stack(&s);
|
||||||
|
|
||||||
printf("--- interpreter run ---\n");
|
printf("--- interpreter run ---\n");
|
||||||
|
|
@ -59,6 +58,7 @@ void run(bytefile *bf) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// char *before_op_ip = s.ip; // save to set s.prev_ip
|
// char *before_op_ip = s.ip; // save to set s.prev_ip
|
||||||
|
bool call_happened = false;
|
||||||
|
|
||||||
char x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
char x = ip_read_byte(&s.ip), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
||||||
|
|
||||||
|
|
@ -93,20 +93,45 @@ void run(bytefile *bf) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: // SEXP %s %d // create sexpr with tag=%s and %d elements from
|
case 2: { // SEXP %s %d // create sexpr with tag=%s and %d elements from
|
||||||
// stack
|
// stack
|
||||||
// params read from stack
|
// params read from stack
|
||||||
s_push_i(&s, LtagHash(ip_read_string(&s.ip, bf)));
|
const char* name = ip_read_string(&s.ip, bf);
|
||||||
Bsexp((aint *)s.sp, ip_read_int(&s.ip)); // TODO: check order
|
aint args_count = ip_read_int(&s.ip);
|
||||||
|
printf("tag hash is %i, n os %i\n", UNBOX(LtagHash((char*)name)), args_count);
|
||||||
|
|
||||||
|
if (args_count < 0) {
|
||||||
|
failure("SEXP: args count should be >= 0");
|
||||||
|
}
|
||||||
|
void ** buffer = calloc(args_count + 1, sizeof(void*));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < args_count; ++i) {
|
||||||
|
buffer[i] = s_pop(&s);
|
||||||
|
}
|
||||||
|
buffer[args_count] = (void*)LtagHash((char*)name);
|
||||||
|
|
||||||
|
// TODO: FIXME: not working with elems
|
||||||
|
void* sexp = Bsexp((aint *)buffer, BOX(args_count + 1));
|
||||||
|
|
||||||
|
push_extra_root(sexp);
|
||||||
|
s_push(&s, sexp);
|
||||||
|
pop_extra_root(sexp);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 3: // STI - write by ref (?)
|
case 3: // STI - write by ref (?)
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: // STA - write to array elem
|
case 4: { // STA - write to array elem
|
||||||
// Bsta // TODO
|
void* elem = s_pop(&s);
|
||||||
|
aint index = s_pop_i(&s);
|
||||||
|
void* data = s_pop(&s);
|
||||||
|
s_push(&s, Bsta(data, index, elem));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 5: { // JMP 0x%.8x
|
case 5: { // JMP 0x%.8x
|
||||||
int jmp_p = ip_read_int(&s.ip); // TODO: check
|
int jmp_p = ip_read_int(&s.ip); // TODO: check
|
||||||
|
|
@ -140,12 +165,7 @@ void run(bytefile *bf) {
|
||||||
|
|
||||||
case 9: // DUP
|
case 9: // DUP
|
||||||
{
|
{
|
||||||
if (s.sp == s.stack + STACK_SIZE ||
|
s_push(&s, *s.sp);
|
||||||
(s.fp != NULL && s.sp == f_locals(s.fp))) {
|
|
||||||
failure("can't DUP: no value on stack");
|
|
||||||
}
|
|
||||||
*s.sp = *(s.sp - 1);
|
|
||||||
++s.sp;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,9 +184,9 @@ void run(bytefile *bf) {
|
||||||
|
|
||||||
case 11: // ELEM
|
case 11: // ELEM
|
||||||
{
|
{
|
||||||
void *array = s_pop(&s);
|
|
||||||
aint index = s_pop_i(&s);
|
aint index = s_pop_i(&s);
|
||||||
s_push(&s, Belem(array, index));
|
void *data = s_pop(&s);
|
||||||
|
s_push(&s, Belem(data, index));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -223,43 +243,62 @@ void run(bytefile *bf) {
|
||||||
case 2: { // BEGIN %d %d // function begin
|
case 2: { // BEGIN %d %d // function begin
|
||||||
int args_sz = ip_read_int(&s.ip);
|
int args_sz = ip_read_int(&s.ip);
|
||||||
int locals_sz = ip_read_int(&s.ip);
|
int locals_sz = ip_read_int(&s.ip);
|
||||||
s_enter_f(&s, s.call_ip /*ip from call*/, args_sz, locals_sz);
|
if (s.fp != NULL && s.call_ip == NULL) {
|
||||||
|
failure("BEGIN: not after call");
|
||||||
|
}
|
||||||
|
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: { // CBEGIN %d %d // TODO: clojure begin ??
|
case 3: { // CBEGIN %d %d // TODO: used ??
|
||||||
int args_sz = ip_read_int(&s.ip);
|
int args_sz = ip_read_int(&s.ip);
|
||||||
int locals_sz = ip_read_int(&s.ip);
|
int locals_sz = ip_read_int(&s.ip);
|
||||||
s_enter_f(&s, s.call_ip /*ip from call*/, args_sz, locals_sz);
|
if (s.fp != NULL && s.call_ip == NULL) {
|
||||||
|
failure("BEGIN: not after call");
|
||||||
|
}
|
||||||
|
s_enter_f(&s, s.call_ip /*ip from call*/, s.is_closure_call, args_sz, locals_sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: // CLOSURE 0x%.8x
|
case 4: // CLOSURE 0x%.8x // TODO: check
|
||||||
// TODO
|
|
||||||
{
|
{
|
||||||
int n = ip_read_int(&s.ip);
|
aint call_offset = ip_read_int(&s.ip);
|
||||||
for (int i = 0; i < n; i++) {
|
aint args_count = ip_read_int(&s.ip);
|
||||||
switch (ip_read_byte(&s.ip)) {
|
for (aint i = 0; i < args_count; i++) {
|
||||||
// case 0: // G(%d)
|
aint arg_type = ip_read_byte(&s.ip);
|
||||||
// case 1: // L(%d)
|
aint arg_id = ip_read_int(&s.ip);
|
||||||
// case 2: // A(%d)
|
|
||||||
// case 3: // C(%d)
|
void **var_ptr =
|
||||||
default:
|
var_by_category(&s, to_var_category(l), ip_read_int(&s.ip));
|
||||||
failure("invalid opcode %d-%d\n", h, l);
|
s_push(&s, *var_ptr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
s_push(&s, bf->code_ptr + call_offset); // TODO: check way of storage ??
|
||||||
|
|
||||||
|
void* closure = Bclosure((aint*)s.sp, args_count);
|
||||||
|
|
||||||
|
push_extra_root(closure);
|
||||||
|
s_popn(&s, args_count + 1);
|
||||||
|
s_push(&s, closure);
|
||||||
|
pop_extra_root(closure);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 5: // CALLC %d // call clojure
|
case 5: // CALLC %d // call clojure
|
||||||
// TODO FIXME: call clojure
|
ip_read_int(&s.ip); // args count
|
||||||
// s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
|
||||||
|
call_happened = true;
|
||||||
|
s.is_closure_call = true;
|
||||||
|
s.call_ip = s.ip;
|
||||||
|
|
||||||
|
s.ip = Belem(s.sp, BOX(0)); // use offset instead ??
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: { // CALL 0x%.8x %d // call function
|
case 6: { // CALL 0x%.8x %d // call function
|
||||||
int call_p = ip_read_int(&s.ip); // TODO: check
|
int call_p = ip_read_int(&s.ip);
|
||||||
ip_read_int(&s.ip);
|
ip_read_int(&s.ip); // args count
|
||||||
|
|
||||||
|
call_happened = true;
|
||||||
|
s.is_closure_call = false;
|
||||||
s.call_ip = s.ip;
|
s.call_ip = s.ip;
|
||||||
|
|
||||||
if (call_p < 0) {
|
if (call_p < 0) {
|
||||||
|
|
@ -269,9 +308,22 @@ void run(bytefile *bf) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 7: // TAG %s
|
case 7: { // TAG %s %d
|
||||||
s_push_i(&s, LtagHash(ip_read_string(&s.ip, bf))); // TODO: check
|
const char* name = ip_read_string(&s.ip, bf);
|
||||||
|
aint args_count = ip_read_int(&s.ip);
|
||||||
|
|
||||||
|
printf("tag hash is %i, n is %i, peek is %i\n", UNBOX(LtagHash((char*)name)), args_count, s_peek(&s));
|
||||||
|
if (UNBOXED(s_peek(&s))) printf("aaaaaaaaaaaaaaaaaaa");
|
||||||
|
else {
|
||||||
|
data* r = TO_DATA(s_peek(&s));
|
||||||
|
if ((aint)BOX(TAG(r->data_header) != SEXP_TAG)) printf("bbbbbbbb %i %i", TAG(r->data_header), SEXP_TAG);
|
||||||
|
if (TO_SEXP(s_peek(&s))->tag != UNBOX(LtagHash((char*)name))) printf("cccccccccc");
|
||||||
|
if (LEN(r->data_header) != UNBOX(args_count)) printf("dddddd %i %i", LEN(r->data_header), UNBOX(args_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
s_push_i(&s, Btag(s_pop(&s), LtagHash((char*)name), args_count));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 8: // ARRAY %d
|
case 8: // ARRAY %d
|
||||||
Barray((aint *)s.sp, ip_read_int(&s.ip));
|
Barray((aint *)s.sp, ip_read_int(&s.ip));
|
||||||
|
|
@ -291,11 +343,11 @@ void run(bytefile *bf) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: // PATT pats[l] // TODO: check
|
case 6: // PATT pats[l]
|
||||||
// {"=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))); // TODO: order
|
s_push_i(&s, Bstring_patt(s_pop(&s), s_pop(&s)));
|
||||||
break;
|
break;
|
||||||
case 1: // #string
|
case 1: // #string
|
||||||
s_push_i(&s, Bstring_tag_patt(s_pop(&s)));
|
s_push_i(&s, Bstring_tag_patt(s_pop(&s)));
|
||||||
|
|
@ -307,10 +359,11 @@ void run(bytefile *bf) {
|
||||||
s_push_i(&s, Bsexp_tag_patt(s_pop(&s)));
|
s_push_i(&s, Bsexp_tag_patt(s_pop(&s)));
|
||||||
break;
|
break;
|
||||||
case 4: // #ref
|
case 4: // #ref
|
||||||
|
s_push_i(&s, Bunboxed_patt(s_pop(&s))); // TODO: check
|
||||||
// TODO
|
// TODO
|
||||||
break;
|
break;
|
||||||
case 5: // #val
|
case 5: // #val
|
||||||
// TODO
|
s_push_i(&s, Bboxed_patt(s_pop(&s))); // TODO: check
|
||||||
break;
|
break;
|
||||||
case 6: // #fun
|
case 6: // #fun
|
||||||
s_push_i(&s, Bclosure_tag_patt(s_pop(&s)));
|
s_push_i(&s, Bclosure_tag_patt(s_pop(&s)));
|
||||||
|
|
@ -359,7 +412,10 @@ void run(bytefile *bf) {
|
||||||
failure("invalid opcode %d-%d\n", h, l);
|
failure("invalid opcode %d-%d\n", h, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
// s.call_ip = before_op_ip;
|
if (!call_happened) {
|
||||||
|
s.is_closure_call = false;
|
||||||
|
s.call_ip = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (s.fp == NULL) {
|
if (s.fp == NULL) {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,34 @@
|
||||||
|
|
||||||
extern size_t __gc_stack_top, __gc_stack_bottom;
|
extern size_t __gc_stack_top, __gc_stack_bottom;
|
||||||
|
|
||||||
|
#define PRE_GC() \
|
||||||
|
bool flag = false; \
|
||||||
|
flag = __gc_stack_top == 0; \
|
||||||
|
if (flag) { __gc_stack_top = (size_t)__builtin_frame_address(0); } \
|
||||||
|
assert(__gc_stack_top != 0); \
|
||||||
|
assert((__gc_stack_top & 0xF) == 0); \
|
||||||
|
assert(__builtin_frame_address(0) <= (void *)__gc_stack_top);
|
||||||
|
|
||||||
|
#define POST_GC() \
|
||||||
|
assert(__builtin_frame_address(0) <= (void *)__gc_stack_top); \
|
||||||
|
if (flag) { __gc_stack_top = 0; }
|
||||||
|
|
||||||
|
// ------
|
||||||
|
|
||||||
|
#define ASSERT_BOXED(memo, x) \
|
||||||
|
do \
|
||||||
|
if (UNBOXED(x)) failure("boxed value expected in %s\n", memo); \
|
||||||
|
while (0)
|
||||||
|
#define ASSERT_UNBOXED(memo, x) \
|
||||||
|
do \
|
||||||
|
if (!UNBOXED(x)) failure("unboxed value expected in %s\n", memo); \
|
||||||
|
while (0)
|
||||||
|
#define ASSERT_STRING(memo, x) \
|
||||||
|
do \
|
||||||
|
if (!UNBOXED(x) && TAG(TO_DATA(x)->data_header) != STRING_TAG) \
|
||||||
|
failure("string value expected in %s\n", memo); \
|
||||||
|
while (0)
|
||||||
|
|
||||||
// ------ basic stack oprs ------
|
// ------ basic stack oprs ------
|
||||||
|
|
||||||
void** s_top(struct State* s) {
|
void** s_top(struct State* s) {
|
||||||
|
|
@ -82,7 +110,7 @@ void s_popn(struct State *s, size_t n) {
|
||||||
|
|
||||||
// ------ functions ------
|
// ------ functions ------
|
||||||
|
|
||||||
void s_enter_f(struct State *s, char *rp, auint args_sz, auint locals_sz) {
|
void s_enter_f(struct State *s, char *rp, bool is_closure_call, auint args_sz, auint locals_sz) {
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -94,11 +122,18 @@ void s_enter_f(struct State *s, char *rp, auint args_sz, auint locals_sz) {
|
||||||
failure("not enough parameters in function stack");
|
failure("not enough parameters in function stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_closure_call) {
|
||||||
|
s_push_nil(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* closure = s_peek(s);
|
||||||
|
|
||||||
// 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(s, frame_sz() - 1);
|
||||||
|
|
||||||
// create frame
|
// create frame
|
||||||
struct Frame frame = {
|
struct Frame frame = {
|
||||||
|
.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,
|
||||||
|
|
@ -149,6 +184,8 @@ void print_stack(struct State* s) {
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- category ---
|
||||||
|
|
||||||
void **var_by_category(struct State *s, enum VarCategory category,
|
void **var_by_category(struct State *s, enum VarCategory category,
|
||||||
int id) {
|
int id) {
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
|
|
@ -169,7 +206,7 @@ void **var_by_category(struct State *s, enum VarCategory category,
|
||||||
if (f_locals_sz(s->fp) <= id) {
|
if (f_locals_sz(s->fp) <= id) {
|
||||||
failure("can't read local: too big id, %i >= %ul", id, f_locals_sz(s->fp));
|
failure("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);
|
// 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);
|
var = f_locals(s->fp) + (f_locals_sz(s->fp) - id - 1);
|
||||||
break;
|
break;
|
||||||
case VAR_ARGUMENT:
|
case VAR_ARGUMENT:
|
||||||
|
|
@ -179,11 +216,26 @@ void **var_by_category(struct State *s, enum VarCategory category,
|
||||||
if (f_args_sz(s->fp) <= id) {
|
if (f_args_sz(s->fp) <= id) {
|
||||||
failure("can't read arguments: too big id, %i >= %ul", id, f_args_sz(s->fp));
|
failure("can't read arguments: too big id, %i >= %ul", id, f_args_sz(s->fp));
|
||||||
}
|
}
|
||||||
printf("id is %i, arg is %i, %i\n", id, UNBOX((auint)*((void**)f_args(s->fp) + id)), f_args(s->fp) - s->sp);
|
var = f_args(s->fp) + (f_args_sz(s->fp) - id - 1);
|
||||||
var = f_args(s->fp) + (f_args_sz(s->fp) - id - 1); // TODO: check if not reversed order
|
break;
|
||||||
|
case VAR_CLOSURE:
|
||||||
|
if (s->fp == NULL) {
|
||||||
|
failure("can't read closure parameter outside of function");
|
||||||
|
}
|
||||||
|
if (s->fp->closure == NULL) {
|
||||||
|
failure("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);
|
||||||
|
size_t count = get_len(d) - 1;
|
||||||
|
printf("id is %i, count is %i\n", id, count);
|
||||||
|
if (count <= id) {
|
||||||
|
failure("can't read arguments: too big id, %i >= %ul", id, count);
|
||||||
|
}
|
||||||
|
// TODO: check if not reversed order
|
||||||
|
return (void **)d->contents + id;
|
||||||
|
// &Belem(s->fp->closure, BOX(id + 1));
|
||||||
break;
|
break;
|
||||||
case VAR_C: // clojure ??
|
|
||||||
// TODO: ??
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,39 +24,36 @@ void **f_args(struct Frame *fp) { return (void **)fp + frame_sz(); }
|
||||||
|
|
||||||
// --- State ---
|
// --- State ---
|
||||||
|
|
||||||
static struct State alloc_state(bytefile *bf) {
|
static void alloc_state(bytefile *bf, struct State* s) {
|
||||||
struct State state = {
|
// s->stack = calloc(STACK_SIZE + 1, sizeof(void*));
|
||||||
.stack = calloc(STACK_SIZE + 1, sizeof(void*)),
|
s->bf = bf;
|
||||||
.ip = bf->code_ptr,
|
s->is_closure_call = false;
|
||||||
.call_ip = NULL,
|
s->ip = bf->code_ptr;
|
||||||
.bf = bf,
|
s->call_ip = NULL;
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < STACK_SIZE; ++i) {
|
for (size_t i = 0; i < STACK_SIZE; ++i) {
|
||||||
state.stack[i] = NULL;
|
s->stack[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.sp = state.stack + STACK_SIZE; // [top -> bottom] stack
|
s->sp = s->stack + STACK_SIZE; // [top -> bottom] stack
|
||||||
print_stack(&state);
|
print_stack(s);
|
||||||
state.fp = NULL;
|
s->fp = NULL;
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State init_state(bytefile *bf) {
|
void init_state(bytefile *bf, struct State* s) {
|
||||||
__init();
|
__init();
|
||||||
struct State state = alloc_state(bf);
|
alloc_state(bf, s);
|
||||||
__gc_stack_bottom = (size_t)state.sp;
|
__gc_stack_bottom = (size_t)s->sp;
|
||||||
// print_stack(&state);
|
// print_stack(s);
|
||||||
|
|
||||||
s_pushn_nil(&state, bf->global_area_size);
|
s_pushn_nil(s, bf->global_area_size);
|
||||||
|
|
||||||
// print_stack(&state);
|
// print_stack(&state);
|
||||||
printf("- state init done\n");
|
printf("- state init done\n");
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destruct_state(struct State* state) {
|
static void destruct_state(struct State* state) {
|
||||||
free(state->stack);
|
// free(state->stack);
|
||||||
|
|
||||||
state->sp = NULL;
|
state->sp = NULL;
|
||||||
state->fp = NULL;
|
state->fp = NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue