lama_byterun/byterun/include/operations.h

256 lines
5.7 KiB
C
Raw Normal View History

2024-10-20 16:42:57 +03:00
#pragma once
#include "../../runtime/runtime.h"
#include "types.h"
#include <cstdlib>
// TODO: use gc
// ------ general ------
// TODO: use gc
inline void free_var_ptr(union VarT *var);
inline void free_var(union VarT var) {
switch (dh_type(var.nil.data_header)) {
case NIL_T:
break;
case INT_T:
break;
case CONST_STR_T:
break;
case STR_T:
free(var.str.value);
break;
case LIST_T:
if (var.list.value != NULL) {
free_var_ptr(to_var(var.list.value));
}
if (var.list.next != NULL) {
free_var_ptr(to_var(var.list.next));
}
break;
case ARRAY_T:
// dh param is size
for (size_t i = 0; i < dh_param(var.array.data_header); ++i) {
free_var_ptr(to_var(var.array.values[i]));
}
free(var.array.values);
break;
case SEXP_T:
// tag is const string, no need to free
if (var.sexp.next != NULL) {
free(var.sexp.next);
}
break;
case FUN_T:
break;
}
}
// TODO: use gc
inline void free_var_ptr(union VarT *var) {
free_var(*var);
free((void *)var);
}
//
inline NilT clear_var() { return NilT{.data_header = NIL_T}; }
// usually not required, because frame is located on shared stack
inline struct Frame clear_frame() {
struct Frame frame = {
.ret_ip = NULL,
.rp = NULL,
.ret = NULL,
.params = NULL,
.locals = NULL,
.end = NULL,
};
return frame;
}
// TODO: not required ??
// inline struct Var deep_copy_var(struct Var var) {
// switch (var.type) {
// case INT_T:
// break;
// case CONST_STR_T:
// break;
// case STR_T: {
// char *old_str = var.value.str_v;
// var.value.str_v = calloc(var.size + 1, sizeof(char));
// strcpy(var.value.str_v, old_str);
// break;
// }
// case LIST_T:
// if (var.value.list_v.elem != NULL) {
// struct Var *old_elem = var.value.list_v.elem;
// var.value.list_v.elem = calloc(1, sizeof(struct Var));
// *var.value.list_v.elem = deep_copy_var(*old_elem);
// }
// if (var.value.list_v.next != NULL) {
// struct Var *old_next = var.value.list_v.next;
// var.value.list_v.next = calloc(1, sizeof(struct Var));
// *var.value.list_v.next = deep_copy_var(*old_next);
// }
// break;
// case ARRAY_T: {
// struct Var *old_array = var.value.array_v;
// var.value.array_v = calloc(var.size, sizeof(char));
// for (size_t i = 0; i < var.size; ++i) {
// var.value.array_v[i] = deep_copy_var(*(old_array + i));
// }
// break;
// }
// case FUN_T:
// break;
// case NIL_T:
// break;
// }
// return var;
// }
// ------ put on stack ---
inline void s_put_var(struct State *s, struct NilT *val) { // any var
*s->vp = val;
++s->vp;
}
inline void s_put_nil(struct State *s) {
struct NilT *var = alloc();
var->data_header = NIL_T; // no param
s_put_var(s, var);
}
inline void s_putn_nil(struct State *s, size_t n) {
for (size_t i = 0; i < n; ++i) {
s_put_nil(s);
}
}
inline void s_put_i(struct State *s, int val) {
struct IntT *var = alloc();
var->data_header = INT_T; // no param
var->value = val;
s_put_var(s, (NilT *)var);
}
inline void s_put_const_str(struct State *s,
const char *val) { // memory controlled externally
struct ConstStrT *var = alloc();
var->data_header = CONST_STR_T; // no param
var->value = val;
s_put_var(s, (NilT *)var);
}
inline void s_put_str(struct State *s, char *val) { // memory controlled by var
struct StrT *var = alloc();
var->data_header = STR_T; // no param
var->value = val;
s_put_var(s, (NilT *)var);
}
// TODO
inline void s_put_array(struct State *s, int sz) { // memory controlled by var
struct Var var = {
.type = ARRAY_T,
.value.array_v = calloc(sz, sizeof(struct Var)),
.size = sz,
};
s_put_var(s, var);
// fill array with nils ?
}
inline void s_put_list(struct State *s,
struct NilT *first_elem) { // memory controlled by var
struct ListT *var;
var->data_header = LIST_T; // no param
var->value = first_elem;
var->next = NULL;
s_put_var(s, (NilT *)var);
*first_elem = clear_var();
}
// ------ take from stack ------
inline union VarT *s_take_var(struct State *s) {
if (s->vp == s->fp->end) {
failure("take: no var");
}
--s->vp;
union VarT *ret = *s->vp;
*s->vp = NULL; // clear top var
return ret;
}
inline int s_take_i(struct State *s) {
union VarT *v = s_take_var(s);
if (dh_type(v->nil.data_header) != INT_T) {
failure("take int: not int");
}
return v->int_t.value;
}
inline void s_drop_var(struct State *s) {
if (s->vp == s->fp->end) {
failure("drop: no var");
}
--s->vp;
free_var_ptr(*s->vp);
*s->vp = NULL;
}
inline void s_dropn_var(struct State *s, size_t n) {
for (size_t i = 0; i < n; ++i) {
s_drop_var(s);
}
}
// ------ functions ------
// TODO
inline void s_exit_f(struct State *s) {
if (s->fp == (void *)s->stack) {
failure("exit: no func");
}
--s->fp;
s_dropn_var(s, s->vp - s->fp->locals);
// drop local var stack and locals // TODO: check +-1
union VarT *ret = *s->vp;
--s->vp;
s_dropn_var(s, s->vp - s->fp->params);
// drop params // TODO: check +-1
s_put_var(s, ret);
s->ip = s->fp->rp;
// *s->fp = clear_frame(); // clear top frame
}
// TODO
inline void s_enter_f(struct State *s, char *func_ip, size_t params_sz,
size_t locals_sz) {
struct Frame frame = {
.rp = s->ip, // ??
.ret = s->vp,
.params = s->vp - params_sz, // TODO: check +-1
.locals = s->vp + 1,
.end = s->vp + locals_sz + 1, // ??
};
// TODO:
s_put_nil(s); // ret
s_putn_nil(s, locals_sz); // locals
s->ip = func_ip;
(*s->fp) = frame;
++s->fp;
}