diff --git a/README.md b/README.md
index 153fc09..d8b7a06 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# __Nasal Script__
+# __Nasal - Modern Interpreter__
@@ -36,7 +36,7 @@ This interpreter is totally rewritten by [ValKmjolnir](https://github.com/ValKmj
without reusing the code in [Andy Ross's nasal interpreter](https://github.com/andyross/nasal).
But we really appreciate that Andy created this amazing programming language.
-This project uses __MIT license__ (2019/7~2021/5/4~2023/5), __GPL v2 license__ (since 2023/6).
+This project uses __MIT license__ (2019/7 ~ 2021/5/4 ~ 2023/5), __GPL v2 license__ (since 2023/6).
### __Why writing this nasal interpreter?__
diff --git a/doc/README_zh.md b/doc/README_zh.md
index aef8878..43bbaa3 100644
--- a/doc/README_zh.md
+++ b/doc/README_zh.md
@@ -1,4 +1,4 @@
-# __Nasal Script__
+# __Nasal - Modern Interpreter__
@@ -32,9 +32,9 @@ __如果有好的意见或建议,欢迎联系我们!__
是一款语法与ECMAscript相似的编程语言,并作为运行脚本被著名开源飞行模拟器 [FlightGear](https://www.flightgear.org/) 所使用。
该语言的设计者为 [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__ 协议。
### __我们为什么想要重新写一个nasal解释器?__
diff --git a/src/ast_dumper.cpp b/src/ast_dumper.cpp
index 2596527..a549ded 100644
--- a/src/ast_dumper.cpp
+++ b/src/ast_dumper.cpp
@@ -289,14 +289,29 @@ bool ast_dumper::visit_definition_expr(definition_expr* node) {
node->get_variables()->accept(this);
}
set_last();
- node->get_value()->accept(this);
+ if (node->get_tuple()) {
+ node->get_tuple()->accept(this);
+ } else {
+ node->get_value()->accept(this);
+ }
pop_indent();
return true;
}
bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
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());
push_indent();
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) {
dump_indent();
- std::cout << "multiple_definition";
+ std::cout << "multiple_identifier";
std::cout << format_location(node->get_location());
push_indent();
for(auto i : node->get_variables()) {
diff --git a/src/ast_visitor.cpp b/src/ast_visitor.cpp
index 6d8c3e1..8757e63 100644
--- a/src/ast_visitor.cpp
+++ b/src/ast_visitor.cpp
@@ -5,6 +5,11 @@ bool ast_visitor::visit_expr(expr* node) {
return true;
}
+bool ast_visitor::visit_call(call* node) {
+ node->accept(this);
+ return true;
+}
+
bool ast_visitor::visit_file_info(file_info* node) {
return true;
}
@@ -134,7 +139,11 @@ bool ast_visitor::visit_definition_expr(definition_expr* node) {
} else {
node->get_variables()->accept(this);
}
- node->get_value()->accept(this);
+ if (node->get_tuple()) {
+ node->get_tuple()->accept(this);
+ } else {
+ node->get_value()->accept(this);
+ }
return true;
}
diff --git a/src/ast_visitor.h b/src/ast_visitor.h
index 4c2a1ed..932c912 100644
--- a/src/ast_visitor.h
+++ b/src/ast_visitor.h
@@ -5,6 +5,7 @@
class ast_visitor {
public:
virtual bool visit_expr(expr*);
+ virtual bool visit_call(call*);
virtual bool visit_file_info(file_info*);
virtual bool visit_null_expr(null_expr*);
virtual bool visit_nil_expr(nil_expr*);
diff --git a/src/main.cpp b/src/main.cpp
index 8202636..3fddb4e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -78,7 +78,7 @@ std::ostream& version(std::ostream& out) {
if (num<0.01) {
parse::easter_egg();
}
- out << "version " << __nasver;
+ out << "nasal interpreter version " << __nasver;
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
return out;
}
@@ -112,9 +112,8 @@ void execute(
// parser gets lexer's token list to compile
parse.compile(lex).chkerr();
if (cmd&VM_RAW_AST) {
- auto dumper = new ast_dumper;
+ auto dumper = std::unique_ptr(new ast_dumper);
dumper->dump(parse.tree());
- delete dumper;
}
// linker gets parser's ast and load import files to this ast
@@ -125,15 +124,14 @@ void execute(
opt->do_optimization(parse.tree());
delete opt;
if (cmd&VM_AST) {
- auto dumper = new ast_dumper;
+ auto dumper = std::unique_ptr(new ast_dumper);
dumper->dump(parse.tree());
- delete dumper;
}
// code generator gets parser's ast and import file list to generate code
gen.compile(parse, ld).chkerr();
if (cmd&VM_CODE) {
- gen.print();
+ gen.print(std::cout);
}
// run
diff --git a/src/nasal_ast.cpp b/src/nasal_ast.cpp
index 5eb9aee..03c8f14 100644
--- a/src/nasal_ast.cpp
+++ b/src/nasal_ast.cpp
@@ -5,6 +5,10 @@ void expr::accept(ast_visitor* visitor) {
visitor->visit_expr(this);
}
+void call::accept(ast_visitor* visitor) {
+ visitor->visit_call(this);
+}
+
void file_info::accept(ast_visitor* visitor) {
visitor->visit_file_info(this);
}
@@ -201,6 +205,9 @@ definition_expr::~definition_expr() {
if (variables) {
delete variables;
}
+ if (tuple) {
+ delete tuple;
+ }
if (value) {
delete value;
}
diff --git a/src/nasal_ast.h b/src/nasal_ast.h
index 370891d..35d03da 100644
--- a/src/nasal_ast.h
+++ b/src/nasal_ast.h
@@ -51,6 +51,7 @@ class slice_vector;
class multi_identifier;
class code_block;
class if_expr;
+class tuple_expr;
class expr {
protected:
@@ -75,6 +76,14 @@ public:
virtual void accept(ast_visitor*);
};
+class call:public expr {
+public:
+ call(const span& location, expr_type node_type):
+ expr(location, node_type) {}
+ ~call() = default;
+ virtual void accept(ast_visitor*);
+};
+
class file_info:public expr {
private:
uint16_t index;
@@ -352,7 +361,7 @@ public:
class call_expr:public expr {
private:
expr* first;
- std::vector calls;
+ std::vector calls;
public:
call_expr(const span& location):
@@ -360,45 +369,45 @@ public:
first(nullptr) {}
~call_expr();
void set_first(expr* node) {first = node;}
- void add_call(expr* node) {calls.push_back(node);}
+ void add_call(call* node) {calls.push_back(node);}
expr* get_first() {return first;}
- std::vector& get_calls() {return calls;}
+ std::vector& get_calls() {return calls;}
void accept(ast_visitor*) override;
};
-class call_hash:public expr {
+class call_hash:public call {
private:
std::string field;
public:
call_hash(const span& location, const std::string& name):
- expr(location, expr_type::ast_callh),
+ call(location, expr_type::ast_callh),
field(name) {}
~call_hash() = default;
const std::string& get_field() const {return field;}
void accept(ast_visitor*) override;
};
-class call_vector:public expr {
+class call_vector:public call {
private:
std::vector calls;
public:
call_vector(const span& location):
- expr(location, expr_type::ast_callv) {}
+ call(location, expr_type::ast_callv) {}
~call_vector();
void add_slice(slice_vector* node) {calls.push_back(node);}
std::vector& get_slices() {return calls;}
void accept(ast_visitor*) override;
};
-class call_function:public expr {
+class call_function:public call {
private:
std::vector args;
public:
call_function(const span& location):
- expr(location, expr_type::ast_callf) {}
+ call(location, expr_type::ast_callf) {}
~call_function();
void add_argument(expr* node) {args.push_back(node);}
std::vector& get_argument() {return args;}
@@ -426,18 +435,22 @@ class definition_expr:public expr {
private:
identifier* variable_name;
multi_identifier* variables;
+ tuple_expr* tuple;
expr* value;
public:
definition_expr(const span& location):
expr(location, expr_type::ast_def),
- variable_name(nullptr), variables(nullptr), value(nullptr) {}
+ variable_name(nullptr), variables(nullptr),
+ tuple(nullptr), value(nullptr) {}
~definition_expr();
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;}
void set_value(expr* node) {value = node;}
identifier* get_variable_name() {return variable_name;}
multi_identifier* get_variables() {return variables;}
+ tuple_expr* get_tuple() {return tuple;}
expr* get_value() {return value;}
void accept(ast_visitor*) override;
};
@@ -562,7 +575,7 @@ public:
class iter_expr:public expr {
private:
identifier* name;
- expr* call;
+ call_expr* call;
public:
iter_expr(const span& location):
@@ -570,9 +583,9 @@ public:
name(nullptr), call(nullptr) {}
~iter_expr();
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;}
- expr* get_call() {return call;}
+ call_expr* get_call() {return call;}
void accept(ast_visitor*) override;
};
diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp
index a6282f6..0312fec 100644
--- a/src/nasal_codegen.cpp
+++ b/src/nasal_codegen.cpp
@@ -27,30 +27,31 @@ void codegen::check_id_exist(identifier* node) {
}
void codegen::regist_num(const f64 num) {
- if (!num_table.count(num)) {
- u32 size = num_table.size();
- num_table[num] = size;
- num_res.push_back(num);
+ if (const_number_map.count(num)) {
+ return;
}
+ u32 size = const_number_map.size();
+ const_number_map[num] = size;
+ const_number_table.push_back(num);
}
void codegen::regist_str(const std::string& str) {
- if (!str_table.count(str)) {
- u32 size = str_table.size();
- str_table[str] = size;
- str_res.push_back(str);
+ if (const_string_map.count(str)) {
+ return;
}
+ u32 size = const_string_map.size();
+ const_string_map[str] = size;
+ const_string_table.push_back(str);
}
void codegen::find_symbol(code_block* node) {
- auto finder = new symbol_finder;
+ auto finder = std::unique_ptr(new symbol_finder);
for(const auto& i : finder->do_find(node)) {
- add_sym(i);
+ add_symbol(i);
}
- delete finder;
}
-void codegen::add_sym(const std::string& name) {
+void codegen::add_symbol(const std::string& name) {
if (local.empty()) {
if (global.count(name)) {
return;
@@ -100,18 +101,19 @@ void codegen::gen(u8 operation_code, u32 num, u32 line) {
void codegen::num_gen(number_literal* node) {
f64 num = node->get_number();
regist_num(num);
- gen(op_pnum,num_table.at(num), node->get_line());
+ gen(op_pnum,const_number_map.at(num), node->get_line());
}
void codegen::str_gen(string_literal* node) {
- regist_str(node->get_content());
- gen(op_pstr, str_table.at(node->get_content()), node->get_line());
+ const auto& str = node->get_content();
+ regist_str(str);
+ gen(op_pstr, const_string_map.at(str), node->get_line());
}
void codegen::bool_gen(bool_literal* node) {
f64 num = node->get_flag()? 1:0;
regist_num(num);
- gen(op_pnum, num_table.at(num), node->get_line());
+ gen(op_pnum, const_number_map.at(num), node->get_line());
}
void codegen::vec_gen(vector_expr* node) {
@@ -127,7 +129,7 @@ void codegen::hash_gen(hash_expr* node) {
calc_gen(child->get_value());
const auto& field_name = child->get_name();
regist_str(field_name);
- gen(op_happ, str_table.at(field_name), child->get_line());
+ gen(op_happ, const_string_map.at(field_name), child->get_line());
}
}
@@ -188,17 +190,17 @@ void codegen::func_gen(function* node) {
regist_str(name);
switch(tmp->get_parameter_type()) {
case parameter::param_type::normal_parameter:
- gen(op_para, str_table.at(name), tmp->get_line());
+ gen(op_para, const_string_map.at(name), tmp->get_line());
break;
case parameter::param_type::default_parameter:
calc_gen(tmp->get_default_value());
- gen(op_deft, str_table.at(name), tmp->get_line());
+ gen(op_deft, const_string_map.at(name), tmp->get_line());
break;
case parameter::param_type::dynamic_parameter:
- gen(op_dyn, str_table.at(name), tmp->get_line());
+ gen(op_dyn, const_string_map.at(name), tmp->get_line());
break;
}
- add_sym(name);
+ add_symbol(name);
}
code[newf].num = code.size()+1; // entry
@@ -235,8 +237,8 @@ void codegen::call_gen(call_expr* node) {
for(auto i : node->get_calls()) {
switch(i->get_type()) {
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_callf: call_func((call_function*)i); break;
+ case expr_type::ast_callv: call_vector_gen((call_vector*)i); break;
+ case expr_type::ast_callf: call_func_gen((call_function*)i); break;
default: break;
}
}
@@ -272,10 +274,10 @@ void codegen::call_id(identifier* node) {
void codegen::call_hash_gen(call_hash* node) {
regist_str(node->get_field());
- gen(op_callh, str_table.at(node->get_field()), node->get_line());
+ gen(op_callh, const_string_map.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
if (node->get_slices().size()==1 &&
!node->get_slices()[0]->get_end()) {
@@ -297,7 +299,7 @@ void codegen::call_vec(call_vector* node) {
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() &&
node->get_argument()[0]->get_type()==expr_type::ast_pair) {
gen(op_newh, 0, node->get_line());
@@ -305,7 +307,7 @@ void codegen::call_func(call_function* node) {
calc_gen(((hash_pair*)child)->get_value());
const auto& field_name = ((hash_pair*)child)->get_name();
regist_str(field_name);
- gen(op_happ, str_table.at(field_name), child->get_line());
+ gen(op_happ, const_string_map.at(field_name), child->get_line());
}
gen(op_callfh, 0, node->get_line());
} else {
@@ -340,8 +342,8 @@ void codegen::mcall(expr* node) {
auto tmp = call_node->get_calls()[i];
switch(tmp->get_type()) {
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_callf: call_func((call_function*)tmp); break;
+ case expr_type::ast_callv: call_vector_gen((call_vector*)tmp); break;
+ case expr_type::ast_callf: call_func_gen((call_function*)tmp); break;
default: break;
}
}
@@ -397,7 +399,7 @@ void codegen::mcall_vec(call_vector* node) {
void codegen::mcall_hash(call_hash* node) {
regist_str(node->get_field());
- gen(op_mcallh, str_table.at(node->get_field()), node->get_line());
+ gen(op_mcallh, const_string_map.at(node->get_field()), node->get_line());
}
void codegen::single_def(definition_expr* node) {
@@ -411,12 +413,15 @@ void codegen::single_def(definition_expr* node) {
void codegen::multi_def(definition_expr* node) {
auto& identifiers = node->get_variables()->get_variables();
usize size = identifiers.size();
- if (node->get_value()->get_type()==expr_type::ast_tuple) { // (var a,b,c)=(c,b,a);
- auto& vals = ((tuple_expr*)node->get_value())->get_elements();
+ // (var a,b,c) = (c,b,a);
+ if (node->get_tuple()) {
+ auto& vals = node->get_tuple()->get_elements();
if (identifiers.size()get_value()->get_location());
+ die("lack values in multi-definition",
+ node->get_tuple()->get_location());
} 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; iget_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_line());
}
- } else { // (var a,b,c)=[0,1,2];
- calc_gen(node->get_value());
- for(usize i = 0; iget_value()->get_line());
- const auto& name = identifiers[i]->get_name();
- local.empty()?
- gen(op_loadg, global_find(name), identifiers[i]->get_line()):
- gen(op_loadl, local_find(name), identifiers[i]->get_line());
- }
- gen(op_pop, 0, node->get_line());
+ return;
}
+ // (var a,b,c) = [0,1,2];
+ calc_gen(node->get_value());
+ for(usize i = 0; iget_value()->get_line());
+ const auto& name = identifiers[i]->get_name();
+ local.empty()?
+ gen(op_loadg, global_find(name), identifiers[i]->get_line()):
+ gen(op_loadl, local_find(name), identifiers[i]->get_line());
+ }
+ gen(op_pop, 0, node->get_line());
}
void codegen::def_gen(definition_expr* node) {
- if (node->get_variable_name() &&
- node->get_value()->get_type()==expr_type::ast_tuple) {
+ if (node->get_variable_name() && node->get_tuple()) {
die("cannot accept too many values", node->get_value()->get_location());
}
node->get_variable_name()? single_def(node):multi_def(node);
@@ -463,7 +468,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_addeqc, num_table[num], node->get_line());
+ gen(op_addeqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::sub_equal:
@@ -476,7 +481,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_subeqc, num_table[num], node->get_line());
+ gen(op_subeqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::mult_equal:
@@ -489,7 +494,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_muleqc, num_table[num], node->get_line());
+ gen(op_muleqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::div_equal:
@@ -502,7 +507,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_diveqc, num_table[num], node->get_line());
+ gen(op_diveqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::concat_equal:
@@ -515,7 +520,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
- gen(op_lnkeqc, str_table[str], node->get_line());
+ gen(op_lnkeqc, const_string_map[str], node->get_line());
}
break;
case assignment_expr::assign_type::bitwise_and_equal:
@@ -607,26 +612,26 @@ void codegen::multi_assign_gen(multi_assign* node) {
gen(op_meq, 1, tuple[i]->get_line());
}
}
- } else {
- calc_gen(node->get_value());
- auto& tuple = node->get_tuple()->get_elements();
- for(i32 i = 0; iget_value()->get_line());
- // multi assign user loadl and loadg to avoid meq's stack--
- // and this operation changes local and global value directly
- mcall(tuple[i]);
- if (code.back().op==op_mcalll) {
- code.back().op=op_loadl;
- } else if (code.back().op==op_mupval) {
- code.back().op=op_loadu;
- } else if (code.back().op==op_mcallg) {
- code.back().op=op_loadg;
- } else {
- gen(op_meq, 1, tuple[i]->get_line());
- }
- }
- gen(op_pop, 0, node->get_line());
+ return;
}
+ calc_gen(node->get_value());
+ auto& tuple = node->get_tuple()->get_elements();
+ for(i32 i = 0; iget_value()->get_line());
+ // multi assign user loadl and loadg to avoid meq's stack--
+ // and this operation changes local and global value directly
+ mcall(tuple[i]);
+ if (code.back().op==op_mcalll) {
+ code.back().op=op_loadl;
+ } else if (code.back().op==op_mupval) {
+ code.back().op=op_loadu;
+ } else if (code.back().op==op_mcallg) {
+ code.back().op=op_loadg;
+ } else {
+ gen(op_meq, 1, tuple[i]->get_line());
+ }
+ }
+ gen(op_pop, 0, node->get_line());
}
void codegen::cond_gen(condition_expr* node) {
@@ -706,7 +711,7 @@ void codegen::for_gen(for_expr* node) {
usize jmp_place = code.size();
if (node->get_condition()->get_type()==expr_type::ast_null) {
regist_num(1);
- gen(op_pnum, num_table.at(1), node->get_condition()->get_line());
+ gen(op_pnum, const_number_map.at(1), node->get_condition()->get_line());
} else {
calc_gen(node->get_condition());
}
@@ -732,10 +737,11 @@ void codegen::forei_gen(forei_expr* node) {
gen(op_feach, 0, node->get_line());
}
if (node->get_iterator()->get_name()) { // define a new iterator
- const auto& str = node->get_iterator()->get_name()->get_name();
+ auto name_node = node->get_iterator()->get_name();
+ const auto& str = name_node->get_name();
local.empty()?
- gen(op_loadg, global_find(str), node->get_iterator()->get_name()->get_line()):
- gen(op_loadl, local_find(str), node->get_iterator()->get_name()->get_line());
+ gen(op_loadg, global_find(str), name_node->get_line()):
+ gen(op_loadl, local_find(str), name_node->get_line());
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
@@ -760,15 +766,17 @@ void codegen::forei_gen(forei_expr* node) {
void codegen::statement_generation(expr* node) {
switch(node->get_type()) {
- case expr_type::ast_null:break;
+ case expr_type::ast_null: break;
case expr_type::ast_def:
def_gen((definition_expr*)node); break;
case expr_type::ast_multi_assign:
multi_assign_gen((multi_assign*)node); break;
case expr_type::ast_assign:
assignment_statement((assignment_expr*)node); break;
- case expr_type::ast_nil:case expr_type::ast_num:
- case expr_type::ast_str:case expr_type::ast_bool: break;
+ case expr_type::ast_nil:
+ case expr_type::ast_num:
+ case expr_type::ast_str:
+ case expr_type::ast_bool: break;
case expr_type::ast_vec:
case expr_type::ast_hash:
case expr_type::ast_func:
@@ -785,35 +793,35 @@ void codegen::statement_generation(expr* node) {
void codegen::or_gen(binary_operator* node) {
calc_gen(node->get_left());
- usize l1 = code.size();
+ usize label_jump_true_1 = code.size();
gen(op_jt, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_left()->get_line());
calc_gen(node->get_right());
- usize l2=code.size();
+ usize label_jump_true_2 = code.size();
gen(op_jt, 0, node->get_right()->get_line());
gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_line());
- code[l1].num = code[l2].num = code.size();
+ code[label_jump_true_1].num = code[label_jump_true_2].num = code.size();
}
void codegen::and_gen(binary_operator* node) {
calc_gen(node->get_left());
gen(op_jt, code.size()+2, node->get_left()->get_line());
- usize lfalse = code.size();
+ usize lable_jump_false = code.size();
gen(op_jmp, 0, node->get_left()->get_line());
- gen(op_pop, 0, node->get_right()->get_line());// jt jumps here
+ gen(op_pop, 0, node->get_right()->get_line()); // jt jumps here
calc_gen(node->get_right());
gen(op_jt, code.size()+3, node->get_right()->get_line());
- code[lfalse].num = code.size();
+ code[lable_jump_false].num = code.size();
gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_line());
- // jt jumps here
+ // jt jumps here, avoid pop and pnil
}
void codegen::unary_gen(unary_operator* node) {
@@ -881,7 +889,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_addc, num_table.at(num), node->get_line());
+ gen(op_addc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::sub:
@@ -892,7 +900,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_subc, num_table.at(num), node->get_line());
+ gen(op_subc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::mult:
@@ -903,7 +911,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_mulc, num_table.at(num), node->get_line());
+ gen(op_mulc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::div:
@@ -914,7 +922,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_divc, num_table.at(num), node->get_line());
+ gen(op_divc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::concat:
@@ -925,7 +933,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
- gen(op_lnkc, str_table.at(str), node->get_line());
+ gen(op_lnkc, const_string_map.at(str), node->get_line());
}
break;
case binary_operator::binary_type::less:
@@ -936,7 +944,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_lessc, num_table.at(num), node->get_line());
+ gen(op_lessc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::leq:
@@ -947,7 +955,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_leqc, num_table.at(num), node->get_line());
+ gen(op_leqc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::grt:
@@ -958,7 +966,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_grtc, num_table.at(num), node->get_line());
+ gen(op_grtc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::geq:
@@ -969,7 +977,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
- gen(op_geqc, num_table.at(num), node->get_line());
+ gen(op_geqc, const_number_map.at(num), node->get_line());
}
return;
default: break;
@@ -978,14 +986,14 @@ void codegen::binary_gen(binary_operator* node) {
void codegen::trino_gen(ternary_operator* node) {
calc_gen(node->get_condition());
- usize lfalse = code.size();
+ usize label_jump_false = code.size();
gen(op_jf, 0, node->get_condition()->get_line());
calc_gen(node->get_left());
- usize lexit = code.size();
+ usize label_jump_to_exit = code.size();
gen(op_jmp, 0, node->get_left()->get_line());
- code[lfalse].num = code.size();
+ code[label_jump_false].num = code.size();
calc_gen(node->get_right());
- code[lexit].num = code.size();
+ code[label_jump_to_exit].num = code.size();
}
void codegen::calc_gen(expr* node) {
@@ -1028,11 +1036,13 @@ void codegen::calc_gen(expr* node) {
void codegen::block_gen(code_block* node) {
for(auto tmp : node->get_expressions()) {
switch(tmp->get_type()) {
- case expr_type::ast_null:break;
+ case expr_type::ast_null: break;
case expr_type::ast_id:
check_id_exist((identifier*)tmp); break;
- case expr_type::ast_nil:case expr_type::ast_num:
- case expr_type::ast_str:case expr_type::ast_bool:break;
+ case expr_type::ast_nil:
+ case expr_type::ast_num:
+ case expr_type::ast_str:
+ case expr_type::ast_bool: break;
case expr_type::ast_file_info:
// special node type in main block
fileindex = ((file_info*)tmp)->get_index(); break;
@@ -1087,73 +1097,76 @@ const error& codegen::compile(parse& parse, linker& import) {
gen(op_exit, 0, 0);
// size out of bound check
- if (num_res.size()>0xffffff) {
- err.load(file[0]); // load main execute file
+ err.load(file[0]); // load main execute file
+ if (const_number_table.size()>0xffffff) {
err.err("code",
- "too many constant numbers: " + std::to_string(num_res.size()));
+ "too many constant numbers: " +
+ std::to_string(const_number_table.size()));
}
- if (str_res.size()>0xffffff) {
- err.load(file[0]); // load main execute file
+ if (const_string_table.size()>0xffffff) {
err.err("code",
- "too many constant strings: " + std::to_string(str_res.size()));
+ "too many constant strings: " +
+ std::to_string(const_string_table.size()));
}
if (global.size()>=STACK_DEPTH) {
- err.load(file[0]); // load main execute file
err.err("code",
- "too many global variants: " + std::to_string(global.size()));
+ "too many global variables: " + std::to_string(global.size()));
}
if (code.size()>0xffffff) {
- err.load(file[0]); // load main execute file
err.err("code",
"bytecode size overflow: " + std::to_string(code.size()));
}
return err;
}
-void codegen::print() {
+void codegen::print(std::ostream& out) {
// func end stack, reserved for code print
- std::stack fbstk;
- std::stack festk;
+ std::stack func_begin_stack;
+ std::stack func_end_stack;
// print const numbers
- for(auto num : num_res) {
- std::cout << " .number " << num << "\n";
+ for(auto num : const_number_table) {
+ out << " .number " << num << "\n";
}
// print const strings
- for(const auto& str : str_res) {
- std::cout << " .symbol \"" << rawstr(str) << "\"\n";
+ for(const auto& str : const_string_table) {
+ out << " .symbol \"" << rawstr(str) << "\"\n";
+ }
+
+ // print blank line
+ if (const_number_table.size() || const_string_table.size()) {
+ out << "\n";
}
// print code
- std::cout<<"\n";
- codestream::set(num_res.data(), str_res.data());
+ codestream::set(const_number_table.data(), const_string_table.data());
for(u32 i = 0; i;\n";
+ if (!func_end_stack.empty() && i==func_end_stack.top()) {
+ out << std::hex << "<0x" << func_begin_stack.top() << std::dec << ">;\n";
// avoid two empty lines
if (c.op!=op_newf) {
- std::cout<<"\n";
+ out<<"\n";
}
- fbstk.pop();
- festk.pop();
+ func_begin_stack.pop();
+ func_end_stack.pop();
}
// get function begin index and end index
if (c.op==op_newf) {
- std::cout << std::hex << "\nfunc <0x" << i << std::dec << ">:\n";
+ out << std::hex << "\nfunc <0x" << i << std::dec << ">:\n";
for(u32 j = i; j in_iterloop;
- std::unordered_map num_table;
- std::unordered_map str_table;
- std::vector num_res;
- std::vector str_res;
+ std::unordered_map const_number_map;
+ std::unordered_map const_string_map;
+ std::vector const_number_table;
+ std::vector const_string_table;
std::vector code;
std::list> continue_ptr;
std::list> break_ptr;
@@ -49,7 +49,7 @@ private:
void regist_num(const f64);
void regist_str(const std::string&);
void find_symbol(code_block*);
- void add_sym(const std::string&);
+ void add_symbol(const std::string&);
i32 local_find(const std::string&);
i32 global_find(const std::string&);
i32 upvalue_find(const std::string&);
@@ -65,8 +65,8 @@ private:
void call_gen(call_expr*);
void call_id(identifier*);
void call_hash_gen(call_hash*);
- void call_vec(call_vector*);
- void call_func(call_function*);
+ void call_vector_gen(call_vector*);
+ void call_func_gen(call_function*);
void mcall(expr*);
void mcall_id(identifier*);
void mcall_vec(call_vector*);
@@ -93,11 +93,13 @@ private:
void block_gen(code_block*);
void ret_gen(return_expr*);
+public:
+ const std::vector& strs() const {return const_string_table;}
+ const std::vector& nums() const {return const_number_table;}
+ const std::vector& codes() const {return code;}
+
public:
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
const error& compile(parse&, linker&);
- void print();
- const std::vector& strs() const {return str_res;}
- const std::vector& nums() const {return num_res;}
- const std::vector& codes() const {return code;}
+ void print(std::ostream&);
};
diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp
index 1a66794..b1888f5 100644
--- a/src/nasal_gc.cpp
+++ b/src/nasal_gc.cpp
@@ -26,33 +26,33 @@ void dylib_destructor(void* ptr) {
void func_addr_destructor(void* ptr) {}
var nas_vec::get_val(const i32 n) {
- i32 size=elems.size();
+ i32 size = elems.size();
if (n<-size || n>=size) {
return var::none();
}
- return elems[n>=0?n:n+size];
+ return elems[n>=0? n:n+size];
}
var* nas_vec::get_mem(const i32 n) {
- i32 size=elems.size();
+ i32 size = elems.size();
if (n<-size || n>=size) {
return nullptr;
}
- return &elems[n>=0?n:n+size];
+ return &elems[n>=0? n:n+size];
}
std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
if (!vec.elems.size() || vec.printed) {
- out<<(vec.elems.size()?"[..]":"[]");
+ out << (vec.elems.size()? "[..]":"[]");
return out;
}
- vec.printed=true;
- usize iter=0,size=vec.elems.size();
- out<<'[';
+ vec.printed = true;
+ usize iter = 0, size = vec.elems.size();
+ out << "[";
for(auto& i:vec.elems) {
- out<destructor(type)(ptr);
- ptr=nullptr;
+ ptr = nullptr;
}
void nas_co::clear() {
- for(u32 i=0;i"; break;
+ case vm_none: out << "undefined"; break;
+ case vm_nil: out << "nil"; break;
+ case vm_num: out << ref.val.num; break;
+ case vm_str: out << ref.str(); break;
+ case vm_vec: out << ref.vec(); break;
+ case vm_hash: out << ref.hash(); break;
+ case vm_func: out << "func(..) {..}"; break;
+ case vm_obj: out << ref.obj(); break;
+ case vm_co: out << ""; break;
}
return out;
}
@@ -304,7 +305,7 @@ void gc::mark() {
mark_context(bfs);
while(!bfs.empty()) {
- var value=bfs.back();
+ var value = bfs.back();
bfs.pop_back();
if (value.type<=vm_num ||
value.val.gcobj->mark!=gc_status::uncollected) {
@@ -317,7 +318,7 @@ void gc::mark() {
void gc::mark_context(std::vector& bfs_queue) {
// scan now running context, this context maybe related to coroutine or main
- for(var* i=rctx->stack;i<=rctx->top;++i) {
+ for(var* i = rctx->stack; i<=rctx->top; ++i) {
bfs_queue.push_back(*i);
}
bfs_queue.push_back(rctx->funcr);
@@ -329,7 +330,7 @@ void gc::mark_context(std::vector& bfs_queue) {
}
// coroutine is running, so scan main process stack from mctx
- for(var* i=mctx.stack;i<=mctx.top;++i) {
+ for(var* i = mctx.stack; i<=mctx.top; ++i) {
bfs_queue.push_back(*i);
}
bfs_queue.push_back(mctx.funcr);
@@ -337,7 +338,7 @@ void gc::mark_context(std::vector& bfs_queue) {
}
void gc::mark_var(std::vector& bfs_queue, var& value) {
- value.val.gcobj->mark=gc_status::found;
+ value.val.gcobj->mark = gc_status::found;
switch(value.type) {
case vm_vec: mark_vec(bfs_queue, value.vec()); break;
case vm_hash: mark_hash(bfs_queue, value.hash()); break;
@@ -349,28 +350,28 @@ void gc::mark_var(std::vector& bfs_queue, var& value) {
}
void gc::mark_vec(std::vector& bfs_queue, nas_vec& vec) {
- for(auto& i:vec.elems) {
+ for(auto& i : vec.elems) {
bfs_queue.push_back(i);
}
}
void gc::mark_hash(std::vector& bfs_queue, nas_hash& hash) {
- for(auto& i:hash.elems) {
+ for(auto& i : hash.elems) {
bfs_queue.push_back(i.second);
}
}
void gc::mark_func(std::vector& bfs_queue, nas_func& function) {
- for(auto& i:function.local) {
+ for(auto& i : function.local) {
bfs_queue.push_back(i);
}
- for(auto& i:function.upval) {
+ for(auto& i : function.upval) {
bfs_queue.push_back(i);
}
}
void gc::mark_upval(std::vector& bfs_queue, nas_upval& upval) {
- for(auto& i:upval.elems) {
+ for(auto& i : upval.elems) {
bfs_queue.push_back(i);
}
}
@@ -378,84 +379,79 @@ void gc::mark_upval(std::vector& bfs_queue, nas_upval& upval) {
void gc::mark_co(std::vector& bfs_queue, nas_co& co) {
bfs_queue.push_back(co.ctx.funcr);
bfs_queue.push_back(co.ctx.upvalr);
- for(var* i=co.stack;i<=co.ctx.top;++i) {
+ for(var* i = co.stack; i<=co.ctx.top; ++i) {
bfs_queue.push_back(*i);
}
}
void gc::sweep() {
- for(auto i:memory) {
+ for(auto i : memory) {
if (i->mark==gc_status::uncollected) {
i->clear();
unused[i->type-vm_str].push_back(i);
- i->mark=gc_status::collected;
+ i->mark = gc_status::collected;
} else if (i->mark==gc_status::found) {
- i->mark=gc_status::uncollected;
+ i->mark = gc_status::uncollected;
}
}
}
void gc::extend(u8 type) {
- const u8 index=type-vm_str;
- size[index]+=incr[index];
+ const u8 index = type-vm_str;
+ size[index] += incr[index];
- for(u32 i=0;i& s, const std::vector& argv) {
// initialize function register
- rctx->funcr=nil;
- worktime=0;
+ rctx->funcr = nil;
+ worktime = 0;
// initialize counters
- for(u8 i=0;iunmut=1;
- strs[i].str()=s[i];
+ strs[i].val.gcobj->unmut = 1;
+ strs[i].str() = s[i];
}
// record arguments
env_argv.resize(argv.size());
- for(usize i=0;iunmut=1;
- env_argv[i].str()=argv[i];
+ for(usize i = 0; iunmut = 1;
+ env_argv[i].str() = argv[i];
}
}
void gc::clear() {
- for(auto i:memory) {
+ for(auto i : memory) {
delete i;
}
memory.clear();
- for(u8 i=0;imark=gc_status::uncollected;
+ var ret = var::gcobj(unused[index].back());
+ ret.val.gcobj->mark = gc_status::uncollected;
unused[index].pop_back();
return ret;
}
void gc::ctxchg(nas_co& co) {
// store running state to main context
- mctx=*rctx;
+ mctx = *rctx;
// restore coroutine context state
- *rctx=co.ctx;
+ *rctx = co.ctx;
// set coroutine pointer
- cort=&co;
+ cort = &co;
// set coroutine state to running
- cort->status=coroutine_status::running;
+ cort->status = coroutine_status::running;
}
void gc::ctxreserve() {
// pc=0 means this coroutine is finished
- cort->status=rctx->pc?
+ cort->status = rctx->pc?
coroutine_status::suspended:
coroutine_status::dead;
// store running state to coroutine
- cort->ctx=*rctx;
+ cort->ctx = *rctx;
// restore main context state
- *rctx=mctx;
+ *rctx = mctx;
// set coroutine pointer to nullptr
- cort=nullptr;
+ cort = nullptr;
}
var nas_err(const std::string& error_function_name, const std::string& info) {
- std::cerr<<"[vm] "<get_ghost_name(ghost.type);
- out<<" at 0x"<";
+ out << "