diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 0df7ff3..588fbc2 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -279,8 +279,10 @@ void nas_val::clear() { } } -f64 var::to_num() { - return type!=vm_type::vm_str? val.num:util::str_to_num(str().c_str()); +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() { @@ -288,8 +290,8 @@ std::string var::to_str() { return str(); } else if (type==vm_type::vm_num) { auto tmp = std::to_string(num()); - tmp.erase(tmp.find_last_not_of('0')+1, std::string::npos); - tmp.erase(tmp.find_last_not_of('.')+1, std::string::npos); + tmp.erase(tmp.find_last_not_of('0') + 1, std::string::npos); + tmp.erase(tmp.find_last_not_of('.') + 1, std::string::npos); return tmp; } @@ -315,8 +317,8 @@ std::ostream& operator<<(std::ostream& out, var& ref) { return out; } -bool var::object_check(const std::string& name) { - return is_ghost() && ghost().type_name==name && ghost().pointer; +bool var::object_check(const std::string& name) const { + return is_ghost() && ghost().type_name == name && ghost().pointer; } var var::none() { @@ -347,54 +349,6 @@ var var::addr(var* p) { return {vm_type::vm_addr, p}; } -var* var::addr() const { - return val.addr; -} - -u64 var::ret() const { - return val.ret; -} - -i64& var::cnt() { - return val.cnt; -} - -f64 var::num() const { - return val.num; -} - -std::string& var::str() { - return *val.gcobj->ptr.str; -} - -nas_vec& var::vec() { - return *val.gcobj->ptr.vec; -} - -nas_hash& var::hash() { - return *val.gcobj->ptr.hash; -} - -nas_func& var::func() { - return *val.gcobj->ptr.func; -} - -nas_upval& var::upval() { - return *val.gcobj->ptr.upval; -} - -nas_ghost& var::ghost() { - return *val.gcobj->ptr.obj; -} - -nas_co& var::co() { - return *val.gcobj->ptr.co; -} - -nas_map& var::map() { - return *val.gcobj->ptr.map; -} - var nas_err(const std::string& error_function_name, const std::string& info) { std::cerr << "[vm] " << error_function_name << ": " << info << "\n"; return var::none(); diff --git a/src/nasal_type.h b/src/nasal_type.h index f3e45c4..029f9da 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -47,8 +47,32 @@ struct nas_ghost; // objects struct nas_co; // coroutine struct nas_map; // mapper -// union type -struct nas_val; // nas_val includes gc-managed types +// nas_val includes gc-managed types +struct nas_val { + enum class gc_status: u8 { + uncollected = 0, + collected, + found + }; + + gc_status mark; + vm_type type; // value type + u8 immutable; // used to mark if a string is immutable + union elem { + std::string* str; + nas_vec* vec; + nas_hash* hash; + nas_func* func; + nas_upval* upval; + nas_ghost* obj; + nas_co* co; + nas_map* map; + } ptr; + + nas_val(vm_type); + ~nas_val(); + void clear(); +}; struct var { public: @@ -78,11 +102,6 @@ public: return type!=nr.type || val.gcobj!=nr.val.gcobj; } - // number and string can be translated to each other - f64 to_num(); - std::string to_str(); - bool object_check(const std::string&); - public: // create new var object static var none(); @@ -95,18 +114,33 @@ public: public: // get value - var* addr() const; - u64 ret() const; - i64& cnt(); - f64 num() const; - std::string& str(); - nas_vec& vec(); - nas_hash& hash(); - nas_func& func(); - nas_upval& upval(); - nas_ghost& ghost(); - nas_co& co(); - nas_map& map(); + var* addr() const { return val.addr; } + u64 ret() const { return val.ret; } + i64& cnt() { return val.cnt; } + f64 num() const { return val.num; } + +public: + // get gc object + std::string& str() { return *val.gcobj->ptr.str; } + nas_vec& vec() { return *val.gcobj->ptr.vec; } + nas_hash& hash() { return *val.gcobj->ptr.hash; } + nas_func& func() { return *val.gcobj->ptr.func; } + nas_upval& upval() { return *val.gcobj->ptr.upval; } + nas_ghost& ghost() { return *val.gcobj->ptr.obj; } + nas_co& co() { return *val.gcobj->ptr.co; } + nas_map& map() { return *val.gcobj->ptr.map; } + + +public: + // get const gc object + const std::string& str() const { return *val.gcobj->ptr.str; } + const nas_vec& vec() const { return *val.gcobj->ptr.vec; } + const nas_hash& hash() const { return *val.gcobj->ptr.hash; } + const nas_func& func() const { return *val.gcobj->ptr.func; } + const nas_upval& upval() const { return *val.gcobj->ptr.upval; } + const nas_ghost& ghost() const { return *val.gcobj->ptr.obj; } + const nas_co& co() const { return *val.gcobj->ptr.co; } + const nas_map& map() const { return *val.gcobj->ptr.map; } public: bool is_none() const { return type==vm_type::vm_none; } @@ -123,6 +157,12 @@ public: 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; }; struct nas_vec { @@ -266,32 +306,6 @@ public: var* get_memory(const std::string&); }; -struct nas_val { - enum class gc_status: u8 { - uncollected = 0, - collected, - found - }; - - gc_status mark; - vm_type type; // value type - u8 immutable; // used to mark if a string is immutable - union { - std::string* str; - nas_vec* vec; - nas_hash* hash; - nas_func* func; - nas_upval* upval; - nas_ghost* obj; - nas_co* co; - nas_map* map; - } ptr; - - nas_val(vm_type); - ~nas_val(); - void clear(); -}; - std::ostream& operator<<(std::ostream&, nas_vec&); std::ostream& operator<<(std::ostream&, nas_hash&); std::ostream& operator<<(std::ostream&, nas_func&); diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 1ea2444..0829bce 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -96,7 +96,7 @@ protected: protected: /* vm calculation functions*/ - inline bool cond(var&); + inline bool boolify(const var&); protected: /* vm operands */ @@ -320,12 +320,20 @@ public: } }; -inline bool vm::cond(var& val) { +inline bool vm::boolify(const var& val) { if (val.is_num()) { return val.num(); } else if (val.is_str()) { const f64 num = util::str_to_num(val.str().c_str()); - return std::isnan(num)? !val.str().empty():num; + return std::isnan(num)? !val.str().empty() : num; + } else if (val.is_vec()) { + return val.vec().size() > 0; + } else if (val.is_hash()) { + return val.hash().size() > 0; + } else if (val.is_func() || val.is_ghost() || val.is_coroutine()) { + return true; + } else if (val.is_map()) { + return val.map().size() > 0; } return false; } @@ -707,14 +715,14 @@ inline void vm::o_jmp() { inline void vm::o_jt() { // jump true needs to reserve the result on stack // because conditional expression in nasal has return value - if (cond(ctx.top[0])) { + if (boolify(ctx.top[0])) { ctx.pc = imm[ctx.pc]-1; } } inline void vm::o_jf() { // jump false doesn't need to reserve result - if (!cond(ctx.top[0])) { + if (!boolify(ctx.top[0])) { ctx.pc = imm[ctx.pc]-1; } --ctx.top;