This commit is contained in:
Valk Richard Li 2020-03-30 21:06:13 +08:00 committed by GitHub
parent a723b878f0
commit ca01383272
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 278 additions and 160 deletions

View File

@ -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"

View File

@ -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<abstract_syntax_tree> 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<abstract_syntax_tree>& 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&);
};

View File

@ -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<<context;
return;
}
// print node types that used in abstract_syntax_tree
void print_ast_type(int type)
{
std::string context="";
@ -204,6 +221,7 @@ void print_ast_type(int type)
return;
}
// basic scalar type used in nasal_runtime and nasal_gc
enum scalar_type
{
scalar_nil=0,
@ -213,6 +231,7 @@ enum scalar_type
scalar_hash,
scalar_function
};
// print types that used in nasal_runtime and nasal_gc
void print_scalar_type(const int type)
{
switch(type)

View File

@ -4,12 +4,12 @@
/*
__token_reserve_word:
for,foreach,forindex,while : loop
var,func : definition
break,continue : in loop
return : in function
if,else,elsif : if-else statement
and,or : calculation
nil : special type
var,func : definition
break,continue : in loop
return : in function
if,else,elsif : conditional expr
and,or : calculation
nil : special type
__token_identifier:
must begin with '_' or 'a'~'z' or 'A'~'Z'
can include '_' or 'a'~'z' or 'A'~'Z' or '0'~'9'
@ -27,11 +27,13 @@
__token_operator:
! + - * / ~
= += -= *= /= ~=
== != > >= < <= ('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<char> resource;
public:
/*
resource_file();
~resource_file();
void delete_all_source();
void input_file(std::string);
void load_lib_file();
std::list<char>& get_source();
void print_resource();
delete_all_source: clear all the source codes in std::list<char> resource
input_file : input source codes by filenames
load_lib_file : input lib source codes
get_source : get the std::list<char> 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> token_list;
std::list<token> 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<char>&);
void generate_detail_token();
int get_error();
std::list<token>& 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()
{

View File

@ -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);

View File

@ -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<token> parse_token_stream;
std::stack<token> 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 <call_id> '=' <calculation>) 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 <call_id> '=' <calculation>) 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> [<calculation>] ';'
/* return_expr() generates ebnf: <return> [<calculation>] ';' */
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<token>&);
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<token> tmp=parse_token_stream;
// indent
std::string indent="";
int brace_cnt=0;
int line=1;
std::cout<<line<<"\t";
while((!tmp.empty()) && (tmp.top().type!=__stack_end))
@ -133,6 +144,7 @@ void nasal_parse::print_detail_token()
if(tmp.top().line!=line)
{
// if line changes,print '\n' and number of line
// by using this loop,empty line will also be output
for(int i=line+1;i<tmp.top().line;++i)
std::cout<<std::endl<<i<<"\t";
line=tmp.top().line;
@ -140,9 +152,14 @@ void nasal_parse::print_detail_token()
}
print_parse_token(tmp.top().type);
if(tmp.top().type==__left_brace)
{
++brace_cnt;
indent+=' ';
}
else if(tmp.top().type==__right_brace)
--brace_cnt;
tmp.pop();
if((!tmp.empty()) && (tmp.top().type==__right_brace))
if((!tmp.empty()) && (tmp.top().type==__right_brace) && brace_cnt>=1)
indent.pop_back();
}
std::cout<<std::endl;
@ -394,8 +411,7 @@ bool nasal_parse::check_multi_assignment()
this->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();

View File

@ -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)."<<std::endl;break;
case __function_returned_value_be_assigned:
std::cout<<"cannot assigned a value that function returns."<<std::endl;break;
std::cout<<"cannot assign a value that function returns."<<std::endl;break;
case __subvec_value_be_assigned:
std::cout<<"cannot assign a subvec value."<<std::endl;break;
case __call_function_lack_para:
std::cout<<"lack parameter(s) when calling a function."<<std::endl;break;
case __forindex_foreach_not_vector:
@ -1863,8 +1866,7 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& 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<int> tmp_subvec_addr;
for(std::list<abstract_syntax_tree>::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<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<std::map<std::string,int> >& local_scope
for(int i=begin_num;i<end_num;++i)
{
// addr used here
int tmp_data_addr=nasal_gc.get_scalar(assigned_value_addr).get_vector().get_elem(i);
int tmp_data_addr=nasal_gc.get_scalar(*assigned_addr).get_vector().get_elem(i);
int new_addr=-1;
if(tmp_data_addr<0)
{
@ -2019,12 +2021,11 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& 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<subvec_result.size();++i)
nasal_gc.get_scalar(assigned_value_addr).get_vector().vec_push(subvec_result[i]);
nasal_gc.reference_delete(tmp_addr);
nasal_gc.get_scalar(tmp_addr).get_vector().vec_push(subvec_result[i]);
tmp_subvec_addr.push_back(tmp_addr);
assigned_addr=NULL;
}// end sub-vector
else
@ -2058,16 +2059,12 @@ int nasal_runtime::assignment(std::list<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<tmp_subvec_addr.size();++i)
nasal_gc.reference_delete(tmp_subvec_addr[i]);
return *assigned_addr;
}
int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
@ -2870,8 +2881,8 @@ int nasal_runtime::block_proc(std::list<std::map<std::string,int> >& local_scope
return state;
}
int nasal_runtime::func_proc(
std::list<std::map<std::string,int> >& parameters_assist_scope,// scope that used to generate parameters
std::list<std::map<std::string,int> >& local_scope,// running scope,often gets the scope that calls it
std::list<std::map<std::string,int> >& 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<std::string,int> new_scope;
local_scope.push_back(new_scope);
for(std::list<std::map<std::string,int> >::iterator i=function_scope.begin();i!=function_scope.end();++i)
for(std::map<std::string,int>::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)