#ifndef __NASAL_RUNTIME_H__ #define __NASAL_RUNTIME_H__ enum runtime_returned_state { rt_return=1, rt_error, rt_break, rt_continue, rt_exit_without_error }; class nasal_runtime { private: nasal_virtual_machine nasal_vm; std::map builtin_func_hashmap; // function_return_address is an address in garbage_collector_memory int function_returned_address; // global_scope_address is an address in garbage_collector_memory int global_scope_address; nasal_ast root; // if error occurred,this value will add 1 int error; void die(int,std::string); // generate vector and return gc place of this vector int vector_generation(nasal_ast&,int); // generate hash and return gc place of this hash int hash_generation(nasal_ast&,int); // generate function and return gc place of this function int function_generation(nasal_ast&,int); /* functions after this note may have parameter named 'local_scope_addr' if no local scope existing when calling these functions,use -1 */ // main expression block running process void main_progress(); // function/loop/conditional expression block running process int block_progress(nasal_ast&,int); // run loop void before_for_loop(nasal_ast&,int); void after_each_for_loop(nasal_ast&,int); int loop_progress(nasal_ast&,int); // run conditional bool check_condition(int); int conditional_progress(nasal_ast&,int); // get scalars in complex data structure like vector/hash/function/closure(scope) int call_scalar(nasal_ast&,int); int call_vector(nasal_ast&,int,int); int call_hash(nasal_ast&,int,int); int call_function(nasal_ast&,std::string,int,int,int); int call_builtin_function(std::string,int); // get scalars' memory place in complex data structure like vector/hash/function/closure(scope) int call_scalar_mem(nasal_ast&,int); int call_vector_mem(nasal_ast&,int,int); int call_hash_mem(nasal_ast&,int,int); // calculate scalars int nasal_scalar_add(int,int); int nasal_scalar_sub(int,int); int nasal_scalar_mult(int,int); int nasal_scalar_div(int,int); int nasal_scalar_link(int,int); int nasal_scalar_unary_sub(int); int nasal_scalar_unary_not(int); int nasal_scalar_cmp_equal(int,int); int nasal_scalar_cmp_not_equal(int,int); int nasal_scalar_cmp_less(int,int); int nasal_scalar_cmp_greater(int,int); int nasal_scalar_cmp_less_or_equal(int,int); int nasal_scalar_cmp_greater_or_equal(int,int); int calculation(nasal_ast&,int); void definition(nasal_ast&,int); void multi_assignment(nasal_ast&,int); // builtin_func defined here void load_builtin_function(); public: nasal_runtime(); ~nasal_runtime(); void set_root(nasal_ast&); void run(); }; nasal_runtime::nasal_runtime() { error=0; this->root.clear(); this->global_scope_address=-1; this->load_builtin_function(); return; } nasal_runtime::~nasal_runtime() { error=0; this->root.clear(); this->global_scope_address=-1; this->builtin_func_hashmap.clear(); return; } void nasal_runtime::die(int line,std::string info) { ++error; std::cout<<">> [runtime] line "<root=parse_result; return; } void nasal_runtime::run() { // this state is reserved for builtin_die builtin_die_state=0; this->error=0; this->function_returned_address=-1; this->global_scope_address=nasal_vm.gc_alloc(vm_closure); nasal_vm.gc_get(global_scope_address).get_closure().add_scope(); time_t begin_time=std::time(NULL); main_progress(); time_t end_time=std::time(NULL); nasal_vm.gc_get(global_scope_address).get_closure().del_scope(); nasal_vm.del_reference(global_scope_address); nasal_vm.clear(); time_t total_run_time=end_time-begin_time; if(total_run_time>=1) std::cout<<">> [runtime] process exited after "<=0) ref_of_this_function.set_closure_addr(local_scope_addr); else { int new_closure=nasal_vm.gc_alloc(vm_closure); ref_of_this_function.set_closure_addr(new_closure); nasal_vm.del_reference(new_closure); } return new_addr; } void nasal_runtime::main_progress() { int expr_number=root.get_children().size(); int process_returned_value_addr=-1; for(int i=0;i=0) value_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(val_name); if(value_address<0) value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(val_name); if(value_address<0) { value_address=call_builtin_function(val_name,local_scope_addr); if(value_address>=0) return value_address; else { if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) die(node.get_children()[0].get_line(),"call "+val_name+" failed"); else die(node.get_children()[0].get_line()," cannot find \""+val_name+"\""); return -1; } } nasal_vm.add_reference(value_address); } else value_address=calculation(node.get_children()[0],local_scope_addr); int call_expr_size=node.get_children().size(); int last_call_hash_addr=-1; for(int i=1;i called_value_addrs; nasal_vector& reference_value=nasal_vm.gc_get(base_value_addr).get_vector(); for(int i=0;i=end_index) { die(subvec_node.get_children()[0].get_line(),"begin index is greater than end index"); return -1; } int vsize=reference_value.size(); if(begin_index<-vsize || begin_index>vsize-1 || end_index<-vsize || end_index>vsize-1) { die(node.get_children()[i].get_line(),"begin index or end index is out of range"); return -1; } for(int i=begin_index;i<=end_index;++i) called_value_addrs.push_back(reference_value.get_value_address(i)); nasal_vm.del_reference(begin_value_addr); nasal_vm.del_reference(end_value_addr); } else { int index_value_addr=calculation(node.get_children()[i],local_scope_addr); int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); if(index_value_type!=vm_number && index_value_type!=vm_string) { die(node.get_children()[i].get_line(),"index must be number/string"); return -1; } int index_num=0; if(index_value_type==vm_string) { std::string str=nasal_vm.gc_get(index_value_addr).get_string(); double number=trans_string_to_number(str); index_num=(int)number; } else index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); nasal_vm.del_reference(index_value_addr); called_value_addrs.push_back(reference_value.get_value_address(index_num)); } } // generate sub-vector if(call_size==1 && node.get_children()[0].get_type()!=ast_subvec) { int value_addr=called_value_addrs[0]; nasal_vm.add_reference(value_addr); return_value_addr=value_addr; } else { return_value_addr=nasal_vm.gc_alloc(vm_vector); nasal_vector& return_vector=nasal_vm.gc_get(return_value_addr).get_vector(); int vec_size=called_value_addrs.size(); for(int i=0;i1) { die(node.get_line(),"use only one key to call a hash"); return -1; } nasal_ast& tmp=node.get_children()[0]; if(tmp.get_type()==ast_subvec) { die(tmp.get_line(),"cannot slice hash"); return -1; } int str_addr=calculation(tmp,local_scope_addr); if(str_addr<0 || nasal_vm.gc_get(str_addr).get_type()!=vm_string) { die(tmp.get_line(),"must use string as the key"); return -1; } std::string str=nasal_vm.gc_get(str_addr).get_string(); int value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(str); nasal_vm.add_reference(value_addr); return_value_addr=value_addr; } else { if(call_size>1) { die(node.get_line(),"use only one index to call a string"); return -1; } nasal_ast& tmp=node.get_children()[0]; if(tmp.get_type()==ast_subvec) { die(tmp.get_line(),"cannot slice string (use substr)"); return -1; } int index_value_addr=calculation(tmp,local_scope_addr); int index_value_type=nasal_vm.gc_get(index_value_addr).get_type(); if(index_value_type!=vm_number && index_value_type!=vm_string) { die(tmp.get_line(),"index is not a number/numerable string"); return -1; } int index_num=0; if(index_value_type==vm_string) { std::string str=nasal_vm.gc_get(index_value_addr).get_string(); double number=trans_string_to_number(str); index_num=(int)number; } else index_num=(int)nasal_vm.gc_get(index_value_addr).get_number(); nasal_vm.del_reference(index_value_addr); return_value_addr=nasal_vm.gc_alloc(vm_number); std::string str=nasal_vm.gc_get(base_value_addr).get_string(); int str_size=str.length(); if(index_num>=str_size || index_num<-str_size) { die(tmp.get_line(),"index out of range"); return -1; } nasal_vm.gc_get(return_value_addr).set_number((double)str[(index_num+str_size)%str_size]); } return return_value_addr; } int nasal_runtime::call_hash(nasal_ast& node,int base_value_addr,int local_scope_addr) { int value_type=nasal_vm.gc_get(base_value_addr).get_type(); if(value_type!=vm_hash) { die(node.get_line(),"called a value that is not a hash"); return -1; } int ret_value_addr=nasal_vm.gc_get(base_value_addr).get_hash().get_value_address(node.get_str()); nasal_vm.add_reference(ret_value_addr); return ret_value_addr; } int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_value_addr,int last_call_hash_addr,int local_scope_addr) { int ret_value_addr=-1; int value_type=nasal_vm.gc_get(base_value_addr).get_type(); if(value_type!=vm_function) { die(node.get_line(),"called a value that is not a function"); return -1; } nasal_function& reference_of_func=nasal_vm.gc_get(base_value_addr).get_func(); int run_closure_addr=reference_of_func.get_closure_addr(); nasal_closure& run_closure=nasal_vm.gc_get(run_closure_addr).get_closure(); run_closure.add_scope(); if(last_call_hash_addr>=0) { // set hash.me nasal_vm.add_reference(last_call_hash_addr); run_closure.add_new_value("me",last_call_hash_addr); } else if(func_name.length()) { // when hash.me does not exist,set self nasal_vm.add_reference(base_value_addr); run_closure.add_new_value(func_name,base_value_addr); } nasal_ast& argument_format=reference_of_func.get_arguments(); if(!node.get_children().size()) { if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()!=ast_default_arg && argument_format.get_children()[0].get_type()!=ast_dynamic_id) { die(node.get_line(),"lack argument(s)"); return -1; } else if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()==ast_dynamic_id) { // load null dynamic-id int vector_value_addr=nasal_vm.gc_alloc(vm_vector); run_closure.add_new_value(argument_format.get_children()[0].get_str(),vector_value_addr); } else if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()==ast_default_arg) { // load default values int size=argument_format.get_children().size(); for(int i=0;i args_usage_table; // check arguments in argument_format is correctly used std::map default_args_table; // check default arguments std::map default_args_node; // if one of default arguments is not in use,use default value // load arguments' name. int arg_format_size=argument_format.get_children().size(); for(int i=0;i::iterator i=default_args_table.begin();i!=default_args_table.end();++i) if(!i->second) { int value_addr=calculation(*default_args_node[i->first],local_scope_addr); if(value_addr<0) return -1; run_closure.add_new_value(i->first,value_addr); args_usage_table[i->first]=true; } // use null vector if dynamic-identifier haven't been initialized. if(argument_format.get_children().back().get_type()==ast_dynamic_id) { std::string dyn_str=argument_format.get_children().back().get_str(); if(!args_usage_table[dyn_str]) { args_usage_table[dyn_str]=true; int vector_value_addr=nasal_vm.gc_alloc(vm_vector); run_closure.add_new_value(dyn_str,vector_value_addr); } } // check if each argument is initialized. for(std::map::iterator i=args_usage_table.begin();i!=args_usage_table.end();++i) if(!i->second) { die(node.get_line(),"argument named \""+i->first+"\" is not in use"); return -1; } } else { std::vector args; // store value address of input arguments int size=node.get_children().size(); for(int i=0;iarg_format_size && argument_format.get_children().back().get_type()!=ast_dynamic_id) { die(node.get_line(),"too much arguments"); return -1; } for(int i=0;i=0) { ret_value_addr=function_returned_address; function_returned_address=-1; } else ret_value_addr=nasal_vm.gc_alloc(vm_nil); return ret_value_addr; } int nasal_runtime::call_builtin_function(std::string val_name,int local_scope_addr) { int ret_value_addr=-1; int builtin_func_num=-1; if(builtin_func_hashmap.find(val_name)!=builtin_func_hashmap.end()) { ret_value_addr=(*builtin_func_hashmap[val_name])(local_scope_addr,nasal_vm); error+=builtin_die_state; } return ret_value_addr; } int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr) { int mem_address=-1; if(node.get_type()==ast_identifier) { std::string id_name=node.get_str(); if(local_scope_addr>=0) mem_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_mem_address(id_name); if(mem_address<0) mem_address=nasal_vm.gc_get(global_scope_address).get_closure().get_mem_address(id_name); if(mem_address<0) { die(node.get_line(),"cannot find \""+id_name+"\""); return -1; } return mem_address; } std::string id_name=node.get_children()[0].get_str(); if(local_scope_addr>=0) mem_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_mem_address(id_name); if(mem_address<0) mem_address=nasal_vm.gc_get(global_scope_address).get_closure().get_mem_address(id_name); if(mem_address<0) { die(node.get_children()[0].get_line(),"cannot find \""+id_name+"\""); return -1; } int call_expr_size=node.get_children().size(); for(int i=1;i> [vm] scalar_add: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(a_num+b_num); return new_value_address; } int nasal_runtime::nasal_scalar_sub(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_sub: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(a_num-b_num); return new_value_address; } int nasal_runtime::nasal_scalar_mult(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_mult: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(a_num*b_num); return new_value_address; } int nasal_runtime::nasal_scalar_div(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_div: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(a_num/b_num); return new_value_address; } int nasal_runtime::nasal_scalar_link(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_link: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if((a_ref_type!=vm_number && a_ref_type!=vm_string)||(b_ref_type!=vm_number && b_ref_type!=vm_string)) { std::cout<<">> [vm] scalar_link: error value type.\n"; return -1; } std::string a_str; std::string b_str; a_str=(a_ref_type==vm_number)? trans_number_to_string(a_ref.get_number()):a_ref.get_string(); b_str=(b_ref_type==vm_number)? trans_number_to_string(b_ref.get_number()):b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_string); nasal_vm.gc_get(new_value_address).set_string(a_str+b_str); return new_value_address; } int nasal_runtime::nasal_scalar_unary_sub(int a_scalar_addr) { if(a_scalar_addr<0) { std::cout<<">> [vm] scalar_unary_sub: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); int a_ref_type=a_ref.get_type(); double a_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(-a_num); return new_value_address; } int nasal_runtime::nasal_scalar_unary_not(int a_scalar_addr) { if(a_scalar_addr<0) { std::cout<<">> [vm] scalar_unary_not: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); int a_ref_type=a_ref.get_type(); int new_value_address=-1; if(a_ref_type==vm_nil) { new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(1); } else if(a_ref_type==vm_number) { double number=(a_ref.get_number()==0); new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(number); } else if(a_ref_type==vm_string) { double number=trans_string_to_number(a_ref.get_string()); if(std::isnan(number)) { new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(!(a_ref.get_string()).length()); } else { new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(number==0)); } } else std::cout<<">> [vm] scalar_unary_not: error value type.\n"; return new_value_address; } int nasal_runtime::nasal_scalar_cmp_equal(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_cmp_equal: memory returned an invalid address.\n"; return -1; } if(a_scalar_addr==b_scalar_addr) { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(1); return new_value_address; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_nil && b_ref_type==vm_nil) { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(1); return new_value_address; } else if((a_ref_type==vm_number || a_ref_type==vm_string) && (b_ref_type==vm_number || b_ref_type==vm_string)) { if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string astr=a_ref.get_string(); std::string bstr=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(astr==bstr)); return new_value_address; } double a_num; double b_num; if(a_ref_type==vm_number) a_num=a_ref.get_number(); else a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_num==b_num)); return new_value_address; } else { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(0); return new_value_address; } return -1; } int nasal_runtime::nasal_scalar_cmp_not_equal(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_cmp_not_equal: memory returned an invalid address.\n"; return -1; } if(a_scalar_addr==b_scalar_addr) { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(0); return new_value_address; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_nil && b_ref_type==vm_nil) { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(0); return new_value_address; } else if((a_ref_type==vm_number || a_ref_type==vm_string) && (b_ref_type==vm_number || b_ref_type==vm_string)) { if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string astr=a_ref.get_string(); std::string bstr=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(astr!=bstr)); return new_value_address; } double a_num; double b_num; if(a_ref_type==vm_number) a_num=a_ref.get_number(); else a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_num!=b_num)); return new_value_address; } else { int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number(1); return new_value_address; } return -1; } int nasal_runtime::nasal_scalar_cmp_less(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_cmp_less: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string a_str=a_ref.get_string(); std::string b_str=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_str> [vm] scalar_cmp_greater: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string a_str=a_ref.get_string(); std::string b_str=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_str>b_str)); return new_value_address; } double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_num>b_num)); return new_value_address; } int nasal_runtime::nasal_scalar_cmp_less_or_equal(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_cmp_lequal: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string a_str=a_ref.get_string(); std::string b_str=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_str<=b_str)); return new_value_address; } double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_num<=b_num)); return new_value_address; } int nasal_runtime::nasal_scalar_cmp_greater_or_equal(int a_scalar_addr,int b_scalar_addr) { if(a_scalar_addr<0 || b_scalar_addr<0) { std::cout<<">> [vm] scalar_cmp_gequal: memory returned an invalid address.\n"; return -1; } nasal_scalar& a_ref=nasal_vm.gc_get(a_scalar_addr); nasal_scalar& b_ref=nasal_vm.gc_get(b_scalar_addr); int a_ref_type=a_ref.get_type(); int b_ref_type=b_ref.get_type(); if(a_ref_type==vm_string && b_ref_type==vm_string) { std::string a_str=a_ref.get_string(); std::string b_str=b_ref.get_string(); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_str>=b_str)); return new_value_address; } double a_num=(1/0.0)+(-1/0.0); double b_num=(1/0.0)+(-1/0.0); if(a_ref_type==vm_number) a_num=a_ref.get_number(); else if(a_ref_type==vm_string) a_num=trans_string_to_number(a_ref.get_string()); if(b_ref_type==vm_number) b_num=b_ref.get_number(); else if(b_ref_type==vm_string) b_num=trans_string_to_number(b_ref.get_string()); int new_value_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(new_value_address).set_number((double)(a_num>=b_num)); return new_value_address; } int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr) { // after this process, a new address(in nasal_vm.garbage_collector_memory) will be returned int ret_address=-1; int calculation_type=node.get_type(); if(calculation_type==ast_null) { ret_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(ret_address).set_number(1); } else if(calculation_type==ast_nil) ret_address=nasal_vm.gc_alloc(vm_nil); else if(calculation_type==ast_number) { ret_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(ret_address).set_number(node.get_num()); } else if(calculation_type==ast_string) { ret_address=nasal_vm.gc_alloc(vm_string); nasal_vm.gc_get(ret_address).set_string(node.get_str()); } else if(calculation_type==ast_identifier) { if(local_scope_addr>=0) ret_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(node.get_str()); if(ret_address<0) ret_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_str()); if(ret_address<0) { die(node.get_line(),"cannot find \""+node.get_str()+"\""); ret_address=nasal_vm.gc_alloc(vm_nil); } nasal_vm.add_reference(ret_address); } else if(calculation_type==ast_vector) ret_address=vector_generation(node,local_scope_addr); else if(calculation_type==ast_hash) ret_address=hash_generation(node,local_scope_addr); else if(calculation_type==ast_function) ret_address=function_generation(node,local_scope_addr); else if(calculation_type==ast_call) ret_address=call_scalar(node,local_scope_addr); else if(calculation_type==ast_add) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_add(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_sub) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_sub(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_mult) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_mult(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_div) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_div(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_link) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_link(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_cmp_equal) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_equal(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_cmp_not_equal) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_not_equal(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_less_than) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_less(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_less_equal) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_less_or_equal(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_greater_than) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_greater(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_greater_equal) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); ret_address=nasal_scalar_cmp_greater_or_equal(left_gc_addr,right_gc_addr); // delete the reference of temporary values nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); } else if(calculation_type==ast_and) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); if(!check_condition(left_gc_addr)) { nasal_vm.del_reference(left_gc_addr); ret_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(ret_address).set_number(0); } else { int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); if(!check_condition(right_gc_addr)) { nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); ret_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(ret_address).set_number(0); } else { nasal_vm.del_reference(left_gc_addr); ret_address=right_gc_addr; } } } else if(calculation_type==ast_or) { int left_gc_addr=calculation(node.get_children()[0],local_scope_addr); if(check_condition(left_gc_addr)) ret_address=left_gc_addr; else { int right_gc_addr=calculation(node.get_children()[1],local_scope_addr); if(check_condition(right_gc_addr)) { nasal_vm.del_reference(left_gc_addr); ret_address=right_gc_addr; } else { nasal_vm.del_reference(left_gc_addr); nasal_vm.del_reference(right_gc_addr); ret_address=nasal_vm.gc_alloc(vm_number); nasal_vm.gc_get(ret_address).set_number(0); } } } else if(calculation_type==ast_unary_not) { int addr=calculation(node.get_children()[0],local_scope_addr); ret_address=nasal_scalar_unary_not(addr); // delete the reference of temporary values nasal_vm.del_reference(addr); } else if(calculation_type==ast_unary_sub) { int addr=calculation(node.get_children()[0],local_scope_addr); ret_address=nasal_scalar_unary_sub(addr); // delete the reference of temporary values nasal_vm.del_reference(addr); } else if(calculation_type==ast_trinocular) { int condition_addr=calculation(node.get_children()[0],local_scope_addr); if(check_condition(condition_addr)) ret_address=calculation(node.get_children()[1],local_scope_addr); else ret_address=calculation(node.get_children()[2],local_scope_addr); // delete the reference of temporary values nasal_vm.del_reference(condition_addr); } else if(calculation_type==ast_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); nasal_vm.mem_change(scalar_mem_space,new_scalar_gc_addr);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(new_scalar_gc_addr);// this reference is reserved for ret_address ret_address=new_scalar_gc_addr; } else if(calculation_type==ast_add_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int scalar_val_space=nasal_vm.mem_get(scalar_mem_space); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); int result_val_address=nasal_scalar_add(scalar_val_space,new_scalar_gc_addr); nasal_vm.del_reference(new_scalar_gc_addr); nasal_vm.mem_change(scalar_mem_space,result_val_address);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(result_val_address);// this reference is reserved for ret_address ret_address=result_val_address; } else if(calculation_type==ast_sub_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int scalar_val_space=nasal_vm.mem_get(scalar_mem_space); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); int result_val_address=nasal_scalar_sub(scalar_val_space,new_scalar_gc_addr); nasal_vm.del_reference(new_scalar_gc_addr); nasal_vm.mem_change(scalar_mem_space,result_val_address);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(result_val_address);// this reference is reserved for ret_address ret_address=result_val_address; } else if(calculation_type==ast_div_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int scalar_val_space=nasal_vm.mem_get(scalar_mem_space); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); int result_val_address=nasal_scalar_div(scalar_val_space,new_scalar_gc_addr); nasal_vm.del_reference(new_scalar_gc_addr); nasal_vm.mem_change(scalar_mem_space,result_val_address);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(result_val_address);// this reference is reserved for ret_address ret_address=result_val_address; } else if(calculation_type==ast_mult_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int scalar_val_space=nasal_vm.mem_get(scalar_mem_space); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); int result_val_address=nasal_scalar_mult(scalar_val_space,new_scalar_gc_addr); nasal_vm.del_reference(new_scalar_gc_addr); nasal_vm.mem_change(scalar_mem_space,result_val_address);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(result_val_address);// this reference is reserved for ret_address ret_address=result_val_address; } else if(calculation_type==ast_link_equal) { int scalar_mem_space=call_scalar_mem(node.get_children()[0],local_scope_addr); int scalar_val_space=nasal_vm.mem_get(scalar_mem_space); int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr); int result_val_address=nasal_scalar_link(scalar_val_space,new_scalar_gc_addr); nasal_vm.del_reference(new_scalar_gc_addr); nasal_vm.mem_change(scalar_mem_space,result_val_address);// this progress will delete the reference to old gc_addr in scalar_mem_space nasal_vm.add_reference(result_val_address);// this reference is reserved for ret_address ret_address=result_val_address; } else { die(node.get_line(),"cannot calculate expression: "+ast_str(node.get_type())); ret_address=nasal_vm.gc_alloc(vm_nil); } return ret_address; } void nasal_runtime::definition(nasal_ast& node,int local_scope_addr) { nasal_ast& define_node=node.get_children()[0]; nasal_ast& value_node=node.get_children()[1]; if(define_node.get_type()==ast_identifier) { std::string new_name=define_node.get_str(); int value_addr=calculation(value_node,local_scope_addr); if(value_addr<0) return; nasal_vm.gc_get(local_scope_addr<0?global_scope_address:local_scope_addr).get_closure().add_new_value(new_name,value_addr); } else { std::vector identifier_table; int id_size=define_node.get_children().size(); for(int i=0;i mem_table; int id_size=multi_call_node.get_children().size(); for(int i=0;i value_table; for(int i=0;i value_table; for(int i=0;i