mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-13 02:08:45 +00:00
part of multimodule execution impl in interpreter: frame extension, state exstension, call and return
This commit is contained in:
parent
0a26953318
commit
59f3dfb43e
9 changed files with 108 additions and 59 deletions
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
#include "parser.h"
|
||||
|
||||
void run(bytefile *bf, int argc, char **argv);
|
||||
void run(uint mod_id, int argc, char **argv);
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
#include "utils.h"
|
||||
|
||||
struct ModSearchResult {
|
||||
ssize_t symbol_offset; // < 0 => not found
|
||||
size_t symbol_offset;
|
||||
uint32_t mod_id;
|
||||
bytefile *mod_file;
|
||||
bytefile *mod_file; // = NULL => not found
|
||||
};
|
||||
|
||||
void mod_add_search_path(const char *path);
|
||||
|
|
@ -16,4 +16,6 @@ bytefile *mod_get(uint32_t id);
|
|||
|
||||
int32_t mod_load(const char *name); // < 0 => not found
|
||||
|
||||
uint32_t mod_add(bytefile *module);
|
||||
|
||||
struct ModSearchResult mod_search_pub_symbol(const char *name);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../runtime/gc.h"
|
||||
#include "module_manager.h"
|
||||
#include "runtime_externs.h"
|
||||
#include "types.h"
|
||||
#include "utils.h"
|
||||
|
|
@ -134,14 +135,14 @@ static inline void s_rotate_n(size_t n) {
|
|||
|
||||
// ------ functions ------
|
||||
|
||||
// |> param_0 ... param_n | frame[ ret rp prev_fp ¶ms &locals &end
|
||||
// |> 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
|
||||
static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz,
|
||||
auint locals_sz) {
|
||||
static inline void s_enter_f(char *rp, aint ret_module_id, bool is_closure_call,
|
||||
auint args_sz, auint locals_sz) {
|
||||
#ifdef DEBUG_VERSION
|
||||
printf("-> %i args sz\n", args_sz);
|
||||
printf("-> %i locals sz\n", locals_sz);
|
||||
|
|
@ -169,6 +170,7 @@ static inline void s_enter_f(char *rp, bool is_closure_call, auint args_sz,
|
|||
.ret = NULL, // field in frame itself
|
||||
.rp = rp,
|
||||
.prev_fp = (void **)s.fp,
|
||||
.ret_module_box = BOX(ret_module_id),
|
||||
.args_sz_box = BOX(args_sz),
|
||||
.locals_sz_box = BOX(locals_sz),
|
||||
};
|
||||
|
|
@ -207,6 +209,10 @@ static inline void s_exit_f() {
|
|||
}
|
||||
|
||||
s.ip = frame.rp;
|
||||
|
||||
s.current_module_id = UNBOX(frame.ret_module_box);
|
||||
s.bf = mod_get(s.current_module_id);
|
||||
// TODO: return to ret_module
|
||||
}
|
||||
|
||||
static inline void print_stack() {
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@ static const size_t MAX_ARRAY_SIZE = 0x11111110;
|
|||
// ------ Frame ------
|
||||
|
||||
struct Frame {
|
||||
void *closure; // where closure value stored if needed
|
||||
void *ret; // store returned value [gc pointer]
|
||||
char *rp; // ret instruction pointer [not gc pointer]
|
||||
void **prev_fp; // ret function frame pointer [boxed value, not gc
|
||||
// pointer]
|
||||
aint args_sz_box; // store arguments [boxed value, not gc pointer]
|
||||
aint locals_sz_box; // store locals [boxed value, not gc pointer]
|
||||
void *closure; // where closure value stored if needed
|
||||
void *ret; // store returned value [gc pointer]
|
||||
char *rp; // ret instruction pointer [not gc pointer]
|
||||
void **prev_fp; // ret function frame pointer [boxed value, not gc
|
||||
// pointer]
|
||||
aint ret_module_box; // module to return [boxed value, not gc pointer]
|
||||
aint args_sz_box; // store arguments [boxed value, not gc pointer]
|
||||
aint locals_sz_box; // store locals [boxed value, not gc pointer]
|
||||
};
|
||||
|
||||
// NOTE: stack is [top -> bottom]
|
||||
|
|
@ -60,14 +61,18 @@ struct State {
|
|||
|
||||
bool is_closure_call;
|
||||
|
||||
uint current_module_id;
|
||||
uint call_module_id;
|
||||
|
||||
char *ip; // instruction pointer
|
||||
char *instr_ip; // poiter to current instruction
|
||||
char *call_ip; // prev instruction pointer (to remember jmp locations)
|
||||
};
|
||||
|
||||
void construct_state(bytefile *bf, struct State *s, void **stack);
|
||||
void construct_state(uint mod_id, struct State *s, void **stack);
|
||||
void cleanup_state(struct State *state);
|
||||
|
||||
// TODO: print current mod id
|
||||
static inline 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);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "interpreter.h"
|
||||
#include "module_manager.h"
|
||||
#include "parser.h"
|
||||
#include "utils.h"
|
||||
#include "../../runtime/runtime.h"
|
||||
|
|
@ -9,15 +10,15 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
bytefile *f = read_file(argv[2]);
|
||||
uint main_mod_id = mod_add(f);
|
||||
if (strcmp(argv[1], "-i") == 0) {
|
||||
run(f, argc - 1, argv + 1);
|
||||
run(main_mod_id, argc - 1, argv + 1); // TODO: init all modules, execute all prev. modules
|
||||
} else if (strcmp(argv[1], "-p") == 0) {
|
||||
dump_file (stdout, f);
|
||||
} else {
|
||||
failure("undefined execution mode. Execution mode should be -i (interpret) or -p (print)\n");
|
||||
}
|
||||
|
||||
free(f->global_ptr);
|
||||
free(f);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "../../runtime/gc.h"
|
||||
#include "../../runtime/runtime.h"
|
||||
|
||||
#include "module_manager.h"
|
||||
#include "runtime_externs.h"
|
||||
#include "stack.h"
|
||||
#include "types.h"
|
||||
|
|
@ -37,10 +38,17 @@ static inline const char *ip_read_string(char **ip) {
|
|||
|
||||
const size_t BUFFER_SIZE = 1000;
|
||||
|
||||
void run(bytefile *bf, int argc, char **argv) {
|
||||
void init_stack(int argc, char **argv) {} // TODO
|
||||
|
||||
void init_mod_rec(uint mod_id) {} // TODO
|
||||
|
||||
void run(uint mod_id, int argc, char **argv) { // TODO: remove mod init and stack init
|
||||
size_t stack[STACK_SIZE];
|
||||
void *buffer[BUFFER_SIZE];
|
||||
construct_state(bf, &s, (void **)stack);
|
||||
construct_state(
|
||||
mod_id, &s,
|
||||
(void **)
|
||||
stack); // TODO: separate on each module part and part for all run
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
printf("--- interpreter run ---\n");
|
||||
|
|
@ -65,11 +73,11 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
do {
|
||||
bool call_happened = false;
|
||||
|
||||
if (s.ip >= bf->code_ptr + bf->code_size) {
|
||||
if (s.ip >= s.bf->code_ptr + s.bf->code_size) {
|
||||
s_failure(&s, "instruction pointer is out of range (>= size)");
|
||||
}
|
||||
|
||||
if (s.ip < bf->code_ptr) {
|
||||
if (s.ip < s.bf->code_ptr) {
|
||||
s_failure(&s, "instruction pointer is out of range (< 0)");
|
||||
}
|
||||
|
||||
|
|
@ -171,10 +179,10 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
case CMD_BASIC_JMP: { // JMP 0x%.8x
|
||||
uint jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p >= bf->code_size) {
|
||||
if (jmp_p >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
s.ip = s.bf->code_ptr + jmp_p;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -246,11 +254,11 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
case CMD_CTRL_CJMPz: { // CJMPz 0x%.8x
|
||||
uint jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p >= bf->code_size) {
|
||||
if (jmp_p >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
if (UNBOX(s_pop_i()) == 0) {
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
s.ip = s.bf->code_ptr + jmp_p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -258,11 +266,11 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
case CMD_CTRL_CJMPnz: { // CJMPnz 0x%.8x
|
||||
uint jmp_p = ip_read_int(&s.ip);
|
||||
|
||||
if (jmp_p >= bf->code_size) {
|
||||
if (jmp_p >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
if (UNBOX(s_pop_i()) != 0) {
|
||||
s.ip = bf->code_ptr + jmp_p;
|
||||
s.ip = s.bf->code_ptr + jmp_p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -273,8 +281,8 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
if (s.fp != NULL && s.call_ip == NULL) {
|
||||
s_failure(&s, "begin should only be called after call");
|
||||
}
|
||||
s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||
locals_sz);
|
||||
s_enter_f(s.call_ip /*ip from call*/, s.call_module_id,
|
||||
s.is_closure_call, args_sz, locals_sz);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -285,8 +293,8 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
if (s.fp != NULL && s.call_ip == NULL) {
|
||||
s_failure(&s, "begin should only be called after call");
|
||||
}
|
||||
s_enter_f(s.call_ip /*ip from call*/, s.is_closure_call, args_sz,
|
||||
locals_sz);
|
||||
s_enter_f(s.call_ip /*ip from call*/, s.call_module_id,
|
||||
s.is_closure_call, args_sz, locals_sz);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -302,10 +310,10 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
var_by_category(to_var_category(l), ip_read_int(&s.ip));
|
||||
s_push(*var_ptr);
|
||||
}
|
||||
if (call_offset >= bf->code_size) {
|
||||
if (call_offset >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
s_push(bf->code_ptr + call_offset);
|
||||
s_push(s.bf->code_ptr + call_offset);
|
||||
|
||||
void *closure = Bclosure((aint *)__gc_stack_top, args_count);
|
||||
|
||||
|
|
@ -320,6 +328,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
call_happened = true;
|
||||
s.is_closure_call = true;
|
||||
s.call_ip = s.ip;
|
||||
s.call_module_id = s.current_module_id;
|
||||
|
||||
s.ip = Belem(*s_nth(args_count), BOX(0)); // use offset instead ??
|
||||
break;
|
||||
|
|
@ -332,11 +341,12 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
call_happened = true;
|
||||
s.is_closure_call = false;
|
||||
s.call_ip = s.ip;
|
||||
s.call_module_id = s.current_module_id;
|
||||
|
||||
if (call_p >= bf->code_size) {
|
||||
if (call_p >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
s.ip = bf->code_ptr + call_p;
|
||||
s.ip = s.bf->code_ptr + call_p;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -370,19 +380,27 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
break;
|
||||
|
||||
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function
|
||||
const char* call_func = ip_read_string(&s.ip);
|
||||
const char *call_func_name = ip_read_string(&s.ip);
|
||||
ip_read_int(&s.ip); // args count
|
||||
|
||||
// TODO: jump to other module, save ret module
|
||||
struct ModSearchResult func = mod_search_pub_symbol(call_func_name);
|
||||
if (func.mod_file == NULL) {
|
||||
s_failure(&s, "external function not found");
|
||||
}
|
||||
|
||||
// call_happened = true;
|
||||
// s.is_closure_call = false;
|
||||
// s.call_ip = s.ip;
|
||||
call_happened = true;
|
||||
s.is_closure_call = false;
|
||||
s.call_ip = s.ip;
|
||||
s.call_module_id = s.current_module_id;
|
||||
|
||||
// if (call_p >= bf->code_size) {
|
||||
// s_failure(&s, "jump out of file");
|
||||
// }
|
||||
// s.ip = bf->code_ptr + call_p;
|
||||
s.current_module_id = func.mod_id;
|
||||
s.bf = func.mod_file;
|
||||
|
||||
if (func.symbol_offset >= s.bf->code_size) {
|
||||
s_failure(&s, "jump out of file");
|
||||
}
|
||||
s.ip = s.bf->code_ptr + func.symbol_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -452,10 +470,9 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
}
|
||||
|
||||
// s_rotate_n(elem_count);
|
||||
void *array =
|
||||
Barray((aint *)opr_buffer,
|
||||
BOX(elem_count)); // NOTE: not shure if elems should be
|
||||
// added
|
||||
void *array = Barray((aint *)opr_buffer,
|
||||
BOX(elem_count)); // NOTE: not shure if elems
|
||||
// should be added
|
||||
|
||||
// void *array = Barray((aint *)s_peek(), BOX(elem_count));
|
||||
s_push(array);
|
||||
|
|
@ -474,6 +491,7 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
if (!call_happened) {
|
||||
s.is_closure_call = false;
|
||||
s.call_ip = NULL;
|
||||
s.call_module_id = 0;
|
||||
}
|
||||
|
||||
if (s.fp == NULL) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <optional>
|
||||
extern "C" {
|
||||
#include "module_manager.h"
|
||||
#include "parser.h"
|
||||
|
|
@ -23,8 +24,8 @@ struct ModuleManager {
|
|||
|
||||
static ModuleManager manager;
|
||||
|
||||
uint32_t path_mod_load(const char *name, std::filesystem::path &&path) {
|
||||
bytefile *module = read_file(path.c_str());
|
||||
uint32_t mod_add_impl(bytefile *module,
|
||||
std::optional<const char *> name = std::nullopt) {
|
||||
uint32_t id = manager.modules.size();
|
||||
manager.modules.push_back(module);
|
||||
for (size_t i = 0; i < module->public_symbols_number; ++i) {
|
||||
|
|
@ -37,9 +38,16 @@ uint32_t path_mod_load(const char *name, std::filesystem::path &&path) {
|
|||
failure("public symbol loaded more then once\n");
|
||||
}
|
||||
}
|
||||
manager.loaded_modules.insert({name, id});
|
||||
if (name) {
|
||||
manager.loaded_modules.insert({*name, id});
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t path_mod_load(const char *name, std::filesystem::path &&path) {
|
||||
bytefile *module = read_file(path.c_str());
|
||||
return mod_add_impl(module, name);
|
||||
}
|
||||
extern "C" {
|
||||
|
||||
void mod_add_search_path(const char *path) {
|
||||
|
|
@ -85,14 +93,16 @@ int32_t mod_load(const char *name) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
uint32_t mod_add(bytefile *module) { return mod_add_impl(module); }
|
||||
|
||||
ModSearchResult mod_search_pub_symbol(const char *name) {
|
||||
auto it = manager.public_symbols_mods.find(name);
|
||||
if (it == manager.public_symbols_mods.end()) {
|
||||
return {.symbol_offset = -1, .mod_id = 0, .mod_file = nullptr};
|
||||
return {.symbol_offset = 0, .mod_id = 0, .mod_file = NULL};
|
||||
}
|
||||
|
||||
return {
|
||||
.symbol_offset = (int32_t)it->second.offset,
|
||||
.symbol_offset = it->second.offset,
|
||||
.mod_id = it->second.mod_id,
|
||||
.mod_file = mod_get(it->second.mod_id),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ bytefile* read_file (const char *fname) {
|
|||
file->imports_ptr = (int*) file->buffer;
|
||||
file->public_ptr = (int*) (file->buffer + imports_size);
|
||||
file->code_ptr = &file->string_ptr [file->stringtab_size];
|
||||
file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int));
|
||||
|
||||
// is allocated on module run on stack
|
||||
file->global_ptr = NULL;
|
||||
// file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int));
|
||||
|
||||
file->code_size = size - strings_buffer_offset - file->stringtab_size;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "types.h"
|
||||
|
||||
#include "module_manager.h"
|
||||
#include "stack.h"
|
||||
#include "utils.h"
|
||||
#include "parser.h"
|
||||
|
|
@ -11,12 +12,14 @@ extern size_t __gc_stack_top, __gc_stack_bottom;
|
|||
|
||||
// --- State ---
|
||||
|
||||
static void init_state(bytefile *bf, struct State* s, void** stack) {
|
||||
static void init_state(uint mod_id, struct State* s, void** stack) {
|
||||
s->stack = stack;
|
||||
s->bf = bf;
|
||||
s->bf = mod_get(mod_id);
|
||||
s->is_closure_call = false;
|
||||
s->ip = bf->code_ptr;
|
||||
s->instr_ip = bf->code_ptr;
|
||||
s->current_module_id = mod_id;
|
||||
s->call_module_id = 0; // TODO: ??
|
||||
s->ip = s->bf->code_ptr;
|
||||
s->instr_ip = s->bf->code_ptr;
|
||||
s->call_ip = NULL;
|
||||
s->current_line = 0;
|
||||
|
||||
|
|
@ -30,13 +33,14 @@ static void init_state(bytefile *bf, struct State* s, void** stack) {
|
|||
s->fp = NULL;
|
||||
}
|
||||
|
||||
void construct_state(bytefile *bf, struct State* s, void** stack) {
|
||||
void construct_state(uint mod_id, struct State* s, void** stack) {
|
||||
__init();
|
||||
init_state(bf, s, stack);
|
||||
init_state(mod_id, s, stack);
|
||||
__gc_stack_bottom = (size_t)(s->stack + STACK_SIZE);
|
||||
__gc_stack_top = __gc_stack_bottom;
|
||||
|
||||
s_pushn_nil(bf->global_area_size);
|
||||
s_pushn_nil(s->bf->global_area_size); // TODO: move to run, do for each module
|
||||
s->bf->global_ptr = (void*)__gc_stack_top;
|
||||
|
||||
#ifdef DEBUG_VERSION
|
||||
print_stack(s);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue