add global_ghost_type_table for test

This commit is contained in:
ValKmjolnir 2023-05-10 00:48:04 +08:00
parent a69d05233b
commit 774ad60c42
7 changed files with 92 additions and 101 deletions

View File

@ -39,6 +39,6 @@ mod_func func_tbl[]={
{nullptr, nullptr}, {nullptr, nullptr},
}; };
extern "C" mod_func* get() { extern "C" mod_func* get(ghost_register_table* table) {
return func_tbl; return func_tbl;
} }

View File

@ -95,6 +95,6 @@ mod_func func_tbl[]={
{nullptr,nullptr} {nullptr,nullptr}
}; };
extern "C" mod_func* get() { extern "C" mod_func* get(ghost_register_table* table) {
return func_tbl; return func_tbl;
} }

View File

@ -291,6 +291,6 @@ mod_func func_tbl[]={
{nullptr,nullptr} {nullptr,nullptr}
}; };
extern "C" mod_func* get() { extern "C" mod_func* get(ghost_register_table* table) {
return func_tbl; return func_tbl;
} }

View File

@ -206,6 +206,6 @@ mod_func func_tbl[]={
{nullptr,nullptr} {nullptr,nullptr}
}; };
extern "C" mod_func* get() { extern "C" mod_func* get(ghost_register_table* table) {
return func_tbl; return func_tbl;
} }

View File

@ -544,13 +544,13 @@ var builtin_open(var* local, gc& ngc) {
return nas_err("open", "failed to open file <"+name.str()+">"); return nas_err("open", "failed to open file <"+name.str()+">");
} }
var ret=ngc.alloc(vm_obj); var ret=ngc.alloc(vm_obj);
ret.obj().set(obj_type::file, res); ret.obj().set(ghost_file, res);
return ret; return ret;
} }
var builtin_close(var* local, gc& ngc) { var builtin_close(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("close", "not a valid filehandle"); return nas_err("close", "not a valid filehandle");
} }
fd.obj().clear(); fd.obj().clear();
@ -561,7 +561,7 @@ var builtin_read(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
var buf=local[2]; var buf=local[2];
var len=local[3]; var len=local[3];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("read", "not a valid filehandle"); return nas_err("read", "not a valid filehandle");
} }
if (buf.type!=vm_str || buf.val.gcobj->unmut) { if (buf.type!=vm_str || buf.val.gcobj->unmut) {
@ -587,7 +587,7 @@ var builtin_read(var* local, gc& ngc) {
var builtin_write(var* local, gc& ngc) { var builtin_write(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
var str=local[2]; var str=local[2];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("write", "not a valid filehandle"); return nas_err("write", "not a valid filehandle");
} }
if (str.type!=vm_str) { if (str.type!=vm_str) {
@ -600,7 +600,7 @@ var builtin_seek(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
var pos=local[2]; var pos=local[2];
var whence=local[3]; var whence=local[3];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("seek", "not a valid filehandle"); return nas_err("seek", "not a valid filehandle");
} }
return var::num((f64)fseek((FILE*)fd.obj().ptr, pos.num(), whence.num())); return var::num((f64)fseek((FILE*)fd.obj().ptr, pos.num(), whence.num()));
@ -608,7 +608,7 @@ var builtin_seek(var* local, gc& ngc) {
var builtin_tell(var* local, gc& ngc) { var builtin_tell(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("tell", "not a valid filehandle"); return nas_err("tell", "not a valid filehandle");
} }
return var::num((f64)ftell((FILE*)fd.obj().ptr)); return var::num((f64)ftell((FILE*)fd.obj().ptr));
@ -616,7 +616,7 @@ var builtin_tell(var* local, gc& ngc) {
var builtin_readln(var* local, gc& ngc) { var builtin_readln(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("readln", "not a valid filehandle"); return nas_err("readln", "not a valid filehandle");
} }
var str=ngc.alloc(vm_str); var str=ngc.alloc(vm_str);
@ -664,7 +664,7 @@ var builtin_stat(var* local, gc& ngc) {
var builtin_eof(var* local, gc& ngc) { var builtin_eof(var* local, gc& ngc) {
var fd=local[1]; var fd=local[1];
if (!fd.objchk(obj_type::file)) { if (!fd.objchk(ghost_file)) {
return nas_err("readln", "not a valid filehandle"); return nas_err("readln", "not a valid filehandle");
} }
return var::num((f64)feof((FILE*)fd.obj().ptr)); return var::num((f64)feof((FILE*)fd.obj().ptr));
@ -849,13 +849,13 @@ var builtin_opendir(var* local, gc& ngc) {
} }
#endif #endif
var ret=ngc.alloc(vm_obj); var ret=ngc.alloc(vm_obj);
ret.obj().set(obj_type::dir,p); ret.obj().set(ghost_dir,p);
return ret; return ret;
} }
var builtin_readdir(var* local, gc& ngc) { var builtin_readdir(var* local, gc& ngc) {
var handle=local[1]; var handle=local[1];
if (!handle.objchk(obj_type::dir)) { if (!handle.objchk(ghost_dir)) {
return nas_err("readdir", "not a valid dir handle"); return nas_err("readdir", "not a valid dir handle");
} }
#ifdef _MSC_VER #ifdef _MSC_VER
@ -872,7 +872,7 @@ var builtin_readdir(var* local, gc& ngc) {
var builtin_closedir(var* local, gc& ngc) { var builtin_closedir(var* local, gc& ngc) {
var handle=local[1]; var handle=local[1];
if (!handle.objchk(obj_type::dir)) { if (!handle.objchk(ghost_dir)) {
return nas_err("closedir", "not a valid dir handle"); return nas_err("closedir", "not a valid dir handle");
} }
handle.obj().clear(); handle.obj().clear();
@ -936,7 +936,7 @@ var builtin_dlopen(var* local, gc& ngc) {
} }
var ret=ngc.temp=ngc.alloc(vm_hash); var ret=ngc.temp=ngc.alloc(vm_hash);
var lib=ngc.alloc(vm_obj); var lib=ngc.alloc(vm_obj);
lib.obj().set(obj_type::dylib, ptr); lib.obj().set(ghost_dylib, ptr);
ret.hash().elems["lib"]=lib; ret.hash().elems["lib"]=lib;
#ifdef _WIN32 #ifdef _WIN32
@ -948,14 +948,14 @@ var builtin_dlopen(var* local, gc& ngc) {
return nas_err("dlopen", "cannot find <get> function"); return nas_err("dlopen", "cannot find <get> function");
} }
// get function pointer by name // get function pointer by name
mod_func* tbl=(mod_func*)((getptr)func)(); mod_func* tbl=(mod_func*)((getptr)func)(&global_ghost_type_table);
if (!tbl) { if (!tbl) {
return nas_err("dlopen", "failed to get module functions"); return nas_err("dlopen", "failed to get module functions");
} }
for(u32 i=0;tbl[i].name;++i) { for(u32 i=0;tbl[i].name;++i) {
void* p=(void*)tbl[i].fd; void* p=(void*)tbl[i].fd;
var tmp=ngc.alloc(vm_obj); var tmp=ngc.alloc(vm_obj);
tmp.obj().set(obj_type::faddr, p); tmp.obj().set(ghost_faddr, p);
ret.hash().elems[tbl[i].name]=tmp; ret.hash().elems[tbl[i].name]=tmp;
} }
@ -965,7 +965,7 @@ var builtin_dlopen(var* local, gc& ngc) {
var builtin_dlclose(var* local, gc& ngc) { var builtin_dlclose(var* local, gc& ngc) {
var libptr=local[1]; var libptr=local[1];
if (!libptr.objchk(obj_type::dylib)) { if (!libptr.objchk(ghost_dylib)) {
return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); return nas_err("dlclose", "\"lib\" is not a valid dynamic lib");
} }
libptr.obj().clear(); libptr.obj().clear();
@ -975,7 +975,7 @@ var builtin_dlclose(var* local, gc& ngc) {
var builtin_dlcallv(var* local, gc& ngc) { var builtin_dlcallv(var* local, gc& ngc) {
var fp=local[1]; var fp=local[1];
var args=local[2]; var args=local[2];
if (!fp.objchk(obj_type::faddr)) { if (!fp.objchk(ghost_faddr)) {
return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
} }
auto& vec=args.vec().elems; auto& vec=args.vec().elems;
@ -984,7 +984,7 @@ var builtin_dlcallv(var* local, gc& ngc) {
var builtin_dlcall(var* local, gc& ngc) { var builtin_dlcall(var* local, gc& ngc) {
var fp=local[1]; var fp=local[1];
if (!fp.objchk(obj_type::faddr)) { if (!fp.objchk(ghost_faddr)) {
return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
} }

View File

@ -43,14 +43,6 @@ enum vm_type:u8 {
const u32 gc_type_size=vm_co-vm_str+1; const u32 gc_type_size=vm_co-vm_str+1;
enum class obj_type:u32 {
null=0,
file=1,
dir,
dylib,
faddr
};
enum class coroutine_status:u32 { enum class coroutine_status:u32 {
suspended, suspended,
running, running,
@ -99,7 +91,7 @@ public:
// number and string can be translated to each other // number and string can be translated to each other
f64 tonum(); f64 tonum();
string tostr(); string tostr();
bool objchk(obj_type); bool objchk(usize);
// create new var object // create new var object
static var none(); static var none();
@ -175,49 +167,76 @@ struct nas_upval {
void clear() {onstk=true;elems.clear();size=0;} void clear() {onstk=true;elems.clear();size=0;}
}; };
struct ghost_info { void file_dtor(void* ptr) {
string name; if ((FILE*)ptr==stdin) {
void (*destructor)(void*); return;
}
fclose((FILE*)ptr);
}
void dir_dtor(void* ptr) {
#ifndef _MSC_VER
closedir((DIR*)ptr);
#else
FindClose(ptr);
#endif
}
void dylib_dtor(void* ptr) {
#ifdef _WIN32
FreeLibrary((HMODULE)ptr);
#else
dlclose(ptr);
#endif
}
void faddr_dtor(void* ptr) {}
usize ghost_file, ghost_dir, ghost_dylib, ghost_faddr;
struct ghost_register_table {
private:
using dtor=void (*)(void*);
private:
std::unordered_map<string,usize> mapper;
std::vector<dtor> destructors;
public:
ghost_register_table() {
ghost_file=register_ghost_type("file", file_dtor);
ghost_dir=register_ghost_type("dir", dir_dtor);
ghost_dylib=register_ghost_type("dylib", dylib_dtor);
ghost_faddr=register_ghost_type("faddr", faddr_dtor);
}
usize register_ghost_type(const std::string& name, dtor ptr) {
if (mapper.count(name)) {
std::cerr<<"ghost type \""<<name<<"\" already exists.\n\n";
std::exit(-1);
}
auto res=destructors.size();
mapper[name]=res;
destructors.push_back(ptr);
return res;
}
dtor destructor(usize index) {
return destructors.at(index);
}
}; };
struct nas_ghost { ghost_register_table global_ghost_type_table;
private:
static std::vector<ghost_info> ghost_register_table; struct nas_obj {
public:
usize type; usize type;
void* ptr; void* ptr;
public: public:
nas_ghost(): type(0), ptr(nullptr) {} nas_obj(): type(0), ptr(nullptr) {}
~nas_ghost() {
if (!ptr) { return; }
ghost_register_table[type].destructor(ptr);
}
static usize regist_ghost_type(ghost_info i) {
auto res=ghost_register_table.size();
ghost_register_table.push_back(i);
return res;
}
const std::string& name() {
return ghost_register_table[type].name;
}
};
struct nas_obj {
obj_type type;
void* ptr;
private:
/* RAII constructor, new object is initialized when creating */
void file_dtor();
void dir_dtor();
void dylib_dtor();
public:
nas_obj(): type(obj_type::null), ptr(nullptr) {}
~nas_obj() {clear();} ~nas_obj() {clear();}
void set(obj_type, void*); void set(usize, void*);
void clear(); void clear();
}; };
@ -357,47 +376,19 @@ void nas_func::clear() {
keys.clear(); keys.clear();
} }
void nas_obj::set(obj_type t, void* p) { void nas_obj::set(usize t, void* p) {
type=t; type=t;
ptr=p; ptr=p;
} }
void nas_obj::clear() { void nas_obj::clear() {
if (!ptr) { if (!ptr || !type) {
return; return;
} }
switch(type) { global_ghost_type_table.destructor(type)(ptr);
case obj_type::file: file_dtor(); break;
case obj_type::dir: dir_dtor(); break;
case obj_type::dylib: dylib_dtor();break;
default: break;
}
ptr=nullptr; ptr=nullptr;
} }
void nas_obj::file_dtor() {
if ((FILE*)ptr==stdin) {
return;
}
fclose((FILE*)ptr);
}
void nas_obj::dir_dtor() {
#ifndef _MSC_VER
closedir((DIR*)ptr);
#else
FindClose(ptr);
#endif
}
void nas_obj::dylib_dtor() {
#ifdef _WIN32
FreeLibrary((HMODULE)ptr);
#else
dlclose(ptr);
#endif
}
void nas_co::clear() { void nas_co::clear() {
for(u32 i=0;i<STACK_DEPTH;++i) { for(u32 i=0;i<STACK_DEPTH;++i) {
stack[i]=var::nil(); stack[i]=var::nil();
@ -485,8 +476,8 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
return out; return out;
} }
bool var::objchk(obj_type objtype) { bool var::objchk(usize obj_type) {
return type==vm_obj && obj().type==objtype && obj().ptr; return type==vm_obj && obj().type==obj_type && obj().ptr;
} }
var var::none() { var var::none() {
@ -884,4 +875,4 @@ struct mod_func {
}; };
// module function "get" type // module function "get" type
typedef mod_func* (*getptr)(); typedef mod_func* (*getptr)(ghost_register_table*);

View File

@ -11,7 +11,7 @@ var new_map=func(width,height){
} }
var prt=func(map){ var prt=func(map){
var s='\e[1;1H'; var s='\ec\e[1;1H';
foreach(var line;map){ foreach(var line;map){
foreach(var elem;line) foreach(var elem;line)
s~=elem~' '; s~=elem~' ';