Merge pull request #28 from ValKmjolnir/develop

 finish simple repl interpreter (experimental)
This commit is contained in:
Li Haokun 2023-09-18 00:50:54 +08:00 committed by GitHub
commit 38920382ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 610 additions and 453 deletions

View File

@ -3,7 +3,8 @@
#include <iostream> #include <iostream>
#include "../src/nasal.h" #include "../src/nasal.h"
namespace nasal_fib_module { namespace nasal {
namespace fib_module {
double fibonaci(double x) { double fibonaci(double x) {
if (x<=2) { if (x<=2) {
@ -41,9 +42,10 @@ const auto ghost_for_test = "ghost_for_test";
void ghost_for_test_destructor(void* ptr) { void ghost_for_test_destructor(void* ptr) {
std::cout << "ghost_for_test::destructor (0x"; std::cout << "ghost_for_test::destructor (0x";
std::cout << std::hex << (u64)ptr << std::dec << ") {\n"; std::cout << std::hex << reinterpret_cast<u64>(ptr) << std::dec << ") {\n";
delete (u32*)ptr; delete static_cast<u32*>(ptr);
std::cout << " delete 0x" << std::hex << (u64)ptr << std::dec << ";\n"; std::cout << " delete 0x" << std::hex;
std::cout << reinterpret_cast<u64>(ptr) << std::dec << ";\n";
std::cout << "}\n"; std::cout << "}\n";
} }
@ -88,5 +90,7 @@ module_func_info func_tbl[] = {
} }
extern "C" module_func_info* get() { extern "C" module_func_info* get() {
return nasal_fib_module::func_tbl; return fib_module::func_tbl;
}
} }

View File

@ -12,46 +12,50 @@
#include <termios.h> #include <termios.h>
#endif #endif
namespace nasal {
class noecho_input { class noecho_input {
private: private:
#ifndef _WIN32 #ifndef _WIN32
struct termios init_termios; struct termios init_termios;
struct termios new_termios; struct termios new_termios;
int peek_char=-1; int peek_char = -1;
#endif #endif
public: public:
noecho_input() { noecho_input() {
#ifndef _WIN32 #ifndef _WIN32
tcflush(0, TCIOFLUSH); tcflush(0, TCIOFLUSH);
tcgetattr(0, &init_termios); tcgetattr(0, &init_termios);
new_termios=init_termios; new_termios = init_termios;
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE); new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE);
// vmin=0 is nonblock input, but in wsl there is a bug that will block input // 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 // so we use fcntl to write the nonblock input
new_termios.c_cc[VMIN]=1; new_termios.c_cc[VMIN] = 1;
new_termios.c_cc[VTIME]=0; new_termios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_termios); tcsetattr(0, TCSANOW, &new_termios);
#endif #endif
} }
~noecho_input() { ~noecho_input() {
#ifndef _WIN32 #ifndef _WIN32
tcflush(0, TCIOFLUSH); tcflush(0, TCIOFLUSH);
tcsetattr(0, TCSANOW, &init_termios); tcsetattr(0, TCSANOW, &init_termios);
#endif #endif
} }
int noecho_kbhit() { int noecho_kbhit() {
#ifndef _WIN32 #ifndef _WIN32
unsigned char ch=0; unsigned char ch = 0;
int nread=0; int nread = 0;
if (peek_char!=-1) { if (peek_char!=-1) {
return 1; return 1;
} }
int flag=fcntl(0, F_GETFL); int flag = fcntl(0, F_GETFL);
fcntl(0, F_SETFL,flag|O_NONBLOCK); fcntl(0, F_SETFL,flag|O_NONBLOCK);
nread=read(0, &ch, 1); nread = read(0, &ch, 1);
fcntl(0, F_SETFL, flag); fcntl(0, F_SETFL, flag);
if (nread==1) { if (nread==1) {
peek_char=ch; peek_char = ch;
return 1; return 1;
} }
return 0; return 0;
@ -59,15 +63,16 @@ public:
return kbhit(); return kbhit();
#endif #endif
} }
int noecho_getch() { int noecho_getch() {
#ifndef _WIN32 #ifndef _WIN32
int ch=0; int ch = 0;
if (peek_char!=-1) { if (peek_char!=-1) {
ch=peek_char; ch = peek_char;
peek_char=-1; peek_char = -1;
return ch; return ch;
} }
ssize_t tmp=read(0, &ch, 1); ssize_t tmp = read(0, &ch, 1);
return ch; return ch;
#else #else
return getch(); return getch();
@ -92,7 +97,7 @@ var nas_noblock(var* args, usize size, gc* ngc) {
return nil; return nil;
} }
module_func_info func_tbl[]={ module_func_info func_tbl[] = {
{"nas_getch",nas_getch}, {"nas_getch",nas_getch},
{"nas_kbhit",nas_kbhit}, {"nas_kbhit",nas_kbhit},
{"nas_noblock",nas_noblock}, {"nas_noblock",nas_noblock},
@ -101,4 +106,6 @@ module_func_info func_tbl[]={
extern "C" module_func_info* get() { extern "C" module_func_info* get() {
return func_tbl; return func_tbl;
} }
}

View File

@ -1,15 +1,17 @@
#include "../src/nasal.h" #include "../src/nasal.h"
#include <cmath> #include <cmath>
namespace nasal {
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]);
@ -19,11 +21,11 @@ var nas_vec3(var* args, usize size, gc* ngc) {
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;
@ -32,11 +34,11 @@ var nas_vec2_add(var* args, usize size, gc* ngc) {
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;
@ -45,11 +47,11 @@ var nas_vec2_sub(var* args, usize size, gc* ngc) {
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;
@ -58,11 +60,11 @@ var nas_vec2_mult(var* args, usize size, gc* ngc) {
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;
@ -71,10 +73,10 @@ var nas_vec2_div(var* args, usize size, gc* ngc) {
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;
@ -83,13 +85,13 @@ var nas_vec2_neg(var* args, usize size, gc* ngc) {
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;
@ -98,19 +100,19 @@ var nas_vec2_norm(var* args, usize size, gc* ngc) {
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());
@ -119,11 +121,11 @@ var nas_vec2_dot(var* args, usize size, gc* ngc) {
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()));
@ -133,11 +135,11 @@ var nas_vec3_add(var* args, usize size, gc* ngc) {
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()));
@ -147,11 +149,11 @@ var nas_vec3_sub(var* args, usize size, gc* ngc) {
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()));
@ -161,11 +163,11 @@ var nas_vec3_mult(var* args, usize size, gc* ngc) {
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()));
@ -175,10 +177,10 @@ var nas_vec3_div(var* args, usize size, gc* ngc) {
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()));
@ -188,14 +190,14 @@ var nas_vec3_neg(var* args, usize size, gc* ngc) {
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));
@ -205,23 +207,23 @@ var nas_vec3_norm(var* args, usize size, gc* ngc) {
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)));
@ -231,11 +233,11 @@ var nas_rotate_x(var* args, usize size, gc* ngc) {
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)));
@ -245,11 +247,11 @@ var nas_rotate_y(var* args, usize size, gc* ngc) {
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()));
@ -259,38 +261,40 @@ var nas_rotate_z(var* args, usize size, gc* ngc) {
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());
} }
module_func_info 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" module_func_info* get() { extern "C" module_func_info* get() {
return func_tbl; return func_tbl;
}
} }

View File

@ -28,16 +28,18 @@ static WSAmanager win;
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
namespace nasal {
var nas_socket(var* args, usize size, gc* ngc) { 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) 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"); return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num()); int sd = socket(args[0].num(), args[1].num(), args[2].num());
return var::num((double)sd); return var::num((double)sd);
} }
var nas_closesocket(var* args, usize size, gc* ngc) { var nas_closesocket(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("closesocket","\"sd\" should be number"); return nas_err("closesocket", "\"sd\" should be number");
#ifdef _WIN32 #ifdef _WIN32
return var::num((double)closesocket(args[0].num())); return var::num((double)closesocket(args[0].num()));
#else #else
@ -47,145 +49,175 @@ var nas_closesocket(var* args, usize size, gc* ngc) {
var nas_shutdown(var* args, usize size, gc* ngc) { var nas_shutdown(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("shutdown","\"sd\" must be a number"); return nas_err("shutdown", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("shutdown","\"how\" must be a number"); return nas_err("shutdown", "\"how\" must be a number");
return var::num((double)shutdown(args[0].num(),args[1].num())); return var::num((double)shutdown(args[0].num(), args[1].num()));
} }
var nas_bind(var* args, usize size, gc* ngc) { var nas_bind(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("bind","\"sd\" muse be a number"); return nas_err("bind", "\"sd\" muse be a number");
if (args[1].type!=vm_str) if (args[1].type!=vm_str)
return nas_err("bind","\"ip\" should be a string including an ip with correct format"); return nas_err("bind", "\"ip\" should be a string including an ip with correct format");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("bind","\"port\" must be a number"); return nas_err("bind", "\"port\" must be a number");
sockaddr_in server; sockaddr_in server;
memset(&server,0,sizeof(sockaddr_in)); memset(&server, 0, sizeof(sockaddr_in));
server.sin_family=AF_INET; server.sin_family = AF_INET;
server.sin_addr.s_addr=inet_addr(args[1].str().c_str()); server.sin_addr.s_addr = inet_addr(args[1].str().c_str());
server.sin_port=htons(args[2].num()); server.sin_port = htons(args[2].num());
return var::num((double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))); return var::num((double)bind(args[0].num(), (sockaddr*)&server, sizeof(server)));
} }
var nas_listen(var* args, usize size, gc* ngc) { var nas_listen(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("listen","\"sd\" must be a number"); return nas_err("listen", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("listen","\"backlog\" must be a number"); return nas_err("listen", "\"backlog\" must be a number");
return var::num((double)listen(args[0].num(),args[1].num())); return var::num((double)listen(args[0].num(), args[1].num()));
} }
var nas_connect(var* args, usize size, gc* ngc) { var nas_connect(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("connect","\"sd\" must be a number"); return nas_err("connect", "\"sd\" must be a number");
if (args[1].type!=vm_str) if (args[1].type!=vm_str)
return nas_err("connect","\"hostname\" must be a string"); return nas_err("connect", "\"hostname\" must be a string");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("connect","\"port\" must be a number"); return nas_err("connect", "\"port\" must be a number");
sockaddr_in addr; sockaddr_in addr;
memset(&addr,0,sizeof(sockaddr_in)); memset(&addr, 0, sizeof(sockaddr_in));
addr.sin_family=AF_INET; addr.sin_family = AF_INET;
addr.sin_port=htons(args[2].num()); addr.sin_port = htons(args[2].num());
hostent* entry=gethostbyname(args[1].str().c_str()); hostent* entry = gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
return var::num((double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); return var::num((double)connect(
args[0].num(),
(sockaddr*)&addr,
sizeof(sockaddr_in)
));
} }
var nas_accept(var* args, usize size, gc* ngc) { var nas_accept(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("accept","\"sd\" must be a number"); return nas_err("accept", "\"sd\" must be a number");
sockaddr_in client; sockaddr_in client;
int socklen=sizeof(sockaddr_in); int socklen = sizeof(sockaddr_in);
#ifdef _WIN32 #ifdef _WIN32
int client_sd=accept(args[0].num(),(sockaddr*)&client,&socklen); int client_sd = accept(args[0].num(), (sockaddr*)&client, &socklen);
#else #else
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); int client_sd = accept(args[0].num(), (sockaddr*)&client, (socklen_t*)&socklen);
#endif #endif
var res=ngc->temp=ngc->alloc(vm_hash); var res=ngc->temp = ngc->alloc(vm_hash);
auto& hash=res.hash().elems; auto& hash = res.hash().elems;
hash["sd"]=var::num((double)client_sd); hash["sd"] = var::num((double)client_sd);
hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr)); hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
ngc->temp=nil; ngc->temp = nil;
return res; return res;
} }
var nas_send(var* args, usize size, gc* ngc) { var nas_send(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("send","\"sd\" must be a number"); return nas_err("send", "\"sd\" must be a number");
if (args[1].type!=vm_str) if (args[1].type!=vm_str)
return nas_err("send","\"buff\" must be a string"); return nas_err("send", "\"buff\" must be a string");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("send","\"flags\" muse be a number"); 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())); 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) { var nas_sendto(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("sendto","\"sd\" must be a number"); return nas_err("sendto", "\"sd\" must be a number");
if (args[1].type!=vm_str) if (args[1].type!=vm_str)
return nas_err("sendto","\"hostname\" must be a string"); return nas_err("sendto", "\"hostname\" must be a string");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("sendto","\"port\" must be a number"); return nas_err("sendto", "\"port\" must be a number");
if (args[3].type!=vm_str) if (args[3].type!=vm_str)
return nas_err("sendto","\"buff\" must be a string"); return nas_err("sendto", "\"buff\" must be a string");
if (args[4].type!=vm_num) if (args[4].type!=vm_num)
return nas_err("sendto","\"flags\" must be a number"); return nas_err("sendto", "\"flags\" must be a number");
sockaddr_in addr; sockaddr_in addr;
memset(&addr,0,sizeof(sockaddr_in)); memset(&addr, 0, sizeof(sockaddr_in));
addr.sin_family=AF_INET; addr.sin_family = AF_INET;
addr.sin_port=htons(args[2].num()); addr.sin_port = htons(args[2].num());
hostent* entry=gethostbyname(args[1].str().c_str()); hostent* entry = gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); 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))); 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) { var nas_recv(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("recv","\"sd\" must be a number"); return nas_err("recv", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("recv","\"len\" must be a number"); return nas_err("recv", "\"len\" must be a number");
if (args[1].num()<=0 || args[1].num()>16*1024*1024) if (args[1].num()<=0 || args[1].num()>16*1024*1024)
return nas_err("recv","\"len\" out of range"); return nas_err("recv", "\"len\" out of range");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("recv","\"flags\" muse be a number"); return nas_err("recv", "\"flags\" muse be a number");
var res=ngc->temp=ngc->alloc(vm_hash); var res = ngc->temp = ngc->alloc(vm_hash);
auto& hash=res.hash().elems; auto& hash = res.hash().elems;
char* buf=new char[(int)args[1].num()]; char* buf = new char[(int)args[1].num()];
auto recvsize=recv(args[0].num(),buf,args[1].num(),args[2].num()); auto recvsize = recv(args[0].num(), buf,args[1].num(), args[2].num());
hash["size"]=var::num((double)recvsize); hash["size"] = var::num((double)recvsize);
buf[recvsize>=0?recvsize:0]=0; buf[recvsize>=0? recvsize:0] = 0;
hash["str"]=ngc->newstr(buf); hash["str"] = ngc->newstr(buf);
delete[] buf; delete[] buf;
ngc->temp=nil; ngc->temp = nil;
return res; return res;
} }
var nas_recvfrom(var* args, usize size, gc* ngc) { var nas_recvfrom(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("recvfrom","\"sd\" must be a number"); return nas_err("recvfrom", "\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("recvfrom","\"len\" must be a number"); return nas_err("recvfrom", "\"len\" must be a number");
if (args[1].num()<=0 || args[1].num()>16*1024*1024) if (args[1].num()<=0 || args[1].num()>16*1024*1024)
return nas_err("recvfrom","\"len\" out of range"); return nas_err("recvfrom", "\"len\" out of range");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("recvfrom","\"flags\" muse be a number"); return nas_err("recvfrom", "\"flags\" muse be a number");
sockaddr_in addr; sockaddr_in addr;
int socklen=sizeof(sockaddr_in); int socklen = sizeof(sockaddr_in);
var res=ngc->temp=ngc->alloc(vm_hash); var res = ngc->temp = ngc->alloc(vm_hash);
auto& hash=res.hash().elems; auto& hash = res.hash().elems;
char* buf=new char[(int)args[1].num()+1]; char* buf = new char[(int)args[1].num()+1];
#ifdef _WIN32 #ifdef _WIN32
auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen); auto recvsize = recvfrom(
args[0].num(),
buf,
args[1].num(),
args[2].num(),
(sockaddr*)&addr,
&socklen
);
#else #else
auto recvsize=recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen); auto recvsize = recvfrom(
args[0].num(),
buf,
args[1].num(),
args[2].num(),
(sockaddr*)&addr,
(socklen_t*)&socklen
);
#endif #endif
hash["size"]=var::num((double)recvsize); hash["size"] = var::num((double)recvsize);
buf[recvsize>=0?recvsize:0]=0; buf[recvsize>=0? recvsize:0] = 0;
hash["str"]=ngc->newstr(buf); hash["str"] = ngc->newstr(buf);
delete[] buf; delete[] buf;
hash["fromip"]=ngc->newstr(inet_ntoa(addr.sin_addr)); hash["fromip"] = ngc->newstr(inet_ntoa(addr.sin_addr));
ngc->temp=nil; ngc->temp = nil;
return res; return res;
} }
@ -193,22 +225,24 @@ var nas_errno(var* args, usize size, gc* ngc) {
return ngc->newstr(strerror(errno)); return ngc->newstr(strerror(errno));
} }
module_func_info func_tbl[]={ module_func_info func_tbl[] = {
{"nas_socket",nas_socket}, {"nas_socket", nas_socket},
{"nas_closesocket",nas_closesocket}, {"nas_closesocket", nas_closesocket},
{"nas_shutdown",nas_shutdown}, {"nas_shutdown", nas_shutdown},
{"nas_bind",nas_bind}, {"nas_bind", nas_bind},
{"nas_listen",nas_listen}, {"nas_listen", nas_listen},
{"nas_connect",nas_connect}, {"nas_connect", nas_connect},
{"nas_accept",nas_accept}, {"nas_accept", nas_accept},
{"nas_send",nas_send}, {"nas_send", nas_send},
{"nas_sendto",nas_sendto}, {"nas_sendto", nas_sendto},
{"nas_recv",nas_recv}, {"nas_recv", nas_recv},
{"nas_recvfrom",nas_recvfrom}, {"nas_recvfrom", nas_recvfrom},
{"nas_errno",nas_errno}, {"nas_errno", nas_errno},
{nullptr,nullptr} {nullptr, nullptr}
}; };
extern "C" module_func_info* get() { extern "C" module_func_info* get() {
return func_tbl; return func_tbl;
} }
}

View File

@ -1,23 +1,37 @@
#include "bits_lib.h" #include "bits_lib.h"
namespace nasal {
var builtin_u32xor(var* local, gc& ngc) { var builtin_u32xor(var* local, gc& ngc) {
return var::num((f64)(u32(local[1].num())^u32(local[2].num()))); return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) ^
static_cast<u32>(local[2].num())
));
} }
var builtin_u32and(var* local, gc& ngc) { var builtin_u32and(var* local, gc& ngc) {
return var::num((f64)(u32(local[1].num())&u32(local[2].num()))); return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) &
static_cast<u32>(local[2].num())
));
} }
var builtin_u32or(var* local, gc& ngc) { var builtin_u32or(var* local, gc& ngc) {
return var::num((f64)(u32(local[1].num())|u32(local[2].num()))); return var::num(static_cast<f64>(
static_cast<u32>(local[1].num()) |
static_cast<u32>(local[2].num())
));
} }
var builtin_u32nand(var* local, gc& ngc) { var builtin_u32nand(var* local, gc& ngc) {
return var::num((f64)(u32)(~(u32(local[1].num())&u32(local[2].num())))); return var::num(static_cast<f64>(~(
static_cast<u32>(local[1].num()) &
static_cast<u32>(local[2].num())
)));
} }
var builtin_u32not(var* local, gc& ngc) { var builtin_u32not(var* local, gc& ngc) {
return var::num((f64)(u32)(~u32(local[1].num()))); return var::num(static_cast<f64>(~static_cast<u32>(local[1].num())));
} }
var builtin_fld(var* local, gc& ngc) { var builtin_fld(var* local, gc& ngc) {
@ -33,8 +47,8 @@ var builtin_fld(var* local, gc& ngc) {
if (startbit.type!=vm_num || length.type!=vm_num) { if (startbit.type!=vm_num || length.type!=vm_num) {
return nas_err("fld", "\"startbit\",\"len\" must be number"); return nas_err("fld", "\"startbit\",\"len\" must be number");
} }
u32 bit = (u32)startbit.num(); u32 bit = static_cast<u32>(startbit.num());
u32 len = (u32)length.num(); u32 len = static_cast<u32>(length.num());
if (bit+len>8*str.str().length()) { if (bit+len>8*str.str().length()) {
return nas_err("fld", "bitfield out of bounds"); return nas_err("fld", "bitfield out of bounds");
} }
@ -45,7 +59,7 @@ var builtin_fld(var* local, gc& ngc) {
res |= 1<<(bit+len-i-1); res |= 1<<(bit+len-i-1);
} }
} }
return var::num((f64)res); return var::num(static_cast<f64>(res));
} }
var builtin_sfld(var* local, gc& ngc) { var builtin_sfld(var* local, gc& ngc) {
@ -62,8 +76,8 @@ var builtin_sfld(var* local, gc& ngc) {
if (startbit.type!=vm_num || length.type!=vm_num) { if (startbit.type!=vm_num || length.type!=vm_num) {
return nas_err("sfld", "\"startbit\",\"len\" must be number"); return nas_err("sfld", "\"startbit\",\"len\" must be number");
} }
u32 bit = (u32)startbit.num(); u32 bit = static_cast<u32>(startbit.num());
u32 len = (u32)length.num(); u32 len = static_cast<u32>(length.num());
if (bit+len>8*str.str().length()) { if (bit+len>8*str.str().length()) {
return nas_err("sfld", "bitfield out of bounds"); return nas_err("sfld", "bitfield out of bounds");
} }
@ -77,7 +91,7 @@ var builtin_sfld(var* local, gc& ngc) {
if (res&(1<<(len-1))) { if (res&(1<<(len-1))) {
res |= ~((1<<len)-1); res |= ~((1<<len)-1);
} }
return var::num((f64)((i32)res)); return var::num(static_cast<f64>(static_cast<i32>(res)));
} }
var builtin_setfld(var* local, gc& ngc) { var builtin_setfld(var* local, gc& ngc) {
@ -95,9 +109,9 @@ var builtin_setfld(var* local, gc& ngc) {
if (startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) { if (startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) {
return nas_err("setfld", "\"startbit\",\"len\",\"val\" must be number"); return nas_err("setfld", "\"startbit\",\"len\",\"val\" must be number");
} }
u32 bit = (u32)startbit.num(); u32 bit = static_cast<u32>(startbit.num());
u32 len = (u32)length.num(); u32 len = static_cast<u32>(length.num());
u64 val = (u64)value.num(); u64 val = static_cast<u64>(value.num());
if (bit+len>8*str.str().length()) { if (bit+len>8*str.str().length()) {
return nas_err("setfld", "bitfield out of bounds"); return nas_err("setfld", "bitfield out of bounds");
} }
@ -134,4 +148,6 @@ nasal_builtin_table bits_native[] = {
{"__setfld", builtin_setfld}, {"__setfld", builtin_setfld},
{"__buf", builtin_buf}, {"__buf", builtin_buf},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -4,6 +4,8 @@
#include "nasal_gc.h" #include "nasal_gc.h"
#include "nasal_builtin.h" #include "nasal_builtin.h"
namespace nasal {
var builtin_u32xor(var*, gc&); var builtin_u32xor(var*, gc&);
var builtin_u32and(var*, gc&); var builtin_u32and(var*, gc&);
var builtin_u32or(var*, gc&); var builtin_u32or(var*, gc&);
@ -15,3 +17,5 @@ var builtin_setfld(var*, gc&);
var builtin_buf(var*, gc&); var builtin_buf(var*, gc&);
extern nasal_builtin_table bits_native[]; extern nasal_builtin_table bits_native[];
}

View File

@ -1,5 +1,7 @@
#include "coroutine.h" #include "coroutine.h"
namespace nasal {
var builtin_cocreate(var* local, gc& ngc) { var builtin_cocreate(var* local, gc& ngc) {
// +-------------+ // +-------------+
// | old pc | <- top[0] // | old pc | <- top[0]
@ -113,4 +115,6 @@ nasal_builtin_table coroutine_native[] = {
{"__costatus", builtin_costatus}, {"__costatus", builtin_costatus},
{"__corun", builtin_corun}, {"__corun", builtin_corun},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -4,10 +4,14 @@
#include "nasal_gc.h" #include "nasal_gc.h"
#include "nasal_builtin.h" #include "nasal_builtin.h"
namespace nasal {
var builtin_cocreate(var*, gc&); var builtin_cocreate(var*, gc&);
var builtin_coresume(var*, gc&); var builtin_coresume(var*, gc&);
var builtin_coyield(var*, gc&); var builtin_coyield(var*, gc&);
var builtin_costatus(var*, gc&); var builtin_costatus(var*, gc&);
var builtin_corun(var*, gc&); var builtin_corun(var*, gc&);
extern nasal_builtin_table coroutine_native[]; extern nasal_builtin_table coroutine_native[];
}

View File

@ -1,11 +1,13 @@
#include "dylib_lib.h" #include "dylib_lib.h"
namespace nasal {
const auto dylib_type_name = "dylib"; const auto dylib_type_name = "dylib";
const auto func_addr_type_name = "faddr"; const auto func_addr_type_name = "faddr";
void dylib_destructor(void* ptr) { void dylib_destructor(void* ptr) {
#ifdef _WIN32 #ifdef _WIN32
FreeLibrary((HMODULE)ptr); FreeLibrary(static_cast<HMODULE>(ptr));
#else #else
dlclose(ptr); dlclose(ptr);
#endif #endif
@ -39,7 +41,10 @@ var builtin_dlopen(var* local, gc& ngc) {
ret.hash().elems["lib"] = lib; ret.hash().elems["lib"] = lib;
#ifdef _WIN32 #ifdef _WIN32
void* func = (void*)GetProcAddress((HMODULE)lib.obj().ptr, "get"); void* func = (void*)GetProcAddress(
static_cast<HMODULE>(lib.obj().ptr),
"get"
);
#else #else
void* func = dlsym(lib.obj().ptr, "get"); void* func = dlsym(lib.obj().ptr, "get");
#endif #endif
@ -47,7 +52,7 @@ 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
module_func_info* tbl = ((get_func_ptr)func)(); module_func_info* tbl = reinterpret_cast<get_func_ptr>(func)();
if (!tbl) { if (!tbl) {
return nas_err("dlopen", "failed to get module functions"); return nas_err("dlopen", "failed to get module functions");
} }
@ -78,7 +83,11 @@ var builtin_dlcallv(var* local, gc& ngc) {
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 ((module_func)fp.obj().ptr)(vec.data(), vec.size(), &ngc); return reinterpret_cast<module_func>(fp.obj().ptr)(
vec.data(),
vec.size(),
&ngc
);
} }
var builtin_dlcall(var* local, gc& ngc) { var builtin_dlcall(var* local, gc& ngc) {
@ -90,10 +99,11 @@ var builtin_dlcall(var* local, gc& ngc) {
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 ((module_func)fp.obj().ptr)( return reinterpret_cast<module_func>(fp.obj().ptr)(
local_frame_start, local_frame_start,
local_frame_size, local_frame_size,
&ngc); &ngc
);
} }
nasal_builtin_table dylib_lib_native[] = { nasal_builtin_table dylib_lib_native[] = {
@ -102,4 +112,6 @@ nasal_builtin_table dylib_lib_native[] = {
{"__dlcallv", builtin_dlcallv}, {"__dlcallv", builtin_dlcallv},
{"__dlcall", builtin_dlcall}, {"__dlcall", builtin_dlcall},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -11,6 +11,8 @@
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
namespace nasal {
void dylib_destructor(void*); void dylib_destructor(void*);
void func_addr_destructor(void*); void func_addr_destructor(void*);
@ -19,4 +21,6 @@ var builtin_dlclose(var*, gc&);
var builtin_dlcallv(var*, gc&); var builtin_dlcallv(var*, gc&);
var builtin_dlcall(var*, gc&); var builtin_dlcall(var*, gc&);
extern nasal_builtin_table dylib_lib_native[]; extern nasal_builtin_table dylib_lib_native[];
}

View File

@ -2,6 +2,8 @@
#include <fstream> #include <fstream>
namespace nasal {
var builtin_logprint(var* local, gc& ngc) { var builtin_logprint(var* local, gc& ngc) {
var level = local[1]; var level = local[1];
var elems = local[2]; var elems = local[2];
@ -21,7 +23,8 @@ var builtin_logprint(var* local, gc& ngc) {
default: default:
return nas_err("logprint", return nas_err("logprint",
"incorrect log level " + "incorrect log level " +
std::to_string(level.num())); std::to_string(level.num())
);
} }
for(auto& i : elems.vec().elems) { for(auto& i : elems.vec().elems) {
out << i << " "; out << i << " ";
@ -33,4 +36,6 @@ var builtin_logprint(var* local, gc& ngc) {
nasal_builtin_table flight_gear_native[] = { nasal_builtin_table flight_gear_native[] = {
{"_logprint", builtin_logprint}, {"_logprint", builtin_logprint},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -4,6 +4,8 @@
#include "nasal_gc.h" #include "nasal_gc.h"
#include "nasal_builtin.h" #include "nasal_builtin.h"
namespace nasal {
#define SG_LOG_BULK 1 #define SG_LOG_BULK 1
#define SG_LOG_DEBUG 2 #define SG_LOG_DEBUG 2
#define SG_LOG_INFO 3 #define SG_LOG_INFO 3
@ -16,3 +18,5 @@
var builtin_logprint(var*, gc&); var builtin_logprint(var*, gc&);
extern nasal_builtin_table flight_gear_native[]; extern nasal_builtin_table flight_gear_native[];
}

View File

@ -1,12 +1,14 @@
#include "io_lib.h" #include "io_lib.h"
namespace nasal {
const auto file_type_name = "file"; const auto file_type_name = "file";
void filehandle_destructor(void* ptr) { void filehandle_destructor(void* ptr) {
if ((FILE*)ptr==stdin) { if (static_cast<FILE*>(ptr)==stdin) {
return; return;
} }
fclose((FILE*)ptr); fclose(static_cast<FILE*>(ptr));
} }
var builtin_readfile(var* local, gc& ngc) { var builtin_readfile(var* local, gc& ngc) {
@ -90,7 +92,7 @@ var builtin_read(var* local, gc& ngc) {
if (!buff) { if (!buff) {
return nas_err("read", "malloc failed"); return nas_err("read", "malloc failed");
} }
f64 res = fread(buff,1,len.num(), (FILE*)fd.obj().ptr); f64 res = fread(buff, 1, len.num(), static_cast<FILE*>(fd.obj().ptr));
buf.str() = buff; buf.str() = buff;
buf.val.gcobj->unmut = true; buf.val.gcobj->unmut = true;
delete []buff; delete []buff;
@ -106,7 +108,12 @@ var builtin_write(var* local, gc& ngc) {
if (str.type!=vm_str) { if (str.type!=vm_str) {
return nas_err("write", "\"str\" must be string"); return nas_err("write", "\"str\" must be string");
} }
return var::num((f64)fwrite(str.str().c_str(), 1, str.str().length(), (FILE*)fd.obj().ptr)); return var::num(static_cast<f64>(fwrite(
str.str().c_str(),
1,
str.str().length(),
static_cast<FILE*>(fd.obj().ptr)
)));
} }
var builtin_seek(var* local, gc& ngc) { var builtin_seek(var* local, gc& ngc) {
@ -116,7 +123,11 @@ var builtin_seek(var* local, gc& ngc) {
if (!fd.objchk(file_type_name)) { if (!fd.objchk(file_type_name)) {
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(static_cast<f64>(fseek(
static_cast<FILE*>(fd.obj().ptr),
pos.num(),
whence.num()
)));
} }
var builtin_tell(var* local, gc& ngc) { var builtin_tell(var* local, gc& ngc) {
@ -124,7 +135,7 @@ var builtin_tell(var* local, gc& ngc) {
if (!fd.objchk(file_type_name)) { if (!fd.objchk(file_type_name)) {
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(static_cast<f64>(ftell(static_cast<FILE*>(fd.obj().ptr))));
} }
var builtin_readln(var* local, gc& ngc) { var builtin_readln(var* local, gc& ngc) {
@ -134,7 +145,7 @@ var builtin_readln(var* local, gc& ngc) {
} }
var str = ngc.alloc(vm_str); var str = ngc.alloc(vm_str);
char c; char c;
while((c = fgetc((FILE*)fd.obj().ptr))!=EOF) { while((c = fgetc(static_cast<FILE*>(fd.obj().ptr)))!=EOF) {
if (c=='\r') { if (c=='\r') {
continue; continue;
} }
@ -160,17 +171,17 @@ var builtin_stat(var* local, gc& ngc) {
} }
var ret = ngc.alloc(vm_vec); var ret = ngc.alloc(vm_vec);
ret.vec().elems = { ret.vec().elems = {
var::num((f64)buf.st_dev), var::num(static_cast<f64>(buf.st_dev)),
var::num((f64)buf.st_ino), var::num(static_cast<f64>(buf.st_ino)),
var::num((f64)buf.st_mode), var::num(static_cast<f64>(buf.st_mode)),
var::num((f64)buf.st_nlink), var::num(static_cast<f64>(buf.st_nlink)),
var::num((f64)buf.st_uid), var::num(static_cast<f64>(buf.st_uid)),
var::num((f64)buf.st_gid), var::num(static_cast<f64>(buf.st_gid)),
var::num((f64)buf.st_rdev), var::num(static_cast<f64>(buf.st_rdev)),
var::num((f64)buf.st_size), var::num(static_cast<f64>(buf.st_size)),
var::num((f64)buf.st_atime), var::num(static_cast<f64>(buf.st_atime)),
var::num((f64)buf.st_mtime), var::num(static_cast<f64>(buf.st_mtime)),
var::num((f64)buf.st_ctime) var::num(static_cast<f64>(buf.st_ctime))
}; };
return ret; return ret;
} }
@ -180,7 +191,7 @@ var builtin_eof(var* local, gc& ngc) {
if (!fd.objchk(file_type_name)) { if (!fd.objchk(file_type_name)) {
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(static_cast<f64>(feof(static_cast<FILE*>(fd.obj().ptr))));
} }
nasal_builtin_table io_lib_native[] = { nasal_builtin_table io_lib_native[] = {
@ -197,4 +208,6 @@ nasal_builtin_table io_lib_native[] = {
{"__stat", builtin_stat}, {"__stat", builtin_stat},
{"__eof", builtin_eof}, {"__eof", builtin_eof},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -10,6 +10,8 @@
#define F_OK 0 // fuck msc #define F_OK 0 // fuck msc
#endif #endif
namespace nasal {
void filehandle_destructor(void*); void filehandle_destructor(void*);
var builtin_readfile(var*, gc&); var builtin_readfile(var*, gc&);
@ -25,4 +27,6 @@ var builtin_readln(var*, gc&);
var builtin_stat(var*, gc&); var builtin_stat(var*, gc&);
var builtin_eof(var*, gc&); var builtin_eof(var*, gc&);
extern nasal_builtin_table io_lib_native[]; extern nasal_builtin_table io_lib_native[];
}

View File

@ -52,7 +52,7 @@ std::ostream& help(std::ostream& out) {
<< " -t, --time | show execute time.\n" << " -t, --time | show execute time.\n"
<< " -d, --detail | get detail info.\n" << " -d, --detail | get detail info.\n"
<< " -dbg, --debug | debug mode.\n" << " -dbg, --debug | debug mode.\n"
<< " --prof | show profiling result, available under debug mode.\n" << " --prof | show profiling result, available in debug mode.\n"
<< " --prof-all | show profiling result of all files," << " --prof-all | show profiling result of all files,"
<< "available under debug mode.\n" << "available under debug mode.\n"
<< "file:\n" << "file:\n"
@ -154,7 +154,8 @@ void execute(
debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL); debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL);
} else if (cmd&VM_TIME || cmd&VM_EXEC) { } else if (cmd&VM_TIME || cmd&VM_EXEC) {
auto runtime = std::unique_ptr<nasal::vm>(new nasal::vm); auto runtime = std::unique_ptr<nasal::vm>(new nasal::vm);
runtime->run(gen, ld, argv, cmd&VM_DETAIL); runtime->set_detail_report_info(cmd&VM_DETAIL);
runtime->run(gen, ld, argv);
} }
// get running time // get running time

View File

@ -1,5 +1,7 @@
#include "math_lib.h" #include "math_lib.h"
namespace nasal {
var builtin_pow(var* local, gc& ngc) { var builtin_pow(var* local, gc& ngc) {
var x = local[1]; var x = local[1];
var y = local[2]; var y = local[2];
@ -11,37 +13,37 @@ var builtin_pow(var* local, gc& ngc) {
var builtin_sin(var* local, gc& ngc) { var builtin_sin(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?sin(val.num()):std::nan("")); return var::num(val.type==vm_num? sin(val.num()):std::nan(""));
} }
var builtin_cos(var* local, gc& ngc) { var builtin_cos(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?cos(val.num()):std::nan("")); return var::num(val.type==vm_num? cos(val.num()):std::nan(""));
} }
var builtin_tan(var* local, gc& ngc) { var builtin_tan(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?tan(val.num()):std::nan("")); return var::num(val.type==vm_num? tan(val.num()):std::nan(""));
} }
var builtin_exp(var* local, gc& ngc) { var builtin_exp(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?exp(val.num()):std::nan("")); return var::num(val.type==vm_num? exp(val.num()):std::nan(""));
} }
var builtin_lg(var* local, gc& ngc) { var builtin_lg(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?log(val.num())/log(10.0):std::nan("")); return var::num(val.type==vm_num? log(val.num())/log(10.0):std::nan(""));
} }
var builtin_ln(var* local, gc& ngc) { var builtin_ln(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?log(val.num()):std::nan("")); return var::num(val.type==vm_num? log(val.num()):std::nan(""));
} }
var builtin_sqrt(var* local, gc& ngc) { var builtin_sqrt(var* local, gc& ngc) {
var val = local[1]; var val = local[1];
return var::num(val.type==vm_num?sqrt(val.num()):std::nan("")); return var::num(val.type==vm_num? sqrt(val.num()):std::nan(""));
} }
var builtin_atan2(var* local, gc& ngc) { var builtin_atan2(var* local, gc& ngc) {
@ -70,4 +72,6 @@ nasal_builtin_table math_lib_native[] = {
{"__atan2", builtin_atan2}, {"__atan2", builtin_atan2},
{"__isnan", builtin_isnan}, {"__isnan", builtin_isnan},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -4,6 +4,8 @@
#include "nasal_gc.h" #include "nasal_gc.h"
#include "nasal_builtin.h" #include "nasal_builtin.h"
namespace nasal {
var builtin_pow(var*, gc&); var builtin_pow(var*, gc&);
var builtin_sin(var*, gc&); var builtin_sin(var*, gc&);
var builtin_cos(var*, gc&); var builtin_cos(var*, gc&);
@ -15,4 +17,6 @@ var builtin_sqrt(var*, gc&);
var builtin_atan2(var*, gc&); var builtin_atan2(var*, gc&);
var builtin_isnan(var*, gc&); var builtin_isnan(var*, gc&);
extern nasal_builtin_table math_lib_native[]; extern nasal_builtin_table math_lib_native[];
}

View File

@ -11,6 +11,17 @@
#include <cmath> #include <cmath>
#include <vector> #include <vector>
using i32 = std::int32_t;
using i64 = std::int64_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
using f64 = double;
namespace nasal {
bool is_windows(); bool is_windows();
bool is_linux(); bool is_linux();
bool is_macos(); bool is_macos();
@ -23,14 +34,7 @@ bool is_ia64();
bool is_powerpc(); bool is_powerpc();
bool is_superh(); bool is_superh();
using i32 = std::int32_t;
using i64 = std::int64_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
using f64 = double;
const u32 STACK_DEPTH = 4096; const u32 STACK_DEPTH = 4096;
@ -50,4 +54,6 @@ i32 utf8_hdchk(const char);
std::string chrhex(const char); std::string chrhex(const char);
std::string rawstr(const std::string&, const usize maxlen=0); std::string rawstr(const std::string&, const usize maxlen=0);
#include "nasal_gc.h" }
#include "nasal_gc.h"

View File

@ -1,6 +1,8 @@
#include "nasal_builtin.h" #include "nasal_builtin.h"
#include <chrono> #include <chrono>
namespace nasal {
var builtin_print(var* local, gc& ngc) { var builtin_print(var* local, gc& ngc) {
for(auto& i : local[1].vec().elems) { for(auto& i : local[1].vec().elems) {
std::cout << i; std::cout << i;
@ -49,7 +51,7 @@ var builtin_setsize(var* local, gc& ngc) {
if (size.type!=vm_num || size.num()<0) { if (size.type!=vm_num || size.num()<0) {
return nil; return nil;
} }
vec.vec().elems.resize((i64)size.num(), nil); vec.vec().elems.resize(static_cast<i64>(size.num()), nil);
return nil; return nil;
} }
@ -58,7 +60,7 @@ var builtin_system(var* local, gc& ngc) {
if (str.type!=vm_str) { if (str.type!=vm_str) {
return var::num(-1); return var::num(-1);
} }
return var::num((f64)system(str.str().c_str())); return var::num(static_cast<f64>(system(str.str().c_str())));
} }
var builtin_input(var* local, gc& ngc) { var builtin_input(var* local, gc& ngc) {
@ -117,7 +119,7 @@ var builtin_rand(var* local, gc& ngc) {
return nas_err("rand", "\"seed\" must be nil or number"); return nas_err("rand", "\"seed\" must be nil or number");
} }
if (val.type==vm_num) { if (val.type==vm_num) {
srand((u32)val.num()); srand(static_cast<u32>(val.num()));
return nil; return nil;
} }
f64 num = 0; f64 num = 0;
@ -132,7 +134,8 @@ var builtin_id(var* local, gc& ngc) {
std::stringstream ss; std::stringstream ss;
ss << "0"; ss << "0";
if (val.type>vm_num) { if (val.type>vm_num) {
ss << "x" << std::hex << (u64)val.val.gcobj << std::dec; ss << "x" << std::hex;
ss << reinterpret_cast<u64>(val.val.gcobj) << std::dec;
} }
return ngc.newstr(ss.str()); return ngc.newstr(ss.str());
} }
@ -142,7 +145,7 @@ var builtin_int(var* local, gc& ngc) {
if (val.type!=vm_num && val.type!=vm_str) { if (val.type!=vm_num && val.type!=vm_str) {
return nil; return nil;
} }
return var::num(f64((i32)val.tonum())); return var::num(static_cast<f64>(static_cast<i32>(val.tonum())));
} }
var builtin_floor(var* local, gc& ngc) { var builtin_floor(var* local, gc& ngc) {
@ -202,7 +205,7 @@ var builtin_time(var* local, gc& ngc) {
return nas_err("time", "\"begin\" must be number"); return nas_err("time", "\"begin\" must be number");
} }
time_t begin = (time_t)val.num(); time_t begin = (time_t)val.num();
return var::num((f64)time(&begin)); return var::num(static_cast<f64>(time(&begin)));
} }
var builtin_contains(var* local, gc& ngc) { var builtin_contains(var* local, gc& ngc) {
@ -259,9 +262,9 @@ var builtin_find(var* local, gc& ngc) {
var haystack = local[2]; var haystack = local[2];
usize pos = haystack.tostr().find(needle.tostr()); usize pos = haystack.tostr().find(needle.tostr());
if (pos==std::string::npos) { if (pos==std::string::npos) {
return var::num((f64)-1); return var::num(-1.0);
} }
return var::num((f64)pos); return var::num(static_cast<f64>(pos));
} }
var builtin_type(var* local, gc& ngc) { var builtin_type(var* local, gc& ngc) {
@ -331,7 +334,7 @@ var builtin_right(var* local, gc& ngc) {
if (len.type!=vm_num) { if (len.type!=vm_num) {
return nas_err("right", "\"length\" must be number"); return nas_err("right", "\"length\" must be number");
} }
i32 length = (i32)len.num(); i32 length = static_cast<i32>(len.num());
i32 srclen = str.str().length(); i32 srclen = str.str().length();
if (length>srclen) { if (length>srclen) {
length = srclen; length = srclen;
@ -348,7 +351,10 @@ var builtin_cmp(var* local, gc& ngc) {
if (a.type!=vm_str || b.type!=vm_str) { if (a.type!=vm_str || b.type!=vm_str) {
return nas_err("cmp", "\"a\" and \"b\" must be string"); return nas_err("cmp", "\"a\" and \"b\" must be string");
} }
return var::num((f64)strcmp(a.str().c_str(), b.str().c_str())); return var::num(static_cast<f64>(strcmp(
a.str().c_str(),
b.str().c_str()
)));
} }
var builtin_chr(var* local, gc& ngc) { var builtin_chr(var* local, gc& ngc) {
@ -606,7 +612,7 @@ var builtin_ghosttype(var* local, gc& ngc) {
} }
const auto& name = arg.obj().get_ghost_name(); const auto& name = arg.obj().get_ghost_name();
if (!name.length()) { if (!name.length()) {
return var::num((u64)arg.obj().ptr); return var::num(reinterpret_cast<u64>(arg.obj().ptr));
} }
return ngc.newstr(name); return ngc.newstr(name);
} }
@ -654,4 +660,6 @@ nasal_builtin_table builtin[] = {
{"__logtime", builtin_logtime}, {"__logtime", builtin_logtime},
{"__ghosttype", builtin_ghosttype}, {"__ghosttype", builtin_ghosttype},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -22,6 +22,8 @@
#define environ (*_NSGetEnviron()) #define environ (*_NSGetEnviron())
#endif #endif
namespace nasal {
var builtin_print(var*, gc&); var builtin_print(var*, gc&);
var builtin_println(var*, gc&); var builtin_println(var*, gc&);
var builtin_exit(var*, gc&); var builtin_exit(var*, gc&);
@ -75,3 +77,5 @@ struct nasal_builtin_table {
}; };
extern nasal_builtin_table builtin[]; extern nasal_builtin_table builtin[];
}

View File

@ -237,7 +237,8 @@ void dbg::run(
const std::vector<std::string>& argv, const std::vector<std::string>& argv,
bool profile, bool profile,
bool show_all_prof_result) { bool show_all_prof_result) {
verbose = true;
set_detail_report_info(true);
do_profiling = profile || show_all_prof_result; do_profiling = profile || show_all_prof_result;
const auto& file_list = linker.get_file_list(); const auto& file_list = linker.get_file_list();

View File

@ -75,10 +75,12 @@ std::ostream& reset(std::ostream& s) {
void flstream::load(const std::string& f) { void flstream::load(const std::string& f) {
if (file==f) { // don't need to load a loaded file if (file==f) { // don't need to load a loaded file
return; return;
} else {
file = f;
} }
// update file name
file = f;
// REPL: load from memory
if (repl::info::instance()->in_repl_mode && if (repl::info::instance()->in_repl_mode &&
repl::info::instance()->repl_file_name==file) { repl::info::instance()->repl_file_name==file) {
const auto& source = repl::info::instance()->repl_file_source; const auto& source = repl::info::instance()->repl_file_source;
@ -134,15 +136,16 @@ void error::err(
const usize maxlen = std::to_string(loc.end_line).length(); const usize maxlen = std::to_string(loc.end_line).length();
const std::string iden = identation(maxlen); const std::string iden = identation(maxlen);
for(u32 line=loc.begin_line; line<=loc.end_line; ++line) { for(u32 line = loc.begin_line; line<=loc.end_line; ++line) {
// skip line 0
if (!line) { if (!line) {
continue; continue;
} }
if (loc.begin_line<line && line<loc.end_line) { if (loc.begin_line<line && line<loc.end_line) {
if (line==loc.begin_line+1) { if (line==loc.begin_line+1) {
std::cerr << cyan << iden << " | " << reset << "...\n" std::cerr << cyan << iden << " | " << reset << "...\n";
<< cyan << iden << " | " << reset << "\n"; std::cerr << cyan << iden << " | " << reset << "\n";
} }
continue; continue;
} }
@ -152,7 +155,12 @@ void error::err(
continue; continue;
} }
const std::string& code=res[line-1]; // line out of range
if (line-1>=res.size()) {
continue;
}
const auto& code = res[line-1];
std::cerr << cyan << leftpad(line, maxlen) << " | " << reset << code << "\n"; std::cerr << cyan << leftpad(line, maxlen) << " | " << reset << code << "\n";
// output underline // output underline
std::cerr << cyan << iden << " | " << reset; std::cerr << cyan << iden << " | " << reset;
@ -160,7 +168,7 @@ void error::err(
for(u32 i = 0; i<loc.begin_column; ++i) { for(u32 i = 0; i<loc.begin_column; ++i) {
std::cerr << char(" \t"[code[i]=='\t']); std::cerr << char(" \t"[code[i]=='\t']);
} }
for(u32 i = loc.begin_column ;i<loc.end_column; ++i) { for(u32 i = loc.begin_column; i<loc.end_column; ++i) {
std::cerr << red << (code[i]=='\t'? "^^^^":"^") << reset; std::cerr << red << (code[i]=='\t'? "^^^^":"^") << reset;
} }
} else if (line==loc.begin_line) { } else if (line==loc.begin_line) {

View File

@ -1,5 +1,7 @@
#include "nasal_gc.h" #include "nasal_gc.h"
namespace nasal {
var nas_vec::get_val(const i32 n) { var nas_vec::get_val(const i32 n) {
i32 size = elems.size(); i32 size = elems.size();
if (n<-size || n>=size) { if (n<-size || n>=size) {
@ -128,7 +130,8 @@ void nas_ghost::clear() {
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) { std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
out << "<object " << ghost.get_ghost_name(); out << "<object " << ghost.get_ghost_name();
out << " at 0x" << std::hex << (u64)ghost.ptr << std::dec << ">"; out << " at 0x" << std::hex;
out << reinterpret_cast<u64>(ghost.ptr) << std::dec << ">";
return out; return out;
} }
@ -152,7 +155,8 @@ void nas_co::clear() {
} }
std::ostream& operator<<(std::ostream& out, const nas_co& co) { std::ostream& operator<<(std::ostream& out, const nas_co& co) {
out << "<coroutine at 0x" << std::hex << u64(&co) << std::dec << ">"; out << "<coroutine at 0x" << std::hex;
out << reinterpret_cast<u64>(&co) << std::dec << ">";
return out; return out;
} }
@ -265,11 +269,11 @@ bool var::objchk(const std::string& name) {
} }
var var::none() { var var::none() {
return {vm_none, (u32)0}; return {vm_none, static_cast<u32>(0)};
} }
var var::nil() { var var::nil() {
return {vm_nil, (u32)0}; return {vm_nil, static_cast<u32>(0)};
} }
var var::ret(u32 pc) { var var::ret(u32 pc) {
@ -533,11 +537,8 @@ void gc::extend(u8 type) {
void gc::init( void gc::init(
const std::vector<std::string>& s, const std::vector<std::string>& argv) { const std::vector<std::string>& s, const std::vector<std::string>& argv) {
// initialize function register
rctx->funcr = nil;
worktime = 0;
// initialize counters // initialize counters
worktime = 0;
for(u8 i = 0; i<gc_type_size; ++i) { for(u8 i = 0; i<gc_type_size; ++i) {
size[i] = gcnt[i] = acnt[i] = 0; size[i] = gcnt[i] = acnt[i] = 0;
} }
@ -716,4 +717,6 @@ void gc::ctxreserve() {
var nas_err(const std::string& error_function_name, const std::string& info) { var nas_err(const std::string& error_function_name, const std::string& info) {
std::cerr << "[vm] " << error_function_name << ": " << info << "\n"; std::cerr << "[vm] " << error_function_name << ": " << info << "\n";
return var::none(); return var::none();
} }
}

View File

@ -32,6 +32,8 @@
#include "nasal.h" #include "nasal.h"
namespace nasal {
enum vm_type:u8 { enum vm_type:u8 {
/* none-gc object */ /* none-gc object */
vm_none = 0, vm_none = 0,
@ -298,9 +300,9 @@ struct gc {
var temp = nil; var temp = nil;
/* constants and memory pool */ /* constants and memory pool */
std::vector<var> strs; // reserved address for const vm_str std::vector<var> strs = {}; // reserved address for const vm_str
std::vector<var> env_argv; // command line arguments std::vector<var> env_argv = {}; // command line arguments
std::vector<nas_val*> memory; // gc memory std::vector<nas_val*> memory; // gc memory
std::vector<nas_val*> unused[gc_type_size]; // gc free list std::vector<nas_val*> unused[gc_type_size]; // gc free list
/* heap increase size */ /* heap increase size */
@ -388,3 +390,5 @@ struct module_func_info {
// module function "get" type // module function "get" type
typedef module_func_info* (*get_func_ptr)(); typedef module_func_info* (*get_func_ptr)();
}

View File

@ -330,6 +330,7 @@ const error& lexer::scan(const std::string& file) {
line = 1; line = 1;
column = 0; column = 0;
ptr = 0; ptr = 0;
toks = {};
open(file); open(file);
while(ptr<res.size()) { while(ptr<res.size()) {

View File

@ -1,5 +1,7 @@
#include "nasal.h" #include "nasal.h"
namespace nasal {
bool is_windows() { bool is_windows() {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
return true; return true;
@ -227,4 +229,6 @@ std::string rawstr(const std::string& str, const usize maxlen) {
ret = ret.substr(0,maxlen)+"..."; ret = ret.substr(0,maxlen)+"...";
} }
return ret; return ret;
} }
}

View File

@ -1,5 +1,7 @@
#include "nasal_opcode.h" #include "nasal_opcode.h"
namespace nasal {
const char* opname[] = { const char* opname[] = {
"exit ", "intg ", "intl ", "loadg ", "exit ", "intg ", "intl ", "loadg ",
"loadl ", "loadu ", "pnum ", "pnil ", "loadl ", "loadu ", "pnum ", "pnil ",
@ -45,7 +47,7 @@ void codestream::dump(std::ostream& out) const {
auto num = code.num; auto num = code.num;
out << hex << "0x" out << hex << "0x"
<< setw(6) << setfill('0') << index << " " << setw(6) << setfill('0') << index << " "
<< setw(2) << setfill('0') << (u32)op << " " << setw(2) << setfill('0') << static_cast<u32>(op) << " "
<< setw(2) << setfill('0') << ((num>>16)&0xff) << " " << setw(2) << setfill('0') << ((num>>16)&0xff) << " "
<< setw(2) << setfill('0') << ((num>>8)&0xff) << " " << setw(2) << setfill('0') << ((num>>8)&0xff) << " "
<< setw(2) << setfill('0') << (num&0xff) << " " << setw(2) << setfill('0') << (num&0xff) << " "
@ -90,7 +92,8 @@ void codestream::dump(std::ostream& out) const {
out << hex << "0x" << num << dec; break; out << hex << "0x" << num << dec; break;
case op_callb: case op_callb:
out << hex << "0x" << num << " <" << natives[num].name out << hex << "0x" << num << " <" << natives[num].name
<< "@0x" << (u64)natives[num].func << dec << ">"; break; << "@0x" << reinterpret_cast<u64>(natives[num].func)
<< dec << ">"; break;
case op_upval: case op_mupval: case op_upval: case op_mupval:
case op_loadu: case op_loadu:
out << hex << "0x" << ((num>>16)&0xffff) out << hex << "0x" << ((num>>16)&0xffff)
@ -115,4 +118,6 @@ void codestream::dump(std::ostream& out) const {
std::ostream& operator<<(std::ostream& out, const codestream& ins) { std::ostream& operator<<(std::ostream& out, const codestream& ins) {
ins.dump(out); ins.dump(out);
return out; return out;
}
} }

View File

@ -5,6 +5,8 @@
#include <iostream> #include <iostream>
namespace nasal {
enum op_code_type:u8 { enum op_code_type:u8 {
op_exit, // stop the virtual machine op_exit, // stop the virtual machine
op_intg, // init global scope op_intg, // init global scope
@ -126,4 +128,6 @@ public:
std::ostream& operator<<(std::ostream&, const codestream&); std::ostream& operator<<(std::ostream&, const codestream&);
extern const char* opname[]; extern const char* opname[];
}

View File

@ -20,19 +20,10 @@ void vm::init(
/* set native functions */ /* set native functions */
native = natives; native = natives;
/* set canary and program counter */ /* set context and global */
ctx.pc = 0; if (!is_repl_mode || first_exec_flag) {
ctx.localr = nullptr; context_and_global_init();
ctx.memr = nullptr; first_exec_flag = false;
ctx.funcr = nil;
ctx.upvalr = nil;
ctx.canary = ctx.stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1]
ctx.top = ctx.stack; // nothing is on stack
/* clear main stack and global */
for(u32 i = 0; i<STACK_DEPTH; ++i) {
ctx.stack[i] = nil;
global[i] = nil;
} }
/* init gc */ /* init gc */
@ -52,41 +43,64 @@ void vm::init(
arg_instance.vec().elems = ngc.env_argv; arg_instance.vec().elems = ngc.env_argv;
} }
void vm::context_and_global_init() {
/* set canary and program counter */
ctx.pc = 0;
ctx.localr = nullptr;
ctx.memr = nullptr;
ctx.funcr = nil;
ctx.upvalr = nil;
/* set canary = stack[STACK_DEPTH-1] */
ctx.canary = ctx.stack+STACK_DEPTH-1;
/* nothing is on stack */
ctx.top = ctx.stack;
/* clear main stack and global */
for(u32 i = 0; i<STACK_DEPTH; ++i) {
ctx.stack[i] = nil;
global[i] = nil;
}
}
void vm::valinfo(var& val) { void vm::valinfo(var& val) {
const nas_val* p = val.val.gcobj; const auto p = reinterpret_cast<u64>(val.val.gcobj);
switch(val.type) { switch(val.type) {
case vm_none: std::clog << "| null |"; break; case vm_none: std::clog << "| null |"; break;
case vm_ret: std::clog << "| pc | 0x" << std::hex case vm_ret: std::clog << "| pc | 0x" << std::hex
<< val.ret() << std::dec; break; << val.ret() << std::dec; break;
case vm_addr: std::clog << "| addr | 0x" << std::hex case vm_addr: std::clog << "| addr | 0x" << std::hex
<< (u64)val.addr() << std::dec; break; << reinterpret_cast<u64>(val.addr())
<< std::dec; break;
case vm_cnt: std::clog << "| cnt | " << val.cnt(); break; case vm_cnt: std::clog << "| cnt | " << val.cnt(); break;
case vm_nil: std::clog << "| nil |"; break; case vm_nil: std::clog << "| nil |"; break;
case vm_num: std::clog << "| num | " << val.num(); break; case vm_num: std::clog << "| num | " << val.num(); break;
case vm_str: std::clog << "| str | <0x" << std::hex << (u64)p case vm_str: std::clog << "| str | <0x" << std::hex << p
<< "> " << rawstr(val.str(), 16) << "> " << rawstr(val.str(), 16)
<< std::dec; break; << std::dec; break;
case vm_func: std::clog << "| func | <0x" << std::hex << (u64)p case vm_func: std::clog << "| func | <0x" << std::hex << p
<< "> entry:0x" << val.func().entry << "> entry:0x" << val.func().entry
<< std::dec; break; << std::dec; break;
case vm_upval:std::clog << "| upval| <0x" << std::hex << (u64)p case vm_upval:std::clog << "| upval| <0x" << std::hex << p
<< std::dec << "> [" << val.upval().size << std::dec << "> [" << val.upval().size
<< " val]"; break; << " val]"; break;
case vm_vec: std::clog << "| vec | <0x" << std::hex << (u64)p case vm_vec: std::clog << "| vec | <0x" << std::hex << p
<< std::dec << "> [" << val.vec().size() << std::dec << "> [" << val.vec().size()
<< " val]"; break; << " val]"; break;
case vm_hash: std::clog << "| hash | <0x" << std::hex << (u64)p case vm_hash: std::clog << "| hash | <0x" << std::hex << p
<< std::dec << "> {" << val.hash().size() << std::dec << "> {" << val.hash().size()
<< " val}"; break; << " val}"; break;
case vm_obj: std::clog << "| obj | <0x" << std::hex << (u64)p case vm_obj: std::clog << "| obj | <0x" << std::hex << p
<< "> obj:0x" << (u64)val.obj().ptr << "> obj:0x"
<< reinterpret_cast<u64>(val.obj().ptr)
<< std::dec; break; << std::dec; break;
case vm_co: std::clog << "| co | <0x" << std::hex << (u64)p case vm_co: std::clog << "| co | <0x" << std::hex << p
<< std::dec << "> coroutine"; break; << std::dec << "> coroutine"; break;
case vm_map: std::clog << "| nmspc| <0x" << std::hex << (u64)p case vm_map: std::clog << "| nmspc| <0x" << std::hex << p
<< std::dec << "> namespace [" << std::dec << "> namespace ["
<< val.map().mapper.size() << " val]"; break; << val.map().mapper.size() << " val]"; break;
default: std::clog << "| err | <0x" << std::hex << (u64)p default: std::clog << "| err | <0x" << std::hex << p
<< std::dec << "> unknown object"; break; << std::dec << "> unknown object"; break;
} }
std::clog << "\n"; std::clog << "\n";
@ -128,13 +142,13 @@ void vm::traceback() {
void vm::stackinfo(const u32 limit = 10) { void vm::stackinfo(const u32 limit = 10) {
var* top = ctx.top; var* top = ctx.top;
var* bottom = ctx.stack; var* bottom = ctx.stack;
std::clog << "stack (0x" << std::hex << (u64)bottom << std::dec; std::clog << "stack (0x" << std::hex << reinterpret_cast<u64>(bottom);
std::clog << ", limit " << limit << ", total "; std::clog << std::dec << ", limit " << limit << ", total ";
std::clog << (top<bottom? 0:(i64)(top-bottom+1)) << ")\n"; std::clog << (top<bottom? 0:static_cast<i64>(top-bottom+1)) << ")\n";
for(u32 i = 0; i<limit && top>=bottom; ++i, --top) { for(u32 i = 0; i<limit && top>=bottom; ++i, --top) {
std::clog << " 0x" << std::hex std::clog << " 0x" << std::hex
<< std::setw(6) << std::setfill('0') << std::setw(6) << std::setfill('0')
<< (u64)(top-bottom) << std::dec << static_cast<u64>(top-bottom) << std::dec
<< " "; << " ";
valinfo(top[0]); valinfo(top[0]);
} }
@ -144,11 +158,16 @@ void vm::reginfo() {
std::clog << "registers (" << (ngc.cort? "coroutine":"main") std::clog << "registers (" << (ngc.cort? "coroutine":"main")
<< ")\n" << std::hex << ")\n" << std::hex
<< " [pc ] | pc | 0x" << ctx.pc << "\n" << " [pc ] | pc | 0x" << ctx.pc << "\n"
<< " [global] | addr | 0x" << (u64)global << "\n" << " [global] | addr | 0x"
<< " [local ] | addr | 0x" << (u64)ctx.localr << "\n" << reinterpret_cast<u64>(global) << "\n"
<< " [memr ] | addr | 0x" << (u64)ctx.memr << "\n" << " [local ] | addr | 0x"
<< " [canary] | addr | 0x" << (u64)ctx.canary << "\n" << reinterpret_cast<u64>(ctx.localr) << "\n"
<< " [top ] | addr | 0x" << (u64)ctx.top << "\n" << " [memr ] | addr | 0x"
<< reinterpret_cast<u64>(ctx.memr) << "\n"
<< " [canary] | addr | 0x"
<< reinterpret_cast<u64>(ctx.canary) << "\n"
<< " [top ] | addr | 0x"
<< reinterpret_cast<u64>(ctx.top) << "\n"
<< std::dec; << std::dec;
std::clog << " [funcr ] "; valinfo(ctx.funcr); std::clog << " [funcr ] "; valinfo(ctx.funcr);
std::clog << " [upval ] "; valinfo(ctx.upvalr); std::clog << " [upval ] "; valinfo(ctx.upvalr);
@ -159,7 +178,7 @@ void vm::gstate() {
return; return;
} }
std::clog << "global (0x" << std::hex std::clog << "global (0x" << std::hex
<< (u64)global << ")\n" << std::dec; << reinterpret_cast<u64>(global) << ")\n" << std::dec;
for(usize i = 0; i<global_size; ++i) { for(usize i = 0; i<global_size; ++i) {
std::clog << " 0x" << std::hex << std::setw(6) std::clog << " 0x" << std::hex << std::setw(6)
<< std::setfill('0') << i << std::dec << std::setfill('0') << i << std::dec
@ -173,8 +192,8 @@ void vm::lstate() {
return; return;
} }
const u32 lsize = ctx.funcr.func().lsize; const u32 lsize = ctx.funcr.func().lsize;
std::clog << "local (0x" << std::hex << (u64)ctx.localr std::clog << "local (0x" << std::hex << reinterpret_cast<u64>(ctx.localr)
<< " <+" << (u64)(ctx.localr-ctx.stack) << " <+" << static_cast<u64>(ctx.localr-ctx.stack)
<< ">)\n" << std::dec; << ">)\n" << std::dec;
for(u32 i = 0; i<lsize; ++i) { for(u32 i = 0; i<lsize; ++i) {
std::clog << " 0x" << std::hex << std::setw(6) std::clog << " 0x" << std::hex << std::setw(6)
@ -233,9 +252,8 @@ void vm::die(const std::string& str) {
void vm::run( void vm::run(
const codegen& gen, const codegen& gen,
const linker& linker, const linker& linker,
const std::vector<std::string>& argv, const std::vector<std::string>& argv
const bool detail) { ) {
verbose = detail;
init(gen.strs(), gen.nums(), gen.natives(), init(gen.strs(), gen.nums(), gen.natives(),
gen.codes(), gen.globals(), linker.get_file_list(), argv); gen.codes(), gen.globals(), linker.get_file_list(), argv);
#ifndef _MSC_VER #ifndef _MSC_VER
@ -334,11 +352,13 @@ void vm::run(
#endif #endif
vmexit: vmexit:
if (detail) { if (verbose) {
ngc.info(); ngc.info();
} }
ngc.clear();
imm.clear(); imm.clear();
if (!is_repl_mode) {
ngc.clear();
}
return; return;
#ifndef _MSC_VER #ifndef _MSC_VER

View File

@ -38,6 +38,10 @@ protected:
const std::string* files = nullptr; // file name list const std::string* files = nullptr; // file name list
const opcode* bytecode = nullptr; // bytecode buffer address const opcode* bytecode = nullptr; // bytecode buffer address
/* variables for repl mode */
bool is_repl_mode = false;
bool first_exec_flag = true;
/* vm initializing function */ /* vm initializing function */
void init( void init(
const std::vector<std::string>&, const std::vector<std::string>&,
@ -46,7 +50,9 @@ protected:
const std::vector<opcode>&, const std::vector<opcode>&,
const std::unordered_map<std::string, i32>&, const std::unordered_map<std::string, i32>&,
const std::vector<std::string>&, const std::vector<std::string>&,
const std::vector<std::string>&); const std::vector<std::string>&
);
void context_and_global_init();
/* debug functions */ /* debug functions */
bool verbose = false; bool verbose = false;
@ -167,8 +173,13 @@ public:
void run( void run(
const codegen&, const codegen&,
const linker&, const linker&,
const std::vector<std::string>&, const std::vector<std::string>&
const bool); );
/* set detail report info flag */
void set_detail_report_info(bool flag) {verbose = flag;}
/* set repl mode flag */
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
}; };
inline bool vm::cond(var& val) { inline bool vm::cond(var& val) {
@ -285,7 +296,7 @@ inline void vm::o_lnot() {
case vm_str: { case vm_str: {
const f64 num = str2num(val.str().c_str()); const f64 num = str2num(val.str().c_str());
if (std::isnan(num)) { if (std::isnan(num)) {
ctx.top[0] = var::num((f64)val.str().empty()); ctx.top[0] = var::num(static_cast<f64>(val.str().empty()));
} else { } else {
ctx.top[0] = num? zero:one; ctx.top[0] = num? zero:one;
} }

View File

@ -21,7 +21,7 @@ void repl::update_temp_file() {
for(const auto& i : source) { for(const auto& i : source) {
content += i + "\n"; content += i + "\n";
} }
info::instance()->repl_file_source = content; info::instance()->repl_file_source = content + " ";
} }
bool repl::check_need_more_input() { bool repl::check_need_more_input() {
@ -49,6 +49,7 @@ bool repl::check_need_more_input() {
if (in_curve<=0 && in_bracket<=0 && in_brace<=0) { if (in_curve<=0 && in_bracket<=0 && in_brace<=0) {
break; break;
} }
auto line = readline("... "); auto line = readline("... ");
source.back() += "\n" + line; source.back() += "\n" + line;
} }
@ -56,27 +57,26 @@ bool repl::check_need_more_input() {
} }
void repl::help() { void repl::help() {
std::cout << ".h, .help | show help\n"; std::cout << ".h, .help | show help\n";
std::cout << ".e, .exit | quit the REPL\n"; std::cout << ".e, .exit | quit the REPL\n";
std::cout << ".q, .quit | quit the REPL\n"; std::cout << ".q, .quit | quit the REPL\n";
std::cout << ".c, .clear | clear the screen\n"; std::cout << ".c, .clear | clear the screen\n";
std::cout << ".s, .source | show source code\n";
std::cout << "\n"; std::cout << "\n";
} }
bool repl::run() { bool repl::run() {
update_temp_file();
using clk = std::chrono::high_resolution_clock; using clk = std::chrono::high_resolution_clock;
const auto den = clk::duration::period::den; const auto den = clk::duration::period::den;
auto start = clk::now();
auto nasal_lexer = std::unique_ptr<lexer>(new lexer); auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
auto nasal_parser = std::unique_ptr<parse>(new parse); auto nasal_parser = std::unique_ptr<parse>(new parse);
auto nasal_linker = std::unique_ptr<linker>(new linker); auto nasal_linker = std::unique_ptr<linker>(new linker);
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer); auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
auto nasal_codegen = std::unique_ptr<codegen>(new codegen); auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
auto nasal_runtime = std::unique_ptr<vm>(new vm);
auto start = clk::now();
update_temp_file();
if (nasal_lexer->scan("<nasal-repl>").geterr()) { if (nasal_lexer->scan("<nasal-repl>").geterr()) {
return false; return false;
} }
@ -89,14 +89,18 @@ bool repl::run() {
return false; return false;
} }
nasal_opt->do_optimization(nasal_parser->tree()); // nasal_opt->do_optimization(nasal_parser->tree());
if (nasal_codegen->compile(*nasal_parser, *nasal_linker).geterr()) { if (nasal_codegen->compile(*nasal_parser, *nasal_linker).geterr()) {
return false; return false;
} }
auto end = clk::now(); auto end = clk::now();
std::clog << "[compile time: " << (end-start).count()*1000.0/den << " ms]\n"; std::clog << "[compile time: " << (end-start).count()*1000.0/den << " ms]\n";
nasal_runtime->run(*nasal_codegen, *nasal_linker, {}, false);
// TODO: gc init stage in this run may cause memory leak,
// because constant strings will be generated again.
// but we could not delete old strings, they maybe still on stack.
runtime.run(*nasal_codegen, *nasal_linker, {});
return true; return true;
} }
@ -114,7 +118,9 @@ void repl::execute() {
continue; continue;
} }
if (line == ".e" || line == ".exit" || line == ".q" || line == ".quit") { if (line == ".e" || line == ".exit") {
break;
} else if (line == ".q" || line == ".quit") {
break; break;
} else if (line == ".h" || line == ".help") { } else if (line == ".h" || line == ".help") {
help(); help();
@ -122,6 +128,10 @@ void repl::execute() {
} else if (line == ".c" || line == ".clear") { } else if (line == ".c" || line == ".clear") {
std::cout << "\033c"; std::cout << "\033c";
continue; continue;
} else if (line == ".s" || line == ".source") {
update_temp_file();
std::cout << info::instance()->repl_file_source << "\n";
continue;
} else if (line[0] == "."[0]) { } else if (line[0] == "."[0]) {
std::cout << "no such command \"" << line; std::cout << "no such command \"" << line;
std::cout << "\", input \".help\" for help\n"; std::cout << "\", input \".help\" for help\n";

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "nasal.h" #include "nasal.h"
#include "nasal_vm.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -26,6 +27,7 @@ struct info {
class repl { class repl {
private: private:
std::vector<std::string> source; std::vector<std::string> source;
vm runtime;
private: private:
std::string readline(std::string); std::string readline(std::string);
@ -35,6 +37,12 @@ private:
bool run(); bool run();
public: public:
repl() {
// set repl mode
runtime.set_repl_mode_flag(true);
// no detail report info
runtime.set_detail_report_info(false);
}
void execute(); void execute();
}; };

View File

@ -1,10 +1,12 @@
#include "unix_lib.h" #include "unix_lib.h"
namespace nasal {
const auto dir_type_name = "dir"; const auto dir_type_name = "dir";
void dir_entry_destructor(void* ptr) { void dir_entry_destructor(void* ptr) {
#ifndef _MSC_VER #ifndef _MSC_VER
closedir((DIR*)ptr); closedir(static_cast<DIR*>(ptr));
#else #else
FindClose(ptr); FindClose(ptr);
#endif #endif
@ -17,11 +19,11 @@ var builtin_pipe(var* local, gc& ngc) {
if (pipe(fd)==-1) { if (pipe(fd)==-1) {
return nas_err("pipe", "failed to create pipe"); return nas_err("pipe", "failed to create pipe");
} }
res.vec().elems.push_back(var::num((f64)fd[0])); res.vec().elems.push_back(var::num(static_cast<f64>(fd[0])));
res.vec().elems.push_back(var::num((f64)fd[1])); res.vec().elems.push_back(var::num(static_cast<f64>(fd[1])));
return res; return res;
#endif #endif
return nas_err("pipe", "not supported"); return nas_err("pipe", "not supported on windows");
} }
var builtin_fork(var* local, gc& ngc) { var builtin_fork(var* local, gc& ngc) {
@ -30,9 +32,9 @@ var builtin_fork(var* local, gc& ngc) {
if (res<0) { if (res<0) {
return nas_err("fork", "failed to fork a process"); return nas_err("fork", "failed to fork a process");
} }
return var::num((f64)res); return var::num(static_cast<f64>(res));
#endif #endif
return nas_err("fork", "not supported"); return nas_err("fork", "not supported on windows");
} }
var builtin_waitpid(var* local, gc& ngc) { var builtin_waitpid(var* local, gc& ngc) {
@ -42,14 +44,14 @@ var builtin_waitpid(var* local, gc& ngc) {
return nas_err("waitpid", "pid and nohang must be number"); return nas_err("waitpid", "pid and nohang must be number");
} }
#ifndef _WIN32 #ifndef _WIN32
i32 ret_pid,status; i32 ret_pid, status;
ret_pid = waitpid(pid.num(),&status,nohang.num()==0? 0:WNOHANG); ret_pid = waitpid(pid.num(), &status, nohang.num()==0? 0:WNOHANG);
var vec = ngc.alloc(vm_vec); var vec = ngc.alloc(vm_vec);
vec.vec().elems.push_back(var::num((f64)ret_pid)); vec.vec().elems.push_back(var::num(static_cast<f64>(ret_pid)));
vec.vec().elems.push_back(var::num((f64)status)); vec.vec().elems.push_back(var::num(static_cast<f64>(status)));
return vec; return vec;
#endif #endif
return nas_err("waitpid", "not supported"); return nas_err("waitpid", "not supported on windows");
} }
var builtin_opendir(var* local, gc& ngc) { var builtin_opendir(var* local, gc& ngc) {
@ -60,7 +62,7 @@ var builtin_opendir(var* local, gc& ngc) {
#ifdef _MSC_VER #ifdef _MSC_VER
WIN32_FIND_DATAA data; WIN32_FIND_DATAA data;
HANDLE p; HANDLE p;
p = FindFirstFileA((path.str()+"\\*.*").c_str(),&data); p = FindFirstFileA((path.str()+"\\*.*").c_str(), &data);
if (p==INVALID_HANDLE_VALUE) { if (p==INVALID_HANDLE_VALUE) {
return nas_err("opendir", "cannot open dir <"+path.str()+">"); return nas_err("opendir", "cannot open dir <"+path.str()+">");
} }
@ -87,7 +89,7 @@ var builtin_readdir(var* local, gc& ngc) {
} }
return ngc.newstr(data.cFileName); return ngc.newstr(data.cFileName);
#else #else
dirent* p = readdir((DIR*)handle.obj().ptr); dirent* p = readdir(static_cast<DIR*>(handle.obj().ptr));
return p? ngc.newstr(p->d_name):nil; return p? ngc.newstr(p->d_name):nil;
#endif #endif
} }
@ -104,9 +106,9 @@ var builtin_closedir(var* local, gc& ngc) {
var builtin_chdir(var* local, gc& ngc) { var builtin_chdir(var* local, gc& ngc) {
var path = local[1]; var path = local[1];
if (path.type!=vm_str) { if (path.type!=vm_str) {
return var::num((f64)-1); return var::num(-1.0);
} }
return var::num((f64)chdir(path.str().c_str())); return var::num(static_cast<f64>(chdir(path.str().c_str())));
} }
var builtin_environ(var* local, gc& ngc) { var builtin_environ(var* local, gc& ngc) {
@ -148,4 +150,6 @@ nasal_builtin_table unix_lib_native[] = {
{"__getcwd", builtin_getcwd}, {"__getcwd", builtin_getcwd},
{"__getenv", builtin_getenv}, {"__getenv", builtin_getenv},
{nullptr, nullptr} {nullptr, nullptr}
}; };
}

View File

@ -20,6 +20,8 @@
#include <sys/wait.h> #include <sys/wait.h>
#endif #endif
namespace nasal {
void dir_entry_destructor(void*); void dir_entry_destructor(void*);
var builtin_pipe(var*, gc&); var builtin_pipe(var*, gc&);
@ -33,4 +35,6 @@ var builtin_environ(var*, gc&);
var builtin_getcwd(var*, gc&); var builtin_getcwd(var*, gc&);
var builtin_getenv(var*, gc&); var builtin_getenv(var*, gc&);
extern nasal_builtin_table unix_lib_native[]; extern nasal_builtin_table unix_lib_native[];
}

View File

@ -1,76 +0,0 @@
# experimental repl
# 2023/8/19 by ValKmjolnir
var help = func() {
println(" .help | show help");
println(" .exit | quit the REPL");
println(" .quit | quit the REPL");
println(" .clear | clear the screen");
println();
}
var content = [];
var log_cache = "";
println("Nasal: This is experimental REPL");
println("Tips : \";\" is automatically added at the end of the input line.");
help();
var count_bracket = func(line) {
var len = size(line);
var count = 0;
for(var i = 0; i < len; i += 1) {
if (line[i] == "{"[0]) {
count += 1;
} elsif (line[i] == "}"[0]) {
count -= 1;
}
}
return count;
}
while(1) {
var line = readline(">>> ");
if (!size(line)) {
continue;
}
if (line == ".exit" or line == ".quit") {
break;
} elsif (line == ".help") {
println();
help();
continue;
} elsif (line == ".clear") {
print("\ec");
continue;
} elsif (line[0] == "."[0]) {
println("no such command \"", line, "\", input \".help\" for help\n");
continue;
}
var in_bracket_level = count_bracket(line);
while(in_bracket_level > 0) {
var temp_line = readline("... ");
in_bracket_level += count_bracket(temp_line);
line ~= temp_line ~ "\n";
}
append(content, line);
var source = "";
foreach(var i; content) {
source ~= i ~ ";\n";
}
io.fout(".temp.nas", source);
var result = system("nasal .temp.nas > .temp.log");
if (result != 0) {
pop(content);
continue;
}
var log = io.readfile(".temp.log");
if (size(log) and size(log) != size(log_cache)) {
println(substr(log, size(log_cache), size(log)), "\n");
log_cache = log;
}
}