improve readability of some codes

This commit is contained in:
ValKmjolnir 2023-10-22 23:45:10 +08:00
parent 1e1ab37e83
commit 9629108a1e
22 changed files with 386 additions and 325 deletions

View File

@ -53,7 +53,7 @@ void ghost_for_test_destructor(void* ptr) {
var create_new_ghost(var* args, usize size, gc* ngc) { var create_new_ghost(var* args, usize size, gc* ngc) {
var res = ngc->alloc(vm_obj); 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; return res;
} }
@ -64,7 +64,7 @@ var set_new_ghost(var* args, usize size, gc* ngc) {
return nil; return nil;
} }
f64 num = args[1].num(); 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"; std::cout << "set_new_ghost: successfully set ghost = " << num << "\n";
return nil; 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"; std::cout << "print_new_ghost: not ghost for test type.\n";
return nil; return nil;
} }
std::cout << "print_new_ghost: " << res.obj() << " result = " std::cout << "print_new_ghost: " << res.ghost() << " result = "
<< *((u32*)res.obj().pointer) << "\n"; << *((u32*)res.ghost().pointer) << "\n";
return nil; return nil;
} }

View File

@ -49,15 +49,15 @@ var builtin_fld(context* ctx, gc* ngc) {
auto startbit = local[2]; auto startbit = local[2];
auto length = local[3]; auto length = local[3];
if (str.type!=vm_str || str.val.gcobj->unmutable) { 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) { 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 bit = static_cast<u32>(startbit.num());
u32 len = static_cast<u32>(length.num()); u32 len = static_cast<u32>(length.num());
if (bit+len>8*str.str().length()) { 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; u32 res = 0;
auto& s = str.str(); auto& s = str.str();
@ -79,15 +79,15 @@ var builtin_sfld(context* ctx, gc* ngc) {
auto startbit = local[2]; auto startbit = local[2];
auto length = local[3]; auto length = local[3];
if (str.type!=vm_str || str.val.gcobj->unmutable) { 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) { 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 bit = static_cast<u32>(startbit.num());
u32 len = static_cast<u32>(length.num()); u32 len = static_cast<u32>(length.num());
if (bit+len>8*str.str().length()) { 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; u32 res = 0;
auto& s = str.str(); auto& s = str.str();
@ -113,16 +113,18 @@ var builtin_setfld(context* ctx, gc* ngc) {
auto length = local[3]; auto length = local[3];
auto value = local[4]; auto value = local[4];
if (str.type!=vm_str || str.val.gcobj->unmutable) { 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) { 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 bit = static_cast<u32>(startbit.num());
u32 len = static_cast<u32>(length.num()); u32 len = static_cast<u32>(length.num());
u64 val = static_cast<u64>(value.num()); u64 val = static_cast<u64>(value.num());
if (bit+len>8*str.str().length()) { 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(); auto& s = str.str();
for(u32 i = bit; i<bit+len; ++i) { 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 builtin_buf(context* ctx, gc* ngc) {
var length = ctx->localr[1]; var length = ctx->localr[1];
if (length.type!=vm_num || length.num()<=0) { 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); var str = ngc->alloc(vm_str);
auto& s = str.str(); auto& s = str.str();

View File

@ -75,7 +75,7 @@ var builtin_coresume(context* ctx, gc* ngc) {
} }
// change to coroutine context // change to coroutine context
ngc->ctxchg(coroutine_object.co()); ngc->context_change(&coroutine_object.co());
// fetch coroutine's stack top and return // fetch coroutine's stack top and return
// then coroutine's stack top will catch this return value // 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; auto coroutine_local_frame = ctx->localr;
// vm context will set to main context // vm context will set to main context
ngc->ctxreserve(); ngc->context_reserve();
// then this will return value to main's stack top[0] // then this will return value to main's stack top[0]
// the procedure seems like coroutine.resume returns the value // the procedure seems like coroutine.resume returns the value

View File

@ -2,89 +2,108 @@
namespace nasal { namespace nasal {
const auto dylib_type_name = "dylib"; const auto dynamic_library_type_name = "dylib";
const auto func_addr_type_name = "faddr"; const auto function_address_type_name = "faddr";
void dylib_destructor(void* ptr) { void dynamic_library_destructor(void* pointer) {
#ifdef _WIN32 #ifdef _WIN32
FreeLibrary(static_cast<HMODULE>(ptr)); FreeLibrary(static_cast<HMODULE>(pointer));
#else #else
dlclose(ptr); dlclose(pointer);
#endif #endif
} }
void func_addr_destructor(void* ptr) {}
var builtin_dlopen(context* ctx, gc* ngc) { var builtin_dlopen(context* ctx, gc* ngc) {
auto dlname = ctx->localr[1]; auto dlname = ctx->localr[1];
if (dlname.type!=vm_str) { 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 #ifdef _WIN32
void* func = (void*)GetProcAddress( wchar_t* wide_string = new wchar_t[dlname.str().size()+1];
static_cast<HMODULE>(lib.obj().pointer), if (!wide_string) {
"get" 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 #else
void* func = dlsym(lib.obj().pointer, "get"); void* register_table_get_function = dlsym(
library_object.ghost().pointer, "get"
);
#endif #endif
if (!func) { if (!register_table_get_function) {
return nas_err("dlopen", "cannot find <get> function"); return nas_err("dylib::dlopen", "cannot find <get> function");
} }
// get function pointer by name // get function pointer by name
auto tbl = reinterpret_cast<get_func_ptr>(func)(); auto table = reinterpret_cast<get_func_ptr>(register_table_get_function)();
if (!tbl) { if (!table) {
return nas_err("dlopen", "failed to get module functions"); return nas_err("dylib::dlopen", "failed to get module functions");
} }
for(u32 i = 0; tbl[i].name; ++i) { for(u32 i = 0; table[i].name; ++i) {
void* p = (void*)tbl[i].fd; auto function_pointer = reinterpret_cast<void*>(table[i].fd);
var tmp = ngc->alloc(vm_obj); auto function_object = ngc->alloc(vm_obj);
tmp.obj().set(func_addr_type_name, func_addr_destructor, p); function_object.ghost().set(
ret.hash().elems[tbl[i].name] = tmp; function_address_type_name,
nullptr,
function_pointer
);
return_hash.hash().elems[table[i].name] = function_object;
} }
ngc->temp = nil; ngc->temp = nil;
return ret; return return_hash;
} }
var builtin_dlclose(context* ctx, gc* ngc) { var builtin_dlclose(context* ctx, gc* ngc) {
auto libptr = ctx->localr[1]; auto library_pointer = ctx->localr[1];
if (!libptr.object_check(dylib_type_name)) { if (!library_pointer.object_check(dynamic_library_type_name)) {
return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); return nas_err("dylib::dlclose", "\"lib\" is not a valid dynamic lib");
} }
libptr.obj().clear(); library_pointer.ghost().clear();
return nil; return nil;
} }
var builtin_dlcallv(context* ctx, gc* ngc) { var builtin_dlcallv(context* ctx, gc* ngc) {
auto local = ctx->localr; auto function_object = ctx->localr[1];
auto fp = local[1]; auto arguments = ctx->localr[2];
auto args = local[2]; if (!function_object.object_check(function_address_type_name)) {
if (!fp.object_check(func_addr_type_name)) { return nas_err("dylib::dlcall",
return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); "\"ptr\" is not a valid function pointer"
);
} }
auto& vec = args.vec().elems; auto& vec = arguments.vec().elems;
return reinterpret_cast<module_func>(fp.obj().pointer)( return reinterpret_cast<module_func>(function_object.ghost().pointer)(
vec.data(), vec.data(),
vec.size(), vec.size(),
ngc ngc
@ -92,16 +111,18 @@ var builtin_dlcallv(context* ctx, gc* ngc) {
} }
var builtin_dlcall(context* ctx, gc* ngc) { var builtin_dlcall(context* ctx, gc* ngc) {
auto local = ctx->localr; auto function_object = ctx->localr[1];
var fp = local[1]; if (!function_object.object_check(function_address_type_name)) {
if (!fp.object_check(func_addr_type_name)) { return nas_err("dylib::dlcall",
return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); "\"ptr\" is not a valid function pointer"
);
} }
var* local_frame_start = local+2; // function pointer is at ctx->localr[1]
usize local_frame_size = ngc->running_context->top-local_frame_start; // so arguments starts from ctx->localr[2]
// arguments' stored place begins at local +2 var* local_frame_start = ctx->localr + 2;
return reinterpret_cast<module_func>(fp.obj().pointer)( 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_start,
local_frame_size, local_frame_size,
ngc ngc

View File

@ -13,8 +13,7 @@
namespace nasal { namespace nasal {
void dylib_destructor(void*); void dynamic_library_destructor(void*);
void func_addr_destructor(void*);
var builtin_dlopen(context*, gc*); var builtin_dlopen(context*, gc*);
var builtin_dlclose(context*, gc*); var builtin_dlclose(context*, gc*);

View File

@ -9,7 +9,7 @@ var builtin_logprint(context* ctx, gc* ngc) {
auto level = local[1]; auto level = local[1];
auto elems = local[2]; auto elems = local[2];
if (elems.type!=vm_vec) { 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); std::ofstream out("fgfs.log", std::ios::app);
switch (static_cast<u32>(level.num())) { 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_DEV_ALERT: out << "[DEV_ALERT]"; break;
case SG_MANDATORY_INFO: out << "[MANDATORY_INFO]"; break; case SG_MANDATORY_INFO: out << "[MANDATORY_INFO]"; break;
default: default:
return nas_err("logprint", return nas_err("fg_env::logprint",
"incorrect log level " + "incorrect log level " + std::to_string(level.num())
std::to_string(level.num())
); );
} }
for(auto& i : elems.vec().elems) { for(auto& value : elems.vec().elems) {
out << i << " "; out << value << " ";
} }
out << "\n"; out << "\n";
return nil; return nil;

View File

@ -12,11 +12,11 @@ void filehandle_destructor(void* ptr) {
} }
var builtin_readfile(context* ctx, gc* ngc) { var builtin_readfile(context* ctx, gc* ngc) {
auto val = ctx->localr[1]; auto filename = ctx->localr[1];
if (val.type!=vm_str) { if (filename.type!=vm_str) {
return nas_err("io::readfile", "\"filename\" must be string"); 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; std::stringstream rd;
if (!in.fail()) { if (!in.fail()) {
rd << in.rdbuf(); rd << in.rdbuf();
@ -26,25 +26,25 @@ var builtin_readfile(context* ctx, gc* ngc) {
var builtin_fout(context* ctx, gc* ngc) { var builtin_fout(context* ctx, gc* ngc) {
auto local = ctx->localr; auto local = ctx->localr;
auto val = local[1]; auto filename = local[1];
auto str = local[2]; auto source = local[2];
if (val.type!=vm_str) { if (filename.type!=vm_str) {
return nas_err("io::fout", "\"filename\" must be string"); return nas_err("io::fout", "\"filename\" must be string");
} }
std::ofstream out(val.str()); std::ofstream out(filename.str());
if (out.fail()) { 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; return nil;
} }
var builtin_exists(context* ctx, gc* ngc) { var builtin_exists(context* ctx, gc* ngc) {
auto local = ctx->localr; auto filename = ctx->localr[1];
if (local[1].type!=vm_str) { if (filename.type!=vm_str) {
return zero; 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) { var builtin_open(context* ctx, gc* ngc) {
@ -52,118 +52,121 @@ var builtin_open(context* ctx, gc* ngc) {
auto name = local[1]; auto name = local[1];
auto mode = local[2]; auto mode = local[2];
if (name.type!=vm_str) { 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) { 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()); auto file_descriptor = fopen(name.str().c_str(), mode.str().c_str());
if (!res) { if (!file_descriptor) {
return nas_err("open", "failed to open file <"+name.str()+">"); return nas_err("io::open", "failed to open file <" + name.str() + ">");
} }
var ret = ngc->alloc(vm_obj); var return_object = ngc->alloc(vm_obj);
ret.obj().set(file_type_name, filehandle_destructor, res); return_object.ghost().set(
return ret; file_type_name, filehandle_destructor, file_descriptor
);
return return_object;
} }
var builtin_close(context* ctx, gc* ngc) { var builtin_close(context* ctx, gc* ngc) {
var fd = ctx->localr[1]; var file_descriptor = ctx->localr[1];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("close", "not a valid filehandle"); return nas_err("io::close", "not a valid filehandle");
} }
fd.obj().clear(); file_descriptor.ghost().clear();
return nil; return nil;
} }
var builtin_read(context* ctx, gc* ngc) { var builtin_read(context* ctx, gc* ngc) {
auto local = ctx->localr; auto local = ctx->localr;
auto fd = local[1]; auto file_descriptor = local[1];
auto buf = local[2]; auto buffer = local[2];
auto len = local[3]; auto length = local[3];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("read", "not a valid filehandle"); return nas_err("io::read", "not a valid filehandle");
} }
if (buf.type!=vm_str || buf.val.gcobj->unmutable) { if (buffer.type!=vm_str || buffer.val.gcobj->unmutable) {
return nas_err("read", "\"buf\" must be mutable string"); return nas_err("io::read", "\"buf\" must be mutable string");
} }
if (len.type!=vm_num) { if (length.type!=vm_num) {
return nas_err("read", "\"len\" must be number"); return nas_err("io::read", "\"len\" must be number");
} }
if (len.num()<=0 || len.num()>=(1<<30)) { if (length.num()<=0 || length.num()>=(1<<30)) {
return nas_err("read", "\"len\" less than 1 or too large"); return nas_err("io::read", "\"len\" less than 1 or too large");
} }
char* buff = new char[(usize)len.num()+1]; auto temp_buffer = new char[static_cast<usize>(length.num())+1];
if (!buff) { if (!temp_buffer) {
return nas_err("read", "malloc failed"); return nas_err("io::read", "malloc failed");
} }
f64 res = fread(buff, 1, len.num(), static_cast<FILE*>(fd.obj().pointer)); auto read_size = fread(
buf.str() = buff; temp_buffer, 1, length.num(),
buf.val.gcobj->unmutable = true; static_cast<FILE*>(file_descriptor.ghost().pointer)
delete []buff; );
return var::num(res); buffer.str() = temp_buffer;
buffer.val.gcobj->unmutable = true;
delete []temp_buffer;
return var::num(read_size);
} }
var builtin_write(context* ctx, gc* ngc) { var builtin_write(context* ctx, gc* ngc) {
auto local = ctx->localr; auto local = ctx->localr;
auto fd = local[1]; auto file_descriptor = local[1];
auto str = local[2]; auto source = local[2];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("write", "not a valid filehandle"); return nas_err("io::write", "not a valid filehandle");
} }
if (str.type!=vm_str) { if (source.type!=vm_str) {
return nas_err("write", "\"str\" must be string"); return nas_err("io::write", "\"str\" must be string");
} }
return var::num(static_cast<f64>(fwrite( return var::num(static_cast<f64>(fwrite(
str.str().c_str(), source.str().c_str(), 1, source.str().length(),
1, static_cast<FILE*>(file_descriptor.ghost().pointer)
str.str().length(),
static_cast<FILE*>(fd.obj().pointer)
))); )));
} }
var builtin_seek(context* ctx, gc* ngc) { var builtin_seek(context* ctx, gc* ngc) {
auto local = ctx->localr; auto local = ctx->localr;
auto fd = local[1]; auto file_descriptor = local[1];
auto pos = local[2]; auto position = local[2];
auto whence = local[3]; auto whence = local[3];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("seek", "not a valid filehandle"); return nas_err("io::seek", "not a valid filehandle");
} }
return var::num(static_cast<f64>(fseek( return var::num(static_cast<f64>(fseek(
static_cast<FILE*>(fd.obj().pointer), static_cast<FILE*>(file_descriptor.ghost().pointer),
pos.num(), position.num(),
whence.num() whence.num()
))); )));
} }
var builtin_tell(context* ctx, gc* ngc) { var builtin_tell(context* ctx, gc* ngc) {
auto fd = ctx->localr[1]; auto file_descriptor = ctx->localr[1];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("tell", "not a valid filehandle"); return nas_err("io::tell", "not a valid filehandle");
} }
return var::num(static_cast<f64>( 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) { var builtin_readln(context* ctx, gc* ngc) {
auto fd = ctx->localr[1]; auto file_descriptor = ctx->localr[1];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("readln", "not a valid filehandle"); return nas_err("io::readln", "not a valid filehandle");
} }
auto str = ngc->alloc(vm_str); auto result = ngc->alloc(vm_str);
char c; 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') { if (c=='\r') {
continue; continue;
} }
if (c=='\n') { if (c=='\n') {
return str; return result;
} }
str.str() += c; result.str().push_back(c);
} }
if (str.str().length()) { if (result.str().length()) {
return str; return result;
} }
return nil; return nil;
} }
@ -171,36 +174,36 @@ var builtin_readln(context* ctx, gc* ngc) {
var builtin_stat(context* ctx, gc* ngc) { var builtin_stat(context* ctx, gc* ngc) {
auto name = ctx->localr[1]; auto name = ctx->localr[1];
if (name.type!=vm_str) { 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; struct stat buffer;
if (stat(name.str().c_str(), &buf)<0) { if (stat(name.str().c_str(), &buffer)<0) {
return nas_err("stat", "failed to open file <"+name.str()+">"); return nas_err("io::stat", "failed to open file <" + name.str() + ">");
} }
auto ret = ngc->alloc(vm_vec); auto result = ngc->alloc(vm_vec);
ret.vec().elems = { result.vec().elems = {
var::num(static_cast<f64>(buf.st_dev)), var::num(static_cast<f64>(buffer.st_dev)),
var::num(static_cast<f64>(buf.st_ino)), var::num(static_cast<f64>(buffer.st_ino)),
var::num(static_cast<f64>(buf.st_mode)), var::num(static_cast<f64>(buffer.st_mode)),
var::num(static_cast<f64>(buf.st_nlink)), var::num(static_cast<f64>(buffer.st_nlink)),
var::num(static_cast<f64>(buf.st_uid)), var::num(static_cast<f64>(buffer.st_uid)),
var::num(static_cast<f64>(buf.st_gid)), var::num(static_cast<f64>(buffer.st_gid)),
var::num(static_cast<f64>(buf.st_rdev)), var::num(static_cast<f64>(buffer.st_rdev)),
var::num(static_cast<f64>(buf.st_size)), var::num(static_cast<f64>(buffer.st_size)),
var::num(static_cast<f64>(buf.st_atime)), var::num(static_cast<f64>(buffer.st_atime)),
var::num(static_cast<f64>(buf.st_mtime)), var::num(static_cast<f64>(buffer.st_mtime)),
var::num(static_cast<f64>(buf.st_ctime)) var::num(static_cast<f64>(buffer.st_ctime))
}; };
return ret; return result;
} }
var builtin_eof(context* ctx, gc* ngc) { var builtin_eof(context* ctx, gc* ngc) {
auto fd = ctx->localr[1]; auto file_descriptor = ctx->localr[1];
if (!fd.object_check(file_type_name)) { if (!file_descriptor.object_check(file_type_name)) {
return nas_err("readln", "not a valid filehandle"); return nas_err("io::readln", "not a valid filehandle");
} }
return var::num(static_cast<f64>( return var::num(static_cast<f64>(
feof(static_cast<FILE*>(fd.obj().pointer)) feof(static_cast<FILE*>(file_descriptor.ghost().pointer))
)); ));
} }

View File

@ -77,7 +77,7 @@ public:
virtual void accept(ast_visitor*); virtual void accept(ast_visitor*);
}; };
class call:public expr { class call: public expr {
public: public:
call(const span& location, expr_type node_type): call(const span& location, expr_type node_type):
expr(location, node_type) {} expr(location, node_type) {}
@ -85,7 +85,7 @@ public:
virtual void accept(ast_visitor*); virtual void accept(ast_visitor*);
}; };
class null_expr:public expr { class null_expr: public expr {
public: public:
null_expr(const span& location): null_expr(const span& location):
expr(location, expr_type::ast_null) {} expr(location, expr_type::ast_null) {}
@ -93,7 +93,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class nil_expr:public expr { class nil_expr: public expr {
public: public:
nil_expr(const span& location): nil_expr(const span& location):
expr(location, expr_type::ast_nil) {} expr(location, expr_type::ast_nil) {}
@ -101,7 +101,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class number_literal:public expr { class number_literal: public expr {
private: private:
f64 number; f64 number;
@ -113,7 +113,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class string_literal:public expr { class string_literal: public expr {
private: private:
std::string content; std::string content;
@ -125,7 +125,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class identifier:public expr { class identifier: public expr {
private: private:
std::string name; std::string name;
@ -137,7 +137,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class bool_literal:public expr { class bool_literal: public expr {
private: private:
bool flag; bool flag;
@ -149,7 +149,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class vector_expr:public expr { class vector_expr: public expr {
private: private:
std::vector<expr*> elements; std::vector<expr*> elements;
@ -162,7 +162,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class hash_expr:public expr { class hash_expr: public expr {
private: private:
std::vector<hash_pair*> members; std::vector<hash_pair*> members;
@ -175,7 +175,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class hash_pair:public expr { class hash_pair: public expr {
private: private:
std::string name; std::string name;
expr* value; expr* value;
@ -192,7 +192,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class function:public expr { class function: public expr {
private: private:
std::vector<parameter*> parameter_list; std::vector<parameter*> parameter_list;
code_block* block; code_block* block;
@ -209,7 +209,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class code_block:public expr { class code_block: public expr {
private: private:
std::vector<expr*> expressions; std::vector<expr*> expressions;
@ -222,7 +222,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class parameter:public expr { class parameter: public expr {
public: public:
enum class param_type { enum class param_type {
normal_parameter, normal_parameter,
@ -249,7 +249,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class ternary_operator:public expr { class ternary_operator: public expr {
private: private:
expr* condition; expr* condition;
expr* left; expr* left;
@ -269,7 +269,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class binary_operator:public expr { class binary_operator: public expr {
public: public:
enum class binary_type { enum class binary_type {
add, add,
@ -317,7 +317,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class unary_operator:public expr { class unary_operator: public expr {
public: public:
enum class unary_type { enum class unary_type {
negative, negative,
@ -344,7 +344,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class call_expr:public expr { class call_expr: public expr {
private: private:
expr* first; expr* first;
std::vector<call*> calls; std::vector<call*> calls;
@ -361,7 +361,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class call_hash:public call { class call_hash: public call {
private: private:
std::string field; std::string field;
@ -374,7 +374,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class call_vector:public call { class call_vector: public call {
private: private:
std::vector<slice_vector*> calls; std::vector<slice_vector*> calls;
@ -387,7 +387,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class call_function:public call { class call_function: public call {
private: private:
std::vector<expr*> args; std::vector<expr*> args;
@ -400,7 +400,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class slice_vector:public expr { class slice_vector: public expr {
private: private:
expr* begin; expr* begin;
expr* end; expr* end;
@ -417,7 +417,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class definition_expr:public expr { class definition_expr: public expr {
private: private:
identifier* variable_name; identifier* variable_name;
multi_identifier* variables; multi_identifier* variables;
@ -441,7 +441,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class assignment_expr:public expr { class assignment_expr: public expr {
public: public:
enum class assign_type { enum class assign_type {
equal, equal,
@ -474,7 +474,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class multi_identifier:public expr { class multi_identifier: public expr {
private: private:
std::vector<identifier*> variables; std::vector<identifier*> variables;
@ -487,7 +487,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class tuple_expr:public expr { class tuple_expr: public expr {
private: private:
std::vector<expr*> elements; std::vector<expr*> elements;
@ -500,7 +500,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class multi_assign:public expr { class multi_assign: public expr {
private: private:
tuple_expr* tuple; tuple_expr* tuple;
expr* value; expr* value;
@ -517,7 +517,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class while_expr:public expr { class while_expr: public expr {
private: private:
expr* condition; expr* condition;
code_block* block; code_block* block;
@ -534,7 +534,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class for_expr:public expr { class for_expr: public expr {
private: private:
expr* initializing; expr* initializing;
expr* condition; expr* condition;
@ -558,7 +558,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class iter_expr:public expr { class iter_expr: public expr {
private: private:
identifier* name; identifier* name;
call_expr* call; call_expr* call;
@ -575,7 +575,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class forei_expr:public expr { class forei_expr: public expr {
public: public:
enum class forei_loop_type { enum class forei_loop_type {
foreach, foreach,
@ -605,7 +605,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class condition_expr:public expr { class condition_expr: public expr {
private: private:
if_expr* if_stmt; if_expr* if_stmt;
std::vector<if_expr*> elsif_stmt; std::vector<if_expr*> elsif_stmt;
@ -625,7 +625,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class if_expr:public expr { class if_expr: public expr {
private: private:
expr* condition; expr* condition;
code_block* block; code_block* block;
@ -642,7 +642,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class continue_expr:public expr { class continue_expr: public expr {
public: public:
continue_expr(const span& location): continue_expr(const span& location):
expr(location, expr_type::ast_continue) {} expr(location, expr_type::ast_continue) {}
@ -650,7 +650,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class break_expr:public expr { class break_expr: public expr {
public: public:
break_expr(const span& location): break_expr(const span& location):
expr(location, expr_type::ast_break) {} expr(location, expr_type::ast_break) {}
@ -658,7 +658,7 @@ public:
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
class return_expr:public expr { class return_expr: public expr {
private: private:
expr* value; expr* value;

View File

@ -632,9 +632,9 @@ var builtin_ghosttype(context* ctx, gc* ngc) {
if (arg.type!=vm_obj) { if (arg.type!=vm_obj) {
return nas_err("ghosttype", "this is not a ghost object."); 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()) { 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); return ngc->newstr(name);
} }

View File

@ -160,7 +160,7 @@ void dbg::step_info() {
begin = (ctx.pc>>3)==0? 0:((ctx.pc>>3)<<3); begin = (ctx.pc>>3)==0? 0:((ctx.pc>>3)<<3);
end = (1+(ctx.pc>>3))<<3; end = (1+(ctx.pc>>3))<<3;
codestream::set(const_number, const_string, native_function.data(), files); 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) { for(u32 i = begin; i<end && bytecode[i].op!=op_exit; ++i) {
std::clog std::clog
<< (i==ctx.pc? back_white:reset) << (i==ctx.pc? back_white:reset)
@ -184,7 +184,7 @@ void dbg::interact() {
// is not break point and is not next stop command // is not break point and is not next stop command
const auto& code = bytecode[ctx.pc]; 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; return;
} }
@ -217,8 +217,8 @@ void dbg::interact() {
} }
} else if (res.size()==3 && } else if (res.size()==3 &&
get_cmd_type(res[0])==dbg_cmd::cmd_break_point) { get_cmd_type(res[0])==dbg_cmd::cmd_break_point) {
bk_fidx = file_index(res[1]); break_file_index = file_index(res[1]);
if (bk_fidx==65535) { if (break_file_index==65535) {
std::clog << "cannot find file named `" << res[1] << "`\n"; std::clog << "cannot find file named `" << res[1] << "`\n";
continue; continue;
} }
@ -226,7 +226,7 @@ void dbg::interact() {
if (tmp<=0) { if (tmp<=0) {
std::clog << "incorrect line number `" << res[2] << "`\n"; std::clog << "incorrect line number `" << res[2] << "`\n";
} else { } else {
bk_line = tmp; break_line = tmp;
} }
} else { } else {
err(); err();

View File

@ -37,7 +37,7 @@ public:
} }
}; };
class dbg:public vm { class dbg: public vm {
private: private:
typedef void (dbg::*nasal_vm_func)(); typedef void (dbg::*nasal_vm_func)();
const nasal_vm_func operand_function[op_ret + 1] = { const nasal_vm_func operand_function[op_ret + 1] = {
@ -139,8 +139,8 @@ private:
private: private:
bool next; bool next;
usize fsize; usize fsize;
u16 bk_fidx; u16 break_file_index;
u32 bk_line; u32 break_line;
error src; error src;
private: private:
@ -159,7 +159,7 @@ private:
public: public:
dbg(): dbg():
next(true), fsize(0), next(true), fsize(0),
bk_fidx(0), bk_line(0), break_file_index(0), break_line(0),
do_profiling(false) {} do_profiling(false) {}
void run( void run(
const codegen&, const codegen&,

View File

@ -352,21 +352,21 @@ var gc::alloc(u8 type) {
return ret; return ret;
} }
void gc::ctxchg(nas_co& co) { void gc::context_change(nas_co* co) {
// store running state to main context // store running state to main context
main_context = *running_context; main_context = *running_context;
// restore coroutine context state // restore coroutine context state
*running_context = co.ctx; *running_context = co->ctx;
// set coroutine pointer // set coroutine pointer
cort = &co; cort = co;
// set coroutine state to running // set coroutine state to running
cort->status = nas_co::status::running; cort->status = nas_co::status::running;
} }
void gc::ctxreserve() { void gc::context_reserve() {
// pc=0 means this coroutine is finished // pc=0 means this coroutine is finished
cort->status = running_context->pc? cort->status = running_context->pc?
nas_co::status::suspended: nas_co::status::suspended:

View File

@ -88,8 +88,8 @@ public:
void clear(); void clear();
void info() const; void info() const;
var alloc(const u8); var alloc(const u8);
void ctxchg(nas_co&); void context_change(nas_co*);
void ctxreserve(); void context_reserve();
public: public:
var newstr(char c) { var newstr(char c) {

View File

@ -1,6 +1,8 @@
#include "nasal_import.h" #include "nasal_import.h"
#include "symbol_finder.h" #include "symbol_finder.h"
#include <memory>
namespace nasal { namespace nasal {
linker::linker(): linker::linker():
@ -234,10 +236,14 @@ code_block* linker::import_nasal_lib() {
// start importing... // start importing...
if (lex.scan(filename).geterr()) { 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()) { 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); auto tmp = par.swap(nullptr);
@ -245,41 +251,71 @@ code_block* linker::import_nasal_lib() {
return load(tmp, find(filename)); return load(tmp, find(filename));
} }
std::string linker::generate_module_name(const std::string& filename) { std::string linker::generate_module_name(const std::string& file_path) {
auto error_name = "error_generated@[" + filename + "]"; auto error_name = "module@[" + file_path + "]";
auto pos = filename.find_last_of(".nas"); if (!file_path.length()) {
if (pos==std::string::npos) {
return error_name; return error_name;
} }
pos -= 4;
auto split_pos = filename.find_last_of("/"); // check file suffix and get file suffix position
if (split_pos==std::string::npos) { auto suffix_position = file_path.find(".nas");
split_pos = filename.find_last_of("\\"); 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? if (suffix_position+4!=file_path.length()) {
filename.substr(0, pos + 1): err.warn("link",
filename.substr(split_pos + 1, pos - split_pos); "get invalid module name from <" + file_path + ">, " +
if (!res.length()) { "will not be easily accessed. " +
err.warn("link", "get empty module name from <" + filename + ">, " + "only one \".nas\" suffix is required in the path."
"will not be easily accessed."); );
return error_name;
} }
if (res.length() && '0' <= res[0] && res[0] <= '9') {
err.warn("link", "get module <" + res + "> from <" + filename + ">, " + // only get the file name as module name, directory path is not included
"will not be easily accessed."); 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 + ">, " + // split file path to get module name
"will not be easily accessed."); 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) { return_expr* linker::generate_module_return(code_block* block) {
auto sf = new symbol_finder; auto finder = std::unique_ptr<symbol_finder>(new symbol_finder);
auto res = new return_expr(block->get_location()); auto result = new return_expr(block->get_location());
auto value = new hash_expr(block->get_location()); auto value = new hash_expr(block->get_location());
res->set_value(value); result->set_value(value);
for(const auto& i : sf->do_find(block)) { for(const auto& i : finder->do_find(block)) {
auto pair = new hash_pair(block->get_location()); auto pair = new hash_pair(block->get_location());
// do not export symbol begins with '_' // do not export symbol begins with '_'
if (i.name.length() && i.name[0]=='_') { 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)); pair->set_value(new identifier(block->get_location(), i.name));
value->add_member(pair); value->add_member(pair);
} }
delete sf; return result;
return res;
} }
definition_expr* linker::generate_module_definition(code_block* block) { definition_expr* linker::generate_module_definition(code_block* block) {

View File

@ -28,13 +28,13 @@ const char* opname[] = {
}; };
void codestream::set( void codestream::set(
const f64* num_buff, const f64* number_list,
const std::string* str_buff, const std::string* string_list,
const nasal_builtin_table* native_table_ptr, const nasal_builtin_table* native_table,
const std::string* file_list) { const std::string* file_list) {
nums = num_buff; const_number = number_list;
strs = str_buff; const_string = string_list;
natives = native_table_ptr; natives = native_table;
files = file_list; files = file_list;
} }
@ -62,24 +62,24 @@ void codestream::dump(std::ostream& out) const {
case op_addeqc: case op_subeqc: case op_addeqc: case op_subeqc:
case op_muleqc:case op_diveqc: case op_muleqc:case op_diveqc:
out << hex << "0x" << num << dec out << hex << "0x" << num << dec
<< " (" << nums[num] << ")"; break; << " (" << const_number[num] << ")"; break;
case op_lnkeqc: case op_lnkeqc:
out << hex << "0x" << num << dec out << hex << "0x" << num << dec
<< " (" << rawstr(strs[num], 16) << ")"; break; << " (" << rawstr(const_string[num], 16) << ")"; break;
case op_addecp: case op_subecp: case op_addecp: case op_subecp:
case op_mulecp: case op_divecp: case op_mulecp: case op_divecp:
out << hex << "0x" << num << dec out << hex << "0x" << num << dec
<< " (" << nums[num] << ") sp-1"; break; << " (" << const_number[num] << ") sp-1"; break;
case op_lnkecp: case op_lnkecp:
out << hex << "0x" << num << dec 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_addc: case op_subc:
case op_mulc: case op_divc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_lessc: case op_leqc:
case op_grtc: case op_geqc: case op_grtc: case op_geqc:
case op_pnum: case op_pnum:
out << hex << "0x" << num << dec out << hex << "0x" << num << dec
<< " (" << nums[num] << ")"; break; << " (" << const_number[num] << ")"; break;
case op_callvi: case op_newv: case op_callvi: case op_newv:
case op_callfv: case op_repl: case op_callfv: case op_repl:
case op_intl: case op_findex: 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_mcallh: case op_para:
case op_deft: case op_dyn: case op_deft: case op_dyn:
out << hex << "0x" << num << dec out << hex << "0x" << num << dec
<< " (" << rawstr(strs[num], 16) << ")"; break; << " (" << rawstr(const_string[num], 16) << ")"; break;
default: default:
if (files) { if (files) {
out << hex << "0x" << num << dec; out << hex << "0x" << num << dec;

View File

@ -111,8 +111,8 @@ class codestream {
private: private:
opcode code; opcode code;
const u32 index; const u32 index;
inline static const f64* nums = nullptr; inline static const f64* const_number = nullptr;
inline static const std::string* strs = nullptr; inline static const std::string* const_string = nullptr;
inline static const nasal_builtin_table* natives = nullptr; inline static const nasal_builtin_table* natives = nullptr;
inline static const std::string* files = nullptr; inline static const std::string* files = nullptr;

View File

@ -2,20 +2,20 @@
namespace nasal { namespace nasal {
var nas_vec::get_value(const i32 n) { var nas_vec::get_value(const i32 index) {
i32 size = elems.size(); i32 size = elems.size();
if (n<-size || n>=size) { if (index<-size || index>=size) {
return var::none(); 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(); i32 size = elems.size();
if (n<-size || n>=size) { if (index<-size || index>=size) {
return nullptr; 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) { std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
@ -194,41 +194,41 @@ nas_val::nas_val(u8 val_type) {
type = val_type; type = val_type;
unmutable = 0; unmutable = 0;
switch(val_type) { switch(val_type) {
case vm_str: ptr.str = new std::string; break; case vm_str: ptr.str = new std::string; break;
case vm_vec: ptr.vec = new nas_vec; break; case vm_vec: ptr.vec = new nas_vec; break;
case vm_hash: ptr.hash = new nas_hash; break; case vm_hash: ptr.hash = new nas_hash; break;
case vm_func: ptr.func = new nas_func; break; case vm_func: ptr.func = new nas_func; break;
case vm_upval: ptr.upval = new nas_upval; break; case vm_upval: ptr.upval = new nas_upval; break;
case vm_obj: ptr.obj = new nas_ghost; break; case vm_obj: ptr.obj = new nas_ghost; break;
case vm_co: ptr.co = new nas_co; break; case vm_co: ptr.co = new nas_co; break;
case vm_map: ptr.map = new nas_map; break; case vm_map: ptr.map = new nas_map; break;
} }
} }
nas_val::~nas_val() { nas_val::~nas_val() {
switch(type) { switch(type) {
case vm_str: delete ptr.str; break; case vm_str: delete ptr.str; break;
case vm_vec: delete ptr.vec; break; case vm_vec: delete ptr.vec; break;
case vm_hash: delete ptr.hash; break; case vm_hash: delete ptr.hash; break;
case vm_func: delete ptr.func; break; case vm_func: delete ptr.func; break;
case vm_upval:delete ptr.upval;break; case vm_upval:delete ptr.upval; break;
case vm_obj: delete ptr.obj; break; case vm_obj: delete ptr.obj; break;
case vm_co: delete ptr.co; break; case vm_co: delete ptr.co; break;
case vm_map: delete ptr.map; break; case vm_map: delete ptr.map; break;
} }
type=vm_nil; type=vm_nil;
} }
void nas_val::clear() { void nas_val::clear() {
switch(type) { switch(type) {
case vm_str: ptr.str->clear(); break; case vm_str: ptr.str->clear(); break;
case vm_vec: ptr.vec->elems.clear(); break; case vm_vec: ptr.vec->elems.clear(); break;
case vm_hash: ptr.hash->elems.clear();break; case vm_hash: ptr.hash->elems.clear(); break;
case vm_func: ptr.func->clear(); break; case vm_func: ptr.func->clear(); break;
case vm_upval:ptr.upval->clear(); break; case vm_upval:ptr.upval->clear(); break;
case vm_obj: ptr.obj->clear(); break; case vm_obj: ptr.obj->clear(); break;
case vm_co: ptr.co->clear(); break; case vm_co: ptr.co->clear(); break;
case vm_map: ptr.map->clear(); break; case vm_map: ptr.map->clear(); break;
} }
} }
@ -240,7 +240,7 @@ std::string var::to_str() {
if (type==vm_str) { if (type==vm_str) {
return str(); return str();
} else if (type==vm_num) { } 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('0')+1, std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1, std::string::npos); tmp.erase(tmp.find_last_not_of('.')+1, std::string::npos);
return tmp; return tmp;
@ -257,7 +257,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
case vm_vec: out << ref.vec(); break; case vm_vec: out << ref.vec(); break;
case vm_hash: out << ref.hash(); break; case vm_hash: out << ref.hash(); break;
case vm_func: out << "func(..) {..}"; 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_co: out << ref.co(); break;
case vm_map: out << ref.map(); 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) { 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() { var var::none() {
@ -300,7 +300,7 @@ var* var::addr() {
return val.addr; return val.addr;
} }
u32 var::ret() { u32 var::ret() const {
return val.ret; return val.ret;
} }
@ -308,7 +308,7 @@ i64& var::cnt() {
return val.cnt; return val.cnt;
} }
f64 var::num() { f64 var::num() const {
return val.num; return val.num;
} }
@ -332,7 +332,7 @@ nas_upval& var::upval() {
return *val.gcobj->ptr.upval; return *val.gcobj->ptr.upval;
} }
nas_ghost& var::obj() { nas_ghost& var::ghost() {
return *val.gcobj->ptr.obj; return *val.gcobj->ptr.obj;
} }

View File

@ -23,11 +23,13 @@ enum vm_type:u8 {
vm_upval, // upvalue vm_upval, // upvalue
vm_obj, // ghost type vm_obj, // ghost type
vm_co, // coroutine 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 // 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 // basic types
struct nas_vec; // vector struct nas_vec; // vector
@ -85,15 +87,15 @@ public:
// get value // get value
var* addr(); var* addr();
u32 ret(); u32 ret() const;
i64& cnt(); i64& cnt();
f64 num(); f64 num() const;
std::string& str(); std::string& str();
nas_vec& vec(); nas_vec& vec();
nas_hash& hash(); nas_hash& hash();
nas_func& func(); nas_func& func();
nas_upval& upval(); nas_upval& upval();
nas_ghost& obj(); nas_ghost& ghost();
nas_co& co(); nas_co& co();
nas_map& map(); nas_map& map();
}; };

View File

@ -93,7 +93,7 @@ void vm::value_info(var& val) {
<< " val}"; break; << " val}"; break;
case vm_obj: std::clog << "| obj | <0x" << std::hex << p case vm_obj: std::clog << "| obj | <0x" << std::hex << p
<< "> obj:0x" << "> obj:0x"
<< reinterpret_cast<u64>(val.obj().pointer) << reinterpret_cast<u64>(val.ghost().pointer)
<< std::dec; break; << std::dec; break;
case vm_co: std::clog << "| co | <0x" << std::hex << p case vm_co: std::clog << "| co | <0x" << std::hex << p
<< std::dec << "> coroutine"; break; << std::dec << "> coroutine"; break;
@ -170,12 +170,12 @@ void vm::function_call_trace() {
} }
void vm::trace_back() { void vm::trace_back() {
var* bottom = ctx.stack; // var* bottom = ctx.stack;
var* top = ctx.top; // var* top = ctx.top;
// generate trace back // generate trace back
std::stack<u32> ret; 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) { if (i->type==vm_ret && i->ret()!=0) {
ret.push(i->ret()); ret.push(i->ret());
} }
@ -401,7 +401,7 @@ void vm::die(const std::string& str) {
} else { } else {
// in coroutine, shut down the coroutine and return to main context // in coroutine, shut down the coroutine and return to main context
ctx.pc = 0; // mark coroutine 'dead' 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' ctx.top[0] = nil; // generate return value 'nil'
} }
} }

View File

@ -1024,7 +1024,7 @@ inline void vm::o_ret() {
// because there maybe another function call inside but return here // because there maybe another function call inside but return here
// coroutine function ends with setting pc to 0 // coroutine function ends with setting pc to 0
if (!ctx.pc) { if (!ctx.pc) {
ngc.ctxreserve(); ngc.context_reserve();
} }
} }

View File

@ -73,7 +73,7 @@ var builtin_opendir(context* ctx, gc* ngc) {
} }
#endif #endif
var ret = ngc->alloc(vm_obj); 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; return ret;
} }
@ -84,12 +84,12 @@ var builtin_readdir(context* ctx, gc* ngc) {
} }
#ifdef _MSC_VER #ifdef _MSC_VER
WIN32_FIND_DATAA data; WIN32_FIND_DATAA data;
if (!FindNextFileA(handle.obj().pointer, &data)) { if (!FindNextFileA(handle.ghost().pointer, &data)) {
return nil; return nil;
} }
return ngc->newstr(data.cFileName); return ngc->newstr(data.cFileName);
#else #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; return p? ngc->newstr(p->d_name):nil;
#endif #endif
} }
@ -99,7 +99,7 @@ var builtin_closedir(context* ctx, gc* ngc) {
if (!handle.object_check(dir_type_name)) { if (!handle.object_check(dir_type_name)) {
return nas_err("unix::closedir", "not a valid dir handle"); return nas_err("unix::closedir", "not a valid dir handle");
} }
handle.obj().clear(); handle.ghost().clear();
return nil; return nil;
} }

View File

@ -24,5 +24,5 @@ while(1) {
res ~= "\n"; res ~= "\n";
} }
print(res); print(res);
unix.sleep(1/20); unix.sleep(1/15);
} }