From cf2323623b3f55f26ed42b0c0be5b944b916717e Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 3 Aug 2024 14:18:29 +0800 Subject: [PATCH 1/4] :art: fix typo in report info --- CMakeLists.txt | 2 ++ doc/tutorial.md | 4 +-- src/nasal_codegen.cpp | 79 ++++++++++++++++++------------------------- src/nasal_codegen.h | 4 +-- src/symbol_finder.cpp | 9 ++--- src/symbol_finder.h | 2 +- 6 files changed, 42 insertions(+), 58 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5d36d7..6941632 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,12 +56,14 @@ target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src) # build nasal add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp) target_link_libraries(nasal nasal-object) + # link ldl and lpthread if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") target_link_libraries(nasal dl) target_link_libraries(nasal pthread) endif() target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src) + # copy nasal from build dir to the outside dir if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") add_custom_command( diff --git a/doc/tutorial.md b/doc/tutorial.md index 1b4cad7..1dbd2ab 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -517,7 +517,7 @@ nasal_builtin_table builtin[] = { }; ``` -At last,warp the `__print` in a nasal file: +At last, wrap the `__print` up in a nasal file: ```javascript var print = func(elems...) { @@ -534,7 +534,7 @@ var print = func(elems...) { }; ``` -If you don't warp built-in function in a normal nasal function, +If you don't wrap built-in function up in a normal nasal function, this native function may cause __segmentation fault__ when searching arguments. Use `import("filename.nas")` to get the nasal file including your built-in functions, then you could use it. diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index 523be41..0a513de 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -49,9 +49,7 @@ void codegen::check_id_exist(identifier* node) { const auto& name = node->get_name(); if (native_function_mapper.count(name)) { if (local.empty()) { - die("native function should not be used in global scope", - node->get_location() - ); + die("native function should not be used in global scope", node); } return; } @@ -65,9 +63,9 @@ void codegen::check_id_exist(identifier* node) { if (global_symbol_find(name)>=0) { return; } - die("undefined symbol \"" + name + - "\", and this symbol is useless here", - node->get_location() + die("undefined symbol \"" + + name + "\", and this symbol is useless here", + node ); } @@ -94,17 +92,18 @@ void codegen::regist_string(const std::string& str) { void codegen::find_symbol(code_block* node) { auto finder = std::make_unique(); for(const auto& i : finder->do_find(node)) { + const auto& file = i.pos_node->get_location().file; // check if symbol conflicts with native function name if (native_function_mapper.count(i.name)) { - die("symbol conflicts with native function", i.location); + die("symbol conflicts with native function", i.pos_node); continue; } // create new namespace with checking existence of location file - if (!nasal_namespace.count(i.location.file)) { - nasal_namespace[i.location.file] = {}; + if (!nasal_namespace.count(file)) { + nasal_namespace[file] = {}; } // if in global scope, load global symbol into this namespace - auto& scope = nasal_namespace.at(i.location.file); + auto& scope = nasal_namespace.at(file); if (local.empty() && !scope.count(i.name)) { scope.insert(i.name); } @@ -223,22 +222,16 @@ void codegen::func_gen(function* node) { if (checked_default && tmp->get_parameter_type()!= parameter::kind::default_parameter) { - die("must use default parameter here", - tmp->get_location() - ); + die("must use default parameter here", tmp); } if (checked_dynamic && tmp!=node->get_parameter_list().back()) { - die("dynamic parameter must be the last one", - tmp->get_location() - ); + die("dynamic parameter must be the last one", tmp); } // check redefinition const auto& name = tmp->get_parameter_name(); if (argname.count(name)) { - die("redefinition of parameter: " + name, - tmp->get_location() - ); + die("redefinition of parameter: " + name, tmp); } else { argname[name] = true; } @@ -260,9 +253,7 @@ void codegen::func_gen(function* node) { for(auto tmp : node->get_parameter_list()) { const auto& name = tmp->get_parameter_name(); if (name=="me") { - die("\"me\" should not be a parameter", - tmp->get_location() - ); + die("\"me\" should not be parameter", tmp); } regist_string(name); switch(tmp->get_parameter_type()) { @@ -317,7 +308,7 @@ void codegen::func_gen(function* node) { if (local.back().size()>=VM_STACK_DEPTH || local.back().size()>=UINT16_MAX) { die("too many local variants: " + std::to_string(local.back().size()), - block->get_location() + block ); } local.pop_back(); @@ -358,9 +349,7 @@ void codegen::call_identifier(identifier* node) { node->get_location() ); if (local.empty()) { - die("should warp native function in local scope", - node->get_location() - ); + die("should wrap up native function in local scope", node); } return; } @@ -378,7 +367,7 @@ void codegen::call_identifier(identifier* node) { emit(op_callg, index, node->get_location()); return; } - die("undefined symbol \"" + name + "\"", node->get_location()); + die("undefined symbol \"" + name + "\"", node); // generation failed, put a push nil operand here to fill the space emit(op_pnil, index, node->get_location()); } @@ -459,7 +448,7 @@ void codegen::call_func_gen(call_function* node) { void codegen::mcall(expr* node) { if (node->get_type()!=expr_type::ast_id && node->get_type()!=expr_type::ast_call) { - die("bad left-value: cannot get memory space", node->get_location()); + die("bad left-value: cannot get memory space", node); return; } // generate symbol call if node is just ast_id and return @@ -492,18 +481,18 @@ void codegen::mcall(expr* node) { case expr_type::ast_callv: mcall_vec(reinterpret_cast(tmp)); break; case expr_type::ast_callf: - die("bad left-value: function call", tmp->get_location()); break; + die("bad left-value: function call", tmp); break; case expr_type::ast_null_access: - die("bad left-value: null access test", tmp->get_location()); break; + die("bad left-value: null access test", tmp); break; default: - die("bad left-value: unknown call", tmp->get_location()); break; + die("bad left-value: unknown call", tmp); break; } } void codegen::mcall_identifier(identifier* node) { const auto& name = node->get_name(); if (native_function_mapper.count(name)) { - die("cannot modify native function", node->get_location()); + die("cannot modify native function", node); return; } @@ -520,17 +509,17 @@ void codegen::mcall_identifier(identifier* node) { emit(op_mcallg, index, node->get_location()); return; } - die("undefined symbol \"" + name + "\"", node->get_location()); + die("undefined symbol \"" + name + "\"", node); } void codegen::mcall_vec(call_vector* node) { if (node->get_slices().size()>1) { - die("bad left-value: subvec call", node->get_location()); + die("bad left-value: subvec call", node); return; } auto call = node->get_slices()[0]; if (call->get_end()) { - die("bad left-value: subvec call", node->get_location()); + die("bad left-value: subvec call", node); return; } calc_gen(call->get_begin()); @@ -566,14 +555,14 @@ void codegen::multi_def(definition_expr* node) { die("lack values in multi-definition, expect " + std::to_string(identifiers.size()) + " but get " + std::to_string(vals.size()), - node->get_tuple()->get_location() + node->get_tuple() ); return; } else if (identifiers.size()get_tuple()->get_location() + node->get_tuple() ); return; } @@ -600,7 +589,7 @@ void codegen::multi_def(definition_expr* node) { void codegen::definition_gen(definition_expr* node) { if (node->get_variable_name() && node->get_tuple()) { - die("cannot accept too many values", node->get_value()->get_location()); + die("cannot accept too many values", node->get_value()); } node->get_variable_name()? single_def(node):multi_def(node); } @@ -724,7 +713,7 @@ void codegen::gen_assignment_equal_statement(assignment_expr* node) { case op_mcallg: code.back().op = op_loadg; break; case op_mcalll: code.back().op = op_loadl; break; case op_mupval: code.back().op = op_loadu; break; - default: die("unexpected operand to replace", node->get_location()); + default: die("unexpected operand to replace", node); } } @@ -779,7 +768,7 @@ void codegen::multi_assign_gen(multi_assign* node) { "lack value(s) in multi-assignment, expect " + std::to_string(tuple_size) + " but get " + std::to_string(value_size), - value_node->get_location() + value_node ); return; } else if (tuple_sizeget_location() + value_node ); return; } @@ -1305,13 +1294,9 @@ void codegen::block_gen(code_block* node) { switch(tmp->get_type()) { case expr_type::ast_use: if (!local.empty()) { - die("module import is not allowed here.", - tmp->get_location() - ); + die("module import is not allowed here.", tmp); } else if (!is_use_statement) { - die("module import should be used at the top of the file.", - tmp->get_location() - ); + die("module import should be used at top of file.", tmp); } break; case expr_type::ast_null: break; diff --git a/src/nasal_codegen.h b/src/nasal_codegen.h index 9a9d749..ae86d3c 100644 --- a/src/nasal_codegen.h +++ b/src/nasal_codegen.h @@ -104,8 +104,8 @@ private: void check_id_exist(identifier*); - void die(const std::string& info, const span& loc) { - err.err("code", loc, info); + void die(const std::string& info, expr* node) { + err.err("code", node->get_location(), info); } void regist_number(const f64); diff --git a/src/symbol_finder.cpp b/src/symbol_finder.cpp index e661b61..e4a0ad5 100644 --- a/src/symbol_finder.cpp +++ b/src/symbol_finder.cpp @@ -8,16 +8,13 @@ bool symbol_finder::visit_definition_expr(definition_expr* node) { // example: var a = 1; symbols.push_back({ node->get_variable_name()->get_name(), - node->get_variable_name()->get_location() + node->get_variable_name() }); } else { // multiple variable definition // example: var (a, b, c) = (0, 1, 2); for(auto i : node->get_variables()->get_variables()) { - symbols.push_back({ - i->get_name(), - i->get_location() - }); + symbols.push_back({i->get_name(), i}); } } if (node->get_tuple()) { @@ -37,7 +34,7 @@ bool symbol_finder::visit_iter_expr(iter_expr* node) { if (node->is_definition() && node->get_name()) { symbols.push_back({ node->get_name()->get_name(), - node->get_name()->get_location() + node->get_name() }); } return true; diff --git a/src/symbol_finder.h b/src/symbol_finder.h index aa7b0cf..b76e3ab 100644 --- a/src/symbol_finder.h +++ b/src/symbol_finder.h @@ -13,7 +13,7 @@ class symbol_finder: public ast_visitor { public: struct symbol_info { std::string name; - span location; + identifier* pos_node; }; private: From 99298b86ab55e221218c4258861aaf8d1b51021b Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 3 Aug 2024 14:53:41 +0800 Subject: [PATCH 2/4] :art: add global variable info in global dump --- src/nasal_vm.cpp | 54 ++++++++++++++++++++++++++++-------------------- src/nasal_vm.h | 1 + 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 1ff0808..70bc2cc 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -31,9 +31,11 @@ void vm::vm_init_enrty(const std::vector& strs, /* init vm globals */ auto map_instance = ngc.alloc(vm_type::vm_map); + global_symbol_name.resize(global_symbol.size()); global[global_symbol.at("globals")] = map_instance; for(const auto& i : global_symbol) { - map_instance.map().mapper[i.first] = global+i.second; + map_instance.map().mapper[i.first] = global + i.second; + global_symbol_name[i.second] = i.first; } /* init vm arg */ @@ -144,21 +146,21 @@ void vm::namespace_value_info(var& val, const usize max_show_elems) { void vm::value_name_form(const var& val) { std::clog << "| "; switch(val.type) { - case vm_type::vm_none: std::clog << "null "; break; - case vm_type::vm_ret: std::clog << "ret "; break; - case vm_type::vm_addr: std::clog << "addr "; break; - case vm_type::vm_cnt: std::clog << "cnt "; break; - case vm_type::vm_nil: std::clog << "nil "; break; - case vm_type::vm_num: std::clog << "num "; break; - case vm_type::vm_str: std::clog << "str "; break; - case vm_type::vm_func: std::clog << "func "; break; - case vm_type::vm_upval: std::clog << "upval "; break; - case vm_type::vm_vec: std::clog << "vec "; break; - case vm_type::vm_hash: std::clog << "hash "; break; - case vm_type::vm_ghost: std::clog << "ghost "; break; - case vm_type::vm_co: std::clog << "co "; break; - case vm_type::vm_map: std::clog << "map "; break; - default: std::clog << "err "; break; + case vm_type::vm_none: std::clog << "null "; break; + case vm_type::vm_ret: std::clog << "ret "; break; + case vm_type::vm_addr: std::clog << "addr "; break; + case vm_type::vm_cnt: std::clog << "cnt "; break; + case vm_type::vm_nil: std::clog << "nil "; break; + case vm_type::vm_num: std::clog << "num "; break; + case vm_type::vm_str: std::clog << "str "; break; + case vm_type::vm_func: std::clog << "func "; break; + case vm_type::vm_upval: std::clog << "upval"; break; + case vm_type::vm_vec: std::clog << "vec "; break; + case vm_type::vm_hash: std::clog << "hash "; break; + case vm_type::vm_ghost: std::clog << "ghost"; break; + case vm_type::vm_co: std::clog << "co "; break; + case vm_type::vm_map: std::clog << "map "; break; + default: std::clog << "err "; break; } std::clog << " | "; } @@ -344,16 +346,16 @@ void vm::stack_info(const u64 limit = 16) { void vm::register_info() { std::clog << "\nregister (" << (ngc.cort? "coroutine":"main") << ")\n"; std::clog << std::hex - << " [ pc ] | pc | 0x" << ctx.pc << "\n" - << " [ global ] | addr | 0x" + << " [ pc ] | pc | 0x" << ctx.pc << "\n" + << " [ global ] | addr | 0x" << reinterpret_cast(global) << "\n" - << " [ local ] | addr | 0x" + << " [ local ] | addr | 0x" << reinterpret_cast(ctx.localr) << "\n" - << " [ memr ] | addr | 0x" + << " [ memr ] | addr | 0x" << reinterpret_cast(ctx.memr) << "\n" - << " [ canary ] | addr | 0x" + << " [ canary ] | addr | 0x" << reinterpret_cast(ctx.canary) << "\n" - << " [ top ] | addr | 0x" + << " [ top ] | addr | 0x" << reinterpret_cast(ctx.top) << "\n" << std::dec; std::clog << " [ funcr ] "; value_info(ctx.funcr); @@ -370,6 +372,14 @@ void vm::global_state() { std::clog << " 0x" << std::hex << std::setw(8) << std::setfill('0') << i << std::dec << " "; + auto name = global_symbol_name[i]; + if (name.length()>=10) { + name = name.substr(0, 7) + "..."; + } else { + + } + std::clog << "| " << std::left << std::setw(10) + << std::setfill(' ') << name << " "; value_info(global[i]); } } diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 830b58d..1ea2444 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -42,6 +42,7 @@ protected: /* values used for debugger */ const std::string* files = nullptr; // file name list const opcode* bytecode = nullptr; // bytecode buffer address + std::vector global_symbol_name; // global symbol name /* variables for repl mode */ bool is_repl_mode = false; From 52dfd52f394dc35377eb971dfa3941657b292b8e Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 3 Aug 2024 17:07:32 +0800 Subject: [PATCH 3/4] :memo: adjust test files --- test/occupation.nas | 4 ++-- test/tui.nas | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 test/tui.nas diff --git a/test/occupation.nas b/test/occupation.nas index 348bbc3..dd62575 100644 --- a/test/occupation.nas +++ b/test/occupation.nas @@ -37,11 +37,11 @@ var cpu_occupation = func() { while(1) { var cpu0 = cpu_stat(); if (first_in) { - unix.sleep(0.1); + unix.sleep(0.05); first_in = 0; } else { for(var i = 0; i < 10; i += 1) { - unix.sleep(0.1); + unix.sleep(0.05); coroutine.yield(nil); } } diff --git a/test/tui.nas b/test/tui.nas new file mode 100644 index 0000000..ec342ba --- /dev/null +++ b/test/tui.nas @@ -0,0 +1,53 @@ +use std.utils; +use std.unix; + +var screen_state = { + width: 0, + height: 0 +}; + +screen_state.update = func() { + var res = utils.terminal_size(); + me.width = res.cols; + me.height = res.rows; +} + +screen_state.clear_screen = func() { + me.update(); + + var screen = "\e[0;0H"; + for (var i = 0; i < me.height; i+=1) { + for (var j = 0; j < me.width; j+=1) { + screen ~= " "; + } + if (i != me.height - 1) + screen ~= "\n"; + } + print(screen, "\e[0;0H"); +} + +screen_state.put_pixel = func(x, y, c) { + x = int(x); + y = int(y); + if (x < 0 or x >= me.width or y < 0 or y >= me.height) + return; + var coord = "\e[" ~ y ~ ";" ~ x ~ "H"; + print(coord, c, "\e[0;0H"); +} + +var test_flush = func() { + screen_state.clear_screen(); + for(var i=0; i<1e6; i+=1) { + unix.sleep(0.001); + screen_state.update(); + screen_state.put_pixel( + rand()*screen_state.width, + rand()*screen_state.height, + "\e[38;5;" ~ int(256*rand()) ~ "m" ~ char(65 + 26*rand()) ~ "\e[0m" + ); + print("\e[0;0H", i); + } + + screen_state.clear_screen(); + println(); +} \ No newline at end of file From 55f84855611b3b3a66ccf7bbf61d5f83984c6e2b Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 16 Aug 2024 23:02:27 +0800 Subject: [PATCH 4/4] :art: add new svg logo --- README.md | 2 +- doc/README_zh.md | 2 +- doc/svg/nasal.svg | 18 ++++++++++++++++++ doc/svg/nasal_transparent.svg | 18 ++++++++++++++++++ doc/tutorial.md | 2 +- doc/tutorial_zh.md | 2 +- src/main.cpp | 2 +- 7 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 doc/svg/nasal.svg create mode 100644 doc/svg/nasal_transparent.svg diff --git a/README.md b/README.md index df1701f..6c024aa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# __Nasal - Modern Interpreter__ +# __Nasal - Modern Interpreter__ diff --git a/doc/README_zh.md b/doc/README_zh.md index c5b0831..6970633 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -1,4 +1,4 @@ -# __Nasal - Modern Interpreter__ +# __Nasal - Modern Interpreter__ diff --git a/doc/svg/nasal.svg b/doc/svg/nasal.svg new file mode 100644 index 0000000..389651a --- /dev/null +++ b/doc/svg/nasal.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/svg/nasal_transparent.svg b/doc/svg/nasal_transparent.svg new file mode 100644 index 0000000..e26e972 --- /dev/null +++ b/doc/svg/nasal_transparent.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/tutorial.md b/doc/tutorial.md index 1dbd2ab..18efbf5 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1,4 +1,4 @@ -# __Tutorial__ +# __Tutorial__ ![mandelbrotset](../doc/pic/mandelbrotset.png) diff --git a/doc/tutorial_zh.md b/doc/tutorial_zh.md index bc2220a..715782c 100644 --- a/doc/tutorial_zh.md +++ b/doc/tutorial_zh.md @@ -1,4 +1,4 @@ -# __教程__ +# __教程__ ![mandelbrotset](../doc/pic/mandelbrotset.png) diff --git a/src/main.cpp b/src/main.cpp index 70e344f..aac6c26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,7 @@ std::ostream& logo(std::ostream& out) { << " - http://fgprc.org\n" << " - http://fgprc.org.cn\n" << "\n" - << "input to get help .\n\n"; + << "input to get help.\n\n"; return out; }