diff --git a/doc/namespace.md b/doc/namespace.md new file mode 100644 index 0000000..de183f3 --- /dev/null +++ b/doc/namespace.md @@ -0,0 +1,64 @@ +# Nasal Namespace + +![feigenbaum](./pic/feigenbaum.png) + +## Introduction + +In this nasal interpreter, +we use this way below to construct namespaces: + +- library is linked directly with the script +- module is wraped by a function generated by linker, and return a hash + +## Library + +Library file is linked with script file directly, like this: + +In `std/lib.nas`: + +```nasal +var a = 1; +``` + +In `example.nas`: + +```nasal +var b = 1; +``` + +At the link stage, +in fact we put the ast of two files together to make a new ast, +so the result is equal to: + +```nasal +var a = 1; +var b = 1; +``` + +## Module + +Modules is wraped up by a function, +and return a hash, for example: + +In `std/example_module.nas`: + +```nasal +var a = 1; +``` + +We analysed this file and generated the ast. +Then we find all the global symbols. +At last we use the information of all the globals symbols in this file to generate a hash to return. + +So the result is equal to: + +```nasal +var example_module = func { + # source code begin + var a = 1; + # source code end + return { + a: a + }; +}(); +``` diff --git a/module/libfib.nas b/module/libfib.nas index 7fe2a1c..889cff1 100644 --- a/module/libfib.nas +++ b/module/libfib.nas @@ -1,3 +1,4 @@ + var libfib=func(){ var dl=dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); var fib=dl.fib; diff --git a/src/ast_dumper.cpp b/src/ast_dumper.cpp index a549ded..84f62f2 100644 --- a/src/ast_dumper.cpp +++ b/src/ast_dumper.cpp @@ -2,13 +2,6 @@ #include -bool ast_dumper::visit_file_info(file_info* node) { - dump_indent(); - std::cout << "file \"" << node->get_file_name() << "\""; - std::cout << format_location(node->get_location()); - return true; -} - bool ast_dumper::visit_null_expr(null_expr* node) { dump_indent(); std::cout << "null" << format_location(node->get_location()); diff --git a/src/ast_dumper.h b/src/ast_dumper.h index cb9bcb9..1f520d2 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -39,7 +39,6 @@ private: } public: - bool visit_file_info(file_info*) override; bool visit_null_expr(null_expr*) override; bool visit_nil_expr(nil_expr*) override; bool visit_number_literal(number_literal*) override; diff --git a/src/ast_visitor.cpp b/src/ast_visitor.cpp index 8757e63..d9aa45a 100644 --- a/src/ast_visitor.cpp +++ b/src/ast_visitor.cpp @@ -10,10 +10,6 @@ bool ast_visitor::visit_call(call* node) { return true; } -bool ast_visitor::visit_file_info(file_info* node) { - return true; -} - bool ast_visitor::visit_null_expr(null_expr* node) { return true; } diff --git a/src/ast_visitor.h b/src/ast_visitor.h index 932c912..9586633 100644 --- a/src/ast_visitor.h +++ b/src/ast_visitor.h @@ -6,7 +6,6 @@ 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*); virtual bool visit_number_literal(number_literal*); diff --git a/src/nasal_ast.cpp b/src/nasal_ast.cpp index 03c8f14..5b2610c 100644 --- a/src/nasal_ast.cpp +++ b/src/nasal_ast.cpp @@ -9,10 +9,6 @@ void call::accept(ast_visitor* visitor) { visitor->visit_call(this); } -void file_info::accept(ast_visitor* visitor) { - visitor->visit_file_info(this); -} - void null_expr::accept(ast_visitor* visitor) { visitor->visit_null_expr(this); } diff --git a/src/nasal_ast.h b/src/nasal_ast.h index b7c0ca8..ffffd95 100644 --- a/src/nasal_ast.h +++ b/src/nasal_ast.h @@ -8,7 +8,6 @@ enum class expr_type:u32 { ast_null = 0, // null node - ast_file_info, // stores file info ast_block, // code block ast_nil, // nil keyword ast_num, // number, basic value type @@ -84,21 +83,6 @@ public: virtual void accept(ast_visitor*); }; -class file_info:public expr { -private: - uint16_t index; - std::string filename; - -public: - file_info(const span& location, uint16_t file_index, const std::string& name): - expr(location, expr_type::ast_file_info), - index(file_index), filename(name) {} - ~file_info() = default; - uint16_t get_index() const {return index;} - const std::string& get_file_name() const {return filename;} - void accept(ast_visitor*) override; -}; - class null_expr:public expr { public: null_expr(const span& location): diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index bd38dc7..7940890 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -100,42 +100,44 @@ i32 codegen::upvalue_find(const std::string& name) { return index; } -void codegen::gen(u8 operation_code, u32 num, u32 line) { - code.push_back({operation_code, fileindex, num, line}); +void codegen::gen(u8 operation_code, u32 num, const span& loc) { + code.push_back({operation_code, + static_cast(file_map.at(loc.file)), + num, loc.begin_line}); } void codegen::num_gen(number_literal* node) { f64 num = node->get_number(); regist_num(num); - gen(op_pnum,const_number_map.at(num), node->get_line()); + gen(op_pnum, const_number_map.at(num), node->get_location()); } void codegen::str_gen(string_literal* node) { const auto& str = node->get_content(); regist_str(str); - gen(op_pstr, const_string_map.at(str), node->get_line()); + gen(op_pstr, const_string_map.at(str), node->get_location()); } void codegen::bool_gen(bool_literal* node) { f64 num = node->get_flag()? 1:0; regist_num(num); - gen(op_pnum, const_number_map.at(num), node->get_line()); + gen(op_pnum, const_number_map.at(num), node->get_location()); } void codegen::vec_gen(vector_expr* node) { for(auto child : node->get_elements()) { calc_gen(child); } - gen(op_newv, node->get_elements().size(), node->get_line()); + gen(op_newv, node->get_elements().size(), node->get_location()); } void codegen::hash_gen(hash_expr* node) { - gen(op_newh, 0, node->get_line()); + gen(op_newh, 0, node->get_location()); for(auto child : node->get_members()) { calc_gen(child->get_value()); const auto& field_name = child->get_name(); regist_str(field_name); - gen(op_happ, const_string_map.at(field_name), child->get_line()); + gen(op_happ, const_string_map.at(field_name), child->get_location()); } } @@ -175,9 +177,9 @@ void codegen::func_gen(function* node) { } usize newf=code.size(); - gen(op_newf, 0, node->get_line()); + gen(op_newf, 0, node->get_location()); usize lsize=code.size(); - gen(op_intl, 0, node->get_line()); + gen(op_intl, 0, node->get_location()); // add special keyword 'me' into symbol table // this symbol is only used in local scope(function's scope) @@ -196,14 +198,14 @@ void codegen::func_gen(function* node) { regist_str(name); switch(tmp->get_parameter_type()) { case parameter::param_type::normal_parameter: - gen(op_para, const_string_map.at(name), tmp->get_line()); + gen(op_para, const_string_map.at(name), tmp->get_location()); break; case parameter::param_type::default_parameter: calc_gen(tmp->get_default_value()); - gen(op_deft, const_string_map.at(name), tmp->get_line()); + gen(op_deft, const_string_map.at(name), tmp->get_location()); break; case parameter::param_type::dynamic_parameter: - gen(op_dyn, const_string_map.at(name), tmp->get_line()); + gen(op_dyn, const_string_map.at(name), tmp->get_location()); break; } add_symbol(name); @@ -211,7 +213,7 @@ void codegen::func_gen(function* node) { code[newf].num = code.size()+1; // entry usize jmp_ptr = code.size(); - gen(op_jmp, 0, node->get_line()); + gen(op_jmp, 0, node->get_location()); auto block = node->get_code_block(); // search symbols first, must use after loading parameters @@ -244,8 +246,8 @@ void codegen::func_gen(function* node) { if (!block->get_expressions().size() || block->get_expressions().back()->get_type()!=expr_type::ast_ret) { - gen(op_pnil, 0, block->get_line()); - gen(op_ret, 0, block->get_line()); + gen(op_pnil, 0, block->get_location()); + gen(op_ret, 0, block->get_location()); } code[jmp_ptr].num = code.size(); } @@ -269,7 +271,7 @@ void codegen::call_id(identifier* node) { const auto& name = node->get_name(); for(u32 i = 0; builtin[i].name; ++i) { if (builtin[i].name==name) { - gen(op_callb, i, node->get_line()); + gen(op_callb, i, node->get_location()); if (local.empty()) { die("should warp native function in local scope", node->get_location()); @@ -279,15 +281,15 @@ void codegen::call_id(identifier* node) { } i32 index; if ((index=local_find(name))>=0) { - gen(op_calll, index, node->get_line()); + gen(op_calll, index, node->get_location()); return; } if ((index=upvalue_find(name))>=0) { - gen(op_upval, index, node->get_line()); + gen(op_upval, index, node->get_location()); return; } if ((index=global_find(name))>=0) { - gen(op_callg, index, node->get_line()); + gen(op_callg, index, node->get_location()); return; } die("undefined symbol \"" + name + "\"", node->get_location()); @@ -295,7 +297,7 @@ void codegen::call_id(identifier* node) { void codegen::call_hash_gen(call_hash* node) { regist_str(node->get_field()); - gen(op_callh, const_string_map.at(node->get_field()), node->get_line()); + gen(op_callh, const_string_map.at(node->get_field()), node->get_location()); } void codegen::call_vector_gen(call_vector* node) { @@ -303,39 +305,39 @@ void codegen::call_vector_gen(call_vector* node) { if (node->get_slices().size()==1 && !node->get_slices()[0]->get_end()) { calc_gen(node->get_slices()[0]->get_begin()); - gen(op_callv, 0, node->get_slices()[0]->get_line()); + gen(op_callv, 0, node->get_slices()[0]->get_location()); return; } - gen(op_slcbeg, 0, node->get_line()); + gen(op_slcbeg, 0, node->get_location()); for(auto tmp : node->get_slices()) { if (!tmp->get_end()) { calc_gen(tmp->get_begin()); - gen(op_slc, 0, tmp->get_line()); + gen(op_slc, 0, tmp->get_location()); } else { calc_gen(tmp->get_begin()); calc_gen(tmp->get_end()); - gen(op_slc2, 0, tmp->get_line()); + gen(op_slc2, 0, tmp->get_location()); } } - gen(op_slcend, 0, node->get_line()); + gen(op_slcend, 0, node->get_location()); } 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()); + gen(op_newh, 0, node->get_location()); for(auto child : node->get_argument()) { calc_gen(((hash_pair*)child)->get_value()); const auto& field_name = ((hash_pair*)child)->get_name(); regist_str(field_name); - gen(op_happ, const_string_map.at(field_name), child->get_line()); + gen(op_happ, const_string_map.at(field_name), child->get_location()); } - gen(op_callfh, 0, node->get_line()); + gen(op_callfh, 0, node->get_location()); } else { for(auto child : node->get_argument()) { calc_gen(child); } - gen(op_callfv, node->get_argument().size(), node->get_line()); + gen(op_callfv, node->get_argument().size(), node->get_location()); } } @@ -390,15 +392,15 @@ void codegen::mcall_id(identifier* node) { } i32 index; if ((index=local_find(name))>=0) { - gen(op_mcalll, index, node->get_line()); + gen(op_mcalll, index, node->get_location()); return; } if ((index=upvalue_find(name))>=0) { - gen(op_mupval, index, node->get_line()); + gen(op_mupval, index, node->get_location()); return; } if ((index=global_find(name))>=0) { - gen(op_mcallg, index, node->get_line()); + gen(op_mcallg, index, node->get_location()); return; } die("undefined symbol \"" + name + "\"", node->get_location()); @@ -415,20 +417,20 @@ void codegen::mcall_vec(call_vector* node) { return; } calc_gen(call->get_begin()); - gen(op_mcallv, 0, node->get_line()); + gen(op_mcallv, 0, node->get_location()); } void codegen::mcall_hash(call_hash* node) { regist_str(node->get_field()); - gen(op_mcallh, const_string_map.at(node->get_field()), node->get_line()); + gen(op_mcallh, const_string_map.at(node->get_field()), node->get_location()); } void codegen::single_def(definition_expr* node) { const auto& str = node->get_variable_name()->get_name(); calc_gen(node->get_value()); local.empty()? - gen(op_loadg, global_find(str), node->get_line()): - gen(op_loadl, local_find(str), node->get_line()); + gen(op_loadg, global_find(str), node->get_location()): + gen(op_loadl, local_find(str), node->get_location()); } void codegen::multi_def(definition_expr* node) { @@ -448,21 +450,21 @@ void codegen::multi_def(definition_expr* node) { calc_gen(vals[i]); 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_loadg, global_find(name), identifiers[i]->get_location()): + gen(op_loadl, local_find(name), identifiers[i]->get_location()); } return; } // (var a,b,c) = [0,1,2]; calc_gen(node->get_value()); for(usize i = 0; iget_value()->get_line()); + gen(op_callvi, i, node->get_value()->get_location()); 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_loadg, global_find(name), identifiers[i]->get_location()): + gen(op_loadl, local_find(name), identifiers[i]->get_location()); } - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); } void codegen::def_gen(definition_expr* node) { @@ -477,7 +479,7 @@ void codegen::assignment_expression(assignment_expr* node) { case assignment_expr::assign_type::equal: calc_gen(node->get_right()); mcall(node->get_left()); - gen(op_meq, 0, node->get_line()); + gen(op_meq, 0, node->get_location()); break; case assignment_expr::assign_type::add_equal: if (node->get_right()->get_type()!=expr_type::ast_num) { @@ -485,11 +487,11 @@ void codegen::assignment_expression(assignment_expr* node) { } mcall(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { - gen(op_addeq, 0, node->get_line()); + gen(op_addeq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_addeqc, const_number_map[num], node->get_line()); + gen(op_addeqc, const_number_map[num], node->get_location()); } break; case assignment_expr::assign_type::sub_equal: @@ -498,11 +500,11 @@ void codegen::assignment_expression(assignment_expr* node) { } mcall(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { - gen(op_subeq, 0, node->get_line()); + gen(op_subeq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_subeqc, const_number_map[num], node->get_line()); + gen(op_subeqc, const_number_map[num], node->get_location()); } break; case assignment_expr::assign_type::mult_equal: @@ -511,11 +513,11 @@ void codegen::assignment_expression(assignment_expr* node) { } mcall(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { - gen(op_muleq, 0, node->get_line()); + gen(op_muleq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_muleqc, const_number_map[num], node->get_line()); + gen(op_muleqc, const_number_map[num], node->get_location()); } break; case assignment_expr::assign_type::div_equal: @@ -524,11 +526,11 @@ void codegen::assignment_expression(assignment_expr* node) { } mcall(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { - gen(op_diveq, 0, node->get_line()); + gen(op_diveq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_diveqc, const_number_map[num], node->get_line()); + gen(op_diveqc, const_number_map[num], node->get_location()); } break; case assignment_expr::assign_type::concat_equal: @@ -537,27 +539,27 @@ void codegen::assignment_expression(assignment_expr* node) { } mcall(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_str) { - gen(op_lnkeq, 0, node->get_line()); + gen(op_lnkeq, 0, node->get_location()); } else { const auto& str = ((string_literal*)node->get_right())->get_content(); regist_str(str); - gen(op_lnkeqc, const_string_map[str], node->get_line()); + gen(op_lnkeqc, const_string_map[str], node->get_location()); } break; case assignment_expr::assign_type::bitwise_and_equal: calc_gen(node->get_right()); mcall(node->get_left()); - gen(op_btandeq, 0, node->get_line()); + gen(op_btandeq, 0, node->get_location()); break; case assignment_expr::assign_type::bitwise_or_equal: calc_gen(node->get_right()); mcall(node->get_left()); - gen(op_btoreq, 0, node->get_line()); + gen(op_btoreq, 0, node->get_location()); break; case assignment_expr::assign_type::bitwise_xor_equal: calc_gen(node->get_right()); mcall(node->get_left()); - gen(op_btxoreq, 0, node->get_line()); + gen(op_btxoreq, 0, node->get_location()); break; } } @@ -581,7 +583,7 @@ void codegen::assignment_statement(assignment_expr* node) { if (code.back().op==op_meq) { code.back().num=1; } else { - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); } } break; @@ -599,7 +601,7 @@ void codegen::assignment_statement(assignment_expr* node) { } else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) { code.back().op=code.back().op-op_addeqc+op_addecp; } else { - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); } break; } @@ -630,7 +632,7 @@ void codegen::multi_assign_gen(multi_assign* node) { } else if (code.back().op==op_mcallg) { code.back().op=op_loadg; } else { - gen(op_meq, 1, tuple[i]->get_line()); + gen(op_meq, 1, tuple[i]->get_location()); } } return; @@ -638,7 +640,7 @@ void codegen::multi_assign_gen(multi_assign* node) { calc_gen(node->get_value()); auto& tuple = node->get_tuple()->get_elements(); for(i32 i = 0; iget_value()->get_line()); + gen(op_callvi, i, node->get_value()->get_location()); // multi assign user loadl and loadg to avoid meq's stack-- // and this operation changes local and global value directly mcall(tuple[i]); @@ -649,35 +651,35 @@ void codegen::multi_assign_gen(multi_assign* node) { } else if (code.back().op==op_mcallg) { code.back().op=op_loadg; } else { - gen(op_meq, 1, tuple[i]->get_line()); + gen(op_meq, 1, tuple[i]->get_location()); } } - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); } void codegen::cond_gen(condition_expr* node) { std::vector jmp_label; calc_gen(node->get_if_statement()->get_condition()); auto ptr = code.size(); - gen(op_jf, 0, node->get_if_statement()->get_line()); + gen(op_jf, 0, node->get_if_statement()->get_location()); block_gen(node->get_if_statement()->get_code_block()); if (node->get_elsif_stataments().size() || node->get_else_statement()) { jmp_label.push_back(code.size()); - gen(op_jmp, 0, node->get_if_statement()->get_line()); + gen(op_jmp, 0, node->get_if_statement()->get_location()); } code[ptr].num = code.size(); for(auto tmp : node->get_elsif_stataments()) { calc_gen(tmp->get_condition()); ptr = code.size(); - gen(op_jf, 0, tmp->get_line()); + gen(op_jf, 0, tmp->get_location()); block_gen(tmp->get_code_block()); // the last condition doesn't need to jmp if (tmp!=node->get_elsif_stataments().back() || node->get_else_statement()) { jmp_label.push_back(code.size()); - gen(op_jmp, 0, tmp->get_line()); + gen(op_jmp, 0, tmp->get_location()); } code[ptr].num=code.size(); } @@ -719,10 +721,10 @@ void codegen::while_gen(while_expr* node) { usize loop_ptr = code.size(); calc_gen(node->get_condition()); usize condition_ptr = code.size(); - gen(op_jf, 0, node->get_condition()->get_line()); + gen(op_jf, 0, node->get_condition()->get_location()); block_gen(node->get_code_block()); - gen(op_jmp, loop_ptr, node->get_code_block()->get_line()); + gen(op_jmp, loop_ptr, node->get_code_block()->get_location()); code[condition_ptr].num = code.size(); load_continue_break(code.size()-1, code.size()); } @@ -732,17 +734,17 @@ 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, const_number_map.at(1), node->get_condition()->get_line()); + gen(op_pnum, const_number_map.at(1), node->get_condition()->get_location()); } else { calc_gen(node->get_condition()); } usize label_exit = code.size(); - gen(op_jf, 0, node->get_condition()->get_line()); + gen(op_jf, 0, node->get_condition()->get_location()); block_gen(node->get_code_block()); usize continue_place = code.size(); statement_generation(node->get_step()); - gen(op_jmp, jmp_place, node->get_step()->get_line()); + gen(op_jmp, jmp_place, node->get_step()->get_location()); code[label_exit].num = code.size(); load_continue_break(continue_place, code.size()); @@ -750,19 +752,19 @@ void codegen::for_gen(for_expr* node) { void codegen::forei_gen(forei_expr* node) { calc_gen(node->get_value()); - gen(op_cnt, 0, node->get_value()->get_line()); + gen(op_cnt, 0, node->get_value()->get_location()); usize ptr = code.size(); if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) { - gen(op_findex, 0, node->get_line()); + gen(op_findex, 0, node->get_location()); } else { - gen(op_feach, 0, node->get_line()); + gen(op_feach, 0, node->get_location()); } if (node->get_iterator()->get_name()) { // define a new iterator auto name_node = node->get_iterator()->get_name(); const auto& str = name_node->get_name(); local.empty()? - gen(op_loadg, global_find(str), name_node->get_line()): - gen(op_loadl, local_find(str), name_node->get_line()); + gen(op_loadg, global_find(str), name_node->get_location()): + gen(op_loadl, local_find(str), name_node->get_location()); } else { // use exist variable as the iterator mcall(node->get_iterator()->get_call()); if (code.back().op==op_mcallg) { @@ -772,17 +774,17 @@ void codegen::forei_gen(forei_expr* node) { } else if (code.back().op==op_mupval) { code.back().op=op_loadu; } else { - gen(op_meq, 1, node->get_iterator()->get_line()); + gen(op_meq, 1, node->get_iterator()->get_location()); } } ++in_loop_level.back(); block_gen(node->get_code_block()); --in_loop_level.back(); - gen(op_jmp, ptr, node->get_line()); + gen(op_jmp, ptr, node->get_location()); code[ptr].num=code.size(); load_continue_break(code.size()-1, code.size()); - gen(op_pop, 0, node->get_value()->get_line());// pop vector - gen(op_pop, 0, node->get_line());// pop iterator + gen(op_pop, 0, node->get_value()->get_location());// pop vector + gen(op_pop, 0, node->get_location());// pop iterator } void codegen::statement_generation(expr* node) { @@ -806,7 +808,7 @@ void codegen::statement_generation(expr* node) { case expr_type::ast_binary: case expr_type::ast_ternary: calc_gen(node); - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); break; default: break; } @@ -815,33 +817,33 @@ void codegen::statement_generation(expr* node) { void codegen::or_gen(binary_operator* node) { calc_gen(node->get_left()); usize label_jump_true_1 = code.size(); - gen(op_jt, 0, node->get_left()->get_line()); + gen(op_jt, 0, node->get_left()->get_location()); - gen(op_pop, 0, node->get_left()->get_line()); + gen(op_pop, 0, node->get_left()->get_location()); calc_gen(node->get_right()); usize label_jump_true_2 = code.size(); - gen(op_jt, 0, node->get_right()->get_line()); + gen(op_jt, 0, node->get_right()->get_location()); - gen(op_pop, 0, node->get_right()->get_line()); - gen(op_pnil, 0, node->get_right()->get_line()); + gen(op_pop, 0, node->get_right()->get_location()); + gen(op_pnil, 0, node->get_right()->get_location()); 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()); + gen(op_jt, code.size()+2, node->get_left()->get_location()); 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_jmp, 0, node->get_left()->get_location()); + gen(op_pop, 0, node->get_right()->get_location()); // jt jumps here calc_gen(node->get_right()); - gen(op_jt, code.size()+3, node->get_right()->get_line()); + gen(op_jt, code.size()+3, node->get_right()->get_location()); 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()); + gen(op_pop, 0, node->get_right()->get_location()); + gen(op_pnil, 0, node->get_right()->get_location()); // jt jumps here, avoid pop and pnil } @@ -849,11 +851,11 @@ void codegen::unary_gen(unary_operator* node) { calc_gen(node->get_value()); switch(node->get_operator_type()) { case unary_operator::unary_type::negative: - gen(op_usub, 0, node->get_line()); break; + gen(op_usub, 0, node->get_location()); break; case unary_operator::unary_type::logical_not: - gen(op_lnot, 0, node->get_line()); break; + gen(op_lnot, 0, node->get_location()); break; case unary_operator::unary_type::bitwise_not: - gen(op_bnot, 0, node->get_line()); break; + gen(op_bnot, 0, node->get_location()); break; } } @@ -877,27 +879,27 @@ void codegen::binary_gen(binary_operator* node) { case binary_operator::binary_type::cmpeq: calc_gen(node->get_left()); calc_gen(node->get_right()); - gen(op_eq, 0, node->get_line()); + gen(op_eq, 0, node->get_location()); return; case binary_operator::binary_type::cmpneq: calc_gen(node->get_left()); calc_gen(node->get_right()); - gen(op_neq, 0, node->get_line()); + gen(op_neq, 0, node->get_location()); return; case binary_operator::binary_type::bitwise_or: calc_gen(node->get_left()); calc_gen(node->get_right()); - gen(op_btor, 0, node->get_line()); + gen(op_btor, 0, node->get_location()); return; case binary_operator::binary_type::bitwise_xor: calc_gen(node->get_left()); calc_gen(node->get_right()); - gen(op_btxor, 0, node->get_line()); + gen(op_btxor, 0, node->get_location()); return; case binary_operator::binary_type::bitwise_and: calc_gen(node->get_left()); calc_gen(node->get_right()); - gen(op_btand, 0, node->get_line()); + gen(op_btand, 0, node->get_location()); return; default: break; } @@ -906,99 +908,99 @@ void codegen::binary_gen(binary_operator* node) { calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_add, 0, node->get_line()); + gen(op_add, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_addc, const_number_map.at(num), node->get_line()); + gen(op_addc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::sub: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_sub, 0, node->get_line()); + gen(op_sub, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_subc, const_number_map.at(num), node->get_line()); + gen(op_subc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::mult: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_mul, 0, node->get_line()); + gen(op_mul, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_mulc, const_number_map.at(num), node->get_line()); + gen(op_mulc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::div: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_div, 0, node->get_line()); + gen(op_div, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_divc, const_number_map.at(num), node->get_line()); + gen(op_divc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::concat: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_str) { calc_gen(node->get_right()); - gen(op_lnk, 0, node->get_line()); + gen(op_lnk, 0, node->get_location()); } else { const auto& str = ((string_literal*)node->get_right())->get_content(); regist_str(str); - gen(op_lnkc, const_string_map.at(str), node->get_line()); + gen(op_lnkc, const_string_map.at(str), node->get_location()); } break; case binary_operator::binary_type::less: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_less, 0, node->get_line()); + gen(op_less, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_lessc, const_number_map.at(num), node->get_line()); + gen(op_lessc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::leq: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_leq, 0, node->get_line()); + gen(op_leq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_leqc, const_number_map.at(num), node->get_line()); + gen(op_leqc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::grt: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_grt, 0, node->get_line()); + gen(op_grt, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_grtc, const_number_map.at(num), node->get_line()); + gen(op_grtc, const_number_map.at(num), node->get_location()); } return; case binary_operator::binary_type::geq: calc_gen(node->get_left()); if (node->get_right()->get_type()!=expr_type::ast_num) { calc_gen(node->get_right()); - gen(op_geq, 0, node->get_line()); + gen(op_geq, 0, node->get_location()); } else { auto num = ((number_literal*)node->get_right())->get_number(); regist_num(num); - gen(op_geqc, const_number_map.at(num), node->get_line()); + gen(op_geqc, const_number_map.at(num), node->get_location()); } return; default: break; @@ -1008,10 +1010,10 @@ void codegen::binary_gen(binary_operator* node) { void codegen::trino_gen(ternary_operator* node) { calc_gen(node->get_condition()); usize label_jump_false = code.size(); - gen(op_jf, 0, node->get_condition()->get_line()); + gen(op_jf, 0, node->get_condition()->get_location()); calc_gen(node->get_left()); usize label_jump_to_exit = code.size(); - gen(op_jmp, 0, node->get_left()->get_line()); + gen(op_jmp, 0, node->get_left()->get_location()); code[label_jump_false].num = code.size(); calc_gen(node->get_right()); code[label_jump_to_exit].num = code.size(); @@ -1020,7 +1022,7 @@ void codegen::trino_gen(ternary_operator* node) { void codegen::calc_gen(expr* node) { switch(node->get_type()) { case expr_type::ast_nil: - gen(op_pnil, 0, node->get_line()); break; + gen(op_pnil, 0, node->get_location()); break; case expr_type::ast_num: num_gen((number_literal*)node); break; case expr_type::ast_str: @@ -1064,18 +1066,15 @@ void codegen::block_gen(code_block* node) { 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; case expr_type::ast_cond: cond_gen((condition_expr*)tmp); break; case expr_type::ast_continue: continue_ptr.front().push_back(code.size()); - gen(op_jmp, 0, tmp->get_line()); + gen(op_jmp, 0, tmp->get_location()); break; case expr_type::ast_break: break_ptr.front().push_back(code.size()); - gen(op_jmp, 0, tmp->get_line()); + gen(op_jmp, 0, tmp->get_location()); break; case expr_type::ast_while: case expr_type::ast_for: @@ -1101,16 +1100,20 @@ void codegen::block_gen(code_block* node) { void codegen::ret_gen(return_expr* node) { for(u32 i = 0; iget_line()); - gen(op_pop, 0, node->get_line()); + gen(op_pop, 0, node->get_location()); + gen(op_pop, 0, node->get_location()); } calc_gen(node->get_value()); - gen(op_ret, 0, node->get_line()); + gen(op_ret, 0, node->get_location()); } const error& codegen::compile(parse& parse, linker& import) { - fileindex = 0; - file = import.filelist(); + const auto& file = import.filelist(); + file_map = {}; + for(usize i = 0; iget_location()); block_gen(parse.tree()); // generate main block - gen(op_exit, 0, 0); + gen(op_exit, 0, parse.tree()->get_location()); // size out of bound check if (const_number_table.size()>0xffffff) { diff --git a/src/nasal_codegen.h b/src/nasal_codegen.h index 884bd64..dc8a683 100644 --- a/src/nasal_codegen.h +++ b/src/nasal_codegen.h @@ -22,15 +22,24 @@ class codegen { private: - u16 fileindex; error err; - std::vector file; + + // file mapper for file -> index + std::unordered_map file_map; + + // used for generate pop in return expression std::vector in_loop_level; + + // constant numbers and strings std::unordered_map const_number_map; std::unordered_map const_string_map; std::vector const_number_table; std::vector const_string_table; + + // generated opcodes std::vector code; + + // used to store jmp operands index, to fill the jump address back std::list> continue_ptr; std::list> break_ptr; @@ -38,6 +47,7 @@ private: // global : max STACK_DEPTH-1 values std::unordered_map global; std::unordered_map> experimental_namespace; + // local : max 32768 upvalues 65536 values // but in fact local scope also has less than STACK_DEPTH value std::list> local; @@ -56,7 +66,7 @@ private: i32 global_find(const std::string&); i32 upvalue_find(const std::string&); - void gen(u8, u32, u32); + void gen(u8, u32, const span&); void num_gen(number_literal*); void str_gen(string_literal*); @@ -105,7 +115,7 @@ public: } public: - codegen(): fileindex(0) {} + codegen() = default; const error& compile(parse&, linker&); void print(std::ostream&); void symbol_dump(std::ostream&) const; diff --git a/src/nasal_import.cpp b/src/nasal_import.cpp index d79ac30..af2e7f0 100644 --- a/src/nasal_import.cpp +++ b/src/nasal_import.cpp @@ -313,12 +313,15 @@ definition_expr* linker::generate_module_definition(code_block* block) { code_block* linker::load(code_block* root, u16 fileindex) { auto tree = new code_block({0, 0, 0, 0, files[fileindex]}); + // load library, this ast will be linked with root directly + // so no namespace is generated if (!lib_loaded) { auto tmp = import_nasal_lib(); link(tree, tmp); delete tmp; lib_loaded = true; } + // load imported modules for(auto i : root->get_expressions()) { if (!import_check(i)) { break; @@ -327,9 +330,6 @@ code_block* linker::load(code_block* root, u16 fileindex) { tree->add_expression(generate_module_definition(tmp)); } // add root to the back of tree - auto file_head = new file_info( - {0, 0, 0, 0, files[fileindex]}, fileindex, files[fileindex]); - tree->add_expression(file_head); link(tree, root); return tree; } diff --git a/std/fg_env.nas b/std/fg_env.nas index c8168d0..47d435d 100644 --- a/std/fg_env.nas +++ b/std/fg_env.nas @@ -1,5 +1,6 @@ # flightgear developer environments simulator (beta) # ValKmjolnir 2022 +import.std.runtime; println("-------------------------------------------------------------"); println(" FlightGear simulated-env for developers project, since 2019"); diff --git a/std/io.nas b/std/io.nas new file mode 100644 index 0000000..cfca4ad --- /dev/null +++ b/std/io.nas @@ -0,0 +1,68 @@ +# io.nas +# 2023 by ValKmjolnir + +var SEEK_SET = 0; +var SEEK_CUR = 1; +var SEEK_END = 2; + +# get content of a file by filename. returns a string. +var readfile = func(filename) { + return __readfile(filename); +} + +# input a string as the content of a file. +var fout = func(filename, str) { + return __fout(filename, str); +} + +# use C access +var exists = func(filename) { + return __exists(filename); +} + +# same as C fopen. open file and get the FILE*. +var open = func(filename, mode = "r") { + return __open(filename, mode); +} + +# same as C fclose. close file by FILE*. +var close = func(filehandle) { + return __close(filehandle); +} + +# same as C fread. read file by FILE*. +# caution: buf must be a mutable string.use mut("") to get an empty mutable string. +var read = func(filehandle, buf, len) { + return __read(filehandle, buf, len); +} + +# same as C fwrite. write file by FILE*. +var write = func(filehandle, str) { + return __write(filehandle, str); +} + +# same as C fseek. seek place by FILE*. +var seek = func(filehandle, pos, whence) { + return __seek(filehandle, pos, whence); +} + +# same as C ftell. +var tell = func(filehandle) { + return __tell(filehandle); +} + +# read file by lines. use FILE*. +# get nil if EOF +var readln = func(filehandle) { + return __readln(filehandle); +} + +# same as C stat. +var stat = func(filename) { + return __stat(filename); +} + +# same as C feof. check if FILE* gets the end of file(EOF). +var eof = func(filehandle) { + return __eof(filehandle); +} diff --git a/std/lib.nas b/std/lib.nas index 6e513fc..c90bd77 100644 --- a/std/lib.nas +++ b/std/lib.nas @@ -2,6 +2,10 @@ # 2019 ValKmjolnir import.std.coroutine; +import.std.math; +import.std.string; +import.std.io; +import.std.os; # print is used to print all things in nasal, try and see how it works. # this function uses std::cout to output logs. @@ -327,38 +331,6 @@ var md5 = func(str) { return __md5(str); } -var io = { - SEEK_SET: 0, - SEEK_CUR: 1, - SEEK_END: 2, - # get content of a file by filename. returns a string. - readfile: func(filename) {return __readfile(filename);}, - # input a string as the content of a file. - fout: func(filename, str) {return __fout(filename, str);}, - # use C access - exists:func(filename) {return __exists(filename);}, - # same as C fopen. open file and get the FILE*. - open: func(filename, mode = "r") {return __open(filename, mode);}, - # same as C fclose. close file by FILE*. - close: func(filehandle) {return __close(filehandle);}, - # same as C fread. read file by FILE*. - # caution: buf must be a mutable string.use mut("") to get an empty mutable string. - read: func(filehandle, buf, len) {return __read(filehandle, buf, len);}, - # same as C fwrite. write file by FILE*. - write: func(filehandle, str) {return __write(filehandle, str);}, - # same as C fseek. seek place by FILE*. - seek: func(filehandle, pos, whence) {return __seek(filehandle, pos, whence);}, - # same as C ftell. - tell: func(filehandle) {return __tell(filehandle);}, - # read file by lines. use FILE*. - # get nil if EOF - readln: func(filehandle) {return __readln(filehandle);}, - # same as C stat. - stat: func(filename) {return __stat(filename);}, - # same as C feof. check if FILE* gets the end of file(EOF). - eof: func(filehandle) {return __eof(filehandle);} -}; - # get file status. using data from io.stat var fstat = func(filename) { var s = io.stat(filename); @@ -412,28 +384,6 @@ var bits = { buf: func(len) {return __buf;} }; -# mostly used math functions and special constants, you know. -var math = { - e: 2.7182818284590452354, - pi: 3.14159265358979323846264338327950288, - inf: 1/0, - nan: 0/0, - abs: func(x) {return x>0? x:-x;}, - floor: func(x) {return __floor(x);}, - pow: func(x, y) {return __pow(x, y);}, - sin: func(x) {return __sin(x);}, - cos: func(x) {return __cos(x);}, - tan: func(x) {return __tan(x);}, - exp: func(x) {return __exp(x);}, - lg: func(x) {return __lg(x);}, - ln: func(x) {return __ln(x);}, - sqrt: func(x) {return __sqrt(x);}, - atan2: func(x, y) {return __atan2(x, y);}, - isnan: func(x) {return __isnan(x);}, - max: func(x, y) {return x>y? x:y;}, - min: func(x, y) {return x0? x:-x; +} + +var floor = func(x) { + return __floor(x); +} + +var pow = func(x, y) { + return __pow(x, y); +} + +var sin = func(x) { + return __sin(x); +} + +var cos = func(x) { + return __cos(x); +} + +var tan = func(x) { + return __tan(x); +} + +var exp = func(x) { + return __exp(x); +} + +var lg = func(x) { + return __lg(x); +} + +var ln = func(x) { + return __ln(x); +} + +var sqrt = func(x) { + return __sqrt(x); +} + +var atan2 = func(x, y) { + return __atan2(x, y); +} + +var isnan = func(x) { + return __isnan(x); +} + +var max = func(x, y) { + return x>y? x:y; +} + +var min = func(x, y) { + return x