✨ change way of calling native functions
This commit is contained in:
parent
7f8a0b6445
commit
820c05c986
|
@ -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;
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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,16 +168,16 @@ 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");
|
||||
}
|
||||
struct stat buf;
|
||||
if (stat(name.str().c_str(),&buf)<0) {
|
||||
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");
|
||||
}
|
||||
|
|
24
src/io_lib.h
24
src/io_lib.h
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
Loading…
Reference in New Issue