change way of calling native functions

This commit is contained in:
ValKmjolnir 2023-10-21 00:31:39 +08:00
parent 7f8a0b6445
commit 820c05c986
17 changed files with 448 additions and 410 deletions

View File

@ -2,45 +2,52 @@
namespace nasal {
var builtin_u32xor(var* local, gc& ngc) {
var builtin_u32xor(context* ctx, gc* ngc) {
auto local = ctx->localr;
return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) ^
static_cast<u32>(local[2].num())
));
}
var builtin_u32and(var* local, gc& ngc) {
var builtin_u32and(context* ctx, gc* ngc) {
auto local = ctx->localr;
return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) &
static_cast<u32>(local[2].num())
));
}
var builtin_u32or(var* local, gc& ngc) {
var builtin_u32or(context* ctx, gc* ngc) {
auto local = ctx->localr;
return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) |
static_cast<u32>(local[2].num())
));
}
var builtin_u32nand(var* local, gc& ngc) {
var builtin_u32nand(context* ctx, gc* ngc) {
auto local = ctx->localr;
return var::num(static_cast<f64>(~(
static_cast<u32>(local[1].num()) &
static_cast<u32>(local[2].num())
)));
}
var builtin_u32not(var* local, gc& ngc) {
return var::num(static_cast<f64>(~static_cast<u32>(local[1].num())));
var builtin_u32not(context* ctx, gc* ngc) {
return var::num(static_cast<f64>(
~static_cast<u32>(ctx->localr[1].num())
));
}
var builtin_fld(var* local, gc& ngc) {
var builtin_fld(context* ctx, gc* ngc) {
// bits.fld(s,0,3);
// if s stores 10100010(162)
// will get 101(5)
var str = local[1];
var startbit = local[2];
var length = local[3];
auto local = ctx->localr;
auto str = local[1];
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");
}
@ -62,14 +69,15 @@ var builtin_fld(var* local, gc& ngc) {
return var::num(static_cast<f64>(res));
}
var builtin_sfld(var* local, gc& ngc) {
var builtin_sfld(context* ctx, gc* ngc) {
// bits.sfld(s,0,3);
// if s stores 10100010(162)
// will get 101(5) then this will be signed extended to
// 11111101(-3)
var str = local[1];
var startbit = local[2];
var length = local[3];
auto local = ctx->localr;
auto str = local[1];
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");
}
@ -94,15 +102,16 @@ var builtin_sfld(var* local, gc& ngc) {
return var::num(static_cast<f64>(static_cast<i32>(res)));
}
var builtin_setfld(var* local, gc& ngc) {
var builtin_setfld(context* ctx, gc* ngc) {
// bits.setfld(s,0,8,69);
// set 01000101(69) to string will get this:
// 10100010(162)
// so s[0]=162
var str = local[1];
var startbit = local[2];
var length = local[3];
var value = local[4];
auto local = ctx->localr;
auto str = local[1];
auto startbit = local[2];
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");
}
@ -126,12 +135,12 @@ var builtin_setfld(var* local, gc& ngc) {
return nil;
}
var builtin_buf(var* local, gc& ngc) {
var length = local[1];
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");
}
var str = ngc.alloc(vm_str);
var str = ngc->alloc(vm_str);
auto& s = str.str();
s.resize(length.num(), '\0');
return str;

View File

@ -6,15 +6,15 @@
namespace nasal {
var builtin_u32xor(var*, gc&);
var builtin_u32and(var*, gc&);
var builtin_u32or(var*, gc&);
var builtin_u32nand(var*, gc&);
var builtin_u32not(var*, gc&);
var builtin_fld(var*, gc&);
var builtin_sfld(var*, gc&);
var builtin_setfld(var*, gc&);
var builtin_buf(var*, gc&);
var builtin_u32xor(context*, gc*);
var builtin_u32and(context*, gc*);
var builtin_u32or(context*, gc*);
var builtin_u32nand(context*, gc*);
var builtin_u32not(context*, gc*);
var builtin_fld(context*, gc*);
var builtin_sfld(context*, gc*);
var builtin_setfld(context*, gc*);
var builtin_buf(context*, gc*);
extern nasal_builtin_table bits_native[];

View File

@ -2,7 +2,8 @@
namespace nasal {
var builtin_cocreate(var* local, gc& ngc) {
var builtin_cocreate(context* ctx, gc* ngc) {
// ```
// +-------------+
// | old pc | <- top[0]
// +-------------+
@ -15,69 +16,73 @@ var builtin_cocreate(var* local, gc& ngc) {
// +-------------+ <- local pointer stored in localr
// | old funcr | <- old function stored in funcr
// +-------------+
var func = local[1];
if (func.type!=vm_func) {
// ```
auto coroutine_function = ctx->localr[1];
if (coroutine_function.type!=vm_func) {
return nas_err(
"coroutine::create",
"must use a function to create coroutine"
);
}
if (ngc.cort) {
if (ngc->cort) {
return nas_err(
"coroutine::create",
"cannot create another coroutine in a coroutine"
);
}
var co = ngc.alloc(vm_co);
nas_co& cort = co.co();
cort.ctx.pc = func.func().entry-1;
auto coroutine_object = ngc->alloc(vm_co);
auto& coroutine = coroutine_object.co();
coroutine.ctx.pc = coroutine_function.func().entry-1;
coroutine.ctx.top[0] = nil;
coroutine.ctx.localr = coroutine.ctx.top+1;
coroutine.ctx.top = coroutine.ctx.localr +
coroutine_function.func().local_size;
coroutine.ctx.localr[0] = coroutine_function.func().local[0];
cort.ctx.top[0] = nil;
cort.ctx.localr = cort.ctx.top+1;
cort.ctx.top = cort.ctx.localr+func.func().local_size;
cort.ctx.localr[0] = func.func().local[0];
// store old upvalr on stack
cort.ctx.top[0] = nil;
cort.ctx.top++;
coroutine.ctx.top[0] = nil;
coroutine.ctx.top++;
// store old localr on stack
cort.ctx.top[0] = var::addr((var*)nullptr);
cort.ctx.top++;
coroutine.ctx.top[0] = var::addr((var*)nullptr);
coroutine.ctx.top++;
// store old pc on stack
// set to zero to make op_ret recognizing this as coroutine function
cort.ctx.top[0] = var::ret(0);
coroutine.ctx.top[0] = var::ret(0);
// make sure the coroutine function can use correct upvalues
cort.ctx.funcr = func;
cort.status = nas_co::status::suspended;
coroutine.ctx.funcr = coroutine_function;
coroutine.status = nas_co::status::suspended;
return co;
return coroutine_object;
}
var builtin_coresume(var* local, gc& ngc) {
if (ngc.cort) {
var builtin_coresume(context* ctx, gc* ngc) {
if (ngc->cort) {
return nas_err(
"coroutine::resume",
"cannot start another coroutine when one is running"
);
}
var co = local[1];
// return nil if is not a coroutine object
if (co.type!=vm_co) {
return nil;
}
// cannot resume a dead coroutine
if (co.co().status==nas_co::status::dead) {
auto main_local_frame = ctx->localr;
auto coroutine_object = main_local_frame[1];
// return nil if is not a coroutine object or coroutine exited
if (coroutine_object.type!=vm_co ||
coroutine_object.co().status==nas_co::status::dead) {
return nil;
}
// change to coroutine context
ngc.ctxchg(co.co());
ngc->ctxchg(coroutine_object.co());
// fetch coroutine's stack top and return
// then coroutine's stack top will catch this return value
// so the coroutine's stack top in fact is not changed
if (ngc.running_context->top[0].type==vm_ret) {
if (ngc->running_context->top[0].type==vm_ret) {
// when first calling this coroutine, the stack top must be vm_ret
return ngc.running_context->top[0];
return ngc->running_context->top[0];
}
// after first calling the coroutine, each time coroutine.yield triggered
@ -87,39 +92,41 @@ var builtin_coresume(var* local, gc& ngc) {
// the coroutine seems like coroutine.yield returns the value
// but in fact coroutine.yield stop the coroutine
// until main context calls the coroutine.resume
return local[2];
return main_local_frame[2];
}
var builtin_coyield(var* local, gc& ngc) {
if (!ngc.cort) {
var builtin_coyield(context* ctx, gc* ngc) {
if (!ngc->cort) {
return nas_err("coroutine::yield", "no coroutine is running");
}
// get coroutine local frame
auto coroutine_local_frame = ctx->localr;
// this will set to main stack top
ngc.ctxreserve();
// vm context will set to main context
ngc->ctxreserve();
// then this will return value to main's stack top[0]
// the procedure seems like coroutine.resume returns the value
// but in fact coroutine.resume stop the main context
// until coroutine calls the coroutine.yield
return local[1];
return coroutine_local_frame[1];
}
var builtin_costatus(var* local, gc& ngc) {
var co = local[1];
if (co.type!=vm_co) {
return ngc.newstr("error");
var builtin_costatus(context* ctx, gc* ngc) {
auto coroutine_object = ctx->localr[1];
if (coroutine_object.type!=vm_co) {
return ngc->newstr("error");
}
switch(co.co().status) {
case nas_co::status::suspended: return ngc.newstr("suspended");
case nas_co::status::running: return ngc.newstr("running");
case nas_co::status::dead: return ngc.newstr("dead");
switch(coroutine_object.co().status) {
case nas_co::status::suspended: return ngc->newstr("suspended");
case nas_co::status::running: return ngc->newstr("running");
case nas_co::status::dead: return ngc->newstr("dead");
}
return nil;
}
var builtin_corun(var* local, gc& ngc) {
return ngc.cort? one:zero;
var builtin_corun(context* ctx, gc* ngc) {
return ngc->cort? one:zero;
}
nasal_builtin_table coroutine_native[] = {

View File

@ -6,11 +6,11 @@
namespace nasal {
var builtin_cocreate(var*, gc&);
var builtin_coresume(var*, gc&);
var builtin_coyield(var*, gc&);
var builtin_costatus(var*, gc&);
var builtin_corun(var*, gc&);
var builtin_cocreate(context*, gc*);
var builtin_coresume(context*, gc*);
var builtin_coyield(context*, gc*);
var builtin_costatus(context*, gc*);
var builtin_corun(context*, gc*);
extern nasal_builtin_table coroutine_native[];

View File

@ -15,8 +15,8 @@ void dylib_destructor(void* ptr) {
void func_addr_destructor(void* ptr) {}
var builtin_dlopen(var* local, gc& ngc) {
var dlname = local[1];
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");
}
@ -35,8 +35,8 @@ var builtin_dlopen(var* local, gc& ngc) {
if (!ptr) {
return nas_err("dlopen", "cannot open dynamic lib <"+dlname.str()+">");
}
var ret = ngc.temp = ngc.alloc(vm_hash);
var lib = ngc.alloc(vm_obj);
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;
@ -52,23 +52,23 @@ var builtin_dlopen(var* local, gc& ngc) {
return nas_err("dlopen", "cannot find <get> function");
}
// get function pointer by name
module_func_info* tbl = reinterpret_cast<get_func_ptr>(func)();
auto tbl = reinterpret_cast<get_func_ptr>(func)();
if (!tbl) {
return nas_err("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);
var tmp = ngc->alloc(vm_obj);
tmp.obj().set(func_addr_type_name, func_addr_destructor, p);
ret.hash().elems[tbl[i].name] = tmp;
}
ngc.temp = nil;
ngc->temp = nil;
return ret;
}
var builtin_dlclose(var* local, gc& ngc) {
var libptr = local[1];
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");
}
@ -76,9 +76,10 @@ var builtin_dlclose(var* local, gc& ngc) {
return nil;
}
var builtin_dlcallv(var* local, gc& ngc) {
var fp = local[1];
var args = local[2];
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");
}
@ -86,23 +87,24 @@ var builtin_dlcallv(var* local, gc& ngc) {
return reinterpret_cast<module_func>(fp.obj().pointer)(
vec.data(),
vec.size(),
&ngc
ngc
);
}
var builtin_dlcall(var* local, 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");
}
var* local_frame_start = local+2;
usize local_frame_size = ngc.running_context->top-local_frame_start;
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)(
local_frame_start,
local_frame_size,
&ngc
ngc
);
}

View File

@ -16,10 +16,10 @@ namespace nasal {
void dylib_destructor(void*);
void func_addr_destructor(void*);
var builtin_dlopen(var*, gc&);
var builtin_dlclose(var*, gc&);
var builtin_dlcallv(var*, gc&);
var builtin_dlcall(var*, gc&);
var builtin_dlopen(context*, gc*);
var builtin_dlclose(context*, gc*);
var builtin_dlcallv(context*, gc*);
var builtin_dlcall(context*, gc*);
extern nasal_builtin_table dylib_lib_native[];

View File

@ -4,9 +4,10 @@
namespace nasal {
var builtin_logprint(var* local, gc& ngc) {
var level = local[1];
var elems = local[2];
var builtin_logprint(context* ctx, gc* ngc) {
auto local = ctx->localr;
auto level = local[1];
auto elems = local[2];
if (elems.type!=vm_vec) {
return nas_err("logprint", "received argument is not vector.");
}

View File

@ -15,7 +15,7 @@ namespace nasal {
#define SG_DEV_ALERT 8
#define SG_MANDATORY_INFO 9
var builtin_logprint(var*, gc&);
var builtin_logprint(context*, gc*);
extern nasal_builtin_table flight_gear_native[];

View File

@ -11,8 +11,8 @@ void filehandle_destructor(void* ptr) {
fclose(static_cast<FILE*>(ptr));
}
var builtin_readfile(var* local, gc& ngc) {
var val = local[1];
var builtin_readfile(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_str) {
return nas_err("io::readfile", "\"filename\" must be string");
}
@ -21,12 +21,13 @@ var builtin_readfile(var* local, gc& ngc) {
if (!in.fail()) {
rd << in.rdbuf();
}
return ngc.newstr(rd.str());
return ngc->newstr(rd.str());
}
var builtin_fout(var* local, gc& ngc) {
var val = local[1];
var str = local[2];
var builtin_fout(context* ctx, gc* ngc) {
auto local = ctx->localr;
auto val = local[1];
auto str = local[2];
if (val.type!=vm_str) {
return nas_err("io::fout", "\"filename\" must be string");
}
@ -38,16 +39,18 @@ var builtin_fout(var* local, gc& ngc) {
return nil;
}
var builtin_exists(var* local, gc& ngc) {
var builtin_exists(context* ctx, gc* ngc) {
auto local = ctx->localr;
if (local[1].type!=vm_str) {
return zero;
}
return access(local[1].str().c_str(), F_OK)!=-1? one:zero;
}
var builtin_open(var* local, gc& ngc) {
var name = local[1];
var mode = local[2];
var builtin_open(context* ctx, gc* ngc) {
auto local = ctx->localr;
auto name = local[1];
auto mode = local[2];
if (name.type!=vm_str) {
return nas_err("open", "\"filename\" must be string");
}
@ -58,13 +61,13 @@ var builtin_open(var* local, gc& ngc) {
if (!res) {
return nas_err("open", "failed to open file <"+name.str()+">");
}
var ret = ngc.alloc(vm_obj);
var ret = ngc->alloc(vm_obj);
ret.obj().set(file_type_name, filehandle_destructor, res);
return ret;
}
var builtin_close(var* local, gc& ngc) {
var fd = local[1];
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");
}
@ -72,10 +75,11 @@ var builtin_close(var* local, gc& ngc) {
return nil;
}
var builtin_read(var* local, gc& ngc) {
var fd = local[1];
var buf = local[2];
var len = local[3];
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");
}
@ -99,9 +103,10 @@ var builtin_read(var* local, gc& ngc) {
return var::num(res);
}
var builtin_write(var* local, gc& ngc) {
var fd = local[1];
var str = local[2];
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");
}
@ -116,10 +121,11 @@ var builtin_write(var* local, gc& ngc) {
)));
}
var builtin_seek(var* local, gc& ngc) {
var fd = local[1];
var pos = local[2];
var whence = local[3];
var builtin_seek(context* ctx, gc* ngc) {
auto local = ctx->localr;
auto fd = local[1];
auto pos = local[2];
auto whence = local[3];
if (!fd.object_check(file_type_name)) {
return nas_err("seek", "not a valid filehandle");
}
@ -130,8 +136,8 @@ var builtin_seek(var* local, gc& ngc) {
)));
}
var builtin_tell(var* local, gc& ngc) {
var fd = local[1];
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");
}
@ -140,12 +146,12 @@ var builtin_tell(var* local, gc& ngc) {
));
}
var builtin_readln(var* local, gc& ngc) {
var fd = local[1];
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");
}
var str = ngc.alloc(vm_str);
auto str = ngc->alloc(vm_str);
char c;
while((c = fgetc(static_cast<FILE*>(fd.obj().pointer)))!=EOF) {
if (c=='\r') {
@ -162,8 +168,8 @@ var builtin_readln(var* local, gc& ngc) {
return nil;
}
var builtin_stat(var* local, gc& ngc) {
var name = local[1];
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");
}
@ -171,7 +177,7 @@ var builtin_stat(var* local, gc& ngc) {
if (stat(name.str().c_str(), &buf)<0) {
return nas_err("stat", "failed to open file <"+name.str()+">");
}
var ret = ngc.alloc(vm_vec);
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)),
@ -188,8 +194,8 @@ var builtin_stat(var* local, gc& ngc) {
return ret;
}
var builtin_eof(var* local, gc& ngc) {
var fd = local[1];
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");
}

View File

@ -20,18 +20,18 @@ namespace nasal {
void filehandle_destructor(void*);
var builtin_readfile(var*, gc&);
var builtin_fout(var*, gc&);
var builtin_exists(var*, gc&);
var builtin_open(var*, gc&);
var builtin_close(var*, gc&);
var builtin_read(var*, gc&);
var builtin_write(var*, gc&);
var builtin_seek(var*, gc&);
var builtin_tell(var*, gc&);
var builtin_readln(var*, gc&);
var builtin_stat(var*, gc&);
var builtin_eof(var*, gc&);
var builtin_readfile(context*, gc*);
var builtin_fout(context*, gc*);
var builtin_exists(context*, gc*);
var builtin_open(context*, gc*);
var builtin_close(context*, gc*);
var builtin_read(context*, gc*);
var builtin_write(context*, gc*);
var builtin_seek(context*, gc*);
var builtin_tell(context*, gc*);
var builtin_readln(context*, gc*);
var builtin_stat(context*, gc*);
var builtin_eof(context*, gc*);
extern nasal_builtin_table io_lib_native[];

View File

@ -2,61 +2,61 @@
namespace nasal {
var builtin_pow(var* local, gc& ngc) {
var x = local[1];
var y = local[2];
var builtin_pow(context* ctx, gc* ngc) {
auto x = ctx->localr[1];
auto y = ctx->localr[2];
if (x.type!=vm_num || y.type!=vm_num) {
return var::num(std::nan(""));
}
return var::num(std::pow(x.num(), y.num()));
}
var builtin_sin(var* local, gc& ngc) {
var val = local[1];
var builtin_sin(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? sin(val.num()):std::nan(""));
}
var builtin_cos(var* local, gc& ngc) {
var val = local[1];
var builtin_cos(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? cos(val.num()):std::nan(""));
}
var builtin_tan(var* local, gc& ngc) {
var val = local[1];
var builtin_tan(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? tan(val.num()):std::nan(""));
}
var builtin_exp(var* local, gc& ngc) {
var val = local[1];
var builtin_exp(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? exp(val.num()):std::nan(""));
}
var builtin_lg(var* local, gc& ngc) {
var val = local[1];
var builtin_lg(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? log(val.num())/log(10.0):std::nan(""));
}
var builtin_ln(var* local, gc& ngc) {
var val = local[1];
var builtin_ln(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? log(val.num()):std::nan(""));
}
var builtin_sqrt(var* local, gc& ngc) {
var val = local[1];
var builtin_sqrt(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
return var::num(val.type==vm_num? sqrt(val.num()):std::nan(""));
}
var builtin_atan2(var* local, gc& ngc) {
var x = local[1];
var y = local[2];
var builtin_atan2(context* ctx, gc* ngc) {
auto x = ctx->localr[1];
auto y = ctx->localr[2];
if (x.type!=vm_num || y.type!=vm_num) {
return var::num(std::nan(""));
}
return var::num(atan2(y.num(), x.num()));
}
var builtin_isnan(var* local, gc& ngc) {
var x = local[1];
var builtin_isnan(context* ctx, gc* ngc) {
auto x = ctx->localr[1];
return (x.type==vm_num && std::isnan(x.num()))? one:zero;
}

View File

@ -6,16 +6,16 @@
namespace nasal {
var builtin_pow(var*, gc&);
var builtin_sin(var*, gc&);
var builtin_cos(var*, gc&);
var builtin_tan(var*, gc&);
var builtin_exp(var*, gc&);
var builtin_lg(var*, gc&);
var builtin_ln(var*, gc&);
var builtin_sqrt(var*, gc&);
var builtin_atan2(var*, gc&);
var builtin_isnan(var*, gc&);
var builtin_pow(context*, gc*);
var builtin_sin(context*, gc*);
var builtin_cos(context*, gc*);
var builtin_tan(context*, gc*);
var builtin_exp(context*, gc*);
var builtin_lg(context*, gc*);
var builtin_ln(context*, gc*);
var builtin_sqrt(context*, gc*);
var builtin_atan2(context*, gc*);
var builtin_isnan(context*, gc*);
extern nasal_builtin_table math_lib_native[];

View File

@ -3,33 +3,34 @@
namespace nasal {
var builtin_print(var* local, gc& ngc) {
for(auto& i : local[1].vec().elems) {
var builtin_print(context* ctx, gc* ngc) {
for(auto& i : ctx->localr[1].vec().elems) {
std::cout << i;
}
std::cout << std::flush;
return nil;
}
var builtin_println(var* local, gc& ngc) {
for(auto& i : local[1].vec().elems) {
var builtin_println(context* ctx, gc* ngc) {
for(auto& i : ctx->localr[1].vec().elems) {
std::cout << i;
}
std::cout << std::endl;
return nil;
}
var builtin_exit(var* local, gc& ngc) {
std::exit(local[1].num());
var builtin_exit(context* ctx, gc* ngc) {
std::exit(ctx->localr[1].num());
return nil;
}
var builtin_abort(var* local, gc& ngc) {
var builtin_abort(context* ctx, gc* ngc) {
std::abort();
return nil;
}
var builtin_append(var* local, gc& ngc) {
var builtin_append(context* ctx, gc* ngc) {
auto local = ctx->localr;
var vec = local[1];
var elem = local[2];
if (vec.type!=vm_vec) {
@ -42,7 +43,8 @@ var builtin_append(var* local, gc& ngc) {
return nil;
}
var builtin_setsize(var* local, gc& ngc) {
var builtin_setsize(context* ctx, gc* ngc) {
auto local = ctx->localr;
var vec = local[1];
var size = local[2];
if (vec.type!=vm_vec) {
@ -55,17 +57,18 @@ var builtin_setsize(var* local, gc& ngc) {
return nil;
}
var builtin_system(var* local, gc& ngc) {
var str = local[1];
var builtin_system(context* ctx, gc* ngc) {
auto str = ctx->localr[1];
if (str.type!=vm_str) {
return var::num(-1);
}
return var::num(static_cast<f64>(system(str.str().c_str())));
}
var builtin_input(var* local, gc& ngc) {
var builtin_input(context* ctx, gc* ngc) {
auto local = ctx->localr;
var end = local[1];
var ret = ngc.alloc(vm_str);
var ret = ngc->alloc(vm_str);
if (end.type!=vm_str || end.str().length()>1 || !end.str().length()) {
std::cin >> ret.str();
} else {
@ -74,7 +77,8 @@ var builtin_input(var* local, gc& ngc) {
return ret;
}
var builtin_split(var* local, gc& ngc) {
var builtin_split(context* ctx, gc* ngc) {
auto local = ctx->localr;
var delimeter = local[1];
var str = local[2];
if (delimeter.type!=vm_str) {
@ -87,34 +91,34 @@ var builtin_split(var* local, gc& ngc) {
const auto& s = str.str();
// avoid being sweeped
var res = ngc.temp = ngc.alloc(vm_vec);
auto res = ngc->temp = ngc->alloc(vm_vec);
auto& vec = res.vec().elems;
if (!deli.length()) {
for(auto i : s) {
vec.push_back(ngc.newstr(i));
vec.push_back(ngc->newstr(i));
}
ngc.temp = nil;
ngc->temp = nil;
return res;
}
usize last = 0;
usize pos = s.find(deli, 0);
while(pos!=std::string::npos) {
if (pos>last) {
vec.push_back(ngc.newstr(s.substr(last, pos-last)));
vec.push_back(ngc->newstr(s.substr(last, pos-last)));
}
last = pos+deli.length();
pos = s.find(deli, last);
}
if (last!=s.length()) {
vec.push_back(ngc.newstr(s.substr(last)));
vec.push_back(ngc->newstr(s.substr(last)));
}
ngc.temp = nil;
ngc->temp = nil;
return res;
}
var builtin_rand(var* local, gc& ngc) {
var val = local[1];
var builtin_rand(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_num && val.type!=vm_nil) {
return nas_err("rand", "\"seed\" must be nil or number");
}
@ -129,65 +133,65 @@ var builtin_rand(var* local, gc& ngc) {
return var::num(num);
}
var builtin_id(var* local, gc& ngc) {
var val = local[1];
var builtin_id(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
std::stringstream ss;
ss << "0";
if (val.type>vm_num) {
ss << "x" << std::hex;
ss << reinterpret_cast<u64>(val.val.gcobj) << std::dec;
}
return ngc.newstr(ss.str());
return ngc->newstr(ss.str());
}
var builtin_int(var* local, gc& ngc) {
var val = local[1];
var builtin_int(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_num && val.type!=vm_str) {
return nil;
}
return var::num(static_cast<f64>(static_cast<i32>(val.to_num())));
}
var builtin_floor(var* local, gc& ngc) {
var val = local[1];
return var::num(std::floor(val.num()));
var builtin_floor(context* ctx, gc* ngc) {
auto value = ctx->localr[1];
return var::num(std::floor(value.num()));
}
var builtin_num(var* local, gc& ngc) {
var val = local[1];
var builtin_num(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type==vm_num) {
return val;
}
if (val.type!=vm_str) {
return nil;
}
f64 res = val.to_num();
auto res = val.to_num();
if (std::isnan(res)) {
return nil;
}
return var::num(res);
}
var builtin_pop(var* local, gc& ngc) {
var val = local[1];
var builtin_pop(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_vec) {
return nas_err("pop", "\"vec\" must be vector");
}
auto& vec = val.vec().elems;
if (vec.size()) {
var tmp = vec.back();
auto tmp = vec.back();
vec.pop_back();
return tmp;
}
return nil;
}
var builtin_str(var* local, gc& ngc) {
return ngc.newstr(local[1].to_str());
var builtin_str(context* ctx, gc* ngc) {
return ngc->newstr(ctx->localr[1].to_str());
}
var builtin_size(var* local, gc& ngc) {
var val = local[1];
var builtin_size(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
f64 num = 0;
switch(val.type) {
case vm_num: num = val.num(); break;
@ -199,16 +203,17 @@ var builtin_size(var* local, gc& ngc) {
return var::num(num);
}
var builtin_time(var* local, gc& ngc) {
var val = local[1];
var builtin_time(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_num) {
return nas_err("time", "\"begin\" must be number");
}
time_t begin = (time_t)val.num();
auto begin = static_cast<time_t>(val.num());
return var::num(static_cast<f64>(time(&begin)));
}
var builtin_contains(var* local, gc& ngc) {
var builtin_contains(context* ctx, gc* ngc) {
auto local = ctx->localr;
var hash = local[1];
var key = local[2];
if (hash.type!=vm_hash || key.type!=vm_str) {
@ -217,7 +222,8 @@ var builtin_contains(var* local, gc& ngc) {
return hash.hash().elems.count(key.str())? one:zero;
}
var builtin_delete(var* local, gc& ngc) {
var builtin_delete(context* ctx, gc* ngc) {
auto local = ctx->localr;
var hash = local[1];
var key = local[2];
if (hash.type!=vm_hash) {
@ -232,32 +238,33 @@ var builtin_delete(var* local, gc& ngc) {
return nil;
}
var builtin_keys(var* local, gc& ngc) {
var hash = local[1];
var builtin_keys(context* ctx, gc* ngc) {
auto hash = ctx->localr[1];
if (hash.type!=vm_hash && hash.type!=vm_map) {
return nas_err("keys", "\"hash\" must be hash");
}
// avoid being sweeped
var res = ngc.temp = ngc.alloc(vm_vec);
auto res = ngc->temp = ngc->alloc(vm_vec);
auto& vec = res.vec().elems;
if (hash.type==vm_hash) {
for(const auto& iter : hash.hash().elems) {
vec.push_back(ngc.newstr(iter.first));
vec.push_back(ngc->newstr(iter.first));
}
} else {
for(const auto& iter : hash.map().mapper) {
vec.push_back(ngc.newstr(iter.first));
vec.push_back(ngc->newstr(iter.first));
}
}
ngc.temp=nil;
ngc->temp=nil;
return res;
}
var builtin_die(var* local, gc& ngc) {
return nas_err("error", local[1].to_str());
var builtin_die(context* ctx, gc* ngc) {
return nas_err("error", ctx->localr[1].to_str());
}
var builtin_find(var* local, gc& ngc) {
var builtin_find(context* ctx, gc* ngc) {
auto local = ctx->localr;
var needle = local[1];
var haystack = local[2];
usize pos = haystack.to_str().find(needle.to_str());
@ -267,23 +274,24 @@ var builtin_find(var* local, gc& ngc) {
return var::num(static_cast<f64>(pos));
}
var builtin_type(var* local, gc& ngc) {
switch(local[1].type) {
case vm_none: return ngc.newstr("undefined");
case vm_nil: return ngc.newstr("nil");
case vm_num: return ngc.newstr("num");
case vm_str: return ngc.newstr("str");
case vm_vec: return ngc.newstr("vec");
case vm_hash: return ngc.newstr("hash");
case vm_func: return ngc.newstr("func");
case vm_obj: return ngc.newstr("obj");
case vm_co: return ngc.newstr("coroutine");
case vm_map: return ngc.newstr("namespace");
var builtin_type(context* ctx, gc* ngc) {
switch(ctx->localr[1].type) {
case vm_none: return ngc->newstr("undefined");
case vm_nil: return ngc->newstr("nil");
case vm_num: return ngc->newstr("num");
case vm_str: return ngc->newstr("str");
case vm_vec: return ngc->newstr("vec");
case vm_hash: return ngc->newstr("hash");
case vm_func: return ngc->newstr("func");
case vm_obj: return ngc->newstr("obj");
case vm_co: return ngc->newstr("coroutine");
case vm_map: return ngc->newstr("namespace");
}
return nil;
}
var builtin_substr(var* local, gc& ngc) {
var builtin_substr(context* ctx, gc* ngc) {
auto local = ctx->localr;
var str = local[1];
var beg = local[2];
var len = local[3];
@ -301,10 +309,11 @@ var builtin_substr(var* local, gc& ngc) {
if (begin>=str.str().length()) {
return nas_err("susbtr", "begin index out of range: "+std::to_string(begin));
}
return ngc.newstr(str.str().substr(begin,length));
return ngc->newstr(str.str().substr(begin,length));
}
var builtin_streq(var* local, gc& ngc) {
var builtin_streq(context* ctx, gc* ngc) {
auto local = ctx->localr;
var a = local[1];
var b = local[2];
return var::num(static_cast<f64>(
@ -312,7 +321,8 @@ var builtin_streq(var* local, gc& ngc) {
));
}
var builtin_left(var* local, gc& ngc) {
var builtin_left(context* ctx, gc* ngc) {
auto local = ctx->localr;
var str = local[1];
var len = local[2];
if (str.type!=vm_str) {
@ -322,12 +332,13 @@ var builtin_left(var* local, gc& ngc) {
return nas_err("left", "\"length\" must be number");
}
if (len.num()<0) {
return ngc.newstr("");
return ngc->newstr("");
}
return ngc.newstr(str.str().substr(0, len.num()));
return ngc->newstr(str.str().substr(0, len.num()));
}
var builtin_right(var* local, gc& ngc) {
var builtin_right(context* ctx, gc* ngc) {
auto local = ctx->localr;
var str = local[1];
var len = local[2];
if (str.type!=vm_str) {
@ -344,10 +355,11 @@ var builtin_right(var* local, gc& ngc) {
if (length<0) {
length = 0;
}
return ngc.newstr(str.str().substr(srclen-length, srclen));
return ngc->newstr(str.str().substr(srclen-length, srclen));
}
var builtin_cmp(var* local, gc& ngc) {
var builtin_cmp(context* ctx, gc* ngc) {
auto local = ctx->localr;
var a = local[1];
var b = local[2];
if (a.type!=vm_str || b.type!=vm_str) {
@ -359,7 +371,7 @@ var builtin_cmp(var* local, gc& ngc) {
)));
}
var builtin_chr(var* local, gc& ngc) {
var builtin_chr(context* ctx, gc* ngc) {
const char* extend[] = {
""," ","","ƒ","","","","",
"ˆ","","Š","","Œ"," ","Ž"," ",
@ -378,25 +390,25 @@ var builtin_chr(var* local, gc& ngc) {
"ð","ñ","ò","ó","ô","õ","ö","÷",
"ø","ù","ú","û","ü","ý","þ","ÿ"
};
i32 num = local[1].num();
auto num = static_cast<i32>(ctx->localr[1].num());
if (0<=num && num<128) {
return ngc.newstr((char)num);
return ngc->newstr((char)num);
} else if (128<=num && num<256) {
return ngc.newstr(extend[num-128]);
return ngc->newstr(extend[num-128]);
}
return ngc.newstr(" ");
return ngc->newstr(" ");
}
var builtin_char(var* local, gc& ngc) {
return ngc.newstr((unsigned char)local[1].num());
var builtin_char(context* ctx, gc* ngc) {
return ngc->newstr(static_cast<unsigned char>(ctx->localr[1].num()));
}
var builtin_values(var* local, gc& ngc) {
var hash = local[1];
var builtin_values(context* ctx, gc* ngc) {
auto hash = ctx->localr[1];
if (hash.type!=vm_hash) {
return nas_err("values", "\"hash\" must be hash");
}
var vec = ngc.alloc(vm_vec);
var vec = ngc->alloc(vm_vec);
auto& v = vec.vec().elems;
for(auto& i : hash.hash().elems) {
v.push_back(i.second);
@ -404,8 +416,8 @@ var builtin_values(var* local, gc& ngc) {
return vec;
}
var builtin_sleep(var* local, gc& ngc) {
var val = local[1];
var builtin_sleep(context* ctx, gc* ngc) {
auto val = ctx->localr[1];
if (val.type!=vm_num) {
return nil;
}
@ -421,36 +433,36 @@ var builtin_sleep(var* local, gc& ngc) {
return nil;
}
var builtin_platform(var* local, gc& ngc) {
var builtin_platform(context* ctx, gc* ngc) {
if (is_windows()) {
return ngc.newstr("windows");
return ngc->newstr("windows");
} else if (is_linux()) {
return ngc.newstr("linux");
return ngc->newstr("linux");
} else if (is_macos()) {
return ngc.newstr("macOS");
return ngc->newstr("macOS");
}
return ngc.newstr("unknown");
return ngc->newstr("unknown");
}
var builtin_arch(var* local, gc& ngc) {
var builtin_arch(context* ctx, gc* ngc) {
if (is_x86()) {
return ngc.newstr("x86");
return ngc->newstr("x86");
} else if (is_x86_64()) {
return ngc.newstr("x86-64");
return ngc->newstr("x86-64");
} else if (is_amd64()) {
return ngc.newstr("amd64");
return ngc->newstr("amd64");
} else if (is_arm()) {
return ngc.newstr("arm");
return ngc->newstr("arm");
} else if (is_aarch64()) {
return ngc.newstr("aarch64");
return ngc->newstr("aarch64");
} else if (is_ia64()) {
return ngc.newstr("ia64");
return ngc->newstr("ia64");
} else if (is_powerpc()) {
return ngc.newstr("powerpc");
return ngc->newstr("powerpc");
} else if (is_superh()) {
return ngc.newstr("superh");
return ngc->newstr("superh");
}
return ngc.newstr("unknown");
return ngc->newstr("unknown");
}
// md5 related functions
@ -536,64 +548,64 @@ std::string md5(const std::string& src) {
return tohex(atmp)+tohex(btmp)+tohex(ctmp)+tohex(dtmp);
}
var builtin_md5(var* local, gc& ngc) {
var str = local[1];
var builtin_md5(context* ctx, gc* ngc) {
auto str = ctx->localr[1];
if (str.type!=vm_str) {
return nas_err("md5", "\"str\" must be string");
}
return ngc.newstr(md5(str.str()));
return ngc->newstr(md5(str.str()));
}
var builtin_millisec(var* local, gc& ngc) {
var builtin_millisec(context* ctx, gc* ngc) {
f64 res = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::high_resolution_clock::now().time_since_epoch())
.count();
return var::num(res);
}
var builtin_gcextend(var* local, gc& ngc) {
var type = local[1];
var builtin_gcextend(context* ctx, gc* ngc) {
auto type = ctx->localr[1];
if (type.type!=vm_str) {
return nil;
}
auto& s = type.str();
const auto& s = type.str();
if (s=="str") {
ngc.extend(vm_str);
ngc->extend(vm_str);
} else if (s=="vec") {
ngc.extend(vm_vec);
ngc->extend(vm_vec);
} else if (s=="hash") {
ngc.extend(vm_hash);
ngc->extend(vm_hash);
} else if (s=="func") {
ngc.extend(vm_func);
ngc->extend(vm_func);
} else if (s=="upval") {
ngc.extend(vm_upval);
ngc->extend(vm_upval);
} else if (s=="obj") {
ngc.extend(vm_obj);
ngc->extend(vm_obj);
} else if (s=="co") {
ngc.extend(vm_co);
ngc->extend(vm_co);
}
return nil;
}
var builtin_gcinfo(var* local, gc& ngc) {
var builtin_gcinfo(context* ctx, gc* ngc) {
auto den = std::chrono::high_resolution_clock::duration::period::den;
var res = ngc.alloc(vm_hash);
var res = ngc->alloc(vm_hash);
double total = 0;
for(u32 i = 0; i<gc_type_size; ++i) {
total += ngc.gcnt[i];
total += ngc->gcnt[i];
}
// using ms
auto& map = res.hash().elems;
map["total"] = var::num(ngc.worktime*1.0/den*1000);
map["average"] = var::num(ngc.worktime*1.0/den*1000/total);
map["max_gc"] = var::num(ngc.max_time*1.0/den*1000);
map["max_mark"] = var::num(ngc.max_mark_time*1.0/den*1000);
map["max_sweep"] = var::num(ngc.max_sweep_time*1.0/den*1000);
map["total"] = var::num(ngc->worktime*1.0/den*1000);
map["average"] = var::num(ngc->worktime*1.0/den*1000/total);
map["max_gc"] = var::num(ngc->max_time*1.0/den*1000);
map["max_mark"] = var::num(ngc->max_mark_time*1.0/den*1000);
map["max_sweep"] = var::num(ngc->max_sweep_time*1.0/den*1000);
return res;
}
var builtin_logtime(var* local, gc& ngc) {
var builtin_logtime(context* ctx, gc* ngc) {
time_t t = time(nullptr);
tm* tm_t = localtime(&t);
char s[64];
@ -606,11 +618,11 @@ var builtin_logtime(var* local, gc& ngc) {
tm_t->tm_min,
tm_t->tm_sec
);
return ngc.newstr(s);
return ngc->newstr(s);
}
var builtin_ghosttype(var* local, gc& ngc) {
var arg = local[1];
var builtin_ghosttype(context* ctx, gc* ngc) {
auto arg = ctx->localr[1];
if (arg.type!=vm_obj) {
return nas_err("ghosttype", "this is not a ghost object.");
}
@ -618,7 +630,7 @@ var builtin_ghosttype(var* local, gc& ngc) {
if (!name.length()) {
return var::num(reinterpret_cast<u64>(arg.obj().pointer));
}
return ngc.newstr(name);
return ngc->newstr(name);
}
nasal_builtin_table builtin[] = {

View File

@ -29,56 +29,56 @@
namespace nasal {
var builtin_print(var*, gc&);
var builtin_println(var*, gc&);
var builtin_exit(var*, gc&);
var builtin_abort(var*, gc&);
var builtin_append(var*, gc&);
var builtin_setsize(var*, gc&);
var builtin_system(var*, gc&);
var builtin_input(var*, gc&);
var builtin_split(var*, gc&);
var builtin_rand(var*, gc&);
var builtin_id(var*, gc&);
var builtin_int(var*, gc&);
var builtin_floor(var*, gc&);
var builtin_num(var*, gc&);
var builtin_pop(var*, gc&);
var builtin_str(var*, gc&);
var builtin_size(var*, gc&);
var builtin_time(var*, gc&);
var builtin_contains(var*, gc&);
var builtin_delete(var*, gc&);
var builtin_keys(var*, gc&);
var builtin_die(var*, gc&);
var builtin_find(var*, gc&);
var builtin_type(var*, gc&);
var builtin_substr(var*, gc&);
var builtin_streq(var*, gc&);
var builtin_left(var*, gc&);
var builtin_right(var*, gc&);
var builtin_cmp(var*, gc&);
var builtin_chr(var*, gc&);
var builtin_char(var*, gc&);
var builtin_values(var*, gc&);
var builtin_sleep(var*, gc&);
var builtin_platform(var*, gc&);
var builtin_arch(var*, gc&);
var builtin_print(context*, gc*);
var builtin_println(context*, gc*);
var builtin_exit(context*, gc*);
var builtin_abort(context*, gc*);
var builtin_append(context*, gc*);
var builtin_setsize(context*, gc*);
var builtin_system(context*, gc*);
var builtin_input(context*, gc*);
var builtin_split(context*, gc*);
var builtin_rand(context*, gc*);
var builtin_id(context*, gc*);
var builtin_int(context*, gc*);
var builtin_floor(context*, gc*);
var builtin_num(context*, gc*);
var builtin_pop(context*, gc*);
var builtin_str(context*, gc*);
var builtin_size(context*, gc*);
var builtin_time(context*, gc*);
var builtin_contains(context*, gc*);
var builtin_delete(context*, gc*);
var builtin_keys(context*, gc*);
var builtin_die(context*, gc*);
var builtin_find(context*, gc*);
var builtin_type(context*, gc*);
var builtin_substr(context*, gc*);
var builtin_streq(context*, gc*);
var builtin_left(context*, gc*);
var builtin_right(context*, gc*);
var builtin_cmp(context*, gc*);
var builtin_chr(context*, gc*);
var builtin_char(context*, gc*);
var builtin_values(context*, gc*);
var builtin_sleep(context*, gc*);
var builtin_platform(context*, gc*);
var builtin_arch(context*, gc*);
// md5 related functions
std::string tohex(u32);
std::string md5(const std::string&);
var builtin_md5(var*, gc&);
var builtin_millisec(var*, gc&);
var builtin_gcextend(var*, gc&);
var builtin_gcinfo(var*, gc&);
var builtin_logtime(var*, gc&);
var builtin_ghosttype(var*, gc&);
var builtin_md5(context*, gc*);
var builtin_millisec(context*, gc*);
var builtin_gcextend(context*, gc*);
var builtin_gcinfo(context*, gc*);
var builtin_logtime(context*, gc*);
var builtin_ghosttype(context*, gc*);
// register builtin function's name and it's address here in this table below
// this table must end with {nullptr,nullptr}
struct nasal_builtin_table {
const char* name;
var (*func)(var*, gc&);
var (*func)(context*, gc*);
};
extern nasal_builtin_table builtin[];

View File

@ -821,11 +821,12 @@ inline void vm::o_callb() {
// if running a native function about coroutine
// (top) will be set to another context.top, instead of main_context.top
var tmp = (*native_function[imm[ctx.pc]].func)(ctx.localr, ngc);
auto function_pointer = native_function[imm[ctx.pc]].func;
var result = (*function_pointer)(&ctx, &ngc);
// so we use tmp variable to store this return value
// and set it to top[0] later
ctx.top[0] = tmp;
ctx.top[0] = result;
// if get none, this means errors occurred when calling this native function
if (ctx.top[0].type==vm_none) {

View File

@ -12,130 +12,130 @@ void dir_entry_destructor(void* ptr) {
#endif
}
var builtin_pipe(var* local, gc& ngc) {
var builtin_pipe(context* ctx, gc* ngc) {
#ifndef _WIN32
i32 fd[2];
var res = ngc.alloc(vm_vec);
var res = ngc->alloc(vm_vec);
if (pipe(fd)==-1) {
return nas_err("pipe", "failed to create pipe");
return nas_err("unix::pipe", "failed to create pipe");
}
res.vec().elems.push_back(var::num(static_cast<f64>(fd[0])));
res.vec().elems.push_back(var::num(static_cast<f64>(fd[1])));
return res;
#endif
return nas_err("pipe", "not supported on windows");
return nas_err("unix::pipe", "not supported on windows");
}
var builtin_fork(var* local, gc& ngc) {
var builtin_fork(context* ctx, gc* ngc) {
#ifndef _WIN32
f64 res=fork();
if (res<0) {
return nas_err("fork", "failed to fork a process");
return nas_err("unix::fork", "failed to fork a process");
}
return var::num(static_cast<f64>(res));
#endif
return nas_err("fork", "not supported on windows");
return nas_err("unix::fork", "not supported on windows");
}
var builtin_waitpid(var* local, gc& ngc) {
var pid = local[1];
var nohang = local[2];
var builtin_waitpid(context* ctx, gc* ngc) {
auto pid = ctx->localr[1];
auto nohang = ctx->localr[2];
if (pid.type!=vm_num || nohang.type!=vm_num) {
return nas_err("waitpid", "pid and nohang must be number");
return nas_err("unix::waitpid", "pid and nohang must be number");
}
#ifndef _WIN32
i32 ret_pid, status;
ret_pid = waitpid(pid.num(), &status, nohang.num()==0? 0:WNOHANG);
var vec = ngc.alloc(vm_vec);
var vec = ngc->alloc(vm_vec);
vec.vec().elems.push_back(var::num(static_cast<f64>(ret_pid)));
vec.vec().elems.push_back(var::num(static_cast<f64>(status)));
return vec;
#endif
return nas_err("waitpid", "not supported on windows");
return nas_err("unix::waitpid", "not supported on windows");
}
var builtin_opendir(var* local, gc& ngc) {
var path = local[1];
var builtin_opendir(context* ctx, gc* ngc) {
auto path = ctx->localr[1];
if (path.type!=vm_str) {
return nas_err("opendir", "\"path\" must be string");
return nas_err("unix::opendir", "\"path\" must be string");
}
#ifdef _MSC_VER
WIN32_FIND_DATAA data;
HANDLE p;
p = FindFirstFileA((path.str()+"\\*.*").c_str(), &data);
if (p==INVALID_HANDLE_VALUE) {
return nas_err("opendir", "cannot open dir <"+path.str()+">");
return nas_err("unix::opendir", "cannot open dir <"+path.str()+">");
}
#else
DIR* p = opendir(path.str().c_str());
if (!p) {
return nas_err("opendir", "cannot open dir <"+path.str()+">");
return nas_err("unix::opendir", "cannot open dir <"+path.str()+">");
}
#endif
var ret = ngc.alloc(vm_obj);
var ret = ngc->alloc(vm_obj);
ret.obj().set(dir_type_name, dir_entry_destructor, p);
return ret;
}
var builtin_readdir(var* local, gc& ngc) {
var handle = local[1];
var builtin_readdir(context* ctx, gc* ngc) {
auto handle = ctx->localr[1];
if (!handle.object_check(dir_type_name)) {
return nas_err("readdir", "not a valid dir handle");
return nas_err("unix::readdir", "not a valid dir handle");
}
#ifdef _MSC_VER
WIN32_FIND_DATAA data;
if (!FindNextFileA(handle.obj().pointer, &data)) {
return nil;
}
return ngc.newstr(data.cFileName);
return ngc->newstr(data.cFileName);
#else
dirent* p = readdir(static_cast<DIR*>(handle.obj().pointer));
return p? ngc.newstr(p->d_name):nil;
return p? ngc->newstr(p->d_name):nil;
#endif
}
var builtin_closedir(var* local, gc& ngc) {
var handle = local[1];
var builtin_closedir(context* ctx, gc* ngc) {
auto handle = ctx->localr[1];
if (!handle.object_check(dir_type_name)) {
return nas_err("closedir", "not a valid dir handle");
return nas_err("unix::closedir", "not a valid dir handle");
}
handle.obj().clear();
return nil;
}
var builtin_chdir(var* local, gc& ngc) {
var path = local[1];
var builtin_chdir(context* ctx, gc* ngc) {
auto path = ctx->localr[1];
if (path.type!=vm_str) {
return var::num(-1.0);
}
return var::num(static_cast<f64>(chdir(path.str().c_str())));
}
var builtin_environ(var* local, gc& ngc) {
var res = ngc.temp = ngc.alloc(vm_vec);
var builtin_environ(context* ctx, gc* ngc) {
var res = ngc->temp = ngc->alloc(vm_vec);
auto& vec = res.vec().elems;
for(char** env = environ; *env; ++env) {
vec.push_back(ngc.newstr(*env));
vec.push_back(ngc->newstr(*env));
}
ngc.temp = nil;
ngc->temp = nil;
return res;
}
var builtin_getcwd(var* local, gc& ngc) {
var builtin_getcwd(context* ctx, gc* ngc) {
char buf[1024];
if (!getcwd(buf, sizeof(buf))) {
return nil;
}
return ngc.newstr(buf);
return ngc->newstr(buf);
}
var builtin_getenv(var* local, gc& ngc) {
var envvar = local[1];
var builtin_getenv(context* ctx, gc* ngc) {
auto envvar = ctx->localr[1];
if (envvar.type!=vm_str) {
return nas_err("getenv", "\"envvar\" must be string");
return nas_err("unix::getenv", "\"envvar\" must be string");
}
char* res = getenv(envvar.str().c_str());
return res? ngc.newstr(res):nil;
return res? ngc->newstr(res):nil;
}
nasal_builtin_table unix_lib_native[] = {

View File

@ -24,16 +24,16 @@ namespace nasal {
void dir_entry_destructor(void*);
var builtin_pipe(var*, gc&);
var builtin_fork(var*, gc&);
var builtin_waitpid(var*, gc&);
var builtin_opendir(var*, gc&);
var builtin_readdir(var*, gc&);
var builtin_closedir(var*, gc&);
var builtin_chdir(var*, gc&);
var builtin_environ(var*, gc&);
var builtin_getcwd(var*, gc&);
var builtin_getenv(var*, gc&);
var builtin_pipe(context*, gc*);
var builtin_fork(context*, gc*);
var builtin_waitpid(context*, gc*);
var builtin_opendir(context*, gc*);
var builtin_readdir(context*, gc*);
var builtin_closedir(context*, gc*);
var builtin_chdir(context*, gc*);
var builtin_environ(context*, gc*);
var builtin_getcwd(context*, gc*);
var builtin_getenv(context*, gc*);
extern nasal_builtin_table unix_lib_native[];