mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
some fixes to work with gc and one stack of pointers
This commit is contained in:
parent
d782934f0c
commit
1c85bf553a
4 changed files with 258 additions and 185 deletions
|
|
@ -33,3 +33,51 @@ inline void f_cons(struct State *s) {
|
|||
|
||||
// TODO
|
||||
}
|
||||
|
||||
// TODO
|
||||
inline void f_binop(struct State *s, const char *opr) {
|
||||
size_t len = strlen(opr);
|
||||
|
||||
if (len < 1) {
|
||||
failure("empty operation");
|
||||
}
|
||||
switch (opr[0]) {
|
||||
case '+':
|
||||
break;
|
||||
case '-':
|
||||
break;
|
||||
case '*':
|
||||
break;
|
||||
case '/':
|
||||
break;
|
||||
case '%':
|
||||
break;
|
||||
case '<':
|
||||
if (len == 1) { // <
|
||||
|
||||
} else { // <=
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (len == 1) { // >
|
||||
|
||||
} else { // >=
|
||||
}
|
||||
break;
|
||||
case '=': // ==
|
||||
break;
|
||||
case '!':
|
||||
if (len == 1) {
|
||||
failure("'!...' opr len is 1");
|
||||
}
|
||||
if (opr[1] == '=') { // !=
|
||||
|
||||
} else { // !!
|
||||
}
|
||||
break;
|
||||
case '&': // &&
|
||||
break;
|
||||
default:
|
||||
failure("unknown operation");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../runtime/gc.h"
|
||||
#include "../../runtime/runtime.h"
|
||||
#include "types.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
// TODO: use gc
|
||||
#include "stdlib.h"
|
||||
|
||||
// ------ general ------
|
||||
|
||||
// TODO: use gc
|
||||
inline void free_var_ptr(union VarT *var);
|
||||
|
||||
inline void free_var(union VarT var) {
|
||||
|
|
@ -36,12 +34,12 @@ inline void free_var(union VarT var) {
|
|||
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);
|
||||
// free(var.array.values); // FIXME
|
||||
break;
|
||||
case SEXP_T:
|
||||
// tag is const string, no need to free
|
||||
if (var.sexp.next != NULL) {
|
||||
free(var.sexp.next);
|
||||
// free(var.sexp.next); // FIXME
|
||||
}
|
||||
break;
|
||||
case FUN_T:
|
||||
|
|
@ -52,77 +50,32 @@ inline void free_var(union VarT var) {
|
|||
// TODO: use gc
|
||||
inline void free_var_ptr(union VarT *var) {
|
||||
free_var(*var);
|
||||
free((void *)var);
|
||||
// free((void *)var); // FIXME
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
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;
|
||||
// }
|
||||
inline struct NilT clear_var() { return NilT{.data_header = NIL_T}; }
|
||||
|
||||
// ------ put on stack ---
|
||||
|
||||
inline void s_put_ptr(struct State *s, char *val) { // any var
|
||||
*s->vp = (NilT *)val;
|
||||
++s->vp;
|
||||
}
|
||||
|
||||
inline void s_put_var_ptr(struct State *s, struct NilT **val) { // any var
|
||||
*s->vp = (NilT *)val;
|
||||
++s->vp;
|
||||
}
|
||||
|
||||
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();
|
||||
struct NilT *var = (NilT *)alloc(sizeof(NilT));
|
||||
var->data_header = NIL_T; // no param
|
||||
s_put_var(s, var);
|
||||
}
|
||||
|
|
@ -134,42 +87,52 @@ inline void s_putn_nil(struct State *s, size_t n) {
|
|||
}
|
||||
|
||||
inline void s_put_i(struct State *s, int val) {
|
||||
struct IntT *var = alloc();
|
||||
struct IntT *var = (IntT *)alloc(sizeof(IntT));
|
||||
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();
|
||||
inline void s_put_const_str(struct State *s, const char *val) {
|
||||
struct ConstStrT *var = (ConstStrT *)alloc(sizeof(ConstStrT));
|
||||
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();
|
||||
inline void s_put_str(struct State *s, char *val) {
|
||||
struct StrT *var = (StrT *)alloc(sizeof(StrT));
|
||||
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_enum(struct State *s, const char *tag, int args_sz) {
|
||||
// TODO FIXME
|
||||
}
|
||||
|
||||
inline void s_put_list(struct State *s,
|
||||
struct NilT *first_elem) { // memory controlled by var
|
||||
struct ListT *var;
|
||||
inline void s_put_array(struct State *s, int sz) {
|
||||
struct ArrayT *var = (ArrayT *)alloc(sizeof(ArrayT));
|
||||
|
||||
if (sz < 0) {
|
||||
failure("array size < 0");
|
||||
}
|
||||
|
||||
if (sz > MAX_ARRAY_SIZE) {
|
||||
failure("too big array size");
|
||||
}
|
||||
|
||||
var->data_header = sz & ARRAY_T;
|
||||
var->values = (NilT **)alloc(sizeof(NilT *) * sz);
|
||||
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
var->values[i] = NULL;
|
||||
}
|
||||
s_put_var(s, (NilT *)var);
|
||||
}
|
||||
|
||||
inline void s_put_list(struct State *s, struct NilT *first_elem) {
|
||||
struct ListT *var = (ListT *)alloc(sizeof(ListT));
|
||||
var->data_header = LIST_T; // no param
|
||||
var->value = first_elem;
|
||||
var->next = NULL;
|
||||
|
|
@ -182,12 +145,12 @@ inline void s_put_list(struct State *s,
|
|||
// ------ take from stack ------
|
||||
|
||||
inline union VarT *s_take_var(struct State *s) {
|
||||
if (s->vp == s->fp->end) {
|
||||
if (s->vp == s->stack || (s->fp != NULL && s->vp == s->fp->end)) {
|
||||
failure("take: no var");
|
||||
}
|
||||
--s->vp;
|
||||
|
||||
union VarT *ret = *s->vp;
|
||||
union VarT *ret = (VarT *)*s->vp;
|
||||
*s->vp = NULL; // clear top var
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -201,11 +164,11 @@ inline int s_take_i(struct State *s) {
|
|||
}
|
||||
|
||||
inline void s_drop_var(struct State *s) {
|
||||
if (s->vp == s->fp->end) {
|
||||
if (s->vp == s->stack || (s->fp != NULL && s->vp == s->fp->end)) {
|
||||
failure("drop: no var");
|
||||
}
|
||||
--s->vp;
|
||||
free_var_ptr(*s->vp);
|
||||
free_var_ptr((VarT *)*s->vp);
|
||||
*s->vp = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -217,39 +180,63 @@ inline void s_dropn_var(struct State *s, size_t n) {
|
|||
|
||||
// ------ 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
|
||||
// |> param_0 ... param_n | frame[ ret rp prev_fp ¶ms &locals &end ]
|
||||
// |> local_0 ... local_m |> | ...
|
||||
//
|
||||
// where |> defines corresponding frame pointer, | is stack pointer location
|
||||
// before / after new frame added
|
||||
inline void s_enter_f(struct State *s, char *func_ip, size_t params_sz,
|
||||
size_t locals_sz) {
|
||||
if (params_sz > s->vp - s->stack or
|
||||
(s->fp != NULL and params_sz > s->vp - s->fp->end)) {
|
||||
failure("not enough parameters in stack");
|
||||
}
|
||||
size_t frame_sz_in_ptr = sizeof(Frame) / sizeof(void *);
|
||||
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, // ??
|
||||
.ret = NULL, // field in frame itself
|
||||
.rp = s->ip,
|
||||
.prev_fp = s->fp,
|
||||
.params = s->vp - params_sz,
|
||||
.locals = s->vp + frame_sz_in_ptr,
|
||||
.end = s->vp + frame_sz_in_ptr + locals_sz,
|
||||
};
|
||||
|
||||
// TODO:
|
||||
s_put_nil(s); // ret
|
||||
s_putn_nil(s, locals_sz); // locals
|
||||
s->ip = func_ip;
|
||||
// put frame on stack
|
||||
s->fp = (Frame *)s->vp;
|
||||
(*s->fp) = frame;
|
||||
++s->fp;
|
||||
|
||||
// update stack pointer
|
||||
s->vp = frame.end;
|
||||
|
||||
// go to function body
|
||||
s->ip = func_ip;
|
||||
}
|
||||
|
||||
inline void s_exit_f(struct State *s) {
|
||||
if (s->fp == NULL) {
|
||||
failure("exit: no func");
|
||||
}
|
||||
|
||||
// drop stack entities and locals
|
||||
s_dropn_var(s, s->vp - s->fp->locals);
|
||||
|
||||
// drop params
|
||||
s->vp = (void **)s->fp;
|
||||
s_dropn_var(s, s->vp - s->fp->params);
|
||||
|
||||
// s->vp = s->fp->params; // done automatically
|
||||
|
||||
// save ret_val;
|
||||
if (s->fp->ret != NULL) {
|
||||
(*s->vp) = s->fp->ret;
|
||||
++s->vp;
|
||||
}
|
||||
|
||||
s->ip = s->fp->rp;
|
||||
s->fp = s->fp->prev_fp;
|
||||
}
|
||||
|
||||
inline union VarT *var_by_category(struct State *s, enum VarCategory category,
|
||||
int id) {
|
||||
// TODO: FIXME
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../runtime/runtime.h"
|
||||
#include "parser.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -18,43 +19,44 @@ enum Type {
|
|||
};
|
||||
|
||||
struct NilT { // AnyVarT too
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
};
|
||||
|
||||
struct IntT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
int32_t value; // int value => size = 1;
|
||||
};
|
||||
|
||||
struct ConstStrT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
struct StrT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct ListT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
struct NilT *value;
|
||||
struct NilT *next;
|
||||
};
|
||||
|
||||
struct ArrayT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
struct NilT **values;
|
||||
};
|
||||
const size_t MAX_ARRAY_SIZE = 0x11111110;
|
||||
|
||||
struct SExpT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
const char *tag;
|
||||
struct NilT *next;
|
||||
};
|
||||
|
||||
struct FunT {
|
||||
int32_t data_header;
|
||||
uint32_t data_header;
|
||||
char *fun_ip;
|
||||
};
|
||||
|
||||
|
|
@ -82,11 +84,12 @@ inline union VarT *to_var(struct NilT *var) { return (union VarT *)var; }
|
|||
// ------ Frame ------
|
||||
|
||||
struct Frame {
|
||||
char *rp; // ret instruction pointer
|
||||
struct NilT **ret; // store returned value
|
||||
struct NilT **params; // store arguments
|
||||
struct NilT **locals; // store locals
|
||||
struct NilT **end; // store locals
|
||||
struct NilT *ret; // store returned value
|
||||
char *rp; // ret instruction pointer
|
||||
struct Frame *prev_fp; // ret function frame pointer
|
||||
void **params; // store arguments
|
||||
void **locals; // store locals
|
||||
void **end; // store locals
|
||||
};
|
||||
|
||||
inline uint64_t frame_locals_sz(struct Frame *frame) {
|
||||
|
|
@ -101,16 +104,16 @@ inline uint64_t frame_params_sz(struct Frame *frame) {
|
|||
union StackValue {
|
||||
union VarT *var;
|
||||
union VarT **var_ptr;
|
||||
// struct Frame frame; // TODO
|
||||
struct Frame frame; // ??
|
||||
char *addr;
|
||||
};
|
||||
|
||||
// inline StackValue *to_sv(void *var) { return (StackValue *)var; }
|
||||
|
||||
struct State {
|
||||
union StackValue *stack; // vaid**
|
||||
struct NilT **vp; // var pointer
|
||||
struct Frame *fp; // function frame pointer
|
||||
void **stack; // vaid**
|
||||
void **vp; // stack pointer
|
||||
struct Frame *fp; // function frame pointer
|
||||
|
||||
char *ip; // instruction pointer
|
||||
char *prev_ip; // prev instruction pointer
|
||||
|
|
@ -118,3 +121,19 @@ struct State {
|
|||
|
||||
struct State init_state(bytefile *bf);
|
||||
void destruct_state(struct State *state);
|
||||
|
||||
// ------ VarCategory ------
|
||||
|
||||
enum VarCategory {
|
||||
VAR_GLOBAL = 0,
|
||||
VAR_LOCAL = 1,
|
||||
VAR_A = 2, // TODO: ??
|
||||
VAR_C = 3 // TODO: ??
|
||||
};
|
||||
|
||||
inline enum VarCategory to_var_category(uint8_t category) {
|
||||
if (category > 3) {
|
||||
failure("unexpected variable category");
|
||||
}
|
||||
return (VarCategory)category;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include "../include/interpreter.h"
|
||||
#include "../include/types.h"
|
||||
#include "../include/builtin.h"
|
||||
#include "../include/operations.h"
|
||||
#include "../../runtime/runtime.h"
|
||||
#include "../../runtime/gc.h"
|
||||
|
||||
int ip_read_int(char** ip) {
|
||||
*ip += sizeof(int);
|
||||
|
|
@ -20,9 +23,11 @@ char* ip_read_string(char** ip, bytefile* bf) {
|
|||
void run(bytefile *bf) {
|
||||
struct State s = init_state(bf);
|
||||
|
||||
const size_t OPS_SIZE = 13;
|
||||
const char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
||||
|
||||
const size_t PATS_SIZE = 7;
|
||||
const char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
||||
const char *lds [] = {"LD", "LDA", "ST"};
|
||||
do {
|
||||
char* before_op_ip = s.ip; // save to set s.prev_ip
|
||||
|
||||
|
|
@ -38,7 +43,13 @@ void run(bytefile *bf) {
|
|||
|
||||
/* BINOP */
|
||||
case 0: // BINOP ops[l-1]
|
||||
// TODO: all binops
|
||||
if (l > OPS_SIZE) {
|
||||
failure("BINOP: l > OPS_SIZE");
|
||||
}
|
||||
if (l < 1) {
|
||||
failure("BINOP: l < 1");
|
||||
}
|
||||
f_binop(&s, ops[l-1]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
|
@ -51,8 +62,9 @@ void run(bytefile *bf) {
|
|||
s_put_const_str(&s, ip_read_string(&s.ip, bf));
|
||||
break;
|
||||
|
||||
case 2: // SEXP %s %d
|
||||
// TODO: call sexp ??
|
||||
case 2: // SEXP %s %d // create sexpr with tag=%s and %d elements from stack
|
||||
// TODO: params??
|
||||
s_put_sexp(&s, ip_read_string(&s.ip, bf), ip_read_int(&s.ip));
|
||||
break;
|
||||
|
||||
case 3: // STI
|
||||
|
|
@ -81,14 +93,17 @@ void run(bytefile *bf) {
|
|||
|
||||
case 9: // DUP
|
||||
{ // guess
|
||||
struct Var v = deep_copy_var(*s.vp);
|
||||
s_put_var(&s, v);
|
||||
if (s.vp == s.stack || (s.fp != NULL && s.vp == s.fp->end)) {
|
||||
failure("can't DUP: no value on stack");
|
||||
}
|
||||
*s.vp = *(s.vp - 1);
|
||||
++s.vp;
|
||||
break;
|
||||
}
|
||||
|
||||
case 10: // SWAP
|
||||
{ // guess
|
||||
struct Var v = *s.vp;
|
||||
struct NilT* v = *s.vp;
|
||||
*s.vp = *(s.vp - 1);
|
||||
*(s.vp - 1) = v;
|
||||
}
|
||||
|
|
@ -96,67 +111,74 @@ void run(bytefile *bf) {
|
|||
|
||||
case 11: // ELEM
|
||||
{
|
||||
struct Var array = s_take_var(&s);
|
||||
struct Var index = s_take_var(&s);
|
||||
if (array.type != ARRAY_T) {
|
||||
failure("ERROR: elem, previous element is not array", h, l);
|
||||
union VarT* array = s_take_var(&s);
|
||||
union VarT* index = s_take_var(&s);
|
||||
if (dh_type(array->nil.data_header) != ARRAY_T) {
|
||||
failure("ELEM: elem, previous element is not array");
|
||||
}
|
||||
if (index.type != INT_T) {
|
||||
failure("ERROR: elem, last element is not int", h, l);
|
||||
if (dh_type(index->nil.data_header) != INT_T) {
|
||||
failure("ELEM: elem, last element is not int");
|
||||
}
|
||||
s_put_var(&s, array.value.array_v[index.value.int_v]);
|
||||
if (index->int_t.value < 0) {
|
||||
failure("ELEM: can't access by index < 0");
|
||||
}
|
||||
if (index->int_t.value >= dh_param(array->array.data_header)) {
|
||||
failure("ELEM: array index is out of range");
|
||||
}
|
||||
s_put_var(&s, array->array.values[index->int_t.value]);
|
||||
|
||||
free_var(array);
|
||||
free_var(index);
|
||||
// FIXME: deal vith deletion of shallow copies of locals
|
||||
free_var_ptr(array);
|
||||
free_var_ptr(index);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
// fprintf (f, "%s\t", lds[h-2]);
|
||||
switch (l) {
|
||||
// case 0: fprintf (f, "G(%d)", INT); break;
|
||||
// case 1: fprintf (f, "L(%d)", INT); break;
|
||||
// case 2: fprintf (f, "A(%d)", INT); break;
|
||||
// case 3: fprintf (f, "C(%d)", INT); break;
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
case 2: { // LD %d
|
||||
int8_t category = ip_read_byte(&s.ip);
|
||||
union VarT* var = var_by_category(&s, to_var_category(category), ip_read_int(&s.ip));
|
||||
// TODO
|
||||
break;
|
||||
|
||||
}
|
||||
case 3: { // LDA %d
|
||||
int8_t category = ip_read_byte(&s.ip);
|
||||
union VarT* var = var_by_category(&s, to_var_category(category), ip_read_int(&s.ip));
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
case 4: { // ST %d
|
||||
int8_t category = ip_read_byte(&s.ip);
|
||||
union VarT* var = var_by_category(&s, to_var_category(category), ip_read_int(&s.ip));
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
switch (l) {
|
||||
case 0: { // CJMPz 0x%.8x
|
||||
// FIXME: TODO: jump by top stack condition ??
|
||||
char* new_ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
||||
if (s_take_i(&s) != 0) { // FIXME: bools ??, other vars ??
|
||||
if (s_take_i(&s) != 0) {
|
||||
s.ip = new_ip;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { // CJMPnz 0x%.8x
|
||||
// FIXME: TODO: jump by top stack condition ??i
|
||||
// FIXME: TODO: jump by top stack condition ??
|
||||
char* new_ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
||||
if (s_take_i(&s) == 0) { // FIXME: bools ??, other vars ??
|
||||
if (s_take_i(&s) == 0) {
|
||||
s.ip = new_ip;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: // BEGIN %d %d
|
||||
case 2: // BEGIN %d %d // function begin
|
||||
s_enter_f(&s, s.prev_ip/*ip from call*/, ip_read_int(&s.ip), ip_read_int(&s.ip));
|
||||
// TODO: is func enter ?
|
||||
break;
|
||||
|
||||
case 3: // CBEGIN %d %d
|
||||
case 3: // CBEGIN %d %d // TODO: clojure begin ??
|
||||
s_enter_f(&s, s.prev_ip/*ip from call*/, ip_read_int(&s.ip), ip_read_int(&s.ip));
|
||||
// TODO: is func enter ?
|
||||
break;
|
||||
|
||||
case 4: // CLOSURE 0x%.8x
|
||||
|
|
@ -169,21 +191,19 @@ void run(bytefile *bf) {
|
|||
// case 2: // A(%d)
|
||||
// case 3: // C(%d)
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
|
||||
case 5: // CALLC %d
|
||||
// TODO: no arguments given ??
|
||||
// TODO: jump only ??
|
||||
s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
||||
case 5: // CALLC %d // call clojure
|
||||
// TODO FIXME: call clojure
|
||||
// s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
||||
break;
|
||||
|
||||
case 6: // CALL 0x%.8x %d
|
||||
// TODO: second arg is given params amount ??
|
||||
// TODO: jump only ??
|
||||
case 6: // CALL 0x%.8x %d // call function
|
||||
// FIXME: second arg ??
|
||||
s.ip = (char*)(long)ip_read_int(&s.ip); // TODO: check
|
||||
break;
|
||||
|
||||
|
|
@ -196,8 +216,7 @@ void run(bytefile *bf) {
|
|||
break;
|
||||
|
||||
case 9: // FAIL %d %d
|
||||
// TODO: ??
|
||||
failure("FAIL: %d-%d\n", ip_read_int(&s.ip), ip_read_int(&s.ip));
|
||||
failure("[FAIL]: %d-%d\n", ip_read_int(&s.ip), ip_read_int(&s.ip));
|
||||
break;
|
||||
|
||||
case 10: // LINE %d
|
||||
|
|
@ -205,7 +224,7 @@ void run(bytefile *bf) {
|
|||
break;
|
||||
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -236,18 +255,18 @@ void run(bytefile *bf) {
|
|||
break;
|
||||
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
failure("ERROR: invalid opcode %d-%d\n", h, l);
|
||||
failure("invalid opcode %d-%d\n", h, l);
|
||||
}
|
||||
|
||||
s.prev_ip = before_op_ip;
|
||||
}
|
||||
while (1);
|
||||
stop:;
|
||||
free_state(&s);
|
||||
destruct_state(&s);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue