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;
}
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);
fcntl(0, F_SETFL, flag);
if (nread==1) {
@ -83,25 +83,25 @@ public:
noecho_input this_window;
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) {
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) {
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;
}
module_func_info func_tbl[] = {
{"nas_getch",nas_getch},
{"nas_kbhit",nas_kbhit},
{"nas_noblock",nas_noblock},
{nullptr,nullptr}
{"nas_getch", nas_getch},
{"nas_kbhit", nas_kbhit},
{"nas_noblock", nas_noblock},
{nullptr, nullptr}
};
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)
return nas_err("socket", "\"af\", \"type\", \"protocol\" should be number");
int sd = socket(args[0].num(), args[1].num(), args[2].num());
return var::num((double)sd);
return var::num(static_cast<double>(sd));
}
var nas_closesocket(var* args, usize size, gc* ngc) {
if (args[0].type!=vm_num)
return nas_err("closesocket", "\"sd\" should be number");
#ifdef _WIN32
return var::num((double)closesocket(args[0].num()));
return var::num(static_cast<double>(closesocket(args[0].num())));
#else
return var::num((double)close(args[0].num()));
return var::num(static_cast<double>(close(args[0].num())));
#endif
}
@ -52,7 +52,7 @@ var nas_shutdown(var* args, usize size, gc* ngc) {
return nas_err("shutdown", "\"sd\" must be a number");
if (args[1].type!=vm_num)
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) {
@ -67,7 +67,11 @@ var nas_bind(var* args, usize size, gc* ngc) {
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(args[1].str().c_str());
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) {
@ -75,7 +79,7 @@ var nas_listen(var* args, usize size, gc* ngc) {
return nas_err("listen", "\"sd\" must be a number");
if (args[1].type!=vm_num)
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) {
@ -91,11 +95,11 @@ var nas_connect(var* args, usize size, gc* ngc) {
addr.sin_port = htons(args[2].num());
hostent* entry = gethostbyname(args[1].str().c_str());
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(),
(sockaddr*)&addr,
sizeof(sockaddr_in)
));
)));
}
var nas_accept(var* args, usize size, gc* ngc) {
@ -110,7 +114,7 @@ var nas_accept(var* args, usize size, gc* ngc) {
#endif
var res=ngc->temp = ngc->alloc(vm_hash);
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));
ngc->temp = nil;
return res;
@ -123,12 +127,12 @@ var nas_send(var* args, usize size, gc* ngc) {
return nas_err("send", "\"buff\" must be a string");
if (args[2].type!=vm_num)
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[1].str().c_str(),
args[1].str().length(),
args[2].num()
));
)));
}
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());
hostent* entry = gethostbyname(args[1].str().c_str());
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[3].str().c_str(),
args[3].str().length(),
args[4].num(),
(sockaddr*)&addr,
sizeof(sockaddr_in)
));
)));
}
var nas_recv(var* args, usize size, gc* ngc) {
@ -169,9 +173,9 @@ var nas_recv(var* args, usize size, gc* ngc) {
return nas_err("recv", "\"flags\" muse be a number");
var res = ngc->temp = ngc->alloc(vm_hash);
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());
hash["size"] = var::num((double)recvsize);
hash["size"] = var::num(static_cast<double>(recvsize));
buf[recvsize>=0? recvsize:0] = 0;
hash["str"] = ngc->newstr(buf);
delete[] buf;
@ -192,7 +196,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
int socklen = sizeof(sockaddr_in);
var res = ngc->temp = ngc->alloc(vm_hash);
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
auto recvsize = recvfrom(
args[0].num(),
@ -212,7 +216,7 @@ var nas_recvfrom(var* args, usize size, gc* ngc) {
(socklen_t*)&socklen
);
#endif
hash["size"] = var::num((double)recvsize);
hash["size"] = var::num(static_cast<double>(recvsize));
buf[recvsize>=0? recvsize:0] = 0;
hash["str"] = ngc->newstr(buf);
delete[] buf;

View File

@ -139,7 +139,7 @@ void execute(
}
// 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) {
gen.print(std::cout);
}
@ -192,7 +192,7 @@ i32 main(i32 argc, const char* argv[]) {
}
// execute with arguments
const std::unordered_map<std::string,u32> cmdlst = {
const std::unordered_map<std::string, u32> cmdlst = {
{"--raw-ast", VM_RAW_AST},
{"--ast", VM_AST},
{"-a", VM_AST},

View File

@ -62,7 +62,7 @@ protected:
public:
expr(const span& location, expr_type node_type):
nd_loc(location), nd_type(node_type) {}
~expr() = default;
virtual ~expr() = default;
void set_begin(u32 line, u32 column) {
nd_loc.begin_line = line;
nd_loc.begin_column = column;
@ -81,7 +81,7 @@ class call:public expr {
public:
call(const span& location, expr_type node_type):
expr(location, node_type) {}
~call() = default;
virtual ~call() = default;
virtual void accept(ast_visitor*);
};
@ -89,7 +89,7 @@ class null_expr:public expr {
public:
null_expr(const span& location):
expr(location, expr_type::ast_null) {}
~null_expr() = default;
~null_expr() override = default;
void accept(ast_visitor*) override;
};
@ -97,7 +97,7 @@ class nil_expr:public expr {
public:
nil_expr(const span& location):
expr(location, expr_type::ast_nil) {}
~nil_expr() = default;
~nil_expr() override = default;
void accept(ast_visitor*) override;
};
@ -108,7 +108,7 @@ private:
public:
number_literal(const span& location, const f64 num):
expr(location, expr_type::ast_num), number(num) {}
~number_literal() = default;
~number_literal() override = default;
f64 get_number() const {return number;}
void accept(ast_visitor*) override;
};
@ -120,7 +120,7 @@ private:
public:
string_literal(const span& location, const std::string& str):
expr(location, expr_type::ast_str), content(str) {}
~string_literal() = default;
~string_literal() override = default;
const std::string get_content() const {return content;}
void accept(ast_visitor*) override;
};
@ -132,8 +132,8 @@ private:
public:
identifier(const span& location, const std::string& str):
expr(location, expr_type::ast_id), name(str) {}
~identifier() = default;
const std::string get_name() const {return name;}
~identifier() override = default;
const std::string& get_name() const {return name;}
void accept(ast_visitor*) override;
};
@ -144,7 +144,7 @@ private:
public:
bool_literal(const span& location, const bool bool_flag):
expr(location, expr_type::ast_bool), flag(bool_flag) {}
~bool_literal() = default;
~bool_literal() override = default;
bool get_flag() const {return flag;}
void accept(ast_visitor*) override;
};
@ -156,7 +156,7 @@ private:
public:
vector_expr(const span& location):
expr(location, expr_type::ast_vec) {}
~vector_expr();
~vector_expr() override;
void add_element(expr* node) {elements.push_back(node);}
std::vector<expr*>& get_elements() {return elements;}
void accept(ast_visitor*) override;
@ -169,7 +169,7 @@ private:
public:
hash_expr(const span& location):
expr(location, expr_type::ast_hash) {}
~hash_expr();
~hash_expr() override;
void add_member(hash_pair* node) {members.push_back(node);}
std::vector<hash_pair*>& get_members() {return members;}
void accept(ast_visitor*) override;
@ -184,7 +184,7 @@ public:
hash_pair(const span& location):
expr(location, expr_type::ast_pair),
value(nullptr) {}
~hash_pair();
~hash_pair() override;
void set_name(const std::string& field_name) {name = field_name;}
void set_value(expr* node) {value = node;}
const std::string& get_name() const {return name;}
@ -201,7 +201,7 @@ public:
function(const span& location):
expr(location, expr_type::ast_func),
block(nullptr) {}
~function();
~function() override;
void add_parameter(parameter* node) {parameter_list.push_back(node);}
void set_code_block(code_block* node) {block = node;}
std::vector<parameter*>& get_parameter_list() {return parameter_list;}
@ -216,7 +216,7 @@ private:
public:
code_block(const span& location):
expr(location, expr_type::ast_block) {}
~code_block();
~code_block() override;
void add_expression(expr* node) {expressions.push_back(node);}
std::vector<expr*>& get_expressions() {return expressions;}
void accept(ast_visitor*) override;
@ -239,7 +239,7 @@ public:
parameter(const span& location):
expr(location, expr_type::ast_param),
name(""), default_value(nullptr) {}
~parameter();
~parameter() override;
void set_parameter_type(param_type pt) {type = pt;}
void set_parameter_name(const std::string& pname) {name = pname;}
void set_default_value(expr* node) {default_value = node;}
@ -259,7 +259,7 @@ public:
ternary_operator(const span& location):
expr(location, expr_type::ast_ternary),
condition(nullptr), left(nullptr), right(nullptr) {}
~ternary_operator();
~ternary_operator() override;
void set_condition(expr* node) {condition = node;}
void set_left(expr* node) {left = node;}
void set_right(expr* node) {right = node;}
@ -303,7 +303,7 @@ public:
left(nullptr), right(nullptr),
optimized_const_number(nullptr),
optimized_const_string(nullptr) {}
~binary_operator();
~binary_operator() override;
void set_operator_type(binary_type operator_type) {type = operator_type;}
void set_left(expr* node) {left = node;}
void set_right(expr* node) {right = node;}
@ -334,7 +334,7 @@ public:
unary_operator(const span& location):
expr(location, expr_type::ast_unary),
value(nullptr), optimized_number(nullptr) {}
~unary_operator();
~unary_operator() override;
void set_operator_type(unary_type operator_type) {type = operator_type;}
void set_value(expr* node) {value = node;}
void set_optimized_number(number_literal* node) {optimized_number = node;}
@ -353,7 +353,7 @@ public:
call_expr(const span& location):
expr(location, expr_type::ast_call),
first(nullptr) {}
~call_expr();
~call_expr() override;
void set_first(expr* node) {first = node;}
void add_call(call* node) {calls.push_back(node);}
expr* get_first() {return first;}
@ -369,7 +369,7 @@ public:
call_hash(const span& location, const std::string& name):
call(location, expr_type::ast_callh),
field(name) {}
~call_hash() = default;
~call_hash() override = default;
const std::string& get_field() const {return field;}
void accept(ast_visitor*) override;
};
@ -381,7 +381,7 @@ private:
public:
call_vector(const span& location):
call(location, expr_type::ast_callv) {}
~call_vector();
~call_vector() override;
void add_slice(slice_vector* node) {calls.push_back(node);}
std::vector<slice_vector*>& get_slices() {return calls;}
void accept(ast_visitor*) override;
@ -394,7 +394,7 @@ private:
public:
call_function(const span& location):
call(location, expr_type::ast_callf) {}
~call_function();
~call_function() override;
void add_argument(expr* node) {args.push_back(node);}
std::vector<expr*>& get_argument() {return args;}
void accept(ast_visitor*) override;
@ -409,7 +409,7 @@ public:
slice_vector(const span& location):
expr(location, expr_type::ast_subvec),
begin(nullptr), end(nullptr) {}
~slice_vector();
~slice_vector() override;
void set_begin(expr* node) {begin = node;}
void set_end(expr* node) {end = node;}
expr* get_begin() {return begin;}
@ -429,7 +429,7 @@ public:
expr(location, expr_type::ast_def),
variable_name(nullptr), variables(nullptr),
tuple(nullptr), value(nullptr) {}
~definition_expr();
~definition_expr() override;
void set_identifier(identifier* node) {variable_name = node;}
void set_multi_define(multi_identifier* node) {variables = node;}
void set_tuple(tuple_expr* node) {tuple = node;}
@ -464,7 +464,7 @@ public:
assignment_expr(const span& location):
expr(location, expr_type::ast_assign),
left(nullptr), right(nullptr) {}
~assignment_expr();
~assignment_expr() override;
void set_assignment_type(assign_type operator_type) {type = operator_type;}
void set_left(expr* node) {left = node;}
void set_right(expr* node) {right = node;}
@ -481,7 +481,7 @@ private:
public:
multi_identifier(const span& location):
expr(location, expr_type::ast_multi_id) {}
~multi_identifier();
~multi_identifier() override;
void add_var(identifier* node) {variables.push_back(node);}
std::vector<identifier*>& get_variables() {return variables;}
void accept(ast_visitor*) override;
@ -494,7 +494,7 @@ private:
public:
tuple_expr(const span& location):
expr(location, expr_type::ast_tuple) {}
~tuple_expr();
~tuple_expr() override;
void add_element(expr* node) {elements.push_back(node);}
std::vector<expr*>& get_elements() {return elements;}
void accept(ast_visitor*) override;
@ -509,7 +509,7 @@ public:
multi_assign(const span& location):
expr(location, expr_type::ast_multi_assign),
tuple(nullptr), value(nullptr) {}
~multi_assign();
~multi_assign() override;
void set_tuple(tuple_expr* node) {tuple = node;}
void set_value(expr* node) {value = node;}
tuple_expr* get_tuple() {return tuple;}
@ -526,7 +526,7 @@ public:
while_expr(const span& location):
expr(location, expr_type::ast_while),
condition(nullptr), block(nullptr) {}
~while_expr();
~while_expr() override;
void set_condition(expr* node) {condition = node;}
void set_code_block (code_block* node) {block = node;}
expr* get_condition() {return condition;}
@ -546,7 +546,7 @@ public:
expr(location, expr_type::ast_for),
initializing(nullptr), condition(nullptr),
step(nullptr), block(nullptr) {}
~for_expr();
~for_expr() override;
void set_initial(expr* node) {initializing = node;}
void set_condition(expr* node) {condition = node;}
void set_step(expr* node) {step = node;}
@ -567,7 +567,7 @@ public:
iter_expr(const span& location):
expr(location, expr_type::ast_iter),
name(nullptr), call(nullptr) {}
~iter_expr();
~iter_expr() override;
void set_name(identifier* node) {name = node;}
void set_call(call_expr* node) {call = node;}
identifier* get_name() {return name;}
@ -593,7 +593,7 @@ public:
expr(location, expr_type::ast_forei),
type(forei_loop_type::foreach), iterator(nullptr),
vector_node(nullptr), block(nullptr) {}
~forei_expr();
~forei_expr() override;
void set_loop_type(forei_loop_type ft) {type = ft;}
void set_iterator(iter_expr* node) {iterator = node;}
void set_value(expr* node) {vector_node = node;}
@ -615,7 +615,7 @@ public:
condition_expr(const span& location):
expr(location, expr_type::ast_cond),
if_stmt(nullptr), else_stmt(nullptr) {}
~condition_expr();
~condition_expr() override;
void set_if_statement(if_expr* node) {if_stmt = node;}
void add_elsif_statement(if_expr* node) {elsif_stmt.push_back(node);}
void set_else_statement(if_expr* node) {else_stmt = node;}
@ -634,7 +634,7 @@ public:
if_expr(const span& location):
expr(location, expr_type::ast_if),
condition(nullptr), block(nullptr) {}
~if_expr();
~if_expr() override;
void set_condition(expr* node) {condition = node;}
void set_code_block(code_block* node) {block = node;}
expr* get_condition() {return condition;}
@ -646,7 +646,7 @@ class continue_expr:public expr {
public:
continue_expr(const span& location):
expr(location, expr_type::ast_continue) {}
~continue_expr() = default;
~continue_expr() override = default;
void accept(ast_visitor*) override;
};
@ -666,7 +666,7 @@ public:
return_expr(const span& location):
expr(location, expr_type::ast_ret),
value(nullptr) {}
~return_expr();
~return_expr() override;
void set_value(expr* node) {value = node;}
expr* get_value() {return value;}
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 a = local[1];
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) {
@ -410,9 +412,11 @@ var builtin_sleep(var* local, gc& ngc) {
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
// mingw-w64 win32 thread model has no std::this_thread
// also msvc will use this
Sleep(i64(val.num()*1e3));
Sleep(static_cast<i64>(val.num()*1e3));
#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
return nil;
}
@ -469,7 +473,7 @@ std::string md5(const std::string& src) {
usize buffsize = num<<4;
buff.resize(buffsize,0);
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[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:
error err;
//
bool need_repl_output;
// file mapper for file -> index
std::unordered_map<std::string, usize> file_map;
void init_file_map(const std::vector<std::string>&);
@ -79,11 +82,11 @@ private:
void regist_str(const std::string&);
void find_symbol(code_block*);
void add_symbol(const std::string&);
i32 local_find(const std::string&);
i32 global_find(const std::string&);
i32 upvalue_find(const std::string&);
i32 local_symbol_find(const std::string&);
i32 global_symbol_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 str_gen(string_literal*);
@ -104,6 +107,8 @@ private:
void single_def(definition_expr*);
void def_gen(definition_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 multi_assign_gen(multi_assign*);
void cond_gen(condition_expr*);
@ -119,6 +124,7 @@ private:
void binary_gen(binary_operator*);
void trino_gen(ternary_operator*);
void calc_gen(expr*);
void repl_mode_info_output_gen(expr*);
void block_gen(code_block*);
void ret_gen(return_expr*);
@ -134,7 +140,7 @@ public:
public:
codegen() = default;
const error& compile(parse&, linker&);
const error& compile(parse&, linker&, bool);
void print(std::ostream&);
void symbol_dump(std::ostream&) const;
};

View File

@ -41,7 +41,7 @@ class dbg:public vm {
private:
typedef void (dbg::*nasal_vm_func)();
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_loadl, &dbg::o_loadu,
&dbg::o_pnum, &dbg::o_pnil,

View File

@ -536,7 +536,9 @@ void gc::extend(u8 type) {
}
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
worktime = 0;
for(u8 i = 0; i<gc_type_size; ++i) {
@ -547,16 +549,24 @@ void gc::init(
cort = nullptr;
// init constant strings
strs.resize(s.size());
strs.resize(constant_strings.size());
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].str() = s[i];
strs[i].str() = constant_strings[i];
}
// record arguments
env_argv.resize(argv.size());
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].val.gcobj->unmut = 1;
env_argv[i].str() = argv[i];

View File

@ -66,7 +66,7 @@ struct nas_val; // nas_val includes gc-managed types
struct var {
public:
u8 type;
u8 type = vm_none;
union {
u32 ret;
i64 cnt;

View File

@ -183,7 +183,7 @@ f64 str2num(const char* str) {
i32 utf8_hdchk(const char head) {
// 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
return 1;
}

View File

@ -3,7 +3,7 @@
namespace nasal {
const char* opname[] = {
"exit ", "intg ", "intl ", "loadg ",
"exit ", "repl ", "intl ", "loadg ",
"loadl ", "loadu ", "pnum ", "pnil ",
"pstr ", "newv ", "newh ", "newf ",
"happ ", "para ", "def ", "dyn ",
@ -81,7 +81,7 @@ void codestream::dump(std::ostream& out) const {
out << hex << "0x" << num << dec
<< " (" << nums[num] << ")"; break;
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_feach: case op_newf:
case op_jmp: case op_jt:

View File

@ -9,7 +9,7 @@ namespace nasal {
enum op_code_type:u8 {
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_loadg, // load global value
op_loadl, // load local value

View File

@ -150,11 +150,7 @@ public:
public:
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
~parse() {
if (root) {
delete root;
}
}
~parse() {delete root;}
const error& compile(const lexer&);
static void easter_egg();
};

View File

@ -55,7 +55,7 @@ void vm::context_and_global_init() {
ctx.canary = ctx.stack+STACK_DEPTH-1;
/* nothing is on stack */
ctx.top = ctx.stack;
ctx.top = ctx.stack - 1;
/* clear main stack and global */
for(u32 i = 0; i<STACK_DEPTH; ++i) {
@ -259,7 +259,7 @@ void vm::run(
#ifndef _MSC_VER
// using labels as values/computed goto
const void* oprs[] = {
&&vmexit, &&intg, &&intl, &&loadg,
&&vmexit, &&repl, &&intl, &&loadg,
&&loadl, &&loadu, &&pnum, &&pnil,
&&pstr, &&newv, &&newh, &&newf,
&&happ, &&para, &&deft, &&dyn,
@ -292,7 +292,7 @@ void vm::run(
#else
typedef void (vm::*nafunc)();
const nafunc oprs[] = {
nullptr, &vm::o_intg,
nullptr, &vm::o_repl,
&vm::o_intl, &vm::o_loadg,
&vm::o_loadl, &vm::o_loadu,
&vm::o_pnum, &vm::o_pnil,
@ -376,7 +376,7 @@ vmexit:
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
loadg: exec_nodie(o_loadg ); // -1
loadl: exec_nodie(o_loadl ); // -1

View File

@ -41,6 +41,7 @@ protected:
/* variables for repl mode */
bool is_repl_mode = false;
bool first_exec_flag = true;
bool allow_repl_output = false;
/* vm initializing function */
void init(
@ -70,7 +71,7 @@ protected:
inline bool cond(var&);
/* vm operands */
inline void o_intg();
inline void o_repl();
inline void o_intl();
inline void o_loadg();
inline void o_loadl();
@ -180,6 +181,8 @@ public:
void set_detail_report_info(bool flag) {verbose = flag;}
/* set 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) {
@ -192,11 +195,11 @@ inline bool vm::cond(var& val) {
return false;
}
inline void vm::o_intg() {
// global values store on stack
// ctx.top += imm[ctx.pc];
// point to the top
--ctx.top;
inline void vm::o_repl() {
// reserved for repl mode stack top value output
if (allow_repl_output) {
std::cout << ctx.top[0] << "\n";
}
}
inline void vm::o_intl() {
@ -301,9 +304,7 @@ inline void vm::o_lnot() {
ctx.top[0] = num? zero:one;
}
} break;
default:
die("incorrect value type");
return;
default: die("incorrect value type"); return;
}
}
@ -317,22 +318,25 @@ inline void vm::o_bnot() {
inline void vm::o_btor() {
ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())|
static_cast<int32_t>(ctx.top[0].tonum()));
static_cast<i32>(ctx.top[-1].tonum())|
static_cast<i32>(ctx.top[0].tonum())
);
--ctx.top;
}
inline void vm::o_btxor() {
ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())^
static_cast<int32_t>(ctx.top[0].tonum()));
static_cast<i32>(ctx.top[-1].tonum())^
static_cast<i32>(ctx.top[0].tonum())
);
--ctx.top;
}
inline void vm::o_btand() {
ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())&
static_cast<int32_t>(ctx.top[0].tonum()));
static_cast<i32>(ctx.top[-1].tonum())&
static_cast<i32>(ctx.top[0].tonum())
);
--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_diveq() {op_calc_eq(/);}
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.top -= imm[ctx.pc]+1;
}
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.top -= imm[ctx.pc]+1;
}
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.top -= imm[ctx.pc]+1;
}
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.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_divecp() {op_calc_eq_const_and_pop(/);}
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.top;
}
@ -461,12 +478,12 @@ inline void vm::o_eq() {
if (val1.type==vm_nil && val2.type==vm_nil) {
ctx.top[0] = one;
} 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)
&& 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 {
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) {
ctx.top[0] = zero;
} 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)
&& 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 {
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()));
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) {
if (val.type!=vm_str) {
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::geq: res = left>=right; break;
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:
res = i32(left)^i32(right); break;
res = static_cast<i32>(left)^static_cast<i32>(right); break;
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;
}
if (std::isinf(res) || std::isnan(res)) {
@ -51,9 +51,12 @@ void optimizer::const_number(
number_literal* value_node) {
auto res = value_node->get_number();
switch(node->get_operator_type()) {
case unary_operator::unary_type::negative: res = -res; break;
case unary_operator::unary_type::bitwise_not: res = ~i32(res); break;
case unary_operator::unary_type::logical_not: res = !res; break;
case unary_operator::unary_type::negative:
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)) {
return;

View File

@ -9,6 +9,16 @@
namespace nasal {
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 = ">>> ") {
auto line = std::string("");
std::cout << prompt;
@ -51,6 +61,7 @@ bool repl::check_need_more_input() {
}
auto line = readline("... ");
add_command_history(line);
source.back() += "\n" + line;
}
return true;
@ -66,16 +77,12 @@ void repl::help() {
}
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_parser = std::unique_ptr<parse>(new parse);
auto nasal_linker = std::unique_ptr<linker>(new linker);
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
auto start = clk::now();
update_temp_file();
if (nasal_lexer->scan("<nasal-repl>").geterr()) {
return false;
@ -89,25 +96,25 @@ bool repl::run() {
return false;
}
// nasal_opt->do_optimization(nasal_parser->tree());
if (nasal_codegen->compile(*nasal_parser, *nasal_linker).geterr()) {
nasal_opt->do_optimization(nasal_parser->tree());
if (nasal_codegen->compile(*nasal_parser, *nasal_linker, true).geterr()) {
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, {});
return true;
}
void repl::execute() {
source = {};
// mark we are in repl mode
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";
help();
@ -117,6 +124,7 @@ void repl::execute() {
if (!line.length()) {
continue;
}
add_command_history(line);
if (line == ".e" || line == ".exit") {
break;

View File

@ -8,6 +8,7 @@
#include <vector>
#include <cstring>
#include <sstream>
#include <deque>
namespace nasal {
namespace repl {
@ -27,9 +28,11 @@ struct info {
class repl {
private:
std::vector<std::string> source;
std::deque<std::string> command_history;
vm runtime;
private:
void add_command_history(const std::string&);
std::string readline(std::string);
bool check_need_more_input();
void update_temp_file();
@ -42,6 +45,8 @@ public:
runtime.set_repl_mode_flag(true);
// no detail report info
runtime.set_detail_report_info(false);
// set empty history
command_history = {""};
}
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;
}