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

View File

@ -8,7 +8,7 @@ double fibonaci(double x) {
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) {
return nas_err("fib","lack arguments");
}
@ -16,7 +16,7 @@ var fib(var* args,usize size,gc* ngc) {
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) {
return nas_err("quick_fib","lack arguments");
}

View File

@ -18,21 +18,21 @@ private:
public:
noecho_input() {
#ifndef _WIN32
tcflush(0,TCIOFLUSH);
tcgetattr(0,&init_termios);
tcflush(0, TCIOFLUSH);
tcgetattr(0, &init_termios);
new_termios=init_termios;
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
// so we use fcntl to write the nonblock input
new_termios.c_cc[VMIN]=1;
new_termios.c_cc[VTIME]=0;
tcsetattr(0,TCSANOW,&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
#endif
}
~noecho_input() {
#ifndef _WIN32
tcflush(0,TCIOFLUSH);
tcsetattr(0,TCSANOW,&init_termios);
tcflush(0, TCIOFLUSH);
tcsetattr(0, TCSANOW, &init_termios);
#endif
}
int noecho_kbhit() {
@ -42,10 +42,10 @@ public:
if (peek_char!=-1) {
return 1;
}
int flag=fcntl(0,F_GETFL);
fcntl(0,F_SETFL,flag|O_NONBLOCK);
nread=read(0,&ch,1);
fcntl(0,F_SETFL,flag);
int flag=fcntl(0, F_GETFL);
fcntl(0, F_SETFL,flag|O_NONBLOCK);
nread=read(0, &ch, 1);
fcntl(0, F_SETFL, flag);
if (nread==1) {
peek_char=ch;
return 1;
@ -63,7 +63,7 @@ public:
peek_char=-1;
return ch;
}
ssize_t tmp=read(0,&ch,1);
ssize_t tmp=read(0, &ch, 1);
return ch;
#else
return getch();
@ -72,13 +72,16 @@ public:
};
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());
}
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());
}
var nas_noblock(var* args,usize size,gc* ngc) {
var nas_noblock(var* args, usize size, gc* ngc) {
if (this_window.noecho_kbhit()) {
return var::num((double)this_window.noecho_getch());
}

View File

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

View File

@ -10,7 +10,7 @@ private:
WSAData data;
public:
WSAmanager() {
WSAStartup(0x1010,&data);
WSAStartup(0x1010, &data);
}
~WSAmanager() {
WSACleanup();
@ -25,14 +25,14 @@ static WSAmanager win;
#include <netinet/in.h>
#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)
return nas_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num());
return var::num((double)sd);
}
var nas_closesocket(var* args,usize size,gc* ngc) {
var nas_closesocket(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("closesocket","\"sd\" should be number");
#ifdef _WIN32
@ -42,7 +42,7 @@ var nas_closesocket(var* args,usize size,gc* ngc) {
#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)
return nas_err("shutdown","\"sd\" must be a number");
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()));
}
var nas_bind(var* args,usize size,gc* ngc) {
var nas_bind(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("bind","\"sd\" muse be a number");
if (args[1].type!=vm_str)
@ -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)));
}
var nas_listen(var* args,usize size,gc* ngc) {
var nas_listen(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("listen","\"sd\" must be a number");
if (args[1].type!=vm_num)
@ -73,7 +73,7 @@ var nas_listen(var* args,usize size,gc* ngc) {
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)
return nas_err("connect","\"sd\" must be a number");
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)));
}
var nas_accept(var* args,usize size,gc* ngc) {
var nas_accept(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("accept","\"sd\" must be a number");
sockaddr_in client;
@ -107,7 +107,7 @@ var nas_accept(var* args,usize size,gc* ngc) {
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)
return nas_err("send","\"sd\" must be a number");
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()));
}
var nas_sendto(var* args,usize size,gc* ngc) {
var nas_sendto(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("sendto","\"sd\" must be a number");
if (args[1].type!=vm_str)
@ -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)));
}
var nas_recv(var* args,usize size,gc* ngc) {
var nas_recv(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("recv","\"sd\" must be a number");
if (args[1].type!=vm_num)
@ -158,7 +158,7 @@ var nas_recv(var* args,usize size,gc* ngc) {
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)
return nas_err("recvfrom","\"sd\" must be a number");
if (args[1].type!=vm_num)
@ -186,7 +186,7 @@ var nas_recvfrom(var* args,usize size,gc* ngc) {
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));
}

10
nasal.h
View File

@ -109,7 +109,7 @@ const u32 STACK_DEPTH=1024;
f64 hex2f(const char* str) {
f64 ret=0;
for(;*str;++str) {
for(; *str; ++str) {
if ('0'<=*str && *str<='9') {
ret=ret*16+(*str-'0');
} else if ('a'<=*str && *str<='f') {
@ -134,10 +134,12 @@ f64 oct2f(const char* str) {
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.
// 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 ret=0,negative=1,num_pow=0;
while('0'<=*str && *str<='9') {
@ -220,7 +222,7 @@ string chrhex(const char c) {
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("");
for(auto i:str) {
// windows doesn't output unicode normally, so we output the hex

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -33,8 +33,8 @@ private:
bool check_memory_reachable(const ast&);
void check_id_exist(const ast&);
void die(const string& info,const span& loc) {
err.err("code",loc,info);
void die(const string& info, const span& loc) {
err.err("code", loc, info);
}
void regist_num(const f64);
@ -45,7 +45,7 @@ private:
i32 global_find(const string&);
i32 upvalue_find(const string&);
void gen(u8,u32,u32);
void gen(u8, u32, u32);
void num_gen(const ast&);
void str_gen(const ast&);
@ -68,7 +68,7 @@ private:
void multi_assign_gen(const ast&);
void cond_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 for_gen(const ast&);
void expr_gen(const ast&);
@ -82,8 +82,8 @@ private:
void ret_gen(const ast&);
public:
codegen(error& e):fileindex(0),err(e),file(nullptr) {}
const error& compile(const parse&,const linker&);
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
const error& compile(const parse&, const linker&);
void print();
const std::vector<string>& strs() const {return str_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) {
const ast& tmp=node.child().back();
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;
}
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;
}
} else if (node.type()!=ast_id) {
die("bad left-value",node.location());
die("bad left-value", node.location());
return false;
}
return true;
@ -113,7 +113,7 @@ void codegen::check_id_exist(const ast& node) {
for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) {
if (local.empty()) {
die("useless native function used in global scope",node.location());
die("useless native function used in global scope", node.location());
}
return;
}
@ -128,7 +128,7 @@ void codegen::check_id_exist(const ast& node) {
if (global_find(str)>=0) {
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) {
@ -213,41 +213,41 @@ i32 codegen::upvalue_find(const string& name) {
return index;
}
void codegen::gen(u8 op,u32 num,u32 line) {
code.push_back({op,fileindex,num,line});
void codegen::gen(u8 op, u32 num, u32 line) {
code.push_back({op, fileindex, num, line});
}
void codegen::num_gen(const ast& node) {
f64 num=node.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) {
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) {
f64 num=node.str()=="true"?1:0;
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) {
for(auto& child:node.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) {
gen(op_newh,0,node.line());
gen(op_newh, 0, node.line());
for(auto& child:node.child()) {
calc_gen(child[1]);
const string& str=child[0].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
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()) {
die("dynamic parameter must be the last one",tmp.location());
die("dynamic parameter must be the last one", tmp.location());
}
// check redefinition
string name=tmp.str();
if (argname.count(name)) {
die("redefinition of parameter: "+name,tmp.location());
die("redefinition of parameter: "+name, tmp.location());
} else {
argname[name]=true;
}
}
usize newf=code.size();
gen(op_newf,0,node.line());
gen(op_newf, 0, node.line());
usize lsize=code.size();
gen(op_intl,0,node.line());
gen(op_intl, 0, node.line());
// add special keyword 'me' into symbol table
// this symbol is only used in local scope(function's scope)
// this keyword is set to nil as default value
// after calling a hash, this keyword is set to this hash
// this symbol's index will be 0
local.push_back({{"me",0}});
local.push_back({{"me", 0}});
// generate parameter list
for(auto& tmp:node[0].child()) {
const string& str=tmp.str();
if (str=="me") {
die("\"me\" should not be a parameter",tmp.location());
die("\"me\" should not be a parameter", tmp.location());
}
regist_str(str);
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:
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;
case ast_dynamic:gen(op_dyn,str_table[str],tmp.line());break;
}
add_sym(str);
}
code[newf].num=code.size()+1; // entry
usize jmp_ptr=code.size();
gen(op_jmp,0,node.line());
gen(op_jmp, 0, node.line());
const ast& block=node[1];
// search symbols first, must use after loading parameters
@ -321,13 +325,13 @@ void codegen::func_gen(const ast& node) {
in_iterloop.pop();
code[lsize].num=local.back().size();
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();
if (!block.size() || block.child().back().type()!=ast_ret) {
gen(op_pnil,0,block.line());
gen(op_ret,0,block.line());
gen(op_pnil, 0, block.line());
gen(op_ret, 0, block.line());
}
code[jmp_ptr].num=code.size();
}
@ -351,66 +355,66 @@ void codegen::call_id(const ast& node) {
const string& str=node.str();
for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) {
gen(op_callb,i,node.line());
gen(op_callb, i, node.line());
if (local.empty()) {
die("should warp native function in local scope",node.location());
die("should warp native function in local scope", node.location());
}
return;
}
}
i32 index;
if ((index=local_find(str))>=0) {
gen(op_calll,index,node.line());
gen(op_calll, index, node.line());
return;
}
if ((index=upvalue_find(str))>=0) {
gen(op_upval,index,node.line());
gen(op_upval, index, node.line());
return;
}
if ((index=global_find(str))>=0) {
gen(op_callg,index,node.line());
gen(op_callg, index, node.line());
return;
}
die("undefined symbol \""+str+"\"",node.location());
die("undefined symbol \""+str+"\"", node.location());
}
void codegen::call_hash(const ast& node) {
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) {
// maybe this place can use callv-const if ast's first child is ast_num
if (node.size()==1 && node[0].type()!=ast_subvec) {
calc_gen(node[0]);
gen(op_callv,0,node[0].line());
gen(op_callv, 0, node[0].line());
return;
}
gen(op_slcbeg,0,node.line());
for(auto& tmp:node.child()) {
if (tmp.type()!=ast_subvec) {
calc_gen(tmp);
gen(op_slc,0,tmp.line());
gen(op_slc, 0, tmp.line());
} else {
calc_gen(tmp[0]);
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) {
if (!node.size()) {
gen(op_callfv,0,node.line());
gen(op_callfv, 0, node.line());
} else if (node[0].type()==ast_pair) {
hash_gen(node);
gen(op_callfh,0,node.line());
gen(op_callfh, 0, node.line());
} else {
for(auto& child:node.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();
for(u32 i=0;builtin[i].name;++i) {
if (builtin[i].name==str) {
die("cannot modify native function",node.location());
die("cannot modify native function", node.location());
return;
}
}
i32 index;
if ((index=local_find(str))>=0) {
gen(op_mcalll,index,node.line());
gen(op_mcalll, index, node.line());
return;
}
if ((index=upvalue_find(str))>=0) {
gen(op_mupval,index,node.line());
gen(op_mupval, index, node.line());
return;
}
if ((index=global_find(str))>=0) {
gen(op_mcallg,index,node.line());
gen(op_mcallg, index, node.line());
return;
}
die("undefined symbol \""+str+"\"",node.location());
die("undefined symbol \""+str+"\"", node.location());
}
void codegen::mcall_vec(const ast& node) {
calc_gen(node[0]);
gen(op_mcallv,0,node.line());
gen(op_mcallv, 0, node.line());
}
void codegen::mcall_hash(const ast& node) {
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) {
const string& str=node[0].str();
calc_gen(node[1]);
local.empty()?
gen(op_loadg,global_find(str),node.line()):
gen(op_loadl,local_find(str),node.line());
gen(op_loadg, global_find(str), node.line()):
gen(op_loadl, local_find(str), node.line());
}
void codegen::multi_def(const ast& node) {
auto& ids=node[0].child();
@ -500,49 +504,49 @@ void codegen::multi_def(const ast& node) {
for(usize i=0;i<size;++i) {
// check node type, only identifier is allowed
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;
}
calc_gen(vals[i]);
const string& str=ids[i].str();
local.empty()?
gen(op_loadg,global_find(str),ids[i].line()):
gen(op_loadl,local_find(str),ids[i].line());
gen(op_loadg, global_find(str), ids[i].line()):
gen(op_loadl, local_find(str), ids[i].line());
}
} else { // (var a,b,c)=[0,1,2];
calc_gen(node[1]);
for(usize i=0;i<size;++i) {
// check node type, only identifier is allowed
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;
}
gen(op_callvi,i,node[1].line());
gen(op_callvi, i, node[1].line());
const string& str=ids[i].str();
local.empty()?
gen(op_loadg,global_find(str),ids[i].line()):
gen(op_loadl,local_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_pop,0,node.line());
gen(op_pop, 0, node.line());
}
}
void codegen::def_gen(const ast& node) {
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()) {
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()) {
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);
}
void codegen::multi_assign_gen(const ast& node) {
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()) {
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();
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) {
code.back().op=op_loadg;
} else {
gen(op_meq,1,node[0][i].line());
gen(op_meq, 1, node[0][i].line());
}
}
} else {
calc_gen(node[1]);
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--
// and this operation changes local and global value directly
mcall(node[0][i]);
@ -577,10 +581,10 @@ void codegen::multi_assign_gen(const ast& node) {
} else if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} 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) {
calc_gen(tmp[0]);
usize ptr=code.size();
gen(op_jf,0,tmp.line());
gen(op_jf, 0, tmp.line());
block_gen(tmp[1]);
// without 'else' the last condition doesn't need to jmp
if (&tmp!=&node.child().back()) {
jmp_label.push_back(code.size());
gen(op_jmp,0,tmp.line());
gen(op_jmp, 0, tmp.line());
}
code[ptr].num=code.size();
} else {
@ -609,8 +613,8 @@ void codegen::cond_gen(const ast& node) {
}
void codegen::loop_gen(const ast& node) {
continue_ptr.push_front(std::vector<i32>());
break_ptr.push_front(std::vector<i32>());
continue_ptr.push_front({});
break_ptr.push_front({});
switch(node.type()) {
case ast_while: while_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();
calc_gen(node[0]);
usize condition_ptr=code.size();
gen(op_jf,0,node[0].line());
gen(op_jf, 0, node[0].line());
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();
load_continue_break(code.size()-1,code.size());
load_continue_break(code.size()-1, code.size());
}
void codegen::for_gen(const ast& node) {
expr_gen(node[0]);
usize jmp_place=code.size();
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 {
calc_gen(node[1]);
}
usize label_exit=code.size();
gen(op_jf,0,node[1].line());
gen(op_jf, 0, node[1].line());
block_gen(node[3]);
usize continue_place=code.size();
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();
load_continue_break(continue_place,code.size());
load_continue_break(continue_place, code.size());
}
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) {
code.back().op=code.back().op-op_addeqc+op_addecp;
} else {
gen(op_pop,0,node.line());
gen(op_pop, 0, node.line());
}
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) {
code.back().num=1;
} else {
gen(op_pop,0,node.line());
gen(op_pop, 0, node.line());
}
break;
case ast_equal:
@ -712,7 +716,7 @@ void codegen::expr_gen(const ast& node) {
if (code.back().op==op_meq) {
code.back().num=1;
} else {
gen(op_pop,0,node.line());
gen(op_pop, 0, node.line());
}
}
break;
@ -721,14 +725,14 @@ void codegen::expr_gen(const ast& node) {
void codegen::forindex_gen(const ast& node) {
calc_gen(node[1]);
gen(op_cnt,0,node[1].line());
gen(op_cnt, 0, node[1].line());
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
const string& str=node[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),node[0][0].line()):
gen(op_loadl,local_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());
} else { // use exist variable as the iterator
mcall(node[0]);
if (code.back().op==op_mcallg) {
@ -738,29 +742,29 @@ void codegen::forindex_gen(const ast& node) {
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq,1,node[0].line());
gen(op_meq, 1, node[0].line());
}
}
++in_iterloop.top();
block_gen(node[2]);
--in_iterloop.top();
gen(op_jmp,ptr,node.line());
gen(op_jmp, ptr, node.line());
code[ptr].num=code.size();
load_continue_break(code.size()-1,code.size());
gen(op_pop,0,node[1].line());// pop vector
gen(op_pop,0,node.line());// pop iterator
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node[1].line());// pop vector
gen(op_pop, 0, node.line());// pop iterator
}
void codegen::foreach_gen(const ast& node) {
calc_gen(node[1]);
gen(op_cnt,0,node.line());
gen(op_cnt, 0, node.line());
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
const string& str=node[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),node[0][0].line()):
gen(op_loadl,local_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());
} else { // use exist variable as the iterator
mcall(node[0]);
if (code.back().op==op_mcallg) {
@ -770,59 +774,59 @@ void codegen::foreach_gen(const ast& node) {
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq,1,node[0].line());
gen(op_meq, 1, node[0].line());
}
}
++in_iterloop.top();
block_gen(node[2]);
--in_iterloop.top();
gen(op_jmp,ptr,node.line());
gen(op_jmp, ptr, node.line());
code[ptr].num=code.size();
load_continue_break(code.size()-1,code.size());
gen(op_pop,0,node[1].line());// pop vector
gen(op_pop,0,node.line());// pop iterator
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node[1].line());// pop vector
gen(op_pop, 0, node.line());// pop iterator
}
void codegen::or_gen(const ast& node) {
calc_gen(node[0]);
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]);
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_pnil,0,node[1].line());
gen(op_pop, 0, node[1].line());
gen(op_pnil, 0, node[1].line());
code[l1].num=code[l2].num=code.size();
}
void codegen::and_gen(const ast& node) {
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();
gen(op_jmp,0,node[0].line());
gen(op_pop,0,node[1].line());// jt jumps here
gen(op_jmp, 0, node[0].line());
gen(op_pop, 0, node[1].line());// jt jumps here
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();
gen(op_pop,0,node[1].line());
gen(op_pnil,0,node[1].line());
//jt jumps here
gen(op_pop, 0, node[1].line());
gen(op_pnil, 0, node[1].line());
// jt jumps here
}
void codegen::trino_gen(const ast& node) {
calc_gen(node[0]);
usize lfalse=code.size();
gen(op_jf,0,node[0].line());
gen(op_jf, 0, node[0].line());
calc_gen(node[1]);
usize lexit=code.size();
gen(op_jmp,0,node[1].line());
gen(op_jmp, 0, node[1].line());
code[lfalse].num=code.size();
calc_gen(node[2]);
code[lexit].num=code.size();
@ -842,7 +846,7 @@ void codegen::calc_gen(const ast& node) {
case ast_equal:
calc_gen(node[1]);
mcall(node[0]);
gen(op_meq,0,node.line());
gen(op_meq, 0, node.line());
break;
// ast_addeq(22)~ast_lnkeq(26) op_addeq(23)~op_lnkeq(27)
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]);
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 {
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;
case ast_lnkeq:
@ -865,15 +869,15 @@ void codegen::calc_gen(const ast& node) {
}
mcall(node[0]);
if (node[1].type()!=ast_str) {
gen(op_lnkeq,0,node.line());
gen(op_lnkeq, 0, node.line());
} else {
gen(op_lnkeqc,str_table[node[1].str()],node.line());
gen(op_lnkeqc, str_table[node[1].str()], node.line());
}
break;
case ast_btandeq:case ast_btoreq:case ast_btxoreq:
calc_gen(node[1]);
mcall(node[0]);
gen(node.type()-ast_btandeq+op_btandeq,0,node.line());
gen(node.type()-ast_btandeq+op_btandeq, 0, node.line());
break;
case ast_or:or_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]);
if (node[1].type()!=ast_num) {
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 {
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;
case ast_link:
calc_gen(node[0]);
if (node[1].type()!=ast_str) {
calc_gen(node[1]);
gen(op_lnk,0,node.line());
gen(op_lnk, 0, node.line());
} else {
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;
// ast_cmpeq(27)~ast_geq(32) op_eq(29)~op_geq(34)
case ast_cmpeq:case ast_neq:
calc_gen(node[0]);
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;
case ast_less:case ast_leq:case ast_grt:case ast_geq:
calc_gen(node[0]);
if (node[1].type()!=ast_num) {
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 {
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;
case ast_trino:trino_gen(node);break;
case ast_neg:
calc_gen(node[0]);
gen(op_usub,0,node.line());
gen(op_usub, 0, node.line());
break;
case ast_lnot:
calc_gen(node[0]);
gen(op_lnot,0,node.line());
gen(op_lnot, 0, node.line());
break;
case ast_bnot:
calc_gen(node[0]);
gen(op_bnot,0,node.line());
gen(op_bnot, 0, node.line());
break;
case ast_bitor:
calc_gen(node[0]);
calc_gen(node[1]);
gen(op_btor,0,node.line());
gen(op_btor, 0, node.line());
break;
case ast_bitxor:
calc_gen(node[0]);
calc_gen(node[1]);
gen(op_btxor,0,node.line());
gen(op_btxor, 0, node.line());
break;
case ast_bitand:
calc_gen(node[0]);
calc_gen(node[1]);
gen(op_btand,0,node.line());
gen(op_btand, 0, node.line());
break;
case ast_def:
single_def(node);
@ -959,11 +963,11 @@ void codegen::block_gen(const ast& node) {
case ast_cond:cond_gen(tmp);break;
case ast_continue:
continue_ptr.front().push_back(code.size());
gen(op_jmp,0,tmp.line());
gen(op_jmp, 0, tmp.line());
break;
case ast_break:
break_ptr.front().push_back(code.size());
gen(op_jmp,0,tmp.line());
gen(op_jmp, 0, tmp.line());
break;
case ast_while:
case ast_for:
@ -992,42 +996,42 @@ void codegen::block_gen(const ast& node) {
void codegen::ret_gen(const ast& node) {
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()) {
calc_gen(node[0]);
} 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;
file=import.filelist().data();
in_iterloop.push(0);
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
gen(op_exit,0,0);
gen(op_exit, 0, 0);
// size out of bound check
if (num_res.size()>0xffffff) {
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) {
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) {
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) {
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;
}
@ -1049,7 +1053,7 @@ void codegen::print() {
// print code
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) {
// print opcode index, opcode name, opcode immediate number
const opcode& c=code[i];

View File

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

View File

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

View File

@ -83,18 +83,18 @@ public:
} val;
private:
var(u8 t,u32 pc) {type=t;val.ret=pc;}
var(u8 t,i64 ct) {type=t;val.cnt=ct;}
var(u8 t,f64 n) {type=t;val.num=n;}
var(u8 t,var* p) {type=t;val.addr=p;}
var(u8 t,nas_val* p) {type=t;val.gcobj=p;}
var(u8 t, u32 pc) {type=t;val.ret=pc;}
var(u8 t, i64 ct) {type=t;val.cnt=ct;}
var(u8 t, f64 n) {type=t;val.num=n;}
var(u8 t, var* p) {type=t;val.addr=p;}
var(u8 t, nas_val* p) {type=t;val.gcobj=p;}
public:
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;}
friend std::ostream& operator<<(std::ostream&,var&);
friend std::ostream& operator<<(std::ostream&, var&);
// number and string can be translated to each other
f64 tonum();
@ -157,7 +157,7 @@ struct nas_func {
std::vector<var> upval; // closure
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();
};
@ -186,9 +186,9 @@ private:
void dylib_dtor();
public:
nas_obj():type(obj_type::null),ptr(nullptr) {}
nas_obj(): type(obj_type::null), ptr(nullptr) {}
~nas_obj() {clear();}
void set(obj_type,void*);
void set(obj_type, void*);
void clear();
};
@ -247,7 +247,7 @@ var* nas_vec::get_mem(const i32 n) {
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) {
out<<(vec.elems.size()?"[..]":"[]");
return out;
@ -306,7 +306,7 @@ var* nas_hash::get_mem(const string& key) {
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) {
out<<(hash.elems.size()?"{..}":"{}");
return out;
@ -328,7 +328,7 @@ void nas_func::clear() {
keys.clear();
}
void nas_obj::set(obj_type t,void* p) {
void nas_obj::set(obj_type t, void* p) {
type=t;
ptr=p;
}
@ -352,6 +352,7 @@ void nas_obj::file_dtor() {
}
fclose((FILE*)ptr);
}
void nas_obj::dir_dtor() {
#ifndef _MSC_VER
closedir((DIR*)ptr);
@ -359,6 +360,7 @@ void nas_obj::dir_dtor() {
FindClose(ptr);
#endif
}
void nas_obj::dylib_dtor() {
#ifdef _WIN32
FreeLibrary((HMODULE)ptr);
@ -432,14 +434,14 @@ string var::tostr() {
return str();
} else if (type==vm_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('.')+1,string::npos);
tmp.erase(tmp.find_last_not_of('0')+1, string::npos);
tmp.erase(tmp.find_last_not_of('.')+1, string::npos);
return tmp;
}
return "";
}
std::ostream& operator<<(std::ostream& out,var& ref) {
std::ostream& operator<<(std::ostream& out, var& ref) {
switch(ref.type) {
case vm_none: out<<"undefined"; break;
case vm_nil: out<<"nil"; break;
@ -459,31 +461,31 @@ bool var::objchk(obj_type objtype) {
}
var var::none() {
return {vm_none,(u32)0};
return {vm_none, (u32)0};
}
var var::nil() {
return {vm_nil,(u32)0};
return {vm_nil, (u32)0};
}
var var::ret(u32 pc) {
return {vm_ret,pc};
return {vm_ret, pc};
}
var var::cnt(i64 n) {
return {vm_cnt,n};
return {vm_cnt, n};
}
var var::num(f64 n) {
return {vm_num,n};
return {vm_num, n};
}
var var::gcobj(nas_val* p) {
return {p->type,p};
return {p->type, p};
}
var var::addr(var* p) {
return {vm_addr,p};
return {vm_addr, p};
}
var* var::addr () {return val.addr; }
@ -542,17 +544,17 @@ private:
/* gc functions */
void mark();
void mark_context(std::vector<var>&);
void mark_var(std::vector<var>&,var&);
inline void mark_vec(std::vector<var>&,nas_vec&);
inline void mark_hash(std::vector<var>&,nas_hash&);
inline void mark_func(std::vector<var>&,nas_func&);
inline void mark_upval(std::vector<var>&,nas_upval&);
inline void mark_co(std::vector<var>&,nas_co&);
void mark_var(std::vector<var>&, var&);
inline void mark_vec(std::vector<var>&, nas_vec&);
inline void mark_hash(std::vector<var>&, nas_hash&);
inline void mark_func(std::vector<var>&, nas_func&);
inline void mark_upval(std::vector<var>&, nas_upval&);
inline void mark_co(std::vector<var>&, nas_co&);
void sweep();
public:
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 info();
var alloc(const u8);
@ -574,7 +576,7 @@ void gc::mark() {
value.val.gcobj->mark!=gc_status::uncollected) {
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);
}
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;
switch(value.type) {
case vm_vec: mark_vec(bfs_queue,value.vec()); break;
case vm_hash: mark_hash(bfs_queue,value.hash()); break;
case vm_func: mark_func(bfs_queue,value.func()); break;
case vm_upval: mark_upval(bfs_queue,value.upval()); break;
case vm_co: mark_co(bfs_queue,value.co()); break;
case vm_vec: mark_vec(bfs_queue, value.vec()); break;
case vm_hash: mark_hash(bfs_queue, value.hash()); break;
case vm_func: mark_func(bfs_queue, value.func()); break;
case vm_upval: mark_upval(bfs_queue, value.upval()); break;
case vm_co: mark_co(bfs_queue, value.co()); 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) {
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) {
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) {
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) {
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.upvalr);
for(var* i=co.stack;i<=co.ctx.top;++i) {
@ -679,7 +681,7 @@ void gc::extend(u8 type) {
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
rctx->funcr=nil;
worktime=0;
@ -838,13 +840,13 @@ void gc::ctxreserve() {
}
// 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";
return var::none();
}
// 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}
struct mod_func {

View File

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

View File

@ -169,7 +169,7 @@ private:
token dots();
token calc_opr();
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 std::vector<token>& result() const {return toks;}
};
@ -223,23 +223,23 @@ void lexer::skip_note() {
void lexer::err_char() {
++column;
char c=res[ptr++];
err.err("lexer",{line,column-1,line,column,filename},"invalid character 0x"+chrhex(c));
err.fatal("lexer","fatal error occurred, stop");
err.err("lexer", {line, column-1, line, column, filename}, "invalid character 0x"+chrhex(c));
err.fatal("lexer", "fatal error occurred, stop");
}
void lexer::open(const string& file) {
// check file exsits and it is a regular file
struct stat buffer;
if (stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode)) {
err.err("lexer","<"+file+"> is not a regular file");
if (stat(file.c_str(), &buffer)==0 && !S_ISREG(buffer.st_mode)) {
err.err("lexer", "<"+file+"> is not a regular file");
err.chkerr();
}
// load
filename=file;
std::ifstream in(file,std::ios::binary);
std::ifstream in(file, std::ios::binary);
if (in.fail()) {
err.err("lexer","failed to open <"+file+">");
err.err("lexer", "failed to open <"+file+">");
} else {
err.load(file);
}
@ -277,8 +277,8 @@ string lexer::utf8_gen() {
for(u32 i=1;i<tmp.size();++i) {
utf_info+=" 0x"+chrhex(tmp[i]);
}
err.err("lexer",{line,column-1,line,column,filename},"invalid utf-8 <"+utf_info+">");
err.fatal("lexer","fatal error occurred, stop");
err.err("lexer", {line, column-1, line, column, filename}, "invalid utf-8 <"+utf_info+">");
err.fatal("lexer", "fatal error occurred, stop");
}
str+=tmp;
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);
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() {
@ -314,9 +314,9 @@ token lexer::num_gen() {
}
column+=str.length();
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
string str="0o";
ptr+=2;
@ -330,9 +330,9 @@ token lexer::num_gen() {
}
column+=str.length();
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
// 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
if (str.back()=='.') {
column+=str.length();
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`");
return {{begin_line,begin_column,line,column,filename},tok::num,"0"};
err.err("lexer",{begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
}
}
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
@ -363,12 +363,12 @@ token lexer::num_gen() {
// "xxxe(-|+)" is not a correct number
if (str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') {
column+=str.length();
err.err("lexer",{begin_line,begin_column,line,column,filename},"invalid number `"+str+"`");
return {{begin_line,begin_column,line,column,filename},tok::num,"0"};
err.err("lexer",{begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`");
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
}
}
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() {
@ -412,14 +412,14 @@ token lexer::str_gen() {
}
// check if this string ends with a " or '
if (ptr++>=res.size()) {
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};
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};
}
++column;
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() {
@ -429,10 +429,10 @@ token lexer::single_opr() {
++column;
tok type=get_type(str);
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;
return {{begin_line,begin_column,line,column,filename},type,str};
return {{begin_line, begin_column, line, column, filename}, type, str};
}
token lexer::dots() {
@ -444,7 +444,7 @@ token lexer::dots() {
}
ptr+=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() {
@ -456,7 +456,7 @@ token lexer::calc_opr() {
str+=res[ptr++];
}
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) {
@ -495,7 +495,7 @@ const error& lexer::scan(const string& file) {
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="";
return err;
}

View File

@ -138,8 +138,8 @@ private:
static const string* strs;
static const string* files;
public:
codestream(const opcode& c,const u32 i):code(c),index(i) {}
static void set(const f64*,const string*,const string*);
codestream(const opcode& c, const u32 i): code(c), index(i) {}
static void set(const f64*, const string*, const string*);
void dump(std::ostream&) const;
};
@ -182,12 +182,12 @@ void codestream::dump(std::ostream& out) const {
case op_muleqc:case op_diveqc:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<")";break;
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_mulecp: case op_divecp:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<") sp-1";break;
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_mulc: case op_divc:
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_mcallh: case op_para:
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:
if (files) {
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);
return out;
}

View File

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

View File

@ -141,7 +141,7 @@ protected:
public:
/* constructor of vm instance */
vm():ngc(&ctx),verbose(false) {}
vm(): ngc(&ctx), verbose(false) {}
/* execution entry */
void run(
@ -229,7 +229,7 @@ void vm::traceback() {
}
ret.push(ctx.pc); // store the position program crashed
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()) {
if ((p=ret.top())==prev) {
++same;
@ -365,7 +365,7 @@ void vm::o_intg() {
}
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];
}
@ -817,7 +817,7 @@ void vm::o_callfv() {
// collected incorrectly
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
local[i]=local[i-1];
}
@ -890,7 +890,7 @@ void vm::o_callb() {
// if running a builtin function about coroutine
// (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
// and set it to top[0] later
@ -1073,9 +1073,10 @@ void vm::run(
const codegen& gen,
const linker& linker,
const std::vector<string>& argv,
const bool detail) {
const bool 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
const void* oprs[]={
&&vmexit, &&intg, &&intl, &&loadg,