From 94d0ce9c2d2c06def54ab5071a66711b4da4b342 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Thu, 26 Dec 2024 00:45:53 +0800 Subject: [PATCH 01/18] :memo: format --- std/csv.nas | 10 +++++----- std/file.nas | 24 +++++++++++------------- std/queue.nas | 24 ++++++++++++------------ std/stack.nas | 4 ++-- std/string.nas | 6 ++++-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/std/csv.nas b/std/csv.nas index c2d843d..d6edac4 100644 --- a/std/csv.nas +++ b/std/csv.nas @@ -2,14 +2,14 @@ # ValKmjolnir 2022/10/15 use std.io; -var read = func(path, delimeter=",", endline="\n") { +var read = func(path, delimeter = ",", endline = "\n") { var context = io.readfile(path); context = split(endline, context); - forindex(var i;context) { - context[i] = split(delimeter,context[i]); + forindex(var i; context) { + context[i] = split(delimeter, context[i]); } - if (size(context)<=1) { - die("incorrect csv file <"~path~">: "~size(context)~" line(s)."); + if (size(context) <= 1) { + die("incorrect csv file <" ~ path ~ ">: " ~ size(context) ~ " line(s)."); } return { property: context[0], diff --git a/std/file.nas b/std/file.nas index 1138a54..d7bf765 100644 --- a/std/file.nas +++ b/std/file.nas @@ -4,12 +4,10 @@ use std.io; use std.unix; var SEEK_SET = io.SEEK_SET; - var SEEK_CUR = io.SEEK_CUR; - var SEEK_END = io.SEEK_END; -var new = func(filename, mode="r") { +var new = func(filename, mode = "r") { if (!io.exists(filename)) { return nil; } @@ -56,7 +54,7 @@ var find_all_files = func(path) { var dd = unix.opendir(path); var res = []; while(var n = unix.readdir(dd)) { - if (unix.isfile(path~"/"~n)) { + if (unix.isfile(path ~ "/" ~ n)) { append(res, n); } } @@ -74,11 +72,11 @@ var recursive_find_files = func(path) { files: [] }; while(var n = unix.readdir(dd)) { - if (unix.isfile(path~"/"~n)) { + if (unix.isfile(path ~ "/" ~ n)) { append(res.files, n); - } elsif (unix.isdir(path~"/"~n) and n!="." and n!="..") { - var tmp = recursive_find_files(path~"/"~n); - if (tmp!=nil) { + } elsif (unix.isdir(path ~ "/" ~ n) and n != "." and n != "..") { + var tmp = recursive_find_files(path ~ "/" ~ n); + if (tmp != nil) { append(res.files, tmp); } } @@ -89,19 +87,19 @@ var recursive_find_files = func(path) { var recursive_find_files_flat = func(path) { var tree_files = recursive_find_files(path); - if (tree_files==nil) { + if (tree_files == nil) { return []; } var flat = []; var bfs = [tree_files]; - while(size(bfs)!=0) { + while(size(bfs) != 0) { var first = pop(bfs); foreach(var file_record; first.files) { if (ishash(file_record)) { append(bfs, file_record); continue; } - append(flat, first.dir~"/"~file_record); + append(flat, first.dir ~ "/" ~ file_record); } } return flat; @@ -110,7 +108,7 @@ var recursive_find_files_flat = func(path) { var recursive_find_files_with_extension = func(path, extensions...) { var in_vec = func(ext) { foreach(var i; extensions) { - if (ext==i) { + if (ext == i) { return 1; } } @@ -121,7 +119,7 @@ var recursive_find_files_with_extension = func(path, extensions...) { var res = []; foreach(var filename; files) { var tmp = split('.', filename); - if (size(tmp)>1 and in_vec(tmp[-1])) { + if (size(tmp) > 1 and in_vec(tmp[-1])) { append(res, filename); } } diff --git a/std/queue.nas b/std/queue.nas index d662e77..392600a 100644 --- a/std/queue.nas +++ b/std/queue.nas @@ -4,32 +4,32 @@ var new = func() { var (begin, end) = (nil, nil); return{ push: func(elem) { - var new_node={ + var new_node = { elem:elem, next:nil }; - if (begin==nil) - begin=end=new_node; + if (begin == nil) + begin = end = new_node; else { - end.next=new_node; - end=new_node; + end.next = new_node; + end = new_node; } }, pop: func() { - if (begin!=nil) - begin=begin.next; - if (begin==nil) - end=nil; + if (begin != nil) + begin = begin.next; + if (begin == nil) + end = nil; }, front: func() { - if (begin!=nil) + if (begin != nil) return begin.elem; }, clear: func() { - begin=end=nil; + begin = end = nil; }, empty: func() { - return begin==nil; + return begin == nil; } }; } diff --git a/std/stack.nas b/std/stack.nas index 596a603..6fc8544 100644 --- a/std/stack.nas +++ b/std/stack.nas @@ -10,7 +10,7 @@ var stack = func() { return pop(vec); }, top: func() { - if (size(vec)!=0) { + if (size(vec) != 0) { return vec[-1]; } }, @@ -18,7 +18,7 @@ var stack = func() { vec = []; }, empty: func() { - return size(vec)==0; + return size(vec) == 0; } }; } diff --git a/std/string.nas b/std/string.nas index b14d2ce..f2ab3b5 100644 --- a/std/string.nas +++ b/std/string.nas @@ -33,11 +33,13 @@ func() { }(); var to_char = func(number) { - return 0<=number and number<256? __num_to_char[number]:""; + return 0 <= number and number < 256? __num_to_char[number] : ""; } var to_num = func(character) { - return __temp_contains(__char_to_num, character)? __char_to_num[character]:-1; + return __temp_contains(__char_to_num, character) + ? __char_to_num[character] + : -1; } var __string_split_with_empty_substr = func(separator, str) { From 985dee800169fa81a6ac6939a9e7e95dc25af9b6 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Thu, 26 Dec 2024 21:02:35 +0800 Subject: [PATCH 02/18] :memo: format --- src/nasal_type.cpp | 37 --------------- src/nasal_type.h | 98 +++++++++++++++++++++++--------------- src/nasal_vm.cpp | 10 ++-- src/nasal_vm.h | 40 ++++++++-------- test/coroutine.nas | 116 +++++++++++++++++++++++---------------------- 5 files changed, 144 insertions(+), 157 deletions(-) diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 588fbc2..8a38b11 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -317,41 +317,4 @@ std::ostream& operator<<(std::ostream& out, var& ref) { return out; } -bool var::object_check(const std::string& name) const { - return is_ghost() && ghost().type_name == name && ghost().pointer; -} - -var var::none() { - return {vm_type::vm_none, static_cast(0)}; -} - -var var::nil() { - return {vm_type::vm_nil, static_cast(0)}; -} - -var var::ret(u64 pc) { - return {vm_type::vm_ret, pc}; -} - -var var::cnt(i64 n) { - return {vm_type::vm_cnt, n}; -} - -var var::num(f64 n) { - return {vm_type::vm_num, n}; -} - -var var::gcobj(nas_val* p) { - return {p->type, p}; -} - -var var::addr(var* p) { - return {vm_type::vm_addr, p}; -} - -var nas_err(const std::string& error_function_name, const std::string& info) { - std::cerr << "[vm] " << error_function_name << ": " << info << "\n"; - return var::none(); -} - } \ No newline at end of file diff --git a/src/nasal_type.h b/src/nasal_type.h index 029f9da..3c240d5 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -86,31 +86,45 @@ public: } val; private: - var(vm_type t, u64 pc) {type = t; val.ret = pc;} - var(vm_type t, i64 ct) {type = t; val.cnt = ct;} - var(vm_type t, f64 n) {type = t; val.num = n;} - var(vm_type t, var* p) {type = t; val.addr = p;} - var(vm_type t, nas_val* p) {type = t; val.gcobj = p;} + var(vm_type t, u64 pc) { type = t; val.ret = pc; } + var(vm_type t, i64 ct) { type = t; val.cnt = ct; } + var(vm_type t, f64 n) { type = t; val.num = n; } + var(vm_type t, var* p) { type = t; val.addr = p; } + var(vm_type t, nas_val* p) { type = t; val.gcobj = p; } public: var() = default; var(const var&) = default; bool operator==(const var& nr) const { - return type==nr.type && val.gcobj==nr.val.gcobj; + return type == nr.type && val.gcobj == nr.val.gcobj; } bool operator!=(const var& nr) const { - return type!=nr.type || val.gcobj!=nr.val.gcobj; + return type != nr.type || val.gcobj != nr.val.gcobj; } public: // create new var object - static var none(); - static var nil(); - static var ret(u64); - static var cnt(i64); - static var num(f64); - static var gcobj(nas_val*); - static var addr(var*); + static var none() { + return var(vm_type::vm_none, static_cast(0)); + } + static var nil() { + return var(vm_type::vm_nil, static_cast(0)); + } + static var ret(u64 pc) { + return var(vm_type::vm_ret, pc); + } + static var cnt(i64 n) { + return var(vm_type::vm_cnt, n); + } + static var num(f64 n) { + return var(vm_type::vm_num, n); + } + static var gcobj(nas_val* p) { + return var(p->type, p); + } + static var addr(var* p) { + return var(vm_type::vm_addr, p); + } public: // get value @@ -143,26 +157,27 @@ public: const nas_map& map() const { return *val.gcobj->ptr.map; } public: - bool is_none() const { return type==vm_type::vm_none; } - bool is_cnt() const { return type==vm_type::vm_cnt; } - bool is_addr() const { return type==vm_type::vm_addr; } - bool is_ret() const { return type==vm_type::vm_ret; } - bool is_nil() const { return type==vm_type::vm_nil; } - bool is_num() const { return type==vm_type::vm_num; } - bool is_str() const { return type==vm_type::vm_str; } - bool is_vec() const { return type==vm_type::vm_vec; } - bool is_hash() const { return type==vm_type::vm_hash; } - bool is_func() const { return type==vm_type::vm_func; } - bool is_upval() const { return type==vm_type::vm_upval; } - bool is_ghost() const { return type==vm_type::vm_ghost; } - bool is_coroutine() const { return type==vm_type::vm_co; } - bool is_map() const { return type==vm_type::vm_map; } + bool is_none() const { return type == vm_type::vm_none; } + bool is_cnt() const { return type == vm_type::vm_cnt; } + bool is_addr() const { return type == vm_type::vm_addr; } + bool is_ret() const { return type == vm_type::vm_ret; } + bool is_nil() const { return type == vm_type::vm_nil; } + bool is_num() const { return type == vm_type::vm_num; } + bool is_str() const { return type == vm_type::vm_str; } + bool is_vec() const { return type == vm_type::vm_vec; } + bool is_hash() const { return type == vm_type::vm_hash; } + bool is_func() const { return type == vm_type::vm_func; } + bool is_upval() const { return type == vm_type::vm_upval; } + bool is_ghost() const { return type == vm_type::vm_ghost; } + bool is_coroutine() const { return type == vm_type::vm_co; } + bool is_map() const { return type == vm_type::vm_map; } public: // number and string can be translated to each other f64 to_num() const; std::string to_str(); - bool object_check(const std::string&) const; + inline bool object_check(const std::string&) const; + friend std::ostream& operator<<(std::ostream&, var&); }; struct nas_vec { @@ -174,6 +189,7 @@ struct nas_vec { auto size() const { return elems.size(); } var get_value(const i32); var* get_memory(const i32); + friend std::ostream& operator<<(std::ostream&, nas_vec&); }; struct nas_hash { @@ -185,6 +201,7 @@ struct nas_hash { auto size() const { return elems.size(); } var get_value(const std::string&); var* get_memory(const std::string&); + friend std::ostream& operator<<(std::ostream&, nas_hash&); }; struct nas_func { @@ -206,6 +223,7 @@ struct nas_func { parameter_size(0), local_size(0), dynamic_parameter_name("") {} void clear(); + friend std::ostream& operator<<(std::ostream&, nas_func&); }; struct nas_upval { @@ -222,7 +240,7 @@ public: nas_upval(): on_stack(true), size(0), stack_frame_offset(nullptr) {} var& operator[](usize n) { - return on_stack? stack_frame_offset[n]:elems[n]; + return on_stack? stack_frame_offset[n] : elems[n]; } void clear() { @@ -250,6 +268,7 @@ public: ~nas_ghost() { clear(); } void set(const std::string&, destructor, marker, void*); void clear(); + friend std::ostream& operator<<(std::ostream&, const nas_ghost&); public: const auto& get_ghost_name() const { return type_name; } @@ -290,6 +309,7 @@ struct nas_co { delete[] ctx.stack; } void clear(); + friend std::ostream& operator<<(std::ostream&, const nas_co&); }; struct nas_map { @@ -304,21 +324,21 @@ public: var get_value(const std::string&); var* get_memory(const std::string&); + friend std::ostream& operator<<(std::ostream&, nas_map&); }; -std::ostream& operator<<(std::ostream&, nas_vec&); -std::ostream& operator<<(std::ostream&, nas_hash&); -std::ostream& operator<<(std::ostream&, nas_func&); -std::ostream& operator<<(std::ostream&, nas_map&); -std::ostream& operator<<(std::ostream&, const nas_ghost&); -std::ostream& operator<<(std::ostream&, const nas_co&); -std::ostream& operator<<(std::ostream&, var&); - const var zero = var::num(0); const var one = var::num(1); const var nil = var::nil(); +inline bool var::object_check(const std::string& name) const { + return is_ghost() && ghost().type_name == name && ghost().pointer; +} + // use to print error log and return error value -var nas_err(const std::string&, const std::string&); +static var nas_err(const std::string& func, const std::string& info) { + std::cerr << "[vm] " << func << ": " << info << "\n"; + return var::none(); +} } \ No newline at end of file diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 70bc2cc..3a57ec4 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -536,12 +536,12 @@ void vm::die(const std::string& str) { if (!ngc.cort) { // in main context, exit directly std::exit(1); - } else { - // in coroutine, shut down the coroutine and return to main context - ctx.pc = 0; // mark coroutine 'dead' - ngc.context_reserve(); // switch context to main - ctx.top[0] = nil; // generate return value 'nil' } + + // in coroutine, shut down the coroutine and return to main context + ctx.pc = 0; // mark coroutine 'dead' + ngc.context_reserve(); // switch context to main + ctx.top[0] = nil; // generate return value 'nil' } void vm::run(const codegen& gen, diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 0829bce..6221208 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -359,8 +359,8 @@ inline void vm::o_loadl() { } inline void vm::o_loadu() { - ctx.funcr.func().upval[(imm[ctx.pc]>>16)&0xffff] - .upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0]; + ctx.funcr.func().upval[(imm[ctx.pc]>>16) & 0xffff] + .upval()[imm[ctx.pc] & 0xffff] = (ctx.top--)[0]; } inline void vm::o_dup() { @@ -452,7 +452,7 @@ inline void vm::o_lnot() { var val = ctx.top[0]; switch(val.type) { case vm_type::vm_nil: ctx.top[0] = one; break; - case vm_type::vm_num: ctx.top[0] = val.num()? zero:one; break; + case vm_type::vm_num: ctx.top[0] = val.num()? zero : one; break; case vm_type::vm_str: { const f64 num = util::str_to_num(val.str().c_str()); if (std::isnan(num)) { @@ -462,7 +462,7 @@ inline void vm::o_lnot() { } } break; default: - die("cannot do not-operation on "+type_name_string(val)); + die("cannot do not-operation on " + type_name_string(val)); return; } } @@ -477,7 +477,7 @@ inline void vm::o_bnot() { inline void vm::o_btor() { ctx.top[-1] = var::num( - static_cast(ctx.top[-1].to_num())| + static_cast(ctx.top[-1].to_num()) | static_cast(ctx.top[0].to_num()) ); --ctx.top; @@ -485,7 +485,7 @@ inline void vm::o_btor() { inline void vm::o_btxor() { ctx.top[-1] = var::num( - static_cast(ctx.top[-1].to_num())^ + static_cast(ctx.top[-1].to_num()) ^ static_cast(ctx.top[0].to_num()) ); --ctx.top; @@ -493,7 +493,7 @@ inline void vm::o_btxor() { inline void vm::o_btand() { ctx.top[-1] = var::num( - static_cast(ctx.top[-1].to_num())& + static_cast(ctx.top[-1].to_num()) & static_cast(ctx.top[0].to_num()) ); --ctx.top; @@ -503,10 +503,10 @@ inline void vm::o_btand() { ctx.top[-1] = var::num(ctx.top[-1].to_num() type ctx.top[0].to_num());\ --ctx.top; -inline void vm::o_add() {op_calc(+);} -inline void vm::o_sub() {op_calc(-);} -inline void vm::o_mul() {op_calc(*);} -inline void vm::o_div() {op_calc(/);} +inline void vm::o_add() { op_calc(+); } +inline void vm::o_sub() { op_calc(-); } +inline void vm::o_mul() { op_calc(*); } +inline void vm::o_div() { op_calc(/); } inline void vm::o_lnk() { // concat two vectors into one if (ctx.top[-1].is_vec() && ctx.top[0].is_vec()) { @@ -535,7 +535,7 @@ inline void vm::o_subc() {op_calc_const(-);} inline void vm::o_mulc() {op_calc_const(*);} inline void vm::o_divc() {op_calc_const(/);} inline void vm::o_lnkc() { - ctx.top[0] = ngc.newstr(ctx.top[0].to_str()+const_string[imm[ctx.pc]]); + ctx.top[0] = ngc.newstr(ctx.top[0].to_str() + const_string[imm[ctx.pc]]); } // top[0] stores the value of memr[0], to avoid being garbage-collected @@ -575,7 +575,7 @@ inline void vm::o_lnkeq() { ctx.memr[0].to_str()+ctx.top[-1].to_str() ); ctx.memr = nullptr; - ctx.top -= imm[ctx.pc]+1; + ctx.top -= imm[ctx.pc] + 1; } inline void vm::o_bandeq() { @@ -598,11 +598,11 @@ inline void vm::o_boreq() { inline void vm::o_bxoreq() { ctx.top[-1] = ctx.memr[0] = var::num( - static_cast(ctx.memr[0].to_num())^ + static_cast(ctx.memr[0].to_num()) ^ static_cast(ctx.top[-1].to_num()) ); ctx.memr = nullptr; - ctx.top -= imm[ctx.pc]+1; + ctx.top -= imm[ctx.pc] + 1; } // top[0] stores the value of memr[0], to avoid being garbage-collected @@ -1083,8 +1083,8 @@ inline void vm::o_mcalll() { inline void vm::o_mupval() { ctx.memr = &( ctx.funcr.func() - .upval[(imm[ctx.pc]>>16)&0xffff] - .upval()[imm[ctx.pc]&0xffff] + .upval[(imm[ctx.pc]>>16) & 0xffff] + .upval()[imm[ctx.pc] & 0xffff] ); (++ctx.top)[0] = ctx.memr[0]; // push value in this memory space on stack @@ -1102,7 +1102,7 @@ inline void vm::o_mcallv() { } } else if (vec.is_hash()) { // do mcallh but use the mcallv way if (!val.is_str()) { - die("must use string as the key but get "+type_name_string(val)); + die("must use string as the key but get " + type_name_string(val)); return; } auto& ref = vec.hash(); @@ -1114,7 +1114,7 @@ inline void vm::o_mcallv() { } } else if (vec.is_map()) { if (!val.is_str()) { - die("must use string as the key but get "+type_name_string(val)); + die("must use string as the key but get " + type_name_string(val)); return; } auto& ref = vec.map(); @@ -1192,7 +1192,7 @@ inline void vm::o_ret() { auto size = func.func().local_size; upval.on_stack = false; upval.elems.resize(size); - for(u64 i = 0; i Date: Thu, 26 Dec 2024 23:19:34 +0800 Subject: [PATCH 03/18] :memo: add doc about how to build on windows --- .gitignore | 3 ++- CMakeLists.txt | 29 +++++++++++++++++------------ README.md | 2 +- doc/README_zh.md | 1 + doc/windows-build.md | 27 +++++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 doc/windows-build.md diff --git a/.gitignore b/.gitignore index 7ccf091..76f7285 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,8 @@ build/ out/ dist/ -cmake-build-*/ +cmake-build-* +cmake-windows-* # IDE and editor files .vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 69c03f8..40d3f42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall") add_compile_options(-fPIC) # MSVC needs this command option to really enable utf-8 output -if(MSVC) +if (MSVC) add_compile_options(/utf-8) endif() @@ -103,16 +103,21 @@ target_link_libraries(mat module-used-object) add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp) target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src) +if (WIN32) + target_link_libraries(nasock ws2_32) +endif() target_link_libraries(nasock module-used-object) -# Add web library -add_library(nasal-web SHARED - src/nasal_web.cpp - ${NASAL_OBJECT_SOURCE_FILE} -) -target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src) -set_target_properties(nasal-web PROPERTIES - C_VISIBILITY_PRESET hidden - CXX_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN ON -) +# Add web library, not for MSVC now +if (NOT MSVC) + add_library(nasal-web SHARED + src/nasal_web.cpp + ${NASAL_OBJECT_SOURCE_FILE} + ) + target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src) + set_target_properties(nasal-web PROPERTIES + C_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON + ) +endif() \ No newline at end of file diff --git a/README.md b/README.md index 119dbf4..bf26763 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Make sure thread model is `posix thread model`, otherwise no thread library exis ### __Windows (Visual Studio)__ -There is a [__CMakelists.txt__](./CMakeLists.txt) to create project. +There is a [__CMakelists.txt__](./CMakeLists.txt) to create project. Recently we find how to build it with command line tools: [__Build Nasal-Interpreter on Windows]__(./doc/windows-build.md). ### __Linux / macOS / Unix__ diff --git a/doc/README_zh.md b/doc/README_zh.md index b750837..ccefecb 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -81,6 +81,7 @@ Windows 平台的预览版解释器现在还没配置相关流水线, ### __Windows 平台 (Vistual Studio)__ 项目提供了 [__CMakeLists.txt__](../CMakeLists.txt) 用于在`Visual Studio`中创建项目。 +最近我们总结了命令行编译的方法 [__如何在 Windows 平台编译 Nasal-Interpreter__](./windows-build.md)。 ### __Linux / macOS / Unix 平台__ diff --git a/doc/windows-build.md b/doc/windows-build.md new file mode 100644 index 0000000..665ba49 --- /dev/null +++ b/doc/windows-build.md @@ -0,0 +1,27 @@ +# Build Nasal-Interpreter on Windows + +## MSVC / Visual Studio + +Need CMake and Visual Studio 2022. Remember to add MSBuild.exe to Path. + +Valid on powershell: + +```sh +mkdir cmake-windows-msvc +cd cmake-windows-msvc +cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" +MSbuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64 +``` + +## MingW-W64 + +Need CMake and MingW-W64. Remember to add MingW-W64 bin to Path. + +Valid on powershell: + +```sh +mkdir cmake-windows-mingw +cd cmake-windows-mingw +cmake .. -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ +mingw32-make.exe -j6 +``` From f6fa78d33e32afeda69f2da8509f226605c8d8d3 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 27 Dec 2024 01:00:36 +0800 Subject: [PATCH 04/18] :memo: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf26763..30e0694 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Make sure thread model is `posix thread model`, otherwise no thread library exis ### __Windows (Visual Studio)__ -There is a [__CMakelists.txt__](./CMakeLists.txt) to create project. Recently we find how to build it with command line tools: [__Build Nasal-Interpreter on Windows]__(./doc/windows-build.md). +There is a [__CMakelists.txt__](./CMakeLists.txt) to create project. Recently we find how to build it with command line tools: [__Build Nasal-Interpreter on Windows__](./doc/windows-build.md). ### __Linux / macOS / Unix__ From 4dc4c1d2b7ce1a59b519f84b4352d7f7355e0877 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 27 Dec 2024 19:21:07 +0800 Subject: [PATCH 05/18] :memo: fix typo --- doc/windows-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/windows-build.md b/doc/windows-build.md index 665ba49..53fdbb7 100644 --- a/doc/windows-build.md +++ b/doc/windows-build.md @@ -10,7 +10,7 @@ Valid on powershell: mkdir cmake-windows-msvc cd cmake-windows-msvc cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -MSbuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64 +MSBuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64 ``` ## MingW-W64 From 688fbe8c5dede479c5cab1b4cddba88024f5c3ca Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 1 Jan 2025 16:39:25 +0800 Subject: [PATCH 06/18] :art: formating --- src/nasal_vm.h | 135 ++++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 64 deletions(-) diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 6221208..258c972 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -511,10 +511,10 @@ inline void vm::o_lnk() { // concat two vectors into one if (ctx.top[-1].is_vec() && ctx.top[0].is_vec()) { ngc.temp = ngc.alloc(vm_type::vm_vec); - for(auto i : ctx.top[-1].vec().elems) { + for(auto& i : ctx.top[-1].vec().elems) { ngc.temp.vec().elems.push_back(i); } - for(auto i : ctx.top[0].vec().elems) { + for(auto& i : ctx.top[0].vec().elems) { ngc.temp.vec().elems.push_back(i); } ctx.top[-1] = ngc.temp; @@ -523,17 +523,17 @@ inline void vm::o_lnk() { return; } // concat strings - ctx.top[-1] = ngc.newstr(ctx.top[-1].to_str()+ctx.top[0].to_str()); + ctx.top[-1] = ngc.newstr(ctx.top[-1].to_str() + ctx.top[0].to_str()); --ctx.top; } #define op_calc_const(type)\ ctx.top[0] = var::num(ctx.top[0].to_num() type const_number[imm[ctx.pc]]); -inline void vm::o_addc() {op_calc_const(+);} -inline void vm::o_subc() {op_calc_const(-);} -inline void vm::o_mulc() {op_calc_const(*);} -inline void vm::o_divc() {op_calc_const(/);} +inline void vm::o_addc() { op_calc_const(+); } +inline void vm::o_subc() { op_calc_const(-); } +inline void vm::o_mulc() { op_calc_const(*); } +inline void vm::o_divc() { op_calc_const(/); } inline void vm::o_lnkc() { ctx.top[0] = ngc.newstr(ctx.top[0].to_str() + const_string[imm[ctx.pc]]); } @@ -548,12 +548,12 @@ inline void vm::o_lnkc() { ctx.memr[0].to_num() type ctx.top[-1].to_num()\ );\ ctx.memr = nullptr;\ - ctx.top -= imm[ctx.pc]+1; + ctx.top -= imm[ctx.pc] + 1; -inline void vm::o_addeq() {op_calc_eq(+);} -inline void vm::o_subeq() {op_calc_eq(-);} -inline void vm::o_muleq() {op_calc_eq(*);} -inline void vm::o_diveq() {op_calc_eq(/);} +inline void vm::o_addeq() { op_calc_eq(+); } +inline void vm::o_subeq() { op_calc_eq(-); } +inline void vm::o_muleq() { op_calc_eq(*); } +inline void vm::o_diveq() { op_calc_eq(/); } inline void vm::o_lnkeq() { // concat two vectors into one if (ctx.top[-1].is_vec() && ctx.memr[0].is_vec()) { @@ -572,7 +572,7 @@ inline void vm::o_lnkeq() { } ctx.top[-1] = ctx.memr[0] = ngc.newstr( - ctx.memr[0].to_str()+ctx.top[-1].to_str() + ctx.memr[0].to_str() + ctx.top[-1].to_str() ); ctx.memr = nullptr; ctx.top -= imm[ctx.pc] + 1; @@ -616,13 +616,13 @@ inline void vm::o_bxoreq() { );\ ctx.memr = nullptr; -inline void vm::o_addeqc() {op_calc_eq_const(+);} -inline void vm::o_subeqc() {op_calc_eq_const(-);} -inline void vm::o_muleqc() {op_calc_eq_const(*);} -inline void vm::o_diveqc() {op_calc_eq_const(/);} +inline void vm::o_addeqc() { op_calc_eq_const(+); } +inline void vm::o_subeqc() { op_calc_eq_const(-); } +inline void vm::o_muleqc() { op_calc_eq_const(*); } +inline void vm::o_diveqc() { op_calc_eq_const(/); } inline void vm::o_lnkeqc() { ctx.top[0] = ctx.memr[0] = ngc.newstr( - ctx.memr[0].to_str()+const_string[imm[ctx.pc]] + ctx.memr[0].to_str() + const_string[imm[ctx.pc]] ); ctx.memr = nullptr; } @@ -634,13 +634,13 @@ inline void vm::o_lnkeqc() { ctx.memr = nullptr;\ --ctx.top; -inline void vm::o_addecp() {op_calc_eq_const_and_pop(+);} -inline void vm::o_subecp() {op_calc_eq_const_and_pop(-);} -inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);} -inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);} +inline void vm::o_addecp() { op_calc_eq_const_and_pop(+); } +inline void vm::o_subecp() { op_calc_eq_const_and_pop(-); } +inline void vm::o_mulecp() { op_calc_eq_const_and_pop(*); } +inline void vm::o_divecp() { op_calc_eq_const_and_pop(/); } inline void vm::o_lnkecp() { ctx.top[0] = ctx.memr[0] = ngc.newstr( - ctx.memr[0].to_str()+const_string[imm[ctx.pc]] + ctx.memr[0].to_str() + const_string[imm[ctx.pc]] ); ctx.memr = nullptr; --ctx.top; @@ -663,12 +663,12 @@ inline void vm::o_eq() { if (val1.is_nil() && val2.is_nil()) { ctx.top[0] = one; } else if (val1.is_str() && val2.is_str()) { - ctx.top[0] = (val1.str()==val2.str())? one:zero; + ctx.top[0] = (val1.str()==val2.str())? one : zero; } else if ((val1.is_num() || val2.is_num()) && !val1.is_nil() && !val2.is_nil()) { - ctx.top[0] = (val1.to_num()==val2.to_num())? one:zero; + ctx.top[0] = (val1.to_num()==val2.to_num())? one : zero; } else { - ctx.top[0] = (val1==val2)? one:zero; + ctx.top[0] = (val1==val2)? one : zero; } } @@ -678,59 +678,59 @@ inline void vm::o_neq() { if (val1.is_nil() && val2.is_nil()) { ctx.top[0] = zero; } else if (val1.is_str() && val2.is_str()) { - ctx.top[0] = (val1.str()!=val2.str())? one:zero; + ctx.top[0] = (val1.str()!=val2.str())? one : zero; } else if ((val1.is_num() || val2.is_num()) && !val1.is_nil() && !val2.is_nil()) { - ctx.top[0] = (val1.to_num()!=val2.to_num())? one:zero; + ctx.top[0] = (val1.to_num()!=val2.to_num())? one : zero; } else { - ctx.top[0] = (val1!=val2)? one:zero; + ctx.top[0] = (val1!=val2)? one : zero; } } #define op_cmp(type)\ --ctx.top;\ - ctx.top[0] = (ctx.top[0].to_num() type ctx.top[1].to_num())? one:zero; + ctx.top[0] = (ctx.top[0].to_num() type ctx.top[1].to_num())? one : zero; -inline void vm::o_less() {op_cmp(<);} -inline void vm::o_leq() {op_cmp(<=);} -inline void vm::o_grt() {op_cmp(>);} -inline void vm::o_geq() {op_cmp(>=);} +inline void vm::o_less() { op_cmp(<); } +inline void vm::o_leq() { op_cmp(<=); } +inline void vm::o_grt() { op_cmp(>); } +inline void vm::o_geq() { op_cmp(>=); } #define op_cmp_const(type)\ - ctx.top[0] = (ctx.top[0].to_num() type const_number[imm[ctx.pc]])? one:zero; + ctx.top[0] = (ctx.top[0].to_num() type const_number[imm[ctx.pc]])? one : zero; -inline void vm::o_lessc() {op_cmp_const(<);} -inline void vm::o_leqc() {op_cmp_const(<=);} -inline void vm::o_grtc() {op_cmp_const(>);} -inline void vm::o_geqc() {op_cmp_const(>=);} +inline void vm::o_lessc() { op_cmp_const(<); } +inline void vm::o_leqc() { op_cmp_const(<=); } +inline void vm::o_grtc() { op_cmp_const(>); } +inline void vm::o_geqc() { op_cmp_const(>=); } inline void vm::o_pop() { --ctx.top; } inline void vm::o_jmp() { - ctx.pc = imm[ctx.pc]-1; + ctx.pc = imm[ctx.pc] - 1; } inline void vm::o_jt() { // jump true needs to reserve the result on stack // because conditional expression in nasal has return value if (boolify(ctx.top[0])) { - ctx.pc = imm[ctx.pc]-1; + ctx.pc = imm[ctx.pc] - 1; } } inline void vm::o_jf() { // jump false doesn't need to reserve result if (!boolify(ctx.top[0])) { - ctx.pc = imm[ctx.pc]-1; + ctx.pc = imm[ctx.pc] - 1; } --ctx.top; } inline void vm::o_cnt() { if (!ctx.top[0].is_vec()) { - die("must use vector in forindex/foreach but get "+ + die("must use vector in forindex/foreach but get " + type_name_string(ctx.top[0]) ); return; @@ -768,8 +768,8 @@ inline void vm::o_calll() { inline void vm::o_upval() { (++ctx.top)[0] = ctx.funcr.func() - .upval[(imm[ctx.pc]>>16)&0xffff] - .upval()[imm[ctx.pc]&0xffff]; + .upval[(imm[ctx.pc] >> 16) & 0xffff] + .upval()[imm[ctx.pc] & 0xffff]; } inline void vm::o_callv() { @@ -783,7 +783,7 @@ inline void vm::o_callv() { } } else if (vec.is_hash()) { if (!val.is_str()) { - die("must use string as the key but get "+type_name_string(val)); + die("must use string as the key but get " + type_name_string(val)); return; } ctx.top[0] = vec.hash().get_value(val.str()); @@ -802,20 +802,20 @@ inline void vm::o_callv() { return; } ctx.top[0] = var::num( - static_cast(static_cast(str[num>=0? num:num+len])) + static_cast(static_cast(str[num>=0? num : num + len])) ); } else if (vec.is_map()) { if (!val.is_str()) { - die("must use string as the key but get "+type_name_string(val)); + die("must use string as the key but get " + type_name_string(val)); return; } ctx.top[0] = vec.map().get_value(val.str()); if (ctx.top[0].is_none()) { - die("cannot find symbol \""+val.str()+"\""); + die("cannot find symbol \"" + val.str() + "\""); return; } } else { - die("must call a vector/hash/string but get "+type_name_string(vec)); + die("must call a vector/hash/string but get " + type_name_string(vec)); return; } } @@ -823,7 +823,7 @@ inline void vm::o_callv() { inline void vm::o_callvi() { var val = ctx.top[0]; if (!val.is_vec()) { - die("must use a vector but get "+type_name_string(val)); + die("must use a vector but get " + type_name_string(val)); return; } // cannot use operator[], because this may cause overflow @@ -837,7 +837,7 @@ inline void vm::o_callvi() { inline void vm::o_callh() { var val = ctx.top[0]; if (!val.is_hash() && !val.is_map()) { - die("must call a hash but get "+type_name_string(val)); + die("must call a hash but get " + type_name_string(val)); return; } @@ -847,21 +847,26 @@ inline void vm::o_callh() { } else { ctx.top[0] = val.map().get_value(str); } + + // report key not found if get_value returns none if (ctx.top[0].is_none()) { - val.is_hash()? - die(report_key_not_found(str, val.hash())): - die("cannot find symbol \"" + str + "\""); + val.is_hash() + ? die(report_key_not_found(str, val.hash())) + : die("cannot find symbol \"" + str + "\""); return; - } else if (ctx.top[0].is_func()) { + } + + // if get function from hash, set 'me' + if (ctx.top[0].is_func() && val.is_hash()) { ctx.top[0].func().local[0] = val; // 'me' } } inline void vm::o_callfv() { const auto argc = imm[ctx.pc]; // arguments counter - var* local = ctx.top-argc+1; // arguments begin address + var* local = ctx.top - argc + 1; // arguments begin address if (!local[-1].is_func()) { - die("must call a function but get "+type_name_string(local[-1])); + die("must call a function but get " + type_name_string(local[-1])); return; } const auto& func = local[-1].func(); @@ -904,7 +909,7 @@ inline void vm::o_callfv() { // then all the available values the vector needs // are all outside the stack top and may be // collected incorrectly - ctx.top = local+func.local_size; + ctx.top = local + func.local_size; // use (std::min) to avoid compilation error in MSVC // MSVC windows.h uses macro std::min @@ -917,12 +922,14 @@ inline void vm::o_callfv() { local[0] = func.local[0]; // load "me" // load local scope & default arguments - for(u64 i = min_size+1; i=0? - parameter_size+1:func.local_size-1] = dynamic; + local[func.dynamic_parameter_index >= 0 + ? parameter_size + 1 + : func.local_size - 1] = dynamic; ctx.top[0] = ctx.upvalr; (++ctx.top)[0] = var::addr(ctx.localr); @@ -935,7 +942,7 @@ inline void vm::o_callfv() { inline void vm::o_callfh() { const auto& hash = ctx.top[0].hash().elems; if (!ctx.top[-1].is_func()) { - die("must call a function but get "+type_name_string(ctx.top[-1])); + die("must call a function but get " + type_name_string(ctx.top[-1])); return; } const auto& func = ctx.top[-1].func(); @@ -1013,7 +1020,7 @@ inline void vm::o_slcbeg() { // +--------------+ (++ctx.top)[0] = ngc.alloc(vm_type::vm_vec); if (!ctx.top[-1].is_vec()) { - die("must slice a vector but get "+type_name_string(ctx.top[-1])); + die("must slice a vector but get " + type_name_string(ctx.top[-1])); return; } } From fd93fbafdf94f4d06f25e170d4737aea61bcb558 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 1 Jan 2025 16:56:11 +0800 Subject: [PATCH 07/18] :art: formating console3D test --- test/burningship.nas | 4 +- test/console3D.nas | 218 +++++++++++++++++++++++++------------------ 2 files changed, 130 insertions(+), 92 deletions(-) diff --git a/test/burningship.nas b/test/burningship.nas index 357b131..277396c 100644 --- a/test/burningship.nas +++ b/test/burningship.nas @@ -16,8 +16,8 @@ var ppm = func(filename, width, height, RGB) { io.close(fd); } -var width = 1920; -var height = 1080; +var width = 1920 * 2; +var height = 1080 * 2; var bar = (os.platform()=="windows")? process_bar.bar(front:"sharp", back:"point", sep:"line", length:50): process_bar.high_resolution_bar(50); diff --git a/test/console3D.nas b/test/console3D.nas index f4a2afa..abf4933 100644 --- a/test/console3D.nas +++ b/test/console3D.nas @@ -31,7 +31,8 @@ func() { runtime.gc.extend("vec", 8); }(); -var (max,min,sqrt,sin,cos,abs)=( +# alias +var (max, min, sqrt, sin, cos, abs) = ( math.max, math.min, math.sqrt, @@ -40,12 +41,12 @@ var (max,min,sqrt,sin,cos,abs)=( math.abs ); -var (vec2,vec3)=( +var (vec2, vec3) = ( libmat.vec2.new, libmat.vec3.new ); -var (vec2add,vec2sub,vec2mul,vec2div,vec2len)=( +var (vec2add, vec2sub, vec2mul, vec2div, vec2len) = ( libmat.vec2.add, libmat.vec2.sub, libmat.vec2.mul, @@ -53,7 +54,7 @@ var (vec2add,vec2sub,vec2mul,vec2div,vec2len)=( libmat.vec2.len ); -var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=( +var (vec3add, vec3sub, vec3mul, vec3div, vec3neg, vec3norm, vec3len, vec3dot) = ( libmat.vec3.add, libmat.vec3.sub, libmat.vec3.mul, @@ -64,116 +65,147 @@ var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=( libmat.vec3.dot ); -var (rotateX,rotateY,rotateZ)=( +var (rotateX, rotateY, rotateZ) = ( libmat.vec3.rx, libmat.vec3.ry, libmat.vec3.rz, ); var use_raw = func() { - vec2 = func(x,y) {return [x,y];} - vec2add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1]];} - vec2sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1]];} - vec2mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1]];} - vec2div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1]];} - vec3 = func(x,y,z) {return [x,y,z];} - vec3add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];} - vec3sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];} - vec3mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];} - vec3div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];} - vec3neg = func(v) {return [-v[0],-v[1],-v[2]];} + vec2 = func(x, y) {return [x,y];} + vec2add = func(v1, v2) {return [v1[0]+v2[0],v1[1]+v2[1]];} + vec2sub = func(v1, v2) {return [v1[0]-v2[0],v1[1]-v2[1]];} + vec2mul = func(v1, v2) {return [v1[0]*v2[0],v1[1]*v2[1]];} + vec2div = func(v1, v2) {return [v1[0]/v2[0],v1[1]/v2[1]];} vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);} + + vec3 = func(x, y, z) {return [x,y,z];} + vec3add = func(v1, v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];} + vec3sub = func(v1, v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];} + vec3mul = func(v1, v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];} + vec3div = func(v1, v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];} + vec3neg = func(v) {return [-v[0],-v[1],-v[2]];} vec3len = func(v) {var (x,y,z)=(v[0],v[1],v[2]); return sqrt(x*x+y*y+z*z);} vec3norm = func(v) {var t=vec3len(v); return vec3div(v,[t,t,t]);} - vec3dot = func(a,b) {return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];} - rotateX = func(a,angle) {return [a[0],a[2]*sin(angle)+a[1]*cos(angle),a[2]*cos(angle)-a[1]*sin(angle)];} - rotateY = func(a,angle) {return [a[0]*cos(angle)-a[2]*sin(angle),a[1],a[0]*sin(angle)+a[2]*cos(angle)];} - rotateZ = func(a,angle) {return [a[0]*cos(angle)-a[1]*sin(angle),a[0]*sin(angle)+a[1]*cos(angle),a[2]];} + vec3dot = func(a, b) { + return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; + } + + rotateX = func(a, angle) { + return [ + a[0], + a[2] * sin(angle) + a[1] * cos(angle), + a[2] * cos(angle) - a[1] * sin(angle) + ]; + } + rotateY = func(a, angle) { + return [ + a[0] * cos(angle) - a[2] * sin(angle), + a[1], + a[0] * sin(angle) + a[2] * cos(angle) + ]; + } + rotateZ = func(a, angle) { + return [ + a[0] * cos(angle) - a[1] * sin(angle), + a[0] * sin(angle) + a[1] * cos(angle), + a[2] + ]; + } } -var clamp = func(value,_min,_max) { - return max(min(value,_max),_min); +var clamp = func(value, _min, _max) { + return max(min(value, _max), _min); } var sign = func(a) { - return (0edge; +var step = func(edge, x) { + return x > edge; } var vec3abs = func(v) { - return [abs(v[0]),abs(v[1]),abs(v[2])]; + return [abs(v[0]), abs(v[1]), abs(v[2])]; } var vec3sign = func(v) { - return [sign(v[0]),sign(v[1]),sign(v[2])]; + return [sign(v[0]), sign(v[1]), sign(v[2])]; } -var vec3step = func(edge,v) { - return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])]; +var vec3step = func(edge, v) { + return [ + step(edge[0], v[0]), + step(edge[1], v[1]), + step(edge[2], v[2]) + ]; } -var vec3reflect = func(rd,n) { - var d=vec3dot(n,rd); - return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d]))); +var vec3reflect = func(rd, n) { + var d = vec3dot(n, rd); + return vec3sub(rd, vec3mul(n, vec3mul([2, 2, 2], [d, d, d]))); } -var sphere = func(ro,rd,r) { - var b=vec3dot(ro,rd); - var c=vec3dot(ro,ro)-r*r; - var h=b*b-c; - if (h<0.0) return [-1.0,-1.0]; - h=sqrt(h); - return [-b-h,-b+h]; +var sphere = func(ro, rd, r) { + var b = vec3dot(ro, rd); + var c = vec3dot(ro, ro) - r * r; + var h = b * b - c; + if (h < 0.0) + return [-1.0, -1.0]; + h = sqrt(h); + return [-b - h, -b + h]; } -var box = func(ro,rd,boxSize,outNormal) { - var m=vec3div([1.0,1.0,1.0],rd); - var n=vec3mul(m,ro); - var k=vec3mul(vec3abs(m),boxSize); - var t1=vec3sub(vec3neg(n),k); - var t2=vec3add(vec3neg(n),k); - var tN=max(max(t1[0],t1[1]),t1[2]); - var tF=min(min(t2[0],t2[1]),t2[2]); - if (tN>tF or tF<0.0) return [-1.0,-1.0]; - var yzx=[t1[1],t1[2],t1[0]]; - var zxy=[t1[2],t1[0],t1[1]]; - var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1)); - outNormal[0]=tmp[0]; - outNormal[1]=tmp[1]; - outNormal[2]=tmp[2]; +var box = func(ro, rd, boxSize, outNormal) { + var m = vec3div([1.0, 1.0, 1.0], rd); + var n = vec3mul(m, ro); + var k = vec3mul(vec3abs(m), boxSize); + var t1 = vec3sub(vec3neg(n), k); + var t2 = vec3add(vec3neg(n), k); + var tN = max(max(t1[0], t1[1]), t1[2]); + var tF = min(min(t2[0], t2[1]), t2[2]); + if (tN>tF or tF<0.0) + return [-1.0, -1.0]; + var yzx = [t1[1], t1[2], t1[0]]; + var zxy = [t1[2], t1[0], t1[1]]; + var tmp = vec3mul( + vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx, t1)), + vec3step(zxy, t1) + ); + outNormal[0] = tmp[0]; + outNormal[1] = tmp[1]; + outNormal[2] = tmp[2]; return [tN, tF]; } -var plane = func(ro,rd,p,w) { - return -(vec3dot(ro,p)+w)/vec3dot(rd,p); +var plane = func(ro, rd, p, w) { + return -(vec3dot(ro, p) + w) / vec3dot(rd, p); } var main = func(frame) { - var height=15*2; - var width=int(height*1/0.618)*2; + var height = 15*2; + var width = int(height*1/0.618)*2; - var aspect=width/height; - var pixelAspect=11.0/24.0; + var aspect = width/height; + var pixelAspect = 11.0/24.0; - var gradient=split(""," .:!/r(l1Z4H9W8$"); - var gradientSize=size(gradient)-1; + var gradient = split("", " .:!/r(l1Z4H9W8$"); + var gradientSize = size(gradient)-1; - var screen=[]; - setsize(screen,width*height); + var screen = []; + setsize(screen, width*height); - var light=vec3norm([-0.5,0.5,-1.0]); - var spherePos=[0,3,0]; - var vec2_2_2=[2,2]; - var vec2_1_1=[1,1]; - var vec3_000=[0,0,0]; - var vec3_00n1=[0,0,-1]; - var vec3_111=[1,1,1]; + var light = vec3norm([-0.5, 0.5, -1.0]); + var spherePos = [0, 3, 0]; + var vec2_2_2 = [2, 2]; + var vec2_1_1 = [1, 1]; + var vec3_000 = [0, 0, 0]; + var vec3_00n1 = [0, 0, -1]; + var vec3_111 = [1, 1, 1]; print("\e[2J"); - var stamp=maketimestamp(); - for(var t=0;t Date: Wed, 1 Jan 2025 18:28:58 +0800 Subject: [PATCH 08/18] :art: dump gc time occupation --- makefile | 10 +++++----- src/main.cpp | 9 ++++++++- src/nasal_gc.h | 6 ++++++ src/nasal_vm.cpp | 23 +++++++++++++++++------ src/nasal_vm.h | 4 ++++ std/argparse.nas | 2 +- std/lib.nas | 2 +- test/feigenbaum.nas | 19 +++++++++++-------- test/mandelbrot.nas | 31 ++++++++++++++++--------------- test/mandelbrotset.nas | 4 ++-- 10 files changed, 71 insertions(+), 39 deletions(-) diff --git a/makefile b/makefile index 4482512..fb2f959 100644 --- a/makefile +++ b/makefile @@ -333,10 +333,10 @@ test: @ ./nasal -t -d test/regex_test.nas @ ./nasal -t -d test/replace_test.nas @ ./nasal -e test/scalar.nas hello world - @ ./nasal test/subprocess_test.nas - @ ./nasal -e test/trait.nas + @ ./nasal -t test/subprocess_test.nas + @ ./nasal -t test/trait.nas @ ./nasal -t -d test/turingmachine.nas - @ ./nasal -d test/wavecollapse.nas - @ ./nasal -d test/wavecity.nas - @ ./nasal test/word_collector.nas test/md5compare.nas + @ ./nasal -t -d test/wavecollapse.nas + @ ./nasal -t -d test/wavecity.nas + @ ./nasal -t test/word_collector.nas test/md5compare.nas @ ./nasal -t -d test/ycombinator.nas diff --git a/src/main.cpp b/src/main.cpp index aac6c26..3e0a4ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -121,6 +121,7 @@ void execute(const nasal::cli::cli_config& config) { // run const auto start = clk::now(); + double gc_time_ms = 0.0; if (config.has(option::cli_debug_mode)) { auto debugger = std::make_unique(); debugger->run( @@ -130,6 +131,7 @@ void execute(const nasal::cli::cli_config& config) { config.has(option::cli_profile), config.has(option::cli_profile_all) ); + gc_time_ms = debugger->get_gc_time_ms(); } else if (config.has(option::cli_show_execute_time) || config.has(option::cli_detail_info) || config.has(option::cli_limit_mode) || @@ -138,13 +140,18 @@ void execute(const nasal::cli::cli_config& config) { runtime->set_detail_report_info(config.has(option::cli_detail_info)); runtime->set_limit_mode_flag(config.has(option::cli_limit_mode)); runtime->run(gen, ld, config.nasal_vm_args); + gc_time_ms = runtime->get_gc_time_ms(); } // get running time const auto end = clk::now(); if (config.has(option::cli_show_execute_time)) { + double execute_time_sec = static_cast((end - start).count())/den; + double gc_time_sec = gc_time_ms / 1000.0; std::clog << "process exited after "; - std::clog << static_cast((end-start).count())/den << "s.\n\n"; + std::clog << execute_time_sec << "s, gc time: "; + std::clog << gc_time_sec << "s ("; + std::clog << gc_time_sec / execute_time_sec * 100.0 << "%)\n\n"; } } diff --git a/src/nasal_gc.h b/src/nasal_gc.h index 5312d60..4827608 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -94,6 +94,12 @@ public: void context_change(nas_co*); void context_reserve(); +public: + double get_gc_time_ms() const { + const auto den = std::chrono::high_resolution_clock::duration::period::den; + return worktime * 1.0 / den * 1000.0; + } + public: var newstr(char c) { var s = alloc(vm_type::vm_str); diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 3a57ec4..c04c7ae 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -226,7 +226,7 @@ void vm::function_call_trace() { std::stack callsite; // load call trace - for(var* i = bottom; i<=top; ++i) { + for(var* i = bottom; i <= top; ++i) { // i-1 is the callsite program counter of this function if (i->is_addr() && i+2<=top && (i+1)->is_ret() && (i+1)->ret()>0 && @@ -238,7 +238,7 @@ void vm::function_call_trace() { // another condition may exist // have ret pc on stack, but no function at the top of the ret pc - for(var * i = top; i>=bottom; --i) { + for(var * i = top; i >= bottom; --i) { if ((i->is_addr() && i+2<=top && (i+1)->is_ret() && !(i+2)->is_func()) || (i->is_addr() && i+1<=top && i+2>top && (i+1)->is_ret())) { functions.push(&ctx.funcr.func()); @@ -254,7 +254,7 @@ void vm::function_call_trace() { std::clog << "\ncall trace "; std::clog << (ngc.cort? "(coroutine)":"(main)") << "\n"; - std::clog << " crash occurred in\n "; + std::clog << " crash occurred at\n "; function_detail_info(ctx.funcr.func()); std::clog << " at " << files[bytecode[ctx.pc].fidx] << ":"; std::clog << bytecode[ctx.pc].line << "\n"; @@ -325,7 +325,7 @@ void vm::trace_back() { // the first called place has no same calls } -void vm::stack_info(const u64 limit = 16) { +void vm::stack_info(const u64 limit) { var* top = ctx.top; var* bottom = ctx.stack; const auto stack_address = reinterpret_cast(bottom); @@ -525,8 +525,16 @@ std::string vm::type_name_string(const var& value) const { void vm::die(const std::string& str) { std::cerr << "[vm] error: " << str << "\n"; function_call_trace(); - trace_back(); - stack_info(); + + // trace back contains bytecode info, dump in verbose mode + if (verbose) { + trace_back(); + } + + // verbose will dump more values on stack + if (verbose) { + stack_info(64); + } // show verbose crash info if (verbose) { @@ -534,6 +542,9 @@ void vm::die(const std::string& str) { } if (!ngc.cort) { + if (!verbose) { + std::cerr << "\n[vm] use <-d> for detailed crash info.\n\n"; + } // in main context, exit directly std::exit(1); } diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 258c972..62c1f87 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -318,6 +318,10 @@ public: void set_limit_mode_flag(bool flag) { flag_limited_mode = flag; } + + auto get_gc_time_ms() const { + return ngc.get_gc_time_ms(); + } }; inline bool vm::boolify(const var& val) { diff --git a/std/argparse.nas b/std/argparse.nas index a183329..507b7a2 100644 --- a/std/argparse.nas +++ b/std/argparse.nas @@ -151,7 +151,7 @@ var _parse = func(parser, args, result_hash) { return; } -var _add_command = func(parser, long, short, help, need_arg , need_nargs) { +var _add_command = func(parser, long, short, help, need_arg, need_nargs) { var new_command = { full_name: long, short_name: short, diff --git a/std/lib.nas b/std/lib.nas index e4b556a..da1eec6 100644 --- a/std/lib.nas +++ b/std/lib.nas @@ -380,7 +380,7 @@ var bind = func(function, locals, outer_scope = nil) { die("this runtime does not support bind"); } -var call = func(function ,args = nil, _me = nil, locals = nil, error = nil) { +var call = func(function, args = nil, _me = nil, locals = nil, error = nil) { die("this runtime does not support call"); } diff --git a/test/feigenbaum.nas b/test/feigenbaum.nas index d56d315..811f135 100644 --- a/test/feigenbaum.nas +++ b/test/feigenbaum.nas @@ -16,25 +16,29 @@ var ppm = func(filename, width, height, RGB) { io.close(fd); } -var width = 1920; -var height = 1080; +var width = 1920 * 2; +var height = 1080 * 2; var bar = (os.platform()=="windows")? process_bar.bar(front:"sharp", back:"point", sep:"line", length:50): process_bar.high_resolution_bar(50); +var abs = math.abs; # alias var RGB = func(h, w) { var r = 2+w*2/width; var x = (height-h)/height; - var res = 0; + var (R, G, B) = (0, 0, 0); + var tmp = 0.5; for(var i = 0; i<50; i+=1) { tmp = r*tmp*(1-tmp); } - for(var i = 0; i<100; i+=1) { + for(var i = 0; i<150; i+=1) { tmp = r*tmp*(1-tmp); - if (math.abs(tmp-x)<0.001) { - res = 255; + if (abs(tmp-x)<0.0005) { + R = int(255*(150 - i)/150); + G = int(255*(150 - i)/150); + B = 255; break; } } @@ -44,8 +48,7 @@ var RGB = func(h, w) { print(bar.bar(progress), " ", progress*100, "% \r"); } - var c = char(res); - return c~c~c; + return char(R) ~ char(G) ~ char(B); } ppm("feigenbaum.ppm", width, height, RGB); diff --git a/test/mandelbrot.nas b/test/mandelbrot.nas index 59722e3..1e712d9 100644 --- a/test/mandelbrot.nas +++ b/test/mandelbrot.nas @@ -1,22 +1,23 @@ -var (yMin,yMax,xMin,xMax,line)=(-0.2,0.2,-1.5,-1.0,""); -var (yDel,xDel)=(yMax-yMin,xMax-xMin); -for(var yPixel=0;yPixel<24;yPixel+=1) { - var y=(yPixel/24)*yDel+yMin; - for(var xPixel=0;xPixel<80;xPixel+=1) { - var x=(xPixel/80)*xDel+xMin; - var pixel=" "; - var (x0,y0)=(x,y); - for(var iter=0;iter<80;iter+=1) { - var x1=(x0*x0)-(y0*y0)+x; - var y1=2*x0*y0+y; - (x0,y0)=(x1,y1); +var (yMin, yMax, xMin, xMax, line) = (-0.2, 0.2, -1.5, -1.0, ""); +var (yDel, xDel) = (yMax-yMin, xMax-xMin); +for(var yPixel = 0; yPixel < 24; yPixel += 1) { + var y = (yPixel/24)*yDel+yMin; + for(var xPixel = 0; xPixel < 80; xPixel += 1) { + var x = (xPixel/80)*xDel+xMin; + var pixel = " "; + var (x0, y0) = (x, y); + for(var iter = 0; iter < 100; iter += 1) { + var x1 = (x0*x0)-(y0*y0)+x; + var y1 = 2*x0*y0+y; + (x0, y0) = (x1, y1); if ((x0*x0)+(y0*y0)>4) { - pixel=chr(" .:;+=xX$&"[iter/8]); + pixel = chr(" .:;+=xX$&"[iter/8]); break; } } - line~=pixel; + line ~= pixel; } - line~='\n'; + line ~= '\n'; } + print(line); \ No newline at end of file diff --git a/test/mandelbrotset.nas b/test/mandelbrotset.nas index c4573bc..064d3c8 100644 --- a/test/mandelbrotset.nas +++ b/test/mandelbrotset.nas @@ -15,8 +15,8 @@ var ppm = func(filename, width, height, RGB) { io.close(fd); } -var width = 1920; -var height = 1080; +var width = 1920 * 2; +var height = 1080 * 2; var bar = (os.platform()=="windows")? process_bar.bar(front:"sharp", back:"point", sep:"line", length:50): process_bar.high_resolution_bar(50); From 030a3ad920a04425f99c3da48f29a1c1000b9270 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 1 Jan 2025 18:35:57 +0800 Subject: [PATCH 09/18] :memo: remove -fPIC if using MSVC --- CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 40d3f42..1cb6a3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,11 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall") -add_compile_options(-fPIC) +# MSVC does not need -fPIC +if (NOT MSVC) + add_compile_options(-fPIC) +endif() + # MSVC needs this command option to really enable utf-8 output if (MSVC) add_compile_options(/utf-8) @@ -19,9 +23,6 @@ if (APPLE) add_compile_options(-mmacosx-version-min=10.15) endif() -# generate release executables -set(CMAKE_BUILD_TYPE "Release") - # build nasal used object set(NASAL_OBJECT_SOURCE_FILE ${CMAKE_SOURCE_DIR}/src/cli/cli.cpp From 77ec4b0d7c8e554084b4db5ce168134de4cf327a Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 3 Jan 2025 01:03:13 +0800 Subject: [PATCH 10/18] :bug: add dylib find rule on mac --- src/nasal_type.cpp | 28 +++------------ src/nasal_type.h | 26 +++++++++++--- src/nasal_vm.h | 24 ++++++------- src/natives/dylib_lib.cpp | 71 +++++++++++++++++++++++++++------------ src/natives/dylib_lib.h | 2 ++ 5 files changed, 90 insertions(+), 61 deletions(-) diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 8a38b11..561f68c 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -6,22 +6,6 @@ namespace nasal { -var nas_vec::get_value(const i32 index) { - i32 size = elems.size(); - if (index<-size || index>=size) { - return var::none(); - } - return elems[index>=0? index:index+size]; -} - -var* nas_vec::get_memory(const i32 index) { - i32 size = elems.size(); - if (index<-size || index>=size) { - return nullptr; - } - return &elems[index>=0? index:index+size]; -} - std::ostream& operator<<(std::ostream& out, nas_vec& vec) { if (!vec.elems.size() || vec.printed) { out << (vec.elems.size()? "[..]":"[]"); @@ -40,7 +24,8 @@ std::ostream& operator<<(std::ostream& out, nas_vec& vec) { var nas_hash::get_value(const std::string& key) { if (elems.count(key)) { return elems.at(key); - } else if (!elems.count("parents")) { + } + if (!elems.count("parents")) { return var::none(); } @@ -63,7 +48,8 @@ var nas_hash::get_value(const std::string& key) { var* nas_hash::get_memory(const std::string& key) { if (elems.count(key)) { return &elems.at(key); - } else if (!elems.count("parents")) { + } + if (!elems.count("parents")) { return nullptr; } @@ -279,12 +265,6 @@ void nas_val::clear() { } } -f64 var::to_num() const { - return type != vm_type::vm_str - ? val.num - : util::str_to_num(str().c_str()); -} - std::string var::to_str() { if (type==vm_type::vm_str) { return str(); diff --git a/src/nasal_type.h b/src/nasal_type.h index 3c240d5..fb283ed 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -1,6 +1,7 @@ #pragma once #include "nasal.h" +#include "util/util.h" #include #include @@ -173,8 +174,13 @@ public: bool is_map() const { return type == vm_type::vm_map; } public: - // number and string can be translated to each other - f64 to_num() const; + // convert to number + f64 to_num() const { + return type != vm_type::vm_str + ? val.num + : util::str_to_num(str().c_str()); + } + // convert to string std::string to_str(); inline bool object_check(const std::string&) const; friend std::ostream& operator<<(std::ostream&, var&); @@ -187,8 +193,20 @@ struct nas_vec { bool printed = false; auto size() const { return elems.size(); } - var get_value(const i32); - var* get_memory(const i32); + var get_value(const i32 index) { + i32 size = elems.size(); + if (index < -size || index >= size) { + return var::none(); + } + return elems[index >= 0 ? index : index + size]; + } + var* get_memory(const i32 index) { + i32 size = elems.size(); + if (index < -size || index >= size) { + return nullptr; + } + return &elems[index >= 0 ? index : index + size]; + } friend std::ostream& operator<<(std::ostream&, nas_vec&); }; diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 62c1f87..312d031 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -97,6 +97,7 @@ protected: protected: /* vm calculation functions*/ inline bool boolify(const var&); + inline void set_frame(const nas_func&, var*); protected: /* vm operands */ @@ -342,6 +343,15 @@ inline bool vm::boolify(const var& val) { return false; } +inline void vm::set_frame(const nas_func& func, var* local) { + ctx.top[0] = ctx.upvalr; + (++ctx.top)[0] = var::addr(ctx.localr); + (++ctx.top)[0] = var::ret(ctx.pc); // rewrite top with vm_ret + ctx.pc = func.entry - 1; + ctx.localr = local; + ctx.upvalr = nil; +} + inline void vm::o_repl() { // reserved for repl mode stack top value output if (allow_repl_output) { @@ -935,12 +945,7 @@ inline void vm::o_callfv() { ? parameter_size + 1 : func.local_size - 1] = dynamic; - ctx.top[0] = ctx.upvalr; - (++ctx.top)[0] = var::addr(ctx.localr); - (++ctx.top)[0] = var::ret(ctx.pc); - ctx.pc = func.entry-1; - ctx.localr = local; - ctx.upvalr = nil; + set_frame(func, local); } inline void vm::o_callfh() { @@ -987,12 +992,7 @@ inline void vm::o_callfh() { return; } - ctx.top[0] = ctx.upvalr; - (++ctx.top)[0] = var::addr(ctx.localr); - (++ctx.top)[0] = var::ret(ctx.pc); // rewrite top with vm_ret - ctx.pc=func.entry-1; - ctx.localr = local; - ctx.upvalr = nil; + set_frame(func, local); } inline void vm::o_callb() { diff --git a/src/natives/dylib_lib.cpp b/src/natives/dylib_lib.cpp index d405974..61e1002 100644 --- a/src/natives/dylib_lib.cpp +++ b/src/natives/dylib_lib.cpp @@ -18,35 +18,64 @@ void dynamic_library_destructor(void* pointer) { #endif } +std::vector possible_dylib_path() { + const auto env_path = std::string(getenv("PATH")); + const auto sep = (util::is_windows()? ";":":"); + const auto path_front = util::is_windows()? "\\module\\":"/module/"; + + // do split string + std::vector env_path_vec = {"."}; + usize last = 0; + usize pos = env_path.find(sep, 0); + while(pos != std::string::npos) { + if (pos > last) { + env_path_vec.push_back(env_path.substr(last, pos - last)); + } + last = pos + 1; + pos = env_path.find(sep, last); + } + if (last != env_path.length()) { + env_path_vec.push_back(env_path.substr(last)); + } + + for (auto& p : env_path_vec) { + p += path_front; + } + + return env_path_vec; +} + std::string search_dynamic_library_path(const std::string& dlname) { const auto ext = (util::is_windows()? ".dll":".so"); const auto lib_path = (util::is_windows()? ".\\":"./") + dlname + ext; if (fs::exists(lib_path)) { return lib_path; } - const auto env_path = std::string(getenv("PATH")); - const auto sep = (util::is_windows()? ";":":"); - - // do split string - std::vector env_path_vec = {"."}; - usize last = 0; - usize pos = env_path.find(sep, 0); - while(pos!=std::string::npos) { - if (pos>last) { - env_path_vec.push_back(env_path.substr(last, pos-last)); + // macos may use .dylib as extension + if (util::is_macos()) { + const auto dylib_path = "./" + dlname + ".dylib"; + if (fs::exists(dylib_path)) { + return dylib_path; } - last = pos + 1; - pos = env_path.find(sep, last); - } - if (last!=env_path.length()) { - env_path_vec.push_back(env_path.substr(last)); } - const auto path_front = util::is_windows()? "\\module\\":"/module/"; - for(auto& p : env_path_vec) { - p += path_front + lib_path; - if (fs::exists(p)) { - return p; + // search library in PATH + const auto possible_path = possible_dylib_path(); + for(const auto& p : possible_path) { + const auto env_p = p + lib_path; + if (fs::exists(env_p)) { + return env_p; + } + } + + // macos may use .dylib as extension + if (util::is_macos()) { + const auto dylib_path = "./" + dlname + ".dylib"; + for(const auto& p : possible_path) { + const auto env_p = p + dylib_path; + if (fs::exists(env_p)) { + return env_p; + } } } return ""; @@ -61,7 +90,7 @@ var builtin_dlopen(context* ctx, gc* ngc) { const auto dlname = search_dynamic_library_path(dl.str()); if (dlname.empty()) { return nas_err("dylib::dlopen", - "cannot find dynamic lib <" + dl.str() + ">" + "cannot find dynamic library <" + dl.str() + ">" ); } diff --git a/src/natives/dylib_lib.h b/src/natives/dylib_lib.h index 67a9ef0..c4ae80f 100644 --- a/src/natives/dylib_lib.h +++ b/src/natives/dylib_lib.h @@ -13,11 +13,13 @@ #include #include +#include namespace nasal { void dynamic_library_destructor(void*); +std::vector possible_dylib_path(); std::string search_dynamic_library_path(const std::string&); var builtin_dlopen(context*, gc*); From dadc0afa35ce81402a4c8d8c7cf4bc59df20fdde Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 3 Jan 2025 01:07:46 +0800 Subject: [PATCH 11/18] :bug: fix build failure --- module/makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/makefile b/module/makefile index 981ab8c..2417329 100644 --- a/module/makefile +++ b/module/makefile @@ -24,45 +24,45 @@ winall: $(dynamic_libs_dll) libfib.so: fib.cpp $(used_header) $(used_object) @ echo "[Compiling] libfib.so" - @ $(CXX) $(CXXFLAGS) fib.cpp -o fib.o + @ $(CXX) $(CXXFLAGS) fib.cpp -o fib.o -I ../src @ $(CXX) -shared -o libfib.so fib.o $(used_object) @ rm fib.o libfib.dll: fib.cpp $(used_header) $(used_object) @ echo [Compiling] libfib.dll - @ $(CXX) -std=$(STD) -c -O3 fib.cpp -fPIC -o fib.o + @ $(CXX) -std=$(STD) -c -O3 fib.cpp -fPIC -o fib.o -I ../src @ $(CXX) -shared -o libfib.dll fib.o $(used_object) -static @ del fib.o libkey.so: keyboard.cpp $(used_header) $(used_object) @ echo "[Compiling] libkey.so" - @ $(CXX) $(CXXFLAGS) keyboard.cpp -o keyboard.o + @ $(CXX) $(CXXFLAGS) keyboard.cpp -o keyboard.o -I ../src @ $(CXX) -shared -o libkey.so keyboard.o $(used_object) @ rm keyboard.o libkey.dll: keyboard.cpp $(used_header) $(used_object) @ echo [Compiling] libkey.dll - @ $(CXX) -std=$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static + @ $(CXX) -std=$(STD) -c -O3 keyboard.cpp -fPIC -o keyboard.o -static -I ../src @ $(CXX) -shared -o libkey.dll keyboard.o $(used_object) -static @ del keyboard.o libnasock.so: nasocket.cpp $(used_header) $(used_object) @ echo "[Compiling] libnasock.so" - @ $(CXX) $(CXXFLAGS) nasocket.cpp -o nasocket.o + @ $(CXX) $(CXXFLAGS) nasocket.cpp -o nasocket.o -I ../src @ $(CXX) -shared -o libnasock.so nasocket.o $(used_object) @ rm nasocket.o libnasock.dll: nasocket.cpp $(used_header) $(used_object) @ echo [Compiling] libnasock.dll - @ $(CXX) -std=$(STD) -c -O3 nasocket.cpp -fPIC -o nasocket.o -lwsock32 -static + @ $(CXX) -std=$(STD) -c -O3 nasocket.cpp -fPIC -I ../src -o nasocket.o -lwsock32 -static @ $(CXX) -shared -o libnasock.dll nasocket.o $(used_object) -lwsock32 -static @ del nasocket.o libmat.so: matrix.cpp $(used_header) $(used_object) @ echo "[Compiling] libmat.so" - @ $(CXX) $(CXXFLAGS) matrix.cpp -o matrix.o + @ $(CXX) $(CXXFLAGS) matrix.cpp -o matrix.o -I ../src @ $(CXX) -shared -o libmat.so matrix.o $(used_object) @ rm matrix.o libmat.dll: matrix.cpp $(used_header) $(used_object) @ echo [Compiling] libmat.dll - @ $(CXX) -std=$(STD) -c -O3 matrix.cpp -fPIC -o matrix.o -static + @ $(CXX) -std=$(STD) -c -O3 matrix.cpp -fPIC -I ../src -o matrix.o -static @ $(CXX) -shared -o libmat.dll matrix.o $(used_object) -static @ del matrix.o From c228dcc149f72c120a316d7f69ee703a30334895 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 11 Jan 2025 17:51:34 +0800 Subject: [PATCH 12/18] :memo: change makefile --- module/makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/module/makefile b/module/makefile index 2417329..6445e8a 100644 --- a/module/makefile +++ b/module/makefile @@ -12,9 +12,9 @@ ifndef OS OS = $(shell uname) endif ifeq ($(OS), Darwin) - CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 + CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 -I ../src else - CXXFLAGS = -std=$(STD) -c -O3 -fPIC + CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I ../src endif all: $(dynamic_libs_so) @@ -24,7 +24,7 @@ winall: $(dynamic_libs_dll) libfib.so: fib.cpp $(used_header) $(used_object) @ echo "[Compiling] libfib.so" - @ $(CXX) $(CXXFLAGS) fib.cpp -o fib.o -I ../src + @ $(CXX) $(CXXFLAGS) fib.cpp -o fib.o @ $(CXX) -shared -o libfib.so fib.o $(used_object) @ rm fib.o libfib.dll: fib.cpp $(used_header) $(used_object) @@ -35,7 +35,7 @@ libfib.dll: fib.cpp $(used_header) $(used_object) libkey.so: keyboard.cpp $(used_header) $(used_object) @ echo "[Compiling] libkey.so" - @ $(CXX) $(CXXFLAGS) keyboard.cpp -o keyboard.o -I ../src + @ $(CXX) $(CXXFLAGS) keyboard.cpp -o keyboard.o @ $(CXX) -shared -o libkey.so keyboard.o $(used_object) @ rm keyboard.o libkey.dll: keyboard.cpp $(used_header) $(used_object) @@ -46,7 +46,7 @@ libkey.dll: keyboard.cpp $(used_header) $(used_object) libnasock.so: nasocket.cpp $(used_header) $(used_object) @ echo "[Compiling] libnasock.so" - @ $(CXX) $(CXXFLAGS) nasocket.cpp -o nasocket.o -I ../src + @ $(CXX) $(CXXFLAGS) nasocket.cpp -o nasocket.o @ $(CXX) -shared -o libnasock.so nasocket.o $(used_object) @ rm nasocket.o libnasock.dll: nasocket.cpp $(used_header) $(used_object) @@ -57,7 +57,7 @@ libnasock.dll: nasocket.cpp $(used_header) $(used_object) libmat.so: matrix.cpp $(used_header) $(used_object) @ echo "[Compiling] libmat.so" - @ $(CXX) $(CXXFLAGS) matrix.cpp -o matrix.o -I ../src + @ $(CXX) $(CXXFLAGS) matrix.cpp -o matrix.o @ $(CXX) -shared -o libmat.so matrix.o $(used_object) @ rm matrix.o libmat.dll: matrix.cpp $(used_header) $(used_object) From 277ddb9c0f44c24951b3e5f57002977e8c6caef6 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sat, 11 Jan 2025 21:06:57 +0800 Subject: [PATCH 13/18] :sparkles: add demo format executable --- .gitignore | 2 + CMakeLists.txt | 13 ++ src/ast_dumper.h | 2 +- src/ast_format.cpp | 412 +++++++++++++++++++++++++++++++++++++++++++++ src/ast_format.h | 144 ++++++++++++++++ src/cli/cli.cpp | 77 +++++++++ src/cli/cli.h | 5 + src/format.cpp | 56 ++++++ src/main.cpp | 55 +----- 9 files changed, 714 insertions(+), 52 deletions(-) create mode 100644 src/ast_format.cpp create mode 100644 src/ast_format.h create mode 100644 src/format.cpp diff --git a/.gitignore b/.gitignore index 76f7285..b3a00de 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,9 @@ cmake-windows-* *.out *.app nasal +nasal-format nasal.exe +nasal-format.exe # Visual Studio specific *.sln diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cb6a3f..a04118e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ set(NASAL_OBJECT_SOURCE_FILE ${CMAKE_SOURCE_DIR}/src/util/fs.cpp ${CMAKE_SOURCE_DIR}/src/util/util.cpp ${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp + ${CMAKE_SOURCE_DIR}/src/ast_format.cpp ${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp ${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp ${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp @@ -62,12 +63,18 @@ target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src) add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp) target_link_libraries(nasal nasal-object) +# build nasal-format +add_executable(nasal-format ${CMAKE_SOURCE_DIR}/src/format.cpp) +target_link_libraries(nasal-format nasal-object) + # link ldl and lpthread if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") target_link_libraries(nasal dl) target_link_libraries(nasal pthread) + target_link_libraries(nasal-format pthread) endif() target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src) +target_include_directories(nasal-format PRIVATE ${CMAKE_SOURCE_DIR}/src) # copy nasal from build dir to the outside dir if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") @@ -77,6 +84,12 @@ if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") ${CMAKE_SOURCE_DIR}/build/nasal ${CMAKE_SOURCE_DIR}/nasal ) + add_custom_command( + TARGET nasal-format POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/build/nasal-format + ${CMAKE_SOURCE_DIR}/nasal-format + ) endif() # build module diff --git a/src/ast_dumper.h b/src/ast_dumper.h index 1586d0b..e8c5565 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -38,7 +38,7 @@ private: if (indent.size() && indent.back()=="│ ") { indent.back() = "├──"; } - for(const auto& i : indent) { + for (const auto& i : indent) { std::cout << i; } } diff --git a/src/ast_format.cpp b/src/ast_format.cpp new file mode 100644 index 0000000..f50b822 --- /dev/null +++ b/src/ast_format.cpp @@ -0,0 +1,412 @@ +#include "ast_format.h" +#include "util/util.h" + +#include + +namespace nasal { + +bool ast_format::visit_use_stmt(use_stmt* node) { + dump_formating_node_info(node, "use statement"); + out << "use "; + for(auto i : node->get_path()) { + i->accept(this); + if (i != node->get_path().back()) { + out << "."; + } + } + return true; +} + +bool ast_format::visit_null_expr(null_expr* node) { + dump_formating_node_info(node, "null expression"); + out << "null"; + return true; +} + +bool ast_format::visit_nil_expr(nil_expr* node) { + dump_formating_node_info(node, "nil expression"); + out << "nil"; + return true; +} + +bool ast_format::visit_number_literal(number_literal* node) { + dump_formating_node_info(node, "number expression"); + out << node->get_number(); + return true; +} + +bool ast_format::visit_string_literal(string_literal* node) { + dump_formating_node_info(node, "string expression"); + out << "\"" << util::rawstr(node->get_content()) << "\""; + return true; +} + +bool ast_format::visit_identifier(identifier* node) { + dump_formating_node_info(node, "identifier"); + out << node->get_name(); + return true; +} + +bool ast_format::visit_bool_literal(bool_literal* node) { + dump_formating_node_info(node, "bool expression"); + out << (node->get_flag()? "true" : "false"); + return true; +} + +bool ast_format::visit_vector_expr(vector_expr* node) { + dump_formating_node_info(node, "vector expression"); + out << "["; + for(auto i : node->get_elements()) { + i->accept(this); + if (i != node->get_elements().back()) { + out << ", "; + } + } + out << "]"; + return true; +} + +bool ast_format::visit_hash_expr(hash_expr* node) { + dump_formating_node_info(node, "hash expression"); + out << "{"; + for(auto i : node->get_members()) { + i->accept(this); + if (i != node->get_members().back()) { + out << ", "; + } + } + out << "}"; + return true; +} + +bool ast_format::visit_hash_pair(hash_pair* node) { + dump_formating_node_info(node, "hash pair"); + out << node->get_name(); + if (node->get_value()) { + out << " : "; + node->get_value()->accept(this); + } + return true; +} + +bool ast_format::visit_function(function* node) { + dump_formating_node_info(node, "function"); + out << "func("; + for(auto i : node->get_parameter_list()) { + i->accept(this); + if (i != node->get_parameter_list().back()) { + out << ", "; + } + } + out << ") "; + node->get_code_block()->accept(this); + return true; +} + +bool ast_format::visit_code_block(code_block* node) { + dump_formating_node_info(node, "code block"); + out << "{\n"; + push_indent(); + for(auto i : node->get_expressions()) { + dump_indent(); + i->accept(this); + if (need_dump_semi(i)) { + out << ";\n"; + } else { + out << "\n"; + } + } + pop_indent(); + dump_indent(); + out << "}"; + return true; +} + +bool ast_format::visit_parameter(parameter* node) { + dump_formating_node_info(node, "parameter"); + out << node->get_parameter_name(); + switch (node->get_parameter_type()) { + case parameter::kind::normal_parameter: break; + case parameter::kind::dynamic_parameter: out << "..."; break; + case parameter::kind::default_parameter: out << " = "; break; + } + if (node->get_default_value()) { + node->get_default_value()->accept(this); + } + return true; +} + +bool ast_format::visit_ternary_operator(ternary_operator* node) { + dump_formating_node_info(node, "ternary operator"); + node->get_condition()->accept(this); + out << " ? "; + node->get_left()->accept(this); + out << " : "; + node->get_right()->accept(this); + return true; +} + +bool ast_format::visit_binary_operator(binary_operator* node) { + dump_formating_node_info(node, "binary operator"); + out << "("; + node->get_left()->accept(this); + switch(node->get_operator_type()) { + case binary_operator::kind::add: out << " + "; break; + case binary_operator::kind::sub: out << " - "; break; + case binary_operator::kind::mult: out << " * "; break; + case binary_operator::kind::div: out << " / "; break; + case binary_operator::kind::concat: out << " ~ "; break; + case binary_operator::kind::bitwise_and: out << " & "; break; + case binary_operator::kind::bitwise_or: out << " | "; break; + case binary_operator::kind::bitwise_xor: out << " ^ "; break; + case binary_operator::kind::cmpeq: out << " == "; break; + case binary_operator::kind::cmpneq: out << " != "; break; + case binary_operator::kind::grt: out << " > "; break; + case binary_operator::kind::geq: out << " >= "; break; + case binary_operator::kind::less: out << " < "; break; + case binary_operator::kind::leq: out << " <= "; break; + case binary_operator::kind::condition_and: out << " and "; break; + case binary_operator::kind::condition_or: out << " or "; break; + case binary_operator::kind::null_chain: out << " ?? "; break; + } + node->get_right()->accept(this); + out << ")"; + return true; +} + +bool ast_format::visit_unary_operator(unary_operator* node) { + dump_formating_node_info(node, "unary operator"); + switch(node->get_operator_type()) { + case unary_operator::kind::negative: out << "-"; break; + case unary_operator::kind::logical_not: out << "!"; break; + case unary_operator::kind::bitwise_not: out << "~"; break; + } + node->get_value()->accept(this); + return true; +} + +bool ast_format::visit_call_expr(call_expr* node) { + dump_formating_node_info(node, "call expression"); + node->get_first()->accept(this); + for(auto i : node->get_calls()) { + i->accept(this); + } + return true; +} + +bool ast_format::visit_call_hash(call_hash* node) { + dump_formating_node_info(node, "call hash"); + out << "." << node->get_field(); + return true; +} + +bool ast_format::visit_null_access(null_access* node) { + dump_formating_node_info(node, "null access operator(?.)"); + out << "?." << node->get_field(); + return true; +} + +bool ast_format::visit_call_vector(call_vector* node) { + dump_formating_node_info(node, "call vector"); + out << "["; + for(auto i : node->get_slices()) { + i->accept(this); + if (i != node->get_slices().back()) { + out << ", "; + } + } + out << "]"; + return true; +} + +bool ast_format::visit_call_function(call_function* node) { + dump_formating_node_info(node, "call function"); + out << "("; + for(auto i : node->get_argument()) { + i->accept(this); + if (i != node->get_argument().back()) { + out << ", "; + } + } + out << ")"; + return true; +} + +bool ast_format::visit_slice_vector(slice_vector* node) { + dump_formating_node_info(node, "slice vector"); + node->get_begin()->accept(this); + if (node->get_end()) { + out << " : "; + node->get_end()->accept(this); + } + return true; +} + +bool ast_format::visit_definition_expr(definition_expr* node) { + dump_formating_node_info(node, "definition"); + out << "var "; + if (node->get_variable_name()) { + node->get_variable_name()->accept(this); + } else { + node->get_variables()->accept(this); + } + out << " = "; + if (node->get_tuple()) { + node->get_tuple()->accept(this); + } else { + node->get_value()->accept(this); + } + return true; +} + +bool ast_format::visit_assignment_expr(assignment_expr* node) { + dump_formating_node_info(node, "assignment"); + node->get_left()->accept(this); + switch(node->get_assignment_type()) { + case assignment_expr::kind::add_equal: out << " += "; break; + case assignment_expr::kind::sub_equal: out << " -= "; break; + case assignment_expr::kind::mult_equal: out << " *= "; break; + case assignment_expr::kind::div_equal: out << " /= "; break; + case assignment_expr::kind::concat_equal: out << " ~= "; break; + case assignment_expr::kind::equal: out << " = "; break; + case assignment_expr::kind::bitwise_and_equal: out << " &= "; break; + case assignment_expr::kind::bitwise_or_equal: out << " |= "; break; + case assignment_expr::kind::bitwise_xor_equal: out << " ^= "; break; + } + node->get_right()->accept(this); + return true; +} + +bool ast_format::visit_multi_identifier(multi_identifier* node) { + dump_formating_node_info(node, "multi identifier"); + out << "("; + for(auto i : node->get_variables()) { + i->accept(this); + if (i != node->get_variables().back()) { + out << ", "; + } + } + out << ")"; + return true; +} + +bool ast_format::visit_tuple_expr(tuple_expr* node) { + dump_formating_node_info(node, "tuple expression"); + out << "("; + for(auto i : node->get_elements()) { + i->accept(this); + if (i != node->get_elements().back()) { + out << ", "; + } + } + out << ")"; + return true; +} + +bool ast_format::visit_multi_assign(multi_assign* node) { + dump_formating_node_info(node, "multi assign"); + node->get_tuple()->accept(this); + out << " = "; + node->get_value()->accept(this); + return true; +} + +bool ast_format::visit_while_expr(while_expr* node) { + dump_formating_node_info(node, "while statement"); + out << "while ("; + node->get_condition()->accept(this); + out << ") "; + node->get_code_block()->accept(this); + return true; +} + +bool ast_format::visit_for_expr(for_expr* node) { + dump_formating_node_info(node, "for statement"); + out << "for ("; + node->get_initial()->accept(this); + out << "; "; + node->get_condition()->accept(this); + out << "; "; + node->get_step()->accept(this); + out << ") "; + node->get_code_block()->accept(this); + return true; +} + +bool ast_format::visit_iter_expr(iter_expr* node) { + dump_formating_node_info(node, "iteration expression"); + if (node->is_definition()) { + out << "var "; + } + if (node->get_name()) { + node->get_name()->accept(this); + } else { + node->get_call()->accept(this); + } + return true; +} + +bool ast_format::visit_forei_expr(forei_expr* node) { + dump_formating_node_info(node, "forindex/foreach statement"); + if (node->get_loop_type()==forei_expr::kind::foreach) { + out << "foreach "; + } else { + out << "forindex "; + } + out << "("; + node->get_iterator()->accept(this); + out << "; "; + node->get_value()->accept(this); + out << ") "; + node->get_code_block()->accept(this); + return true; +} + +bool ast_format::visit_condition_expr(condition_expr* node) { + dump_formating_node_info(node, "condition statement"); + out << "if "; + node->get_if_statement()->accept(this); + for (auto i : node->get_elsif_stataments()) { + out << " elsif "; + i->accept(this); + } + if (node->get_else_statement()) { + out << " else "; + node->get_else_statement()->accept(this); + } + return true; +} + +bool ast_format::visit_if_expr(if_expr* node) { + dump_formating_node_info(node, "if statement"); + if (node->get_condition()) { + out << "("; + node->get_condition()->accept(this); + out << ") "; + } + node->get_code_block()->accept(this); + return true; +} + +bool ast_format::visit_continue_expr(continue_expr* node) { + dump_formating_node_info(node, "continue statement"); + out << "continue"; + return true; +} + +bool ast_format::visit_break_expr(break_expr* node) { + dump_formating_node_info(node, "break statement"); + out << "break"; + return true; +} + +bool ast_format::visit_return_expr(return_expr* node) { + dump_formating_node_info(node, "return statement"); + out << "return "; + if (node->get_value()) { + node->get_value()->accept(this); + } + return true; +} + +} diff --git a/src/ast_format.h b/src/ast_format.h new file mode 100644 index 0000000..8f3b23c --- /dev/null +++ b/src/ast_format.h @@ -0,0 +1,144 @@ +#pragma once + +#include "ast_visitor.h" + +#include +#include +#include +#include +#include +#include + +namespace nasal { + +class ast_format: public ast_visitor { +private: + std::ofstream out; + std::vector indent; + +private: + void push_indent() { + indent.push_back(" "); + } + void pop_indent() { + if (indent.size()) { + indent.pop_back(); + } + } + void dump_indent() { + for (const auto& i : indent) { + out << i; + } + } + void dump_formating_node_info(expr* n, const char* name) { + std::cout << " formating " << name << " @ 0x"; + std::cout << std::hex << n << std::dec << "\n"; + } + bool need_dump_semi(expr* n) { + switch (n->get_type()) { + case expr_type::ast_use: + case expr_type::ast_null: + case expr_type::ast_nil: + case expr_type::ast_num: + case expr_type::ast_str: + case expr_type::ast_bool: + case expr_type::ast_vec: + case expr_type::ast_hash: + case expr_type::ast_call: return true; + case expr_type::ast_def: { + auto dn = reinterpret_cast(n); + if (dn->get_value() && + dn->get_value()->get_type() == expr_type::ast_func) { + return false; + } + return true; + } + case expr_type::ast_assign: { + auto dn = reinterpret_cast(n); + if (dn->get_right() && + dn->get_right()->get_type() == expr_type::ast_func) { + return false; + } + return true; + } + case expr_type::ast_ret: { + auto dn = reinterpret_cast(n); + if (dn->get_value() && + dn->get_value()->get_type() == expr_type::ast_func) { + return false; + } + return true; + } + default: break; + } + + return false; + } + +public: + bool visit_use_stmt(use_stmt*) override; + bool visit_null_expr(null_expr*) override; + bool visit_nil_expr(nil_expr*) override; + bool visit_number_literal(number_literal*) override; + bool visit_string_literal(string_literal*) override; + bool visit_identifier(identifier*) override; + bool visit_bool_literal(bool_literal*) override; + bool visit_vector_expr(vector_expr*) override; + bool visit_hash_expr(hash_expr*) override; + bool visit_hash_pair(hash_pair*) override; + bool visit_function(function*) override; + bool visit_code_block(code_block*) override; + bool visit_parameter(parameter*) override; + bool visit_ternary_operator(ternary_operator*) override; + bool visit_binary_operator(binary_operator*) override; + bool visit_unary_operator(unary_operator*) override; + bool visit_call_expr(call_expr*) override; + bool visit_call_hash(call_hash*) override; + bool visit_null_access(null_access*) override; + bool visit_call_vector(call_vector*) override; + bool visit_call_function(call_function*) override; + bool visit_slice_vector(slice_vector*) override; + bool visit_definition_expr(definition_expr*) override; + bool visit_assignment_expr(assignment_expr*) override; + bool visit_multi_identifier(multi_identifier*) override; + bool visit_tuple_expr(tuple_expr*) override; + bool visit_multi_assign(multi_assign*) override; + bool visit_while_expr(while_expr*) override; + bool visit_for_expr(for_expr*) override; + bool visit_iter_expr(iter_expr*) override; + bool visit_forei_expr(forei_expr*) override; + bool visit_condition_expr(condition_expr*) override; + bool visit_if_expr(if_expr*) override; + bool visit_continue_expr(continue_expr*) override; + bool visit_break_expr(break_expr*) override; + bool visit_return_expr(return_expr*) override; + +public: + ast_format(const std::string output_file): out(output_file) { + if (out.fail()) { + throw std::runtime_error("can't open file: " + output_file); + } + } + + void do_format(code_block* root) { + std::cout << "nasal-format is not stable right now, "; + std::cout << "take care of source code!\n"; + dump_formating_node_info(root, "program root"); + bool is_use_statement = true; + for (auto i : root->get_expressions()) { + if (is_use_statement && i->get_type() != expr_type::ast_use) { + is_use_statement = false; + out << "\n"; + } + + i->accept(this); + if (need_dump_semi(i)) { + out << ";\n"; + } else { + out << "\n"; + } + } + } +}; + +} diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 8605fa1..9961467 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1,6 +1,12 @@ +#include "nasal.h" #include "cli/cli.h" +#include "util/util.h" +#include "nasal_parse.h" #include +#include +#include +#include namespace nasal::cli { @@ -59,4 +65,75 @@ std::ostream& help(std::ostream& out) { return out; } +std::ostream& nasal_format_help(std::ostream& out) { + out + << "\n" + << " ,--#-,\n" + << "<3 / \\____\\ <3\n" + << " |_|__A_|\n" + << "\nnasal-format