#ifndef __NASAL_RUNTIME_H__ #define __NASAL_RUNTIME_H__ enum runtime_returned_state { rt_return=1, rt_break, rt_continue, rt_error, rt_exit_without_error }; class nasal_runtime { private: // 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; // generate number and return gc place of this number int number_generation(nasal_ast&); // generate string and return gc place of this string int string_generation(nasal_ast&); // 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 int main_progress(); // function/loop/conditional expression block running process int block_progress(nasal_ast&,int,bool); // run loop int before_for_loop(nasal_ast&,int); int after_each_for_loop(nasal_ast&,int); int loop_progress(nasal_ast&,int,bool); // run conditional bool check_condition(int); int conditional_progress(nasal_ast&,int,bool); // 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&,int,int,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 calculation(nasal_ast&,int); void definition(nasal_ast&,int); void multi_assignment(nasal_ast&,int); 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; return; } nasal_runtime::~nasal_runtime() { error=0; this->root.clear(); this->global_scope_address=-1; return; } void nasal_runtime::set_root(nasal_ast& parse_result) { this->root=parse_result; return; } void nasal_runtime::run() { int returned_statement; time_t begin_time,end_time; this->global_scope_address=nasal_vm.gc_alloc(); nasal_vm.gc_get(global_scope_address).set_type(vm_closure); nasal_vm.gc_get(global_scope_address).get_closure().add_scope(); begin_time=std::time(NULL); returned_statement=main_progress(); end_time=std::time(NULL); nasal_vm.gc_get(global_scope_address).get_closure().del_scope(); nasal_vm.del_reference(global_scope_address); std::cout<<">> [runtime] process exited after "<=0) { // codes here make closure nasal_vm.add_reference(local_scope_addr); ref_of_this_function.set_closure_addr(local_scope_addr); } else { int new_closure_addr=nasal_vm.gc_alloc(); nasal_vm.gc_get(new_closure_addr).set_type(vm_closure); ref_of_this_function.set_closure_addr(new_closure_addr); } return new_addr; } int nasal_runtime::main_progress() { int ret_state=rt_exit_without_error; int expr_number=root.get_children().size(); int process_returned_value_addr=-1; for(int i=0;i> [runtime] main_progress: cannot use break in main progress."<> [runtime] main_progress: cannot use continue in main progress."<> [runtime] main_progress: cannot use return in main progress."<> [runtime] main_progress: error occurred when executing main progress."<> [runtime] return expression is not allowed here."<> [runtime] block_progress: error occurred when executing sub-progress."<> [runtime] before_for_loop: cannot use this expression before for-loop."<> [runtime] after_each_for_loop: cannot use this expression after each for-loop."<> [runtime] loop_progress: "<<(loop_type==ast_forindex? "forindex":"foreach")<<" gets a value that is not a vector."<> [runtime] loop_progress: get null iterator."<> [runtime] check_condition: error value type when checking condition."<> [runtime] check_condition: error value type, \'"<=0) value_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_value_address(node.get_children()[0].get_str()); if(value_address<0) value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_children()[0].get_str()); if(value_address<0) { // unfinished // builtin-function call will be set here std::cout<<">> [runtime] call_nasal_scalar: cannot find value named \'"<> [runtime] call_vector: incorrect value type,expected a vector/hash/string."< called_value_addrs; nasal_vector& reference_value=nasal_vm.gc_get(base_value_addr).get_vector(); for(int i=0;i> [runtime] call_vector: begin index is not a number/numerable string."<> [runtime] call_vector: end index is not a number/numerable string."<> [runtime] call_vector: begin index is not a numerable string."<> [runtime] call_vector: end index is not a numerable string."<=end_index) { std::cout<<">> [runtime] call_vector: begin index must be less than end index."<> [runtime] call_vector: index is not a number/numerable string."<> [runtime] call_vector: index is not a numerable string."<1) { std::cout<<">> [runtime] call_vector: when calling a hash,only one key is alowed."<> [runtime] call_vector: cannot slice hash."<1) { std::cout<<">> [runtime] call_vector: when calling a string,only one index is alowed."<> [runtime] call_vector: cannot slice string."<> [runtime] call_vector: index is not a number/numerable string."<> [runtime] call_vector: index is not a numerable string."<=str_size || index_num<-str_size) { std::cout<<">> [runtime] call_vector: index out of range."<> [runtime] call_hash: incorrect value type,expected a hash."<> [runtime] call_function: incorrect value type,expected a function."<> [runtime] call_function: lack at least "< 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> [runtime] call_function: identifier named \'"<::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(); nasal_vm.gc_get(vector_value_addr).set_type(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) { std::cout<<">> [runtime] call_function: argument named \'"<first<<"\' is not in use."< args; // store value address of input arguments int size=node.get_children().size(); for(int i=0;i> [runtime] call_function: error value address when generating argument list."<arg_format_size && argument_format.get_children().back().get_type()!=ast_dynamic_id) { std::cout<<">> [runtime] call_function: too much arguments."<> [runtime] call_function: lack argument(s).stop."<=0) { ret_value_addr=function_returned_address; function_returned_address=-1; } else { ret_value_addr=nasal_vm.gc_alloc(); nasal_vm.gc_get(ret_value_addr).set_type(vm_nil); } return ret_value_addr; } int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr) { int mem_address=-1; if(local_scope_addr>=0) mem_address=nasal_vm.gc_get(local_scope_addr).get_closure().get_mem_address(node.get_children()[0].get_str()); if(mem_address<0) mem_address=nasal_vm.gc_get(global_scope_address).get_closure().get_mem_address(node.get_children()[0].get_str()); if(mem_address<0) { std::cout<<">> [runtime] call_scalar_mem: cannot find value named \'"<> [runtime] call_scalar_mem: cannot change the value that function returns."<> [runtime] call_vector_mem: incorrect value type,expected a vector/hash."<1) { std::cout<<">> [runtime] call_vector_mem: when searching a memory space in a vector,only one index is alowed."<> [runtime] call_vector_mem: sub-vector in this progress is a temporary value and cannot be changed."<> [runtime] call_vector_mem: index is not a number/numerable string."<> [runtime] call_vector_mem: index is not a numerable string."<1) { std::cout<<">> [runtime] call_vector_mem: when calling a hash,only one key is alowed."<> [runtime] call_hash_mem: incorrect value type,expected a hash."<> [runtime] calculation: this expression cannot be calculated."<> [runtime] calculation: incorrect values are used in calculation."<> [runtime] definition: one identifier cannot accept too many values."< identifier_table; int id_size=define_node.get_children().size(); for(int i=0;i> [runtime] definition: size of identifiers and size of values do not match."<> [runtime] definition: must use vector in multi-definition."<> [runtime] definition: size of identifiers and size of values do not match."< mem_table; int id_size=multi_call_node.get_children().size(); for(int i=0;i> [runtime] multi_assignment: multi-assignment must use available memory address."<> [runtime] multi_assignment: size of calls and size of values do not match."<> [runtime] multi_assignment: must use vector in multi-assignment."<> [runtime] multi_assignment: size of calls and size of values do not match."<