add cmakelists.txt

This commit is contained in:
ValKmjolnir 2023-05-06 21:12:40 +08:00
parent f914678311
commit 92abad3384
19 changed files with 725 additions and 669 deletions

3
.gitignore vendored
View File

@ -47,6 +47,9 @@ nasal.exe
.vscode .vscode
dump dump
# build dir
build
# macOS special cache directory # macOS special cache directory
.DS_Store .DS_Store

27
CMakeLists.txt Normal file
View File

@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.10)
project(nasal VERSION 10.1)
# -std=c++14 -Wshadow -Wall
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
# generate release executables
set(CMAKE_BUILD_TYPE "Release")
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR})
add_library(key SHARED ${CMAKE_SOURCE_DIR}/module/keyboard.cpp)
target_include_directories(key PRIVATE ${CMAKE_SOURCE_DIR})
add_library(mat SHARED ${CMAKE_SOURCE_DIR}/module/matrix.cpp)
target_include_directories(mat PRIVATE ${CMAKE_SOURCE_DIR})
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})

View File

@ -70,7 +70,11 @@ void err() {
std::exit(1); std::exit(1);
} }
void execute(const string& file, const std::vector<string>& argv, const u32 cmd) { void execute(
const string& file,
const std::vector<string>& argv,
const u32 cmd
) {
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;
@ -96,8 +100,8 @@ void execute(const string& file, const std::vector<string>& argv, const u32 cmd)
parse.tree().dump(); parse.tree().dump();
} }
// code generator gets parser's ast and linker's import file list to generate code // code generator gets parser's ast and import file list to generate code
gen.compile(parse,ld).chkerr(); gen.compile(parse, ld).chkerr();
if (cmd&VM_CODE) { if (cmd&VM_CODE) {
gen.print(); gen.print();
} }
@ -109,6 +113,8 @@ void execute(const string& file, const std::vector<string>& argv, const u32 cmd)
} else if (cmd&VM_TIME || cmd&VM_EXEC) { } else if (cmd&VM_TIME || cmd&VM_EXEC) {
ctx.run(gen, ld, argv, cmd&VM_DETAIL); ctx.run(gen, ld, argv, cmd&VM_DETAIL);
} }
// get running time
if (cmd&VM_TIME) { if (cmd&VM_TIME) {
f64 tm=(clk::now()-start).count()*1.0/den; f64 tm=(clk::now()-start).count()*1.0/den;
std::clog<<"process exited after "<<tm<<"s.\n\n"; std::clog<<"process exited after "<<tm<<"s.\n\n";
@ -137,23 +143,23 @@ i32 main(i32 argc, const char* argv[]) {
// execute with arguments // execute with arguments
const std::unordered_map<string,u32> cmdlst={ const std::unordered_map<string,u32> cmdlst={
{"--ast",VM_AST}, {"--ast", VM_AST},
{"-a",VM_AST}, {"-a", VM_AST},
{"--code",VM_CODE}, {"--code", VM_CODE},
{"-c",VM_CODE}, {"-c", VM_CODE},
{"--exec",VM_EXEC}, {"--exec", VM_EXEC},
{"-e",VM_EXEC}, {"-e", VM_EXEC},
{"--time",VM_TIME|VM_EXEC}, {"--time", VM_TIME|VM_EXEC},
{"-t",VM_TIME|VM_EXEC}, {"-t", VM_TIME|VM_EXEC},
{"--detail",VM_DETAIL|VM_EXEC}, {"--detail", VM_DETAIL|VM_EXEC},
{"-d",VM_DETAIL|VM_EXEC}, {"-d", VM_DETAIL|VM_EXEC},
{"--debug",VM_DEBUG}, {"--debug", VM_DEBUG},
{"-dbg",VM_DEBUG} {"-dbg", VM_DEBUG}
}; };
u32 cmd=0; u32 cmd=0;
string filename=""; string filename="";
std::vector<string> vm_argv; std::vector<string> vm_argv;
for(i32 i=1;i<argc;++i) { for(i32 i=1; i<argc; ++i) {
if (cmdlst.count(argv[i])) { if (cmdlst.count(argv[i])) {
cmd|=cmdlst.at(argv[i]); cmd|=cmdlst.at(argv[i]);
} else if (!filename.length()) { } else if (!filename.length()) {

View File

@ -8,7 +8,7 @@ double fibonaci(double x) {
return fibonaci(x-1)+fibonaci(x-2); return fibonaci(x-1)+fibonaci(x-2);
} }
var fib(var* args,usize size,gc* ngc) { var fib(var* args, usize size, gc* ngc) {
if (!size) { if (!size) {
return nas_err("fib","lack arguments"); return nas_err("fib","lack arguments");
} }
@ -16,7 +16,7 @@ var fib(var* args,usize size,gc* ngc) {
return var::num(fibonaci(num.tonum())); return var::num(fibonaci(num.tonum()));
} }
var quick_fib(var* args,usize size,gc* ngc) { var quick_fib(var* args, usize size, gc* ngc) {
if (!size) { if (!size) {
return nas_err("quick_fib","lack arguments"); return nas_err("quick_fib","lack arguments");
} }

View File

@ -18,21 +18,21 @@ private:
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() {
@ -42,10 +42,10 @@ public:
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;
@ -63,7 +63,7 @@ public:
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();
@ -72,13 +72,16 @@ public:
}; };
noecho_input this_window; noecho_input this_window;
var nas_getch(var* args,usize size,gc* ngc) {
var nas_getch(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_getch()); return var::num((double)this_window.noecho_getch());
} }
var nas_kbhit(var* args,usize size,gc* ngc) {
var nas_kbhit(var* args, usize size, gc* ngc) {
return var::num((double)this_window.noecho_kbhit()); return var::num((double)this_window.noecho_kbhit());
} }
var nas_noblock(var* args,usize size,gc* ngc) {
var nas_noblock(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) { if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch()); return var::num((double)this_window.noecho_getch());
} }

View File

@ -1,14 +1,14 @@
#include "../nasal.h" #include "../nasal.h"
#include <cmath> #include <cmath>
var nas_vec2(var* args,usize size,gc* ngc) { var nas_vec2(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]); res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]); res.vec().elems.push_back(args[1]);
return res; return res;
} }
var nas_vec3(var* args,usize size,gc* ngc) { var nas_vec3(var* args, usize size, gc* ngc) {
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back(args[0]); res.vec().elems.push_back(args[0]);
res.vec().elems.push_back(args[1]); res.vec().elems.push_back(args[1]);
@ -16,7 +16,7 @@ var nas_vec3(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_add(var* args,usize size,gc* ngc) { var nas_vec2_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -29,7 +29,7 @@ var nas_vec2_add(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_sub(var* args,usize size,gc* ngc) { var nas_vec2_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -42,7 +42,7 @@ var nas_vec2_sub(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_mult(var* args,usize size,gc* ngc) { var nas_vec2_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -55,7 +55,7 @@ var nas_vec2_mult(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_div(var* args,usize size,gc* ngc) { var nas_vec2_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -68,7 +68,7 @@ var nas_vec2_div(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_neg(var* args,usize size,gc* ngc) { var nas_vec2_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -80,7 +80,7 @@ var nas_vec2_neg(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_norm(var* args,usize size,gc* ngc) { var nas_vec2_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -95,7 +95,7 @@ var nas_vec2_norm(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec2_len(var* args,usize size,gc* ngc) { var nas_vec2_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -106,7 +106,7 @@ var nas_vec2_len(var* args,usize size,gc* ngc) {
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;
@ -116,7 +116,7 @@ var nas_vec2_dot(var* args,usize size,gc* ngc) {
return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()); return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num());
} }
var nas_vec3_add(var* args,usize size,gc* ngc) { var nas_vec3_add(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -130,7 +130,7 @@ var nas_vec3_add(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_sub(var* args,usize size,gc* ngc) { var nas_vec3_sub(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -144,7 +144,7 @@ var nas_vec3_sub(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_mult(var* args,usize size,gc* ngc) { var nas_vec3_mult(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -158,7 +158,7 @@ var nas_vec3_mult(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_div(var* args,usize size,gc* ngc) { var nas_vec3_div(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -172,7 +172,7 @@ var nas_vec3_div(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_neg(var* args,usize size,gc* ngc) { var nas_vec3_neg(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -185,7 +185,7 @@ var nas_vec3_neg(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_norm(var* args,usize size,gc* ngc) { var nas_vec3_norm(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -202,7 +202,7 @@ var nas_vec3_norm(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_len(var* args,usize size,gc* ngc) { var nas_vec3_len(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -214,7 +214,7 @@ var nas_vec3_len(var* args,usize size,gc* ngc) {
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;
@ -228,7 +228,7 @@ var nas_rotate_x(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_rotate_y(var* args,usize size,gc* ngc) { var nas_rotate_y(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -242,7 +242,7 @@ var nas_rotate_y(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_rotate_z(var* args,usize size,gc* ngc) { var nas_rotate_z(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec) if (args[0].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;
@ -256,7 +256,7 @@ var nas_rotate_z(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_vec3_dot(var* args,usize size,gc* ngc) { var nas_vec3_dot(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_vec || args[1].type!=vm_vec) if (args[0].type!=vm_vec || args[1].type!=vm_vec)
return nil; return nil;
auto& v0=args[0].vec().elems; auto& v0=args[0].vec().elems;

View File

@ -10,7 +10,7 @@ private:
WSAData data; WSAData data;
public: public:
WSAmanager() { WSAmanager() {
WSAStartup(0x1010,&data); WSAStartup(0x1010, &data);
} }
~WSAmanager() { ~WSAmanager() {
WSACleanup(); WSACleanup();
@ -25,14 +25,14 @@ static WSAmanager win;
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
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
@ -42,7 +42,7 @@ var nas_closesocket(var* args,usize size,gc* ngc) {
#endif #endif
} }
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)
@ -50,7 +50,7 @@ var nas_shutdown(var* args,usize size,gc* ngc) {
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)
@ -65,7 +65,7 @@ var nas_bind(var* args,usize size,gc* ngc) {
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)
@ -73,7 +73,7 @@ var nas_listen(var* args,usize size,gc* ngc) {
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)
@ -89,7 +89,7 @@ var nas_connect(var* args,usize size,gc* ngc) {
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;
@ -107,7 +107,7 @@ var nas_accept(var* args,usize size,gc* ngc) {
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)
@ -117,7 +117,7 @@ var nas_send(var* args,usize size,gc* ngc) {
return var::num((double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())); 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)
@ -137,7 +137,7 @@ var nas_sendto(var* args,usize size,gc* ngc) {
return var::num((double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); 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)
@ -158,7 +158,7 @@ var nas_recv(var* args,usize size,gc* ngc) {
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)
@ -186,7 +186,7 @@ var nas_recvfrom(var* args,usize size,gc* ngc) {
return res; return res;
} }
var nas_errno(var* args,usize size,gc* ngc) { var nas_errno(var* args, usize size, gc* ngc) {
return ngc->newstr(strerror(errno)); return ngc->newstr(strerror(errno));
} }

10
nasal.h
View File

@ -109,7 +109,7 @@ const u32 STACK_DEPTH=1024;
f64 hex2f(const char* str) { f64 hex2f(const char* str) {
f64 ret=0; f64 ret=0;
for(;*str;++str) { for(; *str; ++str) {
if ('0'<=*str && *str<='9') { if ('0'<=*str && *str<='9') {
ret=ret*16+(*str-'0'); ret=ret*16+(*str-'0');
} else if ('a'<=*str && *str<='f') { } else if ('a'<=*str && *str<='f') {
@ -134,10 +134,12 @@ f64 oct2f(const char* str) {
return ret; return ret;
} }
// we have the same reason not using atof here just as andy's interpreter does. // we have the same reason not using atof here
// just as andy's interpreter does.
// it is not platform independent, and may have strange output. // it is not platform independent, and may have strange output.
// so we write a new function here to convert str to number manually. // so we write a new function here to convert str to number manually.
// but this also makes 0.1+0.2==0.3, not another result that you may get in other languages. // but this also makes 0.1+0.2==0.3,
// not another result that you may get in other languages.
f64 dec2f(const char* str) { f64 dec2f(const char* str) {
f64 ret=0,negative=1,num_pow=0; f64 ret=0,negative=1,num_pow=0;
while('0'<=*str && *str<='9') { while('0'<=*str && *str<='9') {
@ -220,7 +222,7 @@ string chrhex(const char c) {
return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]}; return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]};
} }
string rawstr(const string& str,const usize maxlen=0) { string rawstr(const string& str, const usize maxlen=0) {
string ret(""); string ret("");
for(auto i:str) { for(auto i:str) {
// windows doesn't output unicode normally, so we output the hex // windows doesn't output unicode normally, so we output the hex

View File

@ -151,8 +151,9 @@ public:
ast(ast&&) = default; ast(ast&&) = default;
ast& operator=(ast&&) = default; ast& operator=(ast&&) = default;
private: private:
void print(u32,bool,std::vector<string>&) const; void print(u32, bool, std::vector<string>&) const;
private: private:
span loc; span loc;
@ -162,23 +163,27 @@ private:
std::vector<ast> nd_child; std::vector<ast> nd_child;
public: public:
ast(const span& s,const u32 t) ast(const span& s, const u32 t)
: loc(s),nd_type(t),nd_num(0),nd_str("") {} : loc(s), nd_type(t), nd_num(0), nd_str("") {}
public:
void dump() const; void dump() const;
void clear(); void clear();
public:
ast& operator[](usize n) {return nd_child[n];} ast& operator[](usize n) {return nd_child[n];}
const ast& operator[](usize n) const {return nd_child[n];} const ast& operator[](usize n) const {return nd_child[n];}
usize size() const {return nd_child.size();} usize size() const {return nd_child.size();}
public:
void add(ast&& node) {nd_child.push_back(std::move(node));} void add(ast&& node) {nd_child.push_back(std::move(node));}
void set_begin(const u32,const u32); void set_begin(const u32, const u32);
void set_end(const u32,const u32); void set_end(const u32, const u32);
void set_type(const u32 t) {nd_type=t;} void set_type(const u32 t) {nd_type=t;}
void set_str(const string& s) {nd_str=s;} void set_str(const string& s) {nd_str=s;}
void set_num(const f64 n) {nd_num=n;} void set_num(const f64 n) {nd_num=n;}
public:
u32 line() const {return loc.end_line;} u32 line() const {return loc.end_line;}
u32 type() const {return nd_type;} u32 type() const {return nd_type;}
f64 num() const {return nd_num;} f64 num() const {return nd_num;}
@ -193,18 +198,18 @@ public:
void update_span(const span&); void update_span(const span&);
}; };
void ast::set_begin(const u32 l,const u32 c) { void ast::set_begin(const u32 l, const u32 c) {
loc.begin_line=l; loc.begin_line=l;
loc.begin_column=c; loc.begin_column=c;
} }
void ast::set_end(const u32 l,const u32 c) { void ast::set_end(const u32 l, const u32 c) {
loc.end_line=l; loc.end_line=l;
loc.end_column=c; loc.end_column=c;
} }
void ast::clear() { void ast::clear() {
loc={0,0,0,0,""}; loc={0, 0, 0, 0, ""};
nd_num=0; nd_num=0;
nd_str.clear(); nd_str.clear();
nd_type=ast_null; nd_type=ast_null;
@ -213,10 +218,10 @@ void ast::clear() {
void ast::dump() const{ void ast::dump() const{
std::vector<string> tmp; std::vector<string> tmp;
print(0,false,tmp); print(0, false, tmp);
} }
void ast::print(u32 depth,bool last,std::vector<string>& indent) const{ void ast::print(u32 depth, bool last, std::vector<string>& indent) const{
// output the indentation first // output the indentation first
for(auto& i:indent) { for(auto& i:indent) {
std::cout<<i; std::cout<<i;
@ -246,7 +251,7 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent) const{
} else if (!last && depth) { } else if (!last && depth) {
indent.back()=is_windows()? "| ":""; indent.back()=is_windows()? "| ":"";
} }
for(u32 i=0;i<nd_child.size();++i) { for(u32 i=0; i<nd_child.size(); ++i) {
if (is_windows()) { if (is_windows()) {
indent.push_back(i==nd_child.size()-1?"+-":"|-"); indent.push_back(i==nd_child.size()-1?"+-":"|-");
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -33,8 +33,8 @@ private:
bool check_memory_reachable(const ast&); bool check_memory_reachable(const ast&);
void check_id_exist(const ast&); void check_id_exist(const ast&);
void die(const string& info,const span& loc) { void die(const string& info, const span& loc) {
err.err("code",loc,info); err.err("code", loc, info);
} }
void regist_num(const f64); void regist_num(const f64);
@ -45,7 +45,7 @@ private:
i32 global_find(const string&); i32 global_find(const string&);
i32 upvalue_find(const string&); i32 upvalue_find(const string&);
void gen(u8,u32,u32); void gen(u8, u32, u32);
void num_gen(const ast&); void num_gen(const ast&);
void str_gen(const ast&); void str_gen(const ast&);
@ -68,7 +68,7 @@ private:
void multi_assign_gen(const ast&); void multi_assign_gen(const ast&);
void cond_gen(const ast&); void cond_gen(const ast&);
void loop_gen(const ast&); void loop_gen(const ast&);
void load_continue_break(i32,i32); void load_continue_break(i32, i32);
void while_gen(const ast&); void while_gen(const ast&);
void for_gen(const ast&); void for_gen(const ast&);
void expr_gen(const ast&); void expr_gen(const ast&);
@ -82,8 +82,8 @@ private:
void ret_gen(const ast&); void ret_gen(const ast&);
public: public:
codegen(error& e):fileindex(0),err(e),file(nullptr) {} codegen(error& e): fileindex(0), err(e), file(nullptr) {}
const error& compile(const parse&,const linker&); const error& compile(const parse&, const linker&);
void print(); void print();
const std::vector<string>& strs() const {return str_res;} const std::vector<string>& strs() const {return str_res;}
const std::vector<f64>& nums() const {return num_res;} const std::vector<f64>& nums() const {return num_res;}
@ -94,15 +94,15 @@ bool codegen::check_memory_reachable(const ast& node) {
if (node.type()==ast_call) { if (node.type()==ast_call) {
const ast& tmp=node.child().back(); const ast& tmp=node.child().back();
if (tmp.type()==ast_callf) { if (tmp.type()==ast_callf) {
die("bad left-value with function call",node.location()); die("bad left-value with function call", node.location());
return false; return false;
} }
if (tmp.type()==ast_callv && (tmp.size()==0 || tmp.size()>1 || tmp[0].type()==ast_subvec)) { if (tmp.type()==ast_callv && (tmp.size()==0 || tmp.size()>1 || tmp[0].type()==ast_subvec)) {
die("bad left-value with subvec",node.location()); die("bad left-value with subvec", node.location());
return false; return false;
} }
} else if (node.type()!=ast_id) { } else if (node.type()!=ast_id) {
die("bad left-value",node.location()); die("bad left-value", node.location());
return false; return false;
} }
return true; return true;
@ -113,7 +113,7 @@ void codegen::check_id_exist(const ast& node) {
for(u32 i=0;builtin[i].name;++i) { for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) { if (builtin[i].name==str) {
if (local.empty()) { if (local.empty()) {
die("useless native function used in global scope",node.location()); die("useless native function used in global scope", node.location());
} }
return; return;
} }
@ -128,7 +128,7 @@ void codegen::check_id_exist(const ast& node) {
if (global_find(str)>=0) { if (global_find(str)>=0) {
return; return;
} }
die("undefined symbol \""+str+"\", and this symbol is useless here",node.location()); die("undefined symbol \""+str+"\", and this symbol is useless here", node.location());
} }
void codegen::regist_num(const f64 num) { void codegen::regist_num(const f64 num) {
@ -213,41 +213,41 @@ i32 codegen::upvalue_find(const string& name) {
return index; return index;
} }
void codegen::gen(u8 op,u32 num,u32 line) { void codegen::gen(u8 op, u32 num, u32 line) {
code.push_back({op,fileindex,num,line}); code.push_back({op, fileindex, num, line});
} }
void codegen::num_gen(const ast& node) { void codegen::num_gen(const ast& node) {
f64 num=node.num(); f64 num=node.num();
regist_num(num); regist_num(num);
gen(op_pnum,num_table[num],node.line()); gen(op_pnum,num_table[num], node.line());
} }
void codegen::str_gen(const ast& node) { void codegen::str_gen(const ast& node) {
regist_str(node.str()); regist_str(node.str());
gen(op_pstr,str_table[node.str()],node.line()); gen(op_pstr, str_table[node.str()], node.line());
} }
void codegen::bool_gen(const ast& node) { void codegen::bool_gen(const ast& node) {
f64 num=node.str()=="true"?1:0; f64 num=node.str()=="true"?1:0;
regist_num(num); regist_num(num);
gen(op_pnum,num_table[num],node.line()); gen(op_pnum, num_table[num], node.line());
} }
void codegen::vec_gen(const ast& node) { void codegen::vec_gen(const ast& node) {
for(auto& child:node.child()) { for(auto& child:node.child()) {
calc_gen(child); calc_gen(child);
} }
gen(op_newv,node.size(),node.line()); gen(op_newv, node.size(), node.line());
} }
void codegen::hash_gen(const ast& node) { void codegen::hash_gen(const ast& node) {
gen(op_newh,0,node.line()); gen(op_newh, 0, node.line());
for(auto& child:node.child()) { for(auto& child:node.child()) {
calc_gen(child[1]); calc_gen(child[1]);
const string& str=child[0].str(); const string& str=child[0].str();
regist_str(str); regist_str(str);
gen(op_happ,str_table[str],child.line()); gen(op_happ, str_table[str], child.line());
} }
} }
@ -264,53 +264,57 @@ void codegen::func_gen(const ast& node) {
} }
// check default parameter and dynamic parameter // check default parameter and dynamic parameter
if (checked_default && tmp.type()!=ast_default) { if (checked_default && tmp.type()!=ast_default) {
die("must use default parameters here",tmp.location()); die("must use default parameters here", tmp.location());
} }
if (checked_dynamic && &tmp!=&node[0].child().back()) { if (checked_dynamic && &tmp!=&node[0].child().back()) {
die("dynamic parameter must be the last one",tmp.location()); die("dynamic parameter must be the last one", tmp.location());
} }
// check redefinition // check redefinition
string name=tmp.str(); string name=tmp.str();
if (argname.count(name)) { if (argname.count(name)) {
die("redefinition of parameter: "+name,tmp.location()); die("redefinition of parameter: "+name, tmp.location());
} else { } else {
argname[name]=true; argname[name]=true;
} }
} }
usize newf=code.size(); usize newf=code.size();
gen(op_newf,0,node.line()); gen(op_newf, 0, node.line());
usize lsize=code.size(); usize lsize=code.size();
gen(op_intl,0,node.line()); gen(op_intl, 0, node.line());
// add special keyword 'me' into symbol table // add special keyword 'me' into symbol table
// this symbol is only used in local scope(function's scope) // this symbol is only used in local scope(function's scope)
// this keyword is set to nil as default value // this keyword is set to nil as default value
// after calling a hash, this keyword is set to this hash // after calling a hash, this keyword is set to this hash
// this symbol's index will be 0 // this symbol's index will be 0
local.push_back({{"me",0}}); local.push_back({{"me", 0}});
// generate parameter list // generate parameter list
for(auto& tmp:node[0].child()) { for(auto& tmp:node[0].child()) {
const string& str=tmp.str(); const string& str=tmp.str();
if (str=="me") { if (str=="me") {
die("\"me\" should not be a parameter",tmp.location()); die("\"me\" should not be a parameter", tmp.location());
} }
regist_str(str); regist_str(str);
switch(tmp.type()) { switch(tmp.type()) {
case ast_id:gen(op_para,str_table[str],tmp.line());break; case ast_id:
gen(op_para, str_table[str], tmp.line());
break;
case ast_default: case ast_default:
calc_gen(tmp[0]); calc_gen(tmp[0]);
gen(op_deft,str_table[str],tmp.line()); gen(op_deft, str_table[str], tmp.line());
break;
case ast_dynamic:
gen(op_dyn, str_table[str], tmp.line());
break; break;
case ast_dynamic:gen(op_dyn,str_table[str],tmp.line());break;
} }
add_sym(str); add_sym(str);
} }
code[newf].num=code.size()+1; // entry code[newf].num=code.size()+1; // entry
usize jmp_ptr=code.size(); usize jmp_ptr=code.size();
gen(op_jmp,0,node.line()); gen(op_jmp, 0, node.line());
const ast& block=node[1]; const ast& block=node[1];
// search symbols first, must use after loading parameters // search symbols first, must use after loading parameters
@ -321,13 +325,13 @@ void codegen::func_gen(const ast& node) {
in_iterloop.pop(); in_iterloop.pop();
code[lsize].num=local.back().size(); code[lsize].num=local.back().size();
if (local.back().size()>=STACK_DEPTH) { if (local.back().size()>=STACK_DEPTH) {
die("too many local variants: "+std::to_string(local.back().size()),block.location()); die("too many local variants: "+std::to_string(local.back().size()), block.location());
} }
local.pop_back(); local.pop_back();
if (!block.size() || block.child().back().type()!=ast_ret) { if (!block.size() || block.child().back().type()!=ast_ret) {
gen(op_pnil,0,block.line()); gen(op_pnil, 0, block.line());
gen(op_ret,0,block.line()); gen(op_ret, 0, block.line());
} }
code[jmp_ptr].num=code.size(); code[jmp_ptr].num=code.size();
} }
@ -351,66 +355,66 @@ void codegen::call_id(const ast& node) {
const string& str=node.str(); const string& str=node.str();
for(u32 i=0;builtin[i].name;++i) { for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) { if (builtin[i].name==str) {
gen(op_callb,i,node.line()); gen(op_callb, i, node.line());
if (local.empty()) { if (local.empty()) {
die("should warp native function in local scope",node.location()); die("should warp native function in local scope", node.location());
} }
return; return;
} }
} }
i32 index; i32 index;
if ((index=local_find(str))>=0) { if ((index=local_find(str))>=0) {
gen(op_calll,index,node.line()); gen(op_calll, index, node.line());
return; return;
} }
if ((index=upvalue_find(str))>=0) { if ((index=upvalue_find(str))>=0) {
gen(op_upval,index,node.line()); gen(op_upval, index, node.line());
return; return;
} }
if ((index=global_find(str))>=0) { if ((index=global_find(str))>=0) {
gen(op_callg,index,node.line()); gen(op_callg, index, node.line());
return; return;
} }
die("undefined symbol \""+str+"\"",node.location()); die("undefined symbol \""+str+"\"", node.location());
} }
void codegen::call_hash(const ast& node) { void codegen::call_hash(const ast& node) {
regist_str(node.str()); regist_str(node.str());
gen(op_callh,str_table[node.str()],node.line()); gen(op_callh, str_table[node.str()], node.line());
} }
void codegen::call_vec(const ast& node) { void codegen::call_vec(const ast& node) {
// maybe this place can use callv-const if ast's first child is ast_num // maybe this place can use callv-const if ast's first child is ast_num
if (node.size()==1 && node[0].type()!=ast_subvec) { if (node.size()==1 && node[0].type()!=ast_subvec) {
calc_gen(node[0]); calc_gen(node[0]);
gen(op_callv,0,node[0].line()); gen(op_callv, 0, node[0].line());
return; return;
} }
gen(op_slcbeg,0,node.line()); gen(op_slcbeg,0,node.line());
for(auto& tmp:node.child()) { for(auto& tmp:node.child()) {
if (tmp.type()!=ast_subvec) { if (tmp.type()!=ast_subvec) {
calc_gen(tmp); calc_gen(tmp);
gen(op_slc,0,tmp.line()); gen(op_slc, 0, tmp.line());
} else { } else {
calc_gen(tmp[0]); calc_gen(tmp[0]);
calc_gen(tmp[1]); calc_gen(tmp[1]);
gen(op_slc2,0,tmp.line()); gen(op_slc2, 0, tmp.line());
} }
} }
gen(op_slcend,0,node.line()); gen(op_slcend, 0, node.line());
} }
void codegen::call_func(const ast& node) { void codegen::call_func(const ast& node) {
if (!node.size()) { if (!node.size()) {
gen(op_callfv,0,node.line()); gen(op_callfv, 0, node.line());
} else if (node[0].type()==ast_pair) { } else if (node[0].type()==ast_pair) {
hash_gen(node); hash_gen(node);
gen(op_callfh,0,node.line()); gen(op_callfh, 0, node.line());
} else { } else {
for(auto& child:node.child()) { for(auto& child:node.child()) {
calc_gen(child); calc_gen(child);
} }
gen(op_callfv,node.size(),node.line()); gen(op_callfv, node.size(), node.line());
} }
} }
@ -455,42 +459,42 @@ void codegen::mcall_id(const ast& node) {
const string& str=node.str(); const string& str=node.str();
for(u32 i=0;builtin[i].name;++i) { for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) { if (builtin[i].name==str) {
die("cannot modify native function",node.location()); die("cannot modify native function", node.location());
return; return;
} }
} }
i32 index; i32 index;
if ((index=local_find(str))>=0) { if ((index=local_find(str))>=0) {
gen(op_mcalll,index,node.line()); gen(op_mcalll, index, node.line());
return; return;
} }
if ((index=upvalue_find(str))>=0) { if ((index=upvalue_find(str))>=0) {
gen(op_mupval,index,node.line()); gen(op_mupval, index, node.line());
return; return;
} }
if ((index=global_find(str))>=0) { if ((index=global_find(str))>=0) {
gen(op_mcallg,index,node.line()); gen(op_mcallg, index, node.line());
return; return;
} }
die("undefined symbol \""+str+"\"",node.location()); die("undefined symbol \""+str+"\"", node.location());
} }
void codegen::mcall_vec(const ast& node) { void codegen::mcall_vec(const ast& node) {
calc_gen(node[0]); calc_gen(node[0]);
gen(op_mcallv,0,node.line()); gen(op_mcallv, 0, node.line());
} }
void codegen::mcall_hash(const ast& node) { void codegen::mcall_hash(const ast& node) {
regist_str(node.str()); regist_str(node.str());
gen(op_mcallh,str_table[node.str()],node.line()); gen(op_mcallh, str_table[node.str()], node.line());
} }
void codegen::single_def(const ast& node) { void codegen::single_def(const ast& node) {
const string& str=node[0].str(); const string& str=node[0].str();
calc_gen(node[1]); calc_gen(node[1]);
local.empty()? local.empty()?
gen(op_loadg,global_find(str),node.line()): gen(op_loadg, global_find(str), node.line()):
gen(op_loadl,local_find(str),node.line()); gen(op_loadl, local_find(str), node.line());
} }
void codegen::multi_def(const ast& node) { void codegen::multi_def(const ast& node) {
auto& ids=node[0].child(); auto& ids=node[0].child();
@ -500,49 +504,49 @@ void codegen::multi_def(const ast& node) {
for(usize i=0;i<size;++i) { for(usize i=0;i<size;++i) {
// check node type, only identifier is allowed // check node type, only identifier is allowed
if (ids[i].type()!=ast_id) { if (ids[i].type()!=ast_id) {
die("cannot call identifier in multi-definition",ids[i].location()); die("cannot call identifier in multi-definition", ids[i].location());
continue; continue;
} }
calc_gen(vals[i]); calc_gen(vals[i]);
const string& str=ids[i].str(); const string& str=ids[i].str();
local.empty()? local.empty()?
gen(op_loadg,global_find(str),ids[i].line()): gen(op_loadg, global_find(str), ids[i].line()):
gen(op_loadl,local_find(str),ids[i].line()); gen(op_loadl, local_find(str), ids[i].line());
} }
} else { // (var a,b,c)=[0,1,2]; } else { // (var a,b,c)=[0,1,2];
calc_gen(node[1]); calc_gen(node[1]);
for(usize i=0;i<size;++i) { for(usize i=0;i<size;++i) {
// check node type, only identifier is allowed // check node type, only identifier is allowed
if (ids[i].type()!=ast_id) { if (ids[i].type()!=ast_id) {
die("cannot call identifier in multi-definition",ids[i].location()); die("cannot call identifier in multi-definition", ids[i].location());
continue; continue;
} }
gen(op_callvi,i,node[1].line()); gen(op_callvi, i, node[1].line());
const string& str=ids[i].str(); const string& str=ids[i].str();
local.empty()? local.empty()?
gen(op_loadg,global_find(str),ids[i].line()): gen(op_loadg, global_find(str), ids[i].line()):
gen(op_loadl,local_find(str),ids[i].line()); gen(op_loadl, local_find(str), ids[i].line());
} }
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
} }
void codegen::def_gen(const ast& node) { void codegen::def_gen(const ast& node) {
if (node[0].type()==ast_id && node[1].type()==ast_tuple) { if (node[0].type()==ast_id && node[1].type()==ast_tuple) {
die("cannot accept too many values",node[1].location()); die("cannot accept too many values", node[1].location());
} else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()<node[1].size()) { } else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()<node[1].size()) {
die("lack values in multi-definition",node[1].location()); die("lack values in multi-definition", node[1].location());
} else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()>node[1].size()) { } else if (node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()>node[1].size()) {
die("too many values in multi-definition",node[1].location()); die("too many values in multi-definition", node[1].location());
} }
node[0].type()==ast_id?single_def(node):multi_def(node); node[0].type()==ast_id?single_def(node):multi_def(node);
} }
void codegen::multi_assign_gen(const ast& node) { void codegen::multi_assign_gen(const ast& node) {
if (node[1].type()==ast_tuple && node[0].size()<node[1].size()) { if (node[1].type()==ast_tuple && node[0].size()<node[1].size()) {
die("lack values in multi-assignment",node[1].location()); die("lack values in multi-assignment", node[1].location());
} else if (node[1].type()==ast_tuple && node[0].size()>node[1].size()) { } else if (node[1].type()==ast_tuple && node[0].size()>node[1].size()) {
die("too many values in multi-assignment",node[1].location()); die("too many values in multi-assignment", node[1].location());
} }
i32 size=node[0].size(); i32 size=node[0].size();
if (node[1].type()==ast_tuple) { if (node[1].type()==ast_tuple) {
@ -560,13 +564,13 @@ void codegen::multi_assign_gen(const ast& node) {
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op=op_loadg;
} else { } else {
gen(op_meq,1,node[0][i].line()); gen(op_meq, 1, node[0][i].line());
} }
} }
} else { } else {
calc_gen(node[1]); calc_gen(node[1]);
for(i32 i=0;i<size;++i) { for(i32 i=0;i<size;++i) {
gen(op_callvi,i,node[1].line()); gen(op_callvi, i, node[1].line());
// multi assign user loadl and loadg to avoid meq's stack-- // multi assign user loadl and loadg to avoid meq's stack--
// and this operation changes local and global value directly // and this operation changes local and global value directly
mcall(node[0][i]); mcall(node[0][i]);
@ -577,10 +581,10 @@ void codegen::multi_assign_gen(const ast& node) {
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op=op_loadg;
} else { } else {
gen(op_meq,1,node[0][i].line()); gen(op_meq, 1, node[0][i].line());
} }
} }
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
} }
@ -590,12 +594,12 @@ void codegen::cond_gen(const ast& node) {
if (tmp.type()==ast_if || tmp.type()==ast_elsif) { if (tmp.type()==ast_if || tmp.type()==ast_elsif) {
calc_gen(tmp[0]); calc_gen(tmp[0]);
usize ptr=code.size(); usize ptr=code.size();
gen(op_jf,0,tmp.line()); gen(op_jf, 0, tmp.line());
block_gen(tmp[1]); block_gen(tmp[1]);
// without 'else' the last condition doesn't need to jmp // without 'else' the last condition doesn't need to jmp
if (&tmp!=&node.child().back()) { if (&tmp!=&node.child().back()) {
jmp_label.push_back(code.size()); jmp_label.push_back(code.size());
gen(op_jmp,0,tmp.line()); gen(op_jmp, 0, tmp.line());
} }
code[ptr].num=code.size(); code[ptr].num=code.size();
} else { } else {
@ -609,8 +613,8 @@ void codegen::cond_gen(const ast& node) {
} }
void codegen::loop_gen(const ast& node) { void codegen::loop_gen(const ast& node) {
continue_ptr.push_front(std::vector<i32>()); continue_ptr.push_front({});
break_ptr.push_front(std::vector<i32>()); break_ptr.push_front({});
switch(node.type()) { switch(node.type()) {
case ast_while: while_gen(node); break; case ast_while: while_gen(node); break;
case ast_for: for_gen(node); break; case ast_for: for_gen(node); break;
@ -634,32 +638,32 @@ void codegen::while_gen(const ast& node) {
usize loop_ptr=code.size(); usize loop_ptr=code.size();
calc_gen(node[0]); calc_gen(node[0]);
usize condition_ptr=code.size(); usize condition_ptr=code.size();
gen(op_jf,0,node[0].line()); gen(op_jf, 0, node[0].line());
block_gen(node[1]); block_gen(node[1]);
gen(op_jmp,loop_ptr,node[1].line()); gen(op_jmp, loop_ptr, node[1].line());
code[condition_ptr].num=code.size(); code[condition_ptr].num=code.size();
load_continue_break(code.size()-1,code.size()); load_continue_break(code.size()-1, code.size());
} }
void codegen::for_gen(const ast& node) { void codegen::for_gen(const ast& node) {
expr_gen(node[0]); expr_gen(node[0]);
usize jmp_place=code.size(); usize jmp_place=code.size();
if (node[1].type()==ast_null) { if (node[1].type()==ast_null) {
gen(op_pnum,num_table[1],node[1].line()); gen(op_pnum, num_table[1], node[1].line());
} else { } else {
calc_gen(node[1]); calc_gen(node[1]);
} }
usize label_exit=code.size(); usize label_exit=code.size();
gen(op_jf,0,node[1].line()); gen(op_jf, 0, node[1].line());
block_gen(node[3]); block_gen(node[3]);
usize continue_place=code.size(); usize continue_place=code.size();
expr_gen(node[2]); expr_gen(node[2]);
gen(op_jmp,jmp_place,node[2].line()); gen(op_jmp, jmp_place, node[2].line());
code[label_exit].num=code.size(); code[label_exit].num=code.size();
load_continue_break(continue_place,code.size()); load_continue_break(continue_place, code.size());
} }
void codegen::expr_gen(const ast& node) { void codegen::expr_gen(const ast& node) {
@ -676,7 +680,7 @@ void codegen::expr_gen(const ast& node) {
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) { } else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
code.back().op=code.back().op-op_addeqc+op_addecp; code.back().op=code.back().op-op_addeqc+op_addecp;
} else { } else {
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
break; break;
case ast_nil:case ast_num:case ast_str:case ast_bool:break; case ast_nil:case ast_num:case ast_str:case ast_bool:break;
@ -692,7 +696,7 @@ void codegen::expr_gen(const ast& node) {
if (code.back().op==op_meq) { if (code.back().op==op_meq) {
code.back().num=1; code.back().num=1;
} else { } else {
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
break; break;
case ast_equal: case ast_equal:
@ -712,7 +716,7 @@ void codegen::expr_gen(const ast& node) {
if (code.back().op==op_meq) { if (code.back().op==op_meq) {
code.back().num=1; code.back().num=1;
} else { } else {
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
} }
break; break;
@ -721,14 +725,14 @@ void codegen::expr_gen(const ast& node) {
void codegen::forindex_gen(const ast& node) { void codegen::forindex_gen(const ast& node) {
calc_gen(node[1]); calc_gen(node[1]);
gen(op_cnt,0,node[1].line()); gen(op_cnt, 0, node[1].line());
usize ptr=code.size(); usize ptr=code.size();
gen(op_findex,0,node.line()); gen(op_findex, 0, node.line());
if (node[0].type()==ast_iter) { // define a new iterator if (node[0].type()==ast_iter) { // define a new iterator
const string& str=node[0][0].str(); const string& str=node[0][0].str();
local.empty()? local.empty()?
gen(op_loadg,global_find(str),node[0][0].line()): gen(op_loadg, global_find(str), node[0][0].line()):
gen(op_loadl,local_find(str),node[0][0].line()); gen(op_loadl, local_find(str), node[0][0].line());
} else { // use exist variable as the iterator } else { // use exist variable as the iterator
mcall(node[0]); mcall(node[0]);
if (code.back().op==op_mcallg) { if (code.back().op==op_mcallg) {
@ -738,29 +742,29 @@ void codegen::forindex_gen(const ast& node) {
} else if (code.back().op==op_mupval) { } else if (code.back().op==op_mupval) {
code.back().op=op_loadu; code.back().op=op_loadu;
} else { } else {
gen(op_meq,1,node[0].line()); gen(op_meq, 1, node[0].line());
} }
} }
++in_iterloop.top(); ++in_iterloop.top();
block_gen(node[2]); block_gen(node[2]);
--in_iterloop.top(); --in_iterloop.top();
gen(op_jmp,ptr,node.line()); gen(op_jmp, ptr, node.line());
code[ptr].num=code.size(); code[ptr].num=code.size();
load_continue_break(code.size()-1,code.size()); load_continue_break(code.size()-1, code.size());
gen(op_pop,0,node[1].line());// pop vector gen(op_pop, 0, node[1].line());// pop vector
gen(op_pop,0,node.line());// pop iterator gen(op_pop, 0, node.line());// pop iterator
} }
void codegen::foreach_gen(const ast& node) { void codegen::foreach_gen(const ast& node) {
calc_gen(node[1]); calc_gen(node[1]);
gen(op_cnt,0,node.line()); gen(op_cnt, 0, node.line());
usize ptr=code.size(); usize ptr=code.size();
gen(op_feach,0,node.line()); gen(op_feach, 0, node.line());
if (node[0].type()==ast_iter) { // define a new iterator if (node[0].type()==ast_iter) { // define a new iterator
const string& str=node[0][0].str(); const string& str=node[0][0].str();
local.empty()? local.empty()?
gen(op_loadg,global_find(str),node[0][0].line()): gen(op_loadg, global_find(str), node[0][0].line()):
gen(op_loadl,local_find(str),node[0][0].line()); gen(op_loadl, local_find(str), node[0][0].line());
} else { // use exist variable as the iterator } else { // use exist variable as the iterator
mcall(node[0]); mcall(node[0]);
if (code.back().op==op_mcallg) { if (code.back().op==op_mcallg) {
@ -770,59 +774,59 @@ void codegen::foreach_gen(const ast& node) {
} else if (code.back().op==op_mupval) { } else if (code.back().op==op_mupval) {
code.back().op=op_loadu; code.back().op=op_loadu;
} else { } else {
gen(op_meq,1,node[0].line()); gen(op_meq, 1, node[0].line());
} }
} }
++in_iterloop.top(); ++in_iterloop.top();
block_gen(node[2]); block_gen(node[2]);
--in_iterloop.top(); --in_iterloop.top();
gen(op_jmp,ptr,node.line()); gen(op_jmp, ptr, node.line());
code[ptr].num=code.size(); code[ptr].num=code.size();
load_continue_break(code.size()-1,code.size()); load_continue_break(code.size()-1, code.size());
gen(op_pop,0,node[1].line());// pop vector gen(op_pop, 0, node[1].line());// pop vector
gen(op_pop,0,node.line());// pop iterator gen(op_pop, 0, node.line());// pop iterator
} }
void codegen::or_gen(const ast& node) { void codegen::or_gen(const ast& node) {
calc_gen(node[0]); calc_gen(node[0]);
usize l1=code.size(); usize l1=code.size();
gen(op_jt,0,node[0].line()); gen(op_jt, 0, node[0].line());
gen(op_pop,0,node[0].line()); gen(op_pop, 0, node[0].line());
calc_gen(node[1]); calc_gen(node[1]);
usize l2=code.size(); usize l2=code.size();
gen(op_jt,0,node[1].line()); gen(op_jt, 0, node[1].line());
gen(op_pop,0,node[1].line()); gen(op_pop, 0, node[1].line());
gen(op_pnil,0,node[1].line()); gen(op_pnil, 0, node[1].line());
code[l1].num=code[l2].num=code.size(); code[l1].num=code[l2].num=code.size();
} }
void codegen::and_gen(const ast& node) { void codegen::and_gen(const ast& node) {
calc_gen(node[0]); calc_gen(node[0]);
gen(op_jt,code.size()+2,node[0].line()); gen(op_jt, code.size()+2, node[0].line());
usize lfalse=code.size(); usize lfalse=code.size();
gen(op_jmp,0,node[0].line()); gen(op_jmp, 0, node[0].line());
gen(op_pop,0,node[1].line());// jt jumps here gen(op_pop, 0, node[1].line());// jt jumps here
calc_gen(node[1]); calc_gen(node[1]);
gen(op_jt,code.size()+3,node[1].line()); gen(op_jt, code.size()+3, node[1].line());
code[lfalse].num=code.size(); code[lfalse].num=code.size();
gen(op_pop,0,node[1].line()); gen(op_pop, 0, node[1].line());
gen(op_pnil,0,node[1].line()); gen(op_pnil, 0, node[1].line());
//jt jumps here // jt jumps here
} }
void codegen::trino_gen(const ast& node) { void codegen::trino_gen(const ast& node) {
calc_gen(node[0]); calc_gen(node[0]);
usize lfalse=code.size(); usize lfalse=code.size();
gen(op_jf,0,node[0].line()); gen(op_jf, 0, node[0].line());
calc_gen(node[1]); calc_gen(node[1]);
usize lexit=code.size(); usize lexit=code.size();
gen(op_jmp,0,node[1].line()); gen(op_jmp, 0, node[1].line());
code[lfalse].num=code.size(); code[lfalse].num=code.size();
calc_gen(node[2]); calc_gen(node[2]);
code[lexit].num=code.size(); code[lexit].num=code.size();
@ -842,7 +846,7 @@ void codegen::calc_gen(const ast& node) {
case ast_equal: case ast_equal:
calc_gen(node[1]); calc_gen(node[1]);
mcall(node[0]); mcall(node[0]);
gen(op_meq,0,node.line()); gen(op_meq, 0, node.line());
break; break;
// ast_addeq(22)~ast_lnkeq(26) op_addeq(23)~op_lnkeq(27) // ast_addeq(22)~ast_lnkeq(26) op_addeq(23)~op_lnkeq(27)
case ast_addeq:case ast_subeq:case ast_multeq:case ast_diveq: case ast_addeq:case ast_subeq:case ast_multeq:case ast_diveq:
@ -851,10 +855,10 @@ void codegen::calc_gen(const ast& node) {
} }
mcall(node[0]); mcall(node[0]);
if (node[1].type()!=ast_num) { if (node[1].type()!=ast_num) {
gen(node.type()-ast_addeq+op_addeq,0,node.line()); gen(node.type()-ast_addeq+op_addeq, 0, node.line());
} else { } else {
regist_num(node[1].num()); regist_num(node[1].num());
gen(node.type()-ast_addeq+op_addeqc,num_table[node[1].num()],node.line()); gen(node.type()-ast_addeq+op_addeqc, num_table[node[1].num()], node.line());
} }
break; break;
case ast_lnkeq: case ast_lnkeq:
@ -865,15 +869,15 @@ void codegen::calc_gen(const ast& node) {
} }
mcall(node[0]); mcall(node[0]);
if (node[1].type()!=ast_str) { if (node[1].type()!=ast_str) {
gen(op_lnkeq,0,node.line()); gen(op_lnkeq, 0, node.line());
} else { } else {
gen(op_lnkeqc,str_table[node[1].str()],node.line()); gen(op_lnkeqc, str_table[node[1].str()], node.line());
} }
break; break;
case ast_btandeq:case ast_btoreq:case ast_btxoreq: case ast_btandeq:case ast_btoreq:case ast_btxoreq:
calc_gen(node[1]); calc_gen(node[1]);
mcall(node[0]); mcall(node[0]);
gen(node.type()-ast_btandeq+op_btandeq,0,node.line()); gen(node.type()-ast_btandeq+op_btandeq, 0, node.line());
break; break;
case ast_or:or_gen(node);break; case ast_or:or_gen(node);break;
case ast_and:and_gen(node);break; case ast_and:and_gen(node);break;
@ -882,65 +886,65 @@ void codegen::calc_gen(const ast& node) {
calc_gen(node[0]); calc_gen(node[0]);
if (node[1].type()!=ast_num) { if (node[1].type()!=ast_num) {
calc_gen(node[1]); calc_gen(node[1]);
gen(node.type()-ast_add+op_add,0,node.line()); gen(node.type()-ast_add+op_add, 0, node.line());
} else { } else {
regist_num(node[1].num()); regist_num(node[1].num());
gen(node.type()-ast_add+op_addc,num_table[node[1].num()],node.line()); gen(node.type()-ast_add+op_addc, num_table[node[1].num()], node.line());
} }
break; break;
case ast_link: case ast_link:
calc_gen(node[0]); calc_gen(node[0]);
if (node[1].type()!=ast_str) { if (node[1].type()!=ast_str) {
calc_gen(node[1]); calc_gen(node[1]);
gen(op_lnk,0,node.line()); gen(op_lnk, 0, node.line());
} else { } else {
regist_str(node[1].str()); regist_str(node[1].str());
gen(op_lnkc,str_table[node[1].str()],node.line()); gen(op_lnkc, str_table[node[1].str()], node.line());
} }
break; break;
// ast_cmpeq(27)~ast_geq(32) op_eq(29)~op_geq(34) // ast_cmpeq(27)~ast_geq(32) op_eq(29)~op_geq(34)
case ast_cmpeq:case ast_neq: case ast_cmpeq:case ast_neq:
calc_gen(node[0]); calc_gen(node[0]);
calc_gen(node[1]); calc_gen(node[1]);
gen(node.type()-ast_cmpeq+op_eq,0,node.line()); gen(node.type()-ast_cmpeq+op_eq, 0, node.line());
break; break;
case ast_less:case ast_leq:case ast_grt:case ast_geq: case ast_less:case ast_leq:case ast_grt:case ast_geq:
calc_gen(node[0]); calc_gen(node[0]);
if (node[1].type()!=ast_num) { if (node[1].type()!=ast_num) {
calc_gen(node[1]); calc_gen(node[1]);
gen(node.type()-ast_less+op_less,0,node.line()); gen(node.type()-ast_less+op_less, 0, node.line());
} else { } else {
regist_num(node[1].num()); regist_num(node[1].num());
gen(node.type()-ast_less+op_lessc,num_table[node[1].num()],node.line()); gen(node.type()-ast_less+op_lessc, num_table[node[1].num()], node.line());
} }
break; break;
case ast_trino:trino_gen(node);break; case ast_trino:trino_gen(node);break;
case ast_neg: case ast_neg:
calc_gen(node[0]); calc_gen(node[0]);
gen(op_usub,0,node.line()); gen(op_usub, 0, node.line());
break; break;
case ast_lnot: case ast_lnot:
calc_gen(node[0]); calc_gen(node[0]);
gen(op_lnot,0,node.line()); gen(op_lnot, 0, node.line());
break; break;
case ast_bnot: case ast_bnot:
calc_gen(node[0]); calc_gen(node[0]);
gen(op_bnot,0,node.line()); gen(op_bnot, 0, node.line());
break; break;
case ast_bitor: case ast_bitor:
calc_gen(node[0]); calc_gen(node[0]);
calc_gen(node[1]); calc_gen(node[1]);
gen(op_btor,0,node.line()); gen(op_btor, 0, node.line());
break; break;
case ast_bitxor: case ast_bitxor:
calc_gen(node[0]); calc_gen(node[0]);
calc_gen(node[1]); calc_gen(node[1]);
gen(op_btxor,0,node.line()); gen(op_btxor, 0, node.line());
break; break;
case ast_bitand: case ast_bitand:
calc_gen(node[0]); calc_gen(node[0]);
calc_gen(node[1]); calc_gen(node[1]);
gen(op_btand,0,node.line()); gen(op_btand, 0, node.line());
break; break;
case ast_def: case ast_def:
single_def(node); single_def(node);
@ -959,11 +963,11 @@ void codegen::block_gen(const ast& node) {
case ast_cond:cond_gen(tmp);break; case ast_cond:cond_gen(tmp);break;
case ast_continue: case ast_continue:
continue_ptr.front().push_back(code.size()); continue_ptr.front().push_back(code.size());
gen(op_jmp,0,tmp.line()); gen(op_jmp, 0, tmp.line());
break; break;
case ast_break: case ast_break:
break_ptr.front().push_back(code.size()); break_ptr.front().push_back(code.size());
gen(op_jmp,0,tmp.line()); gen(op_jmp, 0, tmp.line());
break; break;
case ast_while: case ast_while:
case ast_for: case ast_for:
@ -992,42 +996,42 @@ void codegen::block_gen(const ast& node) {
void codegen::ret_gen(const ast& node) { void codegen::ret_gen(const ast& node) {
for(u32 i=0;i<in_iterloop.top();++i) { for(u32 i=0;i<in_iterloop.top();++i) {
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
gen(op_pop,0,node.line()); gen(op_pop, 0, node.line());
} }
if (node.size()) { if (node.size()) {
calc_gen(node[0]); calc_gen(node[0]);
} else { } else {
gen(op_pnil,0,node.line()); gen(op_pnil, 0, node.line());
} }
gen(op_ret,0,node.line()); gen(op_ret, 0, node.line());
} }
const error& codegen::compile(const parse& parse,const linker& import) { const error& codegen::compile(const parse& parse, const linker& import) {
fileindex=0; fileindex=0;
file=import.filelist().data(); file=import.filelist().data();
in_iterloop.push(0); in_iterloop.push(0);
find_symbol(parse.tree()); // search symbols first find_symbol(parse.tree()); // search symbols first
gen(op_intg,global.size(),0); gen(op_intg, global.size(), 0);
block_gen(parse.tree()); // generate main block block_gen(parse.tree()); // generate main block
gen(op_exit,0,0); gen(op_exit, 0, 0);
// size out of bound check // size out of bound check
if (num_res.size()>0xffffff) { if (num_res.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code","too many constant numbers: "+std::to_string(num_res.size())); err.err("code", "too many constant numbers: "+std::to_string(num_res.size()));
} }
if (str_res.size()>0xffffff) { if (str_res.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code","too many constant strings: "+std::to_string(str_res.size())); err.err("code", "too many constant strings: "+std::to_string(str_res.size()));
} }
if (global.size()>=STACK_DEPTH) { if (global.size()>=STACK_DEPTH) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code","too many global variants: "+std::to_string(global.size())); err.err("code", "too many global variants: "+std::to_string(global.size()));
} }
if (code.size()>0xffffff) { if (code.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code","bytecode size overflow: "+std::to_string(code.size())); err.err("code", "bytecode size overflow: "+std::to_string(code.size()));
} }
return err; return err;
} }
@ -1049,7 +1053,7 @@ void codegen::print() {
// print code // print code
std::cout<<"\n"; std::cout<<"\n";
codestream::set(num_res.data(),str_res.data()); codestream::set(num_res.data(), str_res.data());
for(u32 i=0;i<code.size();++i) { for(u32 i=0;i<code.size();++i) {
// print opcode index, opcode name, opcode immediate number // print opcode index, opcode name, opcode immediate number
const opcode& c=code[i]; const opcode& c=code[i];

View File

@ -23,8 +23,8 @@ private:
void interact(); void interact();
public: public:
dbg(error& err): dbg(error& err):
next(false),fsize(0), next(false), fsize(0),
bk_fidx(0),bk_line(0), bk_fidx(0), bk_line(0),
src(err) {} src(err) {}
void run( void run(
const codegen&, const codegen&,
@ -35,13 +35,14 @@ public:
std::vector<string> dbg::parse(const string& cmd) { std::vector<string> dbg::parse(const string& cmd) {
std::vector<string> res; std::vector<string> res;
usize last=0,pos=cmd.find(" ",0); usize last=0;
usize pos=cmd.find(" ", 0);
while(pos!=string::npos) { while(pos!=string::npos) {
if (pos>last) { if (pos>last) {
res.push_back(cmd.substr(last,pos-last)); res.push_back(cmd.substr(last, pos-last));
} }
last=pos+1; last=pos+1;
pos=cmd.find(" ",last); pos=cmd.find(" ", last);
} }
if (last<cmd.length()) { if (last<cmd.length()) {
res.push_back(cmd.substr(last)); res.push_back(cmd.substr(last));
@ -88,10 +89,10 @@ void dbg::callsort(const u64* arr) {
u64 total=0; u64 total=0;
for(u32 i=0;i<op_ret+1;++i) { for(u32 i=0;i<op_ret+1;++i) {
total+=arr[i]; total+=arr[i];
opcall.push_back({i,arr[i]}); opcall.push_back({i, arr[i]});
} }
std::sort(opcall.begin(),opcall.end(), std::sort(opcall.begin(), opcall.end(),
[](const op& a,const op& b) {return a.second>b.second;} [](const op& a, const op& b) {return a.second>b.second;}
); );
std::clog<<"\noperands call info (<1% ignored)\n"; std::clog<<"\noperands call info (<1% ignored)\n";
for(auto& i:opcall) { for(auto& i:opcall) {
@ -116,13 +117,13 @@ void dbg::stepinfo() {
begin=(ctx.pc>>3)==0?0:((ctx.pc>>3)<<3); begin=(ctx.pc>>3)==0?0:((ctx.pc>>3)<<3);
end=(1+(ctx.pc>>3))<<3; end=(1+(ctx.pc>>3))<<3;
codestream::set(cnum,cstr,files); codestream::set(cnum, cstr, files);
std::cout<<"next bytecode:\n"; std::cout<<"next bytecode:\n";
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) { for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
std::cout std::cout
<<(i==ctx.pc?back_white:reset) <<(i==ctx.pc?back_white:reset)
<<(i==ctx.pc?"--> ":" ") <<(i==ctx.pc?"--> ":" ")
<<codestream(bytecode[i],i) <<codestream(bytecode[i], i)
<<reset<<"\n"; <<reset<<"\n";
} }
stackinfo(10); stackinfo(10);
@ -146,7 +147,7 @@ void dbg::interact() {
stepinfo(); stepinfo();
while(true) { while(true) {
std::cout<<">> "; std::cout<<">> ";
std::getline(std::cin,cmd); std::getline(std::cin, cmd);
auto res=parse(cmd); auto res=parse(cmd);
if (res.size()==0) { if (res.size()==0) {
stepinfo(); stepinfo();
@ -200,11 +201,11 @@ void dbg::interact() {
void dbg::run( void dbg::run(
const codegen& gen, const codegen& gen,
const linker& linker, const linker& linker,
const std::vector<string>& argv) const std::vector<string>& argv
{ ) {
verbose=true; verbose=true;
fsize=linker.filelist().size(); fsize=linker.filelist().size();
init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv); init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
u64 count[op_ret+1]={0}; u64 count[op_ret+1]={0};
typedef void (dbg::*nafunc)(); typedef void (dbg::*nafunc)();
const nafunc oprs[]={ const nafunc oprs[]={

View File

@ -21,14 +21,14 @@ struct span {
struct for_reset { struct for_reset {
CONSOLE_SCREEN_BUFFER_INFO scr; CONSOLE_SCREEN_BUFFER_INFO scr;
for_reset() { for_reset() {
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&scr); GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &scr);
} }
} reset_ter_color; } reset_ter_color;
#endif #endif
std::ostream& back_white(std::ostream& s) { std::ostream& back_white(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0xf0); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xf0);
#else #else
s<<"\033[7m"; s<<"\033[7m";
#endif #endif
@ -37,7 +37,7 @@ std::ostream& back_white(std::ostream& s) {
std::ostream& red(std::ostream& s) { std::ostream& red(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x0c); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0c);
#else #else
s<<"\033[91;1m"; s<<"\033[91;1m";
#endif #endif
@ -46,7 +46,7 @@ std::ostream& red(std::ostream& s) {
std::ostream& cyan(std::ostream& s) { std::ostream& cyan(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x03); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x03);
#else #else
s<<"\033[36;1m"; s<<"\033[36;1m";
#endif #endif
@ -55,7 +55,7 @@ std::ostream& cyan(std::ostream& s) {
std::ostream& orange(std::ostream& s) { std::ostream& orange(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x0e); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0e);
#else #else
s<<"\033[93;1m"; s<<"\033[93;1m";
#endif #endif
@ -64,7 +64,7 @@ std::ostream& orange(std::ostream& s) {
std::ostream& white(std::ostream& s) { std::ostream& white(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x0f); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0f);
#else #else
s<<"\033[0m\033[1m"; s<<"\033[0m\033[1m";
#endif #endif
@ -73,7 +73,7 @@ std::ostream& white(std::ostream& s) {
std::ostream& reset(std::ostream& s) { std::ostream& reset(std::ostream& s) {
#ifdef _WIN32 #ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),reset_ter_color.scr.wAttributes); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), reset_ter_color.scr.wAttributes);
#else #else
s<<"\033[0m"; s<<"\033[0m";
#endif #endif
@ -99,7 +99,7 @@ private:
string identation(usize len) { string identation(usize len) {
return string(len,' '); return string(len,' ');
} }
string leftpad(u32 num,usize len) { string leftpad(u32 num, usize len) {
string tmp=std::to_string(num); string tmp=std::to_string(num);
while(tmp.length()<len) { while(tmp.length()<len) {
tmp=" "+tmp; tmp=" "+tmp;
@ -108,9 +108,9 @@ private:
} }
public: public:
error():cnt(0) {} error():cnt(0) {}
void fatal(const string&,const string&); void fatal(const string&, const string&);
void err(const string&,const string&); void err(const string&, const string&);
void err(const string&,const span&,const string&); void err(const string&, const span&, const string&);
void chkerr() const { void chkerr() const {
if (cnt) { if (cnt) {
@ -128,7 +128,7 @@ void flstream::load(const string& f) {
} }
res.clear(); res.clear();
std::ifstream in(f,std::ios::binary); std::ifstream in(f, std::ios::binary);
if (in.fail()) { if (in.fail()) {
std::cerr<<red<<"src: "<<reset<<"cannot open <"<<f<<">\n"; std::cerr<<red<<"src: "<<reset<<"cannot open <"<<f<<">\n";
std::exit(1); std::exit(1);
@ -136,12 +136,12 @@ void flstream::load(const string& f) {
while(!in.eof()) { while(!in.eof()) {
string line; string line;
std::getline(in,line); std::getline(in, line);
res.push_back(line); res.push_back(line);
} }
} }
void error::fatal(const string& stage,const string& info) { void error::fatal(const string& stage, const string& info) {
std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n"; std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n";
if (file.length()) { if (file.length()) {
std::cerr<<cyan<<" --> "<<red<<file<<reset<<"\n\n"; std::cerr<<cyan<<" --> "<<red<<file<<reset<<"\n\n";
@ -151,7 +151,7 @@ void error::fatal(const string& stage,const string& info) {
std::exit(1); std::exit(1);
} }
void error::err(const string& stage,const string& info) { void error::err(const string& stage, const string& info) {
++cnt; ++cnt;
std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n"; std::cerr<<red<<stage<<": "<<white<<info<<reset<<"\n";
if (file.length()) { if (file.length()) {
@ -161,7 +161,7 @@ void error::err(const string& stage,const string& info) {
} }
} }
void error::err(const string& stage,const span& loc,const string& info) { void error::err(const string& stage, const span& loc, const string& info) {
// load error occurred file into string lines // load error occurred file into string lines
load(loc.file); load(loc.file);
@ -174,7 +174,7 @@ void error::err(const string& stage,const span& loc,const string& info) {
const usize maxlen=std::to_string(loc.end_line).length(); const usize maxlen=std::to_string(loc.end_line).length();
const string iden=identation(maxlen); const 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) {
if (!line) { if (!line) {
continue; continue;
} }
@ -192,29 +192,29 @@ void error::err(const string& stage,const span& loc,const string& info) {
} }
const string& code=res[line-1]; const string& 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;
if (loc.begin_line==loc.end_line) { if (loc.begin_line==loc.end_line) {
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) {
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<code.size();++i) { for(u32 i=loc.begin_column; i<code.size(); ++i) {
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset; std::cerr<<red<<(code[i]=='\t'?"^^^^":"^")<<reset;
} }
} else if (loc.begin_line<line && line<loc.end_line) { } else if (loc.begin_line<line && line<loc.end_line) {
for(u32 i=0;i<code.size();++i) { for(u32 i=0; i<code.size(); ++i) {
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^"); std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
} }
} else { } else {
for(u32 i=0;i<loc.end_column;++i) { for(u32 i=0; i<loc.end_column; ++i) {
std::cerr<<red<<(code[i]=='\t'?"^^^^":"^"); std::cerr<<red<<(code[i]=='\t'?"^^^^":"^");
} }
} }

View File

@ -83,18 +83,18 @@ public:
} val; } val;
private: private:
var(u8 t,u32 pc) {type=t;val.ret=pc;} var(u8 t, u32 pc) {type=t;val.ret=pc;}
var(u8 t,i64 ct) {type=t;val.cnt=ct;} var(u8 t, i64 ct) {type=t;val.cnt=ct;}
var(u8 t,f64 n) {type=t;val.num=n;} var(u8 t, f64 n) {type=t;val.num=n;}
var(u8 t,var* p) {type=t;val.addr=p;} var(u8 t, var* p) {type=t;val.addr=p;}
var(u8 t,nas_val* p) {type=t;val.gcobj=p;} var(u8 t, nas_val* p) {type=t;val.gcobj=p;}
public: public:
var() = default; var() = default;
var(const var&) = default; var(const var&) = default;
bool operator==(const var& nr) const {return type==nr.type && val.gcobj==nr.val.gcobj;} bool operator==(const var& nr) const {return type==nr.type && val.gcobj==nr.val.gcobj;}
bool operator!=(const var& nr) const {return type!=nr.type || val.gcobj!=nr.val.gcobj;} bool operator!=(const var& nr) const {return type!=nr.type || val.gcobj!=nr.val.gcobj;}
friend std::ostream& operator<<(std::ostream&,var&); friend std::ostream& operator<<(std::ostream&, var&);
// number and string can be translated to each other // number and string can be translated to each other
f64 tonum(); f64 tonum();
@ -157,7 +157,7 @@ struct nas_func {
std::vector<var> upval; // closure std::vector<var> upval; // closure
std::unordered_map<u32,u32> keys; // parameter table, u32 begins from 1 std::unordered_map<u32,u32> keys; // parameter table, u32 begins from 1
nas_func():dpara(-1),entry(0),psize(0),lsize(0) {} nas_func(): dpara(-1), entry(0), psize(0), lsize(0) {}
void clear(); void clear();
}; };
@ -186,9 +186,9 @@ private:
void dylib_dtor(); void dylib_dtor();
public: public:
nas_obj():type(obj_type::null),ptr(nullptr) {} nas_obj(): type(obj_type::null), ptr(nullptr) {}
~nas_obj() {clear();} ~nas_obj() {clear();}
void set(obj_type,void*); void set(obj_type, void*);
void clear(); void clear();
}; };
@ -247,7 +247,7 @@ var* nas_vec::get_mem(const i32 n) {
return &elems[n>=0?n:n+size]; return &elems[n>=0?n:n+size];
} }
std::ostream& operator<<(std::ostream& out,nas_vec& vec) { std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
if (!vec.elems.size() || vec.printed) { if (!vec.elems.size() || vec.printed) {
out<<(vec.elems.size()?"[..]":"[]"); out<<(vec.elems.size()?"[..]":"[]");
return out; return out;
@ -306,7 +306,7 @@ var* nas_hash::get_mem(const string& key) {
return addr; return addr;
} }
std::ostream& operator<<(std::ostream& out,nas_hash& hash) { std::ostream& operator<<(std::ostream& out, nas_hash& hash) {
if (!hash.elems.size() || hash.printed) { if (!hash.elems.size() || hash.printed) {
out<<(hash.elems.size()?"{..}":"{}"); out<<(hash.elems.size()?"{..}":"{}");
return out; return out;
@ -328,7 +328,7 @@ void nas_func::clear() {
keys.clear(); keys.clear();
} }
void nas_obj::set(obj_type t,void* p) { void nas_obj::set(obj_type t, void* p) {
type=t; type=t;
ptr=p; ptr=p;
} }
@ -352,6 +352,7 @@ void nas_obj::file_dtor() {
} }
fclose((FILE*)ptr); fclose((FILE*)ptr);
} }
void nas_obj::dir_dtor() { void nas_obj::dir_dtor() {
#ifndef _MSC_VER #ifndef _MSC_VER
closedir((DIR*)ptr); closedir((DIR*)ptr);
@ -359,6 +360,7 @@ void nas_obj::dir_dtor() {
FindClose(ptr); FindClose(ptr);
#endif #endif
} }
void nas_obj::dylib_dtor() { void nas_obj::dylib_dtor() {
#ifdef _WIN32 #ifdef _WIN32
FreeLibrary((HMODULE)ptr); FreeLibrary((HMODULE)ptr);
@ -432,14 +434,14 @@ string var::tostr() {
return str(); return str();
} else if (type==vm_num) { } else if (type==vm_num) {
string tmp=std::to_string(num()); string tmp=std::to_string(num());
tmp.erase(tmp.find_last_not_of('0')+1,string::npos); tmp.erase(tmp.find_last_not_of('0')+1, string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,string::npos); tmp.erase(tmp.find_last_not_of('.')+1, string::npos);
return tmp; return tmp;
} }
return ""; return "";
} }
std::ostream& operator<<(std::ostream& out,var& ref) { std::ostream& operator<<(std::ostream& out, var& ref) {
switch(ref.type) { switch(ref.type) {
case vm_none: out<<"undefined"; break; case vm_none: out<<"undefined"; break;
case vm_nil: out<<"nil"; break; case vm_nil: out<<"nil"; break;
@ -459,31 +461,31 @@ bool var::objchk(obj_type objtype) {
} }
var var::none() { var var::none() {
return {vm_none,(u32)0}; return {vm_none, (u32)0};
} }
var var::nil() { var var::nil() {
return {vm_nil,(u32)0}; return {vm_nil, (u32)0};
} }
var var::ret(u32 pc) { var var::ret(u32 pc) {
return {vm_ret,pc}; return {vm_ret, pc};
} }
var var::cnt(i64 n) { var var::cnt(i64 n) {
return {vm_cnt,n}; return {vm_cnt, n};
} }
var var::num(f64 n) { var var::num(f64 n) {
return {vm_num,n}; return {vm_num, n};
} }
var var::gcobj(nas_val* p) { var var::gcobj(nas_val* p) {
return {p->type,p}; return {p->type, p};
} }
var var::addr(var* p) { var var::addr(var* p) {
return {vm_addr,p}; return {vm_addr, p};
} }
var* var::addr () {return val.addr; } var* var::addr () {return val.addr; }
@ -542,17 +544,17 @@ private:
/* gc functions */ /* gc functions */
void mark(); void mark();
void mark_context(std::vector<var>&); void mark_context(std::vector<var>&);
void mark_var(std::vector<var>&,var&); void mark_var(std::vector<var>&, var&);
inline void mark_vec(std::vector<var>&,nas_vec&); inline void mark_vec(std::vector<var>&, nas_vec&);
inline void mark_hash(std::vector<var>&,nas_hash&); inline void mark_hash(std::vector<var>&, nas_hash&);
inline void mark_func(std::vector<var>&,nas_func&); inline void mark_func(std::vector<var>&, nas_func&);
inline void mark_upval(std::vector<var>&,nas_upval&); inline void mark_upval(std::vector<var>&, nas_upval&);
inline void mark_co(std::vector<var>&,nas_co&); inline void mark_co(std::vector<var>&, nas_co&);
void sweep(); void sweep();
public: public:
void extend(u8); void extend(u8);
void init(const std::vector<string>&,const std::vector<string>&); void init(const std::vector<string>&, const std::vector<string>&);
void clear(); void clear();
void info(); void info();
var alloc(const u8); var alloc(const u8);
@ -574,7 +576,7 @@ void gc::mark() {
value.val.gcobj->mark!=gc_status::uncollected) { value.val.gcobj->mark!=gc_status::uncollected) {
continue; continue;
} }
mark_var(bfs,value); mark_var(bfs, value);
} }
} }
@ -600,31 +602,31 @@ void gc::mark_context(std::vector<var>& bfs_queue) {
bfs_queue.push_back(mctx.upvalr); bfs_queue.push_back(mctx.upvalr);
} }
void gc::mark_var(std::vector<var>& bfs_queue,var& value) { void gc::mark_var(std::vector<var>& bfs_queue, var& value) {
value.val.gcobj->mark=gc_status::found; value.val.gcobj->mark=gc_status::found;
switch(value.type) { switch(value.type) {
case vm_vec: mark_vec(bfs_queue,value.vec()); break; case vm_vec: mark_vec(bfs_queue, value.vec()); break;
case vm_hash: mark_hash(bfs_queue,value.hash()); break; case vm_hash: mark_hash(bfs_queue, value.hash()); break;
case vm_func: mark_func(bfs_queue,value.func()); break; case vm_func: mark_func(bfs_queue, value.func()); break;
case vm_upval: mark_upval(bfs_queue,value.upval()); break; case vm_upval: mark_upval(bfs_queue, value.upval()); break;
case vm_co: mark_co(bfs_queue,value.co()); break; case vm_co: mark_co(bfs_queue, value.co()); break;
default: break; default: break;
} }
} }
void gc::mark_vec(std::vector<var>& bfs_queue,nas_vec& vec) { void gc::mark_vec(std::vector<var>& bfs_queue, nas_vec& vec) {
for(auto& i:vec.elems) { for(auto& i:vec.elems) {
bfs_queue.push_back(i); bfs_queue.push_back(i);
} }
} }
void gc::mark_hash(std::vector<var>& bfs_queue,nas_hash& hash) { void gc::mark_hash(std::vector<var>& bfs_queue, nas_hash& hash) {
for(auto& i:hash.elems) { for(auto& i:hash.elems) {
bfs_queue.push_back(i.second); bfs_queue.push_back(i.second);
} }
} }
void gc::mark_func(std::vector<var>& bfs_queue,nas_func& function) { void gc::mark_func(std::vector<var>& bfs_queue, nas_func& function) {
for(auto& i:function.local) { for(auto& i:function.local) {
bfs_queue.push_back(i); bfs_queue.push_back(i);
} }
@ -633,13 +635,13 @@ void gc::mark_func(std::vector<var>& bfs_queue,nas_func& function) {
} }
} }
void gc::mark_upval(std::vector<var>& bfs_queue,nas_upval& upval) { void gc::mark_upval(std::vector<var>& bfs_queue, nas_upval& upval) {
for(auto& i:upval.elems) { for(auto& i:upval.elems) {
bfs_queue.push_back(i); bfs_queue.push_back(i);
} }
} }
void gc::mark_co(std::vector<var>& bfs_queue,nas_co& co) { void gc::mark_co(std::vector<var>& bfs_queue, nas_co& co) {
bfs_queue.push_back(co.ctx.funcr); bfs_queue.push_back(co.ctx.funcr);
bfs_queue.push_back(co.ctx.upvalr); bfs_queue.push_back(co.ctx.upvalr);
for(var* i=co.stack;i<=co.ctx.top;++i) { for(var* i=co.stack;i<=co.ctx.top;++i) {
@ -679,7 +681,7 @@ void gc::extend(u8 type) {
incr[index]*=2; incr[index]*=2;
} }
void gc::init(const std::vector<string>& s,const std::vector<string>& argv) { void gc::init(const std::vector<string>& s, const std::vector<string>& argv) {
// initialize function register // initialize function register
rctx->funcr=nil; rctx->funcr=nil;
worktime=0; worktime=0;
@ -838,13 +840,13 @@ void gc::ctxreserve() {
} }
// use to print error log and return error value // use to print error log and return error value
var nas_err(const string& err_f,const string& info) { var nas_err(const string& err_f, const string& info) {
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n"; std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
return var::none(); return var::none();
} }
// module function type // module function type
typedef var (*mod)(var*,usize,gc*); typedef var (*mod)(var*, usize, gc*);
// module function stores in tables with this type, end with {nullptr,nullptr} // module function stores in tables with this type, end with {nullptr,nullptr}
struct mod_func { struct mod_func {

View File

@ -27,29 +27,30 @@ private:
bool imptchk(const ast&); bool imptchk(const ast&);
bool exist(const string&); bool exist(const string&);
void link(ast&,ast&&); void link(ast&, ast&&);
string path(const ast&); string path(const ast&);
string findf(const string&); string findf(const string&);
ast fimpt(ast&); ast fimpt(ast&);
ast libimpt(); ast libimpt();
ast load(ast&,u16); ast load(ast&, u16);
public: public:
linker(error&); linker(error&);
const error& link(parse&,const string&,bool); const error& link(parse&, const string&, bool);
const std::vector<string>& filelist() const {return files;} const std::vector<string>& filelist() const {return files;}
}; };
linker::linker(error& e):show_path(false),lib_loaded(false),err(e) { linker::linker(error& e): show_path(false), lib_loaded(false), err(e) {
char sep=is_windows()? ';':':'; char sep=is_windows()? ';':':';
string PATH=getenv("PATH"); string PATH=getenv("PATH");
usize last=0,pos=PATH.find(sep,0); usize last=0;
usize pos=PATH.find(sep, 0);
while(pos!=string::npos) { while(pos!=string::npos) {
string dirpath=PATH.substr(last,pos-last); string dirpath=PATH.substr(last, pos-last);
if (dirpath.length()) { if (dirpath.length()) {
envpath.push_back(dirpath); envpath.push_back(dirpath);
} }
last=pos+1; last=pos+1;
pos=PATH.find(sep,last); pos=PATH.find(sep, last);
} }
if (last!=PATH.length()) { if (last!=PATH.length()) {
envpath.push_back(PATH.substr(last)); envpath.push_back(PATH.substr(last));
@ -78,7 +79,7 @@ string linker::findf(const string& fname) {
// search file // search file
for(auto& i:fpath) { for(auto& i:fpath) {
if (access(i.c_str(),F_OK)!=-1) { if (access(i.c_str(), F_OK)!=-1) {
return i; return i;
} }
} }
@ -88,14 +89,14 @@ string linker::findf(const string& fname) {
return is_windows()? findf("stl\\lib.nas"):findf("stl/lib.nas"); return is_windows()? findf("stl\\lib.nas"):findf("stl/lib.nas");
} }
if (!show_path) { if (!show_path) {
err.err("link","cannot find file <"+fname+">"); err.err("link", "cannot find file <"+fname+">");
return ""; return "";
} }
string paths=""; string paths="";
for(auto& i:fpath) { for(auto& i:fpath) {
paths+=" "+i+"\n"; paths+=" "+i+"\n";
} }
err.err("link","cannot find file <"+fname+"> in these paths:\n"+paths); err.err("link", "cannot find file <"+fname+"> in these paths:\n"+paths);
return ""; return "";
} }
@ -142,7 +143,7 @@ bool linker::exist(const string& file) {
return false; return false;
} }
void linker::link(ast& root,ast&& add_root) { void linker::link(ast& root, ast&& add_root) {
// add children of add_root to the back of root // add children of add_root to the back of root
for(auto& i:add_root.child()) { for(auto& i:add_root.child()) {
root.add(std::move(i)); root.add(std::move(i));
@ -159,7 +160,7 @@ ast linker::fimpt(ast& node) {
// avoid infinite loading loop // avoid infinite loading loop
filename=findf(filename); filename=findf(filename);
if (!filename.length() || exist(filename)) { if (!filename.length() || exist(filename)) {
return {{0,0,0,0,filename},ast_root}; return {{0, 0, 0, 0, filename}, ast_root};
} }
// start importing... // start importing...
@ -168,7 +169,7 @@ ast linker::fimpt(ast& node) {
ast tmp=std::move(par.tree()); ast tmp=std::move(par.tree());
// check if tmp has 'import' // check if tmp has 'import'
return load(tmp,files.size()-1); return load(tmp, files.size()-1);
} }
ast linker::libimpt() { ast linker::libimpt() {
@ -176,12 +177,12 @@ ast linker::libimpt() {
parse par(err); parse par(err);
string filename=findf("lib.nas"); string filename=findf("lib.nas");
if (!filename.length()) { if (!filename.length()) {
return {{0,0,0,0,filename},ast_root}; return {{0, 0, 0, 0, filename}, ast_root};
} }
// avoid infinite loading loop // avoid infinite loading loop
if (exist(filename)) { if (exist(filename)) {
return {{0,0,0,0,filename},ast_root}; return {{0, 0, 0, 0, filename}, ast_root};
} }
// start importing... // start importing...
@ -190,36 +191,36 @@ ast linker::libimpt() {
ast tmp=std::move(par.tree()); ast tmp=std::move(par.tree());
// check if tmp has 'import' // check if tmp has 'import'
return load(tmp,files.size()-1); return load(tmp, files.size()-1);
} }
ast linker::load(ast& root,u16 fileindex) { ast linker::load(ast& root, u16 fileindex) {
ast tree({0,0,0,0,files[fileindex]},ast_root); ast tree({0, 0, 0, 0, files[fileindex]}, ast_root);
if (!lib_loaded) { if (!lib_loaded) {
link(tree,libimpt()); link(tree, libimpt());
lib_loaded=true; lib_loaded=true;
} }
for(auto& i:root.child()) { for(auto& i:root.child()) {
if (imptchk(i)) { if (imptchk(i)) {
link(tree,fimpt(i)); link(tree, fimpt(i));
} else { } else {
break; break;
} }
} }
// add root to the back of tree // add root to the back of tree
ast file_head({0,0,0,0,files[fileindex]},ast_file); ast file_head({0, 0, 0, 0, files[fileindex]}, ast_file);
file_head.set_num(fileindex); file_head.set_num(fileindex);
tree.add(std::move(file_head)); tree.add(std::move(file_head));
link(tree,std::move(root)); link(tree, std::move(root));
return tree; return tree;
} }
const error& linker::link(parse& parse,const string& self,bool spath=false) { const error& linker::link(parse& parse, const string& self, bool spath=false) {
show_path=spath; show_path=spath;
// initializing // initializing
files={self}; files={self};
// scan root and import files,then generate a new ast and return to import_ast // scan root and import files,then generate a new ast and return to import_ast
// the main file's index is 0 // the main file's index is 0
parse.tree()=load(parse.tree(),0); parse.tree()=load(parse.tree(), 0);
return err; return err;
} }

View File

@ -169,7 +169,7 @@ private:
token dots(); token dots();
token calc_opr(); token calc_opr();
public: public:
lexer(error& e): line(1),column(0),ptr(0),filename(""),res(""),err(e) {} lexer(error& e): line(1), column(0), ptr(0), filename(""), res(""), err(e) {}
const error& scan(const string&); const error& scan(const string&);
const std::vector<token>& result() const {return toks;} const std::vector<token>& result() const {return toks;}
}; };
@ -223,23 +223,23 @@ void lexer::skip_note() {
void lexer::err_char() { void lexer::err_char() {
++column; ++column;
char c=res[ptr++]; char c=res[ptr++];
err.err("lexer",{line,column-1,line,column,filename},"invalid character 0x"+chrhex(c)); err.err("lexer", {line, column-1, line, column, filename}, "invalid character 0x"+chrhex(c));
err.fatal("lexer","fatal error occurred, stop"); err.fatal("lexer", "fatal error occurred, stop");
} }
void lexer::open(const string& file) { void lexer::open(const string& file) {
// check file exsits and it is a regular file // check file exsits and it is a regular file
struct stat buffer; struct stat buffer;
if (stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) { if (stat(file.c_str(), &buffer)==0 && !S_ISREG(buffer.st_mode)) {
err.err("lexer","<"+file+"> is not a regular file"); err.err("lexer", "<"+file+"> is not a regular file");
err.chkerr(); err.chkerr();
} }
// load // load
filename=file; filename=file;
std::ifstream in(file,std::ios::binary); std::ifstream in(file, std::ios::binary);
if (in.fail()) { if (in.fail()) {
err.err("lexer","failed to open <"+file+">"); err.err("lexer", "failed to open <"+file+">");
} else { } else {
err.load(file); err.load(file);
} }
@ -277,8 +277,8 @@ string lexer::utf8_gen() {
for(u32 i=1;i<tmp.size();++i) { for(u32 i=1;i<tmp.size();++i) {
utf_info+=" 0x"+chrhex(tmp[i]); utf_info+=" 0x"+chrhex(tmp[i]);
} }
err.err("lexer",{line,column-1,line,column,filename},"invalid utf-8 <"+utf_info+">"); err.err("lexer", {line, column-1, line, column, filename}, "invalid utf-8 <"+utf_info+">");
err.fatal("lexer","fatal error occurred, stop"); err.fatal("lexer", "fatal error occurred, stop");
} }
str+=tmp; str+=tmp;
column+=2; // may have some problems because not all the unicode takes 2 space column+=2; // may have some problems because not all the unicode takes 2 space
@ -299,7 +299,7 @@ token lexer::id_gen() {
} }
} }
tok type=get_type(str); tok type=get_type(str);
return {{begin_line,begin_column,line,column,filename},(type!=tok::null)?type:tok::id,str}; return {{begin_line, begin_column, line, column, filename}, (type!=tok::null)?type:tok::id, str};
} }
token lexer::num_gen() { token lexer::num_gen() {
@ -314,9 +314,9 @@ token lexer::num_gen() {
} }
column+=str.length(); column+=str.length();
if (str.length()<3) { // "0x" if (str.length()<3) { // "0x"
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`"); err.err("lexer", {begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
} }
return {{begin_line,begin_column,line,column,filename},tok::num,str}; return {{begin_line, begin_column, line, column, filename}, tok::num, str};
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number } else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
string str="0o"; string str="0o";
ptr+=2; ptr+=2;
@ -330,9 +330,9 @@ token lexer::num_gen() {
} }
column+=str.length(); column+=str.length();
if (str.length()==2 || erfmt) { if (str.length()==2 || erfmt) {
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`"); err.err("lexer", {begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
} }
return {{begin_line,begin_column,line,column,filename},tok::num,str}; return {{begin_line, begin_column, line, column, filename}, tok::num, str};
} }
// generate dec number // generate dec number
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) // dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
@ -348,8 +348,8 @@ token lexer::num_gen() {
// "xxxx." is not a correct number // "xxxx." is not a correct number
if (str.back()=='.') { if (str.back()=='.') {
column+=str.length(); column+=str.length();
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`"); err.err("lexer",{begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
return {{begin_line,begin_column,line,column,filename},tok::num,"0"}; return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
} }
} }
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) { if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
@ -363,12 +363,12 @@ token lexer::num_gen() {
// "xxxe(-|+)" is not a correct number // "xxxe(-|+)" is not a correct number
if (str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') { if (str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') {
column+=str.length(); column+=str.length();
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`"); err.err("lexer",{begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
return {{begin_line,begin_column,line,column,filename},tok::num,"0"}; return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
} }
} }
column+=str.length(); column+=str.length();
return {{begin_line,begin_column,line,column,filename},tok::num,str}; return {{begin_line, begin_column, line, column, filename}, tok::num, str};
} }
token lexer::str_gen() { token lexer::str_gen() {
@ -412,14 +412,14 @@ token lexer::str_gen() {
} }
// check if this string ends with a " or ' // check if this string ends with a " or '
if (ptr++>=res.size()) { if (ptr++>=res.size()) {
err.err("lexer",{begin_line,begin_column,line,column,filename},"get EOF when generating string"); err.err("lexer", {begin_line, begin_column, line, column, filename}, "get EOF when generating string");
return {{begin_line,begin_column,line,column,filename},tok::str,str}; return {{begin_line, begin_column, line, column, filename}, tok::str, str};
} }
++column; ++column;
if (begin=='`' && str.length()!=1) { if (begin=='`' && str.length()!=1) {
err.err("lexer",{begin_line,begin_column,line,column,filename},"\'`\' is used for string including one character"); err.err("lexer", {begin_line, begin_column, line, column, filename}, "\'`\' is used for string including one character");
} }
return {{begin_line,begin_column,line,column,filename},tok::str,str}; return {{begin_line, begin_column, line, column, filename}, tok::str, str};
} }
token lexer::single_opr() { token lexer::single_opr() {
@ -429,10 +429,10 @@ token lexer::single_opr() {
++column; ++column;
tok type=get_type(str); tok type=get_type(str);
if (type==tok::null) { if (type==tok::null) {
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid operator `"+str+"`"); err.err("lexer", {begin_line, begin_column, line, column, filename}, "invalid operator `"+str+"`");
} }
++ptr; ++ptr;
return {{begin_line,begin_column,line,column,filename},type,str}; return {{begin_line, begin_column, line, column, filename}, type, str};
} }
token lexer::dots() { token lexer::dots() {
@ -444,7 +444,7 @@ token lexer::dots() {
} }
ptr+=str.length(); ptr+=str.length();
column+=str.length(); column+=str.length();
return {{begin_line,begin_column,line,column,filename},get_type(str),str}; return {{begin_line, begin_column, line, column, filename}, get_type(str), str};
} }
token lexer::calc_opr() { token lexer::calc_opr() {
@ -456,7 +456,7 @@ token lexer::calc_opr() {
str+=res[ptr++]; str+=res[ptr++];
} }
column+=str.length(); column+=str.length();
return {{begin_line,begin_column,line,column,filename},get_type(str),str}; return {{begin_line, begin_column, line, column, filename}, get_type(str), str};
} }
const error& lexer::scan(const string& file) { const error& lexer::scan(const string& file) {
@ -495,7 +495,7 @@ const error& lexer::scan(const string& file) {
err_char(); err_char();
} }
} }
toks.push_back({{line,column,line,column,filename},tok::eof,"<eof>"}); toks.push_back({{line, column, line, column, filename}, tok::eof, "<eof>"});
res=""; res="";
return err; return err;
} }

View File

@ -138,8 +138,8 @@ private:
static const string* strs; static const string* strs;
static const string* files; static const string* files;
public: public:
codestream(const opcode& c,const u32 i):code(c),index(i) {} codestream(const opcode& c, const u32 i): code(c), index(i) {}
static void set(const f64*,const string*,const string*); static void set(const f64*, const string*, const string*);
void dump(std::ostream&) const; void dump(std::ostream&) const;
}; };
@ -182,12 +182,12 @@ void codestream::dump(std::ostream& out) const {
case op_muleqc:case op_diveqc: case op_muleqc:case op_diveqc:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<")";break; out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<")";break;
case op_lnkeqc: case op_lnkeqc:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num],16)<<")";break; out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<")";break;
case op_addecp: case op_subecp: case op_addecp: case op_subecp:
case op_mulecp: case op_divecp: case op_mulecp: case op_divecp:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<") sp-1";break; out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<") sp-1";break;
case op_lnkecp: case op_lnkecp:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num],16)<<") sp-1";break; out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<") sp-1";break;
case op_addc: case op_subc: case op_addc: case op_subc:
case op_mulc: case op_divc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_lessc: case op_leqc:
@ -215,7 +215,7 @@ void codestream::dump(std::ostream& out) const {
case op_lnkc: case op_callh: case op_lnkc: case op_callh:
case op_mcallh: case op_para: case op_mcallh: case op_para:
case op_deft: case op_dyn: case op_deft: case op_dyn:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num],16)<<")";break; out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<")";break;
default: default:
if (files) { if (files) {
out<<hex<<"0x"<<num<<dec; out<<hex<<"0x"<<num<<dec;
@ -227,7 +227,7 @@ 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

@ -107,8 +107,8 @@ private:
}; };
void die(const span&,string); void die(const span&,string);
void next() {++ptr;}; void next() {++ptr;}
void match(tok type,const char* info=nullptr); void match(tok type, const char* info=nullptr);
bool lookahead(tok); bool lookahead(tok);
bool is_call(tok); bool is_call(tok);
bool check_comma(const tok*); bool check_comma(const tok*);
@ -163,9 +163,9 @@ private:
ast ret_expr(); ast ret_expr();
public: public:
parse(error& e): parse(error& e):
ptr(0),in_func(0),in_loop(0), ptr(0), in_func(0), in_loop(0),
toks(nullptr), toks(nullptr),
root({0,0,0,0,""},ast_root), root({0, 0, 0, 0, ""}, ast_root),
err(e) {} err(e) {}
const error& compile(const lexer&); const error& compile(const lexer&);
ast& tree() {return root;} ast& tree() {return root;}
@ -176,35 +176,35 @@ const error& parse::compile(const lexer& lexer) {
toks=lexer.result().data(); toks=lexer.result().data();
ptr=in_func=in_loop=0; ptr=in_func=in_loop=0;
root={toks[0].loc,ast_root}; root={toks[0].loc, ast_root};
while(!lookahead(tok::eof)) { while(!lookahead(tok::eof)) {
root.add(expr()); root.add(expr());
if (lookahead(tok::semi)) { if (lookahead(tok::semi)) {
match(tok::semi); match(tok::semi);
} else if (need_semi_check(root.child().back()) && !lookahead(tok::eof)) { } else if (need_semi_check(root.child().back()) && !lookahead(tok::eof)) {
// the last expression can be recognized without semi // the last expression can be recognized without semi
die(prevspan,"expected \";\""); die(prevspan, "expected \";\"");
} }
} }
root.update_span(); root.update_span();
return err; return err;
} }
void parse::die(const span& loc,string info) { void parse::die(const span& loc, string info) {
err.err("parse",loc,info); err.err("parse", loc, info);
} }
void parse::match(tok type,const char* info) { void parse::match(tok type,const char* info) {
if (!lookahead(type)) { if (!lookahead(type)) {
if (info) { if (info) {
die(thisspan,info); die(thisspan, info);
return; return;
} }
switch(type) { switch(type) {
case tok::num:die(thisspan,"expected number"); break; case tok::num:die(thisspan, "expected number"); break;
case tok::str:die(thisspan,"expected string"); break; case tok::str:die(thisspan, "expected string"); break;
case tok::id: die(thisspan,"expected identifier");break; case tok::id: die(thisspan, "expected identifier");break;
default: die(thisspan,"expected '"+tokname.at(type)+"'"); break; default: die(thisspan, "expected '"+tokname.at(type)+"'"); break;
} }
return; return;
} }
@ -225,7 +225,7 @@ bool parse::is_call(tok type) {
bool parse::check_comma(const tok* panic_set) { bool parse::check_comma(const tok* panic_set) {
for(u32 i=0;panic_set[i]!=tok::null;++i) { for(u32 i=0;panic_set[i]!=tok::null;++i) {
if (lookahead(panic_set[i])) { if (lookahead(panic_set[i])) {
die(prevspan,"expected ',' between scalars"); die(prevspan, "expected ',' between scalars");
return true; return true;
} }
} }
@ -233,7 +233,7 @@ bool parse::check_comma(const tok* panic_set) {
} }
bool parse::check_tuple() { bool parse::check_tuple() {
u32 check_ptr=ptr,curve=1,bracket=0,brace=0; u32 check_ptr=ptr, curve=1, bracket=0, brace=0;
while(toks[++check_ptr].type!=tok::eof && curve) { while(toks[++check_ptr].type!=tok::eof && curve) {
switch(toks[check_ptr].type) { switch(toks[check_ptr].type) {
case tok::lcurve: ++curve; break; case tok::lcurve: ++curve; break;
@ -277,7 +277,7 @@ bool parse::check_func_end(const ast& node) {
bool parse::check_special_call() { bool parse::check_special_call() {
// special call means like this: function_name(a:1,b:2,c:3); // special call means like this: function_name(a:1,b:2,c:3);
u32 check_ptr=ptr,curve=1,bracket=0,brace=0; u32 check_ptr=ptr, curve=1, bracket=0, brace=0;
while(toks[++check_ptr].type!=tok::eof && curve) { while(toks[++check_ptr].type!=tok::eof && curve) {
switch(toks[check_ptr].type) { switch(toks[check_ptr].type) {
case tok::lcurve: ++curve; break; case tok::lcurve: ++curve; break;
@ -308,36 +308,36 @@ bool parse::need_semi_check(const ast& node) {
} }
ast parse::null() { ast parse::null() {
return {toks[ptr].loc,ast_null}; return {toks[ptr].loc, ast_null};
} }
ast parse::nil() { ast parse::nil() {
return {toks[ptr].loc,ast_nil}; return {toks[ptr].loc, ast_nil};
} }
ast parse::num() { ast parse::num() {
ast node(toks[ptr].loc,ast_num); ast node(toks[ptr].loc, ast_num);
node.set_num(str2num(toks[ptr].str.c_str())); node.set_num(str2num(toks[ptr].str.c_str()));
match(tok::num); match(tok::num);
return node; return node;
} }
ast parse::str() { ast parse::str() {
ast node(toks[ptr].loc,ast_str); ast node(toks[ptr].loc, ast_str);
node.set_str(toks[ptr].str); node.set_str(toks[ptr].str);
match(tok::str); match(tok::str);
return node; return node;
} }
ast parse::id() { ast parse::id() {
ast node(toks[ptr].loc,ast_id); ast node(toks[ptr].loc, ast_id);
node.set_str(toks[ptr].str); node.set_str(toks[ptr].str);
match(tok::id); match(tok::id);
return node; return node;
} }
ast parse::bools() { ast parse::bools() {
ast node(toks[ptr].loc,ast_bool); ast node(toks[ptr].loc, ast_bool);
node.set_str(toks[ptr].str); node.set_str(toks[ptr].str);
if (lookahead(tok::tktrue)) { if (lookahead(tok::tktrue)) {
match(tok::tktrue); match(tok::tktrue);
@ -357,7 +357,7 @@ ast parse::vec() {
tok::func,tok::var,tok::lcurve,tok::floater, tok::func,tok::var,tok::lcurve,tok::floater,
tok::lbrace,tok::lbracket,tok::null tok::lbrace,tok::lbracket,tok::null
}; };
ast node(toks[ptr].loc,ast_vec); ast node(toks[ptr].loc, ast_vec);
match(tok::lbracket); match(tok::lbracket);
while(!lookahead(tok::rbracket)) { while(!lookahead(tok::rbracket)) {
node.add(calc()); node.add(calc());
@ -370,36 +370,36 @@ ast parse::vec() {
} }
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rbracket,"expected ']' when generating vector"); match(tok::rbracket, "expected ']' when generating vector");
return node; return node;
} }
ast parse::hash() { ast parse::hash() {
ast node(toks[ptr].loc,ast_hash); ast node(toks[ptr].loc, ast_hash);
match(tok::lbrace); match(tok::lbrace);
while(!lookahead(tok::rbrace)) { while(!lookahead(tok::rbrace)) {
node.add(pair()); node.add(pair());
if (lookahead(tok::comma)) { if (lookahead(tok::comma)) {
match(tok::comma); match(tok::comma);
} else if (lookahead(tok::id) || lookahead(tok::str)) { // first set of hashmember } else if (lookahead(tok::id) || lookahead(tok::str)) { // first set of hashmember
die(prevspan,"expected ',' between hash members"); die(prevspan, "expected ',' between hash members");
} else { } else {
break; break;
} }
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rbrace,"expected '}' when generating hash"); match(tok::rbrace, "expected '}' when generating hash");
return node; return node;
} }
ast parse::pair() { ast parse::pair() {
ast node(toks[ptr].loc,ast_pair); ast node(toks[ptr].loc, ast_pair);
if (lookahead(tok::id)) { if (lookahead(tok::id)) {
node.add(id()); node.add(id());
} else if (lookahead(tok::str)) { } else if (lookahead(tok::str)) {
node.add(str()); node.add(str());
} else { } else {
match(tok::id,"expected hashmap key"); match(tok::id, "expected hashmap key");
} }
match(tok::colon); match(tok::colon);
node.add(calc()); node.add(calc());
@ -409,7 +409,7 @@ ast parse::pair() {
ast parse::func() { ast parse::func() {
++in_func; ++in_func;
ast node(toks[ptr].loc,ast_func); ast node(toks[ptr].loc, ast_func);
match(tok::func); match(tok::func);
if (lookahead(tok::lcurve)) { if (lookahead(tok::lcurve)) {
node.add(params()); node.add(params());
@ -423,12 +423,12 @@ ast parse::func() {
} }
ast parse::params() { ast parse::params() {
ast node(toks[ptr].loc,ast_params); ast node(toks[ptr].loc, ast_params);
match(tok::lcurve); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
ast tmp=id(); ast tmp=id();
if (lookahead(tok::eq) || lookahead(tok::ellipsis)) { if (lookahead(tok::eq) || lookahead(tok::ellipsis)) {
ast special_arg(toks[ptr].loc,ast_null); ast special_arg(toks[ptr].loc, ast_null);
if (lookahead(tok::eq)) { if (lookahead(tok::eq)) {
match(tok::eq); match(tok::eq);
special_arg=std::move(tmp); special_arg=std::move(tmp);
@ -446,13 +446,13 @@ ast parse::params() {
if (lookahead(tok::comma)) { if (lookahead(tok::comma)) {
match(tok::comma); match(tok::comma);
} else if (lookahead(tok::id)) { // first set of identifier } else if (lookahead(tok::id)) { // first set of identifier
die(prevspan,"expected ',' between identifiers"); die(prevspan, "expected ',' between identifiers");
} else { } else {
break; break;
} }
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve,"expected ')' after parameter list"); match(tok::rcurve, "expected ')' after parameter list");
return node; return node;
} }
@ -465,10 +465,10 @@ ast parse::lcurve_expr() {
ast parse::expr() { ast parse::expr() {
tok type=toks[ptr].type; tok type=toks[ptr].type;
if ((type==tok::brk || type==tok::cont) && !in_loop) { if ((type==tok::brk || type==tok::cont) && !in_loop) {
die(thisspan,"must use break/continue in loops"); die(thisspan, "must use break/continue in loops");
} }
if (type==tok::ret && !in_func) { if (type==tok::ret && !in_func) {
die(thisspan,"must use return in functions"); die(thisspan, "must use return in functions");
} }
switch(type) { switch(type) {
case tok::tknil: case tok::tknil:
@ -495,21 +495,21 @@ ast parse::expr() {
case tok::ret: return ret_expr(); break; case tok::ret: return ret_expr(); break;
case tok::semi: break; case tok::semi: break;
default: default:
die(thisspan,"incorrect token <"+toks[ptr].str+">"); die(thisspan, "incorrect token <"+toks[ptr].str+">");
next(); next();
break; break;
} }
// unreachable // unreachable
return {toks[ptr].loc,ast_null}; return {toks[ptr].loc, ast_null};
} }
ast parse::exprs() { ast parse::exprs() {
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected expression block"); die(thisspan, "expected expression block");
return null(); return null();
} }
ast node(toks[ptr].loc,ast_block); ast node(toks[ptr].loc, ast_block);
if (lookahead(tok::lbrace)) { if (lookahead(tok::lbrace)) {
match(tok::lbrace); match(tok::lbrace);
while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) { while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) {
@ -518,10 +518,10 @@ ast parse::exprs() {
match(tok::semi); match(tok::semi);
} else if (need_semi_check(node.child().back()) && !lookahead(tok::rbrace)) { } else if (need_semi_check(node.child().back()) && !lookahead(tok::rbrace)) {
// the last expression can be recognized without semi // the last expression can be recognized without semi
die(prevspan,"expected ';'"); die(prevspan, "expected ';'");
} }
} }
match(tok::rbrace,"expected '}' when generating expressions"); match(tok::rbrace, "expected '}' when generating expressions");
} else { } else {
node.add(expr()); node.add(expr());
if (lookahead(tok::semi)) if (lookahead(tok::semi))
@ -535,7 +535,7 @@ ast parse::calc() {
ast node=bitwise_or(); ast node=bitwise_or();
if (lookahead(tok::quesmark)) { if (lookahead(tok::quesmark)) {
// trinocular calculation // trinocular calculation
ast tmp(toks[ptr].loc,ast_trino); ast tmp(toks[ptr].loc, ast_trino);
match(tok::quesmark); match(tok::quesmark);
tmp.add(std::move(node)); tmp.add(std::move(node));
tmp.add(calc()); tmp.add(calc());
@ -544,13 +544,13 @@ ast parse::calc() {
node=std::move(tmp); node=std::move(tmp);
} else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) { } else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) {
// tok::eq~tok::lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26 // tok::eq~tok::lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26
ast tmp(toks[ptr].loc,(u32)toks[ptr].type-(u32)tok::eq+ast_equal); ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::eq+ast_equal);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add(calc()); tmp.add(calc());
node=std::move(tmp); node=std::move(tmp);
} else if (toks[ptr].type==tok::btandeq || toks[ptr].type==tok::btoreq || toks[ptr].type==tok::btxoreq) { } else if (toks[ptr].type==tok::btandeq || toks[ptr].type==tok::btoreq || toks[ptr].type==tok::btxoreq) {
ast tmp(toks[ptr].loc,(u32)toks[ptr].type-(u32)tok::btandeq+ast_btandeq); ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::btandeq+ast_btandeq);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add(calc()); tmp.add(calc());
@ -563,7 +563,7 @@ ast parse::calc() {
ast parse::bitwise_or() { ast parse::bitwise_or() {
ast node=bitwise_xor(); ast node=bitwise_xor();
while(lookahead(tok::btor)) { while(lookahead(tok::btor)) {
ast tmp(toks[ptr].loc,ast_bitor); ast tmp(toks[ptr].loc, ast_bitor);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(tok::btor); match(tok::btor);
tmp.add(bitwise_xor()); tmp.add(bitwise_xor());
@ -577,7 +577,7 @@ ast parse::bitwise_or() {
ast parse::bitwise_xor() { ast parse::bitwise_xor() {
ast node=bitwise_and(); ast node=bitwise_and();
while(lookahead(tok::btxor)) { while(lookahead(tok::btxor)) {
ast tmp(toks[ptr].loc,ast_bitxor); ast tmp(toks[ptr].loc, ast_bitxor);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(tok::btxor); match(tok::btxor);
tmp.add(bitwise_and()); tmp.add(bitwise_and());
@ -591,7 +591,7 @@ ast parse::bitwise_xor() {
ast parse::bitwise_and() { ast parse::bitwise_and() {
ast node=or_expr(); ast node=or_expr();
while(lookahead(tok::btand)) { while(lookahead(tok::btand)) {
ast tmp(toks[ptr].loc,ast_bitand); ast tmp(toks[ptr].loc, ast_bitand);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(tok::btand); match(tok::btand);
tmp.add(or_expr()); tmp.add(or_expr());
@ -605,7 +605,7 @@ ast parse::bitwise_and() {
ast parse::or_expr() { ast parse::or_expr() {
ast node=and_expr(); ast node=and_expr();
while(lookahead(tok::opor)) { while(lookahead(tok::opor)) {
ast tmp(toks[ptr].loc,ast_or); ast tmp(toks[ptr].loc, ast_or);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(tok::opor); match(tok::opor);
tmp.add(and_expr()); tmp.add(and_expr());
@ -619,7 +619,7 @@ ast parse::or_expr() {
ast parse::and_expr() { ast parse::and_expr() {
ast node=cmp_expr(); ast node=cmp_expr();
while(lookahead(tok::opand)) { while(lookahead(tok::opand)) {
ast tmp(toks[ptr].loc,ast_and); ast tmp(toks[ptr].loc, ast_and);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(tok::opand); match(tok::opand);
tmp.add(cmp_expr()); tmp.add(cmp_expr());
@ -634,7 +634,7 @@ ast parse::cmp_expr() {
ast node=additive_expr(); ast node=additive_expr();
while(tok::cmpeq<=toks[ptr].type && toks[ptr].type<=tok::geq) { while(tok::cmpeq<=toks[ptr].type && toks[ptr].type<=tok::geq) {
// tok::cmpeq~tok::geq is 43~48,ast_cmpeq~ast_geq is 27~32 // tok::cmpeq~tok::geq is 43~48,ast_cmpeq~ast_geq is 27~32
ast tmp(toks[ptr].loc,(u32)toks[ptr].type-(u32)tok::cmpeq+ast_cmpeq); ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::cmpeq+ast_cmpeq);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add(additive_expr()); tmp.add(additive_expr());
@ -648,7 +648,7 @@ ast parse::cmp_expr() {
ast parse::additive_expr() { ast parse::additive_expr() {
ast node=multive_expr(); ast node=multive_expr();
while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::floater)) { while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::floater)) {
ast tmp(toks[ptr].loc,ast_null); ast tmp(toks[ptr].loc, ast_null);
switch(toks[ptr].type) { switch(toks[ptr].type) {
case tok::add: tmp.set_type(ast_add); break; case tok::add: tmp.set_type(ast_add); break;
case tok::sub: tmp.set_type(ast_sub); break; case tok::sub: tmp.set_type(ast_sub); break;
@ -668,7 +668,7 @@ ast parse::additive_expr() {
ast parse::multive_expr() { ast parse::multive_expr() {
ast node=(lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar(); ast node=(lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar();
while(lookahead(tok::mult) || lookahead(tok::div)) { while(lookahead(tok::mult) || lookahead(tok::div)) {
ast tmp(toks[ptr].loc,(u32)toks[ptr].type-(u32)tok::mult+ast_mult); ast tmp(toks[ptr].loc, (u32)toks[ptr].type-(u32)tok::mult+ast_mult);
tmp.add(std::move(node)); tmp.add(std::move(node));
match(toks[ptr].type); match(toks[ptr].type);
tmp.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar()); tmp.add((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar());
@ -693,7 +693,7 @@ ast parse::unary() {
} }
ast parse::scalar() { ast parse::scalar() {
ast node(toks[ptr].loc,ast_null); ast node(toks[ptr].loc, ast_null);
if (lookahead(tok::tknil)) { if (lookahead(tok::tknil)) {
node=nil(); node=nil();
match(tok::tknil); match(tok::tknil);
@ -715,7 +715,7 @@ ast parse::scalar() {
const auto& loc=toks[ptr].loc; const auto& loc=toks[ptr].loc;
match(tok::lcurve); match(tok::lcurve);
node=calc(); node=calc();
node.set_begin(loc.begin_line,loc.begin_column); node.set_begin(loc.begin_line, loc.begin_column);
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve); match(tok::rcurve);
} else if (lookahead(tok::var)) { } else if (lookahead(tok::var)) {
@ -725,13 +725,13 @@ ast parse::scalar() {
match(tok::eq); match(tok::eq);
node.add(calc()); node.add(calc());
} else { } else {
die(thisspan,"expected scalar"); die(thisspan, "expected scalar");
return node; return node;
} }
// check call and avoid ambiguous syntax // check call and avoid ambiguous syntax
if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) { if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) {
ast tmp=std::move(node); ast tmp=std::move(node);
node={toks[ptr].loc,ast_call}; node={toks[ptr].loc, ast_call};
node.add(std::move(tmp)); node.add(std::move(tmp));
while(is_call(toks[ptr].type)) { while(is_call(toks[ptr].type)) {
node.add(call_scalar()); node.add(call_scalar());
@ -749,15 +749,15 @@ ast parse::call_scalar() {
default: break; default: break;
} }
// unreachable // unreachable
return {toks[ptr].loc,ast_nil}; return {toks[ptr].loc, ast_nil};
} }
ast parse::callh() { ast parse::callh() {
ast node(toks[ptr].loc,ast_callh); ast node(toks[ptr].loc, ast_callh);
match(tok::dot); match(tok::dot);
node.set_str(toks[ptr].str); node.set_str(toks[ptr].str);
node.set_end(toks[ptr].loc.end_line,toks[ptr].loc.end_column); node.set_end(toks[ptr].loc.end_line, toks[ptr].loc.end_column);
match(tok::id,"expected hashmap key"); // get key match(tok::id, "expected hashmap key"); // get key
return node; return node;
} }
@ -771,7 +771,7 @@ ast parse::callv() {
tok::func,tok::var,tok::lcurve,tok::floater, tok::func,tok::var,tok::lcurve,tok::floater,
tok::lbrace,tok::lbracket,tok::colon,tok::null tok::lbrace,tok::lbracket,tok::colon,tok::null
}; };
ast node(toks[ptr].loc,ast_callv); ast node(toks[ptr].loc, ast_callv);
match(tok::lbracket); match(tok::lbracket);
while(!lookahead(tok::rbracket)) { while(!lookahead(tok::rbracket)) {
node.add(subvec()); node.add(subvec());
@ -784,10 +784,10 @@ ast parse::callv() {
} }
} }
if (node.size()==0) { if (node.size()==0) {
die(thisspan,"expected index value"); die(thisspan, "expected index value");
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rbracket,"expected ']' when calling vector"); match(tok::rbracket, "expected ']' when calling vector");
return node; return node;
} }
@ -801,7 +801,7 @@ ast parse::callf() {
tok::func,tok::var,tok::lcurve,tok::floater, tok::func,tok::var,tok::lcurve,tok::floater,
tok::lbrace,tok::lbracket,tok::null tok::lbrace,tok::lbracket,tok::null
}; };
ast node(toks[ptr].loc,ast_callf); ast node(toks[ptr].loc, ast_callf);
bool special_call=check_special_call(); bool special_call=check_special_call();
match(tok::lcurve); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
@ -814,14 +814,14 @@ ast parse::callf() {
break; break;
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve,"expected ')' when calling function"); match(tok::rcurve, "expected ')' when calling function");
return node; return node;
} }
ast parse::subvec() { ast parse::subvec() {
ast node=lookahead(tok::colon)?nil():calc(); ast node=lookahead(tok::colon)?nil():calc();
if (lookahead(tok::colon)) { if (lookahead(tok::colon)) {
ast tmp(toks[ptr].loc,ast_subvec); ast tmp(toks[ptr].loc, ast_subvec);
match(tok::colon); match(tok::colon);
tmp.add(std::move(node)); tmp.add(std::move(node));
tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc()); tmp.add((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc());
@ -832,13 +832,13 @@ ast parse::subvec() {
} }
ast parse::definition() { ast parse::definition() {
ast node(toks[ptr].loc,ast_def); ast node(toks[ptr].loc, ast_def);
if (lookahead(tok::var)) { if (lookahead(tok::var)) {
match(tok::var); match(tok::var);
switch(toks[ptr].type) { switch(toks[ptr].type) {
case tok::id: node.add(id());break; case tok::id: node.add(id());break;
case tok::lcurve: node.add(outcurve_def());break; case tok::lcurve: node.add(outcurve_def());break;
default: die(thisspan,"expected identifier");break; default: die(thisspan, "expected identifier");break;
} }
} else if (lookahead(tok::lcurve)) { } else if (lookahead(tok::lcurve)) {
node.add(incurve_def()); node.add(incurve_def());
@ -860,7 +860,7 @@ ast parse::incurve_def() {
ast node=multi_id(); ast node=multi_id();
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve); match(tok::rcurve);
node.set_begin(loc.begin_line,loc.begin_column); node.set_begin(loc.begin_line, loc.begin_column);
return node; return node;
} }
@ -870,12 +870,12 @@ ast parse::outcurve_def() {
ast node=multi_id(); ast node=multi_id();
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve); match(tok::rcurve);
node.set_begin(loc.begin_line,loc.begin_column); node.set_begin(loc.begin_line, loc.begin_column);
return node; return node;
} }
ast parse::multi_id() { ast parse::multi_id() {
ast node(toks[ptr].loc,ast_multi_id); ast node(toks[ptr].loc, ast_multi_id);
while(!lookahead(tok::eof)) { while(!lookahead(tok::eof)) {
// only identifier is allowed here // only identifier is allowed here
// but we check it at codegen stage // but we check it at codegen stage
@ -883,7 +883,7 @@ ast parse::multi_id() {
if (lookahead(tok::comma)) { if (lookahead(tok::comma)) {
match(tok::comma); match(tok::comma);
} else if (lookahead(tok::id)) { // first set of identifier } else if (lookahead(tok::id)) { // first set of identifier
die(prevspan,"expected ',' between identifiers"); die(prevspan, "expected ',' between identifiers");
} else { } else {
break; break;
} }
@ -900,7 +900,7 @@ ast parse::multi_scalar() {
tok::func,tok::var,tok::lcurve,tok::floater, tok::func,tok::var,tok::lcurve,tok::floater,
tok::lbrace,tok::lbracket,tok::null tok::lbrace,tok::lbracket,tok::null
}; };
ast node(toks[ptr].loc,ast_tuple); ast node(toks[ptr].loc, ast_tuple);
match(tok::lcurve); match(tok::lcurve);
while(!lookahead(tok::rcurve)) { while(!lookahead(tok::rcurve)) {
node.add(calc()); node.add(calc());
@ -913,16 +913,16 @@ ast parse::multi_scalar() {
} }
} }
node.update_span(thisspan); node.update_span(thisspan);
match(tok::rcurve,"expected ')' after multi-scalar"); match(tok::rcurve, "expected ')' after multi-scalar");
return node; return node;
} }
ast parse::multi_assgin() { ast parse::multi_assgin() {
ast node(toks[ptr].loc,ast_multi_assign); ast node(toks[ptr].loc, ast_multi_assign);
node.add(multi_scalar()); node.add(multi_scalar());
match(tok::eq); match(tok::eq);
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected value list"); die(thisspan, "expected value list");
return node; return node;
} }
if (lookahead(tok::lcurve)) { if (lookahead(tok::lcurve)) {
@ -936,7 +936,7 @@ ast parse::multi_assgin() {
ast parse::loop() { ast parse::loop() {
++in_loop; ++in_loop;
ast node(toks[ptr].loc,ast_null); ast node(toks[ptr].loc, ast_null);
switch(toks[ptr].type) { switch(toks[ptr].type) {
case tok::rwhile: node=while_loop(); break; case tok::rwhile: node=while_loop(); break;
case tok::rfor: node=for_loop(); break; case tok::rfor: node=for_loop(); break;
@ -949,7 +949,7 @@ ast parse::loop() {
} }
ast parse::while_loop() { ast parse::while_loop() {
ast node(toks[ptr].loc,ast_while); ast node(toks[ptr].loc, ast_while);
match(tok::rwhile); match(tok::rwhile);
match(tok::lcurve); match(tok::lcurve);
node.add(calc()); node.add(calc());
@ -960,12 +960,12 @@ ast parse::while_loop() {
} }
ast parse::for_loop() { ast parse::for_loop() {
ast node(toks[ptr].loc,ast_for); ast node(toks[ptr].loc, ast_for);
match(tok::rfor); match(tok::rfor);
match(tok::lcurve); match(tok::lcurve);
// first expression // first expression
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected definition"); die(thisspan, "expected definition");
} }
if (lookahead(tok::semi)) { if (lookahead(tok::semi)) {
node.add(null()); node.add(null());
@ -976,20 +976,20 @@ ast parse::for_loop() {
} else { } else {
node.add(calc()); node.add(calc());
} }
match(tok::semi,"expected ';' in for(;;)"); match(tok::semi, "expected ';' in for(;;)");
// conditional expression // conditional expression
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected conditional expr"); die(thisspan, "expected conditional expr");
} }
if (lookahead(tok::semi)) { if (lookahead(tok::semi)) {
node.add(null()); node.add(null());
} else { } else {
node.add(calc()); node.add(calc());
} }
match(tok::semi,"expected ';' in for(;;)"); match(tok::semi, "expected ';' in for(;;)");
//after loop expression //after loop expression
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected calculation"); die(thisspan, "expected calculation");
} }
if (lookahead(tok::rcurve)) { if (lookahead(tok::rcurve)) {
node.add(null()); node.add(null());
@ -1003,7 +1003,7 @@ ast parse::for_loop() {
} }
ast parse::forei_loop() { ast parse::forei_loop() {
ast node(toks[ptr].loc,ast_null); ast node(toks[ptr].loc, ast_null);
switch(toks[ptr].type) { switch(toks[ptr].type) {
case tok::forindex:node.set_type(ast_forindex);match(tok::forindex);break; case tok::forindex:node.set_type(ast_forindex);match(tok::forindex);break;
case tok::foreach: node.set_type(ast_foreach); match(tok::foreach); break; case tok::foreach: node.set_type(ast_foreach); match(tok::foreach); break;
@ -1013,12 +1013,12 @@ ast parse::forei_loop() {
// first expression // first expression
// foreach/forindex must have an iterator to loop through // foreach/forindex must have an iterator to loop through
if (!lookahead(tok::var) && !lookahead(tok::id)) { if (!lookahead(tok::var) && !lookahead(tok::id)) {
die(thisspan,"expected iterator"); die(thisspan, "expected iterator");
} }
node.add(iter_gen()); node.add(iter_gen());
match(tok::semi,"expected ';' in foreach/forindex(iter;vector)"); match(tok::semi, "expected ';' in foreach/forindex(iter;vector)");
if (lookahead(tok::eof)) { if (lookahead(tok::eof)) {
die(thisspan,"expected vector"); die(thisspan, "expected vector");
} }
node.add(calc()); node.add(calc());
match(tok::rcurve); match(tok::rcurve);
@ -1028,7 +1028,7 @@ ast parse::forei_loop() {
} }
ast parse::iter_gen() { ast parse::iter_gen() {
ast node(toks[ptr].loc,ast_null); ast node(toks[ptr].loc, ast_null);
if (lookahead(tok::var)) { if (lookahead(tok::var)) {
match(tok::var); match(tok::var);
node.set_type(ast_iter); node.set_type(ast_iter);
@ -1045,10 +1045,10 @@ ast parse::iter_gen() {
} }
ast parse::cond() { ast parse::cond() {
ast node(toks[ptr].loc,ast_cond); ast node(toks[ptr].loc, ast_cond);
// generate if // generate if
ast ifnode(toks[ptr].loc,ast_if); ast ifnode(toks[ptr].loc, ast_if);
match(tok::rif); match(tok::rif);
match(tok::lcurve); match(tok::lcurve);
ifnode.add(calc()); ifnode.add(calc());
@ -1059,7 +1059,7 @@ ast parse::cond() {
// generate elsif // generate elsif
while(lookahead(tok::elsif)) { while(lookahead(tok::elsif)) {
ast elsifnode(toks[ptr].loc,ast_elsif); ast elsifnode(toks[ptr].loc, ast_elsif);
match(tok::elsif); match(tok::elsif);
match(tok::lcurve); match(tok::lcurve);
elsifnode.add(calc()); elsifnode.add(calc());
@ -1071,7 +1071,7 @@ ast parse::cond() {
// generate else // generate else
if (lookahead(tok::relse)) { if (lookahead(tok::relse)) {
ast elsenode(toks[ptr].loc,ast_else); ast elsenode(toks[ptr].loc, ast_else);
match(tok::relse); match(tok::relse);
elsenode.add(exprs()); elsenode.add(exprs());
elsenode.update_span(); elsenode.update_span();
@ -1082,19 +1082,19 @@ ast parse::cond() {
} }
ast parse::continue_expr() { ast parse::continue_expr() {
ast node(toks[ptr].loc,ast_continue); ast node(toks[ptr].loc, ast_continue);
match(tok::cont); match(tok::cont);
return node; return node;
} }
ast parse::break_expr() { ast parse::break_expr() {
ast node(toks[ptr].loc,ast_break); ast node(toks[ptr].loc, ast_break);
match(tok::brk); match(tok::brk);
return node; return node;
} }
ast parse::ret_expr() { ast parse::ret_expr() {
ast node(toks[ptr].loc,ast_ret); ast node(toks[ptr].loc, ast_ret);
match(tok::ret); match(tok::ret);
tok type=toks[ptr].type; tok type=toks[ptr].type;
if (type==tok::tknil || type==tok::num || if (type==tok::tknil || type==tok::num ||

View File

@ -141,7 +141,7 @@ protected:
public: public:
/* constructor of vm instance */ /* constructor of vm instance */
vm():ngc(&ctx),verbose(false) {} vm(): ngc(&ctx), verbose(false) {}
/* execution entry */ /* execution entry */
void run( void run(
@ -229,7 +229,7 @@ void vm::traceback() {
} }
ret.push(ctx.pc); // store the position program crashed ret.push(ctx.pc); // store the position program crashed
std::clog<<"trace back ("<<(ngc.rctx->stack==stack?"main":"coroutine")<<")\n"; std::clog<<"trace back ("<<(ngc.rctx->stack==stack?"main":"coroutine")<<")\n";
codestream::set(cnum,cstr,files); codestream::set(cnum, cstr, files);
for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) { for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) {
if ((p=ret.top())==prev) { if ((p=ret.top())==prev) {
++same; ++same;
@ -365,7 +365,7 @@ void vm::o_intg() {
} }
void vm::o_intl() { void vm::o_intl() {
ctx.top[0].func().local.resize(imm[ctx.pc],nil); ctx.top[0].func().local.resize(imm[ctx.pc], nil);
ctx.top[0].func().lsize=imm[ctx.pc]; ctx.top[0].func().lsize=imm[ctx.pc];
} }
@ -817,7 +817,7 @@ void vm::o_callfv() {
// collected incorrectly // collected incorrectly
ctx.top=local+func.lsize; ctx.top=local+func.lsize;
u32 min_size=(std::min)(psize,argc); // avoid error in MSVC u32 min_size=(std::min)(psize, argc); // avoid error in MSVC
for(u32 i=min_size;i>=1;--i) { // load arguments for(u32 i=min_size;i>=1;--i) { // load arguments
local[i]=local[i-1]; local[i]=local[i-1];
} }
@ -890,7 +890,7 @@ void vm::o_callb() {
// if running a builtin function about coroutine // if running a builtin function about coroutine
// (top) will be set to another context.top, instead of main_context.top // (top) will be set to another context.top, instead of main_context.top
var tmp=(*builtin[imm[ctx.pc]].func)(ctx.localr,ngc); var tmp=(*builtin[imm[ctx.pc]].func)(ctx.localr, ngc);
// so we use tmp variable to store this return value // so we use tmp variable to store this return value
// and set it to top[0] later // and set it to top[0] later
@ -1073,9 +1073,10 @@ void vm::run(
const codegen& gen, const codegen& gen,
const linker& linker, const linker& linker,
const std::vector<string>& argv, const std::vector<string>& argv,
const bool detail) { const bool detail
) {
verbose=detail; verbose=detail;
init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv); init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
#ifndef _MSC_VER #ifndef _MSC_VER
const void* oprs[]={ const void* oprs[]={
&&vmexit, &&intg, &&intl, &&loadg, &&vmexit, &&intg, &&intl, &&loadg,