✨ add template get/convert for ghost
This commit is contained in:
parent
9752b8823e
commit
ce204352c6
1
makefile
1
makefile
|
@ -330,6 +330,7 @@ test:nasal
|
||||||
@ ./nasal -t -d test/quick_sort.nas
|
@ ./nasal -t -d test/quick_sort.nas
|
||||||
@ ./nasal -t -d test/regex_test.nas
|
@ ./nasal -t -d test/regex_test.nas
|
||||||
@ ./nasal -e test/scalar.nas hello world
|
@ ./nasal -e test/scalar.nas hello world
|
||||||
|
@ ./nasal test/subprocess_test.nas
|
||||||
@ ./nasal -e test/trait.nas
|
@ ./nasal -e test/trait.nas
|
||||||
@ ./nasal -t -d test/turingmachine.nas
|
@ ./nasal -t -d test/turingmachine.nas
|
||||||
@ ./nasal -d test/wavecollapse.nas
|
@ ./nasal -d test/wavecollapse.nas
|
||||||
|
|
|
@ -91,10 +91,10 @@ var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
}
|
}
|
||||||
f64 num = args[1].num();
|
f64 num = args[1].num();
|
||||||
|
|
||||||
reinterpret_cast<ghost_obj*>(res.ghost().pointer)->number = static_cast<u32>(num);
|
res.ghost().get<ghost_obj>()->number = static_cast<u32>(num);
|
||||||
std::cout << "set_new_ghost: successfully set ghost.number = " << num << "\n";
|
std::cout << "set_new_ghost: successfully set ghost.number = " << num << "\n";
|
||||||
|
|
||||||
reinterpret_cast<ghost_obj*>(res.ghost().pointer)->test_string = ngc->newstr("just for test");
|
res.ghost().get<ghost_obj>()->test_string = ngc->newstr("just for test");
|
||||||
std::cout << "set_new_ghost: successfully set ghost.test_string = just for test\n";
|
std::cout << "set_new_ghost: successfully set ghost.test_string = just for test\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -106,9 +106,9 @@ var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
std::cout << "print_new_ghost: " << res.ghost() << " number = "
|
std::cout << "print_new_ghost: " << res.ghost() << " number = "
|
||||||
<< reinterpret_cast<ghost_obj*>(res.ghost().pointer)->number
|
<< res.ghost().get<ghost_obj>()->number
|
||||||
<< " test_string = "
|
<< " test_string = "
|
||||||
<< reinterpret_cast<ghost_obj*>(res.ghost().pointer)->test_string
|
<< res.ghost().get<ghost_obj>()->test_string
|
||||||
<< "\n";
|
<< "\n";
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ void nas_ghost::clear() {
|
||||||
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
||||||
out << "<object " << ghost.get_ghost_name();
|
out << "<object " << ghost.get_ghost_name();
|
||||||
out << " at 0x" << std::hex;
|
out << " at 0x" << std::hex;
|
||||||
out << reinterpret_cast<u64>(ghost.pointer) << std::dec << ">";
|
out << ghost.convert<u64>() << std::dec << ">";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,12 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const auto& get_ghost_name() const { return type_name; }
|
const auto& get_ghost_name() const { return type_name; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename T>
|
||||||
|
T* get() { return static_cast<T*>(pointer); }
|
||||||
|
template<typename T>
|
||||||
|
T convert() const { return reinterpret_cast<T>(pointer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
|
|
|
@ -615,7 +615,7 @@ var builtin_time_stamp(context* ctx, gc* ngc) {
|
||||||
if (!object.object_check("nasal-time-stamp")) {
|
if (!object.object_check("nasal-time-stamp")) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
auto stamp = static_cast<time_stamp*>(object.ghost().pointer);
|
auto stamp = object.ghost().get<time_stamp>();
|
||||||
stamp->make_stamp();
|
stamp->make_stamp();
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -625,7 +625,7 @@ var builtin_elapsed_millisecond(context* ctx, gc* ngc) {
|
||||||
if (!object.object_check("nasal-time-stamp")) {
|
if (!object.object_check("nasal-time-stamp")) {
|
||||||
return var::num(-1);
|
return var::num(-1);
|
||||||
}
|
}
|
||||||
auto stamp = static_cast<time_stamp*>(object.ghost().pointer);
|
auto stamp = object.ghost().get<time_stamp>();
|
||||||
return var::num(static_cast<f64>(stamp->elapsed_milliseconds()));
|
return var::num(static_cast<f64>(stamp->elapsed_milliseconds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ var builtin_elapsed_microsecond(context* ctx, gc* ngc) {
|
||||||
if (!object.object_check("nasal-time-stamp")) {
|
if (!object.object_check("nasal-time-stamp")) {
|
||||||
return var::num(-1);
|
return var::num(-1);
|
||||||
}
|
}
|
||||||
auto stamp = static_cast<time_stamp*>(object.ghost().pointer);
|
auto stamp = object.ghost().get<time_stamp>();
|
||||||
return var::num(static_cast<f64>(stamp->elapsed_microseconds()));
|
return var::num(static_cast<f64>(stamp->elapsed_microseconds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +717,7 @@ var builtin_ghosttype(context* ctx, gc* ngc) {
|
||||||
if (!name.length()) {
|
if (!name.length()) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "0x" << std::hex;
|
ss << "0x" << std::hex;
|
||||||
ss << reinterpret_cast<u64>(arg.ghost().pointer) << std::dec;
|
ss << arg.ghost().convert<u64>() << std::dec;
|
||||||
return ngc->newstr(ss.str());
|
return ngc->newstr(ss.str());
|
||||||
}
|
}
|
||||||
return ngc->newstr(name);
|
return ngc->newstr(name);
|
||||||
|
|
|
@ -55,7 +55,7 @@ var builtin_dlopen(context* ctx, gc* ngc) {
|
||||||
// get "get" function, to get the register table
|
// get "get" function, to get the register table
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* register_table_get_function = reinterpret_cast<void*>(GetProcAddress(
|
void* register_table_get_function = reinterpret_cast<void*>(GetProcAddress(
|
||||||
static_cast<HMODULE>(library_object.ghost().pointer), "get"
|
library_object.ghost().convert<HMODULE>(), "get"
|
||||||
));
|
));
|
||||||
#else
|
#else
|
||||||
void* register_table_get_function = dlsym(
|
void* register_table_get_function = dlsym(
|
||||||
|
@ -105,7 +105,7 @@ var builtin_dlcallv(context* ctx, gc* ngc) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
auto& vec = arguments.vec().elems;
|
auto& vec = arguments.vec().elems;
|
||||||
return reinterpret_cast<module_func>(function_object.ghost().pointer)(
|
return function_object.ghost().convert<module_func>()(
|
||||||
vec.data(),
|
vec.data(),
|
||||||
vec.size(),
|
vec.size(),
|
||||||
ngc
|
ngc
|
||||||
|
@ -124,7 +124,7 @@ var builtin_dlcall(context* ctx, gc* ngc) {
|
||||||
// so arguments starts from ctx->localr[2]
|
// so arguments starts from ctx->localr[2]
|
||||||
var* local_frame_start = ctx->localr + 2;
|
var* local_frame_start = ctx->localr + 2;
|
||||||
usize local_frame_size = ngc->running_context->top - local_frame_start;
|
usize local_frame_size = ngc->running_context->top - local_frame_start;
|
||||||
return reinterpret_cast<module_func>(function_object.ghost().pointer)(
|
return function_object.ghost().convert<module_func>()(
|
||||||
local_frame_start,
|
local_frame_start,
|
||||||
local_frame_size,
|
local_frame_size,
|
||||||
ngc
|
ngc
|
||||||
|
|
|
@ -101,7 +101,7 @@ var builtin_read(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
auto read_size = fread(
|
auto read_size = fread(
|
||||||
temp_buffer, 1, length.num(),
|
temp_buffer, 1, length.num(),
|
||||||
static_cast<FILE*>(file_descriptor.ghost().pointer)
|
file_descriptor.ghost().get<FILE>()
|
||||||
);
|
);
|
||||||
buffer.str() = temp_buffer;
|
buffer.str() = temp_buffer;
|
||||||
buffer.val.gcobj->immutable = true;
|
buffer.val.gcobj->immutable = true;
|
||||||
|
@ -121,7 +121,7 @@ var builtin_write(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(fwrite(
|
return var::num(static_cast<f64>(fwrite(
|
||||||
source.str().c_str(), 1, source.str().length(),
|
source.str().c_str(), 1, source.str().length(),
|
||||||
static_cast<FILE*>(file_descriptor.ghost().pointer)
|
file_descriptor.ghost().get<FILE>()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ var builtin_seek(context* ctx, gc* ngc) {
|
||||||
return nas_err("io::seek", "not a valid filehandle");
|
return nas_err("io::seek", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(fseek(
|
return var::num(static_cast<f64>(fseek(
|
||||||
static_cast<FILE*>(file_descriptor.ghost().pointer),
|
file_descriptor.ghost().get<FILE>(),
|
||||||
position.num(),
|
position.num(),
|
||||||
whence.num()
|
whence.num()
|
||||||
)));
|
)));
|
||||||
|
@ -146,7 +146,7 @@ var builtin_tell(context* ctx, gc* ngc) {
|
||||||
return nas_err("io::tell", "not a valid filehandle");
|
return nas_err("io::tell", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(
|
return var::num(static_cast<f64>(
|
||||||
ftell(static_cast<FILE*>(file_descriptor.ghost().pointer))
|
ftell(file_descriptor.ghost().get<FILE>())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ var builtin_readln(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
auto result = ngc->alloc(vm_type::vm_str);
|
auto result = ngc->alloc(vm_type::vm_str);
|
||||||
char c;
|
char c;
|
||||||
while((c = fgetc(static_cast<FILE*>(file_descriptor.ghost().pointer)))!=EOF) {
|
while((c = fgetc(file_descriptor.ghost().get<FILE>()))!=EOF) {
|
||||||
if (c=='\r') {
|
if (c=='\r') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ var builtin_eof(context* ctx, gc* ngc) {
|
||||||
return nas_err("io::readln", "not a valid filehandle");
|
return nas_err("io::readln", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(
|
return var::num(static_cast<f64>(
|
||||||
feof(static_cast<FILE*>(file_descriptor.ghost().pointer))
|
feof(file_descriptor.ghost().get<FILE>())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ var builtin_json_stringify(context* ctx, gc* ngc) {
|
||||||
if (!json_object.object_check("nasal::json")) {
|
if (!json_object.object_check("nasal::json")) {
|
||||||
return nas_err("json::stringify", "expect a json object.");
|
return nas_err("json::stringify", "expect a json object.");
|
||||||
}
|
}
|
||||||
auto json_ptr = static_cast<json*>(json_object.ghost().pointer);
|
auto json_ptr = json_object.ghost().get<json>();
|
||||||
return ngc->newstr(json_ptr->stringify(object));
|
return ngc->newstr(json_ptr->stringify(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ var builtin_json_parse(context* ctx, gc* ngc) {
|
||||||
if (!input_string.is_str()) {
|
if (!input_string.is_str()) {
|
||||||
return nas_err("json::parse", "require string as the input.");
|
return nas_err("json::parse", "require string as the input.");
|
||||||
}
|
}
|
||||||
auto json_ptr = static_cast<json*>(json_object.ghost().pointer);
|
auto json_ptr = json_object.ghost().get<json>();
|
||||||
return json_ptr->parse(input_string.str(), ngc);
|
return json_ptr->parse(input_string.str(), ngc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ var builtin_json_get_error(context* ctx, gc* ngc) {
|
||||||
if (!json_object.object_check("nasal::json")) {
|
if (!json_object.object_check("nasal::json")) {
|
||||||
return nas_err("json::get_error", "expect a json object.");
|
return nas_err("json::get_error", "expect a json object.");
|
||||||
}
|
}
|
||||||
auto json_ptr = static_cast<json*>(json_object.ghost().pointer);
|
auto json_ptr = json_object.ghost().get<json>();
|
||||||
return ngc->newstr(json_ptr->get_error());
|
return ngc->newstr(json_ptr->get_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,16 @@
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
const auto subproc_desc_name = "subprocess_descriptor";
|
|
||||||
|
|
||||||
void subprocess_desc_dtor(void* ptr) {
|
void subprocess_desc_dtor(void* ptr) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
auto pi = &static_cast<subprocess_descriptor*>(ptr)->pi;
|
auto pi = &static_cast<subprocess*>(ptr)->pi;
|
||||||
|
|
||||||
WaitForSingleObject(pi->hProcess, 0);
|
WaitForSingleObject(pi->hProcess, 0);
|
||||||
TerminateProcess(pi->hProcess, 0);
|
TerminateProcess(pi->hProcess, 0);
|
||||||
CloseHandle(pi->hProcess);
|
CloseHandle(pi->hProcess);
|
||||||
CloseHandle(pi->hThread);
|
CloseHandle(pi->hThread);
|
||||||
#else
|
#else
|
||||||
auto pid = static_cast<subprocess_descriptor*>(ptr)->pid;
|
auto pid = static_cast<subprocess*>(ptr)->pid;
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
pid_t result = waitpid(pid, &status, WNOHANG);
|
pid_t result = waitpid(pid, &status, WNOHANG);
|
||||||
|
@ -50,26 +48,30 @@ void subprocess_desc_dtor(void* ptr) {
|
||||||
var builtin_subprocess_create(context* ctx, gc* ngc) {
|
var builtin_subprocess_create(context* ctx, gc* ngc) {
|
||||||
auto cmd = ctx->localr[1];
|
auto cmd = ctx->localr[1];
|
||||||
if (!cmd.is_vec()) {
|
if (!cmd.is_vec()) {
|
||||||
return nas_err("subprocess::create", "expect a string as the command");
|
return nas_err("subprocess::create",
|
||||||
|
"expect string vector as the command"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto& v : cmd.vec().elems) {
|
for(const auto& v : cmd.vec().elems) {
|
||||||
if (!v.is_str()) {
|
if (!v.is_str()) {
|
||||||
return nas_err("subprocess::create", "non-string arguments");
|
return nas_err("subprocess::create",
|
||||||
|
"non-string argument found"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto obj = ngc->alloc(vm_type::vm_ghost);
|
auto obj = ngc->alloc(vm_type::vm_ghost);
|
||||||
obj.ghost().set(
|
obj.ghost().set(
|
||||||
subproc_desc_name,
|
subprocess::name(),
|
||||||
subprocess_desc_dtor,
|
subprocess_desc_dtor,
|
||||||
nullptr,
|
nullptr,
|
||||||
new subprocess_descriptor
|
new subprocess
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
auto si = &static_cast<subprocess_descriptor*>(obj.ghost().pointer)->si;
|
auto si = &obj.ghost().get<subprocess>()->si;
|
||||||
auto pi = &static_cast<subprocess_descriptor*>(obj.ghost().pointer)->pi;
|
auto pi = &obj.ghost().get<subprocess>()->pi;
|
||||||
|
|
||||||
// init STARTUPINFO
|
// init STARTUPINFO
|
||||||
ZeroMemory(si, sizeof(STARTUPINFOW));
|
ZeroMemory(si, sizeof(STARTUPINFOW));
|
||||||
|
@ -135,7 +137,7 @@ var builtin_subprocess_create(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parent process
|
// parent process
|
||||||
static_cast<subprocess_descriptor*>(obj.ghost().pointer)->pid = pid;
|
obj.ghost().get<subprocess>()->pid = pid;
|
||||||
for(usize i = 0; argv[i]; ++i) {
|
for(usize i = 0; argv[i]; ++i) {
|
||||||
delete argv[i];
|
delete argv[i];
|
||||||
}
|
}
|
||||||
|
@ -148,14 +150,14 @@ var builtin_subprocess_create(context* ctx, gc* ngc) {
|
||||||
|
|
||||||
var builtin_subprocess_terminate(context* ctx, gc* ngc) {
|
var builtin_subprocess_terminate(context* ctx, gc* ngc) {
|
||||||
auto obj = ctx->localr[1];
|
auto obj = ctx->localr[1];
|
||||||
if (!obj.object_check(subproc_desc_name)) {
|
if (!obj.object_check(subprocess::name())) {
|
||||||
return nas_err("subprocess::terminate",
|
return nas_err("subprocess::terminate",
|
||||||
"need correct subprocess descriptor"
|
"need correct subprocess object"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
auto pi = &static_cast<subprocess_descriptor*>(obj.ghost().pointer)->pi;
|
auto pi = &obj.ghost().get<subprocess>()->pi;
|
||||||
|
|
||||||
WaitForSingleObject(pi->hProcess, 0);
|
WaitForSingleObject(pi->hProcess, 0);
|
||||||
TerminateProcess(pi->hProcess, -1);
|
TerminateProcess(pi->hProcess, -1);
|
||||||
|
@ -166,7 +168,7 @@ var builtin_subprocess_terminate(context* ctx, gc* ngc) {
|
||||||
CloseHandle(pi->hProcess);
|
CloseHandle(pi->hProcess);
|
||||||
CloseHandle(pi->hThread);
|
CloseHandle(pi->hThread);
|
||||||
#else
|
#else
|
||||||
auto pid = static_cast<subprocess_descriptor*>(obj.ghost().pointer)->pid;
|
auto pid = obj.ghost().get<subprocess>()->pid;
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
pid_t result = waitpid(pid, &status, WNOHANG);
|
pid_t result = waitpid(pid, &status, WNOHANG);
|
||||||
|
|
|
@ -14,13 +14,18 @@
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
struct subprocess_descriptor {
|
struct subprocess {
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#else
|
#else
|
||||||
STARTUPINFOW si;
|
STARTUPINFOW si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const char* name() {
|
||||||
|
return "nasal::subprocess";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void subprocess_desc_dtor(void*);
|
void subprocess_desc_dtor(void*);
|
||||||
|
|
|
@ -89,7 +89,7 @@ var builtin_readdir(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
return ngc->newstr(data.cFileName);
|
return ngc->newstr(data.cFileName);
|
||||||
#else
|
#else
|
||||||
dirent* p = readdir(static_cast<DIR*>(handle.ghost().pointer));
|
dirent* p = readdir(handle.ghost().get<DIR>());
|
||||||
return p? ngc->newstr(p->d_name):nil;
|
return p? ngc->newstr(p->d_name):nil;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
use std.unix;
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
while(1) {
|
||||||
|
unix.sleep(0.1);
|
||||||
|
count += 0.1;
|
||||||
|
println("process running time: ", count);
|
||||||
|
if (count > 2) {
|
||||||
|
die("test failed");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
use std.subprocess;
|
||||||
|
use std.unix;
|
||||||
|
|
||||||
|
var process = subprocess.create([
|
||||||
|
"./nasal",
|
||||||
|
"test/for_subprocess_test/infinite_loop.nas"
|
||||||
|
]);
|
||||||
|
|
||||||
|
unix.sleep(1);
|
||||||
|
|
||||||
|
println("kill subprocess...");
|
||||||
|
var res = subprocess.terminate(process);
|
||||||
|
println("subprocess killed, code ", res);
|
Loading…
Reference in New Issue