✨ add cmakelists.txt
This commit is contained in:
parent
f914678311
commit
92abad3384
|
@ -47,6 +47,9 @@ nasal.exe
|
|||
.vscode
|
||||
dump
|
||||
|
||||
# build dir
|
||||
build
|
||||
|
||||
# macOS special cache directory
|
||||
.DS_Store
|
||||
|
||||
|
|
|
@ -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})
|
38
main.cpp
38
main.cpp
|
@ -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()) {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
10
nasal.h
|
@ -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
|
||||
|
|
27
nasal_ast.h
27
nasal_ast.h
|
@ -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 {
|
||||
|
|
385
nasal_builtin.h
385
nasal_builtin.h
File diff suppressed because it is too large
Load Diff
308
nasal_codegen.h
308
nasal_codegen.h
|
@ -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];
|
||||
|
|
29
nasal_dbg.h
29
nasal_dbg.h
|
@ -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[]={
|
||||
|
|
48
nasal_err.h
48
nasal_err.h
|
@ -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'?"^^^^":"^");
|
||||
}
|
||||
}
|
||||
|
|
90
nasal_gc.h
90
nasal_gc.h
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
194
nasal_parse.h
194
nasal_parse.h
|
@ -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 ||
|
||||
|
|
15
nasal_vm.h
15
nasal_vm.h
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue