⚡ improve readability of some codes
This commit is contained in:
parent
1e1ab37e83
commit
9629108a1e
|
@ -53,7 +53,7 @@ void ghost_for_test_destructor(void* ptr) {
|
|||
|
||||
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||
var res = ngc->alloc(vm_obj);
|
||||
res.obj().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||
res.ghost().set(ghost_for_test, ghost_for_test_destructor, new u32);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ var set_new_ghost(var* args, usize size, gc* ngc) {
|
|||
return nil;
|
||||
}
|
||||
f64 num = args[1].num();
|
||||
*((u32*)res.obj().pointer) = static_cast<u32>(num);
|
||||
*((u32*)res.ghost().pointer) = static_cast<u32>(num);
|
||||
std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
|
||||
return nil;
|
||||
}
|
||||
|
@ -75,8 +75,8 @@ var print_new_ghost(var* args, usize size, gc* ngc) {
|
|||
std::cout << "print_new_ghost: not ghost for test type.\n";
|
||||
return nil;
|
||||
}
|
||||
std::cout << "print_new_ghost: " << res.obj() << " result = "
|
||||
<< *((u32*)res.obj().pointer) << "\n";
|
||||
std::cout << "print_new_ghost: " << res.ghost() << " result = "
|
||||
<< *((u32*)res.ghost().pointer) << "\n";
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,15 +49,15 @@ var builtin_fld(context* ctx, gc* ngc) {
|
|||
auto startbit = local[2];
|
||||
auto length = local[3];
|
||||
if (str.type!=vm_str || str.val.gcobj->unmutable) {
|
||||
return nas_err("fld", "\"str\" must be mutable string");
|
||||
return nas_err("bits::fld", "\"str\" must be mutable string");
|
||||
}
|
||||
if (startbit.type!=vm_num || length.type!=vm_num) {
|
||||
return nas_err("fld", "\"startbit\",\"len\" must be number");
|
||||
return nas_err("bits::fld", "\"startbit\",\"len\" must be number");
|
||||
}
|
||||
u32 bit = static_cast<u32>(startbit.num());
|
||||
u32 len = static_cast<u32>(length.num());
|
||||
if (bit+len>8*str.str().length()) {
|
||||
return nas_err("fld", "bitfield out of bounds");
|
||||
return nas_err("bits::fld", "bitfield out of bounds");
|
||||
}
|
||||
u32 res = 0;
|
||||
auto& s = str.str();
|
||||
|
@ -79,15 +79,15 @@ var builtin_sfld(context* ctx, gc* ngc) {
|
|||
auto startbit = local[2];
|
||||
auto length = local[3];
|
||||
if (str.type!=vm_str || str.val.gcobj->unmutable) {
|
||||
return nas_err("sfld", "\"str\" must be mutable string");
|
||||
return nas_err("bits::sfld", "\"str\" must be mutable string");
|
||||
}
|
||||
if (startbit.type!=vm_num || length.type!=vm_num) {
|
||||
return nas_err("sfld", "\"startbit\",\"len\" must be number");
|
||||
return nas_err("bits::sfld", "\"startbit\",\"len\" must be number");
|
||||
}
|
||||
u32 bit = static_cast<u32>(startbit.num());
|
||||
u32 len = static_cast<u32>(length.num());
|
||||
if (bit+len>8*str.str().length()) {
|
||||
return nas_err("sfld", "bitfield out of bounds");
|
||||
return nas_err("bits::sfld", "bitfield out of bounds");
|
||||
}
|
||||
u32 res = 0;
|
||||
auto& s = str.str();
|
||||
|
@ -113,16 +113,18 @@ var builtin_setfld(context* ctx, gc* ngc) {
|
|||
auto length = local[3];
|
||||
auto value = local[4];
|
||||
if (str.type!=vm_str || str.val.gcobj->unmutable) {
|
||||
return nas_err("setfld", "\"str\" must be mutable string");
|
||||
return nas_err("bits::setfld", "\"str\" must be mutable string");
|
||||
}
|
||||
if (startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) {
|
||||
return nas_err("setfld", "\"startbit\",\"len\",\"val\" must be number");
|
||||
return nas_err("bits::setfld",
|
||||
"\"startbit\", \"len\", \"val\" must be number"
|
||||
);
|
||||
}
|
||||
u32 bit = static_cast<u32>(startbit.num());
|
||||
u32 len = static_cast<u32>(length.num());
|
||||
u64 val = static_cast<u64>(value.num());
|
||||
if (bit+len>8*str.str().length()) {
|
||||
return nas_err("setfld", "bitfield out of bounds");
|
||||
return nas_err("bits::setfld", "bitfield out of bounds");
|
||||
}
|
||||
auto& s = str.str();
|
||||
for(u32 i = bit; i<bit+len; ++i) {
|
||||
|
@ -138,7 +140,7 @@ var builtin_setfld(context* ctx, gc* ngc) {
|
|||
var builtin_buf(context* ctx, gc* ngc) {
|
||||
var length = ctx->localr[1];
|
||||
if (length.type!=vm_num || length.num()<=0) {
|
||||
return nas_err("buf", "\"len\" must be number greater than 0");
|
||||
return nas_err("bits::buf", "\"len\" must be number greater than 0");
|
||||
}
|
||||
var str = ngc->alloc(vm_str);
|
||||
auto& s = str.str();
|
||||
|
|
|
@ -75,7 +75,7 @@ var builtin_coresume(context* ctx, gc* ngc) {
|
|||
}
|
||||
|
||||
// change to coroutine context
|
||||
ngc->ctxchg(coroutine_object.co());
|
||||
ngc->context_change(&coroutine_object.co());
|
||||
|
||||
// fetch coroutine's stack top and return
|
||||
// then coroutine's stack top will catch this return value
|
||||
|
@ -103,7 +103,7 @@ var builtin_coyield(context* ctx, gc* ngc) {
|
|||
auto coroutine_local_frame = ctx->localr;
|
||||
|
||||
// vm context will set to main context
|
||||
ngc->ctxreserve();
|
||||
ngc->context_reserve();
|
||||
|
||||
// then this will return value to main's stack top[0]
|
||||
// the procedure seems like coroutine.resume returns the value
|
||||
|
|
|
@ -2,89 +2,108 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
const auto dylib_type_name = "dylib";
|
||||
const auto func_addr_type_name = "faddr";
|
||||
const auto dynamic_library_type_name = "dylib";
|
||||
const auto function_address_type_name = "faddr";
|
||||
|
||||
void dylib_destructor(void* ptr) {
|
||||
void dynamic_library_destructor(void* pointer) {
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(static_cast<HMODULE>(ptr));
|
||||
FreeLibrary(static_cast<HMODULE>(pointer));
|
||||
#else
|
||||
dlclose(ptr);
|
||||
dlclose(pointer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void func_addr_destructor(void* ptr) {}
|
||||
|
||||
var builtin_dlopen(context* ctx, gc* ngc) {
|
||||
auto dlname = ctx->localr[1];
|
||||
if (dlname.type!=vm_str) {
|
||||
return nas_err("dlopen", "\"libname\" must be string");
|
||||
return nas_err("dylib::dlopen", "\"libname\" must be string");
|
||||
}
|
||||
#ifdef _WIN32
|
||||
wchar_t* str = new wchar_t[dlname.str().size()+1];
|
||||
if (!str) {
|
||||
return nas_err("dlopen", "malloc failed");
|
||||
}
|
||||
memset(str, 0, sizeof(wchar_t)*dlname.str().size()+1);
|
||||
mbstowcs(str, dlname.str().c_str(),dlname.str().size()+1);
|
||||
void* ptr = LoadLibraryA(dlname.str().c_str());
|
||||
delete []str;
|
||||
#else
|
||||
void* ptr = dlopen(dlname.str().c_str(), RTLD_LOCAL|RTLD_LAZY);
|
||||
#endif
|
||||
if (!ptr) {
|
||||
return nas_err("dlopen", "cannot open dynamic lib <"+dlname.str()+">");
|
||||
}
|
||||
auto ret = ngc->temp = ngc->alloc(vm_hash);
|
||||
auto lib = ngc->alloc(vm_obj);
|
||||
lib.obj().set(dylib_type_name, dylib_destructor, ptr);
|
||||
ret.hash().elems["lib"] = lib;
|
||||
|
||||
// get library pointer
|
||||
#ifdef _WIN32
|
||||
void* func = (void*)GetProcAddress(
|
||||
static_cast<HMODULE>(lib.obj().pointer),
|
||||
"get"
|
||||
wchar_t* wide_string = new wchar_t[dlname.str().size()+1];
|
||||
if (!wide_string) {
|
||||
return nas_err("dylib::dlopen", "malloc failed");
|
||||
}
|
||||
memset(wide_string, 0, sizeof(wchar_t) * dlname.str().size() + 1);
|
||||
mbstowcs(wide_string, dlname.str().c_str(), dlname.str().size() + 1);
|
||||
// load library by using wide string name
|
||||
void* dynamic_library_pointer = LoadLibraryA(dlname.str().c_str());
|
||||
delete []wide_string;
|
||||
#else
|
||||
void* dynamic_library_pointer = dlopen(
|
||||
dlname.str().c_str(), RTLD_LOCAL|RTLD_LAZY
|
||||
);
|
||||
#endif
|
||||
|
||||
// check library pointer and insert into returned hashmap
|
||||
if (!dynamic_library_pointer) {
|
||||
return nas_err("dylib::dlopen",
|
||||
"cannot open dynamic lib <" + dlname.str() + ">"
|
||||
);
|
||||
}
|
||||
auto return_hash = ngc->temp = ngc->alloc(vm_hash);
|
||||
auto library_object = ngc->alloc(vm_obj);
|
||||
library_object.ghost().set(
|
||||
dynamic_library_type_name,
|
||||
dynamic_library_destructor,
|
||||
dynamic_library_pointer
|
||||
);
|
||||
return_hash.hash().elems["lib"] = library_object;
|
||||
|
||||
// get "get" function, to get the register table
|
||||
#ifdef _WIN32
|
||||
void* register_table_get_function = (void*)GetProcAddress(
|
||||
static_cast<HMODULE>(library_object.ghost().pointer), "get"
|
||||
);
|
||||
#else
|
||||
void* func = dlsym(lib.obj().pointer, "get");
|
||||
void* register_table_get_function = dlsym(
|
||||
library_object.ghost().pointer, "get"
|
||||
);
|
||||
#endif
|
||||
if (!func) {
|
||||
return nas_err("dlopen", "cannot find <get> function");
|
||||
if (!register_table_get_function) {
|
||||
return nas_err("dylib::dlopen", "cannot find <get> function");
|
||||
}
|
||||
|
||||
// get function pointer by name
|
||||
auto tbl = reinterpret_cast<get_func_ptr>(func)();
|
||||
if (!tbl) {
|
||||
return nas_err("dlopen", "failed to get module functions");
|
||||
auto table = reinterpret_cast<get_func_ptr>(register_table_get_function)();
|
||||
if (!table) {
|
||||
return nas_err("dylib::dlopen", "failed to get module functions");
|
||||
}
|
||||
for(u32 i = 0; tbl[i].name; ++i) {
|
||||
void* p = (void*)tbl[i].fd;
|
||||
var tmp = ngc->alloc(vm_obj);
|
||||
tmp.obj().set(func_addr_type_name, func_addr_destructor, p);
|
||||
ret.hash().elems[tbl[i].name] = tmp;
|
||||
for(u32 i = 0; table[i].name; ++i) {
|
||||
auto function_pointer = reinterpret_cast<void*>(table[i].fd);
|
||||
auto function_object = ngc->alloc(vm_obj);
|
||||
function_object.ghost().set(
|
||||
function_address_type_name,
|
||||
nullptr,
|
||||
function_pointer
|
||||
);
|
||||
return_hash.hash().elems[table[i].name] = function_object;
|
||||
}
|
||||
|
||||
ngc->temp = nil;
|
||||
return ret;
|
||||
return return_hash;
|
||||
}
|
||||
|
||||
var builtin_dlclose(context* ctx, gc* ngc) {
|
||||
auto libptr = ctx->localr[1];
|
||||
if (!libptr.object_check(dylib_type_name)) {
|
||||
return nas_err("dlclose", "\"lib\" is not a valid dynamic lib");
|
||||
auto library_pointer = ctx->localr[1];
|
||||
if (!library_pointer.object_check(dynamic_library_type_name)) {
|
||||
return nas_err("dylib::dlclose", "\"lib\" is not a valid dynamic lib");
|
||||
}
|
||||
libptr.obj().clear();
|
||||
library_pointer.ghost().clear();
|
||||
return nil;
|
||||
}
|
||||
|
||||
var builtin_dlcallv(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
auto fp = local[1];
|
||||
auto args = local[2];
|
||||
if (!fp.object_check(func_addr_type_name)) {
|
||||
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
||||
auto function_object = ctx->localr[1];
|
||||
auto arguments = ctx->localr[2];
|
||||
if (!function_object.object_check(function_address_type_name)) {
|
||||
return nas_err("dylib::dlcall",
|
||||
"\"ptr\" is not a valid function pointer"
|
||||
);
|
||||
}
|
||||
auto& vec = args.vec().elems;
|
||||
return reinterpret_cast<module_func>(fp.obj().pointer)(
|
||||
auto& vec = arguments.vec().elems;
|
||||
return reinterpret_cast<module_func>(function_object.ghost().pointer)(
|
||||
vec.data(),
|
||||
vec.size(),
|
||||
ngc
|
||||
|
@ -92,16 +111,18 @@ var builtin_dlcallv(context* ctx, gc* ngc) {
|
|||
}
|
||||
|
||||
var builtin_dlcall(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
var fp = local[1];
|
||||
if (!fp.object_check(func_addr_type_name)) {
|
||||
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
||||
auto function_object = ctx->localr[1];
|
||||
if (!function_object.object_check(function_address_type_name)) {
|
||||
return nas_err("dylib::dlcall",
|
||||
"\"ptr\" is not a valid function pointer"
|
||||
);
|
||||
}
|
||||
|
||||
var* local_frame_start = local+2;
|
||||
usize local_frame_size = ngc->running_context->top-local_frame_start;
|
||||
// arguments' stored place begins at local +2
|
||||
return reinterpret_cast<module_func>(fp.obj().pointer)(
|
||||
// function pointer is at ctx->localr[1]
|
||||
// so arguments starts from ctx->localr[2]
|
||||
var* local_frame_start = ctx->localr + 2;
|
||||
usize local_frame_size = ngc->running_context->top - local_frame_start;
|
||||
return reinterpret_cast<module_func>(function_object.ghost().pointer)(
|
||||
local_frame_start,
|
||||
local_frame_size,
|
||||
ngc
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
void dylib_destructor(void*);
|
||||
void func_addr_destructor(void*);
|
||||
void dynamic_library_destructor(void*);
|
||||
|
||||
var builtin_dlopen(context*, gc*);
|
||||
var builtin_dlclose(context*, gc*);
|
||||
|
|
|
@ -9,7 +9,7 @@ var builtin_logprint(context* ctx, gc* ngc) {
|
|||
auto level = local[1];
|
||||
auto elems = local[2];
|
||||
if (elems.type!=vm_vec) {
|
||||
return nas_err("logprint", "received argument is not vector.");
|
||||
return nas_err("fg_env::logprint", "received argument is not vector.");
|
||||
}
|
||||
std::ofstream out("fgfs.log", std::ios::app);
|
||||
switch (static_cast<u32>(level.num())) {
|
||||
|
@ -22,13 +22,12 @@ var builtin_logprint(context* ctx, gc* ngc) {
|
|||
case SG_DEV_ALERT: out << "[DEV_ALERT]"; break;
|
||||
case SG_MANDATORY_INFO: out << "[MANDATORY_INFO]"; break;
|
||||
default:
|
||||
return nas_err("logprint",
|
||||
"incorrect log level " +
|
||||
std::to_string(level.num())
|
||||
return nas_err("fg_env::logprint",
|
||||
"incorrect log level " + std::to_string(level.num())
|
||||
);
|
||||
}
|
||||
for(auto& i : elems.vec().elems) {
|
||||
out << i << " ";
|
||||
for(auto& value : elems.vec().elems) {
|
||||
out << value << " ";
|
||||
}
|
||||
out << "\n";
|
||||
return nil;
|
||||
|
|
191
src/io_lib.cpp
191
src/io_lib.cpp
|
@ -12,11 +12,11 @@ void filehandle_destructor(void* ptr) {
|
|||
}
|
||||
|
||||
var builtin_readfile(context* ctx, gc* ngc) {
|
||||
auto val = ctx->localr[1];
|
||||
if (val.type!=vm_str) {
|
||||
auto filename = ctx->localr[1];
|
||||
if (filename.type!=vm_str) {
|
||||
return nas_err("io::readfile", "\"filename\" must be string");
|
||||
}
|
||||
std::ifstream in(val.str(), std::ios::binary);
|
||||
std::ifstream in(filename.str(), std::ios::binary);
|
||||
std::stringstream rd;
|
||||
if (!in.fail()) {
|
||||
rd << in.rdbuf();
|
||||
|
@ -26,25 +26,25 @@ var builtin_readfile(context* ctx, gc* ngc) {
|
|||
|
||||
var builtin_fout(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
auto val = local[1];
|
||||
auto str = local[2];
|
||||
if (val.type!=vm_str) {
|
||||
auto filename = local[1];
|
||||
auto source = local[2];
|
||||
if (filename.type!=vm_str) {
|
||||
return nas_err("io::fout", "\"filename\" must be string");
|
||||
}
|
||||
std::ofstream out(val.str());
|
||||
std::ofstream out(filename.str());
|
||||
if (out.fail()) {
|
||||
return nas_err("io::fout", "cannot open <"+val.str()+">");
|
||||
return nas_err("io::fout", "cannot open <" + filename.str() + ">");
|
||||
}
|
||||
out << str;
|
||||
out << source;
|
||||
return nil;
|
||||
}
|
||||
|
||||
var builtin_exists(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
if (local[1].type!=vm_str) {
|
||||
auto filename = ctx->localr[1];
|
||||
if (filename.type!=vm_str) {
|
||||
return zero;
|
||||
}
|
||||
return access(local[1].str().c_str(), F_OK)!=-1? one:zero;
|
||||
return access(filename.str().c_str(), F_OK)!=-1? one:zero;
|
||||
}
|
||||
|
||||
var builtin_open(context* ctx, gc* ngc) {
|
||||
|
@ -52,118 +52,121 @@ var builtin_open(context* ctx, gc* ngc) {
|
|||
auto name = local[1];
|
||||
auto mode = local[2];
|
||||
if (name.type!=vm_str) {
|
||||
return nas_err("open", "\"filename\" must be string");
|
||||
return nas_err("io::open", "\"filename\" must be string");
|
||||
}
|
||||
if (mode.type!=vm_str) {
|
||||
return nas_err("open", "\"mode\" must be string");
|
||||
return nas_err("io::open", "\"mode\" must be string");
|
||||
}
|
||||
FILE* res = fopen(name.str().c_str(), mode.str().c_str());
|
||||
if (!res) {
|
||||
return nas_err("open", "failed to open file <"+name.str()+">");
|
||||
auto file_descriptor = fopen(name.str().c_str(), mode.str().c_str());
|
||||
if (!file_descriptor) {
|
||||
return nas_err("io::open", "failed to open file <" + name.str() + ">");
|
||||
}
|
||||
var ret = ngc->alloc(vm_obj);
|
||||
ret.obj().set(file_type_name, filehandle_destructor, res);
|
||||
return ret;
|
||||
var return_object = ngc->alloc(vm_obj);
|
||||
return_object.ghost().set(
|
||||
file_type_name, filehandle_destructor, file_descriptor
|
||||
);
|
||||
return return_object;
|
||||
}
|
||||
|
||||
var builtin_close(context* ctx, gc* ngc) {
|
||||
var fd = ctx->localr[1];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("close", "not a valid filehandle");
|
||||
var file_descriptor = ctx->localr[1];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::close", "not a valid filehandle");
|
||||
}
|
||||
fd.obj().clear();
|
||||
file_descriptor.ghost().clear();
|
||||
return nil;
|
||||
}
|
||||
|
||||
var builtin_read(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
auto fd = local[1];
|
||||
auto buf = local[2];
|
||||
auto len = local[3];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("read", "not a valid filehandle");
|
||||
auto file_descriptor = local[1];
|
||||
auto buffer = local[2];
|
||||
auto length = local[3];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::read", "not a valid filehandle");
|
||||
}
|
||||
if (buf.type!=vm_str || buf.val.gcobj->unmutable) {
|
||||
return nas_err("read", "\"buf\" must be mutable string");
|
||||
if (buffer.type!=vm_str || buffer.val.gcobj->unmutable) {
|
||||
return nas_err("io::read", "\"buf\" must be mutable string");
|
||||
}
|
||||
if (len.type!=vm_num) {
|
||||
return nas_err("read", "\"len\" must be number");
|
||||
if (length.type!=vm_num) {
|
||||
return nas_err("io::read", "\"len\" must be number");
|
||||
}
|
||||
if (len.num()<=0 || len.num()>=(1<<30)) {
|
||||
return nas_err("read", "\"len\" less than 1 or too large");
|
||||
if (length.num()<=0 || length.num()>=(1<<30)) {
|
||||
return nas_err("io::read", "\"len\" less than 1 or too large");
|
||||
}
|
||||
char* buff = new char[(usize)len.num()+1];
|
||||
if (!buff) {
|
||||
return nas_err("read", "malloc failed");
|
||||
auto temp_buffer = new char[static_cast<usize>(length.num())+1];
|
||||
if (!temp_buffer) {
|
||||
return nas_err("io::read", "malloc failed");
|
||||
}
|
||||
f64 res = fread(buff, 1, len.num(), static_cast<FILE*>(fd.obj().pointer));
|
||||
buf.str() = buff;
|
||||
buf.val.gcobj->unmutable = true;
|
||||
delete []buff;
|
||||
return var::num(res);
|
||||
auto read_size = fread(
|
||||
temp_buffer, 1, length.num(),
|
||||
static_cast<FILE*>(file_descriptor.ghost().pointer)
|
||||
);
|
||||
buffer.str() = temp_buffer;
|
||||
buffer.val.gcobj->unmutable = true;
|
||||
delete []temp_buffer;
|
||||
return var::num(read_size);
|
||||
}
|
||||
|
||||
var builtin_write(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
auto fd = local[1];
|
||||
auto str = local[2];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("write", "not a valid filehandle");
|
||||
auto file_descriptor = local[1];
|
||||
auto source = local[2];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::write", "not a valid filehandle");
|
||||
}
|
||||
if (str.type!=vm_str) {
|
||||
return nas_err("write", "\"str\" must be string");
|
||||
if (source.type!=vm_str) {
|
||||
return nas_err("io::write", "\"str\" must be string");
|
||||
}
|
||||
return var::num(static_cast<f64>(fwrite(
|
||||
str.str().c_str(),
|
||||
1,
|
||||
str.str().length(),
|
||||
static_cast<FILE*>(fd.obj().pointer)
|
||||
source.str().c_str(), 1, source.str().length(),
|
||||
static_cast<FILE*>(file_descriptor.ghost().pointer)
|
||||
)));
|
||||
}
|
||||
|
||||
var builtin_seek(context* ctx, gc* ngc) {
|
||||
auto local = ctx->localr;
|
||||
auto fd = local[1];
|
||||
auto pos = local[2];
|
||||
auto file_descriptor = local[1];
|
||||
auto position = local[2];
|
||||
auto whence = local[3];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("seek", "not a valid filehandle");
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::seek", "not a valid filehandle");
|
||||
}
|
||||
return var::num(static_cast<f64>(fseek(
|
||||
static_cast<FILE*>(fd.obj().pointer),
|
||||
pos.num(),
|
||||
static_cast<FILE*>(file_descriptor.ghost().pointer),
|
||||
position.num(),
|
||||
whence.num()
|
||||
)));
|
||||
}
|
||||
|
||||
var builtin_tell(context* ctx, gc* ngc) {
|
||||
auto fd = ctx->localr[1];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("tell", "not a valid filehandle");
|
||||
auto file_descriptor = ctx->localr[1];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::tell", "not a valid filehandle");
|
||||
}
|
||||
return var::num(static_cast<f64>(
|
||||
ftell(static_cast<FILE*>(fd.obj().pointer))
|
||||
ftell(static_cast<FILE*>(file_descriptor.ghost().pointer))
|
||||
));
|
||||
}
|
||||
|
||||
var builtin_readln(context* ctx, gc* ngc) {
|
||||
auto fd = ctx->localr[1];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("readln", "not a valid filehandle");
|
||||
auto file_descriptor = ctx->localr[1];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::readln", "not a valid filehandle");
|
||||
}
|
||||
auto str = ngc->alloc(vm_str);
|
||||
auto result = ngc->alloc(vm_str);
|
||||
char c;
|
||||
while((c = fgetc(static_cast<FILE*>(fd.obj().pointer)))!=EOF) {
|
||||
while((c = fgetc(static_cast<FILE*>(file_descriptor.ghost().pointer)))!=EOF) {
|
||||
if (c=='\r') {
|
||||
continue;
|
||||
}
|
||||
if (c=='\n') {
|
||||
return str;
|
||||
return result;
|
||||
}
|
||||
str.str() += c;
|
||||
result.str().push_back(c);
|
||||
}
|
||||
if (str.str().length()) {
|
||||
return str;
|
||||
if (result.str().length()) {
|
||||
return result;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
@ -171,36 +174,36 @@ var builtin_readln(context* ctx, gc* ngc) {
|
|||
var builtin_stat(context* ctx, gc* ngc) {
|
||||
auto name = ctx->localr[1];
|
||||
if (name.type!=vm_str) {
|
||||
return nas_err("stat", "\"filename\" must be string");
|
||||
return nas_err("io::stat", "\"filename\" must be string");
|
||||
}
|
||||
struct stat buf;
|
||||
if (stat(name.str().c_str(), &buf)<0) {
|
||||
return nas_err("stat", "failed to open file <"+name.str()+">");
|
||||
struct stat buffer;
|
||||
if (stat(name.str().c_str(), &buffer)<0) {
|
||||
return nas_err("io::stat", "failed to open file <" + name.str() + ">");
|
||||
}
|
||||
auto ret = ngc->alloc(vm_vec);
|
||||
ret.vec().elems = {
|
||||
var::num(static_cast<f64>(buf.st_dev)),
|
||||
var::num(static_cast<f64>(buf.st_ino)),
|
||||
var::num(static_cast<f64>(buf.st_mode)),
|
||||
var::num(static_cast<f64>(buf.st_nlink)),
|
||||
var::num(static_cast<f64>(buf.st_uid)),
|
||||
var::num(static_cast<f64>(buf.st_gid)),
|
||||
var::num(static_cast<f64>(buf.st_rdev)),
|
||||
var::num(static_cast<f64>(buf.st_size)),
|
||||
var::num(static_cast<f64>(buf.st_atime)),
|
||||
var::num(static_cast<f64>(buf.st_mtime)),
|
||||
var::num(static_cast<f64>(buf.st_ctime))
|
||||
auto result = ngc->alloc(vm_vec);
|
||||
result.vec().elems = {
|
||||
var::num(static_cast<f64>(buffer.st_dev)),
|
||||
var::num(static_cast<f64>(buffer.st_ino)),
|
||||
var::num(static_cast<f64>(buffer.st_mode)),
|
||||
var::num(static_cast<f64>(buffer.st_nlink)),
|
||||
var::num(static_cast<f64>(buffer.st_uid)),
|
||||
var::num(static_cast<f64>(buffer.st_gid)),
|
||||
var::num(static_cast<f64>(buffer.st_rdev)),
|
||||
var::num(static_cast<f64>(buffer.st_size)),
|
||||
var::num(static_cast<f64>(buffer.st_atime)),
|
||||
var::num(static_cast<f64>(buffer.st_mtime)),
|
||||
var::num(static_cast<f64>(buffer.st_ctime))
|
||||
};
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
var builtin_eof(context* ctx, gc* ngc) {
|
||||
auto fd = ctx->localr[1];
|
||||
if (!fd.object_check(file_type_name)) {
|
||||
return nas_err("readln", "not a valid filehandle");
|
||||
auto file_descriptor = ctx->localr[1];
|
||||
if (!file_descriptor.object_check(file_type_name)) {
|
||||
return nas_err("io::readln", "not a valid filehandle");
|
||||
}
|
||||
return var::num(static_cast<f64>(
|
||||
feof(static_cast<FILE*>(fd.obj().pointer))
|
||||
feof(static_cast<FILE*>(file_descriptor.ghost().pointer))
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
virtual void accept(ast_visitor*);
|
||||
};
|
||||
|
||||
class call:public expr {
|
||||
class call: public expr {
|
||||
public:
|
||||
call(const span& location, expr_type node_type):
|
||||
expr(location, node_type) {}
|
||||
|
@ -85,7 +85,7 @@ public:
|
|||
virtual void accept(ast_visitor*);
|
||||
};
|
||||
|
||||
class null_expr:public expr {
|
||||
class null_expr: public expr {
|
||||
public:
|
||||
null_expr(const span& location):
|
||||
expr(location, expr_type::ast_null) {}
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class nil_expr:public expr {
|
||||
class nil_expr: public expr {
|
||||
public:
|
||||
nil_expr(const span& location):
|
||||
expr(location, expr_type::ast_nil) {}
|
||||
|
@ -101,7 +101,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class number_literal:public expr {
|
||||
class number_literal: public expr {
|
||||
private:
|
||||
f64 number;
|
||||
|
||||
|
@ -113,7 +113,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class string_literal:public expr {
|
||||
class string_literal: public expr {
|
||||
private:
|
||||
std::string content;
|
||||
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class identifier:public expr {
|
||||
class identifier: public expr {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
|
@ -137,7 +137,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class bool_literal:public expr {
|
||||
class bool_literal: public expr {
|
||||
private:
|
||||
bool flag;
|
||||
|
||||
|
@ -149,7 +149,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class vector_expr:public expr {
|
||||
class vector_expr: public expr {
|
||||
private:
|
||||
std::vector<expr*> elements;
|
||||
|
||||
|
@ -162,7 +162,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class hash_expr:public expr {
|
||||
class hash_expr: public expr {
|
||||
private:
|
||||
std::vector<hash_pair*> members;
|
||||
|
||||
|
@ -175,7 +175,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class hash_pair:public expr {
|
||||
class hash_pair: public expr {
|
||||
private:
|
||||
std::string name;
|
||||
expr* value;
|
||||
|
@ -192,7 +192,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class function:public expr {
|
||||
class function: public expr {
|
||||
private:
|
||||
std::vector<parameter*> parameter_list;
|
||||
code_block* block;
|
||||
|
@ -209,7 +209,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class code_block:public expr {
|
||||
class code_block: public expr {
|
||||
private:
|
||||
std::vector<expr*> expressions;
|
||||
|
||||
|
@ -222,7 +222,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class parameter:public expr {
|
||||
class parameter: public expr {
|
||||
public:
|
||||
enum class param_type {
|
||||
normal_parameter,
|
||||
|
@ -249,7 +249,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class ternary_operator:public expr {
|
||||
class ternary_operator: public expr {
|
||||
private:
|
||||
expr* condition;
|
||||
expr* left;
|
||||
|
@ -269,7 +269,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class binary_operator:public expr {
|
||||
class binary_operator: public expr {
|
||||
public:
|
||||
enum class binary_type {
|
||||
add,
|
||||
|
@ -317,7 +317,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class unary_operator:public expr {
|
||||
class unary_operator: public expr {
|
||||
public:
|
||||
enum class unary_type {
|
||||
negative,
|
||||
|
@ -344,7 +344,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class call_expr:public expr {
|
||||
class call_expr: public expr {
|
||||
private:
|
||||
expr* first;
|
||||
std::vector<call*> calls;
|
||||
|
@ -361,7 +361,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class call_hash:public call {
|
||||
class call_hash: public call {
|
||||
private:
|
||||
std::string field;
|
||||
|
||||
|
@ -374,7 +374,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class call_vector:public call {
|
||||
class call_vector: public call {
|
||||
private:
|
||||
std::vector<slice_vector*> calls;
|
||||
|
||||
|
@ -387,7 +387,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class call_function:public call {
|
||||
class call_function: public call {
|
||||
private:
|
||||
std::vector<expr*> args;
|
||||
|
||||
|
@ -400,7 +400,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class slice_vector:public expr {
|
||||
class slice_vector: public expr {
|
||||
private:
|
||||
expr* begin;
|
||||
expr* end;
|
||||
|
@ -417,7 +417,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class definition_expr:public expr {
|
||||
class definition_expr: public expr {
|
||||
private:
|
||||
identifier* variable_name;
|
||||
multi_identifier* variables;
|
||||
|
@ -441,7 +441,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class assignment_expr:public expr {
|
||||
class assignment_expr: public expr {
|
||||
public:
|
||||
enum class assign_type {
|
||||
equal,
|
||||
|
@ -474,7 +474,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class multi_identifier:public expr {
|
||||
class multi_identifier: public expr {
|
||||
private:
|
||||
std::vector<identifier*> variables;
|
||||
|
||||
|
@ -487,7 +487,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class tuple_expr:public expr {
|
||||
class tuple_expr: public expr {
|
||||
private:
|
||||
std::vector<expr*> elements;
|
||||
|
||||
|
@ -500,7 +500,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class multi_assign:public expr {
|
||||
class multi_assign: public expr {
|
||||
private:
|
||||
tuple_expr* tuple;
|
||||
expr* value;
|
||||
|
@ -517,7 +517,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class while_expr:public expr {
|
||||
class while_expr: public expr {
|
||||
private:
|
||||
expr* condition;
|
||||
code_block* block;
|
||||
|
@ -534,7 +534,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class for_expr:public expr {
|
||||
class for_expr: public expr {
|
||||
private:
|
||||
expr* initializing;
|
||||
expr* condition;
|
||||
|
@ -558,7 +558,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class iter_expr:public expr {
|
||||
class iter_expr: public expr {
|
||||
private:
|
||||
identifier* name;
|
||||
call_expr* call;
|
||||
|
@ -575,7 +575,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class forei_expr:public expr {
|
||||
class forei_expr: public expr {
|
||||
public:
|
||||
enum class forei_loop_type {
|
||||
foreach,
|
||||
|
@ -605,7 +605,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class condition_expr:public expr {
|
||||
class condition_expr: public expr {
|
||||
private:
|
||||
if_expr* if_stmt;
|
||||
std::vector<if_expr*> elsif_stmt;
|
||||
|
@ -625,7 +625,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class if_expr:public expr {
|
||||
class if_expr: public expr {
|
||||
private:
|
||||
expr* condition;
|
||||
code_block* block;
|
||||
|
@ -642,7 +642,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class continue_expr:public expr {
|
||||
class continue_expr: public expr {
|
||||
public:
|
||||
continue_expr(const span& location):
|
||||
expr(location, expr_type::ast_continue) {}
|
||||
|
@ -650,7 +650,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class break_expr:public expr {
|
||||
class break_expr: public expr {
|
||||
public:
|
||||
break_expr(const span& location):
|
||||
expr(location, expr_type::ast_break) {}
|
||||
|
@ -658,7 +658,7 @@ public:
|
|||
void accept(ast_visitor*) override;
|
||||
};
|
||||
|
||||
class return_expr:public expr {
|
||||
class return_expr: public expr {
|
||||
private:
|
||||
expr* value;
|
||||
|
||||
|
|
|
@ -632,9 +632,9 @@ var builtin_ghosttype(context* ctx, gc* ngc) {
|
|||
if (arg.type!=vm_obj) {
|
||||
return nas_err("ghosttype", "this is not a ghost object.");
|
||||
}
|
||||
const auto& name = arg.obj().get_ghost_name();
|
||||
const auto& name = arg.ghost().get_ghost_name();
|
||||
if (!name.length()) {
|
||||
return var::num(reinterpret_cast<u64>(arg.obj().pointer));
|
||||
return var::num(reinterpret_cast<u64>(arg.ghost().pointer));
|
||||
}
|
||||
return ngc->newstr(name);
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ void dbg::step_info() {
|
|||
begin = (ctx.pc>>3)==0? 0:((ctx.pc>>3)<<3);
|
||||
end = (1+(ctx.pc>>3))<<3;
|
||||
codestream::set(const_number, const_string, native_function.data(), files);
|
||||
std::clog << "next bytecode:\n";
|
||||
std::clog << "\nnext bytecode:\n";
|
||||
for(u32 i = begin; i<end && bytecode[i].op!=op_exit; ++i) {
|
||||
std::clog
|
||||
<< (i==ctx.pc? back_white:reset)
|
||||
|
@ -184,7 +184,7 @@ void dbg::interact() {
|
|||
|
||||
// is not break point and is not next stop command
|
||||
const auto& code = bytecode[ctx.pc];
|
||||
if ((code.fidx!=bk_fidx || code.line!=bk_line) && !next) {
|
||||
if ((code.fidx!=break_file_index || code.line!=break_line) && !next) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,8 +217,8 @@ void dbg::interact() {
|
|||
}
|
||||
} else if (res.size()==3 &&
|
||||
get_cmd_type(res[0])==dbg_cmd::cmd_break_point) {
|
||||
bk_fidx = file_index(res[1]);
|
||||
if (bk_fidx==65535) {
|
||||
break_file_index = file_index(res[1]);
|
||||
if (break_file_index==65535) {
|
||||
std::clog << "cannot find file named `" << res[1] << "`\n";
|
||||
continue;
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ void dbg::interact() {
|
|||
if (tmp<=0) {
|
||||
std::clog << "incorrect line number `" << res[2] << "`\n";
|
||||
} else {
|
||||
bk_line = tmp;
|
||||
break_line = tmp;
|
||||
}
|
||||
} else {
|
||||
err();
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class dbg:public vm {
|
||||
class dbg: public vm {
|
||||
private:
|
||||
typedef void (dbg::*nasal_vm_func)();
|
||||
const nasal_vm_func operand_function[op_ret + 1] = {
|
||||
|
@ -139,8 +139,8 @@ private:
|
|||
private:
|
||||
bool next;
|
||||
usize fsize;
|
||||
u16 bk_fidx;
|
||||
u32 bk_line;
|
||||
u16 break_file_index;
|
||||
u32 break_line;
|
||||
error src;
|
||||
|
||||
private:
|
||||
|
@ -159,7 +159,7 @@ private:
|
|||
public:
|
||||
dbg():
|
||||
next(true), fsize(0),
|
||||
bk_fidx(0), bk_line(0),
|
||||
break_file_index(0), break_line(0),
|
||||
do_profiling(false) {}
|
||||
void run(
|
||||
const codegen&,
|
||||
|
|
|
@ -352,21 +352,21 @@ var gc::alloc(u8 type) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void gc::ctxchg(nas_co& co) {
|
||||
void gc::context_change(nas_co* co) {
|
||||
// store running state to main context
|
||||
main_context = *running_context;
|
||||
|
||||
// restore coroutine context state
|
||||
*running_context = co.ctx;
|
||||
*running_context = co->ctx;
|
||||
|
||||
// set coroutine pointer
|
||||
cort = &co;
|
||||
cort = co;
|
||||
|
||||
// set coroutine state to running
|
||||
cort->status = nas_co::status::running;
|
||||
}
|
||||
|
||||
void gc::ctxreserve() {
|
||||
void gc::context_reserve() {
|
||||
// pc=0 means this coroutine is finished
|
||||
cort->status = running_context->pc?
|
||||
nas_co::status::suspended:
|
||||
|
|
|
@ -88,8 +88,8 @@ public:
|
|||
void clear();
|
||||
void info() const;
|
||||
var alloc(const u8);
|
||||
void ctxchg(nas_co&);
|
||||
void ctxreserve();
|
||||
void context_change(nas_co*);
|
||||
void context_reserve();
|
||||
|
||||
public:
|
||||
var newstr(char c) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "nasal_import.h"
|
||||
#include "symbol_finder.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace nasal {
|
||||
|
||||
linker::linker():
|
||||
|
@ -234,10 +236,14 @@ code_block* linker::import_nasal_lib() {
|
|||
|
||||
// start importing...
|
||||
if (lex.scan(filename).geterr()) {
|
||||
err.err("link", "error occurred when analysing library <" + filename + ">");
|
||||
err.err("link",
|
||||
"error occurred when analysing library <" + filename + ">"
|
||||
);
|
||||
}
|
||||
if (par.compile(lex).geterr()) {
|
||||
err.err("link", "error occurred when analysing library <" + filename + ">");
|
||||
err.err("link",
|
||||
"error occurred when analysing library <" + filename + ">"
|
||||
);
|
||||
}
|
||||
auto tmp = par.swap(nullptr);
|
||||
|
||||
|
@ -245,41 +251,71 @@ code_block* linker::import_nasal_lib() {
|
|||
return load(tmp, find(filename));
|
||||
}
|
||||
|
||||
std::string linker::generate_module_name(const std::string& filename) {
|
||||
auto error_name = "error_generated@[" + filename + "]";
|
||||
auto pos = filename.find_last_of(".nas");
|
||||
if (pos==std::string::npos) {
|
||||
std::string linker::generate_module_name(const std::string& file_path) {
|
||||
auto error_name = "module@[" + file_path + "]";
|
||||
if (!file_path.length()) {
|
||||
return error_name;
|
||||
}
|
||||
pos -= 4;
|
||||
auto split_pos = filename.find_last_of("/");
|
||||
if (split_pos==std::string::npos) {
|
||||
split_pos = filename.find_last_of("\\");
|
||||
|
||||
// check file suffix and get file suffix position
|
||||
auto suffix_position = file_path.find(".nas");
|
||||
if (suffix_position==std::string::npos) {
|
||||
err.warn("link",
|
||||
"get invalid module name from <" + file_path + ">, " +
|
||||
"will not be easily accessed. " +
|
||||
"\".nas\" suffix is required."
|
||||
);
|
||||
return error_name;
|
||||
}
|
||||
auto res = split_pos==std::string::npos?
|
||||
filename.substr(0, pos + 1):
|
||||
filename.substr(split_pos + 1, pos - split_pos);
|
||||
if (!res.length()) {
|
||||
err.warn("link", "get empty module name from <" + filename + ">, " +
|
||||
"will not be easily accessed.");
|
||||
if (suffix_position+4!=file_path.length()) {
|
||||
err.warn("link",
|
||||
"get invalid module name from <" + file_path + ">, " +
|
||||
"will not be easily accessed. " +
|
||||
"only one \".nas\" suffix is required in the path."
|
||||
);
|
||||
return error_name;
|
||||
}
|
||||
if (res.length() && '0' <= res[0] && res[0] <= '9') {
|
||||
err.warn("link", "get module <" + res + "> from <" + filename + ">, " +
|
||||
"will not be easily accessed.");
|
||||
|
||||
// only get the file name as module name, directory path is not included
|
||||
auto split_position = file_path.find_last_of("/");
|
||||
// find "\\" in windows platform
|
||||
if (split_position==std::string::npos) {
|
||||
split_position = file_path.find_last_of("\\");
|
||||
}
|
||||
if (res.length() && res.find(".")!=std::string::npos) {
|
||||
err.warn("link", "get module <" + res + "> from <" + filename + ">, " +
|
||||
"will not be easily accessed.");
|
||||
|
||||
// split file path to get module name
|
||||
auto module_name = split_position==std::string::npos?
|
||||
file_path.substr(0, suffix_position):
|
||||
file_path.substr(split_position+1, suffix_position-split_position-1);
|
||||
|
||||
// check validation of module name
|
||||
if (!module_name.length()) {
|
||||
err.warn("link",
|
||||
"get empty module name from <" + file_path + ">, " +
|
||||
"will not be easily accessed."
|
||||
);
|
||||
}
|
||||
return res;
|
||||
if (module_name.length() && '0' <= module_name[0] && module_name[0] <= '9') {
|
||||
err.warn("link",
|
||||
"get module <" + module_name + "> from <" + file_path + ">, " +
|
||||
"will not be easily accessed."
|
||||
);
|
||||
}
|
||||
if (module_name.length() && module_name.find(".")!=std::string::npos) {
|
||||
err.warn("link",
|
||||
"get module <" + module_name + "> from <" + file_path + ">, " +
|
||||
"will not be easily accessed."
|
||||
);
|
||||
}
|
||||
return module_name;
|
||||
}
|
||||
|
||||
return_expr* linker::generate_module_return(code_block* block) {
|
||||
auto sf = new symbol_finder;
|
||||
auto res = new return_expr(block->get_location());
|
||||
auto finder = std::unique_ptr<symbol_finder>(new symbol_finder);
|
||||
auto result = new return_expr(block->get_location());
|
||||
auto value = new hash_expr(block->get_location());
|
||||
res->set_value(value);
|
||||
for(const auto& i : sf->do_find(block)) {
|
||||
result->set_value(value);
|
||||
for(const auto& i : finder->do_find(block)) {
|
||||
auto pair = new hash_pair(block->get_location());
|
||||
// do not export symbol begins with '_'
|
||||
if (i.name.length() && i.name[0]=='_') {
|
||||
|
@ -289,8 +325,7 @@ return_expr* linker::generate_module_return(code_block* block) {
|
|||
pair->set_value(new identifier(block->get_location(), i.name));
|
||||
value->add_member(pair);
|
||||
}
|
||||
delete sf;
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
definition_expr* linker::generate_module_definition(code_block* block) {
|
||||
|
|
|
@ -28,13 +28,13 @@ const char* opname[] = {
|
|||
};
|
||||
|
||||
void codestream::set(
|
||||
const f64* num_buff,
|
||||
const std::string* str_buff,
|
||||
const nasal_builtin_table* native_table_ptr,
|
||||
const f64* number_list,
|
||||
const std::string* string_list,
|
||||
const nasal_builtin_table* native_table,
|
||||
const std::string* file_list) {
|
||||
nums = num_buff;
|
||||
strs = str_buff;
|
||||
natives = native_table_ptr;
|
||||
const_number = number_list;
|
||||
const_string = string_list;
|
||||
natives = native_table;
|
||||
files = file_list;
|
||||
}
|
||||
|
||||
|
@ -62,24 +62,24 @@ void codestream::dump(std::ostream& out) const {
|
|||
case op_addeqc: case op_subeqc:
|
||||
case op_muleqc:case op_diveqc:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << nums[num] << ")"; break;
|
||||
<< " (" << const_number[num] << ")"; break;
|
||||
case op_lnkeqc:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << rawstr(strs[num], 16) << ")"; break;
|
||||
<< " (" << rawstr(const_string[num], 16) << ")"; break;
|
||||
case op_addecp: case op_subecp:
|
||||
case op_mulecp: case op_divecp:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << nums[num] << ") sp-1"; break;
|
||||
<< " (" << const_number[num] << ") sp-1"; break;
|
||||
case op_lnkecp:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << rawstr(strs[num], 16) << ") sp-1"; break;
|
||||
<< " (" << rawstr(const_string[num], 16) << ") sp-1"; break;
|
||||
case op_addc: case op_subc:
|
||||
case op_mulc: case op_divc:
|
||||
case op_lessc: case op_leqc:
|
||||
case op_grtc: case op_geqc:
|
||||
case op_pnum:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << nums[num] << ")"; break;
|
||||
<< " (" << const_number[num] << ")"; break;
|
||||
case op_callvi: case op_newv:
|
||||
case op_callfv: case op_repl:
|
||||
case op_intl: case op_findex:
|
||||
|
@ -103,7 +103,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
case op_mcallh: case op_para:
|
||||
case op_deft: case op_dyn:
|
||||
out << hex << "0x" << num << dec
|
||||
<< " (" << rawstr(strs[num], 16) << ")"; break;
|
||||
<< " (" << rawstr(const_string[num], 16) << ")"; break;
|
||||
default:
|
||||
if (files) {
|
||||
out << hex << "0x" << num << dec;
|
||||
|
|
|
@ -111,8 +111,8 @@ class codestream {
|
|||
private:
|
||||
opcode code;
|
||||
const u32 index;
|
||||
inline static const f64* nums = nullptr;
|
||||
inline static const std::string* strs = nullptr;
|
||||
inline static const f64* const_number = nullptr;
|
||||
inline static const std::string* const_string = nullptr;
|
||||
inline static const nasal_builtin_table* natives = nullptr;
|
||||
inline static const std::string* files = nullptr;
|
||||
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
var nas_vec::get_value(const i32 n) {
|
||||
var nas_vec::get_value(const i32 index) {
|
||||
i32 size = elems.size();
|
||||
if (n<-size || n>=size) {
|
||||
if (index<-size || index>=size) {
|
||||
return var::none();
|
||||
}
|
||||
return elems[n>=0? n:n+size];
|
||||
return elems[index>=0? index:index+size];
|
||||
}
|
||||
|
||||
var* nas_vec::get_memory(const i32 n) {
|
||||
var* nas_vec::get_memory(const i32 index) {
|
||||
i32 size = elems.size();
|
||||
if (n<-size || n>=size) {
|
||||
if (index<-size || index>=size) {
|
||||
return nullptr;
|
||||
}
|
||||
return &elems[n>=0? n:n+size];
|
||||
return &elems[index>=0? index:index+size];
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
|
||||
|
@ -194,41 +194,41 @@ nas_val::nas_val(u8 val_type) {
|
|||
type = val_type;
|
||||
unmutable = 0;
|
||||
switch(val_type) {
|
||||
case vm_str: ptr.str = new std::string; break;
|
||||
case vm_vec: ptr.vec = new nas_vec; break;
|
||||
case vm_hash: ptr.hash = new nas_hash; break;
|
||||
case vm_func: ptr.func = new nas_func; break;
|
||||
case vm_str: ptr.str = new std::string; break;
|
||||
case vm_vec: ptr.vec = new nas_vec; break;
|
||||
case vm_hash: ptr.hash = new nas_hash; break;
|
||||
case vm_func: ptr.func = new nas_func; break;
|
||||
case vm_upval: ptr.upval = new nas_upval; break;
|
||||
case vm_obj: ptr.obj = new nas_ghost; break;
|
||||
case vm_co: ptr.co = new nas_co; break;
|
||||
case vm_map: ptr.map = new nas_map; break;
|
||||
case vm_obj: ptr.obj = new nas_ghost; break;
|
||||
case vm_co: ptr.co = new nas_co; break;
|
||||
case vm_map: ptr.map = new nas_map; break;
|
||||
}
|
||||
}
|
||||
|
||||
nas_val::~nas_val() {
|
||||
switch(type) {
|
||||
case vm_str: delete ptr.str; break;
|
||||
case vm_vec: delete ptr.vec; break;
|
||||
case vm_hash: delete ptr.hash; break;
|
||||
case vm_func: delete ptr.func; break;
|
||||
case vm_upval:delete ptr.upval;break;
|
||||
case vm_obj: delete ptr.obj; break;
|
||||
case vm_co: delete ptr.co; break;
|
||||
case vm_map: delete ptr.map; break;
|
||||
case vm_str: delete ptr.str; break;
|
||||
case vm_vec: delete ptr.vec; break;
|
||||
case vm_hash: delete ptr.hash; break;
|
||||
case vm_func: delete ptr.func; break;
|
||||
case vm_upval:delete ptr.upval; break;
|
||||
case vm_obj: delete ptr.obj; break;
|
||||
case vm_co: delete ptr.co; break;
|
||||
case vm_map: delete ptr.map; break;
|
||||
}
|
||||
type=vm_nil;
|
||||
}
|
||||
|
||||
void nas_val::clear() {
|
||||
switch(type) {
|
||||
case vm_str: ptr.str->clear(); break;
|
||||
case vm_vec: ptr.vec->elems.clear(); break;
|
||||
case vm_hash: ptr.hash->elems.clear();break;
|
||||
case vm_func: ptr.func->clear(); break;
|
||||
case vm_upval:ptr.upval->clear(); break;
|
||||
case vm_obj: ptr.obj->clear(); break;
|
||||
case vm_co: ptr.co->clear(); break;
|
||||
case vm_map: ptr.map->clear(); break;
|
||||
case vm_str: ptr.str->clear(); break;
|
||||
case vm_vec: ptr.vec->elems.clear(); break;
|
||||
case vm_hash: ptr.hash->elems.clear(); break;
|
||||
case vm_func: ptr.func->clear(); break;
|
||||
case vm_upval:ptr.upval->clear(); break;
|
||||
case vm_obj: ptr.obj->clear(); break;
|
||||
case vm_co: ptr.co->clear(); break;
|
||||
case vm_map: ptr.map->clear(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ std::string var::to_str() {
|
|||
if (type==vm_str) {
|
||||
return str();
|
||||
} else if (type==vm_num) {
|
||||
std::string tmp=std::to_string(num());
|
||||
std::string tmp = std::to_string(num());
|
||||
tmp.erase(tmp.find_last_not_of('0')+1, std::string::npos);
|
||||
tmp.erase(tmp.find_last_not_of('.')+1, std::string::npos);
|
||||
return tmp;
|
||||
|
@ -257,7 +257,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
|
|||
case vm_vec: out << ref.vec(); break;
|
||||
case vm_hash: out << ref.hash(); break;
|
||||
case vm_func: out << "func(..) {..}"; break;
|
||||
case vm_obj: out << ref.obj(); break;
|
||||
case vm_obj: out << ref.ghost(); break;
|
||||
case vm_co: out << ref.co(); break;
|
||||
case vm_map: out << ref.map(); break;
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
|
|||
}
|
||||
|
||||
bool var::object_check(const std::string& name) {
|
||||
return type==vm_obj && obj().type_name==name && obj().pointer;
|
||||
return type==vm_obj && ghost().type_name==name && ghost().pointer;
|
||||
}
|
||||
|
||||
var var::none() {
|
||||
|
@ -300,7 +300,7 @@ var* var::addr() {
|
|||
return val.addr;
|
||||
}
|
||||
|
||||
u32 var::ret() {
|
||||
u32 var::ret() const {
|
||||
return val.ret;
|
||||
}
|
||||
|
||||
|
@ -308,7 +308,7 @@ i64& var::cnt() {
|
|||
return val.cnt;
|
||||
}
|
||||
|
||||
f64 var::num() {
|
||||
f64 var::num() const {
|
||||
return val.num;
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ nas_upval& var::upval() {
|
|||
return *val.gcobj->ptr.upval;
|
||||
}
|
||||
|
||||
nas_ghost& var::obj() {
|
||||
nas_ghost& var::ghost() {
|
||||
return *val.gcobj->ptr.obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@ enum vm_type:u8 {
|
|||
vm_upval, // upvalue
|
||||
vm_obj, // ghost type
|
||||
vm_co, // coroutine
|
||||
vm_map // for globals and namespaces
|
||||
vm_map, // for globals and namespaces
|
||||
/* mark type range */
|
||||
vm_type_size_max
|
||||
};
|
||||
|
||||
// size of gc object type
|
||||
const u32 gc_type_size = vm_map-vm_str+1;
|
||||
const u32 gc_type_size = vm_type_size_max-vm_str;
|
||||
|
||||
// basic types
|
||||
struct nas_vec; // vector
|
||||
|
@ -85,15 +87,15 @@ public:
|
|||
|
||||
// get value
|
||||
var* addr();
|
||||
u32 ret();
|
||||
u32 ret() const;
|
||||
i64& cnt();
|
||||
f64 num();
|
||||
f64 num() const;
|
||||
std::string& str();
|
||||
nas_vec& vec();
|
||||
nas_hash& hash();
|
||||
nas_func& func();
|
||||
nas_upval& upval();
|
||||
nas_ghost& obj();
|
||||
nas_ghost& ghost();
|
||||
nas_co& co();
|
||||
nas_map& map();
|
||||
};
|
||||
|
|
|
@ -93,7 +93,7 @@ void vm::value_info(var& val) {
|
|||
<< " val}"; break;
|
||||
case vm_obj: std::clog << "| obj | <0x" << std::hex << p
|
||||
<< "> obj:0x"
|
||||
<< reinterpret_cast<u64>(val.obj().pointer)
|
||||
<< reinterpret_cast<u64>(val.ghost().pointer)
|
||||
<< std::dec; break;
|
||||
case vm_co: std::clog << "| co | <0x" << std::hex << p
|
||||
<< std::dec << "> coroutine"; break;
|
||||
|
@ -170,12 +170,12 @@ void vm::function_call_trace() {
|
|||
}
|
||||
|
||||
void vm::trace_back() {
|
||||
var* bottom = ctx.stack;
|
||||
var* top = ctx.top;
|
||||
// var* bottom = ctx.stack;
|
||||
// var* top = ctx.top;
|
||||
|
||||
// generate trace back
|
||||
std::stack<u32> ret;
|
||||
for(var* i = bottom; i<=top; ++i) {
|
||||
for(var* i = ctx.stack; i<=ctx.top; ++i) {
|
||||
if (i->type==vm_ret && i->ret()!=0) {
|
||||
ret.push(i->ret());
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ void vm::die(const std::string& str) {
|
|||
} else {
|
||||
// in coroutine, shut down the coroutine and return to main context
|
||||
ctx.pc = 0; // mark coroutine 'dead'
|
||||
ngc.ctxreserve(); // switch context to main
|
||||
ngc.context_reserve(); // switch context to main
|
||||
ctx.top[0] = nil; // generate return value 'nil'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1024,7 +1024,7 @@ inline void vm::o_ret() {
|
|||
// because there maybe another function call inside but return here
|
||||
// coroutine function ends with setting pc to 0
|
||||
if (!ctx.pc) {
|
||||
ngc.ctxreserve();
|
||||
ngc.context_reserve();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ var builtin_opendir(context* ctx, gc* ngc) {
|
|||
}
|
||||
#endif
|
||||
var ret = ngc->alloc(vm_obj);
|
||||
ret.obj().set(dir_type_name, dir_entry_destructor, p);
|
||||
ret.ghost().set(dir_type_name, dir_entry_destructor, p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -84,12 +84,12 @@ var builtin_readdir(context* ctx, gc* ngc) {
|
|||
}
|
||||
#ifdef _MSC_VER
|
||||
WIN32_FIND_DATAA data;
|
||||
if (!FindNextFileA(handle.obj().pointer, &data)) {
|
||||
if (!FindNextFileA(handle.ghost().pointer, &data)) {
|
||||
return nil;
|
||||
}
|
||||
return ngc->newstr(data.cFileName);
|
||||
#else
|
||||
dirent* p = readdir(static_cast<DIR*>(handle.obj().pointer));
|
||||
dirent* p = readdir(static_cast<DIR*>(handle.ghost().pointer));
|
||||
return p? ngc->newstr(p->d_name):nil;
|
||||
#endif
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ var builtin_closedir(context* ctx, gc* ngc) {
|
|||
if (!handle.object_check(dir_type_name)) {
|
||||
return nas_err("unix::closedir", "not a valid dir handle");
|
||||
}
|
||||
handle.obj().clear();
|
||||
handle.ghost().clear();
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,5 +24,5 @@ while(1) {
|
|||
res ~= "\n";
|
||||
}
|
||||
print(res);
|
||||
unix.sleep(1/20);
|
||||
unix.sleep(1/15);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue