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
.vs
x64
CMakePresents.json
# nasal executable
nasal
@ -49,6 +50,7 @@ dump
# build dir
build
out
# macOS special cache directory
.DS_Store

View File

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10)
project(nasal VERSION 10.1)
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
# -std=c++14 -Wshadow -Wall
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
@ -9,6 +11,7 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
# generate release executables
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
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})
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 | 首先
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
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`.
2. In Visual Studio, click `File`->`New`->`Project From Existing Code...`.
@ -20,12 +30,14 @@ Make sure you are using VS 2022.
## 如何创建VS工程
1. 用`git`从这个仓库获取代码。
确保你使用的是 VS 2022。这个方式可能无法生成一些动态库。
1. 用 `git` 从这个仓库获取代码。
2. 在VS的界面点击文件(F)->新建(N)->从现有代码创建项目(E)。
3. 选择创建`Visual C++`项目->下一步->项目文件位置选择你下载的代码存放的文件夹->填项目名称,随便写->完成。
3. 选择创建 `Visual C++` 项目->下一步->项目文件位置选择你下载的代码存放的文件夹->填项目名称,随便写->完成。
4. 从项目中去掉 `module` 里的cpp文件以防止编译错误。(那些本应该编译到动态库)
5. 点开左侧解决方案资源管理器中的`Source Files`,右键点击`main.cpp`,编译。
5. 点开左侧解决方案资源管理器中的 `Source Files`,右键点击 `main.cpp`,编译。

View File

@ -1,44 +1,99 @@
#include <iostream>
#include "../nasal.h"
double fibonaci(double x) {
if (x<=2) {
return x;
}
return fibonaci(x-1)+fibonaci(x-2);
}
var fib(var* args, usize size, gc* ngc) {
if (!size) {
return nas_err("fib","lack arguments");
}
var num=args[0];
return var::num(fibonaci(num.tonum()));
}
var quick_fib(var* args, usize size, gc* ngc) {
if (!size) {
return nas_err("quick_fib","lack arguments");
}
double num=args[0].tonum();
if (num<2) {
return var::num(num);
}
double a=1,b=1,res=0;
for(double i=1;i<num;i+=1) {
res=a+b;
a=b;
b=res;
}
return var::num(res);
}
mod_func func_tbl[]={
{"fib",fib},
{"quick_fib",quick_fib},
{nullptr, nullptr},
};
extern "C" mod_func* get() {
return func_tbl;
// module for test
#include <iostream>
#include "../nasal.h"
namespace nasal_fib_module {
double fibonaci(double x) {
if (x<=2) {
return x;
}
return fibonaci(x-1)+fibonaci(x-2);
}
var fib(var* args, usize size, gc* ngc) {
if (!size) {
return nas_err("fib","lack arguments");
}
var num=args[0];
return var::num(fibonaci(num.tonum()));
}
var quick_fib(var* args, usize size, gc* ngc) {
if (!size) {
return nas_err("quick_fib","lack arguments");
}
double num=args[0].tonum();
if (num<2) {
return var::num(num);
}
double a=1,b=1,res=0;
for(double i=1;i<num;i+=1) {
res=a+b;
a=b;
b=res;
}
return var::num(res);
}
u32 ghost_for_test;
void ghost_for_test_destructor(void* ptr) {
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 <unistd.h>
#include <iostream>
#ifdef _WIN32
#include <conio.h>
#else
#include <fcntl.h>
#include <termios.h>
#endif
class noecho_input {
private:
#ifndef _WIN32
struct termios init_termios;
struct termios new_termios;
int peek_char=-1;
#endif
public:
noecho_input() {
#ifndef _WIN32
tcflush(0, TCIOFLUSH);
tcgetattr(0, &init_termios);
new_termios=init_termios;
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
// so we use fcntl to write the nonblock input
new_termios.c_cc[VMIN]=1;
new_termios.c_cc[VTIME]=0;
tcsetattr(0, TCSANOW, &new_termios);
#endif
}
~noecho_input() {
#ifndef _WIN32
tcflush(0, TCIOFLUSH);
tcsetattr(0, TCSANOW, &init_termios);
#endif
}
int noecho_kbhit() {
#ifndef _WIN32
unsigned char ch=0;
int nread=0;
if (peek_char!=-1) {
return 1;
}
int flag=fcntl(0, F_GETFL);
fcntl(0, F_SETFL,flag|O_NONBLOCK);
nread=read(0, &ch, 1);
fcntl(0, F_SETFL, flag);
if (nread==1) {
peek_char=ch;
return 1;
}
return 0;
#else
return kbhit();
#endif
}
int noecho_getch() {
#ifndef _WIN32
int ch=0;
if (peek_char!=-1) {
ch=peek_char;
peek_char=-1;
return ch;
}
ssize_t tmp=read(0, &ch, 1);
return ch;
#else
return getch();
#endif
}
};
noecho_input this_window;
var nas_getch(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_getch());
}
var nas_kbhit(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_kbhit());
}
var nas_noblock(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch());
}
return nil;
}
mod_func func_tbl[]={
{"nas_getch",nas_getch},
{"nas_kbhit",nas_kbhit},
{"nas_noblock",nas_noblock},
{nullptr,nullptr}
};
extern "C" mod_func* get() {
return func_tbl;
#include "../nasal.h"
#include <iostream>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#ifdef _WIN32
#include <conio.h>
#else
#include <fcntl.h>
#include <termios.h>
#endif
class noecho_input {
private:
#ifndef _WIN32
struct termios init_termios;
struct termios new_termios;
int peek_char=-1;
#endif
public:
noecho_input() {
#ifndef _WIN32
tcflush(0, TCIOFLUSH);
tcgetattr(0, &init_termios);
new_termios=init_termios;
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
// so we use fcntl to write the nonblock input
new_termios.c_cc[VMIN]=1;
new_termios.c_cc[VTIME]=0;
tcsetattr(0, TCSANOW, &new_termios);
#endif
}
~noecho_input() {
#ifndef _WIN32
tcflush(0, TCIOFLUSH);
tcsetattr(0, TCSANOW, &init_termios);
#endif
}
int noecho_kbhit() {
#ifndef _WIN32
unsigned char ch=0;
int nread=0;
if (peek_char!=-1) {
return 1;
}
int flag=fcntl(0, F_GETFL);
fcntl(0, F_SETFL,flag|O_NONBLOCK);
nread=read(0, &ch, 1);
fcntl(0, F_SETFL, flag);
if (nread==1) {
peek_char=ch;
return 1;
}
return 0;
#else
return kbhit();
#endif
}
int noecho_getch() {
#ifndef _WIN32
int ch=0;
if (peek_char!=-1) {
ch=peek_char;
peek_char=-1;
return ch;
}
ssize_t tmp=read(0, &ch, 1);
return ch;
#else
return getch();
#endif
}
};
noecho_input this_window;
var nas_getch(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_getch());
}
var nas_kbhit(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_kbhit());
}
var nas_noblock(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch());
}
return nil;
}
module_func_info func_tbl[]={
{"nas_getch",nas_getch},
{"nas_kbhit",nas_kbhit},
{"nas_noblock",nas_noblock},
{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 fib=dl.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);
return {
fib: func(x){return call(fib,x)},
qfib:func(x){return call(qfib,x)}
var test_call=dylib.limitcall(2);
var res={
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 <cmath>
var nas_vec2(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]);
return res;
}
var nas_vec3(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]);
res.vec().elems.push_back(args[2]);
return res;
}
var nas_vec2_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()+v1[1].num()));
return res;
}
var nas_vec2_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()-v1[1].num()));
return res;
}
var nas_vec2_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()*v1[1].num()));
return res;
}
var nas_vec2_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()/v1[1].num()));
return res;
}
var nas_vec2_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back(var::num(-v0[1].num()));
return res;
}
var nas_vec2_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto t=std::sqrt(x*x+y*y);
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back(var::num(y/t));
return res;
}
var nas_vec2_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
return var::num(std::sqrt(x*x+y*y));
}
var nas_vec2_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()+v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()+v1[2].num()));
return res;
}
var nas_vec3_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()-v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()-v1[2].num()));
return res;
}
var nas_vec3_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()*v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()*v1[2].num()));
return res;
}
var nas_vec3_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()/v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()/v1[2].num()));
return res;
}
var nas_vec3_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
var res=ngc->alloc(vm_vec);
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[2].num()));
return res;
}
var nas_vec3_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto z=v0[2].num();
auto t=std::sqrt(x*x+y*y+z*z);
var res=ngc->alloc(vm_vec);
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(z/t));
return res;
}
var nas_vec3_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto z=v0[2].num();
return var::num(std::sqrt(x*x+y*y+z*z));
}
var nas_rotate_x(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
var res=ngc->alloc(vm_vec);
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::cos(angle)-v0[1].num()*std::sin(angle)));
return res;
}
var nas_rotate_y(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
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[1].num()));
res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle)));
return res;
}
var nas_rotate_z(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
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::sin(angle)+v0[1].num()*std::cos(angle)));
res.vec().elems.push_back(var::num(v0[2].num()));
return res;
}
var nas_vec3_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[]={
{"nas_vec2",nas_vec2},
{"nas_vec2_add",nas_vec2_add},
{"nas_vec2_sub",nas_vec2_sub},
{"nas_vec2_mult",nas_vec2_mult},
{"nas_vec2_div",nas_vec2_div},
{"nas_vec2_neg",nas_vec2_neg},
{"nas_vec2_norm",nas_vec2_norm},
{"nas_vec2_len",nas_vec2_len},
{"nas_vec2_dot",nas_vec2_dot},
{"nas_vec3",nas_vec3},
{"nas_vec3_add",nas_vec3_add},
{"nas_vec3_sub",nas_vec3_sub},
{"nas_vec3_mult",nas_vec3_mult},
{"nas_vec3_div",nas_vec3_div},
{"nas_vec3_neg",nas_vec3_neg},
{"nas_vec3_norm",nas_vec3_norm},
{"nas_vec3_len",nas_vec3_len},
{"nas_rotate_x",nas_rotate_x},
{"nas_rotate_y",nas_rotate_y},
{"nas_rotate_z",nas_rotate_z},
{"nas_vec3_dot",nas_vec3_dot},
{nullptr,nullptr}
};
extern "C" mod_func* get() {
return func_tbl;
#include "../nasal.h"
#include <cmath>
var nas_vec2(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]);
return res;
}
var nas_vec3(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]);
res.vec().elems.push_back(args[2]);
return res;
}
var nas_vec2_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()+v1[1].num()));
return res;
}
var nas_vec2_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()-v1[1].num()));
return res;
}
var nas_vec2_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()*v1[1].num()));
return res;
}
var nas_vec2_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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[1].num()/v1[1].num()));
return res;
}
var nas_vec2_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back(var::num(-v0[1].num()));
return res;
}
var nas_vec2_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto t=std::sqrt(x*x+y*y);
var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back(var::num(y/t));
return res;
}
var nas_vec2_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=2)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
return var::num(std::sqrt(x*x+y*y));
}
var nas_vec2_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2)
return nil;
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) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()+v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()+v1[2].num()));
return res;
}
var nas_vec3_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()-v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()-v1[2].num()));
return res;
}
var nas_vec3_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()*v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()*v1[2].num()));
return res;
}
var nas_vec3_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
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[1].num()/v1[1].num()));
res.vec().elems.push_back(var::num(v0[2].num()/v1[2].num()));
return res;
}
var nas_vec3_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
var res=ngc->alloc(vm_vec);
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[2].num()));
return res;
}
var nas_vec3_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto z=v0[2].num();
auto t=std::sqrt(x*x+y*y+z*z);
var res=ngc->alloc(vm_vec);
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(z/t));
return res;
}
var nas_vec3_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto x=v0[0].num();
auto y=v0[1].num();
auto z=v0[2].num();
return var::num(std::sqrt(x*x+y*y+z*z));
}
var nas_rotate_x(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
var res=ngc->alloc(vm_vec);
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::cos(angle)-v0[1].num()*std::sin(angle)));
return res;
}
var nas_rotate_y(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
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[1].num()));
res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle)));
return res;
}
var nas_rotate_z(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
if (v0.size()!=3)
return nil;
auto angle=args[1].num();
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::sin(angle)+v0[1].num()*std::cos(angle)));
res.vec().elems.push_back(var::num(v0[2].num()));
return res;
}
var nas_vec3_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil;
auto& v0=args[0].vec().elems;
auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3)
return nil;
return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num());
}
module_func_info func_tbl[]={
{"nas_vec2",nas_vec2},
{"nas_vec2_add",nas_vec2_add},
{"nas_vec2_sub",nas_vec2_sub},
{"nas_vec2_mult",nas_vec2_mult},
{"nas_vec2_div",nas_vec2_div},
{"nas_vec2_neg",nas_vec2_neg},
{"nas_vec2_norm",nas_vec2_norm},
{"nas_vec2_len",nas_vec2_len},
{"nas_vec2_dot",nas_vec2_dot},
{"nas_vec3",nas_vec3},
{"nas_vec3_add",nas_vec3_add},
{"nas_vec3_sub",nas_vec3_sub},
{"nas_vec3_mult",nas_vec3_mult},
{"nas_vec3_div",nas_vec3_div},
{"nas_vec3_neg",nas_vec3_neg},
{"nas_vec3_norm",nas_vec3_norm},
{"nas_vec3_len",nas_vec3_len},
{"nas_rotate_x",nas_rotate_x},
{"nas_rotate_y",nas_rotate_y},
{"nas_rotate_z",nas_rotate_z},
{"nas_vec3_dot",nas_vec3_dot},
{nullptr,nullptr}
};
extern "C" module_func_info* get(ghost_register_table* table) {
return func_tbl;
}

View File

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

View File

@ -8,6 +8,9 @@
#include <dirent.h>
#else
#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_NONSTDC_NO_DEPRECATE 1
#include <io.h>
@ -544,13 +547,13 @@ var builtin_open(var* local, gc& ngc) {
return nas_err("open", "failed to open file <"+name.str()+">");
}
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;
}
var builtin_close(var* local, gc& ngc) {
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");
}
fd.obj().clear();
@ -561,7 +564,7 @@ var builtin_read(var* local, gc& ngc) {
var fd=local[1];
var buf=local[2];
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");
}
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 fd=local[1];
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");
}
if (str.type!=vm_str) {
@ -600,7 +603,7 @@ var builtin_seek(var* local, gc& ngc) {
var fd=local[1];
var pos=local[2];
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 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 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 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 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");
}
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 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 var::num((f64)feof((FILE*)fd.obj().ptr));
@ -849,13 +852,13 @@ var builtin_opendir(var* local, gc& ngc) {
}
#endif
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;
}
var builtin_readdir(var* local, gc& ngc) {
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");
}
#ifdef _MSC_VER
@ -872,7 +875,7 @@ var builtin_readdir(var* local, gc& ngc) {
var builtin_closedir(var* local, gc& ngc) {
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");
}
handle.obj().clear();
@ -936,7 +939,7 @@ var builtin_dlopen(var* local, gc& ngc) {
}
var ret=ngc.temp=ngc.alloc(vm_hash);
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;
#ifdef _WIN32
@ -948,14 +951,14 @@ var builtin_dlopen(var* local, gc& ngc) {
return nas_err("dlopen", "cannot find <get> function");
}
// 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) {
return nas_err("dlopen", "failed to get module functions");
}
for(u32 i=0;tbl[i].name;++i) {
void* p=(void*)tbl[i].fd;
var tmp=ngc.alloc(vm_obj);
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;
}
@ -965,7 +968,7 @@ var builtin_dlopen(var* local, gc& ngc) {
var builtin_dlclose(var* local, gc& ngc) {
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");
}
libptr.obj().clear();
@ -975,23 +978,27 @@ var builtin_dlclose(var* local, gc& ngc) {
var builtin_dlcallv(var* local, gc& ngc) {
var fp=local[1];
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");
}
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 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");
}
var* local_frame_start=local+2;
usize local_frame_size=ngc.rctx->top-local_frame_start;
// arguments' stored place begins at local +2
return ((mod)fp.obj().ptr)(
return ((module_func)fp.obj().ptr)(
local_frame_start,
local_frame_size,
&ngc

View File

@ -9,6 +9,11 @@
#include <stack>
#include <unordered_map>
#ifdef _MSC_VER
#pragma warning (disable:4244)
#pragma warning (disable:4267)
#endif
class codegen {
private:
u16 fileindex;

View File

@ -1,4 +1,9 @@
#pragma once
#ifdef _MSC_VER
#pragma warning (disable:4244)
#pragma warning (disable:4267)
#pragma warning (disable:4102)
#endif
#ifndef _MSC_VER
#include <unistd.h>
@ -43,14 +48,6 @@ enum vm_type:u8 {
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 {
suspended,
running,
@ -63,13 +60,13 @@ enum class gc_status:u8 {
found
};
struct nas_vec; // vector
struct nas_hash; // hashmap(dict)
struct nas_func; // function(lambda)
struct nas_upval;// upvalue
struct nas_obj; // special objects
struct nas_co; // coroutine
struct nas_val; // nas_val includes gc-managed types
struct nas_vec; // vector
struct nas_hash; // hashmap(dict)
struct nas_func; // function(lambda)
struct nas_upval; // upvalue
struct nas_obj; // special objects
struct nas_co; // coroutine
struct nas_val; // nas_val includes gc-managed types
struct var {
public:
@ -99,7 +96,7 @@ public:
// number and string can be translated to each other
f64 tonum();
string tostr();
bool objchk(obj_type);
bool objchk(usize);
// create new var object
static var none();
@ -162,6 +159,7 @@ struct nas_func {
};
struct nas_upval {
public:
/* on stack, use these variables */
bool onstk;
u32 size;
@ -170,55 +168,119 @@ struct nas_upval {
/* not on stack, use this */
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:
nas_ghost(): type(0), ptr(nullptr) {}
~nas_ghost() {
if (!ptr) { return; }
ghost_register_table[type].destructor(ptr);
nas_upval(): onstk(true), size(0), stk(nullptr) {}
var& operator[](usize n) {
return onstk? stk[n]:elems[n];
}
static usize regist_ghost_type(ghost_info i) {
auto res=ghost_register_table.size();
ghost_register_table.push_back(i);
void clear() {
onstk=true;
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;
}
const std::string& name() {
return ghost_register_table[type].name;
dtor destructor(usize index) {
return destructors.at(index);
}
};
struct nas_obj {
obj_type type;
public:
usize type;
void* ptr;
private:
/* RAII constructor, new object is initialized when creating */
void file_dtor();
void dir_dtor();
void dylib_dtor();
ghost_register_table* ghost_type_table;
public:
nas_obj(): type(obj_type::null), ptr(nullptr) {}
nas_obj(): type(0), ptr(nullptr), ghost_type_table(nullptr) {}
~nas_obj() {clear();}
void set(obj_type, void*);
void set(usize, void*, ghost_register_table*);
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 {
@ -357,47 +419,20 @@ void nas_func::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;
ptr=p;
ghost_type_table=table;
}
void nas_obj::clear() {
if (!ptr) {
return;
}
switch(type) {
case obj_type::file: file_dtor(); break;
case obj_type::dir: dir_dtor(); break;
case obj_type::dylib: dylib_dtor();break;
default: break;
}
ghost_type_table->destructor(type)(ptr);
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() {
for(u32 i=0;i<STACK_DEPTH;++i) {
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_hash: out<<ref.hash(); 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;
}
return out;
}
bool var::objchk(obj_type objtype) {
return type==vm_obj && obj().type==objtype && obj().ptr;
bool var::objchk(usize obj_type) {
return type==vm_obj && obj().type==obj_type && obj().ptr;
}
var var::none() {
@ -534,6 +569,7 @@ const var one =var::num(1);
const var nil =var::nil();
struct gc {
ghost_register_table global_ghost_type_table;
/* main context temporary storage */
context mctx;
@ -587,11 +623,27 @@ public:
void clear();
void info();
var alloc(const u8);
var newstr(char);
var newstr(const char*);
var newstr(const string&);
void ctxchg(nas_co&);
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() {
@ -691,14 +743,15 @@ void gc::sweep() {
}
void gc::extend(u8 type) {
u8 index=type-vm_str;
const u8 index=type-vm_str;
size[index]+=incr[index];
for(u32 i=0;i<incr[index];++i) {
nas_val* tmp=new nas_val(type);
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);
}
@ -720,7 +773,7 @@ void gc::init(const std::vector<string>& s, const std::vector<string>& argv) {
size[i]=gcnt[i]=acnt[i]=0;
}
// coroutine pointer set to nullpre
// coroutine pointer set to nullptr
cort=nullptr;
// init constant strings
@ -820,24 +873,6 @@ var gc::alloc(u8 type) {
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) {
// store running state to main context
mctx=*rctx;
@ -869,19 +904,19 @@ void gc::ctxreserve() {
}
// use to print error log and return error value
var nas_err(const string& err_f, const string& info) {
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
var nas_err(const string& error_function_name, const string& info) {
std::cerr<<"[vm] "<<error_function_name<<": "<<info<<"\n";
return var::none();
}
// 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}
struct mod_func {
struct module_func_info {
const char* name;
mod fd;
module_func fd;
};
// 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
#ifdef _MSC_VER
#pragma warning (disable:4244)
#pragma warning (disable:4267)
#pragma warning (disable:4102)
#endif
#include <cstring>
#include <sstream>

View File

@ -7,6 +7,12 @@
#include "nasal_gc.h"
#include "nasal_codegen.h"
#ifdef _MSC_VER
#pragma warning (disable:4244)
#pragma warning (disable:4267)
#pragma warning (disable:4102)
#endif
class vm {
protected:

View File

@ -11,7 +11,7 @@ var new_map=func(width,height){
}
var prt=func(map){
var s='\e[1;1H';
var s='\ec\e[1;1H';
foreach(var line;map){
foreach(var elem;line)
s~=elem~' ';