#ifndef __NASAL_RUNTIME_H__ #define __NASAL_RUNTIME_H__ #define NAS_LIB_FUNC_NUM 32 std::string inline_func_name[NAS_LIB_FUNC_NUM]= { //base.nas "nasal_call_builtin_push_back",// append "nasal_call_builtin_set_size", // setsize "nasal_call_builtin_subvec", "nasal_call_builtin_contains", "nasal_call_builtin_delete", "nasal_call_builtin_trans_int", "nasal_call_builtin_trans_num", "nasal_call_builtin_get_keys", "nasal_call_builtin_pop_back", "nasal_call_builtin_sizeof", "nasal_call_builtin_str_cmp_equal", "nasal_call_builtin_cmp", "nasal_call_builtin_cpp_sort", "nasal_call_builtin_substr", "nasal_call_builtin_sprintf", "nasal_call_builtin_find_first_occur", "nasal_call_builtin_split", "nasal_call_builtin_rand", "nasal_call_builtin_get_id", //bits.nas "nasal_call_builtin_bitcalc", "nasal_call_builtin_sbitcalc", "nasal_call_builtin_setbit", "nasal_call_builtin_null_string_gen", //io.nas "nasal_call_builtin_c_std_puts",// print //math.nas "nasal_call_builtin_sin", "nasal_call_builtin_cos", "nasal_call_builtin_tan", "nasal_call_builtin_exp", "nasal_call_builtin_cpp_math_ln", "nasal_call_builtin_cpp_math_sqrt", "nasal_call_builtin_cpp_atan2", //system.nas "nasal_call_builtin_scalar_type"//system.type }; class nasal_runtime { private: // global scope is a hash_map // main_local_scope is used in main block // when calling a loop or conditional expression // when adding a new identifier into scope,you need to check if this identifier is already in the scope. std::map global_scope; std::list > main_local_scope; // enum of state type used by loop/conditional enum state_stack_member_type { __state_error = 0, __state_no_operation, __state_continue, __state_break, __state_return, }; // see detail of each enum type in function error_interrupt(const int) enum runtime_error_type { __incorrect_head_of_tree, __undefined_identifier, __multi_assign_incorrect_value_number, __multi_define_incorrect_value_number, __invalid_vector_member, __invalid_hash_member, __class_inheritence_need_vector, __memory_overflow, __not_callable_vector, __not_callable_hash, __not_callable_function, __not_numerable_str, __error_value_type, __error_value_type_when_calling_vector, __error_value_type_when_calling_hash, __special_call_vector_negative_value, __special_call_vector_too_large_value, __normal_call_vector_too_large_value, __function_returned_value_be_assigned, __subvec_value_be_assigned, __call_function_lack_para, __forindex_foreach_not_vector, __break_not_used_in_loop, __continue_not_used_in_loop, __return_not_used_in_function, __stack_overflow, }; int runtime_error_exit_mark; int function_returned_addr; void error_interrupt (const int,const int); int number_generation (abstract_syntax_tree&); int string_generation (abstract_syntax_tree&); // sub-process of call_identifier/vector_generation/hash_generation/function_generation int bracket_call_vector(std::list >&,std::list::iterator&,int); int dot_call_hash (std::list >&,std::list::iterator&,int); int call_function (std::list >&,std::list::iterator&,int,int); int vector_generation (std::list >&,abstract_syntax_tree&); int hash_generation (std::list >&,abstract_syntax_tree&); int function_generation(std::list >&,abstract_syntax_tree&); void update_closure (std::vector&,int); bool check_condition (std::list >&,abstract_syntax_tree&); int calculation (std::list >&,abstract_syntax_tree&); int assignment (std::list >&,abstract_syntax_tree&,int); int call_identifier (std::list >&,abstract_syntax_tree&); void definition (std::list >&,std::map&,abstract_syntax_tree&); int loop_expr (std::list >&,abstract_syntax_tree&); int conditional (std::list >&,abstract_syntax_tree&); int block_proc (std::list >&,abstract_syntax_tree&); int func_proc (std::list >&,std::list >&,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);// checked int builtin_function (std::list >&,std::string); public: nasal_runtime() { global_scope.clear(); nasal_gc.gc_init(); return; } ~nasal_runtime() { global_scope.clear(); nasal_gc.gc_init(); return; } void main_proc(abstract_syntax_tree&); }; void nasal_runtime::error_interrupt(const int type,const int line) { std::cout<<">> [Runtime] line "< >& local_scope,std::list::iterator& call_node,int addr) { // check the scalar type of called identifier here int called_type=nasal_gc.get_scalar(addr).get_type(); if(call_node->get_children().size()==1 && called_type!=scalar_vector && called_type!=scalar_hash) { error_interrupt(__error_value_type_when_calling_vector,call_node->get_node_line()); return -1; } if(call_node->get_children().size()>1 && called_type!=scalar_vector) { error_interrupt(__error_value_type_when_calling_vector,call_node->get_node_line()); return -1; } if(call_node->get_children().size()==1) { if(call_node->get_children().front().get_node_type()==__sub_vector) { if(called_type==scalar_hash) { error_interrupt(__not_callable_vector,call_node->get_node_line()); return -1; } int num1_addr=-1; int num2_addr=-1; // identifier[num1:]; if(call_node->get_children().front().get_children().size()==1) { num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front()); if(num1_addr<0) return -1; } // identifier[num1:num2]; else { num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front()); num2_addr=calculation(local_scope,call_node->get_children().front().get_children().back()); if(num1_addr<0 || num2_addr<0) return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil)) { error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().back().get_node_line()); return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().front().get_node_line()); return -1; } nasal_gc.reference_delete(num1_addr); num1_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num1_addr).set_type(scalar_number); nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().front().get_node_line()); return -1; } } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().back().get_node_line()); return -1; } nasal_gc.reference_delete(num2_addr); num2_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num2_addr).set_type(scalar_number); nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().back().get_node_line()); return -1; } } if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().back().get_node_line()); return -1; } int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number(); int end_num=0; if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil) end_num=nasal_gc.get_scalar(addr).get_vector().get_size(); else end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number(); if(num1_addr>=0) nasal_gc.reference_delete(num1_addr); if(num2_addr>=0) nasal_gc.reference_delete(num2_addr); std::vector subvec_result; for(int i=begin_num;iget_children().front().get_children().front().get_node_line()); return -1; } switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } subvec_result.push_back(new_addr); } int tmp_addr=addr; addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr).set_type(scalar_vector); for(int i=0;iget_children().front()); if(data_addr<0) return -1; if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_number && nasal_gc.get_scalar(data_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_node_line()); return -1; } if(called_type==scalar_vector) { double place_num=0; if(nasal_gc.get_scalar(data_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(data_addr).get_string().get_string())) place_num=(int)trans_string_to_number(nasal_gc.get_scalar(data_addr).get_string().get_string()); else { error_interrupt(__not_numerable_str,call_node->get_children().front().get_node_line()); return -1; } } else if(nasal_gc.get_scalar(data_addr).get_type()==scalar_number) place_num=nasal_gc.get_scalar(data_addr).get_number().get_number(); if(place_num>2147483647 || place_num<-2147483648) { error_interrupt(__normal_call_vector_too_large_value,call_node->get_children().front().get_node_line()); return -1; } int tmp_data_addr=nasal_gc.get_scalar(addr).get_vector().get_elem((int)place_num); if(tmp_data_addr<0) { error_interrupt(__invalid_vector_member,call_node->get_children().front().get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } int tmp_addr=addr; addr=new_addr; nasal_gc.reference_delete(tmp_addr); } else if(called_type==scalar_hash) { if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_hash,call_node->get_children().front().get_node_line()); return -1; } int tmp_data_addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(nasal_gc.get_scalar(data_addr).get_string().get_string()); if(tmp_data_addr<0) { error_interrupt(__invalid_hash_member,call_node->get_children().front().get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } int tmp_addr=addr; addr=new_addr; nasal_gc.reference_delete(tmp_addr); } nasal_gc.reference_delete(data_addr); } } else if(call_node->get_children().size()>1) { int generated_subvec_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(generated_subvec_addr).set_type(scalar_vector); for(std::list::iterator i=call_node->get_children().begin();i!=call_node->get_children().end();++i) { if(i->get_node_type()==__sub_vector) { if(called_type==scalar_hash) { error_interrupt(__not_callable_vector,i->get_node_line()); return -1; } int num1_addr=-1; int num2_addr=-1; // identifier[num1:]; if(i->get_children().size()==1) { num1_addr=calculation(local_scope,i->get_children().front()); if(num1_addr<0) return -1; } // identifier[num1:num2]; else { num1_addr=calculation(local_scope,i->get_children().front()); num2_addr=calculation(local_scope,i->get_children().back()); if(num1_addr<0 || num2_addr<0) return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,i->get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil)) { error_interrupt(__error_value_type_when_calling_vector,i->get_children().back().get_node_line()); return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,i->get_children().front().get_node_line()); return -1; } nasal_gc.reference_delete(num1_addr); num1_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num1_addr).set_type(scalar_number); nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,i->get_children().front().get_node_line()); return -1; } } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,i->get_children().back().get_node_line()); return -1; } nasal_gc.reference_delete(num2_addr); num2_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num2_addr).set_type(scalar_number); nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,i->get_children().back().get_node_line()); return -1; } } if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,i->get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,i->get_children().back().get_node_line()); return -1; } int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number(); int end_num=0; if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil) end_num=nasal_gc.get_scalar(addr).get_vector().get_size(); else end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number(); if(num1_addr>=0) nasal_gc.reference_delete(num1_addr); if(num2_addr>=0) nasal_gc.reference_delete(num2_addr); std::vector subvec_result; for(int j=begin_num;jget_children().front().get_node_line()); return -1; } switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } subvec_result.push_back(new_addr); } for(int j=0;jget_node_line()); return -1; } double place_num=0; if(nasal_gc.get_scalar(data_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(data_addr).get_string().get_string())) place_num=(int)trans_string_to_number(nasal_gc.get_scalar(data_addr).get_string().get_string()); else { error_interrupt(__not_numerable_str,i->get_node_line()); return -1; } } else if(nasal_gc.get_scalar(data_addr).get_type()==scalar_number) place_num=nasal_gc.get_scalar(data_addr).get_number().get_number(); if(place_num>2147483647 || place_num<-2147483648) { error_interrupt(__normal_call_vector_too_large_value,i->get_node_line()); return -1; } int tmp_data_addr=nasal_gc.get_scalar(addr).get_vector().get_elem((int)place_num); if(tmp_data_addr<0) { error_interrupt(__invalid_vector_member,i->get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } nasal_gc.get_scalar(generated_subvec_addr).get_vector().vec_push(new_addr); nasal_gc.reference_delete(data_addr); } } int tmp_addr=addr; addr=generated_subvec_addr; nasal_gc.reference_delete(tmp_addr); } return addr; } int nasal_runtime::dot_call_hash(std::list >& local_scope,std::list::iterator& call_node,int addr) { if(nasal_gc.get_scalar(addr).get_type()!=scalar_hash) { error_interrupt(__not_callable_hash,call_node->get_node_line()); return -1; } int tmp_data_addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(call_node->get_var_name()); if(tmp_data_addr<0) { error_interrupt(__invalid_hash_member,call_node->get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } int tmp_addr=addr; addr=new_addr; nasal_gc.reference_delete(tmp_addr); return addr; } int nasal_runtime::call_function(std::list >& local_scope,std::list::iterator& call_node,int addr,int last_hash_addr) { if(nasal_gc.get_scalar(addr).get_type()!=scalar_function) { error_interrupt(__not_callable_function,call_node->get_node_line()); return -1; } int tmp_addr=addr; addr=func_proc( local_scope, nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_function().get_local_scope()).get_closure().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_statement_block(), *call_node, last_hash_addr ); if(addr<0) return -1; nasal_gc.reference_delete(tmp_addr); return addr; } int nasal_runtime::vector_generation(std::list >& local_scope,abstract_syntax_tree& node) { int addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr).set_type(scalar_vector); std::list::iterator call_node=node.get_children().end(); for(std::list::iterator i=node.get_children().begin();i!=node.get_children().end();++i) { int var_type=i->get_node_type(); if(var_type==__number) nasal_gc.get_scalar(addr).get_vector().vec_push(number_generation(*i)); else if(var_type==__string) nasal_gc.get_scalar(addr).get_vector().vec_push(string_generation(*i)); else if(var_type==__id) nasal_gc.get_scalar(addr).get_vector().vec_push(call_identifier(local_scope,*i)); else if(var_type==__vector) nasal_gc.get_scalar(addr).get_vector().vec_push(vector_generation(local_scope,*i)); else if(var_type==__hash) nasal_gc.get_scalar(addr).get_vector().vec_push(hash_generation(local_scope,*i)); else if(var_type==__function) nasal_gc.get_scalar(addr).get_vector().vec_push(function_generation(local_scope,*i)); else if(var_type==__id) nasal_gc.get_scalar(addr).get_vector().vec_push(call_identifier(local_scope,*i)); else if(var_type==__add_operator || var_type==__sub_operator || var_type==__mul_operator || var_type==__div_operator || var_type==__link_operator || var_type==__cmp_equal || var_type==__cmp_less || var_type==__cmp_more || var_type==__cmp_not_equal || var_type==__cmp_less_or_equal || var_type==__cmp_more_or_equal || var_type==__and_operator || var_type==__or_operator || var_type==__ques_mark || var_type==__equal || var_type==__add_equal || var_type==__sub_equal || var_type==__div_equal || var_type==__mul_equal || var_type==__link_equal) nasal_gc.get_scalar(addr).get_vector().vec_push(calculation(local_scope,*i)); else { call_node=i; break; } } int last_hash_addr=-1; for(;call_node!=node.get_children().end();++call_node) { if(nasal_gc.get_scalar(addr).get_type()==scalar_hash) { int tmp_hash_addr=last_hash_addr; last_hash_addr=addr; nasal_gc.reference_add(last_hash_addr); if(tmp_hash_addr>=0) nasal_gc.reference_delete(tmp_hash_addr); } // call vector/special call hash/subvec // the special type of calling hash like a["name"] is also generated as calling vector if(call_node->get_node_type()==__call_vector) addr=bracket_call_vector(local_scope,call_node,addr); // call hash identifier.identifier else if(call_node->get_node_type()==__call_hash) addr=dot_call_hash(local_scope,call_node,addr); // call function identifier(...) else if(call_node->get_node_type()==__call_function) addr=call_function(local_scope,call_node,addr,last_hash_addr); if(addr<0) break; } return addr; } int nasal_runtime::hash_generation(std::list >& local_scope,abstract_syntax_tree& node) { int addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr).set_type(scalar_hash); std::list::iterator call_node=node.get_children().end(); for(std::list::iterator i=node.get_children().begin();i!=node.get_children().end();++i) { if(i->get_node_type()!=__hash_member) { call_node=i; break; } else { // note:how does nasal_function change the address of me when a hash calls it? // because before calling this function,hash gives the address if itself as a parameter to the function, // and this parameter's name is 'me' std::string member_name=i->get_children().front().get_var_name(); int var_type=i->get_children().back().get_node_type(); if(member_name=="parents") { int vector_addr=-1; if(var_type==__id) vector_addr=call_identifier(local_scope,i->get_children().back()); else if(var_type==__vector) vector_addr=hash_generation(local_scope,i->get_children().back()); else { error_interrupt(__class_inheritence_need_vector,i->get_children().back().get_node_line()); return -1; } if(vector_addr<0) return -1; if(nasal_gc.get_scalar(vector_addr).get_type()!=scalar_vector) { error_interrupt(__class_inheritence_need_vector,i->get_children().back().get_node_line()); return -1; } for(int i=0;iget_children().back())); else if(var_type==__string) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,string_generation(i->get_children().back())); else if(var_type==__id) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,call_identifier(local_scope,i->get_children().back())); else if(var_type==__vector) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,vector_generation(local_scope,i->get_children().back())); else if(var_type==__hash) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,hash_generation(local_scope,i->get_children().back())); else if(var_type==__function) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,function_generation(local_scope,i->get_children().back())); else if(var_type==__add_operator || var_type==__sub_operator || var_type==__mul_operator || var_type==__div_operator || var_type==__link_operator || var_type==__cmp_equal || var_type==__cmp_less || var_type==__cmp_more || var_type==__cmp_not_equal || var_type==__cmp_less_or_equal || var_type==__cmp_more_or_equal || var_type==__and_operator || var_type==__or_operator || var_type==__ques_mark || var_type==__equal || var_type==__add_equal || var_type==__sub_equal || var_type==__div_equal || var_type==__mul_equal || var_type==__link_equal) nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,calculation(local_scope,i->get_children().back())); } } } int last_hash_addr=-1; for(;call_node!=node.get_children().end();++call_node) { if(nasal_gc.get_scalar(addr).get_type()==scalar_hash) { int tmp_hash_addr=last_hash_addr; last_hash_addr=addr; nasal_gc.reference_add(last_hash_addr); if(tmp_hash_addr>=0) nasal_gc.reference_delete(tmp_hash_addr); } // call vector/special call hash/subvec // the special type of calling hash like a["name"] is also generated as calling vector if(call_node->get_node_type()==__call_vector) addr=bracket_call_vector(local_scope,call_node,addr); // call hash identifier.identifier else if(call_node->get_node_type()==__call_hash) addr=dot_call_hash(local_scope,call_node,addr); // call function identifier(...) else if(call_node->get_node_type()==__call_function) addr=call_function(local_scope,call_node,addr,last_hash_addr); if(addr<0) break; } return addr; } int nasal_runtime::function_generation(std::list >& local_scope,abstract_syntax_tree& node) { // function // parameters // block // calls... int addr=nasal_gc.gc_alloc(); int scope_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(scope_addr).set_type(scalar_closure); nasal_gc.get_scalar(scope_addr).get_closure().set_local_scope(local_scope); nasal_gc.get_scalar(addr).set_type(scalar_function); nasal_gc.get_scalar(addr).get_function().set_local_scope(scope_addr); nasal_gc.get_scalar(addr).get_function().set_closure_update_state(false); std::list::iterator i=node.get_children().begin(); nasal_gc.get_scalar(addr).get_function().set_paramemter_list(*i); ++i; nasal_gc.get_scalar(addr).get_function().set_statement_block(*i); ++i; int last_hash_addr=-1; for(std::list::iterator call_node=i;call_node!=node.get_children().end();++call_node) { if(nasal_gc.get_scalar(addr).get_type()==scalar_hash) { int tmp_hash_addr=last_hash_addr; last_hash_addr=addr; nasal_gc.reference_add(last_hash_addr); if(tmp_hash_addr>=0) nasal_gc.reference_delete(tmp_hash_addr); } // call vector/special call hash/subvec // the special type of calling hash like a["name"] is also generated as calling vector if(call_node->get_node_type()==__call_vector) addr=bracket_call_vector(local_scope,call_node,addr); // call hash identifier.identifier else if(call_node->get_node_type()==__call_hash) addr=dot_call_hash(local_scope,call_node,addr); // call function identifier(...) else if(call_node->get_node_type()==__call_function) addr=call_function(local_scope,call_node,addr,last_hash_addr); if(addr<0) break; } return addr; } void nasal_runtime::update_closure(std::vector& update_list,int closure_addr) { // update_closure // each new function will be updated only once, after updating closure,functions' closure_updated flag will be set true int size=update_list.size(); for(int i=0;i >& local_scope,abstract_syntax_tree& node) { bool ret=false; int checked_addr=calculation(local_scope,node); if(checked_addr<0) return false; int checked_type=nasal_gc.get_scalar(checked_addr).get_type(); if(checked_type==scalar_number) ret=(nasal_gc.get_scalar(checked_addr).get_number().get_number()!=0); else if(checked_type==scalar_string) { std::string tmp_str=nasal_gc.get_scalar(checked_addr).get_string().get_string(); if(!tmp_str.length()) ret=false; else if(check_numerable_string(tmp_str)) ret=(trans_string_to_number(tmp_str)!=0); else ret=true;// not numerable string like 'hello' is also true } else { error_interrupt(__error_value_type,node.get_node_line()); return false; } nasal_gc.reference_delete(checked_addr); return ret; } int nasal_runtime::calculation(std::list >& local_scope,abstract_syntax_tree& node) { // calculation will return a value that points to a new area in memory int node_type=node.get_node_type(); if(node_type==__nil) { int ret=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret).set_type(scalar_nil); return ret; } else if(node_type==__number) return number_generation(node); else if(node_type==__string) return string_generation(node); else if(node_type==__vector) return vector_generation(local_scope,node); else if(node_type==__hash) return hash_generation(local_scope,node); else if(node_type==__function) return function_generation(local_scope,node); else if(node_type==__id) return call_identifier(local_scope,node); else if(node_type==__add_operator || node_type==__sub_operator || node_type==__mul_operator || node_type==__div_operator) { // scalar_nil cannot be used here int ret_addr=-1; int addr_1=-1; int addr_2=-1; if(node.get_children().size()==1) { // note: sub operator may mean that this is unary calculation addr_1=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr_1).set_type(scalar_number); nasal_gc.get_scalar(addr_1).get_number().set_number(0); addr_2=calculation(local_scope,node.get_children().front()); } else { addr_1=calculation(local_scope,node.get_children().front()); addr_2=calculation(local_scope,node.get_children().back()); } // check if the address is available if(addr_1<0 || addr_2<0) return -1; int type_1=nasal_gc.get_scalar(addr_1).get_type(); int type_2=nasal_gc.get_scalar(addr_2).get_type(); double num_1=0; double num_2=0; if(type_1==scalar_number && type_2==scalar_number) { num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); } else if(type_1==scalar_number && type_2==scalar_string) { num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); std::string tmp_str=nasal_gc.get_scalar(addr_2).get_string().get_string(); if(check_numerable_string(tmp_str)) num_2=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().back().get_node_line()); return -1; } } else if(type_1==scalar_string && type_2==scalar_number) { std::string tmp_str=nasal_gc.get_scalar(addr_1).get_string().get_string(); if(check_numerable_string(tmp_str)) num_1=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().front().get_node_line()); return -1; } num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); } else if(type_1==scalar_string && type_2==scalar_string) { std::string tmp_str_1=nasal_gc.get_scalar(addr_1).get_string().get_string(); std::string tmp_str_2=nasal_gc.get_scalar(addr_2).get_string().get_string(); if(check_numerable_string(tmp_str_1) && check_numerable_string(tmp_str_2)) { num_1=trans_string_to_number(tmp_str_1); num_2=trans_string_to_number(tmp_str_2); } else { error_interrupt(__not_numerable_str,node.get_node_line()); return -1; } } else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); switch(node_type) { case __add_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1+num_2);break; case __sub_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1-num_2);break; case __mul_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1*num_2);break; case __div_operator:nasal_gc.get_scalar(ret_addr).get_number().set_number(num_1/num_2);break; } nasal_gc.reference_delete(addr_1); nasal_gc.reference_delete(addr_2); return ret_addr; } else if(node_type==__link_operator) { // scalar_nil cannot be used here int ret_addr=-1; int addr_1=calculation(local_scope,node.get_children().front()); int addr_2=calculation(local_scope,node.get_children().back()); // check if the address is available if(addr_1<0 || addr_2<0) return -1; int type_1=nasal_gc.get_scalar(addr_1).get_type(); int type_2=nasal_gc.get_scalar(addr_2).get_type(); std::string str_1; std::string str_2; if(type_1==scalar_number && type_2==scalar_number) { str_1=trans_number_to_string(nasal_gc.get_scalar(addr_1).get_number().get_number()); str_2=trans_number_to_string(nasal_gc.get_scalar(addr_2).get_number().get_number()); } else if(type_1==scalar_number && type_2==scalar_string) { str_1=trans_number_to_string(nasal_gc.get_scalar(addr_1).get_number().get_number()); str_2=nasal_gc.get_scalar(addr_2).get_string().get_string(); } else if(type_1==scalar_string && type_2==scalar_number) { str_1=nasal_gc.get_scalar(addr_1).get_string().get_string(); str_2=trans_number_to_string(nasal_gc.get_scalar(addr_2).get_number().get_number()); } else if(type_1==scalar_string && type_2==scalar_string) { str_1=nasal_gc.get_scalar(addr_1).get_string().get_string(); str_2=nasal_gc.get_scalar(addr_2).get_string().get_string(); } else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_string); nasal_gc.get_scalar(ret_addr).get_string().set_string(str_1+str_2); nasal_gc.reference_delete(addr_1); nasal_gc.reference_delete(addr_2); return ret_addr; } else if(node_type==__cmp_equal || node_type==__cmp_not_equal) { int ret_addr=-1; int addr_1=calculation(local_scope,node.get_children().front()); int addr_2=calculation(local_scope,node.get_children().back()); // check if the address is available if(addr_1<0 || addr_2<0) return -1; int type_1=nasal_gc.get_scalar(addr_1).get_type(); int type_2=nasal_gc.get_scalar(addr_2).get_type(); // note: cmp operator change strings into numbers then making comparation ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); if(type_1==scalar_number && type_2==scalar_number) { double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?num_1==num_2:num_1!=num_2))); } else if(type_1==scalar_number && type_2==scalar_string) { double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); double num_2=0; std::string tmp_str=nasal_gc.get_scalar(addr_2).get_string().get_string(); if(check_numerable_string(tmp_str)) num_2=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().back().get_node_line()); return -1; } nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?num_1==num_2:num_1!=num_2))); } else if(type_1==scalar_string && type_2==scalar_number) { double num_1=0; double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); std::string tmp_str=nasal_gc.get_scalar(addr_1).get_string().get_string(); if(check_numerable_string(tmp_str)) num_1=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().front().get_node_line()); return -1; } nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?num_1==num_2:num_1!=num_2))); } else if(type_1==scalar_string && type_2==scalar_string) { std::string str_1=nasal_gc.get_scalar(addr_1).get_string().get_string(); std::string str_2=nasal_gc.get_scalar(addr_2).get_string().get_string(); nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?str_1==str_2:str_1!=str_2))); } else if(type_1==scalar_vector && type_2==scalar_vector) nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?addr_1==addr_2:addr_1!=addr_2))); else if(type_1==scalar_hash && type_2==scalar_hash) nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?addr_1==addr_2:addr_1!=addr_2))); else if(type_1==scalar_function && type_2==scalar_function) nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal?addr_1==addr_2:addr_1!=addr_2))); else if(type_1==scalar_nil && type_2==scalar_nil) nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type==__cmp_equal))); else if(type_1!=type_2) nasal_gc.get_scalar(ret_addr).get_number().set_number((double(node_type!=__cmp_equal))); else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } nasal_gc.reference_delete(addr_1); nasal_gc.reference_delete(addr_2); return ret_addr; } else if(node_type==__cmp_less || node_type==__cmp_less_or_equal || node_type==__cmp_more || node_type==__cmp_more_or_equal) { int ret_addr=-1; int addr_1=calculation(local_scope,node.get_children().front()); int addr_2=calculation(local_scope,node.get_children().back()); // check if the address is available if(addr_1<0 || addr_2<0) return -1; int type_1=nasal_gc.get_scalar(addr_1).get_type(); int type_2=nasal_gc.get_scalar(addr_2).get_type(); // note: cmp operator change strings into numbers then making comparation // only numbers and strings can take these calculations ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); if(type_1==scalar_number && type_2==scalar_number) { double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); switch(node_type) { case __cmp_less: nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1num_2)));break; case __cmp_more_or_equal:nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1>=num_2)));break; } } else if(type_1==scalar_number && type_2==scalar_string) { double num_1=nasal_gc.get_scalar(addr_1).get_number().get_number(); double num_2=0; std::string tmp_str=nasal_gc.get_scalar(addr_2).get_string().get_string(); if(check_numerable_string(tmp_str)) num_2=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().back().get_node_line()); return -1; } switch(node_type) { case __cmp_less: nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1num_2)));break; case __cmp_more_or_equal:nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1>=num_2)));break; } } else if(type_1==scalar_string && type_2==scalar_number) { double num_1=0; double num_2=nasal_gc.get_scalar(addr_2).get_number().get_number(); std::string tmp_str=nasal_gc.get_scalar(addr_1).get_string().get_string(); if(check_numerable_string(tmp_str)) num_1=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().front().get_node_line()); return -1; } switch(node_type) { case __cmp_less: nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1num_2)));break; case __cmp_more_or_equal:nasal_gc.get_scalar(ret_addr).get_number().set_number((double(num_1>=num_2)));break; } } else if(type_1==scalar_string && type_2==scalar_string) { std::string str_1=nasal_gc.get_scalar(addr_1).get_string().get_string(); std::string str_2=nasal_gc.get_scalar(addr_2).get_string().get_string(); switch(node_type) { case __cmp_less: nasal_gc.get_scalar(ret_addr).get_number().set_number((double(str_1str_2)));break; case __cmp_more_or_equal:nasal_gc.get_scalar(ret_addr).get_number().set_number((double(str_1>=str_2)));break; } } else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } nasal_gc.reference_delete(addr_1); nasal_gc.reference_delete(addr_2); return ret_addr; } else if(node_type==__equal) { // scalar_function needs 'me' changement here // but now it is unfinished int child_node_type_1=node.get_children().front().get_node_type(); int child_node_type_2=node.get_children().back().get_node_type(); if(child_node_type_1==__multi_scalar) { std::vector assignment_ast; for(std::list::iterator i=node.get_children().front().get_children().begin();i!=node.get_children().front().get_children().end();++i) assignment_ast.push_back(&(*i)); if(assignment_ast.empty()) return -1; if(child_node_type_2==__multi_scalar) { std::vector data_addrs; for(std::list::iterator i=node.get_children().back().get_children().begin();i!=node.get_children().back().get_children().end();++i) { int new_addr=calculation(local_scope,*i); if(new_addr<0) return -1; data_addrs.push_back(new_addr); } if(data_addrs.size()!=assignment_ast.size()) { error_interrupt(__multi_assign_incorrect_value_number,node.get_children().back().get_node_line()); return -1; } // multi assignment doesn't have returned value // because multi assignment cannot be used in calculation expression for(int i=0;i=0) nasal_gc.reference_delete(tmp_addr); } for(int i=0;i=0) nasal_gc.reference_delete(tmp_addr); } nasal_gc.reference_delete(data_addr); } return -1; } else { int ret_addr=-1; abstract_syntax_tree* assignment_ast=&node.get_children().front(); int data_addr=calculation(local_scope,node.get_children().back()); if(data_addr<0) return -1; ret_addr=assignment(local_scope,*assignment_ast,data_addr); nasal_gc.reference_delete(data_addr); return ret_addr; } return -1; } else if(node_type==__add_equal || node_type==__sub_equal || node_type==__mul_equal || node_type==__div_equal) { // scalar_nil also cannot be used here // += -= *= /= ~= only works on scalar_number and scalar_string int id_addr=calculation(local_scope,node.get_children().front()); int value_addr=calculation(local_scope,node.get_children().back()); if(id_addr<0 || value_addr<0) return -1; int type_1=nasal_gc.get_scalar(id_addr).get_type(); int type_2=nasal_gc.get_scalar(value_addr).get_type(); double num_1=0; double num_2=0; if(type_1==scalar_number && type_2==scalar_number) { num_1=nasal_gc.get_scalar(id_addr).get_number().get_number(); num_2=nasal_gc.get_scalar(value_addr).get_number().get_number(); } else if(type_1==scalar_number && type_2==scalar_string) { num_1=nasal_gc.get_scalar(id_addr).get_number().get_number(); std::string tmp_str=nasal_gc.get_scalar(value_addr).get_string().get_string(); if(check_numerable_string(tmp_str)) num_2=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().back().get_node_line()); return -1; } } else if(type_1==scalar_string && type_2==scalar_number) { std::string tmp_str=nasal_gc.get_scalar(id_addr).get_string().get_string(); if(check_numerable_string(tmp_str)) num_1=trans_string_to_number(tmp_str); else { error_interrupt(__not_numerable_str,node.get_children().front().get_node_line()); return -1; } num_2=nasal_gc.get_scalar(value_addr).get_number().get_number(); } else if(type_1==scalar_string && type_2==scalar_string) { std::string tmp_str_1=nasal_gc.get_scalar(id_addr).get_string().get_string(); std::string tmp_str_2=nasal_gc.get_scalar(value_addr).get_string().get_string(); if(check_numerable_string(tmp_str_1) && check_numerable_string(tmp_str_2)) { num_1=trans_string_to_number(tmp_str_1); num_2=trans_string_to_number(tmp_str_2); } else { error_interrupt(__not_numerable_str,node.get_node_line()); return -1; } } else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } if(nasal_gc.get_scalar(id_addr).get_type()==scalar_string) { nasal_gc.get_scalar(id_addr).get_string().set_clear(); nasal_gc.get_scalar(id_addr).set_type(scalar_number); } switch(node_type) { case __add_equal:nasal_gc.get_scalar(id_addr).get_number().set_number(num_1+num_2);break; case __sub_equal:nasal_gc.get_scalar(id_addr).get_number().set_number(num_1-num_2);break; case __mul_equal:nasal_gc.get_scalar(id_addr).get_number().set_number(num_1*num_2);break; case __div_equal:nasal_gc.get_scalar(id_addr).get_number().set_number(num_1/num_2);break; } nasal_gc.reference_delete(value_addr); return id_addr; } else if(node_type==__link_equal) { // scalar_nil also cannot be used here // += -= *= /= ~= only works on scalar_number and scalar_string int id_addr=calculation(local_scope,node.get_children().front()); int value_addr=calculation(local_scope,node.get_children().back()); if(id_addr<0 || value_addr<0) return -1; int type_1=nasal_gc.get_scalar(id_addr).get_type(); int type_2=nasal_gc.get_scalar(value_addr).get_type(); std::string str_1,str_2; if(type_1==scalar_number && type_2==scalar_number) { str_1=trans_number_to_string(nasal_gc.get_scalar(id_addr).get_number().get_number()); str_2=trans_number_to_string(nasal_gc.get_scalar(value_addr).get_number().get_number()); } else if(type_1==scalar_number && type_2==scalar_string) { str_1=trans_number_to_string(nasal_gc.get_scalar(id_addr).get_number().get_number()); str_2=nasal_gc.get_scalar(value_addr).get_string().get_string(); } else if(type_1==scalar_string && type_2==scalar_number) { str_1=nasal_gc.get_scalar(id_addr).get_string().get_string(); str_2=trans_number_to_string(nasal_gc.get_scalar(value_addr).get_number().get_number()); } else if(type_1==scalar_string && type_2==scalar_string) { str_1=nasal_gc.get_scalar(id_addr).get_string().get_string(); str_2=nasal_gc.get_scalar(value_addr).get_string().get_string(); } else { error_interrupt(__error_value_type,node.get_node_line()); return -1; } if(nasal_gc.get_scalar(id_addr).get_type()==scalar_number) { nasal_gc.get_scalar(id_addr).get_number().set_clear(); nasal_gc.get_scalar(id_addr).set_type(scalar_string); } nasal_gc.get_scalar(id_addr).get_string().set_string(str_1+str_2); nasal_gc.reference_delete(value_addr); return id_addr; } else if(node_type==__and_operator) { // and will return the last value that is not null // if and gets a null,and returns 0 // vector,hash,function is not allowed here int ret_addr=-1; int val_addr=calculation(local_scope,node.get_children().front()); if(val_addr<0) return -1; int val_type=nasal_gc.get_scalar(val_addr).get_type(); if(val_type==scalar_number) { double num=nasal_gc.get_scalar(val_addr).get_number().get_number(); if(num==0) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else nasal_gc.reference_delete(val_addr); } else if(val_type==scalar_string) { std::string str=nasal_gc.get_scalar(val_addr).get_string().get_string(); if(str.length()==0 || (check_numerable_string(str) && trans_string_to_number(str)==0)) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else nasal_gc.reference_delete(val_addr); } else { error_interrupt(__error_value_type,node.get_children().front().get_node_line()); return -1; } val_addr=calculation(local_scope,node.get_children().back()); if(val_addr<0) return -1; val_type=nasal_gc.get_scalar(val_addr).get_type(); if(val_type==scalar_number) { double num=nasal_gc.get_scalar(val_addr).get_number().get_number(); if(num==0) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else ret_addr=val_addr; } else if(val_type==scalar_string) { std::string str=nasal_gc.get_scalar(val_addr).get_string().get_string(); if(str.length()==0 || (check_numerable_string(str) && trans_string_to_number(str)==0)) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else ret_addr=val_addr; } else { error_interrupt(__error_value_type,node.get_children().back().get_node_line()); return -1; } return ret_addr; } else if(node_type==__or_operator) { // or will return the first value that is not null // if or gets all null(0,'0',nil,"0",'',""),or returns 0 // vector,hash,function is not allowed here int ret_addr=-1; int val_addr=calculation(local_scope,node.get_children().front()); if(val_addr<0) return -1; int val_type=nasal_gc.get_scalar(val_addr).get_type(); if(val_type==scalar_number) { double num=nasal_gc.get_scalar(val_addr).get_number().get_number(); if(num!=0) return val_addr; else nasal_gc.reference_delete(val_addr); } else if(val_type==scalar_string) { std::string str=nasal_gc.get_scalar(val_addr).get_string().get_string(); if(str.length()!=0 && (!check_numerable_string(str) || !trans_string_to_number(str)==0)) return val_addr; else nasal_gc.reference_delete(val_addr); } else { error_interrupt(__error_value_type,node.get_children().front().get_node_line()); return -1; } val_addr=calculation(local_scope,node.get_children().back()); if(val_addr<0) return -1; val_type=nasal_gc.get_scalar(val_addr).get_type(); if(val_type==scalar_number) { double num=nasal_gc.get_scalar(val_addr).get_number().get_number(); if(num==0) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else return val_addr; } else if(val_type==scalar_string) { std::string str=nasal_gc.get_scalar(val_addr).get_string().get_string(); if(str.length()==0 || (check_numerable_string(str) && trans_string_to_number(str)==0)) { ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number(0); nasal_gc.reference_delete(val_addr); return ret_addr; } else return val_addr; } else { error_interrupt(__error_value_type,node.get_children().back().get_node_line()); return -1; } return -1; } else if(node_type==__nor_operator) { // nor will return 0 if the value is not null // nor will return 1 if the value is null(0,nil,'0',"0",'',"") // vector,hash,function is not allowed here int ret_addr=-1; bool checked_result=check_condition(local_scope,node.get_children().front()); ret_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(ret_addr).set_type(scalar_number); nasal_gc.get_scalar(ret_addr).get_number().set_number((double)checked_result); return ret_addr; } else if(node_type==__ques_mark) { // ?: // this will return the first element if the condition is true // this will return the second element if the condition is null(0,nil,"0",'0',"",'',"0x0","0o0") std::list::iterator ptr=node.get_children().begin(); if(check_condition(local_scope,*ptr)) { ++ptr; return calculation(local_scope,*ptr); } else { ++ptr;++ptr; return calculation(local_scope,*ptr); } return -1; } return -1; } int nasal_runtime::assignment(std::list >& local_scope,abstract_syntax_tree& node,int used_data_addr) { int* assigned_addr=NULL; std::string tmp_id_name=node.get_var_name(); if(global_scope.find(tmp_id_name)!=global_scope.end()) assigned_addr=&(global_scope[tmp_id_name]); for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) if(iter->find(tmp_id_name)!=iter->end()) assigned_addr=&((*iter)[tmp_id_name]); if(!assigned_addr) return -1; std::vector tmp_subvec_addr; for(std::list::iterator iter=node.get_children().begin();iter!=node.get_children().end();++iter) { // call vector/special call hash/subvec // the special type of calling hash like a["name"] is also generated as calling vector if(iter->get_node_type()==__call_vector) { // check the scalar type of called identifier here int called_type=-1; if(!assigned_addr && tmp_subvec_addr.size()) called_type=nasal_gc.get_scalar(tmp_subvec_addr.back()).get_type(); else if(assigned_addr) called_type=nasal_gc.get_scalar(*assigned_addr).get_type(); if(iter->get_children().size()==1 && called_type!=scalar_vector && called_type!=scalar_hash) { error_interrupt(__error_value_type_when_calling_vector,iter->get_node_line()); return -1; } if(iter->get_children().size()>1 && called_type!=scalar_vector) { error_interrupt(__error_value_type_when_calling_vector,iter->get_node_line()); return -1; } if(iter->get_children().size()==1) { if(iter->get_children().front().get_node_type()==__sub_vector) { if(called_type==scalar_hash) { error_interrupt(__not_callable_vector,iter->get_node_line()); return -1; } int num1_addr=-1; int num2_addr=-1; // identifier[num1:]; if(iter->get_children().front().get_children().size()==1) { num1_addr=calculation(local_scope,iter->get_children().front().get_children().front()); if(num1_addr<0) return -1; } // identifier[num1:num2]; else { num1_addr=calculation(local_scope,iter->get_children().front().get_children().front()); num2_addr=calculation(local_scope,iter->get_children().front().get_children().back()); if(num1_addr<0 || num2_addr<0) return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,iter->get_children().front().get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil)) { error_interrupt(__error_value_type_when_calling_vector,iter->get_children().front().get_children().back().get_node_line()); return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,iter->get_children().front().get_children().front().get_node_line()); return -1; } nasal_gc.reference_delete(num1_addr); num1_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num1_addr).set_type(scalar_number); nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,iter->get_children().front().get_children().front().get_node_line()); return -1; } } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,iter->get_children().front().get_children().back().get_node_line()); return -1; } nasal_gc.reference_delete(num2_addr); num2_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num2_addr).set_type(scalar_number); nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,iter->get_children().front().get_children().back().get_node_line()); return -1; } } if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,iter->get_children().front().get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,iter->get_children().front().get_children().back().get_node_line()); return -1; } int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number(); int end_num=0; if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil) { if(!assigned_addr && tmp_subvec_addr.size()) end_num=nasal_gc.get_scalar(tmp_subvec_addr.back()).get_vector().get_size(); else if(assigned_addr) end_num=nasal_gc.get_scalar(*assigned_addr).get_vector().get_size(); } else end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number(); if(num1_addr>=0) nasal_gc.reference_delete(num1_addr); if(num2_addr>=0) nasal_gc.reference_delete(num2_addr); std::vector subvec_result; for(int i=begin_num;iget_children().front().get_children().front().get_node_line()); return -1; } switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } subvec_result.push_back(new_addr); } int tmp_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(tmp_addr).set_type(scalar_vector); for(int i=0;iget_children().front()); if(tmp_data_addr<0) return -1; if(nasal_gc.get_scalar(tmp_data_addr).get_type()!=scalar_number && nasal_gc.get_scalar(tmp_data_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,iter->get_children().front().get_node_line()); return -1; } if(called_type==scalar_vector) { double place_num=0; if(nasal_gc.get_scalar(tmp_data_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(tmp_data_addr).get_string().get_string())) place_num=(int)trans_string_to_number(nasal_gc.get_scalar(tmp_data_addr).get_string().get_string()); else { error_interrupt(__not_numerable_str,iter->get_children().front().get_node_line()); return -1; } } else if(nasal_gc.get_scalar(tmp_data_addr).get_type()==scalar_number) place_num=nasal_gc.get_scalar(tmp_data_addr).get_number().get_number(); if(place_num>2147483647 || place_num<-2147483648) { error_interrupt(__normal_call_vector_too_large_value,iter->get_children().front().get_node_line()); return -1; } if(!assigned_addr && tmp_subvec_addr.size()) assigned_addr=nasal_gc.get_scalar(tmp_subvec_addr.back()).get_vector().get_elem_addr((int)place_num); else if(assigned_addr) assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_vector().get_elem_addr((int)place_num); if(!assigned_addr) { error_interrupt(__invalid_vector_member,iter->get_children().front().get_node_line()); return -1; } } else if(called_type==scalar_hash) { if(nasal_gc.get_scalar(tmp_data_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_hash,iter->get_children().front().get_node_line()); return -1; } // only subvec's addr is stored in tmp_subvec_addr // so hash doesn't need to do this assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_hash().get_hash_member_addr(nasal_gc.get_scalar(tmp_data_addr).get_string().get_string()); if(!assigned_addr) { error_interrupt(__invalid_hash_member,iter->get_children().front().get_node_line()); return -1; } } nasal_gc.reference_delete(tmp_data_addr); } } else if(iter->get_children().size()>1) { int generated_subvec_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(generated_subvec_addr).set_type(scalar_vector); for(std::list::iterator i=iter->get_children().begin();i!=iter->get_children().end();++i) { if(i->get_node_type()==__sub_vector) { if(called_type==scalar_hash) { error_interrupt(__not_callable_vector,i->get_node_line()); return -1; } int num1_addr=-1; int num2_addr=-1; // identifier[num1:]; if(i->get_children().size()==1) { num1_addr=calculation(local_scope,i->get_children().front()); if(num1_addr<0) return -1; } // identifier[num1:num2]; else { num1_addr=calculation(local_scope,i->get_children().front()); num2_addr=calculation(local_scope,i->get_children().back()); if(num1_addr<0 || num2_addr<0) return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string) { error_interrupt(__error_value_type_when_calling_vector,i->get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string && nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil)) { error_interrupt(__error_value_type_when_calling_vector,i->get_children().back().get_node_line()); return -1; } if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,i->get_children().front().get_node_line()); return -1; } nasal_gc.reference_delete(num1_addr); num1_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num1_addr).set_type(scalar_number); nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,i->get_children().front().get_node_line()); return -1; } } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string())) { double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string()); if(tmp_num<0) { error_interrupt(__special_call_vector_negative_value,i->get_children().back().get_node_line()); return -1; } nasal_gc.reference_delete(num2_addr); num2_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(num2_addr).set_type(scalar_number); nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num); } else { error_interrupt(__not_numerable_str,i->get_children().back().get_node_line()); return -1; } } if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,i->get_children().front().get_node_line()); return -1; } if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647) { error_interrupt(__special_call_vector_too_large_value,i->get_children().back().get_node_line()); return -1; } int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number(); int end_num=0; if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil) { if(!assigned_addr && tmp_subvec_addr.size()) end_num=nasal_gc.get_scalar(tmp_subvec_addr.back()).get_vector().get_size(); else if(assigned_addr) end_num=nasal_gc.get_scalar(*assigned_addr).get_vector().get_size(); } else end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number(); if(num1_addr>=0) nasal_gc.reference_delete(num1_addr); if(num2_addr>=0) nasal_gc.reference_delete(num2_addr); std::vector subvec_result; for(int j=begin_num;jget_children().front().get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } subvec_result.push_back(new_addr); } for(int j=0;jget_node_line()); return -1; } double place_num=0; if(nasal_gc.get_scalar(data_addr).get_type()==scalar_string) { if(check_numerable_string(nasal_gc.get_scalar(data_addr).get_string().get_string())) place_num=(int)trans_string_to_number(nasal_gc.get_scalar(data_addr).get_string().get_string()); else { error_interrupt(__not_numerable_str,i->get_node_line()); return -1; } } else if(nasal_gc.get_scalar(data_addr).get_type()==scalar_number) place_num=nasal_gc.get_scalar(data_addr).get_number().get_number(); if(place_num>2147483647 || place_num<-2147483648) { error_interrupt(__normal_call_vector_too_large_value,i->get_node_line()); return -1; } int tmp_data_addr=-1; if(!assigned_addr && tmp_subvec_addr.size()) tmp_data_addr=nasal_gc.get_scalar(tmp_subvec_addr.back()).get_vector().get_elem((int)place_num); else if(assigned_addr) tmp_data_addr=nasal_gc.get_scalar(*assigned_addr).get_vector().get_elem((int)place_num); if(tmp_data_addr<0) { error_interrupt(__invalid_vector_member,i->get_node_line()); return -1; } int new_addr=-1; switch(nasal_gc.get_scalar(tmp_data_addr).get_type()) { case scalar_nil: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_nil); break; case scalar_number: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_number); nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number()); break; case scalar_string: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_string); nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string()); break; case scalar_function: new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(scalar_function); nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function()); break; case scalar_vector: case scalar_hash: new_addr=tmp_data_addr; nasal_gc.reference_add(new_addr); break; } nasal_gc.get_scalar(generated_subvec_addr).get_vector().vec_push(new_addr); nasal_gc.reference_delete(data_addr); } } tmp_subvec_addr.push_back(generated_subvec_addr); assigned_addr=NULL; } }// end call vector // call hash identifier.identifier else if(iter->get_node_type()==__call_hash) { if(nasal_gc.get_scalar(*assigned_addr).get_type()!=scalar_hash) { error_interrupt(__not_callable_hash,iter->get_node_line()); return -1; } assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_hash().get_hash_member_addr(iter->get_var_name()); if(!assigned_addr) { error_interrupt(__invalid_hash_member,iter->get_node_line()); return -1; } }// end call hash // call function identifier(...) else if(iter->get_node_type()==__call_function) { error_interrupt(__function_returned_value_be_assigned,iter->get_node_line()); return -1; } } if(assigned_addr) { // delete the value that assigned_addr points to and update it with a new one nasal_gc.reference_delete(*assigned_addr); switch(nasal_gc.get_scalar(used_data_addr).get_type()) { case scalar_nil: *assigned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(*assigned_addr).set_type(scalar_nil); break; case scalar_number: *assigned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(*assigned_addr).set_type(scalar_number); nasal_gc.get_scalar(*assigned_addr).get_number().deep_copy(nasal_gc.get_scalar(used_data_addr).get_number()); break; case scalar_string: *assigned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(*assigned_addr).set_type(scalar_string); nasal_gc.get_scalar(*assigned_addr).get_string().deep_copy(nasal_gc.get_scalar(used_data_addr).get_string()); break; case scalar_function: *assigned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(*assigned_addr).set_type(scalar_function); nasal_gc.get_scalar(*assigned_addr).get_function().deep_copy(nasal_gc.get_scalar(used_data_addr).get_function()); break; case scalar_vector: case scalar_hash: *assigned_addr=used_data_addr; nasal_gc.reference_add(used_data_addr); break; } } else { error_interrupt(__subvec_value_be_assigned,node.get_children().back().get_node_line()); return -1; } /* assigned_addr=find_address(); while(children.size()) { assigned_addr=new_addr(); } *assigned_addr->refcnt--; *assigned_addr=new_value_addr; */ // data_addr is only a parameter here,and it's refcnt has not been changed when using it here nasal_gc.reference_add(*assigned_addr); for(int i=0;i >& local_scope,abstract_syntax_tree& node) { int addr=-1; std::string tmp_id_name=node.get_var_name(); if(global_scope.find(tmp_id_name)!=global_scope.end()) addr=global_scope[tmp_id_name]; for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) if(iter->find(tmp_id_name)!=iter->end()) addr=(*iter)[tmp_id_name]; if(addr>0 && !nasal_gc.get_reference(addr)) { std::cout<<">> [Runtime] line "<=0) return addr; } if(addr<0) { error_interrupt(__undefined_identifier,node.get_node_line()); return -1; } int last_hash_addr=-1; // after calculation or assignment/definition,reference counter of this address will -1 // to avoid nasal_gc collecting this address,reference counter+1 here nasal_gc.reference_add(addr); for(std::list::iterator iter=node.get_children().begin();iter!=node.get_children().end();++iter) { if(nasal_gc.get_scalar(addr).get_type()==scalar_hash) { int tmp_hash_addr=last_hash_addr; last_hash_addr=addr; nasal_gc.reference_add(last_hash_addr); if(tmp_hash_addr>=0) nasal_gc.reference_delete(tmp_hash_addr); } // call vector/special call hash/subvec // the special type of calling hash like a["name"] is also generated as calling vector if(iter->get_node_type()==__call_vector) addr=bracket_call_vector(local_scope,iter,addr); // call hash identifier.identifier else if(iter->get_node_type()==__call_hash) addr=dot_call_hash(local_scope,iter,addr); // call function identifier(...) else if(iter->get_node_type()==__call_function) addr=call_function(local_scope,iter,addr,last_hash_addr); if(addr<0) break; } return addr; } void nasal_runtime::definition(std::list >&local_scope,std::map& now_scope,abstract_syntax_tree& node) { if(node.get_children().front().get_node_type()==__multi_id) { std::vector id_names; for(std::list::iterator i=node.get_children().front().get_children().begin();i!=node.get_children().front().get_children().end();++i) id_names.push_back(i->get_var_name()); int child_node_type=node.get_children().back().get_node_type(); if(child_node_type==__multi_scalar) { std::vector data_addrs; for(std::list::iterator i=node.get_children().back().get_children().begin();i!=node.get_children().back().get_children().end();++i) { int new_addr=calculation(local_scope,*i); if(new_addr<0) return; data_addrs.push_back(new_addr); } if(data_addrs.size()!=id_names.size()) { error_interrupt(__multi_define_incorrect_value_number,node.get_children().back().get_node_line()); return; } for(int i=0;i >& local_scope,abstract_syntax_tree& node) { std::map new_scope; local_scope.push_back(new_scope); int loop_type=node.get_node_type(); int state=__state_no_operation; if(loop_type==__while) { while(check_condition(local_scope,node.get_children().front())) { state=block_proc(local_scope,node.get_children().back()); if(state==__state_break || state==__state_return || state==__state_error) break; } } else if(loop_type==__foreach) { // foreach(i;vector) // foreach gives elements in the vector to the identifier 'i' and the 'i' will take part in calculation std::list::iterator iter=node.get_children().begin(); abstract_syntax_tree& assignment_ast=*iter;// definition/assignment if(iter->get_node_type()==__definition) { std::string identifier_name=iter->get_children().front().get_var_name(); int new_identifier_addr=nasal_gc.gc_alloc(); local_scope.back()[identifier_name]=new_identifier_addr; nasal_gc.get_scalar(new_identifier_addr).set_type(scalar_nil); assignment_ast=iter->get_children().front(); } else assignment_ast=*iter; ++iter; int vec_addr=calculation(local_scope,*iter); if(vec_addr<0) return __state_error; if(nasal_gc.get_scalar(vec_addr).get_type()!=scalar_vector) { error_interrupt(__forindex_foreach_not_vector,iter->get_node_line()); return __state_error; } ++iter; for(int i=0;i=0) nasal_gc.reference_delete(tmp_val); state=block_proc(local_scope,*iter); if(state==__state_break || state==__state_return || state==__state_error) break; } nasal_gc.reference_delete(vec_addr); } else if(loop_type==__forindex) { // forindex(i;vector) // forindex gives the index of elements in the vector to identifier 'i' // and the 'i' will take part in the calculation std::list::iterator iter=node.get_children().begin(); abstract_syntax_tree& assignment_ast=*iter;// definition/assignment if(iter->get_node_type()==__definition) { std::string identifier_name=iter->get_children().front().get_var_name(); int new_identifier_addr=nasal_gc.gc_alloc(); local_scope.back()[identifier_name]=new_identifier_addr; nasal_gc.get_scalar(new_identifier_addr).set_type(scalar_number); nasal_gc.get_scalar(new_identifier_addr).get_number().set_number(0); assignment_ast=iter->get_children().front(); } else assignment_ast=*iter; ++iter; int vec_addr=calculation(local_scope,*iter); if(vec_addr<0) return __state_error; if(nasal_gc.get_scalar(vec_addr).get_type()!=scalar_vector) { error_interrupt(__forindex_foreach_not_vector,iter->get_node_line()); return __state_error; } ++iter; for(int i=0;i=0) nasal_gc.reference_delete(tmp_val); nasal_gc.reference_delete(tmp_addr); state=block_proc(local_scope,*iter); if(state==__state_break || state==__state_return || state==__state_error) break; } nasal_gc.reference_delete(vec_addr); } else if(loop_type==__for) { std::list::iterator iter=node.get_children().begin(); if(iter->get_node_type()!=__null_type) definition(local_scope,local_scope.back(),*iter); // definition before loop ++iter; std::list::iterator condition_iterator=iter; // conditional ++iter; std::list::iterator step_iterator=iter; // step length ++iter; std::list::iterator block_proc_iterator=iter; // run block while(check_condition(local_scope,*condition_iterator)) { state=block_proc(local_scope,*block_proc_iterator); if(state==__state_break || state==__state_return || state==__state_error) break; // step update here if(step_iterator->get_node_type()!=__null_type) { int assign_addr=calculation(local_scope,*step_iterator); if(assign_addr<0) { state=__state_error; break; } nasal_gc.reference_delete(assign_addr); } } } for(std::map::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i) nasal_gc.reference_delete(i->second); local_scope.pop_back(); return state; } int nasal_runtime::conditional(std::list >& local_scope,abstract_syntax_tree& node) { int ret_state=__state_no_operation; std::map new_scope; local_scope.push_back(new_scope); for(std::list::iterator i=node.get_children().begin();i!=node.get_children().end();++i) { int condition_node_type=i->get_node_type(); if(condition_node_type==__if || condition_node_type==__elsif) { if(check_condition(local_scope,i->get_children().front())) { int state=block_proc(local_scope,i->get_children().back()); ret_state=state; break; } } else { int state=block_proc(local_scope,i->get_children().front()); ret_state=state; break; } } for(std::map::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i) nasal_gc.reference_delete(i->second); local_scope.pop_back(); return ret_state; } int nasal_runtime::block_proc(std::list >& local_scope,abstract_syntax_tree& node) { int state=__state_no_operation; int closure_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(closure_addr).set_type(scalar_closure); std::vector assignedfunc_addrs; for(std::list::iterator iter=node.get_children().begin();iter!=node.get_children().end();++iter) { // use local value node_type to avoid calling function too many times. int node_type=iter->get_node_type(); if(node_type==__number || node_type==__string) ; else if(node_type==__id) { int addr=this->call_identifier(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__vector) { int addr=this->vector_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__hash) { int addr=this->hash_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__function) { int addr=this->function_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__add_operator || node_type==__sub_operator || node_type==__mul_operator || node_type==__div_operator || node_type==__link_operator || node_type==__cmp_equal || node_type==__cmp_less || node_type==__cmp_more || node_type==__cmp_not_equal || node_type==__cmp_less_or_equal || node_type==__cmp_more_or_equal || node_type==__and_operator || node_type==__or_operator || node_type==__ques_mark || node_type==__equal || node_type==__add_equal || node_type==__sub_equal || node_type==__div_equal || node_type==__mul_equal || node_type==__link_equal) { int addr=this->calculation(local_scope,*iter); if(addr>=0) { if(nasal_gc.get_scalar(addr).get_type()==scalar_function) assignedfunc_addrs.push_back(addr); nasal_gc.reference_delete(addr); } } else if(node_type==__definition) this->definition(local_scope,local_scope.back(),*iter); else if(node_type==__conditional) state=this->conditional(local_scope,*iter); else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex)) state=this->loop_expr(local_scope,*iter); else if(node_type==__return) { if(!iter->get_children().size()) { function_returned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil); } else function_returned_addr=calculation(local_scope,iter->get_children().front()); state=__state_return; } if(runtime_error_exit_mark>=0) { state=__state_error; break; } if(state==__state_break || state==__state_continue || state==__state_return || state==__state_error) break; } // update_closure nasal_gc.get_scalar(closure_addr).get_closure().set_local_scope(local_scope); update_closure(assignedfunc_addrs,closure_addr); nasal_gc.reference_delete(closure_addr); return state; } int nasal_runtime::func_proc( std::list >& parameters_assist_scope,// scope that used to generate parameters std::list >& local_scope,// running scope,often gets the scope that calls it abstract_syntax_tree& parameter_list, // parameter list format of nasal function abstract_syntax_tree& func_root, // main runnning block of nasal function abstract_syntax_tree& input_parameters, // input parameters when calling this nasal function int called_hash_addr // if called a hash before calling this nasal function,this address will be given to 'me' ) { // local scope should not used as reference // because this will change the elements in scalar_function value itself // if you call the same function in the function,the scope will be in a mess function_returned_addr=-1; std::map new_scope; // new_scope will be used in parameters initialling process // if push back this scope to local_scope // there may be an error if an identifier has the same name as one identifier in the local_scope before if(called_hash_addr>=0) { new_scope["me"]=called_hash_addr; nasal_gc.reference_add(called_hash_addr); } // loading parameters std::vector para_name_list; int dynamic_args=-1; for(std::list::iterator iter=parameter_list.get_children().begin();iter!=parameter_list.get_children().end();++iter) { if(iter->get_node_type()==__id) { para_name_list.push_back(iter->get_var_name()); new_scope[para_name_list.back()]=-1; } else if(iter->get_node_type()==__default_parameter) { para_name_list.push_back(iter->get_children().front().get_var_name()); int default_val_addr=calculation(parameters_assist_scope,iter->get_children().back()); if(default_val_addr<0) return -1; new_scope[para_name_list.back()]=default_val_addr; } else if(iter->get_node_type()==__dynamic_id) { dynamic_args=nasal_gc.gc_alloc(); nasal_gc.get_scalar(dynamic_args).set_type(scalar_vector); new_scope[iter->get_var_name()]=dynamic_args; break; } } if(!input_parameters.get_children().empty() && input_parameters.get_children().front().get_node_type()!=__special_parameter) { int tmp_ptr=0; for(std::list::iterator iter=input_parameters.get_children().begin();iter!=input_parameters.get_children().end();++iter) { if(tmp_ptr>=para_name_list.size()) { if(dynamic_args>=0) { int val_addr=calculation(parameters_assist_scope,*iter); if(val_addr<0) return -1; nasal_gc.get_scalar(dynamic_args).get_vector().vec_push(val_addr); } else break; } else { int val_addr=calculation(parameters_assist_scope,*iter); if(val_addr<0) return -1; if(new_scope[para_name_list[tmp_ptr]]<0) new_scope[para_name_list[tmp_ptr]]=val_addr; else { nasal_gc.reference_delete(new_scope[para_name_list[tmp_ptr]]); new_scope[para_name_list[tmp_ptr]]=val_addr; } } ++tmp_ptr; } } else// special parameter f(a:1,b:2) { for(std::list::iterator iter=input_parameters.get_children().begin();iter!=input_parameters.get_children().end();++iter) { std::string tmp_para_name=iter->get_children().front().get_var_name(); if(new_scope.find(tmp_para_name)!=new_scope.end()) { int val_addr=calculation(parameters_assist_scope,iter->get_children().back()); if(val_addr<0) return -1; if(new_scope[tmp_para_name]<0) new_scope[tmp_para_name]=val_addr; else { nasal_gc.reference_delete(new_scope[tmp_para_name]); new_scope[tmp_para_name]=val_addr; } } } } for(int i=0;i assignedfunc_addrs; for(std::list::iterator iter=func_root.get_children().begin();iter!=func_root.get_children().end();++iter) { // use local value node_type to avoid calling function too many times. int node_type=iter->get_node_type(); if(node_type==__number || node_type==__string) ; else if(node_type==__id) { int addr=this->call_identifier(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__vector) { int addr=this->vector_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__hash) { int addr=this->hash_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__function) { int addr=this->function_generation(local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__add_operator || node_type==__sub_operator || node_type==__mul_operator || node_type==__div_operator || node_type==__link_operator || node_type==__cmp_equal || node_type==__cmp_less || node_type==__cmp_more || node_type==__cmp_not_equal || node_type==__cmp_less_or_equal || node_type==__cmp_more_or_equal || node_type==__and_operator || node_type==__or_operator || node_type==__ques_mark || node_type==__equal || node_type==__add_equal || node_type==__sub_equal || node_type==__div_equal || node_type==__mul_equal || node_type==__link_equal) { int addr=this->calculation(local_scope,*iter); if(addr>=0) { if(nasal_gc.get_scalar(addr).get_type()==scalar_function) assignedfunc_addrs.push_back(addr); nasal_gc.reference_delete(addr); } } else if(node_type==__definition) this->definition(local_scope,local_scope.back(),*iter); else if(node_type==__conditional) state=this->conditional(local_scope,*iter); else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex)) state=this->loop_expr(local_scope,*iter); else if(node_type==__return) { if(!iter->get_children().size()) { function_returned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil); } else function_returned_addr=calculation(local_scope,iter->get_children().front()); state=__state_return; } if(runtime_error_exit_mark>=0) break; if(state==__state_return) break; else if(state==__state_break) { error_interrupt(__break_not_used_in_loop,iter->get_node_line()); return -1; } else if(state==__state_continue) { error_interrupt(__continue_not_used_in_loop,iter->get_node_line()); return -1; } else if(state==__state_error) return -1; else if(state==__state_no_operation) ; } if(state!=__state_return) { function_returned_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil); } // update closure nasal_gc.get_scalar(closure_addr).get_closure().set_local_scope(local_scope); update_closure(assignedfunc_addrs,closure_addr); nasal_gc.reference_delete(closure_addr); for(std::map::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i) nasal_gc.reference_delete(i->second); local_scope.pop_back(); return function_returned_addr; } int nasal_runtime::builtin_function(std::list >& local_scope,std::string func_name) { int ret_addr=-1; if(func_name=="nasal_call_builtin_push_back") ret_addr=append(local_scope); else if(func_name=="nasal_call_builtin_set_size") ret_addr=setsize(local_scope); else if(func_name=="nasal_call_builtin_subvec") ret_addr=subvec(local_scope); else if(func_name=="nasal_call_builtin_c_std_puts") ret_addr=print(local_scope); else if(func_name=="nasal_call_builtin_scalar_type") ret_addr=system_type(local_scope); else if(func_name=="nasal_call_builtin_sin") ret_addr=nas_trigfunc(local_scope,0); else if(func_name=="nasal_call_builtin_cos") ret_addr=nas_trigfunc(local_scope,1); else if(func_name=="nasal_call_builtin_tan") ret_addr=nas_trigfunc(local_scope,2); else if(func_name=="nasal_call_builtin_exp") ret_addr=nas_exp(local_scope); // "nasal_call_builtin_contains", // "nasal_call_builtin_delete", // "nasal_call_builtin_trans_int", // "nasal_call_builtin_trans_num", // "nasal_call_builtin_get_keys", // "nasal_call_builtin_pop_back", // "nasal_call_builtin_sizeof", // "nasal_call_builtin_str_cmp_equal", // "nasal_call_builtin_cmp", // "nasal_call_builtin_cpp_sort", // "nasal_call_builtin_substr", // "nasal_call_builtin_sprintf", // "nasal_call_builtin_find_first_occur", // "nasal_call_builtin_split", // "nasal_call_builtin_rand", // "nasal_call_builtin_get_id", // "nasal_call_builtin_bitcalc", // "nasal_call_builtin_sbitcalc", // "nasal_call_builtin_setbit", // "nasal_call_builtin_null_string_gen", // "nasal_call_builtin_cpp_math_ln", // "nasal_call_builtin_cpp_math_sqrt", // "nasal_call_builtin_cpp_atan2", return ret_addr; } void nasal_runtime::main_proc(abstract_syntax_tree& root) { time_t begin_time,end_time; begin_time=std::time(NULL); // initializing global scope and nasal_gc // runtime_error_exit_mark is set to -1,if runtime_error_exit_mark >=0,this means an error occurred global_scope.clear(); main_local_scope.clear(); nasal_gc.gc_init(); runtime_error_exit_mark=-1; if(root.get_node_type()!=__root) { error_interrupt(__incorrect_head_of_tree,root.get_node_line()); return; } for(std::list::iterator iter=root.get_children().begin();iter!=root.get_children().end();++iter) { // use local value node_type to avoid calling function too many times. int node_type=iter->get_node_type(); int state=__state_no_operation; if(node_type==__number || node_type==__string) ; else if(node_type==__id) { int addr=this->call_identifier(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__vector) { int addr=this->vector_generation(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__hash) { int addr=this->hash_generation(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__function) { int addr=this->function_generation(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); } else if(node_type==__add_operator || node_type==__sub_operator || node_type==__mul_operator || node_type==__div_operator || node_type==__link_operator || node_type==__cmp_equal || node_type==__cmp_less || node_type==__cmp_more || node_type==__cmp_not_equal || node_type==__cmp_less_or_equal || node_type==__cmp_more_or_equal || node_type==__and_operator || node_type==__or_operator || node_type==__ques_mark || node_type==__equal || node_type==__add_equal || node_type==__sub_equal || node_type==__div_equal || node_type==__mul_equal || node_type==__link_equal) { int addr=this->calculation(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); // new functions in global scope must set its closure_update_state to true // or its local scope maybe changed after running other expressions if(nasal_gc.get_scalar(addr).get_type()==scalar_function && !nasal_gc.get_scalar(addr).get_function().get_closure_update_state()) nasal_gc.get_scalar(addr).get_function().set_closure_update_state(true); } else if(node_type==__definition) this->definition(main_local_scope,global_scope,*iter); else if(node_type==__conditional) state=this->conditional(main_local_scope,*iter); else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex)) state=this->loop_expr(main_local_scope,*iter); if(runtime_error_exit_mark>=0) break; if(state==__state_no_operation) ; else if(state==__state_break) { error_interrupt(__break_not_used_in_loop,iter->get_node_line()); break; } else if(state==__state_continue) { error_interrupt(__continue_not_used_in_loop,iter->get_node_line()); break; } else if(state==__state_return) { error_interrupt(__return_not_used_in_function,iter->get_node_line()); break; } else if(state==__state_error) break; } end_time=std::time(NULL); std::cout<> [Runtime] process exited after "<