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:
Li Haokun 2023-05-11 20:59:49 +08:00 committed by GitHub
commit 36f6dd6c96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 959 additions and 788 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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)
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}) 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})
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()

View File

@ -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`,编译。

View File

@ -1,44 +1,99 @@
#include <iostream> // module for test
#include "../nasal.h"
#include <iostream>
double fibonaci(double x) { #include "../nasal.h"
if (x<=2) {
return x; namespace nasal_fib_module {
}
return fibonaci(x-1)+fibonaci(x-2); double fibonaci(double x) {
} if (x<=2) {
return x;
var fib(var* args, usize size, gc* ngc) { }
if (!size) { return fibonaci(x-1)+fibonaci(x-2);
return nas_err("fib","lack arguments"); }
}
var num=args[0]; var fib(var* args, usize size, gc* ngc) {
return var::num(fibonaci(num.tonum())); if (!size) {
} return nas_err("fib","lack arguments");
}
var quick_fib(var* args, usize size, gc* ngc) { var num=args[0];
if (!size) { return var::num(fibonaci(num.tonum()));
return nas_err("quick_fib","lack arguments"); }
}
double num=args[0].tonum(); var quick_fib(var* args, usize size, gc* ngc) {
if (num<2) { if (!size) {
return var::num(num); return nas_err("quick_fib","lack arguments");
} }
double a=1,b=1,res=0; double num=args[0].tonum();
for(double i=1;i<num;i+=1) { if (num<2) {
res=a+b; return var::num(num);
a=b; }
b=res; double a=1,b=1,res=0;
} for(double i=1;i<num;i+=1) {
return var::num(res); res=a+b;
} a=b;
b=res;
mod_func func_tbl[]={ }
{"fib",fib}, return var::num(res);
{"quick_fib",quick_fib}, }
{nullptr, nullptr},
}; u32 ghost_for_test;
extern "C" mod_func* get() { void ghost_for_test_destructor(void* ptr) {
return func_tbl; 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" 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;
} }

View File

@ -1,100 +1,104 @@
#include "../nasal.h" #include "../nasal.h"
#include <unistd.h> #include <iostream>
#include <iostream>
#ifdef _WIN32 #ifndef _MSC_VER
#include <conio.h> #include <unistd.h>
#else #endif
#include <fcntl.h>
#include <termios.h> #ifdef _WIN32
#endif #include <conio.h>
#else
class noecho_input { #include <fcntl.h>
private: #include <termios.h>
#ifndef _WIN32 #endif
struct termios init_termios;
struct termios new_termios; class noecho_input {
int peek_char=-1; private:
#endif #ifndef _WIN32
public: struct termios init_termios;
noecho_input() { struct termios new_termios;
#ifndef _WIN32 int peek_char=-1;
tcflush(0, TCIOFLUSH); #endif
tcgetattr(0, &init_termios); public:
new_termios=init_termios; noecho_input() {
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE); #ifndef _WIN32
// vmin=0 is nonblock input, but in wsl there is a bug that will block input tcflush(0, TCIOFLUSH);
// so we use fcntl to write the nonblock input tcgetattr(0, &init_termios);
new_termios.c_cc[VMIN]=1; new_termios=init_termios;
new_termios.c_cc[VTIME]=0; new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
tcsetattr(0, TCSANOW, &new_termios); // vmin=0 is nonblock input, but in wsl there is a bug that will block input
#endif // so we use fcntl to write the nonblock input
} new_termios.c_cc[VMIN]=1;
~noecho_input() { new_termios.c_cc[VTIME]=0;
#ifndef _WIN32 tcsetattr(0, TCSANOW, &new_termios);
tcflush(0, TCIOFLUSH); #endif
tcsetattr(0, TCSANOW, &init_termios); }
#endif ~noecho_input() {
} #ifndef _WIN32
int noecho_kbhit() { tcflush(0, TCIOFLUSH);
#ifndef _WIN32 tcsetattr(0, TCSANOW, &init_termios);
unsigned char ch=0; #endif
int nread=0; }
if (peek_char!=-1) { int noecho_kbhit() {
return 1; #ifndef _WIN32
} unsigned char ch=0;
int flag=fcntl(0, F_GETFL); int nread=0;
fcntl(0, F_SETFL,flag|O_NONBLOCK); if (peek_char!=-1) {
nread=read(0, &ch, 1); return 1;
fcntl(0, F_SETFL, flag); }
if (nread==1) { int flag=fcntl(0, F_GETFL);
peek_char=ch; fcntl(0, F_SETFL,flag|O_NONBLOCK);
return 1; nread=read(0, &ch, 1);
} fcntl(0, F_SETFL, flag);
return 0; if (nread==1) {
#else peek_char=ch;
return kbhit(); return 1;
#endif }
} return 0;
int noecho_getch() { #else
#ifndef _WIN32 return kbhit();
int ch=0; #endif
if (peek_char!=-1) { }
ch=peek_char; int noecho_getch() {
peek_char=-1; #ifndef _WIN32
return ch; int ch=0;
} if (peek_char!=-1) {
ssize_t tmp=read(0, &ch, 1); ch=peek_char;
return ch; peek_char=-1;
#else return ch;
return getch(); }
#endif ssize_t tmp=read(0, &ch, 1);
} return ch;
}; #else
return getch();
noecho_input this_window; #endif
}
var nas_getch(var* args, usize size, gc* ngc) { };
return var::num((double)this_window.noecho_getch());
} noecho_input this_window;
var nas_kbhit(var* args, usize size, gc* ngc) { var nas_getch(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_kbhit()); return var::num((double)this_window.noecho_getch());
} }
var nas_noblock(var* args, usize size, gc* ngc) { var nas_kbhit(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) { return var::num((double)this_window.noecho_kbhit());
return var::num((double)this_window.noecho_getch()); }
}
return nil; var nas_noblock(var* args, usize size, gc* ngc) {
} if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch());
mod_func func_tbl[]={ }
{"nas_getch",nas_getch}, return nil;
{"nas_kbhit",nas_kbhit}, }
{"nas_noblock",nas_noblock},
{nullptr,nullptr} module_func_info func_tbl[]={
}; {"nas_getch",nas_getch},
{"nas_kbhit",nas_kbhit},
extern "C" mod_func* get() { {"nas_noblock",nas_noblock},
return func_tbl; {nullptr,nullptr}
};
extern "C" module_func_info* get(ghost_register_table* table) {
return func_tbl;
} }

View File

@ -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;
}(); }();

View File

@ -1,296 +1,296 @@
#include "../nasal.h" #include "../nasal.h"
#include <cmath> #include <cmath>
var nas_vec2(var* args, usize size, gc* ngc) { var nas_vec2(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]); res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]); res.vec().elems.push_back(args[1]);
return res; return res;
} }
var nas_vec3(var* args, usize size, gc* ngc) { var nas_vec3(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]); res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]); res.vec().elems.push_back(args[1]);
res.vec().elems.push_back(args[2]); res.vec().elems.push_back(args[2]);
return res; return res;
} }
var nas_vec2_add(var* args, usize size, gc* ngc) { var nas_vec2_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num()));
return res; return res;
} }
var nas_vec2_sub(var* args, usize size, gc* ngc) { var nas_vec2_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num()));
return res; return res;
} }
var nas_vec2_mult(var* args, usize size, gc* ngc) { var nas_vec2_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num()));
return res; return res;
} }
var nas_vec2_div(var* args, usize size, gc* ngc) { var nas_vec2_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num()));
return res; return res;
} }
var nas_vec2_neg(var* args, usize size, gc* ngc) { var nas_vec2_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=2) if (v0.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(-v0[0].num())); res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back(var::num(-v0[1].num())); res.vec().elems.push_back(var::num(-v0[1].num()));
return res; return res;
} }
var nas_vec2_norm(var* args, usize size, gc* ngc) { var nas_vec2_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=2) if (v0.size()!=2)
return nil; return nil;
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].num(); auto y=v0[1].num();
auto t=std::sqrt(x*x+y*y); auto t=std::sqrt(x*x+y*y);
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(x/t)); res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back(var::num(y/t)); res.vec().elems.push_back(var::num(y/t));
return res; return res;
} }
var nas_vec2_len(var* args, usize size, gc* ngc) { var nas_vec2_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=2) if (v0.size()!=2)
return nil; return nil;
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].num(); auto y=v0[1].num();
return var::num(std::sqrt(x*x+y*y)); return var::num(std::sqrt(x*x+y*y));
} }
var nas_vec2_dot(var* args, usize size, gc* ngc) { var nas_vec2_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()); return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num());
} }
var nas_vec3_add(var* args, usize size, gc* ngc) { var nas_vec3_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()+v1[2].num())); res.vec().elems.push_back(var::num(v0[2].num()+v1[2].num()));
return res; return res;
} }
var nas_vec3_sub(var* args, usize size, gc* ngc) { var nas_vec3_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()-v1[2].num())); res.vec().elems.push_back(var::num(v0[2].num()-v1[2].num()));
return res; return res;
} }
var nas_vec3_mult(var* args, usize size, gc* ngc) { var nas_vec3_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()*v1[2].num())); res.vec().elems.push_back(var::num(v0[2].num()*v1[2].num()));
return res; return res;
} }
var nas_vec3_div(var* args, usize size, gc* ngc) { var nas_vec3_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num())); res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num()));
res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num())); res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()/v1[2].num())); res.vec().elems.push_back(var::num(v0[2].num()/v1[2].num()));
return res; return res;
} }
var nas_vec3_neg(var* args, usize size, gc* ngc) { var nas_vec3_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(-v0[0].num())); res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back(var::num(-v0[1].num())); res.vec().elems.push_back(var::num(-v0[1].num()));
res.vec().elems.push_back(var::num(-v0[2].num())); res.vec().elems.push_back(var::num(-v0[2].num()));
return res; return res;
} }
var nas_vec3_norm(var* args, usize size, gc* ngc) { var nas_vec3_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].num(); auto y=v0[1].num();
auto z=v0[2].num(); auto z=v0[2].num();
auto t=std::sqrt(x*x+y*y+z*z); auto t=std::sqrt(x*x+y*y+z*z);
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(x/t)); res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back(var::num(y/t)); res.vec().elems.push_back(var::num(y/t));
res.vec().elems.push_back(var::num(z/t)); res.vec().elems.push_back(var::num(z/t));
return res; return res;
} }
var nas_vec3_len(var* args, usize size, gc* ngc) { var nas_vec3_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].num(); auto y=v0[1].num();
auto z=v0[2].num(); auto z=v0[2].num();
return var::num(std::sqrt(x*x+y*y+z*z)); return var::num(std::sqrt(x*x+y*y+z*z));
} }
var nas_rotate_x(var* args, usize size, gc* ngc) { var nas_rotate_x(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num())); res.vec().elems.push_back(var::num(v0[0].num()));
res.vec().elems.push_back(var::num(v0[2].num()*std::sin(angle)+v0[1].num()*std::cos(angle))); res.vec().elems.push_back(var::num(v0[2].num()*std::sin(angle)+v0[1].num()*std::cos(angle)));
res.vec().elems.push_back(var::num(v0[2].num()*std::cos(angle)-v0[1].num()*std::sin(angle))); res.vec().elems.push_back(var::num(v0[2].num()*std::cos(angle)-v0[1].num()*std::sin(angle)));
return res; return res;
} }
var nas_rotate_y(var* args, usize size, gc* ngc) { var nas_rotate_y(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[2].num()*std::sin(angle))); res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[2].num()*std::sin(angle)));
res.vec().elems.push_back(var::num(v0[1].num())); res.vec().elems.push_back(var::num(v0[1].num()));
res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle))); res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle)));
return res; return res;
} }
var nas_rotate_z(var* args, usize size, gc* ngc) { var nas_rotate_z(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[1].num()*std::sin(angle))); res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[1].num()*std::sin(angle)));
res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[1].num()*std::cos(angle))); res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[1].num()*std::cos(angle)));
res.vec().elems.push_back(var::num(v0[2].num())); res.vec().elems.push_back(var::num(v0[2].num()));
return res; return res;
} }
var nas_vec3_dot(var* args, usize size, gc* ngc) { var nas_vec3_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
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},
{"nas_vec2_mult",nas_vec2_mult}, {"nas_vec2_mult",nas_vec2_mult},
{"nas_vec2_div",nas_vec2_div}, {"nas_vec2_div",nas_vec2_div},
{"nas_vec2_neg",nas_vec2_neg}, {"nas_vec2_neg",nas_vec2_neg},
{"nas_vec2_norm",nas_vec2_norm}, {"nas_vec2_norm",nas_vec2_norm},
{"nas_vec2_len",nas_vec2_len}, {"nas_vec2_len",nas_vec2_len},
{"nas_vec2_dot",nas_vec2_dot}, {"nas_vec2_dot",nas_vec2_dot},
{"nas_vec3",nas_vec3}, {"nas_vec3",nas_vec3},
{"nas_vec3_add",nas_vec3_add}, {"nas_vec3_add",nas_vec3_add},
{"nas_vec3_sub",nas_vec3_sub}, {"nas_vec3_sub",nas_vec3_sub},
{"nas_vec3_mult",nas_vec3_mult}, {"nas_vec3_mult",nas_vec3_mult},
{"nas_vec3_div",nas_vec3_div}, {"nas_vec3_div",nas_vec3_div},
{"nas_vec3_neg",nas_vec3_neg}, {"nas_vec3_neg",nas_vec3_neg},
{"nas_vec3_norm",nas_vec3_norm}, {"nas_vec3_norm",nas_vec3_norm},
{"nas_vec3_len",nas_vec3_len}, {"nas_vec3_len",nas_vec3_len},
{"nas_rotate_x",nas_rotate_x}, {"nas_rotate_x",nas_rotate_x},
{"nas_rotate_y",nas_rotate_y}, {"nas_rotate_y",nas_rotate_y},
{"nas_rotate_z",nas_rotate_z}, {"nas_rotate_z",nas_rotate_z},
{"nas_vec3_dot",nas_vec3_dot}, {"nas_vec3_dot",nas_vec3_dot},
{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;
} }

View File

@ -1,211 +1,214 @@
#include "../nasal.h" #include "../nasal.h"
#include <unistd.h>
#ifndef _MSC_VER
#ifdef _WIN32 #include <unistd.h>
#include <winsock.h> #endif
#pragma comment(lib,"ws2_32")
#ifdef _WIN32
class WSAmanager{ #include <winsock.h>
private: #pragma comment(lib,"ws2_32")
WSAData data;
public: class WSAmanager{
WSAmanager() { private:
WSAStartup(0x1010, &data); WSAData data;
} public:
~WSAmanager() { WSAmanager() {
WSACleanup(); WSAStartup(0x1010, &data);
} }
}; ~WSAmanager() {
WSACleanup();
static WSAmanager win; }
#else };
#include <netdb.h>
#include <sys/socket.h> static WSAmanager win;
#include <arpa/inet.h> #else
#include <netinet/in.h> #include <netdb.h>
#endif #include <sys/socket.h>
#include <arpa/inet.h>
var nas_socket(var* args, usize size, gc* ngc) { #include <netinet/in.h>
if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num) #endif
return nas_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num()); var nas_socket(var* args, usize size, gc* ngc) {
return var::num((double)sd); if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
} return nas_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num());
var nas_closesocket(var* args, usize size, gc* ngc) { return var::num((double)sd);
if (args[0].type!=vm_num) }
return nas_err("closesocket","\"sd\" should be number");
#ifdef _WIN32 var nas_closesocket(var* args, usize size, gc* ngc) {
return var::num((double)closesocket(args[0].num())); if (args[0].type!=vm_num)
#else return nas_err("closesocket","\"sd\" should be number");
return var::num((double)close(args[0].num())); #ifdef _WIN32
#endif return var::num((double)closesocket(args[0].num()));
} #else
return var::num((double)close(args[0].num()));
var nas_shutdown(var* args, usize size, gc* ngc) { #endif
if (args[0].type!=vm_num) }
return nas_err("shutdown","\"sd\" must be a number");
if (args[1].type!=vm_num) var nas_shutdown(var* args, usize size, gc* ngc) {
return nas_err("shutdown","\"how\" must be a number"); if (args[0].type!=vm_num)
return var::num((double)shutdown(args[0].num(),args[1].num())); return nas_err("shutdown","\"sd\" must be a number");
} if (args[1].type!=vm_num)
return nas_err("shutdown","\"how\" must be a number");
var nas_bind(var* args, usize size, gc* ngc) { return var::num((double)shutdown(args[0].num(),args[1].num()));
if (args[0].type!=vm_num) }
return nas_err("bind","\"sd\" muse be a number");
if (args[1].type!=vm_str) var nas_bind(var* args, usize size, gc* ngc) {
return nas_err("bind","\"ip\" should be a string including an ip with correct format"); if (args[0].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("bind","\"sd\" muse be a number");
return nas_err("bind","\"port\" must be a number"); if (args[1].type!=vm_str)
sockaddr_in server; return nas_err("bind","\"ip\" should be a string including an ip with correct format");
memset(&server,0,sizeof(sockaddr_in)); if (args[2].type!=vm_num)
server.sin_family=AF_INET; return nas_err("bind","\"port\" must be a number");
server.sin_addr.s_addr=inet_addr(args[1].str().c_str()); sockaddr_in server;
server.sin_port=htons(args[2].num()); memset(&server,0,sizeof(sockaddr_in));
return var::num((double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))); server.sin_family=AF_INET;
} server.sin_addr.s_addr=inet_addr(args[1].str().c_str());
server.sin_port=htons(args[2].num());
var nas_listen(var* args, usize size, gc* ngc) { return var::num((double)bind(args[0].num(),(sockaddr*)&server,sizeof(server)));
if (args[0].type!=vm_num) }
return nas_err("listen","\"sd\" must be a number");
if (args[1].type!=vm_num) var nas_listen(var* args, usize size, gc* ngc) {
return nas_err("listen","\"backlog\" must be a number"); if (args[0].type!=vm_num)
return var::num((double)listen(args[0].num(),args[1].num())); return nas_err("listen","\"sd\" must be a number");
} if (args[1].type!=vm_num)
return nas_err("listen","\"backlog\" must be a number");
var nas_connect(var* args, usize size, gc* ngc) { return var::num((double)listen(args[0].num(),args[1].num()));
if (args[0].type!=vm_num) }
return nas_err("connect","\"sd\" must be a number");
if (args[1].type!=vm_str) var nas_connect(var* args, usize size, gc* ngc) {
return nas_err("connect","\"hostname\" must be a string"); if (args[0].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("connect","\"sd\" must be a number");
return nas_err("connect","\"port\" must be a number"); if (args[1].type!=vm_str)
sockaddr_in addr; return nas_err("connect","\"hostname\" must be a string");
memset(&addr,0,sizeof(sockaddr_in)); if (args[2].type!=vm_num)
addr.sin_family=AF_INET; return nas_err("connect","\"port\" must be a number");
addr.sin_port=htons(args[2].num()); sockaddr_in addr;
hostent* entry=gethostbyname(args[1].str().c_str()); memset(&addr,0,sizeof(sockaddr_in));
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); addr.sin_family=AF_INET;
return var::num((double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); addr.sin_port=htons(args[2].num());
} hostent* entry=gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length);
var nas_accept(var* args, usize size, gc* ngc) { return var::num((double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in)));
if (args[0].type!=vm_num) }
return nas_err("accept","\"sd\" must be a number");
sockaddr_in client; var nas_accept(var* args, usize size, gc* ngc) {
int socklen=sizeof(sockaddr_in); if (args[0].type!=vm_num)
#ifdef _WIN32 return nas_err("accept","\"sd\" must be a number");
int client_sd=accept(args[0].num(),(sockaddr*)&client,&socklen); sockaddr_in client;
#else int socklen=sizeof(sockaddr_in);
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); #ifdef _WIN32
#endif int client_sd=accept(args[0].num(),(sockaddr*)&client,&socklen);
var res=ngc->temp=ngc->alloc(vm_hash); #else
auto& hash=res.hash().elems; int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen);
hash["sd"]=var::num((double)client_sd); #endif
hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr)); var res=ngc->temp=ngc->alloc(vm_hash);
ngc->temp=nil; auto& hash=res.hash().elems;
return res; hash["sd"]=var::num((double)client_sd);
} hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr));
ngc->temp=nil;
var nas_send(var* args, usize size, gc* ngc) { return res;
if (args[0].type!=vm_num) }
return nas_err("send","\"sd\" must be a number");
if (args[1].type!=vm_str) var nas_send(var* args, usize size, gc* ngc) {
return nas_err("send","\"buff\" must be a string"); if (args[0].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("send","\"sd\" must be a number");
return nas_err("send","\"flags\" muse be a number"); if (args[1].type!=vm_str)
return var::num((double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())); return nas_err("send","\"buff\" must be a string");
} if (args[2].type!=vm_num)
return nas_err("send","\"flags\" muse be a number");
var nas_sendto(var* args, usize size, gc* ngc) { return var::num((double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num()));
if (args[0].type!=vm_num) }
return nas_err("sendto","\"sd\" must be a number");
if (args[1].type!=vm_str) var nas_sendto(var* args, usize size, gc* ngc) {
return nas_err("sendto","\"hostname\" must be a string"); if (args[0].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("sendto","\"sd\" must be a number");
return nas_err("sendto","\"port\" must be a number"); if (args[1].type!=vm_str)
if (args[3].type!=vm_str) return nas_err("sendto","\"hostname\" must be a string");
return nas_err("sendto","\"buff\" must be a string"); if (args[2].type!=vm_num)
if (args[4].type!=vm_num) return nas_err("sendto","\"port\" must be a number");
return nas_err("sendto","\"flags\" must be a number"); if (args[3].type!=vm_str)
sockaddr_in addr; return nas_err("sendto","\"buff\" must be a string");
memset(&addr,0,sizeof(sockaddr_in)); if (args[4].type!=vm_num)
addr.sin_family=AF_INET; return nas_err("sendto","\"flags\" must be a number");
addr.sin_port=htons(args[2].num()); sockaddr_in addr;
hostent* entry=gethostbyname(args[1].str().c_str()); memset(&addr,0,sizeof(sockaddr_in));
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); addr.sin_family=AF_INET;
return var::num((double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); addr.sin_port=htons(args[2].num());
} hostent* entry=gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length);
var nas_recv(var* args, usize size, gc* ngc) { return var::num((double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in)));
if (args[0].type!=vm_num) }
return nas_err("recv","\"sd\" must be a number");
if (args[1].type!=vm_num) var nas_recv(var* args, usize size, gc* ngc) {
return nas_err("recv","\"len\" must be a number"); if (args[0].type!=vm_num)
if (args[1].num()<=0 || args[1].num()>16*1024*1024) return nas_err("recv","\"sd\" must be a number");
return nas_err("recv","\"len\" out of range"); if (args[1].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("recv","\"len\" must be a number");
return nas_err("recv","\"flags\" muse be a number"); if (args[1].num()<=0 || args[1].num()>16*1024*1024)
var res=ngc->temp=ngc->alloc(vm_hash); return nas_err("recv","\"len\" out of range");
auto& hash=res.hash().elems; if (args[2].type!=vm_num)
char* buf=new char[(int)args[1].num()]; return nas_err("recv","\"flags\" muse be a number");
auto recvsize=recv(args[0].num(),buf,args[1].num(),args[2].num()); var res=ngc->temp=ngc->alloc(vm_hash);
hash["size"]=var::num((double)recvsize); auto& hash=res.hash().elems;
buf[recvsize>=0?recvsize:0]=0; char* buf=new char[(int)args[1].num()];
hash["str"]=ngc->newstr(buf); auto recvsize=recv(args[0].num(),buf,args[1].num(),args[2].num());
delete[] buf; hash["size"]=var::num((double)recvsize);
ngc->temp=nil; buf[recvsize>=0?recvsize:0]=0;
return res; hash["str"]=ngc->newstr(buf);
} delete[] buf;
ngc->temp=nil;
var nas_recvfrom(var* args, usize size, gc* ngc) { return res;
if (args[0].type!=vm_num) }
return nas_err("recvfrom","\"sd\" must be a number");
if (args[1].type!=vm_num) var nas_recvfrom(var* args, usize size, gc* ngc) {
return nas_err("recvfrom","\"len\" must be a number"); if (args[0].type!=vm_num)
if (args[1].num()<=0 || args[1].num()>16*1024*1024) return nas_err("recvfrom","\"sd\" must be a number");
return nas_err("recvfrom","\"len\" out of range"); if (args[1].type!=vm_num)
if (args[2].type!=vm_num) return nas_err("recvfrom","\"len\" must be a number");
return nas_err("recvfrom","\"flags\" muse be a number"); if (args[1].num()<=0 || args[1].num()>16*1024*1024)
sockaddr_in addr; return nas_err("recvfrom","\"len\" out of range");
int socklen=sizeof(sockaddr_in); if (args[2].type!=vm_num)
var res=ngc->temp=ngc->alloc(vm_hash); return nas_err("recvfrom","\"flags\" muse be a number");
auto& hash=res.hash().elems; sockaddr_in addr;
char* buf=new char[(int)args[1].num()+1]; int socklen=sizeof(sockaddr_in);
#ifdef _WIN32 var res=ngc->temp=ngc->alloc(vm_hash);
auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen); auto& hash=res.hash().elems;
#else char* buf=new char[(int)args[1].num()+1];
auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen); #ifdef _WIN32
#endif auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen);
hash["size"]=var::num((double)recvsize); #else
buf[recvsize>=0?recvsize:0]=0; auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen);
hash["str"]=ngc->newstr(buf); #endif
delete[] buf; hash["size"]=var::num((double)recvsize);
hash["fromip"]=ngc->newstr(inet_ntoa(addr.sin_addr)); buf[recvsize>=0?recvsize:0]=0;
ngc->temp=nil; hash["str"]=ngc->newstr(buf);
return res; delete[] buf;
} hash["fromip"]=ngc->newstr(inet_ntoa(addr.sin_addr));
ngc->temp=nil;
var nas_errno(var* args, usize size, gc* ngc) { return res;
return ngc->newstr(strerror(errno)); }
}
var nas_errno(var* args, usize size, gc* ngc) {
mod_func func_tbl[]={ return ngc->newstr(strerror(errno));
{"nas_socket",nas_socket}, }
{"nas_closesocket",nas_closesocket},
{"nas_shutdown",nas_shutdown}, module_func_info func_tbl[]={
{"nas_bind",nas_bind}, {"nas_socket",nas_socket},
{"nas_listen",nas_listen}, {"nas_closesocket",nas_closesocket},
{"nas_connect",nas_connect}, {"nas_shutdown",nas_shutdown},
{"nas_accept",nas_accept}, {"nas_bind",nas_bind},
{"nas_send",nas_send}, {"nas_listen",nas_listen},
{"nas_sendto",nas_sendto}, {"nas_connect",nas_connect},
{"nas_recv",nas_recv}, {"nas_accept",nas_accept},
{"nas_recvfrom",nas_recvfrom}, {"nas_send",nas_send},
{"nas_errno",nas_errno}, {"nas_sendto",nas_sendto},
{nullptr,nullptr} {"nas_recv",nas_recv},
}; {"nas_recvfrom",nas_recvfrom},
{"nas_errno",nas_errno},
extern "C" mod_func* get() { {nullptr,nullptr}
return func_tbl; };
extern "C" module_func_info* get(ghost_register_table* table) {
return func_tbl;
} }

View File

@ -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

View File

@ -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;

View File

@ -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*);

View File

@ -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>

View File

@ -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:

View File

@ -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~' ';