Merge pull request #19 from ValKmjolnir/develop
✨ add ghost_type_table for type registration & add cmake for VS to build
This commit is contained in:
commit
36f6dd6c96
|
@ -38,6 +38,7 @@
|
||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
.vs
|
.vs
|
||||||
x64
|
x64
|
||||||
|
CMakePresents.json
|
||||||
|
|
||||||
# nasal executable
|
# nasal executable
|
||||||
nasal
|
nasal
|
||||||
|
@ -49,6 +50,7 @@ dump
|
||||||
|
|
||||||
# build dir
|
# build dir
|
||||||
build
|
build
|
||||||
|
out
|
||||||
|
|
||||||
# macOS special cache directory
|
# macOS special cache directory
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
project(nasal VERSION 10.1)
|
project(nasal VERSION 10.1)
|
||||||
|
|
||||||
|
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||||
|
|
||||||
# -std=c++14 -Wshadow -Wall
|
# -std=c++14 -Wshadow -Wall
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
@ -9,6 +11,7 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
|
||||||
|
|
||||||
# generate release executables
|
# generate release executables
|
||||||
set(CMAKE_BUILD_TYPE "Release")
|
set(CMAKE_BUILD_TYPE "Release")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
|
||||||
|
|
||||||
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
|
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
|
||||||
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR})
|
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR})
|
||||||
|
@ -23,5 +26,20 @@ add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
|
||||||
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR})
|
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
add_executable(nasal main.cpp)
|
add_executable(nasal main.cpp)
|
||||||
target_link_libraries(nasal dl)
|
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
|
message("Ignore linking dl lib")
|
||||||
|
else()
|
||||||
|
target_link_libraries(nasal dl)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR})
|
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
|
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
|
add_custom_command(
|
||||||
|
TARGET nasal POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_SOURCE_DIR}/build/nasal
|
||||||
|
${CMAKE_SOURCE_DIR}/nasal
|
||||||
|
)
|
||||||
|
endif()
|
22
doc/vs.md
22
doc/vs.md
|
@ -2,12 +2,22 @@
|
||||||
|
|
||||||
## First | 首先
|
## First | 首先
|
||||||
|
|
||||||
Make sure you are using VS 2022.
|
We give a __CMakeLists.txt__ for you to create new VS project from it.
|
||||||
|
|
||||||
确保你使用的是 VS 2022。
|
我们为你提供了 __CMakeLists.txt__ 用于创建新的 VS 工程。
|
||||||
|
|
||||||
|
If you are using this way, you will __not need__ to continue reading.
|
||||||
|
|
||||||
|
如果你使用的是这种方式,下面的内容你就 __不需要__ 再读了。
|
||||||
|
|
||||||
|
Creating VS project from a CMake file is the __simplest__ way.
|
||||||
|
|
||||||
|
从 CMake 文件创建 VS 工程是 __最简单__ 的方式。
|
||||||
|
|
||||||
## How to Create VS project
|
## How to Create VS project
|
||||||
|
|
||||||
|
Make sure you are using VS 2022. You may not get the dynamic libraries by using this way to compile.
|
||||||
|
|
||||||
1. Get code from this repo using `git`.
|
1. Get code from this repo using `git`.
|
||||||
|
|
||||||
2. In Visual Studio, click `File`->`New`->`Project From Existing Code...`.
|
2. In Visual Studio, click `File`->`New`->`Project From Existing Code...`.
|
||||||
|
@ -20,12 +30,14 @@ Make sure you are using VS 2022.
|
||||||
|
|
||||||
## 如何创建VS工程
|
## 如何创建VS工程
|
||||||
|
|
||||||
1. 用`git`从这个仓库获取代码。
|
确保你使用的是 VS 2022。这个方式可能无法生成一些动态库。
|
||||||
|
|
||||||
|
1. 用 `git` 从这个仓库获取代码。
|
||||||
|
|
||||||
2. 在VS的界面,点击文件(F)->新建(N)->从现有代码创建项目(E)。
|
2. 在VS的界面,点击文件(F)->新建(N)->从现有代码创建项目(E)。
|
||||||
|
|
||||||
3. 选择创建`Visual C++`项目->下一步->项目文件位置选择你下载的代码存放的文件夹->填项目名称,随便写->完成。
|
3. 选择创建 `Visual C++` 项目->下一步->项目文件位置选择你下载的代码存放的文件夹->填项目名称,随便写->完成。
|
||||||
|
|
||||||
4. 从项目中去掉 `module` 里的cpp文件,以防止编译错误。(那些本应该编译到动态库)
|
4. 从项目中去掉 `module` 里的cpp文件,以防止编译错误。(那些本应该编译到动态库)
|
||||||
|
|
||||||
5. 点开左侧解决方案资源管理器中的`Source Files`,右键点击`main.cpp`,编译。
|
5. 点开左侧解决方案资源管理器中的 `Source Files`,右键点击 `main.cpp`,编译。
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
// module for test
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "../nasal.h"
|
#include "../nasal.h"
|
||||||
|
|
||||||
|
namespace nasal_fib_module {
|
||||||
|
|
||||||
double fibonaci(double x) {
|
double fibonaci(double x) {
|
||||||
if (x<=2) {
|
if (x<=2) {
|
||||||
return x;
|
return x;
|
||||||
|
@ -33,12 +37,63 @@ var quick_fib(var* args, usize size, gc* ngc) {
|
||||||
return var::num(res);
|
return var::num(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_func func_tbl[]={
|
u32 ghost_for_test;
|
||||||
{"fib",fib},
|
|
||||||
{"quick_fib",quick_fib},
|
void ghost_for_test_destructor(void* ptr) {
|
||||||
{nullptr, nullptr},
|
std::cout<<"ghost_for_test::destructor (0x";
|
||||||
|
std::cout<<std::hex<<(u64)ptr<<std::dec<<") {\n";
|
||||||
|
delete (u32*)ptr;
|
||||||
|
std::cout<<" delete 0x"<<std::hex<<(u64)ptr<<std::dec<<";\n";
|
||||||
|
std::cout<<"}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
var create_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
var res=ngc->alloc(vm_obj);
|
||||||
|
res.obj().set(ghost_for_test, new u32, &ngc->global_ghost_type_table);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
var set_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
var res=args[0];
|
||||||
|
if (!res.objchk(ghost_for_test)) {
|
||||||
|
std::cout<<"set_new_ghost: not ghost for test type.\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
f64 num=args[1].num();
|
||||||
|
*((u32*)res.obj().ptr)=static_cast<u32>(num);
|
||||||
|
std::cout<<"set_new_ghost: successfully set ghost = "<<num<<"\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
var print_new_ghost(var* args, usize size, gc* ngc) {
|
||||||
|
var res=args[0];
|
||||||
|
if (!res.objchk(ghost_for_test)) {
|
||||||
|
std::cout<<"print_new_ghost: not ghost for test type.\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
std::cout<<"print_new_ghost: "<<res.obj()<<" result = "<<*((u32*)res.obj().ptr)<<"\n";
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_func_info func_tbl[]={
|
||||||
|
{"fib", fib},
|
||||||
|
{"quick_fib", quick_fib},
|
||||||
|
{"create_ghost", create_new_ghost},
|
||||||
|
{"set_ghost", set_new_ghost},
|
||||||
|
{"print_ghost", print_new_ghost},
|
||||||
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" mod_func* get() {
|
}
|
||||||
return func_tbl;
|
|
||||||
|
extern "C" module_func_info* get(ghost_register_table* table) {
|
||||||
|
if (table->exists("fib_for_test")) {
|
||||||
|
nasal_fib_module::ghost_for_test=table->get_ghost_type_index("fib_for_test");
|
||||||
|
return nasal_fib_module::func_tbl;
|
||||||
|
}
|
||||||
|
nasal_fib_module::ghost_for_test=table->register_ghost_type(
|
||||||
|
"fib_for_test",
|
||||||
|
nasal_fib_module::ghost_for_test_destructor
|
||||||
|
);
|
||||||
|
return nasal_fib_module::func_tbl;
|
||||||
}
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
#include "../nasal.h"
|
#include "../nasal.h"
|
||||||
#include <unistd.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#else
|
#else
|
||||||
|
@ -88,13 +92,13 @@ var nas_noblock(var* args, usize size, gc* ngc) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_func func_tbl[]={
|
module_func_info func_tbl[]={
|
||||||
{"nas_getch",nas_getch},
|
{"nas_getch",nas_getch},
|
||||||
{"nas_kbhit",nas_kbhit},
|
{"nas_kbhit",nas_kbhit},
|
||||||
{"nas_noblock",nas_noblock},
|
{"nas_noblock",nas_noblock},
|
||||||
{nullptr,nullptr}
|
{nullptr,nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" mod_func* get() {
|
extern "C" module_func_info* get(ghost_register_table* table) {
|
||||||
return func_tbl;
|
return func_tbl;
|
||||||
}
|
}
|
|
@ -2,9 +2,28 @@ var libfib=func(){
|
||||||
var dl=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
var dl=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so"));
|
||||||
var fib=dl.fib;
|
var fib=dl.fib;
|
||||||
var qfib=dl.quick_fib;
|
var qfib=dl.quick_fib;
|
||||||
|
var create_ghost=dl.create_ghost;
|
||||||
|
var set_ghost=dl.set_ghost;
|
||||||
|
var print_ghost=dl.print_ghost;
|
||||||
|
var zero_call=dylib.limitcall(0);
|
||||||
var call=dylib.limitcall(1);
|
var call=dylib.limitcall(1);
|
||||||
return {
|
var test_call=dylib.limitcall(2);
|
||||||
fib: func(x){return call(fib,x)},
|
var res={
|
||||||
qfib:func(x){return call(qfib,x)}
|
fib: func(x) {return call(fib,x)},
|
||||||
|
qfib: func(x) {return call(qfib,x)},
|
||||||
|
create_ghost: func() {return zero_call(create_ghost)},
|
||||||
|
set_ghost: func(object, x) {return test_call(set_ghost, object, x)},
|
||||||
|
print_ghost: func(object) {return call(print_ghost, object)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
res.test_ghost=func() {
|
||||||
|
var ghost=res.create_ghost();
|
||||||
|
res.print_ghost(nil); # err
|
||||||
|
res.print_ghost(ghost); # random
|
||||||
|
res.set_ghost(nil, 114); # err
|
||||||
|
res.set_ghost(ghost, 114); # success
|
||||||
|
res.print_ghost(ghost); # 114
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}();
|
}();
|
|
@ -266,7 +266,7 @@ var nas_vec3_dot(var* args, usize size, gc* ngc) {
|
||||||
return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num());
|
return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num());
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_func func_tbl[]={
|
module_func_info func_tbl[]={
|
||||||
{"nas_vec2",nas_vec2},
|
{"nas_vec2",nas_vec2},
|
||||||
{"nas_vec2_add",nas_vec2_add},
|
{"nas_vec2_add",nas_vec2_add},
|
||||||
{"nas_vec2_sub",nas_vec2_sub},
|
{"nas_vec2_sub",nas_vec2_sub},
|
||||||
|
@ -291,6 +291,6 @@ mod_func func_tbl[]={
|
||||||
{nullptr,nullptr}
|
{nullptr,nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" mod_func* get() {
|
extern "C" module_func_info* get(ghost_register_table* table) {
|
||||||
return func_tbl;
|
return func_tbl;
|
||||||
}
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
#include "../nasal.h"
|
#include "../nasal.h"
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
|
@ -190,7 +193,7 @@ var nas_errno(var* args, usize size, gc* ngc) {
|
||||||
return ngc->newstr(strerror(errno));
|
return ngc->newstr(strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_func func_tbl[]={
|
module_func_info func_tbl[]={
|
||||||
{"nas_socket",nas_socket},
|
{"nas_socket",nas_socket},
|
||||||
{"nas_closesocket",nas_closesocket},
|
{"nas_closesocket",nas_closesocket},
|
||||||
{"nas_shutdown",nas_shutdown},
|
{"nas_shutdown",nas_shutdown},
|
||||||
|
@ -206,6 +209,6 @@ mod_func func_tbl[]={
|
||||||
{nullptr,nullptr}
|
{nullptr,nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" mod_func* get() {
|
extern "C" module_func_info* get(ghost_register_table* table) {
|
||||||
return func_tbl;
|
return func_tbl;
|
||||||
}
|
}
|
|
@ -8,6 +8,9 @@
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#else
|
#else
|
||||||
#pragma warning (disable:4566) // i know i'm using utf-8, fuck you
|
#pragma warning (disable:4566) // i know i'm using utf-8, fuck you
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#pragma warning (disable:4267)
|
||||||
|
#pragma warning (disable:4996)
|
||||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
@ -544,13 +547,13 @@ var builtin_open(var* local, gc& ngc) {
|
||||||
return nas_err("open", "failed to open file <"+name.str()+">");
|
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(obj_type::file, res);
|
ret.obj().set(ngc.global_ghost_type_table.ghost_file, res, &ngc.global_ghost_type_table);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_close(var* local, gc& ngc) {
|
var builtin_close(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("close", "not a valid filehandle");
|
return nas_err("close", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
fd.obj().clear();
|
fd.obj().clear();
|
||||||
|
@ -561,7 +564,7 @@ var builtin_read(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
var buf=local[2];
|
var buf=local[2];
|
||||||
var len=local[3];
|
var len=local[3];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("read", "not a valid filehandle");
|
return nas_err("read", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
if (buf.type!=vm_str || buf.val.gcobj->unmut) {
|
if (buf.type!=vm_str || buf.val.gcobj->unmut) {
|
||||||
|
@ -587,7 +590,7 @@ var builtin_read(var* local, gc& ngc) {
|
||||||
var builtin_write(var* local, gc& ngc) {
|
var builtin_write(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
var str=local[2];
|
var str=local[2];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("write", "not a valid filehandle");
|
return nas_err("write", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
if (str.type!=vm_str) {
|
if (str.type!=vm_str) {
|
||||||
|
@ -600,7 +603,7 @@ var builtin_seek(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
var pos=local[2];
|
var pos=local[2];
|
||||||
var whence=local[3];
|
var whence=local[3];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("seek", "not a valid filehandle");
|
return nas_err("seek", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num((f64)fseek((FILE*)fd.obj().ptr, pos.num(), whence.num()));
|
return var::num((f64)fseek((FILE*)fd.obj().ptr, pos.num(), whence.num()));
|
||||||
|
@ -608,7 +611,7 @@ var builtin_seek(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_tell(var* local, gc& ngc) {
|
var builtin_tell(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("tell", "not a valid filehandle");
|
return nas_err("tell", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num((f64)ftell((FILE*)fd.obj().ptr));
|
return var::num((f64)ftell((FILE*)fd.obj().ptr));
|
||||||
|
@ -616,7 +619,7 @@ var builtin_tell(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_readln(var* local, gc& ngc) {
|
var builtin_readln(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("readln", "not a valid filehandle");
|
return nas_err("readln", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
var str=ngc.alloc(vm_str);
|
var str=ngc.alloc(vm_str);
|
||||||
|
@ -664,7 +667,7 @@ var builtin_stat(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_eof(var* local, gc& ngc) {
|
var builtin_eof(var* local, gc& ngc) {
|
||||||
var fd=local[1];
|
var fd=local[1];
|
||||||
if (!fd.objchk(obj_type::file)) {
|
if (!fd.objchk(ngc.global_ghost_type_table.ghost_file)) {
|
||||||
return nas_err("readln", "not a valid filehandle");
|
return nas_err("readln", "not a valid filehandle");
|
||||||
}
|
}
|
||||||
return var::num((f64)feof((FILE*)fd.obj().ptr));
|
return var::num((f64)feof((FILE*)fd.obj().ptr));
|
||||||
|
@ -849,13 +852,13 @@ var builtin_opendir(var* local, gc& ngc) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
var ret=ngc.alloc(vm_obj);
|
var ret=ngc.alloc(vm_obj);
|
||||||
ret.obj().set(obj_type::dir,p);
|
ret.obj().set(ngc.global_ghost_type_table.ghost_dir, p, &ngc.global_ghost_type_table);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_readdir(var* local, gc& ngc) {
|
var builtin_readdir(var* local, gc& ngc) {
|
||||||
var handle=local[1];
|
var handle=local[1];
|
||||||
if (!handle.objchk(obj_type::dir)) {
|
if (!handle.objchk(ngc.global_ghost_type_table.ghost_dir)) {
|
||||||
return nas_err("readdir", "not a valid dir handle");
|
return nas_err("readdir", "not a valid dir handle");
|
||||||
}
|
}
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -872,7 +875,7 @@ var builtin_readdir(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_closedir(var* local, gc& ngc) {
|
var builtin_closedir(var* local, gc& ngc) {
|
||||||
var handle=local[1];
|
var handle=local[1];
|
||||||
if (!handle.objchk(obj_type::dir)) {
|
if (!handle.objchk(ngc.global_ghost_type_table.ghost_dir)) {
|
||||||
return nas_err("closedir", "not a valid dir handle");
|
return nas_err("closedir", "not a valid dir handle");
|
||||||
}
|
}
|
||||||
handle.obj().clear();
|
handle.obj().clear();
|
||||||
|
@ -936,7 +939,7 @@ var builtin_dlopen(var* local, gc& ngc) {
|
||||||
}
|
}
|
||||||
var ret=ngc.temp=ngc.alloc(vm_hash);
|
var ret=ngc.temp=ngc.alloc(vm_hash);
|
||||||
var lib=ngc.alloc(vm_obj);
|
var lib=ngc.alloc(vm_obj);
|
||||||
lib.obj().set(obj_type::dylib, ptr);
|
lib.obj().set(ngc.global_ghost_type_table.ghost_dylib, ptr, &ngc.global_ghost_type_table);
|
||||||
ret.hash().elems["lib"]=lib;
|
ret.hash().elems["lib"]=lib;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -948,14 +951,14 @@ var builtin_dlopen(var* local, gc& ngc) {
|
||||||
return nas_err("dlopen", "cannot find <get> function");
|
return nas_err("dlopen", "cannot find <get> function");
|
||||||
}
|
}
|
||||||
// get function pointer by name
|
// get function pointer by name
|
||||||
mod_func* tbl=(mod_func*)((getptr)func)();
|
module_func_info* tbl=((get_func_ptr)func)(&ngc.global_ghost_type_table);
|
||||||
if (!tbl) {
|
if (!tbl) {
|
||||||
return nas_err("dlopen", "failed to get module functions");
|
return nas_err("dlopen", "failed to get module functions");
|
||||||
}
|
}
|
||||||
for(u32 i=0;tbl[i].name;++i) {
|
for(u32 i=0;tbl[i].name;++i) {
|
||||||
void* p=(void*)tbl[i].fd;
|
void* p=(void*)tbl[i].fd;
|
||||||
var tmp=ngc.alloc(vm_obj);
|
var tmp=ngc.alloc(vm_obj);
|
||||||
tmp.obj().set(obj_type::faddr, p);
|
tmp.obj().set(ngc.global_ghost_type_table.ghost_faddr, p, &ngc.global_ghost_type_table);
|
||||||
ret.hash().elems[tbl[i].name]=tmp;
|
ret.hash().elems[tbl[i].name]=tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,7 +968,7 @@ var builtin_dlopen(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_dlclose(var* local, gc& ngc) {
|
var builtin_dlclose(var* local, gc& ngc) {
|
||||||
var libptr=local[1];
|
var libptr=local[1];
|
||||||
if (!libptr.objchk(obj_type::dylib)) {
|
if (!libptr.objchk(ngc.global_ghost_type_table.ghost_dylib)) {
|
||||||
return nas_err("dlclose", "\"lib\" is not a valid dynamic lib");
|
return nas_err("dlclose", "\"lib\" is not a valid dynamic lib");
|
||||||
}
|
}
|
||||||
libptr.obj().clear();
|
libptr.obj().clear();
|
||||||
|
@ -975,23 +978,27 @@ var builtin_dlclose(var* local, gc& ngc) {
|
||||||
var builtin_dlcallv(var* local, gc& ngc) {
|
var builtin_dlcallv(var* local, gc& ngc) {
|
||||||
var fp=local[1];
|
var fp=local[1];
|
||||||
var args=local[2];
|
var args=local[2];
|
||||||
if (!fp.objchk(obj_type::faddr)) {
|
if (!fp.objchk(ngc.global_ghost_type_table.ghost_faddr)) {
|
||||||
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
||||||
}
|
}
|
||||||
auto& vec=args.vec().elems;
|
auto& vec=args.vec().elems;
|
||||||
return ((mod)fp.obj().ptr)(vec.data(), vec.size(), &ngc);
|
return ((module_func)fp.obj().ptr)(
|
||||||
|
vec.data(),
|
||||||
|
vec.size(),
|
||||||
|
&ngc
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_dlcall(var* local, gc& ngc) {
|
var builtin_dlcall(var* local, gc& ngc) {
|
||||||
var fp=local[1];
|
var fp=local[1];
|
||||||
if (!fp.objchk(obj_type::faddr)) {
|
if (!fp.objchk(ngc.global_ghost_type_table.ghost_faddr)) {
|
||||||
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
|
||||||
}
|
}
|
||||||
|
|
||||||
var* local_frame_start=local+2;
|
var* local_frame_start=local+2;
|
||||||
usize local_frame_size=ngc.rctx->top-local_frame_start;
|
usize local_frame_size=ngc.rctx->top-local_frame_start;
|
||||||
// arguments' stored place begins at local +2
|
// arguments' stored place begins at local +2
|
||||||
return ((mod)fp.obj().ptr)(
|
return ((module_func)fp.obj().ptr)(
|
||||||
local_frame_start,
|
local_frame_start,
|
||||||
local_frame_size,
|
local_frame_size,
|
||||||
&ngc
|
&ngc
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#pragma warning (disable:4267)
|
||||||
|
#endif
|
||||||
|
|
||||||
class codegen {
|
class codegen {
|
||||||
private:
|
private:
|
||||||
u16 fileindex;
|
u16 fileindex;
|
||||||
|
|
257
nasal_gc.h
257
nasal_gc.h
|
@ -1,4 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#pragma warning (disable:4267)
|
||||||
|
#pragma warning (disable:4102)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -43,14 +48,6 @@ enum vm_type:u8 {
|
||||||
|
|
||||||
const u32 gc_type_size=vm_co-vm_str+1;
|
const u32 gc_type_size=vm_co-vm_str+1;
|
||||||
|
|
||||||
enum class obj_type:u32 {
|
|
||||||
null=0,
|
|
||||||
file=1,
|
|
||||||
dir,
|
|
||||||
dylib,
|
|
||||||
faddr
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class coroutine_status:u32 {
|
enum class coroutine_status:u32 {
|
||||||
suspended,
|
suspended,
|
||||||
running,
|
running,
|
||||||
|
@ -63,13 +60,13 @@ enum class gc_status:u8 {
|
||||||
found
|
found
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_vec; // vector
|
struct nas_vec; // vector
|
||||||
struct nas_hash; // hashmap(dict)
|
struct nas_hash; // hashmap(dict)
|
||||||
struct nas_func; // function(lambda)
|
struct nas_func; // function(lambda)
|
||||||
struct nas_upval;// upvalue
|
struct nas_upval; // upvalue
|
||||||
struct nas_obj; // special objects
|
struct nas_obj; // special objects
|
||||||
struct nas_co; // coroutine
|
struct nas_co; // coroutine
|
||||||
struct nas_val; // nas_val includes gc-managed types
|
struct nas_val; // nas_val includes gc-managed types
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
public:
|
public:
|
||||||
|
@ -99,7 +96,7 @@ public:
|
||||||
// number and string can be translated to each other
|
// number and string can be translated to each other
|
||||||
f64 tonum();
|
f64 tonum();
|
||||||
string tostr();
|
string tostr();
|
||||||
bool objchk(obj_type);
|
bool objchk(usize);
|
||||||
|
|
||||||
// create new var object
|
// create new var object
|
||||||
static var none();
|
static var none();
|
||||||
|
@ -162,6 +159,7 @@ struct nas_func {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_upval {
|
struct nas_upval {
|
||||||
|
public:
|
||||||
/* on stack, use these variables */
|
/* on stack, use these variables */
|
||||||
bool onstk;
|
bool onstk;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
@ -170,55 +168,119 @@ struct nas_upval {
|
||||||
/* not on stack, use this */
|
/* not on stack, use this */
|
||||||
std::vector<var> elems;
|
std::vector<var> elems;
|
||||||
|
|
||||||
nas_upval() {onstk=true;stk=nullptr;size=0;}
|
|
||||||
var& operator[](usize n) {return onstk? stk[n]:elems[n];}
|
|
||||||
void clear() {onstk=true;elems.clear();size=0;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ghost_info {
|
|
||||||
string name;
|
|
||||||
void (*destructor)(void*);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nas_ghost {
|
|
||||||
private:
|
|
||||||
static std::vector<ghost_info> ghost_register_table;
|
|
||||||
usize type;
|
|
||||||
void* ptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_ghost(): type(0), ptr(nullptr) {}
|
nas_upval(): onstk(true), size(0), stk(nullptr) {}
|
||||||
~nas_ghost() {
|
|
||||||
if (!ptr) { return; }
|
var& operator[](usize n) {
|
||||||
ghost_register_table[type].destructor(ptr);
|
return onstk? stk[n]:elems[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
static usize regist_ghost_type(ghost_info i) {
|
void clear() {
|
||||||
auto res=ghost_register_table.size();
|
onstk=true;
|
||||||
ghost_register_table.push_back(i);
|
elems.clear();
|
||||||
|
size=0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void filehandle_destructor(void* ptr) {
|
||||||
|
if ((FILE*)ptr==stdin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose((FILE*)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dir_entry_destructor(void* ptr) {
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
closedir((DIR*)ptr);
|
||||||
|
#else
|
||||||
|
FindClose(ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void dylib_destructor(void* ptr) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
FreeLibrary((HMODULE)ptr);
|
||||||
|
#else
|
||||||
|
dlclose(ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void func_addr_destructor(void* ptr) {}
|
||||||
|
|
||||||
|
struct ghost_register_table {
|
||||||
|
private:
|
||||||
|
using dtor=void (*)(void*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<string,usize> mapper;
|
||||||
|
std::vector<string> ghost_name;
|
||||||
|
std::vector<dtor> destructors;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// reserved ghost type only for native functions
|
||||||
|
usize ghost_file;
|
||||||
|
usize ghost_dir;
|
||||||
|
usize ghost_dylib;
|
||||||
|
usize ghost_faddr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ghost_register_table() {
|
||||||
|
ghost_file=register_ghost_type("file", filehandle_destructor);
|
||||||
|
ghost_dir=register_ghost_type("dir", dir_entry_destructor);
|
||||||
|
ghost_dylib=register_ghost_type("dylib", dylib_destructor);
|
||||||
|
ghost_faddr=register_ghost_type("faddr", func_addr_destructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists(const string& name) const {
|
||||||
|
return mapper.count(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize get_ghost_type_index(const string& name) const {
|
||||||
|
return mapper.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& get_ghost_name(usize index) const {
|
||||||
|
return ghost_name.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
usize register_ghost_type(const std::string& name, dtor ptr) {
|
||||||
|
if (mapper.count(name)) {
|
||||||
|
std::cerr<<"nasal_gc.h: ghost_register_table::register_ghost_type: ";
|
||||||
|
std::cerr<<"ghost type \""<<name<<"\" already exists.\n";
|
||||||
|
std::exit(-1);
|
||||||
|
}
|
||||||
|
auto res=destructors.size();
|
||||||
|
mapper[name]=res;
|
||||||
|
ghost_name.push_back(name);
|
||||||
|
destructors.push_back(ptr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& name() {
|
dtor destructor(usize index) {
|
||||||
return ghost_register_table[type].name;
|
return destructors.at(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_obj {
|
struct nas_obj {
|
||||||
obj_type type;
|
public:
|
||||||
|
usize type;
|
||||||
void* ptr;
|
void* ptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* RAII constructor, new object is initialized when creating */
|
ghost_register_table* ghost_type_table;
|
||||||
void file_dtor();
|
|
||||||
void dir_dtor();
|
|
||||||
void dylib_dtor();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_obj(): type(obj_type::null), ptr(nullptr) {}
|
nas_obj(): type(0), ptr(nullptr), ghost_type_table(nullptr) {}
|
||||||
~nas_obj() {clear();}
|
~nas_obj() {clear();}
|
||||||
void set(obj_type, void*);
|
void set(usize, void*, ghost_register_table*);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend std::ostream& operator<<(std::ostream& out, nas_obj& ghost) {
|
||||||
|
out<<"<object "<<ghost.ghost_type_table->get_ghost_name(ghost.type);
|
||||||
|
out<<" at 0x"<<std::hex<<(u64)ghost.ptr<<std::dec<<">";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
|
@ -357,47 +419,20 @@ void nas_func::clear() {
|
||||||
keys.clear();
|
keys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_obj::set(obj_type t, void* p) {
|
void nas_obj::set(usize t, void* p, ghost_register_table* table) {
|
||||||
type=t;
|
type=t;
|
||||||
ptr=p;
|
ptr=p;
|
||||||
|
ghost_type_table=table;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_obj::clear() {
|
void nas_obj::clear() {
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(type) {
|
ghost_type_table->destructor(type)(ptr);
|
||||||
case obj_type::file: file_dtor(); break;
|
|
||||||
case obj_type::dir: dir_dtor(); break;
|
|
||||||
case obj_type::dylib: dylib_dtor();break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
ptr=nullptr;
|
ptr=nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_obj::file_dtor() {
|
|
||||||
if ((FILE*)ptr==stdin) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fclose((FILE*)ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nas_obj::dir_dtor() {
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
closedir((DIR*)ptr);
|
|
||||||
#else
|
|
||||||
FindClose(ptr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void nas_obj::dylib_dtor() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
FreeLibrary((HMODULE)ptr);
|
|
||||||
#else
|
|
||||||
dlclose(ptr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void nas_co::clear() {
|
void nas_co::clear() {
|
||||||
for(u32 i=0;i<STACK_DEPTH;++i) {
|
for(u32 i=0;i<STACK_DEPTH;++i) {
|
||||||
stack[i]=var::nil();
|
stack[i]=var::nil();
|
||||||
|
@ -479,14 +514,14 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
|
||||||
case vm_vec: out<<ref.vec(); break;
|
case vm_vec: out<<ref.vec(); break;
|
||||||
case vm_hash: out<<ref.hash(); break;
|
case vm_hash: out<<ref.hash(); break;
|
||||||
case vm_func: out<<"func(..) {..}";break;
|
case vm_func: out<<"func(..) {..}";break;
|
||||||
case vm_obj: out<<"<object>"; break;
|
case vm_obj: out<<ref.obj(); break;
|
||||||
case vm_co: out<<"<coroutine>"; break;
|
case vm_co: out<<"<coroutine>"; break;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool var::objchk(obj_type objtype) {
|
bool var::objchk(usize obj_type) {
|
||||||
return type==vm_obj && obj().type==objtype && obj().ptr;
|
return type==vm_obj && obj().type==obj_type && obj().ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
var var::none() {
|
var var::none() {
|
||||||
|
@ -534,6 +569,7 @@ const var one =var::num(1);
|
||||||
const var nil =var::nil();
|
const var nil =var::nil();
|
||||||
|
|
||||||
struct gc {
|
struct gc {
|
||||||
|
ghost_register_table global_ghost_type_table;
|
||||||
/* main context temporary storage */
|
/* main context temporary storage */
|
||||||
context mctx;
|
context mctx;
|
||||||
|
|
||||||
|
@ -587,11 +623,27 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
void info();
|
void info();
|
||||||
var alloc(const u8);
|
var alloc(const u8);
|
||||||
var newstr(char);
|
|
||||||
var newstr(const char*);
|
|
||||||
var newstr(const string&);
|
|
||||||
void ctxchg(nas_co&);
|
void ctxchg(nas_co&);
|
||||||
void ctxreserve();
|
void ctxreserve();
|
||||||
|
|
||||||
|
public:
|
||||||
|
var newstr(char c) {
|
||||||
|
var s=alloc(vm_str);
|
||||||
|
s.str()=c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newstr(const char* buff) {
|
||||||
|
var s=alloc(vm_str);
|
||||||
|
s.str()=buff;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newstr(const string& buff) {
|
||||||
|
var s=alloc(vm_str);
|
||||||
|
s.str()=buff;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void gc::mark() {
|
void gc::mark() {
|
||||||
|
@ -691,14 +743,15 @@ void gc::sweep() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::extend(u8 type) {
|
void gc::extend(u8 type) {
|
||||||
u8 index=type-vm_str;
|
const u8 index=type-vm_str;
|
||||||
size[index]+=incr[index];
|
size[index]+=incr[index];
|
||||||
|
|
||||||
for(u32 i=0;i<incr[index];++i) {
|
for(u32 i=0;i<incr[index];++i) {
|
||||||
nas_val* tmp=new nas_val(type);
|
nas_val* tmp=new nas_val(type);
|
||||||
|
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
std::cerr<<"failed to allocate new memory\n";
|
std::cerr<<"nasal_gc.h: gc::extend: ";
|
||||||
|
std::cerr<<"failed to allocate memory\n";
|
||||||
std::exit(-1);
|
std::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,7 +773,7 @@ void gc::init(const std::vector<string>& s, const std::vector<string>& argv) {
|
||||||
size[i]=gcnt[i]=acnt[i]=0;
|
size[i]=gcnt[i]=acnt[i]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// coroutine pointer set to nullpre
|
// coroutine pointer set to nullptr
|
||||||
cort=nullptr;
|
cort=nullptr;
|
||||||
|
|
||||||
// init constant strings
|
// init constant strings
|
||||||
|
@ -820,24 +873,6 @@ var gc::alloc(u8 type) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gc::newstr(char c) {
|
|
||||||
var s=alloc(vm_str);
|
|
||||||
s.str()=c;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
var gc::newstr(const char* buff) {
|
|
||||||
var s=alloc(vm_str);
|
|
||||||
s.str()=buff;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
var gc::newstr(const string& buff) {
|
|
||||||
var s=alloc(vm_str);
|
|
||||||
s.str()=buff;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gc::ctxchg(nas_co& co) {
|
void gc::ctxchg(nas_co& co) {
|
||||||
// store running state to main context
|
// store running state to main context
|
||||||
mctx=*rctx;
|
mctx=*rctx;
|
||||||
|
@ -869,19 +904,19 @@ void gc::ctxreserve() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// use to print error log and return error value
|
// use to print error log and return error value
|
||||||
var nas_err(const string& err_f, const string& info) {
|
var nas_err(const string& error_function_name, const string& info) {
|
||||||
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
|
std::cerr<<"[vm] "<<error_function_name<<": "<<info<<"\n";
|
||||||
return var::none();
|
return var::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
// module function type
|
// module function type
|
||||||
typedef var (*mod)(var*, usize, gc*);
|
typedef var (*module_func)(var*, usize, gc*);
|
||||||
|
|
||||||
// module function stores in tables with this type, end with {nullptr,nullptr}
|
// module function stores in tables with this type, end with {nullptr,nullptr}
|
||||||
struct mod_func {
|
struct module_func_info {
|
||||||
const char* name;
|
const char* name;
|
||||||
mod fd;
|
module_func fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
// module function "get" type
|
// module function "get" type
|
||||||
typedef mod_func* (*getptr)();
|
typedef module_func_info* (*get_func_ptr)(ghost_register_table*);
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#pragma warning (disable:4267)
|
||||||
|
#pragma warning (disable:4102)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable:4244)
|
||||||
|
#pragma warning (disable:4267)
|
||||||
|
#pragma warning (disable:4102)
|
||||||
|
#endif
|
||||||
|
|
||||||
class vm {
|
class vm {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ var new_map=func(width,height){
|
||||||
}
|
}
|
||||||
|
|
||||||
var prt=func(map){
|
var prt=func(map){
|
||||||
var s='\e[1;1H';
|
var s='\ec\e[1;1H';
|
||||||
foreach(var line;map){
|
foreach(var line;map){
|
||||||
foreach(var elem;line)
|
foreach(var elem;line)
|
||||||
s~=elem~' ';
|
s~=elem~' ';
|
||||||
|
|
Loading…
Reference in New Issue