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 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;
}

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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*);

View File

@ -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;

View File

@ -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))
));
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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();

View File

@ -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&,

View File

@ -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:

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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();
};

View File

@ -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'
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

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