Merge pull request #29 from ValKmjolnir/develop
⚡ improve codegen and repl output
This commit is contained in:
commit
982c5750ef
|
@ -51,7 +51,7 @@ public:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int flag = fcntl(0, F_GETFL);
|
int flag = fcntl(0, F_GETFL);
|
||||||
fcntl(0, F_SETFL,flag|O_NONBLOCK);
|
fcntl(0, F_SETFL, flag|O_NONBLOCK);
|
||||||
nread = read(0, &ch, 1);
|
nread = read(0, &ch, 1);
|
||||||
fcntl(0, F_SETFL, flag);
|
fcntl(0, F_SETFL, flag);
|
||||||
if (nread==1) {
|
if (nread==1) {
|
||||||
|
@ -83,25 +83,25 @@ public:
|
||||||
noecho_input this_window;
|
noecho_input this_window;
|
||||||
|
|
||||||
var nas_getch(var* args, usize size, gc* ngc) {
|
var nas_getch(var* args, usize size, gc* ngc) {
|
||||||
return var::num((double)this_window.noecho_getch());
|
return var::num(static_cast<double>(this_window.noecho_getch()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_kbhit(var* args, usize size, gc* ngc) {
|
var nas_kbhit(var* args, usize size, gc* ngc) {
|
||||||
return var::num((double)this_window.noecho_kbhit());
|
return var::num(static_cast<double>(this_window.noecho_kbhit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_noblock(var* args, usize size, gc* ngc) {
|
var nas_noblock(var* args, usize size, gc* ngc) {
|
||||||
if (this_window.noecho_kbhit()) {
|
if (this_window.noecho_kbhit()) {
|
||||||
return var::num((double)this_window.noecho_getch());
|
return var::num(static_cast<double>(this_window.noecho_getch()));
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
module_func_info func_tbl[] = {
|
module_func_info func_tbl[] = {
|
||||||
{"nas_getch",nas_getch},
|
{"nas_getch", nas_getch},
|
||||||
{"nas_kbhit",nas_kbhit},
|
{"nas_kbhit", nas_kbhit},
|
||||||
{"nas_noblock",nas_noblock},
|
{"nas_noblock", nas_noblock},
|
||||||
{nullptr,nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" module_func_info* get() {
|
extern "C" module_func_info* get() {
|
||||||
|
|
|
@ -34,16 +34,16 @@ var nas_socket(var* args, usize size, gc* ngc) {
|
||||||
if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
|
if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num)
|
||||||
return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number");
|
return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number");
|
||||||
int sd = socket(args[0].num(), args[1].num(), args[2].num());
|
int sd = socket(args[0].num(), args[1].num(), args[2].num());
|
||||||
return var::num((double)sd);
|
return var::num(static_cast<double>(sd));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_closesocket(var* args, usize size, gc* ngc) {
|
var nas_closesocket(var* args, usize size, gc* ngc) {
|
||||||
if (args[0].type!=vm_num)
|
if (args[0].type!=vm_num)
|
||||||
return nas_err("closesocket", "\"sd\" should be number");
|
return nas_err("closesocket", "\"sd\" should be number");
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return var::num((double)closesocket(args[0].num()));
|
return var::num(static_cast<double>(closesocket(args[0].num())));
|
||||||
#else
|
#else
|
||||||
return var::num((double)close(args[0].num()));
|
return var::num(static_cast<double>(close(args[0].num())));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ var nas_shutdown(var* args, usize size, gc* ngc) {
|
||||||
return nas_err("shutdown", "\"sd\" must be a number");
|
return nas_err("shutdown", "\"sd\" must be a number");
|
||||||
if (args[1].type!=vm_num)
|
if (args[1].type!=vm_num)
|
||||||
return nas_err("shutdown", "\"how\" must be a number");
|
return nas_err("shutdown", "\"how\" must be a number");
|
||||||
return var::num((double)shutdown(args[0].num(), args[1].num()));
|
return var::num(static_cast<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) {
|
||||||
|
@ -67,7 +67,11 @@ var nas_bind(var* args, usize size, gc* ngc) {
|
||||||
server.sin_family = AF_INET;
|
server.sin_family = AF_INET;
|
||||||
server.sin_addr.s_addr = inet_addr(args[1].str().c_str());
|
server.sin_addr.s_addr = inet_addr(args[1].str().c_str());
|
||||||
server.sin_port = htons(args[2].num());
|
server.sin_port = htons(args[2].num());
|
||||||
return var::num((double)bind(args[0].num(), (sockaddr*)&server, sizeof(server)));
|
return var::num(static_cast<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) {
|
||||||
|
@ -75,7 +79,7 @@ var nas_listen(var* args, usize size, gc* ngc) {
|
||||||
return nas_err("listen", "\"sd\" must be a number");
|
return nas_err("listen", "\"sd\" must be a number");
|
||||||
if (args[1].type!=vm_num)
|
if (args[1].type!=vm_num)
|
||||||
return nas_err("listen", "\"backlog\" must be a number");
|
return nas_err("listen", "\"backlog\" must be a number");
|
||||||
return var::num((double)listen(args[0].num(), args[1].num()));
|
return var::num(static_cast<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) {
|
||||||
|
@ -91,11 +95,11 @@ var nas_connect(var* args, usize size, gc* ngc) {
|
||||||
addr.sin_port = htons(args[2].num());
|
addr.sin_port = htons(args[2].num());
|
||||||
hostent* entry = gethostbyname(args[1].str().c_str());
|
hostent* entry = gethostbyname(args[1].str().c_str());
|
||||||
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
||||||
return var::num((double)connect(
|
return var::num(static_cast<double>(connect(
|
||||||
args[0].num(),
|
args[0].num(),
|
||||||
(sockaddr*)&addr,
|
(sockaddr*)&addr,
|
||||||
sizeof(sockaddr_in)
|
sizeof(sockaddr_in)
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_accept(var* args, usize size, gc* ngc) {
|
var nas_accept(var* args, usize size, gc* ngc) {
|
||||||
|
@ -110,7 +114,7 @@ var nas_accept(var* args, usize size, gc* ngc) {
|
||||||
#endif
|
#endif
|
||||||
var res=ngc->temp = ngc->alloc(vm_hash);
|
var res=ngc->temp = ngc->alloc(vm_hash);
|
||||||
auto& hash = res.hash().elems;
|
auto& hash = res.hash().elems;
|
||||||
hash["sd"] = var::num((double)client_sd);
|
hash["sd"] = var::num(static_cast<double>(client_sd));
|
||||||
hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
|
hash["ip"] = ngc->newstr(inet_ntoa(client.sin_addr));
|
||||||
ngc->temp = nil;
|
ngc->temp = nil;
|
||||||
return res;
|
return res;
|
||||||
|
@ -123,12 +127,12 @@ var nas_send(var* args, usize size, gc* ngc) {
|
||||||
return nas_err("send", "\"buff\" must be a string");
|
return nas_err("send", "\"buff\" must be a string");
|
||||||
if (args[2].type!=vm_num)
|
if (args[2].type!=vm_num)
|
||||||
return nas_err("send", "\"flags\" muse be a number");
|
return nas_err("send", "\"flags\" muse be a number");
|
||||||
return var::num((double)send(
|
return var::num(static_cast<double>(send(
|
||||||
args[0].num(),
|
args[0].num(),
|
||||||
args[1].str().c_str(),
|
args[1].str().c_str(),
|
||||||
args[1].str().length(),
|
args[1].str().length(),
|
||||||
args[2].num()
|
args[2].num()
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_sendto(var* args, usize size, gc* ngc) {
|
var nas_sendto(var* args, usize size, gc* ngc) {
|
||||||
|
@ -148,14 +152,14 @@ var nas_sendto(var* args, usize size, gc* ngc) {
|
||||||
addr.sin_port = htons(args[2].num());
|
addr.sin_port = htons(args[2].num());
|
||||||
hostent* entry = gethostbyname(args[1].str().c_str());
|
hostent* entry = gethostbyname(args[1].str().c_str());
|
||||||
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
|
||||||
return var::num((double)sendto(
|
return var::num(static_cast<double>(sendto(
|
||||||
args[0].num(),
|
args[0].num(),
|
||||||
args[3].str().c_str(),
|
args[3].str().c_str(),
|
||||||
args[3].str().length(),
|
args[3].str().length(),
|
||||||
args[4].num(),
|
args[4].num(),
|
||||||
(sockaddr*)&addr,
|
(sockaddr*)&addr,
|
||||||
sizeof(sockaddr_in)
|
sizeof(sockaddr_in)
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_recv(var* args, usize size, gc* ngc) {
|
var nas_recv(var* args, usize size, gc* ngc) {
|
||||||
|
@ -169,9 +173,9 @@ var nas_recv(var* args, usize size, gc* ngc) {
|
||||||
return nas_err("recv", "\"flags\" muse be a number");
|
return nas_err("recv", "\"flags\" muse be a number");
|
||||||
var res = ngc->temp = ngc->alloc(vm_hash);
|
var res = ngc->temp = ngc->alloc(vm_hash);
|
||||||
auto& hash = res.hash().elems;
|
auto& hash = res.hash().elems;
|
||||||
char* buf = new char[(int)args[1].num()];
|
char* buf = new char[static_cast<int>(args[1].num())];
|
||||||
auto recvsize = recv(args[0].num(), buf,args[1].num(), args[2].num());
|
auto recvsize = recv(args[0].num(), buf,args[1].num(), args[2].num());
|
||||||
hash["size"] = var::num((double)recvsize);
|
hash["size"] = var::num(static_cast<double>(recvsize));
|
||||||
buf[recvsize>=0? recvsize:0] = 0;
|
buf[recvsize>=0? recvsize:0] = 0;
|
||||||
hash["str"] = ngc->newstr(buf);
|
hash["str"] = ngc->newstr(buf);
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
@ -192,7 +196,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
|
||||||
int socklen = sizeof(sockaddr_in);
|
int socklen = sizeof(sockaddr_in);
|
||||||
var res = ngc->temp = ngc->alloc(vm_hash);
|
var res = ngc->temp = ngc->alloc(vm_hash);
|
||||||
auto& hash = res.hash().elems;
|
auto& hash = res.hash().elems;
|
||||||
char* buf = new char[(int)args[1].num()+1];
|
char* buf = new char[static_cast<int>(args[1].num()+1)];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto recvsize = recvfrom(
|
auto recvsize = recvfrom(
|
||||||
args[0].num(),
|
args[0].num(),
|
||||||
|
@ -212,7 +216,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
|
||||||
(socklen_t*)&socklen
|
(socklen_t*)&socklen
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
hash["size"] = var::num((double)recvsize);
|
hash["size"] = var::num(static_cast<double>(recvsize));
|
||||||
buf[recvsize>=0? recvsize:0] = 0;
|
buf[recvsize>=0? recvsize:0] = 0;
|
||||||
hash["str"] = ngc->newstr(buf);
|
hash["str"] = ngc->newstr(buf);
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
|
|
@ -139,7 +139,7 @@ void execute(
|
||||||
}
|
}
|
||||||
|
|
||||||
// code generator gets parser's ast and import file list to generate code
|
// code generator gets parser's ast and import file list to generate code
|
||||||
gen.compile(parse, ld).chkerr();
|
gen.compile(parse, ld, false).chkerr();
|
||||||
if (cmd&VM_CODE) {
|
if (cmd&VM_CODE) {
|
||||||
gen.print(std::cout);
|
gen.print(std::cout);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute with arguments
|
// execute with arguments
|
||||||
const std::unordered_map<std::string,u32> cmdlst = {
|
const std::unordered_map<std::string, u32> cmdlst = {
|
||||||
{"--raw-ast", VM_RAW_AST},
|
{"--raw-ast", VM_RAW_AST},
|
||||||
{"--ast", VM_AST},
|
{"--ast", VM_AST},
|
||||||
{"-a", VM_AST},
|
{"-a", VM_AST},
|
||||||
|
|
|
@ -62,7 +62,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
expr(const span& location, expr_type node_type):
|
expr(const span& location, expr_type node_type):
|
||||||
nd_loc(location), nd_type(node_type) {}
|
nd_loc(location), nd_type(node_type) {}
|
||||||
~expr() = default;
|
virtual ~expr() = default;
|
||||||
void set_begin(u32 line, u32 column) {
|
void set_begin(u32 line, u32 column) {
|
||||||
nd_loc.begin_line = line;
|
nd_loc.begin_line = line;
|
||||||
nd_loc.begin_column = column;
|
nd_loc.begin_column = column;
|
||||||
|
@ -81,7 +81,7 @@ class call:public expr {
|
||||||
public:
|
public:
|
||||||
call(const span& location, expr_type node_type):
|
call(const span& location, expr_type node_type):
|
||||||
expr(location, node_type) {}
|
expr(location, node_type) {}
|
||||||
~call() = default;
|
virtual ~call() = default;
|
||||||
virtual void accept(ast_visitor*);
|
virtual void accept(ast_visitor*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class null_expr:public expr {
|
||||||
public:
|
public:
|
||||||
null_expr(const span& location):
|
null_expr(const span& location):
|
||||||
expr(location, expr_type::ast_null) {}
|
expr(location, expr_type::ast_null) {}
|
||||||
~null_expr() = default;
|
~null_expr() override = default;
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class nil_expr:public expr {
|
||||||
public:
|
public:
|
||||||
nil_expr(const span& location):
|
nil_expr(const span& location):
|
||||||
expr(location, expr_type::ast_nil) {}
|
expr(location, expr_type::ast_nil) {}
|
||||||
~nil_expr() = default;
|
~nil_expr() override = default;
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ private:
|
||||||
public:
|
public:
|
||||||
number_literal(const span& location, const f64 num):
|
number_literal(const span& location, const f64 num):
|
||||||
expr(location, expr_type::ast_num), number(num) {}
|
expr(location, expr_type::ast_num), number(num) {}
|
||||||
~number_literal() = default;
|
~number_literal() override = default;
|
||||||
f64 get_number() const {return number;}
|
f64 get_number() const {return number;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
@ -120,7 +120,7 @@ private:
|
||||||
public:
|
public:
|
||||||
string_literal(const span& location, const std::string& str):
|
string_literal(const span& location, const std::string& str):
|
||||||
expr(location, expr_type::ast_str), content(str) {}
|
expr(location, expr_type::ast_str), content(str) {}
|
||||||
~string_literal() = default;
|
~string_literal() override = default;
|
||||||
const std::string get_content() const {return content;}
|
const std::string get_content() const {return content;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
@ -132,8 +132,8 @@ private:
|
||||||
public:
|
public:
|
||||||
identifier(const span& location, const std::string& str):
|
identifier(const span& location, const std::string& str):
|
||||||
expr(location, expr_type::ast_id), name(str) {}
|
expr(location, expr_type::ast_id), name(str) {}
|
||||||
~identifier() = default;
|
~identifier() override = default;
|
||||||
const std::string get_name() const {return name;}
|
const std::string& get_name() const {return name;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ private:
|
||||||
public:
|
public:
|
||||||
bool_literal(const span& location, const bool bool_flag):
|
bool_literal(const span& location, const bool bool_flag):
|
||||||
expr(location, expr_type::ast_bool), flag(bool_flag) {}
|
expr(location, expr_type::ast_bool), flag(bool_flag) {}
|
||||||
~bool_literal() = default;
|
~bool_literal() override = default;
|
||||||
bool get_flag() const {return flag;}
|
bool get_flag() const {return flag;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
@ -156,7 +156,7 @@ private:
|
||||||
public:
|
public:
|
||||||
vector_expr(const span& location):
|
vector_expr(const span& location):
|
||||||
expr(location, expr_type::ast_vec) {}
|
expr(location, expr_type::ast_vec) {}
|
||||||
~vector_expr();
|
~vector_expr() override;
|
||||||
void add_element(expr* node) {elements.push_back(node);}
|
void add_element(expr* node) {elements.push_back(node);}
|
||||||
std::vector<expr*>& get_elements() {return elements;}
|
std::vector<expr*>& get_elements() {return elements;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -169,7 +169,7 @@ private:
|
||||||
public:
|
public:
|
||||||
hash_expr(const span& location):
|
hash_expr(const span& location):
|
||||||
expr(location, expr_type::ast_hash) {}
|
expr(location, expr_type::ast_hash) {}
|
||||||
~hash_expr();
|
~hash_expr() override;
|
||||||
void add_member(hash_pair* node) {members.push_back(node);}
|
void add_member(hash_pair* node) {members.push_back(node);}
|
||||||
std::vector<hash_pair*>& get_members() {return members;}
|
std::vector<hash_pair*>& get_members() {return members;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -184,7 +184,7 @@ public:
|
||||||
hash_pair(const span& location):
|
hash_pair(const span& location):
|
||||||
expr(location, expr_type::ast_pair),
|
expr(location, expr_type::ast_pair),
|
||||||
value(nullptr) {}
|
value(nullptr) {}
|
||||||
~hash_pair();
|
~hash_pair() override;
|
||||||
void set_name(const std::string& field_name) {name = field_name;}
|
void set_name(const std::string& field_name) {name = field_name;}
|
||||||
void set_value(expr* node) {value = node;}
|
void set_value(expr* node) {value = node;}
|
||||||
const std::string& get_name() const {return name;}
|
const std::string& get_name() const {return name;}
|
||||||
|
@ -201,7 +201,7 @@ public:
|
||||||
function(const span& location):
|
function(const span& location):
|
||||||
expr(location, expr_type::ast_func),
|
expr(location, expr_type::ast_func),
|
||||||
block(nullptr) {}
|
block(nullptr) {}
|
||||||
~function();
|
~function() override;
|
||||||
void add_parameter(parameter* node) {parameter_list.push_back(node);}
|
void add_parameter(parameter* node) {parameter_list.push_back(node);}
|
||||||
void set_code_block(code_block* node) {block = node;}
|
void set_code_block(code_block* node) {block = node;}
|
||||||
std::vector<parameter*>& get_parameter_list() {return parameter_list;}
|
std::vector<parameter*>& get_parameter_list() {return parameter_list;}
|
||||||
|
@ -216,7 +216,7 @@ private:
|
||||||
public:
|
public:
|
||||||
code_block(const span& location):
|
code_block(const span& location):
|
||||||
expr(location, expr_type::ast_block) {}
|
expr(location, expr_type::ast_block) {}
|
||||||
~code_block();
|
~code_block() override;
|
||||||
void add_expression(expr* node) {expressions.push_back(node);}
|
void add_expression(expr* node) {expressions.push_back(node);}
|
||||||
std::vector<expr*>& get_expressions() {return expressions;}
|
std::vector<expr*>& get_expressions() {return expressions;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -239,7 +239,7 @@ public:
|
||||||
parameter(const span& location):
|
parameter(const span& location):
|
||||||
expr(location, expr_type::ast_param),
|
expr(location, expr_type::ast_param),
|
||||||
name(""), default_value(nullptr) {}
|
name(""), default_value(nullptr) {}
|
||||||
~parameter();
|
~parameter() override;
|
||||||
void set_parameter_type(param_type pt) {type = pt;}
|
void set_parameter_type(param_type pt) {type = pt;}
|
||||||
void set_parameter_name(const std::string& pname) {name = pname;}
|
void set_parameter_name(const std::string& pname) {name = pname;}
|
||||||
void set_default_value(expr* node) {default_value = node;}
|
void set_default_value(expr* node) {default_value = node;}
|
||||||
|
@ -259,7 +259,7 @@ public:
|
||||||
ternary_operator(const span& location):
|
ternary_operator(const span& location):
|
||||||
expr(location, expr_type::ast_ternary),
|
expr(location, expr_type::ast_ternary),
|
||||||
condition(nullptr), left(nullptr), right(nullptr) {}
|
condition(nullptr), left(nullptr), right(nullptr) {}
|
||||||
~ternary_operator();
|
~ternary_operator() override;
|
||||||
void set_condition(expr* node) {condition = node;}
|
void set_condition(expr* node) {condition = node;}
|
||||||
void set_left(expr* node) {left = node;}
|
void set_left(expr* node) {left = node;}
|
||||||
void set_right(expr* node) {right = node;}
|
void set_right(expr* node) {right = node;}
|
||||||
|
@ -303,7 +303,7 @@ public:
|
||||||
left(nullptr), right(nullptr),
|
left(nullptr), right(nullptr),
|
||||||
optimized_const_number(nullptr),
|
optimized_const_number(nullptr),
|
||||||
optimized_const_string(nullptr) {}
|
optimized_const_string(nullptr) {}
|
||||||
~binary_operator();
|
~binary_operator() override;
|
||||||
void set_operator_type(binary_type operator_type) {type = operator_type;}
|
void set_operator_type(binary_type operator_type) {type = operator_type;}
|
||||||
void set_left(expr* node) {left = node;}
|
void set_left(expr* node) {left = node;}
|
||||||
void set_right(expr* node) {right = node;}
|
void set_right(expr* node) {right = node;}
|
||||||
|
@ -334,7 +334,7 @@ public:
|
||||||
unary_operator(const span& location):
|
unary_operator(const span& location):
|
||||||
expr(location, expr_type::ast_unary),
|
expr(location, expr_type::ast_unary),
|
||||||
value(nullptr), optimized_number(nullptr) {}
|
value(nullptr), optimized_number(nullptr) {}
|
||||||
~unary_operator();
|
~unary_operator() override;
|
||||||
void set_operator_type(unary_type operator_type) {type = operator_type;}
|
void set_operator_type(unary_type operator_type) {type = operator_type;}
|
||||||
void set_value(expr* node) {value = node;}
|
void set_value(expr* node) {value = node;}
|
||||||
void set_optimized_number(number_literal* node) {optimized_number = node;}
|
void set_optimized_number(number_literal* node) {optimized_number = node;}
|
||||||
|
@ -353,7 +353,7 @@ public:
|
||||||
call_expr(const span& location):
|
call_expr(const span& location):
|
||||||
expr(location, expr_type::ast_call),
|
expr(location, expr_type::ast_call),
|
||||||
first(nullptr) {}
|
first(nullptr) {}
|
||||||
~call_expr();
|
~call_expr() override;
|
||||||
void set_first(expr* node) {first = node;}
|
void set_first(expr* node) {first = node;}
|
||||||
void add_call(call* node) {calls.push_back(node);}
|
void add_call(call* node) {calls.push_back(node);}
|
||||||
expr* get_first() {return first;}
|
expr* get_first() {return first;}
|
||||||
|
@ -369,7 +369,7 @@ public:
|
||||||
call_hash(const span& location, const std::string& name):
|
call_hash(const span& location, const std::string& name):
|
||||||
call(location, expr_type::ast_callh),
|
call(location, expr_type::ast_callh),
|
||||||
field(name) {}
|
field(name) {}
|
||||||
~call_hash() = default;
|
~call_hash() override = default;
|
||||||
const std::string& get_field() const {return field;}
|
const std::string& get_field() const {return field;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
@ -381,7 +381,7 @@ private:
|
||||||
public:
|
public:
|
||||||
call_vector(const span& location):
|
call_vector(const span& location):
|
||||||
call(location, expr_type::ast_callv) {}
|
call(location, expr_type::ast_callv) {}
|
||||||
~call_vector();
|
~call_vector() override;
|
||||||
void add_slice(slice_vector* node) {calls.push_back(node);}
|
void add_slice(slice_vector* node) {calls.push_back(node);}
|
||||||
std::vector<slice_vector*>& get_slices() {return calls;}
|
std::vector<slice_vector*>& get_slices() {return calls;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -394,7 +394,7 @@ private:
|
||||||
public:
|
public:
|
||||||
call_function(const span& location):
|
call_function(const span& location):
|
||||||
call(location, expr_type::ast_callf) {}
|
call(location, expr_type::ast_callf) {}
|
||||||
~call_function();
|
~call_function() override;
|
||||||
void add_argument(expr* node) {args.push_back(node);}
|
void add_argument(expr* node) {args.push_back(node);}
|
||||||
std::vector<expr*>& get_argument() {return args;}
|
std::vector<expr*>& get_argument() {return args;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -409,7 +409,7 @@ public:
|
||||||
slice_vector(const span& location):
|
slice_vector(const span& location):
|
||||||
expr(location, expr_type::ast_subvec),
|
expr(location, expr_type::ast_subvec),
|
||||||
begin(nullptr), end(nullptr) {}
|
begin(nullptr), end(nullptr) {}
|
||||||
~slice_vector();
|
~slice_vector() override;
|
||||||
void set_begin(expr* node) {begin = node;}
|
void set_begin(expr* node) {begin = node;}
|
||||||
void set_end(expr* node) {end = node;}
|
void set_end(expr* node) {end = node;}
|
||||||
expr* get_begin() {return begin;}
|
expr* get_begin() {return begin;}
|
||||||
|
@ -429,7 +429,7 @@ public:
|
||||||
expr(location, expr_type::ast_def),
|
expr(location, expr_type::ast_def),
|
||||||
variable_name(nullptr), variables(nullptr),
|
variable_name(nullptr), variables(nullptr),
|
||||||
tuple(nullptr), value(nullptr) {}
|
tuple(nullptr), value(nullptr) {}
|
||||||
~definition_expr();
|
~definition_expr() override;
|
||||||
void set_identifier(identifier* node) {variable_name = node;}
|
void set_identifier(identifier* node) {variable_name = node;}
|
||||||
void set_multi_define(multi_identifier* node) {variables = node;}
|
void set_multi_define(multi_identifier* node) {variables = node;}
|
||||||
void set_tuple(tuple_expr* node) {tuple = node;}
|
void set_tuple(tuple_expr* node) {tuple = node;}
|
||||||
|
@ -464,7 +464,7 @@ public:
|
||||||
assignment_expr(const span& location):
|
assignment_expr(const span& location):
|
||||||
expr(location, expr_type::ast_assign),
|
expr(location, expr_type::ast_assign),
|
||||||
left(nullptr), right(nullptr) {}
|
left(nullptr), right(nullptr) {}
|
||||||
~assignment_expr();
|
~assignment_expr() override;
|
||||||
void set_assignment_type(assign_type operator_type) {type = operator_type;}
|
void set_assignment_type(assign_type operator_type) {type = operator_type;}
|
||||||
void set_left(expr* node) {left = node;}
|
void set_left(expr* node) {left = node;}
|
||||||
void set_right(expr* node) {right = node;}
|
void set_right(expr* node) {right = node;}
|
||||||
|
@ -481,7 +481,7 @@ private:
|
||||||
public:
|
public:
|
||||||
multi_identifier(const span& location):
|
multi_identifier(const span& location):
|
||||||
expr(location, expr_type::ast_multi_id) {}
|
expr(location, expr_type::ast_multi_id) {}
|
||||||
~multi_identifier();
|
~multi_identifier() override;
|
||||||
void add_var(identifier* node) {variables.push_back(node);}
|
void add_var(identifier* node) {variables.push_back(node);}
|
||||||
std::vector<identifier*>& get_variables() {return variables;}
|
std::vector<identifier*>& get_variables() {return variables;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -494,7 +494,7 @@ private:
|
||||||
public:
|
public:
|
||||||
tuple_expr(const span& location):
|
tuple_expr(const span& location):
|
||||||
expr(location, expr_type::ast_tuple) {}
|
expr(location, expr_type::ast_tuple) {}
|
||||||
~tuple_expr();
|
~tuple_expr() override;
|
||||||
void add_element(expr* node) {elements.push_back(node);}
|
void add_element(expr* node) {elements.push_back(node);}
|
||||||
std::vector<expr*>& get_elements() {return elements;}
|
std::vector<expr*>& get_elements() {return elements;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
@ -509,7 +509,7 @@ public:
|
||||||
multi_assign(const span& location):
|
multi_assign(const span& location):
|
||||||
expr(location, expr_type::ast_multi_assign),
|
expr(location, expr_type::ast_multi_assign),
|
||||||
tuple(nullptr), value(nullptr) {}
|
tuple(nullptr), value(nullptr) {}
|
||||||
~multi_assign();
|
~multi_assign() override;
|
||||||
void set_tuple(tuple_expr* node) {tuple = node;}
|
void set_tuple(tuple_expr* node) {tuple = node;}
|
||||||
void set_value(expr* node) {value = node;}
|
void set_value(expr* node) {value = node;}
|
||||||
tuple_expr* get_tuple() {return tuple;}
|
tuple_expr* get_tuple() {return tuple;}
|
||||||
|
@ -526,7 +526,7 @@ public:
|
||||||
while_expr(const span& location):
|
while_expr(const span& location):
|
||||||
expr(location, expr_type::ast_while),
|
expr(location, expr_type::ast_while),
|
||||||
condition(nullptr), block(nullptr) {}
|
condition(nullptr), block(nullptr) {}
|
||||||
~while_expr();
|
~while_expr() override;
|
||||||
void set_condition(expr* node) {condition = node;}
|
void set_condition(expr* node) {condition = node;}
|
||||||
void set_code_block (code_block* node) {block = node;}
|
void set_code_block (code_block* node) {block = node;}
|
||||||
expr* get_condition() {return condition;}
|
expr* get_condition() {return condition;}
|
||||||
|
@ -546,7 +546,7 @@ public:
|
||||||
expr(location, expr_type::ast_for),
|
expr(location, expr_type::ast_for),
|
||||||
initializing(nullptr), condition(nullptr),
|
initializing(nullptr), condition(nullptr),
|
||||||
step(nullptr), block(nullptr) {}
|
step(nullptr), block(nullptr) {}
|
||||||
~for_expr();
|
~for_expr() override;
|
||||||
void set_initial(expr* node) {initializing = node;}
|
void set_initial(expr* node) {initializing = node;}
|
||||||
void set_condition(expr* node) {condition = node;}
|
void set_condition(expr* node) {condition = node;}
|
||||||
void set_step(expr* node) {step = node;}
|
void set_step(expr* node) {step = node;}
|
||||||
|
@ -567,7 +567,7 @@ public:
|
||||||
iter_expr(const span& location):
|
iter_expr(const span& location):
|
||||||
expr(location, expr_type::ast_iter),
|
expr(location, expr_type::ast_iter),
|
||||||
name(nullptr), call(nullptr) {}
|
name(nullptr), call(nullptr) {}
|
||||||
~iter_expr();
|
~iter_expr() override;
|
||||||
void set_name(identifier* node) {name = node;}
|
void set_name(identifier* node) {name = node;}
|
||||||
void set_call(call_expr* node) {call = node;}
|
void set_call(call_expr* node) {call = node;}
|
||||||
identifier* get_name() {return name;}
|
identifier* get_name() {return name;}
|
||||||
|
@ -593,7 +593,7 @@ public:
|
||||||
expr(location, expr_type::ast_forei),
|
expr(location, expr_type::ast_forei),
|
||||||
type(forei_loop_type::foreach), iterator(nullptr),
|
type(forei_loop_type::foreach), iterator(nullptr),
|
||||||
vector_node(nullptr), block(nullptr) {}
|
vector_node(nullptr), block(nullptr) {}
|
||||||
~forei_expr();
|
~forei_expr() override;
|
||||||
void set_loop_type(forei_loop_type ft) {type = ft;}
|
void set_loop_type(forei_loop_type ft) {type = ft;}
|
||||||
void set_iterator(iter_expr* node) {iterator = node;}
|
void set_iterator(iter_expr* node) {iterator = node;}
|
||||||
void set_value(expr* node) {vector_node = node;}
|
void set_value(expr* node) {vector_node = node;}
|
||||||
|
@ -615,7 +615,7 @@ public:
|
||||||
condition_expr(const span& location):
|
condition_expr(const span& location):
|
||||||
expr(location, expr_type::ast_cond),
|
expr(location, expr_type::ast_cond),
|
||||||
if_stmt(nullptr), else_stmt(nullptr) {}
|
if_stmt(nullptr), else_stmt(nullptr) {}
|
||||||
~condition_expr();
|
~condition_expr() override;
|
||||||
void set_if_statement(if_expr* node) {if_stmt = node;}
|
void set_if_statement(if_expr* node) {if_stmt = node;}
|
||||||
void add_elsif_statement(if_expr* node) {elsif_stmt.push_back(node);}
|
void add_elsif_statement(if_expr* node) {elsif_stmt.push_back(node);}
|
||||||
void set_else_statement(if_expr* node) {else_stmt = node;}
|
void set_else_statement(if_expr* node) {else_stmt = node;}
|
||||||
|
@ -634,7 +634,7 @@ public:
|
||||||
if_expr(const span& location):
|
if_expr(const span& location):
|
||||||
expr(location, expr_type::ast_if),
|
expr(location, expr_type::ast_if),
|
||||||
condition(nullptr), block(nullptr) {}
|
condition(nullptr), block(nullptr) {}
|
||||||
~if_expr();
|
~if_expr() override;
|
||||||
void set_condition(expr* node) {condition = node;}
|
void set_condition(expr* node) {condition = node;}
|
||||||
void set_code_block(code_block* node) {block = node;}
|
void set_code_block(code_block* node) {block = node;}
|
||||||
expr* get_condition() {return condition;}
|
expr* get_condition() {return condition;}
|
||||||
|
@ -646,7 +646,7 @@ class continue_expr:public expr {
|
||||||
public:
|
public:
|
||||||
continue_expr(const span& location):
|
continue_expr(const span& location):
|
||||||
expr(location, expr_type::ast_continue) {}
|
expr(location, expr_type::ast_continue) {}
|
||||||
~continue_expr() = default;
|
~continue_expr() override = default;
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ public:
|
||||||
return_expr(const span& location):
|
return_expr(const span& location):
|
||||||
expr(location, expr_type::ast_ret),
|
expr(location, expr_type::ast_ret),
|
||||||
value(nullptr) {}
|
value(nullptr) {}
|
||||||
~return_expr();
|
~return_expr() override;
|
||||||
void set_value(expr* node) {value = node;}
|
void set_value(expr* node) {value = node;}
|
||||||
expr* get_value() {return value;}
|
expr* get_value() {return value;}
|
||||||
void accept(ast_visitor*) override;
|
void accept(ast_visitor*) override;
|
||||||
|
|
|
@ -307,7 +307,9 @@ var builtin_substr(var* local, gc& ngc) {
|
||||||
var builtin_streq(var* local, gc& ngc) {
|
var builtin_streq(var* local, gc& ngc) {
|
||||||
var a = local[1];
|
var a = local[1];
|
||||||
var b = local[2];
|
var b = local[2];
|
||||||
return var::num(f64((a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str())));
|
return var::num(static_cast<f64>(
|
||||||
|
(a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_left(var* local, gc& ngc) {
|
var builtin_left(var* local, gc& ngc) {
|
||||||
|
@ -410,9 +412,11 @@ var builtin_sleep(var* local, gc& ngc) {
|
||||||
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
|
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
|
||||||
// mingw-w64 win32 thread model has no std::this_thread
|
// mingw-w64 win32 thread model has no std::this_thread
|
||||||
// also msvc will use this
|
// also msvc will use this
|
||||||
Sleep(i64(val.num()*1e3));
|
Sleep(static_cast<i64>(val.num()*1e3));
|
||||||
#else
|
#else
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(i64(val.num()*1e6)));
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::microseconds(static_cast<i64>(val.num()*1e6))
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +473,7 @@ std::string md5(const std::string& src) {
|
||||||
usize buffsize = num<<4;
|
usize buffsize = num<<4;
|
||||||
buff.resize(buffsize,0);
|
buff.resize(buffsize,0);
|
||||||
for(usize i = 0; i<src.length(); i++) {
|
for(usize i = 0; i<src.length(); i++) {
|
||||||
buff[i>>2] |= ((u8)src[i])<<((i&0x3)<<3);
|
buff[i>>2] |= (static_cast<u8>(src[i]))<<((i&0x3)<<3);
|
||||||
}
|
}
|
||||||
buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3);
|
buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3);
|
||||||
buff[buffsize-2] = (src.length()<<3)&0xffffffff;
|
buff[buffsize-2] = (src.length()<<3)&0xffffffff;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,9 @@ class codegen {
|
||||||
private:
|
private:
|
||||||
error err;
|
error err;
|
||||||
|
|
||||||
|
//
|
||||||
|
bool need_repl_output;
|
||||||
|
|
||||||
// file mapper for file -> index
|
// file mapper for file -> index
|
||||||
std::unordered_map<std::string, usize> file_map;
|
std::unordered_map<std::string, usize> file_map;
|
||||||
void init_file_map(const std::vector<std::string>&);
|
void init_file_map(const std::vector<std::string>&);
|
||||||
|
@ -79,11 +82,11 @@ private:
|
||||||
void regist_str(const std::string&);
|
void regist_str(const std::string&);
|
||||||
void find_symbol(code_block*);
|
void find_symbol(code_block*);
|
||||||
void add_symbol(const std::string&);
|
void add_symbol(const std::string&);
|
||||||
i32 local_find(const std::string&);
|
i32 local_symbol_find(const std::string&);
|
||||||
i32 global_find(const std::string&);
|
i32 global_symbol_find(const std::string&);
|
||||||
i32 upvalue_find(const std::string&);
|
i32 upvalue_symbol_find(const std::string&);
|
||||||
|
|
||||||
void gen(u8, u32, const span&);
|
void emit(u8, u32, const span&);
|
||||||
|
|
||||||
void num_gen(number_literal*);
|
void num_gen(number_literal*);
|
||||||
void str_gen(string_literal*);
|
void str_gen(string_literal*);
|
||||||
|
@ -104,6 +107,8 @@ private:
|
||||||
void single_def(definition_expr*);
|
void single_def(definition_expr*);
|
||||||
void def_gen(definition_expr*);
|
void def_gen(definition_expr*);
|
||||||
void assignment_expression(assignment_expr*);
|
void assignment_expression(assignment_expr*);
|
||||||
|
void gen_assignment_equal_statement(assignment_expr*);
|
||||||
|
void replace_left_assignment_with_load(const span&);
|
||||||
void assignment_statement(assignment_expr*);
|
void assignment_statement(assignment_expr*);
|
||||||
void multi_assign_gen(multi_assign*);
|
void multi_assign_gen(multi_assign*);
|
||||||
void cond_gen(condition_expr*);
|
void cond_gen(condition_expr*);
|
||||||
|
@ -119,6 +124,7 @@ private:
|
||||||
void binary_gen(binary_operator*);
|
void binary_gen(binary_operator*);
|
||||||
void trino_gen(ternary_operator*);
|
void trino_gen(ternary_operator*);
|
||||||
void calc_gen(expr*);
|
void calc_gen(expr*);
|
||||||
|
void repl_mode_info_output_gen(expr*);
|
||||||
void block_gen(code_block*);
|
void block_gen(code_block*);
|
||||||
void ret_gen(return_expr*);
|
void ret_gen(return_expr*);
|
||||||
|
|
||||||
|
@ -134,7 +140,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
codegen() = default;
|
codegen() = default;
|
||||||
const error& compile(parse&, linker&);
|
const error& compile(parse&, linker&, bool);
|
||||||
void print(std::ostream&);
|
void print(std::ostream&);
|
||||||
void symbol_dump(std::ostream&) const;
|
void symbol_dump(std::ostream&) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@ class dbg:public vm {
|
||||||
private:
|
private:
|
||||||
typedef void (dbg::*nasal_vm_func)();
|
typedef void (dbg::*nasal_vm_func)();
|
||||||
const nasal_vm_func operand_function[op_ret + 1] = {
|
const nasal_vm_func operand_function[op_ret + 1] = {
|
||||||
nullptr, &dbg::o_intg,
|
nullptr, &dbg::o_repl,
|
||||||
&dbg::o_intl, &dbg::o_loadg,
|
&dbg::o_intl, &dbg::o_loadg,
|
||||||
&dbg::o_loadl, &dbg::o_loadu,
|
&dbg::o_loadl, &dbg::o_loadu,
|
||||||
&dbg::o_pnum, &dbg::o_pnil,
|
&dbg::o_pnum, &dbg::o_pnil,
|
||||||
|
|
|
@ -536,7 +536,9 @@ void gc::extend(u8 type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::init(
|
void gc::init(
|
||||||
const std::vector<std::string>& s, const std::vector<std::string>& argv) {
|
const std::vector<std::string>& constant_strings,
|
||||||
|
const std::vector<std::string>& argv
|
||||||
|
) {
|
||||||
// initialize counters
|
// initialize counters
|
||||||
worktime = 0;
|
worktime = 0;
|
||||||
for(u8 i = 0; i<gc_type_size; ++i) {
|
for(u8 i = 0; i<gc_type_size; ++i) {
|
||||||
|
@ -547,16 +549,24 @@ void gc::init(
|
||||||
cort = nullptr;
|
cort = nullptr;
|
||||||
|
|
||||||
// init constant strings
|
// init constant strings
|
||||||
strs.resize(s.size());
|
strs.resize(constant_strings.size());
|
||||||
for(u32 i = 0; i<strs.size(); ++i) {
|
for(u32 i = 0; i<strs.size(); ++i) {
|
||||||
strs[i]=var::gcobj(new nas_val(vm_str));
|
// incremental initialization, avoid memory leak in repl mode
|
||||||
|
if (strs[i].type==vm_str && strs[i].str()==constant_strings[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
strs[i] = var::gcobj(new nas_val(vm_str));
|
||||||
strs[i].val.gcobj->unmut = 1;
|
strs[i].val.gcobj->unmut = 1;
|
||||||
strs[i].str() = s[i];
|
strs[i].str() = constant_strings[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// record arguments
|
// record arguments
|
||||||
env_argv.resize(argv.size());
|
env_argv.resize(argv.size());
|
||||||
for(usize i = 0; i<argv.size(); ++i) {
|
for(usize i = 0; i<argv.size(); ++i) {
|
||||||
|
// incremental initialization, avoid memory leak in repl mode
|
||||||
|
if (env_argv[i].type==vm_str && env_argv[i].str()==argv[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
env_argv[i] = var::gcobj(new nas_val(vm_str));
|
env_argv[i] = var::gcobj(new nas_val(vm_str));
|
||||||
env_argv[i].val.gcobj->unmut = 1;
|
env_argv[i].val.gcobj->unmut = 1;
|
||||||
env_argv[i].str() = argv[i];
|
env_argv[i].str() = argv[i];
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct nas_val; // nas_val includes gc-managed types
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
public:
|
public:
|
||||||
u8 type;
|
u8 type = vm_none;
|
||||||
union {
|
union {
|
||||||
u32 ret;
|
u32 ret;
|
||||||
i64 cnt;
|
i64 cnt;
|
||||||
|
|
|
@ -183,7 +183,7 @@ f64 str2num(const char* str) {
|
||||||
|
|
||||||
i32 utf8_hdchk(const char head) {
|
i32 utf8_hdchk(const char head) {
|
||||||
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||||
const u8 c = (u8)head;
|
const auto c = static_cast<u8>(head);
|
||||||
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
const char* opname[] = {
|
const char* opname[] = {
|
||||||
"exit ", "intg ", "intl ", "loadg ",
|
"exit ", "repl ", "intl ", "loadg ",
|
||||||
"loadl ", "loadu ", "pnum ", "pnil ",
|
"loadl ", "loadu ", "pnum ", "pnil ",
|
||||||
"pstr ", "newv ", "newh ", "newf ",
|
"pstr ", "newv ", "newh ", "newf ",
|
||||||
"happ ", "para ", "def ", "dyn ",
|
"happ ", "para ", "def ", "dyn ",
|
||||||
|
@ -81,7 +81,7 @@ void codestream::dump(std::ostream& out) const {
|
||||||
out << hex << "0x" << num << dec
|
out << hex << "0x" << num << dec
|
||||||
<< " (" << nums[num] << ")"; break;
|
<< " (" << nums[num] << ")"; break;
|
||||||
case op_callvi: case op_newv:
|
case op_callvi: case op_newv:
|
||||||
case op_callfv: case op_intg:
|
case op_callfv: case op_repl:
|
||||||
case op_intl: case op_findex:
|
case op_intl: case op_findex:
|
||||||
case op_feach: case op_newf:
|
case op_feach: case op_newf:
|
||||||
case op_jmp: case op_jt:
|
case op_jmp: case op_jt:
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace nasal {
|
||||||
|
|
||||||
enum op_code_type:u8 {
|
enum op_code_type:u8 {
|
||||||
op_exit, // stop the virtual machine
|
op_exit, // stop the virtual machine
|
||||||
op_intg, // init global scope
|
op_repl, // in repl mode: print value on stack top
|
||||||
op_intl, // local scope size
|
op_intl, // local scope size
|
||||||
op_loadg, // load global value
|
op_loadg, // load global value
|
||||||
op_loadl, // load local value
|
op_loadl, // load local value
|
||||||
|
|
|
@ -150,11 +150,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
||||||
~parse() {
|
~parse() {delete root;}
|
||||||
if (root) {
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const error& compile(const lexer&);
|
const error& compile(const lexer&);
|
||||||
static void easter_egg();
|
static void easter_egg();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ void vm::context_and_global_init() {
|
||||||
ctx.canary = ctx.stack+STACK_DEPTH-1;
|
ctx.canary = ctx.stack+STACK_DEPTH-1;
|
||||||
|
|
||||||
/* nothing is on stack */
|
/* nothing is on stack */
|
||||||
ctx.top = ctx.stack;
|
ctx.top = ctx.stack - 1;
|
||||||
|
|
||||||
/* clear main stack and global */
|
/* clear main stack and global */
|
||||||
for(u32 i = 0; i<STACK_DEPTH; ++i) {
|
for(u32 i = 0; i<STACK_DEPTH; ++i) {
|
||||||
|
@ -259,7 +259,7 @@ void vm::run(
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
// using labels as values/computed goto
|
// using labels as values/computed goto
|
||||||
const void* oprs[] = {
|
const void* oprs[] = {
|
||||||
&&vmexit, &&intg, &&intl, &&loadg,
|
&&vmexit, &&repl, &&intl, &&loadg,
|
||||||
&&loadl, &&loadu, &&pnum, &&pnil,
|
&&loadl, &&loadu, &&pnum, &&pnil,
|
||||||
&&pstr, &&newv, &&newh, &&newf,
|
&&pstr, &&newv, &&newh, &&newf,
|
||||||
&&happ, &¶, &&deft, &&dyn,
|
&&happ, &¶, &&deft, &&dyn,
|
||||||
|
@ -292,7 +292,7 @@ void vm::run(
|
||||||
#else
|
#else
|
||||||
typedef void (vm::*nafunc)();
|
typedef void (vm::*nafunc)();
|
||||||
const nafunc oprs[] = {
|
const nafunc oprs[] = {
|
||||||
nullptr, &vm::o_intg,
|
nullptr, &vm::o_repl,
|
||||||
&vm::o_intl, &vm::o_loadg,
|
&vm::o_intl, &vm::o_loadg,
|
||||||
&vm::o_loadl, &vm::o_loadu,
|
&vm::o_loadl, &vm::o_loadu,
|
||||||
&vm::o_pnum, &vm::o_pnil,
|
&vm::o_pnum, &vm::o_pnil,
|
||||||
|
@ -376,7 +376,7 @@ vmexit:
|
||||||
goto *code[++ctx.pc];\
|
goto *code[++ctx.pc];\
|
||||||
}
|
}
|
||||||
|
|
||||||
intg: exec_nodie(o_intg ); // +imm[pc] (detected at codegen)
|
repl: exec_nodie(o_repl ); // 0
|
||||||
intl: exec_nodie(o_intl ); // -0
|
intl: exec_nodie(o_intl ); // -0
|
||||||
loadg: exec_nodie(o_loadg ); // -1
|
loadg: exec_nodie(o_loadg ); // -1
|
||||||
loadl: exec_nodie(o_loadl ); // -1
|
loadl: exec_nodie(o_loadl ); // -1
|
||||||
|
|
|
@ -41,6 +41,7 @@ protected:
|
||||||
/* variables for repl mode */
|
/* variables for repl mode */
|
||||||
bool is_repl_mode = false;
|
bool is_repl_mode = false;
|
||||||
bool first_exec_flag = true;
|
bool first_exec_flag = true;
|
||||||
|
bool allow_repl_output = false;
|
||||||
|
|
||||||
/* vm initializing function */
|
/* vm initializing function */
|
||||||
void init(
|
void init(
|
||||||
|
@ -70,7 +71,7 @@ protected:
|
||||||
inline bool cond(var&);
|
inline bool cond(var&);
|
||||||
|
|
||||||
/* vm operands */
|
/* vm operands */
|
||||||
inline void o_intg();
|
inline void o_repl();
|
||||||
inline void o_intl();
|
inline void o_intl();
|
||||||
inline void o_loadg();
|
inline void o_loadg();
|
||||||
inline void o_loadl();
|
inline void o_loadl();
|
||||||
|
@ -180,6 +181,8 @@ public:
|
||||||
void set_detail_report_info(bool flag) {verbose = flag;}
|
void set_detail_report_info(bool flag) {verbose = flag;}
|
||||||
/* set repl mode flag */
|
/* set repl mode flag */
|
||||||
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
|
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
|
||||||
|
/* set repl output flag */
|
||||||
|
void set_allow_repl_output_flag(bool flag) {allow_repl_output = flag;}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool vm::cond(var& val) {
|
inline bool vm::cond(var& val) {
|
||||||
|
@ -192,11 +195,11 @@ inline bool vm::cond(var& val) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_intg() {
|
inline void vm::o_repl() {
|
||||||
// global values store on stack
|
// reserved for repl mode stack top value output
|
||||||
// ctx.top += imm[ctx.pc];
|
if (allow_repl_output) {
|
||||||
// point to the top
|
std::cout << ctx.top[0] << "\n";
|
||||||
--ctx.top;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_intl() {
|
inline void vm::o_intl() {
|
||||||
|
@ -301,9 +304,7 @@ inline void vm::o_lnot() {
|
||||||
ctx.top[0] = num? zero:one;
|
ctx.top[0] = num? zero:one;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default: die("incorrect value type"); return;
|
||||||
die("incorrect value type");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,22 +318,25 @@ inline void vm::o_bnot() {
|
||||||
|
|
||||||
inline void vm::o_btor() {
|
inline void vm::o_btor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())|
|
static_cast<i32>(ctx.top[-1].tonum())|
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btxor() {
|
inline void vm::o_btxor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())^
|
static_cast<i32>(ctx.top[-1].tonum())^
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btand() {
|
inline void vm::o_btand() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())&
|
static_cast<i32>(ctx.top[-1].tonum())&
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,25 +392,36 @@ inline void vm::o_subeq() {op_calc_eq(-);}
|
||||||
inline void vm::o_muleq() {op_calc_eq(*);}
|
inline void vm::o_muleq() {op_calc_eq(*);}
|
||||||
inline void vm::o_diveq() {op_calc_eq(/);}
|
inline void vm::o_diveq() {op_calc_eq(/);}
|
||||||
inline void vm::o_lnkeq() {
|
inline void vm::o_lnkeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+ctx.top[-1].tostr());
|
ctx.top[-1] = ctx.memr[0] = ngc.newstr(
|
||||||
|
ctx.memr[0].tostr()+ctx.top[-1].tostr()
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bandeq() {
|
inline void vm::o_bandeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())&i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())&
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_boreq() {
|
inline void vm::o_boreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())|i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())|
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bxoreq() {
|
inline void vm::o_bxoreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())^i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())^
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +454,9 @@ inline void vm::o_subecp() {op_calc_eq_const_and_pop(-);}
|
||||||
inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
|
inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
|
||||||
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
||||||
inline void vm::o_lnkecp() {
|
inline void vm::o_lnkecp() {
|
||||||
ctx.top[0] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+cstr[imm[ctx.pc]]);
|
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
||||||
|
ctx.memr[0].tostr()+cstr[imm[ctx.pc]]
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
@ -461,12 +478,12 @@ inline void vm::o_eq() {
|
||||||
if (val1.type==vm_nil && val2.type==vm_nil) {
|
if (val1.type==vm_nil && val2.type==vm_nil) {
|
||||||
ctx.top[0] = one;
|
ctx.top[0] = one;
|
||||||
} else if (val1.type==vm_str && val2.type==vm_str) {
|
} else if (val1.type==vm_str && val2.type==vm_str) {
|
||||||
ctx.top[0] = (val1.str()==val2.str())?one:zero;
|
ctx.top[0] = (val1.str()==val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()==val2.tonum())?one:zero;
|
ctx.top[0] = (val1.tonum()==val2.tonum())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1==val2)?one:zero;
|
ctx.top[0] = (val1==val2)? one:zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,12 +493,12 @@ inline void vm::o_neq() {
|
||||||
if (val1.type==vm_nil && val2.type==vm_nil) {
|
if (val1.type==vm_nil && val2.type==vm_nil) {
|
||||||
ctx.top[0] = zero;
|
ctx.top[0] = zero;
|
||||||
} else if (val1.type==vm_str && val2.type==vm_str) {
|
} else if (val1.type==vm_str && val2.type==vm_str) {
|
||||||
ctx.top[0] = (val1.str()!=val2.str())?one:zero;
|
ctx.top[0] = (val1.str()!=val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()!=val2.tonum())?one:zero;
|
ctx.top[0] = (val1.tonum()!=val2.tonum())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1!=val2)?one:zero;
|
ctx.top[0] = (val1!=val2)? one:zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +614,9 @@ inline void vm::o_callv() {
|
||||||
die("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = var::num(f64((u8)str[num>=0? num:num+len]));
|
ctx.top[0] = var::num(
|
||||||
|
static_cast<f64>(static_cast<u8>(str[num>=0? num:num+len]))
|
||||||
|
);
|
||||||
} else if (vec.type==vm_map) {
|
} else if (vec.type==vm_map) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("must use string as the key");
|
die("must use string as the key");
|
||||||
|
|
|
@ -32,11 +32,11 @@ void optimizer::const_number(
|
||||||
case binary_operator::binary_type::grt: res = left>right; break;
|
case binary_operator::binary_type::grt: res = left>right; break;
|
||||||
case binary_operator::binary_type::geq: res = left>=right; break;
|
case binary_operator::binary_type::geq: res = left>=right; break;
|
||||||
case binary_operator::binary_type::bitwise_or:
|
case binary_operator::binary_type::bitwise_or:
|
||||||
res = i32(left)|i32(right); break;
|
res = static_cast<i32>(left)|static_cast<i32>(right); break;
|
||||||
case binary_operator::binary_type::bitwise_xor:
|
case binary_operator::binary_type::bitwise_xor:
|
||||||
res = i32(left)^i32(right); break;
|
res = static_cast<i32>(left)^static_cast<i32>(right); break;
|
||||||
case binary_operator::binary_type::bitwise_and:
|
case binary_operator::binary_type::bitwise_and:
|
||||||
res = i32(left)&i32(right); break;
|
res = static_cast<i32>(left)&static_cast<i32>(right); break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
if (std::isinf(res) || std::isnan(res)) {
|
if (std::isinf(res) || std::isnan(res)) {
|
||||||
|
@ -51,9 +51,12 @@ void optimizer::const_number(
|
||||||
number_literal* value_node) {
|
number_literal* value_node) {
|
||||||
auto res = value_node->get_number();
|
auto res = value_node->get_number();
|
||||||
switch(node->get_operator_type()) {
|
switch(node->get_operator_type()) {
|
||||||
case unary_operator::unary_type::negative: res = -res; break;
|
case unary_operator::unary_type::negative:
|
||||||
case unary_operator::unary_type::bitwise_not: res = ~i32(res); break;
|
res = -res; break;
|
||||||
case unary_operator::unary_type::logical_not: res = !res; break;
|
case unary_operator::unary_type::bitwise_not:
|
||||||
|
res = ~static_cast<i32>(res); break;
|
||||||
|
case unary_operator::unary_type::logical_not:
|
||||||
|
res = !res; break;
|
||||||
}
|
}
|
||||||
if (std::isinf(res) || std::isnan(res)) {
|
if (std::isinf(res) || std::isnan(res)) {
|
||||||
return;
|
return;
|
||||||
|
|
34
src/repl.cpp
34
src/repl.cpp
|
@ -9,6 +9,16 @@
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
namespace repl {
|
namespace repl {
|
||||||
|
|
||||||
|
void repl::add_command_history(const std::string& history) {
|
||||||
|
if (command_history.size() && command_history.back()==history) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
command_history.push_back(history);
|
||||||
|
if (command_history.size()>1000) {
|
||||||
|
command_history.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string repl::readline(std::string prompt = ">>> ") {
|
std::string repl::readline(std::string prompt = ">>> ") {
|
||||||
auto line = std::string("");
|
auto line = std::string("");
|
||||||
std::cout << prompt;
|
std::cout << prompt;
|
||||||
|
@ -51,6 +61,7 @@ bool repl::check_need_more_input() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto line = readline("... ");
|
auto line = readline("... ");
|
||||||
|
add_command_history(line);
|
||||||
source.back() += "\n" + line;
|
source.back() += "\n" + line;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -66,16 +77,12 @@ void repl::help() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool repl::run() {
|
bool repl::run() {
|
||||||
using clk = std::chrono::high_resolution_clock;
|
|
||||||
const auto den = clk::duration::period::den;
|
|
||||||
|
|
||||||
auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
|
auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
|
||||||
auto nasal_parser = std::unique_ptr<parse>(new parse);
|
auto nasal_parser = std::unique_ptr<parse>(new parse);
|
||||||
auto nasal_linker = std::unique_ptr<linker>(new linker);
|
auto nasal_linker = std::unique_ptr<linker>(new linker);
|
||||||
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
|
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
|
||||||
auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
|
auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
|
||||||
|
|
||||||
auto start = clk::now();
|
|
||||||
update_temp_file();
|
update_temp_file();
|
||||||
if (nasal_lexer->scan("<nasal-repl>").geterr()) {
|
if (nasal_lexer->scan("<nasal-repl>").geterr()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -89,25 +96,25 @@ bool repl::run() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nasal_opt->do_optimization(nasal_parser->tree());
|
nasal_opt->do_optimization(nasal_parser->tree());
|
||||||
if (nasal_codegen->compile(*nasal_parser, *nasal_linker).geterr()) {
|
if (nasal_codegen->compile(*nasal_parser, *nasal_linker, true).geterr()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end = clk::now();
|
|
||||||
std::clog << "[compile time: " << (end-start).count()*1000.0/den << " ms]\n";
|
|
||||||
|
|
||||||
// TODO: gc init stage in this run may cause memory leak,
|
|
||||||
// because constant strings will be generated again.
|
|
||||||
// but we could not delete old strings, they maybe still on stack.
|
|
||||||
runtime.run(*nasal_codegen, *nasal_linker, {});
|
runtime.run(*nasal_codegen, *nasal_linker, {});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void repl::execute() {
|
void repl::execute() {
|
||||||
source = {};
|
source = {};
|
||||||
|
// mark we are in repl mode
|
||||||
info::instance()->in_repl_mode = true;
|
info::instance()->in_repl_mode = true;
|
||||||
|
std::cout << "[nasal-repl] Initializating enviroment...\n";
|
||||||
|
// run on pass for initializing basic modules, without output
|
||||||
|
run();
|
||||||
|
// allow output now
|
||||||
|
runtime.set_allow_repl_output_flag(true);
|
||||||
|
std::cout << "[nasal-repl] Initialization complete.\n\n";
|
||||||
|
|
||||||
std::cout << "Nasal REPL interpreter(experimental).\n";
|
std::cout << "Nasal REPL interpreter(experimental).\n";
|
||||||
help();
|
help();
|
||||||
|
@ -117,6 +124,7 @@ void repl::execute() {
|
||||||
if (!line.length()) {
|
if (!line.length()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
add_command_history(line);
|
||||||
|
|
||||||
if (line == ".e" || line == ".exit") {
|
if (line == ".e" || line == ".exit") {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
namespace repl {
|
namespace repl {
|
||||||
|
@ -27,9 +28,11 @@ struct info {
|
||||||
class repl {
|
class repl {
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> source;
|
std::vector<std::string> source;
|
||||||
|
std::deque<std::string> command_history;
|
||||||
vm runtime;
|
vm runtime;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void add_command_history(const std::string&);
|
||||||
std::string readline(std::string);
|
std::string readline(std::string);
|
||||||
bool check_need_more_input();
|
bool check_need_more_input();
|
||||||
void update_temp_file();
|
void update_temp_file();
|
||||||
|
@ -42,6 +45,8 @@ public:
|
||||||
runtime.set_repl_mode_flag(true);
|
runtime.set_repl_mode_flag(true);
|
||||||
// no detail report info
|
// no detail report info
|
||||||
runtime.set_detail_report_info(false);
|
runtime.set_detail_report_info(false);
|
||||||
|
// set empty history
|
||||||
|
command_history = {""};
|
||||||
}
|
}
|
||||||
void execute();
|
void execute();
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# utils.nas
|
||||||
|
# 2023 by ValKmjolnir
|
||||||
|
|
||||||
|
var times_trigger = func(times, count) {
|
||||||
|
return math.mod(times, count)==0;
|
||||||
|
}
|
Loading…
Reference in New Issue