From 96731d180febf52bd1311af90810e8d88ef77433 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 12 May 2024 22:33:51 +0800 Subject: [PATCH] :sparkles: append code size from u32 to u64 --- makefile | 2 +- src/ast_dumper.h | 4 +- src/main.cpp | 6 +- src/nasal_codegen.cpp | 50 +++++---- src/nasal_codegen.h | 19 ++-- src/nasal_dbg.cpp | 30 +++--- src/nasal_gc.cpp | 15 ++- src/nasal_gc.h | 2 +- src/nasal_opcode.cpp | 11 +- src/nasal_opcode.h | 189 +++++++++++++++++----------------- src/nasal_type.cpp | 8 +- src/nasal_type.h | 18 ++-- src/nasal_vm.cpp | 26 +++-- src/nasal_vm.h | 47 ++++----- src/natives/nasal_builtin.cpp | 50 ++++++--- 15 files changed, 252 insertions(+), 225 deletions(-) diff --git a/makefile b/makefile index 7bbc56c..aae7741 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,7 @@ endif ifeq ($(OS), Darwin) CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 -I src else - CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src + CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src -Wconversion -Wno-float-conversion endif NASAL_HEADER = \ diff --git a/src/ast_dumper.h b/src/ast_dumper.h index 2049044..c762f79 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -9,9 +9,11 @@ namespace nasal { -class ast_dumper:public ast_visitor { +class ast_dumper: public ast_visitor { private: std::vector indent; + +private: void push_indent() { if (indent.size()) { if (indent.back()=="|--") { diff --git a/src/main.cpp b/src/main.cpp index 40223ec..42d12f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,7 +95,8 @@ std::ostream& logo(std::ostream& out) { } std::ostream& version(std::ostream& out) { - std::srand(std::time(nullptr)); + std::srand(static_cast(std::time(nullptr))); + f64 num = 0; for(u32 i = 0; i<5; ++i) { num = (num+rand())*(1.0/(RAND_MAX+1.0)); @@ -103,6 +104,7 @@ std::ostream& version(std::ostream& out) { if (num<0.01) { nasal::parse::easter_egg(); } + out << "nasal interpreter version " << __nasver__; out << " " << nasal::get_platform() << " " << nasal::get_arch(); out << " (" << __DATE__ << " " << __TIME__ << ")\n"; @@ -181,7 +183,7 @@ void execute(const std::string& file, const auto end = clk::now(); if (cmd&VM_TIME) { std::clog << "process exited after "; - std::clog << (end-start).count()*1.0/den << "s.\n\n"; + std::clog << static_cast((end-start).count())/den << "s.\n\n"; } } diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index cfc84ab..81ec3ae 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -70,7 +70,8 @@ void codegen::regist_number(const f64 num) { if (const_number_map.count(num)) { return; } - u32 size = const_number_map.size(); + + auto size = const_number_map.size(); const_number_map[num] = size; const_number_table.push_back(num); } @@ -79,7 +80,8 @@ void codegen::regist_string(const std::string& str) { if (const_string_map.count(str)) { return; } - u32 size = const_string_map.size(); + + auto size = const_string_map.size(); const_string_map[str] = size; const_string_table.push_back(str); } @@ -107,18 +109,20 @@ void codegen::find_symbol(code_block* node) { } void codegen::regist_symbol(const std::string& name) { + // regist global if local scope list is empty if (local.empty()) { if (global.count(name)) { return; } - i32 index = global.size(); + auto index = global.size(); global[name] = index; return; } + if (local.back().count(name)) { return; } - i32 index = local.back().size(); + auto index = local.back().size(); local.back()[name] = index; } @@ -149,7 +153,7 @@ i32 codegen::upvalue_symbol_find(const std::string& name) { return index; } -void codegen::emit(u8 operation_code, u32 immediate_num, const span& location) { +void codegen::emit(u8 operation_code, u64 immediate_num, const span& location) { code.push_back({ operation_code, static_cast(file_map.at(location.file)), @@ -505,7 +509,7 @@ void codegen::single_def(definition_expr* node) { const auto& str = node->get_variable_name()->get_name(); calc_gen(node->get_value()); // only generate in repl mode and in global scope - if (need_repl_output && local.empty()) { + if (flag_need_repl_output && local.empty()) { emit(op_repl, 0, node->get_location()); } if (local.empty()) { @@ -752,16 +756,16 @@ void codegen::multi_assign_gen(multi_assign* node) { } } - i32 size = tuple_node->get_elements().size(); + i64 size = static_cast(tuple_node->get_elements().size()); // generate multiple assignment: (a, b, c) = (1, 2, 3); if (value_node->get_type()==expr_type::ast_tuple) { const auto& value_tuple = reinterpret_cast(value_node) ->get_elements(); - for(i32 i = size-1; i>=0; --i) { + for(i64 i = size-1; i>=0; --i) { calc_gen(value_tuple[i]); } auto& tuple = tuple_node->get_elements(); - for(i32 i = 0; iget_elements(); - for(i32 i = 0; iget_location()); mcall(tuple[i]); // use load operands to avoid meq's pop operand // and this operation changes local and global value directly replace_left_assignment_with_load(tuple[i]->get_location()); } + // pop source vector emit(op_pop, 0, node->get_location()); } @@ -834,7 +839,7 @@ void codegen::loop_gen(expr* node) { } } -void codegen::load_continue_break(i32 continue_place, i32 break_place) { +void codegen::load_continue_break(u64 continue_place, u64 break_place) { for(auto i : continue_ptr.front()) { code[i].num = continue_place; } @@ -943,7 +948,7 @@ void codegen::statement_generation(expr* node) { case expr_type::ast_ternary: calc_gen(node); // only generate in repl mode and in global scope - if (need_repl_output && local.empty()) { + if (flag_need_repl_output && local.empty()) { emit(op_repl, 0, node->get_location()); } emit(op_pop, 0, node->get_location()); @@ -1254,7 +1259,7 @@ void codegen::block_gen(code_block* node) { break; case expr_type::ast_null: break; case expr_type::ast_id: - if (need_repl_output && local.empty()) { + if (flag_need_repl_output && local.empty()) { repl_mode_info_output_gen(tmp); } else { check_id_exist(reinterpret_cast(tmp)); @@ -1264,7 +1269,7 @@ void codegen::block_gen(code_block* node) { case expr_type::ast_num: case expr_type::ast_str: case expr_type::ast_bool: - if (need_repl_output && local.empty()) { + if (flag_need_repl_output && local.empty()) { repl_mode_info_output_gen(tmp); } break; @@ -1313,7 +1318,7 @@ const error& codegen::compile(parse& parse, linker& import, bool repl_flag, bool limit_mode) { - need_repl_output = repl_flag; + flag_need_repl_output = repl_flag; flag_limited_mode = limit_mode; init_native_function(); init_file_map(import.get_file_list()); @@ -1334,13 +1339,13 @@ const error& codegen::compile(parse& parse, emit(op_exit, 0, parse.tree()->get_location()); // size out of bound check - if (const_number_table.size()>0xffffff) { + if (const_number_table.size()>INT64_MAX) { err.err("code", "too many constant numbers: " + std::to_string(const_number_table.size()) ); } - if (const_string_table.size()>0xffffff) { + if (const_string_table.size()>INT64_MAX) { err.err("code", "too many constant strings: " + std::to_string(const_string_table.size()) @@ -1356,7 +1361,7 @@ const error& codegen::compile(parse& parse, } // check generated code size - if (code.size()>0xffffff) { + if (code.size()>INT64_MAX) { err.err("code", "bytecode size overflow: " + std::to_string(code.size()) @@ -1367,8 +1372,8 @@ const error& codegen::compile(parse& parse, void codegen::print(std::ostream& out) { // func end stack, reserved for code print - std::stack func_begin_stack; - std::stack func_end_stack; + std::stack func_begin_stack; + std::stack func_end_stack; // print const numbers for(auto num : const_number_table) { @@ -1391,7 +1396,8 @@ void codegen::print(std::ostream& out) { const_string_table.data(), native_function.data() ); - for(u32 i = 0; i:\n"; - for(u32 j = i; j unsafe_system_api = { // builtin @@ -67,8 +68,8 @@ private: std::vector in_foreach_loop_level; // constant numbers and strings - std::unordered_map const_number_map; - std::unordered_map const_string_map; + std::unordered_map const_number_map; + std::unordered_map const_string_map; std::vector const_number_table; std::vector const_string_table; @@ -82,17 +83,17 @@ private: std::vector code; // used to store jmp operands index, to fill the jump address back - std::list> continue_ptr; - std::list> break_ptr; + std::list> continue_ptr; + std::list> break_ptr; // symbol table // global : max STACK_DEPTH-1 values - std::unordered_map global; + std::unordered_map global; std::unordered_map> experimental_namespace; // local : max 32768 upvalues 65536 values // but in fact local scope also has less than STACK_DEPTH value - std::list> local; + std::list> local; void check_id_exist(identifier*); @@ -108,7 +109,7 @@ private: i32 global_symbol_find(const std::string&); i32 upvalue_symbol_find(const std::string&); - void emit(u8, u32, const span&); + void emit(u8, u64, const span&); void number_gen(number_literal*); void string_gen(string_literal*); @@ -135,7 +136,7 @@ private: void multi_assign_gen(multi_assign*); void cond_gen(condition_expr*); void loop_gen(expr*); - void load_continue_break(i32, i32); + void load_continue_break(u64, u64); void while_gen(while_expr*); void for_gen(for_expr*); void forei_gen(forei_expr*); diff --git a/src/nasal_dbg.cpp b/src/nasal_dbg.cpp index 0975d3b..c835817 100644 --- a/src/nasal_dbg.cpp +++ b/src/nasal_dbg.cpp @@ -147,12 +147,14 @@ void dbg::list_file() const { } void dbg::step_info() { - u32 line = bytecode[ctx.pc].line==0? 0:bytecode[ctx.pc].line-1; - u32 begin = (line>>3)==0? 0:((line>>3)<<3); - u32 end = (1+(line>>3))<<3; + u64 line = bytecode[ctx.pc].line==0? 0:bytecode[ctx.pc].line-1; + u64 begin = (line>>3)==0? 0:((line>>3)<<3); + u64 end = (1+(line>>3))<<3; + src.load(files[bytecode[ctx.pc].fidx]); + std::clog << "\nsource code:\n"; - for(u32 i = begin; i ":" ") << src[i] << reset << "\n"; } @@ -160,8 +162,9 @@ void dbg::step_info() { begin = (ctx.pc>>3)==0? 0:((ctx.pc>>3)<<3); end = (1+(ctx.pc>>3))<<3; codestream::set(const_number, const_string, native_function.data(), files); + std::clog << "\nnext bytecode:\n"; - for(u32 i = begin; i ":" ") @@ -234,19 +237,18 @@ void dbg::interact() { } } -void dbg::run( - const codegen& gen, - const linker& linker, - const std::vector& argv, - bool profile, - bool show_all_prof_result) { +void dbg::run(const codegen& gen, + const linker& linker, + const std::vector& argv, + bool profile, + bool show_all_prof_result) { set_detail_report_info(true); do_operand_count = profile || show_all_prof_result; const auto& file_list = linker.get_file_list(); fsize = file_list.size(); - init( + vm_init_enrty( gen.strs(), gen.nums(), gen.natives(), @@ -257,9 +259,9 @@ void dbg::run( ); counter.init(file_list); - std::vector code; + std::vector code; std::vector code_file_index; - std::vector code_line; + std::vector code_line; for(const auto& i : gen.codes()) { code.push_back(i.op); code_file_index.push_back(i.fidx); diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index 215c08a..bbbf3b0 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -189,7 +189,7 @@ void gc::extend(const vm_type type) { const u8 index = static_cast(type)-static_cast(vm_type::vm_str); size[index] += incr[index]; - for(u32 i = 0; i& constant_strings, - const std::vector& argv -) { +void gc::init(const std::vector& constant_strings, + const std::vector& argv) { // initialize counters worktime = 0; for(u8 i = 0; i(gcnt[i]); std::clog << " " << left << setw(indent) << setfill(' ') << name[i]; std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i]; std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i]; diff --git a/src/nasal_gc.h b/src/nasal_gc.h index 63df51a..daf5fa9 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -41,7 +41,7 @@ struct gc { std::vector unused[gc_type_size]; // gc free list /* heap increase size */ - u32 incr[gc_type_size] = { + u64 incr[gc_type_size] = { 128, // vm_str 128, // vm_vec 64, // vm_hash diff --git a/src/nasal_opcode.cpp b/src/nasal_opcode.cpp index 6b8a36c..1678a20 100644 --- a/src/nasal_opcode.cpp +++ b/src/nasal_opcode.cpp @@ -27,11 +27,10 @@ const char* opname[] = { "mcallv", "mcallh", "ret " }; -void codestream::set( - const f64* number_list, - const std::string* string_list, - const nasal_builtin_table* native_table, - const std::string* file_list) { +void codestream::set(const f64* number_list, + const std::string* string_list, + const nasal_builtin_table* native_table, + const std::string* file_list) { const_number = number_list; const_string = string_list; natives = native_table; @@ -110,6 +109,8 @@ void codestream::dump(std::ostream& out) const { } break; } + + // if file list is loaded, dump file location info if (files) { out << " (" << files[code.fidx] << ":" << code.line << ")"; } diff --git a/src/nasal_opcode.h b/src/nasal_opcode.h index 9a3b835..ace9497 100644 --- a/src/nasal_opcode.h +++ b/src/nasal_opcode.h @@ -8,99 +8,99 @@ namespace nasal { enum op_code_type: u8 { - op_exit, // stop the virtual machine - op_repl, // in repl mode: print value on stack top - op_intl, // local scope size - op_loadg, // load global value - op_loadl, // load local value - op_loadu, // load upvalue - op_pnum, // push constant number to the stack - op_pnil, // push constant nil to the stack - op_pstr, // push constant std::string to the stack - op_newv, // push new vector with initial values from stack - op_newh, // push new hash to the stack - op_newf, // push new function to the stack - op_happ, // hash append - op_para, // normal parameter - op_deft, // default parameter - op_dyn, // dynamic parameter - op_lnot, // ! logical negation - op_usub, // - negation - op_bnot, // ~ bitwise not static_cast - op_btor, // | bitwise or - op_btxor, // ^ bitwise xor - op_btand, // & bitwise and - op_add, // + - op_sub, // - - op_mul, // * - op_div, // / - op_lnk, // ~ - op_addc, // + const - op_subc, // - const - op_mulc, // * const - op_divc, // / const - op_lnkc, // ~ const - op_addeq, // += maybe pop stack top - op_subeq, // -= maybe pop stack top - op_muleq, // *= maybe pop stack top - op_diveq, // /= maybe pop stack top - op_lnkeq, // ~= maybe pop stack top - op_btandeq,// &= maybe pop stack top - op_btoreq, // |= maybe pop stack top - op_btxoreq,// ^= maybe pop stack top - op_addeqc, // += const don't pop stack top - op_subeqc, // -= const don't pop stack top - op_muleqc, // *= const don't pop stack top - op_diveqc, // /= const don't pop stack top - op_lnkeqc, // ~= const don't pop stack top - op_addecp, // += const and pop stack top - op_subecp, // -= const and pop stack top - op_mulecp, // *= const and pop stack top - op_divecp, // /= const and pop stack top - op_lnkecp, // ~= concat const std::string and pop stack top - op_meq, // = maybe pop stack top - op_eq, // == compare operator - op_neq, // != compare operator - op_less, // < compare operator - op_leq, // <= compare operator - op_grt, // > compare operator - op_geq, // >= compare operator - op_lessc, // < const compare operator - op_leqc, // <= const compare operator - op_grtc, // > const compare operator - op_geqc, // >= const compare operator - op_pop, // pop a value out of stack top - op_jmp, // jump absolute address with no condition - op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP - op_jf, // used in conditional/loop,jmp when condition is false and POP STACK - op_cnt, // add counter for forindex/foreach - op_findex, // index counter on the top of forindex_stack plus 1 - op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector - op_callg, // get value in global scope - op_calll, // get value in local scope - op_upval, // get value in closure, high 16 as the index of upval, low 16 as the index of local - op_callv, // call vec[index] - op_callvi, // call vec[immediate] (used in multi-assign/multi-define) - op_callh, // call hash.label - op_callfv, // call function(vector as parameters) - op_callfh, // call function(hash as parameters) - op_callb, // call native functions - op_slcbeg, // begin of slice like: vec[1, 2, 3:6, 0, -1] - op_slcend, // end of slice - op_slc, // slice like vec[1] - op_slc2, // slice like vec[nil:10] - op_mcallg, // get memory space of value in global scope - op_mcalll, // get memory space of value in local scope - op_mupval, // get memory space of value in closure - op_mcallv, // get memory space of vec[index] - op_mcallh, // get memory space of hash.label - op_ret // return + op_exit, // stop the virtual machine + op_repl, // in repl mode: print value on stack top + op_intl, // local scope size + op_loadg, // load global value + op_loadl, // load local value + op_loadu, // load upvalue + op_pnum, // push constant number to the stack + op_pnil, // push constant nil to the stack + op_pstr, // push constant std::string to the stack + op_newv, // push new vector with initial values from stack + op_newh, // push new hash to the stack + op_newf, // push new function to the stack + op_happ, // hash append + op_para, // normal parameter + op_deft, // default parameter + op_dyn, // dynamic parameter + op_lnot, // ! logical negation + op_usub, // - negation + op_bnot, // ~ bitwise not static_cast + op_btor, // | bitwise or + op_btxor, // ^ bitwise xor + op_btand, // & bitwise and + op_add, // + + op_sub, // - + op_mul, // * + op_div, // / + op_lnk, // ~ + op_addc, // + const + op_subc, // - const + op_mulc, // * const + op_divc, // / const + op_lnkc, // ~ const + op_addeq, // += maybe pop stack top + op_subeq, // -= maybe pop stack top + op_muleq, // *= maybe pop stack top + op_diveq, // /= maybe pop stack top + op_lnkeq, // ~= maybe pop stack top + op_btandeq, // &= maybe pop stack top + op_btoreq, // |= maybe pop stack top + op_btxoreq, // ^= maybe pop stack top + op_addeqc, // += const don't pop stack top + op_subeqc, // -= const don't pop stack top + op_muleqc, // *= const don't pop stack top + op_diveqc, // /= const don't pop stack top + op_lnkeqc, // ~= const don't pop stack top + op_addecp, // += const and pop stack top + op_subecp, // -= const and pop stack top + op_mulecp, // *= const and pop stack top + op_divecp, // /= const and pop stack top + op_lnkecp, // ~= concat const std::string and pop stack top + op_meq, // = maybe pop stack top + op_eq, // == compare operator + op_neq, // != compare operator + op_less, // < compare operator + op_leq, // <= compare operator + op_grt, // > compare operator + op_geq, // >= compare operator + op_lessc, // < const compare operator + op_leqc, // <= const compare operator + op_grtc, // > const compare operator + op_geqc, // >= const compare operator + op_pop, // pop a value out of stack top + op_jmp, // jump absolute address with no condition + op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP + op_jf, // used in conditional/loop,jmp when condition is false and POP STACK + op_cnt, // add counter for forindex/foreach + op_findex, // index counter on the top of forindex_stack plus 1 + op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector + op_callg, // get value in global scope + op_calll, // get value in local scope + op_upval, // get value in closure, high 16 as the index of upval, low 16 as the index of local + op_callv, // call vec[index] + op_callvi, // call vec[immediate] (used in multi-assign/multi-define) + op_callh, // call hash.label + op_callfv, // call function(vector as parameters) + op_callfh, // call function(hash as parameters) + op_callb, // call native functions + op_slcbeg, // begin of slice like: vec[1, 2, 3:6, 0, -1] + op_slcend, // end of slice + op_slc, // slice like vec[1] + op_slc2, // slice like vec[nil:10] + op_mcallg, // get memory space of value in global scope + op_mcalll, // get memory space of value in local scope + op_mupval, // get memory space of value in closure + op_mcallv, // get memory space of vec[index] + op_mcallh, // get memory space of hash.label + op_ret // return }; struct opcode { u8 op; // opcode u16 fidx; // source code file index - u32 num; // immediate num + u64 num; // immediate num u64 line; // location line of source code opcode() = default; opcode(const opcode&) = default; @@ -110,19 +110,18 @@ struct opcode { class codestream { private: opcode code; - const u32 index; + const u64 index; inline static const f64* const_number = nullptr; inline static const std::string* const_string = nullptr; inline static const nasal_builtin_table* natives = nullptr; inline static const std::string* files = nullptr; public: - codestream(const opcode& c, const u32 i): code(c), index(i) {} - static void set( - const f64*, const std::string*, - const nasal_builtin_table*, - const std::string* file_list = nullptr - ); + codestream(const opcode& c, const u64 i): code(c), index(i) {} + static void set(const f64*, + const std::string*, + const nasal_builtin_table*, + const std::string* file_list = nullptr); void dump(std::ostream&) const; }; diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 5b3cf20..bef537c 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -279,14 +279,14 @@ bool var::object_check(const std::string& name) { } var var::none() { - return {vm_type::vm_none, static_cast(0)}; + return {vm_type::vm_none, static_cast(0)}; } var var::nil() { - return {vm_type::vm_nil, static_cast(0)}; + return {vm_type::vm_nil, static_cast(0)}; } -var var::ret(u32 pc) { +var var::ret(u64 pc) { return {vm_type::vm_ret, pc}; } @@ -310,7 +310,7 @@ var* var::addr() { return val.addr; } -u32 var::ret() const { +u64 var::ret() const { return val.ret; } diff --git a/src/nasal_type.h b/src/nasal_type.h index 7cd3f17..b802066 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -49,7 +49,7 @@ struct var { public: vm_type type = vm_type::vm_none; union { - u32 ret; + u64 ret; i64 cnt; f64 num; var* addr; @@ -57,7 +57,7 @@ public: } val; private: - var(vm_type t, u32 pc) {type = t; val.ret = pc;} + 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;} @@ -82,7 +82,7 @@ public: // create new var object static var none(); static var nil(); - static var ret(u32); + static var ret(u64); static var cnt(i64); static var num(f64); static var gcobj(nas_val*); @@ -91,7 +91,7 @@ public: public: // get value var* addr(); - u32 ret() const; + u64 ret() const; i64& cnt(); f64 num() const; std::string& str(); @@ -143,10 +143,10 @@ struct nas_hash { }; struct nas_func { - i32 dynamic_parameter_index; // dynamic parameter name index in hash. - u32 entry; // pc will set to entry-1 to call this function + i64 dynamic_parameter_index; // dynamic parameter name index in hash. + u64 entry; // pc will set to entry-1 to call this function u32 parameter_size; // used to load default parameters to a new function - u32 local_size; // used to expand memory space for local values on stack + u64 local_size; // used to expand memory space for local values on stack std::vector local; // local scope with default value(var) std::vector upval; // closure @@ -163,7 +163,7 @@ struct nas_upval { public: /* on stack, use these variables */ bool on_stack; - u32 size; + u64 size; var* stack_frame_offset; /* not on stack, use this */ @@ -207,7 +207,7 @@ public: }; struct context { - u32 pc = 0; + u64 pc = 0; var* localr = nullptr; var* memr = nullptr; var funcr = var::nil(); diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 496155f..0de18a2 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -2,15 +2,13 @@ namespace nasal { -void vm::init( - const std::vector& strs, - const std::vector& nums, - const std::vector& natives, - const std::vector& code, - const std::unordered_map& global_symbol, - const std::vector& filenames, - const std::vector& argv -) { +void vm::vm_init_enrty(const std::vector& strs, + const std::vector& nums, + const std::vector& natives, + const std::vector& code, + const std::unordered_map& global_symbol, + const std::vector& filenames, + const std::vector& argv) { const_number = nums.data(); const_string = strs.data(); bytecode = code.data(); @@ -411,11 +409,10 @@ void vm::die(const std::string& str) { } } -void vm::run( - const codegen& gen, - const linker& linker, - const std::vector& argv) { - init( +void vm::run(const codegen& gen, + const linker& linker, + const std::vector& argv) { + vm_init_enrty( gen.strs(), gen.nums(), gen.natives(), @@ -424,6 +421,7 @@ void vm::run( linker.get_file_list(), argv ); + #ifndef _MSC_VER // using labels as values/computed goto const void* oprs[] = { diff --git a/src/nasal_vm.h b/src/nasal_vm.h index bfe5cc6..ea175f7 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -26,7 +26,7 @@ protected: /* constants */ const f64* const_number = nullptr; // constant numbers const std::string* const_string = nullptr; // constant symbols and strings - std::vector imm; // immediate number table + std::vector imm; // immediate number table std::vector native_function; /* garbage collector */ @@ -49,15 +49,13 @@ protected: bool flag_limited_mode = false; /* vm initializing function */ - void init( - const std::vector&, - const std::vector&, - const std::vector&, - const std::vector&, - const std::unordered_map&, - const std::vector&, - const std::vector& - ); + void vm_init_enrty(const std::vector&, + const std::vector&, + const std::vector&, + const std::vector&, + const std::unordered_map&, + const std::vector&, + const std::vector&); void context_and_global_init(); /* debug functions */ @@ -183,11 +181,9 @@ public: } /* execution entry */ - void run( - const codegen&, // get generated code - const linker&, // get list of used files - const std::vector& // get arguments input by command line - ); + void run(const codegen&, // get generated code + const linker&, // get list of used files + const std::vector&); // get command line arguments /* set detail report info flag */ void set_detail_report_info(bool flag) {verbose = flag;} @@ -700,7 +696,7 @@ inline void vm::o_callh() { } inline void vm::o_callfv() { - const u32 argc = imm[ctx.pc]; // arguments counter + const auto argc = imm[ctx.pc]; // arguments counter 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])); @@ -719,7 +715,7 @@ inline void vm::o_callfv() { return; } // parameter size is func->psize-1, 1 is reserved for "me" - const u32 parameter_size = func.parameter_size-1; + const u64 parameter_size = func.parameter_size-1; if (argc=0) { // load dynamic argument dynamic = ngc.alloc(vm_type::vm_vec); - for(u32 i = parameter_size; i=1; --i) { // load arguments + // use (std::min) to avoid compilation error in MSVC + // MSVC windows.h uses macro std::min + const u64 min_size = (std::min)(parameter_size, argc); + + // load arguments + for(u64 i = min_size; i>=1; --i) { local[i] = local[i-1]; } - local[0] = func.local[0];// load "me" + local[0] = func.local[0]; // load "me" // load local scope & default arguments - for(u32 i = min_size+1; ilocalr[1]; - f64 num = 0; + + usize num = 0; switch(val.type) { - case vm_type::vm_num: num = val.num(); break; + case vm_type::vm_num: return val; case vm_type::vm_str: num = val.str().length(); break; case vm_type::vm_vec: num = val.vec().size(); break; case vm_type::vm_hash: num = val.hash().size(); break; case vm_type::vm_map: num = val.map().mapper.size(); break; default: break; } - return var::num(num); + return var::num(static_cast(num)); } var builtin_time(context* ctx, gc* ngc) { @@ -569,12 +570,12 @@ public: stamp = std::chrono::high_resolution_clock::now(); } - f64 elapsed_milliseconds() { + auto elapsed_milliseconds() const { const auto duration = std::chrono::high_resolution_clock::now() - stamp; return std::chrono::duration_cast(duration).count(); } - f64 elapsed_microseconds() { + auto elapsed_microseconds() const { const auto duration = std::chrono::high_resolution_clock::now() - stamp; return std::chrono::duration_cast(duration).count(); } @@ -611,7 +612,7 @@ var builtin_elapsed_millisecond(context* ctx, gc* ngc) { return var::num(-1); } auto stamp = static_cast(object.ghost().pointer); - return var::num(stamp->elapsed_milliseconds()); + return var::num(static_cast(stamp->elapsed_milliseconds())); } var builtin_elapsed_microsecond(context* ctx, gc* ngc) { @@ -620,7 +621,7 @@ var builtin_elapsed_microsecond(context* ctx, gc* ngc) { return var::num(-1); } auto stamp = static_cast(object.ghost().pointer); - return var::num(stamp->elapsed_microseconds()); + return var::num(static_cast(stamp->elapsed_microseconds())); } var builtin_gcextend(context* ctx, gc* ngc) { @@ -648,20 +649,27 @@ var builtin_gcextend(context* ctx, gc* ngc) { } var builtin_gcinfo(context* ctx, gc* ngc) { - auto den = std::chrono::high_resolution_clock::duration::period::den; + const auto den = std::chrono::high_resolution_clock::duration::period::den; var res = ngc->alloc(vm_type::vm_hash); - double total = 0; + f64 total = 0; for(u32 i = 0; igcnt[i]; + total += static_cast(ngc->gcnt[i]); } - // using ms + + auto& map = res.hash().elems; - map["total"] = var::num(ngc->worktime*1.0/den*1000); - map["average"] = var::num(ngc->worktime*1.0/den*1000/total); - map["max_gc"] = var::num(ngc->max_time*1.0/den*1000); - map["max_mark"] = var::num(ngc->max_mark_time*1.0/den*1000); - map["max_sweep"] = var::num(ngc->max_sweep_time*1.0/den*1000); + const auto worktime = static_cast(ngc->worktime); + const auto max_time = static_cast(ngc->max_time); + const auto max_mark_time = static_cast(ngc->max_mark_time); + const auto max_sweep_time = static_cast(ngc->max_sweep_time); + + // using ms + map["total"] = var::num(worktime/den*1000); + map["average"] = var::num(worktime/den*1000/total); + map["max_gc"] = var::num(max_time/den*1000); + map["max_mark"] = var::num(max_mark_time/den*1000); + map["max_sweep"] = var::num(max_sweep_time/den*1000); return res; } @@ -686,9 +694,17 @@ var builtin_ghosttype(context* ctx, gc* ngc) { if (!arg.is_ghost()) { return nas_err("ghosttype", "this is not a ghost object."); } + const auto& name = arg.ghost().get_ghost_name(); + + // https://wiki.flightgear.org/Nasal_library#ghosttype() + // tolds us if no name has been set, + // return a unique id (the pointer to the instance) if (!name.length()) { - return var::num(reinterpret_cast(arg.ghost().pointer)); + std::stringstream ss; + ss << "0x" << std::hex; + ss << reinterpret_cast(arg.ghost().pointer) << std::dec; + return ngc->newstr(ss.str()); } return ngc->newstr(name); }