update

This commit is contained in:
ValKmjolnir 2023-07-04 00:33:57 +08:00
parent 27bc544bbe
commit 5c714d26aa
13 changed files with 221 additions and 191 deletions

View File

@ -1,4 +1,4 @@
# __Nasal Script__ # __Nasal - Modern Interpreter__
<img src="./doc/pic/header.png" style="width:800px"></img> <img src="./doc/pic/header.png" style="width:800px"></img>

View File

@ -1,4 +1,4 @@
# __Nasal Script__ # __Nasal - Modern Interpreter__
<img src="../doc/pic/header.png" style="width:800px"></img> <img src="../doc/pic/header.png" style="width:800px"></img>
@ -32,7 +32,7 @@ __如果有好的意见或建议欢迎联系我们!__
是一款语法与ECMAscript相似的编程语言并作为运行脚本被著名开源飞行模拟器 [FlightGear](https://www.flightgear.org/) 所使用。 是一款语法与ECMAscript相似的编程语言并作为运行脚本被著名开源飞行模拟器 [FlightGear](https://www.flightgear.org/) 所使用。
该语言的设计者为 [Andy Ross](https://github.com/andyross)。 该语言的设计者为 [Andy Ross](https://github.com/andyross)。
该解释器项目由 [ValKmjolnir](https://github.com/ValKmjolnir) 完全使用 `C++`(`-std=c++14`)重新实现,没有复用 [Andy Ross的nasal解释器](https://github.com/andyross/nasal) 中的任何一行代码。尽管没有参考任何代码我们依然非常感谢Andy为我们带来了这样一个神奇且简洁的编程语言。 该解释器项目由 [ValKmjolnir](https://github.com/ValKmjolnir) 完全使用 `C++`(`-std=c++17`)重新实现,没有复用 [Andy Ross的nasal解释器](https://github.com/andyross/nasal) 中的任何一行代码。尽管没有参考任何代码我们依然非常感谢Andy为我们带来了这样一个神奇且简洁的编程语言。
该项目使用 __MIT__ 协议开源 (2019/7 ~ 2021/5/4 ~ 2023/5),从 2023/6 开始使用 __GPL v2__ 协议。 该项目使用 __MIT__ 协议开源 (2019/7 ~ 2021/5/4 ~ 2023/5),从 2023/6 开始使用 __GPL v2__ 协议。

View File

@ -289,7 +289,11 @@ bool ast_dumper::visit_definition_expr(definition_expr* node) {
node->get_variables()->accept(this); node->get_variables()->accept(this);
} }
set_last(); set_last();
if (node->get_tuple()) {
node->get_tuple()->accept(this);
} else {
node->get_value()->accept(this); node->get_value()->accept(this);
}
pop_indent(); pop_indent();
return true; return true;
} }
@ -297,6 +301,17 @@ bool ast_dumper::visit_definition_expr(definition_expr* node) {
bool ast_dumper::visit_assignment_expr(assignment_expr* node) { bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
dump_indent(); dump_indent();
std::cout << "assignment "; std::cout << "assignment ";
switch(node->get_assignment_type()) {
case assignment_expr::assign_type::add_equal: std::cout << "+="; break;
case assignment_expr::assign_type::sub_equal: std::cout << "-="; break;
case assignment_expr::assign_type::mult_equal: std::cout << "*="; break;
case assignment_expr::assign_type::div_equal: std::cout << "/="; break;
case assignment_expr::assign_type::concat_equal: std::cout << "~="; break;
case assignment_expr::assign_type::equal: std::cout << "="; break;
case assignment_expr::assign_type::bitwise_and_equal: std::cout << "&="; break;
case assignment_expr::assign_type::bitwise_or_equal: std::cout << "|="; break;
case assignment_expr::assign_type::bitwise_xor_equal: std::cout << "^="; break;
}
std::cout << format_location(node->get_location()); std::cout << format_location(node->get_location());
push_indent(); push_indent();
node->get_left()->accept(this); node->get_left()->accept(this);
@ -308,7 +323,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
bool ast_dumper::visit_multi_identifier(multi_identifier* node) { bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
dump_indent(); dump_indent();
std::cout << "multiple_definition"; std::cout << "multiple_identifier";
std::cout << format_location(node->get_location()); std::cout << format_location(node->get_location());
push_indent(); push_indent();
for(auto i : node->get_variables()) { for(auto i : node->get_variables()) {

View File

@ -134,7 +134,11 @@ bool ast_visitor::visit_definition_expr(definition_expr* node) {
} else { } else {
node->get_variables()->accept(this); node->get_variables()->accept(this);
} }
if (node->get_tuple()) {
node->get_tuple()->accept(this);
} else {
node->get_value()->accept(this); node->get_value()->accept(this);
}
return true; return true;
} }

View File

@ -78,7 +78,7 @@ std::ostream& version(std::ostream& out) {
if (num<0.01) { if (num<0.01) {
parse::easter_egg(); parse::easter_egg();
} }
out << "version " << __nasver; out << "nasal interpreter version " << __nasver;
out << " (" << __DATE__ << " " << __TIME__ << ")\n"; out << " (" << __DATE__ << " " << __TIME__ << ")\n";
return out; return out;
} }
@ -112,9 +112,8 @@ void execute(
// parser gets lexer's token list to compile // parser gets lexer's token list to compile
parse.compile(lex).chkerr(); parse.compile(lex).chkerr();
if (cmd&VM_RAW_AST) { if (cmd&VM_RAW_AST) {
auto dumper = new ast_dumper; auto dumper = std::unique_ptr<ast_dumper>(new ast_dumper);
dumper->dump(parse.tree()); dumper->dump(parse.tree());
delete dumper;
} }
// linker gets parser's ast and load import files to this ast // linker gets parser's ast and load import files to this ast
@ -125,9 +124,8 @@ void execute(
opt->do_optimization(parse.tree()); opt->do_optimization(parse.tree());
delete opt; delete opt;
if (cmd&VM_AST) { if (cmd&VM_AST) {
auto dumper = new ast_dumper; auto dumper = std::unique_ptr<ast_dumper>(new ast_dumper);
dumper->dump(parse.tree()); dumper->dump(parse.tree());
delete dumper;
} }
// 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

View File

@ -201,6 +201,9 @@ definition_expr::~definition_expr() {
if (variables) { if (variables) {
delete variables; delete variables;
} }
if (tuple) {
delete tuple;
}
if (value) { if (value) {
delete value; delete value;
} }

View File

@ -51,6 +51,7 @@ class slice_vector;
class multi_identifier; class multi_identifier;
class code_block; class code_block;
class if_expr; class if_expr;
class tuple_expr;
class expr { class expr {
protected: protected:
@ -426,18 +427,22 @@ class definition_expr:public expr {
private: private:
identifier* variable_name; identifier* variable_name;
multi_identifier* variables; multi_identifier* variables;
tuple_expr* tuple;
expr* value; expr* value;
public: public:
definition_expr(const span& location): definition_expr(const span& location):
expr(location, expr_type::ast_def), expr(location, expr_type::ast_def),
variable_name(nullptr), variables(nullptr), value(nullptr) {} variable_name(nullptr), variables(nullptr),
tuple(nullptr), value(nullptr) {}
~definition_expr(); ~definition_expr();
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_value(expr* node) {value = node;} void set_value(expr* node) {value = node;}
identifier* get_variable_name() {return variable_name;} identifier* get_variable_name() {return variable_name;}
multi_identifier* get_variables() {return variables;} multi_identifier* get_variables() {return variables;}
tuple_expr* get_tuple() {return tuple;}
expr* get_value() {return value;} expr* get_value() {return value;}
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };
@ -562,7 +567,7 @@ public:
class iter_expr:public expr { class iter_expr:public expr {
private: private:
identifier* name; identifier* name;
expr* call; call_expr* call;
public: public:
iter_expr(const span& location): iter_expr(const span& location):
@ -570,9 +575,9 @@ public:
name(nullptr), call(nullptr) {} name(nullptr), call(nullptr) {}
~iter_expr(); ~iter_expr();
void set_name(identifier* node) {name = node;} void set_name(identifier* node) {name = node;}
void set_call(expr* node) {call = node;} void set_call(call_expr* node) {call = node;}
identifier* get_name() {return name;} identifier* get_name() {return name;}
expr* get_call() {return call;} call_expr* get_call() {return call;}
void accept(ast_visitor*) override; void accept(ast_visitor*) override;
}; };

View File

@ -27,27 +27,28 @@ void codegen::check_id_exist(identifier* node) {
} }
void codegen::regist_num(const f64 num) { void codegen::regist_num(const f64 num) {
if (!num_table.count(num)) { if (num_table.count(num)) {
return;
}
u32 size = num_table.size(); u32 size = num_table.size();
num_table[num] = size; num_table[num] = size;
num_res.push_back(num); num_res.push_back(num);
} }
}
void codegen::regist_str(const std::string& str) { void codegen::regist_str(const std::string& str) {
if (!str_table.count(str)) { if (str_table.count(str)) {
return;
}
u32 size = str_table.size(); u32 size = str_table.size();
str_table[str] = size; str_table[str] = size;
str_res.push_back(str); str_res.push_back(str);
} }
}
void codegen::find_symbol(code_block* node) { void codegen::find_symbol(code_block* node) {
auto finder = new symbol_finder; auto finder = std::unique_ptr<symbol_finder>(new symbol_finder);
for(const auto& i : finder->do_find(node)) { for(const auto& i : finder->do_find(node)) {
add_sym(i); add_sym(i);
} }
delete finder;
} }
void codegen::add_sym(const std::string& name) { void codegen::add_sym(const std::string& name) {
@ -104,8 +105,9 @@ void codegen::num_gen(number_literal* node) {
} }
void codegen::str_gen(string_literal* node) { void codegen::str_gen(string_literal* node) {
regist_str(node->get_content()); const auto& str = node->get_content();
gen(op_pstr, str_table.at(node->get_content()), node->get_line()); regist_str(str);
gen(op_pstr, str_table.at(str), node->get_line());
} }
void codegen::bool_gen(bool_literal* node) { void codegen::bool_gen(bool_literal* node) {
@ -235,8 +237,8 @@ void codegen::call_gen(call_expr* node) {
for(auto i : node->get_calls()) { for(auto i : node->get_calls()) {
switch(i->get_type()) { switch(i->get_type()) {
case expr_type::ast_callh: call_hash_gen((call_hash*)i); break; case expr_type::ast_callh: call_hash_gen((call_hash*)i); break;
case expr_type::ast_callv: call_vec((call_vector*)i); break; case expr_type::ast_callv: call_vector_gen((call_vector*)i); break;
case expr_type::ast_callf: call_func((call_function*)i); break; case expr_type::ast_callf: call_func_gen((call_function*)i); break;
default: break; default: break;
} }
} }
@ -275,7 +277,7 @@ void codegen::call_hash_gen(call_hash* node) {
gen(op_callh, str_table.at(node->get_field()), node->get_line()); gen(op_callh, str_table.at(node->get_field()), node->get_line());
} }
void codegen::call_vec(call_vector* node) { void codegen::call_vector_gen(call_vector* node) {
// maybe this place can use callv-const if ast's first child is ast_num // maybe this place can use callv-const if ast's first child is ast_num
if (node->get_slices().size()==1 && if (node->get_slices().size()==1 &&
!node->get_slices()[0]->get_end()) { !node->get_slices()[0]->get_end()) {
@ -297,7 +299,7 @@ void codegen::call_vec(call_vector* node) {
gen(op_slcend, 0, node->get_line()); gen(op_slcend, 0, node->get_line());
} }
void codegen::call_func(call_function* node) { void codegen::call_func_gen(call_function* node) {
if (node->get_argument().size() && if (node->get_argument().size() &&
node->get_argument()[0]->get_type()==expr_type::ast_pair) { node->get_argument()[0]->get_type()==expr_type::ast_pair) {
gen(op_newh, 0, node->get_line()); gen(op_newh, 0, node->get_line());
@ -340,8 +342,8 @@ void codegen::mcall(expr* node) {
auto tmp = call_node->get_calls()[i]; auto tmp = call_node->get_calls()[i];
switch(tmp->get_type()) { switch(tmp->get_type()) {
case expr_type::ast_callh: call_hash_gen((call_hash*)tmp); break; case expr_type::ast_callh: call_hash_gen((call_hash*)tmp); break;
case expr_type::ast_callv: call_vec((call_vector*)tmp); break; case expr_type::ast_callv: call_vector_gen((call_vector*)tmp); break;
case expr_type::ast_callf: call_func((call_function*)tmp); break; case expr_type::ast_callf: call_func_gen((call_function*)tmp); break;
default: break; default: break;
} }
} }
@ -411,12 +413,13 @@ void codegen::single_def(definition_expr* node) {
void codegen::multi_def(definition_expr* node) { void codegen::multi_def(definition_expr* node) {
auto& identifiers = node->get_variables()->get_variables(); auto& identifiers = node->get_variables()->get_variables();
usize size = identifiers.size(); usize size = identifiers.size();
if (node->get_value()->get_type()==expr_type::ast_tuple) { // (var a,b,c)=(c,b,a); // (var a,b,c) = (c,b,a);
auto& vals = ((tuple_expr*)node->get_value())->get_elements(); if (node->get_tuple()) {
auto& vals = node->get_tuple()->get_elements();
if (identifiers.size()<vals.size()) { if (identifiers.size()<vals.size()) {
die("lack values in multi-definition", node->get_value()->get_location()); die("lack values in multi-definition", node->get_tuple()->get_location());
} else if (identifiers.size()>vals.size()) { } else if (identifiers.size()>vals.size()) {
die("too many values in multi-definition", node->get_value()->get_location()); die("too many values in multi-definition", node->get_tuple()->get_location());
} }
for(usize i = 0; i<size; ++i) { for(usize i = 0; i<size; ++i) {
calc_gen(vals[i]); calc_gen(vals[i]);
@ -425,7 +428,9 @@ void codegen::multi_def(definition_expr* node) {
gen(op_loadg, global_find(name), identifiers[i]->get_line()): gen(op_loadg, global_find(name), identifiers[i]->get_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_line()); gen(op_loadl, local_find(name), identifiers[i]->get_line());
} }
} else { // (var a,b,c)=[0,1,2]; return;
}
// (var a,b,c) = [0,1,2];
calc_gen(node->get_value()); calc_gen(node->get_value());
for(usize i = 0; i<size; ++i) { for(usize i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_line()); gen(op_callvi, i, node->get_value()->get_line());
@ -436,11 +441,9 @@ void codegen::multi_def(definition_expr* node) {
} }
gen(op_pop, 0, node->get_line()); gen(op_pop, 0, node->get_line());
} }
}
void codegen::def_gen(definition_expr* node) { void codegen::def_gen(definition_expr* node) {
if (node->get_variable_name() && if (node->get_variable_name() && node->get_tuple()) {
node->get_value()->get_type()==expr_type::ast_tuple) {
die("cannot accept too many values", node->get_value()->get_location()); die("cannot accept too many values", node->get_value()->get_location());
} }
node->get_variable_name()? single_def(node):multi_def(node); node->get_variable_name()? single_def(node):multi_def(node);

View File

@ -65,8 +65,8 @@ private:
void call_gen(call_expr*); void call_gen(call_expr*);
void call_id(identifier*); void call_id(identifier*);
void call_hash_gen(call_hash*); void call_hash_gen(call_hash*);
void call_vec(call_vector*); void call_vector_gen(call_vector*);
void call_func(call_function*); void call_func_gen(call_function*);
void mcall(expr*); void mcall(expr*);
void mcall_id(identifier*); void mcall_id(identifier*);
void mcall_vec(call_vector*); void mcall_vec(call_vector*);

View File

@ -48,7 +48,7 @@ std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
} }
vec.printed = true; vec.printed = true;
usize iter = 0, size = vec.elems.size(); usize iter = 0, size = vec.elems.size();
out<<'['; out << "[";
for(auto& i:vec.elems) { for(auto& i:vec.elems) {
out << i << ",]"[(++iter)==size]; out << i << ",]"[(++iter)==size];
} }
@ -107,9 +107,9 @@ std::ostream& operator<<(std::ostream& out, nas_hash& hash) {
} }
hash.printed = true; hash.printed = true;
usize iter = 0, size = hash.elems.size(); usize iter = 0, size = hash.elems.size();
out<<'{'; out << "{";
for(auto& i : hash.elems) { for(auto& i : hash.elems) {
out<<i.first<<':'<<i.second<<",}"[(++iter)==size]; out << i.first << ":" << i.second << ",}"[(++iter)==size];
} }
hash.printed = false; hash.printed = false;
return out; return out;
@ -122,9 +122,10 @@ void nas_func::clear() {
keys.clear(); keys.clear();
} }
void nas_ghost::set(usize t, void* p, ghost_register_table* table) { void nas_ghost::set(
type=t; usize ghost_type, void* ghost_pointer, ghost_register_table* table) {
ptr=p; type = ghost_type;
ptr = ghost_pointer;
ghost_type_table = table; ghost_type_table = table;
} }
@ -400,13 +401,8 @@ void gc::extend(u8 type) {
size[index] += incr[index]; size[index] += incr[index];
for(u32 i = 0; i<incr[index]; ++i) { for(u32 i = 0; i<incr[index]; ++i) {
nas_val* tmp=new(std::nothrow) nas_val(type); // no need to check, will be killed if memory is not enough
nas_val* tmp = new nas_val(type);
if (!tmp) {
std::cerr<<"nasal_gc.h: gc::extend: ";
std::cerr<<"failed to allocate memory\n";
std::exit(1);
}
// add to heap // add to heap
memory.push_back(tmp); memory.push_back(tmp);

View File

@ -741,7 +741,9 @@ expr* parse::definition() {
} }
match(tok::eq); match(tok::eq);
if (lookahead(tok::lcurve)) { if (lookahead(tok::lcurve)) {
node->set_value(check_tuple()?multi_scalar():calc()); check_tuple()?
node->set_tuple(multi_scalar()):
node->set_value(calc());
} else { } else {
node->set_value(calc()); node->set_value(calc());
} }

View File

@ -8,7 +8,11 @@ bool symbol_finder::visit_definition_expr(definition_expr* node) {
symbols.push_back(i->get_name()); symbols.push_back(i->get_name());
} }
} }
if (node->get_tuple()) {
node->get_tuple()->accept(this);
} else {
node->get_value()->accept(this); node->get_value()->accept(this);
}
return true; return true;
} }