From ca01383272eeccae6006b8a0c4bb17a5409fd0f2 Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Mon, 30 Mar 2020 21:06:13 +0800 Subject: [PATCH] update --- version2.0/nasal.h | 2 +- version2.0/nasal_ast.h | 43 +++++++++--- version2.0/nasal_enum.h | 43 ++++++++---- version2.0/nasal_lexer.h | 80 +++++++++++----------- version2.0/nasal_misc.h | 45 ++++++++++++- version2.0/nasal_parse.h | 93 ++++++++++++++++---------- version2.0/nasal_runtime.h | 132 +++++++++++++++++++------------------ 7 files changed, 278 insertions(+), 160 deletions(-) diff --git a/version2.0/nasal.h b/version2.0/nasal.h index 70250e3..44ce56f 100644 --- a/version2.0/nasal.h +++ b/version2.0/nasal.h @@ -41,7 +41,7 @@ including a class named nasal_lexer including a string[] named lib_filename, by this way resource_file can load lib files including a string[] named reserve_word, it is used in lexer,when generating an identifier,nasal_lexer will check if it is a reserve word - including a struct named token, this struct is often used in nasal_lexer + including a struct named token, this struct is often used in nasal_lexer and nasal_parse including a function named is_reserve_word, checking if an identifier is a reserve word */ #include "nasal_lexer.h" diff --git a/version2.0/nasal_ast.h b/version2.0/nasal_ast.h index f11c11a..3f3cc9c 100644 --- a/version2.0/nasal_ast.h +++ b/version2.0/nasal_ast.h @@ -4,14 +4,21 @@ class abstract_syntax_tree { private: - // basic elements + /* + basic elements of ast node: + line: this marks the generated node's line in source code + node_type: this marks the node type + children: store the children of this node + */ int line; int node_type; std::list children; - // is this node is a number|string|identifier node - // then the three elements below is of great use - // var_name is set for __id + /* + var_number is used when the node_type is __number + var_string is used when the node_type is __string + var_name is used when the node_type is __id, __dynamic_id, call_hash + */ double var_number; std::string var_string; std::string var_name; @@ -23,11 +30,22 @@ class abstract_syntax_tree abstract_syntax_tree& operator=(const abstract_syntax_tree&); /* main functions */ - // print + /* + print_tree is the entrance of print function + print_tree will print the root address and call print_tree_block(1) + print_tree_block will print the information of each node by using DFS + */ void print_tree(); void print_tree_block(const int); - // set + /* + set_clear : clear all the elements in ast node + set_node_line : set the private:line + set_node_type : set the private:node_type + set_var_number: set the private:var_number + set_var_string: set the private:var_string + set_var_name : set the private:var_name + */ void set_clear(); void set_node_line(const int); void set_node_type(const int); @@ -36,7 +54,13 @@ class abstract_syntax_tree void set_var_name(std::string); void add_children(abstract_syntax_tree); - // get + /* + get_node_line : get the private:line + get_node_type : get the private:node_type + get_var_number: get private:var_number + get_var_string: get private:var_string + get_var_name : get private:var_name + */ int get_node_line(); int get_node_type(); double get_var_number(); @@ -44,7 +68,10 @@ class abstract_syntax_tree std::string get_var_name(); std::list& get_children(); - // merge + /* + merge children of another ast into this one + used to link lib ast and source codes' ast together + */ void merge_children(abstract_syntax_tree&); }; diff --git a/version2.0/nasal_enum.h b/version2.0/nasal_enum.h index 5d67f76..2d1094e 100644 --- a/version2.0/nasal_enum.h +++ b/version2.0/nasal_enum.h @@ -1,6 +1,8 @@ #ifndef __NASAL_ENUM_H__ #define __NASAL_ENUM_H__ +// lexer token type is only used in nasal_lexer +// each scanned token will be recognized as one of these below enum lexer_token_type { __token_reserve_word=1, @@ -25,29 +27,42 @@ void print_lexer_token(int type) // parse_gen_type include enums for parser and ast enum parse_gen_type { + /* + stack end is an important flag for parse token stack to + check if it's stack is at end + if stack is empty,the parser will get a wrong memory space and cause SIGSEGV + */ __stack_end=1, - - // operators - __cmp_equal,__cmp_not_equal,__cmp_less,__cmp_less_or_equal,__cmp_more,__cmp_more_or_equal, - // == != < <= > >= - __and_operator,__or_operator,__nor_operator,__add_operator,__sub_operator,__mul_operator,__div_operator,__link_operator, - // and or ! + - * / ~ - __equal,__add_equal,__sub_equal,__mul_equal,__div_equal,__link_equal, - // = += -= *= /= ~= + // operators == != < <= > >= + __cmp_equal, + __cmp_not_equal, + __cmp_less,__cmp_less_or_equal, + __cmp_more,__cmp_more_or_equal, + // operators and or ! + - * / ~ + __and_operator, __or_operator,__nor_operator, + __add_operator,__sub_operator, + __mul_operator,__div_operator,__link_operator, + // operators = += -= *= /= ~= + __equal, + __add_equal,__sub_equal, + __mul_equal,__div_equal,__link_equal, + // operators {} [] () ; , : . ? __left_brace,__right_brace, // {} __left_bracket,__right_bracket, // [] __left_curve,__right_curve, // () __semi,__comma,__colon,__dot,__ques_mark, // ; , : . ? __unknown_operator, - // reserve words - __var,__func,__return,__nil, + __var, + __func,__return,__nil, __if,__elsif,__else, __continue,__break, __for,__forindex,__foreach,__while, - // basic scalar type: number string identifier dynamic_identifier - __number,__string,__id,__dynamic_id, + // basic scalar type: number string + __number,__string, + // basic identifier type: identifier dynamic_identifier + __id,__dynamic_id, // abstract_syntax_tree type below // abstract_syntax_tree also uses the types above, such as operators @@ -62,6 +77,7 @@ enum parse_gen_type __definition, __conditional }; +// print tokens that used in nasal_parse void print_parse_token(int type) { std::string context=""; @@ -130,6 +146,7 @@ void print_parse_token(int type) std::cout< >= < <= ('and' 'or' are operators too but they are recognized as operator in generate_detail_token()) + == != > >= < <= + ('and' 'or' are operators too but they are recognized as operator in generate_detail_token()) () [] {} ; , . : ? others: __unknown_operator */ +/* filenames of lib files */ const std::string lib_filename[10]= { "lib/base.nas", @@ -45,14 +47,14 @@ const std::string lib_filename[10]= "lib/unix.nas", "lib/utf8.nas" }; - +/* reserve words */ std::string reserve_word[15]= { "for","foreach","forindex","while", "var","func","break","continue","return", "if","else","elsif","and","or","nil" }; - +/* check if an identifier is a reserve word */ int is_reserve_word(std::string str) { for(int i=0;i<15;++i) @@ -67,13 +69,11 @@ class resource_file std::list resource; public: /* - resource_file(); - ~resource_file(); - void delete_all_source(); - void input_file(std::string); - void load_lib_file(); - std::list& get_source(); - void print_resource(); + delete_all_source: clear all the source codes in std::list resource + input_file : input source codes by filenames + load_lib_file : input lib source codes + get_source : get the std::list resource + print_resource : print source codes */ resource_file() { @@ -157,7 +157,7 @@ class resource_file return; } }; - +/* struct token: mainly used in nasal_lexer and nasal_parse*/ struct token { int line; @@ -178,25 +178,27 @@ class nasal_lexer std::list token_list; std::list detail_token_list; int error; + // change utf8 codes into '?' + // this function will be deleted if there is a way to print utf8 codes out correctly std::string utf8_clear(std::string tmp) { /* - 0xxx xxxx 0x0 1 byte - 110x xxxx 0xc0 2 byte - 1110 xxxx 0xe0 3 byte - 1111 0xxx 0xf0 4 byte - 1111 10xx 0xf8 5 byte - 1111 110x 0xfc 6 byte - bytes after it is: - 10xx xxxx 0x80 - - so utf-8 format is: - 0xxxxxxx - 110xxxxx 10xxxxxx - 1110xxxx 10xxxxxx 10xxxxxx - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + 0xxx xxxx 0x0 1 byte + 110x xxxx 0xc0 2 byte + 1110 xxxx 0xe0 3 byte + 1111 0xxx 0xf0 4 byte + 1111 10xx 0xf8 5 byte + 1111 110x 0xfc 6 byte + bytes after it is: + 10xx xxxx 0x80 + + so utf-8 format is: + 0xxxxxxx + 110xxxxx 10xxxxxx + 1110xxxx 10xxxxxx 10xxxxxx + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */ unsigned char utf8head[6]={0x0,0xc0,0xe0,0xf0,0xf8,0xfc}; std::string ret=""; @@ -222,13 +224,11 @@ class nasal_lexer } public: /* - nasal_lexer(); - ~nasal_lexer(); - void print_token_list(); - void scanner(std::list&); - void generate_detail_token(); - int get_error(); - std::list& get_detail_token(); + print_token_list : print generated token list + scanner : scan the source codes and generate tokens + generate_detail_token: recognize and change token types to detailed types that can be processed by nasal_parse + get_error : get the number of errors that occurred when generating tokens + get_detail_token : output the detailed tokens,must be used after generate_detail_token() */ nasal_lexer() { diff --git a/version2.0/nasal_misc.h b/version2.0/nasal_misc.h index afa8dda..632a671 100644 --- a/version2.0/nasal_misc.h +++ b/version2.0/nasal_misc.h @@ -1,6 +1,18 @@ #ifndef __NASAL_MISC_H__ #define __NASAL_MISC_H__ +/* + check_numerable_string: + check if a string can be converted to a number + + strings like these below is correct: + '0.00012' + '12314.234' + '1234' + '0xdeadbeef' + '0xDEADBEEF' + '0o71230' +*/ bool check_numerable_string(std::string str) { if(str.length()>1 && str[0]=='-') @@ -49,6 +61,10 @@ bool check_numerable_string(std::string str) return false; } +/* + trans_string_to_number: + convert string to number +*/ double trans_string_to_number(std::string str) { bool is_negative=false; @@ -120,6 +136,10 @@ double trans_string_to_number(std::string str) return trans_str_number; } +/* + trans_number_to_string: + convert number to string +*/ std::string trans_number_to_string(double number) { std::string trans_num_string=""; @@ -149,9 +169,12 @@ std::string trans_number_to_string(double number) return trans_num_string; } +/* + prt_hex: + transform int to hex format and print it out (std::cout) +*/ void prt_hex(const int ptr) { - // transform int to hex and print it (std::cout) char hex[9]; hex[8]=0; int tmp_plc=ptr; @@ -162,6 +185,26 @@ void prt_hex(const int ptr) } else std::cout<<"0x"; + /* + int: 00000000 00000000 00000000 00000000 + int: 0x00 00 00 00 + example: + a=0x13 57 9b df + a=00010011 01010111 10011011 11011111 + a & 0x00 00 00 0f: + 00010011 01010111 10011011 11011111 + and 00000000 00000000 00000000 00001111 + --------------------------------------- + 00000000 00000000 00000000 00001111 + a>>=4: + 00000001 00110101 01111001 10111101 + a & 0x00 00 00 0f + 00000001 00110101 01111001 10111101 + and 00000000 00000000 00000000 00001111 + --------------------------------------- + 00000000 00000000 00000000 00001101 + then convert 0~15 to 0~9 a~f + */ for(int j=7;j>=0;--j) { int tmp=(tmp_plc & 0x0000000f); diff --git a/version2.0/nasal_parse.h b/version2.0/nasal_parse.h index e0c6826..35a78d8 100644 --- a/version2.0/nasal_parse.h +++ b/version2.0/nasal_parse.h @@ -4,11 +4,19 @@ class nasal_parse { private: + /* + parse_token_stream: get detailed tokens from lexer and store them in this stack + checked_tokens : checked tokens will be stored here + this_token : changed by function get_token and push_token,and used when generating ast + error : record the number of errors occurred when generating ast + root : after generating process, the ast will be stored in root + */ std::stack parse_token_stream; std::stack checked_tokens; token this_token; int error; abstract_syntax_tree root; + /* parsse_error_type: used in print_parse_error,including all types of errors*/ enum parse_error_type { parse_unknown_error=0, // unknown error @@ -52,33 +60,36 @@ class nasal_parse ternary_operator_lack_colon, // lack ':' }; + /* print the error type and it's line*/ void print_parse_error(int,int,int); - // most important function of parser - // these two functions are used to get and push token - // by using them,parser can generate ast + /* + get_token and push_token are most important functions of parser + these two functions are used to get and push token + and the result will be stored in this_token + */ void get_token(); void push_token(); - // block statements generation + /* block statements generation */ abstract_syntax_tree block_generate(); // check ';' void check_semi(); - // check '(' confliction - bool check_multi_assignment();// check multi_call_id '=' multi_scalar - bool check_multi_scalar(); // check multi_scalar - bool check_var_in_curve(); // check multi_definition: (var id,id,id) - bool check_function_end(abstract_syntax_tree&); // check end of definition or '=' is a function + /* check '(' confliction */ + bool check_multi_assignment(); // check multi_call_id '=' multi_scalar + bool check_multi_scalar(); // check multi_scalar + bool check_var_in_curve(); // check multi_definition: (var id,id,id) + bool check_function_end(abstract_syntax_tree&); // check end of definition or '=' is a function /* - calculation() will get elements generated by and_calculation() - and_calculation() will get elements generated by or_calculation() - or_calculation() will get elements generated by cmp_calculation() - cmp_calculation() will get elements generated by additive_calculation() - additive_calculation() will get elements generated by multive_calculation() - multive_calculation() will get elements generated by assign_calculation()(assignment '=' ) and scalar_generate() - assign_calculation() get elements from scalar_generate() - please notice that: - if the elements begin with '!' or '-',multive_calculation() gets them from scalar_generate() - if not,multive_calculation() gets them from assign_calculation() - because '!' and '-' cannot be used with assignment together such as: -a=1 + calculation : will get elements generated by and_calculation() + and_calculation : will get elements generated by or_calculation() + or_calculation : will get elements generated by cmp_calculation() + cmp_calculation : will get elements generated by additive_calculation() + additive_calculation: will get elements generated by multive_calculation() + multive_calculation : will get elements generated by assign_calculation()(assignment '=' ) and scalar_generate() + assign_calculation : get elements from scalar_generate() + please notice that: + if the elements begin with '!' or '-',multive_calculation() gets them from scalar_generate() + if not,multive_calculation() gets them from assign_calculation() + because '!' and '-' cannot be used with assignment together such as: -a=1 */ abstract_syntax_tree calculation(); abstract_syntax_tree and_calculation(); @@ -87,13 +98,13 @@ class nasal_parse abstract_syntax_tree additive_calculation(); abstract_syntax_tree multive_calculation(); abstract_syntax_tree scalar_generate(); - // normal data type generation + /* normal data type generation */ abstract_syntax_tree hash_generate(); abstract_syntax_tree vector_generate(); abstract_syntax_tree function_generate(); - // return_expr() generates ebnf: [] ';' + /* return_expr() generates ebnf: [] ';' */ abstract_syntax_tree return_expr(); - // normal expressions + /* normal expressions */ abstract_syntax_tree multi_scalar_assignment(); abstract_syntax_tree definition(); abstract_syntax_tree loop_expr(); @@ -102,7 +113,7 @@ class nasal_parse // basic functions void delete_all_elements() { - // used in 'del' command + // used in 'del' command in main() while(!parse_token_stream.empty()) parse_token_stream.pop(); while(!checked_tokens.empty()) @@ -114,8 +125,7 @@ class nasal_parse void get_token_list(std::list&); int get_error(); abstract_syntax_tree& get_root(); - // abstract_syntax_tree generation - // main process of parser + /* main process of parser */ void main_generate(); }; @@ -126,6 +136,7 @@ void nasal_parse::print_detail_token() std::stack tmp=parse_token_stream; // indent std::string indent=""; + int brace_cnt=0; int line=1; std::cout<=1) indent.pop_back(); } std::cout<get_token(); ++cnt; // these determine statements are used with curve_cnt,bracket_cnt and brace_cnt together - // to avoid checking commas in other curves/brackets/braces - // such as ([0,1,2,3]) + // to avoid checking commas in other curves/brackets/braces such as ([0,1,2,3]) // but in multi_assignment, only things like (id[scalar],id.id[scalar]) can be recognized as multi_scalar // if ([0,1,2,3]) and i don't use these judgements,then ([0,1,2,3]) will be recognized as multi_scalar // but in fact ([0,1,2,3]) is not @@ -406,13 +422,16 @@ bool nasal_parse::check_multi_assignment() if(this_token.type==__right_bracket)--bracket_cnt; if(this_token.type==__right_brace) --brace_cnt; + // if curves,brackets,braces are in pairs and this_token is comma,it is really multi_id calls if(!curve_cnt && !bracket_cnt && !brace_cnt && this_token.type==__comma) { ret=true; break; } - if(!curve_cnt && !bracket_cnt && brace_cnt<0) + // error occurred + if(curve_cnt<0 || brace_cnt<0 || brace_cnt<0) break; + // exit when meeting stack end if((!parse_token_stream.empty() && parse_token_stream.top().type==__stack_end) || (this_token.type==__semi)) break; } @@ -446,13 +465,16 @@ bool nasal_parse::check_multi_scalar() if(this_token.type==__right_bracket)--bracket_cnt; if(this_token.type==__right_brace) --brace_cnt; + // if curves,brackets,braces are in pairs and this_token is comma,it is really multi_scalar if(!curve_cnt && !bracket_cnt && !brace_cnt && this_token.type==__comma) { ret=true; break; } - if(!curve_cnt && !bracket_cnt && brace_cnt<0) + // error occurred + if(curve_cnt<0 || brace_cnt<0 || brace_cnt<0) break; + // exit when meeting stack end if((!parse_token_stream.empty() && parse_token_stream.top().type==__stack_end) || (this_token.type==__semi)) break; } @@ -575,8 +597,7 @@ abstract_syntax_tree nasal_parse::block_generate() block_node.set_node_type(__normal_statement_block); if(this_token.type!=__left_brace) { - // only one statement - // so this doesn't need check_semi() + // only one statement, so this doesn't need check_semi() switch(this_token.type) { case __var: @@ -629,6 +650,8 @@ abstract_syntax_tree nasal_parse::block_generate() print_parse_error(error_token_in_block,this_token.line,this_token.type); break; } + // thought don't need to check semi at end, a statement having a semi at its end is also right + // this statement is used to check statement having a semi at its end this->get_token(); if(this_token.type!=__semi) this->push_token(); @@ -702,8 +725,8 @@ abstract_syntax_tree nasal_parse::block_generate() print_parse_error(error_token_in_block,this_token.line,this_token.type); break; } - // why the last statement can avoid semi check()? - // see more details in function: check_semi() + // the last statement can avoid semi check althought need_semi_check is true + // because check_semi will scan the next token,if this token is '}',then semi_check can be avoided if(need_semi_check) check_semi(); this->get_token(); diff --git a/version2.0/nasal_runtime.h b/version2.0/nasal_runtime.h index e67c7c9..d4ac039 100644 --- a/version2.0/nasal_runtime.h +++ b/version2.0/nasal_runtime.h @@ -82,6 +82,7 @@ class nasal_runtime __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, @@ -165,7 +166,9 @@ void nasal_runtime::error_interrupt(const int type,const int line) case __normal_call_vector_too_large_value: std::cout<<"the number used to call the vector is too large(over 0x7fffffff)."< >& local_scope assigned_addr=&((*iter)[tmp_id_name]); if(!assigned_addr) return -1; - int assigned_value_addr=*assigned_addr; - nasal_gc.reference_add(*assigned_addr); + 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 @@ -1872,7 +1874,7 @@ int nasal_runtime::assignment(std::list >& local_scope if(iter->get_node_type()==__call_vector) { // check the scalar type of called identifier here - int called_type=nasal_gc.get_scalar(assigned_value_addr).get_type(); + int called_type=nasal_gc.get_scalar(*assigned_addr).get_type(); if(called_type!=scalar_vector && called_type!=scalar_hash) { error_interrupt(__error_value_type,iter->get_node_line()); @@ -1971,7 +1973,7 @@ int nasal_runtime::assignment(std::list >& local_scope 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(assigned_value_addr).get_vector().get_size(); + 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) @@ -1982,7 +1984,7 @@ int nasal_runtime::assignment(std::list >& local_scope for(int i=begin_num;i >& local_scope nasal_gc.reference_delete(tmp_data_addr); subvec_result.push_back(new_addr); } - int tmp_addr=assigned_value_addr; - assigned_value_addr=nasal_gc.gc_alloc(); - nasal_gc.get_scalar(assigned_value_addr).set_type(scalar_vector); + int tmp_addr=nasal_gc.gc_alloc(); + nasal_gc.get_scalar(tmp_addr).set_type(scalar_vector); for(int i=0;i >& local_scope error_interrupt(__normal_call_vector_too_large_value,iter->get_children().front().get_node_line()); return -1; } - int tmp_addr=assigned_value_addr; - assigned_addr=nasal_gc.get_scalar(tmp_addr).get_vector().get_elem_addr((int)place_num); + 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_children().front().get_node_line()); return -1; } - assigned_value_addr=*assigned_addr; - nasal_gc.reference_add(assigned_value_addr); - nasal_gc.reference_delete(tmp_addr); } else if(called_type==scalar_hash) { @@ -2076,16 +2073,12 @@ int nasal_runtime::assignment(std::list >& local_scope error_interrupt(__error_value_type_when_calling_hash,iter->get_children().front().get_node_line()); return -1; } - int tmp_addr=assigned_value_addr; - assigned_addr=nasal_gc.get_scalar(tmp_addr).get_hash().get_hash_member_addr(nasal_gc.get_scalar(data_addr).get_string().get_string()); + assigned_addr=nasal_gc.get_scalar(*assigned_addr).get_hash().get_hash_member_addr(nasal_gc.get_scalar(data_addr).get_string().get_string()); if(!assigned_addr) { error_interrupt(__invalid_hash_member,iter->get_children().front().get_node_line()); return -1; } - assigned_value_addr=*assigned_addr; - nasal_gc.reference_add(assigned_value_addr); - nasal_gc.reference_delete(tmp_addr); } nasal_gc.reference_delete(tmp_data_addr); } @@ -2093,21 +2086,17 @@ int nasal_runtime::assignment(std::list >& local_scope // call hash identifier.identifier else if(iter->get_node_type()==__call_hash) { - if(nasal_gc.get_scalar(assigned_value_addr).get_type()!=scalar_hash) + if(nasal_gc.get_scalar(*assigned_addr).get_type()!=scalar_hash) { error_interrupt(__not_callable_hash,iter->get_node_line()); return -1; } - int tmp_addr=assigned_value_addr; - assigned_addr=nasal_gc.get_scalar(assigned_value_addr).get_hash().get_hash_member_addr(iter->get_var_name()); + 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; } - assigned_value_addr=*assigned_addr; - nasal_gc.reference_add(assigned_value_addr); - nasal_gc.reference_delete(tmp_addr); }// end call hash // call function identifier(...) else if(iter->get_node_type()==__call_function) @@ -2116,34 +2105,56 @@ int nasal_runtime::assignment(std::list >& local_scope return -1; } } - switch(nasal_gc.get_scalar(data_addr).get_type()) + nasal_gc.reference_delete(*assigned_addr); + if(assigned_addr) { - 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(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(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(data_addr).get_function()); - break; - case scalar_vector: - case scalar_hash: - *assigned_addr=data_addr; - nasal_gc.reference_add(data_addr); - break; + switch(nasal_gc.get_scalar(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(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(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(data_addr).get_function()); + break; + case scalar_vector: + case scalar_hash: + *assigned_addr=data_addr; + nasal_gc.reference_add(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) @@ -2870,8 +2881,8 @@ int nasal_runtime::block_proc(std::list >& local_scope 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 - std::list >& function_scope,// running scope,often gets the scope that has been recorded in nasal function 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 @@ -2881,12 +2892,7 @@ int nasal_runtime::func_proc( function_returned_addr=-1; std::map new_scope; local_scope.push_back(new_scope); - for(std::list >::iterator i=function_scope.begin();i!=function_scope.end();++i) - for(std::map::iterator j=i->begin();j!=i->end();++j) - { - local_scope.back()[j->first]=j->second; - nasal_gc.reference_delete(j->second); - } + if(called_hash_addr>=0) local_scope.back()["me"]=called_hash_addr; // loading parameters @@ -2904,7 +2910,7 @@ int nasal_runtime::func_proc( 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(local_scope,iter->get_children().back()); + int default_val_addr=calculation(parameters_assist_scope,iter->get_children().back()); if(default_val_addr<0) return -1; local_scope.back()[para_name_list.back()]=default_val_addr; @@ -2925,7 +2931,7 @@ int nasal_runtime::func_proc( { if(has_dynamic_id) { - int val_addr=calculation(local_scope,*iter); + 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); @@ -2935,7 +2941,7 @@ int nasal_runtime::func_proc( } else { - int val_addr=calculation(local_scope,*iter); + int val_addr=calculation(parameters_assist_scope,*iter); if(val_addr<0) return -1; if(local_scope.back()[para_name_list[tmp_ptr]]<0) @@ -2956,7 +2962,7 @@ int nasal_runtime::func_proc( std::string tmp_para_name=iter->get_children().front().get_var_name(); if(local_scope.back().find(tmp_para_name)!=local_scope.back().end()) { - int val_addr=calculation(local_scope,iter->get_children().back()); + int val_addr=calculation(parameters_assist_scope,iter->get_children().back()); if(val_addr<0) return -1; if(local_scope.back()[tmp_para_name]<0)