diff --git a/makefile b/makefile index 7cde7a3..808bda3 100644 --- a/makefile +++ b/makefile @@ -330,6 +330,7 @@ test:nasal @ ./nasal -t -d test/quick_sort.nas @ ./nasal -t -d test/regex_test.nas @ ./nasal -e test/scalar.nas hello world + @ ./nasal test/subprocess_test.nas @ ./nasal -e test/trait.nas @ ./nasal -t -d test/turingmachine.nas @ ./nasal -d test/wavecollapse.nas diff --git a/module/fib.cpp b/module/fib.cpp index dace56b..36cee41 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -91,10 +91,10 @@ var set_new_ghost(var* args, usize size, gc* ngc) { } f64 num = args[1].num(); - reinterpret_cast(res.ghost().pointer)->number = static_cast(num); + res.ghost().get()->number = static_cast(num); std::cout << "set_new_ghost: successfully set ghost.number = " << num << "\n"; - reinterpret_cast(res.ghost().pointer)->test_string = ngc->newstr("just for test"); + res.ghost().get()->test_string = ngc->newstr("just for test"); std::cout << "set_new_ghost: successfully set ghost.test_string = just for test\n"; return nil; } @@ -106,9 +106,9 @@ var print_new_ghost(var* args, usize size, gc* ngc) { return nil; } std::cout << "print_new_ghost: " << res.ghost() << " number = " - << reinterpret_cast(res.ghost().pointer)->number + << res.ghost().get()->number << " test_string = " - << reinterpret_cast(res.ghost().pointer)->test_string + << res.ghost().get()->test_string << "\n"; return nil; } diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index c163541..4d6b2a2 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -164,7 +164,7 @@ void nas_ghost::clear() { std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) { out << "(ghost.pointer) << std::dec << ">"; + out << ghost.convert() << std::dec << ">"; return out; } diff --git a/src/nasal_type.h b/src/nasal_type.h index 208babb..5a759e5 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -213,6 +213,12 @@ public: public: const auto& get_ghost_name() const { return type_name; } + +public: + template + T* get() { return static_cast(pointer); } + template + T convert() const { return reinterpret_cast(pointer); } }; struct context { diff --git a/src/natives/builtin.cpp b/src/natives/builtin.cpp index 79c0f76..203fae8 100644 --- a/src/natives/builtin.cpp +++ b/src/natives/builtin.cpp @@ -615,7 +615,7 @@ var builtin_time_stamp(context* ctx, gc* ngc) { if (!object.object_check("nasal-time-stamp")) { return nil; } - auto stamp = static_cast(object.ghost().pointer); + auto stamp = object.ghost().get(); stamp->make_stamp(); return nil; } @@ -625,7 +625,7 @@ var builtin_elapsed_millisecond(context* ctx, gc* ngc) { if (!object.object_check("nasal-time-stamp")) { return var::num(-1); } - auto stamp = static_cast(object.ghost().pointer); + auto stamp = object.ghost().get(); return var::num(static_cast(stamp->elapsed_milliseconds())); } @@ -634,7 +634,7 @@ var builtin_elapsed_microsecond(context* ctx, gc* ngc) { if (!object.object_check("nasal-time-stamp")) { return var::num(-1); } - auto stamp = static_cast(object.ghost().pointer); + auto stamp = object.ghost().get(); return var::num(static_cast(stamp->elapsed_microseconds())); } @@ -717,7 +717,7 @@ var builtin_ghosttype(context* ctx, gc* ngc) { if (!name.length()) { std::stringstream ss; ss << "0x" << std::hex; - ss << reinterpret_cast(arg.ghost().pointer) << std::dec; + ss << arg.ghost().convert() << std::dec; return ngc->newstr(ss.str()); } return ngc->newstr(name); diff --git a/src/natives/dylib_lib.cpp b/src/natives/dylib_lib.cpp index f72f700..329d8ed 100644 --- a/src/natives/dylib_lib.cpp +++ b/src/natives/dylib_lib.cpp @@ -55,7 +55,7 @@ var builtin_dlopen(context* ctx, gc* ngc) { // get "get" function, to get the register table #ifdef _WIN32 void* register_table_get_function = reinterpret_cast(GetProcAddress( - static_cast(library_object.ghost().pointer), "get" + library_object.ghost().convert(), "get" )); #else void* register_table_get_function = dlsym( @@ -105,7 +105,7 @@ var builtin_dlcallv(context* ctx, gc* ngc) { ); } auto& vec = arguments.vec().elems; - return reinterpret_cast(function_object.ghost().pointer)( + return function_object.ghost().convert()( vec.data(), vec.size(), ngc @@ -124,7 +124,7 @@ var builtin_dlcall(context* ctx, gc* ngc) { // so arguments starts from ctx->localr[2] var* local_frame_start = ctx->localr + 2; usize local_frame_size = ngc->running_context->top - local_frame_start; - return reinterpret_cast(function_object.ghost().pointer)( + return function_object.ghost().convert()( local_frame_start, local_frame_size, ngc diff --git a/src/natives/io_lib.cpp b/src/natives/io_lib.cpp index c5efb0b..83f81dc 100644 --- a/src/natives/io_lib.cpp +++ b/src/natives/io_lib.cpp @@ -101,7 +101,7 @@ var builtin_read(context* ctx, gc* ngc) { } auto read_size = fread( temp_buffer, 1, length.num(), - static_cast(file_descriptor.ghost().pointer) + file_descriptor.ghost().get() ); buffer.str() = temp_buffer; buffer.val.gcobj->immutable = true; @@ -121,7 +121,7 @@ var builtin_write(context* ctx, gc* ngc) { } return var::num(static_cast(fwrite( source.str().c_str(), 1, source.str().length(), - static_cast(file_descriptor.ghost().pointer) + file_descriptor.ghost().get() ))); } @@ -134,7 +134,7 @@ var builtin_seek(context* ctx, gc* ngc) { return nas_err("io::seek", "not a valid filehandle"); } return var::num(static_cast(fseek( - static_cast(file_descriptor.ghost().pointer), + file_descriptor.ghost().get(), position.num(), whence.num() ))); @@ -146,7 +146,7 @@ var builtin_tell(context* ctx, gc* ngc) { return nas_err("io::tell", "not a valid filehandle"); } return var::num(static_cast( - ftell(static_cast(file_descriptor.ghost().pointer)) + ftell(file_descriptor.ghost().get()) )); } @@ -157,7 +157,7 @@ var builtin_readln(context* ctx, gc* ngc) { } auto result = ngc->alloc(vm_type::vm_str); char c; - while((c = fgetc(static_cast(file_descriptor.ghost().pointer)))!=EOF) { + while((c = fgetc(file_descriptor.ghost().get()))!=EOF) { if (c=='\r') { continue; } @@ -204,7 +204,7 @@ var builtin_eof(context* ctx, gc* ngc) { return nas_err("io::readln", "not a valid filehandle"); } return var::num(static_cast( - feof(static_cast(file_descriptor.ghost().pointer)) + feof(file_descriptor.ghost().get()) )); } diff --git a/src/natives/json_lib.cpp b/src/natives/json_lib.cpp index 719120c..b068f3b 100644 --- a/src/natives/json_lib.cpp +++ b/src/natives/json_lib.cpp @@ -369,7 +369,7 @@ var builtin_json_stringify(context* ctx, gc* ngc) { if (!json_object.object_check("nasal::json")) { return nas_err("json::stringify", "expect a json object."); } - auto json_ptr = static_cast(json_object.ghost().pointer); + auto json_ptr = json_object.ghost().get(); return ngc->newstr(json_ptr->stringify(object)); } @@ -382,7 +382,7 @@ var builtin_json_parse(context* ctx, gc* ngc) { if (!input_string.is_str()) { return nas_err("json::parse", "require string as the input."); } - auto json_ptr = static_cast(json_object.ghost().pointer); + auto json_ptr = json_object.ghost().get(); 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")) { return nas_err("json::get_error", "expect a json object."); } - auto json_ptr = static_cast(json_object.ghost().pointer); + auto json_ptr = json_object.ghost().get(); return ngc->newstr(json_ptr->get_error()); } diff --git a/src/natives/subprocess.cpp b/src/natives/subprocess.cpp index a04038e..1e5394d 100644 --- a/src/natives/subprocess.cpp +++ b/src/natives/subprocess.cpp @@ -24,18 +24,16 @@ namespace nasal { -const auto subproc_desc_name = "subprocess_descriptor"; - void subprocess_desc_dtor(void* ptr) { #ifdef WIN32 - auto pi = &static_cast(ptr)->pi; + auto pi = &static_cast(ptr)->pi; WaitForSingleObject(pi->hProcess, 0); TerminateProcess(pi->hProcess, 0); CloseHandle(pi->hProcess); CloseHandle(pi->hThread); #else - auto pid = static_cast(ptr)->pid; + auto pid = static_cast(ptr)->pid; int status; 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) { auto cmd = ctx->localr[1]; 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) { 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); obj.ghost().set( - subproc_desc_name, + subprocess::name(), subprocess_desc_dtor, nullptr, - new subprocess_descriptor + new subprocess ); #ifdef WIN32 - auto si = &static_cast(obj.ghost().pointer)->si; - auto pi = &static_cast(obj.ghost().pointer)->pi; + auto si = &obj.ghost().get()->si; + auto pi = &obj.ghost().get()->pi; // init STARTUPINFO ZeroMemory(si, sizeof(STARTUPINFOW)); @@ -135,7 +137,7 @@ var builtin_subprocess_create(context* ctx, gc* ngc) { } // parent process - static_cast(obj.ghost().pointer)->pid = pid; + obj.ghost().get()->pid = pid; for(usize i = 0; argv[i]; ++i) { delete argv[i]; } @@ -148,14 +150,14 @@ var builtin_subprocess_create(context* ctx, gc* ngc) { var builtin_subprocess_terminate(context* ctx, gc* ngc) { auto obj = ctx->localr[1]; - if (!obj.object_check(subproc_desc_name)) { + if (!obj.object_check(subprocess::name())) { return nas_err("subprocess::terminate", - "need correct subprocess descriptor" + "need correct subprocess object" ); } #ifdef WIN32 - auto pi = &static_cast(obj.ghost().pointer)->pi; + auto pi = &obj.ghost().get()->pi; WaitForSingleObject(pi->hProcess, 0); TerminateProcess(pi->hProcess, -1); @@ -166,7 +168,7 @@ var builtin_subprocess_terminate(context* ctx, gc* ngc) { CloseHandle(pi->hProcess); CloseHandle(pi->hThread); #else - auto pid = static_cast(obj.ghost().pointer)->pid; + auto pid = obj.ghost().get()->pid; int status; pid_t result = waitpid(pid, &status, WNOHANG); diff --git a/src/natives/subprocess.h b/src/natives/subprocess.h index 4e25f19..587527f 100644 --- a/src/natives/subprocess.h +++ b/src/natives/subprocess.h @@ -14,13 +14,18 @@ namespace nasal { -struct subprocess_descriptor { +struct subprocess { #ifndef WIN32 pid_t pid; #else STARTUPINFOW si; PROCESS_INFORMATION pi; #endif + +public: + static const char* name() { + return "nasal::subprocess"; + } }; void subprocess_desc_dtor(void*); diff --git a/src/natives/unix_lib.cpp b/src/natives/unix_lib.cpp index b791680..f394734 100644 --- a/src/natives/unix_lib.cpp +++ b/src/natives/unix_lib.cpp @@ -89,7 +89,7 @@ var builtin_readdir(context* ctx, gc* ngc) { } return ngc->newstr(data.cFileName); #else - dirent* p = readdir(static_cast(handle.ghost().pointer)); + dirent* p = readdir(handle.ghost().get()); return p? ngc->newstr(p->d_name):nil; #endif } diff --git a/test/for_subprocess_test/infinite_loop.nas b/test/for_subprocess_test/infinite_loop.nas new file mode 100644 index 0000000..bfba824 --- /dev/null +++ b/test/for_subprocess_test/infinite_loop.nas @@ -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"); + } +} \ No newline at end of file diff --git a/test/subprocess_test.nas b/test/subprocess_test.nas new file mode 100644 index 0000000..12cd261 --- /dev/null +++ b/test/subprocess_test.nas @@ -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); \ No newline at end of file