From b25a1bc3f41f83a95dc0743cbd936e7507ff9a1b Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Sat, 5 Jun 2021 20:42:58 +0800 Subject: [PATCH] more efficient str2num --- nasal.h | 102 +++++++++++++++++++++++--------------------------- nasal_gc.h | 32 ++++++---------- nasal_parse.h | 2 +- nasal_vm.h | 8 ++-- 4 files changed, 63 insertions(+), 81 deletions(-) diff --git a/nasal.h b/nasal.h index 6d42546..3521492 100644 --- a/nasal.h +++ b/nasal.h @@ -26,92 +26,84 @@ check if a string can be converted to a number if this string cannot be converted to a number,it will return nan */ -inline double hex_to_double(std::string& str) + +inline double hex_to_double(const char* str) { double ret=0; - for(int i=2;str[i];++i) + for(;*str;++str) { ret*=16; - if('0'<=str[i] && str[i]<='9') - ret+=(str[i]-'0'); - else if('a'<=str[i] && str[i]<='f') - ret+=(str[i]-'a'+10); - else if('A'<=str[i] && str[i]<='F') - ret+=(str[i]-'A'+10); + if('0'<=*str && *str<='9') + ret+=(*str-'0'); + else if('a'<=*str && *str<='f') + ret+=(*str-'a'+10); + else if('A'<=*str && *str<='F') + ret+=(*str-'A'+10); else - return std::nan(""); + return nan(""); } return ret; } -inline double oct_to_double(std::string& str) +inline double oct_to_double(const char* str) { double ret=0; - for(int i=2;str[i];++i) + for(;*str;++str) { ret*=8; - if('0'<=str[i] && str[i]<='8') - ret+=(str[i]-'0'); + if('0'<=*str && *str<='8') + ret+=(*str-'0'); else - return std::nan(""); + return nan(""); } return ret; } -inline double dec_to_double(std::string& str,int len) +inline double dec_to_double(const char* str) { - double ret=0; - int i=0; - while('0'<=str[i] && str[i]<='9' && i1 && str[0]=='0' && str[1]=='x') - ret_num=hex_to_double(str); - else if(len>1 && str[0]=='0' && str[1]=='o') - ret_num=oct_to_double(str); + if(*str=='-' || *str=='+') + is_negative=(*str++=='-'); + if(!*str) + return nan(""); + if(str[0]=='0' && str[1]=='x') + ret_num=hex_to_double(str+2); + else if(str[0]=='0' && str[1]=='o') + ret_num=oct_to_double(str+2); else - ret_num=dec_to_double(str,len); + ret_num=dec_to_double(str); return is_negative?-ret_num:ret_num; } diff --git a/nasal_gc.h b/nasal_gc.h index 8c326a9..8217226 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -24,12 +24,9 @@ const int increment[vm_type_size]= 8 // vm_hash }; -struct nasal_vec; //24 bytes -struct nasal_hash;//56 bytes -struct nasal_func;//120 bytes -struct nasal_val; // 16 bytes +struct nasal_val;//declaration of nasal_val -struct nasal_vec +struct nasal_vec// 24 bytes { std::vector elems; @@ -38,7 +35,7 @@ struct nasal_vec nasal_val** get_mem(int); }; -struct nasal_hash +struct nasal_hash// 56 bytes { std::unordered_map elems; @@ -47,20 +44,20 @@ struct nasal_hash nasal_val** get_mem(std::string&); }; -struct nasal_func +struct nasal_func// 120 bytes { - int32_t dynpara;// dynamic parameter name index in hash - uint32_t offset; - uint32_t entry; - std::vector default_para; + int32_t dynpara;// dynamic parameter name index in hash + uint32_t offset; // arguments will be loaded into local scope from this offset + uint32_t entry; // pc will set to entry-1 to call this function + std::vector default_para;// default value(nasal_val*) std::unordered_map key_table;// parameter name hash - std::vector closure; + std::vector closure;// closure will be loaded to gc.local.back() as the local scope nasal_func(); void clear(); }; -struct nasal_val +struct nasal_val// 16 bytes { #define GC_UNCOLLECTED 0 #define GC_FOUND 1 @@ -76,7 +73,6 @@ struct nasal_val nasal_func* func; }ptr; - nasal_val(); nasal_val(int); ~nasal_val(); double to_number(); @@ -203,12 +199,6 @@ void nasal_func::clear() } /*functions of nasal_val*/ -nasal_val::nasal_val() -{ - mark=GC_COLLECTED; - type=vm_nil; - return; -} nasal_val::nasal_val(int val_type) { mark=GC_COLLECTED; @@ -238,7 +228,7 @@ nasal_val::~nasal_val() double nasal_val::to_number() { if(type==vm_str) - return str2num(*ptr.str); + return str2num(ptr.str->c_str()); return ptr.num; } std::string nasal_val::to_string() diff --git a/nasal_parse.h b/nasal_parse.h index f52b915..453579b 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -315,7 +315,7 @@ nasal_ast nasal_parse::nil_gen() nasal_ast nasal_parse::num_gen() { nasal_ast node(tok_list[ptr].line,ast_num); - node.set_num(str2num(tok_list[ptr].str)); + node.set_num(str2num(tok_list[ptr].str.c_str())); return node; } nasal_ast nasal_parse::str_gen() diff --git a/nasal_vm.h b/nasal_vm.h index 37c87a2..4de1bb0 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -135,7 +135,7 @@ bool nasal_vm::condition(nasal_val* val_addr) else if(type==vm_str) { std::string& str=*val_addr->ptr.str; - double number=str2num(str); + double number=str2num(str.c_str()); if(std::isnan(number)) return !str.empty(); return number; @@ -267,7 +267,7 @@ void nasal_vm::opr_unot() new_val=val->ptr.num?gc.zero_addr:gc.one_addr; else if(type==vm_str) { - double number=str2num(*val->ptr.str); + double number=str2num(val->ptr.str->c_str()); if(std::isnan(number)) new_val=val->ptr.str->empty()?gc.one_addr:gc.zero_addr; else @@ -752,7 +752,7 @@ void nasal_vm::opr_slc() switch(val->type) { case vm_num:num=val->ptr.num;break; - case vm_str:num=str2num(*val->ptr.str);break; + case vm_str:num=str2num(val->ptr.str->c_str());break; default:die("slc: error value type");break; } nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num); @@ -819,7 +819,7 @@ void nasal_vm::opr_mcallv() switch(val->type) { case vm_num:num=(int)val->ptr.num;break; - case vm_str:num=(int)str2num(*val->ptr.str);break; + case vm_str:num=(int)str2num(val->ptr.str->c_str());break; default:die("mcallv: error value type");break; } nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);