Merge pull request #29 from ValKmjolnir/develop

 improve codegen and repl output
This commit is contained in:
Li Haokun 2023-10-02 00:52:05 +08:00 committed by GitHub
commit 982c5750ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 510 additions and 373 deletions

View File

@ -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() {

View File

@ -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;

View File

@ -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},

View File

@ -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;

View File

@ -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

View File

@ -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;
}; };

View File

@ -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,

View File

@ -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];

View File

@ -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;

View File

@ -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;
} }

View File

@ -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:

View File

@ -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

View File

@ -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();
}; };

View File

@ -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, &&para, &&deft, &&dyn, &&happ, &&para, &&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

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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();
}; };

6
std/utils.nas Normal file
View File

@ -0,0 +1,6 @@
# utils.nas
# 2023 by ValKmjolnir
var times_trigger = func(times, count) {
return math.mod(times, count)==0;
}